aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2015-01-23 17:38:55 -0500
committerOlof Johansson <olof@lixom.net>2015-01-23 17:38:55 -0500
commit085dd64e537b06c7b741dac5f0ff3734d27f9a13 (patch)
tree8ae20547b8fb3a5d914bbb46753dfb72eb9cb9e7
parenteeec0434e8b89fa5f29d71e5f8044dcec7939d1a (diff)
parentade9233f2e0cf4b7bf10fd122c7e9f9310bfd1a5 (diff)
Merge tag 'imx-soc-3.20' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into next/soc
Merge "ARM: imx: soc changes for 3.20" from Shawn Guo: The i.MX SoC changes for 3.20: - Add .disable_unused function hook for shared gate clock to ensure the clock tree use count matches the hardware state - Add a deeper idle state for i.MX6SX cpuidle driver powering off the ARM core - One correction on i.MX6Q esai_ipg parent clock setting - Add a missing iounmap call for imx6q_opp_check_speed_grading() - Add missing clocks for VF610 UART4, UART5 and SNVS blocks - Expand VF610 device tree compatible matching table to cover more Vybrid family SoCs - Expand i.MX clk-pllv3 a bit with the shift for frequency multiplier to support Vybrid's USB PLL oddity * tag 'imx-soc-3.20' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux: ARM: clk-imx6q: refine esai_ipg's parent ARM i.MX6q: unmap memory mapped at imx6q_opp_check_speed_grading() ARM: imx: clk-vf610: Add clock for SNVS ARM: imx: clk-vf610: Add clock for UART4 and UART5 ARM: imx: drop CPUIDLE_FLAG_TIME_VALID from cpuidle-imx6sx ARM: imx: support arm power off in cpuidle for i.mx6sx ARM: imx: remove unnecessary setting for DSM ARM: imx: correct the hardware clock gate setting for shared nodes ARM: imx: pllv3: add shift for frequency multiplier ARM vf610: add compatibilty strings of supported Vybrid SoC's Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r--Documentation/devicetree/bindings/arm/fsl.txt12
-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--include/dt-bindings/clock/vf610-clock.h3
16 files changed, 195 insertions, 22 deletions
diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt
index 4e8b7df7fc62..c830b5b65882 100644
--- a/Documentation/devicetree/bindings/arm/fsl.txt
+++ b/Documentation/devicetree/bindings/arm/fsl.txt
@@ -75,6 +75,18 @@ i.MX6q generic board
75Required root node properties: 75Required root node properties:
76 - compatible = "fsl,imx6q"; 76 - compatible = "fsl,imx6q";
77 77
78Freescale Vybrid Platform Device Tree Bindings
79----------------------------------------------
80
81For the Vybrid SoC familiy all variants with DDR controller are supported,
82which is the VF5xx and VF6xx series. Out of historical reasons, in most
83places the kernel uses vf610 to refer to the whole familiy.
84
85Required root node compatible property (one of them):
86 - compatible = "fsl,vf500";
87 - compatible = "fsl,vf510";
88 - compatible = "fsl,vf600";
89 - compatible = "fsl,vf610";
78 90
79Freescale LS1021A Platform Device Tree Bindings 91Freescale LS1021A Platform Device Tree Bindings
80------------------------------------------------ 92------------------------------------------------
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index f5ac685a29fc..8d1b10180908 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -32,8 +32,7 @@ ifeq ($(CONFIG_CPU_IDLE),y)
32obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o 32obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o
33obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o 33obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
34obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o 34obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o
35# i.MX6SX reuses i.MX6Q cpuidle driver 35obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o
36obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6q.o
37endif 36endif
38 37
39ifdef CONFIG_SND_IMX_SOC 38ifdef CONFIG_SND_IMX_SOC
diff --git a/arch/arm/mach-imx/clk-gate2.c b/arch/arm/mach-imx/clk-gate2.c
index 5a75cdc81891..8935bff99fe7 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)
96{ 96{
97 struct clk_gate2 *gate = to_clk_gate2(hw); 97 struct clk_gate2 *gate = to_clk_gate2(hw);
98 98
99 if (gate->share_count) 99 return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
100 return !!__clk_get_enable_count(hw->clk); 100}
101 else 101
102 return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx); 102static void clk_gate2_disable_unused(struct clk_hw *hw)
103{
104 struct clk_gate2 *gate = to_clk_gate2(hw);
105 unsigned long flags = 0;
106 u32 reg;
107
108 spin_lock_irqsave(gate->lock, flags);
109
110 if (!gate->share_count || *gate->share_count == 0) {
111 reg = readl(gate->reg);
112 reg &= ~(3 << gate->bit_idx);
113 writel(reg, gate->reg);
114 }
115
116 spin_unlock_irqrestore(gate->lock, flags);
103} 117}
104 118
105static struct clk_ops clk_gate2_ops = { 119static struct clk_ops clk_gate2_ops = {
106 .enable = clk_gate2_enable, 120 .enable = clk_gate2_enable,
107 .disable = clk_gate2_disable, 121 .disable = clk_gate2_disable,
122 .disable_unused = clk_gate2_disable_unused,
108 .is_enabled = clk_gate2_is_enabled, 123 .is_enabled = clk_gate2_is_enabled,
109}; 124};
110 125
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 5951660d1bd2..108b80bb048a 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)
386 clk[IMX6Q_CLK_ECSPI5] = imx_clk_gate2("ecspi5", "ecspi_root", base + 0x6c, 8); 386 clk[IMX6Q_CLK_ECSPI5] = imx_clk_gate2("ecspi5", "ecspi_root", base + 0x6c, 8);
387 clk[IMX6QDL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x6c, 10); 387 clk[IMX6QDL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x6c, 10);
388 clk[IMX6QDL_CLK_ESAI_EXTAL] = imx_clk_gate2_shared("esai_extal", "esai_podf", base + 0x6c, 16, &share_count_esai); 388 clk[IMX6QDL_CLK_ESAI_EXTAL] = imx_clk_gate2_shared("esai_extal", "esai_podf", base + 0x6c, 16, &share_count_esai);
389 clk[IMX6QDL_CLK_ESAI_IPG] = imx_clk_gate2_shared("esai_ipg", "ipg", base + 0x6c, 16, &share_count_esai); 389 clk[IMX6QDL_CLK_ESAI_IPG] = imx_clk_gate2_shared("esai_ipg", "ahb", base + 0x6c, 16, &share_count_esai);
390 clk[IMX6QDL_CLK_ESAI_MEM] = imx_clk_gate2_shared("esai_mem", "ahb", base + 0x6c, 16, &share_count_esai); 390 clk[IMX6QDL_CLK_ESAI_MEM] = imx_clk_gate2_shared("esai_mem", "ahb", base + 0x6c, 16, &share_count_esai);
391 clk[IMX6QDL_CLK_GPT_IPG] = imx_clk_gate2("gpt_ipg", "ipg", base + 0x6c, 20); 391 clk[IMX6QDL_CLK_GPT_IPG] = imx_clk_gate2("gpt_ipg", "ipg", base + 0x6c, 20);
392 clk[IMX6QDL_CLK_GPT_IPG_PER] = imx_clk_gate2("gpt_ipg_per", "ipg_per", base + 0x6c, 22); 392 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 0ad6e5442fd8..641ebc508920 100644
--- a/arch/arm/mach-imx/clk-pllv3.c
+++ b/arch/arm/mach-imx/clk-pllv3.c
@@ -31,6 +31,7 @@
31 * @base: base address of PLL registers 31 * @base: base address of PLL registers
32 * @powerup_set: set POWER bit to power up the PLL 32 * @powerup_set: set POWER bit to power up the PLL
33 * @div_mask: mask of divider bits 33 * @div_mask: mask of divider bits
34 * @div_shift: shift of divider bits
34 * 35 *
35 * IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3 36 * IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3
36 * is actually a multiplier, and always sits at bit 0. 37 * is actually a multiplier, and always sits at bit 0.
@@ -40,6 +41,7 @@ struct clk_pllv3 {
40 void __iomem *base; 41 void __iomem *base;
41 bool powerup_set; 42 bool powerup_set;
42 u32 div_mask; 43 u32 div_mask;
44 u32 div_shift;
43}; 45};
44 46
45#define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw) 47#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,
97 unsigned long parent_rate) 99 unsigned long parent_rate)
98{ 100{
99 struct clk_pllv3 *pll = to_clk_pllv3(hw); 101 struct clk_pllv3 *pll = to_clk_pllv3(hw);
100 u32 div = readl_relaxed(pll->base) & pll->div_mask; 102 u32 div = (readl_relaxed(pll->base) >> pll->div_shift) & pll->div_mask;
101 103
102 return (div == 1) ? parent_rate * 22 : parent_rate * 20; 104 return (div == 1) ? parent_rate * 22 : parent_rate * 20;
103} 105}
@@ -125,8 +127,8 @@ static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate,
125 return -EINVAL; 127 return -EINVAL;
126 128
127 val = readl_relaxed(pll->base); 129 val = readl_relaxed(pll->base);
128 val &= ~pll->div_mask; 130 val &= ~(pll->div_mask << pll->div_shift);
129 val |= div; 131 val |= (div << pll->div_shift);
130 writel_relaxed(val, pll->base); 132 writel_relaxed(val, pll->base);
131 133
132 return clk_pllv3_wait_lock(pll); 134 return clk_pllv3_wait_lock(pll);
@@ -295,6 +297,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
295 case IMX_PLLV3_SYS: 297 case IMX_PLLV3_SYS:
296 ops = &clk_pllv3_sys_ops; 298 ops = &clk_pllv3_sys_ops;
297 break; 299 break;
300 case IMX_PLLV3_USB_VF610:
301 pll->div_shift = 1;
298 case IMX_PLLV3_USB: 302 case IMX_PLLV3_USB:
299 ops = &clk_pllv3_ops; 303 ops = &clk_pllv3_ops;
300 pll->powerup_set = true; 304 pll->powerup_set = true;
diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c
index 5937ddee1a99..61876ed6e11e 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)
172 172
173 clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1); 173 clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1);
174 clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1); 174 clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1);
175 clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x1); 175 clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x2);
176 clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f); 176 clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f);
177 clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3); 177 clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3);
178 clk[VF610_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_AV, "pll6", "pll6_bypass_src", PLL6_CTRL, 0x7f); 178 clk[VF610_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_AV, "pll6", "pll6_bypass_src", PLL6_CTRL, 0x7f);
179 clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", PLL7_CTRL, 0x1); 179 clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll7", "pll7_bypass_src", PLL7_CTRL, 0x2);
180 180
181 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); 181 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);
182 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); 182 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)
267 clk[VF610_CLK_UART1] = imx_clk_gate2("uart1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(8)); 267 clk[VF610_CLK_UART1] = imx_clk_gate2("uart1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(8));
268 clk[VF610_CLK_UART2] = imx_clk_gate2("uart2", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(9)); 268 clk[VF610_CLK_UART2] = imx_clk_gate2("uart2", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(9));
269 clk[VF610_CLK_UART3] = imx_clk_gate2("uart3", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(10)); 269 clk[VF610_CLK_UART3] = imx_clk_gate2("uart3", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(10));
270 clk[VF610_CLK_UART4] = imx_clk_gate2("uart4", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(9));
271 clk[VF610_CLK_UART5] = imx_clk_gate2("uart5", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(10));
270 272
271 clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(6)); 273 clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(6));
272 clk[VF610_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(7)); 274 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)
380 clk[VF610_CLK_DMAMUX2] = imx_clk_gate2("dmamux2", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(1)); 382 clk[VF610_CLK_DMAMUX2] = imx_clk_gate2("dmamux2", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(1));
381 clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(2)); 383 clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(2));
382 384
385 clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(7));
386
383 imx_check_clocks(clk, ARRAY_SIZE(clk)); 387 imx_check_clocks(clk, ARRAY_SIZE(clk));
384 388
385 clk_set_parent(clk[VF610_CLK_QSPI0_SEL], clk[VF610_CLK_PLL1_PFD4]); 389 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 5ef82e2f8fc5..6a07903a28bc 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -20,6 +20,7 @@ enum imx_pllv3_type {
20 IMX_PLLV3_GENERIC, 20 IMX_PLLV3_GENERIC,
21 IMX_PLLV3_SYS, 21 IMX_PLLV3_SYS,
22 IMX_PLLV3_USB, 22 IMX_PLLV3_USB,
23 IMX_PLLV3_USB_VF610,
23 IMX_PLLV3_AV, 24 IMX_PLLV3_AV,
24 IMX_PLLV3_ENET, 25 IMX_PLLV3_ENET,
25}; 26};
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index cfcdb623d78f..1028b6c505c4 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);
70unsigned int imx_get_soc_revision(void); 70unsigned int imx_get_soc_revision(void);
71void imx_init_revision_from_anatop(void); 71void imx_init_revision_from_anatop(void);
72struct device *imx_soc_device_init(void); 72struct device *imx_soc_device_init(void);
73void imx6_enable_rbc(bool enable);
74void imx_gpc_set_arm_power_in_lpm(bool power_off);
75void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw);
76void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw);
73 77
74enum mxc_cpu_pwr_mode { 78enum mxc_cpu_pwr_mode {
75 WAIT_CLOCKED, /* wfi only */ 79 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 000000000000..5a36722b089d
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx6sx.c
@@ -0,0 +1,105 @@
1/*
2 * Copyright (C) 2014 Freescale Semiconductor, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/cpuidle.h>
10#include <linux/cpu_pm.h>
11#include <linux/module.h>
12#include <asm/cpuidle.h>
13#include <asm/proc-fns.h>
14#include <asm/suspend.h>
15
16#include "common.h"
17#include "cpuidle.h"
18
19static int imx6sx_idle_finish(unsigned long val)
20{
21 cpu_do_idle();
22
23 return 0;
24}
25
26static int imx6sx_enter_wait(struct cpuidle_device *dev,
27 struct cpuidle_driver *drv, int index)
28{
29 imx6q_set_lpm(WAIT_UNCLOCKED);
30
31 switch (index) {
32 case 1:
33 cpu_do_idle();
34 break;
35 case 2:
36 imx6_enable_rbc(true);
37 imx_gpc_set_arm_power_in_lpm(true);
38 imx_set_cpu_jump(0, v7_cpu_resume);
39 /* Need to notify there is a cpu pm operation. */
40 cpu_pm_enter();
41 cpu_cluster_pm_enter();
42
43 cpu_suspend(0, imx6sx_idle_finish);
44
45 cpu_cluster_pm_exit();
46 cpu_pm_exit();
47 imx_gpc_set_arm_power_in_lpm(false);
48 imx6_enable_rbc(false);
49 break;
50 default:
51 break;
52 }
53
54 imx6q_set_lpm(WAIT_CLOCKED);
55
56 return index;
57}
58
59static struct cpuidle_driver imx6sx_cpuidle_driver = {
60 .name = "imx6sx_cpuidle",
61 .owner = THIS_MODULE,
62 .states = {
63 /* WFI */
64 ARM_CPUIDLE_WFI_STATE,
65 /* WAIT */
66 {
67 .exit_latency = 50,
68 .target_residency = 75,
69 .flags = CPUIDLE_FLAG_TIMER_STOP,
70 .enter = imx6sx_enter_wait,
71 .name = "WAIT",
72 .desc = "Clock off",
73 },
74 /* WAIT + ARM power off */
75 {
76 /*
77 * ARM gating 31us * 5 + RBC clear 65us
78 * and some margin for SW execution, here set it
79 * to 300us.
80 */
81 .exit_latency = 300,
82 .target_residency = 500,
83 .enter = imx6sx_enter_wait,
84 .name = "LOW-POWER-IDLE",
85 .desc = "ARM power off",
86 },
87 },
88 .state_count = 3,
89 .safe_state_index = 0,
90};
91
92int __init imx6sx_cpuidle_init(void)
93{
94 imx6_enable_rbc(false);
95 /*
96 * set ARM power up/down timing to the fastest,
97 * sw2iso and sw can be set to one 32K cycle = 31us
98 * except for power up sw2iso which need to be
99 * larger than LDO ramp up time.
100 */
101 imx_gpc_set_arm_power_up_timing(2, 1);
102 imx_gpc_set_arm_power_down_timing(1, 1);
103
104 return cpuidle_register(&imx6sx_cpuidle_driver, NULL);
105}
diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h
index 24e33670417c..f9140128ba05 100644
--- a/arch/arm/mach-imx/cpuidle.h
+++ b/arch/arm/mach-imx/cpuidle.h
@@ -14,6 +14,7 @@
14extern int imx5_cpuidle_init(void); 14extern int imx5_cpuidle_init(void);
15extern int imx6q_cpuidle_init(void); 15extern int imx6q_cpuidle_init(void);
16extern int imx6sl_cpuidle_init(void); 16extern int imx6sl_cpuidle_init(void);
17extern int imx6sx_cpuidle_init(void);
17#else 18#else
18static inline int imx5_cpuidle_init(void) 19static inline int imx5_cpuidle_init(void)
19{ 20{
@@ -27,4 +28,8 @@ static inline int imx6sl_cpuidle_init(void)
27{ 28{
28 return 0; 29 return 0;
29} 30}
31static inline int imx6sx_cpuidle_init(void)
32{
33 return 0;
34}
30#endif 35#endif
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 5f3602ec74fa..745caa18ab2c 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -20,6 +20,10 @@
20 20
21#define GPC_IMR1 0x008 21#define GPC_IMR1 0x008
22#define GPC_PGC_CPU_PDN 0x2a0 22#define GPC_PGC_CPU_PDN 0x2a0
23#define GPC_PGC_CPU_PUPSCR 0x2a4
24#define GPC_PGC_CPU_PDNSCR 0x2a8
25#define GPC_PGC_SW2ISO_SHIFT 0x8
26#define GPC_PGC_SW_SHIFT 0x0
23 27
24#define IMR_NUM 4 28#define IMR_NUM 4
25 29
@@ -27,6 +31,23 @@ static void __iomem *gpc_base;
27static u32 gpc_wake_irqs[IMR_NUM]; 31static u32 gpc_wake_irqs[IMR_NUM];
28static u32 gpc_saved_imrs[IMR_NUM]; 32static u32 gpc_saved_imrs[IMR_NUM];
29 33
34void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw)
35{
36 writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) |
37 (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PUPSCR);
38}
39
40void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw)
41{
42 writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) |
43 (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PDNSCR);
44}
45
46void imx_gpc_set_arm_power_in_lpm(bool power_off)
47{
48 writel_relaxed(power_off, gpc_base + GPC_PGC_CPU_PDN);
49}
50
30void imx_gpc_pre_suspend(bool arm_power_off) 51void imx_gpc_pre_suspend(bool arm_power_off)
31{ 52{
32 void __iomem *reg_imr1 = gpc_base + GPC_IMR1; 53 void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
@@ -34,7 +55,7 @@ void imx_gpc_pre_suspend(bool arm_power_off)
34 55
35 /* Tell GPC to power off ARM core when suspend */ 56 /* Tell GPC to power off ARM core when suspend */
36 if (arm_power_off) 57 if (arm_power_off)
37 writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN); 58 imx_gpc_set_arm_power_in_lpm(arm_power_off);
38 59
39 for (i = 0; i < IMR_NUM; i++) { 60 for (i = 0; i < IMR_NUM; i++) {
40 gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4); 61 gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
@@ -48,7 +69,7 @@ void imx_gpc_post_resume(void)
48 int i; 69 int i;
49 70
50 /* Keep ARM core powered on for other low-power modes */ 71 /* Keep ARM core powered on for other low-power modes */
51 writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN); 72 imx_gpc_set_arm_power_in_lpm(false);
52 73
53 for (i = 0; i < IMR_NUM; i++) 74 for (i = 0; i < IMR_NUM; i++)
54 writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4); 75 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 5057d61298b7..4ad6e473cf83 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)
329 if (dev_pm_opp_disable(cpu_dev, 852000000)) 329 if (dev_pm_opp_disable(cpu_dev, 852000000))
330 pr_warn("failed to disable 852 MHz OPP\n"); 330 pr_warn("failed to disable 852 MHz OPP\n");
331 } 331 }
332 332 iounmap(base);
333put_node: 333put_node:
334 of_node_put(np); 334 of_node_put(np);
335} 335}
diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
index 7a96c6577234..66988eb6a3a4 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)
90 90
91static void __init imx6sx_init_late(void) 91static void __init imx6sx_init_late(void)
92{ 92{
93 imx6q_cpuidle_init(); 93 imx6sx_cpuidle_init();
94 94
95 if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) 95 if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
96 platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0); 96 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 c11ab6a1dc87..2e7c75b66fe0 100644
--- a/arch/arm/mach-imx/mach-vf610.c
+++ b/arch/arm/mach-imx/mach-vf610.c
@@ -13,11 +13,14 @@
13#include <asm/hardware/cache-l2x0.h> 13#include <asm/hardware/cache-l2x0.h>
14 14
15static const char * const vf610_dt_compat[] __initconst = { 15static const char * const vf610_dt_compat[] __initconst = {
16 "fsl,vf500",
17 "fsl,vf510",
18 "fsl,vf600",
16 "fsl,vf610", 19 "fsl,vf610",
17 NULL, 20 NULL,
18}; 21};
19 22
20DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)") 23DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF5xx/VF6xx (Device Tree)")
21 .l2c_aux_val = 0, 24 .l2c_aux_val = 0,
22 .l2c_aux_mask = ~0, 25 .l2c_aux_mask = ~0,
23 .dt_compat = vf610_dt_compat, 26 .dt_compat = vf610_dt_compat,
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index 5d2c1bd5f5ef..46fd695203c7 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)
205 writel_relaxed(val, ccm_base + CGPR); 205 writel_relaxed(val, ccm_base + CGPR);
206} 206}
207 207
208static void imx6q_enable_rbc(bool enable) 208void imx6_enable_rbc(bool enable)
209{ 209{
210 u32 val; 210 u32 val;
211 211
@@ -359,17 +359,16 @@ static int imx6q_pm_enter(suspend_state_t state)
359 * RBC setting, so we do NOT need to do that here. 359 * RBC setting, so we do NOT need to do that here.
360 */ 360 */
361 if (!imx6_suspend_in_ocram_fn) 361 if (!imx6_suspend_in_ocram_fn)
362 imx6q_enable_rbc(true); 362 imx6_enable_rbc(true);
363 imx_gpc_pre_suspend(true); 363 imx_gpc_pre_suspend(true);
364 imx_anatop_pre_suspend(); 364 imx_anatop_pre_suspend();
365 imx_set_cpu_jump(0, v7_cpu_resume);
366 /* Zzz ... */ 365 /* Zzz ... */
367 cpu_suspend(0, imx6q_suspend_finish); 366 cpu_suspend(0, imx6q_suspend_finish);
368 if (cpu_is_imx6q() || cpu_is_imx6dl()) 367 if (cpu_is_imx6q() || cpu_is_imx6dl())
369 imx_smp_prepare(); 368 imx_smp_prepare();
370 imx_anatop_post_resume(); 369 imx_anatop_post_resume();
371 imx_gpc_post_resume(); 370 imx_gpc_post_resume();
372 imx6q_enable_rbc(false); 371 imx6_enable_rbc(false);
373 imx6q_enable_wb(false); 372 imx6q_enable_wb(false);
374 imx6q_set_int_mem_clk_lpm(true); 373 imx6q_set_int_mem_clk_lpm(true);
375 imx6q_set_lpm(WAIT_CLOCKED); 374 imx6q_set_lpm(WAIT_CLOCKED);
diff --git a/include/dt-bindings/clock/vf610-clock.h b/include/dt-bindings/clock/vf610-clock.h
index 801c0ac50c47..979d24a6799f 100644
--- a/include/dt-bindings/clock/vf610-clock.h
+++ b/include/dt-bindings/clock/vf610-clock.h
@@ -192,6 +192,7 @@
192#define VF610_PLL5_BYPASS 179 192#define VF610_PLL5_BYPASS 179
193#define VF610_PLL6_BYPASS 180 193#define VF610_PLL6_BYPASS 180
194#define VF610_PLL7_BYPASS 181 194#define VF610_PLL7_BYPASS 181
195#define VF610_CLK_END 182 195#define VF610_CLK_SNVS 182
196#define VF610_CLK_END 183
196 197
197#endif /* __DT_BINDINGS_CLOCK_VF610_H */ 198#endif /* __DT_BINDINGS_CLOCK_VF610_H */