linux/drivers/phy/lantiq/phy-lantiq-rcu-usb2.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Lantiq XWAY SoC RCU module based USB 1.1/2.0 PHY driver
   4 *
   5 * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
   6 * Copyright (C) 2017 Hauke Mehrtens <hauke@hauke-m.de>
   7 */
   8
   9#include <linux/clk.h>
  10#include <linux/delay.h>
  11#include <linux/mfd/syscon.h>
  12#include <linux/module.h>
  13#include <linux/of.h>
  14#include <linux/of_address.h>
  15#include <linux/of_device.h>
  16#include <linux/phy/phy.h>
  17#include <linux/platform_device.h>
  18#include <linux/property.h>
  19#include <linux/regmap.h>
  20#include <linux/reset.h>
  21
  22/* Transmitter HS Pre-Emphasis Enable */
  23#define RCU_CFG1_TX_PEE         BIT(0)
  24/* Disconnect Threshold */
  25#define RCU_CFG1_DIS_THR_MASK   0x00038000
  26#define RCU_CFG1_DIS_THR_SHIFT  15
  27
  28struct ltq_rcu_usb2_bits {
  29        u8 hostmode;
  30        u8 slave_endianness;
  31        u8 host_endianness;
  32        bool have_ana_cfg;
  33};
  34
  35struct ltq_rcu_usb2_priv {
  36        struct regmap                   *regmap;
  37        unsigned int                    phy_reg_offset;
  38        unsigned int                    ana_cfg1_reg_offset;
  39        const struct ltq_rcu_usb2_bits  *reg_bits;
  40        struct device                   *dev;
  41        struct phy                      *phy;
  42        struct clk                      *phy_gate_clk;
  43        struct reset_control            *ctrl_reset;
  44        struct reset_control            *phy_reset;
  45};
  46
  47static const struct ltq_rcu_usb2_bits xway_rcu_usb2_reg_bits = {
  48        .hostmode = 11,
  49        .slave_endianness = 9,
  50        .host_endianness = 10,
  51        .have_ana_cfg = false,
  52};
  53
  54static const struct ltq_rcu_usb2_bits xrx100_rcu_usb2_reg_bits = {
  55        .hostmode = 11,
  56        .slave_endianness = 17,
  57        .host_endianness = 10,
  58        .have_ana_cfg = false,
  59};
  60
  61static const struct ltq_rcu_usb2_bits xrx200_rcu_usb2_reg_bits = {
  62        .hostmode = 11,
  63        .slave_endianness = 9,
  64        .host_endianness = 10,
  65        .have_ana_cfg = true,
  66};
  67
  68static const struct of_device_id ltq_rcu_usb2_phy_of_match[] = {
  69        {
  70                .compatible = "lantiq,ase-usb2-phy",
  71                .data = &xway_rcu_usb2_reg_bits,
  72        },
  73        {
  74                .compatible = "lantiq,danube-usb2-phy",
  75                .data = &xway_rcu_usb2_reg_bits,
  76        },
  77        {
  78                .compatible = "lantiq,xrx100-usb2-phy",
  79                .data = &xrx100_rcu_usb2_reg_bits,
  80        },
  81        {
  82                .compatible = "lantiq,xrx200-usb2-phy",
  83                .data = &xrx200_rcu_usb2_reg_bits,
  84        },
  85        {
  86                .compatible = "lantiq,xrx300-usb2-phy",
  87                .data = &xrx200_rcu_usb2_reg_bits,
  88        },
  89        { },
  90};
  91MODULE_DEVICE_TABLE(of, ltq_rcu_usb2_phy_of_match);
  92
  93static int ltq_rcu_usb2_phy_init(struct phy *phy)
  94{
  95        struct ltq_rcu_usb2_priv *priv = phy_get_drvdata(phy);
  96
  97        if (priv->reg_bits->have_ana_cfg) {
  98                regmap_update_bits(priv->regmap, priv->ana_cfg1_reg_offset,
  99                        RCU_CFG1_TX_PEE, RCU_CFG1_TX_PEE);
 100                regmap_update_bits(priv->regmap, priv->ana_cfg1_reg_offset,
 101                        RCU_CFG1_DIS_THR_MASK, 7 << RCU_CFG1_DIS_THR_SHIFT);
 102        }
 103
 104        /* Configure core to host mode */
 105        regmap_update_bits(priv->regmap, priv->phy_reg_offset,
 106                           BIT(priv->reg_bits->hostmode), 0);
 107
 108        /* Select DMA endianness (Host-endian: big-endian) */
 109        regmap_update_bits(priv->regmap, priv->phy_reg_offset,
 110                BIT(priv->reg_bits->slave_endianness), 0);
 111        regmap_update_bits(priv->regmap, priv->phy_reg_offset,
 112                BIT(priv->reg_bits->host_endianness),
 113                BIT(priv->reg_bits->host_endianness));
 114
 115        return 0;
 116}
 117
 118static int ltq_rcu_usb2_phy_power_on(struct phy *phy)
 119{
 120        struct ltq_rcu_usb2_priv *priv = phy_get_drvdata(phy);
 121        struct device *dev = priv->dev;
 122        int ret;
 123
 124        reset_control_deassert(priv->phy_reset);
 125
 126        ret = clk_prepare_enable(priv->phy_gate_clk);
 127        if (ret) {
 128                dev_err(dev, "failed to enable PHY gate\n");
 129                return ret;
 130        }
 131
 132        /*
 133         * at least the xrx200 usb2 phy requires some extra time to be
 134         * operational after enabling the clock
 135         */
 136        usleep_range(100, 200);
 137
 138        return ret;
 139}
 140
 141static int ltq_rcu_usb2_phy_power_off(struct phy *phy)
 142{
 143        struct ltq_rcu_usb2_priv *priv = phy_get_drvdata(phy);
 144
 145        reset_control_assert(priv->phy_reset);
 146
 147        clk_disable_unprepare(priv->phy_gate_clk);
 148
 149        return 0;
 150}
 151
 152static const struct phy_ops ltq_rcu_usb2_phy_ops = {
 153        .init           = ltq_rcu_usb2_phy_init,
 154        .power_on       = ltq_rcu_usb2_phy_power_on,
 155        .power_off      = ltq_rcu_usb2_phy_power_off,
 156        .owner          = THIS_MODULE,
 157};
 158
 159static int ltq_rcu_usb2_of_parse(struct ltq_rcu_usb2_priv *priv,
 160                                 struct platform_device *pdev)
 161{
 162        struct device *dev = priv->dev;
 163        const __be32 *offset;
 164
 165        priv->reg_bits = of_device_get_match_data(dev);
 166
 167        priv->regmap = syscon_node_to_regmap(dev->of_node->parent);
 168        if (IS_ERR(priv->regmap)) {
 169                dev_err(dev, "Failed to lookup RCU regmap\n");
 170                return PTR_ERR(priv->regmap);
 171        }
 172
 173        offset = of_get_address(dev->of_node, 0, NULL, NULL);
 174        if (!offset) {
 175                dev_err(dev, "Failed to get RCU PHY reg offset\n");
 176                return -ENOENT;
 177        }
 178        priv->phy_reg_offset = __be32_to_cpu(*offset);
 179
 180        if (priv->reg_bits->have_ana_cfg) {
 181                offset = of_get_address(dev->of_node, 1, NULL, NULL);
 182                if (!offset) {
 183                        dev_err(dev, "Failed to get RCU ANA CFG1 reg offset\n");
 184                        return -ENOENT;
 185                }
 186                priv->ana_cfg1_reg_offset = __be32_to_cpu(*offset);
 187        }
 188
 189        priv->phy_gate_clk = devm_clk_get(dev, "phy");
 190        if (IS_ERR(priv->phy_gate_clk)) {
 191                dev_err(dev, "Unable to get USB phy gate clk\n");
 192                return PTR_ERR(priv->phy_gate_clk);
 193        }
 194
 195        priv->ctrl_reset = devm_reset_control_get_shared(dev, "ctrl");
 196        if (IS_ERR(priv->ctrl_reset)) {
 197                if (PTR_ERR(priv->ctrl_reset) != -EPROBE_DEFER)
 198                        dev_err(dev, "failed to get 'ctrl' reset\n");
 199                return PTR_ERR(priv->ctrl_reset);
 200        }
 201
 202        priv->phy_reset = devm_reset_control_get_optional(dev, "phy");
 203
 204        return PTR_ERR_OR_ZERO(priv->phy_reset);
 205}
 206
 207static int ltq_rcu_usb2_phy_probe(struct platform_device *pdev)
 208{
 209        struct device *dev = &pdev->dev;
 210        struct ltq_rcu_usb2_priv *priv;
 211        struct phy_provider *provider;
 212        int ret;
 213
 214        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 215        if (!priv)
 216                return -ENOMEM;
 217
 218        priv->dev = dev;
 219
 220        ret = ltq_rcu_usb2_of_parse(priv, pdev);
 221        if (ret)
 222                return ret;
 223
 224        /* Reset USB core through reset controller */
 225        reset_control_deassert(priv->ctrl_reset);
 226
 227        reset_control_assert(priv->phy_reset);
 228
 229        priv->phy = devm_phy_create(dev, dev->of_node, &ltq_rcu_usb2_phy_ops);
 230        if (IS_ERR(priv->phy)) {
 231                dev_err(dev, "failed to create PHY\n");
 232                return PTR_ERR(priv->phy);
 233        }
 234
 235        phy_set_drvdata(priv->phy, priv);
 236
 237        provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
 238        if (IS_ERR(provider))
 239                return PTR_ERR(provider);
 240
 241        dev_set_drvdata(priv->dev, priv);
 242        return 0;
 243}
 244
 245static struct platform_driver ltq_rcu_usb2_phy_driver = {
 246        .probe  = ltq_rcu_usb2_phy_probe,
 247        .driver = {
 248                .name   = "lantiq-rcu-usb2-phy",
 249                .of_match_table = ltq_rcu_usb2_phy_of_match,
 250        }
 251};
 252module_platform_driver(ltq_rcu_usb2_phy_driver);
 253
 254MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
 255MODULE_DESCRIPTION("Lantiq XWAY USB2 PHY driver");
 256MODULE_LICENSE("GPL v2");
 257