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 mxs_phy_data imx6ul_phy_data = {
 147        .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
 148};
 149
 150static const struct of_device_id mxs_phy_dt_ids[] = {
 151        { .compatible = "fsl,imx6sx-usbphy", .data = &imx6sx_phy_data, },
 152        { .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, },
 153        { .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, },
 154        { .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, },
 155        { .compatible = "fsl,vf610-usbphy", .data = &vf610_phy_data, },
 156        { .compatible = "fsl,imx6ul-usbphy", .data = &imx6ul_phy_data, },
 157        { /* sentinel */ }
 158};
 159MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
 160
 161struct mxs_phy {
 162        struct usb_phy phy;
 163        struct clk *clk;
 164        const struct mxs_phy_data *data;
 165        struct regmap *regmap_anatop;
 166        int port_id;
 167};
 168
 169static inline bool is_imx6q_phy(struct mxs_phy *mxs_phy)
 170{
 171        return mxs_phy->data == &imx6q_phy_data;
 172}
 173
 174static inline bool is_imx6sl_phy(struct mxs_phy *mxs_phy)
 175{
 176        return mxs_phy->data == &imx6sl_phy_data;
 177}
 178
 179/*
 180 * PHY needs some 32K cycles to switch from 32K clock to
 181 * bus (such as AHB/AXI, etc) clock.
 182 */
 183static void mxs_phy_clock_switch_delay(void)
 184{
 185        usleep_range(300, 400);
 186}
 187
 188static int mxs_phy_hw_init(struct mxs_phy *mxs_phy)
 189{
 190        int ret;
 191        void __iomem *base = mxs_phy->phy.io_priv;
 192
 193        ret = stmp_reset_block(base + HW_USBPHY_CTRL);
 194        if (ret)
 195                return ret;
 196
 197        /* Power up the PHY */
 198        writel(0, base + HW_USBPHY_PWD);
 199
 200        /*
 201         * USB PHY Ctrl Setting
 202         * - Auto clock/power on
 203         * - Enable full/low speed support
 204         */
 205        writel(BM_USBPHY_CTRL_ENAUTOSET_USBCLKS |
 206                BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE |
 207                BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD |
 208                BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE |
 209                BM_USBPHY_CTRL_ENAUTO_PWRON_PLL |
 210                BM_USBPHY_CTRL_ENUTMILEVEL2 |
 211                BM_USBPHY_CTRL_ENUTMILEVEL3,
 212               base + HW_USBPHY_CTRL_SET);
 213
 214        if (mxs_phy->data->flags & MXS_PHY_NEED_IP_FIX)
 215                writel(BM_USBPHY_IP_FIX, base + HW_USBPHY_IP_SET);
 216
 217        return 0;
 218}
 219
 220/* Return true if the vbus is there */
 221static bool mxs_phy_get_vbus_status(struct mxs_phy *mxs_phy)
 222{
 223        unsigned int vbus_value = 0;
 224
 225        if (!mxs_phy->regmap_anatop)
 226                return false;
 227
 228        if (mxs_phy->port_id == 0)
 229                regmap_read(mxs_phy->regmap_anatop,
 230                        ANADIG_USB1_VBUS_DET_STAT,
 231                        &vbus_value);
 232        else if (mxs_phy->port_id == 1)
 233                regmap_read(mxs_phy->regmap_anatop,
 234                        ANADIG_USB2_VBUS_DET_STAT,
 235                        &vbus_value);
 236
 237        if (vbus_value & BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID)
 238                return true;
 239        else
 240                return false;
 241}
 242
 243static void __mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool disconnect)
 244{
 245        void __iomem *base = mxs_phy->phy.io_priv;
 246        u32 reg;
 247
 248        if (disconnect)
 249                writel_relaxed(BM_USBPHY_DEBUG_CLKGATE,
 250                        base + HW_USBPHY_DEBUG_CLR);
 251
 252        if (mxs_phy->port_id == 0) {
 253                reg = disconnect ? ANADIG_USB1_LOOPBACK_SET
 254                        : ANADIG_USB1_LOOPBACK_CLR;
 255                regmap_write(mxs_phy->regmap_anatop, reg,
 256                        BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1 |
 257                        BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN);
 258        } else if (mxs_phy->port_id == 1) {
 259                reg = disconnect ? ANADIG_USB2_LOOPBACK_SET
 260                        : ANADIG_USB2_LOOPBACK_CLR;
 261                regmap_write(mxs_phy->regmap_anatop, reg,
 262                        BM_ANADIG_USB2_LOOPBACK_UTMI_DIG_TST1 |
 263                        BM_ANADIG_USB2_LOOPBACK_TSTI_TX_EN);
 264        }
 265
 266        if (!disconnect)
 267                writel_relaxed(BM_USBPHY_DEBUG_CLKGATE,
 268                        base + HW_USBPHY_DEBUG_SET);
 269
 270        /* Delay some time, and let Linestate be SE0 for controller */
 271        if (disconnect)
 272                usleep_range(500, 1000);
 273}
 274
 275static bool mxs_phy_is_otg_host(struct mxs_phy *mxs_phy)
 276{
 277        void __iomem *base = mxs_phy->phy.io_priv;
 278        u32 phyctrl = readl(base + HW_USBPHY_CTRL);
 279
 280        if (IS_ENABLED(CONFIG_USB_OTG) &&
 281                        !(phyctrl & BM_USBPHY_CTRL_OTG_ID_VALUE))
 282                return true;
 283
 284        return false;
 285}
 286
 287static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on)
 288{
 289        bool vbus_is_on = false;
 290
 291        /* If the SoCs don't need to disconnect line without vbus, quit */
 292        if (!(mxs_phy->data->flags & MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS))
 293                return;
 294
 295        /* If the SoCs don't have anatop, quit */
 296        if (!mxs_phy->regmap_anatop)
 297                return;
 298
 299        vbus_is_on = mxs_phy_get_vbus_status(mxs_phy);
 300
 301        if (on && !vbus_is_on && !mxs_phy_is_otg_host(mxs_phy))
 302                __mxs_phy_disconnect_line(mxs_phy, true);
 303        else
 304                __mxs_phy_disconnect_line(mxs_phy, false);
 305
 306}
 307
 308static int mxs_phy_init(struct usb_phy *phy)
 309{
 310        int ret;
 311        struct mxs_phy *mxs_phy = to_mxs_phy(phy);
 312
 313        mxs_phy_clock_switch_delay();
 314        ret = clk_prepare_enable(mxs_phy->clk);
 315        if (ret)
 316                return ret;
 317
 318        return mxs_phy_hw_init(mxs_phy);
 319}
 320
 321static void mxs_phy_shutdown(struct usb_phy *phy)
 322{
 323        struct mxs_phy *mxs_phy = to_mxs_phy(phy);
 324        u32 value = BM_USBPHY_CTRL_ENVBUSCHG_WKUP |
 325                        BM_USBPHY_CTRL_ENDPDMCHG_WKUP |
 326                        BM_USBPHY_CTRL_ENIDCHG_WKUP |
 327                        BM_USBPHY_CTRL_ENAUTOSET_USBCLKS |
 328                        BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE |
 329                        BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD |
 330                        BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE |
 331                        BM_USBPHY_CTRL_ENAUTO_PWRON_PLL;
 332
 333        writel(value, phy->io_priv + HW_USBPHY_CTRL_CLR);
 334        writel(0xffffffff, phy->io_priv + HW_USBPHY_PWD);
 335
 336        writel(BM_USBPHY_CTRL_CLKGATE,
 337               phy->io_priv + HW_USBPHY_CTRL_SET);
 338
 339        clk_disable_unprepare(mxs_phy->clk);
 340}
 341
 342static bool mxs_phy_is_low_speed_connection(struct mxs_phy *mxs_phy)
 343{
 344        unsigned int line_state;
 345        /* bit definition is the same for all controllers */
 346        unsigned int dp_bit = BM_ANADIG_USB1_MISC_RX_VPIN_FS,
 347                     dm_bit = BM_ANADIG_USB1_MISC_RX_VMIN_FS;
 348        unsigned int reg = ANADIG_USB1_MISC;
 349
 350        /* If the SoCs don't have anatop, quit */
 351        if (!mxs_phy->regmap_anatop)
 352                return false;
 353
 354        if (mxs_phy->port_id == 0)
 355                reg = ANADIG_USB1_MISC;
 356        else if (mxs_phy->port_id == 1)
 357                reg = ANADIG_USB2_MISC;
 358
 359        regmap_read(mxs_phy->regmap_anatop, reg, &line_state);
 360
 361        if ((line_state & (dp_bit | dm_bit)) ==  dm_bit)
 362                return true;
 363        else
 364                return false;
 365}
 366
 367static int mxs_phy_suspend(struct usb_phy *x, int suspend)
 368{
 369        int ret;
 370        struct mxs_phy *mxs_phy = to_mxs_phy(x);
 371        bool low_speed_connection, vbus_is_on;
 372
 373        low_speed_connection = mxs_phy_is_low_speed_connection(mxs_phy);
 374        vbus_is_on = mxs_phy_get_vbus_status(mxs_phy);
 375
 376        if (suspend) {
 377                /*
 378                 * FIXME: Do not power down RXPWD1PT1 bit for low speed
 379                 * connect. The low speed connection will have problem at
 380                 * very rare cases during usb suspend and resume process.
 381                 */
 382                if (low_speed_connection & vbus_is_on) {
 383                        /*
 384                         * If value to be set as pwd value is not 0xffffffff,
 385                         * several 32Khz cycles are needed.
 386                         */
 387                        mxs_phy_clock_switch_delay();
 388                        writel(0xffbfffff, x->io_priv + HW_USBPHY_PWD);
 389                } else {
 390                        writel(0xffffffff, x->io_priv + HW_USBPHY_PWD);
 391                }
 392                writel(BM_USBPHY_CTRL_CLKGATE,
 393                       x->io_priv + HW_USBPHY_CTRL_SET);
 394                clk_disable_unprepare(mxs_phy->clk);
 395        } else {
 396                mxs_phy_clock_switch_delay();
 397                ret = clk_prepare_enable(mxs_phy->clk);
 398                if (ret)
 399                        return ret;
 400                writel(BM_USBPHY_CTRL_CLKGATE,
 401                       x->io_priv + HW_USBPHY_CTRL_CLR);
 402                writel(0, x->io_priv + HW_USBPHY_PWD);
 403        }
 404
 405        return 0;
 406}
 407
 408static int mxs_phy_set_wakeup(struct usb_phy *x, bool enabled)
 409{
 410        struct mxs_phy *mxs_phy = to_mxs_phy(x);
 411        u32 value = BM_USBPHY_CTRL_ENVBUSCHG_WKUP |
 412                        BM_USBPHY_CTRL_ENDPDMCHG_WKUP |
 413                                BM_USBPHY_CTRL_ENIDCHG_WKUP;
 414        if (enabled) {
 415                mxs_phy_disconnect_line(mxs_phy, true);
 416                writel_relaxed(value, x->io_priv + HW_USBPHY_CTRL_SET);
 417        } else {
 418                writel_relaxed(value, x->io_priv + HW_USBPHY_CTRL_CLR);
 419                mxs_phy_disconnect_line(mxs_phy, false);
 420        }
 421
 422        return 0;
 423}
 424
 425static int mxs_phy_on_connect(struct usb_phy *phy,
 426                enum usb_device_speed speed)
 427{
 428        dev_dbg(phy->dev, "%s device has connected\n",
 429                (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
 430
 431        if (speed == USB_SPEED_HIGH)
 432                writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
 433                       phy->io_priv + HW_USBPHY_CTRL_SET);
 434
 435        return 0;
 436}
 437
 438static int mxs_phy_on_disconnect(struct usb_phy *phy,
 439                enum usb_device_speed speed)
 440{
 441        dev_dbg(phy->dev, "%s device has disconnected\n",
 442                (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
 443
 444        /* Sometimes, the speed is not high speed when the error occurs */
 445        if (readl(phy->io_priv + HW_USBPHY_CTRL) &
 446                        BM_USBPHY_CTRL_ENHOSTDISCONDETECT)
 447                writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
 448                       phy->io_priv + HW_USBPHY_CTRL_CLR);
 449
 450        return 0;
 451}
 452
 453static int mxs_phy_probe(struct platform_device *pdev)
 454{
 455        struct resource *res;
 456        void __iomem *base;
 457        struct clk *clk;
 458        struct mxs_phy *mxs_phy;
 459        int ret;
 460        const struct of_device_id *of_id;
 461        struct device_node *np = pdev->dev.of_node;
 462
 463        of_id = of_match_device(mxs_phy_dt_ids, &pdev->dev);
 464        if (!of_id)
 465                return -ENODEV;
 466
 467        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 468        base = devm_ioremap_resource(&pdev->dev, res);
 469        if (IS_ERR(base))
 470                return PTR_ERR(base);
 471
 472        clk = devm_clk_get(&pdev->dev, NULL);
 473        if (IS_ERR(clk)) {
 474                dev_err(&pdev->dev,
 475                        "can't get the clock, err=%ld", PTR_ERR(clk));
 476                return PTR_ERR(clk);
 477        }
 478
 479        mxs_phy = devm_kzalloc(&pdev->dev, sizeof(*mxs_phy), GFP_KERNEL);
 480        if (!mxs_phy)
 481                return -ENOMEM;
 482
 483        /* Some SoCs don't have anatop registers */
 484        if (of_get_property(np, "fsl,anatop", NULL)) {
 485                mxs_phy->regmap_anatop = syscon_regmap_lookup_by_phandle
 486                        (np, "fsl,anatop");
 487                if (IS_ERR(mxs_phy->regmap_anatop)) {
 488                        dev_dbg(&pdev->dev,
 489                                "failed to find regmap for anatop\n");
 490                        return PTR_ERR(mxs_phy->regmap_anatop);
 491                }
 492        }
 493
 494        ret = of_alias_get_id(np, "usbphy");
 495        if (ret < 0)
 496                dev_dbg(&pdev->dev, "failed to get alias id, errno %d\n", ret);
 497        mxs_phy->port_id = ret;
 498
 499        mxs_phy->phy.io_priv            = base;
 500        mxs_phy->phy.dev                = &pdev->dev;
 501        mxs_phy->phy.label              = DRIVER_NAME;
 502        mxs_phy->phy.init               = mxs_phy_init;
 503        mxs_phy->phy.shutdown           = mxs_phy_shutdown;
 504        mxs_phy->phy.set_suspend        = mxs_phy_suspend;
 505        mxs_phy->phy.notify_connect     = mxs_phy_on_connect;
 506        mxs_phy->phy.notify_disconnect  = mxs_phy_on_disconnect;
 507        mxs_phy->phy.type               = USB_PHY_TYPE_USB2;
 508        mxs_phy->phy.set_wakeup         = mxs_phy_set_wakeup;
 509
 510        mxs_phy->clk = clk;
 511        mxs_phy->data = of_id->data;
 512
 513        platform_set_drvdata(pdev, mxs_phy);
 514
 515        device_set_wakeup_capable(&pdev->dev, true);
 516
 517        return usb_add_phy_dev(&mxs_phy->phy);
 518}
 519
 520static int mxs_phy_remove(struct platform_device *pdev)
 521{
 522        struct mxs_phy *mxs_phy = platform_get_drvdata(pdev);
 523
 524        usb_remove_phy(&mxs_phy->phy);
 525
 526        return 0;
 527}
 528
 529#ifdef CONFIG_PM_SLEEP
 530static void mxs_phy_enable_ldo_in_suspend(struct mxs_phy *mxs_phy, bool on)
 531{
 532        unsigned int reg = on ? ANADIG_ANA_MISC0_SET : ANADIG_ANA_MISC0_CLR;
 533
 534        /* If the SoCs don't have anatop, quit */
 535        if (!mxs_phy->regmap_anatop)
 536                return;
 537
 538        if (is_imx6q_phy(mxs_phy))
 539                regmap_write(mxs_phy->regmap_anatop, reg,
 540                        BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG);
 541        else if (is_imx6sl_phy(mxs_phy))
 542                regmap_write(mxs_phy->regmap_anatop,
 543                        reg, BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL);
 544}
 545
 546static int mxs_phy_system_suspend(struct device *dev)
 547{
 548        struct mxs_phy *mxs_phy = dev_get_drvdata(dev);
 549
 550        if (device_may_wakeup(dev))
 551                mxs_phy_enable_ldo_in_suspend(mxs_phy, true);
 552
 553        return 0;
 554}
 555
 556static int mxs_phy_system_resume(struct device *dev)
 557{
 558        struct mxs_phy *mxs_phy = dev_get_drvdata(dev);
 559
 560        if (device_may_wakeup(dev))
 561                mxs_phy_enable_ldo_in_suspend(mxs_phy, false);
 562
 563        return 0;
 564}
 565#endif /* CONFIG_PM_SLEEP */
 566
 567static SIMPLE_DEV_PM_OPS(mxs_phy_pm, mxs_phy_system_suspend,
 568                mxs_phy_system_resume);
 569
 570static struct platform_driver mxs_phy_driver = {
 571        .probe = mxs_phy_probe,
 572        .remove = mxs_phy_remove,
 573        .driver = {
 574                .name = DRIVER_NAME,
 575                .of_match_table = mxs_phy_dt_ids,
 576                .pm = &mxs_phy_pm,
 577         },
 578};
 579
 580static int __init mxs_phy_module_init(void)
 581{
 582        return platform_driver_register(&mxs_phy_driver);
 583}
 584postcore_initcall(mxs_phy_module_init);
 585
 586static void __exit mxs_phy_module_exit(void)
 587{
 588        platform_driver_unregister(&mxs_phy_driver);
 589}
 590module_exit(mxs_phy_module_exit);
 591
 592MODULE_ALIAS("platform:mxs-usb-phy");
 593MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
 594MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
 595MODULE_DESCRIPTION("Freescale MXS USB PHY driver");
 596MODULE_LICENSE("GPL");
 597