blob: d5b46a87a188e5f2739d05d73e1f0d2d1c43c229 [file] [log] [blame]
Stefan Bosch95e9a8e2020-07-10 19:07:26 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2016 Nexell
4 * Hyunseok, Jung <hsjung@nexell.co.kr>
5 */
6
7#include <common.h>
8#include <command.h>
9#include <linux/err.h>
10#include <asm/io.h>
11#include <asm/arch/nexell.h>
12#include <asm/arch/clk.h>
13
14/*
15 * clock generator macros
16 */
17#define I_PLL0_BIT (0)
18#define I_PLL1_BIT (1)
19#define I_PLL2_BIT (2)
20#define I_PLL3_BIT (3)
21#define I_EXT1_BIT (4)
22#define I_EXT2_BIT (5)
23#define I_CLKn_BIT (7)
24#define I_EXT1_BIT_FORCE (8)
25#define I_EXT2_BIT_FORCE (9)
26
27#define I_CLOCK_NUM 6 /* PLL0, PLL1, PLL2, PLL3, EXT1, EXT2 */
28
29#define I_EXECEPT_CLK (0)
30#define I_CLOCK_MASK (((1 << I_CLOCK_NUM) - 1) & ~I_EXECEPT_CLK)
31
32#define I_PLL0 (1 << I_PLL0_BIT)
33#define I_PLL1 (1 << I_PLL1_BIT)
34#define I_PLL2 (1 << I_PLL2_BIT)
35#define I_PLL3 (1 << I_PLL3_BIT)
36#define I_EXTCLK1 (1 << I_EXT1_BIT)
37#define I_EXTCLK2 (1 << I_EXT2_BIT)
38#define I_EXTCLK1_FORCE (1 << I_EXT1_BIT_FORCE)
39#define I_EXTCLK2_FORCE (1 << I_EXT2_BIT_FORCE)
40
41#define I_PLL_0_1 (I_PLL0 | I_PLL1)
42#define I_PLL_0_2 (I_PLL_0_1 | I_PLL2)
43#define I_PLL_0_3 (I_PLL_0_2 | I_PLL3)
44#define I_CLKnOUT (0)
45
46#define I_PCLK (1 << 16)
47#define I_BCLK (1 << 17)
48#define I_GATE_PCLK (1 << 20)
49#define I_GATE_BCLK (1 << 21)
50#define I_PCLK_MASK (I_GATE_PCLK | I_PCLK)
51#define I_BCLK_MASK (I_GATE_BCLK | I_BCLK)
52
53struct clk_dev_peri {
54 const char *dev_name;
55 void __iomem *base;
56 int dev_id;
57 int periph_id;
58 int clk_step;
59 u32 in_mask;
60 u32 in_mask1;
61 int div_src_0;
62 int div_val_0;
63 int invert_0;
64 int div_src_1;
65 int div_val_1;
66 int invert_1;
67 int in_extclk_1;
68 int in_extclk_2;
69};
70
71struct clk_dev {
72 struct clk clk;
73 struct clk *link;
74 const char *name;
75 struct clk_dev_peri *peri;
76};
77
78struct clk_dev_map {
79 unsigned int con_enb;
80 unsigned int con_gen[4];
81};
82
83#define CLK_PERI_1S(name, devid, id, addr, mk)[id] = \
84 { .dev_name = name, .dev_id = devid, .periph_id = id, .clk_step = 1, \
85 .base = (void *)addr, .in_mask = mk, }
86
87#define CLK_PERI_2S(name, devid, id, addr, mk, mk2)[id] = \
88 { .dev_name = name, .dev_id = devid, .periph_id = id, .clk_step = 2, \
89 .base = (void *)addr, .in_mask = mk, .in_mask1 = mk2, }
90
91static const char * const clk_core[] = {
92 CORECLK_NAME_PLL0, CORECLK_NAME_PLL1, CORECLK_NAME_PLL2,
93 CORECLK_NAME_PLL3, CORECLK_NAME_FCLK, CORECLK_NAME_MCLK,
94 CORECLK_NAME_BCLK, CORECLK_NAME_PCLK, CORECLK_NAME_HCLK,
95};
96
97/*
98 * Section ".data" must be used because BSS is not available before relocation,
99 * in board_init_f(), respectively! I.e. global variables can not be used!
100 */
101static struct clk_dev_peri clk_periphs[]
Marek BehĂșn236f2ec2021-05-20 13:23:52 +0200102 __section(".data") = {
Stefan Bosch95e9a8e2020-07-10 19:07:26 +0200103 CLK_PERI_1S(DEV_NAME_TIMER, 0, CLK_ID_TIMER_0,
104 PHY_BASEADDR_CLKGEN14, (I_PLL_0_2)),
105 CLK_PERI_1S(DEV_NAME_TIMER, 1, CLK_ID_TIMER_1,
106 PHY_BASEADDR_CLKGEN0, (I_PLL_0_2)),
107 CLK_PERI_1S(DEV_NAME_TIMER, 2, CLK_ID_TIMER_2,
108 PHY_BASEADDR_CLKGEN1, (I_PLL_0_2)),
109 CLK_PERI_1S(DEV_NAME_TIMER, 3, CLK_ID_TIMER_3,
110 PHY_BASEADDR_CLKGEN2, (I_PLL_0_2)),
111 CLK_PERI_1S(DEV_NAME_UART, 0, CLK_ID_UART_0,
112 PHY_BASEADDR_CLKGEN22, (I_PLL_0_2)),
113 CLK_PERI_1S(DEV_NAME_UART, 1, CLK_ID_UART_1,
114 PHY_BASEADDR_CLKGEN24, (I_PLL_0_2)),
115 CLK_PERI_1S(DEV_NAME_UART, 2, CLK_ID_UART_2,
116 PHY_BASEADDR_CLKGEN23, (I_PLL_0_2)),
117 CLK_PERI_1S(DEV_NAME_UART, 3, CLK_ID_UART_3,
118 PHY_BASEADDR_CLKGEN25, (I_PLL_0_2)),
119 CLK_PERI_1S(DEV_NAME_UART, 4, CLK_ID_UART_4,
120 PHY_BASEADDR_CLKGEN26, (I_PLL_0_2)),
121 CLK_PERI_1S(DEV_NAME_UART, 5, CLK_ID_UART_5,
122 PHY_BASEADDR_CLKGEN27, (I_PLL_0_2)),
123 CLK_PERI_1S(DEV_NAME_PWM, 0, CLK_ID_PWM_0,
124 PHY_BASEADDR_CLKGEN13, (I_PLL_0_2)),
125 CLK_PERI_1S(DEV_NAME_PWM, 1, CLK_ID_PWM_1,
126 PHY_BASEADDR_CLKGEN3, (I_PLL_0_2)),
127 CLK_PERI_1S(DEV_NAME_PWM, 2, CLK_ID_PWM_2,
128 PHY_BASEADDR_CLKGEN4, (I_PLL_0_2)),
129 CLK_PERI_1S(DEV_NAME_PWM, 3, CLK_ID_PWM_3,
130 PHY_BASEADDR_CLKGEN5, (I_PLL_0_2)),
131 CLK_PERI_1S(DEV_NAME_I2C, 0, CLK_ID_I2C_0,
132 PHY_BASEADDR_CLKGEN6, (I_GATE_PCLK)),
133 CLK_PERI_1S(DEV_NAME_I2C, 1, CLK_ID_I2C_1,
134 PHY_BASEADDR_CLKGEN7, (I_GATE_PCLK)),
135 CLK_PERI_1S(DEV_NAME_I2C, 2, CLK_ID_I2C_2,
136 PHY_BASEADDR_CLKGEN8, (I_GATE_PCLK)),
137 CLK_PERI_2S(DEV_NAME_GMAC, 0, CLK_ID_GMAC,
138 PHY_BASEADDR_CLKGEN10,
139 (I_PLL_0_3 | I_EXTCLK1 | I_EXTCLK1_FORCE),
140 (I_CLKnOUT)),
141 CLK_PERI_2S(DEV_NAME_I2S, 0, CLK_ID_I2S_0,
142 PHY_BASEADDR_CLKGEN15, (I_PLL_0_3 | I_EXTCLK1),
143 (I_CLKnOUT)),
144 CLK_PERI_2S(DEV_NAME_I2S, 1, CLK_ID_I2S_1,
145 PHY_BASEADDR_CLKGEN16, (I_PLL_0_3 | I_EXTCLK1),
146 (I_CLKnOUT)),
147 CLK_PERI_2S(DEV_NAME_I2S, 2, CLK_ID_I2S_2,
148 PHY_BASEADDR_CLKGEN17, (I_PLL_0_3 | I_EXTCLK1),
149 (I_CLKnOUT)),
150 CLK_PERI_1S(DEV_NAME_SDHC, 0, CLK_ID_SDHC_0,
151 PHY_BASEADDR_CLKGEN18, (I_PLL_0_2 | I_GATE_PCLK)),
152 CLK_PERI_1S(DEV_NAME_SDHC, 1, CLK_ID_SDHC_1,
153 PHY_BASEADDR_CLKGEN19, (I_PLL_0_2 | I_GATE_PCLK)),
154 CLK_PERI_1S(DEV_NAME_SDHC, 2, CLK_ID_SDHC_2,
155 PHY_BASEADDR_CLKGEN20, (I_PLL_0_2 | I_GATE_PCLK)),
156 CLK_PERI_1S(DEV_NAME_SPI, 0, CLK_ID_SPI_0,
157 PHY_BASEADDR_CLKGEN37, (I_PLL_0_2)),
158 CLK_PERI_1S(DEV_NAME_SPI, 1, CLK_ID_SPI_1,
159 PHY_BASEADDR_CLKGEN38, (I_PLL_0_2)),
160 CLK_PERI_1S(DEV_NAME_SPI, 2, CLK_ID_SPI_2,
161 PHY_BASEADDR_CLKGEN39, (I_PLL_0_2)),
162};
163
164#define CLK_PERI_NUM ((int)ARRAY_SIZE(clk_periphs))
165#define CLK_CORE_NUM ((int)ARRAY_SIZE(clk_core))
166#define CLK_DEVS_NUM (CLK_CORE_NUM + CLK_PERI_NUM)
167#define MAX_DIVIDER ((1 << 8) - 1) /* 256, align 2 */
168
169static struct clk_dev st_clk_devs[CLK_DEVS_NUM]
Marek BehĂșn236f2ec2021-05-20 13:23:52 +0200170 __section(".data");
Stefan Bosch95e9a8e2020-07-10 19:07:26 +0200171#define clk_dev_get(n) ((struct clk_dev *)&st_clk_devs[n])
172#define clk_container(p) (container_of(p, struct clk_dev, clk))
173
174/*
175 * Core frequencys
176 */
177struct _core_hz_ {
178 unsigned long pll[4]; /* PLL */
179 unsigned long cpu_fclk, cpu_bclk; /* cpu */
180 unsigned long mem_fclk, mem_dclk, mem_bclk, mem_pclk; /* ddr */
181 unsigned long bus_bclk, bus_pclk; /* bus */
182#if defined(CONFIG_ARCH_S5P6818)
183 unsigned long cci4_bclk, cci4_pclk; /* cci */
184#endif
185 /* ip */
186 unsigned long g3d_bclk;
187 unsigned long coda_bclk, coda_pclk;
188#if defined(CONFIG_ARCH_S5P6818)
189 unsigned long disp_bclk, disp_pclk;
190 unsigned long hdmi_pclk;
191#endif
192};
193
194/*
195 * Section ".data" must be used because BSS is not available before relocation,
196 * in board_init_f(), respectively! I.e. global variables can not be used!
197 */
198/* core clock */
Marek BehĂșn236f2ec2021-05-20 13:23:52 +0200199static struct _core_hz_ core_hz __section(".data");
Stefan Bosch95e9a8e2020-07-10 19:07:26 +0200200
201#define CORE_HZ_SIZE (sizeof(core_hz) / 4)
202
203/*
204 * CLKGEN HW
205 */
206static inline void clk_dev_bclk(void *base, int on)
207{
208 struct clk_dev_map *reg = base;
209 unsigned int val = readl(&reg->con_enb) & ~(0x3);
210
211 val |= (on ? 3 : 0) & 0x3; /* always BCLK */
212 writel(val, &reg->con_enb);
213}
214
215static inline void clk_dev_pclk(void *base, int on)
216{
217 struct clk_dev_map *reg = base;
218 unsigned int val = 0;
219
220 if (!on)
221 return;
222
223 val = readl(&reg->con_enb) & ~(1 << 3);
224 val |= (1 << 3);
225 writel(val, &reg->con_enb);
226}
227
228static inline void clk_dev_rate(void *base, int step, int src, int div)
229{
230 struct clk_dev_map *reg = base;
231 unsigned int val = 0;
232
233 val = readl(&reg->con_gen[step << 1]);
234 val &= ~(0x07 << 2);
235 val |= (src << 2); /* source */
236 val &= ~(0xFF << 5);
237 val |= (div - 1) << 5; /* divider */
238 writel(val, &reg->con_gen[step << 1]);
239}
240
241static inline void clk_dev_inv(void *base, int step, int inv)
242{
243 struct clk_dev_map *reg = base;
244 unsigned int val = readl(&reg->con_gen[step << 1]) & ~(1 << 1);
245
246 val |= (inv << 1);
247 writel(val, &reg->con_gen[step << 1]);
248}
249
250static inline void clk_dev_enb(void *base, int on)
251{
252 struct clk_dev_map *reg = base;
253 unsigned int val = readl(&reg->con_enb) & ~(1 << 2);
254
255 val |= ((on ? 1 : 0) << 2);
256 writel(val, &reg->con_enb);
257}
258
259/*
260 * CORE FREQUENCY
261 *
262 * PLL0 [P,M,S] ------- | | ----- [DIV0] --- CPU-G0
263 * |M| ----- [DIV1] --- BCLK/PCLK
264 * PLL1 [P,M,S] ------- | | ----- [DIV2] --- DDR
265 * |U| ----- [DIV3] --- 3D
266 * PLL2 [P,M,S,K]-------| | ----- [DIV4] --- CODA
267 * |X| ----- [DIV5] --- DISPLAY
268 * PLL3 [P,M,S,K]-------| | ----- [DIV6] --- HDMI
269 * | | ----- [DIV7] --- CPU-G1
270 * | | ----- [DIV8] --- CCI-400(FASTBUS)
271 *
272 */
273
274struct nx_clkpwr_registerset {
275 u32 clkmodereg0; /* 0x000 : Clock Mode Register0 */
276 u32 __reserved0; /* 0x004 */
277 u32 pllsetreg[4]; /* 0x008 ~ 0x014 : PLL Setting Register */
278 u32 __reserved1[2]; /* 0x018 ~ 0x01C */
279 u32 dvoreg[9]; /* 0x020 ~ 0x040 : Divider Setting Register */
280 u32 __Reserved2; /* 0x044 */
281 u32 pllsetreg_sscg[6]; /* 0x048 ~ 0x05C */
282 u32 __reserved3[8]; /* 0x060 ~ 0x07C */
283 u8 __reserved4[0x200 - 0x80]; /* padding (0x80 ~ 0x1FF) */
284 u32 gpiowakeupriseenb; /* 0x200 : GPIO Rising Edge Detect En. Reg. */
285 u32 gpiowakeupfallenb; /* 0x204 : GPIO Falling Edge Detect En. Reg. */
286 u32 gpiorstenb; /* 0x208 : GPIO Reset Enable Register */
287 u32 gpiowakeupenb; /* 0x20C : GPIO Wakeup Source Enable */
288 u32 gpiointenb; /* 0x210 : Interrupt Enable Register */
289 u32 gpiointpend; /* 0x214 : Interrupt Pend Register */
290 u32 resetstatus; /* 0x218 : Reset Status Register */
291 u32 intenable; /* 0x21C : Interrupt Enable Register */
292 u32 intpend; /* 0x220 : Interrupt Pend Register */
293 u32 pwrcont; /* 0x224 : Power Control Register */
294 u32 pwrmode; /* 0x228 : Power Mode Register */
295 u32 __reserved5; /* 0x22C : Reserved Region */
296 u32 scratch[3]; /* 0x230 ~ 0x238 : Scratch Register */
297 u32 sysrstconfig; /* 0x23C : System Reset Configuration Reg. */
298 u8 __reserved6[0x2A0 - 0x240]; /* padding (0x240 ~ 0x29F) */
299 u32 cpupowerdownreq; /* 0x2A0 : CPU Power Down Request Register */
300 u32 cpupoweronreq; /* 0x2A4 : CPU Power On Request Register */
301 u32 cpuresetmode; /* 0x2A8 : CPU Reset Mode Register */
302 u32 cpuwarmresetreq; /* 0x2AC : CPU Warm Reset Request Register */
303 u32 __reserved7; /* 0x2B0 */
304 u32 cpustatus; /* 0x2B4 : CPU Status Register */
305 u8 __reserved8[0x400 - 0x2B8]; /* padding (0x2B8 ~ 0x33F) */
306};
307
308static struct nx_clkpwr_registerset * const clkpwr =
309 (struct nx_clkpwr_registerset *)PHY_BASEADDR_CLKPWR;
310
311#define getquotient(v, d) ((v) / (d))
312
313#define DIV_CPUG0 0
314#define DIV_BUS 1
315#define DIV_MEM 2
316#define DIV_G3D 3
317#define DIV_CODA 4
318#if defined(CONFIG_ARCH_S5P6818)
319#define DIV_DISP 5
320#define DIV_HDMI 6
321#define DIV_CPUG1 7
322#define DIV_CCI4 8
323#endif
324
325#define DVO0 3
326#define DVO1 9
327#define DVO2 15
328#define DVO3 21
329
330static unsigned int pll_rate(unsigned int plln, unsigned int xtal)
331{
332 unsigned int val, val1, nP, nM, nS, nK;
333 unsigned int temp = 0;
334
335 val = clkpwr->pllsetreg[plln];
336 val1 = clkpwr->pllsetreg_sscg[plln];
337 xtal /= 1000; /* Unit Khz */
338
339 nP = (val >> 18) & 0x03F;
340 nM = (val >> 8) & 0x3FF;
341 nS = (val >> 0) & 0x0FF;
342 nK = (val1 >> 16) & 0xFFFF;
343
344 if (plln > 1 && nK) {
345 temp = (unsigned int)(getquotient((getquotient((nK * 1000),
346 65536) * xtal), nP) >> nS);
347 }
348
349 temp = (unsigned int)((getquotient((nM * xtal), nP) >> nS) * 1000)
350 + temp;
351 return temp;
352}
353
354static unsigned int pll_dvo(int dvo)
355{
356 unsigned int val;
357
358 val = (clkpwr->dvoreg[dvo] & 0x7);
359 return val;
360}
361
362static unsigned int pll_div(int dvo)
363{
364 unsigned int val = clkpwr->dvoreg[dvo];
365
366 return ((((val >> DVO3) & 0x3F) + 1) << 24) |
367 ((((val >> DVO2) & 0x3F) + 1) << 16) |
368 ((((val >> DVO1) & 0x3F) + 1) << 8) |
369 ((((val >> DVO0) & 0x3F) + 1) << 0);
370}
371
372#define PLLN_RATE(n) (pll_rate(n, CONFIG_SYS_PLLFIN)) /* 0~ 3 */
373#define CPU_FCLK_RATE(n) (pll_rate(pll_dvo(n), CONFIG_SYS_PLLFIN) / \
374 ((pll_div(n) >> 0) & 0x3F))
375#define CPU_BCLK_RATE(n) (pll_rate(pll_dvo(n), CONFIG_SYS_PLLFIN) / \
376 ((pll_div(n) >> 0) & 0x3F) / \
377 ((pll_div(n) >> 8) & 0x3F))
378
379#define MEM_FCLK_RATE() (pll_rate(pll_dvo(DIV_MEM), CONFIG_SYS_PLLFIN) / \
380 ((pll_div(DIV_MEM) >> 0) & 0x3F) / \
381 ((pll_div(DIV_MEM) >> 8) & 0x3F))
382
383#define MEM_DCLK_RATE() (pll_rate(pll_dvo(DIV_MEM), CONFIG_SYS_PLLFIN) / \
384 ((pll_div(DIV_MEM) >> 0) & 0x3F))
385
386#define MEM_BCLK_RATE() (pll_rate(pll_dvo(DIV_MEM), CONFIG_SYS_PLLFIN) / \
387 ((pll_div(DIV_MEM) >> 0) & 0x3F) / \
388 ((pll_div(DIV_MEM) >> 8) & 0x3F) / \
389 ((pll_div(DIV_MEM) >> 16) & 0x3F))
390#define MEM_PCLK_RATE() (pll_rate(pll_dvo(DIV_MEM), CONFIG_SYS_PLLFIN) / \
391 ((pll_div(DIV_MEM) >> 0) & 0x3F) / \
392 ((pll_div(DIV_MEM) >> 8) & 0x3F) / \
393 ((pll_div(DIV_MEM) >> 16) & 0x3F) / \
394 ((pll_div(DIV_MEM) >> 24) & 0x3F))
395
396#define BUS_BCLK_RATE() (pll_rate(pll_dvo(DIV_BUS), CONFIG_SYS_PLLFIN) / \
397 ((pll_div(DIV_BUS) >> 0) & 0x3F))
398#define BUS_PCLK_RATE() (pll_rate(pll_dvo(DIV_BUS), CONFIG_SYS_PLLFIN) / \
399 ((pll_div(DIV_BUS) >> 0) & 0x3F) / \
400 ((pll_div(DIV_BUS) >> 8) & 0x3F))
401
402#define G3D_BCLK_RATE() (pll_rate(pll_dvo(DIV_G3D), CONFIG_SYS_PLLFIN) / \
403 ((pll_div(DIV_G3D) >> 0) & 0x3F))
404
405#define MPG_BCLK_RATE() (pll_rate(pll_dvo(DIV_CODA), CONFIG_SYS_PLLFIN) / \
406 ((pll_div(DIV_CODA) >> 0) & 0x3F))
407#define MPG_PCLK_RATE() (pll_rate(pll_dvo(DIV_CODA), CONFIG_SYS_PLLFIN) / \
408 ((pll_div(DIV_CODA) >> 0) & 0x3F) / \
409 ((pll_div(DIV_CODA) >> 8) & 0x3F))
410
411#if defined(CONFIG_ARCH_S5P6818)
412#define DISP_BCLK_RATE() (pll_rate(pll_dvo(DIV_DISP), CONFIG_SYS_PLLFIN) / \
413 ((pll_div(DIV_DISP) >> 0) & 0x3F))
414#define DISP_PCLK_RATE() (pll_rate(pll_dvo(DIV_DISP), CONFIG_SYS_PLLFIN) / \
415 ((pll_div(DIV_DISP) >> 0) & 0x3F) / \
416 ((pll_div(DIV_DISP) >> 8) & 0x3F))
417
418#define HDMI_PCLK_RATE() (pll_rate(pll_dvo(DIV_HDMI), CONFIG_SYS_PLLFIN) / \
419 ((pll_div(DIV_HDMI) >> 0) & 0x3F))
420
421#define CCI4_BCLK_RATE() (pll_rate(pll_dvo(DIV_CCI4), CONFIG_SYS_PLLFIN) / \
422 ((pll_div(DIV_CCI4) >> 0) & 0x3F))
423#define CCI4_PCLK_RATE() (pll_rate(pll_dvo(DIV_CCI4), CONFIG_SYS_PLLFIN) / \
424 ((pll_div(DIV_CCI4) >> 0) & 0x3F) / \
425 ((pll_div(DIV_CCI4) >> 8) & 0x3F))
426#endif
427
428static void core_update_rate(int type)
429{
430 switch (type) {
431 case 0:
432 core_hz.pll[0] = PLLN_RATE(0); break;
433 case 1:
434 core_hz.pll[1] = PLLN_RATE(1); break;
435 case 2:
436 core_hz.pll[2] = PLLN_RATE(2); break;
437 case 3:
438 core_hz.pll[3] = PLLN_RATE(3); break;
439 case 4:
440 core_hz.cpu_fclk = CPU_FCLK_RATE(DIV_CPUG0); break;
441 case 5:
442 core_hz.mem_fclk = MEM_FCLK_RATE(); break;
443 case 6:
444 core_hz.bus_bclk = BUS_BCLK_RATE(); break;
445 case 7:
446 core_hz.bus_pclk = BUS_PCLK_RATE(); break;
447 case 8:
448 core_hz.cpu_bclk = CPU_BCLK_RATE(DIV_CPUG0); break;
449 case 9:
450 core_hz.mem_dclk = MEM_DCLK_RATE(); break;
451 case 10:
452 core_hz.mem_bclk = MEM_BCLK_RATE(); break;
453 case 11:
454 core_hz.mem_pclk = MEM_PCLK_RATE(); break;
455 case 12:
456 core_hz.g3d_bclk = G3D_BCLK_RATE(); break;
457 case 13:
458 core_hz.coda_bclk = MPG_BCLK_RATE(); break;
459 case 14:
460 core_hz.coda_pclk = MPG_PCLK_RATE(); break;
461#if defined(CONFIG_ARCH_S5P6818)
462 case 15:
463 core_hz.disp_bclk = DISP_BCLK_RATE(); break;
464 case 16:
465 core_hz.disp_pclk = DISP_PCLK_RATE(); break;
466 case 17:
467 core_hz.hdmi_pclk = HDMI_PCLK_RATE(); break;
468 case 18:
469 core_hz.cci4_bclk = CCI4_BCLK_RATE(); break;
470 case 19:
471 core_hz.cci4_pclk = CCI4_PCLK_RATE(); break;
472#endif
473 };
474}
475
476static unsigned long core_get_rate(int type)
477{
478 unsigned long rate = 0;
479
480 switch (type) {
481 case 0:
482 rate = core_hz.pll[0]; break;
483 case 1:
484 rate = core_hz.pll[1]; break;
485 case 2:
486 rate = core_hz.pll[2]; break;
487 case 3:
488 rate = core_hz.pll[3]; break;
489 case 4:
490 rate = core_hz.cpu_fclk; break;
491 case 5:
492 rate = core_hz.mem_fclk; break;
493 case 6:
494 rate = core_hz.bus_bclk; break;
495 case 7:
496 rate = core_hz.bus_pclk; break;
497 case 8:
498 rate = core_hz.cpu_bclk; break;
499 case 9:
500 rate = core_hz.mem_dclk; break;
501 case 10:
502 rate = core_hz.mem_bclk; break;
503 case 11:
504 rate = core_hz.mem_pclk; break;
505 case 12:
506 rate = core_hz.g3d_bclk; break;
507 case 13:
508 rate = core_hz.coda_bclk; break;
509 case 14:
510 rate = core_hz.coda_pclk; break;
511#if defined(CONFIG_ARCH_S5P6818)
512 case 15:
513 rate = core_hz.disp_bclk; break;
514 case 16:
515 rate = core_hz.disp_pclk; break;
516 case 17:
517 rate = core_hz.hdmi_pclk; break;
518 case 18:
519 rate = core_hz.cci4_bclk; break;
520 case 19:
521 rate = core_hz.cci4_pclk; break;
522#endif
523 default:
524 printf("unknown core clock type %d ...\n", type);
525 break;
526 };
527 return rate;
528}
529
530static long core_set_rate(struct clk *clk, long rate)
531{
532 return clk->rate;
533}
534
535static void core_rate_init(void)
536{
537 int i;
538
539 for (i = 0; i < CORE_HZ_SIZE; i++)
540 core_update_rate(i);
541}
542
543/*
544 * Clock Interfaces
545 */
546static inline long clk_divide(long rate, long request,
547 int align, int *divide)
548{
549 int div = (rate / request);
550 int max = MAX_DIVIDER & ~(align - 1);
551 int adv = (div & ~(align - 1)) + align;
552 long ret;
553
554 if (!div) {
555 if (divide)
556 *divide = 1;
557 return rate;
558 }
559
560 if (div != 1)
561 div &= ~(align - 1);
562
563 if (div != adv && abs(request - rate / div) > abs(request - rate / adv))
564 div = adv;
565
566 div = (div > max ? max : div);
567 if (divide)
568 *divide = div;
569
570 ret = rate / div;
571 return ret;
572}
573
574void clk_put(struct clk *clk)
575{
576}
577
578struct clk *clk_get(const char *id)
579{
580 struct clk_dev *cdev = clk_dev_get(0);
581 struct clk *clk = NULL;
582 const char *str = NULL, *c = NULL;
583 int i, devid;
584
585 if (id)
586 str = id;
587
588 for (i = 0; i < CLK_DEVS_NUM; i++, cdev++) {
589 if (!cdev->name)
590 continue;
591 if (!strncmp(cdev->name, str, strlen(cdev->name))) {
592 c = strrchr((const char *)str, (int)'.');
593 if (!c || !cdev->peri)
594 break;
595 devid = simple_strtoul(++c, NULL, 10);
596 if (cdev->peri->dev_id == devid)
597 break;
598 }
599 }
600 if (i < CLK_DEVS_NUM)
601 clk = &cdev->clk;
602 else
603 clk = &(clk_dev_get(7))->clk; /* pclk */
604
605 return clk ? clk : ERR_PTR(-ENOENT);
606}
607
608long clk_round_rate(struct clk *clk, unsigned long rate)
609{
610 struct clk_dev *pll = NULL, *cdev = clk_container(clk);
611 struct clk_dev_peri *peri = cdev->peri;
612 unsigned long request = rate, rate_hz = 0;
613 unsigned int mask;
614 int step, div[2] = { 0, };
615 int i, n, clk2 = 0;
616 int start_src = 0, max_src = I_CLOCK_NUM;
617 short s1 = 0, s2 = 0, d1 = 0, d2 = 0;
618
619 if (!peri)
620 return core_set_rate(clk, rate);
621
622 step = peri->clk_step;
623 mask = peri->in_mask;
624 debug("clk: %s.%d request = %ld [input=0x%x]\n", peri->dev_name,
625 peri->dev_id, rate, mask);
626
627 if (!(I_CLOCK_MASK & mask)) {
628 if (I_PCLK_MASK & mask)
629 return core_get_rate(CORECLK_ID_PCLK);
630 else if (I_BCLK_MASK & mask)
631 return core_get_rate(CORECLK_ID_BCLK);
632 else
633 return clk->rate;
634 }
635
636next:
637 if (peri->in_mask & I_EXTCLK1_FORCE) {
638 start_src = 4; max_src = 5;
639 }
640 for (n = start_src ; max_src > n; n++) {
641 if (!(((mask & I_CLOCK_MASK) >> n) & 0x1))
642 continue;
643
644 if (n == I_EXT1_BIT) {
645 rate = peri->in_extclk_1;
646 } else if (n == I_EXT2_BIT) {
647 rate = peri->in_extclk_2;
648 } else {
649 pll = clk_dev_get(n);
650 rate = pll->clk.rate;
651 }
652
653 if (!rate)
654 continue;
655
656 for (i = 0; step > i ; i++)
657 rate = clk_divide(rate, request, 2, &div[i]);
658
659 if (rate_hz && (abs(rate - request) > abs(rate_hz - request)))
660 continue;
661
662 debug("clk: %s.%d, pll.%d[%lu] request[%ld] calc[%ld]\n",
663 peri->dev_name, peri->dev_id, n, pll->clk.rate,
664 request, rate);
665
666 if (clk2) {
667 s1 = -1, d1 = -1; /* not use */
668 s2 = n, d2 = div[0];
669 } else {
670 s1 = n, d1 = div[0];
671 s2 = I_CLKn_BIT, d2 = div[1];
672 }
673 rate_hz = rate;
674 }
675
676 /* search 2th clock from input */
677 if (!clk2 && abs(rate_hz - request) &&
678 peri->in_mask1 & ((1 << I_CLOCK_NUM) - 1)) {
679 clk2 = 1;
680 mask = peri->in_mask1;
681 step = 1;
682 goto next;
683 }
684 if (peri->in_mask & I_EXTCLK1_FORCE) {
685 if (s1 == 0) {
686 s1 = 4; s2 = 7;
687 d1 = 1; d2 = 1;
688 }
689 }
690
691 peri->div_src_0 = s1, peri->div_val_0 = d1;
692 peri->div_src_1 = s2, peri->div_val_1 = d2;
693 clk->rate = rate_hz;
694
695 debug("clk: %s.%d, step[%d] src[%d,%d] %ld", peri->dev_name,
696 peri->dev_id, peri->clk_step, peri->div_src_0, peri->div_src_1,
697 rate);
698 debug("/(div0: %d * div1: %d) = %ld, %ld diff (%ld)\n",
699 peri->div_val_0, peri->div_val_1, rate_hz, request,
700 abs(rate_hz - request));
701
702 return clk->rate;
703}
704
705unsigned long clk_get_rate(struct clk *clk)
706{
707 struct clk_dev *cdev = clk_container(clk);
708
709 if (cdev->link)
710 clk = cdev->link;
711 return clk->rate;
712}
713
714int clk_set_rate(struct clk *clk, unsigned long rate)
715{
716 struct clk_dev *cdev = clk_container(clk);
717 struct clk_dev_peri *peri = cdev->peri;
718 int i;
719
720 if (!peri)
721 return core_set_rate(clk, rate);
722
723 clk_round_rate(clk, rate);
724
725 for (i = 0; peri->clk_step > i ; i++) {
726 int s = (i == 0 ? peri->div_src_0 : peri->div_src_1);
727 int d = (i == 0 ? peri->div_val_0 : peri->div_val_1);
728
729 if (-1 == s)
730 continue;
731
732 clk_dev_rate(peri->base, i, s, d);
733
734 debug("clk: %s.%d (%p) set_rate [%d] src[%d] div[%d]\n",
735 peri->dev_name, peri->dev_id, peri->base, i, s, d);
736 }
737
738 return clk->rate;
739}
740
741int clk_enable(struct clk *clk)
742{
743 struct clk_dev *cdev = clk_container(clk);
744 struct clk_dev_peri *peri = cdev->peri;
745 int i = 0, inv = 0;
746
747 if (!peri)
748 return 0;
749
750 debug("clk: %s.%d enable (BCLK=%s, PCLK=%s)\n", peri->dev_name,
751 peri->dev_id, I_GATE_BCLK & peri->in_mask ? "ON" : "PASS",
752 I_GATE_PCLK & peri->in_mask ? "ON" : "PASS");
753
754 if (!(I_CLOCK_MASK & peri->in_mask)) {
755 /* Gated BCLK/PCLK enable */
756 if (I_GATE_BCLK & peri->in_mask)
757 clk_dev_bclk(peri->base, 1);
758
759 if (I_GATE_PCLK & peri->in_mask)
760 clk_dev_pclk(peri->base, 1);
761
762 return 0;
763 }
764
765 /* invert */
766 inv = peri->invert_0;
767 for (; peri->clk_step > i; i++, inv = peri->invert_1)
768 clk_dev_inv(peri->base, i, inv);
769
770 /* Gated BCLK/PCLK enable */
771 if (I_GATE_BCLK & peri->in_mask)
772 clk_dev_bclk(peri->base, 1);
773
774 if (I_GATE_PCLK & peri->in_mask)
775 clk_dev_pclk(peri->base, 1);
776
777 /* restore clock rate */
778 for (i = 0; peri->clk_step > i ; i++) {
779 int s = (i == 0 ? peri->div_src_0 : peri->div_src_1);
780 int d = (i == 0 ? peri->div_val_0 : peri->div_val_1);
781
782 if (s == -1)
783 continue;
784 clk_dev_rate(peri->base, i, s, d);
785 }
786
787 clk_dev_enb(peri->base, 1);
788
789 return 0;
790}
791
792void clk_disable(struct clk *clk)
793{
794 struct clk_dev *cdev = clk_container(clk);
795 struct clk_dev_peri *peri = cdev->peri;
796
797 if (!peri)
798 return;
799
800 debug("clk: %s.%d disable\n", peri->dev_name, peri->dev_id);
801
802 if (!(I_CLOCK_MASK & peri->in_mask)) {
803 /* Gated BCLK/PCLK disable */
804 if (I_GATE_BCLK & peri->in_mask)
805 clk_dev_bclk(peri->base, 0);
806
807 if (I_GATE_PCLK & peri->in_mask)
808 clk_dev_pclk(peri->base, 0);
809
810 return;
811 }
812
813 clk_dev_rate(peri->base, 0, 7, 256); /* for power save */
814 clk_dev_enb(peri->base, 0);
815
816 /* Gated BCLK/PCLK disable */
817 if (I_GATE_BCLK & peri->in_mask)
818 clk_dev_bclk(peri->base, 0);
819
820 if (I_GATE_PCLK & peri->in_mask)
821 clk_dev_pclk(peri->base, 0);
822}
823
824/*
825 * Core clocks APIs
826 */
827void __init clk_init(void)
828{
829 struct clk_dev *cdev = st_clk_devs;
830 struct clk_dev_peri *peri = clk_periphs;
831 struct clk *clk = NULL;
832 int i = 0;
833
834 memset(cdev, 0, sizeof(st_clk_devs));
835 core_rate_init();
836
837 for (i = 0; (CLK_CORE_NUM + CLK_PERI_NUM) > i; i++, cdev++) {
838 if (i < CLK_CORE_NUM) {
839 cdev->name = clk_core[i];
840 clk = &cdev->clk;
841 clk->rate = core_get_rate(i);
842 continue;
843 }
844
845 peri = &clk_periphs[i - CLK_CORE_NUM];
846 peri->base = (void *)peri->base;
847
848 cdev->peri = peri;
849 cdev->name = peri->dev_name;
850
851 if (!(I_CLOCK_MASK & peri->in_mask)) {
852 if (I_BCLK_MASK & peri->in_mask)
853 cdev->clk.rate = core_get_rate(CORECLK_ID_BCLK);
854 if (I_PCLK_MASK & peri->in_mask)
855 cdev->clk.rate = core_get_rate(CORECLK_ID_PCLK);
856 }
857
858 /* prevent uart clock disable for low step debug message */
859 #ifndef CONFIG_DEBUG_NX_UART
860 if (peri->dev_name) {
861 #ifdef CONFIG_BACKLIGHT_PWM
862 if (!strcmp(peri->dev_name, DEV_NAME_PWM))
863 continue;
864 #endif
865 }
866 #endif
867 }
868 debug("CPU : Clock Generator= %d EA, ", CLK_DEVS_NUM);
869}