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                platform_device_put(qcom->dwc3);
 603                return -ENOMEM;
 604        }
 605
 606        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 607        if (!res) {
 608                dev_err(&pdev->dev, "failed to get memory resource\n");
 609                ret = -ENODEV;
 610                goto out;
 611        }
 612
 613        child_res[0].flags = res->flags;
 614        child_res[0].start = res->start;
 615        child_res[0].end = child_res[0].start +
 616                qcom->acpi_pdata->dwc3_core_base_size;
 617
 618        irq = platform_get_irq(pdev_irq, 0);
 619        if (irq < 0) {
 620                ret = irq;
 621                goto out;
 622        }
 623        child_res[1].flags = IORESOURCE_IRQ;
 624        child_res[1].start = child_res[1].end = irq;
 625
 626        ret = platform_device_add_resources(qcom->dwc3, child_res, 2);
 627        if (ret) {
 628                dev_err(&pdev->dev, "failed to add resources\n");
 629                goto out;
 630        }
 631
 632        ret = device_add_software_node(&qcom->dwc3->dev, &dwc3_qcom_swnode);
 633        if (ret < 0) {
 634                dev_err(&pdev->dev, "failed to add properties\n");
 635                goto out;
 636        }
 637
 638        ret = platform_device_add(qcom->dwc3);
 639        if (ret) {
 640                dev_err(&pdev->dev, "failed to add device\n");
 641                device_remove_software_node(&qcom->dwc3->dev);
 642                goto out;
 643        }
 644        kfree(child_res);
 645        return 0;
 646
 647out:
 648        platform_device_put(qcom->dwc3);
 649        kfree(child_res);
 650        return ret;
 651}
 652
 653static int dwc3_qcom_of_register_core(struct platform_device *pdev)
 654{
 655        struct dwc3_qcom        *qcom = platform_get_drvdata(pdev);
 656        struct device_node      *np = pdev->dev.of_node, *dwc3_np;
 657        struct device           *dev = &pdev->dev;
 658        int                     ret;
 659
 660        dwc3_np = of_get_compatible_child(np, "snps,dwc3");
 661        if (!dwc3_np) {
 662                dev_err(dev, "failed to find dwc3 core child\n");
 663                return -ENODEV;
 664        }
 665
 666        ret = of_platform_populate(np, NULL, NULL, dev);
 667        if (ret) {
 668                dev_err(dev, "failed to register dwc3 core - %d\n", ret);
 669                goto node_put;
 670        }
 671
 672        qcom->dwc3 = of_find_device_by_node(dwc3_np);
 673        if (!qcom->dwc3) {
 674                ret = -ENODEV;
 675                dev_err(dev, "failed to get dwc3 platform device\n");
 676        }
 677
 678node_put:
 679        of_node_put(dwc3_np);
 680
 681        return ret;
 682}
 683
 684static struct platform_device *
 685dwc3_qcom_create_urs_usb_platdev(struct device *dev)
 686{
 687        struct fwnode_handle *fwh;
 688        struct acpi_device *adev;
 689        char name[8];
 690        int ret;
 691        int id;
 692
 693        /* Figure out device id */
 694        ret = sscanf(fwnode_get_name(dev->fwnode), "URS%d", &id);
 695        if (!ret)
 696                return NULL;
 697
 698        /* Find the child using name */
 699        snprintf(name, sizeof(name), "USB%d", id);
 700        fwh = fwnode_get_named_child_node(dev->fwnode, name);
 701        if (!fwh)
 702                return NULL;
 703
 704        adev = to_acpi_device_node(fwh);
 705        if (!adev)
 706                return NULL;
 707
 708        return acpi_create_platform_device(adev, NULL);
 709}
 710
 711static int dwc3_qcom_probe(struct platform_device *pdev)
 712{
 713        struct device_node      *np = pdev->dev.of_node;
 714        struct device           *dev = &pdev->dev;
 715        struct dwc3_qcom        *qcom;
 716        struct resource         *res, *parent_res = NULL;
 717        int                     ret, i;
 718        bool                    ignore_pipe_clk;
 719
 720        qcom = devm_kzalloc(&pdev->dev, sizeof(*qcom), GFP_KERNEL);
 721        if (!qcom)
 722                return -ENOMEM;
 723
 724        platform_set_drvdata(pdev, qcom);
 725        qcom->dev = &pdev->dev;
 726
 727        if (has_acpi_companion(dev)) {
 728                qcom->acpi_pdata = acpi_device_get_match_data(dev);
 729                if (!qcom->acpi_pdata) {
 730                        dev_err(&pdev->dev, "no supporting ACPI device data\n");
 731                        return -EINVAL;
 732                }
 733        }
 734
 735        qcom->resets = devm_reset_control_array_get_optional_exclusive(dev);
 736        if (IS_ERR(qcom->resets)) {
 737                ret = PTR_ERR(qcom->resets);
 738                dev_err(&pdev->dev, "failed to get resets, err=%d\n", ret);
 739                return ret;
 740        }
 741
 742        ret = reset_control_assert(qcom->resets);
 743        if (ret) {
 744                dev_err(&pdev->dev, "failed to assert resets, err=%d\n", ret);
 745                return ret;
 746        }
 747
 748        usleep_range(10, 1000);
 749
 750        ret = reset_control_deassert(qcom->resets);
 751        if (ret) {
 752                dev_err(&pdev->dev, "failed to deassert resets, err=%d\n", ret);
 753                goto reset_assert;
 754        }
 755
 756        ret = dwc3_qcom_clk_init(qcom, of_clk_get_parent_count(np));
 757        if (ret) {
 758                dev_err(dev, "failed to get clocks\n");
 759                goto reset_assert;
 760        }
 761
 762        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 763
 764        if (np) {
 765                parent_res = res;
 766        } else {
 767                parent_res = kmemdup(res, sizeof(struct resource), GFP_KERNEL);
 768                if (!parent_res)
 769                        return -ENOMEM;
 770
 771                parent_res->start = res->start +
 772                        qcom->acpi_pdata->qscratch_base_offset;
 773                parent_res->end = parent_res->start +
 774                        qcom->acpi_pdata->qscratch_base_size;
 775
 776                if (qcom->acpi_pdata->is_urs) {
 777                        qcom->urs_usb = dwc3_qcom_create_urs_usb_platdev(dev);
 778                        if (IS_ERR_OR_NULL(qcom->urs_usb)) {
 779                                dev_err(dev, "failed to create URS USB platdev\n");
 780                                if (!qcom->urs_usb)
 781                                        return -ENODEV;
 782                                else
 783                                        return PTR_ERR(qcom->urs_usb);
 784                        }
 785                }
 786        }
 787
 788        qcom->qscratch_base = devm_ioremap_resource(dev, parent_res);
 789        if (IS_ERR(qcom->qscratch_base)) {
 790                ret = PTR_ERR(qcom->qscratch_base);
 791                goto clk_disable;
 792        }
 793
 794        ret = dwc3_qcom_setup_irq(pdev);
 795        if (ret) {
 796                dev_err(dev, "failed to setup IRQs, err=%d\n", ret);
 797                goto clk_disable;
 798        }
 799
 800        /*
 801         * Disable pipe_clk requirement if specified. Used when dwc3
 802         * operates without SSPHY and only HS/FS/LS modes are supported.
 803         */
 804        ignore_pipe_clk = device_property_read_bool(dev,
 805                                "qcom,select-utmi-as-pipe-clk");
 806        if (ignore_pipe_clk)
 807                dwc3_qcom_select_utmi_clk(qcom);
 808
 809        if (np)
 810                ret = dwc3_qcom_of_register_core(pdev);
 811        else
 812                ret = dwc3_qcom_acpi_register_core(pdev);
 813
 814        if (ret) {
 815                dev_err(dev, "failed to register DWC3 Core, err=%d\n", ret);
 816                goto depopulate;
 817        }
 818
 819        ret = dwc3_qcom_interconnect_init(qcom);
 820        if (ret)
 821                goto depopulate;
 822
 823        qcom->mode = usb_get_dr_mode(&qcom->dwc3->dev);
 824
 825        /* enable vbus override for device mode */
 826        if (qcom->mode == USB_DR_MODE_PERIPHERAL)
 827                dwc3_qcom_vbus_override_enable(qcom, true);
 828
 829        /* register extcon to override sw_vbus on Vbus change later */
 830        ret = dwc3_qcom_register_extcon(qcom);
 831        if (ret)
 832                goto interconnect_exit;
 833
 834        device_init_wakeup(&pdev->dev, 1);
 835        qcom->is_suspended = false;
 836        pm_runtime_set_active(dev);
 837        pm_runtime_enable(dev);
 838        pm_runtime_forbid(dev);
 839
 840        return 0;
 841
 842interconnect_exit:
 843        dwc3_qcom_interconnect_exit(qcom);
 844depopulate:
 845        if (np)
 846                of_platform_depopulate(&pdev->dev);
 847        else
 848                platform_device_put(pdev);
 849clk_disable:
 850        for (i = qcom->num_clocks - 1; i >= 0; i--) {
 851                clk_disable_unprepare(qcom->clks[i]);
 852                clk_put(qcom->clks[i]);
 853        }
 854reset_assert:
 855        reset_control_assert(qcom->resets);
 856
 857        return ret;
 858}
 859
 860static int dwc3_qcom_remove(struct platform_device *pdev)
 861{
 862        struct dwc3_qcom *qcom = platform_get_drvdata(pdev);
 863        struct device *dev = &pdev->dev;
 864        int i;
 865
 866        device_remove_software_node(&qcom->dwc3->dev);
 867        of_platform_depopulate(dev);
 868
 869        for (i = qcom->num_clocks - 1; i >= 0; i--) {
 870                clk_disable_unprepare(qcom->clks[i]);
 871                clk_put(qcom->clks[i]);
 872        }
 873        qcom->num_clocks = 0;
 874
 875        dwc3_qcom_interconnect_exit(qcom);
 876        reset_control_assert(qcom->resets);
 877
 878        pm_runtime_allow(dev);
 879        pm_runtime_disable(dev);
 880
 881        return 0;
 882}
 883
 884static int __maybe_unused dwc3_qcom_pm_suspend(struct device *dev)
 885{
 886        struct dwc3_qcom *qcom = dev_get_drvdata(dev);
 887        int ret = 0;
 888
 889        ret = dwc3_qcom_suspend(qcom);
 890        if (!ret)
 891                qcom->pm_suspended = true;
 892
 893        return ret;
 894}
 895
 896static int __maybe_unused dwc3_qcom_pm_resume(struct device *dev)
 897{
 898        struct dwc3_qcom *qcom = dev_get_drvdata(dev);
 899        int ret;
 900
 901        ret = dwc3_qcom_resume(qcom);
 902        if (!ret)
 903                qcom->pm_suspended = false;
 904
 905        return ret;
 906}
 907
 908static int __maybe_unused dwc3_qcom_runtime_suspend(struct device *dev)
 909{
 910        struct dwc3_qcom *qcom = dev_get_drvdata(dev);
 911
 912        return dwc3_qcom_suspend(qcom);
 913}
 914
 915static int __maybe_unused dwc3_qcom_runtime_resume(struct device *dev)
 916{
 917        struct dwc3_qcom *qcom = dev_get_drvdata(dev);
 918
 919        return dwc3_qcom_resume(qcom);
 920}
 921
 922static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = {
 923        SET_SYSTEM_SLEEP_PM_OPS(dwc3_qcom_pm_suspend, dwc3_qcom_pm_resume)
 924        SET_RUNTIME_PM_OPS(dwc3_qcom_runtime_suspend, dwc3_qcom_runtime_resume,
 925                           NULL)
 926};
 927
 928static const struct of_device_id dwc3_qcom_of_match[] = {
 929        { .compatible = "qcom,dwc3" },
 930        { .compatible = "qcom,msm8996-dwc3" },
 931        { .compatible = "qcom,msm8998-dwc3" },
 932        { .compatible = "qcom,sdm660-dwc3" },
 933        { .compatible = "qcom,sdm845-dwc3" },
 934        { }
 935};
 936MODULE_DEVICE_TABLE(of, dwc3_qcom_of_match);
 937
 938#ifdef CONFIG_ACPI
 939static const struct dwc3_acpi_pdata sdm845_acpi_pdata = {
 940        .qscratch_base_offset = SDM845_QSCRATCH_BASE_OFFSET,
 941        .qscratch_base_size = SDM845_QSCRATCH_SIZE,
 942        .dwc3_core_base_size = SDM845_DWC3_CORE_SIZE,
 943        .hs_phy_irq_index = 1,
 944        .dp_hs_phy_irq_index = 4,
 945        .dm_hs_phy_irq_index = 3,
 946        .ss_phy_irq_index = 2
 947};
 948
 949static const struct dwc3_acpi_pdata sdm845_acpi_urs_pdata = {
 950        .qscratch_base_offset = SDM845_QSCRATCH_BASE_OFFSET,
 951        .qscratch_base_size = SDM845_QSCRATCH_SIZE,
 952        .dwc3_core_base_size = SDM845_DWC3_CORE_SIZE,
 953        .hs_phy_irq_index = 1,
 954        .dp_hs_phy_irq_index = 4,
 955        .dm_hs_phy_irq_index = 3,
 956        .ss_phy_irq_index = 2,
 957        .is_urs = true,
 958};
 959
 960static const struct acpi_device_id dwc3_qcom_acpi_match[] = {
 961        { "QCOM2430", (unsigned long)&sdm845_acpi_pdata },
 962        { "QCOM0304", (unsigned long)&sdm845_acpi_urs_pdata },
 963        { "QCOM0497", (unsigned long)&sdm845_acpi_urs_pdata },
 964        { "QCOM04A6", (unsigned long)&sdm845_acpi_pdata },
 965        { },
 966};
 967MODULE_DEVICE_TABLE(acpi, dwc3_qcom_acpi_match);
 968#endif
 969
 970static struct platform_driver dwc3_qcom_driver = {
 971        .probe          = dwc3_qcom_probe,
 972        .remove         = dwc3_qcom_remove,
 973        .driver         = {
 974                .name   = "dwc3-qcom",
 975                .pm     = &dwc3_qcom_dev_pm_ops,
 976                .of_match_table = dwc3_qcom_of_match,
 977                .acpi_match_table = ACPI_PTR(dwc3_qcom_acpi_match),
 978        },
 979};
 980
 981module_platform_driver(dwc3_qcom_driver);
 982
 983MODULE_LICENSE("GPL v2");
 984MODULE_DESCRIPTION("DesignWare DWC3 QCOM Glue Driver");
 985