linux/drivers/usb/dwc3/dwc3-qcom.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
   3 *
   4 * Inspired by dwc3-of-simple.c
   5 */
   6
   7#include <linux/acpi.h>
   8#include <linux/io.h>
   9#include <linux/of.h>
  10#include <linux/clk.h>
  11#include <linux/irq.h>
  12#include <linux/of_clk.h>
  13#include <linux/module.h>
  14#include <linux/kernel.h>
  15#include <linux/extcon.h>
  16#include <linux/interconnect.h>
  17#include <linux/of_platform.h>
  18#include <linux/platform_device.h>
  19#include <linux/phy/phy.h>
  20#include <linux/usb/of.h>
  21#include <linux/reset.h>
  22#include <linux/iopoll.h>
  23
  24#include "core.h"
  25
  26/* USB QSCRATCH Hardware registers */
  27#define QSCRATCH_HS_PHY_CTRL                    0x10
  28#define UTMI_OTG_VBUS_VALID                     BIT(20)
  29#define SW_SESSVLD_SEL                          BIT(28)
  30
  31#define QSCRATCH_SS_PHY_CTRL                    0x30
  32#define LANE0_PWR_PRESENT                       BIT(24)
  33
  34#define QSCRATCH_GENERAL_CFG                    0x08
  35#define PIPE_UTMI_CLK_SEL                       BIT(0)
  36#define PIPE3_PHYSTATUS_SW                      BIT(3)
  37#define PIPE_UTMI_CLK_DIS                       BIT(8)
  38
  39#define PWR_EVNT_IRQ_STAT_REG                   0x58
  40#define PWR_EVNT_LPM_IN_L2_MASK                 BIT(4)
  41#define PWR_EVNT_LPM_OUT_L2_MASK                BIT(5)
  42
  43#define SDM845_QSCRATCH_BASE_OFFSET             0xf8800
  44#define SDM845_QSCRATCH_SIZE                    0x400
  45#define SDM845_DWC3_CORE_SIZE                   0xcd00
  46
  47/* Interconnect path bandwidths in MBps */
  48#define USB_MEMORY_AVG_HS_BW MBps_to_icc(240)
  49#define USB_MEMORY_PEAK_HS_BW MBps_to_icc(700)
  50#define USB_MEMORY_AVG_SS_BW  MBps_to_icc(1000)
  51#define USB_MEMORY_PEAK_SS_BW MBps_to_icc(2500)
  52#define APPS_USB_AVG_BW 0
  53#define APPS_USB_PEAK_BW MBps_to_icc(40)
  54
  55struct dwc3_acpi_pdata {
  56        u32                     qscratch_base_offset;
  57        u32                     qscratch_base_size;
  58        u32                     dwc3_core_base_size;
  59        int                     hs_phy_irq_index;
  60        int                     dp_hs_phy_irq_index;
  61        int                     dm_hs_phy_irq_index;
  62        int                     ss_phy_irq_index;
  63        bool                    is_urs;
  64};
  65
  66struct dwc3_qcom {
  67        struct device           *dev;
  68        void __iomem            *qscratch_base;
  69        struct platform_device  *dwc3;
  70        struct platform_device  *urs_usb;
  71        struct clk              **clks;
  72        int                     num_clocks;
  73        struct reset_control    *resets;
  74
  75        int                     hs_phy_irq;
  76        int                     dp_hs_phy_irq;
  77        int                     dm_hs_phy_irq;
  78        int                     ss_phy_irq;
  79
  80        struct extcon_dev       *edev;
  81        struct extcon_dev       *host_edev;
  82        struct notifier_block   vbus_nb;
  83        struct notifier_block   host_nb;
  84
  85        const struct dwc3_acpi_pdata *acpi_pdata;
  86
  87        enum usb_dr_mode        mode;
  88        bool                    is_suspended;
  89        bool                    pm_suspended;
  90        struct icc_path         *icc_path_ddr;
  91        struct icc_path         *icc_path_apps;
  92};
  93
  94static inline void dwc3_qcom_setbits(void __iomem *base, u32 offset, u32 val)
  95{
  96        u32 reg;
  97
  98        reg = readl(base + offset);
  99        reg |= val;
 100        writel(reg, base + offset);
 101
 102        /* ensure that above write is through */
 103        readl(base + offset);
 104}
 105
 106static inline void dwc3_qcom_clrbits(void __iomem *base, u32 offset, u32 val)
 107{
 108        u32 reg;
 109
 110        reg = readl(base + offset);
 111        reg &= ~val;
 112        writel(reg, base + offset);
 113
 114        /* ensure that above write is through */
 115        readl(base + offset);
 116}
 117
 118static void dwc3_qcom_vbus_override_enable(struct dwc3_qcom *qcom, bool enable)
 119{
 120        if (enable) {
 121                dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL,
 122                                  LANE0_PWR_PRESENT);
 123                dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_HS_PHY_CTRL,
 124                                  UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
 125        } else {
 126                dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL,
 127                                  LANE0_PWR_PRESENT);
 128                dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_HS_PHY_CTRL,
 129                                  UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
 130        }
 131}
 132
 133static int dwc3_qcom_vbus_notifier(struct notifier_block *nb,
 134                                   unsigned long event, void *ptr)
 135{
 136        struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, vbus_nb);
 137
 138        /* enable vbus override for device mode */
 139        dwc3_qcom_vbus_override_enable(qcom, event);
 140        qcom->mode = event ? USB_DR_MODE_PERIPHERAL : USB_DR_MODE_HOST;
 141
 142        return NOTIFY_DONE;
 143}
 144
 145static int dwc3_qcom_host_notifier(struct notifier_block *nb,
 146                                   unsigned long event, void *ptr)
 147{
 148        struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, host_nb);
 149
 150        /* disable vbus override in host mode */
 151        dwc3_qcom_vbus_override_enable(qcom, !event);
 152        qcom->mode = event ? USB_DR_MODE_HOST : USB_DR_MODE_PERIPHERAL;
 153
 154        return NOTIFY_DONE;
 155}
 156
 157static int dwc3_qcom_register_extcon(struct dwc3_qcom *qcom)
 158{
 159        struct device           *dev = qcom->dev;
 160        struct extcon_dev       *host_edev;
 161        int                     ret;
 162
 163        if (!of_property_read_bool(dev->of_node, "extcon"))
 164                return 0;
 165
 166        qcom->edev = extcon_get_edev_by_phandle(dev, 0);
 167        if (IS_ERR(qcom->edev))
 168                return PTR_ERR(qcom->edev);
 169
 170        qcom->vbus_nb.notifier_call = dwc3_qcom_vbus_notifier;
 171
 172        qcom->host_edev = extcon_get_edev_by_phandle(dev, 1);
 173        if (IS_ERR(qcom->host_edev))
 174                qcom->host_edev = NULL;
 175
 176        ret = devm_extcon_register_notifier(dev, qcom->edev, EXTCON_USB,
 177                                            &qcom->vbus_nb);
 178        if (ret < 0) {
 179                dev_err(dev, "VBUS notifier register failed\n");
 180                return ret;
 181        }
 182
 183        if (qcom->host_edev)
 184                host_edev = qcom->host_edev;
 185        else
 186                host_edev = qcom->edev;
 187
 188        qcom->host_nb.notifier_call = dwc3_qcom_host_notifier;
 189        ret = devm_extcon_register_notifier(dev, host_edev, EXTCON_USB_HOST,
 190                                            &qcom->host_nb);
 191        if (ret < 0) {
 192                dev_err(dev, "Host notifier register failed\n");
 193                return ret;
 194        }
 195
 196        /* Update initial VBUS override based on extcon state */
 197        if (extcon_get_state(qcom->edev, EXTCON_USB) ||
 198            !extcon_get_state(host_edev, EXTCON_USB_HOST))
 199                dwc3_qcom_vbus_notifier(&qcom->vbus_nb, true, qcom->edev);
 200        else
 201                dwc3_qcom_vbus_notifier(&qcom->vbus_nb, false, qcom->edev);
 202
 203        return 0;
 204}
 205
 206static int dwc3_qcom_interconnect_enable(struct dwc3_qcom *qcom)
 207{
 208        int ret;
 209
 210        ret = icc_enable(qcom->icc_path_ddr);
 211        if (ret)
 212                return ret;
 213
 214        ret = icc_enable(qcom->icc_path_apps);
 215        if (ret)
 216                icc_disable(qcom->icc_path_ddr);
 217
 218        return ret;
 219}
 220
 221static int dwc3_qcom_interconnect_disable(struct dwc3_qcom *qcom)
 222{
 223        int ret;
 224
 225        ret = icc_disable(qcom->icc_path_ddr);
 226        if (ret)
 227                return ret;
 228
 229        ret = icc_disable(qcom->icc_path_apps);
 230        if (ret)
 231                icc_enable(qcom->icc_path_ddr);
 232
 233        return ret;
 234}
 235
 236/**
 237 * dwc3_qcom_interconnect_init() - Get interconnect path handles
 238 * and set bandwidth.
 239 * @qcom:                       Pointer to the concerned usb core.
 240 *
 241 */
 242static int dwc3_qcom_interconnect_init(struct dwc3_qcom *qcom)
 243{
 244        struct device *dev = qcom->dev;
 245        int ret;
 246
 247        if (has_acpi_companion(dev))
 248                return 0;
 249
 250        qcom->icc_path_ddr = of_icc_get(dev, "usb-ddr");
 251        if (IS_ERR(qcom->icc_path_ddr)) {
 252                dev_err(dev, "failed to get usb-ddr path: %ld\n",
 253                        PTR_ERR(qcom->icc_path_ddr));
 254                return PTR_ERR(qcom->icc_path_ddr);
 255        }
 256
 257        qcom->icc_path_apps = of_icc_get(dev, "apps-usb");
 258        if (IS_ERR(qcom->icc_path_apps)) {
 259                dev_err(dev, "failed to get apps-usb path: %ld\n",
 260                                PTR_ERR(qcom->icc_path_apps));
 261                return PTR_ERR(qcom->icc_path_apps);
 262        }
 263
 264        if (usb_get_maximum_speed(&qcom->dwc3->dev) >= USB_SPEED_SUPER ||
 265                        usb_get_maximum_speed(&qcom->dwc3->dev) == USB_SPEED_UNKNOWN)
 266                ret = icc_set_bw(qcom->icc_path_ddr,
 267                        USB_MEMORY_AVG_SS_BW, USB_MEMORY_PEAK_SS_BW);
 268        else
 269                ret = icc_set_bw(qcom->icc_path_ddr,
 270                        USB_MEMORY_AVG_HS_BW, USB_MEMORY_PEAK_HS_BW);
 271
 272        if (ret) {
 273                dev_err(dev, "failed to set bandwidth for usb-ddr path: %d\n", ret);
 274                return ret;
 275        }
 276
 277        ret = icc_set_bw(qcom->icc_path_apps,
 278                APPS_USB_AVG_BW, APPS_USB_PEAK_BW);
 279        if (ret) {
 280                dev_err(dev, "failed to set bandwidth for apps-usb path: %d\n", ret);
 281                return ret;
 282        }
 283
 284        return 0;
 285}
 286
 287/**
 288 * dwc3_qcom_interconnect_exit() - Release interconnect path handles
 289 * @qcom:                       Pointer to the concerned usb core.
 290 *
 291 * This function is used to release interconnect path handle.
 292 */
 293static void dwc3_qcom_interconnect_exit(struct dwc3_qcom *qcom)
 294{
 295        icc_put(qcom->icc_path_ddr);
 296        icc_put(qcom->icc_path_apps);
 297}
 298
 299static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom)
 300{
 301        if (qcom->hs_phy_irq) {
 302                disable_irq_wake(qcom->hs_phy_irq);
 303                disable_irq_nosync(qcom->hs_phy_irq);
 304        }
 305
 306        if (qcom->dp_hs_phy_irq) {
 307                disable_irq_wake(qcom->dp_hs_phy_irq);
 308                disable_irq_nosync(qcom->dp_hs_phy_irq);
 309        }
 310
 311        if (qcom->dm_hs_phy_irq) {
 312                disable_irq_wake(qcom->dm_hs_phy_irq);
 313                disable_irq_nosync(qcom->dm_hs_phy_irq);
 314        }
 315
 316        if (qcom->ss_phy_irq) {
 317                disable_irq_wake(qcom->ss_phy_irq);
 318                disable_irq_nosync(qcom->ss_phy_irq);
 319        }
 320}
 321
 322static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom)
 323{
 324        if (qcom->hs_phy_irq) {
 325                enable_irq(qcom->hs_phy_irq);
 326                enable_irq_wake(qcom->hs_phy_irq);
 327        }
 328
 329        if (qcom->dp_hs_phy_irq) {
 330                enable_irq(qcom->dp_hs_phy_irq);
 331                enable_irq_wake(qcom->dp_hs_phy_irq);
 332        }
 333
 334        if (qcom->dm_hs_phy_irq) {
 335                enable_irq(qcom->dm_hs_phy_irq);
 336                enable_irq_wake(qcom->dm_hs_phy_irq);
 337        }
 338
 339        if (qcom->ss_phy_irq) {
 340                enable_irq(qcom->ss_phy_irq);
 341                enable_irq_wake(qcom->ss_phy_irq);
 342        }
 343}
 344
 345static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
 346{
 347        u32 val;
 348        int i, ret;
 349
 350        if (qcom->is_suspended)
 351                return 0;
 352
 353        val = readl(qcom->qscratch_base + PWR_EVNT_IRQ_STAT_REG);
 354        if (!(val & PWR_EVNT_LPM_IN_L2_MASK))
 355                dev_err(qcom->dev, "HS-PHY not in L2\n");
 356
 357        for (i = qcom->num_clocks - 1; i >= 0; i--)
 358                clk_disable_unprepare(qcom->clks[i]);
 359
 360        ret = dwc3_qcom_interconnect_disable(qcom);
 361        if (ret)
 362                dev_warn(qcom->dev, "failed to disable interconnect: %d\n", ret);
 363
 364        if (device_may_wakeup(qcom->dev))
 365                dwc3_qcom_enable_interrupts(qcom);
 366
 367        qcom->is_suspended = true;
 368
 369        return 0;
 370}
 371
 372static int dwc3_qcom_resume(struct dwc3_qcom *qcom)
 373{
 374        int ret;
 375        int i;
 376
 377        if (!qcom->is_suspended)
 378                return 0;
 379
 380        if (device_may_wakeup(qcom->dev))
 381                dwc3_qcom_disable_interrupts(qcom);
 382
 383        for (i = 0; i < qcom->num_clocks; i++) {
 384                ret = clk_prepare_enable(qcom->clks[i]);
 385                if (ret < 0) {
 386                        while (--i >= 0)
 387                                clk_disable_unprepare(qcom->clks[i]);
 388                        return ret;
 389                }
 390        }
 391
 392        ret = dwc3_qcom_interconnect_enable(qcom);
 393        if (ret)
 394                dev_warn(qcom->dev, "failed to enable interconnect: %d\n", ret);
 395
 396        /* Clear existing events from PHY related to L2 in/out */
 397        dwc3_qcom_setbits(qcom->qscratch_base, PWR_EVNT_IRQ_STAT_REG,
 398                          PWR_EVNT_LPM_IN_L2_MASK | PWR_EVNT_LPM_OUT_L2_MASK);
 399
 400        qcom->is_suspended = false;
 401
 402        return 0;
 403}
 404
 405static irqreturn_t qcom_dwc3_resume_irq(int irq, void *data)
 406{
 407        struct dwc3_qcom *qcom = data;
 408        struct dwc3     *dwc = platform_get_drvdata(qcom->dwc3);
 409
 410        /* If pm_suspended then let pm_resume take care of resuming h/w */
 411        if (qcom->pm_suspended)
 412                return IRQ_HANDLED;
 413
 414        if (dwc->xhci)
 415                pm_runtime_resume(&dwc->xhci->dev);
 416
 417        return IRQ_HANDLED;
 418}
 419
 420static void dwc3_qcom_select_utmi_clk(struct dwc3_qcom *qcom)
 421{
 422        /* Configure dwc3 to use UTMI clock as PIPE clock not present */
 423        dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG,
 424                          PIPE_UTMI_CLK_DIS);
 425
 426        usleep_range(100, 1000);
 427
 428        dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG,
 429                          PIPE_UTMI_CLK_SEL | PIPE3_PHYSTATUS_SW);
 430
 431        usleep_range(100, 1000);
 432
 433        dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG,
 434                          PIPE_UTMI_CLK_DIS);
 435}
 436
 437static int dwc3_qcom_get_irq(struct platform_device *pdev,
 438                             const char *name, int num)
 439{
 440        struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
 441        struct platform_device *pdev_irq = qcom->urs_usb ? qcom->urs_usb : pdev;
 442        struct device_node *np = pdev->dev.of_node;
 443        int ret;
 444
 445        if (np)
 446                ret = platform_get_irq_byname(pdev_irq, name);
 447        else
 448                ret = platform_get_irq(pdev_irq, num);
 449
 450        return ret;
 451}
 452
 453static int dwc3_qcom_setup_irq(struct platform_device *pdev)
 454{
 455        struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
 456        const struct dwc3_acpi_pdata *pdata = qcom->acpi_pdata;
 457        int irq;
 458        int ret;
 459
 460        irq = dwc3_qcom_get_irq(pdev, "hs_phy_irq",
 461                                pdata ? pdata->hs_phy_irq_index : -1);
 462        if (irq > 0) {
 463                /* Keep wakeup interrupts disabled until suspend */
 464                irq_set_status_flags(irq, IRQ_NOAUTOEN);
 465                ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
 466                                        qcom_dwc3_resume_irq,
 467                                        IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
 468                                        "qcom_dwc3 HS", qcom);
 469                if (ret) {
 470                        dev_err(qcom->dev, "hs_phy_irq failed: %d\n", ret);
 471                        return ret;
 472                }
 473                qcom->hs_phy_irq = irq;
 474        }
 475
 476        irq = dwc3_qcom_get_irq(pdev, "dp_hs_phy_irq",
 477                                pdata ? pdata->dp_hs_phy_irq_index : -1);
 478        if (irq > 0) {
 479                irq_set_status_flags(irq, IRQ_NOAUTOEN);
 480                ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
 481                                        qcom_dwc3_resume_irq,
 482                                        IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
 483                                        "qcom_dwc3 DP_HS", qcom);
 484                if (ret) {
 485                        dev_err(qcom->dev, "dp_hs_phy_irq failed: %d\n", ret);
 486                        return ret;
 487                }
 488                qcom->dp_hs_phy_irq = irq;
 489        }
 490
 491        irq = dwc3_qcom_get_irq(pdev, "dm_hs_phy_irq",
 492                                pdata ? pdata->dm_hs_phy_irq_index : -1);
 493        if (irq > 0) {
 494                irq_set_status_flags(irq, IRQ_NOAUTOEN);
 495                ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
 496                                        qcom_dwc3_resume_irq,
 497                                        IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
 498                                        "qcom_dwc3 DM_HS", qcom);
 499                if (ret) {
 500                        dev_err(qcom->dev, "dm_hs_phy_irq failed: %d\n", ret);
 501                        return ret;
 502                }
 503                qcom->dm_hs_phy_irq = irq;
 504        }
 505
 506        irq = dwc3_qcom_get_irq(pdev, "ss_phy_irq",
 507                                pdata ? pdata->ss_phy_irq_index : -1);
 508        if (irq > 0) {
 509                irq_set_status_flags(irq, IRQ_NOAUTOEN);
 510                ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
 511                                        qcom_dwc3_resume_irq,
 512                                        IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
 513                                        "qcom_dwc3 SS", qcom);
 514                if (ret) {
 515                        dev_err(qcom->dev, "ss_phy_irq failed: %d\n", ret);
 516                        return ret;
 517                }
 518                qcom->ss_phy_irq = irq;
 519        }
 520
 521        return 0;
 522}
 523
 524static int dwc3_qcom_clk_init(struct dwc3_qcom *qcom, int count)
 525{
 526        struct device           *dev = qcom->dev;
 527        struct device_node      *np = dev->of_node;
 528        int                     i;
 529
 530        if (!np || !count)
 531                return 0;
 532
 533        if (count < 0)
 534                return count;
 535
 536        qcom->num_clocks = count;
 537
 538        qcom->clks = devm_kcalloc(dev, qcom->num_clocks,
 539                                  sizeof(struct clk *), GFP_KERNEL);
 540        if (!qcom->clks)
 541                return -ENOMEM;
 542
 543        for (i = 0; i < qcom->num_clocks; i++) {
 544                struct clk      *clk;
 545                int             ret;
 546
 547                clk = of_clk_get(np, i);
 548                if (IS_ERR(clk)) {
 549                        while (--i >= 0)
 550                                clk_put(qcom->clks[i]);
 551                        return PTR_ERR(clk);
 552                }
 553
 554                ret = clk_prepare_enable(clk);
 555                if (ret < 0) {
 556                        while (--i >= 0) {
 557                                clk_disable_unprepare(qcom->clks[i]);
 558                                clk_put(qcom->clks[i]);
 559                        }
 560                        clk_put(clk);
 561
 562                        return ret;
 563                }
 564
 565                qcom->clks[i] = clk;
 566        }
 567
 568        return 0;
 569}
 570
 571static const struct property_entry dwc3_qcom_acpi_properties[] = {
 572        PROPERTY_ENTRY_STRING("dr_mode", "host"),
 573        {}
 574};
 575
 576static const struct software_node dwc3_qcom_swnode = {
 577        .properties = dwc3_qcom_acpi_properties,
 578};
 579
 580static int dwc3_qcom_acpi_register_core(struct platform_device *pdev)
 581{
 582        struct dwc3_qcom        *qcom = platform_get_drvdata(pdev);
 583        struct device           *dev = &pdev->dev;
 584        struct resource         *res, *child_res = NULL;
 585        struct platform_device  *pdev_irq = qcom->urs_usb ? qcom->urs_usb :
 586                                                            pdev;
 587        int                     irq;
 588        int                     ret;
 589
 590        qcom->dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
 591        if (!qcom->dwc3)
 592                return -ENOMEM;
 593
 594        qcom->dwc3->dev.parent = dev;
 595        qcom->dwc3->dev.type = dev->type;
 596        qcom->dwc3->dev.dma_mask = dev->dma_mask;
 597        qcom->dwc3->dev.dma_parms = dev->dma_parms;
 598        qcom->dwc3->dev.coherent_dma_mask = dev->coherent_dma_mask;
 599
 600        child_res = kcalloc(2, sizeof(*child_res), GFP_KERNEL);
 601        if (!child_res)
 602                return -ENOMEM;
 603
 604        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 605        if (!res) {
 606                dev_err(&pdev->dev, "failed to get memory resource\n");
 607                ret = -ENODEV;
 608                goto out;
 609        }
 610
 611        child_res[0].flags = res->flags;
 612        child_res[0].start = res->start;
 613        child_res[0].end = child_res[0].start +
 614                qcom->acpi_pdata->dwc3_core_base_size;
 615
 616        irq = platform_get_irq(pdev_irq, 0);
 617        if (irq < 0) {
 618                ret = irq;
 619                goto out;
 620        }
 621        child_res[1].flags = IORESOURCE_IRQ;
 622        child_res[1].start = child_res[1].end = irq;
 623
 624        ret = platform_device_add_resources(qcom->dwc3, child_res, 2);
 625        if (ret) {
 626                dev_err(&pdev->dev, "failed to add resources\n");
 627                goto out;
 628        }
 629
 630        ret = device_add_software_node(&qcom->dwc3->dev, &dwc3_qcom_swnode);
 631        if (ret < 0) {
 632                dev_err(&pdev->dev, "failed to add properties\n");
 633                goto out;
 634        }
 635
 636        ret = platform_device_add(qcom->dwc3);
 637        if (ret) {
 638                dev_err(&pdev->dev, "failed to add device\n");
 639                device_remove_software_node(&qcom->dwc3->dev);
 640        }
 641
 642out:
 643        kfree(child_res);
 644        return ret;
 645}
 646
 647static int dwc3_qcom_of_register_core(struct platform_device *pdev)
 648{
 649        struct dwc3_qcom        *qcom = platform_get_drvdata(pdev);
 650        struct device_node      *np = pdev->dev.of_node, *dwc3_np;
 651        struct device           *dev = &pdev->dev;
 652        struct property         *prop;
 653        int                     ret;
 654
 655        dwc3_np = of_get_compatible_child(np, "snps,dwc3");
 656        if (!dwc3_np) {
 657                dev_err(dev, "failed to find dwc3 core child\n");
 658                return -ENODEV;
 659        }
 660
 661        prop = devm_kzalloc(dev, sizeof(*prop), GFP_KERNEL);
 662        if (!prop) {
 663                ret = -ENOMEM;
 664                dev_err(dev, "unable to allocate memory for property\n");
 665                goto node_put;
 666        }
 667
 668        prop->name = "tx-fifo-resize";
 669        ret = of_add_property(dwc3_np, prop);
 670        if (ret) {
 671                dev_err(dev, "unable to add property\n");
 672                goto node_put;
 673        }
 674
 675        ret = of_platform_populate(np, NULL, NULL, dev);
 676        if (ret) {
 677                dev_err(dev, "failed to register dwc3 core - %d\n", ret);
 678                goto node_put;
 679        }
 680
 681        qcom->dwc3 = of_find_device_by_node(dwc3_np);
 682        if (!qcom->dwc3) {
 683                ret = -ENODEV;
 684                dev_err(dev, "failed to get dwc3 platform device\n");
 685        }
 686
 687node_put:
 688        of_node_put(dwc3_np);
 689
 690        return ret;
 691}
 692
 693static struct platform_device *
 694dwc3_qcom_create_urs_usb_platdev(struct device *dev)
 695{
 696        struct fwnode_handle *fwh;
 697        struct acpi_device *adev;
 698        char name[8];
 699        int ret;
 700        int id;
 701
 702        /* Figure out device id */
 703        ret = sscanf(fwnode_get_name(dev->fwnode), "URS%d", &id);
 704        if (!ret)
 705                return NULL;
 706
 707        /* Find the child using name */
 708        snprintf(name, sizeof(name), "USB%d", id);
 709        fwh = fwnode_get_named_child_node(dev->fwnode, name);
 710        if (!fwh)
 711                return NULL;
 712
 713        adev = to_acpi_device_node(fwh);
 714        if (!adev)
 715                return NULL;
 716
 717        return acpi_create_platform_device(adev, NULL);
 718}
 719
 720static int dwc3_qcom_probe(struct platform_device *pdev)
 721{
 722        struct device_node      *np = pdev->dev.of_node;
 723        struct device           *dev = &pdev->dev;
 724        struct dwc3_qcom        *qcom;
 725        struct resource         *res, *parent_res = NULL;
 726        int                     ret, i;
 727        bool                    ignore_pipe_clk;
 728
 729        qcom = devm_kzalloc(&pdev->dev, sizeof(*qcom), GFP_KERNEL);
 730        if (!qcom)
 731                return -ENOMEM;
 732
 733        platform_set_drvdata(pdev, qcom);
 734        qcom->dev = &pdev->dev;
 735
 736        if (has_acpi_companion(dev)) {
 737                qcom->acpi_pdata = acpi_device_get_match_data(dev);
 738                if (!qcom->acpi_pdata) {
 739                        dev_err(&pdev->dev, "no supporting ACPI device data\n");
 740                        return -EINVAL;
 741                }
 742        }
 743
 744        qcom->resets = devm_reset_control_array_get_optional_exclusive(dev);
 745        if (IS_ERR(qcom->resets)) {
 746                ret = PTR_ERR(qcom->resets);
 747                dev_err(&pdev->dev, "failed to get resets, err=%d\n", ret);
 748                return ret;
 749        }
 750
 751        ret = reset_control_assert(qcom->resets);
 752        if (ret) {
 753                dev_err(&pdev->dev, "failed to assert resets, err=%d\n", ret);
 754                return ret;
 755        }
 756
 757        usleep_range(10, 1000);
 758
 759        ret = reset_control_deassert(qcom->resets);
 760        if (ret) {
 761                dev_err(&pdev->dev, "failed to deassert resets, err=%d\n", ret);
 762                goto reset_assert;
 763        }
 764
 765        ret = dwc3_qcom_clk_init(qcom, of_clk_get_parent_count(np));
 766        if (ret) {
 767                dev_err(dev, "failed to get clocks\n");
 768                goto reset_assert;
 769        }
 770
 771        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 772
 773        if (np) {
 774                parent_res = res;
 775        } else {
 776                parent_res = kmemdup(res, sizeof(struct resource), GFP_KERNEL);
 777                if (!parent_res)
 778                        return -ENOMEM;
 779
 780                parent_res->start = res->start +
 781                        qcom->acpi_pdata->qscratch_base_offset;
 782                parent_res->end = parent_res->start +
 783                        qcom->acpi_pdata->qscratch_base_size;
 784
 785                if (qcom->acpi_pdata->is_urs) {
 786                        qcom->urs_usb = dwc3_qcom_create_urs_usb_platdev(dev);
 787                        if (!qcom->urs_usb) {
 788                                dev_err(dev, "failed to create URS USB platdev\n");
 789                                return -ENODEV;
 790                        }
 791                }
 792        }
 793
 794        qcom->qscratch_base = devm_ioremap_resource(dev, parent_res);
 795        if (IS_ERR(qcom->qscratch_base)) {
 796                ret = PTR_ERR(qcom->qscratch_base);
 797                goto clk_disable;
 798        }
 799
 800        ret = dwc3_qcom_setup_irq(pdev);
 801        if (ret) {
 802                dev_err(dev, "failed to setup IRQs, err=%d\n", ret);
 803                goto clk_disable;
 804        }
 805
 806        /*
 807         * Disable pipe_clk requirement if specified. Used when dwc3
 808         * operates without SSPHY and only HS/FS/LS modes are supported.
 809         */
 810        ignore_pipe_clk = device_property_read_bool(dev,
 811                                "qcom,select-utmi-as-pipe-clk");
 812        if (ignore_pipe_clk)
 813                dwc3_qcom_select_utmi_clk(qcom);
 814
 815        if (np)
 816                ret = dwc3_qcom_of_register_core(pdev);
 817        else
 818                ret = dwc3_qcom_acpi_register_core(pdev);
 819
 820        if (ret) {
 821                dev_err(dev, "failed to register DWC3 Core, err=%d\n", ret);
 822                goto depopulate;
 823        }
 824
 825        ret = dwc3_qcom_interconnect_init(qcom);
 826        if (ret)
 827                goto depopulate;
 828
 829        qcom->mode = usb_get_dr_mode(&qcom->dwc3->dev);
 830
 831        /* enable vbus override for device mode */
 832        if (qcom->mode == USB_DR_MODE_PERIPHERAL)
 833                dwc3_qcom_vbus_override_enable(qcom, true);
 834
 835        /* register extcon to override sw_vbus on Vbus change later */
 836        ret = dwc3_qcom_register_extcon(qcom);
 837        if (ret)
 838                goto interconnect_exit;
 839
 840        device_init_wakeup(&pdev->dev, 1);
 841        qcom->is_suspended = false;
 842        pm_runtime_set_active(dev);
 843        pm_runtime_enable(dev);
 844        pm_runtime_forbid(dev);
 845
 846        return 0;
 847
 848interconnect_exit:
 849        dwc3_qcom_interconnect_exit(qcom);
 850depopulate:
 851        if (np)
 852                of_platform_depopulate(&pdev->dev);
 853        else
 854                platform_device_put(pdev);
 855clk_disable:
 856        for (i = qcom->num_clocks - 1; i >= 0; i--) {
 857                clk_disable_unprepare(qcom->clks[i]);
 858                clk_put(qcom->clks[i]);
 859        }
 860reset_assert:
 861        reset_control_assert(qcom->resets);
 862
 863        return ret;
 864}
 865
 866static int dwc3_qcom_remove(struct platform_device *pdev)
 867{
 868        struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
 869        struct device *dev = &pdev->dev;
 870        int i;
 871
 872        device_remove_software_node(&qcom->dwc3->dev);
 873        of_platform_depopulate(dev);
 874
 875        for (i = qcom->num_clocks - 1; i >= 0; i--) {
 876                clk_disable_unprepare(qcom->clks[i]);
 877                clk_put(qcom->clks[i]);
 878        }
 879        qcom->num_clocks = 0;
 880
 881        dwc3_qcom_interconnect_exit(qcom);
 882        reset_control_assert(qcom->resets);
 883
 884        pm_runtime_allow(dev);
 885        pm_runtime_disable(dev);
 886
 887        return 0;
 888}
 889
 890static int __maybe_unused dwc3_qcom_pm_suspend(struct device *dev)
 891{
 892        struct dwc3_qcom *qcom = dev_get_drvdata(dev);
 893        int ret = 0;
 894
 895        ret = dwc3_qcom_suspend(qcom);
 896        if (!ret)
 897                qcom->pm_suspended = true;
 898
 899        return ret;
 900}
 901
 902static int __maybe_unused dwc3_qcom_pm_resume(struct device *dev)
 903{
 904        struct dwc3_qcom *qcom = dev_get_drvdata(dev);
 905        int ret;
 906
 907        ret = dwc3_qcom_resume(qcom);
 908        if (!ret)
 909                qcom->pm_suspended = false;
 910
 911        return ret;
 912}
 913
 914static int __maybe_unused dwc3_qcom_runtime_suspend(struct device *dev)
 915{
 916        struct dwc3_qcom *qcom = dev_get_drvdata(dev);
 917
 918        return dwc3_qcom_suspend(qcom);
 919}
 920
 921static int __maybe_unused dwc3_qcom_runtime_resume(struct device *dev)
 922{
 923        struct dwc3_qcom *qcom = dev_get_drvdata(dev);
 924
 925        return dwc3_qcom_resume(qcom);
 926}
 927
 928static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = {
 929        SET_SYSTEM_SLEEP_PM_OPS(dwc3_qcom_pm_suspend, dwc3_qcom_pm_resume)
 930        SET_RUNTIME_PM_OPS(dwc3_qcom_runtime_suspend, dwc3_qcom_runtime_resume,
 931                           NULL)
 932};
 933
 934static const struct of_device_id dwc3_qcom_of_match[] = {
 935        { .compatible = "qcom,dwc3" },
 936        { .compatible = "qcom,msm8996-dwc3" },
 937        { .compatible = "qcom,msm8998-dwc3" },
 938        { .compatible = "qcom,sdm660-dwc3" },
 939        { .compatible = "qcom,sdm845-dwc3" },
 940        { }
 941};
 942MODULE_DEVICE_TABLE(of, dwc3_qcom_of_match);
 943
 944#ifdef CONFIG_ACPI
 945static const struct dwc3_acpi_pdata sdm845_acpi_pdata = {
 946        .qscratch_base_offset = SDM845_QSCRATCH_BASE_OFFSET,
 947        .qscratch_base_size = SDM845_QSCRATCH_SIZE,
 948        .dwc3_core_base_size = SDM845_DWC3_CORE_SIZE,
 949        .hs_phy_irq_index = 1,
 950        .dp_hs_phy_irq_index = 4,
 951        .dm_hs_phy_irq_index = 3,
 952        .ss_phy_irq_index = 2
 953};
 954
 955static const struct dwc3_acpi_pdata sdm845_acpi_urs_pdata = {
 956        .qscratch_base_offset = SDM845_QSCRATCH_BASE_OFFSET,
 957        .qscratch_base_size = SDM845_QSCRATCH_SIZE,
 958        .dwc3_core_base_size = SDM845_DWC3_CORE_SIZE,
 959        .hs_phy_irq_index = 1,
 960        .dp_hs_phy_irq_index = 4,
 961        .dm_hs_phy_irq_index = 3,
 962        .ss_phy_irq_index = 2,
 963        .is_urs = true,
 964};
 965
 966static const struct acpi_device_id dwc3_qcom_acpi_match[] = {
 967        { "QCOM2430", (unsigned long)&sdm845_acpi_pdata },
 968        { "QCOM0304", (unsigned long)&sdm845_acpi_urs_pdata },
 969        { "QCOM0497", (unsigned long)&sdm845_acpi_urs_pdata },
 970        { "QCOM04A6", (unsigned long)&sdm845_acpi_pdata },
 971        { },
 972};
 973MODULE_DEVICE_TABLE(acpi, dwc3_qcom_acpi_match);
 974#endif
 975
 976static struct platform_driver dwc3_qcom_driver = {
 977        .probe          = dwc3_qcom_probe,
 978        .remove         = dwc3_qcom_remove,
 979        .driver         = {
 980                .name   = "dwc3-qcom",
 981                .pm     = &dwc3_qcom_dev_pm_ops,
 982                .of_match_table = dwc3_qcom_of_match,
 983                .acpi_match_table = ACPI_PTR(dwc3_qcom_acpi_match),
 984        },
 985};
 986
 987module_platform_driver(dwc3_qcom_driver);
 988
 989MODULE_LICENSE("GPL v2");
 990MODULE_DESCRIPTION("DesignWare DWC3 QCOM Glue Driver");
 991