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