0001
0002
0003 #include <linux/clk-provider.h>
0004 #include <linux/init.h>
0005 #include <linux/of.h>
0006 #include <linux/of_device.h>
0007 #include <linux/platform_device.h>
0008
0009 #include <dt-bindings/clock/bcm3368-clock.h>
0010 #include <dt-bindings/clock/bcm6318-clock.h>
0011 #include <dt-bindings/clock/bcm6328-clock.h>
0012 #include <dt-bindings/clock/bcm6358-clock.h>
0013 #include <dt-bindings/clock/bcm6362-clock.h>
0014 #include <dt-bindings/clock/bcm6368-clock.h>
0015 #include <dt-bindings/clock/bcm63268-clock.h>
0016
0017 struct clk_bcm63xx_table_entry {
0018 const char * const name;
0019 u8 bit;
0020 unsigned long flags;
0021 };
0022
0023 struct clk_bcm63xx_hw {
0024 void __iomem *regs;
0025 spinlock_t lock;
0026
0027 struct clk_hw_onecell_data data;
0028 };
0029
0030 static const struct clk_bcm63xx_table_entry bcm3368_clocks[] = {
0031 {
0032 .name = "mac",
0033 .bit = BCM3368_CLK_MAC,
0034 }, {
0035 .name = "tc",
0036 .bit = BCM3368_CLK_TC,
0037 }, {
0038 .name = "us_top",
0039 .bit = BCM3368_CLK_US_TOP,
0040 }, {
0041 .name = "ds_top",
0042 .bit = BCM3368_CLK_DS_TOP,
0043 }, {
0044 .name = "acm",
0045 .bit = BCM3368_CLK_ACM,
0046 }, {
0047 .name = "spi",
0048 .bit = BCM3368_CLK_SPI,
0049 }, {
0050 .name = "usbs",
0051 .bit = BCM3368_CLK_USBS,
0052 }, {
0053 .name = "bmu",
0054 .bit = BCM3368_CLK_BMU,
0055 }, {
0056 .name = "pcm",
0057 .bit = BCM3368_CLK_PCM,
0058 }, {
0059 .name = "ntp",
0060 .bit = BCM3368_CLK_NTP,
0061 }, {
0062 .name = "acp_b",
0063 .bit = BCM3368_CLK_ACP_B,
0064 }, {
0065 .name = "acp_a",
0066 .bit = BCM3368_CLK_ACP_A,
0067 }, {
0068 .name = "emusb",
0069 .bit = BCM3368_CLK_EMUSB,
0070 }, {
0071 .name = "enet0",
0072 .bit = BCM3368_CLK_ENET0,
0073 }, {
0074 .name = "enet1",
0075 .bit = BCM3368_CLK_ENET1,
0076 }, {
0077 .name = "usbsu",
0078 .bit = BCM3368_CLK_USBSU,
0079 }, {
0080 .name = "ephy",
0081 .bit = BCM3368_CLK_EPHY,
0082 }, {
0083
0084 },
0085 };
0086
0087 static const struct clk_bcm63xx_table_entry bcm6318_clocks[] = {
0088 {
0089 .name = "adsl_asb",
0090 .bit = BCM6318_CLK_ADSL_ASB,
0091 }, {
0092 .name = "usb_asb",
0093 .bit = BCM6318_CLK_USB_ASB,
0094 }, {
0095 .name = "mips_asb",
0096 .bit = BCM6318_CLK_MIPS_ASB,
0097 }, {
0098 .name = "pcie_asb",
0099 .bit = BCM6318_CLK_PCIE_ASB,
0100 }, {
0101 .name = "phymips_asb",
0102 .bit = BCM6318_CLK_PHYMIPS_ASB,
0103 }, {
0104 .name = "robosw_asb",
0105 .bit = BCM6318_CLK_ROBOSW_ASB,
0106 }, {
0107 .name = "sar_asb",
0108 .bit = BCM6318_CLK_SAR_ASB,
0109 }, {
0110 .name = "sdr_asb",
0111 .bit = BCM6318_CLK_SDR_ASB,
0112 }, {
0113 .name = "swreg_asb",
0114 .bit = BCM6318_CLK_SWREG_ASB,
0115 }, {
0116 .name = "periph_asb",
0117 .bit = BCM6318_CLK_PERIPH_ASB,
0118 }, {
0119 .name = "cpubus160",
0120 .bit = BCM6318_CLK_CPUBUS160,
0121 }, {
0122 .name = "adsl",
0123 .bit = BCM6318_CLK_ADSL,
0124 }, {
0125 .name = "sar125",
0126 .bit = BCM6318_CLK_SAR125,
0127 }, {
0128 .name = "mips",
0129 .bit = BCM6318_CLK_MIPS,
0130 .flags = CLK_IS_CRITICAL,
0131 }, {
0132 .name = "pcie",
0133 .bit = BCM6318_CLK_PCIE,
0134 }, {
0135 .name = "robosw250",
0136 .bit = BCM6318_CLK_ROBOSW250,
0137 }, {
0138 .name = "robosw025",
0139 .bit = BCM6318_CLK_ROBOSW025,
0140 }, {
0141 .name = "sdr",
0142 .bit = BCM6318_CLK_SDR,
0143 .flags = CLK_IS_CRITICAL,
0144 }, {
0145 .name = "usbd",
0146 .bit = BCM6318_CLK_USBD,
0147 }, {
0148 .name = "hsspi",
0149 .bit = BCM6318_CLK_HSSPI,
0150 }, {
0151 .name = "pcie25",
0152 .bit = BCM6318_CLK_PCIE25,
0153 }, {
0154 .name = "phymips",
0155 .bit = BCM6318_CLK_PHYMIPS,
0156 }, {
0157 .name = "afe",
0158 .bit = BCM6318_CLK_AFE,
0159 }, {
0160 .name = "qproc",
0161 .bit = BCM6318_CLK_QPROC,
0162 }, {
0163
0164 },
0165 };
0166
0167 static const struct clk_bcm63xx_table_entry bcm6318_ubus_clocks[] = {
0168 {
0169 .name = "adsl-ubus",
0170 .bit = BCM6318_UCLK_ADSL,
0171 }, {
0172 .name = "arb-ubus",
0173 .bit = BCM6318_UCLK_ARB,
0174 .flags = CLK_IS_CRITICAL,
0175 }, {
0176 .name = "mips-ubus",
0177 .bit = BCM6318_UCLK_MIPS,
0178 .flags = CLK_IS_CRITICAL,
0179 }, {
0180 .name = "pcie-ubus",
0181 .bit = BCM6318_UCLK_PCIE,
0182 }, {
0183 .name = "periph-ubus",
0184 .bit = BCM6318_UCLK_PERIPH,
0185 .flags = CLK_IS_CRITICAL,
0186 }, {
0187 .name = "phymips-ubus",
0188 .bit = BCM6318_UCLK_PHYMIPS,
0189 }, {
0190 .name = "robosw-ubus",
0191 .bit = BCM6318_UCLK_ROBOSW,
0192 }, {
0193 .name = "sar-ubus",
0194 .bit = BCM6318_UCLK_SAR,
0195 }, {
0196 .name = "sdr-ubus",
0197 .bit = BCM6318_UCLK_SDR,
0198 }, {
0199 .name = "usb-ubus",
0200 .bit = BCM6318_UCLK_USB,
0201 }, {
0202
0203 },
0204 };
0205
0206 static const struct clk_bcm63xx_table_entry bcm6328_clocks[] = {
0207 {
0208 .name = "phy_mips",
0209 .bit = BCM6328_CLK_PHYMIPS,
0210 }, {
0211 .name = "adsl_qproc",
0212 .bit = BCM6328_CLK_ADSL_QPROC,
0213 }, {
0214 .name = "adsl_afe",
0215 .bit = BCM6328_CLK_ADSL_AFE,
0216 }, {
0217 .name = "adsl",
0218 .bit = BCM6328_CLK_ADSL,
0219 }, {
0220 .name = "mips",
0221 .bit = BCM6328_CLK_MIPS,
0222 .flags = CLK_IS_CRITICAL,
0223 }, {
0224 .name = "sar",
0225 .bit = BCM6328_CLK_SAR,
0226 }, {
0227 .name = "pcm",
0228 .bit = BCM6328_CLK_PCM,
0229 }, {
0230 .name = "usbd",
0231 .bit = BCM6328_CLK_USBD,
0232 }, {
0233 .name = "usbh",
0234 .bit = BCM6328_CLK_USBH,
0235 }, {
0236 .name = "hsspi",
0237 .bit = BCM6328_CLK_HSSPI,
0238 }, {
0239 .name = "pcie",
0240 .bit = BCM6328_CLK_PCIE,
0241 }, {
0242 .name = "robosw",
0243 .bit = BCM6328_CLK_ROBOSW,
0244 }, {
0245
0246 },
0247 };
0248
0249 static const struct clk_bcm63xx_table_entry bcm6358_clocks[] = {
0250 {
0251 .name = "enet",
0252 .bit = BCM6358_CLK_ENET,
0253 }, {
0254 .name = "adslphy",
0255 .bit = BCM6358_CLK_ADSLPHY,
0256 }, {
0257 .name = "pcm",
0258 .bit = BCM6358_CLK_PCM,
0259 }, {
0260 .name = "spi",
0261 .bit = BCM6358_CLK_SPI,
0262 }, {
0263 .name = "usbs",
0264 .bit = BCM6358_CLK_USBS,
0265 }, {
0266 .name = "sar",
0267 .bit = BCM6358_CLK_SAR,
0268 }, {
0269 .name = "emusb",
0270 .bit = BCM6358_CLK_EMUSB,
0271 }, {
0272 .name = "enet0",
0273 .bit = BCM6358_CLK_ENET0,
0274 }, {
0275 .name = "enet1",
0276 .bit = BCM6358_CLK_ENET1,
0277 }, {
0278 .name = "usbsu",
0279 .bit = BCM6358_CLK_USBSU,
0280 }, {
0281 .name = "ephy",
0282 .bit = BCM6358_CLK_EPHY,
0283 }, {
0284
0285 },
0286 };
0287
0288 static const struct clk_bcm63xx_table_entry bcm6362_clocks[] = {
0289 {
0290 .name = "adsl_qproc",
0291 .bit = BCM6362_CLK_ADSL_QPROC,
0292 }, {
0293 .name = "adsl_afe",
0294 .bit = BCM6362_CLK_ADSL_AFE,
0295 }, {
0296 .name = "adsl",
0297 .bit = BCM6362_CLK_ADSL,
0298 }, {
0299 .name = "mips",
0300 .bit = BCM6362_CLK_MIPS,
0301 .flags = CLK_IS_CRITICAL,
0302 }, {
0303 .name = "wlan_ocp",
0304 .bit = BCM6362_CLK_WLAN_OCP,
0305 }, {
0306 .name = "swpkt_usb",
0307 .bit = BCM6362_CLK_SWPKT_USB,
0308 }, {
0309 .name = "swpkt_sar",
0310 .bit = BCM6362_CLK_SWPKT_SAR,
0311 }, {
0312 .name = "sar",
0313 .bit = BCM6362_CLK_SAR,
0314 }, {
0315 .name = "robosw",
0316 .bit = BCM6362_CLK_ROBOSW,
0317 }, {
0318 .name = "pcm",
0319 .bit = BCM6362_CLK_PCM,
0320 }, {
0321 .name = "usbd",
0322 .bit = BCM6362_CLK_USBD,
0323 }, {
0324 .name = "usbh",
0325 .bit = BCM6362_CLK_USBH,
0326 }, {
0327 .name = "ipsec",
0328 .bit = BCM6362_CLK_IPSEC,
0329 }, {
0330 .name = "spi",
0331 .bit = BCM6362_CLK_SPI,
0332 }, {
0333 .name = "hsspi",
0334 .bit = BCM6362_CLK_HSSPI,
0335 }, {
0336 .name = "pcie",
0337 .bit = BCM6362_CLK_PCIE,
0338 }, {
0339 .name = "fap",
0340 .bit = BCM6362_CLK_FAP,
0341 }, {
0342 .name = "phymips",
0343 .bit = BCM6362_CLK_PHYMIPS,
0344 }, {
0345 .name = "nand",
0346 .bit = BCM6362_CLK_NAND,
0347 }, {
0348
0349 },
0350 };
0351
0352 static const struct clk_bcm63xx_table_entry bcm6368_clocks[] = {
0353 {
0354 .name = "vdsl_qproc",
0355 .bit = BCM6368_CLK_VDSL_QPROC,
0356 }, {
0357 .name = "vdsl_afe",
0358 .bit = BCM6368_CLK_VDSL_AFE,
0359 }, {
0360 .name = "vdsl_bonding",
0361 .bit = BCM6368_CLK_VDSL_BONDING,
0362 }, {
0363 .name = "vdsl",
0364 .bit = BCM6368_CLK_VDSL,
0365 }, {
0366 .name = "phymips",
0367 .bit = BCM6368_CLK_PHYMIPS,
0368 }, {
0369 .name = "swpkt_usb",
0370 .bit = BCM6368_CLK_SWPKT_USB,
0371 }, {
0372 .name = "swpkt_sar",
0373 .bit = BCM6368_CLK_SWPKT_SAR,
0374 }, {
0375 .name = "spi",
0376 .bit = BCM6368_CLK_SPI,
0377 }, {
0378 .name = "usbd",
0379 .bit = BCM6368_CLK_USBD,
0380 }, {
0381 .name = "sar",
0382 .bit = BCM6368_CLK_SAR,
0383 }, {
0384 .name = "robosw",
0385 .bit = BCM6368_CLK_ROBOSW,
0386 }, {
0387 .name = "utopia",
0388 .bit = BCM6368_CLK_UTOPIA,
0389 }, {
0390 .name = "pcm",
0391 .bit = BCM6368_CLK_PCM,
0392 }, {
0393 .name = "usbh",
0394 .bit = BCM6368_CLK_USBH,
0395 }, {
0396 .name = "disable_gless",
0397 .bit = BCM6368_CLK_DIS_GLESS,
0398 }, {
0399 .name = "nand",
0400 .bit = BCM6368_CLK_NAND,
0401 }, {
0402 .name = "ipsec",
0403 .bit = BCM6368_CLK_IPSEC,
0404 }, {
0405
0406 },
0407 };
0408
0409 static const struct clk_bcm63xx_table_entry bcm63268_clocks[] = {
0410 {
0411 .name = "disable_gless",
0412 .bit = BCM63268_CLK_DIS_GLESS,
0413 }, {
0414 .name = "vdsl_qproc",
0415 .bit = BCM63268_CLK_VDSL_QPROC,
0416 }, {
0417 .name = "vdsl_afe",
0418 .bit = BCM63268_CLK_VDSL_AFE,
0419 }, {
0420 .name = "vdsl",
0421 .bit = BCM63268_CLK_VDSL,
0422 }, {
0423 .name = "mips",
0424 .bit = BCM63268_CLK_MIPS,
0425 .flags = CLK_IS_CRITICAL,
0426 }, {
0427 .name = "wlan_ocp",
0428 .bit = BCM63268_CLK_WLAN_OCP,
0429 }, {
0430 .name = "dect",
0431 .bit = BCM63268_CLK_DECT,
0432 }, {
0433 .name = "fap0",
0434 .bit = BCM63268_CLK_FAP0,
0435 }, {
0436 .name = "fap1",
0437 .bit = BCM63268_CLK_FAP1,
0438 }, {
0439 .name = "sar",
0440 .bit = BCM63268_CLK_SAR,
0441 }, {
0442 .name = "robosw",
0443 .bit = BCM63268_CLK_ROBOSW,
0444 }, {
0445 .name = "pcm",
0446 .bit = BCM63268_CLK_PCM,
0447 }, {
0448 .name = "usbd",
0449 .bit = BCM63268_CLK_USBD,
0450 }, {
0451 .name = "usbh",
0452 .bit = BCM63268_CLK_USBH,
0453 }, {
0454 .name = "ipsec",
0455 .bit = BCM63268_CLK_IPSEC,
0456 }, {
0457 .name = "spi",
0458 .bit = BCM63268_CLK_SPI,
0459 }, {
0460 .name = "hsspi",
0461 .bit = BCM63268_CLK_HSSPI,
0462 }, {
0463 .name = "pcie",
0464 .bit = BCM63268_CLK_PCIE,
0465 }, {
0466 .name = "phymips",
0467 .bit = BCM63268_CLK_PHYMIPS,
0468 }, {
0469 .name = "gmac",
0470 .bit = BCM63268_CLK_GMAC,
0471 }, {
0472 .name = "nand",
0473 .bit = BCM63268_CLK_NAND,
0474 }, {
0475 .name = "tbus",
0476 .bit = BCM63268_CLK_TBUS,
0477 }, {
0478 .name = "robosw250",
0479 .bit = BCM63268_CLK_ROBOSW250,
0480 }, {
0481
0482 },
0483 };
0484
0485 static int clk_bcm63xx_probe(struct platform_device *pdev)
0486 {
0487 const struct clk_bcm63xx_table_entry *entry, *table;
0488 struct clk_bcm63xx_hw *hw;
0489 u8 maxbit = 0;
0490 int i, ret;
0491
0492 table = of_device_get_match_data(&pdev->dev);
0493 if (!table)
0494 return -EINVAL;
0495
0496 for (entry = table; entry->name; entry++)
0497 maxbit = max_t(u8, maxbit, entry->bit);
0498 maxbit++;
0499
0500 hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit),
0501 GFP_KERNEL);
0502 if (!hw)
0503 return -ENOMEM;
0504
0505 platform_set_drvdata(pdev, hw);
0506
0507 spin_lock_init(&hw->lock);
0508
0509 hw->data.num = maxbit;
0510 for (i = 0; i < maxbit; i++)
0511 hw->data.hws[i] = ERR_PTR(-ENODEV);
0512
0513 hw->regs = devm_platform_ioremap_resource(pdev, 0);
0514 if (IS_ERR(hw->regs))
0515 return PTR_ERR(hw->regs);
0516
0517 for (entry = table; entry->name; entry++) {
0518 struct clk_hw *clk;
0519
0520 clk = clk_hw_register_gate(&pdev->dev, entry->name, NULL,
0521 entry->flags, hw->regs, entry->bit,
0522 CLK_GATE_BIG_ENDIAN, &hw->lock);
0523 if (IS_ERR(clk)) {
0524 ret = PTR_ERR(clk);
0525 goto out_err;
0526 }
0527
0528 hw->data.hws[entry->bit] = clk;
0529 }
0530
0531 ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get,
0532 &hw->data);
0533 if (!ret)
0534 return 0;
0535 out_err:
0536 for (i = 0; i < hw->data.num; i++) {
0537 if (!IS_ERR(hw->data.hws[i]))
0538 clk_hw_unregister_gate(hw->data.hws[i]);
0539 }
0540
0541 return ret;
0542 }
0543
0544 static int clk_bcm63xx_remove(struct platform_device *pdev)
0545 {
0546 struct clk_bcm63xx_hw *hw = platform_get_drvdata(pdev);
0547 int i;
0548
0549 of_clk_del_provider(pdev->dev.of_node);
0550
0551 for (i = 0; i < hw->data.num; i++) {
0552 if (!IS_ERR(hw->data.hws[i]))
0553 clk_hw_unregister_gate(hw->data.hws[i]);
0554 }
0555
0556 return 0;
0557 }
0558
0559 static const struct of_device_id clk_bcm63xx_dt_ids[] = {
0560 { .compatible = "brcm,bcm3368-clocks", .data = &bcm3368_clocks, },
0561 { .compatible = "brcm,bcm6318-clocks", .data = &bcm6318_clocks, },
0562 { .compatible = "brcm,bcm6318-ubus-clocks", .data = &bcm6318_ubus_clocks, },
0563 { .compatible = "brcm,bcm6328-clocks", .data = &bcm6328_clocks, },
0564 { .compatible = "brcm,bcm6358-clocks", .data = &bcm6358_clocks, },
0565 { .compatible = "brcm,bcm6362-clocks", .data = &bcm6362_clocks, },
0566 { .compatible = "brcm,bcm6368-clocks", .data = &bcm6368_clocks, },
0567 { .compatible = "brcm,bcm63268-clocks", .data = &bcm63268_clocks, },
0568 { }
0569 };
0570
0571 static struct platform_driver clk_bcm63xx = {
0572 .probe = clk_bcm63xx_probe,
0573 .remove = clk_bcm63xx_remove,
0574 .driver = {
0575 .name = "bcm63xx-clock",
0576 .of_match_table = clk_bcm63xx_dt_ids,
0577 },
0578 };
0579 builtin_platform_driver(clk_bcm63xx);