linux/drivers/usb/phy/phy-rcar-usb.c
<<
>>
Prefs
   1/*
   2 * Renesas R-Car USB phy driver
   3 *
   4 * Copyright (C) 2012-2013 Renesas Solutions Corp.
   5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
   6 * Copyright (C) 2013 Cogent Embedded, Inc.
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/delay.h>
  14#include <linux/io.h>
  15#include <linux/usb/otg.h>
  16#include <linux/platform_device.h>
  17#include <linux/spinlock.h>
  18#include <linux/module.h>
  19#include <linux/platform_data/usb-rcar-phy.h>
  20
  21/* REGS block */
  22#define USBPCTRL0       0x00
  23#define USBPCTRL1       0x04
  24#define USBST           0x08
  25#define USBEH0          0x0C
  26#define USBOH0          0x1C
  27#define USBCTL0         0x58
  28
  29/* High-speed signal quality characteristic control registers (R8A7778 only) */
  30#define HSQCTL1         0x24
  31#define HSQCTL2         0x28
  32
  33/* USBPCTRL0 */
  34#define OVC2            (1 << 10) /* (R8A7779 only)                     */
  35                                /* Switches the OVC input pin for port 2: */
  36                                /* 1: USB_OVC2, 0: OVC2                 */
  37#define OVC1_VBUS1      (1 << 9) /* Switches the OVC input pin for port 1: */
  38                                /* 1: USB_OVC1, 0: OVC1/VBUS1           */
  39                                /* Function mode: set to 0              */
  40#define OVC0            (1 << 8) /* Switches the OVC input pin for port 0: */
  41                                /* 1: USB_OVC0 pin, 0: OVC0             */
  42#define OVC2_ACT        (1 << 6) /* (R8A7779 only)                      */
  43                                /* Host mode: OVC2 polarity:            */
  44                                /* 1: active-high, 0: active-low        */
  45#define PENC            (1 << 4) /* Function mode: output level of PENC1 pin: */
  46                                /* 1: high, 0: low                      */
  47#define OVC0_ACT        (1 << 3) /* Host mode: OVC0 polarity:           */
  48                                /* 1: active-high, 0: active-low        */
  49#define OVC1_ACT        (1 << 1) /* Host mode: OVC1 polarity:           */
  50                                /* 1: active-high, 0: active-low        */
  51                                /* Function mode: be sure to set to 1   */
  52#define PORT1           (1 << 0) /* Selects port 1 mode:                */
  53                                /* 1: function, 0: host                 */
  54/* USBPCTRL1 */
  55#define PHY_RST         (1 << 2)
  56#define PLL_ENB         (1 << 1)
  57#define PHY_ENB         (1 << 0)
  58
  59/* USBST */
  60#define ST_ACT          (1 << 31)
  61#define ST_PLL          (1 << 30)
  62
  63struct rcar_usb_phy_priv {
  64        struct usb_phy phy;
  65        spinlock_t lock;
  66
  67        void __iomem *reg0;
  68        void __iomem *reg1;
  69        int counter;
  70};
  71
  72#define usb_phy_to_priv(p) container_of(p, struct rcar_usb_phy_priv, phy)
  73
  74
  75/*
  76 * USB initial/install operation.
  77 *
  78 * This function setup USB phy.
  79 * The used value and setting order came from
  80 * [USB :: Initial setting] on datasheet.
  81 */
  82static int rcar_usb_phy_init(struct usb_phy *phy)
  83{
  84        struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
  85        struct device *dev = phy->dev;
  86        struct rcar_phy_platform_data *pdata = dev_get_platdata(dev);
  87        void __iomem *reg0 = priv->reg0;
  88        void __iomem *reg1 = priv->reg1;
  89        static const u8 ovcn_act[] = { OVC0_ACT, OVC1_ACT, OVC2_ACT };
  90        int i;
  91        u32 val;
  92        unsigned long flags;
  93
  94        spin_lock_irqsave(&priv->lock, flags);
  95        if (priv->counter++ == 0) {
  96
  97                /*
  98                 * USB phy start-up
  99                 */
 100
 101                /* (1) USB-PHY standby release */
 102                iowrite32(PHY_ENB, (reg0 + USBPCTRL1));
 103
 104                /* (2) start USB-PHY internal PLL */
 105                iowrite32(PHY_ENB | PLL_ENB, (reg0 + USBPCTRL1));
 106
 107                /* (3) set USB-PHY in accord with the conditions of usage */
 108                if (reg1) {
 109                        u32 hsqctl1 = pdata->ferrite_bead ? 0x41 : 0;
 110                        u32 hsqctl2 = pdata->ferrite_bead ? 0x0d : 7;
 111
 112                        iowrite32(hsqctl1, reg1 + HSQCTL1);
 113                        iowrite32(hsqctl2, reg1 + HSQCTL2);
 114                }
 115
 116                /* (4) USB module status check */
 117                for (i = 0; i < 1024; i++) {
 118                        udelay(10);
 119                        val = ioread32(reg0 + USBST);
 120                        if (val == (ST_ACT | ST_PLL))
 121                                break;
 122                }
 123
 124                if (val != (ST_ACT | ST_PLL)) {
 125                        dev_err(dev, "USB phy not ready\n");
 126                        goto phy_init_end;
 127                }
 128
 129                /* (5) USB-PHY reset clear */
 130                iowrite32(PHY_ENB | PLL_ENB | PHY_RST, (reg0 + USBPCTRL1));
 131
 132                /* Board specific port settings */
 133                val = 0;
 134                if (pdata->port1_func)
 135                        val |= PORT1;
 136                if (pdata->penc1)
 137                        val |= PENC;
 138                for (i = 0; i < 3; i++) {
 139                        /* OVCn bits follow each other in the right order */
 140                        if (pdata->ovc_pin[i].select_3_3v)
 141                                val |= OVC0 << i;
 142                        /* OVCn_ACT bits are spaced by irregular intervals */
 143                        if (pdata->ovc_pin[i].active_high)
 144                                val |= ovcn_act[i];
 145                }
 146                iowrite32(val, (reg0 + USBPCTRL0));
 147
 148                /*
 149                 * Bus alignment settings
 150                 */
 151
 152                /* (1) EHCI bus alignment (little endian) */
 153                iowrite32(0x00000000, (reg0 + USBEH0));
 154
 155                /* (1) OHCI bus alignment (little endian) */
 156                iowrite32(0x00000000, (reg0 + USBOH0));
 157        }
 158
 159phy_init_end:
 160        spin_unlock_irqrestore(&priv->lock, flags);
 161
 162        return 0;
 163}
 164
 165static void rcar_usb_phy_shutdown(struct usb_phy *phy)
 166{
 167        struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
 168        void __iomem *reg0 = priv->reg0;
 169        unsigned long flags;
 170
 171        spin_lock_irqsave(&priv->lock, flags);
 172
 173        if (priv->counter-- == 1)       /* last user */
 174                iowrite32(0x00000000, (reg0 + USBPCTRL1));
 175
 176        spin_unlock_irqrestore(&priv->lock, flags);
 177}
 178
 179static int rcar_usb_phy_probe(struct platform_device *pdev)
 180{
 181        struct rcar_usb_phy_priv *priv;
 182        struct resource *res0, *res1;
 183        struct device *dev = &pdev->dev;
 184        void __iomem *reg0, *reg1 = NULL;
 185        int ret;
 186
 187        if (!dev_get_platdata(&pdev->dev)) {
 188                dev_err(dev, "No platform data\n");
 189                return -EINVAL;
 190        }
 191
 192        res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 193        reg0 = devm_ioremap_resource(dev, res0);
 194        if (IS_ERR(reg0))
 195                return PTR_ERR(reg0);
 196
 197        res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 198        reg1 = devm_ioremap_resource(dev, res1);
 199        if (IS_ERR(reg1))
 200                return PTR_ERR(reg1);
 201
 202        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 203        if (!priv)
 204                return -ENOMEM;
 205
 206        priv->reg0              = reg0;
 207        priv->reg1              = reg1;
 208        priv->counter           = 0;
 209        priv->phy.dev           = dev;
 210        priv->phy.label         = dev_name(dev);
 211        priv->phy.init          = rcar_usb_phy_init;
 212        priv->phy.shutdown      = rcar_usb_phy_shutdown;
 213        spin_lock_init(&priv->lock);
 214
 215        ret = usb_add_phy(&priv->phy, USB_PHY_TYPE_USB2);
 216        if (ret < 0) {
 217                dev_err(dev, "usb phy addition error\n");
 218                return ret;
 219        }
 220
 221        platform_set_drvdata(pdev, priv);
 222
 223        return ret;
 224}
 225
 226static int rcar_usb_phy_remove(struct platform_device *pdev)
 227{
 228        struct rcar_usb_phy_priv *priv = platform_get_drvdata(pdev);
 229
 230        usb_remove_phy(&priv->phy);
 231
 232        return 0;
 233}
 234
 235static struct platform_driver rcar_usb_phy_driver = {
 236        .driver         = {
 237                .name   = "rcar_usb_phy",
 238        },
 239        .probe          = rcar_usb_phy_probe,
 240        .remove         = rcar_usb_phy_remove,
 241};
 242
 243module_platform_driver(rcar_usb_phy_driver);
 244
 245MODULE_LICENSE("GPL v2");
 246MODULE_DESCRIPTION("Renesas R-Car USB phy");
 247MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
 248