summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig.debug89
-rw-r--r--arch/arm/boot/dts/tegra124-jetson-tk1.dts7
-rw-r--r--arch/arm/include/debug/msm.S6
-rw-r--r--arch/arm/include/debug/sirf.S30
-rw-r--r--arch/arm/mach-bcm/platsmp-brcmstb.c85
-rw-r--r--arch/arm/mach-hisi/Kconfig8
-rw-r--r--arch/arm/mach-hisi/core.h5
-rw-r--r--arch/arm/mach-hisi/headsmp.S2
-rw-r--r--arch/arm/mach-hisi/hisilicon.c10
-rw-r--r--arch/arm/mach-hisi/hotplug.c31
-rw-r--r--arch/arm/mach-hisi/platsmp.c56
-rw-r--r--arch/arm/mach-imx/Makefile3
-rw-r--r--arch/arm/mach-imx/clk-gate2.c23
-rw-r--r--arch/arm/mach-imx/clk-imx6q.c2
-rw-r--r--arch/arm/mach-imx/clk-pllv3.c10
-rw-r--r--arch/arm/mach-imx/clk-vf610.c8
-rw-r--r--arch/arm/mach-imx/clk.h1
-rw-r--r--arch/arm/mach-imx/common.h4
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6sx.c105
-rw-r--r--arch/arm/mach-imx/cpuidle.h5
-rw-r--r--arch/arm/mach-imx/gpc.c25
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c2
-rw-r--r--arch/arm/mach-imx/mach-imx6sx.c2
-rw-r--r--arch/arm/mach-imx/mach-vf610.c5
-rw-r--r--arch/arm/mach-imx/pm-imx6.c7
-rw-r--r--arch/arm/mach-mediatek/Kconfig22
-rw-r--r--arch/arm/mach-mvebu/coherency.c51
-rw-r--r--arch/arm/mach-mvebu/mvebu-soc-id.h18
-rw-r--r--arch/arm/mach-prima2/Kconfig22
-rw-r--r--arch/arm/mach-prima2/Makefile1
-rw-r--r--arch/arm/mach-prima2/common.c22
-rw-r--r--arch/arm/mach-prima2/lluart.c35
-rw-r--r--arch/arm/mach-prima2/platsmp.c52
-rw-r--r--arch/arm/mach-prima2/rstc.c41
-rw-r--r--arch/arm/mach-prima2/rtciobrg.c1
-rw-r--r--arch/arm/mach-qcom/Kconfig3
-rw-r--r--arch/arm/mach-qcom/scm-boot.c10
-rw-r--r--arch/arm/mach-qcom/scm-boot.h4
-rw-r--r--arch/arm/mach-qcom/scm.c85
-rw-r--r--arch/arm/mach-rockchip/Makefile1
-rw-r--r--arch/arm/mach-rockchip/pm.c260
-rw-r--r--arch/arm/mach-rockchip/pm.h99
-rw-r--r--arch/arm/mach-rockchip/rockchip.c4
-rw-r--r--arch/arm/mach-rockchip/sleep.S73
-rw-r--r--arch/arm/mach-shmobile/Kconfig8
-rw-r--r--arch/arm/mach-shmobile/clock-sh73a0.c10
-rw-r--r--arch/arm/mach-shmobile/pm-r8a7740.c14
-rw-r--r--arch/arm/mach-shmobile/pm-rmobile.c314
-rw-r--r--arch/arm/mach-shmobile/pm-rmobile.h3
-rw-r--r--arch/arm/mach-shmobile/pm-sh7372.c11
-rw-r--r--arch/arm/mach-shmobile/setup-rcar-gen2.c4
-rw-r--r--arch/arm/mach-shmobile/smp-r8a7779.c2
-rw-r--r--arch/arm/mach-sti/board-dt.c1
-rw-r--r--arch/arm/mach-tegra/Kconfig4
54 files changed, 1381 insertions, 325 deletions
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 575db67a61d..453ae2feaee 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -278,6 +278,14 @@ choice
Say Y here if you want the debug print routines to direct
their output to the UART on Highbank based devices.
+ config DEBUG_HIP01_UART
+ bool "Hisilicon Hip01 Debug UART"
+ depends on ARCH_HIP01
+ select DEBUG_UART_8250
+ help
+ Say Y here if you want kernel low-level debugging support
+ on HIP01 UART.
+
config DEBUG_HIP04_UART
bool "Hisilicon HiP04 Debug UART"
depends on ARCH_HIP04
@@ -433,7 +441,7 @@ choice
Say Y here if you want the debug print routines to direct
their output to the serial port on MSM devices.
- ARCH DEBUG_UART_PHYS DEBUG_UART_BASE #
+ ARCH DEBUG_UART_PHYS DEBUG_UART_VIRT #
MSM7X00A, QSD8X50 0xa9a00000 0xe1000000 UART1
MSM7X00A, QSD8X50 0xa9b00000 0xe1000000 UART2
MSM7X00A, QSD8X50 0xa9c00000 0xe1000000 UART3
@@ -452,7 +460,8 @@ choice
Say Y here if you want the debug print routines to direct
their output to the serial port on Qualcomm devices.
- ARCH DEBUG_UART_PHYS DEBUG_UART_BASE
+ ARCH DEBUG_UART_PHYS DEBUG_UART_VIRT
+ APQ8064 0x16640000 0xf0040000
APQ8084 0xf995e000 0xfa75e000
MSM8X60 0x19c40000 0xf0040000
MSM8960 0x16440000 0xf0040000
@@ -461,13 +470,13 @@ choice
Please adjust DEBUG_UART_PHYS and DEBUG_UART_BASE configuration
options based on your needs.
- config DEBUG_MVEBU_UART
- bool "Kernel low-level debugging messages via MVEBU UART (old bootloaders)"
+ config DEBUG_MVEBU_UART0
+ bool "Kernel low-level debugging messages via MVEBU UART0 (old bootloaders)"
depends on ARCH_MVEBU
select DEBUG_UART_8250
help
Say Y here if you want kernel low-level debugging support
- on MVEBU based platforms.
+ on MVEBU based platforms on UART0.
This option should be used with the old bootloaders
that left the internal registers mapped at
@@ -480,13 +489,28 @@ choice
when u-boot hands over to the kernel, the system
silently crashes, with no serial output at all.
- config DEBUG_MVEBU_UART_ALTERNATE
- bool "Kernel low-level debugging messages via MVEBU UART (new bootloaders)"
+ config DEBUG_MVEBU_UART0_ALTERNATE
+ bool "Kernel low-level debugging messages via MVEBU UART0 (new bootloaders)"
depends on ARCH_MVEBU
select DEBUG_UART_8250
help
Say Y here if you want kernel low-level debugging support
- on MVEBU based platforms.
+ on MVEBU based platforms on UART0.
+
+ This option should be used with the new bootloaders
+ that remap the internal registers at 0xf1000000.
+
+ If the wrong DEBUG_MVEBU_UART* option is selected,
+ when u-boot hands over to the kernel, the system
+ silently crashes, with no serial output at all.
+
+ config DEBUG_MVEBU_UART1_ALTERNATE
+ bool "Kernel low-level debugging messages via MVEBU UART1 (new bootloaders)"
+ depends on ARCH_MVEBU
+ select DEBUG_UART_8250
+ help
+ Say Y here if you want kernel low-level debugging support
+ on MVEBU based platforms on UART1.
This option should be used with the new bootloaders
that remap the internal registers at 0xf1000000.
@@ -922,16 +946,28 @@ choice
config DEBUG_SIRFPRIMA2_UART1
bool "Kernel low-level debugging messages via SiRFprimaII UART1"
depends on ARCH_PRIMA2
+ select DEBUG_SIRFSOC_UART
help
Say Y here if you want the debug print routines to direct
their output to the uart1 port on SiRFprimaII devices.
- config DEBUG_SIRFMARCO_UART1
- bool "Kernel low-level debugging messages via SiRFmarco UART1"
- depends on ARCH_MARCO
+ config DEBUG_SIRFATLAS7_UART0
+ bool "Kernel low-level debugging messages via SiRFatlas7 UART0"
+ depends on ARCH_ATLAS7
+ select DEBUG_SIRFSOC_UART
help
Say Y here if you want the debug print routines to direct
- their output to the uart1 port on SiRFmarco devices.
+ their output to the uart0 port on SiRFATLAS7 devices.The uart0
+ is used on SiRFATLAS7 as a extra debug port.sometimes an extra
+ debug port can be very useful.
+
+ config DEBUG_SIRFATLAS7_UART1
+ bool "Kernel low-level debugging messages via SiRFatlas7 UART1"
+ depends on ARCH_ATLAS7
+ select DEBUG_SIRFSOC_UART
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to the uart1 port on SiRFATLAS7 devices.
config STIH41X_DEBUG_ASC2
bool "Use StiH415/416 ASC2 UART for low-level debug"
@@ -979,7 +1015,7 @@ choice
for Mediatek mt6589 based platforms on UART0.
config DEBUG_MT8127_UART0
- bool "Mediatek mt8127 UART0"
+ bool "Mediatek mt8127/mt6592 UART0"
depends on ARCH_MEDIATEK
select DEBUG_UART_8250
help
@@ -1171,6 +1207,10 @@ config DEBUG_STI_UART
bool
depends on ARCH_STI
+config DEBUG_SIRFSOC_UART
+ bool
+ depends on ARCH_SIRF
+
config DEBUG_LL_INCLUDE
string
default "debug/sa1100.S" if DEBUG_SA1100
@@ -1206,7 +1246,7 @@ config DEBUG_LL_INCLUDE
default "debug/renesas-scif.S" if DEBUG_RMOBILE_SCIFA4
default "debug/s3c24xx.S" if DEBUG_S3C24XX_UART
default "debug/s5pv210.S" if DEBUG_S5PV210_UART
- default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1
+ default "debug/sirf.S" if DEBUG_SIRFSOC_UART
default "debug/sti.S" if DEBUG_STI_UART
default "debug/tegra.S" if DEBUG_TEGRA_UART
default "debug/ux500.S" if DEBUG_UX500_UART
@@ -1262,7 +1302,10 @@ config DEBUG_UART_PHYS
default 0x11009000 if DEBUG_MT8135_UART3
default 0x16000000 if ARCH_INTEGRATOR
default 0x18000300 if DEBUG_BCM_5301X
+ default 0x18010000 if DEBUG_SIRFATLAS7_UART0
+ default 0x18020000 if DEBUG_SIRFATLAS7_UART1
default 0x1c090000 if DEBUG_VEXPRESS_UART0_RS1
+ default 0x20001000 if DEBUG_HIP01_UART
default 0x20060000 if DEBUG_RK29_UART0
default 0x20064000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2
default 0x20068000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3
@@ -1288,12 +1331,13 @@ config DEBUG_UART_PHYS
default 0x808c0000 if ARCH_EP93XX
default 0x90020000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART
default 0xa9a00000 if DEBUG_MSM_UART
+ default 0xb0060000 if DEBUG_SIRFPRIMA2_UART1
default 0xb0090000 if DEBUG_VEXPRESS_UART0_CRX
default 0xc0013000 if DEBUG_U300_UART
default 0xc8000000 if ARCH_IXP4XX && !CPU_BIG_ENDIAN
default 0xc8000003 if ARCH_IXP4XX && CPU_BIG_ENDIAN
default 0xd0000000 if ARCH_SPEAR3XX || ARCH_SPEAR6XX
- default 0xd0012000 if DEBUG_MVEBU_UART
+ default 0xd0012000 if DEBUG_MVEBU_UART0
default 0xc81004c0 if DEBUG_MESON_UARTAO
default 0xd4017000 if DEBUG_MMP_UART2
default 0xd4018000 if DEBUG_MMP_UART3
@@ -1307,7 +1351,8 @@ config DEBUG_UART_PHYS
default 0xe8008000 if DEBUG_R7S72100_SCIF2
default 0xf0000be0 if ARCH_EBSA110
default 0xf040ab00 if DEBUG_BRCMSTB_UART
- default 0xf1012000 if DEBUG_MVEBU_UART_ALTERNATE
+ default 0xf1012000 if DEBUG_MVEBU_UART0_ALTERNATE
+ default 0xf1012100 if DEBUG_MVEBU_UART1_ALTERNATE
default 0xf1012000 if ARCH_DOVE || ARCH_MV78XX0 || \
ARCH_ORION5X
default 0xf7fc9000 if DEBUG_BERLIN_UART
@@ -1331,7 +1376,8 @@ config DEBUG_UART_PHYS
DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF2 || \
DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \
DEBUG_RMOBILE_SCIFA4 || DEBUG_S3C24XX_UART || \
- DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART
+ DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || \
+ DEBUG_SIRFSOC_UART
config DEBUG_UART_VIRT
hex "Virtual base address of debug UART"
@@ -1388,8 +1434,12 @@ config DEBUG_UART_VIRT
default 0xfeb30c00 if DEBUG_KEYSTONE_UART0
default 0xfeb31000 if DEBUG_KEYSTONE_UART1
default 0xfec02000 if DEBUG_SOCFPGA_UART
- default 0xfec12000 if DEBUG_MVEBU_UART || DEBUG_MVEBU_UART_ALTERNATE
+ default 0xfec12000 if DEBUG_MVEBU_UART0 || DEBUG_MVEBU_UART0_ALTERNATE
+ default 0xfec12100 if DEBUG_MVEBU_UART1_ALTERNATE
+ default 0xfec10000 if DEBUG_SIRFATLAS7_UART0
default 0xfec20000 if DEBUG_DAVINCI_DMx_UART0
+ default 0xfec20000 if DEBUG_SIRFATLAS7_UART1
+ default 0xfec60000 if DEBUG_SIRFPRIMA2_UART1
default 0xfec90000 if DEBUG_RK32_UART2
default 0xfed0c000 if DEBUG_DAVINCI_DA8XX_UART1
default 0xfed0d000 if DEBUG_DAVINCI_DA8XX_UART2
@@ -1405,11 +1455,12 @@ config DEBUG_UART_VIRT
default 0xfef36000 if DEBUG_HIGHBANK_UART
default 0xfefff700 if ARCH_IOP33X
default 0xff003000 if DEBUG_U300_UART
+ default 0xffd01000 if DEBUG_HIP01_UART
default DEBUG_UART_PHYS if !MMU
depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \
DEBUG_MSM_UART || DEBUG_QCOM_UARTDM || DEBUG_S3C24XX_UART || \
- DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART
+ DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || DEBUG_SIRFSOC_UART
config DEBUG_UART_8250_SHIFT
int "Register offset shift for the 8250 debug UART"
diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
index 4eb540be368..dbfaba09703 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
@@ -1673,6 +1673,13 @@
nvidia,core-pwr-off-time = <61036>;
nvidia,core-power-req-active-high;
nvidia,sys-clock-req-active-high;
+
+ i2c-thermtrip {
+ nvidia,i2c-controller-id = <4>;
+ nvidia,bus-addr = <0x40>;
+ nvidia,reg-addr = <0x36>;
+ nvidia,reg-data = <0x2>;
+ };
};
/* Serial ATA */
diff --git a/arch/arm/include/debug/msm.S b/arch/arm/include/debug/msm.S
index 9ef57612811..e55a9426b49 100644
--- a/arch/arm/include/debug/msm.S
+++ b/arch/arm/include/debug/msm.S
@@ -23,6 +23,7 @@
.endm
.macro senduart, rd, rx
+ARM_BE8(rev \rd, \rd )
#ifdef CONFIG_DEBUG_QCOM_UARTDM
@ Write the 1 character to UARTDM_TF
str \rd, [\rx, #0x70]
@@ -35,24 +36,29 @@
#ifdef CONFIG_DEBUG_QCOM_UARTDM
@ check for TX_EMT in UARTDM_SR
ldr \rd, [\rx, #0x08]
+ARM_BE8(rev \rd, \rd )
tst \rd, #0x08
bne 1002f
@ wait for TXREADY in UARTDM_ISR
1001: ldr \rd, [\rx, #0x14]
+ARM_BE8(rev \rd, \rd )
tst \rd, #0x80
beq 1001b
1002:
@ Clear TX_READY by writing to the UARTDM_CR register
mov \rd, #0x300
+ARM_BE8(rev \rd, \rd )
str \rd, [\rx, #0x10]
@ Write 0x1 to NCF register
mov \rd, #0x1
+ARM_BE8(rev \rd, \rd )
str \rd, [\rx, #0x40]
@ UARTDM reg. Read to induce delay
ldr \rd, [\rx, #0x08]
#else
@ wait for TX_READY
1001: ldr \rd, [\rx, #0x08]
+ARM_BE8(rev \rd, \rd )
tst \rd, #0x04
beq 1001b
#endif
diff --git a/arch/arm/include/debug/sirf.S b/arch/arm/include/debug/sirf.S
index dbf250cf18e..630f231f2f3 100644
--- a/arch/arm/include/debug/sirf.S
+++ b/arch/arm/include/debug/sirf.S
@@ -6,37 +6,33 @@
* Licensed under GPLv2 or later.
*/
-#if defined(CONFIG_DEBUG_SIRFPRIMA2_UART1)
-#define SIRFSOC_UART1_PA_BASE 0xb0060000
-#elif defined(CONFIG_DEBUG_SIRFMARCO_UART1)
-#define SIRFSOC_UART1_PA_BASE 0xcc060000
-#else
-#define SIRFSOC_UART1_PA_BASE 0
-#endif
+#define SIRF_LLUART_TXFIFO_STATUS 0x0114
+#define SIRF_LLUART_TXFIFO_DATA 0x0118
-#define SIRFSOC_UART1_VA_BASE 0xFEC60000
+#define SIRF_LLUART_TXFIFO_FULL (1 << 5)
-#define SIRFSOC_UART_TXFIFO_STATUS 0x0114
-#define SIRFSOC_UART_TXFIFO_DATA 0x0118
+#ifdef CONFIG_DEBUG_SIRFATLAS7_UART0
+#define SIRF_LLUART_TXFIFO_EMPTY (1 << 8)
+#else
+#define SIRF_LLUART_TXFIFO_EMPTY (1 << 6)
+#endif
-#define SIRFSOC_UART1_TXFIFO_FULL (1 << 5)
-#define SIRFSOC_UART1_TXFIFO_EMPTY (1 << 6)
.macro addruart, rp, rv, tmp
- ldr \rp, =SIRFSOC_UART1_PA_BASE @ physical
- ldr \rv, =SIRFSOC_UART1_VA_BASE @ virtual
+ ldr \rp, =CONFIG_DEBUG_UART_PHYS @ physical
+ ldr \rv, =CONFIG_DEBUG_UART_VIRT @ virtual
.endm
.macro senduart,rd,rx
- str \rd, [\rx, #SIRFSOC_UART_TXFIFO_DATA]
+ str \rd, [\rx, #SIRF_LLUART_TXFIFO_DATA]
.endm
.macro busyuart,rd,rx
.endm
.macro waituart,rd,rx
-1001: ldr \rd, [\rx, #SIRFSOC_UART_TXFIFO_STATUS]
- tst \rd, #SIRFSOC_UART1_TXFIFO_EMPTY
+1001: ldr \rd, [\rx, #SIRF_LLUART_TXFIFO_STATUS]
+ tst \rd, #SIRF_LLUART_TXFIFO_EMPTY
beq 1001b
.endm
diff --git a/arch/arm/mach-bcm/platsmp-brcmstb.c b/arch/arm/mach-bcm/platsmp-brcmstb.c
index 31c87a284a3..e209e6fc7ca 100644
--- a/arch/arm/mach-bcm/platsmp-brcmstb.c
+++ b/arch/arm/mach-bcm/platsmp-brcmstb.c
@@ -17,6 +17,7 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/jiffies.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/printk.h>
@@ -94,10 +95,35 @@ static u32 pwr_ctrl_rd(u32 cpu)
return readl_relaxed(base);
}
-static void pwr_ctrl_wr(u32 cpu, u32 val)
+static void pwr_ctrl_set(unsigned int cpu, u32 val, u32 mask)
{
void __iomem *base = pwr_ctrl_get_base(cpu);
- writel(val, base);
+ writel((readl(base) & mask) | val, base);
+}
+
+static void pwr_ctrl_clr(unsigned int cpu, u32 val, u32 mask)
+{
+ void __iomem *base = pwr_ctrl_get_base(cpu);
+ writel((readl(base) & mask) & ~val, base);
+}
+
+#define POLL_TMOUT_MS 500
+static int pwr_ctrl_wait_tmout(unsigned int cpu, u32 set, u32 mask)
+{
+ const unsigned long timeo = jiffies + msecs_to_jiffies(POLL_TMOUT_MS);
+ u32 tmp;
+
+ do {
+ tmp = pwr_ctrl_rd(cpu) & mask;
+ if (!set == !tmp)
+ return 0;
+ } while (time_before(jiffies, timeo));
+
+ tmp = pwr_ctrl_rd(cpu) & mask;
+ if (!set == !tmp)
+ return 0;
+
+ return -ETIMEDOUT;
}
static void cpu_rst_cfg_set(u32 cpu, int set)
@@ -139,15 +165,22 @@ static void brcmstb_cpu_power_on(u32 cpu)
* The secondary cores power was cut, so we must go through
* power-on initialization.
*/
- u32 tmp;
+ pwr_ctrl_set(cpu, ZONE_MAN_ISO_CNTL_MASK, 0xffffff00);
+ pwr_ctrl_set(cpu, ZONE_MANUAL_CONTROL_MASK, -1);
+ pwr_ctrl_set(cpu, ZONE_RESERVED_1_MASK, -1);
- /* Request zone power up */
- pwr_ctrl_wr(cpu, ZONE_PWR_UP_REQ_MASK);
+ pwr_ctrl_set(cpu, ZONE_MAN_MEM_PWR_MASK, -1);
- /* Wait for the power up FSM to complete */
- do {
- tmp = pwr_ctrl_rd(cpu);
- } while (!(tmp & ZONE_PWR_ON_STATE_MASK));
+ if (pwr_ctrl_wait_tmout(cpu, 1, ZONE_MEM_PWR_STATE_MASK))
+ panic("ZONE_MEM_PWR_STATE_MASK set timeout");
+
+ pwr_ctrl_set(cpu, ZONE_MAN_CLKEN_MASK, -1);
+
+ if (pwr_ctrl_wait_tmout(cpu, 1, ZONE_DPG_PWR_STATE_MASK))
+ panic("ZONE_DPG_PWR_STATE_MASK set timeout");
+
+ pwr_ctrl_clr(cpu, ZONE_MAN_ISO_CNTL_MASK, -1);
+ pwr_ctrl_set(cpu, ZONE_MAN_RESET_CNTL_MASK, -1);
}
static int brcmstb_cpu_get_power_state(u32 cpu)
@@ -174,25 +207,33 @@ static void brcmstb_cpu_die(u32 cpu)
static int brcmstb_cpu_kill(u32 cpu)
{
- u32 tmp;
+ /*
+ * Ordinarily, the hardware forbids power-down of CPU0 (which is good
+ * because it is the boot CPU), but this is not true when using BPCM
+ * manual mode. Consequently, we must avoid turning off CPU0 here to
+ * ensure that TI2C master reset will work.
+ */
+ if (cpu == 0) {
+ pr_warn("SMP: refusing to power off CPU0\n");
+ return 1;
+ }
while (per_cpu_sw_state_rd(cpu))
;
- /* Program zone reset */
- pwr_ctrl_wr(cpu, ZONE_RESET_STATE_MASK | ZONE_BLK_RST_ASSERT_MASK |
- ZONE_PWR_DN_REQ_MASK);
+ pwr_ctrl_set(cpu, ZONE_MANUAL_CONTROL_MASK, -1);
+ pwr_ctrl_clr(cpu, ZONE_MAN_RESET_CNTL_MASK, -1);
+ pwr_ctrl_clr(cpu, ZONE_MAN_CLKEN_MASK, -1);
+ pwr_ctrl_set(cpu, ZONE_MAN_ISO_CNTL_MASK, -1);
+ pwr_ctrl_clr(cpu, ZONE_MAN_MEM_PWR_MASK, -1);
- /* Verify zone reset */
- tmp = pwr_ctrl_rd(cpu);
- if (!(tmp & ZONE_RESET_STATE_MASK))
- pr_err("%s: Zone reset bit for CPU %d not asserted!\n",
- __func__, cpu);
+ if (pwr_ctrl_wait_tmout(cpu, 0, ZONE_MEM_PWR_STATE_MASK))
+ panic("ZONE_MEM_PWR_STATE_MASK clear timeout");
- /* Wait for power down */
- do {
- tmp = pwr_ctrl_rd(cpu);
- } while (!(tmp & ZONE_PWR_OFF_STATE_MASK));
+ pwr_ctrl_clr(cpu, ZONE_RESERVED_1_MASK, -1);
+
+ if (pwr_ctrl_wait_tmout(cpu, 0, ZONE_DPG_PWR_STATE_MASK))
+ panic("ZONE_DPG_PWR_STATE_MASK clear timeout");
/* Flush pipeline before resetting CPU */
mb();
diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig
index cd19433f76d..83061ad0e28 100644
--- a/arch/arm/mach-hisi/Kconfig
+++ b/arch/arm/mach-hisi/Kconfig
@@ -22,6 +22,14 @@ config ARCH_HI3xxx
help
Support for Hisilicon Hi36xx SoC family
+config ARCH_HIP01
+ bool "Hisilicon HIP01 family" if ARCH_MULTI_V7
+ select HAVE_ARM_SCU if SMP
+ select HAVE_ARM_TWD if SMP
+ select ARM_GLOBAL_TIMER
+ help
+ Support for Hisilicon HIP01 SoC family
+
config ARCH_HIP04
bool "Hisilicon HiP04 Cortex A15 family" if ARCH_MULTI_V7
select ARM_ERRATA_798181 if SMP
diff --git a/arch/arm/mach-hisi/core.h b/arch/arm/mach-hisi/core.h
index 88b1f487d06..92a682d8e93 100644
--- a/arch/arm/mach-hisi/core.h
+++ b/arch/arm/mach-hisi/core.h
@@ -12,9 +12,12 @@ extern void hi3xxx_cpu_die(unsigned int cpu);
extern int hi3xxx_cpu_kill(unsigned int cpu);
extern void hi3xxx_set_cpu(int cpu, bool enable);
-extern void hix5hd2_secondary_startup(void);
+extern void hisi_secondary_startup(void);
extern struct smp_operations hix5hd2_smp_ops;
extern void hix5hd2_set_cpu(int cpu, bool enable);
extern void hix5hd2_cpu_die(unsigned int cpu);
+extern struct smp_operations hip01_smp_ops;
+extern void hip01_set_cpu(int cpu, bool enable);
+extern void hip01_cpu_die(unsigned int cpu);
#endif
diff --git a/arch/arm/mach-hisi/headsmp.S b/arch/arm/mach-hisi/headsmp.S
index 278889c00b7..81e35b159e7 100644
--- a/arch/arm/mach-hisi/headsmp.S
+++ b/arch/arm/mach-hisi/headsmp.S
@@ -11,6 +11,6 @@
__CPUINIT
-ENTRY(hix5hd2_secondary_startup)
+ENTRY(hisi_secondary_startup)
bl v7_invalidate_l1
b secondary_startup
diff --git a/arch/arm/mach-hisi/hisilicon.c b/arch/arm/mach-hisi/hisilicon.c
index 7744c351bbf..76b907078b5 100644
--- a/arch/arm/mach-hisi/hisilicon.c
+++ b/arch/arm/mach-hisi/hisilicon.c
@@ -72,3 +72,13 @@ static const char *hip04_compat[] __initconst = {
DT_MACHINE_START(HIP04, "Hisilicon HiP04 (Flattened Device Tree)")
.dt_compat = hip04_compat,
MACHINE_END
+
+static const char *hip01_compat[] __initconst = {
+ "hisilicon,hip01",
+ "hisilicon,hip01-ca9x2",
+ NULL,
+};
+
+DT_MACHINE_START(HIP01, "Hisilicon HIP01 (Flattened Device Tree)")
+ .dt_compat = hip01_compat,
+MACHINE_END
diff --git a/arch/arm/mach-hisi/hotplug.c b/arch/arm/mach-hisi/hotplug.c
index 84e6919f68c..a129aae7260 100644
--- a/arch/arm/mach-hisi/hotplug.c
+++ b/arch/arm/mach-hisi/hotplug.c
@@ -65,6 +65,9 @@
#define PMC0_CPU1_PMC_ENABLE (1 << 7)
#define PMC0_CPU1_POWERDOWN (1 << 3)
+#define HIP01_PERI9 0x50
+#define PERI9_CPU1_RESET (1 << 1)
+
enum {
HI3620_CTRL,
ERROR_CTRL,
@@ -209,6 +212,34 @@ void hix5hd2_set_cpu(int cpu, bool enable)
}
}
+void hip01_set_cpu(int cpu, bool enable)
+{
+ unsigned int temp;
+ struct device_node *np;
+
+ if (!ctrl_base) {
+ np = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl");
+ if (np)
+ ctrl_base = of_iomap(np, 0);
+ else
+ BUG();
+ }
+
+ if (enable) {
+ /* reset on CPU1 */
+ temp = readl_relaxed(ctrl_base + HIP01_PERI9);
+ temp |= PERI9_CPU1_RESET;
+ writel_relaxed(temp, ctrl_base + HIP01_PERI9);
+
+ udelay(50);
+
+ /* unreset on CPU1 */
+ temp = readl_relaxed(ctrl_base + HIP01_PERI9);
+ temp &= ~PERI9_CPU1_RESET;
+ writel_relaxed(temp, ctrl_base + HIP01_PERI9);
+ }
+}
+
static inline void cpu_enter_lowpower(void)
{
unsigned int v;
diff --git a/arch/arm/mach-hisi/platsmp.c b/arch/arm/mach-hisi/platsmp.c
index 575dd8285f1..8880c8e8b29 100644
--- a/arch/arm/mach-hisi/platsmp.c
+++ b/arch/arm/mach-hisi/platsmp.c
@@ -10,10 +10,12 @@
#include <linux/smp.h>
#include <linux/io.h>
#include <linux/of_address.h>
+#include <linux/delay.h>
#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
+#include <asm/mach/map.h>
#include "core.h"
@@ -96,7 +98,7 @@ struct smp_operations hi3xxx_smp_ops __initdata = {
#endif
};
-static void __init hix5hd2_smp_prepare_cpus(unsigned int max_cpus)
+static void __init hisi_common_smp_prepare_cpus(unsigned int max_cpus)
{
hisi_enable_scu_a9();
}
@@ -116,7 +118,7 @@ static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
phys_addr_t jumpaddr;
- jumpaddr = virt_to_phys(hix5hd2_secondary_startup);
+ jumpaddr = virt_to_phys(hisi_secondary_startup);
hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr);
hix5hd2_set_cpu(cpu, true);
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
@@ -125,12 +127,60 @@ static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle)
struct smp_operations hix5hd2_smp_ops __initdata = {
- .smp_prepare_cpus = hix5hd2_smp_prepare_cpus,
+ .smp_prepare_cpus = hisi_common_smp_prepare_cpus,
.smp_boot_secondary = hix5hd2_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_die = hix5hd2_cpu_die,
#endif
};
+
+#define SC_SCTL_REMAP_CLR 0x00000100
+#define HIP01_BOOT_ADDRESS 0x80000000
+#define REG_SC_CTRL 0x000
+
+void hip01_set_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr)
+{
+ void __iomem *virt;
+
+ virt = phys_to_virt(start_addr);
+
+ writel_relaxed(0xe51ff004, virt);
+ writel_relaxed(jump_addr, virt + 4);
+}
+
+static int hip01_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ phys_addr_t jumpaddr;
+ unsigned int remap_reg_value = 0;
+ struct device_node *node;
+
+
+ jumpaddr = virt_to_phys(hisi_secondary_startup);
+ hip01_set_boot_addr(HIP01_BOOT_ADDRESS, jumpaddr);
+
+ node = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl");
+ if (WARN_ON(!node))
+ return -1;
+ ctrl_base = of_iomap(node, 0);
+
+ /* set the secondary core boot from DDR */
+ remap_reg_value = readl_relaxed(ctrl_base + REG_SC_CTRL);
+ barrier();
+ remap_reg_value |= SC_SCTL_REMAP_CLR;
+ barrier();
+ writel_relaxed(remap_reg_value, ctrl_base + REG_SC_CTRL);
+
+ hip01_set_cpu(cpu, true);
+
+ return 0;
+}
+
+struct smp_operations hip01_smp_ops __initdata = {
+ .smp_prepare_cpus = hisi_common_smp_prepare_cpus,
+ .smp_boot_secondary = hip01_boot_secondary,
+};
+
CPU_METHOD_OF_DECLARE(hi3xxx_smp, "hisilicon,hi3620-smp", &hi3xxx_smp_ops);
CPU_METHOD_OF_DECLARE(hix5hd2_smp, "hisilicon,hix5hd2-smp", &hix5hd2_smp_ops);
+CPU_METHOD_OF_DECLARE(hip01_smp, "hisilicon,hip01-smp", &hip01_smp_ops);
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index f5ac685a29f..8d1b1018090 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -32,8 +32,7 @@ ifeq ($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o
obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o
-# i.MX6SX reuses i.MX6Q cpuidle driver
-obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6q.o
+obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o
endif
ifdef CONFIG_SND_IMX_SOC
diff --git a/arch/arm/mach-imx/clk-gate2.c b/arch/arm/mach-imx/clk-gate2.c
index 5a75cdc8189..8935bff99fe 100644
--- a/arch/arm/mach-imx/clk-gate2.c
+++ b/arch/arm/mach-imx/clk-gate2.c
@@ -96,15 +96,30 @@ static int clk_gate2_is_enabled(struct clk_hw *hw)
{
struct clk_gate2 *gate = to_clk_gate2(hw);
- if (gate->share_count)
- return !!__clk_get_enable_count(hw->clk);
- else
- return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
+ return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
+}
+
+static void clk_gate2_disable_unused(struct clk_hw *hw)
+{
+ struct clk_gate2 *gate = to_clk_gate2(hw);
+ unsigned long flags = 0;
+ u32 reg;
+
+ spin_lock_irqsave(gate->lock, flags);
+
+ if (!gate->share_count || *gate->share_count == 0) {
+ reg = readl(gate->reg);
+ reg &= ~(3 << gate->bit_idx);
+ writel(reg, gate->reg);
+ }
+
+ spin_unlock_irqrestore(gate->lock, flags);
}
static struct clk_ops clk_gate2_ops = {
.enable = clk_gate2_enable,
.disable = clk_gate2_disable,
+ .disable_unused = clk_gate2_disable_unused,
.is_enabled = clk_gate2_is_enabled,
};
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 5951660d1bd..108b80bb048 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -386,7 +386,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6Q_CLK_ECSPI5] = imx_clk_gate2("ecspi5", "ecspi_root", base + 0x6c, 8);
clk[IMX6QDL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x6c, 10);
clk[IMX6QDL_CLK_ESAI_EXTAL] = imx_clk_gate2_shared("esai_extal", "esai_podf", base + 0x6c, 16, &share_count_esai);
- clk[IMX6QDL_CLK_ESAI_IPG] = imx_clk_gate2_shared("esai_ipg", "ipg", base + 0x6c, 16, &share_count_esai);
+ clk[IMX6QDL_CLK_ESAI_IPG] = imx_clk_gate2_shared("esai_ipg", "ahb", base + 0x6c, 16, &share_count_esai);
clk[IMX6QDL_CLK_ESAI_MEM] = imx_clk_gate2_shared("esai_mem", "ahb", base + 0x6c, 16, &share_count_esai);
clk[IMX6QDL_CLK_GPT_IPG] = imx_clk_gate2("gpt_ipg", "ipg", base + 0x6c, 20);
clk[IMX6QDL_CLK_GPT_IPG_PER] = imx_clk_gate2("gpt_ipg_per", "ipg_per", base + 0x6c, 22);
diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c
index 0ad6e5442fd..641ebc50892 100644
--- a/arch/arm/mach-imx/clk-pllv3.c
+++ b/arch/arm/mach-imx/clk-pllv3.c
@@ -31,6 +31,7 @@
* @base: base address of PLL registers
* @powerup_set: set POWER bit to power up the PLL
* @div_mask: mask of divider bits
+ * @div_shift: shift of divider bits
*
* IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3
* is actually a multiplier, and always sits at bit 0.
@@ -40,6 +41,7 @@ struct clk_pllv3 {
void __iomem *base;
bool powerup_set;
u32 div_mask;
+ u32 div_shift;
};
#define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw)
@@ -97,7 +99,7 @@ static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
- u32 div = readl_relaxed(pll->base) & pll->div_mask;
+ u32 div = (readl_relaxed(pll->base) >> pll->div_shift) & pll->div_mask;
return (div == 1) ? parent_rate * 22 : parent_rate * 20;
}
@@ -125,8 +127,8 @@ static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate,
return -EINVAL;
val = readl_relaxed(pll->base);
- val &= ~pll->div_mask;
- val |= div;
+ val &= ~(pll->div_mask << pll->div_shift);
+ val |= (div << pll->div_shift);
writel_relaxed(val, pll->base);
return clk_pllv3_wait_lock(pll);
@@ -295,6 +297,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
case IMX_PLLV3_SYS:
ops = &clk_pllv3_sys_ops;
break;
+ case IMX_PLLV3_USB_VF610:
+ pll->div_shift = 1;
case IMX_PLLV3_USB:
ops = &clk_pllv3_ops;
pll->powerup_set = true;
diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c
index 5937ddee1a9..61876ed6e11 100644
--- a/arch/arm/mach-imx/clk-vf610.c
+++ b/arch/arm/mach-imx/clk-vf610.c
@@ -172,11 +172,11 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1);
clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1);
- clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x1);
+ clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x2);
clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f);
clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3);
clk[VF610_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_AV, "pll6", "pll6_bypass_src", PLL6_CTRL, 0x7f);
- clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", PLL7_CTRL, 0x1);
+ clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll7", "pll7_bypass_src", PLL7_CTRL, 0x2);
clk[VF610_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", PLL1_CTRL, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
clk[VF610_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", PLL2_CTRL, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
@@ -267,6 +267,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_UART1] = imx_clk_gate2("uart1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(8));
clk[VF610_CLK_UART2] = imx_clk_gate2("uart2", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(9));
clk[VF610_CLK_UART3] = imx_clk_gate2("uart3", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(10));
+ clk[VF610_CLK_UART4] = imx_clk_gate2("uart4", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(9));
+ clk[VF610_CLK_UART5] = imx_clk_gate2("uart5", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(10));
clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(6));
clk[VF610_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(7));
@@ -380,6 +382,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_DMAMUX2] = imx_clk_gate2("dmamux2", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(1));
clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(2));
+ clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(7));
+
imx_check_clocks(clk, ARRAY_SIZE(clk));
clk_set_parent(clk[VF610_CLK_QSPI0_SEL], clk[VF610_CLK_PLL1_PFD4]);
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index 5ef82e2f8fc..6a07903a28b 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -20,6 +20,7 @@ enum imx_pllv3_type {
IMX_PLLV3_GENERIC,
IMX_PLLV3_SYS,
IMX_PLLV3_USB,
+ IMX_PLLV3_USB_VF610,
IMX_PLLV3_AV,
IMX_PLLV3_ENET,
};
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index cfcdb623d78..1028b6c505c 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -70,6 +70,10 @@ void imx_set_soc_revision(unsigned int rev);
unsigned int imx_get_soc_revision(void);
void imx_init_revision_from_anatop(void);
struct device *imx_soc_device_init(void);
+void imx6_enable_rbc(bool enable);
+void imx_gpc_set_arm_power_in_lpm(bool power_off);
+void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw);
+void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw);
enum mxc_cpu_pwr_mode {
WAIT_CLOCKED, /* wfi only */
diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c
new file mode 100644
index 00000000000..5a36722b089
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx6sx.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/cpuidle.h>
+#include <linux/cpu_pm.h>
+#include <linux/module.h>
+#include <asm/cpuidle.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+
+#include "common.h"
+#include "cpuidle.h"
+
+static int imx6sx_idle_finish(unsigned long val)
+{
+ cpu_do_idle();
+
+ return 0;
+}
+
+static int imx6sx_enter_wait(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ imx6q_set_lpm(WAIT_UNCLOCKED);
+
+ switch (index) {
+ case 1:
+ cpu_do_idle();
+ break;
+ case 2:
+ imx6_enable_rbc(true);
+ imx_gpc_set_arm_power_in_lpm(true);
+ imx_set_cpu_jump(0, v7_cpu_resume);
+ /* Need to notify there is a cpu pm operation. */
+ cpu_pm_enter();
+ cpu_cluster_pm_enter();
+
+ cpu_suspend(0, imx6sx_idle_finish);
+
+ cpu_cluster_pm_exit();
+ cpu_pm_exit();
+ imx_gpc_set_arm_power_in_lpm(false);
+ imx6_enable_rbc(false);
+ break;
+ default:
+ break;
+ }
+
+ imx6q_set_lpm(WAIT_CLOCKED);
+
+ return index;
+}
+
+static struct cpuidle_driver imx6sx_cpuidle_driver = {
+ .name = "imx6sx_cpuidle",
+ .owner = THIS_MODULE,
+ .states = {
+ /* WFI */
+ ARM_CPUIDLE_WFI_STATE,
+ /* WAIT */
+ {
+ .exit_latency = 50,
+ .target_residency = 75,
+ .flags = CPUIDLE_FLAG_TIMER_STOP,
+ .enter = imx6sx_enter_wait,
+ .name = "WAIT",
+ .desc = "Clock off",
+ },
+ /* WAIT + ARM power off */
+ {
+ /*
+ * ARM gating 31us * 5 + RBC clear 65us
+ * and some margin for SW execution, here set it
+ * to 300us.
+ */
+ .exit_latency = 300,
+ .target_residency = 500,
+ .enter = imx6sx_enter_wait,
+ .name = "LOW-POWER-IDLE",
+ .desc = "ARM power off",
+ },
+ },
+ .state_count = 3,
+ .safe_state_index = 0,
+};
+
+int __init imx6sx_cpuidle_init(void)
+{
+ imx6_enable_rbc(false);
+ /*
+ * set ARM power up/down timing to the fastest,
+ * sw2iso and sw can be set to one 32K cycle = 31us
+ * except for power up sw2iso which need to be
+ * larger than LDO ramp up time.
+ */
+ imx_gpc_set_arm_power_up_timing(2, 1);
+ imx_gpc_set_arm_power_down_timing(1, 1);
+
+ return cpuidle_register(&imx6sx_cpuidle_driver, NULL);
+}
diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h
index 24e33670417..f9140128ba0 100644
--- a/arch/arm/mach-imx/cpuidle.h
+++ b/arch/arm/mach-imx/cpuidle.h
@@ -14,6 +14,7 @@
extern int imx5_cpuidle_init(void);
extern int imx6q_cpuidle_init(void);
extern int imx6sl_cpuidle_init(void);
+extern int imx6sx_cpuidle_init(void);
#else
static inline int imx5_cpuidle_init(void)
{
@@ -27,4 +28,8 @@ static inline int imx6sl_cpuidle_init(void)
{
return 0;
}
+static inline int imx6sx_cpuidle_init(void)
+{
+ return 0;
+}
#endif
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 5f3602ec74f..745caa18ab2 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -20,6 +20,10 @@
#define GPC_IMR1 0x008
#define GPC_PGC_CPU_PDN 0x2a0
+#define GPC_PGC_CPU_PUPSCR 0x2a4
+#define GPC_PGC_CPU_PDNSCR 0x2a8
+#define GPC_PGC_SW2ISO_SHIFT 0x8
+#define GPC_PGC_SW_SHIFT 0x0
#define IMR_NUM 4
@@ -27,6 +31,23 @@ static void __iomem *gpc_base;
static u32 gpc_wake_irqs[IMR_NUM];
static u32 gpc_saved_imrs[IMR_NUM];
+void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw)
+{
+ writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) |
+ (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PUPSCR);
+}
+
+void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw)
+{
+ writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) |
+ (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PDNSCR);
+}
+
+void imx_gpc_set_arm_power_in_lpm(bool power_off)
+{
+ writel_relaxed(power_off, gpc_base + GPC_PGC_CPU_PDN);
+}
+
void imx_gpc_pre_suspend(bool arm_power_off)
{
void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
@@ -34,7 +55,7 @@ void imx_gpc_pre_suspend(bool arm_power_off)
/* Tell GPC to power off ARM core when suspend */
if (arm_power_off)
- writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
+ imx_gpc_set_arm_power_in_lpm(arm_power_off);
for (i = 0; i < IMR_NUM; i++) {
gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
@@ -48,7 +69,7 @@ void imx_gpc_post_resume(void)
int i;
/* Keep ARM core powered on for other low-power modes */
- writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN);
+ imx_gpc_set_arm_power_in_lpm(false);
for (i = 0; i < IMR_NUM; i++)
writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 5057d61298b..4ad6e473cf8 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -329,7 +329,7 @@ static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev)
if (dev_pm_opp_disable(cpu_dev, 852000000))
pr_warn("failed to disable 852 MHz OPP\n");
}
-
+ iounmap(base);
put_node:
of_node_put(np);
}
diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
index 7a96c657723..66988eb6a3a 100644
--- a/arch/arm/mach-imx/mach-imx6sx.c
+++ b/arch/arm/mach-imx/mach-imx6sx.c
@@ -90,7 +90,7 @@ static void __init imx6sx_init_irq(void)
static void __init imx6sx_init_late(void)
{
- imx6q_cpuidle_init();
+ imx6sx_cpuidle_init();
if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c
index c11ab6a1dc8..2e7c75b66fe 100644
--- a/arch/arm/mach-imx/mach-vf610.c
+++ b/arch/arm/mach-imx/mach-vf610.c
@@ -13,11 +13,14 @@
#include <asm/hardware/cache-l2x0.h>
static const char * const vf610_dt_compat[] __initconst = {
+ "fsl,vf500",
+ "fsl,vf510",
+ "fsl,vf600",
"fsl,vf610",
NULL,
};
-DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)")
+DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF5xx/VF6xx (Device Tree)")
.l2c_aux_val = 0,
.l2c_aux_mask = ~0,
.dt_compat = vf610_dt_compat,
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index 5d2c1bd5f5e..46fd695203c 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -205,7 +205,7 @@ void imx6q_set_int_mem_clk_lpm(bool enable)
writel_relaxed(val, ccm_base + CGPR);
}
-static void imx6q_enable_rbc(bool enable)
+void imx6_enable_rbc(bool enable)
{
u32 val;
@@ -359,17 +359,16 @@ static int imx6q_pm_enter(suspend_state_t state)
* RBC setting, so we do NOT need to do that here.
*/
if (!imx6_suspend_in_ocram_fn)
- imx6q_enable_rbc(true);
+ imx6_enable_rbc(true);
imx_gpc_pre_suspend(true);
imx_anatop_pre_suspend();
- imx_set_cpu_jump(0, v7_cpu_resume);
/* Zzz ... */
cpu_suspend(0, imx6q_suspend_finish);
if (cpu_is_imx6q() || cpu_is_imx6dl())
imx_smp_prepare();
imx_anatop_post_resume();
imx_gpc_post_resume();
- imx6q_enable_rbc(false);
+ imx6_enable_rbc(false);
imx6q_enable_wb(false);
imx6q_set_int_mem_clk_lpm(true);
imx6q_set_lpm(WAIT_CLOCKED);
diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
index f73f588f649..f7e463ca028 100644
--- a/arch/arm/mach-mediatek/Kconfig
+++ b/arch/arm/mach-mediatek/Kconfig
@@ -1,6 +1,26 @@
-config ARCH_MEDIATEK
+menuconfig ARCH_MEDIATEK
bool "Mediatek MT65xx & MT81xx SoC" if ARCH_MULTI_V7
select ARM_GIC
select MTK_TIMER
help
Support for Mediatek MT65xx & MT81xx SoCs
+
+if ARCH_MEDIATEK
+
+config MACH_MT6589
+ bool "MediaTek MT6589 SoCs support"
+ default ARCH_MEDIATEK
+
+config MACH_MT6592
+ bool "MediaTek MT6592 SoCs support"
+ default ARCH_MEDIATEK
+
+config MACH_MT8127
+ bool "MediaTek MT8127 SoCs support"
+ default ARCH_MEDIATEK
+
+config MACH_MT8135
+ bool "MediaTek MT8135 SoCs support"
+ default ARCH_MEDIATEK
+
+endif
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index 3585cb394e9..440799ba664 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -33,6 +33,7 @@
#include <asm/smp_plat.h>
#include <asm/cacheflush.h>
#include <asm/mach/map.h>
+#include <asm/dma-mapping.h>
#include "coherency.h"
#include "mvebu-soc-id.h"
@@ -76,54 +77,6 @@ int set_cpu_coherent(void)
return ll_enable_coherency();
}
-static inline void mvebu_hwcc_sync_io_barrier(void)
-{
- writel(0x1, coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET);
- while (readl(coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET) & 0x1);
-}
-
-static dma_addr_t mvebu_hwcc_dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction dir,
- struct dma_attrs *attrs)
-{
- if (dir != DMA_TO_DEVICE)
- mvebu_hwcc_sync_io_barrier();
- return pfn_to_dma(dev, page_to_pfn(page)) + offset;
-}
-
-
-static void mvebu_hwcc_dma_unmap_page(struct device *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
-{
- if (dir != DMA_TO_DEVICE)
- mvebu_hwcc_sync_io_barrier();
-}
-
-static void mvebu_hwcc_dma_sync(struct device *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction dir)
-{
- if (dir != DMA_TO_DEVICE)
- mvebu_hwcc_sync_io_barrier();
-}
-
-static struct dma_map_ops mvebu_hwcc_dma_ops = {
- .alloc = arm_dma_alloc,
- .free = arm_dma_free,
- .mmap = arm_dma_mmap,
- .map_page = mvebu_hwcc_dma_map_page,
- .unmap_page = mvebu_hwcc_dma_unmap_page,
- .get_sgtable = arm_dma_get_sgtable,
- .map_sg = arm_dma_map_sg,
- .unmap_sg = arm_dma_unmap_sg,
- .sync_single_for_cpu = mvebu_hwcc_dma_sync,
- .sync_single_for_device = mvebu_hwcc_dma_sync,
- .sync_sg_for_cpu = arm_dma_sync_sg_for_cpu,
- .sync_sg_for_device = arm_dma_sync_sg_for_device,
- .set_dma_mask = arm_dma_set_mask,
-};
-
static int mvebu_hwcc_notifier(struct notifier_block *nb,
unsigned long event, void *__dev)
{
@@ -131,7 +84,7 @@ static int mvebu_hwcc_notifier(struct notifier_block *nb,
if (event != BUS_NOTIFY_ADD_DEVICE)
return NOTIFY_DONE;
- set_dma_ops(dev, &mvebu_hwcc_dma_ops);
+ set_dma_ops(dev, &arm_coherent_dma_ops);
return NOTIFY_OK;
}
diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.h b/arch/arm/mach-mvebu/mvebu-soc-id.h
index c16bb68ca81..e124a0b82a3 100644
--- a/arch/arm/mach-mvebu/mvebu-soc-id.h
+++ b/arch/arm/mach-mvebu/mvebu-soc-id.h
@@ -20,10 +20,28 @@
#define MV78XX0_A0_REV 0x1
#define MV78XX0_B0_REV 0x2
+/* Amada 370 ID */
+#define ARMADA_370_DEV_ID 0x6710
+
+/* Amada 370 Revision */
+#define ARMADA_370_A1_REV 0x1
+
+/* Armada 375 ID */
+#define ARMADA_375_DEV_ID 0x6720
+
/* Armada 375 */
#define ARMADA_375_Z1_REV 0x0
#define ARMADA_375_A0_REV 0x3
+/* Armada 38x ID */
+#define ARMADA_380_DEV_ID 0x6810
+#define ARMADA_385_DEV_ID 0x6820
+#define ARMADA_388_DEV_ID 0x6828
+
+/* Armada 38x Revision */
+#define ARMADA_38x_Z1_REV 0x0
+#define ARMADA_38x_A0_REV 0x4
+
#ifdef CONFIG_ARCH_MVEBU
int mvebu_get_soc_id(u32 *dev, u32 *rev);
#else
diff --git a/arch/arm/mach-prima2/Kconfig b/arch/arm/mach-prima2/Kconfig
index 042f693ef42..a219dc310d5 100644
--- a/arch/arm/mach-prima2/Kconfig
+++ b/arch/arm/mach-prima2/Kconfig
@@ -11,7 +11,7 @@ menuconfig ARCH_SIRF
if ARCH_SIRF
-comment "CSR SiRF atlas6/primaII/Marco/Polo Specific Features"
+comment "CSR SiRF atlas6/primaII/Atlas7 Specific Features"
config ARCH_ATLAS6
bool "CSR SiRFSoC ATLAS6 ARM Cortex A9 Platform"
@@ -20,6 +20,17 @@ config ARCH_ATLAS6
help
Support for CSR SiRFSoC ARM Cortex A9 Platform
+config ARCH_ATLAS7
+ bool "CSR SiRFSoC ATLAS7 ARM Cortex A7 Platform"
+ default y
+ select ARM_GIC
+ select CPU_V7
+ select HAVE_ARM_SCU if SMP
+ select HAVE_SMP
+ select SMP_ON_UP if SMP
+ help
+ Support for CSR SiRFSoC ARM Cortex A7 Platform
+
config ARCH_PRIMA2
bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform"
default y
@@ -28,15 +39,6 @@ config ARCH_PRIMA2
help
Support for CSR SiRFSoC ARM Cortex A9 Platform
-config ARCH_MARCO
- bool "CSR SiRFSoC MARCO ARM Cortex A9 Platform"
- default y
- select ARM_GIC
- select HAVE_ARM_SCU if SMP
- select SMP_ON_UP if SMP
- help
- Support for CSR SiRFSoC ARM Cortex A9 Platform
-
config SIRF_IRQ
bool
diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile
index 8846e7d87ea..d7d02b04344 100644
--- a/arch/arm/mach-prima2/Makefile
+++ b/arch/arm/mach-prima2/Makefile
@@ -1,7 +1,6 @@
obj-y += rstc.o
obj-y += common.o
obj-y += rtciobrg.o
-obj-$(CONFIG_DEBUG_LL) += lluart.o
obj-$(CONFIG_SUSPEND) += pm.o sleep.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
diff --git a/arch/arm/mach-prima2/common.c b/arch/arm/mach-prima2/common.c
index a860ea27e8a..0c819bb8841 100644
--- a/arch/arm/mach-prima2/common.c
+++ b/arch/arm/mach-prima2/common.c
@@ -20,12 +20,6 @@ static void __init sirfsoc_init_late(void)
sirfsoc_pm_init();
}
-static __init void sirfsoc_map_io(void)
-{
- sirfsoc_map_lluart();
- sirfsoc_map_scu();
-}
-
#ifdef CONFIG_ARCH_ATLAS6
static const char *atlas6_dt_match[] __initconst = {
"sirf,atlas6",
@@ -36,7 +30,6 @@ DT_MACHINE_START(ATLAS6_DT, "Generic ATLAS6 (Flattened Device Tree)")
/* Maintainer: Barry Song <baohua.song@csr.com> */
.l2c_aux_val = 0,
.l2c_aux_mask = ~0,
- .map_io = sirfsoc_map_io,
.init_late = sirfsoc_init_late,
.dt_compat = atlas6_dt_match,
MACHINE_END
@@ -52,26 +45,21 @@ DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
/* Maintainer: Barry Song <baohua.song@csr.com> */
.l2c_aux_val = 0,
.l2c_aux_mask = ~0,
- .map_io = sirfsoc_map_io,
.dma_zone_size = SZ_256M,
.init_late = sirfsoc_init_late,
.dt_compat = prima2_dt_match,
MACHINE_END
#endif
-#ifdef CONFIG_ARCH_MARCO
-static const char *marco_dt_match[] __initconst = {
- "sirf,marco",
+#ifdef CONFIG_ARCH_ATLAS7
+static const char *atlas7_dt_match[] __initdata = {
+ "sirf,atlas7",
NULL
};
-DT_MACHINE_START(MARCO_DT, "Generic MARCO (Flattened Device Tree)")
+DT_MACHINE_START(ATLAS7_DT, "Generic ATLAS7 (Flattened Device Tree)")
/* Maintainer: Barry Song <baohua.song@csr.com> */
- .l2c_aux_val = 0,
- .l2c_aux_mask = ~0,
.smp = smp_ops(sirfsoc_smp_ops),
- .map_io = sirfsoc_map_io,
- .init_late = sirfsoc_init_late,
- .dt_compat = marco_dt_match,
+ .dt_compat = atlas7_dt_match,
MACHINE_END
#endif
diff --git a/arch/arm/mach-prima2/lluart.c b/arch/arm/mach-prima2/lluart.c
deleted file mode 100644
index 99c0c927ca4..00000000000
--- a/arch/arm/mach-prima2/lluart.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Static memory mapping for DEBUG_LL
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- *
- * Licensed under GPLv2 or later.
- */
-
-#include <linux/kernel.h>
-#include <asm/page.h>
-#include <asm/mach/map.h>
-#include "common.h"
-
-#if defined(CONFIG_DEBUG_SIRFPRIMA2_UART1)
-#define SIRFSOC_UART1_PA_BASE 0xb0060000
-#elif defined(CONFIG_DEBUG_SIRFMARCO_UART1)
-#define SIRFSOC_UART1_PA_BASE 0xcc060000
-#else
-#define SIRFSOC_UART1_PA_BASE 0
-#endif
-
-#define SIRFSOC_UART1_VA_BASE SIRFSOC_VA(0x060000)
-#define SIRFSOC_UART1_SIZE SZ_4K
-
-void __init sirfsoc_map_lluart(void)
-{
- struct map_desc sirfsoc_lluart_map = {
- .virtual = SIRFSOC_UART1_VA_BASE,
- .pfn = __phys_to_pfn(SIRFSOC_UART1_PA_BASE),
- .length = SIRFSOC_UART1_SIZE,
- .type = MT_DEVICE,
- };
-
- iotable_init(&sirfsoc_lluart_map, 1);
-}
diff --git a/arch/arm/mach-prima2/platsmp.c b/arch/arm/mach-prima2/platsmp.c
index 335c12e9226..fc2b03c81e5 100644
--- a/arch/arm/mach-prima2/platsmp.c
+++ b/arch/arm/mach-prima2/platsmp.c
@@ -20,30 +20,10 @@
#include "common.h"
-static void __iomem *scu_base;
-static void __iomem *rsc_base;
+static void __iomem *clk_base;
static DEFINE_SPINLOCK(boot_lock);
-static struct map_desc scu_io_desc __initdata = {
- .length = SZ_4K,
- .type = MT_DEVICE,
-};
-
-void __init sirfsoc_map_scu(void)
-{
- unsigned long base;
-
- /* Get SCU base */
- asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
-
- scu_io_desc.virtual = SIRFSOC_VA(base);
- scu_io_desc.pfn = __phys_to_pfn(base);
- iotable_init(&scu_io_desc, 1);
-
- scu_base = (void __iomem *)SIRFSOC_VA(base);
-}
-
static void sirfsoc_secondary_init(unsigned int cpu)
{
/*
@@ -60,8 +40,8 @@ static void sirfsoc_secondary_init(unsigned int cpu)
spin_unlock(&boot_lock);
}
-static struct of_device_id rsc_ids[] = {
- { .compatible = "sirf,marco-rsc" },
+static struct of_device_id clk_ids[] = {
+ { .compatible = "sirf,atlas7-clkc" },
{},
};
@@ -70,27 +50,27 @@ static int sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle)
unsigned long timeout;
struct device_node *np;
- np = of_find_matching_node(NULL, rsc_ids);
+ np = of_find_matching_node(NULL, clk_ids);
if (!np)
return -ENODEV;
- rsc_base = of_iomap(np, 0);
- if (!rsc_base)
+ clk_base = of_iomap(np, 0);
+ if (!clk_base)
return -ENOMEM;
/*
- * write the address of secondary startup into the sram register
- * at offset 0x2C, then write the magic number 0x3CAF5D62 to the
- * RSC register at offset 0x28, which is what boot rom code is
+ * write the address of secondary startup into the clkc register
+ * at offset 0x2bC, then write the magic number 0x3CAF5D62 to the
+ * clkc register at offset 0x2b8, which is what boot rom code is
* waiting for. This would wake up the secondary core from WFE
*/
-#define SIRFSOC_CPU1_JUMPADDR_OFFSET 0x2C
+#define SIRFSOC_CPU1_JUMPADDR_OFFSET 0x2bc
__raw_writel(virt_to_phys(sirfsoc_secondary_startup),
- rsc_base + SIRFSOC_CPU1_JUMPADDR_OFFSET);
+ clk_base + SIRFSOC_CPU1_JUMPADDR_OFFSET);
-#define SIRFSOC_CPU1_WAKEMAGIC_OFFSET 0x28
+#define SIRFSOC_CPU1_WAKEMAGIC_OFFSET 0x2b8
__raw_writel(0x3CAF5D62,
- rsc_base + SIRFSOC_CPU1_WAKEMAGIC_OFFSET);
+ clk_base + SIRFSOC_CPU1_WAKEMAGIC_OFFSET);
/* make sure write buffer is drained */
mb();
@@ -132,13 +112,7 @@ static int sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle)
return pen_release != -1 ? -ENOSYS : 0;
}
-static void __init sirfsoc_smp_prepare_cpus(unsigned int max_cpus)
-{
- scu_enable(scu_base);
-}
-
struct smp_operations sirfsoc_smp_ops __initdata = {
- .smp_prepare_cpus = sirfsoc_smp_prepare_cpus,
.smp_secondary_init = sirfsoc_secondary_init,
.smp_boot_secondary = sirfsoc_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/arm/mach-prima2/rstc.c b/arch/arm/mach-prima2/rstc.c
index e1f1f86f6a9..7c251eb11d0 100644
--- a/arch/arm/mach-prima2/rstc.c
+++ b/arch/arm/mach-prima2/rstc.c
@@ -34,36 +34,20 @@ static int sirfsoc_reset_module(struct reset_controller_dev *rcdev,
mutex_lock(&rstc_lock);
- if (of_device_is_compatible(rcdev->of_node, "sirf,prima2-rstc")) {
- /*
- * Writing 1 to this bit resets corresponding block.
- * Writing 0 to this bit de-asserts reset signal of the
- * corresponding block. datasheet doesn't require explicit
- * delay between the set and clear of reset bit. it could
- * be shorter if tests pass.
- */
- writel(readl(sirfsoc_rstc_base +
+ /*
+ * Writing 1 to this bit resets corresponding block.
+ * Writing 0 to this bit de-asserts reset signal of the
+ * corresponding block. datasheet doesn't require explicit
+ * delay between the set and clear of reset bit. it could
+ * be shorter if tests pass.
+ */
+ writel(readl(sirfsoc_rstc_base +
(reset_bit / 32) * 4) | (1 << reset_bit),
- sirfsoc_rstc_base + (reset_bit / 32) * 4);
- msleep(20);
- writel(readl(sirfsoc_rstc_base +
+ sirfsoc_rstc_base + (reset_bit / 32) * 4);
+ msleep(20);
+ writel(readl(sirfsoc_rstc_base +
(reset_bit / 32) * 4) & ~(1 << reset_bit),
- sirfsoc_rstc_base + (reset_bit / 32) * 4);
- } else {
- /*
- * For MARCO and POLO
- * Writing 1 to SET register resets corresponding block.
- * Writing 1 to CLEAR register de-asserts reset signal of the
- * corresponding block.
- * datasheet doesn't require explicit delay between the set and
- * clear of reset bit. it could be shorter if tests pass.
- */
- writel(1 << reset_bit,
- sirfsoc_rstc_base + (reset_bit / 32) * 8);
- msleep(20);
- writel(1 << reset_bit,
- sirfsoc_rstc_base + (reset_bit / 32) * 8 + 4);
- }
+ sirfsoc_rstc_base + (reset_bit / 32) * 4);
mutex_unlock(&rstc_lock);
@@ -106,7 +90,6 @@ static int sirfsoc_rstc_probe(struct platform_device *pdev)
static const struct of_device_id rstc_ids[] = {
{ .compatible = "sirf,prima2-rstc" },
- { .compatible = "sirf,marco-rstc" },
{},
};
diff --git a/arch/arm/mach-prima2/rtciobrg.c b/arch/arm/mach-prima2/rtciobrg.c
index 70a0b475062..8f66d8f7ca7 100644
--- a/arch/arm/mach-prima2/rtciobrg.c
+++ b/arch/arm/mach-prima2/rtciobrg.c
@@ -104,7 +104,6 @@ EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_writel);
static const struct of_device_id rtciobrg_ids[] = {
{ .compatible = "sirf,prima2-rtciobg" },
- { .compatible = "sirf,marco-rtciobg" },
{}
};
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index ee5697ba05b..48003ea652b 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -1,9 +1,8 @@
menuconfig ARCH_QCOM
bool "Qualcomm Support" if ARCH_MULTI_V7
- select ARCH_REQUIRE_GPIOLIB
+ select ARCH_SUPPORTS_BIG_ENDIAN
select ARM_GIC
select ARM_AMBA
- select CLKSRC_OF
select PINCTRL
select QCOM_SCM if SMP
help
diff --git a/arch/arm/mach-qcom/scm-boot.c b/arch/arm/mach-qcom/scm-boot.c
index 45cee3e469a..e8ff7beb621 100644
--- a/arch/arm/mach-qcom/scm-boot.c
+++ b/arch/arm/mach-qcom/scm-boot.c
@@ -24,15 +24,15 @@
/*
* Set the cold/warm boot address for one of the CPU cores.
*/
-int scm_set_boot_addr(phys_addr_t addr, int flags)
+int scm_set_boot_addr(u32 addr, int flags)
{
struct {
- unsigned int flags;
- phys_addr_t addr;
+ __le32 flags;
+ __le32 addr;
} cmd;
- cmd.addr = addr;
- cmd.flags = flags;
+ cmd.addr = cpu_to_le32(addr);
+ cmd.flags = cpu_to_le32(flags);
return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
&cmd, sizeof(cmd), NULL, 0);
}
diff --git a/arch/arm/mach-qcom/scm-boot.h b/arch/arm/mach-qcom/scm-boot.h
index 6aabb242817..3e210fb818b 100644
--- a/arch/arm/mach-qcom/scm-boot.h
+++ b/arch/arm/mach-qcom/scm-boot.h
@@ -18,7 +18,9 @@
#define SCM_FLAG_COLDBOOT_CPU3 0x20
#define SCM_FLAG_WARMBOOT_CPU0 0x04
#define SCM_FLAG_WARMBOOT_CPU1 0x02
+#define SCM_FLAG_WARMBOOT_CPU2 0x10
+#define SCM_FLAG_WARMBOOT_CPU3 0x40
-int scm_set_boot_addr(phys_addr_t addr, int flags);
+int scm_set_boot_addr(u32 addr, int flags);
#endif
diff --git a/arch/arm/mach-qcom/scm.c b/arch/arm/mach-qcom/scm.c
index c536fd6bf82..1d9cf18c709 100644
--- a/arch/arm/mach-qcom/scm.c
+++ b/arch/arm/mach-qcom/scm.c
@@ -22,13 +22,11 @@
#include <linux/errno.h>
#include <linux/err.h>
+#include <asm/outercache.h>
#include <asm/cacheflush.h>
#include "scm.h"
-/* Cache line size for msm8x60 */
-#define CACHELINESIZE 32
-
#define SCM_ENOMEM -5
#define SCM_EOPNOTSUPP -4
#define SCM_EINVAL_ADDR -3
@@ -63,11 +61,11 @@ static DEFINE_MUTEX(scm_lock);
* to access the buffers in a safe manner.
*/
struct scm_command {
- u32 len;
- u32 buf_offset;
- u32 resp_hdr_offset;
- u32 id;
- u32 buf[0];
+ __le32 len;
+ __le32 buf_offset;
+ __le32 resp_hdr_offset;
+ __le32 id;
+ __le32 buf[0];
};
/**
@@ -77,9 +75,9 @@ struct scm_command {
* @is_complete: indicates if the command has finished processing
*/
struct scm_response {
- u32 len;
- u32 buf_offset;
- u32 is_complete;
+ __le32 len;
+ __le32 buf_offset;
+ __le32 is_complete;
};
/**
@@ -97,12 +95,14 @@ static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
struct scm_command *cmd;
size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
resp_size;
+ u32 offset;
cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
if (cmd) {
- cmd->len = len;
- cmd->buf_offset = offsetof(struct scm_command, buf);
- cmd->resp_hdr_offset = cmd->buf_offset + cmd_size;
+ cmd->len = cpu_to_le32(len);
+ offset = offsetof(struct scm_command, buf);
+ cmd->buf_offset = cpu_to_le32(offset);
+ cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size);
}
return cmd;
}
@@ -127,7 +127,7 @@ static inline void free_scm_command(struct scm_command *cmd)
static inline struct scm_response *scm_command_to_response(
const struct scm_command *cmd)
{
- return (void *)cmd + cmd->resp_hdr_offset;
+ return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset);
}
/**
@@ -149,11 +149,12 @@ static inline void *scm_get_command_buffer(const struct scm_command *cmd)
*/
static inline void *scm_get_response_buffer(const struct scm_response *rsp)
{
- return (void *)rsp + rsp->buf_offset;
+ return (void *)rsp + le32_to_cpu(rsp->buf_offset);
}
static int scm_remap_error(int err)
{
+ pr_err("scm_call failed with error code %d\n", err);
switch (err) {
case SCM_ERROR:
return -EIO;
@@ -198,11 +199,12 @@ static int __scm_call(const struct scm_command *cmd)
u32 cmd_addr = virt_to_phys(cmd);
/*
- * Flush the entire cache here so callers don't have to remember
- * to flush the cache when passing physical addresses to the secure
- * side in the buffer.
+ * Flush the command buffer so that the secure world sees
+ * the correct data.
*/
- flush_cache_all();
+ __cpuc_flush_dcache_area((void *)cmd, cmd->len);
+ outer_flush_range(cmd_addr, cmd_addr + cmd->len);
+
ret = smc(cmd_addr);
if (ret < 0)
ret = scm_remap_error(ret);
@@ -210,6 +212,25 @@ static int __scm_call(const struct scm_command *cmd)
return ret;
}
+static void scm_inv_range(unsigned long start, unsigned long end)
+{
+ u32 cacheline_size, ctr;
+
+ asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
+ cacheline_size = 4 << ((ctr >> 16) & 0xf);
+
+ start = round_down(start, cacheline_size);
+ end = round_up(end, cacheline_size);
+ outer_inv_range(start, end);
+ while (start < end) {
+ asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
+ : "memory");
+ start += cacheline_size;
+ }
+ dsb();
+ isb();
+}
+
/**
* scm_call() - Send an SCM command
* @svc_id: service identifier
@@ -220,6 +241,13 @@ static int __scm_call(const struct scm_command *cmd)
* @resp_len: length of the response buffer
*
* Sends a command to the SCM and waits for the command to finish processing.
+ *
+ * A note on cache maintenance:
+ * Note that any buffers that are expected to be accessed by the secure world
+ * must be flushed before invoking scm_call and invalidated in the cache
+ * immediately after scm_call returns. Cache maintenance on the command and
+ * response buffers is taken care of by scm_call; however, callers are
+ * responsible for any other cached buffers passed over to the secure world.
*/
int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
void *resp_buf, size_t resp_len)
@@ -227,12 +255,13 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
int ret;
struct scm_command *cmd;
struct scm_response *rsp;
+ unsigned long start, end;
cmd = alloc_scm_command(cmd_len, resp_len);
if (!cmd)
return -ENOMEM;
- cmd->id = (svc_id << 10) | cmd_id;
+ cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
if (cmd_buf)
memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
@@ -243,17 +272,15 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
goto out;
rsp = scm_command_to_response(cmd);
+ start = (unsigned long)rsp;
+
do {
- u32 start = (u32)rsp;
- u32 end = (u32)scm_get_response_buffer(rsp) + resp_len;
- start &= ~(CACHELINESIZE - 1);
- while (start < end) {
- asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
- : "memory");
- start += CACHELINESIZE;
- }
+ scm_inv_range(start, start + sizeof(*rsp));
} while (!rsp->is_complete);
+ end = (unsigned long)scm_get_response_buffer(rsp) + resp_len;
+ scm_inv_range(start, end);
+
if (resp_buf)
memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
out:
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index b29d8ead4cf..5c3a9b2de92 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -1,4 +1,5 @@
CFLAGS_platsmp.o := -march=armv7-a
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o
+obj-$(CONFIG_PM_SLEEP) += pm.o sleep.o
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff --git a/arch/arm/mach-rockchip/pm.c b/arch/arm/mach-rockchip/pm.c
new file mode 100644
index 00000000000..50cb781aaa3
--- /dev/null
+++ b/arch/arm/mach-rockchip/pm.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Tony Xie <tony.xie@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/regmap.h>
+#include <linux/suspend.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regulator/machine.h>
+
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/suspend.h>
+
+#include "pm.h"
+
+/* These enum are option of low power mode */
+enum {
+ ROCKCHIP_ARM_OFF_LOGIC_NORMAL = 0,
+ ROCKCHIP_ARM_OFF_LOGIC_DEEP = 1,
+};
+
+struct rockchip_pm_data {
+ const struct platform_suspend_ops *ops;
+ int (*init)(struct device_node *np);
+};
+
+static void __iomem *rk3288_bootram_base;
+static phys_addr_t rk3288_bootram_phy;
+
+static struct regmap *pmu_regmap;
+static struct regmap *sgrf_regmap;
+
+static u32 rk3288_pmu_pwr_mode_con;
+static u32 rk3288_sgrf_soc_con0;
+
+static inline u32 rk3288_l2_config(void)
+{
+ u32 l2ctlr;
+
+ asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (l2ctlr));
+ return l2ctlr;
+}
+
+static void rk3288_config_bootdata(void)
+{
+ rkpm_bootdata_cpusp = rk3288_bootram_phy + (SZ_4K - 8);
+ rkpm_bootdata_cpu_code = virt_to_phys(cpu_resume);
+
+ rkpm_bootdata_l2ctlr_f = 1;
+ rkpm_bootdata_l2ctlr = rk3288_l2_config();
+}
+
+static void rk3288_slp_mode_set(int level)
+{
+ u32 mode_set, mode_set1;
+
+ regmap_read(sgrf_regmap, RK3288_SGRF_SOC_CON0, &rk3288_sgrf_soc_con0);
+
+ regmap_read(pmu_regmap, RK3288_PMU_PWRMODE_CON,
+ &rk3288_pmu_pwr_mode_con);
+
+ /* set bit 8 so that system will resume to FAST_BOOT_ADDR */
+ regmap_write(sgrf_regmap, RK3288_SGRF_SOC_CON0,
+ SGRF_FAST_BOOT_EN | SGRF_FAST_BOOT_EN_WRITE);
+
+ /* booting address of resuming system is from this register value */
+ regmap_write(sgrf_regmap, RK3288_SGRF_FAST_BOOT_ADDR,
+ rk3288_bootram_phy);
+
+ regmap_write(pmu_regmap, RK3288_PMU_WAKEUP_CFG1,
+ PMU_ARMINT_WAKEUP_EN);
+
+ mode_set = BIT(PMU_GLOBAL_INT_DISABLE) | BIT(PMU_L2FLUSH_EN) |
+ BIT(PMU_SREF0_ENTER_EN) | BIT(PMU_SREF1_ENTER_EN) |
+ BIT(PMU_DDR0_GATING_EN) | BIT(PMU_DDR1_GATING_EN) |
+ BIT(PMU_PWR_MODE_EN) | BIT(PMU_CHIP_PD_EN) |
+ BIT(PMU_SCU_EN);
+
+ mode_set1 = BIT(PMU_CLR_CORE) | BIT(PMU_CLR_CPUP);
+
+ if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) {
+ /* arm off, logic deep sleep */
+ mode_set |= BIT(PMU_BUS_PD_EN) |
+ BIT(PMU_DDR1IO_RET_EN) | BIT(PMU_DDR0IO_RET_EN) |
+ BIT(PMU_OSC_24M_DIS) | BIT(PMU_PMU_USE_LF) |
+ BIT(PMU_ALIVE_USE_LF) | BIT(PMU_PLL_PD_EN);
+
+ mode_set1 |= BIT(PMU_CLR_ALIVE) | BIT(PMU_CLR_BUS) |
+ BIT(PMU_CLR_PERI) | BIT(PMU_CLR_DMA);
+ } else {
+ /*
+ * arm off, logic normal
+ * if pmu_clk_core_src_gate_en is not set,
+ * wakeup will be error
+ */
+ mode_set |= BIT(PMU_CLK_CORE_SRC_GATE_EN);
+ }
+
+ regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON, mode_set);
+ regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON1, mode_set1);
+}
+
+static void rk3288_slp_mode_set_resume(void)
+{
+ regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON,
+ rk3288_pmu_pwr_mode_con);
+
+ regmap_write(sgrf_regmap, RK3288_SGRF_SOC_CON0,
+ rk3288_sgrf_soc_con0 | SGRF_FAST_BOOT_EN_WRITE);
+}
+
+static int rockchip_lpmode_enter(unsigned long arg)
+{
+ flush_cache_all();
+
+ cpu_do_idle();
+
+ pr_err("%s: Failed to suspend\n", __func__);
+
+ return 1;
+}
+
+static int rk3288_suspend_enter(suspend_state_t state)
+{
+ local_fiq_disable();
+
+ rk3288_slp_mode_set(ROCKCHIP_ARM_OFF_LOGIC_NORMAL);
+
+ cpu_suspend(0, rockchip_lpmode_enter);
+
+ rk3288_slp_mode_set_resume();
+
+ local_fiq_enable();
+
+ return 0;
+}
+
+static int rk3288_suspend_prepare(void)
+{
+ return regulator_suspend_prepare(PM_SUSPEND_MEM);
+}
+
+static void rk3288_suspend_finish(void)
+{
+ if (regulator_suspend_finish())
+ pr_err("%s: Suspend finish failed\n", __func__);
+}
+
+static int rk3288_suspend_init(struct device_node *np)
+{
+ struct device_node *sram_np;
+ struct resource res;
+ int ret;
+
+ pmu_regmap = syscon_node_to_regmap(np);
+ if (IS_ERR(pmu_regmap)) {
+ pr_err("%s: could not find pmu regmap\n", __func__);
+ return PTR_ERR(pmu_regmap);
+ }
+
+ sgrf_regmap = syscon_regmap_lookup_by_compatible(
+ "rockchip,rk3288-sgrf");
+ if (IS_ERR(sgrf_regmap)) {
+ pr_err("%s: could not find sgrf regmap\n", __func__);
+ return PTR_ERR(pmu_regmap);
+ }
+
+ sram_np = of_find_compatible_node(NULL, NULL,
+ "rockchip,rk3288-pmu-sram");
+ if (!sram_np) {
+ pr_err("%s: could not find bootram dt node\n", __func__);
+ return -ENODEV;
+ }
+
+ rk3288_bootram_base = of_iomap(sram_np, 0);
+ if (!rk3288_bootram_base) {
+ pr_err("%s: could not map bootram base\n", __func__);
+ return -ENOMEM;
+ }
+
+ ret = of_address_to_resource(sram_np, 0, &res);
+ if (ret) {
+ pr_err("%s: could not get bootram phy addr\n", __func__);
+ return ret;
+ }
+ rk3288_bootram_phy = res.start;
+
+ of_node_put(sram_np);
+
+ rk3288_config_bootdata();
+
+ /* copy resume code and data to bootsram */
+ memcpy(rk3288_bootram_base, rockchip_slp_cpu_resume,
+ rk3288_bootram_sz);
+
+ return 0;
+}
+
+static const struct platform_suspend_ops rk3288_suspend_ops = {
+ .enter = rk3288_suspend_enter,
+ .valid = suspend_valid_only_mem,
+ .prepare = rk3288_suspend_prepare,
+ .finish = rk3288_suspend_finish,
+};
+
+static const struct rockchip_pm_data rk3288_pm_data __initconst = {
+ .ops = &rk3288_suspend_ops,
+ .init = rk3288_suspend_init,
+};
+
+static const struct of_device_id rockchip_pmu_of_device_ids[] __initconst = {
+ {
+ .compatible = "rockchip,rk3288-pmu",
+ .data = &rk3288_pm_data,
+ },
+ { /* sentinel */ },
+};
+
+void __init rockchip_suspend_init(void)
+{
+ const struct rockchip_pm_data *pm_data;
+ const struct of_device_id *match;
+ struct device_node *np;
+ int ret;
+
+ np = of_find_matching_node_and_match(NULL, rockchip_pmu_of_device_ids,
+ &match);
+ if (!match) {
+ pr_err("Failed to find PMU node\n");
+ return;
+ }
+ pm_data = (struct rockchip_pm_data *) match->data;
+
+ if (pm_data->init) {
+ ret = pm_data->init(np);
+
+ if (ret) {
+ pr_err("%s: matches init error %d\n", __func__, ret);
+ return;
+ }
+ }
+
+ suspend_set_ops(pm_data->ops);
+}
diff --git a/arch/arm/mach-rockchip/pm.h b/arch/arm/mach-rockchip/pm.h
new file mode 100644
index 00000000000..7d752ff39f9
--- /dev/null
+++ b/arch/arm/mach-rockchip/pm.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Tony Xie <tony.xie@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef __MACH_ROCKCHIP_PM_H
+#define __MACH_ROCKCHIP_PM_H
+
+extern unsigned long rkpm_bootdata_cpusp;
+extern unsigned long rkpm_bootdata_cpu_code;
+extern unsigned long rkpm_bootdata_l2ctlr_f;
+extern unsigned long rkpm_bootdata_l2ctlr;
+extern unsigned long rkpm_bootdata_ddr_code;
+extern unsigned long rkpm_bootdata_ddr_data;
+extern unsigned long rk3288_bootram_sz;
+
+void rockchip_slp_cpu_resume(void);
+void __init rockchip_suspend_init(void);
+
+/****** following is rk3288 defined **********/
+#define RK3288_PMU_WAKEUP_CFG0 0x00
+#define RK3288_PMU_WAKEUP_CFG1 0x04
+#define RK3288_PMU_PWRMODE_CON 0x18
+#define RK3288_PMU_OSC_CNT 0x20
+#define RK3288_PMU_PLL_CNT 0x24
+#define RK3288_PMU_STABL_CNT 0x28
+#define RK3288_PMU_DDR0IO_PWRON_CNT 0x2c
+#define RK3288_PMU_DDR1IO_PWRON_CNT 0x30
+#define RK3288_PMU_CORE_PWRDWN_CNT 0x34
+#define RK3288_PMU_CORE_PWRUP_CNT 0x38
+#define RK3288_PMU_GPU_PWRDWN_CNT 0x3c
+#define RK3288_PMU_GPU_PWRUP_CNT 0x40
+#define RK3288_PMU_WAKEUP_RST_CLR_CNT 0x44
+#define RK3288_PMU_PWRMODE_CON1 0x90
+
+#define RK3288_SGRF_SOC_CON0 (0x0000)
+#define RK3288_SGRF_FAST_BOOT_ADDR (0x0120)
+#define SGRF_FAST_BOOT_EN BIT(8)
+#define SGRF_FAST_BOOT_EN_WRITE BIT(24)
+
+#define RK3288_CRU_MODE_CON 0x50
+#define RK3288_CRU_SEL0_CON 0x60
+#define RK3288_CRU_SEL1_CON 0x64
+#define RK3288_CRU_SEL10_CON 0x88
+#define RK3288_CRU_SEL33_CON 0xe4
+#define RK3288_CRU_SEL37_CON 0xf4
+
+/* PMU_WAKEUP_CFG1 bits */
+#define PMU_ARMINT_WAKEUP_EN BIT(0)
+
+enum rk3288_pwr_mode_con {
+ PMU_PWR_MODE_EN = 0,
+ PMU_CLK_CORE_SRC_GATE_EN,
+ PMU_GLOBAL_INT_DISABLE,
+ PMU_L2FLUSH_EN,
+ PMU_BUS_PD_EN,
+ PMU_A12_0_PD_EN,
+ PMU_SCU_EN,
+ PMU_PLL_PD_EN,
+ PMU_CHIP_PD_EN, /* POWER OFF PIN ENABLE */
+ PMU_PWROFF_COMB,
+ PMU_ALIVE_USE_LF,
+ PMU_PMU_USE_LF,
+ PMU_OSC_24M_DIS,
+ PMU_INPUT_CLAMP_EN,
+ PMU_WAKEUP_RESET_EN,
+ PMU_SREF0_ENTER_EN,
+ PMU_SREF1_ENTER_EN,
+ PMU_DDR0IO_RET_EN,
+ PMU_DDR1IO_RET_EN,
+ PMU_DDR0_GATING_EN,
+ PMU_DDR1_GATING_EN,
+ PMU_DDR0IO_RET_DE_REQ,
+ PMU_DDR1IO_RET_DE_REQ
+};
+
+enum rk3288_pwr_mode_con1 {
+ PMU_CLR_BUS = 0,
+ PMU_CLR_CORE,
+ PMU_CLR_CPUP,
+ PMU_CLR_ALIVE,
+ PMU_CLR_DMA,
+ PMU_CLR_PERI,
+ PMU_CLR_GPU,
+ PMU_CLR_VIDEO,
+ PMU_CLR_HEVC,
+ PMU_CLR_VIO,
+};
+
+#endif /* __MACH_ROCKCHIP_PM_H */
diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index d226b71d21d..f70861174cb 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -23,9 +23,11 @@
#include <asm/mach/map.h>
#include <asm/hardware/cache-l2x0.h>
#include "core.h"
+#include "pm.h"
static void __init rockchip_dt_init(void)
{
+ rockchip_suspend_init();
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
platform_device_register_simple("cpufreq-dt", 0, NULL, 0);
}
@@ -39,7 +41,7 @@ static const char * const rockchip_board_dt_compat[] = {
NULL,
};
-DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)")
+DT_MACHINE_START(ROCKCHIP_DT, "Rockchip (Device Tree)")
.l2c_aux_val = 0,
.l2c_aux_mask = ~0,
.dt_compat = rockchip_board_dt_compat,
diff --git a/arch/arm/mach-rockchip/sleep.S b/arch/arm/mach-rockchip/sleep.S
new file mode 100644
index 00000000000..2eec9a341f0
--- /dev/null
+++ b/arch/arm/mach-rockchip/sleep.S
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Tony Xie <tony.xie@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/memory.h>
+
+.data
+/*
+ * this code will be copied from
+ * ddr to sram for system resumeing.
+ * so it is ".data section".
+ */
+.align
+
+ENTRY(rockchip_slp_cpu_resume)
+ setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set svc, irqs off
+ mrc p15, 0, r1, c0, c0, 5
+ and r1, r1, #0xf
+ cmp r1, #0
+ /* olny cpu0 can continue to run, the others is halt here */
+ beq cpu0run
+secondary_loop:
+ wfe
+ b secondary_loop
+cpu0run:
+ ldr r3, rkpm_bootdata_l2ctlr_f
+ cmp r3, #0
+ beq sp_set
+ ldr r3, rkpm_bootdata_l2ctlr
+ mcr p15, 1, r3, c9, c0, 2
+sp_set:
+ ldr sp, rkpm_bootdata_cpusp
+ ldr r1, rkpm_bootdata_cpu_code
+ bx r1
+ENDPROC(rockchip_slp_cpu_resume)
+
+/* Parameters filled in by the kernel */
+
+/* Flag for whether to restore L2CTLR on resume */
+ .global rkpm_bootdata_l2ctlr_f
+rkpm_bootdata_l2ctlr_f:
+ .long 0
+
+/* Saved L2CTLR to restore on resume */
+ .global rkpm_bootdata_l2ctlr
+rkpm_bootdata_l2ctlr:
+ .long 0
+
+/* CPU resume SP addr */
+ .globl rkpm_bootdata_cpusp
+rkpm_bootdata_cpusp:
+ .long 0
+
+/* CPU resume function (physical address) */
+ .globl rkpm_bootdata_cpu_code
+rkpm_bootdata_cpu_code:
+ .long 0
+
+ENTRY(rk3288_bootram_sz)
+ .word . - rockchip_slp_cpu_resume
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 1b4fafe524f..894c6876006 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -7,6 +7,7 @@ config PM_RCAR
config PM_RMOBILE
bool
+ select PM_GENERIC_DOMAINS
config ARCH_RCAR_GEN1
bool
@@ -23,7 +24,7 @@ config ARCH_RCAR_GEN2
config ARCH_RMOBILE
bool
- select PM_RMOBILE if PM && !ARCH_SHMOBILE_MULTI
+ select PM_RMOBILE if PM
select SYS_SUPPORTS_SH_CMT
select SYS_SUPPORTS_SH_TMU
@@ -51,6 +52,11 @@ config ARCH_R7S72100
bool "RZ/A1H (R7S72100)"
select SYS_SUPPORTS_SH_MTU2
+config ARCH_R8A73A4
+ bool "R-Mobile APE6 (R8A73A40)"
+ select ARCH_RMOBILE
+ select RENESAS_IRQC
+
config ARCH_R8A7740
bool "R-Mobile A1 (R8A77400)"
select ARCH_RMOBILE
diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
index 6b4c1f313cc..3855fb024fd 100644
--- a/arch/arm/mach-shmobile/clock-sh73a0.c
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -553,6 +553,7 @@ enum { MSTP001,
MSTP314, MSTP313, MSTP312, MSTP311,
MSTP304, MSTP303, MSTP302, MSTP301, MSTP300,
MSTP411, MSTP410, MSTP403,
+ MSTP508,
MSTP_NR };
#define MSTP(_parent, _reg, _bit, _flags) \
@@ -597,6 +598,7 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP411] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */
[MSTP410] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */
[MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
+ [MSTP508] = MSTP(&div4_clks[DIV4_HP], SMSTPCR5, 8, 0), /* INTCA0 */
};
/* The lookups structure below includes duplicate entries for some clocks
@@ -677,6 +679,14 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */
CLKDEV_DEV_ID("e6828000.i2c", &mstp_clks[MSTP410]), /* I2C4 */
CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
+ CLKDEV_DEV_ID("renesas_intc_irqpin.0", &mstp_clks[MSTP508]), /* INTCA0 */
+ CLKDEV_DEV_ID("e6900000.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */
+ CLKDEV_DEV_ID("renesas_intc_irqpin.1", &mstp_clks[MSTP508]), /* INTCA0 */
+ CLKDEV_DEV_ID("e6900004.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */
+ CLKDEV_DEV_ID("renesas_intc_irqpin.2", &mstp_clks[MSTP508]), /* INTCA0 */
+ CLKDEV_DEV_ID("e6900008.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */
+ CLKDEV_DEV_ID("renesas_intc_irqpin.3", &mstp_clks[MSTP508]), /* INTCA0 */
+ CLKDEV_DEV_ID("e690000c.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */
/* ICK */
CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]),
diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c
index ac2eecd6f5e..34608fcf064 100644
--- a/arch/arm/mach-shmobile/pm-r8a7740.c
+++ b/arch/arm/mach-shmobile/pm-r8a7740.c
@@ -9,10 +9,14 @@
* for more details.
*/
#include <linux/console.h>
+#include <linux/io.h>
#include <linux/suspend.h>
+
#include "common.h"
#include "pm-rmobile.h"
+#define SYSC_BASE IOMEM(0xe6180000)
+
#if defined(CONFIG_PM) && !defined(CONFIG_ARCH_MULTIPLATFORM)
static int r8a7740_pd_a3sm_suspend(void)
{
@@ -45,41 +49,51 @@ static int r8a7740_pd_d4_suspend(void)
static struct rmobile_pm_domain r8a7740_pm_domains[] = {
{
.genpd.name = "A4LC",
+ .base = SYSC_BASE,
.bit_shift = 1,
}, {
.genpd.name = "A4MP",
+ .base = SYSC_BASE,
.bit_shift = 2,
}, {
.genpd.name = "D4",
+ .base = SYSC_BASE,
.bit_shift = 3,
.gov = &pm_domain_always_on_gov,
.suspend = r8a7740_pd_d4_suspend,
}, {
.genpd.name = "A4R",
+ .base = SYSC_BASE,
.bit_shift = 5,
}, {
.genpd.name = "A3RV",
+ .base = SYSC_BASE,
.bit_shift = 6,
}, {
.genpd.name = "A4S",
+ .base = SYSC_BASE,
.bit_shift = 10,
.no_debug = true,
}, {
.genpd.name = "A3SP",
+ .base = SYSC_BASE,
.bit_shift = 11,
.gov = &pm_domain_always_on_gov,
.no_debug = true,
.suspend = r8a7740_pd_a3sp_suspend,
}, {
.genpd.name = "A3SM",
+ .base = SYSC_BASE,
.bit_shift = 12,
.gov = &pm_domain_always_on_gov,
.suspend = r8a7740_pd_a3sm_suspend,
}, {
.genpd.name = "A3SG",
+ .base = SYSC_BASE,
.bit_shift = 13,
}, {
.genpd.name = "A4SU",
+ .base = SYSC_BASE,
.bit_shift = 20,
},
};
diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c
index 6f7d56ecf96..95018209ff0 100644
--- a/arch/arm/mach-shmobile/pm-rmobile.c
+++ b/arch/arm/mach-shmobile/pm-rmobile.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2012 Renesas Solutions Corp.
* Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ * Copyright (C) 2014 Glider bvba
*
* based on pm-sh7372.c
* Copyright (C) 2011 Magnus Damm
@@ -13,16 +14,22 @@
*/
#include <linux/console.h>
#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pm_clock.h>
+#include <linux/slab.h>
+
#include <asm/io.h>
+
#include "pm-rmobile.h"
/* SYSC */
-#define SPDCR IOMEM(0xe6180008)
-#define SWUCR IOMEM(0xe6180014)
-#define PSTR IOMEM(0xe6180080)
+#define SPDCR 0x08 /* SYS Power Down Control Register */
+#define SWUCR 0x14 /* SYS Wakeup Control Register */
+#define PSTR 0x80 /* Power Status Register */
#define PSTR_RETRIES 100
#define PSTR_DELAY_US 10
@@ -30,8 +37,12 @@
static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
{
struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
- unsigned int mask = 1 << rmobile_pd->bit_shift;
+ unsigned int mask;
+
+ if (rmobile_pd->bit_shift == ~0)
+ return -EBUSY;
+ mask = 1 << rmobile_pd->bit_shift;
if (rmobile_pd->suspend) {
int ret = rmobile_pd->suspend();
@@ -39,12 +50,12 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
return ret;
}
- if (__raw_readl(PSTR) & mask) {
+ if (__raw_readl(rmobile_pd->base + PSTR) & mask) {
unsigned int retry_count;
- __raw_writel(mask, SPDCR);
+ __raw_writel(mask, rmobile_pd->base + SPDCR);
for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
- if (!(__raw_readl(SPDCR) & mask))
+ if (!(__raw_readl(rmobile_pd->base + SPDCR) & mask))
break;
cpu_relax();
}
@@ -52,7 +63,8 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
if (!rmobile_pd->no_debug)
pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n",
- genpd->name, mask, __raw_readl(PSTR));
+ genpd->name, mask,
+ __raw_readl(rmobile_pd->base + PSTR));
return 0;
}
@@ -60,17 +72,21 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd,
bool do_resume)
{
- unsigned int mask = 1 << rmobile_pd->bit_shift;
+ unsigned int mask;
unsigned int retry_count;
int ret = 0;
- if (__raw_readl(PSTR) & mask)
+ if (rmobile_pd->bit_shift == ~0)
+ return 0;
+
+ mask = 1 << rmobile_pd->bit_shift;
+ if (__raw_readl(rmobile_pd->base + PSTR) & mask)
goto out;
- __raw_writel(mask, SWUCR);
+ __raw_writel(mask, rmobile_pd->base + SWUCR);
for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
- if (!(__raw_readl(SWUCR) & mask))
+ if (!(__raw_readl(rmobile_pd->base + SWUCR) & mask))
break;
if (retry_count > PSTR_RETRIES)
udelay(PSTR_DELAY_US);
@@ -82,7 +98,8 @@ static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd,
if (!rmobile_pd->no_debug)
pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
- rmobile_pd->genpd.name, mask, __raw_readl(PSTR));
+ rmobile_pd->genpd.name, mask,
+ __raw_readl(rmobile_pd->base + PSTR));
out:
if (ret == 0 && rmobile_pd->resume && do_resume)
@@ -101,6 +118,36 @@ static bool rmobile_pd_active_wakeup(struct device *dev)
return true;
}
+static int rmobile_pd_attach_dev(struct generic_pm_domain *domain,
+ struct device *dev)
+{
+ int error;
+
+ error = pm_clk_create(dev);
+ if (error) {
+ dev_err(dev, "pm_clk_create failed %d\n", error);
+ return error;
+ }
+
+ error = pm_clk_add(dev, NULL);
+ if (error) {
+ dev_err(dev, "pm_clk_add failed %d\n", error);
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ pm_clk_destroy(dev);
+ return error;
+}
+
+static void rmobile_pd_detach_dev(struct generic_pm_domain *domain,
+ struct device *dev)
+{
+ pm_clk_destroy(dev);
+}
+
static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
{
struct generic_pm_domain *genpd = &rmobile_pd->genpd;
@@ -111,9 +158,13 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup;
genpd->power_off = rmobile_pd_power_down;
genpd->power_on = rmobile_pd_power_up;
+ genpd->attach_dev = rmobile_pd_attach_dev;
+ genpd->detach_dev = rmobile_pd_detach_dev;
__rmobile_pd_power_up(rmobile_pd, false);
}
+#ifdef CONFIG_ARCH_SHMOBILE_LEGACY
+
void rmobile_init_domains(struct rmobile_pm_domain domains[], int num)
{
int j;
@@ -129,8 +180,6 @@ void rmobile_add_device_to_domain_td(const char *domain_name,
struct device *dev = &pdev->dev;
__pm_genpd_name_add_device(domain_name, dev, td);
- if (pm_clk_no_clocks(dev))
- pm_clk_add(dev, NULL);
}
void rmobile_add_devices_to_domains(struct pm_domain_device data[],
@@ -148,3 +197,238 @@ void rmobile_add_devices_to_domains(struct pm_domain_device data[],
rmobile_add_device_to_domain_td(data[j].domain_name,
data[j].pdev, &latencies);
}
+
+#else /* !CONFIG_ARCH_SHMOBILE_LEGACY */
+
+static int rmobile_pd_suspend_busy(void)
+{
+ /*
+ * This domain should not be turned off.
+ */
+ return -EBUSY;
+}
+
+static int rmobile_pd_suspend_console(void)
+{
+ /*
+ * Serial consoles make use of SCIF hardware located in this domain,
+ * hence keep the power domain on if "no_console_suspend" is set.
+ */
+ return console_suspend_enabled ? 0 : -EBUSY;
+}
+
+enum pd_types {
+ PD_NORMAL,
+ PD_CPU,
+ PD_CONSOLE,
+ PD_DEBUG,
+ PD_MEMCTL,
+};
+
+#define MAX_NUM_SPECIAL_PDS 16
+
+static struct special_pd {
+ struct device_node *pd;
+ enum pd_types type;
+} special_pds[MAX_NUM_SPECIAL_PDS] __initdata;
+
+static unsigned int num_special_pds __initdata;
+
+static const struct of_device_id special_ids[] __initconst = {
+ { .compatible = "arm,coresight-etm3x", .data = (void *)PD_DEBUG },
+ { .compatible = "renesas,dbsc-r8a73a4", .data = (void *)PD_MEMCTL, },
+ { .compatible = "renesas,dbsc3-r8a7740", .data = (void *)PD_MEMCTL, },
+ { .compatible = "renesas,sbsc-sh73a0", .data = (void *)PD_MEMCTL, },
+ { /* sentinel */ },
+};
+
+static void __init add_special_pd(struct device_node *np, enum pd_types type)
+{
+ unsigned int i;
+ struct device_node *pd;
+
+ pd = of_parse_phandle(np, "power-domains", 0);
+ if (!pd)
+ return;
+
+ for (i = 0; i < num_special_pds; i++)
+ if (pd == special_pds[i].pd && type == special_pds[i].type) {
+ of_node_put(pd);
+ return;
+ }
+
+ if (num_special_pds == ARRAY_SIZE(special_pds)) {
+ pr_warn("Too many special PM domains\n");
+ of_node_put(pd);
+ return;
+ }
+
+ pr_debug("Special PM domain %s type %d for %s\n", pd->name, type,
+ np->full_name);
+
+ special_pds[num_special_pds].pd = pd;
+ special_pds[num_special_pds].type = type;
+ num_special_pds++;
+}
+
+static void __init get_special_pds(void)
+{
+ struct device_node *np;
+ const struct of_device_id *id;
+
+ /* PM domains containing CPUs */
+ for_each_node_by_type(np, "cpu")
+ add_special_pd(np, PD_CPU);
+
+ /* PM domain containing console */
+ if (of_stdout)
+ add_special_pd(of_stdout, PD_CONSOLE);
+
+ /* PM domains containing other special devices */
+ for_each_matching_node_and_match(np, special_ids, &id)
+ add_special_pd(np, (enum pd_types)id->data);
+}
+
+static void __init put_special_pds(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_special_pds; i++)
+ of_node_put(special_pds[i].pd);
+}
+
+static enum pd_types __init pd_type(const struct device_node *pd)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_special_pds; i++)
+ if (pd == special_pds[i].pd)
+ return special_pds[i].type;
+
+ return PD_NORMAL;
+}
+
+static void __init rmobile_setup_pm_domain(struct device_node *np,
+ struct rmobile_pm_domain *pd)
+{
+ const char *name = pd->genpd.name;
+
+ switch (pd_type(np)) {
+ case PD_CPU:
+ /*
+ * This domain contains the CPU core and therefore it should
+ * only be turned off if the CPU is not in use.
+ */
+ pr_debug("PM domain %s contains CPU\n", name);
+ pd->gov = &pm_domain_always_on_gov;
+ pd->suspend = rmobile_pd_suspend_busy;
+ break;
+
+ case PD_CONSOLE:
+ pr_debug("PM domain %s contains serial console\n", name);
+ pd->gov = &pm_domain_always_on_gov;
+ pd->suspend = rmobile_pd_suspend_console;
+ break;
+
+ case PD_DEBUG:
+ /*
+ * This domain contains the Coresight-ETM hardware block and
+ * therefore it should only be turned off if the debug module
+ * is not in use.
+ */
+ pr_debug("PM domain %s contains Coresight-ETM\n", name);
+ pd->gov = &pm_domain_always_on_gov;
+ pd->suspend = rmobile_pd_suspend_busy;
+ break;
+
+ case PD_MEMCTL:
+ /*
+ * This domain contains a memory-controller and therefore it
+ * should only be turned off if memory is not in use.
+ */
+ pr_debug("PM domain %s contains MEMCTL\n", name);
+ pd->gov = &pm_domain_always_on_gov;
+ pd->suspend = rmobile_pd_suspend_busy;
+ break;
+
+ case PD_NORMAL:
+ break;
+ }
+
+ rmobile_init_pm_domain(pd);
+}
+
+static int __init rmobile_add_pm_domains(void __iomem *base,
+ struct device_node *parent,
+ struct generic_pm_domain *genpd_parent)
+{
+ struct device_node *np;
+
+ for_each_child_of_node(parent, np) {
+ struct rmobile_pm_domain *pd;
+ u32 idx = ~0;
+
+ if (of_property_read_u32(np, "reg", &idx)) {
+ /* always-on domain */
+ }
+
+ pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return -ENOMEM;
+
+ pd->genpd.name = np->name;
+ pd->base = base;
+ pd->bit_shift = idx;
+
+ rmobile_setup_pm_domain(np, pd);
+ if (genpd_parent)
+ pm_genpd_add_subdomain(genpd_parent, &pd->genpd);
+ of_genpd_add_provider_simple(np, &pd->genpd);
+
+ rmobile_add_pm_domains(base, np, &pd->genpd);
+ }
+ return 0;
+}
+
+static int __init rmobile_init_pm_domains(void)
+{
+ struct device_node *np, *pmd;
+ bool scanned = false;
+ void __iomem *base;
+ int ret = 0;
+
+ for_each_compatible_node(np, NULL, "renesas,sysc-rmobile") {
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_warn("%s cannot map reg 0\n", np->full_name);
+ continue;
+ }
+
+ pmd = of_get_child_by_name(np, "pm-domains");
+ if (!pmd) {
+ pr_warn("%s lacks pm-domains node\n", np->full_name);
+ continue;
+ }
+
+ if (!scanned) {
+ /* Find PM domains containing special blocks */
+ get_special_pds();
+ scanned = true;
+ }
+
+ ret = rmobile_add_pm_domains(base, pmd, NULL);
+ of_node_put(pmd);
+ if (ret) {
+ of_node_put(np);
+ break;
+ }
+ }
+
+ put_special_pds();
+
+ return ret;
+}
+
+core_initcall(rmobile_init_pm_domains);
+
+#endif /* !CONFIG_ARCH_SHMOBILE_LEGACY */
diff --git a/arch/arm/mach-shmobile/pm-rmobile.h b/arch/arm/mach-shmobile/pm-rmobile.h
index 8f66b343162..53219786f53 100644
--- a/arch/arm/mach-shmobile/pm-rmobile.h
+++ b/arch/arm/mach-shmobile/pm-rmobile.h
@@ -21,6 +21,7 @@ struct rmobile_pm_domain {
struct dev_power_governor *gov;
int (*suspend)(void);
void (*resume)(void);
+ void __iomem *base;
unsigned int bit_shift;
bool no_debug;
};
@@ -36,7 +37,7 @@ struct pm_domain_device {
struct platform_device *pdev;
};
-#ifdef CONFIG_PM_RMOBILE
+#if defined(CONFIG_PM_RMOBILE) && defined(CONFIG_ARCH_SHMOBILE_LEGACY)
extern void rmobile_init_domains(struct rmobile_pm_domain domains[], int num);
extern void rmobile_add_device_to_domain_td(const char *domain_name,
struct platform_device *pdev,
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c
index 0e37da654ed..c0293ae4b01 100644
--- a/arch/arm/mach-shmobile/pm-sh7372.c
+++ b/arch/arm/mach-shmobile/pm-sh7372.c
@@ -45,6 +45,8 @@
#define PLLC01STPCR IOMEM(0xe61500c8)
/* SYSC */
+#define SYSC_BASE IOMEM(0xe6180000)
+
#define SBAR IOMEM(0xe6180020)
#define WUPRMSK IOMEM(0xe6180028)
#define WUPSMSK IOMEM(0xe618002c)
@@ -118,24 +120,28 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = {
.genpd.name = "A4LC",
.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+ .base = SYSC_BASE,
.bit_shift = 1,
},
{
.genpd.name = "A4MP",
.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+ .base = SYSC_BASE,
.bit_shift = 2,
},
{
.genpd.name = "D4",
.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+ .base = SYSC_BASE,
.bit_shift = 3,
},
{
.genpd.name = "A4R",
.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+ .base = SYSC_BASE,
.bit_shift = 5,
.suspend = sh7372_a4r_pd_suspend,
.resume = sh7372_intcs_resume,
@@ -144,18 +150,21 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = {
.genpd.name = "A3RV",
.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+ .base = SYSC_BASE,
.bit_shift = 6,
},
{
.genpd.name = "A3RI",
.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+ .base = SYSC_BASE,
.bit_shift = 8,
},
{
.genpd.name = "A4S",
.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+ .base = SYSC_BASE,
.bit_shift = 10,
.gov = &pm_domain_always_on_gov,
.no_debug = true,
@@ -166,6 +175,7 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = {
.genpd.name = "A3SP",
.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+ .base = SYSC_BASE,
.bit_shift = 11,
.gov = &pm_domain_always_on_gov,
.no_debug = true,
@@ -175,6 +185,7 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = {
.genpd.name = "A3SG",
.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+ .base = SYSC_BASE,
.bit_shift = 13,
},
};
diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c
index 3dd6edd9bd1..c35b91d9219 100644
--- a/arch/arm/mach-shmobile/setup-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c
@@ -52,15 +52,13 @@ void __init rcar_gen2_timer_init(void)
{
#if defined(CONFIG_ARM_ARCH_TIMER) || defined(CONFIG_COMMON_CLK)
u32 mode = rcar_gen2_read_mode_pins();
- bool is_e2 = (bool)of_find_compatible_node(NULL, NULL,
- "renesas,r8a7794");
#endif
#ifdef CONFIG_ARM_ARCH_TIMER
void __iomem *base;
int extal_mhz = 0;
u32 freq;
- if (is_e2) {
+ if (of_machine_is_compatible("renesas,r8a7794")) {
freq = 260000000 / 8; /* ZS / 8 */
/* CNTVOFF has to be initialized either from non-secure
* Hypervisor mode or secure Monitor mode with SCR.NS==1.
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c
index 3f761f83904..9fc280e24ef 100644
--- a/arch/arm/mach-shmobile/smp-r8a7779.c
+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
@@ -56,7 +56,7 @@ static struct rcar_sysc_ch *r8a7779_ch_cpu[4] = {
[3] = &r8a7779_ch_cpu3,
};
-#ifdef CONFIG_HAVE_ARM_TWD
+#if defined(CONFIG_HAVE_ARM_TWD) && !defined(CONFIG_ARCH_MULTIPLATFORM)
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, R8A7779_SCU_BASE + 0x600, 29);
void __init r8a7779_register_twd(void)
{
diff --git a/arch/arm/mach-sti/board-dt.c b/arch/arm/mach-sti/board-dt.c
index 3cf6ef8d431..b067390cef4 100644
--- a/arch/arm/mach-sti/board-dt.c
+++ b/arch/arm/mach-sti/board-dt.c
@@ -18,6 +18,7 @@ static const char *stih41x_dt_match[] __initdata = {
"st,stih415",
"st,stih416",
"st,stih407",
+ "st,stih418",
NULL
};
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index d0be9a1ef6b..5d1a318f130 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -27,6 +27,7 @@ config ARCH_TEGRA_2x_SOC
select PINCTRL_TEGRA20
select PL310_ERRATA_727915 if CACHE_L2X0
select PL310_ERRATA_769419 if CACHE_L2X0
+ select TEGRA_TIMER
help
Support for NVIDIA Tegra AP20 and T20 processors, based on the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -37,6 +38,7 @@ config ARCH_TEGRA_3x_SOC
select ARM_ERRATA_764369 if SMP
select PINCTRL_TEGRA30
select PL310_ERRATA_769419 if CACHE_L2X0
+ select TEGRA_TIMER
help
Support for NVIDIA Tegra T30 processor family, based on the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -47,6 +49,7 @@ config ARCH_TEGRA_114_SOC
select ARM_L1_CACHE_SHIFT_6
select HAVE_ARM_ARCH_TIMER
select PINCTRL_TEGRA114
+ select TEGRA_TIMER
help
Support for NVIDIA Tegra T114 processor family, based on the
ARM CortexA15MP CPU
@@ -56,6 +59,7 @@ config ARCH_TEGRA_124_SOC
select ARM_L1_CACHE_SHIFT_6
select HAVE_ARM_ARCH_TIMER
select PINCTRL_TEGRA124
+ select TEGRA_TIMER
help
Support for NVIDIA Tegra T124 processor family, based on the
ARM CortexA15MP CPU