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