443 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Renesas R-Car Gen2 PHY driver4 *5 * Copyright (C) 2014 Renesas Solutions Corp.6 * Copyright (C) 2014 Cogent Embedded, Inc.7 * Copyright (C) 2019 Renesas Electronics Corp.8 */9 10#include <linux/clk.h>11#include <linux/delay.h>12#include <linux/io.h>13#include <linux/module.h>14#include <linux/of.h>15#include <linux/phy/phy.h>16#include <linux/platform_device.h>17#include <linux/spinlock.h>18#include <linux/atomic.h>19 20#define USBHS_LPSTS 0x0221#define USBHS_UGCTRL 0x8022#define USBHS_UGCTRL2 0x8423#define USBHS_UGSTS 0x88 /* From technical update */24 25/* Low Power Status register (LPSTS) */26#define USBHS_LPSTS_SUSPM 0x400027 28/* USB General control register (UGCTRL) */29#define USBHS_UGCTRL_CONNECT 0x0000000430#define USBHS_UGCTRL_PLLRESET 0x0000000131 32/* USB General control register 2 (UGCTRL2) */33#define USBHS_UGCTRL2_USB2SEL 0x8000000034#define USBHS_UGCTRL2_USB2SEL_PCI 0x0000000035#define USBHS_UGCTRL2_USB2SEL_USB30 0x8000000036#define USBHS_UGCTRL2_USB0SEL 0x0000003037#define USBHS_UGCTRL2_USB0SEL_PCI 0x0000001038#define USBHS_UGCTRL2_USB0SEL_HS_USB 0x0000003039#define USBHS_UGCTRL2_USB0SEL_USB20 0x0000001040#define USBHS_UGCTRL2_USB0SEL_HS_USB20 0x0000002041 42/* USB General status register (UGSTS) */43#define USBHS_UGSTS_LOCK 0x00000100 /* From technical update */44 45#define PHYS_PER_CHANNEL 246 47struct rcar_gen2_phy {48 struct phy *phy;49 struct rcar_gen2_channel *channel;50 int number;51 u32 select_value;52};53 54struct rcar_gen2_channel {55 struct device_node *of_node;56 struct rcar_gen2_phy_driver *drv;57 struct rcar_gen2_phy phys[PHYS_PER_CHANNEL];58 int selected_phy;59 u32 select_mask;60};61 62struct rcar_gen2_phy_driver {63 void __iomem *base;64 struct clk *clk;65 spinlock_t lock;66 int num_channels;67 struct rcar_gen2_channel *channels;68};69 70struct rcar_gen2_phy_data {71 const struct phy_ops *gen2_phy_ops;72 const u32 (*select_value)[PHYS_PER_CHANNEL];73 const u32 num_channels;74};75 76static int rcar_gen2_phy_init(struct phy *p)77{78 struct rcar_gen2_phy *phy = phy_get_drvdata(p);79 struct rcar_gen2_channel *channel = phy->channel;80 struct rcar_gen2_phy_driver *drv = channel->drv;81 unsigned long flags;82 u32 ugctrl2;83 84 /*85 * Try to acquire exclusive access to PHY. The first driver calling86 * phy_init() on a given channel wins, and all attempts to use another87 * PHY on this channel will fail until phy_exit() is called by the first88 * driver. Achieving this with cmpxcgh() should be SMP-safe.89 */90 if (cmpxchg(&channel->selected_phy, -1, phy->number) != -1)91 return -EBUSY;92 93 clk_prepare_enable(drv->clk);94 95 spin_lock_irqsave(&drv->lock, flags);96 ugctrl2 = readl(drv->base + USBHS_UGCTRL2);97 ugctrl2 &= ~channel->select_mask;98 ugctrl2 |= phy->select_value;99 writel(ugctrl2, drv->base + USBHS_UGCTRL2);100 spin_unlock_irqrestore(&drv->lock, flags);101 return 0;102}103 104static int rcar_gen2_phy_exit(struct phy *p)105{106 struct rcar_gen2_phy *phy = phy_get_drvdata(p);107 struct rcar_gen2_channel *channel = phy->channel;108 109 clk_disable_unprepare(channel->drv->clk);110 111 channel->selected_phy = -1;112 113 return 0;114}115 116static int rcar_gen2_phy_power_on(struct phy *p)117{118 struct rcar_gen2_phy *phy = phy_get_drvdata(p);119 struct rcar_gen2_phy_driver *drv = phy->channel->drv;120 void __iomem *base = drv->base;121 unsigned long flags;122 u32 value;123 int err = 0, i;124 125 /* Skip if it's not USBHS */126 if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB)127 return 0;128 129 spin_lock_irqsave(&drv->lock, flags);130 131 /* Power on USBHS PHY */132 value = readl(base + USBHS_UGCTRL);133 value &= ~USBHS_UGCTRL_PLLRESET;134 writel(value, base + USBHS_UGCTRL);135 136 value = readw(base + USBHS_LPSTS);137 value |= USBHS_LPSTS_SUSPM;138 writew(value, base + USBHS_LPSTS);139 140 for (i = 0; i < 20; i++) {141 value = readl(base + USBHS_UGSTS);142 if ((value & USBHS_UGSTS_LOCK) == USBHS_UGSTS_LOCK) {143 value = readl(base + USBHS_UGCTRL);144 value |= USBHS_UGCTRL_CONNECT;145 writel(value, base + USBHS_UGCTRL);146 goto out;147 }148 udelay(1);149 }150 151 /* Timed out waiting for the PLL lock */152 err = -ETIMEDOUT;153 154out:155 spin_unlock_irqrestore(&drv->lock, flags);156 157 return err;158}159 160static int rcar_gen2_phy_power_off(struct phy *p)161{162 struct rcar_gen2_phy *phy = phy_get_drvdata(p);163 struct rcar_gen2_phy_driver *drv = phy->channel->drv;164 void __iomem *base = drv->base;165 unsigned long flags;166 u32 value;167 168 /* Skip if it's not USBHS */169 if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB)170 return 0;171 172 spin_lock_irqsave(&drv->lock, flags);173 174 /* Power off USBHS PHY */175 value = readl(base + USBHS_UGCTRL);176 value &= ~USBHS_UGCTRL_CONNECT;177 writel(value, base + USBHS_UGCTRL);178 179 value = readw(base + USBHS_LPSTS);180 value &= ~USBHS_LPSTS_SUSPM;181 writew(value, base + USBHS_LPSTS);182 183 value = readl(base + USBHS_UGCTRL);184 value |= USBHS_UGCTRL_PLLRESET;185 writel(value, base + USBHS_UGCTRL);186 187 spin_unlock_irqrestore(&drv->lock, flags);188 189 return 0;190}191 192static int rz_g1c_phy_power_on(struct phy *p)193{194 struct rcar_gen2_phy *phy = phy_get_drvdata(p);195 struct rcar_gen2_phy_driver *drv = phy->channel->drv;196 void __iomem *base = drv->base;197 unsigned long flags;198 u32 value;199 200 spin_lock_irqsave(&drv->lock, flags);201 202 /* Power on USBHS PHY */203 value = readl(base + USBHS_UGCTRL);204 value &= ~USBHS_UGCTRL_PLLRESET;205 writel(value, base + USBHS_UGCTRL);206 207 /* As per the data sheet wait 340 micro sec for power stable */208 udelay(340);209 210 if (phy->select_value == USBHS_UGCTRL2_USB0SEL_HS_USB20) {211 value = readw(base + USBHS_LPSTS);212 value |= USBHS_LPSTS_SUSPM;213 writew(value, base + USBHS_LPSTS);214 }215 216 spin_unlock_irqrestore(&drv->lock, flags);217 218 return 0;219}220 221static int rz_g1c_phy_power_off(struct phy *p)222{223 struct rcar_gen2_phy *phy = phy_get_drvdata(p);224 struct rcar_gen2_phy_driver *drv = phy->channel->drv;225 void __iomem *base = drv->base;226 unsigned long flags;227 u32 value;228 229 spin_lock_irqsave(&drv->lock, flags);230 /* Power off USBHS PHY */231 if (phy->select_value == USBHS_UGCTRL2_USB0SEL_HS_USB20) {232 value = readw(base + USBHS_LPSTS);233 value &= ~USBHS_LPSTS_SUSPM;234 writew(value, base + USBHS_LPSTS);235 }236 237 value = readl(base + USBHS_UGCTRL);238 value |= USBHS_UGCTRL_PLLRESET;239 writel(value, base + USBHS_UGCTRL);240 241 spin_unlock_irqrestore(&drv->lock, flags);242 243 return 0;244}245 246static const struct phy_ops rcar_gen2_phy_ops = {247 .init = rcar_gen2_phy_init,248 .exit = rcar_gen2_phy_exit,249 .power_on = rcar_gen2_phy_power_on,250 .power_off = rcar_gen2_phy_power_off,251 .owner = THIS_MODULE,252};253 254static const struct phy_ops rz_g1c_phy_ops = {255 .init = rcar_gen2_phy_init,256 .exit = rcar_gen2_phy_exit,257 .power_on = rz_g1c_phy_power_on,258 .power_off = rz_g1c_phy_power_off,259 .owner = THIS_MODULE,260};261 262static const u32 pci_select_value[][PHYS_PER_CHANNEL] = {263 [0] = { USBHS_UGCTRL2_USB0SEL_PCI, USBHS_UGCTRL2_USB0SEL_HS_USB },264 [2] = { USBHS_UGCTRL2_USB2SEL_PCI, USBHS_UGCTRL2_USB2SEL_USB30 },265};266 267static const u32 usb20_select_value[][PHYS_PER_CHANNEL] = {268 { USBHS_UGCTRL2_USB0SEL_USB20, USBHS_UGCTRL2_USB0SEL_HS_USB20 },269};270 271static const struct rcar_gen2_phy_data rcar_gen2_usb_phy_data = {272 .gen2_phy_ops = &rcar_gen2_phy_ops,273 .select_value = pci_select_value,274 .num_channels = ARRAY_SIZE(pci_select_value),275};276 277static const struct rcar_gen2_phy_data rz_g1c_usb_phy_data = {278 .gen2_phy_ops = &rz_g1c_phy_ops,279 .select_value = usb20_select_value,280 .num_channels = ARRAY_SIZE(usb20_select_value),281};282 283static const struct of_device_id rcar_gen2_phy_match_table[] = {284 {285 .compatible = "renesas,usb-phy-r8a77470",286 .data = &rz_g1c_usb_phy_data,287 },288 {289 .compatible = "renesas,usb-phy-r8a7790",290 .data = &rcar_gen2_usb_phy_data,291 },292 {293 .compatible = "renesas,usb-phy-r8a7791",294 .data = &rcar_gen2_usb_phy_data,295 },296 {297 .compatible = "renesas,usb-phy-r8a7794",298 .data = &rcar_gen2_usb_phy_data,299 },300 {301 .compatible = "renesas,rcar-gen2-usb-phy",302 .data = &rcar_gen2_usb_phy_data,303 },304 { /* sentinel */ },305};306MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table);307 308static struct phy *rcar_gen2_phy_xlate(struct device *dev,309 const struct of_phandle_args *args)310{311 struct rcar_gen2_phy_driver *drv;312 struct device_node *np = args->np;313 int i;314 315 drv = dev_get_drvdata(dev);316 if (!drv)317 return ERR_PTR(-EINVAL);318 319 for (i = 0; i < drv->num_channels; i++) {320 if (np == drv->channels[i].of_node)321 break;322 }323 324 if (i >= drv->num_channels || args->args[0] >= 2)325 return ERR_PTR(-ENODEV);326 327 return drv->channels[i].phys[args->args[0]].phy;328}329 330static const u32 select_mask[] = {331 [0] = USBHS_UGCTRL2_USB0SEL,332 [2] = USBHS_UGCTRL2_USB2SEL,333};334 335static int rcar_gen2_phy_probe(struct platform_device *pdev)336{337 struct device *dev = &pdev->dev;338 struct rcar_gen2_phy_driver *drv;339 struct phy_provider *provider;340 struct device_node *np;341 void __iomem *base;342 struct clk *clk;343 const struct rcar_gen2_phy_data *data;344 int i = 0;345 346 if (!dev->of_node) {347 dev_err(dev,348 "This driver is required to be instantiated from device tree\n");349 return -EINVAL;350 }351 352 clk = devm_clk_get(dev, "usbhs");353 if (IS_ERR(clk)) {354 dev_err(dev, "Can't get USBHS clock\n");355 return PTR_ERR(clk);356 }357 358 base = devm_platform_ioremap_resource(pdev, 0);359 if (IS_ERR(base))360 return PTR_ERR(base);361 362 drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);363 if (!drv)364 return -ENOMEM;365 366 spin_lock_init(&drv->lock);367 368 drv->clk = clk;369 drv->base = base;370 371 data = of_device_get_match_data(dev);372 if (!data)373 return -EINVAL;374 375 drv->num_channels = of_get_child_count(dev->of_node);376 drv->channels = devm_kcalloc(dev, drv->num_channels,377 sizeof(struct rcar_gen2_channel),378 GFP_KERNEL);379 if (!drv->channels)380 return -ENOMEM;381 382 for_each_child_of_node(dev->of_node, np) {383 struct rcar_gen2_channel *channel = drv->channels + i;384 u32 channel_num;385 int error, n;386 387 channel->of_node = np;388 channel->drv = drv;389 channel->selected_phy = -1;390 391 error = of_property_read_u32(np, "reg", &channel_num);392 if (error || channel_num >= data->num_channels) {393 dev_err(dev, "Invalid \"reg\" property\n");394 of_node_put(np);395 return error;396 }397 channel->select_mask = select_mask[channel_num];398 399 for (n = 0; n < PHYS_PER_CHANNEL; n++) {400 struct rcar_gen2_phy *phy = &channel->phys[n];401 402 phy->channel = channel;403 phy->number = n;404 phy->select_value = data->select_value[channel_num][n];405 406 phy->phy = devm_phy_create(dev, NULL,407 data->gen2_phy_ops);408 if (IS_ERR(phy->phy)) {409 dev_err(dev, "Failed to create PHY\n");410 of_node_put(np);411 return PTR_ERR(phy->phy);412 }413 phy_set_drvdata(phy->phy, phy);414 }415 416 i++;417 }418 419 provider = devm_of_phy_provider_register(dev, rcar_gen2_phy_xlate);420 if (IS_ERR(provider)) {421 dev_err(dev, "Failed to register PHY provider\n");422 return PTR_ERR(provider);423 }424 425 dev_set_drvdata(dev, drv);426 427 return 0;428}429 430static struct platform_driver rcar_gen2_phy_driver = {431 .driver = {432 .name = "phy_rcar_gen2",433 .of_match_table = rcar_gen2_phy_match_table,434 },435 .probe = rcar_gen2_phy_probe,436};437 438module_platform_driver(rcar_gen2_phy_driver);439 440MODULE_LICENSE("GPL v2");441MODULE_DESCRIPTION("Renesas R-Car Gen2 PHY");442MODULE_AUTHOR("Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>");443