1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <linux/gpio/consumer.h> 4 #include <linux/mdio.h> 5 #include <linux/module.h> 6 #include <linux/pcs/pcs-mtk-lynxi.h> 7 #include <linux/of_irq.h> 8 #include <linux/of_mdio.h> 9 #include <linux/of_net.h> 10 #include <linux/of_platform.h> 11 #include <linux/regmap.h> 12 #include <linux/reset.h> 13 #include <linux/regulator/consumer.h> 14 #include <net/dsa.h> 15 16 #include "mt7530.h" 17 18 static int 19 mt7530_regmap_write(void *context, unsigned int reg, unsigned int val) 20 { 21 struct mt7530_priv *priv = context; 22 struct mii_bus *bus = priv->bus; 23 u16 page, r, lo, hi; 24 int ret; 25 26 page = (reg >> 6) & 0x3ff; 27 r = (reg >> 2) & 0xf; 28 lo = val & 0xffff; 29 hi = val >> 16; 30 31 ret = bus->write(bus, priv->mdiodev->addr, 0x1f, page); 32 if (ret < 0) 33 return ret; 34 35 ret = bus->write(bus, priv->mdiodev->addr, r, lo); 36 if (ret < 0) 37 return ret; 38 39 ret = bus->write(bus, priv->mdiodev->addr, 0x10, hi); 40 return ret; 41 } 42 43 static int 44 mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val) 45 { 46 struct mt7530_priv *priv = context; 47 struct mii_bus *bus = priv->bus; 48 u16 page, r, lo, hi; 49 int ret; 50 51 /* Callers do not check for errors, keep the value deterministic */ 52 *val = 0; 53 54 page = (reg >> 6) & 0x3ff; 55 r = (reg >> 2) & 0xf; 56 57 ret = bus->write(bus, priv->mdiodev->addr, 0x1f, page); 58 if (ret < 0) 59 return ret; 60 61 ret = bus->read(bus, priv->mdiodev->addr, r); 62 if (ret < 0) 63 return ret; 64 lo = ret; 65 66 ret = bus->read(bus, priv->mdiodev->addr, 0x10); 67 if (ret < 0) 68 return ret; 69 hi = ret; 70 71 *val = (hi << 16) | (lo & 0xffff); 72 73 return 0; 74 } 75 76 static void 77 mt7530_mdio_regmap_lock(void *mdio_lock) 78 { 79 mutex_lock_nested(mdio_lock, MDIO_MUTEX_NESTED); 80 } 81 82 static void 83 mt7530_mdio_regmap_unlock(void *mdio_lock) 84 { 85 mutex_unlock(mdio_lock); 86 } 87 88 static const struct regmap_bus mt7530_regmap_bus = { 89 .reg_write = mt7530_regmap_write, 90 .reg_read = mt7530_regmap_read, 91 }; 92 93 static int 94 mt7531_create_sgmii(struct mt7530_priv *priv) 95 { 96 struct regmap_config *mt7531_pcs_config[2] = {}; 97 struct phylink_pcs *pcs; 98 struct regmap *regmap; 99 int i, ret = 0; 100 101 for (i = priv->p5_sgmii ? 0 : 1; i < 2; i++) { 102 mt7531_pcs_config[i] = devm_kzalloc(priv->dev, 103 sizeof(struct regmap_config), 104 GFP_KERNEL); 105 if (!mt7531_pcs_config[i]) { 106 ret = -ENOMEM; 107 break; 108 } 109 110 mt7531_pcs_config[i]->name = i ? "port6" : "port5"; 111 mt7531_pcs_config[i]->reg_bits = 16; 112 mt7531_pcs_config[i]->val_bits = 32; 113 mt7531_pcs_config[i]->reg_stride = 4; 114 mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i); 115 mt7531_pcs_config[i]->max_register = 0x17c; 116 mt7531_pcs_config[i]->lock = mt7530_mdio_regmap_lock; 117 mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock; 118 mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock; 119 120 regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, priv, 121 mt7531_pcs_config[i]); 122 if (IS_ERR(regmap)) { 123 ret = PTR_ERR(regmap); 124 break; 125 } 126 pcs = mtk_pcs_lynxi_create(priv->dev, NULL, regmap, 127 MT7531_PHYA_CTRL_SIGNAL3); 128 if (!pcs) { 129 ret = -ENXIO; 130 break; 131 } 132 priv->ports[5 + i].sgmii_pcs = pcs; 133 } 134 135 if (ret && i) 136 mtk_pcs_lynxi_destroy(priv->ports[5].sgmii_pcs); 137 138 return ret; 139 } 140 141 static const struct of_device_id mt7530_of_match[] = { 142 { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], }, 143 { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], }, 144 { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], }, 145 { /* sentinel */ } 146 }; 147 MODULE_DEVICE_TABLE(of, mt7530_of_match); 148 149 static const struct regmap_config regmap_config = { 150 .reg_bits = 16, 151 .val_bits = 32, 152 .reg_stride = 4, 153 .max_register = MT7530_CREV, 154 .lock = mt7530_mdio_regmap_lock, 155 .unlock = mt7530_mdio_regmap_unlock, 156 }; 157 158 static int 159 mt7530_probe(struct mdio_device *mdiodev) 160 { 161 struct regmap_config rc = regmap_config; 162 struct mt7530_priv *priv; 163 struct device_node *dn; 164 int ret; 165 166 dn = mdiodev->dev.of_node; 167 168 priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); 169 if (!priv) 170 return -ENOMEM; 171 172 priv->bus = mdiodev->bus; 173 priv->dev = &mdiodev->dev; 174 priv->mdiodev = mdiodev; 175 176 ret = mt7530_probe_common(priv); 177 if (ret) 178 return ret; 179 180 /* Use medatek,mcm property to distinguish hardware type that would 181 * cause a little bit differences on power-on sequence. 182 * Not MCM that indicates switch works as the remote standalone 183 * integrated circuit so the GPIO pin would be used to complete 184 * the reset, otherwise memory-mapped register accessing used 185 * through syscon provides in the case of MCM. 186 */ 187 priv->mcm = of_property_read_bool(dn, "mediatek,mcm"); 188 if (priv->mcm) { 189 dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n"); 190 191 priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm"); 192 if (IS_ERR(priv->rstc)) { 193 dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); 194 return PTR_ERR(priv->rstc); 195 } 196 } else { 197 priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset", 198 GPIOD_OUT_LOW); 199 if (IS_ERR(priv->reset)) { 200 dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); 201 return PTR_ERR(priv->reset); 202 } 203 } 204 205 if (priv->id == ID_MT7530) { 206 priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); 207 if (IS_ERR(priv->core_pwr)) 208 return PTR_ERR(priv->core_pwr); 209 210 priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io"); 211 if (IS_ERR(priv->io_pwr)) 212 return PTR_ERR(priv->io_pwr); 213 } 214 215 rc.lock_arg = &priv->bus->mdio_lock; 216 priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, 217 priv, &rc); 218 if (IS_ERR(priv->regmap)) 219 return PTR_ERR(priv->regmap); 220 221 if (priv->id == ID_MT7531) 222 priv->create_sgmii = mt7531_create_sgmii; 223 224 return dsa_register_switch(priv->ds); 225 } 226 227 static void 228 mt7530_remove(struct mdio_device *mdiodev) 229 { 230 struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); 231 int ret = 0, i; 232 233 if (!priv) 234 return; 235 236 if (priv->id == ID_MT7530) { 237 ret = regulator_disable(priv->core_pwr); 238 if (ret < 0) 239 dev_err(priv->dev, 240 "Failed to disable core power: %d\n", ret); 241 242 ret = regulator_disable(priv->io_pwr); 243 if (ret < 0) 244 dev_err(priv->dev, "Failed to disable io pwr: %d\n", 245 ret); 246 } 247 248 mt7530_remove_common(priv); 249 250 for (i = 0; i < 2; ++i) 251 mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs); 252 } 253 254 static void mt7530_shutdown(struct mdio_device *mdiodev) 255 { 256 struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); 257 258 if (!priv) 259 return; 260 261 dsa_switch_shutdown(priv->ds); 262 263 dev_set_drvdata(&mdiodev->dev, NULL); 264 } 265 266 static struct mdio_driver mt7530_mdio_driver = { 267 .probe = mt7530_probe, 268 .remove = mt7530_remove, 269 .shutdown = mt7530_shutdown, 270 .mdiodrv.driver = { 271 .name = "mt7530-mdio", 272 .of_match_table = mt7530_of_match, 273 }, 274 }; 275 276 mdio_module_driver(mt7530_mdio_driver); 277 278 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); 279 MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch (MDIO)"); 280 MODULE_LICENSE("GPL"); 281