0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/init.h>
0010 #include <linux/export.h>
0011 #include <linux/mutex.h>
0012 #include <linux/err.h>
0013 #include <linux/clk.h>
0014 #include <linux/clkdev.h>
0015 #include <linux/delay.h>
0016 #include <bcm63xx_cpu.h>
0017 #include <bcm63xx_io.h>
0018 #include <bcm63xx_regs.h>
0019 #include <bcm63xx_reset.h>
0020
0021 struct clk {
0022 void (*set)(struct clk *, int);
0023 unsigned int rate;
0024 unsigned int usage;
0025 int id;
0026 };
0027
0028 static DEFINE_MUTEX(clocks_mutex);
0029
0030
0031 static void clk_enable_unlocked(struct clk *clk)
0032 {
0033 if (clk->set && (clk->usage++) == 0)
0034 clk->set(clk, 1);
0035 }
0036
0037 static void clk_disable_unlocked(struct clk *clk)
0038 {
0039 if (clk->set && (--clk->usage) == 0)
0040 clk->set(clk, 0);
0041 }
0042
0043 static void bcm_hwclock_set(u32 mask, int enable)
0044 {
0045 u32 reg;
0046
0047 reg = bcm_perf_readl(PERF_CKCTL_REG);
0048 if (enable)
0049 reg |= mask;
0050 else
0051 reg &= ~mask;
0052 bcm_perf_writel(reg, PERF_CKCTL_REG);
0053 }
0054
0055
0056
0057
0058 static void enet_misc_set(struct clk *clk, int enable)
0059 {
0060 u32 mask;
0061
0062 if (BCMCPU_IS_6338())
0063 mask = CKCTL_6338_ENET_EN;
0064 else if (BCMCPU_IS_6345())
0065 mask = CKCTL_6345_ENET_EN;
0066 else if (BCMCPU_IS_6348())
0067 mask = CKCTL_6348_ENET_EN;
0068 else
0069
0070 mask = CKCTL_6358_EMUSB_EN;
0071 bcm_hwclock_set(mask, enable);
0072 }
0073
0074 static struct clk clk_enet_misc = {
0075 .set = enet_misc_set,
0076 };
0077
0078
0079
0080
0081
0082 static void enetx_set(struct clk *clk, int enable)
0083 {
0084 if (enable)
0085 clk_enable_unlocked(&clk_enet_misc);
0086 else
0087 clk_disable_unlocked(&clk_enet_misc);
0088
0089 if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) {
0090 u32 mask;
0091
0092 if (clk->id == 0)
0093 mask = CKCTL_6358_ENET0_EN;
0094 else
0095 mask = CKCTL_6358_ENET1_EN;
0096 bcm_hwclock_set(mask, enable);
0097 }
0098 }
0099
0100 static struct clk clk_enet0 = {
0101 .id = 0,
0102 .set = enetx_set,
0103 };
0104
0105 static struct clk clk_enet1 = {
0106 .id = 1,
0107 .set = enetx_set,
0108 };
0109
0110
0111
0112
0113 static void ephy_set(struct clk *clk, int enable)
0114 {
0115 if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
0116 bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable);
0117 }
0118
0119
0120 static struct clk clk_ephy = {
0121 .set = ephy_set,
0122 };
0123
0124
0125
0126
0127 static void swpkt_sar_set(struct clk *clk, int enable)
0128 {
0129 if (BCMCPU_IS_6368())
0130 bcm_hwclock_set(CKCTL_6368_SWPKT_SAR_EN, enable);
0131 else
0132 return;
0133 }
0134
0135 static struct clk clk_swpkt_sar = {
0136 .set = swpkt_sar_set,
0137 };
0138
0139
0140
0141
0142 static void swpkt_usb_set(struct clk *clk, int enable)
0143 {
0144 if (BCMCPU_IS_6368())
0145 bcm_hwclock_set(CKCTL_6368_SWPKT_USB_EN, enable);
0146 else
0147 return;
0148 }
0149
0150 static struct clk clk_swpkt_usb = {
0151 .set = swpkt_usb_set,
0152 };
0153
0154
0155
0156
0157 static void enetsw_set(struct clk *clk, int enable)
0158 {
0159 if (BCMCPU_IS_6328()) {
0160 bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable);
0161 } else if (BCMCPU_IS_6362()) {
0162 bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable);
0163 } else if (BCMCPU_IS_6368()) {
0164 if (enable) {
0165 clk_enable_unlocked(&clk_swpkt_sar);
0166 clk_enable_unlocked(&clk_swpkt_usb);
0167 } else {
0168 clk_disable_unlocked(&clk_swpkt_usb);
0169 clk_disable_unlocked(&clk_swpkt_sar);
0170 }
0171 bcm_hwclock_set(CKCTL_6368_ROBOSW_EN, enable);
0172 } else {
0173 return;
0174 }
0175
0176 if (enable) {
0177
0178 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
0179 msleep(10);
0180 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
0181 msleep(10);
0182 }
0183 }
0184
0185 static struct clk clk_enetsw = {
0186 .set = enetsw_set,
0187 };
0188
0189
0190
0191
0192 static void pcm_set(struct clk *clk, int enable)
0193 {
0194 if (BCMCPU_IS_3368())
0195 bcm_hwclock_set(CKCTL_3368_PCM_EN, enable);
0196 if (BCMCPU_IS_6358())
0197 bcm_hwclock_set(CKCTL_6358_PCM_EN, enable);
0198 }
0199
0200 static struct clk clk_pcm = {
0201 .set = pcm_set,
0202 };
0203
0204
0205
0206
0207 static void usbh_set(struct clk *clk, int enable)
0208 {
0209 if (BCMCPU_IS_6328())
0210 bcm_hwclock_set(CKCTL_6328_USBH_EN, enable);
0211 else if (BCMCPU_IS_6348())
0212 bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
0213 else if (BCMCPU_IS_6362())
0214 bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
0215 else if (BCMCPU_IS_6368())
0216 bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
0217 }
0218
0219 static struct clk clk_usbh = {
0220 .set = usbh_set,
0221 };
0222
0223
0224
0225
0226 static void usbd_set(struct clk *clk, int enable)
0227 {
0228 if (BCMCPU_IS_6328())
0229 bcm_hwclock_set(CKCTL_6328_USBD_EN, enable);
0230 else if (BCMCPU_IS_6362())
0231 bcm_hwclock_set(CKCTL_6362_USBD_EN, enable);
0232 else if (BCMCPU_IS_6368())
0233 bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
0234 }
0235
0236 static struct clk clk_usbd = {
0237 .set = usbd_set,
0238 };
0239
0240
0241
0242
0243 static void spi_set(struct clk *clk, int enable)
0244 {
0245 u32 mask;
0246
0247 if (BCMCPU_IS_6338())
0248 mask = CKCTL_6338_SPI_EN;
0249 else if (BCMCPU_IS_6348())
0250 mask = CKCTL_6348_SPI_EN;
0251 else if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
0252 mask = CKCTL_6358_SPI_EN;
0253 else if (BCMCPU_IS_6362())
0254 mask = CKCTL_6362_SPI_EN;
0255 else
0256
0257 mask = CKCTL_6368_SPI_EN;
0258 bcm_hwclock_set(mask, enable);
0259 }
0260
0261 static struct clk clk_spi = {
0262 .set = spi_set,
0263 };
0264
0265
0266
0267
0268 static void hsspi_set(struct clk *clk, int enable)
0269 {
0270 u32 mask;
0271
0272 if (BCMCPU_IS_6328())
0273 mask = CKCTL_6328_HSSPI_EN;
0274 else if (BCMCPU_IS_6362())
0275 mask = CKCTL_6362_HSSPI_EN;
0276 else
0277 return;
0278
0279 bcm_hwclock_set(mask, enable);
0280 }
0281
0282 static struct clk clk_hsspi = {
0283 .set = hsspi_set,
0284 };
0285
0286
0287
0288
0289 static struct clk clk_hsspi_pll;
0290
0291
0292
0293
0294 static void xtm_set(struct clk *clk, int enable)
0295 {
0296 if (!BCMCPU_IS_6368())
0297 return;
0298
0299 if (enable)
0300 clk_enable_unlocked(&clk_swpkt_sar);
0301 else
0302 clk_disable_unlocked(&clk_swpkt_sar);
0303
0304 bcm_hwclock_set(CKCTL_6368_SAR_EN, enable);
0305
0306 if (enable) {
0307
0308 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
0309 mdelay(1);
0310 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
0311 mdelay(1);
0312 }
0313 }
0314
0315
0316 static struct clk clk_xtm = {
0317 .set = xtm_set,
0318 };
0319
0320
0321
0322
0323 static void ipsec_set(struct clk *clk, int enable)
0324 {
0325 if (BCMCPU_IS_6362())
0326 bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable);
0327 else if (BCMCPU_IS_6368())
0328 bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
0329 }
0330
0331 static struct clk clk_ipsec = {
0332 .set = ipsec_set,
0333 };
0334
0335
0336
0337
0338
0339 static void pcie_set(struct clk *clk, int enable)
0340 {
0341 if (BCMCPU_IS_6328())
0342 bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
0343 else if (BCMCPU_IS_6362())
0344 bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
0345 }
0346
0347 static struct clk clk_pcie = {
0348 .set = pcie_set,
0349 };
0350
0351
0352
0353
0354 static struct clk clk_periph = {
0355 .rate = (50 * 1000 * 1000),
0356 };
0357
0358
0359
0360
0361
0362 int clk_enable(struct clk *clk)
0363 {
0364 mutex_lock(&clocks_mutex);
0365 clk_enable_unlocked(clk);
0366 mutex_unlock(&clocks_mutex);
0367 return 0;
0368 }
0369
0370 EXPORT_SYMBOL(clk_enable);
0371
0372 void clk_disable(struct clk *clk)
0373 {
0374 if (!clk)
0375 return;
0376
0377 mutex_lock(&clocks_mutex);
0378 clk_disable_unlocked(clk);
0379 mutex_unlock(&clocks_mutex);
0380 }
0381
0382 EXPORT_SYMBOL(clk_disable);
0383
0384 struct clk *clk_get_parent(struct clk *clk)
0385 {
0386 return NULL;
0387 }
0388 EXPORT_SYMBOL(clk_get_parent);
0389
0390 int clk_set_parent(struct clk *clk, struct clk *parent)
0391 {
0392 return 0;
0393 }
0394 EXPORT_SYMBOL(clk_set_parent);
0395
0396 unsigned long clk_get_rate(struct clk *clk)
0397 {
0398 if (!clk)
0399 return 0;
0400
0401 return clk->rate;
0402 }
0403
0404 EXPORT_SYMBOL(clk_get_rate);
0405
0406 int clk_set_rate(struct clk *clk, unsigned long rate)
0407 {
0408 return 0;
0409 }
0410 EXPORT_SYMBOL_GPL(clk_set_rate);
0411
0412 long clk_round_rate(struct clk *clk, unsigned long rate)
0413 {
0414 return 0;
0415 }
0416 EXPORT_SYMBOL_GPL(clk_round_rate);
0417
0418 static struct clk_lookup bcm3368_clks[] = {
0419
0420 CLKDEV_INIT(NULL, "periph", &clk_periph),
0421 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
0422 CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
0423
0424 CLKDEV_INIT(NULL, "enet0", &clk_enet0),
0425 CLKDEV_INIT(NULL, "enet1", &clk_enet1),
0426 CLKDEV_INIT(NULL, "ephy", &clk_ephy),
0427 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
0428 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
0429 CLKDEV_INIT(NULL, "spi", &clk_spi),
0430 CLKDEV_INIT(NULL, "pcm", &clk_pcm),
0431 CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0),
0432 CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1),
0433 };
0434
0435 static struct clk_lookup bcm6328_clks[] = {
0436
0437 CLKDEV_INIT(NULL, "periph", &clk_periph),
0438 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
0439 CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
0440 CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
0441
0442 CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
0443 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
0444 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
0445 CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
0446 CLKDEV_INIT(NULL, "pcie", &clk_pcie),
0447 };
0448
0449 static struct clk_lookup bcm6338_clks[] = {
0450
0451 CLKDEV_INIT(NULL, "periph", &clk_periph),
0452 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
0453
0454 CLKDEV_INIT(NULL, "enet0", &clk_enet0),
0455 CLKDEV_INIT(NULL, "enet1", &clk_enet1),
0456 CLKDEV_INIT(NULL, "ephy", &clk_ephy),
0457 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
0458 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
0459 CLKDEV_INIT(NULL, "spi", &clk_spi),
0460 CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
0461 };
0462
0463 static struct clk_lookup bcm6345_clks[] = {
0464
0465 CLKDEV_INIT(NULL, "periph", &clk_periph),
0466 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
0467
0468 CLKDEV_INIT(NULL, "enet0", &clk_enet0),
0469 CLKDEV_INIT(NULL, "enet1", &clk_enet1),
0470 CLKDEV_INIT(NULL, "ephy", &clk_ephy),
0471 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
0472 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
0473 CLKDEV_INIT(NULL, "spi", &clk_spi),
0474 CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
0475 };
0476
0477 static struct clk_lookup bcm6348_clks[] = {
0478
0479 CLKDEV_INIT(NULL, "periph", &clk_periph),
0480 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
0481
0482 CLKDEV_INIT(NULL, "enet0", &clk_enet0),
0483 CLKDEV_INIT(NULL, "enet1", &clk_enet1),
0484 CLKDEV_INIT(NULL, "ephy", &clk_ephy),
0485 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
0486 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
0487 CLKDEV_INIT(NULL, "spi", &clk_spi),
0488 CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
0489 CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet_misc),
0490 };
0491
0492 static struct clk_lookup bcm6358_clks[] = {
0493
0494 CLKDEV_INIT(NULL, "periph", &clk_periph),
0495 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
0496 CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
0497
0498 CLKDEV_INIT(NULL, "enet0", &clk_enet0),
0499 CLKDEV_INIT(NULL, "enet1", &clk_enet1),
0500 CLKDEV_INIT(NULL, "ephy", &clk_ephy),
0501 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
0502 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
0503 CLKDEV_INIT(NULL, "spi", &clk_spi),
0504 CLKDEV_INIT(NULL, "pcm", &clk_pcm),
0505 CLKDEV_INIT(NULL, "swpkt_sar", &clk_swpkt_sar),
0506 CLKDEV_INIT(NULL, "swpkt_usb", &clk_swpkt_usb),
0507 CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0),
0508 CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1),
0509 };
0510
0511 static struct clk_lookup bcm6362_clks[] = {
0512
0513 CLKDEV_INIT(NULL, "periph", &clk_periph),
0514 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
0515 CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
0516 CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
0517
0518 CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
0519 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
0520 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
0521 CLKDEV_INIT(NULL, "spi", &clk_spi),
0522 CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
0523 CLKDEV_INIT(NULL, "pcie", &clk_pcie),
0524 CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
0525 };
0526
0527 static struct clk_lookup bcm6368_clks[] = {
0528
0529 CLKDEV_INIT(NULL, "periph", &clk_periph),
0530 CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
0531 CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
0532
0533 CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
0534 CLKDEV_INIT(NULL, "usbh", &clk_usbh),
0535 CLKDEV_INIT(NULL, "usbd", &clk_usbd),
0536 CLKDEV_INIT(NULL, "spi", &clk_spi),
0537 CLKDEV_INIT(NULL, "xtm", &clk_xtm),
0538 CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
0539 };
0540
0541 #define HSSPI_PLL_HZ_6328 133333333
0542 #define HSSPI_PLL_HZ_6362 400000000
0543
0544 static int __init bcm63xx_clk_init(void)
0545 {
0546 switch (bcm63xx_get_cpu_id()) {
0547 case BCM3368_CPU_ID:
0548 clkdev_add_table(bcm3368_clks, ARRAY_SIZE(bcm3368_clks));
0549 break;
0550 case BCM6328_CPU_ID:
0551 clk_hsspi_pll.rate = HSSPI_PLL_HZ_6328;
0552 clkdev_add_table(bcm6328_clks, ARRAY_SIZE(bcm6328_clks));
0553 break;
0554 case BCM6338_CPU_ID:
0555 clkdev_add_table(bcm6338_clks, ARRAY_SIZE(bcm6338_clks));
0556 break;
0557 case BCM6345_CPU_ID:
0558 clkdev_add_table(bcm6345_clks, ARRAY_SIZE(bcm6345_clks));
0559 break;
0560 case BCM6348_CPU_ID:
0561 clkdev_add_table(bcm6348_clks, ARRAY_SIZE(bcm6348_clks));
0562 break;
0563 case BCM6358_CPU_ID:
0564 clkdev_add_table(bcm6358_clks, ARRAY_SIZE(bcm6358_clks));
0565 break;
0566 case BCM6362_CPU_ID:
0567 clk_hsspi_pll.rate = HSSPI_PLL_HZ_6362;
0568 clkdev_add_table(bcm6362_clks, ARRAY_SIZE(bcm6362_clks));
0569 break;
0570 case BCM6368_CPU_ID:
0571 clkdev_add_table(bcm6368_clks, ARRAY_SIZE(bcm6368_clks));
0572 break;
0573 }
0574
0575 return 0;
0576 }
0577 arch_initcall(bcm63xx_clk_init);