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 = {
255 static void xtm_set(struct clk *clk, int enable)
257 if (!BCMCPU_IS_6368())
260 bcm_hwclock_set(CKCTL_6368_SAR_EN |
261 CKCTL_6368_SWPKT_SAR_EN, enable);
264 /* reset sar core afer clock change */
265 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
267 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
273 static struct clk clk_xtm = {
280 static void ipsec_set(struct clk *clk, int enable)
282 if (BCMCPU_IS_6362())
283 bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable);
284 else if (BCMCPU_IS_6368())
285 bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
288 static struct clk clk_ipsec = {
296 static void pcie_set(struct clk *clk, int enable)
298 if (BCMCPU_IS_6328())
299 bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
300 else if (BCMCPU_IS_6362())
301 bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
304 static struct clk clk_pcie = {
309 * Internal peripheral clock
311 static struct clk clk_periph = {
312 .rate = (50 * 1000 * 1000),
317 * Linux clock API implementation
319 int clk_enable(struct clk *clk)
321 mutex_lock(&clocks_mutex);
322 clk_enable_unlocked(clk);
323 mutex_unlock(&clocks_mutex);
327 EXPORT_SYMBOL(clk_enable);
329 void clk_disable(struct clk *clk)
334 mutex_lock(&clocks_mutex);
335 clk_disable_unlocked(clk);
336 mutex_unlock(&clocks_mutex);
339 EXPORT_SYMBOL(clk_disable);
341 unsigned long clk_get_rate(struct clk *clk)
349 EXPORT_SYMBOL(clk_get_rate);
351 int clk_set_rate(struct clk *clk, unsigned long rate)
355 EXPORT_SYMBOL_GPL(clk_set_rate);
357 long clk_round_rate(struct clk *clk, unsigned long rate)
361 EXPORT_SYMBOL_GPL(clk_round_rate);
363 static struct clk_lookup bcm3368_clks[] = {
364 /* fixed rate clocks */
365 CLKDEV_INIT(NULL, "periph", &clk_periph),
367 CLKDEV_INIT(NULL, "enet0", &clk_enet0),
368 CLKDEV_INIT(NULL, "enet1", &clk_enet1),
369 CLKDEV_INIT(NULL, "ephy", &clk_ephy),
370 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
371 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
372 CLKDEV_INIT(NULL, "spi", &clk_spi),
373 CLKDEV_INIT(NULL, "pcm", &clk_pcm),
376 static struct clk_lookup bcm6328_clks[] = {
377 /* fixed rate clocks */
378 CLKDEV_INIT(NULL, "periph", &clk_periph),
380 CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
381 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
382 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
383 CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
384 CLKDEV_INIT(NULL, "pcie", &clk_pcie),
387 static struct clk_lookup bcm6338_clks[] = {
388 /* fixed rate clocks */
389 CLKDEV_INIT(NULL, "periph", &clk_periph),
391 CLKDEV_INIT(NULL, "enet0", &clk_enet0),
392 CLKDEV_INIT(NULL, "enet1", &clk_enet1),
393 CLKDEV_INIT(NULL, "ephy", &clk_ephy),
394 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
395 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
396 CLKDEV_INIT(NULL, "spi", &clk_spi),
399 static struct clk_lookup bcm6345_clks[] = {
400 /* fixed rate clocks */
401 CLKDEV_INIT(NULL, "periph", &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),
411 static struct clk_lookup bcm6348_clks[] = {
412 /* fixed rate clocks */
413 CLKDEV_INIT(NULL, "periph", &clk_periph),
415 CLKDEV_INIT(NULL, "enet0", &clk_enet0),
416 CLKDEV_INIT(NULL, "enet1", &clk_enet1),
417 CLKDEV_INIT(NULL, "ephy", &clk_ephy),
418 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
419 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
420 CLKDEV_INIT(NULL, "spi", &clk_spi),
423 static struct clk_lookup bcm6358_clks[] = {
424 /* fixed rate clocks */
425 CLKDEV_INIT(NULL, "periph", &clk_periph),
427 CLKDEV_INIT(NULL, "enet0", &clk_enet0),
428 CLKDEV_INIT(NULL, "enet1", &clk_enet1),
429 CLKDEV_INIT(NULL, "ephy", &clk_ephy),
430 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
431 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
432 CLKDEV_INIT(NULL, "spi", &clk_spi),
433 CLKDEV_INIT(NULL, "pcm", &clk_pcm),
436 static struct clk_lookup bcm6362_clks[] = {
437 /* fixed rate clocks */
438 CLKDEV_INIT(NULL, "periph", &clk_periph),
440 CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
441 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
442 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
443 CLKDEV_INIT(NULL, "spi", &clk_spi),
444 CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
445 CLKDEV_INIT(NULL, "pcie", &clk_pcie),
446 CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
449 static struct clk_lookup bcm6368_clks[] = {
450 /* fixed rate clocks */
451 CLKDEV_INIT(NULL, "periph", &clk_periph),
453 CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
454 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
455 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
456 CLKDEV_INIT(NULL, "spi", &clk_spi),
457 CLKDEV_INIT(NULL, "xtm", &clk_xtm),
458 CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
461 #define HSSPI_PLL_HZ_6328 133333333
462 #define HSSPI_PLL_HZ_6362 400000000
464 static int __init bcm63xx_clk_init(void)
466 switch (bcm63xx_get_cpu_id()) {
468 clkdev_add_table(bcm3368_clks, ARRAY_SIZE(bcm3368_clks));
471 clk_hsspi.rate = HSSPI_PLL_HZ_6328;
472 clkdev_add_table(bcm6328_clks, ARRAY_SIZE(bcm6328_clks));
475 clkdev_add_table(bcm6338_clks, ARRAY_SIZE(bcm6338_clks));
478 clkdev_add_table(bcm6345_clks, ARRAY_SIZE(bcm6345_clks));
481 clkdev_add_table(bcm6348_clks, ARRAY_SIZE(bcm6348_clks));
484 clkdev_add_table(bcm6358_clks, ARRAY_SIZE(bcm6358_clks));
487 clk_hsspi.rate = HSSPI_PLL_HZ_6362;
488 clkdev_add_table(bcm6362_clks, ARRAY_SIZE(bcm6362_clks));
491 clkdev_add_table(bcm6368_clks, ARRAY_SIZE(bcm6368_clks));
497 arch_initcall(bcm63xx_clk_init);