1 // SPDX-License-Identifier: GPL-2.0+ 2 3 #include <linux/module.h> 4 #include <linux/regmap.h> 5 #include <linux/of_mdio.h> 6 7 #include "realtek.h" 8 #include "rtl83xx.h" 9 10 /** 11 * rtl83xx_lock() - Locks the mutex used by regmaps 12 * @ctx: realtek_priv pointer 13 * 14 * This function is passed to regmap to be used as the lock function. 15 * It is also used externally to block regmap before executing multiple 16 * operations that must happen in sequence (which will use 17 * realtek_priv.map_nolock instead). 18 * 19 * Context: Can sleep. Holds priv->map_lock lock. 20 * Return: nothing 21 */ 22 void rtl83xx_lock(void *ctx) 23 { 24 struct realtek_priv *priv = ctx; 25 26 mutex_lock(&priv->map_lock); 27 } 28 EXPORT_SYMBOL_NS_GPL(rtl83xx_lock, REALTEK_DSA); 29 30 /** 31 * rtl83xx_unlock() - Unlocks the mutex used by regmaps 32 * @ctx: realtek_priv pointer 33 * 34 * This function unlocks the lock acquired by rtl83xx_lock. 35 * 36 * Context: Releases priv->map_lock lock. 37 * Return: nothing 38 */ 39 void rtl83xx_unlock(void *ctx) 40 { 41 struct realtek_priv *priv = ctx; 42 43 mutex_unlock(&priv->map_lock); 44 } 45 EXPORT_SYMBOL_NS_GPL(rtl83xx_unlock, REALTEK_DSA); 46 47 static int rtl83xx_user_mdio_read(struct mii_bus *bus, int addr, int regnum) 48 { 49 struct realtek_priv *priv = bus->priv; 50 51 return priv->ops->phy_read(priv, addr, regnum); 52 } 53 54 static int rtl83xx_user_mdio_write(struct mii_bus *bus, int addr, int regnum, 55 u16 val) 56 { 57 struct realtek_priv *priv = bus->priv; 58 59 return priv->ops->phy_write(priv, addr, regnum, val); 60 } 61 62 /** 63 * rtl83xx_setup_user_mdio() - register the user mii bus driver 64 * @ds: DSA switch associated with this user_mii_bus 65 * 66 * Registers the MDIO bus for built-in Ethernet PHYs, and associates it with 67 * the mandatory 'mdio' child OF node of the switch. 68 * 69 * Context: Can sleep. 70 * Return: 0 on success, negative value for failure. 71 */ 72 int rtl83xx_setup_user_mdio(struct dsa_switch *ds) 73 { 74 struct realtek_priv *priv = ds->priv; 75 struct device_node *mdio_np; 76 struct mii_bus *bus; 77 int ret = 0; 78 79 mdio_np = of_get_child_by_name(priv->dev->of_node, "mdio"); 80 if (!mdio_np) { 81 dev_err(priv->dev, "no MDIO bus node\n"); 82 return -ENODEV; 83 } 84 85 bus = devm_mdiobus_alloc(priv->dev); 86 if (!bus) { 87 ret = -ENOMEM; 88 goto err_put_node; 89 } 90 91 bus->priv = priv; 92 bus->name = "Realtek user MII"; 93 bus->read = rtl83xx_user_mdio_read; 94 bus->write = rtl83xx_user_mdio_write; 95 snprintf(bus->id, MII_BUS_ID_SIZE, "%s:user_mii", dev_name(priv->dev)); 96 bus->parent = priv->dev; 97 98 ret = devm_of_mdiobus_register(priv->dev, bus, mdio_np); 99 if (ret) { 100 dev_err(priv->dev, "unable to register MDIO bus %s\n", 101 bus->id); 102 goto err_put_node; 103 } 104 105 priv->user_mii_bus = bus; 106 107 err_put_node: 108 of_node_put(mdio_np); 109 110 return ret; 111 } 112 EXPORT_SYMBOL_NS_GPL(rtl83xx_setup_user_mdio, REALTEK_DSA); 113 114 /** 115 * rtl83xx_probe() - probe a Realtek switch 116 * @dev: the device being probed 117 * @interface_info: specific management interface info. 118 * 119 * This function initializes realtek_priv and reads data from the device tree 120 * node. The switch is hard resetted if a method is provided. 121 * 122 * Context: Can sleep. 123 * Return: Pointer to the realtek_priv or ERR_PTR() in case of failure. 124 * 125 * The realtek_priv pointer does not need to be freed as it is controlled by 126 * devres. 127 */ 128 struct realtek_priv * 129 rtl83xx_probe(struct device *dev, 130 const struct realtek_interface_info *interface_info) 131 { 132 const struct realtek_variant *var; 133 struct realtek_priv *priv; 134 struct regmap_config rc = { 135 .reg_bits = 10, /* A4..A0 R4..R0 */ 136 .val_bits = 16, 137 .reg_stride = 1, 138 .max_register = 0xffff, 139 .reg_format_endian = REGMAP_ENDIAN_BIG, 140 .reg_read = interface_info->reg_read, 141 .reg_write = interface_info->reg_write, 142 .cache_type = REGCACHE_NONE, 143 .lock = rtl83xx_lock, 144 .unlock = rtl83xx_unlock, 145 }; 146 int ret; 147 148 var = of_device_get_match_data(dev); 149 if (!var) 150 return ERR_PTR(-EINVAL); 151 152 priv = devm_kzalloc(dev, size_add(sizeof(*priv), var->chip_data_sz), 153 GFP_KERNEL); 154 if (!priv) 155 return ERR_PTR(-ENOMEM); 156 157 mutex_init(&priv->map_lock); 158 159 rc.lock_arg = priv; 160 priv->map = devm_regmap_init(dev, NULL, priv, &rc); 161 if (IS_ERR(priv->map)) { 162 ret = PTR_ERR(priv->map); 163 dev_err(dev, "regmap init failed: %d\n", ret); 164 return ERR_PTR(ret); 165 } 166 167 rc.disable_locking = true; 168 priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc); 169 if (IS_ERR(priv->map_nolock)) { 170 ret = PTR_ERR(priv->map_nolock); 171 dev_err(dev, "regmap init failed: %d\n", ret); 172 return ERR_PTR(ret); 173 } 174 175 /* Link forward and backward */ 176 priv->dev = dev; 177 priv->variant = var; 178 priv->ops = var->ops; 179 priv->chip_data = (void *)priv + sizeof(*priv); 180 181 spin_lock_init(&priv->lock); 182 183 priv->leds_disabled = of_property_read_bool(dev->of_node, 184 "realtek,disable-leds"); 185 186 /* TODO: if power is software controlled, set up any regulators here */ 187 priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); 188 if (IS_ERR(priv->reset)) { 189 dev_err(dev, "failed to get RESET GPIO\n"); 190 return ERR_CAST(priv->reset); 191 } 192 193 dev_set_drvdata(dev, priv); 194 195 if (priv->reset) { 196 gpiod_set_value(priv->reset, 1); 197 dev_dbg(dev, "asserted RESET\n"); 198 msleep(REALTEK_HW_STOP_DELAY); 199 gpiod_set_value(priv->reset, 0); 200 msleep(REALTEK_HW_START_DELAY); 201 dev_dbg(dev, "deasserted RESET\n"); 202 } 203 204 return priv; 205 } 206 EXPORT_SYMBOL_NS_GPL(rtl83xx_probe, REALTEK_DSA); 207 208 /** 209 * rtl83xx_register_switch() - detects and register a switch 210 * @priv: realtek_priv pointer 211 * 212 * This function first checks the switch chip ID and register a DSA 213 * switch. 214 * 215 * Context: Can sleep. Takes and releases priv->map_lock. 216 * Return: 0 on success, negative value for failure. 217 */ 218 int rtl83xx_register_switch(struct realtek_priv *priv) 219 { 220 struct dsa_switch *ds = &priv->ds; 221 int ret; 222 223 ret = priv->ops->detect(priv); 224 if (ret) { 225 dev_err_probe(priv->dev, ret, "unable to detect switch\n"); 226 return ret; 227 } 228 229 ds->priv = priv; 230 ds->dev = priv->dev; 231 ds->ops = priv->variant->ds_ops; 232 ds->num_ports = priv->num_ports; 233 234 ret = dsa_register_switch(ds); 235 if (ret) { 236 dev_err_probe(priv->dev, ret, "unable to register switch\n"); 237 return ret; 238 } 239 240 return 0; 241 } 242 EXPORT_SYMBOL_NS_GPL(rtl83xx_register_switch, REALTEK_DSA); 243 244 /** 245 * rtl83xx_unregister_switch() - unregister a switch 246 * @priv: realtek_priv pointer 247 * 248 * This function unregister a DSA switch. 249 * 250 * Context: Can sleep. 251 * Return: Nothing. 252 */ 253 void rtl83xx_unregister_switch(struct realtek_priv *priv) 254 { 255 struct dsa_switch *ds = &priv->ds; 256 257 dsa_unregister_switch(ds); 258 } 259 EXPORT_SYMBOL_NS_GPL(rtl83xx_unregister_switch, REALTEK_DSA); 260 261 /** 262 * rtl83xx_shutdown() - shutdown a switch 263 * @priv: realtek_priv pointer 264 * 265 * This function shuts down the DSA switch and cleans the platform driver data, 266 * to prevent realtek_{smi,mdio}_remove() from running afterwards, which is 267 * possible if the parent bus implements its own .shutdown() as .remove(). 268 * 269 * Context: Can sleep. 270 * Return: Nothing. 271 */ 272 void rtl83xx_shutdown(struct realtek_priv *priv) 273 { 274 struct dsa_switch *ds = &priv->ds; 275 276 dsa_switch_shutdown(ds); 277 278 dev_set_drvdata(priv->dev, NULL); 279 } 280 EXPORT_SYMBOL_NS_GPL(rtl83xx_shutdown, REALTEK_DSA); 281 282 /** 283 * rtl83xx_remove() - Cleanup a realtek switch driver 284 * @priv: realtek_priv pointer 285 * 286 * If a method is provided, this function asserts the hard reset of the switch 287 * in order to avoid leaking traffic when the driver is gone. 288 * 289 * Context: Might sleep if priv->gdev->chip->can_sleep. 290 * Return: nothing 291 */ 292 void rtl83xx_remove(struct realtek_priv *priv) 293 { 294 /* leave the device reset asserted */ 295 if (priv->reset) 296 gpiod_set_value(priv->reset, 1); 297 } 298 EXPORT_SYMBOL_NS_GPL(rtl83xx_remove, REALTEK_DSA); 299 300 MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>"); 301 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); 302 MODULE_DESCRIPTION("Realtek DSA switches common module"); 303 MODULE_LICENSE("GPL"); 304