CLK: ARC: HSDK: define clock map with DT binding constants
[oweals/u-boot.git] / drivers / clk / clk-hsdk-cgu.c
1 /*
2  * Synopsys HSDK SDP CGU clock driver
3  *
4  * Copyright (C) 2017 Synopsys
5  * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
6  *
7  * This file is licensed under the terms of the GNU General Public
8  * License version 2. This program is licensed "as is" without any
9  * warranty of any kind, whether express or implied.
10  */
11
12 #include <common.h>
13 #include <clk-uclass.h>
14 #include <div64.h>
15 #include <dm.h>
16 #include <linux/io.h>
17
18 #include <dt-bindings/clock/snps,hsdk-cgu.h>
19
20 /*
21  * Synopsys ARC HSDK clock tree.
22  *
23  *   ------------------
24  *   | 33.33 MHz xtal |
25  *   ------------------
26  *            |
27  *            |   -----------
28  *            |-->| ARC PLL |
29  *            |   -----------
30  *            |        |
31  *            |        |-->|CGU_ARC_IDIV|----------->
32  *            |        |-->|CREG_CORE_IF_DIV|------->
33  *            |
34  *            |   --------------
35  *            |-->| SYSTEM PLL |
36  *            |   --------------
37  *            |        |
38  *            |        |-->|CGU_SYS_IDIV_APB|------->
39  *            |        |-->|CGU_SYS_IDIV_AXI|------->
40  *            |        |-->|CGU_SYS_IDIV_*|--------->
41  *            |        |-->|CGU_SYS_IDIV_EBI_REF|--->
42  *            |
43  *            |   --------------
44  *            |-->| TUNNEL PLL |
45  *            |   --------------
46  *            |        |
47  *            |        |-->|CGU_TUN_IDIV_TUN|----------->
48  *            |        |-->|CGU_TUN_IDIV_ROM|----------->
49  *            |        |-->|CGU_TUN_IDIV_PWM|----------->
50  *            |
51  *            |   -----------
52  *            |-->| DDR PLL |
53  *                -----------
54  *                     |
55  *                     |---------------------------->
56  *
57  *   ------------------
58  *   | 27.00 MHz xtal |
59  *   ------------------
60  *            |
61  *            |   ------------
62  *            |-->| HDMI PLL |
63  *                ------------
64  *                     |
65  *                     |-->|CGU_HDMI_IDIV_APB|------>
66  */
67
68 #define CGU_ARC_IDIV            0x080
69 #define CGU_TUN_IDIV_TUN        0x380
70 #define CGU_TUN_IDIV_ROM        0x390
71 #define CGU_TUN_IDIV_PWM        0x3A0
72 #define CGU_TUN_IDIV_TIMER      0x3B0
73 #define CGU_HDMI_IDIV_APB       0x480
74 #define CGU_SYS_IDIV_APB        0x180
75 #define CGU_SYS_IDIV_AXI        0x190
76 #define CGU_SYS_IDIV_ETH        0x1A0
77 #define CGU_SYS_IDIV_USB        0x1B0
78 #define CGU_SYS_IDIV_SDIO       0x1C0
79 #define CGU_SYS_IDIV_HDMI       0x1D0
80 #define CGU_SYS_IDIV_GFX_CORE   0x1E0
81 #define CGU_SYS_IDIV_GFX_DMA    0x1F0
82 #define CGU_SYS_IDIV_GFX_CFG    0x200
83 #define CGU_SYS_IDIV_DMAC_CORE  0x210
84 #define CGU_SYS_IDIV_DMAC_CFG   0x220
85 #define CGU_SYS_IDIV_SDIO_REF   0x230
86 #define CGU_SYS_IDIV_SPI_REF    0x240
87 #define CGU_SYS_IDIV_I2C_REF    0x250
88 #define CGU_SYS_IDIV_UART_REF   0x260
89 #define CGU_SYS_IDIV_EBI_REF    0x270
90
91 #define CGU_IDIV_MASK           0xFF /* All idiv have 8 significant bits */
92
93 #define CGU_ARC_PLL             0x0
94 #define CGU_SYS_PLL             0x10
95 #define CGU_DDR_PLL             0x20
96 #define CGU_TUN_PLL             0x30
97 #define CGU_HDMI_PLL            0x40
98
99 #define CGU_PLL_CTRL            0x000 /* ARC PLL control register */
100 #define CGU_PLL_STATUS          0x004 /* ARC PLL status register */
101 #define CGU_PLL_FMEAS           0x008 /* ARC PLL frequency measurement register */
102 #define CGU_PLL_MON             0x00C /* ARC PLL monitor register */
103
104 #define CGU_PLL_CTRL_ODIV_SHIFT         2
105 #define CGU_PLL_CTRL_IDIV_SHIFT         4
106 #define CGU_PLL_CTRL_FBDIV_SHIFT        9
107 #define CGU_PLL_CTRL_BAND_SHIFT         20
108
109 #define CGU_PLL_CTRL_ODIV_MASK          GENMASK(3, CGU_PLL_CTRL_ODIV_SHIFT)
110 #define CGU_PLL_CTRL_IDIV_MASK          GENMASK(8, CGU_PLL_CTRL_IDIV_SHIFT)
111 #define CGU_PLL_CTRL_FBDIV_MASK         GENMASK(15, CGU_PLL_CTRL_FBDIV_SHIFT)
112
113 #define CGU_PLL_CTRL_PD                 BIT(0)
114 #define CGU_PLL_CTRL_BYPASS             BIT(1)
115
116 #define CGU_PLL_STATUS_LOCK             BIT(0)
117 #define CGU_PLL_STATUS_ERR              BIT(1)
118
119 #define HSDK_PLL_MAX_LOCK_TIME          100 /* 100 us */
120
121 #define CREG_CORE_IF_DIV                0x000 /* ARC CORE interface divider */
122 #define CORE_IF_CLK_THRESHOLD_HZ        500000000
123 #define CREG_CORE_IF_CLK_DIV_1          0x0
124 #define CREG_CORE_IF_CLK_DIV_2          0x1
125
126 #define MIN_PLL_RATE                    100000000 /* 100 MHz */
127 #define PARENT_RATE_33                  33333333 /* fixed clock - xtal */
128 #define PARENT_RATE_27                  27000000 /* fixed clock - xtal */
129 #define CGU_MAX_CLOCKS                  27
130
131 #define MAX_FREQ_VARIATIONS             6
132
133 struct hsdk_idiv_cfg {
134         const u32 oft;
135         const u8  val[MAX_FREQ_VARIATIONS];
136 };
137
138 struct hsdk_div_full_cfg {
139         const u32 clk_rate[MAX_FREQ_VARIATIONS];
140         const u32 pll_rate[MAX_FREQ_VARIATIONS];
141         const struct hsdk_idiv_cfg idiv[];
142 };
143
144 static const struct hsdk_div_full_cfg tun_clk_cfg = {
145         { 25000000,  50000000,  75000000,  100000000, 125000000, 150000000 },
146         { 600000000, 600000000, 600000000, 600000000, 750000000, 600000000 }, {
147         { CGU_TUN_IDIV_TUN,     { 24,   12,     8,      6,      6,      4 } },
148         { CGU_TUN_IDIV_ROM,     { 4,    4,      4,      4,      5,      4 } },
149         { CGU_TUN_IDIV_PWM,     { 8,    8,      8,      8,      10,     8 } },
150         { CGU_TUN_IDIV_TIMER,   { 12,   12,     12,     12,     15,     12 } },
151         { /* last one */ }
152         }
153 };
154
155 static const struct hsdk_div_full_cfg axi_clk_cfg = {
156         { 200000000,    400000000,      600000000,      800000000 },
157         { 800000000,    800000000,      600000000,      800000000 }, {
158         { CGU_SYS_IDIV_APB,      { 4,   4,      3,      4 } },  /* APB */
159         { CGU_SYS_IDIV_AXI,      { 4,   2,      1,      1 } },  /* AXI */
160         { CGU_SYS_IDIV_ETH,      { 2,   2,      2,      2 } },  /* ETH */
161         { CGU_SYS_IDIV_USB,      { 2,   2,      2,      2 } },  /* USB */
162         { CGU_SYS_IDIV_SDIO,     { 2,   2,      2,      2 } },  /* SDIO */
163         { CGU_SYS_IDIV_HDMI,     { 2,   2,      2,      2 } },  /* HDMI */
164         { CGU_SYS_IDIV_GFX_CORE, { 1,   1,      1,      1 } },  /* GPU-CORE */
165         { CGU_SYS_IDIV_GFX_DMA,  { 2,   2,      2,      2 } },  /* GPU-DMA */
166         { CGU_SYS_IDIV_GFX_CFG,  { 4,   4,      3,      4 } },  /* GPU-CFG */
167         { CGU_SYS_IDIV_DMAC_CORE,{ 2,   2,      2,      2 } },  /* DMAC-CORE */
168         { CGU_SYS_IDIV_DMAC_CFG, { 4,   4,      3,      4 } },  /* DMAC-CFG */
169         { CGU_SYS_IDIV_SDIO_REF, { 8,   8,      6,      8 } },  /* SDIO-REF */
170         { CGU_SYS_IDIV_SPI_REF,  { 24,  24,     18,     24 } }, /* SPI-REF */
171         { CGU_SYS_IDIV_I2C_REF,  { 4,   4,      3,      4 } },  /* I2C-REF */
172         { CGU_SYS_IDIV_UART_REF, { 24,  24,     18,     24 } }, /* UART-REF */
173         { CGU_SYS_IDIV_EBI_REF,  { 16,  16,     12,     16 } }, /* EBI-REF */
174         { /* last one */ }
175         }
176 };
177
178 struct hsdk_pll_cfg {
179         const u32 rate;
180         const u8  idiv;
181         const u8  fbdiv;
182         const u8  odiv;
183         const u8  band;
184 };
185
186 static const struct hsdk_pll_cfg asdt_pll_cfg[] = {
187         { 100000000,  0, 11, 3, 0 },
188         { 125000000,  0, 14, 3, 0 },
189         { 133000000,  0, 15, 3, 0 },
190         { 150000000,  0, 17, 3, 0 },
191         { 200000000,  1, 47, 3, 0 },
192         { 233000000,  1, 27, 2, 0 },
193         { 300000000,  1, 35, 2, 0 },
194         { 333000000,  1, 39, 2, 0 },
195         { 400000000,  1, 47, 2, 0 },
196         { 500000000,  0, 14, 1, 0 },
197         { 600000000,  0, 17, 1, 0 },
198         { 700000000,  0, 20, 1, 0 },
199         { 750000000,  1, 44, 1, 0 },
200         { 800000000,  0, 23, 1, 0 },
201         { 900000000,  1, 26, 0, 0 },
202         { 1000000000, 1, 29, 0, 0 },
203         { 1100000000, 1, 32, 0, 0 },
204         { 1200000000, 1, 35, 0, 0 },
205         { 1300000000, 1, 38, 0, 0 },
206         { 1400000000, 1, 41, 0, 0 },
207         { 1500000000, 1, 44, 0, 0 },
208         { 1600000000, 1, 47, 0, 0 },
209         {}
210 };
211
212 static const struct hsdk_pll_cfg hdmi_pll_cfg[] = {
213         { 297000000,  0, 21, 2, 0 },
214         { 540000000,  0, 19, 1, 0 },
215         { 594000000,  0, 21, 1, 0 },
216         {}
217 };
218
219 struct hsdk_cgu_domain {
220         /* PLLs registers */
221         void __iomem *pll_regs;
222         /* PLLs special registers */
223         void __iomem *spec_regs;
224         /* PLLs devdata */
225         const struct hsdk_pll_devdata *pll;
226
227         /* Dividers registers */
228         void __iomem *idiv_regs;
229 };
230
231 struct hsdk_cgu_clk {
232         const struct cgu_clk_map *map;
233         /* CGU block register */
234         void __iomem *cgu_regs;
235         /* CREG block register */
236         void __iomem *creg_regs;
237
238         /* The domain we are working with */
239         struct hsdk_cgu_domain curr_domain;
240 };
241
242 struct hsdk_pll_devdata {
243         const u32 parent_rate;
244         const struct hsdk_pll_cfg *const pll_cfg;
245         const int (*const update_rate)(struct hsdk_cgu_clk *clk,
246                                        unsigned long rate,
247                                        const struct hsdk_pll_cfg *cfg);
248 };
249
250 static int hsdk_pll_core_update_rate(struct hsdk_cgu_clk *, unsigned long,
251                                      const struct hsdk_pll_cfg *);
252 static int hsdk_pll_comm_update_rate(struct hsdk_cgu_clk *, unsigned long,
253                                      const struct hsdk_pll_cfg *);
254
255 static const struct hsdk_pll_devdata core_pll_dat = {
256         .parent_rate = PARENT_RATE_33,
257         .pll_cfg = asdt_pll_cfg,
258         .update_rate = hsdk_pll_core_update_rate,
259 };
260
261 static const struct hsdk_pll_devdata sdt_pll_dat = {
262         .parent_rate = PARENT_RATE_33,
263         .pll_cfg = asdt_pll_cfg,
264         .update_rate = hsdk_pll_comm_update_rate,
265 };
266
267 static const struct hsdk_pll_devdata hdmi_pll_dat = {
268         .parent_rate = PARENT_RATE_27,
269         .pll_cfg = hdmi_pll_cfg,
270         .update_rate = hsdk_pll_comm_update_rate,
271 };
272
273 static ulong idiv_set(struct clk *, ulong);
274 static ulong cpu_clk_set(struct clk *, ulong);
275 static ulong axi_clk_set(struct clk *, ulong);
276 static ulong tun_clk_set(struct clk *, ulong);
277 static ulong idiv_get(struct clk *);
278 static int idiv_off(struct clk *);
279 static ulong pll_set(struct clk *, ulong);
280 static ulong pll_get(struct clk *);
281
282 struct cgu_clk_map {
283         const u32 cgu_pll_oft;
284         const u32 cgu_div_oft;
285         const struct hsdk_pll_devdata *const pll_devdata;
286         const ulong (*const get_rate)(struct clk *clk);
287         const ulong (*const set_rate)(struct clk *clk, ulong rate);
288         const int (*const disable)(struct clk *clk);
289 };
290
291 static const struct cgu_clk_map clock_map[] = {
292         [CLK_ARC_PLL]        = { CGU_ARC_PLL,  0,                      &core_pll_dat, pll_get,  pll_set,      NULL     },
293         [CLK_ARC]            = { CGU_ARC_PLL,  CGU_ARC_IDIV,           &core_pll_dat, idiv_get, cpu_clk_set,  idiv_off },
294         [CLK_DDR_PLL]        = { CGU_DDR_PLL,  0,                      &sdt_pll_dat,  pll_get,  pll_set,      NULL     },
295         [CLK_SYS_PLL]        = { CGU_SYS_PLL,  0,                      &sdt_pll_dat,  pll_get,  pll_set,      NULL     },
296         [CLK_SYS_APB]        = { CGU_SYS_PLL,  CGU_SYS_IDIV_APB,       &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
297         [CLK_SYS_AXI]        = { CGU_SYS_PLL,  CGU_SYS_IDIV_AXI,       &sdt_pll_dat,  idiv_get, axi_clk_set,  idiv_off },
298         [CLK_SYS_ETH]        = { CGU_SYS_PLL,  CGU_SYS_IDIV_ETH,       &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
299         [CLK_SYS_USB]        = { CGU_SYS_PLL,  CGU_SYS_IDIV_USB,       &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
300         [CLK_SYS_SDIO]       = { CGU_SYS_PLL,  CGU_SYS_IDIV_SDIO,      &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
301         [CLK_SYS_HDMI]       = { CGU_SYS_PLL,  CGU_SYS_IDIV_HDMI,      &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
302         [CLK_SYS_GFX_CORE]   = { CGU_SYS_PLL,  CGU_SYS_IDIV_GFX_CORE,  &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
303         [CLK_SYS_GFX_DMA]    = { CGU_SYS_PLL,  CGU_SYS_IDIV_GFX_DMA,   &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
304         [CLK_SYS_GFX_CFG]    = { CGU_SYS_PLL,  CGU_SYS_IDIV_GFX_CFG,   &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
305         [CLK_SYS_DMAC_CORE]  = { CGU_SYS_PLL,  CGU_SYS_IDIV_DMAC_CORE, &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
306         [CLK_SYS_DMAC_CFG]   = { CGU_SYS_PLL,  CGU_SYS_IDIV_DMAC_CFG,  &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
307         [CLK_SYS_SDIO_REF]   = { CGU_SYS_PLL,  CGU_SYS_IDIV_SDIO_REF,  &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
308         [CLK_SYS_SPI_REF]    = { CGU_SYS_PLL,  CGU_SYS_IDIV_SPI_REF,   &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
309         [CLK_SYS_I2C_REF]    = { CGU_SYS_PLL,  CGU_SYS_IDIV_I2C_REF,   &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
310         [CLK_SYS_UART_REF]   = { CGU_SYS_PLL,  CGU_SYS_IDIV_UART_REF,  &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
311         [CLK_SYS_EBI_REF]    = { CGU_SYS_PLL,  CGU_SYS_IDIV_EBI_REF,   &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
312         [CLK_TUN_PLL]        = { CGU_TUN_PLL,  0,                      &sdt_pll_dat,  pll_get,  pll_set,      NULL     },
313         [CLK_TUN_TUN]        = { CGU_TUN_PLL,  CGU_TUN_IDIV_TUN,       &sdt_pll_dat,  idiv_get, tun_clk_set,  idiv_off },
314         [CLK_TUN_ROM]        = { CGU_TUN_PLL,  CGU_TUN_IDIV_ROM,       &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
315         [CLK_TUN_PWM]        = { CGU_TUN_PLL,  CGU_TUN_IDIV_PWM,       &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
316         [CLK_TUN_TIMER]      = { CGU_TUN_PLL,  CGU_TUN_IDIV_TIMER,     &sdt_pll_dat,  idiv_get, idiv_set,     idiv_off },
317         [CLK_HDMI_PLL]       = { CGU_HDMI_PLL, 0,                      &hdmi_pll_dat, pll_get,  pll_set,      NULL     },
318         [CLK_HDMI]           = { CGU_HDMI_PLL, CGU_HDMI_IDIV_APB,      &hdmi_pll_dat, idiv_get, idiv_set,     idiv_off }
319 };
320
321 static inline void hsdk_idiv_write(struct hsdk_cgu_clk *clk, u32 val)
322 {
323         iowrite32(val, clk->curr_domain.idiv_regs);
324 }
325
326 static inline u32 hsdk_idiv_read(struct hsdk_cgu_clk *clk)
327 {
328         return ioread32(clk->curr_domain.idiv_regs);
329 }
330
331 static inline void hsdk_pll_write(struct hsdk_cgu_clk *clk, u32 reg, u32 val)
332 {
333         iowrite32(val, clk->curr_domain.pll_regs + reg);
334 }
335
336 static inline u32 hsdk_pll_read(struct hsdk_cgu_clk *clk, u32 reg)
337 {
338         return ioread32(clk->curr_domain.pll_regs + reg);
339 }
340
341 static inline void hsdk_pll_spcwrite(struct hsdk_cgu_clk *clk, u32 reg, u32 val)
342 {
343         iowrite32(val, clk->curr_domain.spec_regs + reg);
344 }
345
346 static inline u32 hsdk_pll_spcread(struct hsdk_cgu_clk *clk, u32 reg)
347 {
348         return ioread32(clk->curr_domain.spec_regs + reg);
349 }
350
351 static inline void hsdk_pll_set_cfg(struct hsdk_cgu_clk *clk,
352                                     const struct hsdk_pll_cfg *cfg)
353 {
354         u32 val = 0;
355
356         /* Powerdown and Bypass bits should be cleared */
357         val |= (u32)cfg->idiv << CGU_PLL_CTRL_IDIV_SHIFT;
358         val |= (u32)cfg->fbdiv << CGU_PLL_CTRL_FBDIV_SHIFT;
359         val |= (u32)cfg->odiv << CGU_PLL_CTRL_ODIV_SHIFT;
360         val |= (u32)cfg->band << CGU_PLL_CTRL_BAND_SHIFT;
361
362         pr_debug("write configurarion: %#x\n", val);
363
364         hsdk_pll_write(clk, CGU_PLL_CTRL, val);
365 }
366
367 static inline bool hsdk_pll_is_locked(struct hsdk_cgu_clk *clk)
368 {
369         return !!(hsdk_pll_read(clk, CGU_PLL_STATUS) & CGU_PLL_STATUS_LOCK);
370 }
371
372 static inline bool hsdk_pll_is_err(struct hsdk_cgu_clk *clk)
373 {
374         return !!(hsdk_pll_read(clk, CGU_PLL_STATUS) & CGU_PLL_STATUS_ERR);
375 }
376
377 static ulong pll_get(struct clk *sclk)
378 {
379         u32 val;
380         u64 rate;
381         u32 idiv, fbdiv, odiv;
382         struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
383         u32 parent_rate = clk->curr_domain.pll->parent_rate;
384
385         val = hsdk_pll_read(clk, CGU_PLL_CTRL);
386
387         pr_debug("current configurarion: %#x\n", val);
388
389         /* Check if PLL is bypassed */
390         if (val & CGU_PLL_CTRL_BYPASS)
391                 return parent_rate;
392
393         /* Check if PLL is disabled */
394         if (val & CGU_PLL_CTRL_PD)
395                 return 0;
396
397         /* input divider = reg.idiv + 1 */
398         idiv = 1 + ((val & CGU_PLL_CTRL_IDIV_MASK) >> CGU_PLL_CTRL_IDIV_SHIFT);
399         /* fb divider = 2*(reg.fbdiv + 1) */
400         fbdiv = 2 * (1 + ((val & CGU_PLL_CTRL_FBDIV_MASK) >> CGU_PLL_CTRL_FBDIV_SHIFT));
401         /* output divider = 2^(reg.odiv) */
402         odiv = 1 << ((val & CGU_PLL_CTRL_ODIV_MASK) >> CGU_PLL_CTRL_ODIV_SHIFT);
403
404         rate = (u64)parent_rate * fbdiv;
405         do_div(rate, idiv * odiv);
406
407         return rate;
408 }
409
410 static unsigned long hsdk_pll_round_rate(struct clk *sclk, unsigned long rate)
411 {
412         int i;
413         unsigned long best_rate;
414         struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
415         const struct hsdk_pll_cfg *pll_cfg = clk->curr_domain.pll->pll_cfg;
416
417         if (pll_cfg[0].rate == 0)
418                 return -EINVAL;
419
420         best_rate = pll_cfg[0].rate;
421
422         for (i = 1; pll_cfg[i].rate != 0; i++) {
423                 if (abs(rate - pll_cfg[i].rate) < abs(rate - best_rate))
424                         best_rate = pll_cfg[i].rate;
425         }
426
427         pr_debug("chosen best rate: %lu\n", best_rate);
428
429         return best_rate;
430 }
431
432 static int hsdk_pll_comm_update_rate(struct hsdk_cgu_clk *clk,
433                                      unsigned long rate,
434                                      const struct hsdk_pll_cfg *cfg)
435 {
436         hsdk_pll_set_cfg(clk, cfg);
437
438         /*
439          * Wait until CGU relocks and check error status.
440          * If after timeout CGU is unlocked yet return error.
441          */
442         udelay(HSDK_PLL_MAX_LOCK_TIME);
443         if (!hsdk_pll_is_locked(clk))
444                 return -ETIMEDOUT;
445
446         if (hsdk_pll_is_err(clk))
447                 return -EINVAL;
448
449         return 0;
450 }
451
452 static int hsdk_pll_core_update_rate(struct hsdk_cgu_clk *clk,
453                                      unsigned long rate,
454                                      const struct hsdk_pll_cfg *cfg)
455 {
456         /*
457          * When core clock exceeds 500MHz, the divider for the interface
458          * clock must be programmed to div-by-2.
459          */
460         if (rate > CORE_IF_CLK_THRESHOLD_HZ)
461                 hsdk_pll_spcwrite(clk, CREG_CORE_IF_DIV, CREG_CORE_IF_CLK_DIV_2);
462
463         hsdk_pll_set_cfg(clk, cfg);
464
465         /*
466          * Wait until CGU relocks and check error status.
467          * If after timeout CGU is unlocked yet return error.
468          */
469         udelay(HSDK_PLL_MAX_LOCK_TIME);
470         if (!hsdk_pll_is_locked(clk))
471                 return -ETIMEDOUT;
472
473         if (hsdk_pll_is_err(clk))
474                 return -EINVAL;
475
476         /*
477          * Program divider to div-by-1 if we succesfuly set core clock below
478          * 500MHz threshold.
479          */
480         if (rate <= CORE_IF_CLK_THRESHOLD_HZ)
481                 hsdk_pll_spcwrite(clk, CREG_CORE_IF_DIV, CREG_CORE_IF_CLK_DIV_1);
482
483         return 0;
484 }
485
486 static ulong pll_set(struct clk *sclk, ulong rate)
487 {
488         int i;
489         unsigned long best_rate;
490         struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
491         const struct hsdk_pll_devdata *pll = clk->curr_domain.pll;
492         const struct hsdk_pll_cfg *pll_cfg = pll->pll_cfg;
493
494         best_rate = hsdk_pll_round_rate(sclk, rate);
495
496         for (i = 0; pll_cfg[i].rate != 0; i++)
497                 if (pll_cfg[i].rate == best_rate)
498                         return pll->update_rate(clk, best_rate, &pll_cfg[i]);
499
500         pr_err("invalid rate=%ld Hz, parent_rate=%d Hz\n", best_rate,
501                pll->parent_rate);
502
503         return -EINVAL;
504 }
505
506 static int idiv_off(struct clk *sclk)
507 {
508         struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
509
510         hsdk_idiv_write(clk, 0);
511
512         return 0;
513 }
514
515 static ulong idiv_get(struct clk *sclk)
516 {
517         struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
518         ulong parent_rate = pll_get(sclk);
519         u32 div_factor = hsdk_idiv_read(clk);
520
521         div_factor &= CGU_IDIV_MASK;
522
523         pr_debug("current configurarion: %#x (%d)\n", div_factor, div_factor);
524
525         if (div_factor == 0)
526                 return 0;
527
528         return parent_rate / div_factor;
529 }
530
531 /* Special behavior: wen we set this clock we set both idiv and pll */
532 static ulong cpu_clk_set(struct clk *sclk, ulong rate)
533 {
534         ulong ret;
535
536         ret = pll_set(sclk, rate);
537         idiv_set(sclk, rate);
538
539         return ret;
540 }
541
542 /*
543  * Special behavior:
544  * when we set these clocks we set both PLL and all idiv dividers related to
545  * this PLL domain.
546  */
547 static ulong common_div_clk_set(struct clk *sclk, ulong rate,
548                                 const struct hsdk_div_full_cfg *cfg)
549 {
550         struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
551         ulong pll_rate;
552         int i, freq_idx = -1;
553         ulong ret = 0;
554
555         pll_rate = pll_get(sclk);
556
557         for (i = 0; i < MAX_FREQ_VARIATIONS; i++) {
558                 /* unused freq variations are filled with 0 */
559                 if (!cfg->clk_rate[i])
560                         break;
561
562                 if (cfg->clk_rate[i] == rate) {
563                         freq_idx = i;
564                         break;
565                 }
566         }
567
568         if (freq_idx < 0) {
569                 pr_err("clk: invalid rate=%ld Hz\n", rate);
570                 return -EINVAL;
571         }
572
573         /* configure PLL before dividers */
574         if (cfg->pll_rate[freq_idx] < pll_rate)
575                 ret = pll_set(sclk, cfg->pll_rate[freq_idx]);
576
577         /* configure SYS dividers */
578         for (i = 0; cfg->idiv[i].oft != 0; i++) {
579                 clk->curr_domain.idiv_regs = clk->cgu_regs + cfg->idiv[i].oft;
580                 hsdk_idiv_write(clk, cfg->idiv[i].val[freq_idx]);
581         }
582
583         /* configure PLL after dividers */
584         if (cfg->pll_rate[freq_idx] >= pll_rate)
585                 ret = pll_set(sclk, cfg->pll_rate[freq_idx]);
586
587         return ret;
588 }
589
590 static ulong axi_clk_set(struct clk *sclk, ulong rate)
591 {
592         return common_div_clk_set(sclk, rate, &axi_clk_cfg);
593 }
594
595 static ulong tun_clk_set(struct clk *sclk, ulong rate)
596 {
597         return common_div_clk_set(sclk, rate, &tun_clk_cfg);
598 }
599
600 static ulong idiv_set(struct clk *sclk, ulong rate)
601 {
602         struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
603         ulong parent_rate = pll_get(sclk);
604         u32 div_factor;
605
606         div_factor = parent_rate / rate;
607         if (abs(rate - parent_rate / (div_factor + 1)) <=
608             abs(rate - parent_rate / div_factor)) {
609                 div_factor += 1;
610         }
611
612         if (div_factor & ~CGU_IDIV_MASK) {
613                 pr_err("invalid rate=%ld Hz, parent_rate=%ld Hz, div=%d: max divider valie is%d\n",
614                        rate, parent_rate, div_factor, CGU_IDIV_MASK);
615
616                 div_factor = CGU_IDIV_MASK;
617         }
618
619         if (div_factor == 0) {
620                 pr_err("invalid rate=%ld Hz, parent_rate=%ld Hz, div=%d: min divider valie is 1\n",
621                        rate, parent_rate, div_factor);
622
623                 div_factor = 1;
624         }
625
626         hsdk_idiv_write(clk, div_factor);
627
628         return 0;
629 }
630
631 static int hsdk_prepare_clock_tree_branch(struct clk *sclk)
632 {
633         struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
634
635         if (sclk->id >= CGU_MAX_CLOCKS)
636                 return -EINVAL;
637
638         /* clocks missing in current map have their entry zeroed */
639         if (!clk->map[sclk->id].pll_devdata)
640                 return -EINVAL;
641
642         clk->curr_domain.pll = clk->map[sclk->id].pll_devdata;
643         clk->curr_domain.pll_regs = clk->cgu_regs + clk->map[sclk->id].cgu_pll_oft;
644         clk->curr_domain.spec_regs = clk->creg_regs;
645         clk->curr_domain.idiv_regs = clk->cgu_regs + clk->map[sclk->id].cgu_div_oft;
646
647         return 0;
648 }
649
650 static ulong hsdk_cgu_get_rate(struct clk *sclk)
651 {
652         struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
653
654         if (hsdk_prepare_clock_tree_branch(sclk))
655                 return -EINVAL;
656
657         return clk->map[sclk->id].get_rate(sclk);
658 }
659
660 static ulong hsdk_cgu_set_rate(struct clk *sclk, ulong rate)
661 {
662         struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
663
664         if (hsdk_prepare_clock_tree_branch(sclk))
665                 return -EINVAL;
666
667         if (clk->map[sclk->id].set_rate)
668                 return clk->map[sclk->id].set_rate(sclk, rate);
669
670         return -ENOTSUPP;
671 }
672
673 static int hsdk_cgu_disable(struct clk *sclk)
674 {
675         struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
676
677         if (hsdk_prepare_clock_tree_branch(sclk))
678                 return -EINVAL;
679
680         if (clk->map[sclk->id].disable)
681                 return clk->map[sclk->id].disable(sclk);
682
683         return -ENOTSUPP;
684 }
685
686 static const struct clk_ops hsdk_cgu_ops = {
687         .set_rate = hsdk_cgu_set_rate,
688         .get_rate = hsdk_cgu_get_rate,
689         .disable = hsdk_cgu_disable,
690 };
691
692 static int hsdk_cgu_clk_probe(struct udevice *dev)
693 {
694         struct hsdk_cgu_clk *hsdk_clk = dev_get_priv(dev);
695
696         BUILD_BUG_ON(ARRAY_SIZE(clock_map) != CGU_MAX_CLOCKS);
697
698         hsdk_clk->map = clock_map;
699
700         hsdk_clk->cgu_regs = (void __iomem *)devfdt_get_addr_index(dev, 0);
701         if (!hsdk_clk->cgu_regs)
702                 return -EINVAL;
703
704         hsdk_clk->creg_regs = (void __iomem *)devfdt_get_addr_index(dev, 1);
705         if (!hsdk_clk->creg_regs)
706                 return -EINVAL;
707
708         return 0;
709 }
710
711 static const struct udevice_id hsdk_cgu_clk_id[] = {
712         { .compatible = "snps,hsdk-cgu-clock" },
713         { }
714 };
715
716 U_BOOT_DRIVER(hsdk_cgu_clk) = {
717         .name = "hsdk-cgu-clk",
718         .id = UCLASS_CLK,
719         .of_match = hsdk_cgu_clk_id,
720         .probe = hsdk_cgu_clk_probe,
721         .priv_auto_alloc_size = sizeof(struct hsdk_cgu_clk),
722         .ops = &hsdk_cgu_ops,
723 };