Message ID | 20180709093400.28832-2-judge.packham@gmail.com |
---|---|
State | Accepted |
Commit | fb73107 |
Delegated to: | Joe Hershberger |
Headers | show |
Series | [U-Boot,v3,1/2] net: mvgbe: prepare for conversion to driver model | expand |
Am 2018-07-09 11:34, schrieb Chris Packham: > Add driver model support to the mvgbe driver. As a temporary measure > both DM and non-DM uses are supported. Once all the users have been > converted the non-DM support can be dropped. > > Signed-off-by: Chris Packham <judge.packham@gmail.com> Works for me now, after adding the phy-mode property to my dts ;) Will post a patch for lsxl later. Tested-by: Michael Walle <michael@walle.cc> > --- > > Changes in v3: > - select PHYLIB (thanks Michael) > - parse phy info from subnode > > Changes in v2: > - create __mvgbe_phy_init and mvgbe_alloc_buffers helper functions > - move device tree reads to mvgbe_ofdata_to_platdata > > drivers/net/Kconfig | 1 + > drivers/net/mvgbe.c | 306 +++++++++++++++++++++++++++++++++++++------- > drivers/net/mvgbe.h | 16 +++ > 3 files changed, 275 insertions(+), 48 deletions(-) > > diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig > index e88f056d8448..7256d4167666 100644 > --- a/drivers/net/Kconfig > +++ b/drivers/net/Kconfig > @@ -181,6 +181,7 @@ config FTMAC100 > config MVGBE > bool "Marvell Orion5x/Kirkwood network interface support" > depends on KIRKWOOD || ORION5X > + select PHYLIB if DM_ETH > help > This driver supports the network interface units in the > Marvell Orion5x and Kirkwood SoCs > diff --git a/drivers/net/mvgbe.c b/drivers/net/mvgbe.c > index 96ca35512f01..d9d76a8ce0cc 100644 > --- a/drivers/net/mvgbe.c > +++ b/drivers/net/mvgbe.c > @@ -12,6 +12,7 @@ > */ > > #include <common.h> > +#include <dm.h> > #include <net.h> > #include <malloc.h> > #include <miiphy.h> > @@ -127,8 +128,12 @@ static int __mvgbe_mdio_read(struct mvgbe_device > *dmvgbe, int phy_adr, > static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad, > int reg_ofs) > { > +#ifdef CONFIG_DM_ETH > + struct mvgbe_device *dmvgbe = bus->priv; > +#else > struct eth_device *dev = eth_get_dev_by_name(bus->name); > struct mvgbe_device *dmvgbe = to_mvgbe(dev); > +#endif > > return __mvgbe_mdio_read(dmvgbe, phy_adr, devad, reg_ofs); > } > @@ -180,8 +185,12 @@ static int __mvgbe_mdio_write(struct mvgbe_device > *dmvgbe, int phy_adr, > static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad, > int reg_ofs, u16 data) > { > +#ifdef CONFIG_DM_ETH > + struct mvgbe_device *dmvgbe = bus->priv; > +#else > struct eth_device *dev = eth_get_dev_by_name(bus->name); > struct mvgbe_device *dmvgbe = to_mvgbe(dev); > +#endif > > return __mvgbe_mdio_write(dmvgbe, phy_adr, devad, reg_ofs, data); > } > @@ -415,11 +424,12 @@ static void mvgbe_init_rx_desc_ring(struct > mvgbe_device *dmvgbe) > dmvgbe->p_rxdesc_curr = dmvgbe->p_rxdesc; > } > > -static int __mvgbe_init(struct mvgbe_device *dmvgbe) > +static int __mvgbe_init(struct mvgbe_device *dmvgbe, u8 *enetaddr) > { > struct mvgbe_registers *regs = dmvgbe->regs; > #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \ > !defined(CONFIG_PHYLIB) && \ > + !defined(CONFIG_DM_ETH) && \ > defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) > int i; > #endif > @@ -436,7 +446,7 @@ static int __mvgbe_init(struct mvgbe_device > *dmvgbe) > > set_dram_access(regs); > port_init_mac_tables(regs); > - port_uc_addr_set(dmvgbe, dmvgbe->dev.enetaddr); > + port_uc_addr_set(dmvgbe, enetaddr); > > /* Assign port configuration and command. */ > MVGBE_REG_WR(regs->pxc, PRT_CFG_VAL); > @@ -473,6 +483,7 @@ static int __mvgbe_init(struct mvgbe_device > *dmvgbe) > > #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \ > !defined(CONFIG_PHYLIB) && \ > + !defined(CONFIG_DM_ETH) && \ > defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) > /* Wait up to 5s for the link status */ > for (i = 0; i < 5; i++) { > @@ -492,12 +503,14 @@ static int __mvgbe_init(struct mvgbe_device > *dmvgbe) > return 0; > } > > +#ifndef CONFIG_DM_ETH > static int mvgbe_init(struct eth_device *dev) > { > struct mvgbe_device *dmvgbe = to_mvgbe(dev); > > - return __mvgbe_init(dmvgbe); > + return __mvgbe_init(dmvgbe, dmvgbe->dev.enetaddr); > } > +#endif > > static void __mvgbe_halt(struct mvgbe_device *dmvgbe) > { > @@ -524,6 +537,7 @@ static void __mvgbe_halt(struct mvgbe_device > *dmvgbe) > MVGBE_REG_WR(regs->peim, 0); > } > > +#ifndef CONFIG_DM_ETH > static int mvgbe_halt(struct eth_device *dev) > { > struct mvgbe_device *dmvgbe = to_mvgbe(dev); > @@ -532,7 +546,18 @@ static int mvgbe_halt(struct eth_device *dev) > > return 0; > } > +#endif > > +#ifdef CONFIG_DM_ETH > +static int mvgbe_write_hwaddr(struct udevice *dev) > +{ > + struct eth_pdata *pdata = dev_get_platdata(dev); > + > + port_uc_addr_set(dev_get_priv(dev), pdata->enetaddr); > + > + return 0; > +} > +#else > static int mvgbe_write_hwaddr(struct eth_device *dev) > { > struct mvgbe_device *dmvgbe = to_mvgbe(dev); > @@ -541,6 +566,7 @@ static int mvgbe_write_hwaddr(struct eth_device > *dev) > port_uc_addr_set(dmvgbe, dmvgbe->dev.enetaddr); > return 0; > } > +#endif > > static int __mvgbe_send(struct mvgbe_device *dmvgbe, void *dataptr, > int datasize) > @@ -597,12 +623,14 @@ static int __mvgbe_send(struct mvgbe_device > *dmvgbe, void *dataptr, > return 0; > } > > +#ifndef CONFIG_DM_ETH > static int mvgbe_send(struct eth_device *dev, void *dataptr, int > datasize) > { > struct mvgbe_device *dmvgbe = to_mvgbe(dev); > > return __mvgbe_send(dmvgbe, dataptr, datasize); > } > +#endif > > static int __mvgbe_recv(struct mvgbe_device *dmvgbe, uchar **packetp) > { > @@ -677,6 +705,7 @@ static int __mvgbe_recv(struct mvgbe_device > *dmvgbe, uchar **packetp) > return rx_bytes; > } > > +#ifndef CONFIG_DM_ETH > static int mvgbe_recv(struct eth_device *dev) > { > struct mvgbe_device *dmvgbe = to_mvgbe(dev); > @@ -691,8 +720,41 @@ static int mvgbe_recv(struct eth_device *dev) > > return 0; > } > +#endif > > -#if defined(CONFIG_PHYLIB) > +#if defined(CONFIG_PHYLIB) || defined(CONFIG_DM_ETH) > +#if defined(CONFIG_DM_ETH) > +static struct phy_device *__mvgbe_phy_init(struct udevice *dev, > + struct mii_dev *bus, > + phy_interface_t phy_interface, > + int phyid) > +#else > +static struct phy_device *__mvgbe_phy_init(struct eth_device *dev, > + struct mii_dev *bus, > + phy_interface_t phy_interface, > + int phyid) > +#endif > +{ > + struct phy_device *phydev; > + > + /* Set phy address of the port */ > + miiphy_write(dev->name, MV_PHY_ADR_REQUEST, MV_PHY_ADR_REQUEST, > + phyid); > + > + phydev = phy_connect(bus, phyid, dev, phy_interface); > + if (!phydev) { > + printf("phy_connect failed\n"); > + return NULL; > + } > + > + phy_config(phydev); > + phy_startup(phydev); > + > + return phydev; > +} > +#endif /* CONFIG_PHYLIB || CONFIG_DM_ETH */ > + > +#if defined(CONFIG_PHYLIB) && !defined(CONFIG_DM_ETH) > int mvgbe_phylib_init(struct eth_device *dev, int phyid) > { > struct mii_dev *bus; > @@ -715,27 +777,53 @@ int mvgbe_phylib_init(struct eth_device *dev, int > phyid) > return -ENOMEM; > } > > - /* Set phy address of the port */ > - smi_reg_write(bus, MV_PHY_ADR_REQUEST, 0, MV_PHY_ADR_REQUEST, phyid); > - > - phydev = phy_connect(bus, phyid, dev, PHY_INTERFACE_MODE_RGMII); > - if (!phydev) { > - printf("phy_connect failed\n"); > + phydev = __mvgbe_phy_init(dev, bus, PHY_INTERFACE_MODE_RGMII, phyid); > + if (!phydev) > return -ENODEV; > - } > - > - phy_config(phydev); > - phy_startup(phydev); > > return 0; > } > #endif > > +static int mvgbe_alloc_buffers(struct mvgbe_device *dmvgbe) > +{ > + dmvgbe->p_rxdesc = memalign(PKTALIGN, > + MV_RXQ_DESC_ALIGNED_SIZE * RINGSZ + 1); > + if (!dmvgbe->p_rxdesc) > + goto error1; > + > + dmvgbe->p_rxbuf = memalign(PKTALIGN, > + RINGSZ * PKTSIZE_ALIGN + 1); > + if (!dmvgbe->p_rxbuf) > + goto error2; > + > + dmvgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN); > + if (!dmvgbe->p_aligned_txbuf) > + goto error3; > + > + dmvgbe->p_txdesc = memalign(PKTALIGN, sizeof(struct mvgbe_txdesc) + > 1); > + if (!dmvgbe->p_txdesc) > + goto error4; > + > + return 0; > + > +error4: > + free(dmvgbe->p_aligned_txbuf); > +error3: > + free(dmvgbe->p_rxbuf); > +error2: > + free(dmvgbe->p_rxdesc); > +error1: > + return -ENOMEM; > +} > + > +#ifndef CONFIG_DM_ETH > int mvgbe_initialize(bd_t *bis) > { > struct mvgbe_device *dmvgbe; > struct eth_device *dev; > int devnum; > + int ret; > u8 used_ports[MAX_MVGBE_DEVS] = CONFIG_MVGBE_PORTS; > > for (devnum = 0; devnum < MAX_MVGBE_DEVS; devnum++) { > @@ -744,45 +832,16 @@ int mvgbe_initialize(bd_t *bis) > continue; > > dmvgbe = malloc(sizeof(struct mvgbe_device)); > - > if (!dmvgbe) > - goto error1; > + return -ENOMEM; > > memset(dmvgbe, 0, sizeof(struct mvgbe_device)); > - > - dmvgbe->p_rxdesc = > - (struct mvgbe_rxdesc *)memalign(PKTALIGN, > - MV_RXQ_DESC_ALIGNED_SIZE*RINGSZ + 1); > - > - if (!dmvgbe->p_rxdesc) > - goto error2; > - > - dmvgbe->p_rxbuf = (u8 *) memalign(PKTALIGN, > - RINGSZ*PKTSIZE_ALIGN + 1); > - > - if (!dmvgbe->p_rxbuf) > - goto error3; > - > - dmvgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN); > - > - if (!dmvgbe->p_aligned_txbuf) > - goto error4; > - > - dmvgbe->p_txdesc = (struct mvgbe_txdesc *) memalign( > - PKTALIGN, sizeof(struct mvgbe_txdesc) + 1); > - > - if (!dmvgbe->p_txdesc) { > - free(dmvgbe->p_aligned_txbuf); > -error4: > - free(dmvgbe->p_rxbuf); > -error3: > - free(dmvgbe->p_rxdesc); > -error2: > - free(dmvgbe); > -error1: > + ret = mvgbe_alloc_buffers(dmvgbe); > + if (ret) { > printf("Err.. %s Failed to allocate memory\n", > __func__); > - return -1; > + free(dmvgbe); > + return ret; > } > > dev = &dmvgbe->dev; > @@ -834,3 +893,154 @@ error1: > } > return 0; > } > +#endif > + > +#ifdef CONFIG_DM_ETH > +static int mvgbe_port_is_fixed_link(struct mvgbe_device *dmvgbe) > +{ > + return dmvgbe->phyaddr > PHY_MAX_ADDR; > +} > + > +static int mvgbe_start(struct udevice *dev) > +{ > + struct eth_pdata *pdata = dev_get_platdata(dev); > + struct mvgbe_device *dmvgbe = dev_get_priv(dev); > + int ret; > + > + ret = __mvgbe_init(dmvgbe, pdata->enetaddr); > + if (ret) > + return ret; > + > + if (!mvgbe_port_is_fixed_link(dmvgbe)) { > + dmvgbe->phydev = __mvgbe_phy_init(dev, dmvgbe->bus, > + dmvgbe->phy_interface, > + dmvgbe->phyaddr); > + if (!dmvgbe->phydev) > + return -ENODEV; > + } > + > + return 0; > +} > + > +static int mvgbe_send(struct udevice *dev, void *packet, int length) > +{ > + struct mvgbe_device *dmvgbe = dev_get_priv(dev); > + > + return __mvgbe_send(dmvgbe, packet, length); > +} > + > +static int mvgbe_recv(struct udevice *dev, int flags, uchar **packetp) > +{ > + struct mvgbe_device *dmvgbe = dev_get_priv(dev); > + > + return __mvgbe_recv(dmvgbe, packetp); > +} > + > +static void mvgbe_stop(struct udevice *dev) > +{ > + struct mvgbe_device *dmvgbe = dev_get_priv(dev); > + > + __mvgbe_halt(dmvgbe); > +} > + > +static int mvgbe_probe(struct udevice *dev) > +{ > + struct eth_pdata *pdata = dev_get_platdata(dev); > + struct mvgbe_device *dmvgbe = dev_get_priv(dev); > + struct mii_dev *bus; > + int ret; > + > + ret = mvgbe_alloc_buffers(dmvgbe); > + if (ret) > + return ret; > + > + dmvgbe->regs = (void __iomem *)pdata->iobase; > + > + bus = mdio_alloc(); > + if (!bus) { > + printf("Failed to allocate MDIO bus\n"); > + return -ENOMEM; > + } > + > + bus->read = smi_reg_read; > + bus->write = smi_reg_write; > + snprintf(bus->name, sizeof(bus->name), dev->name); > + bus->priv = dmvgbe; > + dmvgbe->bus = bus; > + > + ret = mdio_register(bus); > + if (ret < 0) > + return ret; > + > + return 0; > +} > + > +static const struct eth_ops mvgbe_ops = { > + .start = mvgbe_start, > + .send = mvgbe_send, > + .recv = mvgbe_recv, > + .stop = mvgbe_stop, > + .write_hwaddr = mvgbe_write_hwaddr, > +}; > + > +static int mvgbe_ofdata_to_platdata(struct udevice *dev) > +{ > + struct eth_pdata *pdata = dev_get_platdata(dev); > + struct mvgbe_device *dmvgbe = dev_get_priv(dev); > + void *blob = (void *)gd->fdt_blob; > + int node = dev_of_offset(dev); > + const char *phy_mode; > + int fl_node; > + int pnode; > + unsigned long addr; > + > + pdata->iobase = devfdt_get_addr(dev); > + pdata->phy_interface = -1; > + > + pnode = fdt_node_offset_by_compatible(blob, node, > + "marvell,kirkwood-eth-port"); > + > + /* Get phy-mode / phy_interface from DT */ > + phy_mode = fdt_getprop(gd->fdt_blob, pnode, "phy-mode", NULL); > + if (phy_mode) > + pdata->phy_interface = phy_get_interface_by_name(phy_mode); > + if (pdata->phy_interface == -1) { > + debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); > + return -EINVAL; > + } > + > + dmvgbe->phy_interface = pdata->phy_interface; > + > + /* fetch 'fixed-link' property */ > + fl_node = fdt_subnode_offset(blob, pnode, "fixed-link"); > + if (fl_node != -FDT_ERR_NOTFOUND) { > + /* set phy_addr to invalid value for fixed link */ > + dmvgbe->phyaddr = PHY_MAX_ADDR + 1; > + dmvgbe->duplex = fdtdec_get_bool(blob, fl_node, "full-duplex"); > + dmvgbe->speed = fdtdec_get_int(blob, fl_node, "speed", 0); > + } else { > + /* Now read phyaddr from DT */ > + addr = fdtdec_lookup_phandle(blob, pnode, "phy-handle"); > + if (addr > 0) > + dmvgbe->phyaddr = fdtdec_get_int(blob, addr, "reg", 0); > + } > + > + return 0; > +} > + > +static const struct udevice_id mvgbe_ids[] = { > + { .compatible = "marvell,kirkwood-eth" }, > + { } > +}; > + > +U_BOOT_DRIVER(mvgbe) = { > + .name = "mvgbe", > + .id = UCLASS_ETH, > + .of_match = mvgbe_ids, > + .ofdata_to_platdata = mvgbe_ofdata_to_platdata, > + .probe = mvgbe_probe, > + .ops = &mvgbe_ops, > + .priv_auto_alloc_size = sizeof(struct mvgbe_device), > + .platdata_auto_alloc_size = sizeof(struct eth_pdata), > +}; > +#endif /* CONFIG_DM_ETH */ > diff --git a/drivers/net/mvgbe.h b/drivers/net/mvgbe.h > index 1dc9bbea2f42..44541c0a85e3 100644 > --- a/drivers/net/mvgbe.h > +++ b/drivers/net/mvgbe.h > @@ -30,7 +30,9 @@ > #define RXUQ 0 /* Used Rx queue */ > #define TXUQ 0 /* Used Rx queue */ > > +#ifndef CONFIG_DM_ETH > #define to_mvgbe(_d) container_of(_d, struct mvgbe_device, dev) > +#endif > #define MVGBE_REG_WR(adr, val) writel(val, &adr) > #define MVGBE_REG_RD(adr) readl(&adr) > #define MVGBE_REG_BITS_RESET(adr, val) writel(readl(&adr) & ~(val), > &adr) > @@ -479,13 +481,27 @@ struct mvgbe_txdesc { > > /* port device data struct */ > struct mvgbe_device { > +#ifndef CONFIG_DM_ETH > struct eth_device dev; > +#endif > struct mvgbe_registers *regs; > struct mvgbe_txdesc *p_txdesc; > struct mvgbe_rxdesc *p_rxdesc; > struct mvgbe_rxdesc *p_rxdesc_curr; > u8 *p_rxbuf; > u8 *p_aligned_txbuf; > + > +#ifdef CONFIG_DM_ETH > + phy_interface_t phy_interface; > + unsigned int link; > + unsigned int duplex; > + unsigned int speed; > + > + int init; > + int phyaddr; > + struct phy_device *phydev; > + struct mii_dev *bus; > +#endif > }; > > #endif /* __MVGBE_H__ */
On Mon, Jul 9, 2018 at 4:34 AM, Chris Packham <judge.packham@gmail.com> wrote: > Add driver model support to the mvgbe driver. As a temporary measure > both DM and non-DM uses are supported. Once all the users have been > converted the non-DM support can be dropped. > > Signed-off-by: Chris Packham <judge.packham@gmail.com> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Hi Chris, https://patchwork.ozlabs.org/patch/941175/ was applied to http://git.denx.de/?p=u-boot/u-boot-net.git Thanks! -Joe
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e88f056d8448..7256d4167666 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -181,6 +181,7 @@ config FTMAC100 config MVGBE bool "Marvell Orion5x/Kirkwood network interface support" depends on KIRKWOOD || ORION5X + select PHYLIB if DM_ETH help This driver supports the network interface units in the Marvell Orion5x and Kirkwood SoCs diff --git a/drivers/net/mvgbe.c b/drivers/net/mvgbe.c index 96ca35512f01..d9d76a8ce0cc 100644 --- a/drivers/net/mvgbe.c +++ b/drivers/net/mvgbe.c @@ -12,6 +12,7 @@ */ #include <common.h> +#include <dm.h> #include <net.h> #include <malloc.h> #include <miiphy.h> @@ -127,8 +128,12 @@ static int __mvgbe_mdio_read(struct mvgbe_device *dmvgbe, int phy_adr, static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad, int reg_ofs) { +#ifdef CONFIG_DM_ETH + struct mvgbe_device *dmvgbe = bus->priv; +#else struct eth_device *dev = eth_get_dev_by_name(bus->name); struct mvgbe_device *dmvgbe = to_mvgbe(dev); +#endif return __mvgbe_mdio_read(dmvgbe, phy_adr, devad, reg_ofs); } @@ -180,8 +185,12 @@ static int __mvgbe_mdio_write(struct mvgbe_device *dmvgbe, int phy_adr, static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad, int reg_ofs, u16 data) { +#ifdef CONFIG_DM_ETH + struct mvgbe_device *dmvgbe = bus->priv; +#else struct eth_device *dev = eth_get_dev_by_name(bus->name); struct mvgbe_device *dmvgbe = to_mvgbe(dev); +#endif return __mvgbe_mdio_write(dmvgbe, phy_adr, devad, reg_ofs, data); } @@ -415,11 +424,12 @@ static void mvgbe_init_rx_desc_ring(struct mvgbe_device *dmvgbe) dmvgbe->p_rxdesc_curr = dmvgbe->p_rxdesc; } -static int __mvgbe_init(struct mvgbe_device *dmvgbe) +static int __mvgbe_init(struct mvgbe_device *dmvgbe, u8 *enetaddr) { struct mvgbe_registers *regs = dmvgbe->regs; #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \ !defined(CONFIG_PHYLIB) && \ + !defined(CONFIG_DM_ETH) && \ defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) int i; #endif @@ -436,7 +446,7 @@ static int __mvgbe_init(struct mvgbe_device *dmvgbe) set_dram_access(regs); port_init_mac_tables(regs); - port_uc_addr_set(dmvgbe, dmvgbe->dev.enetaddr); + port_uc_addr_set(dmvgbe, enetaddr); /* Assign port configuration and command. */ MVGBE_REG_WR(regs->pxc, PRT_CFG_VAL); @@ -473,6 +483,7 @@ static int __mvgbe_init(struct mvgbe_device *dmvgbe) #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \ !defined(CONFIG_PHYLIB) && \ + !defined(CONFIG_DM_ETH) && \ defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) /* Wait up to 5s for the link status */ for (i = 0; i < 5; i++) { @@ -492,12 +503,14 @@ static int __mvgbe_init(struct mvgbe_device *dmvgbe) return 0; } +#ifndef CONFIG_DM_ETH static int mvgbe_init(struct eth_device *dev) { struct mvgbe_device *dmvgbe = to_mvgbe(dev); - return __mvgbe_init(dmvgbe); + return __mvgbe_init(dmvgbe, dmvgbe->dev.enetaddr); } +#endif static void __mvgbe_halt(struct mvgbe_device *dmvgbe) { @@ -524,6 +537,7 @@ static void __mvgbe_halt(struct mvgbe_device *dmvgbe) MVGBE_REG_WR(regs->peim, 0); } +#ifndef CONFIG_DM_ETH static int mvgbe_halt(struct eth_device *dev) { struct mvgbe_device *dmvgbe = to_mvgbe(dev); @@ -532,7 +546,18 @@ static int mvgbe_halt(struct eth_device *dev) return 0; } +#endif +#ifdef CONFIG_DM_ETH +static int mvgbe_write_hwaddr(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + + port_uc_addr_set(dev_get_priv(dev), pdata->enetaddr); + + return 0; +} +#else static int mvgbe_write_hwaddr(struct eth_device *dev) { struct mvgbe_device *dmvgbe = to_mvgbe(dev); @@ -541,6 +566,7 @@ static int mvgbe_write_hwaddr(struct eth_device *dev) port_uc_addr_set(dmvgbe, dmvgbe->dev.enetaddr); return 0; } +#endif static int __mvgbe_send(struct mvgbe_device *dmvgbe, void *dataptr, int datasize) @@ -597,12 +623,14 @@ static int __mvgbe_send(struct mvgbe_device *dmvgbe, void *dataptr, return 0; } +#ifndef CONFIG_DM_ETH static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize) { struct mvgbe_device *dmvgbe = to_mvgbe(dev); return __mvgbe_send(dmvgbe, dataptr, datasize); } +#endif static int __mvgbe_recv(struct mvgbe_device *dmvgbe, uchar **packetp) { @@ -677,6 +705,7 @@ static int __mvgbe_recv(struct mvgbe_device *dmvgbe, uchar **packetp) return rx_bytes; } +#ifndef CONFIG_DM_ETH static int mvgbe_recv(struct eth_device *dev) { struct mvgbe_device *dmvgbe = to_mvgbe(dev); @@ -691,8 +720,41 @@ static int mvgbe_recv(struct eth_device *dev) return 0; } +#endif -#if defined(CONFIG_PHYLIB) +#if defined(CONFIG_PHYLIB) || defined(CONFIG_DM_ETH) +#if defined(CONFIG_DM_ETH) +static struct phy_device *__mvgbe_phy_init(struct udevice *dev, + struct mii_dev *bus, + phy_interface_t phy_interface, + int phyid) +#else +static struct phy_device *__mvgbe_phy_init(struct eth_device *dev, + struct mii_dev *bus, + phy_interface_t phy_interface, + int phyid) +#endif +{ + struct phy_device *phydev; + + /* Set phy address of the port */ + miiphy_write(dev->name, MV_PHY_ADR_REQUEST, MV_PHY_ADR_REQUEST, + phyid); + + phydev = phy_connect(bus, phyid, dev, phy_interface); + if (!phydev) { + printf("phy_connect failed\n"); + return NULL; + } + + phy_config(phydev); + phy_startup(phydev); + + return phydev; +} +#endif /* CONFIG_PHYLIB || CONFIG_DM_ETH */ + +#if defined(CONFIG_PHYLIB) && !defined(CONFIG_DM_ETH) int mvgbe_phylib_init(struct eth_device *dev, int phyid) { struct mii_dev *bus; @@ -715,27 +777,53 @@ int mvgbe_phylib_init(struct eth_device *dev, int phyid) return -ENOMEM; } - /* Set phy address of the port */ - smi_reg_write(bus, MV_PHY_ADR_REQUEST, 0, MV_PHY_ADR_REQUEST, phyid); - - phydev = phy_connect(bus, phyid, dev, PHY_INTERFACE_MODE_RGMII); - if (!phydev) { - printf("phy_connect failed\n"); + phydev = __mvgbe_phy_init(dev, bus, PHY_INTERFACE_MODE_RGMII, phyid); + if (!phydev) return -ENODEV; - } - - phy_config(phydev); - phy_startup(phydev); return 0; } #endif +static int mvgbe_alloc_buffers(struct mvgbe_device *dmvgbe) +{ + dmvgbe->p_rxdesc = memalign(PKTALIGN, + MV_RXQ_DESC_ALIGNED_SIZE * RINGSZ + 1); + if (!dmvgbe->p_rxdesc) + goto error1; + + dmvgbe->p_rxbuf = memalign(PKTALIGN, + RINGSZ * PKTSIZE_ALIGN + 1); + if (!dmvgbe->p_rxbuf) + goto error2; + + dmvgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN); + if (!dmvgbe->p_aligned_txbuf) + goto error3; + + dmvgbe->p_txdesc = memalign(PKTALIGN, sizeof(struct mvgbe_txdesc) + 1); + if (!dmvgbe->p_txdesc) + goto error4; + + return 0; + +error4: + free(dmvgbe->p_aligned_txbuf); +error3: + free(dmvgbe->p_rxbuf); +error2: + free(dmvgbe->p_rxdesc); +error1: + return -ENOMEM; +} + +#ifndef CONFIG_DM_ETH int mvgbe_initialize(bd_t *bis) { struct mvgbe_device *dmvgbe; struct eth_device *dev; int devnum; + int ret; u8 used_ports[MAX_MVGBE_DEVS] = CONFIG_MVGBE_PORTS; for (devnum = 0; devnum < MAX_MVGBE_DEVS; devnum++) { @@ -744,45 +832,16 @@ int mvgbe_initialize(bd_t *bis) continue; dmvgbe = malloc(sizeof(struct mvgbe_device)); - if (!dmvgbe) - goto error1; + return -ENOMEM; memset(dmvgbe, 0, sizeof(struct mvgbe_device)); - - dmvgbe->p_rxdesc = - (struct mvgbe_rxdesc *)memalign(PKTALIGN, - MV_RXQ_DESC_ALIGNED_SIZE*RINGSZ + 1); - - if (!dmvgbe->p_rxdesc) - goto error2; - - dmvgbe->p_rxbuf = (u8 *) memalign(PKTALIGN, - RINGSZ*PKTSIZE_ALIGN + 1); - - if (!dmvgbe->p_rxbuf) - goto error3; - - dmvgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN); - - if (!dmvgbe->p_aligned_txbuf) - goto error4; - - dmvgbe->p_txdesc = (struct mvgbe_txdesc *) memalign( - PKTALIGN, sizeof(struct mvgbe_txdesc) + 1); - - if (!dmvgbe->p_txdesc) { - free(dmvgbe->p_aligned_txbuf); -error4: - free(dmvgbe->p_rxbuf); -error3: - free(dmvgbe->p_rxdesc); -error2: - free(dmvgbe); -error1: + ret = mvgbe_alloc_buffers(dmvgbe); + if (ret) { printf("Err.. %s Failed to allocate memory\n", __func__); - return -1; + free(dmvgbe); + return ret; } dev = &dmvgbe->dev; @@ -834,3 +893,154 @@ error1: } return 0; } +#endif + +#ifdef CONFIG_DM_ETH +static int mvgbe_port_is_fixed_link(struct mvgbe_device *dmvgbe) +{ + return dmvgbe->phyaddr > PHY_MAX_ADDR; +} + +static int mvgbe_start(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + struct mvgbe_device *dmvgbe = dev_get_priv(dev); + int ret; + + ret = __mvgbe_init(dmvgbe, pdata->enetaddr); + if (ret) + return ret; + + if (!mvgbe_port_is_fixed_link(dmvgbe)) { + dmvgbe->phydev = __mvgbe_phy_init(dev, dmvgbe->bus, + dmvgbe->phy_interface, + dmvgbe->phyaddr); + if (!dmvgbe->phydev) + return -ENODEV; + } + + return 0; +} + +static int mvgbe_send(struct udevice *dev, void *packet, int length) +{ + struct mvgbe_device *dmvgbe = dev_get_priv(dev); + + return __mvgbe_send(dmvgbe, packet, length); +} + +static int mvgbe_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct mvgbe_device *dmvgbe = dev_get_priv(dev); + + return __mvgbe_recv(dmvgbe, packetp); +} + +static void mvgbe_stop(struct udevice *dev) +{ + struct mvgbe_device *dmvgbe = dev_get_priv(dev); + + __mvgbe_halt(dmvgbe); +} + +static int mvgbe_probe(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + struct mvgbe_device *dmvgbe = dev_get_priv(dev); + struct mii_dev *bus; + int ret; + + ret = mvgbe_alloc_buffers(dmvgbe); + if (ret) + return ret; + + dmvgbe->regs = (void __iomem *)pdata->iobase; + + bus = mdio_alloc(); + if (!bus) { + printf("Failed to allocate MDIO bus\n"); + return -ENOMEM; + } + + bus->read = smi_reg_read; + bus->write = smi_reg_write; + snprintf(bus->name, sizeof(bus->name), dev->name); + bus->priv = dmvgbe; + dmvgbe->bus = bus; + + ret = mdio_register(bus); + if (ret < 0) + return ret; + + return 0; +} + +static const struct eth_ops mvgbe_ops = { + .start = mvgbe_start, + .send = mvgbe_send, + .recv = mvgbe_recv, + .stop = mvgbe_stop, + .write_hwaddr = mvgbe_write_hwaddr, +}; + +static int mvgbe_ofdata_to_platdata(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + struct mvgbe_device *dmvgbe = dev_get_priv(dev); + void *blob = (void *)gd->fdt_blob; + int node = dev_of_offset(dev); + const char *phy_mode; + int fl_node; + int pnode; + unsigned long addr; + + pdata->iobase = devfdt_get_addr(dev); + pdata->phy_interface = -1; + + pnode = fdt_node_offset_by_compatible(blob, node, + "marvell,kirkwood-eth-port"); + + /* Get phy-mode / phy_interface from DT */ + phy_mode = fdt_getprop(gd->fdt_blob, pnode, "phy-mode", NULL); + if (phy_mode) + pdata->phy_interface = phy_get_interface_by_name(phy_mode); + if (pdata->phy_interface == -1) { + debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); + return -EINVAL; + } + + dmvgbe->phy_interface = pdata->phy_interface; + + /* fetch 'fixed-link' property */ + fl_node = fdt_subnode_offset(blob, pnode, "fixed-link"); + if (fl_node != -FDT_ERR_NOTFOUND) { + /* set phy_addr to invalid value for fixed link */ + dmvgbe->phyaddr = PHY_MAX_ADDR + 1; + dmvgbe->duplex = fdtdec_get_bool(blob, fl_node, "full-duplex"); + dmvgbe->speed = fdtdec_get_int(blob, fl_node, "speed", 0); + } else { + /* Now read phyaddr from DT */ + addr = fdtdec_lookup_phandle(blob, pnode, "phy-handle"); + if (addr > 0) + dmvgbe->phyaddr = fdtdec_get_int(blob, addr, "reg", 0); + } + + return 0; +} + +static const struct udevice_id mvgbe_ids[] = { + { .compatible = "marvell,kirkwood-eth" }, + { } +}; + +U_BOOT_DRIVER(mvgbe) = { + .name = "mvgbe", + .id = UCLASS_ETH, + .of_match = mvgbe_ids, + .ofdata_to_platdata = mvgbe_ofdata_to_platdata, + .probe = mvgbe_probe, + .ops = &mvgbe_ops, + .priv_auto_alloc_size = sizeof(struct mvgbe_device), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +}; +#endif /* CONFIG_DM_ETH */ diff --git a/drivers/net/mvgbe.h b/drivers/net/mvgbe.h index 1dc9bbea2f42..44541c0a85e3 100644 --- a/drivers/net/mvgbe.h +++ b/drivers/net/mvgbe.h @@ -30,7 +30,9 @@ #define RXUQ 0 /* Used Rx queue */ #define TXUQ 0 /* Used Rx queue */ +#ifndef CONFIG_DM_ETH #define to_mvgbe(_d) container_of(_d, struct mvgbe_device, dev) +#endif #define MVGBE_REG_WR(adr, val) writel(val, &adr) #define MVGBE_REG_RD(adr) readl(&adr) #define MVGBE_REG_BITS_RESET(adr, val) writel(readl(&adr) & ~(val), &adr) @@ -479,13 +481,27 @@ struct mvgbe_txdesc { /* port device data struct */ struct mvgbe_device { +#ifndef CONFIG_DM_ETH struct eth_device dev; +#endif struct mvgbe_registers *regs; struct mvgbe_txdesc *p_txdesc; struct mvgbe_rxdesc *p_rxdesc; struct mvgbe_rxdesc *p_rxdesc_curr; u8 *p_rxbuf; u8 *p_aligned_txbuf; + +#ifdef CONFIG_DM_ETH + phy_interface_t phy_interface; + unsigned int link; + unsigned int duplex; + unsigned int speed; + + int init; + int phyaddr; + struct phy_device *phydev; + struct mii_dev *bus; +#endif }; #endif /* __MVGBE_H__ */
Add driver model support to the mvgbe driver. As a temporary measure both DM and non-DM uses are supported. Once all the users have been converted the non-DM support can be dropped. Signed-off-by: Chris Packham <judge.packham@gmail.com> --- Changes in v3: - select PHYLIB (thanks Michael) - parse phy info from subnode Changes in v2: - create __mvgbe_phy_init and mvgbe_alloc_buffers helper functions - move device tree reads to mvgbe_ofdata_to_platdata drivers/net/Kconfig | 1 + drivers/net/mvgbe.c | 306 +++++++++++++++++++++++++++++++++++++------- drivers/net/mvgbe.h | 16 +++ 3 files changed, 275 insertions(+), 48 deletions(-)