linux/drivers/phy/renesas/phy-rcar-gen2.c
<<
>>
Prefs
   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        { .compatible = "renesas,rcar-gen2-usb-phy" },
 199        { }
 200};
 201MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table);
 202
 203static struct phy *rcar_gen2_phy_xlate(struct device *dev,
 204                                       struct of_phandle_args *args)
 205{
 206        struct rcar_gen2_phy_driver *drv;
 207        struct device_node *np = args->np;
 208        int i;
 209
 210        drv = dev_get_drvdata(dev);
 211        if (!drv)
 212                return ERR_PTR(-EINVAL);
 213
 214        for (i = 0; i < drv->num_channels; i++) {
 215                if (np == drv->channels[i].of_node)
 216                        break;
 217        }
 218
 219        if (i >= drv->num_channels || args->args[0] >= 2)
 220                return ERR_PTR(-ENODEV);
 221
 222        return drv->channels[i].phys[args->args[0]].phy;
 223}
 224
 225static const u32 select_mask[] = {
 226        [0]     = USBHS_UGCTRL2_USB0SEL,
 227        [2]     = USBHS_UGCTRL2_USB2SEL,
 228};
 229
 230static const u32 select_value[][PHYS_PER_CHANNEL] = {
 231        [0]     = { USBHS_UGCTRL2_USB0SEL_PCI, USBHS_UGCTRL2_USB0SEL_HS_USB },
 232        [2]     = { USBHS_UGCTRL2_USB2SEL_PCI, USBHS_UGCTRL2_USB2SEL_USB30 },
 233};
 234
 235static int rcar_gen2_phy_probe(struct platform_device *pdev)
 236{
 237        struct device *dev = &pdev->dev;
 238        struct rcar_gen2_phy_driver *drv;
 239        struct phy_provider *provider;
 240        struct device_node *np;
 241        struct resource *res;
 242        void __iomem *base;
 243        struct clk *clk;
 244        int i = 0;
 245
 246        if (!dev->of_node) {
 247                dev_err(dev,
 248                        "This driver is required to be instantiated from device tree\n");
 249                return -EINVAL;
 250        }
 251
 252        clk = devm_clk_get(dev, "usbhs");
 253        if (IS_ERR(clk)) {
 254                dev_err(dev, "Can't get USBHS clock\n");
 255                return PTR_ERR(clk);
 256        }
 257
 258        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 259        base = devm_ioremap_resource(dev, res);
 260        if (IS_ERR(base))
 261                return PTR_ERR(base);
 262
 263        drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
 264        if (!drv)
 265                return -ENOMEM;
 266
 267        spin_lock_init(&drv->lock);
 268
 269        drv->clk = clk;
 270        drv->base = base;
 271
 272        drv->num_channels = of_get_child_count(dev->of_node);
 273        drv->channels = devm_kcalloc(dev, drv->num_channels,
 274                                     sizeof(struct rcar_gen2_channel),
 275                                     GFP_KERNEL);
 276        if (!drv->channels)
 277                return -ENOMEM;
 278
 279        for_each_child_of_node(dev->of_node, np) {
 280                struct rcar_gen2_channel *channel = drv->channels + i;
 281                u32 channel_num;
 282                int error, n;
 283
 284                channel->of_node = np;
 285                channel->drv = drv;
 286                channel->selected_phy = -1;
 287
 288                error = of_property_read_u32(np, "reg", &channel_num);
 289                if (error || channel_num > 2) {
 290                        dev_err(dev, "Invalid \"reg\" property\n");
 291                        return error;
 292                }
 293                channel->select_mask = select_mask[channel_num];
 294
 295                for (n = 0; n < PHYS_PER_CHANNEL; n++) {
 296                        struct rcar_gen2_phy *phy = &channel->phys[n];
 297
 298                        phy->channel = channel;
 299                        phy->number = n;
 300                        phy->select_value = select_value[channel_num][n];
 301
 302                        phy->phy = devm_phy_create(dev, NULL,
 303                                                   &rcar_gen2_phy_ops);
 304                        if (IS_ERR(phy->phy)) {
 305                                dev_err(dev, "Failed to create PHY\n");
 306                                return PTR_ERR(phy->phy);
 307                        }
 308                        phy_set_drvdata(phy->phy, phy);
 309                }
 310
 311                i++;
 312        }
 313
 314        provider = devm_of_phy_provider_register(dev, rcar_gen2_phy_xlate);
 315        if (IS_ERR(provider)) {
 316                dev_err(dev, "Failed to register PHY provider\n");
 317                return PTR_ERR(provider);
 318        }
 319
 320        dev_set_drvdata(dev, drv);
 321
 322        return 0;
 323}
 324
 325static struct platform_driver rcar_gen2_phy_driver = {
 326        .driver = {
 327                .name           = "phy_rcar_gen2",
 328                .of_match_table = rcar_gen2_phy_match_table,
 329        },
 330        .probe  = rcar_gen2_phy_probe,
 331};
 332
 333module_platform_driver(rcar_gen2_phy_driver);
 334
 335MODULE_LICENSE("GPL v2");
 336MODULE_DESCRIPTION("Renesas R-Car Gen2 PHY");
 337MODULE_AUTHOR("Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>");
 338