[U-Boot] [PATCH v3 2/2] net: mvgbe: convert to DM

Michael Walle michael at walle.cc
Mon Jul 9 18:54:34 UTC 2018


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


More information about the U-Boot mailing list