Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Renesas R-Car Gen2 PHY driver
0004  *
0005  * Copyright (C) 2014 Renesas Solutions Corp.
0006  * Copyright (C) 2014 Cogent Embedded, Inc.
0007  * Copyright (C) 2019 Renesas Electronics Corp.
0008  */
0009 
0010 #include <linux/clk.h>
0011 #include <linux/delay.h>
0012 #include <linux/io.h>
0013 #include <linux/module.h>
0014 #include <linux/of.h>
0015 #include <linux/phy/phy.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/spinlock.h>
0018 #include <linux/atomic.h>
0019 #include <linux/of_device.h>
0020 
0021 #define USBHS_LPSTS         0x02
0022 #define USBHS_UGCTRL            0x80
0023 #define USBHS_UGCTRL2           0x84
0024 #define USBHS_UGSTS         0x88    /* From technical update */
0025 
0026 /* Low Power Status register (LPSTS) */
0027 #define USBHS_LPSTS_SUSPM       0x4000
0028 
0029 /* USB General control register (UGCTRL) */
0030 #define USBHS_UGCTRL_CONNECT        0x00000004
0031 #define USBHS_UGCTRL_PLLRESET       0x00000001
0032 
0033 /* USB General control register 2 (UGCTRL2) */
0034 #define USBHS_UGCTRL2_USB2SEL       0x80000000
0035 #define USBHS_UGCTRL2_USB2SEL_PCI   0x00000000
0036 #define USBHS_UGCTRL2_USB2SEL_USB30 0x80000000
0037 #define USBHS_UGCTRL2_USB0SEL       0x00000030
0038 #define USBHS_UGCTRL2_USB0SEL_PCI   0x00000010
0039 #define USBHS_UGCTRL2_USB0SEL_HS_USB    0x00000030
0040 #define USBHS_UGCTRL2_USB0SEL_USB20 0x00000010
0041 #define USBHS_UGCTRL2_USB0SEL_HS_USB20  0x00000020
0042 
0043 /* USB General status register (UGSTS) */
0044 #define USBHS_UGSTS_LOCK        0x00000100 /* From technical update */
0045 
0046 #define PHYS_PER_CHANNEL    2
0047 
0048 struct rcar_gen2_phy {
0049     struct phy *phy;
0050     struct rcar_gen2_channel *channel;
0051     int number;
0052     u32 select_value;
0053 };
0054 
0055 struct rcar_gen2_channel {
0056     struct device_node *of_node;
0057     struct rcar_gen2_phy_driver *drv;
0058     struct rcar_gen2_phy phys[PHYS_PER_CHANNEL];
0059     int selected_phy;
0060     u32 select_mask;
0061 };
0062 
0063 struct rcar_gen2_phy_driver {
0064     void __iomem *base;
0065     struct clk *clk;
0066     spinlock_t lock;
0067     int num_channels;
0068     struct rcar_gen2_channel *channels;
0069 };
0070 
0071 struct rcar_gen2_phy_data {
0072     const struct phy_ops *gen2_phy_ops;
0073     const u32 (*select_value)[PHYS_PER_CHANNEL];
0074     const u32 num_channels;
0075 };
0076 
0077 static int rcar_gen2_phy_init(struct phy *p)
0078 {
0079     struct rcar_gen2_phy *phy = phy_get_drvdata(p);
0080     struct rcar_gen2_channel *channel = phy->channel;
0081     struct rcar_gen2_phy_driver *drv = channel->drv;
0082     unsigned long flags;
0083     u32 ugctrl2;
0084 
0085     /*
0086      * Try to acquire exclusive access to PHY.  The first driver calling
0087      * phy_init()  on a given channel wins, and all attempts  to use another
0088      * PHY on this channel will fail until phy_exit() is called by the first
0089      * driver.   Achieving this with cmpxcgh() should be SMP-safe.
0090      */
0091     if (cmpxchg(&channel->selected_phy, -1, phy->number) != -1)
0092         return -EBUSY;
0093 
0094     clk_prepare_enable(drv->clk);
0095 
0096     spin_lock_irqsave(&drv->lock, flags);
0097     ugctrl2 = readl(drv->base + USBHS_UGCTRL2);
0098     ugctrl2 &= ~channel->select_mask;
0099     ugctrl2 |= phy->select_value;
0100     writel(ugctrl2, drv->base + USBHS_UGCTRL2);
0101     spin_unlock_irqrestore(&drv->lock, flags);
0102     return 0;
0103 }
0104 
0105 static int rcar_gen2_phy_exit(struct phy *p)
0106 {
0107     struct rcar_gen2_phy *phy = phy_get_drvdata(p);
0108     struct rcar_gen2_channel *channel = phy->channel;
0109 
0110     clk_disable_unprepare(channel->drv->clk);
0111 
0112     channel->selected_phy = -1;
0113 
0114     return 0;
0115 }
0116 
0117 static int rcar_gen2_phy_power_on(struct phy *p)
0118 {
0119     struct rcar_gen2_phy *phy = phy_get_drvdata(p);
0120     struct rcar_gen2_phy_driver *drv = phy->channel->drv;
0121     void __iomem *base = drv->base;
0122     unsigned long flags;
0123     u32 value;
0124     int err = 0, i;
0125 
0126     /* Skip if it's not USBHS */
0127     if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB)
0128         return 0;
0129 
0130     spin_lock_irqsave(&drv->lock, flags);
0131 
0132     /* Power on USBHS PHY */
0133     value = readl(base + USBHS_UGCTRL);
0134     value &= ~USBHS_UGCTRL_PLLRESET;
0135     writel(value, base + USBHS_UGCTRL);
0136 
0137     value = readw(base + USBHS_LPSTS);
0138     value |= USBHS_LPSTS_SUSPM;
0139     writew(value, base + USBHS_LPSTS);
0140 
0141     for (i = 0; i < 20; i++) {
0142         value = readl(base + USBHS_UGSTS);
0143         if ((value & USBHS_UGSTS_LOCK) == USBHS_UGSTS_LOCK) {
0144             value = readl(base + USBHS_UGCTRL);
0145             value |= USBHS_UGCTRL_CONNECT;
0146             writel(value, base + USBHS_UGCTRL);
0147             goto out;
0148         }
0149         udelay(1);
0150     }
0151 
0152     /* Timed out waiting for the PLL lock */
0153     err = -ETIMEDOUT;
0154 
0155 out:
0156     spin_unlock_irqrestore(&drv->lock, flags);
0157 
0158     return err;
0159 }
0160 
0161 static int rcar_gen2_phy_power_off(struct phy *p)
0162 {
0163     struct rcar_gen2_phy *phy = phy_get_drvdata(p);
0164     struct rcar_gen2_phy_driver *drv = phy->channel->drv;
0165     void __iomem *base = drv->base;
0166     unsigned long flags;
0167     u32 value;
0168 
0169     /* Skip if it's not USBHS */
0170     if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB)
0171         return 0;
0172 
0173     spin_lock_irqsave(&drv->lock, flags);
0174 
0175     /* Power off USBHS PHY */
0176     value = readl(base + USBHS_UGCTRL);
0177     value &= ~USBHS_UGCTRL_CONNECT;
0178     writel(value, base + USBHS_UGCTRL);
0179 
0180     value = readw(base + USBHS_LPSTS);
0181     value &= ~USBHS_LPSTS_SUSPM;
0182     writew(value, base + USBHS_LPSTS);
0183 
0184     value = readl(base + USBHS_UGCTRL);
0185     value |= USBHS_UGCTRL_PLLRESET;
0186     writel(value, base + USBHS_UGCTRL);
0187 
0188     spin_unlock_irqrestore(&drv->lock, flags);
0189 
0190     return 0;
0191 }
0192 
0193 static int rz_g1c_phy_power_on(struct phy *p)
0194 {
0195     struct rcar_gen2_phy *phy = phy_get_drvdata(p);
0196     struct rcar_gen2_phy_driver *drv = phy->channel->drv;
0197     void __iomem *base = drv->base;
0198     unsigned long flags;
0199     u32 value;
0200 
0201     spin_lock_irqsave(&drv->lock, flags);
0202 
0203     /* Power on USBHS PHY */
0204     value = readl(base + USBHS_UGCTRL);
0205     value &= ~USBHS_UGCTRL_PLLRESET;
0206     writel(value, base + USBHS_UGCTRL);
0207 
0208     /* As per the data sheet wait 340 micro sec for power stable */
0209     udelay(340);
0210 
0211     if (phy->select_value == USBHS_UGCTRL2_USB0SEL_HS_USB20) {
0212         value = readw(base + USBHS_LPSTS);
0213         value |= USBHS_LPSTS_SUSPM;
0214         writew(value, base + USBHS_LPSTS);
0215     }
0216 
0217     spin_unlock_irqrestore(&drv->lock, flags);
0218 
0219     return 0;
0220 }
0221 
0222 static int rz_g1c_phy_power_off(struct phy *p)
0223 {
0224     struct rcar_gen2_phy *phy = phy_get_drvdata(p);
0225     struct rcar_gen2_phy_driver *drv = phy->channel->drv;
0226     void __iomem *base = drv->base;
0227     unsigned long flags;
0228     u32 value;
0229 
0230     spin_lock_irqsave(&drv->lock, flags);
0231     /* Power off USBHS PHY */
0232     if (phy->select_value == USBHS_UGCTRL2_USB0SEL_HS_USB20) {
0233         value = readw(base + USBHS_LPSTS);
0234         value &= ~USBHS_LPSTS_SUSPM;
0235         writew(value, base + USBHS_LPSTS);
0236     }
0237 
0238     value = readl(base + USBHS_UGCTRL);
0239     value |= USBHS_UGCTRL_PLLRESET;
0240     writel(value, base + USBHS_UGCTRL);
0241 
0242     spin_unlock_irqrestore(&drv->lock, flags);
0243 
0244     return 0;
0245 }
0246 
0247 static const struct phy_ops rcar_gen2_phy_ops = {
0248     .init       = rcar_gen2_phy_init,
0249     .exit       = rcar_gen2_phy_exit,
0250     .power_on   = rcar_gen2_phy_power_on,
0251     .power_off  = rcar_gen2_phy_power_off,
0252     .owner      = THIS_MODULE,
0253 };
0254 
0255 static const struct phy_ops rz_g1c_phy_ops = {
0256     .init       = rcar_gen2_phy_init,
0257     .exit       = rcar_gen2_phy_exit,
0258     .power_on   = rz_g1c_phy_power_on,
0259     .power_off  = rz_g1c_phy_power_off,
0260     .owner      = THIS_MODULE,
0261 };
0262 
0263 static const u32 pci_select_value[][PHYS_PER_CHANNEL] = {
0264     [0] = { USBHS_UGCTRL2_USB0SEL_PCI, USBHS_UGCTRL2_USB0SEL_HS_USB },
0265     [2] = { USBHS_UGCTRL2_USB2SEL_PCI, USBHS_UGCTRL2_USB2SEL_USB30 },
0266 };
0267 
0268 static const u32 usb20_select_value[][PHYS_PER_CHANNEL] = {
0269     { USBHS_UGCTRL2_USB0SEL_USB20, USBHS_UGCTRL2_USB0SEL_HS_USB20 },
0270 };
0271 
0272 static const struct rcar_gen2_phy_data rcar_gen2_usb_phy_data = {
0273     .gen2_phy_ops = &rcar_gen2_phy_ops,
0274     .select_value = pci_select_value,
0275     .num_channels = ARRAY_SIZE(pci_select_value),
0276 };
0277 
0278 static const struct rcar_gen2_phy_data rz_g1c_usb_phy_data = {
0279     .gen2_phy_ops = &rz_g1c_phy_ops,
0280     .select_value = usb20_select_value,
0281     .num_channels = ARRAY_SIZE(usb20_select_value),
0282 };
0283 
0284 static const struct of_device_id rcar_gen2_phy_match_table[] = {
0285     {
0286         .compatible = "renesas,usb-phy-r8a77470",
0287         .data = &rz_g1c_usb_phy_data,
0288     },
0289     {
0290         .compatible = "renesas,usb-phy-r8a7790",
0291         .data = &rcar_gen2_usb_phy_data,
0292     },
0293     {
0294         .compatible = "renesas,usb-phy-r8a7791",
0295         .data = &rcar_gen2_usb_phy_data,
0296     },
0297     {
0298         .compatible = "renesas,usb-phy-r8a7794",
0299         .data = &rcar_gen2_usb_phy_data,
0300     },
0301     {
0302         .compatible = "renesas,rcar-gen2-usb-phy",
0303         .data = &rcar_gen2_usb_phy_data,
0304     },
0305     { /* sentinel */ },
0306 };
0307 MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table);
0308 
0309 static struct phy *rcar_gen2_phy_xlate(struct device *dev,
0310                        struct of_phandle_args *args)
0311 {
0312     struct rcar_gen2_phy_driver *drv;
0313     struct device_node *np = args->np;
0314     int i;
0315 
0316     drv = dev_get_drvdata(dev);
0317     if (!drv)
0318         return ERR_PTR(-EINVAL);
0319 
0320     for (i = 0; i < drv->num_channels; i++) {
0321         if (np == drv->channels[i].of_node)
0322             break;
0323     }
0324 
0325     if (i >= drv->num_channels || args->args[0] >= 2)
0326         return ERR_PTR(-ENODEV);
0327 
0328     return drv->channels[i].phys[args->args[0]].phy;
0329 }
0330 
0331 static const u32 select_mask[] = {
0332     [0] = USBHS_UGCTRL2_USB0SEL,
0333     [2] = USBHS_UGCTRL2_USB2SEL,
0334 };
0335 
0336 static int rcar_gen2_phy_probe(struct platform_device *pdev)
0337 {
0338     struct device *dev = &pdev->dev;
0339     struct rcar_gen2_phy_driver *drv;
0340     struct phy_provider *provider;
0341     struct device_node *np;
0342     void __iomem *base;
0343     struct clk *clk;
0344     const struct rcar_gen2_phy_data *data;
0345     int i = 0;
0346 
0347     if (!dev->of_node) {
0348         dev_err(dev,
0349             "This driver is required to be instantiated from device tree\n");
0350         return -EINVAL;
0351     }
0352 
0353     clk = devm_clk_get(dev, "usbhs");
0354     if (IS_ERR(clk)) {
0355         dev_err(dev, "Can't get USBHS clock\n");
0356         return PTR_ERR(clk);
0357     }
0358 
0359     base = devm_platform_ioremap_resource(pdev, 0);
0360     if (IS_ERR(base))
0361         return PTR_ERR(base);
0362 
0363     drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
0364     if (!drv)
0365         return -ENOMEM;
0366 
0367     spin_lock_init(&drv->lock);
0368 
0369     drv->clk = clk;
0370     drv->base = base;
0371 
0372     data = of_device_get_match_data(dev);
0373     if (!data)
0374         return -EINVAL;
0375 
0376     drv->num_channels = of_get_child_count(dev->of_node);
0377     drv->channels = devm_kcalloc(dev, drv->num_channels,
0378                      sizeof(struct rcar_gen2_channel),
0379                      GFP_KERNEL);
0380     if (!drv->channels)
0381         return -ENOMEM;
0382 
0383     for_each_child_of_node(dev->of_node, np) {
0384         struct rcar_gen2_channel *channel = drv->channels + i;
0385         u32 channel_num;
0386         int error, n;
0387 
0388         channel->of_node = np;
0389         channel->drv = drv;
0390         channel->selected_phy = -1;
0391 
0392         error = of_property_read_u32(np, "reg", &channel_num);
0393         if (error || channel_num >= data->num_channels) {
0394             dev_err(dev, "Invalid \"reg\" property\n");
0395             of_node_put(np);
0396             return error;
0397         }
0398         channel->select_mask = select_mask[channel_num];
0399 
0400         for (n = 0; n < PHYS_PER_CHANNEL; n++) {
0401             struct rcar_gen2_phy *phy = &channel->phys[n];
0402 
0403             phy->channel = channel;
0404             phy->number = n;
0405             phy->select_value = data->select_value[channel_num][n];
0406 
0407             phy->phy = devm_phy_create(dev, NULL,
0408                            data->gen2_phy_ops);
0409             if (IS_ERR(phy->phy)) {
0410                 dev_err(dev, "Failed to create PHY\n");
0411                 of_node_put(np);
0412                 return PTR_ERR(phy->phy);
0413             }
0414             phy_set_drvdata(phy->phy, phy);
0415         }
0416 
0417         i++;
0418     }
0419 
0420     provider = devm_of_phy_provider_register(dev, rcar_gen2_phy_xlate);
0421     if (IS_ERR(provider)) {
0422         dev_err(dev, "Failed to register PHY provider\n");
0423         return PTR_ERR(provider);
0424     }
0425 
0426     dev_set_drvdata(dev, drv);
0427 
0428     return 0;
0429 }
0430 
0431 static struct platform_driver rcar_gen2_phy_driver = {
0432     .driver = {
0433         .name       = "phy_rcar_gen2",
0434         .of_match_table = rcar_gen2_phy_match_table,
0435     },
0436     .probe  = rcar_gen2_phy_probe,
0437 };
0438 
0439 module_platform_driver(rcar_gen2_phy_driver);
0440 
0441 MODULE_LICENSE("GPL v2");
0442 MODULE_DESCRIPTION("Renesas R-Car Gen2 PHY");
0443 MODULE_AUTHOR("Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>");