448 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Amlogic G12A USB3 + PCIE Combo PHY driver4 *5 * Copyright (C) 2017 Amlogic, Inc. All rights reserved6 * Copyright (C) 2019 BayLibre, SAS7 * Author: Neil Armstrong <narmstrong@baylibre.com>8 */9 10#include <linux/bitfield.h>11#include <linux/bitops.h>12#include <linux/clk.h>13#include <linux/module.h>14#include <linux/of.h>15#include <linux/phy/phy.h>16#include <linux/regmap.h>17#include <linux/reset.h>18#include <linux/platform_device.h>19#include <dt-bindings/phy/phy.h>20 21#define PHY_R0 0x0022 #define PHY_R0_PCIE_POWER_STATE GENMASK(4, 0)23 #define PHY_R0_PCIE_USB3_SWITCH GENMASK(6, 5)24 25#define PHY_R1 0x0426 #define PHY_R1_PHY_TX1_TERM_OFFSET GENMASK(4, 0)27 #define PHY_R1_PHY_TX0_TERM_OFFSET GENMASK(9, 5)28 #define PHY_R1_PHY_RX1_EQ GENMASK(12, 10)29 #define PHY_R1_PHY_RX0_EQ GENMASK(15, 13)30 #define PHY_R1_PHY_LOS_LEVEL GENMASK(20, 16)31 #define PHY_R1_PHY_LOS_BIAS GENMASK(23, 21)32 #define PHY_R1_PHY_REF_CLKDIV2 BIT(24)33 #define PHY_R1_PHY_MPLL_MULTIPLIER GENMASK(31, 25)34 35#define PHY_R2 0x0836 #define PHY_R2_PCS_TX_DEEMPH_GEN2_6DB GENMASK(5, 0)37 #define PHY_R2_PCS_TX_DEEMPH_GEN2_3P5DB GENMASK(11, 6)38 #define PHY_R2_PCS_TX_DEEMPH_GEN1 GENMASK(17, 12)39 #define PHY_R2_PHY_TX_VBOOST_LVL GENMASK(20, 18)40 41#define PHY_R4 0x1042 #define PHY_R4_PHY_CR_WRITE BIT(0)43 #define PHY_R4_PHY_CR_READ BIT(1)44 #define PHY_R4_PHY_CR_DATA_IN GENMASK(17, 2)45 #define PHY_R4_PHY_CR_CAP_DATA BIT(18)46 #define PHY_R4_PHY_CR_CAP_ADDR BIT(19)47 48#define PHY_R5 0x1449 #define PHY_R5_PHY_CR_DATA_OUT GENMASK(15, 0)50 #define PHY_R5_PHY_CR_ACK BIT(16)51 #define PHY_R5_PHY_BS_OUT BIT(17)52 53#define PCIE_RESET_DELAY 50054 55struct phy_g12a_usb3_pcie_priv {56 struct regmap *regmap;57 struct regmap *regmap_cr;58 struct clk *clk_ref;59 struct reset_control *reset;60 struct phy *phy;61 unsigned int mode;62};63 64static const struct regmap_config phy_g12a_usb3_pcie_regmap_conf = {65 .reg_bits = 8,66 .val_bits = 32,67 .reg_stride = 4,68 .max_register = PHY_R5,69};70 71static int phy_g12a_usb3_pcie_cr_bus_addr(struct phy_g12a_usb3_pcie_priv *priv,72 unsigned int addr)73{74 unsigned int val, reg;75 int ret;76 77 reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, addr);78 79 regmap_write(priv->regmap, PHY_R4, reg);80 regmap_write(priv->regmap, PHY_R4, reg);81 82 regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_ADDR);83 84 ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,85 (val & PHY_R5_PHY_CR_ACK),86 5, 1000);87 if (ret)88 return ret;89 90 regmap_write(priv->regmap, PHY_R4, reg);91 92 ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,93 !(val & PHY_R5_PHY_CR_ACK),94 5, 1000);95 if (ret)96 return ret;97 98 return 0;99}100 101static int phy_g12a_usb3_pcie_cr_bus_read(void *context, unsigned int addr,102 unsigned int *data)103{104 struct phy_g12a_usb3_pcie_priv *priv = context;105 unsigned int val;106 int ret;107 108 ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr);109 if (ret)110 return ret;111 112 regmap_write(priv->regmap, PHY_R4, 0);113 regmap_write(priv->regmap, PHY_R4, PHY_R4_PHY_CR_READ);114 115 ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,116 (val & PHY_R5_PHY_CR_ACK),117 5, 1000);118 if (ret)119 return ret;120 121 *data = FIELD_GET(PHY_R5_PHY_CR_DATA_OUT, val);122 123 regmap_write(priv->regmap, PHY_R4, 0);124 125 ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,126 !(val & PHY_R5_PHY_CR_ACK),127 5, 1000);128 if (ret)129 return ret;130 131 return 0;132}133 134static int phy_g12a_usb3_pcie_cr_bus_write(void *context, unsigned int addr,135 unsigned int data)136{137 struct phy_g12a_usb3_pcie_priv *priv = context;138 unsigned int val, reg;139 int ret;140 141 ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr);142 if (ret)143 return ret;144 145 reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, data);146 147 regmap_write(priv->regmap, PHY_R4, reg);148 regmap_write(priv->regmap, PHY_R4, reg);149 150 regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_DATA);151 152 ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,153 (val & PHY_R5_PHY_CR_ACK),154 5, 1000);155 if (ret)156 return ret;157 158 regmap_write(priv->regmap, PHY_R4, reg);159 160 ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,161 (val & PHY_R5_PHY_CR_ACK) == 0,162 5, 1000);163 if (ret)164 return ret;165 166 regmap_write(priv->regmap, PHY_R4, reg);167 168 regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_WRITE);169 170 ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,171 (val & PHY_R5_PHY_CR_ACK),172 5, 1000);173 if (ret)174 return ret;175 176 regmap_write(priv->regmap, PHY_R4, reg);177 178 ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,179 (val & PHY_R5_PHY_CR_ACK) == 0,180 5, 1000);181 if (ret)182 return ret;183 184 return 0;185}186 187static const struct regmap_config phy_g12a_usb3_pcie_cr_regmap_conf = {188 .reg_bits = 16,189 .val_bits = 16,190 .reg_read = phy_g12a_usb3_pcie_cr_bus_read,191 .reg_write = phy_g12a_usb3_pcie_cr_bus_write,192 .max_register = 0xffff,193 .disable_locking = true,194};195 196static int phy_g12a_usb3_init(struct phy *phy)197{198 struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy);199 int data, ret;200 201 ret = reset_control_reset(priv->reset);202 if (ret)203 return ret;204 205 /* Switch PHY to USB3 */206 /* TODO figure out how to handle when PCIe was set in the bootloader */207 regmap_update_bits(priv->regmap, PHY_R0,208 PHY_R0_PCIE_USB3_SWITCH,209 PHY_R0_PCIE_USB3_SWITCH);210 211 /*212 * WORKAROUND: There is SSPHY suspend bug due to213 * which USB enumerates214 * in HS mode instead of SS mode. Workaround it by asserting215 * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus216 * mode217 */218 ret = regmap_update_bits(priv->regmap_cr, 0x102d, BIT(7), BIT(7));219 if (ret)220 return ret;221 222 ret = regmap_update_bits(priv->regmap_cr, 0x1010, 0xff0, 20);223 if (ret)224 return ret;225 226 /*227 * Fix RX Equalization setting as follows228 * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0229 * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1230 * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3231 * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1232 */233 ret = regmap_read(priv->regmap_cr, 0x1006, &data);234 if (ret)235 return ret;236 237 data &= ~BIT(6);238 data |= BIT(7);239 data &= ~(0x7 << 8);240 data |= (0x3 << 8);241 data |= (1 << 11);242 ret = regmap_write(priv->regmap_cr, 0x1006, data);243 if (ret)244 return ret;245 246 /*247 * Set EQ and TX launch amplitudes as follows248 * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22249 * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127250 * LANE0.TX_OVRD_DRV_LO.EN set to 1.251 */252 ret = regmap_read(priv->regmap_cr, 0x1002, &data);253 if (ret)254 return ret;255 256 data &= ~0x3f80;257 data |= (0x16 << 7);258 data &= ~0x7f;259 data |= (0x7f | BIT(14));260 ret = regmap_write(priv->regmap_cr, 0x1002, data);261 if (ret)262 return ret;263 264 /* MPLL_LOOP_CTL.PROP_CNTRL = 8 */265 ret = regmap_update_bits(priv->regmap_cr, 0x30, 0xf << 4, 8 << 4);266 if (ret)267 return ret;268 269 regmap_update_bits(priv->regmap, PHY_R2,270 PHY_R2_PHY_TX_VBOOST_LVL,271 FIELD_PREP(PHY_R2_PHY_TX_VBOOST_LVL, 0x4));272 273 regmap_update_bits(priv->regmap, PHY_R1,274 PHY_R1_PHY_LOS_BIAS | PHY_R1_PHY_LOS_LEVEL,275 FIELD_PREP(PHY_R1_PHY_LOS_BIAS, 4) |276 FIELD_PREP(PHY_R1_PHY_LOS_LEVEL, 9));277 278 return 0;279}280 281static int phy_g12a_usb3_pcie_power_on(struct phy *phy)282{283 struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy);284 285 if (priv->mode == PHY_TYPE_USB3)286 return 0;287 288 regmap_update_bits(priv->regmap, PHY_R0,289 PHY_R0_PCIE_POWER_STATE,290 FIELD_PREP(PHY_R0_PCIE_POWER_STATE, 0x1c));291 292 return 0;293}294 295static int phy_g12a_usb3_pcie_power_off(struct phy *phy)296{297 struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy);298 299 if (priv->mode == PHY_TYPE_USB3)300 return 0;301 302 regmap_update_bits(priv->regmap, PHY_R0,303 PHY_R0_PCIE_POWER_STATE,304 FIELD_PREP(PHY_R0_PCIE_POWER_STATE, 0x1d));305 306 return 0;307}308 309static int phy_g12a_usb3_pcie_reset(struct phy *phy)310{311 struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy);312 int ret;313 314 if (priv->mode == PHY_TYPE_USB3)315 return 0;316 317 ret = reset_control_assert(priv->reset);318 if (ret)319 return ret;320 321 udelay(PCIE_RESET_DELAY);322 323 ret = reset_control_deassert(priv->reset);324 if (ret)325 return ret;326 327 udelay(PCIE_RESET_DELAY);328 329 return 0;330}331 332static int phy_g12a_usb3_pcie_init(struct phy *phy)333{334 struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy);335 336 if (priv->mode == PHY_TYPE_USB3)337 return phy_g12a_usb3_init(phy);338 339 return 0;340}341 342static int phy_g12a_usb3_pcie_exit(struct phy *phy)343{344 struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy);345 346 if (priv->mode == PHY_TYPE_USB3)347 return reset_control_reset(priv->reset);348 349 return 0;350}351 352static struct phy *phy_g12a_usb3_pcie_xlate(struct device *dev,353 const struct of_phandle_args *args)354{355 struct phy_g12a_usb3_pcie_priv *priv = dev_get_drvdata(dev);356 unsigned int mode;357 358 if (args->args_count < 1) {359 dev_err(dev, "invalid number of arguments\n");360 return ERR_PTR(-EINVAL);361 }362 363 mode = args->args[0];364 365 if (mode != PHY_TYPE_USB3 && mode != PHY_TYPE_PCIE) {366 dev_err(dev, "invalid phy mode select argument\n");367 return ERR_PTR(-EINVAL);368 }369 370 priv->mode = mode;371 372 return priv->phy;373}374 375static const struct phy_ops phy_g12a_usb3_pcie_ops = {376 .init = phy_g12a_usb3_pcie_init,377 .exit = phy_g12a_usb3_pcie_exit,378 .power_on = phy_g12a_usb3_pcie_power_on,379 .power_off = phy_g12a_usb3_pcie_power_off,380 .reset = phy_g12a_usb3_pcie_reset,381 .owner = THIS_MODULE,382};383 384static int phy_g12a_usb3_pcie_probe(struct platform_device *pdev)385{386 struct device *dev = &pdev->dev;387 struct device_node *np = dev->of_node;388 struct phy_g12a_usb3_pcie_priv *priv;389 struct phy_provider *phy_provider;390 void __iomem *base;391 392 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);393 if (!priv)394 return -ENOMEM;395 396 base = devm_platform_ioremap_resource(pdev, 0);397 if (IS_ERR(base))398 return PTR_ERR(base);399 400 priv->regmap = devm_regmap_init_mmio(dev, base,401 &phy_g12a_usb3_pcie_regmap_conf);402 if (IS_ERR(priv->regmap))403 return PTR_ERR(priv->regmap);404 405 priv->regmap_cr = devm_regmap_init(dev, NULL, priv,406 &phy_g12a_usb3_pcie_cr_regmap_conf);407 if (IS_ERR(priv->regmap_cr))408 return PTR_ERR(priv->regmap_cr);409 410 priv->clk_ref = devm_clk_get_enabled(dev, "ref_clk");411 if (IS_ERR(priv->clk_ref))412 return PTR_ERR(priv->clk_ref);413 414 priv->reset = devm_reset_control_array_get_exclusive(dev);415 if (IS_ERR(priv->reset))416 return PTR_ERR(priv->reset);417 418 priv->phy = devm_phy_create(dev, np, &phy_g12a_usb3_pcie_ops);419 if (IS_ERR(priv->phy))420 return dev_err_probe(dev, PTR_ERR(priv->phy), "failed to create PHY\n");421 422 phy_set_drvdata(priv->phy, priv);423 dev_set_drvdata(dev, priv);424 425 phy_provider = devm_of_phy_provider_register(dev,426 phy_g12a_usb3_pcie_xlate);427 return PTR_ERR_OR_ZERO(phy_provider);428}429 430static const struct of_device_id phy_g12a_usb3_pcie_of_match[] = {431 { .compatible = "amlogic,g12a-usb3-pcie-phy", },432 { },433};434MODULE_DEVICE_TABLE(of, phy_g12a_usb3_pcie_of_match);435 436static struct platform_driver phy_g12a_usb3_pcie_driver = {437 .probe = phy_g12a_usb3_pcie_probe,438 .driver = {439 .name = "phy-g12a-usb3-pcie",440 .of_match_table = phy_g12a_usb3_pcie_of_match,441 },442};443module_platform_driver(phy_g12a_usb3_pcie_driver);444 445MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");446MODULE_DESCRIPTION("Amlogic G12A USB3 + PCIE Combo PHY driver");447MODULE_LICENSE("GPL v2");448