[PATCH v3 09/12] driver: net: fm: add DM ETH support

Madalin Bucur madalin.bucur at oss.nxp.com
Thu Apr 30 07:55:09 CEST 2020


Probe the FMan MACs based on the device tree while
retaining the legacy code/functionality.
One notable change introduced here is that, for DM_ETH,
the name of the interfaces is corrected to the fmX-macY
format, that avoids the referral to the MAC block names,
which were incorrect for FMan v3 devices (i.e. DTSEC,
TGEC) and had weird formatting (i.e. FM1 at DTSEC6, FM1 at TGEC1).
The legacy code is left unchanged in this respect.

Signed-off-by: Madalin Bucur <madalin.bucur at oss.nxp.com>
---
 arch/arm/cpu/armv8/fsl-layerscape/cpu.c   |   2 +
 board/freescale/ls1043ardb/ls1043ardb.c   |   2 +
 board/freescale/ls1046afrwy/ls1046afrwy.c |   2 +
 board/freescale/ls1046aqds/ls1046aqds.c   |   2 +
 board/freescale/ls1046ardb/ls1046ardb.c   |   2 +
 drivers/net/fm/eth.c                      | 351 +++++++++++++++++++++++++++++-
 drivers/net/fm/fm.c                       |  80 +++++++
 drivers/net/fm/fm.h                       |  23 ++
 drivers/net/fm/init.c                     |   2 +
 drivers/net/fm/memac.c                    |   1 +
 include/fsl_mdio.h                        |   1 +
 11 files changed, 458 insertions(+), 10 deletions(-)

diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index b443894..e0f8a50 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -1156,8 +1156,10 @@ int arch_early_init_r(void)
 	fsl_rgmii_init();
 #endif
 #ifdef CONFIG_FMAN_ENET
+#ifndef CONFIG_DM_ETH
 	fman_enet_init();
 #endif
+#endif
 #ifdef CONFIG_SYS_DPAA_QBMAN
 	setup_qbman_portals();
 #endif
diff --git a/board/freescale/ls1043ardb/ls1043ardb.c b/board/freescale/ls1043ardb/ls1043ardb.c
index 9bc78d6..26a1929 100644
--- a/board/freescale/ls1043ardb/ls1043ardb.c
+++ b/board/freescale/ls1043ardb/ls1043ardb.c
@@ -285,8 +285,10 @@ int ft_board_setup(void *blob, bd_t *bd)
 	ft_cpu_setup(blob, bd);
 
 #ifdef CONFIG_SYS_DPAA_FMAN
+#ifndef CONFIG_DM_ETH
 	fdt_fixup_fman_ethernet(blob);
 #endif
+#endif
 
 	fdt_fixup_icid(blob);
 
diff --git a/board/freescale/ls1046afrwy/ls1046afrwy.c b/board/freescale/ls1046afrwy/ls1046afrwy.c
index 8c0abb6..71ace19 100644
--- a/board/freescale/ls1046afrwy/ls1046afrwy.c
+++ b/board/freescale/ls1046afrwy/ls1046afrwy.c
@@ -232,8 +232,10 @@ int ft_board_setup(void *blob, bd_t *bd)
 	ft_cpu_setup(blob, bd);
 
 #ifdef CONFIG_SYS_DPAA_FMAN
+#ifndef CONFIG_DM_ETH
 	fdt_fixup_fman_ethernet(blob);
 #endif
+#endif
 
 	fdt_fixup_icid(blob);
 
diff --git a/board/freescale/ls1046aqds/ls1046aqds.c b/board/freescale/ls1046aqds/ls1046aqds.c
index cabd7ee..e6648e9 100644
--- a/board/freescale/ls1046aqds/ls1046aqds.c
+++ b/board/freescale/ls1046aqds/ls1046aqds.c
@@ -462,7 +462,9 @@ int ft_board_setup(void *blob, bd_t *bd)
 	ft_cpu_setup(blob, bd);
 
 #ifdef CONFIG_SYS_DPAA_FMAN
+#ifndef CONFIG_DM_ETH
 	fdt_fixup_fman_ethernet(blob);
+#endif
 	fdt_fixup_board_enet(blob);
 #endif
 
diff --git a/board/freescale/ls1046ardb/ls1046ardb.c b/board/freescale/ls1046ardb/ls1046ardb.c
index cc6bd88..5308cb2 100644
--- a/board/freescale/ls1046ardb/ls1046ardb.c
+++ b/board/freescale/ls1046ardb/ls1046ardb.c
@@ -172,8 +172,10 @@ int ft_board_setup(void *blob, bd_t *bd)
 	ft_cpu_setup(blob, bd);
 
 #ifdef CONFIG_SYS_DPAA_FMAN
+#ifndef CONFIG_DM_ETH
 	fdt_fixup_fman_ethernet(blob);
 #endif
+#endif
 
 	fdt_fixup_icid(blob);
 
diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c
index 7d13736..371c5d2 100644
--- a/drivers/net/fm/eth.c
+++ b/drivers/net/fm/eth.c
@@ -1,10 +1,17 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2009-2012 Freescale Semiconductor, Inc.
+ * Copyright 2020 NXP
  *	Dave Liu <daveliu at freescale.com>
  */
 #include <common.h>
 #include <asm/io.h>
+#ifdef CONFIG_DM_ETH
+#include <dm.h>
+#include <dm/ofnode.h>
+#include <linux/compat.h>
+#include <phy_interface.h>
+#endif
 #include <malloc.h>
 #include <net.h>
 #include <hwconfig.h>
@@ -18,8 +25,10 @@
 
 #include "fm.h"
 
+#ifndef CONFIG_DM_ETH
 static struct eth_device *devlist[NUM_FM_PORTS];
 static int num_controllers;
+#endif
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) && !defined(BITBANGMII)
 
@@ -37,10 +46,18 @@ static void dtsec_configure_serdes(struct fm_eth *priv)
 #ifdef CONFIG_SYS_FMAN_V3
 	u32 value;
 	struct mii_dev bus;
-	bus.priv = priv->mac->phyregs;
 	bool sgmii_2500 = (priv->enet_if ==
 			PHY_INTERFACE_MODE_SGMII_2500) ? true : false;
-	int i = 0;
+	int i = 0, j;
+
+#ifndef CONFIG_DM_ETH
+	bus.priv = priv->mac->phyregs;
+#else
+	bus.priv = priv->pcs_mdio;
+	bus.read = memac_mdio_read;
+	bus.write = memac_mdio_write;
+	bus.reset = memac_mdio_reset;
+#endif
 
 qsgmii_loop:
 	/* SGMII IF mode + AN enable only for 1G SGMII, not for 2.5G */
@@ -51,6 +68,10 @@ qsgmii_loop:
 	else
 		value = PHY_SGMII_IF_MODE_SGMII | PHY_SGMII_IF_MODE_AN;
 
+	for (j = 0; j <= 3; j++)
+		debug("dump PCS reg %#x: %#x\n", j,
+		      memac_mdio_read(&bus, i, MDIO_DEVAD_NONE, j));
+
 	memac_mdio_write(&bus, i, MDIO_DEVAD_NONE, 0x14, value);
 
 	/* Dev ability according to SGMII specification */
@@ -113,6 +134,7 @@ static void dtsec_init_phy(struct fm_eth *fm_eth)
 		dtsec_configure_serdes(fm_eth);
 }
 
+#ifndef CONFIG_DM_ETH
 #ifdef CONFIG_PHYLIB
 static int tgec_is_fibre(struct fm_eth *fm)
 {
@@ -123,6 +145,7 @@ static int tgec_is_fibre(struct fm_eth *fm)
 	return hwconfig_arg_cmp(phyopt, "xfi");
 }
 #endif
+#endif /* CONFIG_DM_ETH */
 #endif
 
 static u16 muram_readw(u16 *addr)
@@ -166,6 +189,8 @@ static void bmi_rx_port_disable(struct fm_bmi_rx_port *rx_port)
 	/* wait until the rx port is not busy */
 	while ((in_be32(&rx_port->fmbm_rst) & FMBM_RST_BSY) && timeout--)
 		;
+	if (!timeout)
+		printf("%s - timeout\n", __func__);
 }
 
 static void bmi_rx_port_init(struct fm_bmi_rx_port *rx_port)
@@ -194,6 +219,8 @@ static void bmi_tx_port_disable(struct fm_bmi_tx_port *tx_port)
 	/* wait until the tx port is not busy */
 	while ((in_be32(&tx_port->fmbm_tst) & FMBM_TST_BSY) && timeout--)
 		;
+	if (!timeout)
+		printf("%s - timeout\n", __func__);
 }
 
 static void bmi_tx_port_init(struct fm_bmi_tx_port *tx_port)
@@ -433,23 +460,39 @@ static void fmc_tx_port_graceful_stop_disable(struct fm_eth *fm_eth)
 	sync();
 }
 
+#ifndef CONFIG_DM_ETH
 static int fm_eth_open(struct eth_device *dev, bd_t *bd)
+#else
+static int fm_eth_open(struct udevice *dev)
+#endif
 {
-	struct fm_eth *fm_eth;
+#ifndef CONFIG_DM_ETH
+	struct fm_eth *fm_eth = dev->priv;
+#else
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct fm_eth *fm_eth = dev_get_priv(dev);
+#endif
+	unsigned char *enetaddr;
 	struct fsl_enet_mac *mac;
 #ifdef CONFIG_PHYLIB
 	int ret;
 #endif
 
-	fm_eth = (struct fm_eth *)dev->priv;
 	mac = fm_eth->mac;
 
+#ifndef CONFIG_DM_ETH
+	enetaddr = &dev->enetaddr[0];
+#else
+	enetaddr = pdata->enetaddr;
+#endif
+
 	/* setup the MAC address */
-	if (dev->enetaddr[0] & 0x01) {
-		printf("%s: MacAddress is multcast address\n",	__func__);
-		return 1;
+	if (enetaddr[0] & 0x01) {
+		printf("%s: MacAddress is multicast address\n",	__func__);
+		enetaddr[0] = 0;
+		enetaddr[5] = fm_eth->num;
 	}
-	mac->set_mac_addr(mac, dev->enetaddr);
+	mac->set_mac_addr(mac, enetaddr);
 
 	/* enable bmi Rx port */
 	setbits_be32(&fm_eth->rx_port->fmbm_rcfg, FMBM_RCFG_EN);
@@ -464,8 +507,12 @@ static int fm_eth_open(struct eth_device *dev, bd_t *bd)
 	if (fm_eth->phydev) {
 		ret = phy_startup(fm_eth->phydev);
 		if (ret) {
+#ifndef CONFIG_DM_ETH
 			printf("%s: Could not initialize\n",
 			       fm_eth->phydev->dev->name);
+#else
+			printf("%s: Could not initialize\n", dev->name);
+#endif
 			return ret;
 		}
 	} else {
@@ -479,6 +526,8 @@ static int fm_eth_open(struct eth_device *dev, bd_t *bd)
 
 	/* set the MAC-PHY mode */
 	mac->set_if_mode(mac, fm_eth->enet_if, fm_eth->phydev->speed);
+	debug("MAC IF mode %d, speed %d, link %d\n", fm_eth->enet_if,
+	      fm_eth->phydev->speed, fm_eth->phydev->link);
 
 	if (!fm_eth->phydev->link)
 		printf("%s: No link.\n", fm_eth->phydev->dev->name);
@@ -486,7 +535,11 @@ static int fm_eth_open(struct eth_device *dev, bd_t *bd)
 	return fm_eth->phydev->link ? 0 : -1;
 }
 
+#ifndef CONFIG_DM_ETH
 static void fm_eth_halt(struct eth_device *dev)
+#else
+static void fm_eth_halt(struct udevice *dev)
+#endif
 {
 	struct fm_eth *fm_eth;
 	struct fsl_enet_mac *mac;
@@ -509,7 +562,11 @@ static void fm_eth_halt(struct eth_device *dev)
 #endif
 }
 
+#ifndef CONFIG_DM_ETH
 static int fm_eth_send(struct eth_device *dev, void *buf, int len)
+#else
+static int fm_eth_send(struct udevice *dev, void *buf, int len)
+#endif
 {
 	struct fm_eth *fm_eth;
 	struct fm_port_global_pram *pram;
@@ -598,7 +655,11 @@ static struct fm_port_bd *fm_eth_free_one(struct fm_eth *fm_eth,
 	return rxbd;
 }
 
+#ifndef CONFIG_DM_ETH
 static int fm_eth_recv(struct eth_device *dev)
+#else
+static int fm_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+#endif
 {
 	struct fm_eth *fm_eth = (struct fm_eth *)dev->priv;
 	struct fm_port_bd *rxbd = fm_eth->cur_rxbd;
@@ -615,7 +676,12 @@ static int fm_eth_recv(struct eth_device *dev)
 			buf_lo = in_be32(&rxbd->buf_ptr_lo);
 			data = (u8 *)((ulong)(buf_hi << 16) << 16 | buf_lo);
 			len = muram_readw(&rxbd->len);
+#ifndef CONFIG_DM_ETH
 			net_process_received_packet(data, len);
+#else
+			*packetp = data;
+			return len;
+#endif
 		} else {
 			printf("%s: Rx error\n", dev->name);
 			ret = 0;
@@ -632,6 +698,18 @@ static int fm_eth_recv(struct eth_device *dev)
 	return ret;
 }
 
+#ifdef CONFIG_DM_ETH
+static int fm_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+	struct fm_eth *fm_eth = (struct fm_eth *)dev->priv;
+
+	fm_eth->cur_rxbd = fm_eth_free_one(fm_eth, fm_eth->cur_rxbd);
+
+	return 0;
+}
+#endif /* CONFIG_DM_ETH */
+
+#ifndef CONFIG_DM_ETH
 static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg)
 {
 	struct fsl_enet_mac *mac;
@@ -687,17 +765,71 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg)
 
 	return 0;
 }
+#else /* CONFIG_DM_ETH */
+static int fm_eth_init_mac(struct fm_eth *fm_eth, void *reg)
+{
+#ifndef CONFIG_SYS_FMAN_V3
+	void *mdio;
+#endif
+
+	fm_eth->mac = kzalloc(sizeof(*fm_eth->mac), GFP_KERNEL);
+	if (!fm_eth->mac)
+		return -ENOMEM;
+
+#ifndef CONFIG_SYS_FMAN_V3
+	mdio = fman_mdio(fm_eth->dev->parent, fm_eth->mac_type, fm_eth->num);
+	debug("MDIO %d @ %p\n", fm_eth->num, mdio);
+#endif
+
+	switch (fm_eth->mac_type) {
+#ifdef CONFIG_SYS_FMAN_V3
+	case FM_MEMAC:
+		init_memac(fm_eth->mac, reg, NULL, MAX_RXBUF_LEN);
+		break;
+#else
+	case FM_DTSEC:
+		init_dtsec(fm_eth->mac, reg, mdio, MAX_RXBUF_LEN);
+		break;
+	case FM_TGEC:
+		init_tgec(fm_eth->mac, reg, mdio, MAX_RXBUF_LEN);
+		break;
+#endif
+	}
+
+	return 0;
+}
+#endif /* CONFIG_DM_ETH */
 
 static int init_phy(struct fm_eth *fm_eth)
 {
 #ifdef CONFIG_PHYLIB
+	u32 supported = PHY_GBIT_FEATURES;
+#ifndef CONFIG_DM_ETH
 	struct phy_device *phydev = NULL;
-	u32 supported;
+#endif
+
+	if (fm_eth->type == FM_ETH_10G_E)
+		supported = PHY_10G_FEATURES;
+	if (fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII_2500)
+		supported |= SUPPORTED_2500baseX_Full;
 #endif
 
 	if (fm_eth->type == FM_ETH_1G_E)
 		dtsec_init_phy(fm_eth);
 
+#ifdef CONFIG_DM_ETH
+#ifdef CONFIG_PHYLIB
+#ifdef CONFIG_DM_MDIO
+	fm_eth->phydev = dm_eth_phy_connect(fm_eth->dev);
+	if (!fm_eth->phydev)
+		return -ENODEV;
+#endif
+	fm_eth->phydev->advertising &= supported;
+	fm_eth->phydev->supported &= supported;
+
+	phy_config(fm_eth->phydev);
+#endif
+#else /* CONFIG_DM_ETH */
 #ifdef CONFIG_PHYLIB
 	if (fm_eth->bus) {
 		phydev = phy_connect(fm_eth->bus, fm_eth->phyaddr, fm_eth->dev,
@@ -730,10 +862,11 @@ static int init_phy(struct fm_eth *fm_eth)
 
 	phy_config(phydev);
 #endif
-
+#endif /* CONFIG_DM_ETH */
 	return 0;
 }
 
+#ifndef CONFIG_DM_ETH
 int fm_eth_initialize(struct ccsr_fman *reg, struct fm_eth_info *info)
 {
 	struct eth_device *dev;
@@ -801,3 +934,201 @@ int fm_eth_initialize(struct ccsr_fman *reg, struct fm_eth_info *info)
 
 	return 0;
 }
+#else /* CONFIG_DM_ETH */
+#ifdef CONFIG_PHYLIB
+phy_interface_t fman_read_sys_if(struct udevice *dev)
+{
+	const char *if_str;
+
+	if_str = ofnode_read_string(dev->node, "phy-connection-type");
+	debug("MAC system interface mode %s\n", if_str);
+
+	return phy_get_interface_by_name(if_str);
+}
+#endif
+
+static int fm_eth_bind(struct udevice *dev)
+{
+	char mac_name[11];
+	u32 fm, num;
+
+	if (ofnode_read_u32(ofnode_get_parent(dev->node), "cell-index", &fm)) {
+		printf("FMan node property cell-index missing\n");
+		return -EINVAL;
+	}
+
+	if (dev && dev_read_u32(dev, "cell-index", &num)) {
+		printf("FMan MAC node property cell-index missing\n");
+		return -EINVAL;
+	}
+
+	sprintf(mac_name, "fm%d-mac%d", fm + 1, num + 1);
+	device_set_name(dev, mac_name);
+
+	debug("%s - binding %s\n", __func__, mac_name);
+
+	return 0;
+}
+
+static struct udevice *fm_get_internal_mdio(struct udevice *dev)
+{
+	struct ofnode_phandle_args phandle = {.node = ofnode_null()};
+	struct udevice *mdiodev;
+
+	if (dev_read_phandle_with_args(dev, "pcsphy-handle", NULL,
+				       0, 0, &phandle) ||
+	    !ofnode_valid(phandle.node)) {
+		if (dev_read_phandle_with_args(dev, "tbi-handle", NULL,
+					       0, 0, &phandle) ||
+		    !ofnode_valid(phandle.node)) {
+			printf("Issue reading pcsphy-handle/tbi-handle for MAC %s\n",
+			       dev->name);
+			return NULL;
+		}
+	}
+
+	if (uclass_get_device_by_ofnode(UCLASS_MDIO,
+					ofnode_get_parent(phandle.node),
+					&mdiodev)) {
+		printf("can't find MDIO bus for node %s\n",
+		       ofnode_get_name(ofnode_get_parent(phandle.node)));
+		return NULL;
+	}
+	debug("Found internal MDIO bus %p\n", mdiodev);
+
+	return mdiodev;
+}
+
+static int fm_eth_probe(struct udevice *dev)
+{
+	struct fm_eth *fm_eth = (struct fm_eth *)dev->priv;
+	struct ofnode_phandle_args args;
+	void *reg;
+	int ret, index;
+
+	debug("%s enter for dev %p fm_eth %p - %s\n", __func__, dev, fm_eth,
+	      (dev) ? dev->name : "-");
+
+	if (fm_eth->dev) {
+		printf("%s already probed, exit\n", (dev) ? dev->name : "-");
+		return 0;
+	}
+
+	fm_eth->dev = dev;
+	fm_eth->fm_index = fman_id(dev->parent);
+	reg = (void *)(uintptr_t)dev_read_addr(dev);
+	fm_eth->mac_type = dev_get_driver_data(dev);
+#ifdef CONFIG_PHYLIB
+	fm_eth->enet_if = fman_read_sys_if(dev);
+#else
+	fm_eth->enet_if = PHY_INTERFACE_MODE_SGMII;
+	printf("%s: warning - unable to determine interface type\n", __func__);
+#endif
+	switch (fm_eth->mac_type) {
+#ifndef CONFIG_SYS_FMAN_V3
+	case FM_TGEC:
+		fm_eth->type = FM_ETH_10G_E;
+		break;
+	case FM_DTSEC:
+#else
+	case FM_MEMAC:
+		/* default to 1G, 10G is indicated by port property in dts */
+#endif
+		fm_eth->type = FM_ETH_1G_E;
+		break;
+	}
+
+	if (dev_read_u32(dev, "cell-index", &fm_eth->num)) {
+		printf("FMan MAC node property cell-index missing\n");
+		return -EINVAL;
+	}
+
+	if (dev_read_phandle_with_args(dev, "fsl,fman-ports", NULL,
+				       0, 0, &args))
+		goto ports_ref_failure;
+	index = ofnode_read_u32_default(args.node, "cell-index", 0);
+	if (index <= 0)
+		goto ports_ref_failure;
+	fm_eth->rx_port = fman_port(dev->parent, index);
+
+	if (ofnode_read_bool(args.node, "fsl,fman-10g-port"))
+		fm_eth->type = FM_ETH_10G_E;
+
+	if (dev_read_phandle_with_args(dev, "fsl,fman-ports", NULL,
+				       0, 1, &args))
+		goto ports_ref_failure;
+	index = ofnode_read_u32_default(args.node, "cell-index", 0);
+	if (index <= 0)
+		goto ports_ref_failure;
+	fm_eth->tx_port = fman_port(dev->parent, index);
+
+	/* set the ethernet max receive length */
+	fm_eth->max_rx_len = MAX_RXBUF_LEN;
+
+	switch (fm_eth->enet_if) {
+	case PHY_INTERFACE_MODE_QSGMII:
+		/* all PCS blocks are accessed on one controller */
+		if (fm_eth->num != 0)
+			break;
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_SGMII_2500:
+		fm_eth->pcs_mdio = fm_get_internal_mdio(dev);
+		break;
+	default:
+		break;
+	}
+
+	/* init global mac structure */
+	ret = fm_eth_init_mac(fm_eth, reg);
+	if (ret)
+		return ret;
+
+	/* startup the FM im */
+	ret = fm_eth_startup(fm_eth);
+
+	if (!ret)
+		ret = init_phy(fm_eth);
+
+	return ret;
+
+ports_ref_failure:
+	printf("Issue reading fsl,fman-ports for MAC %s\n", dev->name);
+	return -ENOENT;
+}
+
+static int fm_eth_remove(struct udevice *dev)
+{
+	return 0;
+}
+
+static const struct eth_ops fm_eth_ops = {
+	.start = fm_eth_open,
+	.send = fm_eth_send,
+	.recv = fm_eth_recv,
+	.free_pkt = fm_eth_free_pkt,
+	.stop = fm_eth_halt,
+};
+
+static const struct udevice_id fm_eth_ids[] = {
+#ifdef CONFIG_SYS_FMAN_V3
+	{ .compatible = "fsl,fman-memac", .data = FM_MEMAC },
+#else
+	{ .compatible = "fsl,fman-dtsec", .data = FM_DTSEC },
+	{ .compatible = "fsl,fman-xgec", .data = FM_TGEC },
+#endif
+	{}
+};
+
+U_BOOT_DRIVER(eth_fman) = {
+	.name = "eth_fman",
+	.id = UCLASS_ETH,
+	.of_match = fm_eth_ids,
+	.bind = fm_eth_bind,
+	.probe = fm_eth_probe,
+	.remove = fm_eth_remove,
+	.ops = &fm_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct fm_eth),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+	.flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
+#endif /* CONFIG_DM_ETH */
diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c
index 7a081b9..8ab1816 100644
--- a/drivers/net/fm/fm.c
+++ b/drivers/net/fm/fm.c
@@ -9,6 +9,9 @@
 #include <asm/io.h>
 #include <linux/errno.h>
 #include <u-boot/crc.h>
+#ifdef CONFIG_DM_ETH
+#include <dm.h>
+#endif
 
 #include "fm.h"
 #include <fsl_qe.h>		/* For struct qe_firmware */
@@ -529,3 +532,80 @@ int fm_init_common(int index, struct ccsr_fman *reg)
 	return fm_init_bmi(index, &reg->fm_bmi_common);
 }
 #endif
+
+#ifdef CONFIG_DM_ETH
+struct fman_priv {
+	struct ccsr_fman *reg;
+	unsigned int fman_id;
+};
+
+static const struct udevice_id fman_ids[] = {
+	{ .compatible = "fsl,fman" },
+	{}
+};
+
+static int fman_probe(struct udevice *dev)
+{
+	struct fman_priv *priv = dev_get_priv(dev);
+
+	priv->reg = (struct ccsr_fman *)(uintptr_t)dev_read_addr(dev);
+
+	if (dev_read_u32(dev, "cell-index", &priv->fman_id)) {
+		printf("FMan node property cell-index missing\n");
+		return -EINVAL;
+	}
+
+	return fm_init_common(priv->fman_id, priv->reg);
+}
+
+static int fman_remove(struct udevice *dev)
+{
+	return 0;
+}
+
+int fman_id(struct udevice *dev)
+{
+	struct fman_priv *priv = dev_get_priv(dev);
+
+	return priv->fman_id;
+}
+
+void *fman_port(struct udevice *dev, int num)
+{
+	struct fman_priv *priv = dev_get_priv(dev);
+
+	return &priv->reg->port[num - 1].fm_bmi;
+}
+
+void *fman_mdio(struct udevice *dev, enum fm_mac_type type, int num)
+{
+	struct fman_priv *priv = dev_get_priv(dev);
+	void *res = NULL;
+
+	switch (type) {
+#ifdef CONFIG_SYS_FMAN_V3
+	case FM_MEMAC:
+		res = &priv->reg->memac[num].fm_memac_mdio;
+		break;
+#else
+	case FM_DTSEC:
+		res = &priv->reg->mac_1g[num].fm_mdio.miimcfg;
+		break;
+	case FM_TGEC:
+		res = &priv->reg->mac_10g[num].fm_10gec_mdio;
+		break;
+#endif
+	}
+	return res;
+}
+
+U_BOOT_DRIVER(fman) = {
+	.name = "fman",
+	.id = UCLASS_SIMPLE_BUS,
+	.of_match = fman_ids,
+	.probe = fman_probe,
+	.remove = fman_remove,
+	.priv_auto_alloc_size = sizeof(struct fman_priv),
+	.flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
+#endif /* CONFIG_DM_ETH */
diff --git a/drivers/net/fm/fm.h b/drivers/net/fm/fm.h
index e5deaf5..2379b3a 100644
--- a/drivers/net/fm/fm.h
+++ b/drivers/net/fm/fm.h
@@ -57,6 +57,18 @@ struct fm_port_bd {
 #define TxBD_READY		0x8000
 #define TxBD_LAST		BD_LAST
 
+#ifdef CONFIG_DM_ETH
+enum fm_mac_type {
+#ifdef CONFIG_SYS_FMAN_V3
+	FM_MEMAC,
+#else
+	FM_DTSEC,
+	FM_TGEC,
+#endif
+};
+#endif
+
+/* Fman ethernet private struct */
 /* Rx/Tx queue descriptor */
 struct fm_port_qd {
 	u16 gen;
@@ -101,6 +113,11 @@ int fm_eth_initialize(struct ccsr_fman *reg, struct fm_eth_info *info);
 phy_interface_t fman_port_enet_if(enum fm_port port);
 void fman_disable_port(enum fm_port port);
 void fman_enable_port(enum fm_port port);
+int fman_id(struct udevice *dev);
+void *fman_port(struct udevice *dev, int num);
+#ifdef CONFIG_DM_ETH
+void *fman_mdio(struct udevice *dev, enum fm_mac_type type, int num);
+#endif
 
 struct fsl_enet_mac {
 	void *base; /* MAC controller registers base address */
@@ -126,7 +143,13 @@ struct fm_eth {
 	struct mii_dev *bus;
 	struct phy_device *phydev;
 	int phyaddr;
+#ifndef CONFIG_DM_ETH
 	struct eth_device *dev;
+#else
+	enum fm_mac_type mac_type;
+	struct udevice *dev;
+	struct udevice *pcs_mdio;
+#endif
 	int max_rx_len;
 	struct fm_port_global_pram *rx_pram; /* Rx parameter table */
 	struct fm_port_global_pram *tx_pram; /* Tx parameter table */
diff --git a/drivers/net/fm/init.c b/drivers/net/fm/init.c
index f896e80..8669d21 100644
--- a/drivers/net/fm/init.c
+++ b/drivers/net/fm/init.c
@@ -15,6 +15,7 @@
 
 #include "fm.h"
 
+#ifndef CONFIG_DM_ETH
 struct fm_eth_info fm_info[] = {
 #if (CONFIG_SYS_NUM_FM1_DTSEC >= 1)
 	FM_DTSEC_INFO_INITIALIZER(1, 1),
@@ -380,3 +381,4 @@ int is_qsgmii_riser_card(struct mii_dev *bus, int phy_base_addr,
 
 	return 0;
 }
+#endif /* CONFIG_DM_ETH */
diff --git a/drivers/net/fm/memac.c b/drivers/net/fm/memac.c
index bed8f14..77ea083 100644
--- a/drivers/net/fm/memac.c
+++ b/drivers/net/fm/memac.c
@@ -137,6 +137,7 @@ static void memac_set_interface_mode(struct fsl_enet_mac *mac,
 void init_memac(struct fsl_enet_mac *mac, void *base,
 		void *phyregs, int max_rx_len)
 {
+	debug("%s: @ %p, mdio @ %p\n", __func__, base, phyregs);
 	mac->base = base;
 	mac->phyregs = phyregs;
 	mac->max_rx_len = max_rx_len;
diff --git a/include/fsl_mdio.h b/include/fsl_mdio.h
index b87346c..8857d50 100644
--- a/include/fsl_mdio.h
+++ b/include/fsl_mdio.h
@@ -53,6 +53,7 @@ int memac_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr,
 		int regnum, u16 value);
 int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
 		int regnum);
+int memac_mdio_reset(struct mii_dev *bus);
 
 struct fsl_pq_mdio_info {
 	struct tsec_mii_mng __iomem *regs;
-- 
2.1.0



More information about the U-Boot mailing list