
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__ */