Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.3-rc5 442 lines 11 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Renesas R-Car Gen2 PHY driver 4 * 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#include <linux/of_device.h> 20 21#define USBHS_LPSTS 0x02 22#define USBHS_UGCTRL 0x80 23#define USBHS_UGCTRL2 0x84 24#define USBHS_UGSTS 0x88 /* From technical update */ 25 26/* Low Power Status register (LPSTS) */ 27#define USBHS_LPSTS_SUSPM 0x4000 28 29/* USB General control register (UGCTRL) */ 30#define USBHS_UGCTRL_CONNECT 0x00000004 31#define USBHS_UGCTRL_PLLRESET 0x00000001 32 33/* USB General control register 2 (UGCTRL2) */ 34#define USBHS_UGCTRL2_USB2SEL 0x80000000 35#define USBHS_UGCTRL2_USB2SEL_PCI 0x00000000 36#define USBHS_UGCTRL2_USB2SEL_USB30 0x80000000 37#define USBHS_UGCTRL2_USB0SEL 0x00000030 38#define USBHS_UGCTRL2_USB0SEL_PCI 0x00000010 39#define USBHS_UGCTRL2_USB0SEL_HS_USB 0x00000030 40#define USBHS_UGCTRL2_USB0SEL_USB20 0x00000010 41#define USBHS_UGCTRL2_USB0SEL_HS_USB20 0x00000020 42 43/* USB General status register (UGSTS) */ 44#define USBHS_UGSTS_LOCK 0x00000100 /* From technical update */ 45 46#define PHYS_PER_CHANNEL 2 47 48struct rcar_gen2_phy { 49 struct phy *phy; 50 struct rcar_gen2_channel *channel; 51 int number; 52 u32 select_value; 53}; 54 55struct rcar_gen2_channel { 56 struct device_node *of_node; 57 struct rcar_gen2_phy_driver *drv; 58 struct rcar_gen2_phy phys[PHYS_PER_CHANNEL]; 59 int selected_phy; 60 u32 select_mask; 61}; 62 63struct rcar_gen2_phy_driver { 64 void __iomem *base; 65 struct clk *clk; 66 spinlock_t lock; 67 int num_channels; 68 struct rcar_gen2_channel *channels; 69}; 70 71struct rcar_gen2_phy_data { 72 const struct phy_ops *gen2_phy_ops; 73 const u32 (*select_value)[PHYS_PER_CHANNEL]; 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 calling 86 * phy_init() on a given channel wins, and all attempts to use another 87 * PHY on this channel will fail until phy_exit() is called by the first 88 * 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}; 275 276static const struct rcar_gen2_phy_data rz_g1c_usb_phy_data = { 277 .gen2_phy_ops = &rz_g1c_phy_ops, 278 .select_value = usb20_select_value, 279}; 280 281static const struct of_device_id rcar_gen2_phy_match_table[] = { 282 { 283 .compatible = "renesas,usb-phy-r8a77470", 284 .data = &rz_g1c_usb_phy_data, 285 }, 286 { 287 .compatible = "renesas,usb-phy-r8a7790", 288 .data = &rcar_gen2_usb_phy_data, 289 }, 290 { 291 .compatible = "renesas,usb-phy-r8a7791", 292 .data = &rcar_gen2_usb_phy_data, 293 }, 294 { 295 .compatible = "renesas,usb-phy-r8a7794", 296 .data = &rcar_gen2_usb_phy_data, 297 }, 298 { 299 .compatible = "renesas,rcar-gen2-usb-phy", 300 .data = &rcar_gen2_usb_phy_data, 301 }, 302 { /* sentinel */ }, 303}; 304MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table); 305 306static struct phy *rcar_gen2_phy_xlate(struct device *dev, 307 struct of_phandle_args *args) 308{ 309 struct rcar_gen2_phy_driver *drv; 310 struct device_node *np = args->np; 311 int i; 312 313 drv = dev_get_drvdata(dev); 314 if (!drv) 315 return ERR_PTR(-EINVAL); 316 317 for (i = 0; i < drv->num_channels; i++) { 318 if (np == drv->channels[i].of_node) 319 break; 320 } 321 322 if (i >= drv->num_channels || args->args[0] >= 2) 323 return ERR_PTR(-ENODEV); 324 325 return drv->channels[i].phys[args->args[0]].phy; 326} 327 328static const u32 select_mask[] = { 329 [0] = USBHS_UGCTRL2_USB0SEL, 330 [2] = USBHS_UGCTRL2_USB2SEL, 331}; 332 333static int rcar_gen2_phy_probe(struct platform_device *pdev) 334{ 335 struct device *dev = &pdev->dev; 336 struct rcar_gen2_phy_driver *drv; 337 struct phy_provider *provider; 338 struct device_node *np; 339 struct resource *res; 340 void __iomem *base; 341 struct clk *clk; 342 const struct rcar_gen2_phy_data *data; 343 int i = 0; 344 345 if (!dev->of_node) { 346 dev_err(dev, 347 "This driver is required to be instantiated from device tree\n"); 348 return -EINVAL; 349 } 350 351 clk = devm_clk_get(dev, "usbhs"); 352 if (IS_ERR(clk)) { 353 dev_err(dev, "Can't get USBHS clock\n"); 354 return PTR_ERR(clk); 355 } 356 357 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 358 base = devm_ioremap_resource(dev, res); 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 > 2) { 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>");