1 // SPDX-License-Identifier: GPL-2.0+
2 /* Realtek MDIO interface driver
4 * ASICs we intend to support with this driver:
6 * RTL8366 - The original version, apparently
7 * RTL8369 - Similar enough to have the same datsheet as RTL8366
8 * RTL8366RB - Probably reads out "RTL8366 revision B", has a quite
9 * different register layout from the other two
10 * RTL8366S - Is this "RTL8366 super"?
11 * RTL8367 - Has an OpenWRT driver as well
12 * RTL8368S - Seems to be an alternative name for RTL8366RB
13 * RTL8370 - Also uses SMI
15 * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
16 * Copyright (C) 2010 Antti Seppälä <a.seppala@gmail.com>
17 * Copyright (C) 2010 Roman Yeryomin <roman@advem.lv>
18 * Copyright (C) 2011 Colin Leitner <colin.leitner@googlemail.com>
19 * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
22 #include <linux/module.h>
23 #include <linux/of_device.h>
24 #include <linux/regmap.h>
28 /* Read/write via mdiobus */
29 #define REALTEK_MDIO_CTRL0_REG 31
30 #define REALTEK_MDIO_START_REG 29
31 #define REALTEK_MDIO_CTRL1_REG 21
32 #define REALTEK_MDIO_ADDRESS_REG 23
33 #define REALTEK_MDIO_DATA_WRITE_REG 24
34 #define REALTEK_MDIO_DATA_READ_REG 25
36 #define REALTEK_MDIO_START_OP 0xFFFF
37 #define REALTEK_MDIO_ADDR_OP 0x000E
38 #define REALTEK_MDIO_READ_OP 0x0001
39 #define REALTEK_MDIO_WRITE_OP 0x0003
41 static int realtek_mdio_write(void *ctx, u32 reg, u32 val)
43 struct realtek_priv *priv = ctx;
44 struct mii_bus *bus = priv->bus;
47 mutex_lock(&bus->mdio_lock);
49 ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP);
53 ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_ADDRESS_REG, reg);
57 ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_DATA_WRITE_REG, val);
61 ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_WRITE_OP);
64 mutex_unlock(&bus->mdio_lock);
69 static int realtek_mdio_read(void *ctx, u32 reg, u32 *val)
71 struct realtek_priv *priv = ctx;
72 struct mii_bus *bus = priv->bus;
75 mutex_lock(&bus->mdio_lock);
77 ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP);
81 ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_ADDRESS_REG, reg);
85 ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_READ_OP);
89 ret = bus->read(bus, priv->mdio_addr, REALTEK_MDIO_DATA_READ_REG);
96 mutex_unlock(&bus->mdio_lock);
101 static void realtek_mdio_lock(void *ctx)
103 struct realtek_priv *priv = ctx;
105 mutex_lock(&priv->map_lock);
108 static void realtek_mdio_unlock(void *ctx)
110 struct realtek_priv *priv = ctx;
112 mutex_unlock(&priv->map_lock);
115 static const struct regmap_config realtek_mdio_regmap_config = {
116 .reg_bits = 10, /* A4..A0 R4..R0 */
119 /* PHY regs are at 0x8000 */
120 .max_register = 0xffff,
121 .reg_format_endian = REGMAP_ENDIAN_BIG,
122 .reg_read = realtek_mdio_read,
123 .reg_write = realtek_mdio_write,
124 .cache_type = REGCACHE_NONE,
125 .lock = realtek_mdio_lock,
126 .unlock = realtek_mdio_unlock,
129 static const struct regmap_config realtek_mdio_nolock_regmap_config = {
130 .reg_bits = 10, /* A4..A0 R4..R0 */
133 /* PHY regs are at 0x8000 */
134 .max_register = 0xffff,
135 .reg_format_endian = REGMAP_ENDIAN_BIG,
136 .reg_read = realtek_mdio_read,
137 .reg_write = realtek_mdio_write,
138 .cache_type = REGCACHE_NONE,
139 .disable_locking = true,
142 static int realtek_mdio_probe(struct mdio_device *mdiodev)
144 struct realtek_priv *priv;
145 struct device *dev = &mdiodev->dev;
146 const struct realtek_variant *var;
147 struct regmap_config rc;
148 struct device_node *np;
151 var = of_device_get_match_data(dev);
155 priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
159 mutex_init(&priv->map_lock);
161 rc = realtek_mdio_regmap_config;
163 priv->map = devm_regmap_init(dev, NULL, priv, &rc);
164 if (IS_ERR(priv->map)) {
165 ret = PTR_ERR(priv->map);
166 dev_err(dev, "regmap init failed: %d\n", ret);
170 rc = realtek_mdio_nolock_regmap_config;
171 priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
172 if (IS_ERR(priv->map_nolock)) {
173 ret = PTR_ERR(priv->map_nolock);
174 dev_err(dev, "regmap init failed: %d\n", ret);
178 priv->mdio_addr = mdiodev->addr;
179 priv->bus = mdiodev->bus;
180 priv->dev = &mdiodev->dev;
181 priv->chip_data = (void *)priv + sizeof(*priv);
183 priv->clk_delay = var->clk_delay;
184 priv->cmd_read = var->cmd_read;
185 priv->cmd_write = var->cmd_write;
186 priv->ops = var->ops;
188 priv->write_reg_noack = realtek_mdio_write;
192 dev_set_drvdata(dev, priv);
194 /* TODO: if power is software controlled, set up any regulators here */
195 priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
197 priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
198 if (IS_ERR(priv->reset)) {
199 dev_err(dev, "failed to get RESET GPIO\n");
200 return PTR_ERR(priv->reset);
204 gpiod_set_value(priv->reset, 1);
205 dev_dbg(dev, "asserted RESET\n");
206 msleep(REALTEK_HW_STOP_DELAY);
207 gpiod_set_value(priv->reset, 0);
208 msleep(REALTEK_HW_START_DELAY);
209 dev_dbg(dev, "deasserted RESET\n");
212 ret = priv->ops->detect(priv);
214 dev_err(dev, "unable to detect switch\n");
218 priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL);
223 priv->ds->num_ports = priv->num_ports;
224 priv->ds->priv = priv;
225 priv->ds->ops = var->ds_ops_mdio;
227 ret = dsa_register_switch(priv->ds);
229 dev_err(priv->dev, "unable to register switch ret = %d\n", ret);
236 static void realtek_mdio_remove(struct mdio_device *mdiodev)
238 struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
243 dsa_unregister_switch(priv->ds);
245 /* leave the device reset asserted */
247 gpiod_set_value(priv->reset, 1);
249 dev_set_drvdata(&mdiodev->dev, NULL);
252 static void realtek_mdio_shutdown(struct mdio_device *mdiodev)
254 struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
259 dsa_switch_shutdown(priv->ds);
261 dev_set_drvdata(&mdiodev->dev, NULL);
264 static const struct of_device_id realtek_mdio_of_match[] = {
265 #if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8366RB)
266 { .compatible = "realtek,rtl8366rb", .data = &rtl8366rb_variant, },
268 #if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB)
269 { .compatible = "realtek,rtl8365mb", .data = &rtl8365mb_variant, },
273 MODULE_DEVICE_TABLE(of, realtek_mdio_of_match);
275 static struct mdio_driver realtek_mdio_driver = {
277 .name = "realtek-mdio",
278 .of_match_table = of_match_ptr(realtek_mdio_of_match),
280 .probe = realtek_mdio_probe,
281 .remove = realtek_mdio_remove,
282 .shutdown = realtek_mdio_shutdown,
285 mdio_module_driver(realtek_mdio_driver);
287 MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
288 MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface");
289 MODULE_LICENSE("GPL");