Commit 9e8147bb5ec5d1dda2141da70f96b98985a306cb

Authored by Shawn Guo
1 parent 803648db20

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 }