All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jagan Teki <jteki@openedev.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v5 2/5] net: fec_mxc: Convert into driver model
Date: Thu,  6 Oct 2016 16:25:21 +0530	[thread overview]
Message-ID: <1475751324-14605-3-git-send-email-jteki@openedev.com> (raw)
In-Reply-To: <1475751324-14605-1-git-send-email-jteki@openedev.com>

From: Jagan Teki <jagan@amarulasolutions.com>

This patch add driver model support for fec_mxc driver.

Cc: Simon Glass <sjg@chromium.org>
Cc: Joe Hershberger <joe.hershberger@ni.com>
Cc: Peng Fan <peng.fan@nxp.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/net/fec_mxc.c | 314 ++++++++++++++++++++++++++++++++++++++++++--------
 drivers/net/fec_mxc.h |   4 +
 2 files changed, 271 insertions(+), 47 deletions(-)

diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 0838d58..c0ec976 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -9,6 +9,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <malloc.h>
 #include <memalign.h>
 #include <net.h>
@@ -368,11 +369,8 @@ static int fec_get_hwaddr(int dev_id, unsigned char *mac)
 	return !is_valid_ethaddr(mac);
 }
 
-static int fec_set_hwaddr(struct eth_device *dev)
+static int _fec_set_hwaddr(struct fec_priv *fec, uchar *mac)
 {
-	uchar *mac = dev->enetaddr;
-	struct fec_priv *fec = (struct fec_priv *)dev->priv;
-
 	writel(0, &fec->eth->iaddr1);
 	writel(0, &fec->eth->iaddr2);
 	writel(0, &fec->eth->gaddr1);
@@ -426,9 +424,8 @@ static void fec_reg_setup(struct fec_priv *fec)
  * Start the FEC engine
  * @param[in] dev Our device to handle
  */
-static int fec_open(struct eth_device *edev)
+static int fec_open(struct fec_priv *fec)
 {
-	struct fec_priv *fec = (struct fec_priv *)edev->priv;
 	int speed;
 	uint32_t addr, size;
 	int i;
@@ -534,14 +531,13 @@ static int fec_open(struct eth_device *edev)
 	return 0;
 }
 
-static int fec_init(struct eth_device *dev, bd_t* bd)
+static int _fec_init(struct fec_priv *fec, uchar *mac)
 {
-	struct fec_priv *fec = (struct fec_priv *)dev->priv;
 	uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop;
 	int i;
 
 	/* Initialize MAC address */
-	fec_set_hwaddr(dev);
+	_fec_set_hwaddr(fec, mac);
 
 	/*
 	 * Setup transmit descriptors, there are two in total.
@@ -587,7 +583,7 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
 	if (fec->xcv_type != SEVENWIRE)
 		miiphy_restart_aneg(dev);
 #endif
-	fec_open(dev);
+	fec_open(fec);
 	return 0;
 }
 
@@ -595,9 +591,8 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
  * Halt the FEC engine
  * @param[in] dev Our device to handle
  */
-static void fec_halt(struct eth_device *dev)
+static void _fec_halt(struct fec_priv *fec)
 {
-	struct fec_priv *fec = (struct fec_priv *)dev->priv;
 	int counter = 0xffff;
 
 	/*
@@ -637,7 +632,7 @@ static void fec_halt(struct eth_device *dev)
  * @param[in] length Data count in bytes
  * @return 0 on success
  */
-static int fec_send(struct eth_device *dev, void *packet, int length)
+static int _fec_send(struct fec_priv *fec, void *packet, int length)
 {
 	unsigned int status;
 	uint32_t size, end;
@@ -649,8 +644,6 @@ static int fec_send(struct eth_device *dev, void *packet, int length)
 	 * This routine transmits one frame.  This routine only accepts
 	 * 6-byte Ethernet addresses.
 	 */
-	struct fec_priv *fec = (struct fec_priv *)dev->priv;
-
 	/*
 	 * Check for valid length of data.
 	 */
@@ -777,14 +770,14 @@ out:
 	return ret;
 }
 
+
 /**
  * Pull one frame from the card
  * @param[in] dev Our ethernet device to handle
  * @return Length of packet read
  */
-static int fec_recv(struct eth_device *dev)
+static int _fec_recv(struct fec_priv *fec, uchar *mac)
 {
-	struct fec_priv *fec = (struct fec_priv *)dev->priv;
 	struct fec_bd *rbd = &fec->rbd_base[fec->rbd_index];
 	unsigned long ievent;
 	int frame_length, len = 0;
@@ -800,8 +793,8 @@ static int fec_recv(struct eth_device *dev)
 	writel(ievent, &fec->eth->ievent);
 	debug("fec_recv: ievent 0x%lx\n", ievent);
 	if (ievent & FEC_IEVENT_BABR) {
-		fec_halt(dev);
-		fec_init(dev, fec->bd);
+		_fec_halt(fec);
+		_fec_init(fec, mac);
 		printf("some error: 0x%08lx\n", ievent);
 		return 0;
 	}
@@ -813,10 +806,10 @@ static int fec_recv(struct eth_device *dev)
 	if (ievent & FEC_IEVENT_GRA) {
 		/* Graceful stop complete */
 		if (readl(&fec->eth->x_cntrl) & 0x00000001) {
-			fec_halt(dev);
+			_fec_halt(fec);
 			writel(~0x00000001 & readl(&fec->eth->x_cntrl),
 					&fec->eth->x_cntrl);
-			fec_init(dev, fec->bd);
+			_fec_init(fec, mac);
 		}
 	}
 
@@ -970,6 +963,71 @@ static void fec_free_descs(struct fec_priv *fec)
 	free(fec->tbd_base);
 }
 
+struct mii_dev *fec_get_miibus(uint32_t base_addr, int dev_id)
+{
+	struct ethernet_regs *eth = (struct ethernet_regs *)base_addr;
+	struct mii_dev *bus;
+	int ret;
+
+	bus = mdio_alloc();
+	if (!bus) {
+		printf("mdio_alloc failed\n");
+		return NULL;
+	}
+	bus->read = fec_phy_read;
+	bus->write = fec_phy_write;
+	bus->priv = eth;
+	fec_set_dev_name(bus->name, dev_id);
+
+	ret = mdio_register(bus);
+	if (ret) {
+		printf("mdio_register failed\n");
+		free(bus);
+		return NULL;
+	}
+	fec_mii_setspeed(eth);
+	return bus;
+}
+
+#ifndef CONFIG_DM_ETH
+static int fec_recv(struct eth_device *dev)
+{
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+	uchar *mac = dev->enetaddr;
+
+	return _fec_recv(fec, mac);
+}
+
+static int fec_send(struct eth_device *dev, void *packet, int length)
+{
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+
+	return _fec_send(fec, packet, length);
+}
+
+static void fec_halt(struct eth_device *dev)
+{
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+
+	_fec_halt(fec);
+}
+
+static int fec_set_hwaddr(struct eth_device *dev)
+{
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+	uchar *mac = dev->enetaddr;
+
+	return _fec_set_hwaddr(fec, mac);
+}
+
+static int fec_init(struct eth_device *dev, bd_t *bd)
+{
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+	uchar *mac = dev->enetaddr;
+
+	return _fec_init(fec, mac);
+}
+
 #ifdef CONFIG_PHYLIB
 int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
 		struct mii_dev *bus, struct phy_device *phydev)
@@ -1061,32 +1119,6 @@ err1:
 	return ret;
 }
 
-struct mii_dev *fec_get_miibus(uint32_t base_addr, int dev_id)
-{
-	struct ethernet_regs *eth = (struct ethernet_regs *)base_addr;
-	struct mii_dev *bus;
-	int ret;
-
-	bus = mdio_alloc();
-	if (!bus) {
-		printf("mdio_alloc failed\n");
-		return NULL;
-	}
-	bus->read = fec_phy_read;
-	bus->write = fec_phy_write;
-	bus->priv = eth;
-	fec_set_dev_name(bus->name, dev_id);
-
-	ret = mdio_register(bus);
-	if (ret) {
-		printf("mdio_register failed\n");
-		free(bus);
-		return NULL;
-	}
-	fec_mii_setspeed(eth);
-	return bus;
-}
-
 int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
 {
 	uint32_t base_mii;
@@ -1146,3 +1178,191 @@ int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int))
 	return 0;
 }
 #endif
+
+#else
+
+static int fec_set_hwaddr(struct udevice *dev)
+{
+	struct fec_priv *fec = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	uchar *mac = pdata->enetaddr;
+
+	return _fec_set_hwaddr(fec, mac);
+}
+
+static void fec_halt(struct udevice *dev)
+{
+	struct fec_priv *fec = dev_get_priv(dev);
+
+	_fec_halt(fec);
+}
+
+static int fec_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct fec_priv *fec = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	uchar *mac = pdata->enetaddr;
+
+	return _fec_recv(fec, mac);
+}
+
+static int fec_send(struct udevice *dev, void *packet, int length)
+{
+	struct fec_priv *fec = dev_get_priv(dev);
+
+	return _fec_send(fec, packet, length);
+}
+
+static int fec_init(struct udevice *dev)
+{
+	struct fec_priv *fec = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	uchar *mac = pdata->enetaddr;
+
+	return _fec_init(fec, mac);
+}
+
+static const struct eth_ops fecmxc_ops = {
+	.start			= fec_init,
+	.send			= fec_send,
+	.recv			= fec_recv,
+	.stop			= fec_halt,
+	.write_hwaddr		= fec_set_hwaddr,
+};
+
+static int fec_phy_init(struct fec_priv *priv, struct udevice *dev)
+{
+	struct phy_device *phydev;
+	int mask = 0xffffffff;
+
+#ifdef CONFIG_PHYLIB
+	mask = 1 << CONFIG_FEC_MXC_PHYADDR;
+#endif
+
+	phydev = phy_find_by_mask(priv->bus, mask, priv->interface);
+	if (!phydev)
+		return -ENODEV;
+
+	phy_connect_dev(phydev, dev);
+
+	priv->phydev = phydev;
+	phy_config(phydev);
+
+	return 0;
+}
+
+static int fecmxc_probe(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct fec_priv *priv = dev_get_priv(dev);
+	struct mii_dev *bus = NULL;
+	int dev_id = -1;
+	unsigned char ethaddr[6];
+	uint32_t start;
+	int ret;
+
+	ret = fec_alloc_descs(priv);
+	if (ret)
+		return ret;
+
+	bus = fec_get_miibus((uint32_t)priv->eth, dev_id);
+	if (!bus)
+		goto err_mii;
+
+	priv->bus = bus;
+	priv->xcv_type = CONFIG_FEC_XCV_TYPE;
+	priv->interface = pdata->phy_interface;
+	ret = fec_phy_init(priv, dev);
+	if (ret)
+		goto err_phy;
+
+	/* Reset chip. */
+	writel(readl(&priv->eth->ecntrl) | FEC_ECNTRL_RESET, &priv->eth->ecntrl);
+	start = get_timer(0);
+	while (readl(&priv->eth->ecntrl) & FEC_ECNTRL_RESET) {
+		if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
+			printf("FEC MXC: Timeout reseting chip\n");
+			goto err_timeout;
+		}
+		udelay(10);
+	}
+
+	fec_reg_setup(priv);
+	fec_set_dev_name((char *)dev->name, dev_id);
+	priv->dev_id = (dev_id == -1) ? 0 : dev_id;
+
+	ret = fec_get_hwaddr(dev_id, ethaddr);
+	if (!ret) {
+		debug("got MAC%d address from fuse: %pM\n", dev_id, ethaddr);
+		memcpy(pdata->enetaddr, ethaddr, 6);
+		if (!getenv("ethaddr"))
+			eth_setenv_enetaddr("ethaddr", ethaddr);
+	}
+
+	return 0;
+
+err_timeout:
+	free(priv->phydev);
+err_phy:
+	mdio_unregister(bus);
+	free(bus);
+err_mii:
+	fec_free_descs(priv);
+	return ret;
+}
+
+static int fecmxc_remove(struct udevice *dev)
+{
+	struct fec_priv *priv = dev_get_priv(dev);
+
+	free(priv->phydev);
+	fec_free_descs(priv);
+	mdio_unregister(priv->bus);
+	mdio_free(priv->bus);
+
+	return 0;
+}
+
+static int fecmxc_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct fec_priv *priv = dev_get_priv(dev);
+	const char *phy_mode;
+
+	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
+	priv->eth = (struct ethernet_regs *)pdata->iobase;
+
+	pdata->phy_interface = -1;
+	phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "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;
+	}
+
+	/* TODO
+	 * Need to get the reset-gpio and related properties from DT
+	 * and implemet the enet reset code on .probe call
+	 */
+
+	return 0;
+}
+
+static const struct udevice_id fecmxc_ids[] = {
+	{ .compatible = "fsl,imx6q-fec" },
+	{ }
+};
+
+U_BOOT_DRIVER(fec_gem) = {
+	.name	= "fecmxc",
+	.id	= UCLASS_ETH,
+	.of_match = fecmxc_ids,
+	.ofdata_to_platdata = fecmxc_ofdata_to_platdata,
+	.probe	= fecmxc_probe,
+	.remove	= fecmxc_remove,
+	.ops	= &fecmxc_ops,
+	.priv_auto_alloc_size = sizeof(struct fec_priv),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
+#endif
diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h
index 0717cc6..9fc6153 100644
--- a/drivers/net/fec_mxc.h
+++ b/drivers/net/fec_mxc.h
@@ -264,6 +264,10 @@ struct fec_priv {
 	int phy_id;
 	int (*mii_postcall)(int);
 #endif
+
+#ifdef CONFIG_DM_ETH
+	u32 interface;
+#endif
 };
 
 /**
-- 
2.7.4

  parent reply	other threads:[~2016-10-06 10:55 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-06 10:55 [U-Boot] [PATCH v5 0/5] net: fec_mxc: Convert to DM Jagan Teki
2016-10-06 10:55 ` [U-Boot] [PATCH v5 1/5] net: fec_mxc: Remove unneeded eth_device arg from fec_get_hwaddr Jagan Teki
2016-10-11 20:52   ` Joe Hershberger
2016-10-06 10:55 ` Jagan Teki [this message]
2016-10-09 14:51   ` [U-Boot] [PATCH v5 2/5] net: fec_mxc: Convert into driver model Jagan Teki
2016-10-11 20:58     ` Simon Glass
2016-10-12 16:16       ` Jagan Teki
2016-10-17 22:17         ` Simon Glass
2016-10-11 20:45   ` Joe Hershberger
2016-10-12 16:12     ` Jagan Teki
2016-10-06 10:55 ` [U-Boot] [PATCH v5 3/5] net: fec_mxc: Driver cleanups Jagan Teki
2016-10-11 20:57   ` Joe Hershberger
2016-10-06 10:55 ` [U-Boot] [PATCH v5 4/5] ARM: dts: imx6qdl-icore: Add FEC support Jagan Teki
2016-10-11 20:58   ` Joe Hershberger
2016-10-06 10:55 ` [U-Boot] [PATCH v5 5/5] icorem6: Use CONFIG_DM_ETH support Jagan Teki
2016-10-11 20:47   ` Joe Hershberger
2016-10-11  3:31 ` [U-Boot] [PATCH v5 0/5] net: fec_mxc: Convert to DM Jagan Teki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1475751324-14605-3-git-send-email-jteki@openedev.com \
    --to=jteki@openedev.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.