[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, ®s->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], ®s->macaddr[0].hi);
> writel(macaddr[0], ®s->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, ®s->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, ®s->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(®s->macaddr[0].hi);
> + macaddr[0] = readl(®s->macaddr[0].lo);
> + memcpy(pdata->enetaddr, macaddr, ARP_HLEN);
>
> - /* check hardware version */
> - if (readl(®s->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(®s->macaddr[0].hi);
> - macaddr[0] = readl(®s->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(®s->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