[PATCH 3/6] net: calxedagmac: Convert to DM_ETH

Ramon Fried rfried.dev at gmail.com
Thu Apr 15 03:53:31 CEST 2021


On Mon, Apr 12, 2021 at 3:05 AM Andre Przywara <andre.przywara at arm.com> wrote:
>
> To squash that nasty warning message and make better use of the newly
> gained OF_CONTROL feature, let's convert the calxedagmac driver to the
> "new" driver model.
> The conversion is pretty straight forward, mostly just adjusting the
> use of the involved data structures.
> The only actual change is the required split of the receive routine into
> a receive and free_pkt part.
> Also this allows us to get rid of the hardcoded platform information and
> explicit init calls.
>
> This also uses the opportunity to wrap the code decoding the MMIO
> register base address, to make it safe for using PHYS_64BIT later.
>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  arch/arm/Kconfig             |   1 +
>  board/highbank/highbank.c    |  13 ---
>  configs/highbank_defconfig   |   1 +
>  drivers/net/Kconfig          |   7 ++
>  drivers/net/calxedaxgmac.c   | 192 +++++++++++++++++++++++------------
>  include/configs/highbank.h   |   2 -
>  include/netdev.h             |   1 -
>  scripts/config_whitelist.txt |   1 -
>  8 files changed, 137 insertions(+), 81 deletions(-)
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index bd6064923fe..0082d06182a 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -756,6 +756,7 @@ config ARCH_HIGHBANK
>         select CLK
>         select CLK_CCF
>         select AHCI
> +       select DM_ETH
>
>  config ARCH_INTEGRATOR
>         bool "ARM Ltd. Integrator family"
> diff --git a/board/highbank/highbank.c b/board/highbank/highbank.c
> index 2e2300a307f..0667a48965c 100644
> --- a/board/highbank/highbank.c
> +++ b/board/highbank/highbank.c
> @@ -10,7 +10,6 @@
>  #include <fdt_support.h>
>  #include <init.h>
>  #include <net.h>
> -#include <netdev.h>
>  #include <scsi.h>
>  #include <asm/global_data.h>
>
> @@ -52,18 +51,6 @@ int board_init(void)
>         return 0;
>  }
>
> -/* We know all the init functions have been run now */
> -int board_eth_init(struct bd_info *bis)
> -{
> -       int rc = 0;
> -
> -#ifdef CONFIG_CALXEDA_XGMAC
> -       rc += calxedaxgmac_initialize(0, 0xfff50000);
> -       rc += calxedaxgmac_initialize(1, 0xfff51000);
> -#endif
> -       return rc;
> -}
> -
>  #ifdef CONFIG_SCSI_AHCI_PLAT
>  void scsi_init(void)
>  {
> diff --git a/configs/highbank_defconfig b/configs/highbank_defconfig
> index 773ed7a00bf..c3352b827d7 100644
> --- a/configs/highbank_defconfig
> +++ b/configs/highbank_defconfig
> @@ -27,3 +27,4 @@ CONFIG_SCSI=y
>  CONFIG_CONS_INDEX=0
>  CONFIG_OF_LIBFDT=y
>  CONFIG_OF_BOARD=y
> +CONFIG_CALXEDA_XGMAC=y
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index cf062fad4da..cebd84035c8 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -171,6 +171,13 @@ config CORTINA_NI_ENET
>           This driver supports the Cortina-Access Ethernet MAC for
>           all supported CAxxxx SoCs.
>
> +config CALXEDA_XGMAC
> +       bool "Calxeda XGMAC support"
> +       depends on DM_ETH
> +       help
> +         This driver supports the XGMAC in Calxeda Highbank and Midway
> +         machines.
> +
>  config DWC_ETH_QOS
>         bool "Synopsys DWC Ethernet QOS device support"
>         depends on DM_ETH
> diff --git a/drivers/net/calxedaxgmac.c b/drivers/net/calxedaxgmac.c
> index 8b2ee49b441..b98d709117a 100644
> --- a/drivers/net/calxedaxgmac.c
> +++ b/drivers/net/calxedaxgmac.c
> @@ -10,6 +10,8 @@
>  #include <linux/delay.h>
>  #include <linux/err.h>
>  #include <asm/io.h>
> +#include <dm.h>
> +#include <dm/device-internal.h>        /* for dev_set_priv() */
>
>  #define TX_NUM_DESC                    1
>  #define RX_NUM_DESC                    32
> @@ -212,6 +214,18 @@ struct xgmac_dma_desc {
>         __le32 res[3];
>  };
>
> +static struct xgmac_regs *xgmac_get_regs(struct eth_pdata *pdata)
> +{
> +       /*
> +        * We use PHYS_64BIT on Highbank, so phys_addr_t is bigger than
> +        * a pointer. U-Boot doesn't use LPAE (not even the MMU on highbank),
> +        * so we can't access anything above 4GB.
> +        * We have a check in the probe function below the ensure this,
> +        * so casting to a 32-bit pointer type is fine here.
> +        */
> +       return (struct xgmac_regs *)(uintptr_t)pdata->iobase;
> +}
> +
>  /* XGMAC Descriptor Access Helpers */
>  static inline void desc_set_buf_len(struct xgmac_dma_desc *p, u32 buf_sz)
>  {
> @@ -304,8 +318,6 @@ struct calxeda_eth_dev {
>
>         u32 tx_currdesc;
>         u32 rx_currdesc;
> -
> -       struct eth_device *dev;
>  } __aligned(32);
>
>  /*
> @@ -313,10 +325,10 @@ struct calxeda_eth_dev {
>   * advanced descriptors.
>   */
>
> -static void init_rx_desc(struct calxeda_eth_dev *priv)
> +static void init_rx_desc(struct eth_pdata *pdata, struct calxeda_eth_dev *priv)
>  {
>         struct xgmac_dma_desc *rxdesc = priv->rx_chain;
> -       struct xgmac_regs *regs = (struct xgmac_regs *)priv->dev->iobase;
> +       struct xgmac_regs *regs = xgmac_get_regs(pdata);
>         void *rxbuffer = priv->rxbuffer;
>         int i;
>
> @@ -330,17 +342,16 @@ static void init_rx_desc(struct calxeda_eth_dev *priv)
>         }
>  }
>
> -static void init_tx_desc(struct calxeda_eth_dev *priv)
> +static void init_tx_desc(struct eth_pdata *pdata, struct calxeda_eth_dev *priv)
>  {
> -       struct xgmac_regs *regs = (struct xgmac_regs *)priv->dev->iobase;
> +       struct xgmac_regs *regs = xgmac_get_regs(pdata);
>
>         desc_init_tx_desc(priv->tx_chain, TX_NUM_DESC);
>         writel((ulong)priv->tx_chain, &regs->txdesclist);
>  }
>
> -static int xgmac_reset(struct eth_device *dev)
> +static int xgmac_reset(struct xgmac_regs *regs)
>  {
> -       struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
>         int timeout = MAC_TIMEOUT;
>         u32 value;
>
> @@ -356,27 +367,28 @@ static int xgmac_reset(struct eth_device *dev)
>         return timeout;
>  }
>
> -static void xgmac_hwmacaddr(struct eth_device *dev)
> +static void xgmac_hwmacaddr(struct eth_pdata *pdata)
>  {
> -       struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
> +       struct xgmac_regs *regs = xgmac_get_regs(pdata);
>         u32 macaddr[2];
>
> -       memcpy(macaddr, dev->enetaddr, 6);
> +       memcpy(macaddr, pdata->enetaddr, ARP_HLEN);
>         writel(macaddr[1], &regs->macaddr[0].hi);
>         writel(macaddr[0], &regs->macaddr[0].lo);
>  }
>
> -static int xgmac_init(struct eth_device *dev, struct bd_info * bis)
> +static int xgmac_eth_start(struct udevice *dev)
>  {
> -       struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
> -       struct calxeda_eth_dev *priv = dev->priv;
> -       int value;
> +       struct eth_pdata *pdata = dev_get_plat(dev);
> +       struct xgmac_regs *regs = xgmac_get_regs(pdata);
> +       struct calxeda_eth_dev *priv = dev_get_priv(dev);
> +       u32 value;
>
> -       if (xgmac_reset(dev) < 0)
> -               return -1;
> +       if (xgmac_reset(regs) < 0)
> +               return -ETIMEDOUT;
>
>         /* set the hardware MAC address */
> -       xgmac_hwmacaddr(dev);
> +       xgmac_hwmacaddr(pdata);
>
>         /* set the AXI bus modes */
>         value = XGMAC_DMA_BUSMODE_ATDS |
> @@ -401,8 +413,8 @@ static int xgmac_init(struct eth_device *dev, struct bd_info * bis)
>         writel(value, &regs->flow_control);
>
>         /* Initialize the descriptor chains */
> -       init_rx_desc(priv);
> -       init_tx_desc(priv);
> +       init_rx_desc(pdata, priv);
> +       init_tx_desc(pdata, priv);
>
>         /* must set to 0, or when started up will cause issues */
>         priv->tx_currdesc = 0;
> @@ -425,10 +437,11 @@ static int xgmac_init(struct eth_device *dev, struct bd_info * bis)
>         return 0;
>  }
>
> -static int xgmac_tx(struct eth_device *dev, void *packet, int length)
> +static int xgmac_tx(struct udevice *dev, void *packet, int length)
>  {
> -       struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
> -       struct calxeda_eth_dev *priv = dev->priv;
> +       struct calxeda_eth_dev *priv = dev_get_priv(dev);
> +       struct eth_pdata *pdata = dev_get_plat(dev);
> +       struct xgmac_regs *regs = xgmac_get_regs(pdata);
>         u32 currdesc = priv->tx_currdesc;
>         struct xgmac_dma_desc *txdesc = &priv->tx_chain[currdesc];
>         int timeout;
> @@ -453,35 +466,45 @@ static int xgmac_tx(struct eth_device *dev, void *packet, int length)
>         return 0;
>  }
>
> -static int xgmac_rx(struct eth_device *dev)
> +static int xgmac_rx(struct udevice *dev, int flags, uchar **packetp)
>  {
> -       struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
> -       struct calxeda_eth_dev *priv = dev->priv;
> +       struct calxeda_eth_dev *priv = dev_get_priv(dev);
>         u32 currdesc = priv->rx_currdesc;
>         struct xgmac_dma_desc *rxdesc = &priv->rx_chain[currdesc];
>         int length = 0;
>
>         /* check if the host has the desc */
>         if (desc_get_owner(rxdesc))
> -               return -1; /* something bad happened */
> +               return -EAGAIN; /* the MAC is still chewing on it */
>
>         length = desc_get_rx_frame_len(rxdesc);
> +       *packetp = desc_get_buf_addr(rxdesc);
>
> -       net_process_received_packet(desc_get_buf_addr(rxdesc), length);
> +       priv->rx_currdesc = (currdesc + 1) & (RX_NUM_DESC - 1);
> +
> +       return length;
> +}
> +
> +static int xgmac_free_pkt(struct udevice *dev, uchar *packet, int length)
> +{
> +       struct eth_pdata *pdata = dev_get_plat(dev);
> +       struct xgmac_regs *regs = xgmac_get_regs(pdata);
> +       struct calxeda_eth_dev *priv = dev_get_priv(dev);
> +       u32 rxdesc = ((char *)packet - priv->rxbuffer) / ETH_BUF_SZ;
> +       struct xgmac_dma_desc *p = &priv->rx_chain[rxdesc];
>
>         /* set descriptor back to owned by XGMAC */
> -       desc_set_rx_owner(rxdesc);
> +       desc_set_rx_owner(p);
>         writel(1, &regs->rxpoll);
>
> -       priv->rx_currdesc = (currdesc + 1) & (RX_NUM_DESC - 1);
> -
> -       return length;
> +       return 0;
>  }
>
> -static void xgmac_halt(struct eth_device *dev)
> +static void xgmac_eth_stop(struct udevice *dev)
>  {
> -       struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
> -       struct calxeda_eth_dev *priv = dev->priv;
> +       struct calxeda_eth_dev *priv = dev_get_priv(dev);
> +       struct eth_pdata *pdata = dev_get_plat(dev);
> +       struct xgmac_regs *regs = xgmac_get_regs(pdata);
>         int value;
>
>         /* Disable TX/RX */
> @@ -499,47 +522,88 @@ static void xgmac_halt(struct eth_device *dev)
>         priv->rx_currdesc = 0;
>  }
>
> -int calxedaxgmac_initialize(u32 id, ulong base_addr)
> +/*
> + * Changing the MAC address is not a good idea, as the fabric would
> + * need to know about this as well (it does not learn MAC addresses).
> + */
> +static int xgmac_eth_write_hwaddr(struct udevice *dev)
> +{
> +       return -ENOSYS;
> +}
> +
> +static int xgmac_eth_read_rom_hwaddr(struct udevice *dev)
>  {
> -       struct eth_device *dev;
> -       struct calxeda_eth_dev *priv;
> -       struct xgmac_regs *regs;
> +       struct eth_pdata *pdata = dev_get_plat(dev);
> +       struct xgmac_regs *regs = xgmac_get_regs(pdata);
>         u32 macaddr[2];
>
> -       regs = (struct xgmac_regs *)base_addr;
> +       /* The MAC address is already configured, so read it from registers. */
> +       macaddr[1] = readl(&regs->macaddr[0].hi);
> +       macaddr[0] = readl(&regs->macaddr[0].lo);
> +       memcpy(pdata->enetaddr, macaddr, ARP_HLEN);
>
> -       /* check hardware version */
> -       if (readl(&regs->version) != 0x1012)
> -               return -1;
> +       return 0;
> +}
>
> -       dev = malloc(sizeof(*dev));
> -       if (!dev)
> -               return 0;
> -       memset(dev, 0, sizeof(*dev));
> +static int xgmac_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct eth_pdata *pdata = dev_get_plat(dev);
> +       struct calxeda_eth_dev *priv;
>
>         /* Structure must be aligned, because it contains the descriptors */
>         priv = memalign(32, sizeof(*priv));
> -       if (!priv) {
> -               free(dev);
> -               return 0;
> +       if (!priv)
> +               return -ENOMEM;
> +       dev_set_priv(dev, priv);
> +
> +       pdata->iobase = devfdt_get_addr(dev);
> +       if (pdata->iobase == FDT_ADDR_T_NONE) {
> +               printf("%s: Cannot find XGMAC base address\n", __func__);
> +               return -EINVAL;
> +       }
> +       if (pdata->iobase >= (1ULL << 32)) {
> +               printf("%s: MMIO base address cannot be above 4GB\n", __func__);
> +               return -EINVAL;
>         }
>
> -       dev->iobase = (int)base_addr;
> -       dev->priv = priv;
> -       priv->dev = dev;
> -       sprintf(dev->name, "xgmac%d", id);
> +       return 0;
> +}
>
> -       /* The MAC address is already configured, so read it from registers. */
> -       macaddr[1] = readl(&regs->macaddr[0].hi);
> -       macaddr[0] = readl(&regs->macaddr[0].lo);
> -       memcpy(dev->enetaddr, macaddr, 6);
> +static int xgmac_eth_probe(struct udevice *dev)
> +{
> +       struct eth_pdata *pdata = dev_get_plat(dev);
> +       struct xgmac_regs *regs = xgmac_get_regs(pdata);
>
> -       dev->init = xgmac_init;
> -       dev->send = xgmac_tx;
> -       dev->recv = xgmac_rx;
> -       dev->halt = xgmac_halt;
> +       /* check hardware version */
> +       if (readl(&regs->version) != 0x1012)
> +               return -ENODEV;
>
> -       eth_register(dev);
> +       xgmac_eth_read_rom_hwaddr(dev);
>
> -       return 1;
> +       return 0;
>  }
> +
> +static const struct eth_ops xgmac_eth_ops = {
> +       .start          = xgmac_eth_start,
> +       .send           = xgmac_tx,
> +       .recv           = xgmac_rx,
> +       .free_pkt       = xgmac_free_pkt,
> +       .stop           = xgmac_eth_stop,
> +       .write_hwaddr   = xgmac_eth_write_hwaddr,
> +       .read_rom_hwaddr = xgmac_eth_read_rom_hwaddr,
> +};
> +
> +static const struct udevice_id xgmac_eth_ids[] = {
> +       { .compatible = "calxeda,hb-xgmac" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(eth_xgmac) = {
> +       .name           = "eth_xgmac",
> +       .id             = UCLASS_ETH,
> +       .of_match       = xgmac_eth_ids,
> +       .of_to_plat     = xgmac_ofdata_to_platdata,
> +       .probe          = xgmac_eth_probe,
> +       .ops            = &xgmac_eth_ops,
> +       .plat_auto      = sizeof(struct eth_pdata),
> +};
> diff --git a/include/configs/highbank.h b/include/configs/highbank.h
> index 7f37c81fc9f..fbd26ddd0fc 100644
> --- a/include/configs/highbank.h
> +++ b/include/configs/highbank.h
> @@ -27,8 +27,6 @@
>  #define CONFIG_SYS_SCSI_MAX_DEVICE     (CONFIG_SYS_SCSI_MAX_SCSI_ID * \
>                                         CONFIG_SYS_SCSI_MAX_LUN)
>
> -#define CONFIG_CALXEDA_XGMAC
> -
>  #define CONFIG_BOOT_RETRY_TIME         -1
>  #define CONFIG_RESET_TO_RETRY
>
> diff --git a/include/netdev.h b/include/netdev.h
> index 0ad9f8dc3a5..b960c421063 100644
> --- a/include/netdev.h
> +++ b/include/netdev.h
> @@ -33,7 +33,6 @@ int at91emac_register(struct bd_info *bis, unsigned long iobase);
>  int ax88180_initialize(struct bd_info *bis);
>  int bcm_sf2_eth_register(struct bd_info *bis, u8 dev_num);
>  int bfin_EMAC_initialize(struct bd_info *bis);
> -int calxedaxgmac_initialize(u32 id, ulong base_addr);
>  int cs8900_initialize(u8 dev_num, int base_addr);
>  int dc21x4x_initialize(struct bd_info *bis);
>  int designware_initialize(ulong base_addr, u32 interface);
> diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
> index 39e6416afc0..25d25dcc9e9 100644
> --- a/scripts/config_whitelist.txt
> +++ b/scripts/config_whitelist.txt
> @@ -149,7 +149,6 @@ CONFIG_BTB
>  CONFIG_BUFNO_AUTO_INCR_BIT
>  CONFIG_BUILD_ENVCRC
>  CONFIG_BUS_WIDTH
> -CONFIG_CALXEDA_XGMAC
>  CONFIG_CDP_APPLIANCE_VLAN_TYPE
>  CONFIG_CDP_CAPABILITIES
>  CONFIG_CDP_DEVICE_ID
> --
> 2.17.5
>

Nicely done. Thanks.
Reviewed-by: Ramon Fried <rfried.dev at gmail.com>


More information about the U-Boot mailing list