You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC platform updates from Arnd Bergmann:
"SoC platform changes (arch/arm/mach-*). This merge window, the bulk is
for a few platforms:
- Andres Färber adds initial support for the Actions Semi S500 (aka
'owl') platform, a close relative of the S900 platform he adds for
arm64.
- in mach-omap2, we remove more legacy code
- Rockchips gains support for the RV1108 SoC designed for camera
applications.
- For Atmel, we gain support for MMU-less SoCs (SAME70/V71/S70/V70)
- Minor updates for other platforms, including davinci, s3c64xx,
prima2, stm32, broadcom nsp, amlogic, pxa, imx and renesas"
* tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (74 commits)
ARM: owl: smp: Drop bogus holding pen
ARM: owl: Drop custom machine
ARM: owl: smp: Implement SPS power-gating for CPU2 and CPU3
soc: actions: owl-sps: Factor out owl_sps_set_pg() for power-gating
soc: actions: Add Owl SPS
dt-bindings: power: Add Owl SPS power domains
MAINTAINERS: Update Actions Semi section with SPS
ARM: owl: Implement CPU enable-method for S500
MAINTAINERS: Add Actions Semi Owl section
ARM: Prepare Actions Semi S500
ARM: socfpga: Increase max number of GPIOs
ARM: stm32: Introduce MACH_STM32F469 flag
ARM: prima2: remove redundant select CPU_V7
ARM: davinci: fix const warnings
ARM: shmobile: pm-rmobile: Use GENPD_FLAG_ALWAYS_ON
ARM: OMAP4: hwmod_data: add SHAM crypto accelerator
ARM: OMAP4: hwmod data: add des
ARM: OMAP4: hwmod data: add aes2
ARM: OMAP4: hwmod data: add aes1
ARM: pxa: Delete an error message for a failed memory allocation in pxa3xx_u2d_probe()
...
This commit is contained in:
@@ -16,7 +16,7 @@ git branches/tags and email subject always contain this "at91" sub-string.
|
||||
|
||||
AT91 SoCs
|
||||
---------
|
||||
Documentation and detailled datasheet for each product are available on
|
||||
Documentation and detailed datasheet for each product are available on
|
||||
the Atmel website: http://www.atmel.com.
|
||||
|
||||
Flavors:
|
||||
@@ -101,6 +101,42 @@ the Atmel website: http://www.atmel.com.
|
||||
+ Datasheet
|
||||
http://www.atmel.com/Images/Atmel-11267-32-bit-Cortex-A5-Microcontroller-SAMA5D2_Datasheet.pdf
|
||||
|
||||
* ARM Cortex-M7 MCUs
|
||||
- sams70 family
|
||||
- sams70j19
|
||||
- sams70j20
|
||||
- sams70j21
|
||||
- sams70n19
|
||||
- sams70n20
|
||||
- sams70n21
|
||||
- sams70q19
|
||||
- sams70q20
|
||||
- sams70q21
|
||||
+ Datasheet
|
||||
http://www.atmel.com/Images/Atmel-11242-32-bit-Cortex-M7-Microcontroller-SAM-S70Q-SAM-S70N-SAM-S70J_Datasheet.pdf
|
||||
|
||||
- samv70 family
|
||||
- samv70j19
|
||||
- samv70j20
|
||||
- samv70n19
|
||||
- samv70n20
|
||||
- samv70q19
|
||||
- samv70q20
|
||||
+ Datasheet
|
||||
http://www.atmel.com/Images/Atmel-11297-32-bit-Cortex-M7-Microcontroller-SAM-V70Q-SAM-V70N-SAM-V70J_Datasheet.pdf
|
||||
|
||||
- samv71 family
|
||||
- samv71j19
|
||||
- samv71j20
|
||||
- samv71j21
|
||||
- samv71n19
|
||||
- samv71n20
|
||||
- samv71n21
|
||||
- samv71q19
|
||||
- samv71q20
|
||||
- samv71q21
|
||||
+ Datasheet
|
||||
http://www.atmel.com/Images/Atmel-44003-32-bit-Cortex-M7-Microcontroller-SAM-V71Q-SAM-V71N-SAM-V71J_Datasheet.pdf
|
||||
|
||||
Linux kernel information
|
||||
------------------------
|
||||
|
||||
@@ -41,6 +41,36 @@ compatible: must be one of:
|
||||
- "atmel,sama5d43"
|
||||
- "atmel,sama5d44"
|
||||
|
||||
* "atmel,samv7" for MCUs using a Cortex-M7, shall be extended with the specific
|
||||
SoC family:
|
||||
o "atmel,sams70" shall be extended with the specific MCU compatible:
|
||||
- "atmel,sams70j19"
|
||||
- "atmel,sams70j20"
|
||||
- "atmel,sams70j21"
|
||||
- "atmel,sams70n19"
|
||||
- "atmel,sams70n20"
|
||||
- "atmel,sams70n21"
|
||||
- "atmel,sams70q19"
|
||||
- "atmel,sams70q20"
|
||||
- "atmel,sams70q21"
|
||||
o "atmel,samv70" shall be extended with the specific MCU compatible:
|
||||
- "atmel,samv70j19"
|
||||
- "atmel,samv70j20"
|
||||
- "atmel,samv70n19"
|
||||
- "atmel,samv70n20"
|
||||
- "atmel,samv70q19"
|
||||
- "atmel,samv70q20"
|
||||
o "atmel,samv71" shall be extended with the specific MCU compatible:
|
||||
- "atmel,samv71j19"
|
||||
- "atmel,samv71j20"
|
||||
- "atmel,samv71j21"
|
||||
- "atmel,samv71n19"
|
||||
- "atmel,samv71n20"
|
||||
- "atmel,samv71n21"
|
||||
- "atmel,samv71q19"
|
||||
- "atmel,samv71q20"
|
||||
- "atmel,samv71q21"
|
||||
|
||||
Chipid required properties:
|
||||
- compatible: Should be "atmel,sama5d2-chipid"
|
||||
- reg : Should contain registers location and length
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
Actions Semi Owl Smart Power System (SPS)
|
||||
|
||||
Required properties:
|
||||
- compatible : "actions,s500-sps" for S500
|
||||
- reg : Offset and length of the register set for the device.
|
||||
- #power-domain-cells : Must be 1.
|
||||
See macros in:
|
||||
include/dt-bindings/power/owl-s500-powergate.h for S500
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
sps: power-controller@b01b0100 {
|
||||
compatible = "actions,s500-sps";
|
||||
reg = <0xb01b0100 0x100>;
|
||||
#power-domain-cells = <1>;
|
||||
};
|
||||
+16
@@ -1036,6 +1036,22 @@ S: Maintained
|
||||
F: drivers/amba/
|
||||
F: include/linux/amba/bus.h
|
||||
|
||||
ARM/ACTIONS SEMI ARCHITECTURE
|
||||
M: Andreas Färber <afaerber@suse.de>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
N: owl
|
||||
F: arch/arm/mach-actions/
|
||||
F: arch/arm/boot/dts/owl-*
|
||||
F: arch/arm64/boot/dts/actions/
|
||||
F: drivers/clocksource/owl-*
|
||||
F: drivers/soc/actions/
|
||||
F: include/dt-bindings/power/owl-*
|
||||
F: include/linux/soc/actions/
|
||||
F: Documentation/devicetree/bindings/arm/actions.txt
|
||||
F: Documentation/devicetree/bindings/power/actions,owl-sps.txt
|
||||
F: Documentation/devicetree/bindings/timer/actions,owl-timer.txt
|
||||
|
||||
ARM/ADS SPHERE MACHINE SUPPORT
|
||||
M: Lennert Buytenhek <kernel@wantstofly.org>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
|
||||
@@ -712,6 +712,8 @@ config ARCH_VIRT
|
||||
#
|
||||
source "arch/arm/mach-mvebu/Kconfig"
|
||||
|
||||
source "arch/arm/mach-actions/Kconfig"
|
||||
|
||||
source "arch/arm/mach-alpine/Kconfig"
|
||||
|
||||
source "arch/arm/mach-artpec/Kconfig"
|
||||
@@ -1462,6 +1464,7 @@ config ARM_PSCI
|
||||
# selected platforms.
|
||||
config ARCH_NR_GPIO
|
||||
int
|
||||
default 2048 if ARCH_SOCFPGA
|
||||
default 1024 if ARCH_BRCMSTB || ARCH_SHMOBILE || ARCH_TEGRA || \
|
||||
ARCH_ZYNQ
|
||||
default 512 if ARCH_EXYNOS || ARCH_KEYSTONE || SOC_OMAP5 || \
|
||||
|
||||
@@ -145,6 +145,15 @@ choice
|
||||
Say Y here if you want kernel low-level debugging support
|
||||
on the USART3 port of sama5d4.
|
||||
|
||||
config DEBUG_AT91_SAMV7_USART1
|
||||
bool "Kernel low-level debugging via SAMV7 USART1"
|
||||
select DEBUG_AT91_UART
|
||||
depends on SOC_SAMV7
|
||||
help
|
||||
Say Y here if you want the debug print routines to direct
|
||||
their output to the USART1 port on SAMV7 based
|
||||
machines.
|
||||
|
||||
config DEBUG_BCM2835
|
||||
bool "Kernel low-level debugging on BCM2835 PL011 UART"
|
||||
depends on ARCH_BCM2835 && ARCH_MULTI_V6
|
||||
@@ -751,6 +760,7 @@ choice
|
||||
ARCH DEBUG_UART_PHYS DEBUG_UART_VIRT
|
||||
APQ8064 0x16640000 0xf0040000
|
||||
APQ8084 0xf995e000 0xfa75e000
|
||||
IPQ4019 0x078af000 0xf78af000
|
||||
MSM8X60 0x19c40000 0xf0040000
|
||||
MSM8960 0x16440000 0xf0040000
|
||||
MSM8974 0xf991e000 0xfa71e000
|
||||
@@ -776,6 +786,30 @@ choice
|
||||
their output to the standard serial port on the RealView
|
||||
PB1176 platform.
|
||||
|
||||
config DEBUG_RV1108_UART0
|
||||
bool "Kernel low-level debugging messages via Rockchip RV1108 UART0"
|
||||
depends on ARCH_ROCKCHIP
|
||||
select DEBUG_UART_8250
|
||||
help
|
||||
Say Y here if you want kernel low-level debugging support
|
||||
on Rockchip RV1108 based platforms.
|
||||
|
||||
config DEBUG_RV1108_UART1
|
||||
bool "Kernel low-level debugging messages via Rockchip RV1108 UART1"
|
||||
depends on ARCH_ROCKCHIP
|
||||
select DEBUG_UART_8250
|
||||
help
|
||||
Say Y here if you want kernel low-level debugging support
|
||||
on Rockchip RV1108 based platforms.
|
||||
|
||||
config DEBUG_RV1108_UART2
|
||||
bool "Kernel low-level debugging messages via Rockchip RV1108 UART2"
|
||||
depends on ARCH_ROCKCHIP
|
||||
select DEBUG_UART_8250
|
||||
help
|
||||
Say Y here if you want kernel low-level debugging support
|
||||
on Rockchip RV1108 based platforms.
|
||||
|
||||
config DEBUG_RK29_UART0
|
||||
bool "Kernel low-level debugging messages via Rockchip RK29 UART0"
|
||||
depends on ARCH_ROCKCHIP
|
||||
@@ -1465,6 +1499,9 @@ config DEBUG_UART_PHYS
|
||||
default 0x10126000 if DEBUG_RK3X_UART1
|
||||
default 0x101f1000 if DEBUG_VERSATILE
|
||||
default 0x101fb000 if DEBUG_NOMADIK_UART
|
||||
default 0x10210000 if DEBUG_RV1108_UART2
|
||||
default 0x10220000 if DEBUG_RV1108_UART1
|
||||
default 0x10230000 if DEBUG_RV1108_UART0
|
||||
default 0x11002000 if DEBUG_MT8127_UART0
|
||||
default 0x11006000 if DEBUG_MT6589_UART0
|
||||
default 0x11009000 if DEBUG_MT8135_UART3
|
||||
@@ -1481,6 +1518,7 @@ config DEBUG_UART_PHYS
|
||||
default 0x3f201000 if DEBUG_BCM2836
|
||||
default 0x3e000000 if DEBUG_BCM_KONA_UART
|
||||
default 0x4000e400 if DEBUG_LL_UART_EFM32
|
||||
default 0x40028000 if DEBUG_AT91_SAMV7_USART1
|
||||
default 0x40081000 if DEBUG_LPC18XX_UART0
|
||||
default 0x40090000 if DEBUG_LPC32XX
|
||||
default 0x40100000 if DEBUG_PXA_UART1
|
||||
@@ -1563,6 +1601,9 @@ config DEBUG_UART_PHYS
|
||||
|
||||
config DEBUG_UART_VIRT
|
||||
hex "Virtual base address of debug UART"
|
||||
default 0xc881f000 if DEBUG_RV1108_UART2
|
||||
default 0xc8821000 if DEBUG_RV1108_UART1
|
||||
default 0xc8912000 if DEBUG_RV1108_UART0
|
||||
default 0xe0000a00 if DEBUG_NETX_UART
|
||||
default 0xe0010fe0 if ARCH_RPC
|
||||
default 0xf0000be0 if ARCH_EBSA110
|
||||
|
||||
@@ -151,6 +151,7 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000
|
||||
|
||||
# Machine directory name. This list is sorted alphanumerically
|
||||
# by CONFIG_* macro name.
|
||||
machine-$(CONFIG_ARCH_ACTIONS) += actions
|
||||
machine-$(CONFIG_ARCH_ALPINE) += alpine
|
||||
machine-$(CONFIG_ARCH_ARTPEC) += artpec
|
||||
machine-$(CONFIG_ARCH_AT91) += at91
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
menuconfig ARCH_ACTIONS
|
||||
bool "Actions Semi SoCs"
|
||||
depends on ARCH_MULTI_V7
|
||||
select ARM_AMBA
|
||||
select ARM_GIC
|
||||
select ARM_GLOBAL_TIMER
|
||||
select CACHE_L2X0
|
||||
select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
|
||||
select COMMON_CLK
|
||||
select GENERIC_IRQ_CHIP
|
||||
select HAVE_ARM_SCU if SMP
|
||||
select HAVE_ARM_TWD if SMP
|
||||
select OWL_PM_DOMAINS_HELPER
|
||||
select OWL_TIMER
|
||||
help
|
||||
This enables support for the Actions Semiconductor S500 SoC family.
|
||||
@@ -0,0 +1,3 @@
|
||||
obj-${CONFIG_SMP} += platsmp.o headsmp.o
|
||||
|
||||
AFLAGS_headsmp.o := -Wa,-march=armv7-a
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2012 Actions Semi Inc.
|
||||
* Author: Actions Semi, Inc.
|
||||
*
|
||||
* Copyright (c) 2017 Andreas Färber
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
ENTRY(owl_v7_invalidate_l1)
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
|
||||
mcr p15, 2, r0, c0, c0, 0
|
||||
mrc p15, 1, r0, c0, c0, 0
|
||||
|
||||
ldr r1, =0x7fff
|
||||
and r2, r1, r0, lsr #13
|
||||
|
||||
ldr r1, =0x3ff
|
||||
|
||||
and r3, r1, r0, lsr #3 @ NumWays - 1
|
||||
add r2, r2, #1 @ NumSets
|
||||
|
||||
and r0, r0, #0x7
|
||||
add r0, r0, #4 @ SetShift
|
||||
|
||||
clz r1, r3 @ WayShift
|
||||
add r4, r3, #1 @ NumWays
|
||||
1: sub r2, r2, #1 @ NumSets--
|
||||
mov r3, r4 @ Temp = NumWays
|
||||
2: subs r3, r3, #1 @ Temp--
|
||||
mov r5, r3, lsl r1
|
||||
mov r6, r2, lsl r0
|
||||
orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
|
||||
mcr p15, 0, r5, c7, c6, 2
|
||||
bgt 2b
|
||||
cmp r2, #0
|
||||
bgt 1b
|
||||
dsb
|
||||
isb
|
||||
mov pc, lr
|
||||
ENDPROC(owl_v7_invalidate_l1)
|
||||
|
||||
ENTRY(owl_secondary_startup)
|
||||
bl owl_v7_invalidate_l1
|
||||
b secondary_startup
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Actions Semi Leopard
|
||||
*
|
||||
* This file is based on arm realview smp platform.
|
||||
*
|
||||
* Copyright 2012 Actions Semi Inc.
|
||||
* Author: Actions Semi, Inc.
|
||||
*
|
||||
* Copyright (c) 2017 Andreas Färber
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/soc/actions/owl-sps.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include <asm/smp_scu.h>
|
||||
|
||||
#define OWL_CPU1_ADDR 0x50
|
||||
#define OWL_CPU1_FLAG 0x5c
|
||||
|
||||
#define OWL_CPUx_FLAG_BOOT 0x55aa
|
||||
|
||||
#define OWL_SPS_PG_CTL_PWR_CPU2 BIT(5)
|
||||
#define OWL_SPS_PG_CTL_PWR_CPU3 BIT(6)
|
||||
#define OWL_SPS_PG_CTL_ACK_CPU2 BIT(21)
|
||||
#define OWL_SPS_PG_CTL_ACK_CPU3 BIT(22)
|
||||
|
||||
static void __iomem *scu_base_addr;
|
||||
static void __iomem *sps_base_addr;
|
||||
static void __iomem *timer_base_addr;
|
||||
static int ncores;
|
||||
|
||||
static DEFINE_SPINLOCK(boot_lock);
|
||||
|
||||
void owl_secondary_startup(void);
|
||||
|
||||
static int s500_wakeup_secondary(unsigned int cpu)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (cpu > 3)
|
||||
return -EINVAL;
|
||||
|
||||
/* The generic PM domain driver is not available this early. */
|
||||
switch (cpu) {
|
||||
case 2:
|
||||
ret = owl_sps_set_pg(sps_base_addr,
|
||||
OWL_SPS_PG_CTL_PWR_CPU2,
|
||||
OWL_SPS_PG_CTL_ACK_CPU2, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case 3:
|
||||
ret = owl_sps_set_pg(sps_base_addr,
|
||||
OWL_SPS_PG_CTL_PWR_CPU3,
|
||||
OWL_SPS_PG_CTL_ACK_CPU3, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
|
||||
/* wait for CPUx to run to WFE instruction */
|
||||
udelay(200);
|
||||
|
||||
writel(virt_to_phys(owl_secondary_startup),
|
||||
timer_base_addr + OWL_CPU1_ADDR + (cpu - 1) * 4);
|
||||
writel(OWL_CPUx_FLAG_BOOT,
|
||||
timer_base_addr + OWL_CPU1_FLAG + (cpu - 1) * 4);
|
||||
|
||||
dsb_sev();
|
||||
mb();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s500_smp_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
unsigned long timeout;
|
||||
int ret;
|
||||
|
||||
ret = s500_wakeup_secondary(cpu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
udelay(10);
|
||||
|
||||
spin_lock(&boot_lock);
|
||||
|
||||
smp_send_reschedule(cpu);
|
||||
|
||||
timeout = jiffies + (1 * HZ);
|
||||
while (time_before(jiffies, timeout)) {
|
||||
if (pen_release == -1)
|
||||
break;
|
||||
}
|
||||
|
||||
writel(0, timer_base_addr + OWL_CPU1_ADDR + (cpu - 1) * 4);
|
||||
writel(0, timer_base_addr + OWL_CPU1_FLAG + (cpu - 1) * 4);
|
||||
|
||||
spin_unlock(&boot_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init s500_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
struct device_node *node;
|
||||
|
||||
node = of_find_compatible_node(NULL, NULL, "actions,s500-timer");
|
||||
if (!node) {
|
||||
pr_err("%s: missing timer\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
timer_base_addr = of_iomap(node, 0);
|
||||
if (!timer_base_addr) {
|
||||
pr_err("%s: could not map timer registers\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
node = of_find_compatible_node(NULL, NULL, "actions,s500-sps");
|
||||
if (!node) {
|
||||
pr_err("%s: missing sps\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
sps_base_addr = of_iomap(node, 0);
|
||||
if (!sps_base_addr) {
|
||||
pr_err("%s: could not map sps registers\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
|
||||
node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
|
||||
if (!node) {
|
||||
pr_err("%s: missing scu\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
scu_base_addr = of_iomap(node, 0);
|
||||
if (!scu_base_addr) {
|
||||
pr_err("%s: could not map scu registers\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* While the number of cpus is gathered from dt, also get the
|
||||
* number of cores from the scu to verify this value when
|
||||
* booting the cores.
|
||||
*/
|
||||
ncores = scu_get_core_count(scu_base_addr);
|
||||
pr_debug("%s: ncores %d\n", __func__, ncores);
|
||||
|
||||
scu_enable(scu_base_addr);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct smp_operations s500_smp_ops __initconst = {
|
||||
.smp_prepare_cpus = s500_smp_prepare_cpus,
|
||||
.smp_boot_secondary = s500_smp_boot_secondary,
|
||||
};
|
||||
CPU_METHOD_OF_DECLARE(s500_smp, "actions,s500-smp", &s500_smp_ops);
|
||||
@@ -1,6 +1,6 @@
|
||||
menuconfig ARCH_AT91
|
||||
bool "Atmel SoCs"
|
||||
depends on ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V7
|
||||
depends on ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V7 || ARM_SINGLE_ARMV7M
|
||||
select ARM_CPU_SUSPEND if PM
|
||||
select COMMON_CLK_AT91
|
||||
select GPIOLIB
|
||||
@@ -8,6 +8,14 @@ menuconfig ARCH_AT91
|
||||
select SOC_BUS
|
||||
|
||||
if ARCH_AT91
|
||||
config SOC_SAMV7
|
||||
bool "SAM Cortex-M7 family" if ARM_SINGLE_ARMV7M
|
||||
select COMMON_CLK_AT91
|
||||
select PINCTRL_AT91
|
||||
help
|
||||
Select this if you are using an SoC from Atmel's SAME7, SAMS7 or SAMV7
|
||||
families.
|
||||
|
||||
config SOC_SAMA5D2
|
||||
bool "SAMA5D2 family"
|
||||
depends on ARCH_MULTI_V7
|
||||
@@ -53,6 +61,7 @@ config SOC_AT91RM9200
|
||||
bool "AT91RM9200"
|
||||
depends on ARCH_MULTI_V4T
|
||||
select ATMEL_AIC_IRQ
|
||||
select ATMEL_PM if PM
|
||||
select ATMEL_ST
|
||||
select CPU_ARM920T
|
||||
select HAVE_AT91_USB_CLK
|
||||
@@ -66,6 +75,7 @@ config SOC_AT91SAM9
|
||||
bool "AT91SAM9"
|
||||
depends on ARCH_MULTI_V5
|
||||
select ATMEL_AIC_IRQ
|
||||
select ATMEL_PM if PM
|
||||
select ATMEL_SDRAMC
|
||||
select CPU_ARM926T
|
||||
select HAVE_AT91_SMD
|
||||
@@ -124,9 +134,13 @@ config SOC_SAM_V7
|
||||
config SOC_SAMA5
|
||||
bool
|
||||
select ATMEL_AIC5_IRQ
|
||||
select ATMEL_PM if PM
|
||||
select ATMEL_SDRAMC
|
||||
select MEMORY
|
||||
select SOC_SAM_V7
|
||||
select SRAM if PM
|
||||
|
||||
config ATMEL_PM
|
||||
bool
|
||||
|
||||
endif
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o
|
||||
obj-$(CONFIG_SOC_AT91SAM9) += at91sam9.o
|
||||
obj-$(CONFIG_SOC_SAMA5) += sama5.o
|
||||
obj-$(CONFIG_SOC_SAMV7) += samv7.o
|
||||
|
||||
# Power Management
|
||||
obj-$(CONFIG_PM) += pm.o
|
||||
obj-$(CONFIG_PM) += pm_suspend.o
|
||||
obj-$(CONFIG_ATMEL_PM) += pm.o pm_suspend.o
|
||||
|
||||
ifeq ($(CONFIG_CPU_V7),y)
|
||||
AFLAGS_pm_suspend.o := -march=armv7-a
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# Empty file waiting for deletion once Makefile.boot isn't needed any more.
|
||||
# Patch waits for application at
|
||||
# http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=7889/1 .
|
||||
@@ -15,10 +15,12 @@
|
||||
extern void __init at91rm9200_pm_init(void);
|
||||
extern void __init at91sam9_pm_init(void);
|
||||
extern void __init sama5_pm_init(void);
|
||||
extern void __init sama5d2_pm_init(void);
|
||||
#else
|
||||
static inline void __init at91rm9200_pm_init(void) { }
|
||||
static inline void __init at91sam9_pm_init(void) { }
|
||||
static inline void __init sama5_pm_init(void) { }
|
||||
static inline void __init sama5d2_pm_init(void) { }
|
||||
#endif
|
||||
|
||||
#endif /* _AT91_GENERIC_H */
|
||||
|
||||
+178
-28
@@ -15,6 +15,7 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/parser.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include <linux/clk/at91_pmc.h>
|
||||
@@ -22,6 +23,7 @@
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/fncpy.h>
|
||||
#include <asm/system_misc.h>
|
||||
#include <asm/suspend.h>
|
||||
|
||||
#include "generic.h"
|
||||
#include "pm.h"
|
||||
@@ -37,7 +39,17 @@ extern void at91_pinctrl_gpio_suspend(void);
|
||||
extern void at91_pinctrl_gpio_resume(void);
|
||||
#endif
|
||||
|
||||
static struct at91_pm_data pm_data;
|
||||
static const match_table_t pm_modes __initconst = {
|
||||
{ 0, "standby" },
|
||||
{ AT91_PM_SLOW_CLOCK, "ulp0" },
|
||||
{ AT91_PM_BACKUP, "backup" },
|
||||
{ -1, NULL },
|
||||
};
|
||||
|
||||
static struct at91_pm_data pm_data = {
|
||||
.standby_mode = 0,
|
||||
.suspend_mode = AT91_PM_SLOW_CLOCK,
|
||||
};
|
||||
|
||||
#define at91_ramc_read(id, field) \
|
||||
__raw_readl(pm_data.ramc[id] + field)
|
||||
@@ -58,15 +70,33 @@ static int at91_pm_valid_state(suspend_state_t state)
|
||||
}
|
||||
}
|
||||
|
||||
static int canary = 0xA5A5A5A5;
|
||||
|
||||
static suspend_state_t target_state;
|
||||
static struct at91_pm_bu {
|
||||
int suspended;
|
||||
unsigned long reserved;
|
||||
phys_addr_t canary;
|
||||
phys_addr_t resume;
|
||||
} *pm_bu;
|
||||
|
||||
/*
|
||||
* Called after processes are frozen, but before we shutdown devices.
|
||||
*/
|
||||
static int at91_pm_begin(suspend_state_t state)
|
||||
{
|
||||
target_state = state;
|
||||
switch (state) {
|
||||
case PM_SUSPEND_MEM:
|
||||
pm_data.mode = pm_data.suspend_mode;
|
||||
break;
|
||||
|
||||
case PM_SUSPEND_STANDBY:
|
||||
pm_data.mode = pm_data.standby_mode;
|
||||
break;
|
||||
|
||||
default:
|
||||
pm_data.mode = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -115,7 +145,7 @@ static int at91_pm_verify_clocks(void)
|
||||
*/
|
||||
int at91_suspend_entering_slow_clock(void)
|
||||
{
|
||||
return (target_state == PM_SUSPEND_MEM);
|
||||
return (pm_data.mode >= AT91_PM_SLOW_CLOCK);
|
||||
}
|
||||
EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
|
||||
|
||||
@@ -123,50 +153,65 @@ static void (*at91_suspend_sram_fn)(struct at91_pm_data *);
|
||||
extern void at91_pm_suspend_in_sram(struct at91_pm_data *pm_data);
|
||||
extern u32 at91_pm_suspend_in_sram_sz;
|
||||
|
||||
static void at91_pm_suspend(suspend_state_t state)
|
||||
static int at91_suspend_finish(unsigned long val)
|
||||
{
|
||||
pm_data.mode = (state == PM_SUSPEND_MEM) ? AT91_PM_SLOW_CLOCK : 0;
|
||||
|
||||
flush_cache_all();
|
||||
outer_disable();
|
||||
|
||||
at91_suspend_sram_fn(&pm_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void at91_pm_suspend(suspend_state_t state)
|
||||
{
|
||||
if (pm_data.mode == AT91_PM_BACKUP) {
|
||||
pm_bu->suspended = 1;
|
||||
|
||||
cpu_suspend(0, at91_suspend_finish);
|
||||
|
||||
/* The SRAM is lost between suspend cycles */
|
||||
at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn,
|
||||
&at91_pm_suspend_in_sram,
|
||||
at91_pm_suspend_in_sram_sz);
|
||||
} else {
|
||||
at91_suspend_finish(0);
|
||||
}
|
||||
|
||||
outer_resume();
|
||||
}
|
||||
|
||||
/*
|
||||
* STANDBY mode has *all* drivers suspended; ignores irqs not marked as 'wakeup'
|
||||
* event sources; and reduces DRAM power. But otherwise it's identical to
|
||||
* PM_SUSPEND_ON: cpu idle, and nothing fancy done with main or cpu clocks.
|
||||
*
|
||||
* AT91_PM_SLOW_CLOCK is like STANDBY plus slow clock mode, so drivers must
|
||||
* suspend more deeply, the master clock switches to the clk32k and turns off
|
||||
* the main oscillator
|
||||
*
|
||||
* AT91_PM_BACKUP turns off the whole SoC after placing the DDR in self refresh
|
||||
*/
|
||||
static int at91_pm_enter(suspend_state_t state)
|
||||
{
|
||||
#ifdef CONFIG_PINCTRL_AT91
|
||||
at91_pinctrl_gpio_suspend();
|
||||
#endif
|
||||
|
||||
switch (state) {
|
||||
/*
|
||||
* Suspend-to-RAM is like STANDBY plus slow clock mode, so
|
||||
* drivers must suspend more deeply, the master clock switches
|
||||
* to the clk32k and turns off the main oscillator
|
||||
*/
|
||||
case PM_SUSPEND_MEM:
|
||||
case PM_SUSPEND_STANDBY:
|
||||
/*
|
||||
* Ensure that clocks are in a valid state.
|
||||
*/
|
||||
if (!at91_pm_verify_clocks())
|
||||
if ((pm_data.mode >= AT91_PM_SLOW_CLOCK) &&
|
||||
!at91_pm_verify_clocks())
|
||||
goto error;
|
||||
|
||||
at91_pm_suspend(state);
|
||||
|
||||
break;
|
||||
|
||||
/*
|
||||
* STANDBY mode has *all* drivers suspended; ignores irqs not
|
||||
* marked as 'wakeup' event sources; and reduces DRAM power.
|
||||
* But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and
|
||||
* nothing fancy done with main or cpu clocks.
|
||||
*/
|
||||
case PM_SUSPEND_STANDBY:
|
||||
at91_pm_suspend(state);
|
||||
break;
|
||||
|
||||
case PM_SUSPEND_ON:
|
||||
cpu_do_idle();
|
||||
break;
|
||||
@@ -177,8 +222,6 @@ static int at91_pm_enter(suspend_state_t state)
|
||||
}
|
||||
|
||||
error:
|
||||
target_state = PM_SUSPEND_ON;
|
||||
|
||||
#ifdef CONFIG_PINCTRL_AT91
|
||||
at91_pinctrl_gpio_resume();
|
||||
#endif
|
||||
@@ -190,7 +233,6 @@ error:
|
||||
*/
|
||||
static void at91_pm_end(void)
|
||||
{
|
||||
target_state = PM_SUSPEND_ON;
|
||||
}
|
||||
|
||||
|
||||
@@ -436,6 +478,79 @@ static void __init at91_pm_sram_init(void)
|
||||
&at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
|
||||
}
|
||||
|
||||
static void __init at91_pm_backup_init(void)
|
||||
{
|
||||
struct gen_pool *sram_pool;
|
||||
struct device_node *np;
|
||||
struct platform_device *pdev = NULL;
|
||||
|
||||
if ((pm_data.standby_mode != AT91_PM_BACKUP) &&
|
||||
(pm_data.suspend_mode != AT91_PM_BACKUP))
|
||||
return;
|
||||
|
||||
pm_bu = NULL;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-shdwc");
|
||||
if (!np) {
|
||||
pr_warn("%s: failed to find shdwc!\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
pm_data.shdwc = of_iomap(np, 0);
|
||||
of_node_put(np);
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
|
||||
if (!np) {
|
||||
pr_warn("%s: failed to find sfrbu!\n", __func__);
|
||||
goto sfrbu_fail;
|
||||
}
|
||||
|
||||
pm_data.sfrbu = of_iomap(np, 0);
|
||||
of_node_put(np);
|
||||
pm_bu = NULL;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam");
|
||||
if (!np)
|
||||
goto securam_fail;
|
||||
|
||||
pdev = of_find_device_by_node(np);
|
||||
of_node_put(np);
|
||||
if (!pdev) {
|
||||
pr_warn("%s: failed to find securam device!\n", __func__);
|
||||
goto securam_fail;
|
||||
}
|
||||
|
||||
sram_pool = gen_pool_get(&pdev->dev, NULL);
|
||||
if (!sram_pool) {
|
||||
pr_warn("%s: securam pool unavailable!\n", __func__);
|
||||
goto securam_fail;
|
||||
}
|
||||
|
||||
pm_bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
|
||||
if (!pm_bu) {
|
||||
pr_warn("%s: unable to alloc securam!\n", __func__);
|
||||
goto securam_fail;
|
||||
}
|
||||
|
||||
pm_bu->suspended = 0;
|
||||
pm_bu->canary = virt_to_phys(&canary);
|
||||
pm_bu->resume = virt_to_phys(cpu_resume);
|
||||
|
||||
return;
|
||||
|
||||
sfrbu_fail:
|
||||
iounmap(pm_data.shdwc);
|
||||
pm_data.shdwc = NULL;
|
||||
securam_fail:
|
||||
iounmap(pm_data.sfrbu);
|
||||
pm_data.sfrbu = NULL;
|
||||
|
||||
if (pm_data.standby_mode == AT91_PM_BACKUP)
|
||||
pm_data.standby_mode = AT91_PM_SLOW_CLOCK;
|
||||
if (pm_data.suspend_mode == AT91_PM_BACKUP)
|
||||
pm_data.suspend_mode = AT91_PM_SLOW_CLOCK;
|
||||
}
|
||||
|
||||
struct pmc_info {
|
||||
unsigned long uhp_udp_mask;
|
||||
};
|
||||
@@ -481,10 +596,14 @@ static void __init at91_pm_init(void (*pm_idle)(void))
|
||||
|
||||
at91_pm_sram_init();
|
||||
|
||||
if (at91_suspend_sram_fn)
|
||||
if (at91_suspend_sram_fn) {
|
||||
suspend_set_ops(&at91_pm_ops);
|
||||
else
|
||||
pr_info("AT91: PM: standby: %s, suspend: %s\n",
|
||||
pm_modes[pm_data.standby_mode].pattern,
|
||||
pm_modes[pm_data.suspend_mode].pattern);
|
||||
} else {
|
||||
pr_info("AT91: PM not supported, due to no SRAM allocated\n");
|
||||
}
|
||||
}
|
||||
|
||||
void __init at91rm9200_pm_init(void)
|
||||
@@ -510,3 +629,34 @@ void __init sama5_pm_init(void)
|
||||
at91_dt_ramc();
|
||||
at91_pm_init(NULL);
|
||||
}
|
||||
|
||||
void __init sama5d2_pm_init(void)
|
||||
{
|
||||
at91_pm_backup_init();
|
||||
sama5_pm_init();
|
||||
}
|
||||
|
||||
static int __init at91_pm_modes_select(char *str)
|
||||
{
|
||||
char *s;
|
||||
substring_t args[MAX_OPT_ARGS];
|
||||
int standby, suspend;
|
||||
|
||||
if (!str)
|
||||
return 0;
|
||||
|
||||
s = strsep(&str, ",");
|
||||
standby = match_token(s, pm_modes, args);
|
||||
if (standby < 0)
|
||||
return 0;
|
||||
|
||||
suspend = match_token(str, pm_modes, args);
|
||||
if (suspend < 0)
|
||||
return 0;
|
||||
|
||||
pm_data.standby_mode = standby;
|
||||
pm_data.suspend_mode = suspend;
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_param("atmel.pm_modes", at91_pm_modes_select);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define AT91_MEMCTRL_DDRSDR 2
|
||||
|
||||
#define AT91_PM_SLOW_CLOCK 0x01
|
||||
#define AT91_PM_BACKUP 0x02
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
struct at91_pm_data {
|
||||
@@ -30,6 +31,10 @@ struct at91_pm_data {
|
||||
unsigned long uhp_udp_mask;
|
||||
unsigned int memctrl;
|
||||
unsigned int mode;
|
||||
void __iomem *shdwc;
|
||||
void __iomem *sfrbu;
|
||||
unsigned int standby_mode;
|
||||
unsigned int suspend_mode;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -9,5 +9,8 @@ int main(void)
|
||||
DEFINE(PM_DATA_RAMC1, offsetof(struct at91_pm_data, ramc[1]));
|
||||
DEFINE(PM_DATA_MEMCTRL, offsetof(struct at91_pm_data, memctrl));
|
||||
DEFINE(PM_DATA_MODE, offsetof(struct at91_pm_data, mode));
|
||||
DEFINE(PM_DATA_SHDWC, offsetof(struct at91_pm_data, shdwc));
|
||||
DEFINE(PM_DATA_SFRBU, offsetof(struct at91_pm_data, sfrbu));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -97,15 +97,61 @@ ENTRY(at91_pm_suspend_in_sram)
|
||||
str tmp1, .memtype
|
||||
ldr tmp1, [r0, #PM_DATA_MODE]
|
||||
str tmp1, .pm_mode
|
||||
/* Both ldrne below are here to preload their address in the TLB */
|
||||
ldr tmp1, [r0, #PM_DATA_SHDWC]
|
||||
str tmp1, .shdwc
|
||||
cmp tmp1, #0
|
||||
ldrne tmp2, [tmp1, #0]
|
||||
ldr tmp1, [r0, #PM_DATA_SFRBU]
|
||||
str tmp1, .sfr
|
||||
cmp tmp1, #0
|
||||
ldrne tmp2, [tmp1, #0x10]
|
||||
|
||||
/* Active the self-refresh mode */
|
||||
mov r0, #SRAMC_SELF_FRESH_ACTIVE
|
||||
bl at91_sramc_self_refresh
|
||||
|
||||
ldr r0, .pm_mode
|
||||
tst r0, #AT91_PM_SLOW_CLOCK
|
||||
beq skip_disable_main_clock
|
||||
cmp r0, #AT91_PM_SLOW_CLOCK
|
||||
beq slow_clock
|
||||
cmp r0, #AT91_PM_BACKUP
|
||||
beq backup_mode
|
||||
|
||||
/* Wait for interrupt */
|
||||
ldr pmc, .pmc_base
|
||||
at91_cpu_idle
|
||||
b exit_suspend
|
||||
|
||||
slow_clock:
|
||||
bl at91_slowck_mode
|
||||
b exit_suspend
|
||||
backup_mode:
|
||||
bl at91_backup_mode
|
||||
b exit_suspend
|
||||
|
||||
exit_suspend:
|
||||
/* Exit the self-refresh mode */
|
||||
mov r0, #SRAMC_SELF_FRESH_EXIT
|
||||
bl at91_sramc_self_refresh
|
||||
|
||||
/* Restore registers, and return */
|
||||
ldmfd sp!, {r4 - r12, pc}
|
||||
ENDPROC(at91_pm_suspend_in_sram)
|
||||
|
||||
ENTRY(at91_backup_mode)
|
||||
/*BUMEN*/
|
||||
ldr r0, .sfr
|
||||
mov tmp1, #0x1
|
||||
str tmp1, [r0, #0x10]
|
||||
|
||||
/* Shutdown */
|
||||
ldr r0, .shdwc
|
||||
mov tmp1, #0xA5000000
|
||||
add tmp1, tmp1, #0x1
|
||||
str tmp1, [r0, #0]
|
||||
ENDPROC(at91_backup_mode)
|
||||
|
||||
ENTRY(at91_slowck_mode)
|
||||
ldr pmc, .pmc_base
|
||||
|
||||
/* Save Master clock setting */
|
||||
@@ -134,18 +180,9 @@ ENTRY(at91_pm_suspend_in_sram)
|
||||
orr tmp1, tmp1, #AT91_PMC_KEY
|
||||
str tmp1, [pmc, #AT91_CKGR_MOR]
|
||||
|
||||
skip_disable_main_clock:
|
||||
ldr pmc, .pmc_base
|
||||
|
||||
/* Wait for interrupt */
|
||||
at91_cpu_idle
|
||||
|
||||
ldr r0, .pm_mode
|
||||
tst r0, #AT91_PM_SLOW_CLOCK
|
||||
beq skip_enable_main_clock
|
||||
|
||||
ldr pmc, .pmc_base
|
||||
|
||||
/* Turn on the main oscillator */
|
||||
ldr tmp1, [pmc, #AT91_CKGR_MOR]
|
||||
orr tmp1, tmp1, #AT91_PMC_MOSCEN
|
||||
@@ -174,14 +211,8 @@ skip_disable_main_clock:
|
||||
|
||||
wait_mckrdy
|
||||
|
||||
skip_enable_main_clock:
|
||||
/* Exit the self-refresh mode */
|
||||
mov r0, #SRAMC_SELF_FRESH_EXIT
|
||||
bl at91_sramc_self_refresh
|
||||
|
||||
/* Restore registers, and return */
|
||||
ldmfd sp!, {r4 - r12, pc}
|
||||
ENDPROC(at91_pm_suspend_in_sram)
|
||||
mov pc, lr
|
||||
ENDPROC(at91_slowck_mode)
|
||||
|
||||
/*
|
||||
* void at91_sramc_self_refresh(unsigned int is_active)
|
||||
@@ -314,6 +345,10 @@ ENDPROC(at91_sramc_self_refresh)
|
||||
.word 0
|
||||
.sramc1_base:
|
||||
.word 0
|
||||
.shdwc:
|
||||
.word 0
|
||||
.sfr:
|
||||
.word 0
|
||||
.memtype:
|
||||
.word 0
|
||||
.pm_mode:
|
||||
|
||||
@@ -34,7 +34,6 @@ DT_MACHINE_START(sama5_dt, "Atmel SAMA5")
|
||||
MACHINE_END
|
||||
|
||||
static const char *const sama5_alt_dt_board_compat[] __initconst = {
|
||||
"atmel,sama5d2",
|
||||
"atmel,sama5d4",
|
||||
NULL
|
||||
};
|
||||
@@ -45,3 +44,21 @@ DT_MACHINE_START(sama5_alt_dt, "Atmel SAMA5")
|
||||
.dt_compat = sama5_alt_dt_board_compat,
|
||||
.l2c_aux_mask = ~0UL,
|
||||
MACHINE_END
|
||||
|
||||
static void __init sama5d2_init(void)
|
||||
{
|
||||
of_platform_default_populate(NULL, NULL, NULL);
|
||||
sama5d2_pm_init();
|
||||
}
|
||||
|
||||
static const char *const sama5d2_compat[] __initconst = {
|
||||
"atmel,sama5d2",
|
||||
NULL
|
||||
};
|
||||
|
||||
DT_MACHINE_START(sama5d2, "Atmel SAMA5")
|
||||
/* Maintainer: Atmel */
|
||||
.init_machine = sama5d2_init,
|
||||
.dt_compat = sama5d2_compat,
|
||||
.l2c_aux_mask = ~0UL,
|
||||
MACHINE_END
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user