aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c
diff options
context:
space:
mode:
authorChuanhong Guo <gch981213@gmail.com>2018-07-17 17:09:13 +0800
committerJohn Crispin <john@phrozen.org>2018-07-30 10:43:33 +0200
commit83d2dbc59924c90dd865de113a55d60826ac0c04 (patch)
tree2fb028041fcffa2e1de5342fa6f9a98462da5e48 /target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c
parent24cbe27bb7ff83b9bb3a2640904bced1a2d14a8d (diff)
downloadupstream-83d2dbc59924c90dd865de113a55d60826ac0c04.tar.gz
upstream-83d2dbc59924c90dd865de113a55d60826ac0c04.tar.bz2
upstream-83d2dbc59924c90dd865de113a55d60826ac0c04.zip
ath79: ag71xx: Split mdio driver into an independent platform device.
We need to have mdio1 belonging to gmac1 initialized before gmac0. Split it into a separated mdio device to get both mdios ready before probing gmac. Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
Diffstat (limited to 'target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c')
-rw-r--r--target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c140
1 files changed, 70 insertions, 70 deletions
diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c
index 8c1572b181..baaa33e10b 100644
--- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c
+++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c
@@ -20,7 +20,7 @@
static int bus_count;
-static int ag71xx_mdio_wait_busy(struct ag71xx *ag)
+static int ag71xx_mdio_wait_busy(struct ag71xx_mdio *am)
{
int i;
@@ -29,57 +29,57 @@ static int ag71xx_mdio_wait_busy(struct ag71xx *ag)
udelay(AG71XX_MDIO_DELAY);
- regmap_read(ag->mii_regmap, AG71XX_REG_MII_IND, &busy);
+ regmap_read(am->mii_regmap, AG71XX_REG_MII_IND, &busy);
if (!busy)
return 0;
udelay(AG71XX_MDIO_DELAY);
}
- pr_err("%s: MDIO operation timed out\n", ag->mii_bus->name);
+ pr_err("%s: MDIO operation timed out\n", am->mii_bus->name);
return -ETIMEDOUT;
}
-int ag71xx_mdio_mii_read(struct mii_bus *bus, int addr, int reg)
+static int ag71xx_mdio_mii_read(struct mii_bus *bus, int addr, int reg)
{
- struct ag71xx *ag = bus->priv;
+ struct ag71xx_mdio *am = bus->priv;
int err;
int ret;
- err = ag71xx_mdio_wait_busy(ag);
+ err = ag71xx_mdio_wait_busy(am);
if (err)
return 0xffff;
- regmap_write(ag->mii_regmap, AG71XX_REG_MII_CMD, MII_CMD_WRITE);
- regmap_write(ag->mii_regmap, AG71XX_REG_MII_ADDR,
+ regmap_write(am->mii_regmap, AG71XX_REG_MII_CMD, MII_CMD_WRITE);
+ regmap_write(am->mii_regmap, AG71XX_REG_MII_ADDR,
((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff));
- regmap_write(ag->mii_regmap, AG71XX_REG_MII_CMD, MII_CMD_READ);
+ regmap_write(am->mii_regmap, AG71XX_REG_MII_CMD, MII_CMD_READ);
- err = ag71xx_mdio_wait_busy(ag);
+ err = ag71xx_mdio_wait_busy(am);
if (err)
return 0xffff;
- regmap_read(ag->mii_regmap, AG71XX_REG_MII_STATUS, &ret);
+ regmap_read(am->mii_regmap, AG71XX_REG_MII_STATUS, &ret);
ret &= 0xffff;
- regmap_write(ag->mii_regmap, AG71XX_REG_MII_CMD, MII_CMD_WRITE);
+ regmap_write(am->mii_regmap, AG71XX_REG_MII_CMD, MII_CMD_WRITE);
DBG("mii_read: addr=%04x, reg=%04x, value=%04x\n", addr, reg, ret);
return ret;
}
-int ag71xx_mdio_mii_write(struct mii_bus *bus, int addr, int reg, u16 val)
+static int ag71xx_mdio_mii_write(struct mii_bus *bus, int addr, int reg, u16 val)
{
- struct ag71xx *ag = bus->priv;
+ struct ag71xx_mdio *am = bus->priv;
DBG("mii_write: addr=%04x, reg=%04x, value=%04x\n", addr, reg, val);
- regmap_write(ag->mii_regmap, AG71XX_REG_MII_ADDR,
+ regmap_write(am->mii_regmap, AG71XX_REG_MII_ADDR,
((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff));
- regmap_write(ag->mii_regmap, AG71XX_REG_MII_CTRL, val);
+ regmap_write(am->mii_regmap, AG71XX_REG_MII_CTRL, val);
- ag71xx_mdio_wait_busy(ag);
+ ag71xx_mdio_wait_busy(am);
return 0;
}
@@ -97,23 +97,22 @@ static int ar934x_mdio_clock_div(unsigned int rate)
static int ag71xx_mdio_reset(struct mii_bus *bus)
{
struct device_node *np = bus->dev.of_node;
- struct ag71xx *ag = bus->priv;
- struct device_node *np_ag = ag->pdev->dev.of_node;
+ struct ag71xx_mdio *am = bus->priv;
bool builtin_switch;
u32 t;
builtin_switch = of_property_read_bool(np, "builtin-switch");
- if (of_device_is_compatible(np_ag, "qca,ar7240-eth"))
+ if (of_device_is_compatible(np, "qca,ar7240-mdio"))
t = MII_CFG_CLK_DIV_6;
- else if (of_device_is_compatible(np_ag, "qca,ar9340-eth"))
+ else if (of_device_is_compatible(np, "qca,ar9340-mdio"))
t = MII_CFG_CLK_DIV_58;
else if (builtin_switch)
t = MII_CFG_CLK_DIV_10;
else
t = MII_CFG_CLK_DIV_28;
- if (builtin_switch && of_device_is_compatible(np_ag, "qca,ar9340-eth")) {
+ if (builtin_switch && of_device_is_compatible(np, "qca,ar9340-mdio")) {
struct clk *ref_clk = of_clk_get(np, 0);
int clock_rate;
@@ -126,56 +125,45 @@ static int ag71xx_mdio_reset(struct mii_bus *bus)
clk_put(ref_clk);
}
- regmap_write(ag->mii_regmap, AG71XX_REG_MII_CFG, t | MII_CFG_RESET);
+ regmap_write(am->mii_regmap, AG71XX_REG_MII_CFG, t | MII_CFG_RESET);
udelay(100);
- regmap_write(ag->mii_regmap, AG71XX_REG_MII_CFG, t);
+ regmap_write(am->mii_regmap, AG71XX_REG_MII_CFG, t);
udelay(100);
return 0;
}
-int ag71xx_mdio_init(struct ag71xx *ag)
+static int ag71xx_mdio_probe(struct platform_device *pdev)
{
- struct device *parent = &ag->pdev->dev;
- struct device_node *np;
+ struct device *amdev = &pdev->dev;
+ struct device_node *np = pdev->dev.of_node;
+ struct ag71xx_mdio *am;
struct mii_bus *mii_bus;
bool builtin_switch;
int i, err;
- np = of_get_child_by_name(parent->of_node, "mdio-bus");
- if (!np)
- return -ENODEV;
+ am = devm_kzalloc(amdev, sizeof(*am), GFP_KERNEL);
+ if (!am)
+ return -ENOMEM;
- if (!of_device_is_available(np)) {
- err = 0;
- goto err_out;
- }
-
- ag->mii_regmap = syscon_regmap_lookup_by_phandle(np, "regmap");
- if (!ag->mii_regmap)
+ am->mii_regmap = syscon_regmap_lookup_by_phandle(np, "regmap");
+ if (!am->mii_regmap)
return -ENOENT;
- mii_bus = devm_mdiobus_alloc(parent);
- if (!mii_bus) {
- err = -ENOMEM;
- goto err_out;
- }
+ mii_bus = devm_mdiobus_alloc(amdev);
+ if (!mii_bus)
+ return -ENOMEM;
- ag->mdio_reset = of_reset_control_get_exclusive(np, "mdio");
+ am->mdio_reset = of_reset_control_get_exclusive(np, "mdio");
builtin_switch = of_property_read_bool(np, "builtin-switch");
- mii_bus->name = "mdio";
- if (builtin_switch) {
- mii_bus->read = ar7240sw_phy_read;
- mii_bus->write = ar7240sw_phy_write;
- } else {
- mii_bus->read = ag71xx_mdio_mii_read;
- mii_bus->write = ag71xx_mdio_mii_write;
- }
+ mii_bus->name = "ag71xx_mdio";
+ mii_bus->read = ag71xx_mdio_mii_read;
+ mii_bus->write = ag71xx_mdio_mii_write;
mii_bus->reset = ag71xx_mdio_reset;
- mii_bus->priv = ag;
- mii_bus->parent = parent;
+ mii_bus->priv = am;
+ mii_bus->parent = amdev;
snprintf(mii_bus->id, MII_BUS_ID_SIZE, "%s.%d", np->name, bus_count++);
if (!builtin_switch &&
@@ -185,34 +173,46 @@ int ag71xx_mdio_init(struct ag71xx *ag)
for (i = 0; i < PHY_MAX_ADDR; i++)
mii_bus->irq[i] = PHY_POLL;
- if (!IS_ERR(ag->mdio_reset)) {
- reset_control_assert(ag->mdio_reset);
+ if (!IS_ERR(am->mdio_reset)) {
+ reset_control_assert(am->mdio_reset);
msleep(100);
- reset_control_deassert(ag->mdio_reset);
+ reset_control_deassert(am->mdio_reset);
msleep(200);
}
err = of_mdiobus_register(mii_bus, np);
if (err)
- goto err_out;
-
- ag->mii_bus = mii_bus;
+ return err;
- if (builtin_switch)
- ag71xx_ar7240_init(ag, np);
+ am->mii_bus = mii_bus;
+ platform_set_drvdata(pdev, am);
return 0;
-
-err_out:
- of_node_put(np);
- return err;
}
-void ag71xx_mdio_cleanup(struct ag71xx *ag)
+static int ag71xx_mdio_remove(struct platform_device *pdev)
{
- if (!ag->mii_bus)
- return;
+ struct ag71xx_mdio *am = platform_get_drvdata(pdev);
- ag71xx_ar7240_cleanup(ag);
- mdiobus_unregister(ag->mii_bus);
+ mdiobus_unregister(am->mii_bus);
+ return 0;
}
+
+static const struct of_device_id ag71xx_mdio_match[] = {
+ { .compatible = "qca,ar7240-mdio" },
+ { .compatible = "qca,ar9340-mdio" },
+ { .compatible = "qca,ath79-mdio" },
+ {}
+};
+
+static struct platform_driver ag71xx_mdio_driver = {
+ .probe = ag71xx_mdio_probe,
+ .remove = ag71xx_mdio_remove,
+ .driver = {
+ .name = "ag71xx-mdio",
+ .of_match_table = ag71xx_mdio_match,
+ }
+};
+
+module_platform_driver(ag71xx_mdio_driver);
+MODULE_LICENSE("GPL");