diff options
author | Renaud Barbier <renaud.barbier@ge.com> | 2013-06-25 14:09:59 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2013-06-25 22:16:55 +0200 |
commit | eb99c09f7c7edf27188e2d3e70773f9d29b93547 (patch) | |
tree | 43337c6c4bf785b3926ad13fe3dc4d51b9baa6a4 /drivers/net/gianfar.c | |
parent | 0cbb2155193ae04b4b9be501d22339ab80c03fee (diff) | |
download | barebox-eb99c09f7c7edf27188e2d3e70773f9d29b93547.tar.gz barebox-eb99c09f7c7edf27188e2d3e70773f9d29b93547.tar.xz |
ppc: gianfar MDIO buses
This commit creates MDIO bus devices to separate the MDIO bus
abstraction from the Ethernet device initialisation.
It also updates the configuration of the P2020RDB ports.
Signed-off-by: Renaud Barbier <renaud.barbier@ge.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/net/gianfar.c')
-rw-r--r-- | drivers/net/gianfar.c | 146 |
1 files changed, 111 insertions, 35 deletions
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 96055bd39c..f944c6c060 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -184,10 +184,11 @@ static int gfar_open(struct eth_device *edev) { int ix; struct gfar_private *priv = edev->priv; + struct gfar_phy *phy = priv->gfar_mdio; void __iomem *regs = priv->regs; int ret; - ret = phy_device_connect(edev, &priv->miibus, priv->phyaddr, + ret = phy_device_connect(edev, &phy->miibus, priv->phyaddr, gfar_adjust_link, 0, PHY_INTERFACE_MODE_NA); if (ret) return ret; @@ -305,44 +306,51 @@ static uint gfar_local_mdio_read(void __iomem *phyregs, uint phyid, uint regnum) static void gfar_configure_serdes(struct gfar_private *priv) { - gfar_local_mdio_write(priv->phyregs_sgmii, + struct gfar_phy *phy = priv->gfar_tbi; + + gfar_local_mdio_write(phy->regs, in_be32(priv->regs + GFAR_TBIPA_OFFSET), GFAR_TBI_ANA, priv->tbiana); - gfar_local_mdio_write(priv->phyregs_sgmii, + gfar_local_mdio_write(phy->regs, in_be32(priv->regs + GFAR_TBIPA_OFFSET), GFAR_TBI_TBICON, GFAR_TBICON_CLK_SELECT); - gfar_local_mdio_write(priv->phyregs_sgmii, + gfar_local_mdio_write(phy->regs, in_be32(priv->regs + GFAR_TBIPA_OFFSET), GFAR_TBI_CR, priv->tbicr); } -/* Reset the internal and external PHYs. */ -static void gfar_init_phy(struct eth_device *dev) +static int gfar_bus_reset(struct mii_bus *bus) { - struct gfar_private *priv = dev->priv; - void __iomem *regs = priv->regs; + struct gfar_phy *phy = bus->priv; uint64_t start; - /* Assign a Physical address to the TBI */ - out_be32(regs + GFAR_TBIPA_OFFSET, GFAR_TBIPA_VALUE); - /* Reset MII (due to new addresses) */ - out_be32(priv->phyregs + GFAR_MIIMCFG_OFFSET, GFAR_MIIMCFG_RESET); - out_be32(priv->phyregs + GFAR_MIIMCFG_OFFSET, GFAR_MIIMCFG_INIT_VALUE); + out_be32(phy->regs + GFAR_MIIMCFG_OFFSET, GFAR_MIIMCFG_RESET); + out_be32(phy->regs + GFAR_MIIMCFG_OFFSET, GFAR_MIIMCFG_INIT_VALUE); start = get_time_ns(); while (!is_timeout(start, 10 * MSECOND)) { - if (!(in_be32(priv->phyregs + GFAR_MIIMMIND_OFFSET) & + if (!(in_be32(phy->regs + GFAR_MIIMMIND_OFFSET) & GFAR_MIIMIND_BUSY)) break; } + return 0; +} - gfar_local_mdio_write(priv->phyregs, priv->phyaddr, GFAR_MIIM_CR, +/* Reset the external PHYs. */ +static void gfar_init_phy(struct eth_device *dev) +{ + struct gfar_private *priv = dev->priv; + struct gfar_phy *phy = priv->gfar_mdio; + void __iomem *regs = priv->regs; + uint64_t start; + + gfar_local_mdio_write(phy->regs, priv->phyaddr, GFAR_MIIM_CR, GFAR_MIIM_CR_RST); start = get_time_ns(); while (!is_timeout(start, 10 * MSECOND)) { - if (!(gfar_local_mdio_read(priv->phyregs, priv->phyaddr, + if (!(gfar_local_mdio_read(phy->regs, priv->phyaddr, GFAR_MIIM_CR) & GFAR_MIIM_CR_RST)) break; } @@ -433,13 +441,12 @@ static int gfar_recv(struct eth_device *edev) /* Read a MII PHY register. */ static int gfar_miiphy_read(struct mii_bus *bus, int addr, int reg) { - struct device_d *dev = bus->parent; - struct gfar_private *priv = bus->priv; + struct gfar_phy *phy = bus->priv; int ret; - ret = gfar_local_mdio_read(priv->phyregs, addr, reg); + ret = gfar_local_mdio_read(phy->regs, addr, reg); if (ret == -EIO) - dev_err(dev, "Can't read PHY at address %d\n", addr); + dev_err(phy->dev, "Can't read PHY at address %d\n", addr); return ret; } @@ -448,15 +455,14 @@ static int gfar_miiphy_read(struct mii_bus *bus, int addr, int reg) static int gfar_miiphy_write(struct mii_bus *bus, int addr, int reg, u16 value) { - struct device_d *dev = bus->parent; - struct gfar_private *priv = bus->priv; + struct gfar_phy *phy = bus->priv; unsigned short val = value; int ret; - ret = gfar_local_mdio_write(priv->phyregs, addr, reg, val); + ret = gfar_local_mdio_write(phy->regs, addr, reg, val); if (ret) - dev_err(dev, "Can't write PHY at address %d\n", addr); + dev_err(phy->dev, "Can't write PHY at address %d\n", addr); return 0; } @@ -470,7 +476,9 @@ static int gfar_probe(struct device_d *dev) struct gfar_info_struct *gfar_info = dev->platform_data; struct eth_device *edev; struct gfar_private *priv; + struct device_d *mdev; size_t size; + char devname[16]; char *p; priv = xzalloc(sizeof(struct gfar_private)); @@ -480,14 +488,28 @@ static int gfar_probe(struct device_d *dev) edev = &priv->edev; - priv->regs = dev_request_mem_region(dev, 0); - priv->phyregs = dev_request_mem_region(dev, 1); - priv->phyregs_sgmii = dev_request_mem_region(dev, 2); - + priv->mdiobus_tbi = gfar_info->mdiobus_tbi; + priv->regs = dev_get_mem_region(dev, 0); priv->phyaddr = gfar_info->phyaddr; priv->tbicr = gfar_info->tbicr; priv->tbiana = gfar_info->tbiana; + mdev = get_device_by_name("gfar-mdio0"); + if (mdev == NULL) { + pr_err("gfar-mdio0 was not found\n"); + return -ENODEV; + } + priv->gfar_mdio = mdev->priv; + + if (priv->mdiobus_tbi != 0) { + sprintf(devname, "%s%d", "gfar-tbiphy", priv->mdiobus_tbi); + mdev = get_device_by_name(devname); + if (mdev == NULL) { + pr_err("%s was not found\n", devname); + return -ENODEV; + } + } + priv->gfar_tbi = mdev->priv; /* * Allocate descriptors 64-bit aligned. Descriptors * are 8 bytes in size. @@ -512,15 +534,8 @@ static int gfar_probe(struct device_d *dev) udelay(2); clrbits_be32(priv->regs + GFAR_MACCFG1_OFFSET, GFAR_MACCFG1_SOFT_RESET); - priv->miibus.read = gfar_miiphy_read; - priv->miibus.write = gfar_miiphy_write; - priv->miibus.priv = priv; - priv->miibus.parent = dev; - gfar_init_phy(edev); - mdiobus_register(&priv->miibus); - return eth_register(edev); } @@ -529,3 +544,64 @@ static struct driver_d gfar_eth_driver = { .probe = gfar_probe, }; device_platform_driver(gfar_eth_driver); + +static int gfar_phy_probe(struct device_d *dev) +{ + struct gfar_phy *phy; + int ret; + + phy = xzalloc(sizeof(*phy)); + phy->dev = dev; + phy->regs = dev_get_mem_region(dev, 0); + if (!phy->regs) + return -ENOMEM; + + phy->miibus.read = gfar_miiphy_read; + phy->miibus.write = gfar_miiphy_write; + phy->miibus.priv = phy; + phy->miibus.reset = gfar_bus_reset; + phy->miibus.parent = dev; + dev->priv = phy; + + ret = mdiobus_register(&phy->miibus); + if (ret) + return ret; + + return 0; +} + +static struct driver_d gfar_phy_driver = { + .name = "gfar-mdio", + .probe = gfar_phy_probe, +}; +register_driver_macro(coredevice, platform, gfar_phy_driver); + +static int gfar_tbiphy_probe(struct device_d *dev) +{ + struct gfar_phy *phy; + int ret; + + phy = xzalloc(sizeof(*phy)); + phy->dev = dev; + phy->regs = dev_get_mem_region(dev, 0); + if (!phy->regs) + return -ENOMEM; + + phy->miibus.read = gfar_miiphy_read; + phy->miibus.write = gfar_miiphy_write; + phy->miibus.priv = phy; + phy->miibus.parent = dev; + dev->priv = phy; + + ret = mdiobus_register(&phy->miibus); + if (ret) + return ret; + + return 0; +} + +static struct driver_d gfar_tbiphy_driver = { + .name = "gfar-tbiphy", + .probe = gfar_tbiphy_probe, +}; +register_driver_macro(coredevice, platform, gfar_tbiphy_driver); |