1 // SPDX-License-Identifier: GPL-2.0-only
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>
19 mt7530_regmap_write(void *context, unsigned int reg, unsigned int val)
21 struct mt7530_priv *priv = context;
22 struct mii_bus *bus = priv->bus;
26 page = (reg >> 6) & 0x3ff;
31 ret = bus->write(bus, priv->mdiodev->addr, 0x1f, page);
35 ret = bus->write(bus, priv->mdiodev->addr, r, lo);
39 ret = bus->write(bus, priv->mdiodev->addr, 0x10, hi);
44 mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val)
46 struct mt7530_priv *priv = context;
47 struct mii_bus *bus = priv->bus;
51 page = (reg >> 6) & 0x3ff;
54 ret = bus->write(bus, priv->mdiodev->addr, 0x1f, page);
58 lo = bus->read(bus, priv->mdiodev->addr, r);
59 hi = bus->read(bus, priv->mdiodev->addr, 0x10);
61 *val = (hi << 16) | (lo & 0xffff);
67 mt7530_mdio_regmap_lock(void *mdio_lock)
69 mutex_lock_nested(mdio_lock, MDIO_MUTEX_NESTED);
73 mt7530_mdio_regmap_unlock(void *mdio_lock)
75 mutex_unlock(mdio_lock);
78 static const struct regmap_bus mt7530_regmap_bus = {
79 .reg_write = mt7530_regmap_write,
80 .reg_read = mt7530_regmap_read,
84 mt7531_create_sgmii(struct mt7530_priv *priv)
86 struct regmap_config *mt7531_pcs_config[2] = {};
87 struct phylink_pcs *pcs;
88 struct regmap *regmap;
91 for (i = priv->p5_sgmii ? 0 : 1; i < 2; i++) {
92 mt7531_pcs_config[i] = devm_kzalloc(priv->dev,
93 sizeof(struct regmap_config),
95 if (!mt7531_pcs_config[i]) {
100 mt7531_pcs_config[i]->name = i ? "port6" : "port5";
101 mt7531_pcs_config[i]->reg_bits = 16;
102 mt7531_pcs_config[i]->val_bits = 32;
103 mt7531_pcs_config[i]->reg_stride = 4;
104 mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i);
105 mt7531_pcs_config[i]->max_register = 0x17c;
106 mt7531_pcs_config[i]->lock = mt7530_mdio_regmap_lock;
107 mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock;
108 mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock;
110 regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, priv,
111 mt7531_pcs_config[i]);
112 if (IS_ERR(regmap)) {
113 ret = PTR_ERR(regmap);
116 pcs = mtk_pcs_lynxi_create(priv->dev, regmap,
117 MT7531_PHYA_CTRL_SIGNAL3, 0);
122 priv->ports[5 + i].sgmii_pcs = pcs;
126 mtk_pcs_lynxi_destroy(priv->ports[5].sgmii_pcs);
131 static const struct of_device_id mt7530_of_match[] = {
132 { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], },
133 { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], },
134 { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], },
137 MODULE_DEVICE_TABLE(of, mt7530_of_match);
140 mt7530_probe(struct mdio_device *mdiodev)
142 static struct regmap_config *regmap_config;
143 struct mt7530_priv *priv;
144 struct device_node *dn;
147 dn = mdiodev->dev.of_node;
149 priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
153 priv->bus = mdiodev->bus;
154 priv->dev = &mdiodev->dev;
155 priv->mdiodev = mdiodev;
157 ret = mt7530_probe_common(priv);
161 /* Use medatek,mcm property to distinguish hardware type that would
162 * cause a little bit differences on power-on sequence.
163 * Not MCM that indicates switch works as the remote standalone
164 * integrated circuit so the GPIO pin would be used to complete
165 * the reset, otherwise memory-mapped register accessing used
166 * through syscon provides in the case of MCM.
168 priv->mcm = of_property_read_bool(dn, "mediatek,mcm");
170 dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n");
172 priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm");
173 if (IS_ERR(priv->rstc)) {
174 dev_err(&mdiodev->dev, "Couldn't get our reset line\n");
175 return PTR_ERR(priv->rstc);
178 priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset",
180 if (IS_ERR(priv->reset)) {
181 dev_err(&mdiodev->dev, "Couldn't get our reset line\n");
182 return PTR_ERR(priv->reset);
186 if (priv->id == ID_MT7530) {
187 priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core");
188 if (IS_ERR(priv->core_pwr))
189 return PTR_ERR(priv->core_pwr);
191 priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io");
192 if (IS_ERR(priv->io_pwr))
193 return PTR_ERR(priv->io_pwr);
196 regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config),
201 regmap_config->reg_bits = 16;
202 regmap_config->val_bits = 32;
203 regmap_config->reg_stride = 4;
204 regmap_config->max_register = MT7530_CREV;
205 regmap_config->disable_locking = true;
206 priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, priv,
208 if (IS_ERR(priv->regmap))
209 return PTR_ERR(priv->regmap);
211 if (priv->id == ID_MT7531)
212 priv->create_sgmii = mt7531_create_sgmii;
214 return dsa_register_switch(priv->ds);
218 mt7530_remove(struct mdio_device *mdiodev)
220 struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
226 ret = regulator_disable(priv->core_pwr);
229 "Failed to disable core power: %d\n", ret);
231 ret = regulator_disable(priv->io_pwr);
233 dev_err(priv->dev, "Failed to disable io pwr: %d\n",
236 mt7530_remove_common(priv);
238 for (i = 0; i < 2; ++i)
239 mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs);
242 static void mt7530_shutdown(struct mdio_device *mdiodev)
244 struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
249 dsa_switch_shutdown(priv->ds);
251 dev_set_drvdata(&mdiodev->dev, NULL);
254 static struct mdio_driver mt7530_mdio_driver = {
255 .probe = mt7530_probe,
256 .remove = mt7530_remove,
257 .shutdown = mt7530_shutdown,
259 .name = "mt7530-mdio",
260 .of_match_table = mt7530_of_match,
264 mdio_module_driver(mt7530_mdio_driver);
267 MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch (MDIO)");
268 MODULE_LICENSE("GPL");