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
6 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
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>
22 void (*set)(struct clk *, int);
28 static DEFINE_MUTEX(clocks_mutex);
31 static void clk_enable_unlocked(struct clk *clk)
33 if (clk->set && (clk->usage++) == 0)
37 static void clk_disable_unlocked(struct clk *clk)
39 if (clk->set && (--clk->usage) == 0)
43 static void bcm_hwclock_set(u32 mask, int enable)
47 reg = bcm_perf_readl(PERF_CKCTL_REG);
52 bcm_perf_writel(reg, PERF_CKCTL_REG);
56 * Ethernet MAC "misc" clock: dma clocks and main clock on 6348
58 static void enet_misc_set(struct clk *clk, int enable)
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;
70 mask = CKCTL_6358_EMUSB_EN;
71 bcm_hwclock_set(mask, enable);
74 static struct clk clk_enet_misc = {
79 * Ethernet MAC clocks: only revelant on 6358, silently enable misc
82 static void enetx_set(struct clk *clk, int enable)
85 clk_enable_unlocked(&clk_enet_misc);
87 clk_disable_unlocked(&clk_enet_misc);
89 if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) {
93 mask = CKCTL_6358_ENET0_EN;
95 mask = CKCTL_6358_ENET1_EN;
96 bcm_hwclock_set(mask, enable);
100 static struct clk clk_enet0 = {
105 static struct clk clk_enet1 = {
113 static void ephy_set(struct clk *clk, int enable)
115 if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
116 bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable);
120 static struct clk clk_ephy = {
125 * Ethernet switch clock
127 static void enetsw_set(struct clk *clk, int enable)
129 if (BCMCPU_IS_6328())
130 bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable);
131 else if (BCMCPU_IS_6362())
132 bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable);
133 else if (BCMCPU_IS_6368())
134 bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
135 CKCTL_6368_SWPKT_USB_EN |
136 CKCTL_6368_SWPKT_SAR_EN,
142 /* reset switch core afer clock change */
143 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
145 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
150 static struct clk clk_enetsw = {
157 static void pcm_set(struct clk *clk, int enable)
159 if (BCMCPU_IS_3368())
160 bcm_hwclock_set(CKCTL_3368_PCM_EN, enable);
161 if (BCMCPU_IS_6358())
162 bcm_hwclock_set(CKCTL_6358_PCM_EN, enable);
165 static struct clk clk_pcm = {
172 static void usbh_set(struct clk *clk, int enable)
174 if (BCMCPU_IS_6328())
175 bcm_hwclock_set(CKCTL_6328_USBH_EN, enable);
176 else if (BCMCPU_IS_6348())
177 bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
178 else if (BCMCPU_IS_6362())
179 bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
180 else if (BCMCPU_IS_6368())
181 bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
184 static struct clk clk_usbh = {
191 static void usbd_set(struct clk *clk, int enable)
193 if (BCMCPU_IS_6328())
194 bcm_hwclock_set(CKCTL_6328_USBD_EN, enable);
195 else if (BCMCPU_IS_6362())
196 bcm_hwclock_set(CKCTL_6362_USBD_EN, enable);
197 else if (BCMCPU_IS_6368())
198 bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
201 static struct clk clk_usbd = {
208 static void spi_set(struct clk *clk, int enable)
212 if (BCMCPU_IS_6338())
213 mask = CKCTL_6338_SPI_EN;
214 else if (BCMCPU_IS_6348())
215 mask = CKCTL_6348_SPI_EN;
216 else if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
217 mask = CKCTL_6358_SPI_EN;
218 else if (BCMCPU_IS_6362())
219 mask = CKCTL_6362_SPI_EN;
222 mask = CKCTL_6368_SPI_EN;
223 bcm_hwclock_set(mask, enable);
226 static struct clk clk_spi = {
233 static void hsspi_set(struct clk *clk, int enable)
237 if (BCMCPU_IS_6328())
238 mask = CKCTL_6328_HSSPI_EN;
239 else if (BCMCPU_IS_6362())
240 mask = CKCTL_6362_HSSPI_EN;
244 bcm_hwclock_set(mask, enable);
247 static struct clk clk_hsspi = {
254 static struct clk clk_hsspi_pll;
259 static void xtm_set(struct clk *clk, int enable)
261 if (!BCMCPU_IS_6368())
264 bcm_hwclock_set(CKCTL_6368_SAR_EN |
265 CKCTL_6368_SWPKT_SAR_EN, enable);
268 /* reset sar core afer clock change */
269 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
271 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
277 static struct clk clk_xtm = {
284 static void ipsec_set(struct clk *clk, int enable)
286 if (BCMCPU_IS_6362())
287 bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable);
288 else if (BCMCPU_IS_6368())
289 bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
292 static struct clk clk_ipsec = {
300 static void pcie_set(struct clk *clk, int enable)
302 if (BCMCPU_IS_6328())
303 bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
304 else if (BCMCPU_IS_6362())
305 bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
308 static struct clk clk_pcie = {
313 * Internal peripheral clock
315 static struct clk clk_periph = {
316 .rate = (50 * 1000 * 1000),
321 * Linux clock API implementation
323 int clk_enable(struct clk *clk)
325 mutex_lock(&clocks_mutex);
326 clk_enable_unlocked(clk);
327 mutex_unlock(&clocks_mutex);
331 EXPORT_SYMBOL(clk_enable);
333 void clk_disable(struct clk *clk)
338 mutex_lock(&clocks_mutex);
339 clk_disable_unlocked(clk);
340 mutex_unlock(&clocks_mutex);
343 EXPORT_SYMBOL(clk_disable);
345 unsigned long clk_get_rate(struct clk *clk)
353 EXPORT_SYMBOL(clk_get_rate);
355 int clk_set_rate(struct clk *clk, unsigned long rate)
359 EXPORT_SYMBOL_GPL(clk_set_rate);
361 long clk_round_rate(struct clk *clk, unsigned long rate)
365 EXPORT_SYMBOL_GPL(clk_round_rate);
367 static struct clk_lookup bcm3368_clks[] = {
368 /* fixed rate clocks */
369 CLKDEV_INIT(NULL, "periph", &clk_periph),
370 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
371 CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
373 CLKDEV_INIT(NULL, "enet0", &clk_enet0),
374 CLKDEV_INIT(NULL, "enet1", &clk_enet1),
375 CLKDEV_INIT(NULL, "ephy", &clk_ephy),
376 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
377 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
378 CLKDEV_INIT(NULL, "spi", &clk_spi),
379 CLKDEV_INIT(NULL, "pcm", &clk_pcm),
380 CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0),
381 CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1),
384 static struct clk_lookup bcm6328_clks[] = {
385 /* fixed rate clocks */
386 CLKDEV_INIT(NULL, "periph", &clk_periph),
387 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
388 CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
389 CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
391 CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
392 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
393 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
394 CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
395 CLKDEV_INIT(NULL, "pcie", &clk_pcie),
398 static struct clk_lookup bcm6338_clks[] = {
399 /* fixed rate clocks */
400 CLKDEV_INIT(NULL, "periph", &clk_periph),
401 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
403 CLKDEV_INIT(NULL, "enet0", &clk_enet0),
404 CLKDEV_INIT(NULL, "enet1", &clk_enet1),
405 CLKDEV_INIT(NULL, "ephy", &clk_ephy),
406 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
407 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
408 CLKDEV_INIT(NULL, "spi", &clk_spi),
409 CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
412 static struct clk_lookup bcm6345_clks[] = {
413 /* fixed rate clocks */
414 CLKDEV_INIT(NULL, "periph", &clk_periph),
415 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
417 CLKDEV_INIT(NULL, "enet0", &clk_enet0),
418 CLKDEV_INIT(NULL, "enet1", &clk_enet1),
419 CLKDEV_INIT(NULL, "ephy", &clk_ephy),
420 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
421 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
422 CLKDEV_INIT(NULL, "spi", &clk_spi),
423 CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
426 static struct clk_lookup bcm6348_clks[] = {
427 /* fixed rate clocks */
428 CLKDEV_INIT(NULL, "periph", &clk_periph),
429 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
431 CLKDEV_INIT(NULL, "enet0", &clk_enet0),
432 CLKDEV_INIT(NULL, "enet1", &clk_enet1),
433 CLKDEV_INIT(NULL, "ephy", &clk_ephy),
434 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
435 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
436 CLKDEV_INIT(NULL, "spi", &clk_spi),
437 CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
438 CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet_misc),
441 static struct clk_lookup bcm6358_clks[] = {
442 /* fixed rate clocks */
443 CLKDEV_INIT(NULL, "periph", &clk_periph),
444 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
445 CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
447 CLKDEV_INIT(NULL, "enet0", &clk_enet0),
448 CLKDEV_INIT(NULL, "enet1", &clk_enet1),
449 CLKDEV_INIT(NULL, "ephy", &clk_ephy),
450 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
451 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
452 CLKDEV_INIT(NULL, "spi", &clk_spi),
453 CLKDEV_INIT(NULL, "pcm", &clk_pcm),
454 CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0),
455 CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1),
458 static struct clk_lookup bcm6362_clks[] = {
459 /* fixed rate clocks */
460 CLKDEV_INIT(NULL, "periph", &clk_periph),
461 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
462 CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
463 CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
465 CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
466 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
467 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
468 CLKDEV_INIT(NULL, "spi", &clk_spi),
469 CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
470 CLKDEV_INIT(NULL, "pcie", &clk_pcie),
471 CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
474 static struct clk_lookup bcm6368_clks[] = {
475 /* fixed rate clocks */
476 CLKDEV_INIT(NULL, "periph", &clk_periph),
477 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
478 CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
480 CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
481 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
482 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
483 CLKDEV_INIT(NULL, "spi", &clk_spi),
484 CLKDEV_INIT(NULL, "xtm", &clk_xtm),
485 CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
488 #define HSSPI_PLL_HZ_6328 133333333
489 #define HSSPI_PLL_HZ_6362 400000000
491 static int __init bcm63xx_clk_init(void)
493 switch (bcm63xx_get_cpu_id()) {
495 clkdev_add_table(bcm3368_clks, ARRAY_SIZE(bcm3368_clks));
498 clk_hsspi_pll.rate = HSSPI_PLL_HZ_6328;
499 clkdev_add_table(bcm6328_clks, ARRAY_SIZE(bcm6328_clks));
502 clkdev_add_table(bcm6338_clks, ARRAY_SIZE(bcm6338_clks));
505 clkdev_add_table(bcm6345_clks, ARRAY_SIZE(bcm6345_clks));
508 clkdev_add_table(bcm6348_clks, ARRAY_SIZE(bcm6348_clks));
511 clkdev_add_table(bcm6358_clks, ARRAY_SIZE(bcm6358_clks));
514 clk_hsspi_pll.rate = HSSPI_PLL_HZ_6362;
515 clkdev_add_table(bcm6362_clks, ARRAY_SIZE(bcm6362_clks));
518 clkdev_add_table(bcm6368_clks, ARRAY_SIZE(bcm6368_clks));
524 arch_initcall(bcm63xx_clk_init);