uboot/drivers/phy/meson-gxl-usb2.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Meson GXL and GXM USB2 PHY driver
   4 *
   5 * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
   6 * Copyright (C) 2018 BayLibre, SAS
   7 * Author: Neil Armstrong <narmstron@baylibre.com>
   8 */
   9
  10#include <common.h>
  11#include <malloc.h>
  12#include <asm/io.h>
  13#include <bitfield.h>
  14#include <dm.h>
  15#include <errno.h>
  16#include <generic-phy.h>
  17#include <regmap.h>
  18#include <linux/delay.h>
  19#include <power/regulator.h>
  20#include <clk.h>
  21#include <linux/usb/otg.h>
  22
  23#include <asm/arch/usb-gx.h>
  24
  25#include <linux/bitops.h>
  26#include <linux/compat.h>
  27
  28/* bits [31:27] are read-only */
  29#define U2P_R0                                                  0x0
  30        #define U2P_R0_BYPASS_SEL                               BIT(0)
  31        #define U2P_R0_BYPASS_DM_EN                             BIT(1)
  32        #define U2P_R0_BYPASS_DP_EN                             BIT(2)
  33        #define U2P_R0_TXBITSTUFF_ENH                           BIT(3)
  34        #define U2P_R0_TXBITSTUFF_EN                            BIT(4)
  35        #define U2P_R0_DM_PULLDOWN                              BIT(5)
  36        #define U2P_R0_DP_PULLDOWN                              BIT(6)
  37        #define U2P_R0_DP_VBUS_VLD_EXT_SEL                      BIT(7)
  38        #define U2P_R0_DP_VBUS_VLD_EXT                          BIT(8)
  39        #define U2P_R0_ADP_PRB_EN                               BIT(9)
  40        #define U2P_R0_ADP_DISCHARGE                            BIT(10)
  41        #define U2P_R0_ADP_CHARGE                               BIT(11)
  42        #define U2P_R0_DRV_VBUS                                 BIT(12)
  43        #define U2P_R0_ID_PULLUP                                BIT(13)
  44        #define U2P_R0_LOOPBACK_EN_B                            BIT(14)
  45        #define U2P_R0_OTG_DISABLE                              BIT(15)
  46        #define U2P_R0_COMMON_ONN                               BIT(16)
  47        #define U2P_R0_FSEL_MASK                                GENMASK(19, 17)
  48        #define U2P_R0_REF_CLK_SEL_MASK                         GENMASK(21, 20)
  49        #define U2P_R0_POWER_ON_RESET                           BIT(22)
  50        #define U2P_R0_V_ATE_TEST_EN_B_MASK                     GENMASK(24, 23)
  51        #define U2P_R0_ID_SET_ID_DQ                             BIT(25)
  52        #define U2P_R0_ATE_RESET                                BIT(26)
  53        #define U2P_R0_FSV_MINUS                                BIT(27)
  54        #define U2P_R0_FSV_PLUS                                 BIT(28)
  55        #define U2P_R0_BYPASS_DM_DATA                           BIT(29)
  56        #define U2P_R0_BYPASS_DP_DATA                           BIT(30)
  57
  58#define U2P_R1                                                  0x4
  59        #define U2P_R1_BURN_IN_TEST                             BIT(0)
  60        #define U2P_R1_ACA_ENABLE                               BIT(1)
  61        #define U2P_R1_DCD_ENABLE                               BIT(2)
  62        #define U2P_R1_VDAT_SRC_EN_B                            BIT(3)
  63        #define U2P_R1_VDAT_DET_EN_B                            BIT(4)
  64        #define U2P_R1_CHARGES_SEL                              BIT(5)
  65        #define U2P_R1_TX_PREEMP_PULSE_TUNE                     BIT(6)
  66        #define U2P_R1_TX_PREEMP_AMP_TUNE_MASK                  GENMASK(8, 7)
  67        #define U2P_R1_TX_RES_TUNE_MASK                         GENMASK(10, 9)
  68        #define U2P_R1_TX_RISE_TUNE_MASK                        GENMASK(12, 11)
  69        #define U2P_R1_TX_VREF_TUNE_MASK                        GENMASK(16, 13)
  70        #define U2P_R1_TX_FSLS_TUNE_MASK                        GENMASK(20, 17)
  71        #define U2P_R1_TX_HSXV_TUNE_MASK                        GENMASK(22, 21)
  72        #define U2P_R1_OTG_TUNE_MASK                            GENMASK(25, 23)
  73        #define U2P_R1_SQRX_TUNE_MASK                           GENMASK(28, 26)
  74        #define U2P_R1_COMP_DIS_TUNE_MASK                       GENMASK(31, 29)
  75
  76/* bits [31:14] are read-only */
  77#define U2P_R2                                                  0x8
  78        #define U2P_R2_TESTDATA_IN_MASK                         GENMASK(7, 0)
  79        #define U2P_R2_TESTADDR_MASK                            GENMASK(11, 8)
  80        #define U2P_R2_TESTDATA_OUT_SEL                         BIT(12)
  81        #define U2P_R2_TESTCLK                                  BIT(13)
  82        #define U2P_R2_TESTDATA_OUT_MASK                        GENMASK(17, 14)
  83        #define U2P_R2_ACA_PIN_RANGE_C                          BIT(18)
  84        #define U2P_R2_ACA_PIN_RANGE_B                          BIT(19)
  85        #define U2P_R2_ACA_PIN_RANGE_A                          BIT(20)
  86        #define U2P_R2_ACA_PIN_GND                              BIT(21)
  87        #define U2P_R2_ACA_PIN_FLOAT                            BIT(22)
  88        #define U2P_R2_CHARGE_DETECT                            BIT(23)
  89        #define U2P_R2_DEVICE_SESSION_VALID                     BIT(24)
  90        #define U2P_R2_ADP_PROBE                                BIT(25)
  91        #define U2P_R2_ADP_SENSE                                BIT(26)
  92        #define U2P_R2_SESSION_END                              BIT(27)
  93        #define U2P_R2_VBUS_VALID                               BIT(28)
  94        #define U2P_R2_B_VALID                                  BIT(29)
  95        #define U2P_R2_A_VALID                                  BIT(30)
  96        #define U2P_R2_ID_DIG                                   BIT(31)
  97
  98#define U2P_R3                                                  0xc
  99
 100#define RESET_COMPLETE_TIME                             500
 101
 102struct phy_meson_gxl_usb2_priv {
 103        struct regmap           *regmap;
 104#if CONFIG_IS_ENABLED(DM_REGULATOR)
 105        struct udevice          *phy_supply;
 106#endif
 107#if CONFIG_IS_ENABLED(CLK)
 108        struct clk              clk;
 109#endif
 110};
 111
 112static void phy_meson_gxl_usb2_reset(struct phy_meson_gxl_usb2_priv *priv)
 113{
 114        uint val;
 115
 116        regmap_read(priv->regmap, U2P_R0, &val);
 117
 118        /* reset the PHY and wait until settings are stabilized */
 119        val |= U2P_R0_POWER_ON_RESET;
 120        regmap_write(priv->regmap, U2P_R0, val);
 121        udelay(RESET_COMPLETE_TIME);
 122
 123        val &= ~U2P_R0_POWER_ON_RESET;
 124        regmap_write(priv->regmap, U2P_R0, val);
 125        udelay(RESET_COMPLETE_TIME);
 126}
 127
 128void phy_meson_gxl_usb2_set_mode(struct phy *phy, enum usb_dr_mode mode)
 129{
 130        struct udevice *dev = phy->dev;
 131        struct phy_meson_gxl_usb2_priv *priv = dev_get_priv(dev);
 132        uint val;
 133
 134        regmap_read(priv->regmap, U2P_R0, &val);
 135
 136        switch (mode) {
 137        case USB_DR_MODE_UNKNOWN:
 138        case USB_DR_MODE_HOST:
 139        case USB_DR_MODE_OTG:
 140                val |= U2P_R0_DM_PULLDOWN;
 141                val |= U2P_R0_DP_PULLDOWN;
 142                val &= ~U2P_R0_ID_PULLUP;
 143                break;
 144
 145        case USB_DR_MODE_PERIPHERAL:
 146                val &= ~U2P_R0_DM_PULLDOWN;
 147                val &= ~U2P_R0_DP_PULLDOWN;
 148                val |= U2P_R0_ID_PULLUP;
 149                break;
 150        }
 151
 152        regmap_write(priv->regmap, U2P_R0, val);
 153
 154        phy_meson_gxl_usb2_reset(priv);
 155}
 156
 157static int phy_meson_gxl_usb2_power_on(struct phy *phy)
 158{
 159        struct udevice *dev = phy->dev;
 160        struct phy_meson_gxl_usb2_priv *priv = dev_get_priv(dev);
 161        uint val;
 162
 163        regmap_read(priv->regmap, U2P_R0, &val);
 164        /* power on the PHY by taking it out of reset mode */
 165        val &= ~U2P_R0_POWER_ON_RESET;
 166        regmap_write(priv->regmap, U2P_R0, val);
 167
 168        phy_meson_gxl_usb2_set_mode(phy, USB_DR_MODE_HOST);
 169
 170#if CONFIG_IS_ENABLED(DM_REGULATOR)
 171        if (priv->phy_supply) {
 172                int ret = regulator_set_enable(priv->phy_supply, true);
 173                if (ret)
 174                        return ret;
 175        }
 176#endif
 177
 178        return 0;
 179}
 180
 181static int phy_meson_gxl_usb2_power_off(struct phy *phy)
 182{
 183        struct udevice *dev = phy->dev;
 184        struct phy_meson_gxl_usb2_priv *priv = dev_get_priv(dev);
 185        uint val;
 186
 187        regmap_read(priv->regmap, U2P_R0, &val);
 188        /* power off the PHY by putting it into reset mode */
 189        val |= U2P_R0_POWER_ON_RESET;
 190        regmap_write(priv->regmap, U2P_R0, val);
 191
 192#if CONFIG_IS_ENABLED(DM_REGULATOR)
 193        if (priv->phy_supply) {
 194                int ret = regulator_set_enable(priv->phy_supply, false);
 195                if (ret) {
 196                        pr_err("Error disabling PHY supply\n");
 197                        return ret;
 198                }
 199        }
 200#endif
 201
 202        return 0;
 203}
 204
 205struct phy_ops meson_gxl_usb2_phy_ops = {
 206        .power_on = phy_meson_gxl_usb2_power_on,
 207        .power_off = phy_meson_gxl_usb2_power_off,
 208};
 209
 210int meson_gxl_usb2_phy_probe(struct udevice *dev)
 211{
 212        struct phy_meson_gxl_usb2_priv *priv = dev_get_priv(dev);
 213        int ret;
 214
 215        ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
 216        if (ret)
 217                return ret;
 218
 219#if CONFIG_IS_ENABLED(CLK)
 220        ret = clk_get_by_index(dev, 0, &priv->clk);
 221        if (ret < 0)
 222                return ret;
 223
 224        ret = clk_enable(&priv->clk);
 225        if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
 226                pr_err("failed to enable PHY clock\n");
 227                clk_free(&priv->clk);
 228                return ret;
 229        }
 230#endif
 231
 232#if CONFIG_IS_ENABLED(DM_REGULATOR)
 233        ret = device_get_supply_regulator(dev, "phy-supply", &priv->phy_supply);
 234        if (ret && ret != -ENOENT) {
 235                pr_err("Failed to get PHY regulator\n");
 236                return ret;
 237        }
 238#endif
 239
 240        return 0;
 241}
 242
 243static const struct udevice_id meson_gxl_usb2_phy_ids[] = {
 244        { .compatible = "amlogic,meson-gxl-usb2-phy" },
 245        { }
 246};
 247
 248U_BOOT_DRIVER(meson_gxl_usb2_phy) = {
 249        .name = "meson_gxl_usb2_phy",
 250        .id = UCLASS_PHY,
 251        .of_match = meson_gxl_usb2_phy_ids,
 252        .probe = meson_gxl_usb2_phy_probe,
 253        .ops = &meson_gxl_usb2_phy_ops,
 254        .priv_auto_alloc_size = sizeof(struct phy_meson_gxl_usb2_priv),
 255};
 256