|
@@ -12,6 +12,7 @@
|
|
*/
|
|
*/
|
|
|
|
|
|
#include <common.h>
|
|
#include <common.h>
|
|
|
|
+#include <dm.h>
|
|
#include <net.h>
|
|
#include <net.h>
|
|
#include <malloc.h>
|
|
#include <malloc.h>
|
|
#include <miiphy.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,
|
|
static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad,
|
|
int reg_ofs)
|
|
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 eth_device *dev = eth_get_dev_by_name(bus->name);
|
|
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
|
|
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
|
|
|
|
+#endif
|
|
|
|
|
|
return __mvgbe_mdio_read(dmvgbe, phy_adr, devad, reg_ofs);
|
|
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,
|
|
static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad,
|
|
int reg_ofs, u16 data)
|
|
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 eth_device *dev = eth_get_dev_by_name(bus->name);
|
|
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
|
|
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
|
|
|
|
+#endif
|
|
|
|
|
|
return __mvgbe_mdio_write(dmvgbe, phy_adr, devad, reg_ofs, data);
|
|
return __mvgbe_mdio_write(dmvgbe, phy_adr, devad, reg_ofs, data);
|
|
}
|
|
}
|
|
@@ -415,11 +424,13 @@ static void mvgbe_init_rx_desc_ring(struct mvgbe_device *dmvgbe)
|
|
dmvgbe->p_rxdesc_curr = dmvgbe->p_rxdesc;
|
|
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,
|
|
|
|
+ const char *name)
|
|
{
|
|
{
|
|
struct mvgbe_registers *regs = dmvgbe->regs;
|
|
struct mvgbe_registers *regs = dmvgbe->regs;
|
|
#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
|
|
#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
|
|
!defined(CONFIG_PHYLIB) && \
|
|
!defined(CONFIG_PHYLIB) && \
|
|
|
|
+ !defined(CONFIG_DM_ETH) && \
|
|
defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
|
|
defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
|
|
int i;
|
|
int i;
|
|
#endif
|
|
#endif
|
|
@@ -436,7 +447,7 @@ static int __mvgbe_init(struct mvgbe_device *dmvgbe)
|
|
|
|
|
|
set_dram_access(regs);
|
|
set_dram_access(regs);
|
|
port_init_mac_tables(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. */
|
|
/* Assign port configuration and command. */
|
|
MVGBE_REG_WR(regs->pxc, PRT_CFG_VAL);
|
|
MVGBE_REG_WR(regs->pxc, PRT_CFG_VAL);
|
|
@@ -473,31 +484,34 @@ static int __mvgbe_init(struct mvgbe_device *dmvgbe)
|
|
|
|
|
|
#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
|
|
#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
|
|
!defined(CONFIG_PHYLIB) && \
|
|
!defined(CONFIG_PHYLIB) && \
|
|
|
|
+ !defined(CONFIG_DM_ETH) && \
|
|
defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
|
|
defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
|
|
/* Wait up to 5s for the link status */
|
|
/* Wait up to 5s for the link status */
|
|
for (i = 0; i < 5; i++) {
|
|
for (i = 0; i < 5; i++) {
|
|
u16 phyadr;
|
|
u16 phyadr;
|
|
|
|
|
|
- miiphy_read(dmvgbe->dev.name, MV_PHY_ADR_REQUEST,
|
|
|
|
|
|
+ miiphy_read(name, MV_PHY_ADR_REQUEST,
|
|
MV_PHY_ADR_REQUEST, &phyadr);
|
|
MV_PHY_ADR_REQUEST, &phyadr);
|
|
/* Return if we get link up */
|
|
/* Return if we get link up */
|
|
- if (miiphy_link(dmvgbe->dev.name, phyadr))
|
|
|
|
|
|
+ if (miiphy_link(name, phyadr))
|
|
return 0;
|
|
return 0;
|
|
udelay(1000000);
|
|
udelay(1000000);
|
|
}
|
|
}
|
|
|
|
|
|
- printf("No link on %s\n", dmvgbe->dev.name);
|
|
|
|
|
|
+ printf("No link on %s\n", name);
|
|
return -1;
|
|
return -1;
|
|
#endif
|
|
#endif
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifndef CONFIG_DM_ETH
|
|
static int mvgbe_init(struct eth_device *dev)
|
|
static int mvgbe_init(struct eth_device *dev)
|
|
{
|
|
{
|
|
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
|
|
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
|
|
|
|
|
|
- return __mvgbe_init(dmvgbe);
|
|
|
|
|
|
+ return __mvgbe_init(dmvgbe, dmvgbe->dev.enetaddr, dmvgbe->dev.name);
|
|
}
|
|
}
|
|
|
|
+#endif
|
|
|
|
|
|
static void __mvgbe_halt(struct mvgbe_device *dmvgbe)
|
|
static void __mvgbe_halt(struct mvgbe_device *dmvgbe)
|
|
{
|
|
{
|
|
@@ -524,6 +538,7 @@ static void __mvgbe_halt(struct mvgbe_device *dmvgbe)
|
|
MVGBE_REG_WR(regs->peim, 0);
|
|
MVGBE_REG_WR(regs->peim, 0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifndef CONFIG_DM_ETH
|
|
static int mvgbe_halt(struct eth_device *dev)
|
|
static int mvgbe_halt(struct eth_device *dev)
|
|
{
|
|
{
|
|
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
|
|
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
|
|
@@ -532,7 +547,18 @@ static int mvgbe_halt(struct eth_device *dev)
|
|
|
|
|
|
return 0;
|
|
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)
|
|
static int mvgbe_write_hwaddr(struct eth_device *dev)
|
|
{
|
|
{
|
|
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
|
|
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
|
|
@@ -541,6 +567,7 @@ static int mvgbe_write_hwaddr(struct eth_device *dev)
|
|
port_uc_addr_set(dmvgbe, dmvgbe->dev.enetaddr);
|
|
port_uc_addr_set(dmvgbe, dmvgbe->dev.enetaddr);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+#endif
|
|
|
|
|
|
static int __mvgbe_send(struct mvgbe_device *dmvgbe, void *dataptr,
|
|
static int __mvgbe_send(struct mvgbe_device *dmvgbe, void *dataptr,
|
|
int datasize)
|
|
int datasize)
|
|
@@ -597,12 +624,14 @@ static int __mvgbe_send(struct mvgbe_device *dmvgbe, void *dataptr,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifndef CONFIG_DM_ETH
|
|
static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize)
|
|
static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize)
|
|
{
|
|
{
|
|
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
|
|
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
|
|
|
|
|
|
return __mvgbe_send(dmvgbe, dataptr, datasize);
|
|
return __mvgbe_send(dmvgbe, dataptr, datasize);
|
|
}
|
|
}
|
|
|
|
+#endif
|
|
|
|
|
|
static int __mvgbe_recv(struct mvgbe_device *dmvgbe, uchar **packetp)
|
|
static int __mvgbe_recv(struct mvgbe_device *dmvgbe, uchar **packetp)
|
|
{
|
|
{
|
|
@@ -677,6 +706,7 @@ static int __mvgbe_recv(struct mvgbe_device *dmvgbe, uchar **packetp)
|
|
return rx_bytes;
|
|
return rx_bytes;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifndef CONFIG_DM_ETH
|
|
static int mvgbe_recv(struct eth_device *dev)
|
|
static int mvgbe_recv(struct eth_device *dev)
|
|
{
|
|
{
|
|
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
|
|
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
|
|
@@ -691,8 +721,41 @@ static int mvgbe_recv(struct eth_device *dev)
|
|
|
|
|
|
return 0;
|
|
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)
|
|
int mvgbe_phylib_init(struct eth_device *dev, int phyid)
|
|
{
|
|
{
|
|
struct mii_dev *bus;
|
|
struct mii_dev *bus;
|
|
@@ -715,27 +778,53 @@ int mvgbe_phylib_init(struct eth_device *dev, int phyid)
|
|
return -ENOMEM;
|
|
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;
|
|
return -ENODEV;
|
|
- }
|
|
|
|
-
|
|
|
|
- phy_config(phydev);
|
|
|
|
- phy_startup(phydev);
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
#endif
|
|
#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)
|
|
int mvgbe_initialize(bd_t *bis)
|
|
{
|
|
{
|
|
struct mvgbe_device *dmvgbe;
|
|
struct mvgbe_device *dmvgbe;
|
|
struct eth_device *dev;
|
|
struct eth_device *dev;
|
|
int devnum;
|
|
int devnum;
|
|
|
|
+ int ret;
|
|
u8 used_ports[MAX_MVGBE_DEVS] = CONFIG_MVGBE_PORTS;
|
|
u8 used_ports[MAX_MVGBE_DEVS] = CONFIG_MVGBE_PORTS;
|
|
|
|
|
|
for (devnum = 0; devnum < MAX_MVGBE_DEVS; devnum++) {
|
|
for (devnum = 0; devnum < MAX_MVGBE_DEVS; devnum++) {
|
|
@@ -744,45 +833,16 @@ int mvgbe_initialize(bd_t *bis)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
dmvgbe = malloc(sizeof(struct mvgbe_device));
|
|
dmvgbe = malloc(sizeof(struct mvgbe_device));
|
|
-
|
|
|
|
if (!dmvgbe)
|
|
if (!dmvgbe)
|
|
- goto error1;
|
|
|
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
memset(dmvgbe, 0, sizeof(struct mvgbe_device));
|
|
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",
|
|
printf("Err.. %s Failed to allocate memory\n",
|
|
__func__);
|
|
__func__);
|
|
- return -1;
|
|
|
|
|
|
+ free(dmvgbe);
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
dev = &dmvgbe->dev;
|
|
dev = &dmvgbe->dev;
|
|
@@ -834,3 +894,154 @@ error1:
|
|
}
|
|
}
|
|
return 0;
|
|
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, dev->name);
|
|
|
|
+ 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 */
|