linux/drivers/phy/allwinner/phy-sun4i-usb.c
<<
>>
Prefs
   1/*
   2 * Allwinner sun4i USB phy driver
   3 *
   4 * Copyright (C) 2014-2015 Hans de Goede <hdegoede@redhat.com>
   5 *
   6 * Based on code from
   7 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
   8 *
   9 * Modelled after: Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver
  10 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
  11 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
  12 *
  13 * This program is free software; you can redistribute it and/or modify
  14 * it under the terms of the GNU General Public License as published by
  15 * the Free Software Foundation; either version 2 of the License, or
  16 * (at your option) any later version.
  17 *
  18 * This program is distributed in the hope that it will be useful,
  19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 * GNU General Public License for more details.
  22 */
  23
  24#include <linux/clk.h>
  25#include <linux/delay.h>
  26#include <linux/err.h>
  27#include <linux/extcon.h>
  28#include <linux/io.h>
  29#include <linux/interrupt.h>
  30#include <linux/kernel.h>
  31#include <linux/module.h>
  32#include <linux/mutex.h>
  33#include <linux/of.h>
  34#include <linux/of_address.h>
  35#include <linux/of_device.h>
  36#include <linux/of_gpio.h>
  37#include <linux/phy/phy.h>
  38#include <linux/phy/phy-sun4i-usb.h>
  39#include <linux/platform_device.h>
  40#include <linux/power_supply.h>
  41#include <linux/regulator/consumer.h>
  42#include <linux/reset.h>
  43#include <linux/spinlock.h>
  44#include <linux/usb/of.h>
  45#include <linux/workqueue.h>
  46
  47#define REG_ISCR                        0x00
  48#define REG_PHYCTL_A10                  0x04
  49#define REG_PHYBIST                     0x08
  50#define REG_PHYTUNE                     0x0c
  51#define REG_PHYCTL_A33                  0x10
  52#define REG_PHY_OTGCTL                  0x20
  53
  54#define REG_PMU_UNK1                    0x10
  55
  56#define PHYCTL_DATA                     BIT(7)
  57
  58#define OTGCTL_ROUTE_MUSB               BIT(0)
  59
  60#define SUNXI_AHB_ICHR8_EN              BIT(10)
  61#define SUNXI_AHB_INCR4_BURST_EN        BIT(9)
  62#define SUNXI_AHB_INCRX_ALIGN_EN        BIT(8)
  63#define SUNXI_ULPI_BYPASS_EN            BIT(0)
  64
  65/* ISCR, Interface Status and Control bits */
  66#define ISCR_ID_PULLUP_EN               (1 << 17)
  67#define ISCR_DPDM_PULLUP_EN     (1 << 16)
  68/* sunxi has the phy id/vbus pins not connected, so we use the force bits */
  69#define ISCR_FORCE_ID_MASK      (3 << 14)
  70#define ISCR_FORCE_ID_LOW               (2 << 14)
  71#define ISCR_FORCE_ID_HIGH      (3 << 14)
  72#define ISCR_FORCE_VBUS_MASK    (3 << 12)
  73#define ISCR_FORCE_VBUS_LOW     (2 << 12)
  74#define ISCR_FORCE_VBUS_HIGH    (3 << 12)
  75
  76/* Common Control Bits for Both PHYs */
  77#define PHY_PLL_BW                      0x03
  78#define PHY_RES45_CAL_EN                0x0c
  79
  80/* Private Control Bits for Each PHY */
  81#define PHY_TX_AMPLITUDE_TUNE           0x20
  82#define PHY_TX_SLEWRATE_TUNE            0x22
  83#define PHY_VBUSVALID_TH_SEL            0x25
  84#define PHY_PULLUP_RES_SEL              0x27
  85#define PHY_OTG_FUNC_EN                 0x28
  86#define PHY_VBUS_DET_EN                 0x29
  87#define PHY_DISCON_TH_SEL               0x2a
  88#define PHY_SQUELCH_DETECT              0x3c
  89
  90#define MAX_PHYS                        4
  91
  92/*
  93 * Note do not raise the debounce time, we must report Vusb high within 100ms
  94 * otherwise we get Vbus errors
  95 */
  96#define DEBOUNCE_TIME                   msecs_to_jiffies(50)
  97#define POLL_TIME                       msecs_to_jiffies(250)
  98
  99enum sun4i_usb_phy_type {
 100        sun4i_a10_phy,
 101        sun6i_a31_phy,
 102        sun8i_a33_phy,
 103        sun8i_h3_phy,
 104        sun8i_v3s_phy,
 105        sun50i_a64_phy,
 106};
 107
 108struct sun4i_usb_phy_cfg {
 109        int num_phys;
 110        enum sun4i_usb_phy_type type;
 111        u32 disc_thresh;
 112        u8 phyctl_offset;
 113        bool dedicated_clocks;
 114        bool enable_pmu_unk1;
 115        bool phy0_dual_route;
 116};
 117
 118struct sun4i_usb_phy_data {
 119        void __iomem *base;
 120        const struct sun4i_usb_phy_cfg *cfg;
 121        enum usb_dr_mode dr_mode;
 122        spinlock_t reg_lock; /* guard access to phyctl reg */
 123        struct sun4i_usb_phy {
 124                struct phy *phy;
 125                void __iomem *pmu;
 126                struct regulator *vbus;
 127                struct reset_control *reset;
 128                struct clk *clk;
 129                bool regulator_on;
 130                int index;
 131        } phys[MAX_PHYS];
 132        /* phy0 / otg related variables */
 133        struct extcon_dev *extcon;
 134        bool phy0_init;
 135        struct gpio_desc *id_det_gpio;
 136        struct gpio_desc *vbus_det_gpio;
 137        struct power_supply *vbus_power_supply;
 138        struct notifier_block vbus_power_nb;
 139        bool vbus_power_nb_registered;
 140        bool force_session_end;
 141        int id_det_irq;
 142        int vbus_det_irq;
 143        int id_det;
 144        int vbus_det;
 145        struct delayed_work detect;
 146};
 147
 148#define to_sun4i_usb_phy_data(phy) \
 149        container_of((phy), struct sun4i_usb_phy_data, phys[(phy)->index])
 150
 151static void sun4i_usb_phy0_update_iscr(struct phy *_phy, u32 clr, u32 set)
 152{
 153        struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
 154        struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
 155        u32 iscr;
 156
 157        iscr = readl(data->base + REG_ISCR);
 158        iscr &= ~clr;
 159        iscr |= set;
 160        writel(iscr, data->base + REG_ISCR);
 161}
 162
 163static void sun4i_usb_phy0_set_id_detect(struct phy *phy, u32 val)
 164{
 165        if (val)
 166                val = ISCR_FORCE_ID_HIGH;
 167        else
 168                val = ISCR_FORCE_ID_LOW;
 169
 170        sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_ID_MASK, val);
 171}
 172
 173static void sun4i_usb_phy0_set_vbus_detect(struct phy *phy, u32 val)
 174{
 175        if (val)
 176                val = ISCR_FORCE_VBUS_HIGH;
 177        else
 178                val = ISCR_FORCE_VBUS_LOW;
 179
 180        sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_VBUS_MASK, val);
 181}
 182
 183static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
 184                                int len)
 185{
 186        struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
 187        u32 temp, usbc_bit = BIT(phy->index * 2);
 188        void __iomem *phyctl = phy_data->base + phy_data->cfg->phyctl_offset;
 189        unsigned long flags;
 190        int i;
 191
 192        spin_lock_irqsave(&phy_data->reg_lock, flags);
 193
 194        if (phy_data->cfg->phyctl_offset == REG_PHYCTL_A33) {
 195                /* SoCs newer than A33 need us to set phyctl to 0 explicitly */
 196                writel(0, phyctl);
 197        }
 198
 199        for (i = 0; i < len; i++) {
 200                temp = readl(phyctl);
 201
 202                /* clear the address portion */
 203                temp &= ~(0xff << 8);
 204
 205                /* set the address */
 206                temp |= ((addr + i) << 8);
 207                writel(temp, phyctl);
 208
 209                /* set the data bit and clear usbc bit*/
 210                temp = readb(phyctl);
 211                if (data & 0x1)
 212                        temp |= PHYCTL_DATA;
 213                else
 214                        temp &= ~PHYCTL_DATA;
 215                temp &= ~usbc_bit;
 216                writeb(temp, phyctl);
 217
 218                /* pulse usbc_bit */
 219                temp = readb(phyctl);
 220                temp |= usbc_bit;
 221                writeb(temp, phyctl);
 222
 223                temp = readb(phyctl);
 224                temp &= ~usbc_bit;
 225                writeb(temp, phyctl);
 226
 227                data >>= 1;
 228        }
 229
 230        spin_unlock_irqrestore(&phy_data->reg_lock, flags);
 231}
 232
 233static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable)
 234{
 235        u32 bits, reg_value;
 236
 237        if (!phy->pmu)
 238                return;
 239
 240        bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN |
 241                SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN;
 242
 243        reg_value = readl(phy->pmu);
 244
 245        if (enable)
 246                reg_value |= bits;
 247        else
 248                reg_value &= ~bits;
 249
 250        writel(reg_value, phy->pmu);
 251}
 252
 253static int sun4i_usb_phy_init(struct phy *_phy)
 254{
 255        struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
 256        struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
 257        int ret;
 258        u32 val;
 259
 260        ret = clk_prepare_enable(phy->clk);
 261        if (ret)
 262                return ret;
 263
 264        ret = reset_control_deassert(phy->reset);
 265        if (ret) {
 266                clk_disable_unprepare(phy->clk);
 267                return ret;
 268        }
 269
 270        if (phy->pmu && data->cfg->enable_pmu_unk1) {
 271                val = readl(phy->pmu + REG_PMU_UNK1);
 272                writel(val & ~2, phy->pmu + REG_PMU_UNK1);
 273        }
 274
 275        /* Enable USB 45 Ohm resistor calibration */
 276        if (phy->index == 0)
 277                sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1);
 278
 279        /* Adjust PHY's magnitude and rate */
 280        sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
 281
 282        /* Disconnect threshold adjustment */
 283        sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL,
 284                            data->cfg->disc_thresh, 2);
 285
 286        sun4i_usb_phy_passby(phy, 1);
 287
 288        if (phy->index == 0) {
 289                data->phy0_init = true;
 290
 291                /* Enable pull-ups */
 292                sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_DPDM_PULLUP_EN);
 293                sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_ID_PULLUP_EN);
 294
 295                /* Force ISCR and cable state updates */
 296                data->id_det = -1;
 297                data->vbus_det = -1;
 298                queue_delayed_work(system_wq, &data->detect, 0);
 299        }
 300
 301        return 0;
 302}
 303
 304static int sun4i_usb_phy_exit(struct phy *_phy)
 305{
 306        struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
 307        struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
 308
 309        if (phy->index == 0) {
 310                /* Disable pull-ups */
 311                sun4i_usb_phy0_update_iscr(_phy, ISCR_DPDM_PULLUP_EN, 0);
 312                sun4i_usb_phy0_update_iscr(_phy, ISCR_ID_PULLUP_EN, 0);
 313                data->phy0_init = false;
 314        }
 315
 316        sun4i_usb_phy_passby(phy, 0);
 317        reset_control_assert(phy->reset);
 318        clk_disable_unprepare(phy->clk);
 319
 320        return 0;
 321}
 322
 323static int sun4i_usb_phy0_get_id_det(struct sun4i_usb_phy_data *data)
 324{
 325        switch (data->dr_mode) {
 326        case USB_DR_MODE_OTG:
 327                if (data->id_det_gpio)
 328                        return gpiod_get_value_cansleep(data->id_det_gpio);
 329                else
 330                        return 1; /* Fallback to peripheral mode */
 331        case USB_DR_MODE_HOST:
 332                return 0;
 333        case USB_DR_MODE_PERIPHERAL:
 334        default:
 335                return 1;
 336        }
 337}
 338
 339static int sun4i_usb_phy0_get_vbus_det(struct sun4i_usb_phy_data *data)
 340{
 341        if (data->vbus_det_gpio)
 342                return gpiod_get_value_cansleep(data->vbus_det_gpio);
 343
 344        if (data->vbus_power_supply) {
 345                union power_supply_propval val;
 346                int r;
 347
 348                r = power_supply_get_property(data->vbus_power_supply,
 349                                              POWER_SUPPLY_PROP_PRESENT, &val);
 350                if (r == 0)
 351                        return val.intval;
 352        }
 353
 354        /* Fallback: report vbus as high */
 355        return 1;
 356}
 357
 358static bool sun4i_usb_phy0_have_vbus_det(struct sun4i_usb_phy_data *data)
 359{
 360        return data->vbus_det_gpio || data->vbus_power_supply;
 361}
 362
 363static bool sun4i_usb_phy0_poll(struct sun4i_usb_phy_data *data)
 364{
 365        if ((data->id_det_gpio && data->id_det_irq <= 0) ||
 366            (data->vbus_det_gpio && data->vbus_det_irq <= 0))
 367                return true;
 368
 369        /*
 370         * The A31 companion pmic (axp221) does not generate vbus change
 371         * interrupts when the board is driving vbus, so we must poll
 372         * when using the pmic for vbus-det _and_ we're driving vbus.
 373         */
 374        if (data->cfg->type == sun6i_a31_phy &&
 375            data->vbus_power_supply && data->phys[0].regulator_on)
 376                return true;
 377
 378        return false;
 379}
 380
 381static int sun4i_usb_phy_power_on(struct phy *_phy)
 382{
 383        struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
 384        struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
 385        int ret;
 386
 387        if (!phy->vbus || phy->regulator_on)
 388                return 0;
 389
 390        /* For phy0 only turn on Vbus if we don't have an ext. Vbus */
 391        if (phy->index == 0 && sun4i_usb_phy0_have_vbus_det(data) &&
 392                                data->vbus_det) {
 393                dev_warn(&_phy->dev, "External vbus detected, not enabling our own vbus\n");
 394                return 0;
 395        }
 396
 397        ret = regulator_enable(phy->vbus);
 398        if (ret)
 399                return ret;
 400
 401        phy->regulator_on = true;
 402
 403        /* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */
 404        if (phy->index == 0 && sun4i_usb_phy0_poll(data))
 405                mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
 406
 407        return 0;
 408}
 409
 410static int sun4i_usb_phy_power_off(struct phy *_phy)
 411{
 412        struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
 413        struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
 414
 415        if (!phy->vbus || !phy->regulator_on)
 416                return 0;
 417
 418        regulator_disable(phy->vbus);
 419        phy->regulator_on = false;
 420
 421        /*
 422         * phy0 vbus typically slowly discharges, sometimes this causes the
 423         * Vbus gpio to not trigger an edge irq on Vbus off, so force a rescan.
 424         */
 425        if (phy->index == 0 && !sun4i_usb_phy0_poll(data))
 426                mod_delayed_work(system_wq, &data->detect, POLL_TIME);
 427
 428        return 0;
 429}
 430
 431static int sun4i_usb_phy_set_mode(struct phy *_phy, enum phy_mode mode)
 432{
 433        struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
 434        struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
 435        int new_mode;
 436
 437        if (phy->index != 0)
 438                return -EINVAL;
 439
 440        switch (mode) {
 441        case PHY_MODE_USB_HOST:
 442                new_mode = USB_DR_MODE_HOST;
 443                break;
 444        case PHY_MODE_USB_DEVICE:
 445                new_mode = USB_DR_MODE_PERIPHERAL;
 446                break;
 447        case PHY_MODE_USB_OTG:
 448                new_mode = USB_DR_MODE_OTG;
 449                break;
 450        default:
 451                return -EINVAL;
 452        }
 453
 454        if (new_mode != data->dr_mode) {
 455                dev_info(&_phy->dev, "Changing dr_mode to %d\n", new_mode);
 456                data->dr_mode = new_mode;
 457        }
 458
 459        data->id_det = -1; /* Force reprocessing of id */
 460        data->force_session_end = true;
 461        queue_delayed_work(system_wq, &data->detect, 0);
 462
 463        return 0;
 464}
 465
 466void sun4i_usb_phy_set_squelch_detect(struct phy *_phy, bool enabled)
 467{
 468        struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
 469
 470        sun4i_usb_phy_write(phy, PHY_SQUELCH_DETECT, enabled ? 0 : 2, 2);
 471}
 472EXPORT_SYMBOL_GPL(sun4i_usb_phy_set_squelch_detect);
 473
 474static const struct phy_ops sun4i_usb_phy_ops = {
 475        .init           = sun4i_usb_phy_init,
 476        .exit           = sun4i_usb_phy_exit,
 477        .power_on       = sun4i_usb_phy_power_on,
 478        .power_off      = sun4i_usb_phy_power_off,
 479        .set_mode       = sun4i_usb_phy_set_mode,
 480        .owner          = THIS_MODULE,
 481};
 482
 483static void sun4i_usb_phy0_reroute(struct sun4i_usb_phy_data *data, int id_det)
 484{
 485        u32 regval;
 486
 487        regval = readl(data->base + REG_PHY_OTGCTL);
 488        if (id_det == 0) {
 489                /* Host mode. Route phy0 to EHCI/OHCI */
 490                regval &= ~OTGCTL_ROUTE_MUSB;
 491        } else {
 492                /* Peripheral mode. Route phy0 to MUSB */
 493                regval |= OTGCTL_ROUTE_MUSB;
 494        }
 495        writel(regval, data->base + REG_PHY_OTGCTL);
 496}
 497
 498static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
 499{
 500        struct sun4i_usb_phy_data *data =
 501                container_of(work, struct sun4i_usb_phy_data, detect.work);
 502        struct phy *phy0 = data->phys[0].phy;
 503        bool force_session_end, id_notify = false, vbus_notify = false;
 504        int id_det, vbus_det;
 505
 506        if (phy0 == NULL)
 507                return;
 508
 509        id_det = sun4i_usb_phy0_get_id_det(data);
 510        vbus_det = sun4i_usb_phy0_get_vbus_det(data);
 511
 512        mutex_lock(&phy0->mutex);
 513
 514        if (!data->phy0_init) {
 515                mutex_unlock(&phy0->mutex);
 516                return;
 517        }
 518
 519        force_session_end = data->force_session_end;
 520        data->force_session_end = false;
 521
 522        if (id_det != data->id_det) {
 523                /* id-change, force session end if we've no vbus detection */
 524                if (data->dr_mode == USB_DR_MODE_OTG &&
 525                    !sun4i_usb_phy0_have_vbus_det(data))
 526                        force_session_end = true;
 527
 528                /* When entering host mode (id = 0) force end the session now */
 529                if (force_session_end && id_det == 0) {
 530                        sun4i_usb_phy0_set_vbus_detect(phy0, 0);
 531                        msleep(200);
 532                        sun4i_usb_phy0_set_vbus_detect(phy0, 1);
 533                }
 534                sun4i_usb_phy0_set_id_detect(phy0, id_det);
 535                data->id_det = id_det;
 536                id_notify = true;
 537        }
 538
 539        if (vbus_det != data->vbus_det) {
 540                sun4i_usb_phy0_set_vbus_detect(phy0, vbus_det);
 541                data->vbus_det = vbus_det;
 542                vbus_notify = true;
 543        }
 544
 545        mutex_unlock(&phy0->mutex);
 546
 547        if (id_notify) {
 548                extcon_set_state_sync(data->extcon, EXTCON_USB_HOST,
 549                                        !id_det);
 550                /* When leaving host mode force end the session here */
 551                if (force_session_end && id_det == 1) {
 552                        mutex_lock(&phy0->mutex);
 553                        sun4i_usb_phy0_set_vbus_detect(phy0, 0);
 554                        msleep(1000);
 555                        sun4i_usb_phy0_set_vbus_detect(phy0, 1);
 556                        mutex_unlock(&phy0->mutex);
 557                }
 558
 559                /* Re-route PHY0 if necessary */
 560                if (data->cfg->phy0_dual_route)
 561                        sun4i_usb_phy0_reroute(data, id_det);
 562        }
 563
 564        if (vbus_notify)
 565                extcon_set_state_sync(data->extcon, EXTCON_USB, vbus_det);
 566
 567        if (sun4i_usb_phy0_poll(data))
 568                queue_delayed_work(system_wq, &data->detect, POLL_TIME);
 569}
 570
 571static irqreturn_t sun4i_usb_phy0_id_vbus_det_irq(int irq, void *dev_id)
 572{
 573        struct sun4i_usb_phy_data *data = dev_id;
 574
 575        /* vbus or id changed, let the pins settle and then scan them */
 576        mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
 577
 578        return IRQ_HANDLED;
 579}
 580
 581static int sun4i_usb_phy0_vbus_notify(struct notifier_block *nb,
 582                                      unsigned long val, void *v)
 583{
 584        struct sun4i_usb_phy_data *data =
 585                container_of(nb, struct sun4i_usb_phy_data, vbus_power_nb);
 586        struct power_supply *psy = v;
 587
 588        /* Properties on the vbus_power_supply changed, scan vbus_det */
 589        if (val == PSY_EVENT_PROP_CHANGED && psy == data->vbus_power_supply)
 590                mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
 591
 592        return NOTIFY_OK;
 593}
 594
 595static struct phy *sun4i_usb_phy_xlate(struct device *dev,
 596                                        struct of_phandle_args *args)
 597{
 598        struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
 599
 600        if (args->args[0] >= data->cfg->num_phys)
 601                return ERR_PTR(-ENODEV);
 602
 603        return data->phys[args->args[0]].phy;
 604}
 605
 606static int sun4i_usb_phy_remove(struct platform_device *pdev)
 607{
 608        struct device *dev = &pdev->dev;
 609        struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
 610
 611        if (data->vbus_power_nb_registered)
 612                power_supply_unreg_notifier(&data->vbus_power_nb);
 613        if (data->id_det_irq > 0)
 614                devm_free_irq(dev, data->id_det_irq, data);
 615        if (data->vbus_det_irq > 0)
 616                devm_free_irq(dev, data->vbus_det_irq, data);
 617
 618        cancel_delayed_work_sync(&data->detect);
 619
 620        return 0;
 621}
 622
 623static const unsigned int sun4i_usb_phy0_cable[] = {
 624        EXTCON_USB,
 625        EXTCON_USB_HOST,
 626        EXTCON_NONE,
 627};
 628
 629static int sun4i_usb_phy_probe(struct platform_device *pdev)
 630{
 631        struct sun4i_usb_phy_data *data;
 632        struct device *dev = &pdev->dev;
 633        struct device_node *np = dev->of_node;
 634        struct phy_provider *phy_provider;
 635        struct resource *res;
 636        int i, ret;
 637
 638        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 639        if (!data)
 640                return -ENOMEM;
 641
 642        spin_lock_init(&data->reg_lock);
 643        INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan);
 644        dev_set_drvdata(dev, data);
 645        data->cfg = of_device_get_match_data(dev);
 646        if (!data->cfg)
 647                return -EINVAL;
 648
 649        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
 650        data->base = devm_ioremap_resource(dev, res);
 651        if (IS_ERR(data->base))
 652                return PTR_ERR(data->base);
 653
 654        data->id_det_gpio = devm_gpiod_get_optional(dev, "usb0_id_det",
 655                                                    GPIOD_IN);
 656        if (IS_ERR(data->id_det_gpio))
 657                return PTR_ERR(data->id_det_gpio);
 658
 659        data->vbus_det_gpio = devm_gpiod_get_optional(dev, "usb0_vbus_det",
 660                                                      GPIOD_IN);
 661        if (IS_ERR(data->vbus_det_gpio))
 662                return PTR_ERR(data->vbus_det_gpio);
 663
 664        if (of_find_property(np, "usb0_vbus_power-supply", NULL)) {
 665                data->vbus_power_supply = devm_power_supply_get_by_phandle(dev,
 666                                                     "usb0_vbus_power-supply");
 667                if (IS_ERR(data->vbus_power_supply))
 668                        return PTR_ERR(data->vbus_power_supply);
 669
 670                if (!data->vbus_power_supply)
 671                        return -EPROBE_DEFER;
 672        }
 673
 674        data->dr_mode = of_usb_get_dr_mode_by_phy(np, 0);
 675
 676        data->extcon = devm_extcon_dev_allocate(dev, sun4i_usb_phy0_cable);
 677        if (IS_ERR(data->extcon))
 678                return PTR_ERR(data->extcon);
 679
 680        ret = devm_extcon_dev_register(dev, data->extcon);
 681        if (ret) {
 682                dev_err(dev, "failed to register extcon: %d\n", ret);
 683                return ret;
 684        }
 685
 686        for (i = 0; i < data->cfg->num_phys; i++) {
 687                struct sun4i_usb_phy *phy = data->phys + i;
 688                char name[16];
 689
 690                snprintf(name, sizeof(name), "usb%d_vbus", i);
 691                phy->vbus = devm_regulator_get_optional(dev, name);
 692                if (IS_ERR(phy->vbus)) {
 693                        if (PTR_ERR(phy->vbus) == -EPROBE_DEFER)
 694                                return -EPROBE_DEFER;
 695                        phy->vbus = NULL;
 696                }
 697
 698                if (data->cfg->dedicated_clocks)
 699                        snprintf(name, sizeof(name), "usb%d_phy", i);
 700                else
 701                        strlcpy(name, "usb_phy", sizeof(name));
 702
 703                phy->clk = devm_clk_get(dev, name);
 704                if (IS_ERR(phy->clk)) {
 705                        dev_err(dev, "failed to get clock %s\n", name);
 706                        return PTR_ERR(phy->clk);
 707                }
 708
 709                snprintf(name, sizeof(name), "usb%d_reset", i);
 710                phy->reset = devm_reset_control_get(dev, name);
 711                if (IS_ERR(phy->reset)) {
 712                        dev_err(dev, "failed to get reset %s\n", name);
 713                        return PTR_ERR(phy->reset);
 714                }
 715
 716                if (i || data->cfg->phy0_dual_route) { /* No pmu for musb */
 717                        snprintf(name, sizeof(name), "pmu%d", i);
 718                        res = platform_get_resource_byname(pdev,
 719                                                        IORESOURCE_MEM, name);
 720                        phy->pmu = devm_ioremap_resource(dev, res);
 721                        if (IS_ERR(phy->pmu))
 722                                return PTR_ERR(phy->pmu);
 723                }
 724
 725                phy->phy = devm_phy_create(dev, NULL, &sun4i_usb_phy_ops);
 726                if (IS_ERR(phy->phy)) {
 727                        dev_err(dev, "failed to create PHY %d\n", i);
 728                        return PTR_ERR(phy->phy);
 729                }
 730
 731                phy->index = i;
 732                phy_set_drvdata(phy->phy, &data->phys[i]);
 733        }
 734
 735        data->id_det_irq = gpiod_to_irq(data->id_det_gpio);
 736        if (data->id_det_irq > 0) {
 737                ret = devm_request_irq(dev, data->id_det_irq,
 738                                sun4i_usb_phy0_id_vbus_det_irq,
 739                                IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 740                                "usb0-id-det", data);
 741                if (ret) {
 742                        dev_err(dev, "Err requesting id-det-irq: %d\n", ret);
 743                        return ret;
 744                }
 745        }
 746
 747        data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio);
 748        if (data->vbus_det_irq > 0) {
 749                ret = devm_request_irq(dev, data->vbus_det_irq,
 750                                sun4i_usb_phy0_id_vbus_det_irq,
 751                                IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 752                                "usb0-vbus-det", data);
 753                if (ret) {
 754                        dev_err(dev, "Err requesting vbus-det-irq: %d\n", ret);
 755                        data->vbus_det_irq = -1;
 756                        sun4i_usb_phy_remove(pdev); /* Stop detect work */
 757                        return ret;
 758                }
 759        }
 760
 761        if (data->vbus_power_supply) {
 762                data->vbus_power_nb.notifier_call = sun4i_usb_phy0_vbus_notify;
 763                data->vbus_power_nb.priority = 0;
 764                ret = power_supply_reg_notifier(&data->vbus_power_nb);
 765                if (ret) {
 766                        sun4i_usb_phy_remove(pdev); /* Stop detect work */
 767                        return ret;
 768                }
 769                data->vbus_power_nb_registered = true;
 770        }
 771
 772        phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
 773        if (IS_ERR(phy_provider)) {
 774                sun4i_usb_phy_remove(pdev); /* Stop detect work */
 775                return PTR_ERR(phy_provider);
 776        }
 777
 778        return 0;
 779}
 780
 781static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = {
 782        .num_phys = 3,
 783        .type = sun4i_a10_phy,
 784        .disc_thresh = 3,
 785        .phyctl_offset = REG_PHYCTL_A10,
 786        .dedicated_clocks = false,
 787        .enable_pmu_unk1 = false,
 788};
 789
 790static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = {
 791        .num_phys = 2,
 792        .type = sun4i_a10_phy,
 793        .disc_thresh = 2,
 794        .phyctl_offset = REG_PHYCTL_A10,
 795        .dedicated_clocks = false,
 796        .enable_pmu_unk1 = false,
 797};
 798
 799static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = {
 800        .num_phys = 3,
 801        .type = sun6i_a31_phy,
 802        .disc_thresh = 3,
 803        .phyctl_offset = REG_PHYCTL_A10,
 804        .dedicated_clocks = true,
 805        .enable_pmu_unk1 = false,
 806};
 807
 808static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = {
 809        .num_phys = 3,
 810        .type = sun4i_a10_phy,
 811        .disc_thresh = 2,
 812        .phyctl_offset = REG_PHYCTL_A10,
 813        .dedicated_clocks = false,
 814        .enable_pmu_unk1 = false,
 815};
 816
 817static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = {
 818        .num_phys = 2,
 819        .type = sun4i_a10_phy,
 820        .disc_thresh = 3,
 821        .phyctl_offset = REG_PHYCTL_A10,
 822        .dedicated_clocks = true,
 823        .enable_pmu_unk1 = false,
 824};
 825
 826static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = {
 827        .num_phys = 2,
 828        .type = sun8i_a33_phy,
 829        .disc_thresh = 3,
 830        .phyctl_offset = REG_PHYCTL_A33,
 831        .dedicated_clocks = true,
 832        .enable_pmu_unk1 = false,
 833};
 834
 835static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
 836        .num_phys = 4,
 837        .type = sun8i_h3_phy,
 838        .disc_thresh = 3,
 839        .phyctl_offset = REG_PHYCTL_A33,
 840        .dedicated_clocks = true,
 841        .enable_pmu_unk1 = true,
 842        .phy0_dual_route = true,
 843};
 844
 845static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = {
 846        .num_phys = 1,
 847        .type = sun8i_v3s_phy,
 848        .disc_thresh = 3,
 849        .phyctl_offset = REG_PHYCTL_A33,
 850        .dedicated_clocks = true,
 851        .enable_pmu_unk1 = true,
 852};
 853
 854static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
 855        .num_phys = 2,
 856        .type = sun50i_a64_phy,
 857        .disc_thresh = 3,
 858        .phyctl_offset = REG_PHYCTL_A33,
 859        .dedicated_clocks = true,
 860        .enable_pmu_unk1 = true,
 861        .phy0_dual_route = true,
 862};
 863
 864static const struct of_device_id sun4i_usb_phy_of_match[] = {
 865        { .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg },
 866        { .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg },
 867        { .compatible = "allwinner,sun6i-a31-usb-phy", .data = &sun6i_a31_cfg },
 868        { .compatible = "allwinner,sun7i-a20-usb-phy", .data = &sun7i_a20_cfg },
 869        { .compatible = "allwinner,sun8i-a23-usb-phy", .data = &sun8i_a23_cfg },
 870        { .compatible = "allwinner,sun8i-a33-usb-phy", .data = &sun8i_a33_cfg },
 871        { .compatible = "allwinner,sun8i-h3-usb-phy", .data = &sun8i_h3_cfg },
 872        { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg },
 873        { .compatible = "allwinner,sun50i-a64-usb-phy",
 874          .data = &sun50i_a64_cfg},
 875        { },
 876};
 877MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
 878
 879static struct platform_driver sun4i_usb_phy_driver = {
 880        .probe  = sun4i_usb_phy_probe,
 881        .remove = sun4i_usb_phy_remove,
 882        .driver = {
 883                .of_match_table = sun4i_usb_phy_of_match,
 884                .name  = "sun4i-usb-phy",
 885        }
 886};
 887module_platform_driver(sun4i_usb_phy_driver);
 888
 889MODULE_DESCRIPTION("Allwinner sun4i USB phy driver");
 890MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 891MODULE_LICENSE("GPL v2");
 892