brintos

brintos / linux-shallow public Read only

0
0
Text · 4.7 KiB · 078b1a7 Raw
198 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2004-2013 Synopsys, Inc. (www.synopsys.com)4 *5 * MDIO implementation for ARC EMAC6 */7 8#include <linux/delay.h>9#include <linux/of_mdio.h>10#include <linux/platform_device.h>11#include <linux/gpio/consumer.h>12 13#include "emac.h"14 15/* Number of seconds we wait for "MDIO complete" flag to appear */16#define ARC_MDIO_COMPLETE_POLL_COUNT	117 18/**19 * arc_mdio_complete_wait - Waits until MDIO transaction is completed.20 * @priv:	Pointer to ARC EMAC private data structure.21 *22 * returns:	0 on success, -ETIMEDOUT on a timeout.23 */24static int arc_mdio_complete_wait(struct arc_emac_priv *priv)25{26	unsigned int i;27 28	for (i = 0; i < ARC_MDIO_COMPLETE_POLL_COUNT * 40; i++) {29		unsigned int status = arc_reg_get(priv, R_STATUS);30 31		status &= MDIO_MASK;32 33		if (status) {34			/* Reset "MDIO complete" flag */35			arc_reg_set(priv, R_STATUS, status);36			return 0;37		}38 39		msleep(25);40	}41 42	return -ETIMEDOUT;43}44 45/**46 * arc_mdio_read - MDIO interface read function.47 * @bus:	Pointer to MII bus structure.48 * @phy_addr:	Address of the PHY device.49 * @reg_num:	PHY register to read.50 *51 * returns:	The register contents on success, -ETIMEDOUT on a timeout.52 *53 * Reads the contents of the requested register from the requested PHY54 * address.55 */56static int arc_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num)57{58	struct arc_emac_priv *priv = bus->priv;59	unsigned int value;60	int error;61 62	arc_reg_set(priv, R_MDIO,63		    0x60020000 | (phy_addr << 23) | (reg_num << 18));64 65	error = arc_mdio_complete_wait(priv);66	if (error < 0)67		return error;68 69	value = arc_reg_get(priv, R_MDIO) & 0xffff;70 71	dev_dbg(priv->dev, "arc_mdio_read(phy_addr=%i, reg_num=%x) = %x\n",72		phy_addr, reg_num, value);73 74	return value;75}76 77/**78 * arc_mdio_write - MDIO interface write function.79 * @bus:	Pointer to MII bus structure.80 * @phy_addr:	Address of the PHY device.81 * @reg_num:	PHY register to write to.82 * @value:	Value to be written into the register.83 *84 * returns:	0 on success, -ETIMEDOUT on a timeout.85 *86 * Writes the value to the requested register.87 */88static int arc_mdio_write(struct mii_bus *bus, int phy_addr,89			  int reg_num, u16 value)90{91	struct arc_emac_priv *priv = bus->priv;92 93	dev_dbg(priv->dev,94		"arc_mdio_write(phy_addr=%i, reg_num=%x, value=%x)\n",95		phy_addr, reg_num, value);96 97	arc_reg_set(priv, R_MDIO,98		    0x50020000 | (phy_addr << 23) | (reg_num << 18) | value);99 100	return arc_mdio_complete_wait(priv);101}102 103/**104 * arc_mdio_reset105 * @bus: points to the mii_bus structure106 * Description: reset the MII bus107 */108static int arc_mdio_reset(struct mii_bus *bus)109{110	struct arc_emac_priv *priv = bus->priv;111	struct arc_emac_mdio_bus_data *data = &priv->bus_data;112 113	if (data->reset_gpio) {114		gpiod_set_value_cansleep(data->reset_gpio, 1);115		msleep(data->msec);116		gpiod_set_value_cansleep(data->reset_gpio, 0);117	}118 119	return 0;120}121 122/**123 * arc_mdio_probe - MDIO probe function.124 * @priv:	Pointer to ARC EMAC private data structure.125 *126 * returns:	0 on success, -ENOMEM when mdiobus_alloc127 * (to allocate memory for MII bus structure) fails.128 *129 * Sets up and registers the MDIO interface.130 */131int arc_mdio_probe(struct arc_emac_priv *priv)132{133	struct arc_emac_mdio_bus_data *data = &priv->bus_data;134	struct device_node *np = priv->dev->of_node;135	const char *name = "Synopsys MII Bus";136	struct device_node *mdio_node;137	struct mii_bus *bus;138	int error;139 140	bus = mdiobus_alloc();141	if (!bus)142		return -ENOMEM;143 144	priv->bus = bus;145	bus->priv = priv;146	bus->parent = priv->dev;147	bus->name = name;148	bus->read = &arc_mdio_read;149	bus->write = &arc_mdio_write;150	bus->reset = &arc_mdio_reset;151 152	/* optional reset-related properties */153	data->reset_gpio = devm_gpiod_get_optional(priv->dev, "phy-reset",154						   GPIOD_OUT_LOW);155	if (IS_ERR(data->reset_gpio)) {156		mdiobus_free(bus);157		return dev_err_probe(priv->dev, PTR_ERR(data->reset_gpio),158				     "Failed to request gpio\n");159	}160 161	of_property_read_u32(np, "phy-reset-duration", &data->msec);162	/* A sane reset duration should not be longer than 1s */163	if (data->msec > 1000)164		data->msec = 1;165 166	snprintf(bus->id, MII_BUS_ID_SIZE, "%s", bus->name);167 168	/* Backwards compatibility for EMAC nodes without MDIO subnode. */169	mdio_node = of_get_child_by_name(np, "mdio");170	if (!mdio_node)171		mdio_node = of_node_get(np);172 173	error = of_mdiobus_register(bus, mdio_node);174	of_node_put(mdio_node);175	if (error) {176		mdiobus_free(bus);177		return dev_err_probe(priv->dev, error,178				     "cannot register MDIO bus %s\n", name);179	}180 181	return 0;182}183 184/**185 * arc_mdio_remove - MDIO remove function.186 * @priv:	Pointer to ARC EMAC private data structure.187 *188 * Unregisters the MDIO and frees any associate memory for MII bus.189 */190int arc_mdio_remove(struct arc_emac_priv *priv)191{192	mdiobus_unregister(priv->bus);193	mdiobus_free(priv->bus);194	priv->bus = NULL;195 196	return 0;197}198