Commit 9e8147bb5ec5d1dda2141da70f96b98985a306cb
1 parent
803648db20
Exists in
master
and in
16 other branches
ARM: imx6q: move low-power code out of clock driver
The LPM (Low Power Mode) code that currently sits in imx6q clock driver will be reused by imx6sl. Let's move it into pm-imx6q.c, so that we can keep clock driver SoC specific and reuse pm-imx6q.c on imx6sl. In order to avoid adding another ioremap for CCM block, imx6q_pm_set_ccm_base() is created to let clock driver set up ccm_base for pm code. During the move, the unused CCGR macros get removed. Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Showing 3 changed files with 156 additions and 154 deletions Side-by-side Diff
arch/arm/mach-imx/clk-imx6q.c
... | ... | @@ -14,7 +14,6 @@ |
14 | 14 | #include <linux/types.h> |
15 | 15 | #include <linux/clk.h> |
16 | 16 | #include <linux/clkdev.h> |
17 | -#include <linux/delay.h> | |
18 | 17 | #include <linux/err.h> |
19 | 18 | #include <linux/io.h> |
20 | 19 | #include <linux/of.h> |
... | ... | @@ -25,155 +24,6 @@ |
25 | 24 | #include "common.h" |
26 | 25 | #include "hardware.h" |
27 | 26 | |
28 | -#define CCR 0x0 | |
29 | -#define BM_CCR_WB_COUNT (0x7 << 16) | |
30 | -#define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21) | |
31 | -#define BM_CCR_RBC_EN (0x1 << 27) | |
32 | - | |
33 | -#define CCGR0 0x68 | |
34 | -#define CCGR1 0x6c | |
35 | -#define CCGR2 0x70 | |
36 | -#define CCGR3 0x74 | |
37 | -#define CCGR4 0x78 | |
38 | -#define CCGR5 0x7c | |
39 | -#define CCGR6 0x80 | |
40 | -#define CCGR7 0x84 | |
41 | - | |
42 | -#define CLPCR 0x54 | |
43 | -#define BP_CLPCR_LPM 0 | |
44 | -#define BM_CLPCR_LPM (0x3 << 0) | |
45 | -#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2) | |
46 | -#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5) | |
47 | -#define BM_CLPCR_SBYOS (0x1 << 6) | |
48 | -#define BM_CLPCR_DIS_REF_OSC (0x1 << 7) | |
49 | -#define BM_CLPCR_VSTBY (0x1 << 8) | |
50 | -#define BP_CLPCR_STBY_COUNT 9 | |
51 | -#define BM_CLPCR_STBY_COUNT (0x3 << 9) | |
52 | -#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11) | |
53 | -#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16) | |
54 | -#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17) | |
55 | -#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19) | |
56 | -#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21) | |
57 | -#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22) | |
58 | -#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23) | |
59 | -#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24) | |
60 | -#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25) | |
61 | -#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26) | |
62 | -#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27) | |
63 | - | |
64 | -#define CGPR 0x64 | |
65 | -#define BM_CGPR_CHICKEN_BIT (0x1 << 17) | |
66 | - | |
67 | -static void __iomem *ccm_base; | |
68 | - | |
69 | -void imx6q_set_chicken_bit(void) | |
70 | -{ | |
71 | - u32 val = readl_relaxed(ccm_base + CGPR); | |
72 | - | |
73 | - val |= BM_CGPR_CHICKEN_BIT; | |
74 | - writel_relaxed(val, ccm_base + CGPR); | |
75 | -} | |
76 | - | |
77 | -static void imx6q_enable_rbc(bool enable) | |
78 | -{ | |
79 | - u32 val; | |
80 | - static bool last_rbc_mode; | |
81 | - | |
82 | - if (last_rbc_mode == enable) | |
83 | - return; | |
84 | - /* | |
85 | - * need to mask all interrupts in GPC before | |
86 | - * operating RBC configurations | |
87 | - */ | |
88 | - imx_gpc_mask_all(); | |
89 | - | |
90 | - /* configure RBC enable bit */ | |
91 | - val = readl_relaxed(ccm_base + CCR); | |
92 | - val &= ~BM_CCR_RBC_EN; | |
93 | - val |= enable ? BM_CCR_RBC_EN : 0; | |
94 | - writel_relaxed(val, ccm_base + CCR); | |
95 | - | |
96 | - /* configure RBC count */ | |
97 | - val = readl_relaxed(ccm_base + CCR); | |
98 | - val &= ~BM_CCR_RBC_BYPASS_COUNT; | |
99 | - val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0; | |
100 | - writel(val, ccm_base + CCR); | |
101 | - | |
102 | - /* | |
103 | - * need to delay at least 2 cycles of CKIL(32K) | |
104 | - * due to hardware design requirement, which is | |
105 | - * ~61us, here we use 65us for safe | |
106 | - */ | |
107 | - udelay(65); | |
108 | - | |
109 | - /* restore GPC interrupt mask settings */ | |
110 | - imx_gpc_restore_all(); | |
111 | - | |
112 | - last_rbc_mode = enable; | |
113 | -} | |
114 | - | |
115 | -static void imx6q_enable_wb(bool enable) | |
116 | -{ | |
117 | - u32 val; | |
118 | - static bool last_wb_mode; | |
119 | - | |
120 | - if (last_wb_mode == enable) | |
121 | - return; | |
122 | - | |
123 | - /* configure well bias enable bit */ | |
124 | - val = readl_relaxed(ccm_base + CLPCR); | |
125 | - val &= ~BM_CLPCR_WB_PER_AT_LPM; | |
126 | - val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0; | |
127 | - writel_relaxed(val, ccm_base + CLPCR); | |
128 | - | |
129 | - /* configure well bias count */ | |
130 | - val = readl_relaxed(ccm_base + CCR); | |
131 | - val &= ~BM_CCR_WB_COUNT; | |
132 | - val |= enable ? BM_CCR_WB_COUNT : 0; | |
133 | - writel_relaxed(val, ccm_base + CCR); | |
134 | - | |
135 | - last_wb_mode = enable; | |
136 | -} | |
137 | - | |
138 | -int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) | |
139 | -{ | |
140 | - u32 val = readl_relaxed(ccm_base + CLPCR); | |
141 | - | |
142 | - val &= ~BM_CLPCR_LPM; | |
143 | - switch (mode) { | |
144 | - case WAIT_CLOCKED: | |
145 | - imx6q_enable_wb(false); | |
146 | - imx6q_enable_rbc(false); | |
147 | - break; | |
148 | - case WAIT_UNCLOCKED: | |
149 | - val |= 0x1 << BP_CLPCR_LPM; | |
150 | - val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM; | |
151 | - break; | |
152 | - case STOP_POWER_ON: | |
153 | - val |= 0x2 << BP_CLPCR_LPM; | |
154 | - break; | |
155 | - case WAIT_UNCLOCKED_POWER_OFF: | |
156 | - val |= 0x1 << BP_CLPCR_LPM; | |
157 | - val &= ~BM_CLPCR_VSTBY; | |
158 | - val &= ~BM_CLPCR_SBYOS; | |
159 | - break; | |
160 | - case STOP_POWER_OFF: | |
161 | - val |= 0x2 << BP_CLPCR_LPM; | |
162 | - val |= 0x3 << BP_CLPCR_STBY_COUNT; | |
163 | - val |= BM_CLPCR_VSTBY; | |
164 | - val |= BM_CLPCR_SBYOS; | |
165 | - imx6q_enable_wb(true); | |
166 | - imx6q_enable_rbc(true); | |
167 | - break; | |
168 | - default: | |
169 | - return -EINVAL; | |
170 | - } | |
171 | - | |
172 | - writel_relaxed(val, ccm_base + CLPCR); | |
173 | - | |
174 | - return 0; | |
175 | -} | |
176 | - | |
177 | 27 | static const char *step_sels[] = { "osc", "pll2_pfd2_396m", }; |
178 | 28 | static const char *pll1_sw_sels[] = { "pll1_sys", "step", }; |
179 | 29 | static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", }; |
180 | 30 | |
... | ... | @@ -384,8 +234,9 @@ |
384 | 234 | np = ccm_node; |
385 | 235 | base = of_iomap(np, 0); |
386 | 236 | WARN_ON(!base); |
387 | - ccm_base = base; | |
388 | 237 | |
238 | + imx6q_pm_set_ccm_base(base); | |
239 | + | |
389 | 240 | /* name reg shift width parent_names num_parents */ |
390 | 241 | clk[step] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); |
391 | 242 | clk[pll1_sw] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels)); |
... | ... | @@ -626,9 +477,6 @@ |
626 | 477 | /* All existing boards with PCIe use LVDS1 */ |
627 | 478 | if (IS_ENABLED(CONFIG_PCI_IMX6)) |
628 | 479 | clk_set_parent(clk[lvds1_sel], clk[sata_ref]); |
629 | - | |
630 | - /* Set initial power mode */ | |
631 | - imx6q_set_lpm(WAIT_CLOCKED); | |
632 | 480 | |
633 | 481 | np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"); |
634 | 482 | base = of_iomap(np, 0); |
arch/arm/mach-imx/common.h
... | ... | @@ -147,9 +147,11 @@ |
147 | 147 | |
148 | 148 | #ifdef CONFIG_PM |
149 | 149 | void imx6q_pm_init(void); |
150 | +void imx6q_pm_set_ccm_base(void __iomem *base); | |
150 | 151 | void imx5_pm_init(void); |
151 | 152 | #else |
152 | 153 | static inline void imx6q_pm_init(void) {} |
154 | +static inline void imx6q_pm_set_ccm_base(void __iomem *base) {} | |
153 | 155 | static inline void imx5_pm_init(void) {} |
154 | 156 | #endif |
155 | 157 |
arch/arm/mach-imx/pm-imx6q.c
... | ... | @@ -10,9 +10,11 @@ |
10 | 10 | * http://www.gnu.org/copyleft/gpl.html |
11 | 11 | */ |
12 | 12 | |
13 | +#include <linux/delay.h> | |
13 | 14 | #include <linux/init.h> |
14 | 15 | #include <linux/io.h> |
15 | 16 | #include <linux/of.h> |
17 | +#include <linux/of_address.h> | |
16 | 18 | #include <linux/suspend.h> |
17 | 19 | #include <asm/cacheflush.h> |
18 | 20 | #include <asm/proc-fns.h> |
... | ... | @@ -22,6 +24,146 @@ |
22 | 24 | #include "common.h" |
23 | 25 | #include "hardware.h" |
24 | 26 | |
27 | +#define CCR 0x0 | |
28 | +#define BM_CCR_WB_COUNT (0x7 << 16) | |
29 | +#define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21) | |
30 | +#define BM_CCR_RBC_EN (0x1 << 27) | |
31 | + | |
32 | +#define CLPCR 0x54 | |
33 | +#define BP_CLPCR_LPM 0 | |
34 | +#define BM_CLPCR_LPM (0x3 << 0) | |
35 | +#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2) | |
36 | +#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5) | |
37 | +#define BM_CLPCR_SBYOS (0x1 << 6) | |
38 | +#define BM_CLPCR_DIS_REF_OSC (0x1 << 7) | |
39 | +#define BM_CLPCR_VSTBY (0x1 << 8) | |
40 | +#define BP_CLPCR_STBY_COUNT 9 | |
41 | +#define BM_CLPCR_STBY_COUNT (0x3 << 9) | |
42 | +#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11) | |
43 | +#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16) | |
44 | +#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17) | |
45 | +#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19) | |
46 | +#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21) | |
47 | +#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22) | |
48 | +#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23) | |
49 | +#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24) | |
50 | +#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25) | |
51 | +#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26) | |
52 | +#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27) | |
53 | + | |
54 | +#define CGPR 0x64 | |
55 | +#define BM_CGPR_CHICKEN_BIT (0x1 << 17) | |
56 | + | |
57 | +static void __iomem *ccm_base; | |
58 | + | |
59 | +void imx6q_set_chicken_bit(void) | |
60 | +{ | |
61 | + u32 val = readl_relaxed(ccm_base + CGPR); | |
62 | + | |
63 | + val |= BM_CGPR_CHICKEN_BIT; | |
64 | + writel_relaxed(val, ccm_base + CGPR); | |
65 | +} | |
66 | + | |
67 | +static void imx6q_enable_rbc(bool enable) | |
68 | +{ | |
69 | + u32 val; | |
70 | + static bool last_rbc_mode; | |
71 | + | |
72 | + if (last_rbc_mode == enable) | |
73 | + return; | |
74 | + /* | |
75 | + * need to mask all interrupts in GPC before | |
76 | + * operating RBC configurations | |
77 | + */ | |
78 | + imx_gpc_mask_all(); | |
79 | + | |
80 | + /* configure RBC enable bit */ | |
81 | + val = readl_relaxed(ccm_base + CCR); | |
82 | + val &= ~BM_CCR_RBC_EN; | |
83 | + val |= enable ? BM_CCR_RBC_EN : 0; | |
84 | + writel_relaxed(val, ccm_base + CCR); | |
85 | + | |
86 | + /* configure RBC count */ | |
87 | + val = readl_relaxed(ccm_base + CCR); | |
88 | + val &= ~BM_CCR_RBC_BYPASS_COUNT; | |
89 | + val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0; | |
90 | + writel(val, ccm_base + CCR); | |
91 | + | |
92 | + /* | |
93 | + * need to delay at least 2 cycles of CKIL(32K) | |
94 | + * due to hardware design requirement, which is | |
95 | + * ~61us, here we use 65us for safe | |
96 | + */ | |
97 | + udelay(65); | |
98 | + | |
99 | + /* restore GPC interrupt mask settings */ | |
100 | + imx_gpc_restore_all(); | |
101 | + | |
102 | + last_rbc_mode = enable; | |
103 | +} | |
104 | + | |
105 | +static void imx6q_enable_wb(bool enable) | |
106 | +{ | |
107 | + u32 val; | |
108 | + static bool last_wb_mode; | |
109 | + | |
110 | + if (last_wb_mode == enable) | |
111 | + return; | |
112 | + | |
113 | + /* configure well bias enable bit */ | |
114 | + val = readl_relaxed(ccm_base + CLPCR); | |
115 | + val &= ~BM_CLPCR_WB_PER_AT_LPM; | |
116 | + val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0; | |
117 | + writel_relaxed(val, ccm_base + CLPCR); | |
118 | + | |
119 | + /* configure well bias count */ | |
120 | + val = readl_relaxed(ccm_base + CCR); | |
121 | + val &= ~BM_CCR_WB_COUNT; | |
122 | + val |= enable ? BM_CCR_WB_COUNT : 0; | |
123 | + writel_relaxed(val, ccm_base + CCR); | |
124 | + | |
125 | + last_wb_mode = enable; | |
126 | +} | |
127 | + | |
128 | +int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) | |
129 | +{ | |
130 | + u32 val = readl_relaxed(ccm_base + CLPCR); | |
131 | + | |
132 | + val &= ~BM_CLPCR_LPM; | |
133 | + switch (mode) { | |
134 | + case WAIT_CLOCKED: | |
135 | + imx6q_enable_wb(false); | |
136 | + imx6q_enable_rbc(false); | |
137 | + break; | |
138 | + case WAIT_UNCLOCKED: | |
139 | + val |= 0x1 << BP_CLPCR_LPM; | |
140 | + val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM; | |
141 | + break; | |
142 | + case STOP_POWER_ON: | |
143 | + val |= 0x2 << BP_CLPCR_LPM; | |
144 | + break; | |
145 | + case WAIT_UNCLOCKED_POWER_OFF: | |
146 | + val |= 0x1 << BP_CLPCR_LPM; | |
147 | + val &= ~BM_CLPCR_VSTBY; | |
148 | + val &= ~BM_CLPCR_SBYOS; | |
149 | + break; | |
150 | + case STOP_POWER_OFF: | |
151 | + val |= 0x2 << BP_CLPCR_LPM; | |
152 | + val |= 0x3 << BP_CLPCR_STBY_COUNT; | |
153 | + val |= BM_CLPCR_VSTBY; | |
154 | + val |= BM_CLPCR_SBYOS; | |
155 | + imx6q_enable_wb(true); | |
156 | + imx6q_enable_rbc(true); | |
157 | + break; | |
158 | + default: | |
159 | + return -EINVAL; | |
160 | + } | |
161 | + | |
162 | + writel_relaxed(val, ccm_base + CLPCR); | |
163 | + | |
164 | + return 0; | |
165 | +} | |
166 | + | |
25 | 167 | static int imx6q_suspend_finish(unsigned long val) |
26 | 168 | { |
27 | 169 | cpu_do_idle(); |
28 | 170 | |
... | ... | @@ -55,8 +197,18 @@ |
55 | 197 | .valid = suspend_valid_only_mem, |
56 | 198 | }; |
57 | 199 | |
200 | +void __init imx6q_pm_set_ccm_base(void __iomem *base) | |
201 | +{ | |
202 | + ccm_base = base; | |
203 | +} | |
204 | + | |
58 | 205 | void __init imx6q_pm_init(void) |
59 | 206 | { |
207 | + WARN_ON(!ccm_base); | |
208 | + | |
209 | + /* Set initial power mode */ | |
210 | + imx6q_set_lpm(WAIT_CLOCKED); | |
211 | + | |
60 | 212 | suspend_set_ops(&imx6q_pm_ops); |
61 | 213 | } |