linux/drivers/usb/phy/rcar-phy.c
<<
>>
Prefs
   1/*
   2 * Renesas R-Car USB phy driver
   3 *
   4 * Copyright (C) 2012 Renesas Solutions Corp.
   5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
   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/delay.h>
  13#include <linux/io.h>
  14#include <linux/usb/otg.h>
  15#include <linux/platform_device.h>
  16#include <linux/spinlock.h>
  17#include <linux/module.h>
  18
  19/* USBH common register */
  20#define USBPCTRL0       0x0800
  21#define USBPCTRL1       0x0804
  22#define USBST           0x0808
  23#define USBEH0          0x080C
  24#define USBOH0          0x081C
  25#define USBCTL0         0x0858
  26#define EIIBC1          0x0094
  27#define EIIBC2          0x009C
  28
  29/* USBPCTRL1 */
  30#define PHY_RST         (1 << 2)
  31#define PLL_ENB         (1 << 1)
  32#define PHY_ENB         (1 << 0)
  33
  34/* USBST */
  35#define ST_ACT          (1 << 31)
  36#define ST_PLL          (1 << 30)
  37
  38struct rcar_usb_phy_priv {
  39        struct usb_phy phy;
  40        spinlock_t lock;
  41
  42        void __iomem *reg0;
  43        void __iomem *reg1;
  44        int counter;
  45};
  46
  47#define usb_phy_to_priv(p) container_of(p, struct rcar_usb_phy_priv, phy)
  48
  49
  50/*
  51 * USB initial/install operation.
  52 *
  53 * This function setup USB phy.
  54 * The used value and setting order came from
  55 * [USB :: Initial setting] on datasheet.
  56 */
  57static int rcar_usb_phy_init(struct usb_phy *phy)
  58{
  59        struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
  60        struct device *dev = phy->dev;
  61        void __iomem *reg0 = priv->reg0;
  62        void __iomem *reg1 = priv->reg1;
  63        int i;
  64        u32 val;
  65        unsigned long flags;
  66
  67        spin_lock_irqsave(&priv->lock, flags);
  68        if (priv->counter++ == 0) {
  69
  70                /*
  71                 * USB phy start-up
  72                 */
  73
  74                /* (1) USB-PHY standby release */
  75                iowrite32(PHY_ENB, (reg0 + USBPCTRL1));
  76
  77                /* (2) start USB-PHY internal PLL */
  78                iowrite32(PHY_ENB | PLL_ENB, (reg0 + USBPCTRL1));
  79
  80                /* (3) USB module status check */
  81                for (i = 0; i < 1024; i++) {
  82                        udelay(10);
  83                        val = ioread32(reg0 + USBST);
  84                        if (val == (ST_ACT | ST_PLL))
  85                                break;
  86                }
  87
  88                if (val != (ST_ACT | ST_PLL)) {
  89                        dev_err(dev, "USB phy not ready\n");
  90                        goto phy_init_end;
  91                }
  92
  93                /* (4) USB-PHY reset clear */
  94                iowrite32(PHY_ENB | PLL_ENB | PHY_RST, (reg0 + USBPCTRL1));
  95
  96                /* set platform specific port settings */
  97                iowrite32(0x00000000, (reg0 + USBPCTRL0));
  98
  99                /*
 100                 * EHCI IP internal buffer setting
 101                 * EHCI IP internal buffer enable
 102                 *
 103                 * These are recommended value of a datasheet
 104                 * see [USB :: EHCI internal buffer setting]
 105                 */
 106                iowrite32(0x00ff0040, (reg0 + EIIBC1));
 107                iowrite32(0x00ff0040, (reg1 + EIIBC1));
 108
 109                iowrite32(0x00000001, (reg0 + EIIBC2));
 110                iowrite32(0x00000001, (reg1 + EIIBC2));
 111
 112                /*
 113                 * Bus alignment settings
 114                 */
 115
 116                /* (1) EHCI bus alignment (little endian) */
 117                iowrite32(0x00000000, (reg0 + USBEH0));
 118
 119                /* (1) OHCI bus alignment (little endian) */
 120                iowrite32(0x00000000, (reg0 + USBOH0));
 121        }
 122
 123phy_init_end:
 124        spin_unlock_irqrestore(&priv->lock, flags);
 125
 126        return 0;
 127}
 128
 129static void rcar_usb_phy_shutdown(struct usb_phy *phy)
 130{
 131        struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
 132        void __iomem *reg0 = priv->reg0;
 133        unsigned long flags;
 134
 135        spin_lock_irqsave(&priv->lock, flags);
 136
 137        if (priv->counter-- == 1) { /* last user */
 138                iowrite32(0x00000000, (reg0 + USBPCTRL0));
 139                iowrite32(0x00000000, (reg0 + USBPCTRL1));
 140        }
 141
 142        spin_unlock_irqrestore(&priv->lock, flags);
 143}
 144
 145static int rcar_usb_phy_probe(struct platform_device *pdev)
 146{
 147        struct rcar_usb_phy_priv *priv;
 148        struct resource *res0, *res1;
 149        struct device *dev = &pdev->dev;
 150        void __iomem *reg0, *reg1;
 151        int ret;
 152
 153        res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 154        res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 155        if (!res0 || !res1) {
 156                dev_err(dev, "Not enough platform resources\n");
 157                return -EINVAL;
 158        }
 159
 160        /*
 161         * CAUTION
 162         *
 163         * Because this phy address is also mapped under OHCI/EHCI address area,
 164         * this driver can't use devm_request_and_ioremap(dev, res) here
 165         */
 166        reg0 = devm_ioremap_nocache(dev, res0->start, resource_size(res0));
 167        reg1 = devm_ioremap_nocache(dev, res1->start, resource_size(res1));
 168        if (!reg0 || !reg1) {
 169                dev_err(dev, "ioremap error\n");
 170                return -ENOMEM;
 171        }
 172
 173        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 174        if (!priv) {
 175                dev_err(dev, "priv data allocation error\n");
 176                return -ENOMEM;
 177        }
 178
 179        priv->reg0              = reg0;
 180        priv->reg1              = reg1;
 181        priv->counter           = 0;
 182        priv->phy.dev           = dev;
 183        priv->phy.label         = dev_name(dev);
 184        priv->phy.init          = rcar_usb_phy_init;
 185        priv->phy.shutdown      = rcar_usb_phy_shutdown;
 186        spin_lock_init(&priv->lock);
 187
 188        ret = usb_add_phy(&priv->phy, USB_PHY_TYPE_USB2);
 189        if (ret < 0) {
 190                dev_err(dev, "usb phy addition error\n");
 191                return ret;
 192        }
 193
 194        platform_set_drvdata(pdev, priv);
 195
 196        return ret;
 197}
 198
 199static int rcar_usb_phy_remove(struct platform_device *pdev)
 200{
 201        struct rcar_usb_phy_priv *priv = platform_get_drvdata(pdev);
 202
 203        usb_remove_phy(&priv->phy);
 204
 205        return 0;
 206}
 207
 208static struct platform_driver rcar_usb_phy_driver = {
 209        .driver         = {
 210                .name   = "rcar_usb_phy",
 211        },
 212        .probe          = rcar_usb_phy_probe,
 213        .remove         = rcar_usb_phy_remove,
 214};
 215
 216module_platform_driver(rcar_usb_phy_driver);
 217
 218MODULE_LICENSE("GPL v2");
 219MODULE_DESCRIPTION("Renesas R-Car USB phy");
 220MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
 221