GNU Linux-libre 4.19.286-gnu1
[releases.git] / arch / mips / bcm63xx / clk.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
7  */
8
9 #include <linux/init.h>
10 #include <linux/export.h>
11 #include <linux/mutex.h>
12 #include <linux/err.h>
13 #include <linux/clk.h>
14 #include <linux/clkdev.h>
15 #include <linux/delay.h>
16 #include <bcm63xx_cpu.h>
17 #include <bcm63xx_io.h>
18 #include <bcm63xx_regs.h>
19 #include <bcm63xx_reset.h>
20
21 struct clk {
22         void            (*set)(struct clk *, int);
23         unsigned int    rate;
24         unsigned int    usage;
25         int             id;
26 };
27
28 static DEFINE_MUTEX(clocks_mutex);
29
30
31 static void clk_enable_unlocked(struct clk *clk)
32 {
33         if (clk->set && (clk->usage++) == 0)
34                 clk->set(clk, 1);
35 }
36
37 static void clk_disable_unlocked(struct clk *clk)
38 {
39         if (clk->set && (--clk->usage) == 0)
40                 clk->set(clk, 0);
41 }
42
43 static void bcm_hwclock_set(u32 mask, int enable)
44 {
45         u32 reg;
46
47         reg = bcm_perf_readl(PERF_CKCTL_REG);
48         if (enable)
49                 reg |= mask;
50         else
51                 reg &= ~mask;
52         bcm_perf_writel(reg, PERF_CKCTL_REG);
53 }
54
55 /*
56  * Ethernet MAC "misc" clock: dma clocks and main clock on 6348
57  */
58 static void enet_misc_set(struct clk *clk, int enable)
59 {
60         u32 mask;
61
62         if (BCMCPU_IS_6338())
63                 mask = CKCTL_6338_ENET_EN;
64         else if (BCMCPU_IS_6345())
65                 mask = CKCTL_6345_ENET_EN;
66         else if (BCMCPU_IS_6348())
67                 mask = CKCTL_6348_ENET_EN;
68         else
69                 /* BCMCPU_IS_6358 */
70                 mask = CKCTL_6358_EMUSB_EN;
71         bcm_hwclock_set(mask, enable);
72 }
73
74 static struct clk clk_enet_misc = {
75         .set    = enet_misc_set,
76 };
77
78 /*
79  * Ethernet MAC clocks: only revelant on 6358, silently enable misc
80  * clocks
81  */
82 static void enetx_set(struct clk *clk, int enable)
83 {
84         if (enable)
85                 clk_enable_unlocked(&clk_enet_misc);
86         else
87                 clk_disable_unlocked(&clk_enet_misc);
88
89         if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) {
90                 u32 mask;
91
92                 if (clk->id == 0)
93                         mask = CKCTL_6358_ENET0_EN;
94                 else
95                         mask = CKCTL_6358_ENET1_EN;
96                 bcm_hwclock_set(mask, enable);
97         }
98 }
99
100 static struct clk clk_enet0 = {
101         .id     = 0,
102         .set    = enetx_set,
103 };
104
105 static struct clk clk_enet1 = {
106         .id     = 1,
107         .set    = enetx_set,
108 };
109
110 /*
111  * Ethernet PHY clock
112  */
113 static void ephy_set(struct clk *clk, int enable)
114 {
115         if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
116                 bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable);
117 }
118
119
120 static struct clk clk_ephy = {
121         .set    = ephy_set,
122 };
123
124 /*
125  * Ethernet switch SAR clock
126  */
127 static void swpkt_sar_set(struct clk *clk, int enable)
128 {
129         if (BCMCPU_IS_6368())
130                 bcm_hwclock_set(CKCTL_6368_SWPKT_SAR_EN, enable);
131         else
132                 return;
133 }
134
135 static struct clk clk_swpkt_sar = {
136         .set    = swpkt_sar_set,
137 };
138
139 /*
140  * Ethernet switch USB clock
141  */
142 static void swpkt_usb_set(struct clk *clk, int enable)
143 {
144         if (BCMCPU_IS_6368())
145                 bcm_hwclock_set(CKCTL_6368_SWPKT_USB_EN, enable);
146         else
147                 return;
148 }
149
150 static struct clk clk_swpkt_usb = {
151         .set    = swpkt_usb_set,
152 };
153
154 /*
155  * Ethernet switch clock
156  */
157 static void enetsw_set(struct clk *clk, int enable)
158 {
159         if (BCMCPU_IS_6328()) {
160                 bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable);
161         } else if (BCMCPU_IS_6362()) {
162                 bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable);
163         } else if (BCMCPU_IS_6368()) {
164                 if (enable) {
165                         clk_enable_unlocked(&clk_swpkt_sar);
166                         clk_enable_unlocked(&clk_swpkt_usb);
167                 } else {
168                         clk_disable_unlocked(&clk_swpkt_usb);
169                         clk_disable_unlocked(&clk_swpkt_sar);
170                 }
171                 bcm_hwclock_set(CKCTL_6368_ROBOSW_EN, enable);
172         } else {
173                 return;
174         }
175
176         if (enable) {
177                 /* reset switch core afer clock change */
178                 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
179                 msleep(10);
180                 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
181                 msleep(10);
182         }
183 }
184
185 static struct clk clk_enetsw = {
186         .set    = enetsw_set,
187 };
188
189 /*
190  * PCM clock
191  */
192 static void pcm_set(struct clk *clk, int enable)
193 {
194         if (BCMCPU_IS_3368())
195                 bcm_hwclock_set(CKCTL_3368_PCM_EN, enable);
196         if (BCMCPU_IS_6358())
197                 bcm_hwclock_set(CKCTL_6358_PCM_EN, enable);
198 }
199
200 static struct clk clk_pcm = {
201         .set    = pcm_set,
202 };
203
204 /*
205  * USB host clock
206  */
207 static void usbh_set(struct clk *clk, int enable)
208 {
209         if (BCMCPU_IS_6328())
210                 bcm_hwclock_set(CKCTL_6328_USBH_EN, enable);
211         else if (BCMCPU_IS_6348())
212                 bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
213         else if (BCMCPU_IS_6362())
214                 bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
215         else if (BCMCPU_IS_6368())
216                 bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
217 }
218
219 static struct clk clk_usbh = {
220         .set    = usbh_set,
221 };
222
223 /*
224  * USB device clock
225  */
226 static void usbd_set(struct clk *clk, int enable)
227 {
228         if (BCMCPU_IS_6328())
229                 bcm_hwclock_set(CKCTL_6328_USBD_EN, enable);
230         else if (BCMCPU_IS_6362())
231                 bcm_hwclock_set(CKCTL_6362_USBD_EN, enable);
232         else if (BCMCPU_IS_6368())
233                 bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
234 }
235
236 static struct clk clk_usbd = {
237         .set    = usbd_set,
238 };
239
240 /*
241  * SPI clock
242  */
243 static void spi_set(struct clk *clk, int enable)
244 {
245         u32 mask;
246
247         if (BCMCPU_IS_6338())
248                 mask = CKCTL_6338_SPI_EN;
249         else if (BCMCPU_IS_6348())
250                 mask = CKCTL_6348_SPI_EN;
251         else if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
252                 mask = CKCTL_6358_SPI_EN;
253         else if (BCMCPU_IS_6362())
254                 mask = CKCTL_6362_SPI_EN;
255         else
256                 /* BCMCPU_IS_6368 */
257                 mask = CKCTL_6368_SPI_EN;
258         bcm_hwclock_set(mask, enable);
259 }
260
261 static struct clk clk_spi = {
262         .set    = spi_set,
263 };
264
265 /*
266  * HSSPI clock
267  */
268 static void hsspi_set(struct clk *clk, int enable)
269 {
270         u32 mask;
271
272         if (BCMCPU_IS_6328())
273                 mask = CKCTL_6328_HSSPI_EN;
274         else if (BCMCPU_IS_6362())
275                 mask = CKCTL_6362_HSSPI_EN;
276         else
277                 return;
278
279         bcm_hwclock_set(mask, enable);
280 }
281
282 static struct clk clk_hsspi = {
283         .set    = hsspi_set,
284 };
285
286 /*
287  * HSSPI PLL
288  */
289 static struct clk clk_hsspi_pll;
290
291 /*
292  * XTM clock
293  */
294 static void xtm_set(struct clk *clk, int enable)
295 {
296         if (!BCMCPU_IS_6368())
297                 return;
298
299         if (enable)
300                 clk_enable_unlocked(&clk_swpkt_sar);
301         else
302                 clk_disable_unlocked(&clk_swpkt_sar);
303
304         bcm_hwclock_set(CKCTL_6368_SAR_EN, enable);
305
306         if (enable) {
307                 /* reset sar core afer clock change */
308                 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
309                 mdelay(1);
310                 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
311                 mdelay(1);
312         }
313 }
314
315
316 static struct clk clk_xtm = {
317         .set    = xtm_set,
318 };
319
320 /*
321  * IPsec clock
322  */
323 static void ipsec_set(struct clk *clk, int enable)
324 {
325         if (BCMCPU_IS_6362())
326                 bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable);
327         else if (BCMCPU_IS_6368())
328                 bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
329 }
330
331 static struct clk clk_ipsec = {
332         .set    = ipsec_set,
333 };
334
335 /*
336  * PCIe clock
337  */
338
339 static void pcie_set(struct clk *clk, int enable)
340 {
341         if (BCMCPU_IS_6328())
342                 bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
343         else if (BCMCPU_IS_6362())
344                 bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
345 }
346
347 static struct clk clk_pcie = {
348         .set    = pcie_set,
349 };
350
351 /*
352  * Internal peripheral clock
353  */
354 static struct clk clk_periph = {
355         .rate   = (50 * 1000 * 1000),
356 };
357
358
359 /*
360  * Linux clock API implementation
361  */
362 int clk_enable(struct clk *clk)
363 {
364         if (!clk)
365                 return 0;
366         mutex_lock(&clocks_mutex);
367         clk_enable_unlocked(clk);
368         mutex_unlock(&clocks_mutex);
369         return 0;
370 }
371
372 EXPORT_SYMBOL(clk_enable);
373
374 void clk_disable(struct clk *clk)
375 {
376         if (!clk)
377                 return;
378
379         mutex_lock(&clocks_mutex);
380         clk_disable_unlocked(clk);
381         mutex_unlock(&clocks_mutex);
382 }
383
384 EXPORT_SYMBOL(clk_disable);
385
386 struct clk *clk_get_parent(struct clk *clk)
387 {
388         return NULL;
389 }
390 EXPORT_SYMBOL(clk_get_parent);
391
392 int clk_set_parent(struct clk *clk, struct clk *parent)
393 {
394         return 0;
395 }
396 EXPORT_SYMBOL(clk_set_parent);
397
398 unsigned long clk_get_rate(struct clk *clk)
399 {
400         if (!clk)
401                 return 0;
402
403         return clk->rate;
404 }
405
406 EXPORT_SYMBOL(clk_get_rate);
407
408 int clk_set_rate(struct clk *clk, unsigned long rate)
409 {
410         return 0;
411 }
412 EXPORT_SYMBOL_GPL(clk_set_rate);
413
414 long clk_round_rate(struct clk *clk, unsigned long rate)
415 {
416         return 0;
417 }
418 EXPORT_SYMBOL_GPL(clk_round_rate);
419
420 static struct clk_lookup bcm3368_clks[] = {
421         /* fixed rate clocks */
422         CLKDEV_INIT(NULL, "periph", &clk_periph),
423         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
424         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
425         /* gated clocks */
426         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
427         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
428         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
429         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
430         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
431         CLKDEV_INIT(NULL, "spi", &clk_spi),
432         CLKDEV_INIT(NULL, "pcm", &clk_pcm),
433         CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0),
434         CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1),
435 };
436
437 static struct clk_lookup bcm6328_clks[] = {
438         /* fixed rate clocks */
439         CLKDEV_INIT(NULL, "periph", &clk_periph),
440         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
441         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
442         CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
443         /* gated clocks */
444         CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
445         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
446         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
447         CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
448         CLKDEV_INIT(NULL, "pcie", &clk_pcie),
449 };
450
451 static struct clk_lookup bcm6338_clks[] = {
452         /* fixed rate clocks */
453         CLKDEV_INIT(NULL, "periph", &clk_periph),
454         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
455         /* gated clocks */
456         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
457         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
458         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
459         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
460         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
461         CLKDEV_INIT(NULL, "spi", &clk_spi),
462         CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
463 };
464
465 static struct clk_lookup bcm6345_clks[] = {
466         /* fixed rate clocks */
467         CLKDEV_INIT(NULL, "periph", &clk_periph),
468         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
469         /* gated clocks */
470         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
471         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
472         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
473         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
474         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
475         CLKDEV_INIT(NULL, "spi", &clk_spi),
476         CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
477 };
478
479 static struct clk_lookup bcm6348_clks[] = {
480         /* fixed rate clocks */
481         CLKDEV_INIT(NULL, "periph", &clk_periph),
482         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
483         /* gated clocks */
484         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
485         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
486         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
487         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
488         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
489         CLKDEV_INIT(NULL, "spi", &clk_spi),
490         CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
491         CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet_misc),
492 };
493
494 static struct clk_lookup bcm6358_clks[] = {
495         /* fixed rate clocks */
496         CLKDEV_INIT(NULL, "periph", &clk_periph),
497         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
498         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
499         /* gated clocks */
500         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
501         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
502         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
503         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
504         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
505         CLKDEV_INIT(NULL, "spi", &clk_spi),
506         CLKDEV_INIT(NULL, "pcm", &clk_pcm),
507         CLKDEV_INIT(NULL, "swpkt_sar", &clk_swpkt_sar),
508         CLKDEV_INIT(NULL, "swpkt_usb", &clk_swpkt_usb),
509         CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0),
510         CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1),
511 };
512
513 static struct clk_lookup bcm6362_clks[] = {
514         /* fixed rate clocks */
515         CLKDEV_INIT(NULL, "periph", &clk_periph),
516         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
517         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
518         CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
519         /* gated clocks */
520         CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
521         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
522         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
523         CLKDEV_INIT(NULL, "spi", &clk_spi),
524         CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
525         CLKDEV_INIT(NULL, "pcie", &clk_pcie),
526         CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
527 };
528
529 static struct clk_lookup bcm6368_clks[] = {
530         /* fixed rate clocks */
531         CLKDEV_INIT(NULL, "periph", &clk_periph),
532         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
533         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
534         /* gated clocks */
535         CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
536         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
537         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
538         CLKDEV_INIT(NULL, "spi", &clk_spi),
539         CLKDEV_INIT(NULL, "xtm", &clk_xtm),
540         CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
541 };
542
543 #define HSSPI_PLL_HZ_6328       133333333
544 #define HSSPI_PLL_HZ_6362       400000000
545
546 static int __init bcm63xx_clk_init(void)
547 {
548         switch (bcm63xx_get_cpu_id()) {
549         case BCM3368_CPU_ID:
550                 clkdev_add_table(bcm3368_clks, ARRAY_SIZE(bcm3368_clks));
551                 break;
552         case BCM6328_CPU_ID:
553                 clk_hsspi_pll.rate = HSSPI_PLL_HZ_6328;
554                 clkdev_add_table(bcm6328_clks, ARRAY_SIZE(bcm6328_clks));
555                 break;
556         case BCM6338_CPU_ID:
557                 clkdev_add_table(bcm6338_clks, ARRAY_SIZE(bcm6338_clks));
558                 break;
559         case BCM6345_CPU_ID:
560                 clkdev_add_table(bcm6345_clks, ARRAY_SIZE(bcm6345_clks));
561                 break;
562         case BCM6348_CPU_ID:
563                 clkdev_add_table(bcm6348_clks, ARRAY_SIZE(bcm6348_clks));
564                 break;
565         case BCM6358_CPU_ID:
566                 clkdev_add_table(bcm6358_clks, ARRAY_SIZE(bcm6358_clks));
567                 break;
568         case BCM6362_CPU_ID:
569                 clk_hsspi_pll.rate = HSSPI_PLL_HZ_6362;
570                 clkdev_add_table(bcm6362_clks, ARRAY_SIZE(bcm6362_clks));
571                 break;
572         case BCM6368_CPU_ID:
573                 clkdev_add_table(bcm6368_clks, ARRAY_SIZE(bcm6368_clks));
574                 break;
575         }
576
577         return 0;
578 }
579 arch_initcall(bcm63xx_clk_init);