1/* 2 * Renesas R-Car Gen2 PHY driver 3 * 4 * Copyright (C) 2014 Renesas Solutions Corp. 5 * Copyright (C) 2014 Cogent Embedded, Inc. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 12#include <linux/clk.h> 13#include <linux/delay.h> 14#include <linux/io.h> 15#include <linux/module.h> 16#include <linux/of.h> 17#include <linux/phy/phy.h> 18#include <linux/platform_device.h> 19#include <linux/spinlock.h> 20#include <linux/atomic.h> 21 22#define USBHS_LPSTS 0x02 23#define USBHS_UGCTRL 0x80 24#define USBHS_UGCTRL2 0x84 25#define USBHS_UGSTS 0x88 /* From technical update */ 26 27/* Low Power Status register (LPSTS) */ 28#define USBHS_LPSTS_SUSPM 0x4000 29 30/* USB General control register (UGCTRL) */ 31#define USBHS_UGCTRL_CONNECT 0x00000004 32#define USBHS_UGCTRL_PLLRESET 0x00000001 33 34/* USB General control register 2 (UGCTRL2) */ 35#define USBHS_UGCTRL2_USB2SEL 0x80000000 36#define USBHS_UGCTRL2_USB2SEL_PCI 0x00000000 37#define USBHS_UGCTRL2_USB2SEL_USB30 0x80000000 38#define USBHS_UGCTRL2_USB0SEL 0x00000030 39#define USBHS_UGCTRL2_USB0SEL_PCI 0x00000010 40#define USBHS_UGCTRL2_USB0SEL_HS_USB 0x00000030 41 42/* USB General status register (UGSTS) */ 43#define USBHS_UGSTS_LOCK 0x00000100 /* From technical update */ 44 45#define PHYS_PER_CHANNEL 2 46 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 70static int rcar_gen2_phy_init(struct phy *p) 71{ 72 struct rcar_gen2_phy *phy = phy_get_drvdata(p); 73 struct rcar_gen2_channel *channel = phy->channel; 74 struct rcar_gen2_phy_driver *drv = channel->drv; 75 unsigned long flags; 76 u32 ugctrl2; 77 78 /* 79 * Try to acquire exclusive access to PHY. The first driver calling 80 * phy_init() on a given channel wins, and all attempts to use another 81 * PHY on this channel will fail until phy_exit() is called by the first 82 * driver. Achieving this with cmpxcgh() should be SMP-safe. 83 */ 84 if (cmpxchg(&channel->selected_phy, -1, phy->number) != -1) 85 return -EBUSY; 86 87 clk_prepare_enable(drv->clk); 88 89 spin_lock_irqsave(&drv->lock, flags); 90 ugctrl2 = readl(drv->base + USBHS_UGCTRL2); 91 ugctrl2 &= ~channel->select_mask; 92 ugctrl2 |= phy->select_value; 93 writel(ugctrl2, drv->base + USBHS_UGCTRL2); 94 spin_unlock_irqrestore(&drv->lock, flags); 95 return 0; 96} 97 98static int rcar_gen2_phy_exit(struct phy *p) 99{ 100 struct rcar_gen2_phy *phy = phy_get_drvdata(p); 101 struct rcar_gen2_channel *channel = phy->channel; 102 103 clk_disable_unprepare(channel->drv->clk); 104 105 channel->selected_phy = -1; 106 107 return 0; 108} 109 110static int rcar_gen2_phy_power_on(struct phy *p) 111{ 112 struct rcar_gen2_phy *phy = phy_get_drvdata(p); 113 struct rcar_gen2_phy_driver *drv = phy->channel->drv; 114 void __iomem *base = drv->base; 115 unsigned long flags; 116 u32 value; 117 int err = 0, i; 118 119 /* Skip if it's not USBHS */ 120 if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB) 121 return 0; 122 123 spin_lock_irqsave(&drv->lock, flags); 124 125 /* Power on USBHS PHY */ 126 value = readl(base + USBHS_UGCTRL); 127 value &= ~USBHS_UGCTRL_PLLRESET; 128 writel(value, base + USBHS_UGCTRL); 129 130 value = readw(base + USBHS_LPSTS); 131 value |= USBHS_LPSTS_SUSPM; 132 writew(value, base + USBHS_LPSTS); 133 134 for (i = 0; i < 20; i++) { 135 value = readl(base + USBHS_UGSTS); 136 if ((value & USBHS_UGSTS_LOCK) == USBHS_UGSTS_LOCK) { 137 value = readl(base + USBHS_UGCTRL); 138 value |= USBHS_UGCTRL_CONNECT; 139 writel(value, base + USBHS_UGCTRL); 140 goto out; 141 } 142 udelay(1); 143 } 144 145 /* Timed out waiting for the PLL lock */ 146 err = -ETIMEDOUT; 147 148out: 149 spin_unlock_irqrestore(&drv->lock, flags); 150 151 return err; 152} 153 154static int rcar_gen2_phy_power_off(struct phy *p) 155{ 156 struct rcar_gen2_phy *phy = phy_get_drvdata(p); 157 struct rcar_gen2_phy_driver *drv = phy->channel->drv; 158 void __iomem *base = drv->base; 159 unsigned long flags; 160 u32 value; 161 162 /* Skip if it's not USBHS */ 163 if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB) 164 return 0; 165 166 spin_lock_irqsave(&drv->lock, flags); 167 168 /* Power off USBHS PHY */ 169 value = readl(base + USBHS_UGCTRL); 170 value &= ~USBHS_UGCTRL_CONNECT; 171 writel(value, base + USBHS_UGCTRL); 172 173 value = readw(base + USBHS_LPSTS); 174 value &= ~USBHS_LPSTS_SUSPM; 175 writew(value, base + USBHS_LPSTS); 176 177 value = readl(base + USBHS_UGCTRL); 178 value |= USBHS_UGCTRL_PLLRESET; 179 writel(value, base + USBHS_UGCTRL); 180 181 spin_unlock_irqrestore(&drv->lock, flags); 182 183 return 0; 184} 185 186static const struct phy_ops rcar_gen2_phy_ops = { 187 .init = rcar_gen2_phy_init, 188 .exit = rcar_gen2_phy_exit, 189 .power_on = rcar_gen2_phy_power_on, 190 .power_off = rcar_gen2_phy_power_off, 191 .owner = THIS_MODULE, 192}; 193 194static const struct of_device_id rcar_gen2_phy_match_table[] = { 195 { .compatible = "renesas,usb-phy-r8a7790" }, 196 { .compatible = "renesas,usb-phy-r8a7791" }, 197 { .compatible = "renesas,usb-phy-r8a7794" }, 198 { } 199}; 200MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table); 201 202static struct phy *rcar_gen2_phy_xlate(struct device *dev, 203 struct of_phandle_args *args) 204{ 205 struct rcar_gen2_phy_driver *drv; 206 struct device_node *np = args->np; 207 int i; 208 209 drv = dev_get_drvdata(dev); 210 if (!drv) 211 return ERR_PTR(-EINVAL); 212 213 for (i = 0; i < drv->num_channels; i++) { 214 if (np == drv->channels[i].of_node) 215 break; 216 } 217 218 if (i >= drv->num_channels || args->args[0] >= 2) 219 return ERR_PTR(-ENODEV); 220 221 return drv->channels[i].phys[args->args[0]].phy; 222} 223 224static const u32 select_mask[] = { 225 [0] = USBHS_UGCTRL2_USB0SEL, 226 [2] = USBHS_UGCTRL2_USB2SEL, 227}; 228 229static const u32 select_value[][PHYS_PER_CHANNEL] = { 230 [0] = { USBHS_UGCTRL2_USB0SEL_PCI, USBHS_UGCTRL2_USB0SEL_HS_USB }, 231 [2] = { USBHS_UGCTRL2_USB2SEL_PCI, USBHS_UGCTRL2_USB2SEL_USB30 }, 232}; 233 234static int rcar_gen2_phy_probe(struct platform_device *pdev) 235{ 236 struct device *dev = &pdev->dev; 237 struct rcar_gen2_phy_driver *drv; 238 struct phy_provider *provider; 239 struct device_node *np; 240 struct resource *res; 241 void __iomem *base; 242 struct clk *clk; 243 int i = 0; 244 245 if (!dev->of_node) { 246 dev_err(dev, 247 "This driver is required to be instantiated from device tree\n"); 248 return -EINVAL; 249 } 250 251 clk = devm_clk_get(dev, "usbhs"); 252 if (IS_ERR(clk)) { 253 dev_err(dev, "Can't get USBHS clock\n"); 254 return PTR_ERR(clk); 255 } 256 257 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 258 base = devm_ioremap_resource(dev, res); 259 if (IS_ERR(base)) 260 return PTR_ERR(base); 261 262 drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); 263 if (!drv) 264 return -ENOMEM; 265 266 spin_lock_init(&drv->lock); 267 268 drv->clk = clk; 269 drv->base = base; 270 271 drv->num_channels = of_get_child_count(dev->of_node); 272 drv->channels = devm_kcalloc(dev, drv->num_channels, 273 sizeof(struct rcar_gen2_channel), 274 GFP_KERNEL); 275 if (!drv->channels) 276 return -ENOMEM; 277 278 for_each_child_of_node(dev->of_node, np) { 279 struct rcar_gen2_channel *channel = drv->channels + i; 280 u32 channel_num; 281 int error, n; 282 283 channel->of_node = np; 284 channel->drv = drv; 285 channel->selected_phy = -1; 286 287 error = of_property_read_u32(np, "reg", &channel_num); 288 if (error || channel_num > 2) { 289 dev_err(dev, "Invalid \"reg\" property\n"); 290 return error; 291 } 292 channel->select_mask = select_mask[channel_num]; 293 294 for (n = 0; n < PHYS_PER_CHANNEL; n++) { 295 struct rcar_gen2_phy *phy = &channel->phys[n]; 296 297 phy->channel = channel; 298 phy->number = n; 299 phy->select_value = select_value[channel_num][n]; 300 301 phy->phy = devm_phy_create(dev, NULL, 302 &rcar_gen2_phy_ops); 303 if (IS_ERR(phy->phy)) { 304 dev_err(dev, "Failed to create PHY\n"); 305 return PTR_ERR(phy->phy); 306 } 307 phy_set_drvdata(phy->phy, phy); 308 } 309 310 i++; 311 } 312 313 provider = devm_of_phy_provider_register(dev, rcar_gen2_phy_xlate); 314 if (IS_ERR(provider)) { 315 dev_err(dev, "Failed to register PHY provider\n"); 316 return PTR_ERR(provider); 317 } 318 319 dev_set_drvdata(dev, drv); 320 321 return 0; 322} 323 324static struct platform_driver rcar_gen2_phy_driver = { 325 .driver = { 326 .name = "phy_rcar_gen2", 327 .of_match_table = rcar_gen2_phy_match_table, 328 }, 329 .probe = rcar_gen2_phy_probe, 330}; 331 332module_platform_driver(rcar_gen2_phy_driver); 333 334MODULE_LICENSE("GPL v2"); 335MODULE_DESCRIPTION("Renesas R-Car Gen2 PHY"); 336MODULE_AUTHOR("Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>"); 337