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