@@ -43,14 +43,34 @@ struct exynos_cpuclk;
4343typedef int (* exynos_rate_change_fn_t )(struct clk_notifier_data * ndata ,
4444 struct exynos_cpuclk * cpuclk );
4545
46+ /**
47+ * struct exynos_cpuclk_regs - Register offsets for CPU related clocks
48+ * @mux_sel: offset of CPU MUX_SEL register (for selecting MUX clock parent)
49+ * @mux_stat: offset of CPU MUX_STAT register (for checking MUX clock status)
50+ * @div_cpu0: offset of CPU DIV0 register (for modifying divider values)
51+ * @div_cpu1: offset of CPU DIV1 register (for modifying divider values)
52+ * @div_stat_cpu0: offset of CPU DIV0_STAT register (for checking DIV status)
53+ * @div_stat_cpu1: offset of CPU DIV1_STAT register (for checking DIV status)
54+ */
55+ struct exynos_cpuclk_regs {
56+ u32 mux_sel ;
57+ u32 mux_stat ;
58+ u32 div_cpu0 ;
59+ u32 div_cpu1 ;
60+ u32 div_stat_cpu0 ;
61+ u32 div_stat_cpu1 ;
62+ };
63+
4664/**
4765 * struct exynos_cpuclk_chip - Chip specific data for CPU clock
66+ * @regs: register offsets for CPU related clocks
4867 * @pre_rate_cb: callback to run before CPU clock rate change
4968 * @post_rate_cb: callback to run after CPU clock rate change
5069 */
5170struct exynos_cpuclk_chip {
52- exynos_rate_change_fn_t pre_rate_cb ;
53- exynos_rate_change_fn_t post_rate_cb ;
71+ const struct exynos_cpuclk_regs * regs ;
72+ exynos_rate_change_fn_t pre_rate_cb ;
73+ exynos_rate_change_fn_t post_rate_cb ;
5474};
5575
5676/**
@@ -130,43 +150,48 @@ static void wait_until_mux_stable(void __iomem *mux_reg, u32 mux_pos,
130150 pr_err ("%s: re-parenting mux timed-out\n" , __func__ );
131151}
132152
133- /* ---- Exynos 3/4/5 -------------------------------------------------------- */
134-
135- #define E4210_SRC_CPU 0x200
136- #define E4210_STAT_CPU 0x400
137- #define E4210_DIV_CPU0 0x500
138- #define E4210_DIV_CPU1 0x504
139- #define E4210_DIV_STAT_CPU0 0x600
140- #define E4210_DIV_STAT_CPU1 0x604
141-
142- #define E4210_DIV0_RATIO0_MASK GENMASK(2, 0)
143- #define E4210_DIV1_HPM_MASK GENMASK(6, 4)
144- #define E4210_DIV1_COPY_MASK GENMASK(2, 0)
145- #define E4210_MUX_HPM_MASK BIT(20)
146- #define E4210_DIV0_ATB_SHIFT 16
147- #define E4210_DIV0_ATB_MASK (DIV_MASK << E4210_DIV0_ATB_SHIFT)
148-
149153/*
150154 * Helper function to set the 'safe' dividers for the CPU clock. The parameters
151155 * div and mask contain the divider value and the register bit mask of the
152156 * dividers to be programmed.
153157 */
154- static void exynos_set_safe_div (void __iomem * base , unsigned long div ,
158+ static void exynos_set_safe_div (struct exynos_cpuclk * cpuclk , unsigned long div ,
155159 unsigned long mask )
156160{
161+ const struct exynos_cpuclk_regs * const regs = cpuclk -> chip -> regs ;
162+ void __iomem * base = cpuclk -> base ;
157163 unsigned long div0 ;
158164
159- div0 = readl (base + E4210_DIV_CPU0 );
165+ div0 = readl (base + regs -> div_cpu0 );
160166 div0 = (div0 & ~mask ) | (div & mask );
161- writel (div0 , base + E4210_DIV_CPU0 );
162- wait_until_divider_stable (base + E4210_DIV_STAT_CPU0 , mask );
167+ writel (div0 , base + regs -> div_cpu0 );
168+ wait_until_divider_stable (base + regs -> div_stat_cpu0 , mask );
163169}
164170
171+ /* ---- Exynos 3/4/5 -------------------------------------------------------- */
172+
173+ #define E4210_DIV0_RATIO0_MASK GENMASK(2, 0)
174+ #define E4210_DIV1_HPM_MASK GENMASK(6, 4)
175+ #define E4210_DIV1_COPY_MASK GENMASK(2, 0)
176+ #define E4210_MUX_HPM_MASK BIT(20)
177+ #define E4210_DIV0_ATB_SHIFT 16
178+ #define E4210_DIV0_ATB_MASK (DIV_MASK << E4210_DIV0_ATB_SHIFT)
179+
180+ static const struct exynos_cpuclk_regs e4210_cpuclk_regs = {
181+ .mux_sel = 0x200 ,
182+ .mux_stat = 0x400 ,
183+ .div_cpu0 = 0x500 ,
184+ .div_cpu1 = 0x504 ,
185+ .div_stat_cpu0 = 0x600 ,
186+ .div_stat_cpu1 = 0x604 ,
187+ };
188+
165189/* handler for pre-rate change notification from parent clock */
166190static int exynos_cpuclk_pre_rate_change (struct clk_notifier_data * ndata ,
167191 struct exynos_cpuclk * cpuclk )
168192{
169193 const struct exynos_cpuclk_cfg_data * cfg_data = cpuclk -> cfg ;
194+ const struct exynos_cpuclk_regs * const regs = cpuclk -> chip -> regs ;
170195 void __iomem * base = cpuclk -> base ;
171196 unsigned long alt_prate = clk_hw_get_rate (cpuclk -> alt_parent );
172197 unsigned long div0 , div1 = 0 , mux_reg ;
@@ -189,8 +214,8 @@ static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
189214 div0 = cfg_data -> div0 ;
190215 if (cpuclk -> flags & CLK_CPU_HAS_DIV1 ) {
191216 div1 = cfg_data -> div1 ;
192- if (readl (base + E4210_SRC_CPU ) & E4210_MUX_HPM_MASK )
193- div1 = readl (base + E4210_DIV_CPU1 ) &
217+ if (readl (base + regs -> mux_sel ) & E4210_MUX_HPM_MASK )
218+ div1 = readl (base + regs -> div_cpu1 ) &
194219 (E4210_DIV1_HPM_MASK | E4210_DIV1_COPY_MASK );
195220 }
196221
@@ -217,22 +242,22 @@ static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
217242 alt_div |= E4210_DIV0_ATB_MASK ;
218243 alt_div_mask |= E4210_DIV0_ATB_MASK ;
219244 }
220- exynos_set_safe_div (base , alt_div , alt_div_mask );
245+ exynos_set_safe_div (cpuclk , alt_div , alt_div_mask );
221246 div0 |= alt_div ;
222247 }
223248
224249 /* select sclk_mpll as the alternate parent */
225- mux_reg = readl (base + E4210_SRC_CPU );
226- writel (mux_reg | (1 << 16 ), base + E4210_SRC_CPU );
227- wait_until_mux_stable (base + E4210_STAT_CPU , 16 , 2 );
250+ mux_reg = readl (base + regs -> mux_sel );
251+ writel (mux_reg | (1 << 16 ), base + regs -> mux_sel );
252+ wait_until_mux_stable (base + regs -> mux_stat , 16 , 2 );
228253
229254 /* alternate parent is active now. set the dividers */
230- writel (div0 , base + E4210_DIV_CPU0 );
231- wait_until_divider_stable (base + E4210_DIV_STAT_CPU0 , DIV_MASK_ALL );
255+ writel (div0 , base + regs -> div_cpu0 );
256+ wait_until_divider_stable (base + regs -> div_stat_cpu0 , DIV_MASK_ALL );
232257
233258 if (cpuclk -> flags & CLK_CPU_HAS_DIV1 ) {
234- writel (div1 , base + E4210_DIV_CPU1 );
235- wait_until_divider_stable (base + E4210_DIV_STAT_CPU1 ,
259+ writel (div1 , base + regs -> div_cpu1 );
260+ wait_until_divider_stable (base + regs -> div_stat_cpu1 ,
236261 DIV_MASK_ALL );
237262 }
238263
@@ -245,6 +270,7 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
245270 struct exynos_cpuclk * cpuclk )
246271{
247272 const struct exynos_cpuclk_cfg_data * cfg_data = cpuclk -> cfg ;
273+ const struct exynos_cpuclk_regs * const regs = cpuclk -> chip -> regs ;
248274 void __iomem * base = cpuclk -> base ;
249275 unsigned long div = 0 , div_mask = DIV_MASK ;
250276 unsigned long mux_reg ;
@@ -262,50 +288,37 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
262288 spin_lock_irqsave (cpuclk -> lock , flags );
263289
264290 /* select mout_apll as the alternate parent */
265- mux_reg = readl (base + E4210_SRC_CPU );
266- writel (mux_reg & ~(1 << 16 ), base + E4210_SRC_CPU );
267- wait_until_mux_stable (base + E4210_STAT_CPU , 16 , 1 );
291+ mux_reg = readl (base + regs -> mux_sel );
292+ writel (mux_reg & ~(1 << 16 ), base + regs -> mux_sel );
293+ wait_until_mux_stable (base + regs -> mux_stat , 16 , 1 );
268294
269295 if (cpuclk -> flags & CLK_CPU_NEEDS_DEBUG_ALT_DIV ) {
270296 div |= (cfg_data -> div0 & E4210_DIV0_ATB_MASK );
271297 div_mask |= E4210_DIV0_ATB_MASK ;
272298 }
273299
274- exynos_set_safe_div (base , div , div_mask );
300+ exynos_set_safe_div (cpuclk , div , div_mask );
275301 spin_unlock_irqrestore (cpuclk -> lock , flags );
276302 return 0 ;
277303}
278304
279305/* ---- Exynos5433 ---------------------------------------------------------- */
280306
281- #define E5433_MUX_SEL2 0x208
282- #define E5433_MUX_STAT2 0x408
283- #define E5433_DIV_CPU0 0x600
284- #define E5433_DIV_CPU1 0x604
285- #define E5433_DIV_STAT_CPU0 0x700
286- #define E5433_DIV_STAT_CPU1 0x704
287-
288- /*
289- * Helper function to set the 'safe' dividers for the CPU clock. The parameters
290- * div and mask contain the divider value and the register bit mask of the
291- * dividers to be programmed.
292- */
293- static void exynos5433_set_safe_div (void __iomem * base , unsigned long div ,
294- unsigned long mask )
295- {
296- unsigned long div0 ;
297-
298- div0 = readl (base + E5433_DIV_CPU0 );
299- div0 = (div0 & ~mask ) | (div & mask );
300- writel (div0 , base + E5433_DIV_CPU0 );
301- wait_until_divider_stable (base + E5433_DIV_STAT_CPU0 , mask );
302- }
307+ static const struct exynos_cpuclk_regs e5433_cpuclk_regs = {
308+ .mux_sel = 0x208 ,
309+ .mux_stat = 0x408 ,
310+ .div_cpu0 = 0x600 ,
311+ .div_cpu1 = 0x604 ,
312+ .div_stat_cpu0 = 0x700 ,
313+ .div_stat_cpu1 = 0x704 ,
314+ };
303315
304316/* handler for pre-rate change notification from parent clock */
305317static int exynos5433_cpuclk_pre_rate_change (struct clk_notifier_data * ndata ,
306318 struct exynos_cpuclk * cpuclk )
307319{
308320 const struct exynos_cpuclk_cfg_data * cfg_data = cpuclk -> cfg ;
321+ const struct exynos_cpuclk_regs * const regs = cpuclk -> chip -> regs ;
309322 void __iomem * base = cpuclk -> base ;
310323 unsigned long alt_prate = clk_hw_get_rate (cpuclk -> alt_parent );
311324 unsigned long div0 , div1 = 0 , mux_reg ;
@@ -342,21 +355,21 @@ static int exynos5433_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
342355 alt_div = DIV_ROUND_UP (alt_prate , tmp_rate ) - 1 ;
343356 WARN_ON (alt_div >= MAX_DIV );
344357
345- exynos5433_set_safe_div ( base , alt_div , alt_div_mask );
358+ exynos_set_safe_div ( cpuclk , alt_div , alt_div_mask );
346359 div0 |= alt_div ;
347360 }
348361
349362 /* select the alternate parent */
350- mux_reg = readl (base + E5433_MUX_SEL2 );
351- writel (mux_reg | 1 , base + E5433_MUX_SEL2 );
352- wait_until_mux_stable (base + E5433_MUX_STAT2 , 0 , 2 );
363+ mux_reg = readl (base + regs -> mux_sel );
364+ writel (mux_reg | 1 , base + regs -> mux_sel );
365+ wait_until_mux_stable (base + regs -> mux_stat , 0 , 2 );
353366
354367 /* alternate parent is active now. set the dividers */
355- writel (div0 , base + E5433_DIV_CPU0 );
356- wait_until_divider_stable (base + E5433_DIV_STAT_CPU0 , DIV_MASK_ALL );
368+ writel (div0 , base + regs -> div_cpu0 );
369+ wait_until_divider_stable (base + regs -> div_stat_cpu0 , DIV_MASK_ALL );
357370
358- writel (div1 , base + E5433_DIV_CPU1 );
359- wait_until_divider_stable (base + E5433_DIV_STAT_CPU1 , DIV_MASK_ALL );
371+ writel (div1 , base + regs -> div_cpu1 );
372+ wait_until_divider_stable (base + regs -> div_stat_cpu1 , DIV_MASK_ALL );
360373
361374 spin_unlock_irqrestore (cpuclk -> lock , flags );
362375 return 0 ;
@@ -366,6 +379,7 @@ static int exynos5433_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
366379static int exynos5433_cpuclk_post_rate_change (struct clk_notifier_data * ndata ,
367380 struct exynos_cpuclk * cpuclk )
368381{
382+ const struct exynos_cpuclk_regs * const regs = cpuclk -> chip -> regs ;
369383 void __iomem * base = cpuclk -> base ;
370384 unsigned long div = 0 , div_mask = DIV_MASK ;
371385 unsigned long mux_reg ;
@@ -374,11 +388,11 @@ static int exynos5433_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
374388 spin_lock_irqsave (cpuclk -> lock , flags );
375389
376390 /* select apll as the alternate parent */
377- mux_reg = readl (base + E5433_MUX_SEL2 );
378- writel (mux_reg & ~1 , base + E5433_MUX_SEL2 );
379- wait_until_mux_stable (base + E5433_MUX_STAT2 , 0 , 1 );
391+ mux_reg = readl (base + regs -> mux_sel );
392+ writel (mux_reg & ~1 , base + regs -> mux_sel );
393+ wait_until_mux_stable (base + regs -> mux_stat , 0 , 1 );
380394
381- exynos5433_set_safe_div ( base , div , div_mask );
395+ exynos_set_safe_div ( cpuclk , div , div_mask );
382396 spin_unlock_irqrestore (cpuclk -> lock , flags );
383397 return 0 ;
384398}
@@ -436,10 +450,12 @@ static int exynos_cpuclk_notifier_cb(struct notifier_block *nb,
436450
437451static const struct exynos_cpuclk_chip exynos_clkcpu_chips [] = {
438452 [CPUCLK_LAYOUT_E4210 ] = {
453+ .regs = & e4210_cpuclk_regs ,
439454 .pre_rate_cb = exynos_cpuclk_pre_rate_change ,
440455 .post_rate_cb = exynos_cpuclk_post_rate_change ,
441456 },
442457 [CPUCLK_LAYOUT_E5433 ] = {
458+ .regs = & e5433_cpuclk_regs ,
443459 .pre_rate_cb = exynos5433_cpuclk_pre_rate_change ,
444460 .post_rate_cb = exynos5433_cpuclk_post_rate_change ,
445461 },
0 commit comments