Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Broadcom Northstar USB 3.0 PHY Driver
0004  *
0005  * Copyright (C) 2016 Rafał Miłecki <rafal@milecki.pl>
0006  * Copyright (C) 2016 Broadcom
0007  *
0008  * All magic values used for initialization (and related comments) were obtained
0009  * from Broadcom's SDK:
0010  * Copyright (c) Broadcom Corp, 2012
0011  */
0012 
0013 #include <linux/bcma/bcma.h>
0014 #include <linux/delay.h>
0015 #include <linux/err.h>
0016 #include <linux/iopoll.h>
0017 #include <linux/mdio.h>
0018 #include <linux/module.h>
0019 #include <linux/of_address.h>
0020 #include <linux/of_platform.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/phy/phy.h>
0023 #include <linux/slab.h>
0024 
0025 #define BCM_NS_USB3_PHY_BASE_ADDR_REG   0x1f
0026 #define BCM_NS_USB3_PHY_PLL30_BLOCK 0x8000
0027 #define BCM_NS_USB3_PHY_TX_PMD_BLOCK    0x8040
0028 #define BCM_NS_USB3_PHY_PIPE_BLOCK  0x8060
0029 
0030 /* Registers of PLL30 block */
0031 #define BCM_NS_USB3_PLL_CONTROL     0x01
0032 #define BCM_NS_USB3_PLLA_CONTROL0   0x0a
0033 #define BCM_NS_USB3_PLLA_CONTROL1   0x0b
0034 
0035 /* Registers of TX PMD block */
0036 #define BCM_NS_USB3_TX_PMD_CONTROL1 0x01
0037 
0038 /* Registers of PIPE block */
0039 #define BCM_NS_USB3_LFPS_CMP        0x02
0040 #define BCM_NS_USB3_LFPS_DEGLITCH   0x03
0041 
0042 enum bcm_ns_family {
0043     BCM_NS_UNKNOWN,
0044     BCM_NS_AX,
0045     BCM_NS_BX,
0046 };
0047 
0048 struct bcm_ns_usb3 {
0049     struct device *dev;
0050     enum bcm_ns_family family;
0051     void __iomem *dmp;
0052     struct mdio_device *mdiodev;
0053     struct phy *phy;
0054 };
0055 
0056 static const struct of_device_id bcm_ns_usb3_id_table[] = {
0057     {
0058         .compatible = "brcm,ns-ax-usb3-phy",
0059         .data = (int *)BCM_NS_AX,
0060     },
0061     {
0062         .compatible = "brcm,ns-bx-usb3-phy",
0063         .data = (int *)BCM_NS_BX,
0064     },
0065     {},
0066 };
0067 
0068 static int bcm_ns_usb3_mdio_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
0069                       u16 value);
0070 
0071 static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)
0072 {
0073     int err;
0074 
0075     /* USB3 PLL Block */
0076     err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
0077                      BCM_NS_USB3_PHY_PLL30_BLOCK);
0078     if (err < 0)
0079         return err;
0080 
0081     /* Assert Ana_Pllseq start */
0082     bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLL_CONTROL, 0x1000);
0083 
0084     /* Assert CML Divider ratio to 26 */
0085     bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL0, 0x6400);
0086 
0087     /* Asserting PLL Reset */
0088     bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL1, 0xc000);
0089 
0090     /* Deaaserting PLL Reset */
0091     bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL1, 0x8000);
0092 
0093     /* Deasserting USB3 system reset */
0094     writel(0, usb3->dmp + BCMA_RESET_CTL);
0095 
0096     /* PLL frequency monitor enable */
0097     bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLL_CONTROL, 0x9000);
0098 
0099     /* PIPE Block */
0100     bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
0101                    BCM_NS_USB3_PHY_PIPE_BLOCK);
0102 
0103     /* CMPMAX & CMPMINTH setting */
0104     bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_LFPS_CMP, 0xf30d);
0105 
0106     /* DEGLITCH MIN & MAX setting */
0107     bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_LFPS_DEGLITCH, 0x6302);
0108 
0109     /* TXPMD block */
0110     bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
0111                    BCM_NS_USB3_PHY_TX_PMD_BLOCK);
0112 
0113     /* Enabling SSC */
0114     bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003);
0115 
0116     return 0;
0117 }
0118 
0119 static int bcm_ns_usb3_phy_init_ns_ax(struct bcm_ns_usb3 *usb3)
0120 {
0121     int err;
0122 
0123     /* PLL30 block */
0124     err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
0125                      BCM_NS_USB3_PHY_PLL30_BLOCK);
0126     if (err < 0)
0127         return err;
0128 
0129     bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL0, 0x6400);
0130 
0131     bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG, 0x80e0);
0132 
0133     bcm_ns_usb3_mdio_phy_write(usb3, 0x02, 0x009c);
0134 
0135     /* Enable SSC */
0136     bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
0137                    BCM_NS_USB3_PHY_TX_PMD_BLOCK);
0138 
0139     bcm_ns_usb3_mdio_phy_write(usb3, 0x02, 0x21d3);
0140 
0141     bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003);
0142 
0143     /* Deasserting USB3 system reset */
0144     writel(0, usb3->dmp + BCMA_RESET_CTL);
0145 
0146     return 0;
0147 }
0148 
0149 static int bcm_ns_usb3_phy_init(struct phy *phy)
0150 {
0151     struct bcm_ns_usb3 *usb3 = phy_get_drvdata(phy);
0152     int err;
0153 
0154     /* Perform USB3 system soft reset */
0155     writel(BCMA_RESET_CTL_RESET, usb3->dmp + BCMA_RESET_CTL);
0156 
0157     switch (usb3->family) {
0158     case BCM_NS_AX:
0159         err = bcm_ns_usb3_phy_init_ns_ax(usb3);
0160         break;
0161     case BCM_NS_BX:
0162         err = bcm_ns_usb3_phy_init_ns_bx(usb3);
0163         break;
0164     default:
0165         WARN_ON(1);
0166         err = -ENOTSUPP;
0167     }
0168 
0169     return err;
0170 }
0171 
0172 static const struct phy_ops ops = {
0173     .init       = bcm_ns_usb3_phy_init,
0174     .owner      = THIS_MODULE,
0175 };
0176 
0177 /**************************************************
0178  * MDIO driver code
0179  **************************************************/
0180 
0181 static int bcm_ns_usb3_mdio_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
0182                       u16 value)
0183 {
0184     struct mdio_device *mdiodev = usb3->mdiodev;
0185 
0186     return mdiodev_write(mdiodev, reg, value);
0187 }
0188 
0189 static int bcm_ns_usb3_mdio_probe(struct mdio_device *mdiodev)
0190 {
0191     struct device *dev = &mdiodev->dev;
0192     const struct of_device_id *of_id;
0193     struct phy_provider *phy_provider;
0194     struct device_node *syscon_np;
0195     struct bcm_ns_usb3 *usb3;
0196     struct resource res;
0197     int err;
0198 
0199     usb3 = devm_kzalloc(dev, sizeof(*usb3), GFP_KERNEL);
0200     if (!usb3)
0201         return -ENOMEM;
0202 
0203     usb3->dev = dev;
0204     usb3->mdiodev = mdiodev;
0205 
0206     of_id = of_match_device(bcm_ns_usb3_id_table, dev);
0207     if (!of_id)
0208         return -EINVAL;
0209     usb3->family = (enum bcm_ns_family)of_id->data;
0210 
0211     syscon_np = of_parse_phandle(dev->of_node, "usb3-dmp-syscon", 0);
0212     err = of_address_to_resource(syscon_np, 0, &res);
0213     of_node_put(syscon_np);
0214     if (err)
0215         return err;
0216 
0217     usb3->dmp = devm_ioremap_resource(dev, &res);
0218     if (IS_ERR(usb3->dmp))
0219         return PTR_ERR(usb3->dmp);
0220 
0221     usb3->phy = devm_phy_create(dev, NULL, &ops);
0222     if (IS_ERR(usb3->phy)) {
0223         dev_err(dev, "Failed to create PHY\n");
0224         return PTR_ERR(usb3->phy);
0225     }
0226 
0227     phy_set_drvdata(usb3->phy, usb3);
0228 
0229     phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
0230 
0231     return PTR_ERR_OR_ZERO(phy_provider);
0232 }
0233 
0234 static struct mdio_driver bcm_ns_usb3_mdio_driver = {
0235     .mdiodrv = {
0236         .driver = {
0237             .name = "bcm_ns_mdio_usb3",
0238             .of_match_table = bcm_ns_usb3_id_table,
0239         },
0240     },
0241     .probe = bcm_ns_usb3_mdio_probe,
0242 };
0243 
0244 mdio_module_driver(bcm_ns_usb3_mdio_driver);
0245 
0246 MODULE_LICENSE("GPL v2");
0247 MODULE_DEVICE_TABLE(of, bcm_ns_usb3_id_table);