brintos

brintos / linux-shallow public Read only

0
0
Text · 8.1 KiB · 3c5018d Raw
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