1 // SPDX-License-Identifier: GPL-2.0+ 2 /* Realtek MDIO interface driver 3 * 4 * ASICs we intend to support with this driver: 5 * 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 14 * 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> 20 */ 21 22 #include <linux/module.h> 23 #include <linux/of_device.h> 24 #include <linux/overflow.h> 25 #include <linux/regmap.h> 26 27 #include "realtek.h" 28 29 /* Read/write via mdiobus */ 30 #define REALTEK_MDIO_CTRL0_REG 31 31 #define REALTEK_MDIO_START_REG 29 32 #define REALTEK_MDIO_CTRL1_REG 21 33 #define REALTEK_MDIO_ADDRESS_REG 23 34 #define REALTEK_MDIO_DATA_WRITE_REG 24 35 #define REALTEK_MDIO_DATA_READ_REG 25 36 37 #define REALTEK_MDIO_START_OP 0xFFFF 38 #define REALTEK_MDIO_ADDR_OP 0x000E 39 #define REALTEK_MDIO_READ_OP 0x0001 40 #define REALTEK_MDIO_WRITE_OP 0x0003 41 42 static int realtek_mdio_write(void *ctx, u32 reg, u32 val) 43 { 44 struct realtek_priv *priv = ctx; 45 struct mii_bus *bus = priv->bus; 46 int ret; 47 48 mutex_lock(&bus->mdio_lock); 49 50 ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP); 51 if (ret) 52 goto out_unlock; 53 54 ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_ADDRESS_REG, reg); 55 if (ret) 56 goto out_unlock; 57 58 ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_DATA_WRITE_REG, val); 59 if (ret) 60 goto out_unlock; 61 62 ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_WRITE_OP); 63 64 out_unlock: 65 mutex_unlock(&bus->mdio_lock); 66 67 return ret; 68 } 69 70 static int realtek_mdio_read(void *ctx, u32 reg, u32 *val) 71 { 72 struct realtek_priv *priv = ctx; 73 struct mii_bus *bus = priv->bus; 74 int ret; 75 76 mutex_lock(&bus->mdio_lock); 77 78 ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP); 79 if (ret) 80 goto out_unlock; 81 82 ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_ADDRESS_REG, reg); 83 if (ret) 84 goto out_unlock; 85 86 ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_READ_OP); 87 if (ret) 88 goto out_unlock; 89 90 ret = bus->read(bus, priv->mdio_addr, REALTEK_MDIO_DATA_READ_REG); 91 if (ret >= 0) { 92 *val = ret; 93 ret = 0; 94 } 95 96 out_unlock: 97 mutex_unlock(&bus->mdio_lock); 98 99 return ret; 100 } 101 102 static void realtek_mdio_lock(void *ctx) 103 { 104 struct realtek_priv *priv = ctx; 105 106 mutex_lock(&priv->map_lock); 107 } 108 109 static void realtek_mdio_unlock(void *ctx) 110 { 111 struct realtek_priv *priv = ctx; 112 113 mutex_unlock(&priv->map_lock); 114 } 115 116 static const struct regmap_config realtek_mdio_regmap_config = { 117 .reg_bits = 10, /* A4..A0 R4..R0 */ 118 .val_bits = 16, 119 .reg_stride = 1, 120 /* PHY regs are at 0x8000 */ 121 .max_register = 0xffff, 122 .reg_format_endian = REGMAP_ENDIAN_BIG, 123 .reg_read = realtek_mdio_read, 124 .reg_write = realtek_mdio_write, 125 .cache_type = REGCACHE_NONE, 126 .lock = realtek_mdio_lock, 127 .unlock = realtek_mdio_unlock, 128 }; 129 130 static const struct regmap_config realtek_mdio_nolock_regmap_config = { 131 .reg_bits = 10, /* A4..A0 R4..R0 */ 132 .val_bits = 16, 133 .reg_stride = 1, 134 /* PHY regs are at 0x8000 */ 135 .max_register = 0xffff, 136 .reg_format_endian = REGMAP_ENDIAN_BIG, 137 .reg_read = realtek_mdio_read, 138 .reg_write = realtek_mdio_write, 139 .cache_type = REGCACHE_NONE, 140 .disable_locking = true, 141 }; 142 143 static int realtek_mdio_probe(struct mdio_device *mdiodev) 144 { 145 struct realtek_priv *priv; 146 struct device *dev = &mdiodev->dev; 147 const struct realtek_variant *var; 148 struct regmap_config rc; 149 struct device_node *np; 150 int ret; 151 152 var = of_device_get_match_data(dev); 153 if (!var) 154 return -EINVAL; 155 156 priv = devm_kzalloc(&mdiodev->dev, 157 size_add(sizeof(*priv), var->chip_data_sz), 158 GFP_KERNEL); 159 if (!priv) 160 return -ENOMEM; 161 162 mutex_init(&priv->map_lock); 163 164 rc = realtek_mdio_regmap_config; 165 rc.lock_arg = priv; 166 priv->map = devm_regmap_init(dev, NULL, priv, &rc); 167 if (IS_ERR(priv->map)) { 168 ret = PTR_ERR(priv->map); 169 dev_err(dev, "regmap init failed: %d\n", ret); 170 return ret; 171 } 172 173 rc = realtek_mdio_nolock_regmap_config; 174 priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc); 175 if (IS_ERR(priv->map_nolock)) { 176 ret = PTR_ERR(priv->map_nolock); 177 dev_err(dev, "regmap init failed: %d\n", ret); 178 return ret; 179 } 180 181 priv->mdio_addr = mdiodev->addr; 182 priv->bus = mdiodev->bus; 183 priv->dev = &mdiodev->dev; 184 priv->chip_data = (void *)priv + sizeof(*priv); 185 186 priv->clk_delay = var->clk_delay; 187 priv->cmd_read = var->cmd_read; 188 priv->cmd_write = var->cmd_write; 189 priv->ops = var->ops; 190 191 priv->write_reg_noack = realtek_mdio_write; 192 193 np = dev->of_node; 194 195 dev_set_drvdata(dev, priv); 196 197 /* TODO: if power is software controlled, set up any regulators here */ 198 priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds"); 199 200 priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); 201 if (IS_ERR(priv->reset)) { 202 dev_err(dev, "failed to get RESET GPIO\n"); 203 return PTR_ERR(priv->reset); 204 } 205 206 if (priv->reset) { 207 gpiod_set_value(priv->reset, 1); 208 dev_dbg(dev, "asserted RESET\n"); 209 msleep(REALTEK_HW_STOP_DELAY); 210 gpiod_set_value(priv->reset, 0); 211 msleep(REALTEK_HW_START_DELAY); 212 dev_dbg(dev, "deasserted RESET\n"); 213 } 214 215 ret = priv->ops->detect(priv); 216 if (ret) { 217 dev_err(dev, "unable to detect switch\n"); 218 return ret; 219 } 220 221 priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL); 222 if (!priv->ds) 223 return -ENOMEM; 224 225 priv->ds->dev = dev; 226 priv->ds->num_ports = priv->num_ports; 227 priv->ds->priv = priv; 228 priv->ds->ops = var->ds_ops_mdio; 229 230 ret = dsa_register_switch(priv->ds); 231 if (ret) { 232 dev_err(priv->dev, "unable to register switch ret = %d\n", ret); 233 return ret; 234 } 235 236 return 0; 237 } 238 239 static void realtek_mdio_remove(struct mdio_device *mdiodev) 240 { 241 struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev); 242 243 if (!priv) 244 return; 245 246 dsa_unregister_switch(priv->ds); 247 248 /* leave the device reset asserted */ 249 if (priv->reset) 250 gpiod_set_value(priv->reset, 1); 251 } 252 253 static void realtek_mdio_shutdown(struct mdio_device *mdiodev) 254 { 255 struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev); 256 257 if (!priv) 258 return; 259 260 dsa_switch_shutdown(priv->ds); 261 262 dev_set_drvdata(&mdiodev->dev, NULL); 263 } 264 265 static const struct of_device_id realtek_mdio_of_match[] = { 266 #if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8366RB) 267 { .compatible = "realtek,rtl8366rb", .data = &rtl8366rb_variant, }, 268 #endif 269 #if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB) 270 { .compatible = "realtek,rtl8365mb", .data = &rtl8365mb_variant, }, 271 #endif 272 { /* sentinel */ }, 273 }; 274 MODULE_DEVICE_TABLE(of, realtek_mdio_of_match); 275 276 static struct mdio_driver realtek_mdio_driver = { 277 .mdiodrv.driver = { 278 .name = "realtek-mdio", 279 .of_match_table = of_match_ptr(realtek_mdio_of_match), 280 }, 281 .probe = realtek_mdio_probe, 282 .remove = realtek_mdio_remove, 283 .shutdown = realtek_mdio_shutdown, 284 }; 285 286 mdio_module_driver(realtek_mdio_driver); 287 288 MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>"); 289 MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface"); 290 MODULE_LICENSE("GPL"); 291