linux/drivers/phy/phy-rcar-gen3-usb2.c
<<
>>
Prefs
   1/*
   2 * Renesas R-Car Gen3 for USB2.0 PHY driver
   3 *
   4 * Copyright (C) 2015 Renesas Electronics Corporation
   5 *
   6 * This is based on the phy-rcar-gen2 driver:
   7 * Copyright (C) 2014 Renesas Solutions Corp.
   8 * Copyright (C) 2014 Cogent Embedded, Inc.
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13 */
  14
  15#include <linux/extcon.h>
  16#include <linux/interrupt.h>
  17#include <linux/io.h>
  18#include <linux/module.h>
  19#include <linux/of.h>
  20#include <linux/of_address.h>
  21#include <linux/phy/phy.h>
  22#include <linux/platform_device.h>
  23#include <linux/regulator/consumer.h>
  24#include <linux/workqueue.h>
  25
  26/******* USB2.0 Host registers (original offset is +0x200) *******/
  27#define USB2_INT_ENABLE         0x000
  28#define USB2_USBCTR             0x00c
  29#define USB2_SPD_RSM_TIMSET     0x10c
  30#define USB2_OC_TIMSET          0x110
  31#define USB2_COMMCTRL           0x600
  32#define USB2_OBINTSTA           0x604
  33#define USB2_OBINTEN            0x608
  34#define USB2_VBCTRL             0x60c
  35#define USB2_LINECTRL1          0x610
  36#define USB2_ADPCTRL            0x630
  37
  38/* INT_ENABLE */
  39#define USB2_INT_ENABLE_UCOM_INTEN      BIT(3)
  40#define USB2_INT_ENABLE_USBH_INTB_EN    BIT(2)
  41#define USB2_INT_ENABLE_USBH_INTA_EN    BIT(1)
  42#define USB2_INT_ENABLE_INIT            (USB2_INT_ENABLE_UCOM_INTEN | \
  43                                         USB2_INT_ENABLE_USBH_INTB_EN | \
  44                                         USB2_INT_ENABLE_USBH_INTA_EN)
  45
  46/* USBCTR */
  47#define USB2_USBCTR_DIRPD       BIT(2)
  48#define USB2_USBCTR_PLL_RST     BIT(1)
  49
  50/* SPD_RSM_TIMSET */
  51#define USB2_SPD_RSM_TIMSET_INIT        0x014e029b
  52
  53/* OC_TIMSET */
  54#define USB2_OC_TIMSET_INIT             0x000209ab
  55
  56/* COMMCTRL */
  57#define USB2_COMMCTRL_OTG_PERI          BIT(31) /* 1 = Peripheral mode */
  58
  59/* OBINTSTA and OBINTEN */
  60#define USB2_OBINT_SESSVLDCHG           BIT(12)
  61#define USB2_OBINT_IDDIGCHG             BIT(11)
  62#define USB2_OBINT_BITS                 (USB2_OBINT_SESSVLDCHG | \
  63                                         USB2_OBINT_IDDIGCHG)
  64
  65/* VBCTRL */
  66#define USB2_VBCTRL_DRVVBUSSEL          BIT(8)
  67
  68/* LINECTRL1 */
  69#define USB2_LINECTRL1_DPRPD_EN         BIT(19)
  70#define USB2_LINECTRL1_DP_RPD           BIT(18)
  71#define USB2_LINECTRL1_DMRPD_EN         BIT(17)
  72#define USB2_LINECTRL1_DM_RPD           BIT(16)
  73
  74/* ADPCTRL */
  75#define USB2_ADPCTRL_OTGSESSVLD         BIT(20)
  76#define USB2_ADPCTRL_IDDIG              BIT(19)
  77#define USB2_ADPCTRL_IDPULLUP           BIT(5)  /* 1 = ID sampling is enabled */
  78#define USB2_ADPCTRL_DRVVBUS            BIT(4)
  79
  80struct rcar_gen3_chan {
  81        void __iomem *base;
  82        struct extcon_dev *extcon;
  83        struct phy *phy;
  84        struct regulator *vbus;
  85        struct work_struct work;
  86        bool extcon_host;
  87        bool has_otg;
  88};
  89
  90static void rcar_gen3_phy_usb2_work(struct work_struct *work)
  91{
  92        struct rcar_gen3_chan *ch = container_of(work, struct rcar_gen3_chan,
  93                                                 work);
  94
  95        if (ch->extcon_host) {
  96                extcon_set_cable_state_(ch->extcon, EXTCON_USB_HOST, true);
  97                extcon_set_cable_state_(ch->extcon, EXTCON_USB, false);
  98        } else {
  99                extcon_set_cable_state_(ch->extcon, EXTCON_USB_HOST, false);
 100                extcon_set_cable_state_(ch->extcon, EXTCON_USB, true);
 101        }
 102}
 103
 104static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host)
 105{
 106        void __iomem *usb2_base = ch->base;
 107        u32 val = readl(usb2_base + USB2_COMMCTRL);
 108
 109        dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, host);
 110        if (host)
 111                val &= ~USB2_COMMCTRL_OTG_PERI;
 112        else
 113                val |= USB2_COMMCTRL_OTG_PERI;
 114        writel(val, usb2_base + USB2_COMMCTRL);
 115}
 116
 117static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm)
 118{
 119        void __iomem *usb2_base = ch->base;
 120        u32 val = readl(usb2_base + USB2_LINECTRL1);
 121
 122        dev_vdbg(&ch->phy->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm);
 123        val &= ~(USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD);
 124        if (dp)
 125                val |= USB2_LINECTRL1_DP_RPD;
 126        if (dm)
 127                val |= USB2_LINECTRL1_DM_RPD;
 128        writel(val, usb2_base + USB2_LINECTRL1);
 129}
 130
 131static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
 132{
 133        void __iomem *usb2_base = ch->base;
 134        u32 val = readl(usb2_base + USB2_ADPCTRL);
 135
 136        dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, vbus);
 137        if (vbus)
 138                val |= USB2_ADPCTRL_DRVVBUS;
 139        else
 140                val &= ~USB2_ADPCTRL_DRVVBUS;
 141        writel(val, usb2_base + USB2_ADPCTRL);
 142}
 143
 144static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch)
 145{
 146        rcar_gen3_set_linectrl(ch, 1, 1);
 147        rcar_gen3_set_host_mode(ch, 1);
 148        rcar_gen3_enable_vbus_ctrl(ch, 1);
 149
 150        ch->extcon_host = true;
 151        schedule_work(&ch->work);
 152}
 153
 154static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch)
 155{
 156        rcar_gen3_set_linectrl(ch, 0, 1);
 157        rcar_gen3_set_host_mode(ch, 0);
 158        rcar_gen3_enable_vbus_ctrl(ch, 0);
 159
 160        ch->extcon_host = false;
 161        schedule_work(&ch->work);
 162}
 163
 164static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch)
 165{
 166        return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG);
 167}
 168
 169static void rcar_gen3_device_recognition(struct rcar_gen3_chan *ch)
 170{
 171        if (!rcar_gen3_check_id(ch))
 172                rcar_gen3_init_for_host(ch);
 173        else
 174                rcar_gen3_init_for_peri(ch);
 175}
 176
 177static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
 178{
 179        void __iomem *usb2_base = ch->base;
 180        u32 val;
 181
 182        val = readl(usb2_base + USB2_VBCTRL);
 183        writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL);
 184        writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
 185        val = readl(usb2_base + USB2_OBINTEN);
 186        writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
 187        val = readl(usb2_base + USB2_ADPCTRL);
 188        writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL);
 189        val = readl(usb2_base + USB2_LINECTRL1);
 190        rcar_gen3_set_linectrl(ch, 0, 0);
 191        writel(val | USB2_LINECTRL1_DPRPD_EN | USB2_LINECTRL1_DMRPD_EN,
 192               usb2_base + USB2_LINECTRL1);
 193
 194        rcar_gen3_device_recognition(ch);
 195}
 196
 197static int rcar_gen3_phy_usb2_init(struct phy *p)
 198{
 199        struct rcar_gen3_chan *channel = phy_get_drvdata(p);
 200        void __iomem *usb2_base = channel->base;
 201
 202        /* Initialize USB2 part */
 203        writel(USB2_INT_ENABLE_INIT, usb2_base + USB2_INT_ENABLE);
 204        writel(USB2_SPD_RSM_TIMSET_INIT, usb2_base + USB2_SPD_RSM_TIMSET);
 205        writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET);
 206
 207        /* Initialize otg part */
 208        if (channel->has_otg)
 209                rcar_gen3_init_otg(channel);
 210
 211        return 0;
 212}
 213
 214static int rcar_gen3_phy_usb2_exit(struct phy *p)
 215{
 216        struct rcar_gen3_chan *channel = phy_get_drvdata(p);
 217
 218        writel(0, channel->base + USB2_INT_ENABLE);
 219
 220        return 0;
 221}
 222
 223static int rcar_gen3_phy_usb2_power_on(struct phy *p)
 224{
 225        struct rcar_gen3_chan *channel = phy_get_drvdata(p);
 226        void __iomem *usb2_base = channel->base;
 227        u32 val;
 228        int ret;
 229
 230        if (channel->vbus) {
 231                ret = regulator_enable(channel->vbus);
 232                if (ret)
 233                        return ret;
 234        }
 235
 236        val = readl(usb2_base + USB2_USBCTR);
 237        val |= USB2_USBCTR_PLL_RST;
 238        writel(val, usb2_base + USB2_USBCTR);
 239        val &= ~USB2_USBCTR_PLL_RST;
 240        writel(val, usb2_base + USB2_USBCTR);
 241
 242        return 0;
 243}
 244
 245static int rcar_gen3_phy_usb2_power_off(struct phy *p)
 246{
 247        struct rcar_gen3_chan *channel = phy_get_drvdata(p);
 248        int ret = 0;
 249
 250        if (channel->vbus)
 251                ret = regulator_disable(channel->vbus);
 252
 253        return ret;
 254}
 255
 256static struct phy_ops rcar_gen3_phy_usb2_ops = {
 257        .init           = rcar_gen3_phy_usb2_init,
 258        .exit           = rcar_gen3_phy_usb2_exit,
 259        .power_on       = rcar_gen3_phy_usb2_power_on,
 260        .power_off      = rcar_gen3_phy_usb2_power_off,
 261        .owner          = THIS_MODULE,
 262};
 263
 264static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
 265{
 266        struct rcar_gen3_chan *ch = _ch;
 267        void __iomem *usb2_base = ch->base;
 268        u32 status = readl(usb2_base + USB2_OBINTSTA);
 269        irqreturn_t ret = IRQ_NONE;
 270
 271        if (status & USB2_OBINT_BITS) {
 272                dev_vdbg(&ch->phy->dev, "%s: %08x\n", __func__, status);
 273                writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
 274                rcar_gen3_device_recognition(ch);
 275                ret = IRQ_HANDLED;
 276        }
 277
 278        return ret;
 279}
 280
 281static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
 282        { .compatible = "renesas,usb2-phy-r8a7795" },
 283        { .compatible = "renesas,usb2-phy-r8a7796" },
 284        { .compatible = "renesas,rcar-gen3-usb2-phy" },
 285        { }
 286};
 287MODULE_DEVICE_TABLE(of, rcar_gen3_phy_usb2_match_table);
 288
 289static const unsigned int rcar_gen3_phy_cable[] = {
 290        EXTCON_USB,
 291        EXTCON_USB_HOST,
 292        EXTCON_NONE,
 293};
 294
 295static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
 296{
 297        struct device *dev = &pdev->dev;
 298        struct rcar_gen3_chan *channel;
 299        struct phy_provider *provider;
 300        struct resource *res;
 301        int irq;
 302
 303        if (!dev->of_node) {
 304                dev_err(dev, "This driver needs device tree\n");
 305                return -EINVAL;
 306        }
 307
 308        channel = devm_kzalloc(dev, sizeof(*channel), GFP_KERNEL);
 309        if (!channel)
 310                return -ENOMEM;
 311
 312        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 313        channel->base = devm_ioremap_resource(dev, res);
 314        if (IS_ERR(channel->base))
 315                return PTR_ERR(channel->base);
 316
 317        /* call request_irq for OTG */
 318        irq = platform_get_irq(pdev, 0);
 319        if (irq >= 0) {
 320                int ret;
 321
 322                INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work);
 323                irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq,
 324                                       IRQF_SHARED, dev_name(dev), channel);
 325                if (irq < 0)
 326                        dev_err(dev, "No irq handler (%d)\n", irq);
 327                channel->has_otg = true;
 328                channel->extcon = devm_extcon_dev_allocate(dev,
 329                                                        rcar_gen3_phy_cable);
 330                if (IS_ERR(channel->extcon))
 331                        return PTR_ERR(channel->extcon);
 332
 333                ret = devm_extcon_dev_register(dev, channel->extcon);
 334                if (ret < 0) {
 335                        dev_err(dev, "Failed to register extcon\n");
 336                        return ret;
 337                }
 338        }
 339
 340        /* devm_phy_create() will call pm_runtime_enable(dev); */
 341        channel->phy = devm_phy_create(dev, NULL, &rcar_gen3_phy_usb2_ops);
 342        if (IS_ERR(channel->phy)) {
 343                dev_err(dev, "Failed to create USB2 PHY\n");
 344                return PTR_ERR(channel->phy);
 345        }
 346
 347        channel->vbus = devm_regulator_get_optional(dev, "vbus");
 348        if (IS_ERR(channel->vbus)) {
 349                if (PTR_ERR(channel->vbus) == -EPROBE_DEFER)
 350                        return PTR_ERR(channel->vbus);
 351                channel->vbus = NULL;
 352        }
 353
 354        phy_set_drvdata(channel->phy, channel);
 355
 356        provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
 357        if (IS_ERR(provider))
 358                dev_err(dev, "Failed to register PHY provider\n");
 359
 360        return PTR_ERR_OR_ZERO(provider);
 361}
 362
 363static struct platform_driver rcar_gen3_phy_usb2_driver = {
 364        .driver = {
 365                .name           = "phy_rcar_gen3_usb2",
 366                .of_match_table = rcar_gen3_phy_usb2_match_table,
 367        },
 368        .probe  = rcar_gen3_phy_usb2_probe,
 369};
 370module_platform_driver(rcar_gen3_phy_usb2_driver);
 371
 372MODULE_LICENSE("GPL v2");
 373MODULE_DESCRIPTION("Renesas R-Car Gen3 USB 2.0 PHY");
 374MODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>");
 375