linux/drivers/usb/chipidea/ci_hdrc_imx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2012 Freescale Semiconductor, Inc.
   4 * Copyright (C) 2012 Marek Vasut <marex@denx.de>
   5 * on behalf of DENX Software Engineering GmbH
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/of_platform.h>
  10#include <linux/platform_device.h>
  11#include <linux/pm_runtime.h>
  12#include <linux/usb/chipidea.h>
  13#include <linux/usb/of.h>
  14#include <linux/clk.h>
  15#include <linux/pinctrl/consumer.h>
  16#include <linux/pm_qos.h>
  17
  18#include "ci.h"
  19#include "ci_hdrc_imx.h"
  20
  21struct ci_hdrc_imx_platform_flag {
  22        unsigned int flags;
  23};
  24
  25static const struct ci_hdrc_imx_platform_flag imx23_usb_data = {
  26        .flags = CI_HDRC_TURN_VBUS_EARLY_ON |
  27                CI_HDRC_DISABLE_STREAMING,
  28};
  29
  30static const struct ci_hdrc_imx_platform_flag imx27_usb_data = {
  31        .flags = CI_HDRC_DISABLE_STREAMING,
  32};
  33
  34static const struct ci_hdrc_imx_platform_flag imx28_usb_data = {
  35        .flags = CI_HDRC_IMX28_WRITE_FIX |
  36                CI_HDRC_TURN_VBUS_EARLY_ON |
  37                CI_HDRC_DISABLE_STREAMING,
  38};
  39
  40static const struct ci_hdrc_imx_platform_flag imx6q_usb_data = {
  41        .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
  42                CI_HDRC_TURN_VBUS_EARLY_ON |
  43                CI_HDRC_DISABLE_STREAMING,
  44};
  45
  46static const struct ci_hdrc_imx_platform_flag imx6sl_usb_data = {
  47        .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
  48                CI_HDRC_TURN_VBUS_EARLY_ON |
  49                CI_HDRC_DISABLE_HOST_STREAMING,
  50};
  51
  52static const struct ci_hdrc_imx_platform_flag imx6sx_usb_data = {
  53        .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
  54                CI_HDRC_TURN_VBUS_EARLY_ON |
  55                CI_HDRC_DISABLE_HOST_STREAMING,
  56};
  57
  58static const struct ci_hdrc_imx_platform_flag imx6ul_usb_data = {
  59        .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
  60                CI_HDRC_TURN_VBUS_EARLY_ON |
  61                CI_HDRC_DISABLE_DEVICE_STREAMING,
  62};
  63
  64static const struct ci_hdrc_imx_platform_flag imx7d_usb_data = {
  65        .flags = CI_HDRC_SUPPORTS_RUNTIME_PM,
  66};
  67
  68static const struct ci_hdrc_imx_platform_flag imx7ulp_usb_data = {
  69        .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
  70                CI_HDRC_PMQOS,
  71};
  72
  73static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
  74        { .compatible = "fsl,imx23-usb", .data = &imx23_usb_data},
  75        { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data},
  76        { .compatible = "fsl,imx27-usb", .data = &imx27_usb_data},
  77        { .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data},
  78        { .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data},
  79        { .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data},
  80        { .compatible = "fsl,imx6ul-usb", .data = &imx6ul_usb_data},
  81        { .compatible = "fsl,imx7d-usb", .data = &imx7d_usb_data},
  82        { .compatible = "fsl,imx7ulp-usb", .data = &imx7ulp_usb_data},
  83        { /* sentinel */ }
  84};
  85MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
  86
  87struct ci_hdrc_imx_data {
  88        struct usb_phy *phy;
  89        struct platform_device *ci_pdev;
  90        struct clk *clk;
  91        struct imx_usbmisc_data *usbmisc_data;
  92        bool supports_runtime_pm;
  93        bool override_phy_control;
  94        bool in_lpm;
  95        struct pinctrl *pinctrl;
  96        struct pinctrl_state *pinctrl_hsic_active;
  97        struct regulator *hsic_pad_regulator;
  98        /* SoC before i.mx6 (except imx23/imx28) needs three clks */
  99        bool need_three_clks;
 100        struct clk *clk_ipg;
 101        struct clk *clk_ahb;
 102        struct clk *clk_per;
 103        /* --------------------------------- */
 104        struct pm_qos_request pm_qos_req;
 105        const struct ci_hdrc_imx_platform_flag *plat_data;
 106};
 107
 108/* Common functions shared by usbmisc drivers */
 109
 110static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
 111{
 112        struct platform_device *misc_pdev;
 113        struct device_node *np = dev->of_node;
 114        struct of_phandle_args args;
 115        struct imx_usbmisc_data *data;
 116        int ret;
 117
 118        /*
 119         * In case the fsl,usbmisc property is not present this device doesn't
 120         * need usbmisc. Return NULL (which is no error here)
 121         */
 122        if (!of_get_property(np, "fsl,usbmisc", NULL))
 123                return NULL;
 124
 125        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 126        if (!data)
 127                return ERR_PTR(-ENOMEM);
 128
 129        ret = of_parse_phandle_with_args(np, "fsl,usbmisc", "#index-cells",
 130                                        0, &args);
 131        if (ret) {
 132                dev_err(dev, "Failed to parse property fsl,usbmisc, errno %d\n",
 133                        ret);
 134                return ERR_PTR(ret);
 135        }
 136
 137        data->index = args.args[0];
 138
 139        misc_pdev = of_find_device_by_node(args.np);
 140        of_node_put(args.np);
 141
 142        if (!misc_pdev)
 143                return ERR_PTR(-EPROBE_DEFER);
 144
 145        if (!platform_get_drvdata(misc_pdev)) {
 146                put_device(&misc_pdev->dev);
 147                return ERR_PTR(-EPROBE_DEFER);
 148        }
 149        data->dev = &misc_pdev->dev;
 150
 151        /*
 152         * Check the various over current related properties. If over current
 153         * detection is disabled we're not interested in the polarity.
 154         */
 155        if (of_find_property(np, "disable-over-current", NULL)) {
 156                data->disable_oc = 1;
 157        } else if (of_find_property(np, "over-current-active-high", NULL)) {
 158                data->oc_pol_active_low = 0;
 159                data->oc_pol_configured = 1;
 160        } else if (of_find_property(np, "over-current-active-low", NULL)) {
 161                data->oc_pol_active_low = 1;
 162                data->oc_pol_configured = 1;
 163        } else {
 164                dev_warn(dev, "No over current polarity defined\n");
 165        }
 166
 167        data->pwr_pol = of_property_read_bool(np, "power-active-high");
 168        data->evdo = of_property_read_bool(np, "external-vbus-divider");
 169
 170        if (of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI)
 171                data->ulpi = 1;
 172
 173        of_property_read_u32(np, "samsung,picophy-pre-emp-curr-control",
 174                        &data->emp_curr_control);
 175        of_property_read_u32(np, "samsung,picophy-dc-vol-level-adjust",
 176                        &data->dc_vol_level_adjust);
 177
 178        return data;
 179}
 180
 181/* End of common functions shared by usbmisc drivers*/
 182static int imx_get_clks(struct device *dev)
 183{
 184        struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
 185        int ret = 0;
 186
 187        data->clk_ipg = devm_clk_get(dev, "ipg");
 188        if (IS_ERR(data->clk_ipg)) {
 189                /* If the platform only needs one clocks */
 190                data->clk = devm_clk_get(dev, NULL);
 191                if (IS_ERR(data->clk)) {
 192                        ret = PTR_ERR(data->clk);
 193                        dev_err(dev,
 194                                "Failed to get clks, err=%ld,%ld\n",
 195                                PTR_ERR(data->clk), PTR_ERR(data->clk_ipg));
 196                        return ret;
 197                }
 198                return ret;
 199        }
 200
 201        data->clk_ahb = devm_clk_get(dev, "ahb");
 202        if (IS_ERR(data->clk_ahb)) {
 203                ret = PTR_ERR(data->clk_ahb);
 204                dev_err(dev,
 205                        "Failed to get ahb clock, err=%d\n", ret);
 206                return ret;
 207        }
 208
 209        data->clk_per = devm_clk_get(dev, "per");
 210        if (IS_ERR(data->clk_per)) {
 211                ret = PTR_ERR(data->clk_per);
 212                dev_err(dev,
 213                        "Failed to get per clock, err=%d\n", ret);
 214                return ret;
 215        }
 216
 217        data->need_three_clks = true;
 218        return ret;
 219}
 220
 221static int imx_prepare_enable_clks(struct device *dev)
 222{
 223        struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
 224        int ret = 0;
 225
 226        if (data->need_three_clks) {
 227                ret = clk_prepare_enable(data->clk_ipg);
 228                if (ret) {
 229                        dev_err(dev,
 230                                "Failed to prepare/enable ipg clk, err=%d\n",
 231                                ret);
 232                        return ret;
 233                }
 234
 235                ret = clk_prepare_enable(data->clk_ahb);
 236                if (ret) {
 237                        dev_err(dev,
 238                                "Failed to prepare/enable ahb clk, err=%d\n",
 239                                ret);
 240                        clk_disable_unprepare(data->clk_ipg);
 241                        return ret;
 242                }
 243
 244                ret = clk_prepare_enable(data->clk_per);
 245                if (ret) {
 246                        dev_err(dev,
 247                                "Failed to prepare/enable per clk, err=%d\n",
 248                                ret);
 249                        clk_disable_unprepare(data->clk_ahb);
 250                        clk_disable_unprepare(data->clk_ipg);
 251                        return ret;
 252                }
 253        } else {
 254                ret = clk_prepare_enable(data->clk);
 255                if (ret) {
 256                        dev_err(dev,
 257                                "Failed to prepare/enable clk, err=%d\n",
 258                                ret);
 259                        return ret;
 260                }
 261        }
 262
 263        return ret;
 264}
 265
 266static void imx_disable_unprepare_clks(struct device *dev)
 267{
 268        struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
 269
 270        if (data->need_three_clks) {
 271                clk_disable_unprepare(data->clk_per);
 272                clk_disable_unprepare(data->clk_ahb);
 273                clk_disable_unprepare(data->clk_ipg);
 274        } else {
 275                clk_disable_unprepare(data->clk);
 276        }
 277}
 278
 279static int ci_hdrc_imx_notify_event(struct ci_hdrc *ci, unsigned int event)
 280{
 281        struct device *dev = ci->dev->parent;
 282        struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
 283        int ret = 0;
 284        struct imx_usbmisc_data *mdata = data->usbmisc_data;
 285
 286        switch (event) {
 287        case CI_HDRC_IMX_HSIC_ACTIVE_EVENT:
 288                if (data->pinctrl) {
 289                        ret = pinctrl_select_state(data->pinctrl,
 290                                        data->pinctrl_hsic_active);
 291                        if (ret)
 292                                dev_err(dev,
 293                                        "hsic_active select failed, err=%d\n",
 294                                        ret);
 295                }
 296                break;
 297        case CI_HDRC_IMX_HSIC_SUSPEND_EVENT:
 298                ret = imx_usbmisc_hsic_set_connect(mdata);
 299                if (ret)
 300                        dev_err(dev,
 301                                "hsic_set_connect failed, err=%d\n", ret);
 302                break;
 303        case CI_HDRC_CONTROLLER_VBUS_EVENT:
 304                if (ci->vbus_active)
 305                        ret = imx_usbmisc_charger_detection(mdata, true);
 306                else
 307                        ret = imx_usbmisc_charger_detection(mdata, false);
 308                if (ci->usb_phy)
 309                        schedule_work(&ci->usb_phy->chg_work);
 310                break;
 311        default:
 312                break;
 313        }
 314
 315        return ret;
 316}
 317
 318static int ci_hdrc_imx_probe(struct platform_device *pdev)
 319{
 320        struct ci_hdrc_imx_data *data;
 321        struct ci_hdrc_platform_data pdata = {
 322                .name           = dev_name(&pdev->dev),
 323                .capoffset      = DEF_CAPOFFSET,
 324                .notify_event   = ci_hdrc_imx_notify_event,
 325        };
 326        int ret;
 327        const struct ci_hdrc_imx_platform_flag *imx_platform_flag;
 328        struct device_node *np = pdev->dev.of_node;
 329        struct device *dev = &pdev->dev;
 330
 331        imx_platform_flag = of_device_get_match_data(&pdev->dev);
 332
 333        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 334        if (!data)
 335                return -ENOMEM;
 336
 337        data->plat_data = imx_platform_flag;
 338        pdata.flags |= imx_platform_flag->flags;
 339        platform_set_drvdata(pdev, data);
 340        data->usbmisc_data = usbmisc_get_init_data(dev);
 341        if (IS_ERR(data->usbmisc_data))
 342                return PTR_ERR(data->usbmisc_data);
 343
 344        if ((of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC)
 345                && data->usbmisc_data) {
 346                pdata.flags |= CI_HDRC_IMX_IS_HSIC;
 347                data->usbmisc_data->hsic = 1;
 348                data->pinctrl = devm_pinctrl_get(dev);
 349                if (PTR_ERR(data->pinctrl) == -ENODEV)
 350                        data->pinctrl = NULL;
 351                else if (IS_ERR(data->pinctrl)) {
 352                        if (PTR_ERR(data->pinctrl) != -EPROBE_DEFER)
 353                                dev_err(dev, "pinctrl get failed, err=%ld\n",
 354                                        PTR_ERR(data->pinctrl));
 355                        return PTR_ERR(data->pinctrl);
 356                }
 357
 358                data->hsic_pad_regulator =
 359                                devm_regulator_get_optional(dev, "hsic");
 360                if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) {
 361                        /* no pad regualator is needed */
 362                        data->hsic_pad_regulator = NULL;
 363                } else if (IS_ERR(data->hsic_pad_regulator)) {
 364                        if (PTR_ERR(data->hsic_pad_regulator) != -EPROBE_DEFER)
 365                                dev_err(dev,
 366                                        "Get HSIC pad regulator error: %ld\n",
 367                                        PTR_ERR(data->hsic_pad_regulator));
 368                        return PTR_ERR(data->hsic_pad_regulator);
 369                }
 370
 371                if (data->hsic_pad_regulator) {
 372                        ret = regulator_enable(data->hsic_pad_regulator);
 373                        if (ret) {
 374                                dev_err(dev,
 375                                        "Failed to enable HSIC pad regulator\n");
 376                                return ret;
 377                        }
 378                }
 379        }
 380
 381        /* HSIC pinctrl handling */
 382        if (data->pinctrl) {
 383                struct pinctrl_state *pinctrl_hsic_idle;
 384
 385                pinctrl_hsic_idle = pinctrl_lookup_state(data->pinctrl, "idle");
 386                if (IS_ERR(pinctrl_hsic_idle)) {
 387                        dev_err(dev,
 388                                "pinctrl_hsic_idle lookup failed, err=%ld\n",
 389                                        PTR_ERR(pinctrl_hsic_idle));
 390                        return PTR_ERR(pinctrl_hsic_idle);
 391                }
 392
 393                ret = pinctrl_select_state(data->pinctrl, pinctrl_hsic_idle);
 394                if (ret) {
 395                        dev_err(dev, "hsic_idle select failed, err=%d\n", ret);
 396                        return ret;
 397                }
 398
 399                data->pinctrl_hsic_active = pinctrl_lookup_state(data->pinctrl,
 400                                                                "active");
 401                if (IS_ERR(data->pinctrl_hsic_active)) {
 402                        dev_err(dev,
 403                                "pinctrl_hsic_active lookup failed, err=%ld\n",
 404                                        PTR_ERR(data->pinctrl_hsic_active));
 405                        return PTR_ERR(data->pinctrl_hsic_active);
 406                }
 407        }
 408
 409        if (pdata.flags & CI_HDRC_PMQOS)
 410                cpu_latency_qos_add_request(&data->pm_qos_req, 0);
 411
 412        ret = imx_get_clks(dev);
 413        if (ret)
 414                goto disable_hsic_regulator;
 415
 416        ret = imx_prepare_enable_clks(dev);
 417        if (ret)
 418                goto disable_hsic_regulator;
 419
 420        data->phy = devm_usb_get_phy_by_phandle(dev, "fsl,usbphy", 0);
 421        if (IS_ERR(data->phy)) {
 422                ret = PTR_ERR(data->phy);
 423                if (ret != -ENODEV)
 424                        goto err_clk;
 425                data->phy = devm_usb_get_phy_by_phandle(dev, "phys", 0);
 426                if (IS_ERR(data->phy)) {
 427                        ret = PTR_ERR(data->phy);
 428                        if (ret == -ENODEV)
 429                                data->phy = NULL;
 430                        else
 431                                goto err_clk;
 432                }
 433        }
 434
 435        pdata.usb_phy = data->phy;
 436        if (data->usbmisc_data)
 437                data->usbmisc_data->usb_phy = data->phy;
 438
 439        if ((of_device_is_compatible(np, "fsl,imx53-usb") ||
 440             of_device_is_compatible(np, "fsl,imx51-usb")) && pdata.usb_phy &&
 441            of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) {
 442                pdata.flags |= CI_HDRC_OVERRIDE_PHY_CONTROL;
 443                data->override_phy_control = true;
 444                usb_phy_init(pdata.usb_phy);
 445        }
 446
 447        if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM)
 448                data->supports_runtime_pm = true;
 449
 450        ret = imx_usbmisc_init(data->usbmisc_data);
 451        if (ret) {
 452                dev_err(dev, "usbmisc init failed, ret=%d\n", ret);
 453                goto err_clk;
 454        }
 455
 456        data->ci_pdev = ci_hdrc_add_device(dev,
 457                                pdev->resource, pdev->num_resources,
 458                                &pdata);
 459        if (IS_ERR(data->ci_pdev)) {
 460                ret = PTR_ERR(data->ci_pdev);
 461                if (ret != -EPROBE_DEFER)
 462                        dev_err(dev, "ci_hdrc_add_device failed, err=%d\n",
 463                                        ret);
 464                goto err_clk;
 465        }
 466
 467        if (data->usbmisc_data) {
 468                if (!IS_ERR(pdata.id_extcon.edev) ||
 469                    of_property_read_bool(np, "usb-role-switch"))
 470                        data->usbmisc_data->ext_id = 1;
 471
 472                if (!IS_ERR(pdata.vbus_extcon.edev) ||
 473                    of_property_read_bool(np, "usb-role-switch"))
 474                        data->usbmisc_data->ext_vbus = 1;
 475
 476                /* usbmisc needs to know dr mode to choose wakeup setting */
 477                data->usbmisc_data->available_role =
 478                        ci_hdrc_query_available_role(data->ci_pdev);
 479        }
 480
 481        ret = imx_usbmisc_init_post(data->usbmisc_data);
 482        if (ret) {
 483                dev_err(dev, "usbmisc post failed, ret=%d\n", ret);
 484                goto disable_device;
 485        }
 486
 487        if (data->supports_runtime_pm) {
 488                pm_runtime_set_active(dev);
 489                pm_runtime_enable(dev);
 490        }
 491
 492        device_set_wakeup_capable(dev, true);
 493
 494        return 0;
 495
 496disable_device:
 497        ci_hdrc_remove_device(data->ci_pdev);
 498err_clk:
 499        imx_disable_unprepare_clks(dev);
 500disable_hsic_regulator:
 501        if (data->hsic_pad_regulator)
 502                /* don't overwrite original ret (cf. EPROBE_DEFER) */
 503                regulator_disable(data->hsic_pad_regulator);
 504        if (pdata.flags & CI_HDRC_PMQOS)
 505                cpu_latency_qos_remove_request(&data->pm_qos_req);
 506        data->ci_pdev = NULL;
 507        return ret;
 508}
 509
 510static int ci_hdrc_imx_remove(struct platform_device *pdev)
 511{
 512        struct ci_hdrc_imx_data *data = platform_get_drvdata(pdev);
 513
 514        if (data->supports_runtime_pm) {
 515                pm_runtime_get_sync(&pdev->dev);
 516                pm_runtime_disable(&pdev->dev);
 517                pm_runtime_put_noidle(&pdev->dev);
 518        }
 519        if (data->ci_pdev)
 520                ci_hdrc_remove_device(data->ci_pdev);
 521        if (data->override_phy_control)
 522                usb_phy_shutdown(data->phy);
 523        if (data->ci_pdev) {
 524                imx_disable_unprepare_clks(&pdev->dev);
 525                if (data->plat_data->flags & CI_HDRC_PMQOS)
 526                        cpu_latency_qos_remove_request(&data->pm_qos_req);
 527                if (data->hsic_pad_regulator)
 528                        regulator_disable(data->hsic_pad_regulator);
 529        }
 530
 531        return 0;
 532}
 533
 534static void ci_hdrc_imx_shutdown(struct platform_device *pdev)
 535{
 536        ci_hdrc_imx_remove(pdev);
 537}
 538
 539static int __maybe_unused imx_controller_suspend(struct device *dev)
 540{
 541        struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
 542        int ret = 0;
 543
 544        dev_dbg(dev, "at %s\n", __func__);
 545
 546        ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, false);
 547        if (ret) {
 548                dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret);
 549                return ret;
 550        }
 551
 552        imx_disable_unprepare_clks(dev);
 553        if (data->plat_data->flags & CI_HDRC_PMQOS)
 554                cpu_latency_qos_remove_request(&data->pm_qos_req);
 555
 556        data->in_lpm = true;
 557
 558        return 0;
 559}
 560
 561static int __maybe_unused imx_controller_resume(struct device *dev)
 562{
 563        struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
 564        int ret = 0;
 565
 566        dev_dbg(dev, "at %s\n", __func__);
 567
 568        if (!data->in_lpm) {
 569                WARN_ON(1);
 570                return 0;
 571        }
 572
 573        if (data->plat_data->flags & CI_HDRC_PMQOS)
 574                cpu_latency_qos_add_request(&data->pm_qos_req, 0);
 575
 576        ret = imx_prepare_enable_clks(dev);
 577        if (ret)
 578                return ret;
 579
 580        data->in_lpm = false;
 581
 582        ret = imx_usbmisc_set_wakeup(data->usbmisc_data, false);
 583        if (ret) {
 584                dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", ret);
 585                goto clk_disable;
 586        }
 587
 588        ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, true);
 589        if (ret) {
 590                dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret);
 591                goto hsic_set_clk_fail;
 592        }
 593
 594        return 0;
 595
 596hsic_set_clk_fail:
 597        imx_usbmisc_set_wakeup(data->usbmisc_data, true);
 598clk_disable:
 599        imx_disable_unprepare_clks(dev);
 600        return ret;
 601}
 602
 603static int __maybe_unused ci_hdrc_imx_suspend(struct device *dev)
 604{
 605        int ret;
 606
 607        struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
 608
 609        if (data->in_lpm)
 610                /* The core's suspend doesn't run */
 611                return 0;
 612
 613        if (device_may_wakeup(dev)) {
 614                ret = imx_usbmisc_set_wakeup(data->usbmisc_data, true);
 615                if (ret) {
 616                        dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n",
 617                                        ret);
 618                        return ret;
 619                }
 620        }
 621
 622        ret = imx_controller_suspend(dev);
 623        if (ret)
 624                return ret;
 625
 626        pinctrl_pm_select_sleep_state(dev);
 627        return ret;
 628}
 629
 630static int __maybe_unused ci_hdrc_imx_resume(struct device *dev)
 631{
 632        struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
 633        int ret;
 634
 635        pinctrl_pm_select_default_state(dev);
 636        ret = imx_controller_resume(dev);
 637        if (!ret && data->supports_runtime_pm) {
 638                pm_runtime_disable(dev);
 639                pm_runtime_set_active(dev);
 640                pm_runtime_enable(dev);
 641        }
 642
 643        return ret;
 644}
 645
 646static int __maybe_unused ci_hdrc_imx_runtime_suspend(struct device *dev)
 647{
 648        struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
 649        int ret;
 650
 651        if (data->in_lpm) {
 652                WARN_ON(1);
 653                return 0;
 654        }
 655
 656        ret = imx_usbmisc_set_wakeup(data->usbmisc_data, true);
 657        if (ret) {
 658                dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", ret);
 659                return ret;
 660        }
 661
 662        return imx_controller_suspend(dev);
 663}
 664
 665static int __maybe_unused ci_hdrc_imx_runtime_resume(struct device *dev)
 666{
 667        return imx_controller_resume(dev);
 668}
 669
 670static const struct dev_pm_ops ci_hdrc_imx_pm_ops = {
 671        SET_SYSTEM_SLEEP_PM_OPS(ci_hdrc_imx_suspend, ci_hdrc_imx_resume)
 672        SET_RUNTIME_PM_OPS(ci_hdrc_imx_runtime_suspend,
 673                        ci_hdrc_imx_runtime_resume, NULL)
 674};
 675static struct platform_driver ci_hdrc_imx_driver = {
 676        .probe = ci_hdrc_imx_probe,
 677        .remove = ci_hdrc_imx_remove,
 678        .shutdown = ci_hdrc_imx_shutdown,
 679        .driver = {
 680                .name = "imx_usb",
 681                .of_match_table = ci_hdrc_imx_dt_ids,
 682                .pm = &ci_hdrc_imx_pm_ops,
 683         },
 684};
 685
 686module_platform_driver(ci_hdrc_imx_driver);
 687
 688MODULE_ALIAS("platform:imx-usb");
 689MODULE_LICENSE("GPL");
 690MODULE_DESCRIPTION("CI HDRC i.MX USB binding");
 691MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
 692MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
 693