On Mon, Apr 12, 2021 at 3:05 AM Andre Przywara <andre.przyw...@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.przyw...@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....@gmail.com>