~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/bcm63xx/clk.c

Version: ~ [ linux-5.9.1 ] ~ [ linux-5.8.16 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.72 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.152 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.202 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.240 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.240 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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         mutex_lock(&clocks_mutex);
365         clk_enable_unlocked(clk);
366         mutex_unlock(&clocks_mutex);
367         return 0;
368 }
369 
370 EXPORT_SYMBOL(clk_enable);
371 
372 void clk_disable(struct clk *clk)
373 {
374         if (!clk)
375                 return;
376 
377         mutex_lock(&clocks_mutex);
378         clk_disable_unlocked(clk);
379         mutex_unlock(&clocks_mutex);
380 }
381 
382 EXPORT_SYMBOL(clk_disable);
383 
384 unsigned long clk_get_rate(struct clk *clk)
385 {
386         if (!clk)
387                 return 0;
388 
389         return clk->rate;
390 }
391 
392 EXPORT_SYMBOL(clk_get_rate);
393 
394 int clk_set_rate(struct clk *clk, unsigned long rate)
395 {
396         return 0;
397 }
398 EXPORT_SYMBOL_GPL(clk_set_rate);
399 
400 long clk_round_rate(struct clk *clk, unsigned long rate)
401 {
402         return 0;
403 }
404 EXPORT_SYMBOL_GPL(clk_round_rate);
405 
406 static struct clk_lookup bcm3368_clks[] = {
407         /* fixed rate clocks */
408         CLKDEV_INIT(NULL, "periph", &clk_periph),
409         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
410         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
411         /* gated clocks */
412         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
413         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
414         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
415         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
416         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
417         CLKDEV_INIT(NULL, "spi", &clk_spi),
418         CLKDEV_INIT(NULL, "pcm", &clk_pcm),
419         CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0),
420         CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1),
421 };
422 
423 static struct clk_lookup bcm6328_clks[] = {
424         /* fixed rate clocks */
425         CLKDEV_INIT(NULL, "periph", &clk_periph),
426         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
427         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
428         CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
429         /* gated clocks */
430         CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
431         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
432         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
433         CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
434         CLKDEV_INIT(NULL, "pcie", &clk_pcie),
435 };
436 
437 static struct clk_lookup bcm6338_clks[] = {
438         /* fixed rate clocks */
439         CLKDEV_INIT(NULL, "periph", &clk_periph),
440         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
441         /* gated clocks */
442         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
443         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
444         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
445         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
446         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
447         CLKDEV_INIT(NULL, "spi", &clk_spi),
448         CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
449 };
450 
451 static struct clk_lookup bcm6345_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 bcm6348_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         CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet_misc),
478 };
479 
480 static struct clk_lookup bcm6358_clks[] = {
481         /* fixed rate clocks */
482         CLKDEV_INIT(NULL, "periph", &clk_periph),
483         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
484         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
485         /* gated clocks */
486         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
487         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
488         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
489         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
490         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
491         CLKDEV_INIT(NULL, "spi", &clk_spi),
492         CLKDEV_INIT(NULL, "pcm", &clk_pcm),
493         CLKDEV_INIT(NULL, "swpkt_sar", &clk_swpkt_sar),
494         CLKDEV_INIT(NULL, "swpkt_usb", &clk_swpkt_usb),
495         CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0),
496         CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1),
497 };
498 
499 static struct clk_lookup bcm6362_clks[] = {
500         /* fixed rate clocks */
501         CLKDEV_INIT(NULL, "periph", &clk_periph),
502         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
503         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
504         CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
505         /* gated clocks */
506         CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
507         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
508         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
509         CLKDEV_INIT(NULL, "spi", &clk_spi),
510         CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
511         CLKDEV_INIT(NULL, "pcie", &clk_pcie),
512         CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
513 };
514 
515 static struct clk_lookup bcm6368_clks[] = {
516         /* fixed rate clocks */
517         CLKDEV_INIT(NULL, "periph", &clk_periph),
518         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
519         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
520         /* gated clocks */
521         CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
522         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
523         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
524         CLKDEV_INIT(NULL, "spi", &clk_spi),
525         CLKDEV_INIT(NULL, "xtm", &clk_xtm),
526         CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
527 };
528 
529 #define HSSPI_PLL_HZ_6328       133333333
530 #define HSSPI_PLL_HZ_6362       400000000
531 
532 static int __init bcm63xx_clk_init(void)
533 {
534         switch (bcm63xx_get_cpu_id()) {
535         case BCM3368_CPU_ID:
536                 clkdev_add_table(bcm3368_clks, ARRAY_SIZE(bcm3368_clks));
537                 break;
538         case BCM6328_CPU_ID:
539                 clk_hsspi_pll.rate = HSSPI_PLL_HZ_6328;
540                 clkdev_add_table(bcm6328_clks, ARRAY_SIZE(bcm6328_clks));
541                 break;
542         case BCM6338_CPU_ID:
543                 clkdev_add_table(bcm6338_clks, ARRAY_SIZE(bcm6338_clks));
544                 break;
545         case BCM6345_CPU_ID:
546                 clkdev_add_table(bcm6345_clks, ARRAY_SIZE(bcm6345_clks));
547                 break;
548         case BCM6348_CPU_ID:
549                 clkdev_add_table(bcm6348_clks, ARRAY_SIZE(bcm6348_clks));
550                 break;
551         case BCM6358_CPU_ID:
552                 clkdev_add_table(bcm6358_clks, ARRAY_SIZE(bcm6358_clks));
553                 break;
554         case BCM6362_CPU_ID:
555                 clk_hsspi_pll.rate = HSSPI_PLL_HZ_6362;
556                 clkdev_add_table(bcm6362_clks, ARRAY_SIZE(bcm6362_clks));
557                 break;
558         case BCM6368_CPU_ID:
559                 clkdev_add_table(bcm6368_clks, ARRAY_SIZE(bcm6368_clks));
560                 break;
561         }
562 
563         return 0;
564 }
565 arch_initcall(bcm63xx_clk_init);
566 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp