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