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 int ret; 135 136 priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL); 137 if (!priv) 138 return -ENOMEM; 139 140 priv->phy = devm_phy_create(dev, np, &phy_axg_pcie_ops); 141 if (IS_ERR(priv->phy)) { 142 ret = PTR_ERR(priv->phy); 143 if (ret != -EPROBE_DEFER) 144 dev_err(dev, "failed to create PHY\n"); 145 return ret; 146 } 147 148 base = devm_platform_ioremap_resource(pdev, 0); 149 if (IS_ERR(base)) 150 return PTR_ERR(base); 151 152 priv->regmap = devm_regmap_init_mmio(dev, base, 153 &phy_axg_pcie_regmap_conf); 154 if (IS_ERR(priv->regmap)) 155 return PTR_ERR(priv->regmap); 156 157 priv->reset = devm_reset_control_array_get_exclusive(dev); 158 if (IS_ERR(priv->reset)) 159 return PTR_ERR(priv->reset); 160 161 priv->analog = devm_phy_get(dev, "analog"); 162 if (IS_ERR(priv->analog)) 163 return PTR_ERR(priv->analog); 164 165 phy_set_drvdata(priv->phy, priv); 166 dev_set_drvdata(dev, priv); 167 pphy = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 168 169 return PTR_ERR_OR_ZERO(pphy); 170 } 171 172 static const struct of_device_id phy_axg_pcie_of_match[] = { 173 { 174 .compatible = "amlogic,axg-pcie-phy", 175 }, 176 { }, 177 }; 178 MODULE_DEVICE_TABLE(of, phy_axg_pcie_of_match); 179 180 static struct platform_driver phy_axg_pcie_driver = { 181 .probe = phy_axg_pcie_probe, 182 .driver = { 183 .name = "phy-axg-pcie", 184 .of_match_table = phy_axg_pcie_of_match, 185 }, 186 }; 187 module_platform_driver(phy_axg_pcie_driver); 188 189 MODULE_AUTHOR("Remi Pommarel <repk@triplefau.lt>"); 190 MODULE_DESCRIPTION("Amlogic AXG PCIE PHY driver"); 191 MODULE_LICENSE("GPL v2"); 192