linux/drivers/phy/amlogic/phy-meson8b-usb2.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Meson8, Meson8b and GXBB USB2 PHY driver
   4 *
   5 * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
   6 */
   7
   8#include <linux/clk.h>
   9#include <linux/delay.h>
  10#include <linux/io.h>
  11#include <linux/module.h>
  12#include <linux/of_device.h>
  13#include <linux/property.h>
  14#include <linux/regmap.h>
  15#include <linux/reset.h>
  16#include <linux/phy/phy.h>
  17#include <linux/platform_device.h>
  18#include <linux/usb/of.h>
  19
  20#define REG_CONFIG                                      0x00
  21        #define REG_CONFIG_CLK_EN                       BIT(0)
  22        #define REG_CONFIG_CLK_SEL_MASK                 GENMASK(3, 1)
  23        #define REG_CONFIG_CLK_DIV_MASK                 GENMASK(10, 4)
  24        #define REG_CONFIG_CLK_32k_ALTSEL               BIT(15)
  25        #define REG_CONFIG_TEST_TRIG                    BIT(31)
  26
  27#define REG_CTRL                                        0x04
  28        #define REG_CTRL_SOFT_PRST                      BIT(0)
  29        #define REG_CTRL_SOFT_HRESET                    BIT(1)
  30        #define REG_CTRL_SS_SCALEDOWN_MODE_MASK         GENMASK(3, 2)
  31        #define REG_CTRL_CLK_DET_RST                    BIT(4)
  32        #define REG_CTRL_INTR_SEL                       BIT(5)
  33        #define REG_CTRL_CLK_DETECTED                   BIT(8)
  34        #define REG_CTRL_SOF_SENT_RCVD_TGL              BIT(9)
  35        #define REG_CTRL_SOF_TOGGLE_OUT                 BIT(10)
  36        #define REG_CTRL_POWER_ON_RESET                 BIT(15)
  37        #define REG_CTRL_SLEEPM                         BIT(16)
  38        #define REG_CTRL_TX_BITSTUFF_ENN_H              BIT(17)
  39        #define REG_CTRL_TX_BITSTUFF_ENN                BIT(18)
  40        #define REG_CTRL_COMMON_ON                      BIT(19)
  41        #define REG_CTRL_REF_CLK_SEL_MASK               GENMASK(21, 20)
  42        #define REG_CTRL_REF_CLK_SEL_SHIFT              20
  43        #define REG_CTRL_FSEL_MASK                      GENMASK(24, 22)
  44        #define REG_CTRL_FSEL_SHIFT                     22
  45        #define REG_CTRL_PORT_RESET                     BIT(25)
  46        #define REG_CTRL_THREAD_ID_MASK                 GENMASK(31, 26)
  47
  48#define REG_ENDP_INTR                                   0x08
  49
  50/* bits [31:26], [24:21] and [15:3] seem to be read-only */
  51#define REG_ADP_BC                                      0x0c
  52        #define REG_ADP_BC_VBUS_VLD_EXT_SEL             BIT(0)
  53        #define REG_ADP_BC_VBUS_VLD_EXT                 BIT(1)
  54        #define REG_ADP_BC_OTG_DISABLE                  BIT(2)
  55        #define REG_ADP_BC_ID_PULLUP                    BIT(3)
  56        #define REG_ADP_BC_DRV_VBUS                     BIT(4)
  57        #define REG_ADP_BC_ADP_PRB_EN                   BIT(5)
  58        #define REG_ADP_BC_ADP_DISCHARGE                BIT(6)
  59        #define REG_ADP_BC_ADP_CHARGE                   BIT(7)
  60        #define REG_ADP_BC_SESS_END                     BIT(8)
  61        #define REG_ADP_BC_DEVICE_SESS_VLD              BIT(9)
  62        #define REG_ADP_BC_B_VALID                      BIT(10)
  63        #define REG_ADP_BC_A_VALID                      BIT(11)
  64        #define REG_ADP_BC_ID_DIG                       BIT(12)
  65        #define REG_ADP_BC_VBUS_VALID                   BIT(13)
  66        #define REG_ADP_BC_ADP_PROBE                    BIT(14)
  67        #define REG_ADP_BC_ADP_SENSE                    BIT(15)
  68        #define REG_ADP_BC_ACA_ENABLE                   BIT(16)
  69        #define REG_ADP_BC_DCD_ENABLE                   BIT(17)
  70        #define REG_ADP_BC_VDAT_DET_EN_B                BIT(18)
  71        #define REG_ADP_BC_VDAT_SRC_EN_B                BIT(19)
  72        #define REG_ADP_BC_CHARGE_SEL                   BIT(20)
  73        #define REG_ADP_BC_CHARGE_DETECT                BIT(21)
  74        #define REG_ADP_BC_ACA_PIN_RANGE_C              BIT(22)
  75        #define REG_ADP_BC_ACA_PIN_RANGE_B              BIT(23)
  76        #define REG_ADP_BC_ACA_PIN_RANGE_A              BIT(24)
  77        #define REG_ADP_BC_ACA_PIN_GND                  BIT(25)
  78        #define REG_ADP_BC_ACA_PIN_FLOAT                BIT(26)
  79
  80#define REG_DBG_UART                                    0x10
  81        #define REG_DBG_UART_BYPASS_SEL                 BIT(0)
  82        #define REG_DBG_UART_BYPASS_DM_EN               BIT(1)
  83        #define REG_DBG_UART_BYPASS_DP_EN               BIT(2)
  84        #define REG_DBG_UART_BYPASS_DM_DATA             BIT(3)
  85        #define REG_DBG_UART_BYPASS_DP_DATA             BIT(4)
  86        #define REG_DBG_UART_FSV_MINUS                  BIT(5)
  87        #define REG_DBG_UART_FSV_PLUS                   BIT(6)
  88        #define REG_DBG_UART_FSV_BURN_IN_TEST           BIT(7)
  89        #define REG_DBG_UART_LOOPBACK_EN_B              BIT(8)
  90        #define REG_DBG_UART_SET_IDDQ                   BIT(9)
  91        #define REG_DBG_UART_ATE_RESET                  BIT(10)
  92
  93#define REG_TEST                                        0x14
  94        #define REG_TEST_DATA_IN_MASK                   GENMASK(3, 0)
  95        #define REG_TEST_EN_MASK                        GENMASK(7, 4)
  96        #define REG_TEST_ADDR_MASK                      GENMASK(11, 8)
  97        #define REG_TEST_DATA_OUT_SEL                   BIT(12)
  98        #define REG_TEST_CLK                            BIT(13)
  99        #define REG_TEST_VA_TEST_EN_B_MASK              GENMASK(15, 14)
 100        #define REG_TEST_DATA_OUT_MASK                  GENMASK(19, 16)
 101        #define REG_TEST_DISABLE_ID_PULLUP              BIT(20)
 102
 103#define REG_TUNE                                        0x18
 104        #define REG_TUNE_TX_RES_TUNE_MASK               GENMASK(1, 0)
 105        #define REG_TUNE_TX_HSXV_TUNE_MASK              GENMASK(3, 2)
 106        #define REG_TUNE_TX_VREF_TUNE_MASK              GENMASK(7, 4)
 107        #define REG_TUNE_TX_RISE_TUNE_MASK              GENMASK(9, 8)
 108        #define REG_TUNE_TX_PREEMP_PULSE_TUNE           BIT(10)
 109        #define REG_TUNE_TX_PREEMP_AMP_TUNE_MASK        GENMASK(12, 11)
 110        #define REG_TUNE_TX_FSLS_TUNE_MASK              GENMASK(16, 13)
 111        #define REG_TUNE_SQRX_TUNE_MASK                 GENMASK(19, 17)
 112        #define REG_TUNE_OTG_TUNE                       GENMASK(22, 20)
 113        #define REG_TUNE_COMP_DIS_TUNE                  GENMASK(25, 23)
 114        #define REG_TUNE_HOST_DM_PULLDOWN               BIT(26)
 115        #define REG_TUNE_HOST_DP_PULLDOWN               BIT(27)
 116
 117#define RESET_COMPLETE_TIME                             500
 118#define ACA_ENABLE_COMPLETE_TIME                        50
 119
 120struct phy_meson8b_usb2_match_data {
 121        bool                    host_enable_aca;
 122};
 123
 124struct phy_meson8b_usb2_priv {
 125        struct regmap                                   *regmap;
 126        enum usb_dr_mode                                dr_mode;
 127        struct clk                                      *clk_usb_general;
 128        struct clk                                      *clk_usb;
 129        struct reset_control                            *reset;
 130        const struct phy_meson8b_usb2_match_data        *match;
 131};
 132
 133static const struct regmap_config phy_meson8b_usb2_regmap_conf = {
 134        .reg_bits = 8,
 135        .val_bits = 32,
 136        .reg_stride = 4,
 137        .max_register = REG_TUNE,
 138};
 139
 140static int phy_meson8b_usb2_power_on(struct phy *phy)
 141{
 142        struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy);
 143        u32 reg;
 144        int ret;
 145
 146        if (!IS_ERR_OR_NULL(priv->reset)) {
 147                ret = reset_control_reset(priv->reset);
 148                if (ret) {
 149                        dev_err(&phy->dev, "Failed to trigger USB reset\n");
 150                        return ret;
 151                }
 152        }
 153
 154        ret = clk_prepare_enable(priv->clk_usb_general);
 155        if (ret) {
 156                dev_err(&phy->dev, "Failed to enable USB general clock\n");
 157                return ret;
 158        }
 159
 160        ret = clk_prepare_enable(priv->clk_usb);
 161        if (ret) {
 162                dev_err(&phy->dev, "Failed to enable USB DDR clock\n");
 163                clk_disable_unprepare(priv->clk_usb_general);
 164                return ret;
 165        }
 166
 167        regmap_update_bits(priv->regmap, REG_CONFIG, REG_CONFIG_CLK_32k_ALTSEL,
 168                           REG_CONFIG_CLK_32k_ALTSEL);
 169
 170        regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_REF_CLK_SEL_MASK,
 171                           0x2 << REG_CTRL_REF_CLK_SEL_SHIFT);
 172
 173        regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_FSEL_MASK,
 174                           0x5 << REG_CTRL_FSEL_SHIFT);
 175
 176        /* reset the PHY */
 177        regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_POWER_ON_RESET,
 178                           REG_CTRL_POWER_ON_RESET);
 179        udelay(RESET_COMPLETE_TIME);
 180        regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_POWER_ON_RESET, 0);
 181        udelay(RESET_COMPLETE_TIME);
 182
 183        regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_SOF_TOGGLE_OUT,
 184                           REG_CTRL_SOF_TOGGLE_OUT);
 185
 186        if (priv->dr_mode == USB_DR_MODE_HOST) {
 187                regmap_update_bits(priv->regmap, REG_DBG_UART,
 188                                   REG_DBG_UART_SET_IDDQ, 0);
 189
 190                if (priv->match->host_enable_aca) {
 191                        regmap_update_bits(priv->regmap, REG_ADP_BC,
 192                                           REG_ADP_BC_ACA_ENABLE,
 193                                           REG_ADP_BC_ACA_ENABLE);
 194
 195                        udelay(ACA_ENABLE_COMPLETE_TIME);
 196
 197                        regmap_read(priv->regmap, REG_ADP_BC, &reg);
 198                        if (reg & REG_ADP_BC_ACA_PIN_FLOAT) {
 199                                dev_warn(&phy->dev, "USB ID detect failed!\n");
 200                                clk_disable_unprepare(priv->clk_usb);
 201                                clk_disable_unprepare(priv->clk_usb_general);
 202                                return -EINVAL;
 203                        }
 204                }
 205        }
 206
 207        return 0;
 208}
 209
 210static int phy_meson8b_usb2_power_off(struct phy *phy)
 211{
 212        struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy);
 213
 214        if (priv->dr_mode == USB_DR_MODE_HOST)
 215                regmap_update_bits(priv->regmap, REG_DBG_UART,
 216                                   REG_DBG_UART_SET_IDDQ,
 217                                   REG_DBG_UART_SET_IDDQ);
 218
 219        clk_disable_unprepare(priv->clk_usb);
 220        clk_disable_unprepare(priv->clk_usb_general);
 221
 222        /* power off the PHY by putting it into reset mode */
 223        regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_POWER_ON_RESET,
 224                           REG_CTRL_POWER_ON_RESET);
 225
 226        return 0;
 227}
 228
 229static const struct phy_ops phy_meson8b_usb2_ops = {
 230        .power_on       = phy_meson8b_usb2_power_on,
 231        .power_off      = phy_meson8b_usb2_power_off,
 232        .owner          = THIS_MODULE,
 233};
 234
 235static int phy_meson8b_usb2_probe(struct platform_device *pdev)
 236{
 237        struct phy_meson8b_usb2_priv *priv;
 238        struct phy *phy;
 239        struct phy_provider *phy_provider;
 240        void __iomem *base;
 241
 242        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 243        if (!priv)
 244                return -ENOMEM;
 245
 246        base = devm_platform_ioremap_resource(pdev, 0);
 247        if (IS_ERR(base))
 248                return PTR_ERR(base);
 249
 250        priv->match = device_get_match_data(&pdev->dev);
 251        if (!priv->match)
 252                return -ENODEV;
 253
 254        priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
 255                                             &phy_meson8b_usb2_regmap_conf);
 256        if (IS_ERR(priv->regmap))
 257                return PTR_ERR(priv->regmap);
 258
 259        priv->clk_usb_general = devm_clk_get(&pdev->dev, "usb_general");
 260        if (IS_ERR(priv->clk_usb_general))
 261                return PTR_ERR(priv->clk_usb_general);
 262
 263        priv->clk_usb = devm_clk_get(&pdev->dev, "usb");
 264        if (IS_ERR(priv->clk_usb))
 265                return PTR_ERR(priv->clk_usb);
 266
 267        priv->reset = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
 268        if (PTR_ERR(priv->reset) == -EPROBE_DEFER)
 269                return PTR_ERR(priv->reset);
 270
 271        priv->dr_mode = of_usb_get_dr_mode_by_phy(pdev->dev.of_node, -1);
 272        if (priv->dr_mode == USB_DR_MODE_UNKNOWN) {
 273                dev_err(&pdev->dev,
 274                        "missing dual role configuration of the controller\n");
 275                return -EINVAL;
 276        }
 277
 278        phy = devm_phy_create(&pdev->dev, NULL, &phy_meson8b_usb2_ops);
 279        if (IS_ERR(phy)) {
 280                return dev_err_probe(&pdev->dev, PTR_ERR(phy),
 281                                     "failed to create PHY\n");
 282        }
 283
 284        phy_set_drvdata(phy, priv);
 285
 286        phy_provider =
 287                devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
 288
 289        return PTR_ERR_OR_ZERO(phy_provider);
 290}
 291
 292static const struct phy_meson8b_usb2_match_data phy_meson8_usb2_match_data = {
 293        .host_enable_aca = false,
 294};
 295
 296static const struct phy_meson8b_usb2_match_data phy_meson8b_usb2_match_data = {
 297        .host_enable_aca = true,
 298};
 299
 300static const struct of_device_id phy_meson8b_usb2_of_match[] = {
 301        {
 302                .compatible = "amlogic,meson8-usb2-phy",
 303                .data = &phy_meson8_usb2_match_data
 304        },
 305        {
 306                .compatible = "amlogic,meson8b-usb2-phy",
 307                .data = &phy_meson8b_usb2_match_data
 308        },
 309        {
 310                .compatible = "amlogic,meson8m2-usb2-phy",
 311                .data = &phy_meson8b_usb2_match_data
 312        },
 313        {
 314                .compatible = "amlogic,meson-gxbb-usb2-phy",
 315                .data = &phy_meson8b_usb2_match_data
 316        },
 317        { /* sentinel */ }
 318};
 319MODULE_DEVICE_TABLE(of, phy_meson8b_usb2_of_match);
 320
 321static struct platform_driver phy_meson8b_usb2_driver = {
 322        .probe  = phy_meson8b_usb2_probe,
 323        .driver = {
 324                .name           = "phy-meson-usb2",
 325                .of_match_table = phy_meson8b_usb2_of_match,
 326        },
 327};
 328module_platform_driver(phy_meson8b_usb2_driver);
 329
 330MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
 331MODULE_DESCRIPTION("Meson8, Meson8b, Meson8m2 and GXBB USB2 PHY driver");
 332MODULE_LICENSE("GPL");
 333