summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--board/highbank/highbank.c13
-rw-r--r--configs/highbank_defconfig1
-rw-r--r--drivers/net/Kconfig7
-rw-r--r--drivers/net/calxedaxgmac.c192
-rw-r--r--include/configs/highbank.h2
-rw-r--r--include/netdev.h1
-rw-r--r--scripts/config_whitelist.txt1
8 files changed, 137 insertions, 81 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 358642669c..e9f72b155c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -719,6 +719,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 2e2300a307..0667a48965 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 773ed7a00b..c3352b827d 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 72822eaec4..382639044b 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -180,6 +180,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 8b2ee49b44..b98d709117 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 7f37c81fc9..fbd26ddd0f 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 0ad9f8dc3a..b960c42106 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 b24fa36da0..a2fcafd2e6 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