diff options
author | Olof Johansson <olof@lixom.net> | 2015-01-23 17:38:55 -0500 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2015-01-23 17:38:55 -0500 |
commit | 085dd64e537b06c7b741dac5f0ff3734d27f9a13 (patch) | |
tree | 8ae20547b8fb3a5d914bbb46753dfb72eb9cb9e7 | |
parent | eeec0434e8b89fa5f29d71e5f8044dcec7939d1a (diff) | |
parent | ade9233f2e0cf4b7bf10fd122c7e9f9310bfd1a5 (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.txt | 12 | ||||
-rw-r--r-- | arch/arm/mach-imx/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-gate2.c | 23 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-imx6q.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-pllv3.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-vf610.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-imx/common.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-imx/cpuidle-imx6sx.c | 105 | ||||
-rw-r--r-- | arch/arm/mach-imx/cpuidle.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-imx/gpc.c | 25 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-imx6q.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-imx6sx.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-vf610.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-imx/pm-imx6.c | 7 | ||||
-rw-r--r-- | include/dt-bindings/clock/vf610-clock.h | 3 |
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 | |||
75 | Required root node properties: | 75 | Required root node properties: |
76 | - compatible = "fsl,imx6q"; | 76 | - compatible = "fsl,imx6q"; |
77 | 77 | ||
78 | Freescale Vybrid Platform Device Tree Bindings | ||
79 | ---------------------------------------------- | ||
80 | |||
81 | For the Vybrid SoC familiy all variants with DDR controller are supported, | ||
82 | which is the VF5xx and VF6xx series. Out of historical reasons, in most | ||
83 | places the kernel uses vf610 to refer to the whole familiy. | ||
84 | |||
85 | Required 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 | ||
79 | Freescale LS1021A Platform Device Tree Bindings | 91 | Freescale 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) | |||
32 | obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o | 32 | obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o |
33 | obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o | 33 | obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o |
34 | obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o | 34 | obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o |
35 | # i.MX6SX reuses i.MX6Q cpuidle driver | 35 | obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o |
36 | obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6q.o | ||
37 | endif | 36 | endif |
38 | 37 | ||
39 | ifdef CONFIG_SND_IMX_SOC | 38 | ifdef 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); | 102 | static 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 | ||
105 | static struct clk_ops clk_gate2_ops = { | 119 | static 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); | |||
70 | unsigned int imx_get_soc_revision(void); | 70 | unsigned int imx_get_soc_revision(void); |
71 | void imx_init_revision_from_anatop(void); | 71 | void imx_init_revision_from_anatop(void); |
72 | struct device *imx_soc_device_init(void); | 72 | struct device *imx_soc_device_init(void); |
73 | void imx6_enable_rbc(bool enable); | ||
74 | void imx_gpc_set_arm_power_in_lpm(bool power_off); | ||
75 | void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw); | ||
76 | void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw); | ||
73 | 77 | ||
74 | enum mxc_cpu_pwr_mode { | 78 | enum 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 | |||
19 | static int imx6sx_idle_finish(unsigned long val) | ||
20 | { | ||
21 | cpu_do_idle(); | ||
22 | |||
23 | return 0; | ||
24 | } | ||
25 | |||
26 | static 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 | |||
59 | static 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 | |||
92 | int __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 @@ | |||
14 | extern int imx5_cpuidle_init(void); | 14 | extern int imx5_cpuidle_init(void); |
15 | extern int imx6q_cpuidle_init(void); | 15 | extern int imx6q_cpuidle_init(void); |
16 | extern int imx6sl_cpuidle_init(void); | 16 | extern int imx6sl_cpuidle_init(void); |
17 | extern int imx6sx_cpuidle_init(void); | ||
17 | #else | 18 | #else |
18 | static inline int imx5_cpuidle_init(void) | 19 | static 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 | } |
31 | static 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; | |||
27 | static u32 gpc_wake_irqs[IMR_NUM]; | 31 | static u32 gpc_wake_irqs[IMR_NUM]; |
28 | static u32 gpc_saved_imrs[IMR_NUM]; | 32 | static u32 gpc_saved_imrs[IMR_NUM]; |
29 | 33 | ||
34 | void 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 | |||
40 | void 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 | |||
46 | void imx_gpc_set_arm_power_in_lpm(bool power_off) | ||
47 | { | ||
48 | writel_relaxed(power_off, gpc_base + GPC_PGC_CPU_PDN); | ||
49 | } | ||
50 | |||
30 | void imx_gpc_pre_suspend(bool arm_power_off) | 51 | void 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); | |
333 | put_node: | 333 | put_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 | ||
91 | static void __init imx6sx_init_late(void) | 91 | static 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 | ||
15 | static const char * const vf610_dt_compat[] __initconst = { | 15 | static 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 | ||
20 | DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)") | 23 | DT_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 | ||
208 | static void imx6q_enable_rbc(bool enable) | 208 | void 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 */ |