1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Amlogic AXG PCIE PHY driver 4 * 5 * Copyright (C) 2020 Remi Pommarel <repk@triplefau.lt> 6 */ 7 #include <linux/mod_devicetable.h> 8 #include <linux/module.h> 9 #include <linux/phy/phy.h> 10 #include <linux/regmap.h> 11 #include <linux/reset.h> 12 #include <linux/platform_device.h> 13 #include <linux/bitfield.h> 14 #include <dt-bindings/phy/phy.h> 15 16 #define MESON_PCIE_REG0 0x00 17 #define MESON_PCIE_COMMON_CLK BIT(4) 18 #define MESON_PCIE_PORT_SEL GENMASK(3, 2) 19 #define MESON_PCIE_CLK BIT(1) 20 #define MESON_PCIE_POWERDOWN BIT(0) 21 22 #define MESON_PCIE_TWO_X1 FIELD_PREP(MESON_PCIE_PORT_SEL, 0x3) 23 #define MESON_PCIE_COMMON_REF_CLK FIELD_PREP(MESON_PCIE_COMMON_CLK, 0x1) 24 #define MESON_PCIE_PHY_INIT (MESON_PCIE_TWO_X1 | \ 25 MESON_PCIE_COMMON_REF_CLK) 26 #define MESON_PCIE_RESET_DELAY 500 27 28 struct phy_axg_pcie_priv { 29 struct phy *phy; 30 struct phy *analog; 31 struct regmap *regmap; 32 struct reset_control *reset; 33 }; 34 35 static const struct regmap_config phy_axg_pcie_regmap_conf = { 36 .reg_bits = 8, 37 .val_bits = 32, 38 .reg_stride = 4, 39 .max_register = MESON_PCIE_REG0, 40 }; 41 42 static int phy_axg_pcie_power_on(struct phy *phy) 43 { 44 struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy); 45 int ret; 46 47 ret = phy_power_on(priv->analog); 48 if (ret != 0) 49 return ret; 50 51 regmap_update_bits(priv->regmap, MESON_PCIE_REG0, 52 MESON_PCIE_POWERDOWN, 0); 53 return 0; 54 } 55 56 static int phy_axg_pcie_power_off(struct phy *phy) 57 { 58 struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy); 59 int ret; 60 61 ret = phy_power_off(priv->analog); 62 if (ret != 0) 63 return ret; 64 65 regmap_update_bits(priv->regmap, MESON_PCIE_REG0, 66 MESON_PCIE_POWERDOWN, 1); 67 return 0; 68 } 69 70 static int phy_axg_pcie_init(struct phy *phy) 71 { 72 struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy); 73 int ret; 74 75 ret = phy_init(priv->analog); 76 if (ret != 0) 77 return ret; 78 79 regmap_write(priv->regmap, MESON_PCIE_REG0, MESON_PCIE_PHY_INIT); 80 return reset_control_reset(priv->reset); 81 } 82 83 static int phy_axg_pcie_exit(struct phy *phy) 84 { 85 struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy); 86 int ret; 87 88 ret = phy_exit(priv->analog); 89 if (ret != 0) 90 return ret; 91 92 return reset_control_reset(priv->reset); 93 } 94 95 static int phy_axg_pcie_reset(struct phy *phy) 96 { 97 struct phy_axg_pcie_priv *priv = phy_get_drvdata(phy); 98 int ret = 0; 99 100 ret = phy_reset(priv->analog); 101 if (ret != 0) 102 goto out; 103 104 ret = reset_control_assert(priv->reset); 105 if (ret != 0) 106 goto out; 107 udelay(MESON_PCIE_RESET_DELAY); 108 109 ret = reset_control_deassert(priv->reset); 110 if (ret != 0) 111 goto out; 112 udelay(MESON_PCIE_RESET_DELAY); 113 114 out: 115 return ret; 116 } 117 118 static const struct phy_ops phy_axg_pcie_ops = { 119 .init = phy_axg_pcie_init, 120 .exit = phy_axg_pcie_exit, 121 .power_on = phy_axg_pcie_power_on, 122 .power_off = phy_axg_pcie_power_off, 123 .reset = phy_axg_pcie_reset, 124 .owner = THIS_MODULE, 125 }; 126 127 static int phy_axg_pcie_probe(struct platform_device *pdev) 128 { 129 struct phy_provider *pphy; 130 struct device *dev = &pdev->dev; 131 struct phy_axg_pcie_priv *priv; 132 struct device_node *np = dev->of_node; 133 void __iomem *base; 134 135 priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL); 136 if (!priv) 137 return -ENOMEM; 138 139 base = devm_platform_ioremap_resource(pdev, 0); 140 if (IS_ERR(base)) 141 return PTR_ERR(base); 142 143 priv->regmap = devm_regmap_init_mmio(dev, base, 144 &phy_axg_pcie_regmap_conf); 145 if (IS_ERR(priv->regmap)) 146 return PTR_ERR(priv->regmap); 147 148 priv->reset = devm_reset_control_array_get_exclusive(dev); 149 if (IS_ERR(priv->reset)) 150 return PTR_ERR(priv->reset); 151 152 priv->analog = devm_phy_get(dev, "analog"); 153 if (IS_ERR(priv->analog)) 154 return PTR_ERR(priv->analog); 155 156 priv->phy = devm_phy_create(dev, np, &phy_axg_pcie_ops); 157 if (IS_ERR(priv->phy)) 158 return dev_err_probe(dev, PTR_ERR(priv->phy), 159 "failed to create PHY\n"); 160 161 phy_set_drvdata(priv->phy, priv); 162 dev_set_drvdata(dev, priv); 163 pphy = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 164 165 return PTR_ERR_OR_ZERO(pphy); 166 } 167 168 static const struct of_device_id phy_axg_pcie_of_match[] = { 169 { 170 .compatible = "amlogic,axg-pcie-phy", 171 }, 172 { }, 173 }; 174 MODULE_DEVICE_TABLE(of, phy_axg_pcie_of_match); 175 176 static struct platform_driver phy_axg_pcie_driver = { 177 .probe = phy_axg_pcie_probe, 178 .driver = { 179 .name = "phy-axg-pcie", 180 .of_match_table = phy_axg_pcie_of_match, 181 }, 182 }; 183 module_platform_driver(phy_axg_pcie_driver); 184 185 MODULE_AUTHOR("Remi Pommarel <repk@triplefau.lt>"); 186 MODULE_DESCRIPTION("Amlogic AXG PCIE PHY driver"); 187 MODULE_LICENSE("GPL v2"); 188