Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Lantiq XWAY SoC RCU module based USB 1.1/2.0 PHY driver
0004  *
0005  * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
0006  * Copyright (C) 2017 Hauke Mehrtens <hauke@hauke-m.de>
0007  */
0008 
0009 #include <linux/clk.h>
0010 #include <linux/delay.h>
0011 #include <linux/mfd/syscon.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/of_address.h>
0015 #include <linux/of_device.h>
0016 #include <linux/phy/phy.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/property.h>
0019 #include <linux/regmap.h>
0020 #include <linux/reset.h>
0021 
0022 /* Transmitter HS Pre-Emphasis Enable */
0023 #define RCU_CFG1_TX_PEE     BIT(0)
0024 /* Disconnect Threshold */
0025 #define RCU_CFG1_DIS_THR_MASK   0x00038000
0026 #define RCU_CFG1_DIS_THR_SHIFT  15
0027 
0028 struct ltq_rcu_usb2_bits {
0029     u8 hostmode;
0030     u8 slave_endianness;
0031     u8 host_endianness;
0032     bool have_ana_cfg;
0033 };
0034 
0035 struct ltq_rcu_usb2_priv {
0036     struct regmap           *regmap;
0037     unsigned int            phy_reg_offset;
0038     unsigned int            ana_cfg1_reg_offset;
0039     const struct ltq_rcu_usb2_bits  *reg_bits;
0040     struct device           *dev;
0041     struct phy          *phy;
0042     struct clk          *phy_gate_clk;
0043     struct reset_control        *ctrl_reset;
0044     struct reset_control        *phy_reset;
0045 };
0046 
0047 static const struct ltq_rcu_usb2_bits xway_rcu_usb2_reg_bits = {
0048     .hostmode = 11,
0049     .slave_endianness = 9,
0050     .host_endianness = 10,
0051     .have_ana_cfg = false,
0052 };
0053 
0054 static const struct ltq_rcu_usb2_bits xrx100_rcu_usb2_reg_bits = {
0055     .hostmode = 11,
0056     .slave_endianness = 17,
0057     .host_endianness = 10,
0058     .have_ana_cfg = false,
0059 };
0060 
0061 static const struct ltq_rcu_usb2_bits xrx200_rcu_usb2_reg_bits = {
0062     .hostmode = 11,
0063     .slave_endianness = 9,
0064     .host_endianness = 10,
0065     .have_ana_cfg = true,
0066 };
0067 
0068 static const struct of_device_id ltq_rcu_usb2_phy_of_match[] = {
0069     {
0070         .compatible = "lantiq,ase-usb2-phy",
0071         .data = &xway_rcu_usb2_reg_bits,
0072     },
0073     {
0074         .compatible = "lantiq,danube-usb2-phy",
0075         .data = &xway_rcu_usb2_reg_bits,
0076     },
0077     {
0078         .compatible = "lantiq,xrx100-usb2-phy",
0079         .data = &xrx100_rcu_usb2_reg_bits,
0080     },
0081     {
0082         .compatible = "lantiq,xrx200-usb2-phy",
0083         .data = &xrx200_rcu_usb2_reg_bits,
0084     },
0085     {
0086         .compatible = "lantiq,xrx300-usb2-phy",
0087         .data = &xrx200_rcu_usb2_reg_bits,
0088     },
0089     { },
0090 };
0091 MODULE_DEVICE_TABLE(of, ltq_rcu_usb2_phy_of_match);
0092 
0093 static int ltq_rcu_usb2_phy_init(struct phy *phy)
0094 {
0095     struct ltq_rcu_usb2_priv *priv = phy_get_drvdata(phy);
0096 
0097     if (priv->reg_bits->have_ana_cfg) {
0098         regmap_update_bits(priv->regmap, priv->ana_cfg1_reg_offset,
0099             RCU_CFG1_TX_PEE, RCU_CFG1_TX_PEE);
0100         regmap_update_bits(priv->regmap, priv->ana_cfg1_reg_offset,
0101             RCU_CFG1_DIS_THR_MASK, 7 << RCU_CFG1_DIS_THR_SHIFT);
0102     }
0103 
0104     /* Configure core to host mode */
0105     regmap_update_bits(priv->regmap, priv->phy_reg_offset,
0106                BIT(priv->reg_bits->hostmode), 0);
0107 
0108     /* Select DMA endianness (Host-endian: big-endian) */
0109     regmap_update_bits(priv->regmap, priv->phy_reg_offset,
0110         BIT(priv->reg_bits->slave_endianness), 0);
0111     regmap_update_bits(priv->regmap, priv->phy_reg_offset,
0112         BIT(priv->reg_bits->host_endianness),
0113         BIT(priv->reg_bits->host_endianness));
0114 
0115     return 0;
0116 }
0117 
0118 static int ltq_rcu_usb2_phy_power_on(struct phy *phy)
0119 {
0120     struct ltq_rcu_usb2_priv *priv = phy_get_drvdata(phy);
0121     struct device *dev = priv->dev;
0122     int ret;
0123 
0124     reset_control_deassert(priv->phy_reset);
0125 
0126     ret = clk_prepare_enable(priv->phy_gate_clk);
0127     if (ret) {
0128         dev_err(dev, "failed to enable PHY gate\n");
0129         return ret;
0130     }
0131 
0132     /*
0133      * at least the xrx200 usb2 phy requires some extra time to be
0134      * operational after enabling the clock
0135      */
0136     usleep_range(100, 200);
0137 
0138     return ret;
0139 }
0140 
0141 static int ltq_rcu_usb2_phy_power_off(struct phy *phy)
0142 {
0143     struct ltq_rcu_usb2_priv *priv = phy_get_drvdata(phy);
0144 
0145     reset_control_assert(priv->phy_reset);
0146 
0147     clk_disable_unprepare(priv->phy_gate_clk);
0148 
0149     return 0;
0150 }
0151 
0152 static const struct phy_ops ltq_rcu_usb2_phy_ops = {
0153     .init       = ltq_rcu_usb2_phy_init,
0154     .power_on   = ltq_rcu_usb2_phy_power_on,
0155     .power_off  = ltq_rcu_usb2_phy_power_off,
0156     .owner      = THIS_MODULE,
0157 };
0158 
0159 static int ltq_rcu_usb2_of_parse(struct ltq_rcu_usb2_priv *priv,
0160                  struct platform_device *pdev)
0161 {
0162     struct device *dev = priv->dev;
0163     const __be32 *offset;
0164 
0165     priv->reg_bits = of_device_get_match_data(dev);
0166 
0167     priv->regmap = syscon_node_to_regmap(dev->of_node->parent);
0168     if (IS_ERR(priv->regmap)) {
0169         dev_err(dev, "Failed to lookup RCU regmap\n");
0170         return PTR_ERR(priv->regmap);
0171     }
0172 
0173     offset = of_get_address(dev->of_node, 0, NULL, NULL);
0174     if (!offset) {
0175         dev_err(dev, "Failed to get RCU PHY reg offset\n");
0176         return -ENOENT;
0177     }
0178     priv->phy_reg_offset = __be32_to_cpu(*offset);
0179 
0180     if (priv->reg_bits->have_ana_cfg) {
0181         offset = of_get_address(dev->of_node, 1, NULL, NULL);
0182         if (!offset) {
0183             dev_err(dev, "Failed to get RCU ANA CFG1 reg offset\n");
0184             return -ENOENT;
0185         }
0186         priv->ana_cfg1_reg_offset = __be32_to_cpu(*offset);
0187     }
0188 
0189     priv->phy_gate_clk = devm_clk_get(dev, "phy");
0190     if (IS_ERR(priv->phy_gate_clk)) {
0191         dev_err(dev, "Unable to get USB phy gate clk\n");
0192         return PTR_ERR(priv->phy_gate_clk);
0193     }
0194 
0195     priv->ctrl_reset = devm_reset_control_get_shared(dev, "ctrl");
0196     if (IS_ERR(priv->ctrl_reset)) {
0197         if (PTR_ERR(priv->ctrl_reset) != -EPROBE_DEFER)
0198             dev_err(dev, "failed to get 'ctrl' reset\n");
0199         return PTR_ERR(priv->ctrl_reset);
0200     }
0201 
0202     priv->phy_reset = devm_reset_control_get_optional(dev, "phy");
0203 
0204     return PTR_ERR_OR_ZERO(priv->phy_reset);
0205 }
0206 
0207 static int ltq_rcu_usb2_phy_probe(struct platform_device *pdev)
0208 {
0209     struct device *dev = &pdev->dev;
0210     struct ltq_rcu_usb2_priv *priv;
0211     struct phy_provider *provider;
0212     int ret;
0213 
0214     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0215     if (!priv)
0216         return -ENOMEM;
0217 
0218     priv->dev = dev;
0219 
0220     ret = ltq_rcu_usb2_of_parse(priv, pdev);
0221     if (ret)
0222         return ret;
0223 
0224     /* Reset USB core through reset controller */
0225     reset_control_deassert(priv->ctrl_reset);
0226 
0227     reset_control_assert(priv->phy_reset);
0228 
0229     priv->phy = devm_phy_create(dev, dev->of_node, &ltq_rcu_usb2_phy_ops);
0230     if (IS_ERR(priv->phy)) {
0231         dev_err(dev, "failed to create PHY\n");
0232         return PTR_ERR(priv->phy);
0233     }
0234 
0235     phy_set_drvdata(priv->phy, priv);
0236 
0237     provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
0238     if (IS_ERR(provider))
0239         return PTR_ERR(provider);
0240 
0241     dev_set_drvdata(priv->dev, priv);
0242     return 0;
0243 }
0244 
0245 static struct platform_driver ltq_rcu_usb2_phy_driver = {
0246     .probe  = ltq_rcu_usb2_phy_probe,
0247     .driver = {
0248         .name   = "lantiq-rcu-usb2-phy",
0249         .of_match_table = ltq_rcu_usb2_phy_of_match,
0250     }
0251 };
0252 module_platform_driver(ltq_rcu_usb2_phy_driver);
0253 
0254 MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
0255 MODULE_DESCRIPTION("Lantiq XWAY USB2 PHY driver");
0256 MODULE_LICENSE("GPL v2");