net: mvgbe: convert to DM

Add driver model support to the mvgbe driver. As a temporary measure
both DM and non-DM uses are supported. Once all the users have been
converted the non-DM support can be dropped.

Signed-off-by: Chris Packham <judge.packham@gmail.com>
Tested-by: Michael Walle <michael@walle.cc>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
This commit is contained in:
Chris Packham 2018-07-09 21:34:00 +12:00 committed by Joe Hershberger
parent e9bf75c9d3
commit fb73107698
3 changed files with 279 additions and 51 deletions

View file

@ -181,6 +181,7 @@ config FTMAC100
config MVGBE
bool "Marvell Orion5x/Kirkwood network interface support"
depends on KIRKWOOD || ORION5X
select PHYLIB if DM_ETH
help
This driver supports the network interface units in the
Marvell Orion5x and Kirkwood SoCs

View file

@ -12,6 +12,7 @@
*/
#include <common.h>
#include <dm.h>
#include <net.h>
#include <malloc.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,
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 mvgbe_device *dmvgbe = to_mvgbe(dev);
#endif
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,
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 mvgbe_device *dmvgbe = to_mvgbe(dev);
#endif
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;
}
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;
#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
!defined(CONFIG_PHYLIB) && \
!defined(CONFIG_DM_ETH) && \
defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
int i;
#endif
@ -436,7 +447,7 @@ static int __mvgbe_init(struct mvgbe_device *dmvgbe)
set_dram_access(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. */
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)) && \
!defined(CONFIG_PHYLIB) && \
!defined(CONFIG_DM_ETH) && \
defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
/* Wait up to 5s for the link status */
for (i = 0; i < 5; i++) {
u16 phyadr;
miiphy_read(dmvgbe->dev.name, MV_PHY_ADR_REQUEST,
miiphy_read(name, MV_PHY_ADR_REQUEST,
MV_PHY_ADR_REQUEST, &phyadr);
/* Return if we get link up */
if (miiphy_link(dmvgbe->dev.name, phyadr))
if (miiphy_link(name, phyadr))
return 0;
udelay(1000000);
}
printf("No link on %s\n", dmvgbe->dev.name);
printf("No link on %s\n", name);
return -1;
#endif
return 0;
}
#ifndef CONFIG_DM_ETH
static int mvgbe_init(struct eth_device *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)
{
@ -524,6 +538,7 @@ static void __mvgbe_halt(struct mvgbe_device *dmvgbe)
MVGBE_REG_WR(regs->peim, 0);
}
#ifndef CONFIG_DM_ETH
static int mvgbe_halt(struct eth_device *dev)
{
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
@ -532,7 +547,18 @@ static int mvgbe_halt(struct eth_device *dev)
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)
{
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);
return 0;
}
#endif
static int __mvgbe_send(struct mvgbe_device *dmvgbe, void *dataptr,
int datasize)
@ -597,12 +624,14 @@ static int __mvgbe_send(struct mvgbe_device *dmvgbe, void *dataptr,
return 0;
}
#ifndef CONFIG_DM_ETH
static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize)
{
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
return __mvgbe_send(dmvgbe, dataptr, datasize);
}
#endif
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;
}
#ifndef CONFIG_DM_ETH
static int mvgbe_recv(struct eth_device *dev)
{
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
@ -691,8 +721,41 @@ static int mvgbe_recv(struct eth_device *dev)
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)
{
struct mii_dev *bus;
@ -715,27 +778,53 @@ int mvgbe_phylib_init(struct eth_device *dev, int phyid)
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;
}
phy_config(phydev);
phy_startup(phydev);
return 0;
}
#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)
{
struct mvgbe_device *dmvgbe;
struct eth_device *dev;
int devnum;
int ret;
u8 used_ports[MAX_MVGBE_DEVS] = CONFIG_MVGBE_PORTS;
for (devnum = 0; devnum < MAX_MVGBE_DEVS; devnum++) {
@ -744,45 +833,16 @@ int mvgbe_initialize(bd_t *bis)
continue;
dmvgbe = malloc(sizeof(struct mvgbe_device));
if (!dmvgbe)
goto error1;
return -ENOMEM;
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",
__func__);
return -1;
free(dmvgbe);
return ret;
}
dev = &dmvgbe->dev;
@ -834,3 +894,154 @@ error1:
}
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 */

View file

@ -30,7 +30,9 @@
#define RXUQ 0 /* Used Rx queue */
#define TXUQ 0 /* Used Rx queue */
#ifndef CONFIG_DM_ETH
#define to_mvgbe(_d) container_of(_d, struct mvgbe_device, dev)
#endif
#define MVGBE_REG_WR(adr, val) writel(val, &adr)
#define MVGBE_REG_RD(adr) readl(&adr)
#define MVGBE_REG_BITS_RESET(adr, val) writel(readl(&adr) & ~(val), &adr)
@ -479,13 +481,27 @@ struct mvgbe_txdesc {
/* port device data struct */
struct mvgbe_device {
#ifndef CONFIG_DM_ETH
struct eth_device dev;
#endif
struct mvgbe_registers *regs;
struct mvgbe_txdesc *p_txdesc;
struct mvgbe_rxdesc *p_rxdesc;
struct mvgbe_rxdesc *p_rxdesc_curr;
u8 *p_rxbuf;
u8 *p_aligned_txbuf;
#ifdef CONFIG_DM_ETH
phy_interface_t phy_interface;
unsigned int link;
unsigned int duplex;
unsigned int speed;
int init;
int phyaddr;
struct phy_device *phydev;
struct mii_dev *bus;
#endif
};
#endif /* __MVGBE_H__ */