linux/drivers/usb/phy/phy-mxs-usb.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012-2014 Freescale Semiconductor, Inc.
   3 * Copyright (C) 2012 Marek Vasut <marex@denx.de>
   4 * on behalf of DENX Software Engineering GmbH
   5 *
   6 * The code contained herein is licensed under the GNU General Public
   7 * License. You may obtain a copy of the GNU General Public License
   8 * Version 2 or later at the following locations:
   9 *
  10 * http://www.opensource.org/licenses/gpl-license.html
  11 * http://www.gnu.org/copyleft/gpl.html
  12 */
  13
  14#include <linux/module.h>
  15#include <linux/kernel.h>
  16#include <linux/platform_device.h>
  17#include <linux/clk.h>
  18#include <linux/usb/otg.h>
  19#include <linux/stmp_device.h>
  20#include <linux/delay.h>
  21#include <linux/err.h>
  22#include <linux/io.h>
  23#include <linux/of_device.h>
  24#include <linux/regmap.h>
  25#include <linux/mfd/syscon.h>
  26
  27#define DRIVER_NAME "mxs_phy"
  28
  29#define HW_USBPHY_PWD                           0x00
  30#define HW_USBPHY_CTRL                          0x30
  31#define HW_USBPHY_CTRL_SET                      0x34
  32#define HW_USBPHY_CTRL_CLR                      0x38
  33
  34#define HW_USBPHY_DEBUG_SET                     0x54
  35#define HW_USBPHY_DEBUG_CLR                     0x58
  36
  37#define HW_USBPHY_IP                            0x90
  38#define HW_USBPHY_IP_SET                        0x94
  39#define HW_USBPHY_IP_CLR                        0x98
  40
  41#define BM_USBPHY_CTRL_SFTRST                   BIT(31)
  42#define BM_USBPHY_CTRL_CLKGATE                  BIT(30)
  43#define BM_USBPHY_CTRL_OTG_ID_VALUE             BIT(27)
  44#define BM_USBPHY_CTRL_ENAUTOSET_USBCLKS        BIT(26)
  45#define BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE     BIT(25)
  46#define BM_USBPHY_CTRL_ENVBUSCHG_WKUP           BIT(23)
  47#define BM_USBPHY_CTRL_ENIDCHG_WKUP             BIT(22)
  48#define BM_USBPHY_CTRL_ENDPDMCHG_WKUP           BIT(21)
  49#define BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD        BIT(20)
  50#define BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE        BIT(19)
  51#define BM_USBPHY_CTRL_ENAUTO_PWRON_PLL         BIT(18)
  52#define BM_USBPHY_CTRL_ENUTMILEVEL3             BIT(15)
  53#define BM_USBPHY_CTRL_ENUTMILEVEL2             BIT(14)
  54#define BM_USBPHY_CTRL_ENHOSTDISCONDETECT       BIT(1)
  55
  56#define BM_USBPHY_IP_FIX                       (BIT(17) | BIT(18))
  57
  58#define BM_USBPHY_DEBUG_CLKGATE                 BIT(30)
  59
  60/* Anatop Registers */
  61#define ANADIG_ANA_MISC0                        0x150
  62#define ANADIG_ANA_MISC0_SET                    0x154
  63#define ANADIG_ANA_MISC0_CLR                    0x158
  64
  65#define ANADIG_USB1_VBUS_DET_STAT               0x1c0
  66#define ANADIG_USB2_VBUS_DET_STAT               0x220
  67
  68#define ANADIG_USB1_LOOPBACK_SET                0x1e4
  69#define ANADIG_USB1_LOOPBACK_CLR                0x1e8
  70#define ANADIG_USB2_LOOPBACK_SET                0x244
  71#define ANADIG_USB2_LOOPBACK_CLR                0x248
  72
  73#define ANADIG_USB1_MISC                        0x1f0
  74#define ANADIG_USB2_MISC                        0x250
  75
  76#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG    BIT(12)
  77#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL BIT(11)
  78
  79#define BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID BIT(3)
  80#define BM_ANADIG_USB2_VBUS_DET_STAT_VBUS_VALID BIT(3)
  81
  82#define BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1   BIT(2)
  83#define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN      BIT(5)
  84#define BM_ANADIG_USB2_LOOPBACK_UTMI_DIG_TST1   BIT(2)
  85#define BM_ANADIG_USB2_LOOPBACK_TSTI_TX_EN      BIT(5)
  86
  87#define BM_ANADIG_USB1_MISC_RX_VPIN_FS          BIT(29)
  88#define BM_ANADIG_USB1_MISC_RX_VMIN_FS          BIT(28)
  89#define BM_ANADIG_USB2_MISC_RX_VPIN_FS          BIT(29)
  90#define BM_ANADIG_USB2_MISC_RX_VMIN_FS          BIT(28)
  91
  92#define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
  93
  94/* Do disconnection between PHY and controller without vbus */
  95#define MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS    BIT(0)
  96
  97/*
  98 * The PHY will be in messy if there is a wakeup after putting
  99 * bus to suspend (set portsc.suspendM) but before setting PHY to low
 100 * power mode (set portsc.phcd).
 101 */
 102#define MXS_PHY_ABNORMAL_IN_SUSPEND             BIT(1)
 103
 104/*
 105 * The SOF sends too fast after resuming, it will cause disconnection
 106 * between host and high speed device.
 107 */
 108#define MXS_PHY_SENDING_SOF_TOO_FAST            BIT(2)
 109
 110/*
 111 * IC has bug fixes logic, they include
 112 * MXS_PHY_ABNORMAL_IN_SUSPEND and MXS_PHY_SENDING_SOF_TOO_FAST
 113 * which are described at above flags, the RTL will handle it
 114 * according to different versions.
 115 */
 116#define MXS_PHY_NEED_IP_FIX                     BIT(3)
 117
 118struct mxs_phy_data {
 119        unsigned int flags;
 120};
 121
 122static const struct mxs_phy_data imx23_phy_data = {
 123        .flags = MXS_PHY_ABNORMAL_IN_SUSPEND | MXS_PHY_SENDING_SOF_TOO_FAST,
 124};
 125
 126static const struct mxs_phy_data imx6q_phy_data = {
 127        .flags = MXS_PHY_SENDING_SOF_TOO_FAST |
 128                MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
 129                MXS_PHY_NEED_IP_FIX,
 130};
 131
 132static const struct mxs_phy_data imx6sl_phy_data = {
 133        .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
 134                MXS_PHY_NEED_IP_FIX,
 135};
 136
 137static const struct mxs_phy_data vf610_phy_data = {
 138        .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
 139                MXS_PHY_NEED_IP_FIX,
 140};
 141
 142static const struct mxs_phy_data imx6sx_phy_data = {
 143        .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
 144};
 145
 146static const struct of_device_id mxs_phy_dt_ids[] = {
 147        { .compatible = "fsl,imx6sx-usbphy", .data = &imx6sx_phy_data, },
 148        { .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, },
 149        { .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, },
 150        { .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, },
 151        { .compatible = "fsl,vf610-usbphy", .data = &vf610_phy_data, },
 152        { /* sentinel */ }
 153};
 154MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
 155
 156struct mxs_phy {
 157        struct usb_phy phy;
 158        struct clk *clk;
 159        const struct mxs_phy_data *data;
 160        struct regmap *regmap_anatop;
 161        int port_id;
 162};
 163
 164static inline bool is_imx6q_phy(struct mxs_phy *mxs_phy)
 165{
 166        return mxs_phy->data == &imx6q_phy_data;
 167}
 168
 169static inline bool is_imx6sl_phy(struct mxs_phy *mxs_phy)
 170{
 171        return mxs_phy->data == &imx6sl_phy_data;
 172}
 173
 174/*
 175 * PHY needs some 32K cycles to switch from 32K clock to
 176 * bus (such as AHB/AXI, etc) clock.
 177 */
 178static void mxs_phy_clock_switch_delay(void)
 179{
 180        usleep_range(300, 400);
 181}
 182
 183static int mxs_phy_hw_init(struct mxs_phy *mxs_phy)
 184{
 185        int ret;
 186        void __iomem *base = mxs_phy->phy.io_priv;
 187
 188        ret = stmp_reset_block(base + HW_USBPHY_CTRL);
 189        if (ret)
 190                return ret;
 191
 192        /* Power up the PHY */
 193        writel(0, base + HW_USBPHY_PWD);
 194
 195        /*
 196         * USB PHY Ctrl Setting
 197         * - Auto clock/power on
 198         * - Enable full/low speed support
 199         */
 200        writel(BM_USBPHY_CTRL_ENAUTOSET_USBCLKS |
 201                BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE |
 202                BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD |
 203                BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE |
 204                BM_USBPHY_CTRL_ENAUTO_PWRON_PLL |
 205                BM_USBPHY_CTRL_ENUTMILEVEL2 |
 206                BM_USBPHY_CTRL_ENUTMILEVEL3,
 207               base + HW_USBPHY_CTRL_SET);
 208
 209        if (mxs_phy->data->flags & MXS_PHY_NEED_IP_FIX)
 210                writel(BM_USBPHY_IP_FIX, base + HW_USBPHY_IP_SET);
 211
 212        return 0;
 213}
 214
 215/* Return true if the vbus is there */
 216static bool mxs_phy_get_vbus_status(struct mxs_phy *mxs_phy)
 217{
 218        unsigned int vbus_value;
 219
 220        if (mxs_phy->port_id == 0)
 221                regmap_read(mxs_phy->regmap_anatop,
 222                        ANADIG_USB1_VBUS_DET_STAT,
 223                        &vbus_value);
 224        else if (mxs_phy->port_id == 1)
 225                regmap_read(mxs_phy->regmap_anatop,
 226                        ANADIG_USB2_VBUS_DET_STAT,
 227                        &vbus_value);
 228
 229        if (vbus_value & BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID)
 230                return true;
 231        else
 232                return false;
 233}
 234
 235static void __mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool disconnect)
 236{
 237        void __iomem *base = mxs_phy->phy.io_priv;
 238        u32 reg;
 239
 240        if (disconnect)
 241                writel_relaxed(BM_USBPHY_DEBUG_CLKGATE,
 242                        base + HW_USBPHY_DEBUG_CLR);
 243
 244        if (mxs_phy->port_id == 0) {
 245                reg = disconnect ? ANADIG_USB1_LOOPBACK_SET
 246                        : ANADIG_USB1_LOOPBACK_CLR;
 247                regmap_write(mxs_phy->regmap_anatop, reg,
 248                        BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1 |
 249                        BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN);
 250        } else if (mxs_phy->port_id == 1) {
 251                reg = disconnect ? ANADIG_USB2_LOOPBACK_SET
 252                        : ANADIG_USB2_LOOPBACK_CLR;
 253                regmap_write(mxs_phy->regmap_anatop, reg,
 254                        BM_ANADIG_USB2_LOOPBACK_UTMI_DIG_TST1 |
 255                        BM_ANADIG_USB2_LOOPBACK_TSTI_TX_EN);
 256        }
 257
 258        if (!disconnect)
 259                writel_relaxed(BM_USBPHY_DEBUG_CLKGATE,
 260                        base + HW_USBPHY_DEBUG_SET);
 261
 262        /* Delay some time, and let Linestate be SE0 for controller */
 263        if (disconnect)
 264                usleep_range(500, 1000);
 265}
 266
 267static bool mxs_phy_is_otg_host(struct mxs_phy *mxs_phy)
 268{
 269        void __iomem *base = mxs_phy->phy.io_priv;
 270        u32 phyctrl = readl(base + HW_USBPHY_CTRL);
 271
 272        if (IS_ENABLED(CONFIG_USB_OTG) &&
 273                        !(phyctrl & BM_USBPHY_CTRL_OTG_ID_VALUE))
 274                return true;
 275
 276        return false;
 277}
 278
 279static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on)
 280{
 281        bool vbus_is_on = false;
 282
 283        /* If the SoCs don't need to disconnect line without vbus, quit */
 284        if (!(mxs_phy->data->flags & MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS))
 285                return;
 286
 287        /* If the SoCs don't have anatop, quit */
 288        if (!mxs_phy->regmap_anatop)
 289                return;
 290
 291        vbus_is_on = mxs_phy_get_vbus_status(mxs_phy);
 292
 293        if (on && !vbus_is_on && !mxs_phy_is_otg_host(mxs_phy))
 294                __mxs_phy_disconnect_line(mxs_phy, true);
 295        else
 296                __mxs_phy_disconnect_line(mxs_phy, false);
 297
 298}
 299
 300static int mxs_phy_init(struct usb_phy *phy)
 301{
 302        int ret;
 303        struct mxs_phy *mxs_phy = to_mxs_phy(phy);
 304
 305        mxs_phy_clock_switch_delay();
 306        ret = clk_prepare_enable(mxs_phy->clk);
 307        if (ret)
 308                return ret;
 309
 310        return mxs_phy_hw_init(mxs_phy);
 311}
 312
 313static void mxs_phy_shutdown(struct usb_phy *phy)
 314{
 315        struct mxs_phy *mxs_phy = to_mxs_phy(phy);
 316        u32 value = BM_USBPHY_CTRL_ENVBUSCHG_WKUP |
 317                        BM_USBPHY_CTRL_ENDPDMCHG_WKUP |
 318                        BM_USBPHY_CTRL_ENIDCHG_WKUP |
 319                        BM_USBPHY_CTRL_ENAUTOSET_USBCLKS |
 320                        BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE |
 321                        BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD |
 322                        BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE |
 323                        BM_USBPHY_CTRL_ENAUTO_PWRON_PLL;
 324
 325        writel(value, phy->io_priv + HW_USBPHY_CTRL_CLR);
 326        writel(0xffffffff, phy->io_priv + HW_USBPHY_PWD);
 327
 328        writel(BM_USBPHY_CTRL_CLKGATE,
 329               phy->io_priv + HW_USBPHY_CTRL_SET);
 330
 331        clk_disable_unprepare(mxs_phy->clk);
 332}
 333
 334static bool mxs_phy_is_low_speed_connection(struct mxs_phy *mxs_phy)
 335{
 336        unsigned int line_state;
 337        /* bit definition is the same for all controllers */
 338        unsigned int dp_bit = BM_ANADIG_USB1_MISC_RX_VPIN_FS,
 339                     dm_bit = BM_ANADIG_USB1_MISC_RX_VMIN_FS;
 340        unsigned int reg = ANADIG_USB1_MISC;
 341
 342        /* If the SoCs don't have anatop, quit */
 343        if (!mxs_phy->regmap_anatop)
 344                return false;
 345
 346        if (mxs_phy->port_id == 0)
 347                reg = ANADIG_USB1_MISC;
 348        else if (mxs_phy->port_id == 1)
 349                reg = ANADIG_USB2_MISC;
 350
 351        regmap_read(mxs_phy->regmap_anatop, reg, &line_state);
 352
 353        if ((line_state & (dp_bit | dm_bit)) ==  dm_bit)
 354                return true;
 355        else
 356                return false;
 357}
 358
 359static int mxs_phy_suspend(struct usb_phy *x, int suspend)
 360{
 361        int ret;
 362        struct mxs_phy *mxs_phy = to_mxs_phy(x);
 363        bool low_speed_connection, vbus_is_on;
 364
 365        low_speed_connection = mxs_phy_is_low_speed_connection(mxs_phy);
 366        vbus_is_on = mxs_phy_get_vbus_status(mxs_phy);
 367
 368        if (suspend) {
 369                /*
 370                 * FIXME: Do not power down RXPWD1PT1 bit for low speed
 371                 * connect. The low speed connection will have problem at
 372                 * very rare cases during usb suspend and resume process.
 373                 */
 374                if (low_speed_connection & vbus_is_on) {
 375                        /*
 376                         * If value to be set as pwd value is not 0xffffffff,
 377                         * several 32Khz cycles are needed.
 378                         */
 379                        mxs_phy_clock_switch_delay();
 380                        writel(0xffbfffff, x->io_priv + HW_USBPHY_PWD);
 381                } else {
 382                        writel(0xffffffff, x->io_priv + HW_USBPHY_PWD);
 383                }
 384                writel(BM_USBPHY_CTRL_CLKGATE,
 385                       x->io_priv + HW_USBPHY_CTRL_SET);
 386                clk_disable_unprepare(mxs_phy->clk);
 387        } else {
 388                mxs_phy_clock_switch_delay();
 389                ret = clk_prepare_enable(mxs_phy->clk);
 390                if (ret)
 391                        return ret;
 392                writel(BM_USBPHY_CTRL_CLKGATE,
 393                       x->io_priv + HW_USBPHY_CTRL_CLR);
 394                writel(0, x->io_priv + HW_USBPHY_PWD);
 395        }
 396
 397        return 0;
 398}
 399
 400static int mxs_phy_set_wakeup(struct usb_phy *x, bool enabled)
 401{
 402        struct mxs_phy *mxs_phy = to_mxs_phy(x);
 403        u32 value = BM_USBPHY_CTRL_ENVBUSCHG_WKUP |
 404                        BM_USBPHY_CTRL_ENDPDMCHG_WKUP |
 405                                BM_USBPHY_CTRL_ENIDCHG_WKUP;
 406        if (enabled) {
 407                mxs_phy_disconnect_line(mxs_phy, true);
 408                writel_relaxed(value, x->io_priv + HW_USBPHY_CTRL_SET);
 409        } else {
 410                writel_relaxed(value, x->io_priv + HW_USBPHY_CTRL_CLR);
 411                mxs_phy_disconnect_line(mxs_phy, false);
 412        }
 413
 414        return 0;
 415}
 416
 417static int mxs_phy_on_connect(struct usb_phy *phy,
 418                enum usb_device_speed speed)
 419{
 420        dev_dbg(phy->dev, "%s device has connected\n",
 421                (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
 422
 423        if (speed == USB_SPEED_HIGH)
 424                writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
 425                       phy->io_priv + HW_USBPHY_CTRL_SET);
 426
 427        return 0;
 428}
 429
 430static int mxs_phy_on_disconnect(struct usb_phy *phy,
 431                enum usb_device_speed speed)
 432{
 433        dev_dbg(phy->dev, "%s device has disconnected\n",
 434                (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
 435
 436        /* Sometimes, the speed is not high speed when the error occurs */
 437        if (readl(phy->io_priv + HW_USBPHY_CTRL) &
 438                        BM_USBPHY_CTRL_ENHOSTDISCONDETECT)
 439                writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
 440                       phy->io_priv + HW_USBPHY_CTRL_CLR);
 441
 442        return 0;
 443}
 444
 445static int mxs_phy_probe(struct platform_device *pdev)
 446{
 447        struct resource *res;
 448        void __iomem *base;
 449        struct clk *clk;
 450        struct mxs_phy *mxs_phy;
 451        int ret;
 452        const struct of_device_id *of_id =
 453                        of_match_device(mxs_phy_dt_ids, &pdev->dev);
 454        struct device_node *np = pdev->dev.of_node;
 455
 456        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 457        base = devm_ioremap_resource(&pdev->dev, res);
 458        if (IS_ERR(base))
 459                return PTR_ERR(base);
 460
 461        clk = devm_clk_get(&pdev->dev, NULL);
 462        if (IS_ERR(clk)) {
 463                dev_err(&pdev->dev,
 464                        "can't get the clock, err=%ld", PTR_ERR(clk));
 465                return PTR_ERR(clk);
 466        }
 467
 468        mxs_phy = devm_kzalloc(&pdev->dev, sizeof(*mxs_phy), GFP_KERNEL);
 469        if (!mxs_phy)
 470                return -ENOMEM;
 471
 472        /* Some SoCs don't have anatop registers */
 473        if (of_get_property(np, "fsl,anatop", NULL)) {
 474                mxs_phy->regmap_anatop = syscon_regmap_lookup_by_phandle
 475                        (np, "fsl,anatop");
 476                if (IS_ERR(mxs_phy->regmap_anatop)) {
 477                        dev_dbg(&pdev->dev,
 478                                "failed to find regmap for anatop\n");
 479                        return PTR_ERR(mxs_phy->regmap_anatop);
 480                }
 481        }
 482
 483        ret = of_alias_get_id(np, "usbphy");
 484        if (ret < 0)
 485                dev_dbg(&pdev->dev, "failed to get alias id, errno %d\n", ret);
 486        mxs_phy->port_id = ret;
 487
 488        mxs_phy->phy.io_priv            = base;
 489        mxs_phy->phy.dev                = &pdev->dev;
 490        mxs_phy->phy.label              = DRIVER_NAME;
 491        mxs_phy->phy.init               = mxs_phy_init;
 492        mxs_phy->phy.shutdown           = mxs_phy_shutdown;
 493        mxs_phy->phy.set_suspend        = mxs_phy_suspend;
 494        mxs_phy->phy.notify_connect     = mxs_phy_on_connect;
 495        mxs_phy->phy.notify_disconnect  = mxs_phy_on_disconnect;
 496        mxs_phy->phy.type               = USB_PHY_TYPE_USB2;
 497        mxs_phy->phy.set_wakeup         = mxs_phy_set_wakeup;
 498
 499        mxs_phy->clk = clk;
 500        mxs_phy->data = of_id->data;
 501
 502        platform_set_drvdata(pdev, mxs_phy);
 503
 504        device_set_wakeup_capable(&pdev->dev, true);
 505
 506        ret = usb_add_phy_dev(&mxs_phy->phy);
 507        if (ret)
 508                return ret;
 509
 510        return 0;
 511}
 512
 513static int mxs_phy_remove(struct platform_device *pdev)
 514{
 515        struct mxs_phy *mxs_phy = platform_get_drvdata(pdev);
 516
 517        usb_remove_phy(&mxs_phy->phy);
 518
 519        return 0;
 520}
 521
 522#ifdef CONFIG_PM_SLEEP
 523static void mxs_phy_enable_ldo_in_suspend(struct mxs_phy *mxs_phy, bool on)
 524{
 525        unsigned int reg = on ? ANADIG_ANA_MISC0_SET : ANADIG_ANA_MISC0_CLR;
 526
 527        /* If the SoCs don't have anatop, quit */
 528        if (!mxs_phy->regmap_anatop)
 529                return;
 530
 531        if (is_imx6q_phy(mxs_phy))
 532                regmap_write(mxs_phy->regmap_anatop, reg,
 533                        BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG);
 534        else if (is_imx6sl_phy(mxs_phy))
 535                regmap_write(mxs_phy->regmap_anatop,
 536                        reg, BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL);
 537}
 538
 539static int mxs_phy_system_suspend(struct device *dev)
 540{
 541        struct mxs_phy *mxs_phy = dev_get_drvdata(dev);
 542
 543        if (device_may_wakeup(dev))
 544                mxs_phy_enable_ldo_in_suspend(mxs_phy, true);
 545
 546        return 0;
 547}
 548
 549static int mxs_phy_system_resume(struct device *dev)
 550{
 551        struct mxs_phy *mxs_phy = dev_get_drvdata(dev);
 552
 553        if (device_may_wakeup(dev))
 554                mxs_phy_enable_ldo_in_suspend(mxs_phy, false);
 555
 556        return 0;
 557}
 558#endif /* CONFIG_PM_SLEEP */
 559
 560static SIMPLE_DEV_PM_OPS(mxs_phy_pm, mxs_phy_system_suspend,
 561                mxs_phy_system_resume);
 562
 563static struct platform_driver mxs_phy_driver = {
 564        .probe = mxs_phy_probe,
 565        .remove = mxs_phy_remove,
 566        .driver = {
 567                .name = DRIVER_NAME,
 568                .of_match_table = mxs_phy_dt_ids,
 569                .pm = &mxs_phy_pm,
 570         },
 571};
 572
 573static int __init mxs_phy_module_init(void)
 574{
 575        return platform_driver_register(&mxs_phy_driver);
 576}
 577postcore_initcall(mxs_phy_module_init);
 578
 579static void __exit mxs_phy_module_exit(void)
 580{
 581        platform_driver_unregister(&mxs_phy_driver);
 582}
 583module_exit(mxs_phy_module_exit);
 584
 585MODULE_ALIAS("platform:mxs-usb-phy");
 586MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
 587MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
 588MODULE_DESCRIPTION("Freescale MXS USB PHY driver");
 589MODULE_LICENSE("GPL");
 590