332 lines · c
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 regmaps12 * @ctx: realtek_priv pointer13 *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 multiple16 * operations that must happen in sequence (which will use17 * realtek_priv.map_nolock instead).18 *19 * Context: Can sleep. Holds priv->map_lock lock.20 * Return: nothing21 */22void rtl83xx_lock(void *ctx)23{24 struct realtek_priv *priv = ctx;25 26 mutex_lock(&priv->map_lock);27}28EXPORT_SYMBOL_NS_GPL(rtl83xx_lock, REALTEK_DSA);29 30/**31 * rtl83xx_unlock() - Unlocks the mutex used by regmaps32 * @ctx: realtek_priv pointer33 *34 * This function unlocks the lock acquired by rtl83xx_lock.35 *36 * Context: Releases priv->map_lock lock.37 * Return: nothing38 */39void rtl83xx_unlock(void *ctx)40{41 struct realtek_priv *priv = ctx;42 43 mutex_unlock(&priv->map_lock);44}45EXPORT_SYMBOL_NS_GPL(rtl83xx_unlock, REALTEK_DSA);46 47static 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 54static 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 driver64 * @ds: DSA switch associated with this user_mii_bus65 *66 * Registers the MDIO bus for built-in Ethernet PHYs, and associates it with67 * the mandatory 'mdio' child OF node of the switch.68 *69 * Context: Can sleep.70 * Return: 0 on success, negative value for failure.71 */72int 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 107err_put_node:108 of_node_put(mdio_np);109 110 return ret;111}112EXPORT_SYMBOL_NS_GPL(rtl83xx_setup_user_mdio, REALTEK_DSA);113 114/**115 * rtl83xx_probe() - probe a Realtek switch116 * @dev: the device being probed117 * @interface_info: specific management interface info.118 *119 * This function initializes realtek_priv and reads data from the device tree120 * 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 by126 * devres.127 */128struct realtek_priv *129rtl83xx_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_ctl = devm_reset_control_get_optional(dev, NULL);188 if (IS_ERR(priv->reset_ctl))189 return dev_err_cast_probe(dev, priv->reset_ctl,190 "failed to get reset control\n");191 192 priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);193 if (IS_ERR(priv->reset)) {194 dev_err(dev, "failed to get RESET GPIO\n");195 return ERR_CAST(priv->reset);196 }197 198 dev_set_drvdata(dev, priv);199 200 if (priv->reset_ctl || priv->reset) {201 rtl83xx_reset_assert(priv);202 dev_dbg(dev, "asserted RESET\n");203 msleep(REALTEK_HW_STOP_DELAY);204 rtl83xx_reset_deassert(priv);205 msleep(REALTEK_HW_START_DELAY);206 dev_dbg(dev, "deasserted RESET\n");207 }208 209 return priv;210}211EXPORT_SYMBOL_NS_GPL(rtl83xx_probe, REALTEK_DSA);212 213/**214 * rtl83xx_register_switch() - detects and register a switch215 * @priv: realtek_priv pointer216 *217 * This function first checks the switch chip ID and register a DSA218 * switch.219 *220 * Context: Can sleep. Takes and releases priv->map_lock.221 * Return: 0 on success, negative value for failure.222 */223int rtl83xx_register_switch(struct realtek_priv *priv)224{225 struct dsa_switch *ds = &priv->ds;226 int ret;227 228 ret = priv->ops->detect(priv);229 if (ret) {230 dev_err_probe(priv->dev, ret, "unable to detect switch\n");231 return ret;232 }233 234 ds->priv = priv;235 ds->dev = priv->dev;236 ds->ops = priv->variant->ds_ops;237 ds->phylink_mac_ops = priv->variant->phylink_mac_ops;238 ds->num_ports = priv->num_ports;239 240 ret = dsa_register_switch(ds);241 if (ret) {242 dev_err_probe(priv->dev, ret, "unable to register switch\n");243 return ret;244 }245 246 return 0;247}248EXPORT_SYMBOL_NS_GPL(rtl83xx_register_switch, REALTEK_DSA);249 250/**251 * rtl83xx_unregister_switch() - unregister a switch252 * @priv: realtek_priv pointer253 *254 * This function unregister a DSA switch.255 *256 * Context: Can sleep.257 * Return: Nothing.258 */259void rtl83xx_unregister_switch(struct realtek_priv *priv)260{261 struct dsa_switch *ds = &priv->ds;262 263 dsa_unregister_switch(ds);264}265EXPORT_SYMBOL_NS_GPL(rtl83xx_unregister_switch, REALTEK_DSA);266 267/**268 * rtl83xx_shutdown() - shutdown a switch269 * @priv: realtek_priv pointer270 *271 * This function shuts down the DSA switch and cleans the platform driver data,272 * to prevent realtek_{smi,mdio}_remove() from running afterwards, which is273 * possible if the parent bus implements its own .shutdown() as .remove().274 *275 * Context: Can sleep.276 * Return: Nothing.277 */278void rtl83xx_shutdown(struct realtek_priv *priv)279{280 struct dsa_switch *ds = &priv->ds;281 282 dsa_switch_shutdown(ds);283 284 dev_set_drvdata(priv->dev, NULL);285}286EXPORT_SYMBOL_NS_GPL(rtl83xx_shutdown, REALTEK_DSA);287 288/**289 * rtl83xx_remove() - Cleanup a realtek switch driver290 * @priv: realtek_priv pointer291 *292 * Placehold for common cleanup procedures.293 *294 * Context: Any295 * Return: nothing296 */297void rtl83xx_remove(struct realtek_priv *priv)298{299}300EXPORT_SYMBOL_NS_GPL(rtl83xx_remove, REALTEK_DSA);301 302void rtl83xx_reset_assert(struct realtek_priv *priv)303{304 int ret;305 306 ret = reset_control_assert(priv->reset_ctl);307 if (ret)308 dev_warn(priv->dev,309 "Failed to assert the switch reset control: %pe\n",310 ERR_PTR(ret));311 312 gpiod_set_value(priv->reset, true);313}314 315void rtl83xx_reset_deassert(struct realtek_priv *priv)316{317 int ret;318 319 ret = reset_control_deassert(priv->reset_ctl);320 if (ret)321 dev_warn(priv->dev,322 "Failed to deassert the switch reset control: %pe\n",323 ERR_PTR(ret));324 325 gpiod_set_value(priv->reset, false);326}327 328MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");329MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");330MODULE_DESCRIPTION("Realtek DSA switches common module");331MODULE_LICENSE("GPL");332