diff options
-rw-r--r-- | arch/arm/mach-imx/clk-imx6q.c | 156 | ||||
-rw-r--r-- | arch/arm/mach-imx/common.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-imx/pm-imx6q.c | 152 |
3 files changed, 156 insertions, 154 deletions
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 07bc0d8b573f..d756d91fd741 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
16 | #include <linux/clkdev.h> | 16 | #include <linux/clkdev.h> |
17 | #include <linux/delay.h> | ||
18 | #include <linux/err.h> | 17 | #include <linux/err.h> |
19 | #include <linux/io.h> | 18 | #include <linux/io.h> |
20 | #include <linux/of.h> | 19 | #include <linux/of.h> |
@@ -25,155 +24,6 @@ | |||
25 | #include "common.h" | 24 | #include "common.h" |
26 | #include "hardware.h" | 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 | static const char *step_sels[] = { "osc", "pll2_pfd2_396m", }; | 27 | static const char *step_sels[] = { "osc", "pll2_pfd2_396m", }; |
178 | static const char *pll1_sw_sels[] = { "pll1_sys", "step", }; | 28 | static const char *pll1_sw_sels[] = { "pll1_sys", "step", }; |
179 | static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", }; | 29 | static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", }; |
@@ -384,7 +234,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) | |||
384 | np = ccm_node; | 234 | np = ccm_node; |
385 | base = of_iomap(np, 0); | 235 | base = of_iomap(np, 0); |
386 | WARN_ON(!base); | 236 | WARN_ON(!base); |
387 | ccm_base = base; | 237 | |
238 | imx6q_pm_set_ccm_base(base); | ||
388 | 239 | ||
389 | /* name reg shift width parent_names num_parents */ | 240 | /* name reg shift width parent_names num_parents */ |
390 | clk[step] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); | 241 | clk[step] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); |
@@ -627,9 +478,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) | |||
627 | if (IS_ENABLED(CONFIG_PCI_IMX6)) | 478 | if (IS_ENABLED(CONFIG_PCI_IMX6)) |
628 | clk_set_parent(clk[lvds1_sel], clk[sata_ref]); | 479 | clk_set_parent(clk[lvds1_sel], clk[sata_ref]); |
629 | 480 | ||
630 | /* Set initial power mode */ | ||
631 | imx6q_set_lpm(WAIT_CLOCKED); | ||
632 | |||
633 | np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"); | 481 | np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"); |
634 | base = of_iomap(np, 0); | 482 | base = of_iomap(np, 0); |
635 | WARN_ON(!base); | 483 | WARN_ON(!base); |
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index ddcbd90b4edf..fde6661ef70d 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h | |||
@@ -147,9 +147,11 @@ int imx_cpu_kill(unsigned int cpu); | |||
147 | 147 | ||
148 | #ifdef CONFIG_PM | 148 | #ifdef CONFIG_PM |
149 | void imx6q_pm_init(void); | 149 | void imx6q_pm_init(void); |
150 | void imx6q_pm_set_ccm_base(void __iomem *base); | ||
150 | void imx5_pm_init(void); | 151 | void imx5_pm_init(void); |
151 | #else | 152 | #else |
152 | static inline void imx6q_pm_init(void) {} | 153 | static inline void imx6q_pm_init(void) {} |
154 | static inline void imx6q_pm_set_ccm_base(void __iomem *base) {} | ||
153 | static inline void imx5_pm_init(void) {} | 155 | static inline void imx5_pm_init(void) {} |
154 | #endif | 156 | #endif |
155 | 157 | ||
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c index 204942749e21..461a895a1388 100644 --- a/arch/arm/mach-imx/pm-imx6q.c +++ b/arch/arm/mach-imx/pm-imx6q.c | |||
@@ -10,9 +10,11 @@ | |||
10 | * http://www.gnu.org/copyleft/gpl.html | 10 | * http://www.gnu.org/copyleft/gpl.html |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/delay.h> | ||
13 | #include <linux/init.h> | 14 | #include <linux/init.h> |
14 | #include <linux/io.h> | 15 | #include <linux/io.h> |
15 | #include <linux/of.h> | 16 | #include <linux/of.h> |
17 | #include <linux/of_address.h> | ||
16 | #include <linux/suspend.h> | 18 | #include <linux/suspend.h> |
17 | #include <asm/cacheflush.h> | 19 | #include <asm/cacheflush.h> |
18 | #include <asm/proc-fns.h> | 20 | #include <asm/proc-fns.h> |
@@ -22,6 +24,146 @@ | |||
22 | #include "common.h" | 24 | #include "common.h" |
23 | #include "hardware.h" | 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 | static int imx6q_suspend_finish(unsigned long val) | 167 | static int imx6q_suspend_finish(unsigned long val) |
26 | { | 168 | { |
27 | cpu_do_idle(); | 169 | cpu_do_idle(); |
@@ -55,7 +197,17 @@ static const struct platform_suspend_ops imx6q_pm_ops = { | |||
55 | .valid = suspend_valid_only_mem, | 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 | void __init imx6q_pm_init(void) | 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 | suspend_set_ops(&imx6q_pm_ops); | 212 | suspend_set_ops(&imx6q_pm_ops); |
61 | } | 213 | } |