Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
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         /* sentinel */
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         /* sentinel */
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         /* sentinel */
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         /* sentinel */
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         /* sentinel */
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         /* sentinel */
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         /* sentinel */
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         /* sentinel */
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);