All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/10] split out emac cpdma and mdio for reuse
@ 2010-09-15 14:11 Cyril Chemparathy
  2010-09-15 14:11 ` [PATCH v4 01/10] net: davinci_emac: separate out davinci mdio Cyril Chemparathy
                   ` (10 more replies)
  0 siblings, 11 replies; 13+ messages in thread
From: Cyril Chemparathy @ 2010-09-15 14:11 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

Davinci's EMAC device has an in-built MDIO controller and a CPDMA engine.
These hardware modules are not restricted to EMAC device alone.  For example,
CPSW3G (3-port gigabit ethernet switch) hardware uses these very same modules
internally.  This patch series separates out EMAC's MDIO and CPDMA
functionality, allowing these individual pieces to be reused across TI
hardware.  

This patch series has been broadly organized as follows:

MDIO:
  - Add new functionality
      netdev: separate out davinci mdio controller code
  - Hookup new functionality
      davinci: add mdio platform devices
      omap: add mdio platform devices
      netdev: switch davinci emac to new mdio driver
  - Cleanup left over cruft
      davinci: cleanup unused davinci mdio arch code
      omap: cleanup unused davinci mdio arch code
      netdev: cleanup unused davinci mdio emac code

CPDMA:
  - Add new functionality
     netdev: separate out davinci cpdma controller code
  - Hookup new functionality
     netdev: switch davinci emac to new cpdma layer
  - Cleanup left over cruft
     netdev: cleanup unused davinci emac cpdma code

This series has been tested on dm365 and tnetv107x (with additional cpsw
patches) hardware.  Although am3517 (omap) board support code has been updated
as needed, emac does not work on this platform.

Changes from v1:
  1. Fixed memory leak in cpdma_chan_create() failure case
  2. Included new omap patches for am3517, avoids build breakage

Changes from v2:
  1. Updated series to include mityomapl138 board
  2. Minor white-space fixes

Changes from v3 (rolled in "post cpdma/mdio refactoring fixes" series):
  1. allow forced 100/full mode instead of phy auto-detect
  2. specify phy_id on boards that had a phy_mask defined earlier
  3. requeue cpdma descriptors when EOQ at submit
  4. use calculated mdio bus access times instead of hardcoded delays
  5. work around emac soft-reset impact on mdio controller state
  6. extend register dumps to include cpdma registers
  7. updated sign offs and acks


Cyril Chemparathy (10):
  net: davinci_emac: separate out davinci mdio
  davinci: add mdio platform devices
  omap: add mdio platform devices
  net: davinci_emac: switch to new mdio
  davinci: cleanup mdio arch code and switch to phy_id
  omap: cleanup unused davinci mdio arch code
  net: davinci_emac: cleanup unused mdio emac code
  net: davinci_emac: separate out cpdma code
  net: davinci_emac: switch to new cpdma layer
  net: davinci_emac: cleanup unused cpdma code

 arch/arm/mach-davinci/board-da830-evm.c     |    7 +-
 arch/arm/mach-davinci/board-da850-evm.c     |    7 +-
 arch/arm/mach-davinci/board-dm365-evm.c     |    7 +-
 arch/arm/mach-davinci/board-dm644x-evm.c    |    8 +-
 arch/arm/mach-davinci/board-dm646x-evm.c    |    7 +-
 arch/arm/mach-davinci/board-mityomapl138.c  |    8 +-
 arch/arm/mach-davinci/board-neuros-osd2.c   |    7 +-
 arch/arm/mach-davinci/board-sffsdr.c        |    7 +-
 arch/arm/mach-davinci/devices-da8xx.c       |   31 +-
 arch/arm/mach-davinci/dm365.c               |   23 +-
 arch/arm/mach-davinci/dm644x.c              |   23 +-
 arch/arm/mach-davinci/dm646x.c              |   22 +-
 arch/arm/mach-davinci/include/mach/dm365.h  |    2 +-
 arch/arm/mach-davinci/include/mach/dm644x.h |    2 +-
 arch/arm/mach-davinci/include/mach/dm646x.h |    2 +-
 arch/arm/mach-omap2/board-am3517evm.c       |   31 +-
 drivers/net/Kconfig                         |   21 +
 drivers/net/Makefile                        |    2 +
 drivers/net/davinci_cpdma.c                 |  965 +++++++++++++++++++
 drivers/net/davinci_cpdma.h                 |  108 +++
 drivers/net/davinci_emac.c                  | 1338 ++++-----------------------
 drivers/net/davinci_mdio.c                  |  475 ++++++++++
 include/linux/davinci_emac.h                |   16 +-
 23 files changed, 1894 insertions(+), 1225 deletions(-)
 create mode 100644 drivers/net/davinci_cpdma.c
 create mode 100644 drivers/net/davinci_cpdma.h
 create mode 100644 drivers/net/davinci_mdio.c


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v4 01/10] net: davinci_emac: separate out davinci mdio
  2010-09-15 14:11 [PATCH v4 00/10] split out emac cpdma and mdio for reuse Cyril Chemparathy
@ 2010-09-15 14:11 ` Cyril Chemparathy
  2010-09-15 14:11 ` [PATCH v4 02/10] davinci: add mdio platform devices Cyril Chemparathy
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Cyril Chemparathy @ 2010-09-15 14:11 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

Davinci's MDIO controller is present on other TI devices, without an
accompanying EMAC.  For example, on tnetv107x, the same MDIO module is used in
conjunction with a 3-port switch hardware.

By separating the MDIO controller code into its own platform driver, this
patch allows common logic to be reused on such platforms.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Tested-by: Michael Williamson <michael.williamson@criticallink.com>
Tested-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 drivers/net/Kconfig          |   10 +
 drivers/net/Makefile         |    1 +
 drivers/net/davinci_mdio.c   |  475 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/davinci_emac.h |    4 +
 4 files changed, 490 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/davinci_mdio.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2cc81a5..c5c86e0 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -958,6 +958,16 @@ config TI_DAVINCI_EMAC
 	  To compile this driver as a module, choose M here: the module
 	  will be called davinci_emac_driver.  This is recommended.
 
+config TI_DAVINCI_MDIO
+	tristate "TI DaVinci MDIO Support"
+	depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
+	select PHYLIB
+	help
+	  This driver supports TI's DaVinci MDIO module.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called davinci_mdio.  This is recommended.
+
 config DM9000
 	tristate "DM9000 support"
 	depends on ARM || BLACKFIN || MIPS
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 3e8f150..d38a7ab 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_MDIO) += mdio.o
 obj-$(CONFIG_PHYLIB) += phy/
 
 obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
+obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
 
 obj-$(CONFIG_E1000) += e1000/
 obj-$(CONFIG_E1000E) += e1000e/
diff --git a/drivers/net/davinci_mdio.c b/drivers/net/davinci_mdio.c
new file mode 100644
index 0000000..7615040
--- /dev/null
+++ b/drivers/net/davinci_mdio.c
@@ -0,0 +1,475 @@
+/*
+ * DaVinci MDIO Module driver
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * Shamelessly ripped out of davinci_emac.c, original copyrights follow:
+ *
+ * Copyright (C) 2009 Texas Instruments.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ---------------------------------------------------------------------------
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/phy.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/davinci_emac.h>
+
+/*
+ * This timeout definition is a worst-case ultra defensive measure against
+ * unexpected controller lock ups.  Ideally, we should never ever hit this
+ * scenario in practice.
+ */
+#define MDIO_TIMEOUT		100 /* msecs */
+
+#define PHY_REG_MASK		0x1f
+#define PHY_ID_MASK		0x1f
+
+#define DEF_OUT_FREQ		2200000		/* 2.2 MHz */
+
+struct davinci_mdio_regs {
+	u32	version;
+	u32	control;
+#define CONTROL_IDLE		BIT(31)
+#define CONTROL_ENABLE		BIT(30)
+#define CONTROL_MAX_DIV		(0xff)
+
+	u32	alive;
+	u32	link;
+	u32	linkintraw;
+	u32	linkintmasked;
+	u32	__reserved_0[2];
+	u32	userintraw;
+	u32	userintmasked;
+	u32	userintmaskset;
+	u32	userintmaskclr;
+	u32	__reserved_1[20];
+
+	struct {
+		u32	access;
+#define USERACCESS_GO		BIT(31)
+#define USERACCESS_WRITE	BIT(30)
+#define USERACCESS_ACK		BIT(29)
+#define USERACCESS_READ		(0)
+#define USERACCESS_DATA		(0xffff)
+
+		u32	physel;
+	}	user[0];
+};
+
+struct mdio_platform_data default_pdata = {
+	.bus_freq = DEF_OUT_FREQ,
+};
+
+struct davinci_mdio_data {
+	struct mdio_platform_data pdata;
+	struct davinci_mdio_regs __iomem *regs;
+	spinlock_t	lock;
+	struct clk	*clk;
+	struct device	*dev;
+	struct mii_bus	*bus;
+	bool		suspended;
+	unsigned long	access_time; /* jiffies */
+};
+
+static void __davinci_mdio_reset(struct davinci_mdio_data *data)
+{
+	u32 mdio_in, div, mdio_out_khz, access_time;
+
+	mdio_in = clk_get_rate(data->clk);
+	div = (mdio_in / data->pdata.bus_freq) - 1;
+	if (div > CONTROL_MAX_DIV)
+		div = CONTROL_MAX_DIV;
+
+	/* set enable and clock divider */
+	__raw_writel(div | CONTROL_ENABLE, &data->regs->control);
+
+	/*
+	 * One mdio transaction consists of:
+	 *	32 bits of preamble
+	 *	32 bits of transferred data
+	 *	24 bits of bus yield (not needed unless shared?)
+	 */
+	mdio_out_khz = mdio_in / (1000 * (div + 1));
+	access_time  = (88 * 1000) / mdio_out_khz;
+
+	/*
+	 * In the worst case, we could be kicking off a user-access immediately
+	 * after the mdio bus scan state-machine triggered its own read.  If
+	 * so, our request could get deferred by one access cycle.  We
+	 * defensively allow for 4 access cycles.
+	 */
+	data->access_time = usecs_to_jiffies(access_time * 4);
+	if (!data->access_time)
+		data->access_time = 1;
+}
+
+static int davinci_mdio_reset(struct mii_bus *bus)
+{
+	struct davinci_mdio_data *data = bus->priv;
+	u32 phy_mask, ver;
+
+	__davinci_mdio_reset(data);
+
+	/* wait for scan logic to settle */
+	msleep(PHY_MAX_ADDR * data->access_time);
+
+	/* dump hardware version info */
+	ver = __raw_readl(&data->regs->version);
+	dev_info(data->dev, "davinci mdio revision %d.%d\n",
+		 (ver >> 8) & 0xff, ver & 0xff);
+
+	/* get phy mask from the alive register */
+	phy_mask = __raw_readl(&data->regs->alive);
+	if (phy_mask) {
+		/* restrict mdio bus to live phys only */
+		dev_info(data->dev, "detected phy mask %x\n", ~phy_mask);
+		phy_mask = ~phy_mask;
+	} else {
+		/* desperately scan all phys */
+		dev_warn(data->dev, "no live phy, scanning all\n");
+		phy_mask = 0;
+	}
+	data->bus->phy_mask = phy_mask;
+
+	return 0;
+}
+
+/* wait until hardware is ready for another user access */
+static inline int wait_for_user_access(struct davinci_mdio_data *data)
+{
+	struct davinci_mdio_regs __iomem *regs = data->regs;
+	unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);
+	u32 reg;
+
+	while (time_after(timeout, jiffies)) {
+		reg = __raw_readl(&regs->user[0].access);
+		if ((reg & USERACCESS_GO) == 0)
+			return 0;
+
+		reg = __raw_readl(&regs->control);
+		if ((reg & CONTROL_IDLE) == 0)
+			continue;
+
+		/*
+		 * An emac soft_reset may have clobbered the mdio controller's
+		 * state machine.  We need to reset and retry the current
+		 * operation
+		 */
+		dev_warn(data->dev, "resetting idled controller\n");
+		__davinci_mdio_reset(data);
+		return -EAGAIN;
+	}
+	dev_err(data->dev, "timed out waiting for user access\n");
+	return -ETIMEDOUT;
+}
+
+/* wait until hardware state machine is idle */
+static inline int wait_for_idle(struct davinci_mdio_data *data)
+{
+	struct davinci_mdio_regs __iomem *regs = data->regs;
+	unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);
+
+	while (time_after(timeout, jiffies)) {
+		if (__raw_readl(&regs->control) & CONTROL_IDLE)
+			return 0;
+	}
+	dev_err(data->dev, "timed out waiting for idle\n");
+	return -ETIMEDOUT;
+}
+
+static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg)
+{
+	struct davinci_mdio_data *data = bus->priv;
+	u32 reg;
+	int ret;
+
+	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
+		return -EINVAL;
+
+	spin_lock(&data->lock);
+
+	if (data->suspended) {
+		spin_unlock(&data->lock);
+		return -ENODEV;
+	}
+
+	reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) |
+	       (phy_id << 16));
+
+	while (1) {
+		ret = wait_for_user_access(data);
+		if (ret == -EAGAIN)
+			continue;
+		if (ret < 0)
+			break;
+
+		__raw_writel(reg, &data->regs->user[0].access);
+
+		ret = wait_for_user_access(data);
+		if (ret == -EAGAIN)
+			continue;
+		if (ret < 0)
+			break;
+
+		reg = __raw_readl(&data->regs->user[0].access);
+		ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO;
+		break;
+	}
+
+	spin_unlock(&data->lock);
+
+	return ret;
+}
+
+static int davinci_mdio_write(struct mii_bus *bus, int phy_id,
+			      int phy_reg, u16 phy_data)
+{
+	struct davinci_mdio_data *data = bus->priv;
+	u32 reg;
+	int ret;
+
+	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
+		return -EINVAL;
+
+	spin_lock(&data->lock);
+
+	if (data->suspended) {
+		spin_unlock(&data->lock);
+		return -ENODEV;
+	}
+
+	reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) |
+		   (phy_id << 16) | (phy_data & USERACCESS_DATA));
+
+	while (1) {
+		ret = wait_for_user_access(data);
+		if (ret == -EAGAIN)
+			continue;
+		if (ret < 0)
+			break;
+
+		__raw_writel(reg, &data->regs->user[0].access);
+
+		ret = wait_for_user_access(data);
+		if (ret == -EAGAIN)
+			continue;
+		break;
+	}
+
+	spin_unlock(&data->lock);
+
+	return 0;
+}
+
+static int __devinit davinci_mdio_probe(struct platform_device *pdev)
+{
+	struct mdio_platform_data *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct davinci_mdio_data *data;
+	struct resource *res;
+	struct phy_device *phy;
+	int ret, addr;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		dev_err(dev, "failed to alloc device data\n");
+		return -ENOMEM;
+	}
+
+	data->pdata = pdata ? (*pdata) : default_pdata;
+
+	data->bus = mdiobus_alloc();
+	if (!data->bus) {
+		dev_err(dev, "failed to alloc mii bus\n");
+		ret = -ENOMEM;
+		goto bail_out;
+	}
+
+	data->bus->name		= dev_name(dev);
+	data->bus->read		= davinci_mdio_read,
+	data->bus->write	= davinci_mdio_write,
+	data->bus->reset	= davinci_mdio_reset,
+	data->bus->parent	= dev;
+	data->bus->priv		= data;
+	snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+
+	data->clk = clk_get(dev, NULL);
+	if (IS_ERR(data->clk)) {
+		data->clk = NULL;
+		dev_err(dev, "failed to get device clock\n");
+		ret = PTR_ERR(data->clk);
+		goto bail_out;
+	}
+
+	clk_enable(data->clk);
+
+	dev_set_drvdata(dev, data);
+	data->dev = dev;
+	spin_lock_init(&data->lock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "could not find register map resource\n");
+		ret = -ENOENT;
+		goto bail_out;
+	}
+
+	res = devm_request_mem_region(dev, res->start, resource_size(res),
+					    dev_name(dev));
+	if (!res) {
+		dev_err(dev, "could not allocate register map resource\n");
+		ret = -ENXIO;
+		goto bail_out;
+	}
+
+	data->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
+	if (!data->regs) {
+		dev_err(dev, "could not map mdio registers\n");
+		ret = -ENOMEM;
+		goto bail_out;
+	}
+
+	/* register the mii bus */
+	ret = mdiobus_register(data->bus);
+	if (ret)
+		goto bail_out;
+
+	/* scan and dump the bus */
+	for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
+		phy = data->bus->phy_map[addr];
+		if (phy) {
+			dev_info(dev, "phy[%d]: device %s, driver %s\n",
+				 phy->addr, dev_name(&phy->dev),
+				 phy->drv ? phy->drv->name : "unknown");
+		}
+	}
+
+	return 0;
+
+bail_out:
+	if (data->bus)
+		mdiobus_free(data->bus);
+
+	if (data->clk) {
+		clk_disable(data->clk);
+		clk_put(data->clk);
+	}
+
+	kfree(data);
+
+	return ret;
+}
+
+static int __devexit davinci_mdio_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct davinci_mdio_data *data = dev_get_drvdata(dev);
+
+	if (data->bus)
+		mdiobus_free(data->bus);
+
+	if (data->clk) {
+		clk_disable(data->clk);
+		clk_put(data->clk);
+	}
+
+	dev_set_drvdata(dev, NULL);
+
+	kfree(data);
+
+	return 0;
+}
+
+static int davinci_mdio_suspend(struct device *dev)
+{
+	struct davinci_mdio_data *data = dev_get_drvdata(dev);
+	u32 ctrl;
+
+	spin_lock(&data->lock);
+
+	/* shutdown the scan state machine */
+	ctrl = __raw_readl(&data->regs->control);
+	ctrl &= ~CONTROL_ENABLE;
+	__raw_writel(ctrl, &data->regs->control);
+	wait_for_idle(data);
+
+	if (data->clk)
+		clk_disable(data->clk);
+
+	data->suspended = true;
+	spin_unlock(&data->lock);
+
+	return 0;
+}
+
+static int davinci_mdio_resume(struct device *dev)
+{
+	struct davinci_mdio_data *data = dev_get_drvdata(dev);
+	u32 ctrl;
+
+	spin_lock(&data->lock);
+	if (data->clk)
+		clk_enable(data->clk);
+
+	/* restart the scan state machine */
+	ctrl = __raw_readl(&data->regs->control);
+	ctrl |= CONTROL_ENABLE;
+	__raw_writel(ctrl, &data->regs->control);
+
+	data->suspended = false;
+	spin_unlock(&data->lock);
+
+	return 0;
+}
+
+static const struct dev_pm_ops davinci_mdio_pm_ops = {
+	.suspend	= davinci_mdio_suspend,
+	.resume		= davinci_mdio_resume,
+};
+
+static struct platform_driver davinci_mdio_driver = {
+	.driver = {
+		.name	 = "davinci_mdio",
+		.owner	 = THIS_MODULE,
+		.pm	 = &davinci_mdio_pm_ops,
+	},
+	.probe = davinci_mdio_probe,
+	.remove = __devexit_p(davinci_mdio_remove),
+};
+
+static int __init davinci_mdio_init(void)
+{
+	return platform_driver_register(&davinci_mdio_driver);
+}
+device_initcall(davinci_mdio_init);
+
+static void __exit davinci_mdio_exit(void)
+{
+	platform_driver_unregister(&davinci_mdio_driver);
+}
+module_exit(davinci_mdio_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DaVinci MDIO driver");
diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h
index 7c930db..a04fd8c 100644
--- a/include/linux/davinci_emac.h
+++ b/include/linux/davinci_emac.h
@@ -14,6 +14,10 @@
 #include <linux/if_ether.h>
 #include <linux/memory.h>
 
+struct mdio_platform_data {
+	unsigned long		bus_freq;
+};
+
 struct emac_platform_data {
 	char mac_addr[ETH_ALEN];
 	u32 ctrl_reg_offset;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 02/10] davinci: add mdio platform devices
  2010-09-15 14:11 [PATCH v4 00/10] split out emac cpdma and mdio for reuse Cyril Chemparathy
  2010-09-15 14:11 ` [PATCH v4 01/10] net: davinci_emac: separate out davinci mdio Cyril Chemparathy
@ 2010-09-15 14:11 ` Cyril Chemparathy
  2010-09-15 14:11 ` [PATCH v4 03/10] omap: " Cyril Chemparathy
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Cyril Chemparathy @ 2010-09-15 14:11 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

This patch adds mdio platform devices on SoCs that have the necessary
hardware.  Clock lookup entries (aliases) have also been added, so that the
MDIO and EMAC drivers can independently enable/disable a shared underlying
clock.  Further, the EMAC MMR region has been split down into separate MDIO
and EMAC regions.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Acked-by: David S. Miller <davem@davemloft.net>
Tested-by: Michael Williamson <michael.williamson@criticallink.com>
Tested-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 arch/arm/mach-davinci/devices-da8xx.c       |   29 +++++++++++++++++++++++++-
 arch/arm/mach-davinci/dm365.c               |   22 +++++++++++++++++++-
 arch/arm/mach-davinci/dm644x.c              |   22 +++++++++++++++++++-
 arch/arm/mach-davinci/dm646x.c              |   21 ++++++++++++++++++-
 arch/arm/mach-davinci/include/mach/dm365.h  |    1 +
 arch/arm/mach-davinci/include/mach/dm644x.h |    1 +
 arch/arm/mach-davinci/include/mach/dm646x.h |    1 +
 7 files changed, 92 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index caeb7f4..9039221 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -352,7 +352,7 @@ int __init da8xx_register_watchdog(void)
 static struct resource da8xx_emac_resources[] = {
 	{
 		.start	= DA8XX_EMAC_CPPI_PORT_BASE,
-		.end	= DA8XX_EMAC_CPPI_PORT_BASE + 0x5000 - 1,
+		.end	= DA8XX_EMAC_CPPI_PORT_BASE + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
@@ -396,9 +396,34 @@ static struct platform_device da8xx_emac_device = {
 	.resource	= da8xx_emac_resources,
 };
 
+static struct resource da8xx_mdio_resources[] = {
+	{
+		.start	= DA8XX_EMAC_MDIO_BASE,
+		.end	= DA8XX_EMAC_MDIO_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device da8xx_mdio_device = {
+	.name		= "davinci_mdio",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(da8xx_mdio_resources),
+	.resource	= da8xx_mdio_resources,
+};
+
 int __init da8xx_register_emac(void)
 {
-	return platform_device_register(&da8xx_emac_device);
+	int ret;
+
+	ret = platform_device_register(&da8xx_mdio_device);
+	if (ret < 0)
+		return ret;
+	ret = platform_device_register(&da8xx_emac_device);
+	if (ret < 0)
+		return ret;
+	ret = clk_add_alias(NULL, dev_name(&da8xx_mdio_device.dev),
+			    NULL, &da8xx_emac_device.dev);
+	return ret;
 }
 
 static struct resource da830_mcasp1_resources[] = {
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index 6b6f4c6..71f0f9d 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -699,7 +699,7 @@ static struct emac_platform_data dm365_emac_pdata = {
 static struct resource dm365_emac_resources[] = {
 	{
 		.start	= DM365_EMAC_BASE,
-		.end	= DM365_EMAC_BASE + 0x47ff,
+		.end	= DM365_EMAC_BASE + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
@@ -734,6 +734,21 @@ static struct platform_device dm365_emac_device = {
 	.resource	= dm365_emac_resources,
 };
 
+static struct resource dm365_mdio_resources[] = {
+	{
+		.start	= DM365_EMAC_MDIO_BASE,
+		.end	= DM365_EMAC_MDIO_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device dm365_mdio_device = {
+	.name		= "davinci_mdio",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(dm365_mdio_resources),
+	.resource	= dm365_mdio_resources,
+};
+
 static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = {
 	[IRQ_VDINT0]			= 2,
 	[IRQ_VDINT1]			= 6,
@@ -1220,7 +1235,12 @@ static int __init dm365_init_devices(void)
 
 	davinci_cfg_reg(DM365_INT_EDMA_CC);
 	platform_device_register(&dm365_edma_device);
+
+	platform_device_register(&dm365_mdio_device);
 	platform_device_register(&dm365_emac_device);
+	clk_add_alias(NULL, dev_name(&dm365_mdio_device.dev),
+		      NULL, &dm365_emac_device.dev);
+
 	/* Add isif clock alias */
 	clk_add_alias("master", dm365_isif_dev.name, "vpss_master", NULL);
 	platform_device_register(&dm365_vpss_device);
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 40fec31..c103b2c 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -330,7 +330,7 @@ static struct emac_platform_data dm644x_emac_pdata = {
 static struct resource dm644x_emac_resources[] = {
 	{
 		.start	= DM644X_EMAC_BASE,
-		.end	= DM644X_EMAC_BASE + 0x47ff,
+		.end	= DM644X_EMAC_BASE + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
@@ -350,6 +350,21 @@ static struct platform_device dm644x_emac_device = {
        .resource	= dm644x_emac_resources,
 };
 
+static struct resource dm644x_mdio_resources[] = {
+	{
+		.start	= DM644X_EMAC_MDIO_BASE,
+		.end	= DM644X_EMAC_MDIO_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device dm644x_mdio_device = {
+	.name		= "davinci_mdio",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(dm644x_mdio_resources),
+	.resource	= dm644x_mdio_resources,
+};
+
 /*
  * Device specific mux setup
  *
@@ -777,7 +792,12 @@ static int __init dm644x_init_devices(void)
 	clk_add_alias("master", dm644x_ccdc_dev.name, "vpss_master", NULL);
 	clk_add_alias("slave", dm644x_ccdc_dev.name, "vpss_slave", NULL);
 	platform_device_register(&dm644x_edma_device);
+
+	platform_device_register(&dm644x_mdio_device);
 	platform_device_register(&dm644x_emac_device);
+	clk_add_alias(NULL, dev_name(&dm644x_mdio_device.dev),
+		      NULL, &dm644x_emac_device.dev);
+
 	platform_device_register(&dm644x_vpss_device);
 	platform_device_register(&dm644x_ccdc_dev);
 	platform_device_register(&vpfe_capture_dev);
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index e4a3df1..8da886b 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -366,7 +366,7 @@ static struct emac_platform_data dm646x_emac_pdata = {
 static struct resource dm646x_emac_resources[] = {
 	{
 		.start	= DM646X_EMAC_BASE,
-		.end	= DM646X_EMAC_BASE + 0x47ff,
+		.end	= DM646X_EMAC_BASE + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
@@ -401,6 +401,21 @@ static struct platform_device dm646x_emac_device = {
 	.resource	= dm646x_emac_resources,
 };
 
+static struct resource dm646x_mdio_resources[] = {
+	{
+		.start	= DM646X_EMAC_MDIO_BASE,
+		.end	= DM646X_EMAC_MDIO_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device dm646x_mdio_device = {
+	.name		= "davinci_mdio",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(dm646x_mdio_resources),
+	.resource	= dm646x_mdio_resources,
+};
+
 /*
  * Device specific mux setup
  *
@@ -897,7 +912,11 @@ static int __init dm646x_init_devices(void)
 	if (!cpu_is_davinci_dm646x())
 		return 0;
 
+	platform_device_register(&dm646x_mdio_device);
 	platform_device_register(&dm646x_emac_device);
+	clk_add_alias(NULL, dev_name(&dm646x_mdio_device.dev),
+		      NULL, &dm646x_emac_device.dev);
+
 	return 0;
 }
 postcore_initcall(dm646x_init_devices);
diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h
index ea5df3b..dbb5052 100644
--- a/arch/arm/mach-davinci/include/mach/dm365.h
+++ b/arch/arm/mach-davinci/include/mach/dm365.h
@@ -21,6 +21,7 @@
 #include <media/davinci/vpfe_capture.h>
 
 #define DM365_EMAC_BASE			(0x01D07000)
+#define DM365_EMAC_MDIO_BASE		(DM365_EMAC_BASE + 0x4000)
 #define DM365_EMAC_CNTRL_OFFSET		(0x0000)
 #define DM365_EMAC_CNTRL_MOD_OFFSET	(0x3000)
 #define DM365_EMAC_CNTRL_RAM_OFFSET	(0x1000)
diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h
index 6fca568..5159117 100644
--- a/arch/arm/mach-davinci/include/mach/dm644x.h
+++ b/arch/arm/mach-davinci/include/mach/dm644x.h
@@ -28,6 +28,7 @@
 #include <media/davinci/vpfe_capture.h>
 
 #define DM644X_EMAC_BASE		(0x01C80000)
+#define DM644X_EMAC_MDIO_BASE		(DM644X_EMAC_BASE + 0x4000)
 #define DM644X_EMAC_CNTRL_OFFSET	(0x0000)
 #define DM644X_EMAC_CNTRL_MOD_OFFSET	(0x1000)
 #define DM644X_EMAC_CNTRL_RAM_OFFSET	(0x2000)
diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h
index 0a27ee9..1c4dca9 100644
--- a/arch/arm/mach-davinci/include/mach/dm646x.h
+++ b/arch/arm/mach-davinci/include/mach/dm646x.h
@@ -19,6 +19,7 @@
 #include <linux/davinci_emac.h>
 
 #define DM646X_EMAC_BASE		(0x01C80000)
+#define DM646X_EMAC_MDIO_BASE		(DM646X_EMAC_BASE + 0x4000)
 #define DM646X_EMAC_CNTRL_OFFSET	(0x0000)
 #define DM646X_EMAC_CNTRL_MOD_OFFSET	(0x1000)
 #define DM646X_EMAC_CNTRL_RAM_OFFSET	(0x2000)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 03/10] omap: add mdio platform devices
  2010-09-15 14:11 [PATCH v4 00/10] split out emac cpdma and mdio for reuse Cyril Chemparathy
  2010-09-15 14:11 ` [PATCH v4 01/10] net: davinci_emac: separate out davinci mdio Cyril Chemparathy
  2010-09-15 14:11 ` [PATCH v4 02/10] davinci: add mdio platform devices Cyril Chemparathy
@ 2010-09-15 14:11 ` Cyril Chemparathy
  2010-09-15 14:11 ` [PATCH v4 04/10] net: davinci_emac: switch to new mdio Cyril Chemparathy
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Cyril Chemparathy @ 2010-09-15 14:11 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

This patch adds mdio platform devices on SoCs that have the necessary
hardware.  Clock lookup entries (aliases) have also been added, so that the
MDIO and EMAC drivers can independently enable/disable a shared underlying
clock.  Further, the EMAC MMR region has been split down into separate MDIO
and EMAC regions.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Acked-by: David S. Miller <davem@davemloft.net>
Acked-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/board-am3517evm.c |   27 ++++++++++++++++++++++++++-
 1 files changed, 26 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 4d0f585..5dd1b73 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -18,6 +18,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/i2c/pca953x.h>
@@ -41,6 +42,27 @@
 #define AM35XX_EVM_PHY_MASK		(0xF)
 #define AM35XX_EVM_MDIO_FREQUENCY	(1000000)
 
+static struct mdio_platform_data am3517_evm_mdio_pdata = {
+	.bus_freq	= AM35XX_EVM_MDIO_FREQUENCY,
+};
+
+static struct resource am3517_mdio_resources[] = {
+	{
+		.start  = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET,
+		.end    = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET +
+			  SZ_4K - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device am3517_mdio_device = {
+	.name		= "davinci_mdio",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(am3517_mdio_resources),
+	.resource	= am3517_mdio_resources,
+	.dev.platform_data = &am3517_evm_mdio_pdata,
+};
+
 static struct emac_platform_data am3517_evm_emac_pdata = {
 	.phy_mask	= AM35XX_EVM_PHY_MASK,
 	.mdio_max_freq	= AM35XX_EVM_MDIO_FREQUENCY,
@@ -50,7 +72,7 @@ static struct emac_platform_data am3517_evm_emac_pdata = {
 static struct resource am3517_emac_resources[] = {
 	{
 		.start  = AM35XX_IPSS_EMAC_BASE,
-		.end    = AM35XX_IPSS_EMAC_BASE + 0x3FFFF,
+		.end    = AM35XX_IPSS_EMAC_BASE + 0x2FFFF,
 		.flags  = IORESOURCE_MEM,
 	},
 	{
@@ -121,6 +143,9 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
 	pdata->interrupt_disable	= am3517_disable_ethernet_int;
 	am3517_emac_device.dev.platform_data	= pdata;
 	platform_device_register(&am3517_emac_device);
+	platform_device_register(&am3517_mdio_device);
+	clk_add_alias(NULL, dev_name(&am3517_mdio_device.dev),
+		      NULL, &am3517_emac_device.dev);
 
 	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
 	regval = regval & (~(AM35XX_CPGMACSS_SW_RST));
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 04/10] net: davinci_emac: switch to new mdio
  2010-09-15 14:11 [PATCH v4 00/10] split out emac cpdma and mdio for reuse Cyril Chemparathy
                   ` (2 preceding siblings ...)
  2010-09-15 14:11 ` [PATCH v4 03/10] omap: " Cyril Chemparathy
@ 2010-09-15 14:11 ` Cyril Chemparathy
  2010-09-15 14:11 ` [PATCH v4 05/10] davinci: cleanup mdio arch code and switch to phy_id Cyril Chemparathy
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Cyril Chemparathy @ 2010-09-15 14:11 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

This patch switches the emac implementation over to the newly separated
MDIO driver.

With this, the mdio bus frequency defaults to a safe 2.2MHz.  Boards may
optionally specify a bus frequency via platform data.

The phy identification scheme has been modified to use a phy bus id instead
of a mask.  This largely serves to eliminate the "phy search" code in emac
init.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Acked-by: David S. Miller <davem@davemloft.net>
Tested-by: Michael Williamson <michael.williamson@criticallink.com>
Tested-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 drivers/net/Kconfig          |    1 +
 drivers/net/davinci_emac.c   |   88 ++++++++++++++---------------------------
 include/linux/davinci_emac.h |    9 ++++
 3 files changed, 40 insertions(+), 58 deletions(-)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index c5c86e0..911e7f1 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -951,6 +951,7 @@ config NET_NETX
 config TI_DAVINCI_EMAC
 	tristate "TI DaVinci EMAC Support"
 	depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
+	select TI_DAVINCI_MDIO
 	select PHYLIB
 	help
 	  This driver supports TI's DaVinci Ethernet .
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 7fbd052..997f599 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -500,6 +500,7 @@ struct emac_priv {
 	u32 phy_mask;
 	/* mii_bus,phy members */
 	struct mii_bus *mii_bus;
+	const char *phy_id;
 	struct phy_device *phydev;
 	spinlock_t lock;
 	/*platform specific members*/
@@ -686,7 +687,7 @@ static int emac_get_settings(struct net_device *ndev,
 			     struct ethtool_cmd *ecmd)
 {
 	struct emac_priv *priv = netdev_priv(ndev);
-	if (priv->phy_mask)
+	if (priv->phydev)
 		return phy_ethtool_gset(priv->phydev, ecmd);
 	else
 		return -EOPNOTSUPP;
@@ -704,7 +705,7 @@ static int emac_get_settings(struct net_device *ndev,
 static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
 {
 	struct emac_priv *priv = netdev_priv(ndev);
-	if (priv->phy_mask)
+	if (priv->phydev)
 		return phy_ethtool_sset(priv->phydev, ecmd);
 	else
 		return -EOPNOTSUPP;
@@ -841,7 +842,7 @@ static void emac_update_phystatus(struct emac_priv *priv)
 	mac_control = emac_read(EMAC_MACCONTROL);
 	cur_duplex = (mac_control & EMAC_MACCONTROL_FULLDUPLEXEN) ?
 			DUPLEX_FULL : DUPLEX_HALF;
-	if (priv->phy_mask)
+	if (priv->phydev)
 		new_duplex = priv->phydev->duplex;
 	else
 		new_duplex = DUPLEX_FULL;
@@ -2485,6 +2486,11 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
 	return -EOPNOTSUPP;
 }
 
+static int match_first_device(struct device *dev, void *data)
+{
+	return 1;
+}
+
 /**
  * emac_dev_open: EMAC device open
  * @ndev: The DaVinci EMAC network adapter
@@ -2499,7 +2505,6 @@ static int emac_dev_open(struct net_device *ndev)
 {
 	struct device *emac_dev = &ndev->dev;
 	u32 rc, cnt, ch;
-	int phy_addr;
 	struct resource *res;
 	int q, m;
 	int i = 0;
@@ -2560,28 +2565,26 @@ static int emac_dev_open(struct net_device *ndev)
 		emac_set_coalesce(ndev, &coal);
 	}
 
-	/* find the first phy */
 	priv->phydev = NULL;
-	if (priv->phy_mask) {
-		emac_mii_reset(priv->mii_bus);
-		for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
-			if (priv->mii_bus->phy_map[phy_addr]) {
-				priv->phydev = priv->mii_bus->phy_map[phy_addr];
-				break;
-			}
-		}
+	/* use the first phy on the bus if pdata did not give us a phy id */
+	if (!priv->phy_id) {
+		struct device *phy;
 
-		if (!priv->phydev) {
-			printk(KERN_ERR "%s: no PHY found\n", ndev->name);
-			return -1;
-		}
+		phy = bus_find_device(&mdio_bus_type, NULL, NULL,
+				      match_first_device);
+		if (phy)
+			priv->phy_id = dev_name(phy);
+	}
 
-		priv->phydev = phy_connect(ndev, dev_name(&priv->phydev->dev),
-				&emac_adjust_link, 0, PHY_INTERFACE_MODE_MII);
+	if (priv->phy_id && *priv->phy_id) {
+		priv->phydev = phy_connect(ndev, priv->phy_id,
+					   &emac_adjust_link, 0,
+					   PHY_INTERFACE_MODE_MII);
 
 		if (IS_ERR(priv->phydev)) {
-			printk(KERN_ERR "%s: Could not attach to PHY\n",
-								ndev->name);
+			dev_err(emac_dev, "could not connect to phy %s\n",
+				priv->phy_id);
+			priv->phydev = NULL;
 			return PTR_ERR(priv->phydev);
 		}
 
@@ -2589,12 +2592,13 @@ static int emac_dev_open(struct net_device *ndev)
 		priv->speed = 0;
 		priv->duplex = ~0;
 
-		printk(KERN_INFO "%s: attached PHY driver [%s] "
-			"(mii_bus:phy_addr=%s, id=%x)\n", ndev->name,
+		dev_info(emac_dev, "attached PHY driver [%s] "
+			"(mii_bus:phy_addr=%s, id=%x)\n",
 			priv->phydev->drv->name, dev_name(&priv->phydev->dev),
 			priv->phydev->phy_id);
-	} else{
+	} else {
 		/* No PHY , fix the link, speed and duplex settings */
+		dev_notice(emac_dev, "no phy, defaulting to 100/full\n");
 		priv->link = 1;
 		priv->speed = SPEED_100;
 		priv->duplex = DUPLEX_FULL;
@@ -2607,7 +2611,7 @@ static int emac_dev_open(struct net_device *ndev)
 	if (netif_msg_drv(priv))
 		dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name);
 
-	if (priv->phy_mask)
+	if (priv->phydev)
 		phy_start(priv->phydev);
 
 	return 0;
@@ -2794,7 +2798,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
 
 	/* MAC addr and PHY mask , RMII enable info from platform_data */
 	memcpy(priv->mac_addr, pdata->mac_addr, 6);
-	priv->phy_mask = pdata->phy_mask;
+	priv->phy_id = pdata->phy_id;
 	priv->rmii_en = pdata->rmii_en;
 	priv->version = pdata->version;
 	priv->int_enable = pdata->interrupt_enable;
@@ -2871,32 +2875,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
 	}
 
 
-	/* MII/Phy intialisation, mdio bus registration */
-	emac_mii = mdiobus_alloc();
-	if (emac_mii == NULL) {
-		dev_err(emac_dev, "DaVinci EMAC: Error allocating mii_bus\n");
-		rc = -ENOMEM;
-		goto mdio_alloc_err;
-	}
-
-	priv->mii_bus = emac_mii;
-	emac_mii->name  = "emac-mii",
-	emac_mii->read  = emac_mii_read,
-	emac_mii->write = emac_mii_write,
-	emac_mii->reset = emac_mii_reset,
-	emac_mii->irq   = mii_irqs,
-	emac_mii->phy_mask = ~(priv->phy_mask);
-	emac_mii->parent = &pdev->dev;
-	emac_mii->priv = priv->remap_addr + pdata->mdio_reg_offset;
-	snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", priv->pdev->id);
-	mdio_max_freq = pdata->mdio_max_freq;
-	emac_mii->reset(emac_mii);
-
-	/* Register the MII bus */
-	rc = mdiobus_register(emac_mii);
-	if (rc)
-		goto mdiobus_quit;
-
 	if (netif_msg_probe(priv)) {
 		dev_notice(emac_dev, "DaVinci EMAC Probe found device "\
 			   "(regs: %p, irq: %d)\n",
@@ -2904,11 +2882,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
 	}
 	return 0;
 
-mdiobus_quit:
-	mdiobus_free(emac_mii);
-
 netdev_reg_err:
-mdio_alloc_err:
 	clk_disable(emac_clk);
 no_irq_res:
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -2938,8 +2912,6 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, NULL);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mdiobus_unregister(priv->mii_bus);
-	mdiobus_free(priv->mii_bus);
 
 	release_mem_region(res->start, res->end - res->start + 1);
 
diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h
index a04fd8c..46a759f 100644
--- a/include/linux/davinci_emac.h
+++ b/include/linux/davinci_emac.h
@@ -28,6 +28,15 @@ struct emac_platform_data {
 	u32 ctrl_ram_size;
 	u32 phy_mask;
 	u32 mdio_max_freq;
+
+	/*
+	 * phy_id can be one of the following:
+	 *   - NULL		: use the first phy on the bus,
+	 *   - ""		: force to 100/full, no mdio control
+	 *   - "<bus>:<addr>"	: use the specified bus and phy
+	 */
+	const char *phy_id;
+
 	u8 rmii_en;
 	u8 version;
 	void (*interrupt_enable) (void);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 05/10] davinci: cleanup mdio arch code and switch to phy_id
  2010-09-15 14:11 [PATCH v4 00/10] split out emac cpdma and mdio for reuse Cyril Chemparathy
                   ` (3 preceding siblings ...)
  2010-09-15 14:11 ` [PATCH v4 04/10] net: davinci_emac: switch to new mdio Cyril Chemparathy
@ 2010-09-15 14:11 ` Cyril Chemparathy
  2010-09-15 14:11 ` [PATCH v4 06/10] omap: cleanup unused davinci mdio arch code Cyril Chemparathy
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Cyril Chemparathy @ 2010-09-15 14:11 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

This patch removes davinci architecture code that has now been rendered
useless by the previous patches in the MDIO separation series.

In addition, the earlier phy_mask definitions have been replaced with
corresponding phy_id definitions.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Tested-by: Michael Williamson <michael.williamson@criticallink.com>
Tested-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 arch/arm/mach-davinci/board-da830-evm.c     |    7 ++-----
 arch/arm/mach-davinci/board-da850-evm.c     |    7 ++-----
 arch/arm/mach-davinci/board-dm365-evm.c     |    7 ++-----
 arch/arm/mach-davinci/board-dm644x-evm.c    |    8 ++------
 arch/arm/mach-davinci/board-dm646x-evm.c    |    7 ++-----
 arch/arm/mach-davinci/board-mityomapl138.c  |    8 ++------
 arch/arm/mach-davinci/board-neuros-osd2.c   |    7 ++-----
 arch/arm/mach-davinci/board-sffsdr.c        |    7 ++-----
 arch/arm/mach-davinci/devices-da8xx.c       |    2 --
 arch/arm/mach-davinci/dm365.c               |    1 -
 arch/arm/mach-davinci/dm644x.c              |    1 -
 arch/arm/mach-davinci/dm646x.c              |    1 -
 arch/arm/mach-davinci/include/mach/dm365.h  |    1 -
 arch/arm/mach-davinci/include/mach/dm644x.h |    1 -
 arch/arm/mach-davinci/include/mach/dm646x.h |    1 -
 15 files changed, 16 insertions(+), 50 deletions(-)

diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index ef1ab0b..1bb89d3 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -31,9 +31,7 @@
 #include <mach/usb.h>
 #include <mach/aemif.h>
 
-#define DA830_EVM_PHY_MASK		0x0
-#define DA830_EVM_MDIO_FREQUENCY	2200000	/* PHY bus frequency */
-
+#define DA830_EVM_PHY_ID		""
 /*
  * USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4].
  */
@@ -558,9 +556,8 @@ static __init void da830_evm_init(void)
 
 	da830_evm_usb_init();
 
-	soc_info->emac_pdata->phy_mask = DA830_EVM_PHY_MASK;
-	soc_info->emac_pdata->mdio_max_freq = DA830_EVM_MDIO_FREQUENCY;
 	soc_info->emac_pdata->rmii_en = 1;
+	soc_info->emac_pdata->phy_id = DA830_EVM_PHY_ID;
 
 	ret = davinci_cfg_reg_list(da830_cpgmac_pins);
 	if (ret)
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index ac2297c..5e435b0 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -38,9 +38,7 @@
 #include <mach/mux.h>
 #include <mach/aemif.h>
 
-#define DA850_EVM_PHY_MASK		0x1
-#define DA850_EVM_MDIO_FREQUENCY	2200000 /* PHY bus frequency */
-
+#define DA850_EVM_PHY_ID		"0:00"
 #define DA850_LCD_PWR_PIN		GPIO_TO_PIN(2, 8)
 #define DA850_LCD_BL_PIN		GPIO_TO_PIN(2, 15)
 
@@ -678,8 +676,7 @@ static int __init da850_evm_config_emac(void)
 	/* Enable/Disable MII MDIO clock */
 	gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en);
 
-	soc_info->emac_pdata->phy_mask = DA850_EVM_PHY_MASK;
-	soc_info->emac_pdata->mdio_max_freq = DA850_EVM_MDIO_FREQUENCY;
+	soc_info->emac_pdata->phy_id = DA850_EVM_PHY_ID;
 
 	ret = da8xx_register_emac();
 	if (ret)
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index bdea2da..a06b84c 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -54,9 +54,7 @@ static inline int have_tvp7002(void)
 	return 0;
 }
 
-#define DM365_EVM_PHY_MASK		(0x2)
-#define DM365_EVM_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */
-
+#define DM365_EVM_PHY_ID		"0:01"
 /*
  * A MAX-II CPLD is used for various board control functions.
  */
@@ -535,8 +533,7 @@ fail:
 
 		/* ... and ENET ... */
 		dm365evm_emac_configure();
-		soc_info->emac_pdata->phy_mask = DM365_EVM_PHY_MASK;
-		soc_info->emac_pdata->mdio_max_freq = DM365_EVM_MDIO_FREQUENCY;
+		soc_info->emac_pdata->phy_id = DM365_EVM_PHY_ID;
 		resets &= ~BIT(3);
 
 		/* ... and AIC33 */
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 65bb940..44a2f0a 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -39,9 +39,7 @@
 #include <mach/usb.h>
 #include <mach/aemif.h>
 
-#define DM644X_EVM_PHY_MASK		(0x2)
-#define DM644X_EVM_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */
-
+#define DM644X_EVM_PHY_ID		"0:01"
 #define LXT971_PHY_ID	(0x001378e2)
 #define LXT971_PHY_MASK	(0xfffffff0)
 
@@ -707,9 +705,7 @@ static __init void davinci_evm_init(void)
 	davinci_serial_init(&uart_config);
 	dm644x_init_asp(&dm644x_evm_snd_data);
 
-	soc_info->emac_pdata->phy_mask = DM644X_EVM_PHY_MASK;
-	soc_info->emac_pdata->mdio_max_freq = DM644X_EVM_MDIO_FREQUENCY;
-
+	soc_info->emac_pdata->phy_id = DM644X_EVM_PHY_ID;
 	/* Register the fixup for PHY on DaVinci */
 	phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK,
 					davinci_phy_fixup);
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 5a29955..67669bb 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -729,9 +729,7 @@ static struct davinci_uart_config uart_config __initdata = {
 	.enabled_uarts = (1 << 0),
 };
 
-#define DM646X_EVM_PHY_MASK		(0x2)
-#define DM646X_EVM_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */
-
+#define DM646X_EVM_PHY_ID		"0:01"
 /*
  * The following EDMA channels/slots are not being used by drivers (for
  * example: Timer, GPIO, UART events etc) on dm646x, hence they are being
@@ -784,8 +782,7 @@ static __init void evm_init(void)
 	if (HAS_ATA)
 		davinci_init_ide();
 
-	soc_info->emac_pdata->phy_mask = DM646X_EVM_PHY_MASK;
-	soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY;
+	soc_info->emac_pdata->phy_id = DM646X_EVM_PHY_ID;
 }
 
 #define DM646X_EVM_REF_FREQ		27000000
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index 84d5aff..6f12a18 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -24,9 +24,7 @@
 #include <mach/nand.h>
 #include <mach/mux.h>
 
-#define MITYOMAPL138_PHY_MASK		0x08 /* hardcoded for now */
-#define MITYOMAPL138_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */
-
+#define MITYOMAPL138_PHY_ID		"0:03"
 static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = {
 	.bus_freq	= 100,	/* kHz */
 	.bus_delay	= 0,	/* usec */
@@ -273,9 +271,7 @@ static void __init mityomapl138_config_emac(void)
 	/* configure the CFGCHIP3 register for RMII or MII */
 	__raw_writel(val, cfg_chip3_base);
 
-	soc_info->emac_pdata->phy_mask = MITYOMAPL138_PHY_MASK;
-	pr_debug("setting phy_mask to %x\n", soc_info->emac_pdata->phy_mask);
-	soc_info->emac_pdata->mdio_max_freq = MITYOMAPL138_MDIO_FREQUENCY;
+	soc_info->emac_pdata->phy_id = MITYOMAPL138_PHY_ID;
 
 	ret = da8xx_register_emac();
 	if (ret)
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index 4c30e92..04a8d16 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -39,9 +39,7 @@
 #include <mach/mmc.h>
 #include <mach/usb.h>
 
-#define NEUROS_OSD2_PHY_MASK		0x2
-#define NEUROS_OSD2_MDIO_FREQUENCY	2200000 /* PHY bus frequency */
-
+#define NEUROS_OSD2_PHY_ID		"0:01"
 #define LXT971_PHY_ID			0x001378e2
 #define LXT971_PHY_MASK			0xfffffff0
 
@@ -252,8 +250,7 @@ static __init void davinci_ntosd2_init(void)
 	davinci_serial_init(&uart_config);
 	dm644x_init_asp(&dm644x_ntosd2_snd_data);
 
-	soc_info->emac_pdata->phy_mask = NEUROS_OSD2_PHY_MASK;
-	soc_info->emac_pdata->mdio_max_freq = NEUROS_OSD2_MDIO_FREQUENCY;
+	soc_info->emac_pdata->phy_id = NEUROS_OSD2_PHY_ID;
 
 	davinci_setup_usb(1000, 8);
 	/*
diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c
index 23e664a..ab4292d 100644
--- a/arch/arm/mach-davinci/board-sffsdr.c
+++ b/arch/arm/mach-davinci/board-sffsdr.c
@@ -42,9 +42,7 @@
 #include <mach/mux.h>
 #include <mach/usb.h>
 
-#define SFFSDR_PHY_MASK		(0x2)
-#define SFFSDR_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */
-
+#define SFFSDR_PHY_ID		"0:01"
 static struct mtd_partition davinci_sffsdr_nandflash_partition[] = {
 	/* U-Boot Environment: Block 0
 	 * UBL:                Block 1
@@ -143,8 +141,7 @@ static __init void davinci_sffsdr_init(void)
 			     ARRAY_SIZE(davinci_sffsdr_devices));
 	sffsdr_init_i2c();
 	davinci_serial_init(&uart_config);
-	soc_info->emac_pdata->phy_mask = SFFSDR_PHY_MASK;
-	soc_info->emac_pdata->mdio_max_freq = SFFSDR_MDIO_FREQUENCY;
+	soc_info->emac_pdata->phy_id = SFFSDR_PHY_ID;
 	davinci_setup_usb(0, 0); /* We support only peripheral mode. */
 
 	/* mux VLYNQ pins */
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 9039221..9eec630 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -42,7 +42,6 @@
 #define DA8XX_EMAC_CTRL_REG_OFFSET	0x3000
 #define DA8XX_EMAC_MOD_REG_OFFSET	0x2000
 #define DA8XX_EMAC_RAM_OFFSET		0x0000
-#define DA8XX_MDIO_REG_OFFSET		0x4000
 #define DA8XX_EMAC_CTRL_RAM_SIZE	SZ_8K
 
 void __iomem *da8xx_syscfg0_base;
@@ -381,7 +380,6 @@ struct emac_platform_data da8xx_emac_pdata = {
 	.ctrl_reg_offset	= DA8XX_EMAC_CTRL_REG_OFFSET,
 	.ctrl_mod_reg_offset	= DA8XX_EMAC_MOD_REG_OFFSET,
 	.ctrl_ram_offset	= DA8XX_EMAC_RAM_OFFSET,
-	.mdio_reg_offset	= DA8XX_MDIO_REG_OFFSET,
 	.ctrl_ram_size		= DA8XX_EMAC_CTRL_RAM_SIZE,
 	.version		= EMAC_VERSION_2,
 };
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index 71f0f9d..240f392 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -691,7 +691,6 @@ static struct emac_platform_data dm365_emac_pdata = {
 	.ctrl_reg_offset	= DM365_EMAC_CNTRL_OFFSET,
 	.ctrl_mod_reg_offset	= DM365_EMAC_CNTRL_MOD_OFFSET,
 	.ctrl_ram_offset	= DM365_EMAC_CNTRL_RAM_OFFSET,
-	.mdio_reg_offset	= DM365_EMAC_MDIO_OFFSET,
 	.ctrl_ram_size		= DM365_EMAC_CNTRL_RAM_SIZE,
 	.version		= EMAC_VERSION_2,
 };
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index c103b2c..41b7a95 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -322,7 +322,6 @@ static struct emac_platform_data dm644x_emac_pdata = {
 	.ctrl_reg_offset	= DM644X_EMAC_CNTRL_OFFSET,
 	.ctrl_mod_reg_offset	= DM644X_EMAC_CNTRL_MOD_OFFSET,
 	.ctrl_ram_offset	= DM644X_EMAC_CNTRL_RAM_OFFSET,
-	.mdio_reg_offset	= DM644X_EMAC_MDIO_OFFSET,
 	.ctrl_ram_size		= DM644X_EMAC_CNTRL_RAM_SIZE,
 	.version		= EMAC_VERSION_1,
 };
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 8da886b..08db90f 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -358,7 +358,6 @@ static struct emac_platform_data dm646x_emac_pdata = {
 	.ctrl_reg_offset	= DM646X_EMAC_CNTRL_OFFSET,
 	.ctrl_mod_reg_offset	= DM646X_EMAC_CNTRL_MOD_OFFSET,
 	.ctrl_ram_offset	= DM646X_EMAC_CNTRL_RAM_OFFSET,
-	.mdio_reg_offset	= DM646X_EMAC_MDIO_OFFSET,
 	.ctrl_ram_size		= DM646X_EMAC_CNTRL_RAM_SIZE,
 	.version		= EMAC_VERSION_2,
 };
diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h
index dbb5052..2563bf4 100644
--- a/arch/arm/mach-davinci/include/mach/dm365.h
+++ b/arch/arm/mach-davinci/include/mach/dm365.h
@@ -25,7 +25,6 @@
 #define DM365_EMAC_CNTRL_OFFSET		(0x0000)
 #define DM365_EMAC_CNTRL_MOD_OFFSET	(0x3000)
 #define DM365_EMAC_CNTRL_RAM_OFFSET	(0x1000)
-#define DM365_EMAC_MDIO_OFFSET		(0x4000)
 #define DM365_EMAC_CNTRL_RAM_SIZE	(0x2000)
 
 /* Base of key scan register bank */
diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h
index 5159117..5a1b26d 100644
--- a/arch/arm/mach-davinci/include/mach/dm644x.h
+++ b/arch/arm/mach-davinci/include/mach/dm644x.h
@@ -32,7 +32,6 @@
 #define DM644X_EMAC_CNTRL_OFFSET	(0x0000)
 #define DM644X_EMAC_CNTRL_MOD_OFFSET	(0x1000)
 #define DM644X_EMAC_CNTRL_RAM_OFFSET	(0x2000)
-#define DM644X_EMAC_MDIO_OFFSET		(0x4000)
 #define DM644X_EMAC_CNTRL_RAM_SIZE	(0x2000)
 
 #define DM644X_ASYNC_EMIF_CONTROL_BASE	0x01E00000
diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h
index 1c4dca9..7a27f3f 100644
--- a/arch/arm/mach-davinci/include/mach/dm646x.h
+++ b/arch/arm/mach-davinci/include/mach/dm646x.h
@@ -23,7 +23,6 @@
 #define DM646X_EMAC_CNTRL_OFFSET	(0x0000)
 #define DM646X_EMAC_CNTRL_MOD_OFFSET	(0x1000)
 #define DM646X_EMAC_CNTRL_RAM_OFFSET	(0x2000)
-#define DM646X_EMAC_MDIO_OFFSET		(0x4000)
 #define DM646X_EMAC_CNTRL_RAM_SIZE	(0x2000)
 
 #define DM646X_ASYNC_EMIF_CONTROL_BASE	0x20008000
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 06/10] omap: cleanup unused davinci mdio arch code
  2010-09-15 14:11 [PATCH v4 00/10] split out emac cpdma and mdio for reuse Cyril Chemparathy
                   ` (4 preceding siblings ...)
  2010-09-15 14:11 ` [PATCH v4 05/10] davinci: cleanup mdio arch code and switch to phy_id Cyril Chemparathy
@ 2010-09-15 14:11 ` Cyril Chemparathy
  2010-09-15 14:11 ` [PATCH v4 07/10] net: davinci_emac: cleanup unused mdio emac code Cyril Chemparathy
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Cyril Chemparathy @ 2010-09-15 14:11 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

This patch removes davinci architecture code that has now been rendered
useless by the previous patches in the MDIO separation series.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Acked-by: David S. Miller <davem@davemloft.net>
Acked-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/board-am3517evm.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 5dd1b73..5225df6 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -39,7 +39,6 @@
 
 #include "mux.h"
 
-#define AM35XX_EVM_PHY_MASK		(0xF)
 #define AM35XX_EVM_MDIO_FREQUENCY	(1000000)
 
 static struct mdio_platform_data am3517_evm_mdio_pdata = {
@@ -64,8 +63,6 @@ static struct platform_device am3517_mdio_device = {
 };
 
 static struct emac_platform_data am3517_evm_emac_pdata = {
-	.phy_mask	= AM35XX_EVM_PHY_MASK,
-	.mdio_max_freq	= AM35XX_EVM_MDIO_FREQUENCY,
 	.rmii_en	= 1,
 };
 
@@ -135,7 +132,6 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
 	pdata->ctrl_reg_offset		= AM35XX_EMAC_CNTRL_OFFSET;
 	pdata->ctrl_mod_reg_offset	= AM35XX_EMAC_CNTRL_MOD_OFFSET;
 	pdata->ctrl_ram_offset		= AM35XX_EMAC_CNTRL_RAM_OFFSET;
-	pdata->mdio_reg_offset		= AM35XX_EMAC_MDIO_OFFSET;
 	pdata->ctrl_ram_size		= AM35XX_EMAC_CNTRL_RAM_SIZE;
 	pdata->version			= EMAC_VERSION_2;
 	pdata->hw_ram_addr		= AM35XX_EMAC_HW_RAM_ADDR;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 07/10] net: davinci_emac: cleanup unused mdio emac code
  2010-09-15 14:11 [PATCH v4 00/10] split out emac cpdma and mdio for reuse Cyril Chemparathy
                   ` (5 preceding siblings ...)
  2010-09-15 14:11 ` [PATCH v4 06/10] omap: cleanup unused davinci mdio arch code Cyril Chemparathy
@ 2010-09-15 14:11 ` Cyril Chemparathy
  2010-09-15 14:11 ` [PATCH v4 08/10] net: davinci_emac: separate out cpdma code Cyril Chemparathy
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Cyril Chemparathy @ 2010-09-15 14:11 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

This patch removes code that has been rendered useless by the previous patches
in this series.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Acked-by: David S. Miller <davem@davemloft.net>
Tested-by: Michael Williamson <michael.williamson@criticallink.com>
Tested-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 drivers/net/davinci_emac.c   |  107 ------------------------------------------
 include/linux/davinci_emac.h |    3 -
 2 files changed, 0 insertions(+), 110 deletions(-)

diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 997f599..d4298cb 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -113,7 +113,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_DEF_MAX_FRAME_SIZE		(1500 + 14 + 4 + 4)
 #define EMAC_DEF_TX_CH			(0) /* Default 0th channel */
 #define EMAC_DEF_RX_CH			(0) /* Default 0th channel */
-#define EMAC_DEF_MDIO_TICK_MS		(10) /* typically 1 tick=1 ms) */
 #define EMAC_DEF_MAX_TX_CH		(1) /* Max TX channels configured */
 #define EMAC_DEF_MAX_RX_CH		(1) /* Max RX channels configured */
 #define EMAC_POLL_WEIGHT		(64) /* Default NAPI poll weight */
@@ -303,25 +302,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_DM644X_INTMIN_INTVL	0x1
 #define EMAC_DM644X_INTMAX_INTVL	(EMAC_DM644X_EWINTCNT_MASK)
 
-/* EMAC MDIO related */
-/* Mask & Control defines */
-#define MDIO_CONTROL_CLKDIV	(0xFF)
-#define MDIO_CONTROL_ENABLE	BIT(30)
-#define MDIO_USERACCESS_GO	BIT(31)
-#define MDIO_USERACCESS_WRITE	BIT(30)
-#define MDIO_USERACCESS_READ	(0)
-#define MDIO_USERACCESS_REGADR	(0x1F << 21)
-#define MDIO_USERACCESS_PHYADR	(0x1F << 16)
-#define MDIO_USERACCESS_DATA	(0xFFFF)
-#define MDIO_USERPHYSEL_LINKSEL	BIT(7)
-#define MDIO_VER_MODID		(0xFFFF << 16)
-#define MDIO_VER_REVMAJ		(0xFF   << 8)
-#define MDIO_VER_REVMIN		(0xFF)
-
-#define MDIO_USERACCESS(inst)	(0x80 + (inst * 8))
-#define MDIO_USERPHYSEL(inst)	(0x84 + (inst * 8))
-#define MDIO_CONTROL		(0x04)
-
 /* EMAC DM646X control module registers */
 #define EMAC_DM646X_CMINTCTRL	0x0C
 #define EMAC_DM646X_CMRXINTEN	0x14
@@ -493,13 +473,6 @@ struct emac_priv {
 	u32 mac_hash2;
 	u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS];
 	u32 rx_addr_type;
-	/* periodic timer required for MDIO polling */
-	struct timer_list periodic_timer;
-	u32 periodic_ticks;
-	u32 timer_active;
-	u32 phy_mask;
-	/* mii_bus,phy members */
-	struct mii_bus *mii_bus;
 	const char *phy_id;
 	struct phy_device *phydev;
 	spinlock_t lock;
@@ -511,7 +484,6 @@ struct emac_priv {
 /* clock frequency for EMAC */
 static struct clk *emac_clk;
 static unsigned long emac_bus_frequency;
-static unsigned long mdio_max_freq;
 
 #define emac_virt_to_phys(addr, priv) \
 	(((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \
@@ -549,9 +521,6 @@ static char *emac_rxhost_errcodes[16] = {
 #define emac_ctrl_read(reg)	  ioread32((priv->ctrl_base + (reg)))
 #define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg)))
 
-#define emac_mdio_read(reg)	  ioread32(bus->priv + (reg))
-#define emac_mdio_write(reg, val) iowrite32(val, (bus->priv + (reg)))
-
 /**
  * emac_dump_regs: Dump important EMAC registers to debug terminal
  * @priv: The DaVinci EMAC private adapter structure
@@ -657,9 +626,6 @@ static void emac_dump_regs(struct emac_priv *priv)
 		emac_read(EMAC_RXDMAOVERRUNS));
 }
 
-/*************************************************************************
- *  EMAC MDIO/Phy Functionality
- *************************************************************************/
 /**
  * emac_get_drvinfo: Get EMAC driver information
  * @ndev: The DaVinci EMAC network adapter
@@ -2349,79 +2315,6 @@ void emac_poll_controller(struct net_device *ndev)
 }
 #endif
 
-/* PHY/MII bus related */
-
-/* Wait until mdio is ready for next command */
-#define MDIO_WAIT_FOR_USER_ACCESS\
-		while ((emac_mdio_read((MDIO_USERACCESS(0))) &\
-			MDIO_USERACCESS_GO) != 0)
-
-static int emac_mii_read(struct mii_bus *bus, int phy_id, int phy_reg)
-{
-	unsigned int phy_data = 0;
-	unsigned int phy_control;
-
-	/* Wait until mdio is ready for next command */
-	MDIO_WAIT_FOR_USER_ACCESS;
-
-	phy_control = (MDIO_USERACCESS_GO |
-		       MDIO_USERACCESS_READ |
-		       ((phy_reg << 21) & MDIO_USERACCESS_REGADR) |
-		       ((phy_id << 16) & MDIO_USERACCESS_PHYADR) |
-		       (phy_data & MDIO_USERACCESS_DATA));
-	emac_mdio_write(MDIO_USERACCESS(0), phy_control);
-
-	/* Wait until mdio is ready for next command */
-	MDIO_WAIT_FOR_USER_ACCESS;
-
-	return emac_mdio_read(MDIO_USERACCESS(0)) & MDIO_USERACCESS_DATA;
-
-}
-
-static int emac_mii_write(struct mii_bus *bus, int phy_id,
-			  int phy_reg, u16 phy_data)
-{
-
-	unsigned int control;
-
-	/*  until mdio is ready for next command */
-	MDIO_WAIT_FOR_USER_ACCESS;
-
-	control = (MDIO_USERACCESS_GO |
-		   MDIO_USERACCESS_WRITE |
-		   ((phy_reg << 21) & MDIO_USERACCESS_REGADR) |
-		   ((phy_id << 16) & MDIO_USERACCESS_PHYADR) |
-		   (phy_data & MDIO_USERACCESS_DATA));
-	emac_mdio_write(MDIO_USERACCESS(0), control);
-
-	return 0;
-}
-
-static int emac_mii_reset(struct mii_bus *bus)
-{
-	unsigned int clk_div;
-	int mdio_bus_freq = emac_bus_frequency;
-
-	if (mdio_max_freq && mdio_bus_freq)
-		clk_div = ((mdio_bus_freq / mdio_max_freq) - 1);
-	else
-		clk_div = 0xFF;
-
-	clk_div &= MDIO_CONTROL_CLKDIV;
-
-	/* Set enable and clock divider in MDIOControl */
-	emac_mdio_write(MDIO_CONTROL, (clk_div | MDIO_CONTROL_ENABLE));
-
-	return 0;
-
-}
-
-static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, PHY_POLL };
-
-/* emac_driver: EMAC MII bus structure */
-
-static struct mii_bus *emac_mii;
-
 static void emac_adjust_link(struct net_device *ndev)
 {
 	struct emac_priv *priv = netdev_priv(ndev);
diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h
index 46a759f..5dd4285 100644
--- a/include/linux/davinci_emac.h
+++ b/include/linux/davinci_emac.h
@@ -24,10 +24,7 @@ struct emac_platform_data {
 	u32 ctrl_mod_reg_offset;
 	u32 ctrl_ram_offset;
 	u32 hw_ram_addr;
-	u32 mdio_reg_offset;
 	u32 ctrl_ram_size;
-	u32 phy_mask;
-	u32 mdio_max_freq;
 
 	/*
 	 * phy_id can be one of the following:
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 08/10] net: davinci_emac: separate out cpdma code
  2010-09-15 14:11 [PATCH v4 00/10] split out emac cpdma and mdio for reuse Cyril Chemparathy
                   ` (6 preceding siblings ...)
  2010-09-15 14:11 ` [PATCH v4 07/10] net: davinci_emac: cleanup unused mdio emac code Cyril Chemparathy
@ 2010-09-15 14:11 ` Cyril Chemparathy
  2010-09-15 14:11 ` [PATCH v4 09/10] net: davinci_emac: switch to new cpdma layer Cyril Chemparathy
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Cyril Chemparathy @ 2010-09-15 14:11 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

In addition to being embedded into the EMAC controller, the CPDMA hardware
block is used in TI's CPSW switch controller.  Fortunately, the programming
interface to this hardware block remains pretty nicely consistent across these
devices.

This patch adds a new CPDMA services layer, which can then be reused across
EMAC and CPSW drivers.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Tested-by: Michael Williamson <michael.williamson@criticallink.com>
Tested-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 drivers/net/Kconfig         |   10 +
 drivers/net/Makefile        |    1 +
 drivers/net/davinci_cpdma.c |  965 +++++++++++++++++++++++++++++++++++++++++++
 drivers/net/davinci_cpdma.h |  108 +++++
 4 files changed, 1084 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/davinci_cpdma.c
 create mode 100644 drivers/net/davinci_cpdma.h

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 911e7f1..775fd87 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -952,6 +952,7 @@ config TI_DAVINCI_EMAC
 	tristate "TI DaVinci EMAC Support"
 	depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
 	select TI_DAVINCI_MDIO
+	select TI_DAVINCI_CPDMA
 	select PHYLIB
 	help
 	  This driver supports TI's DaVinci Ethernet .
@@ -969,6 +970,15 @@ config TI_DAVINCI_MDIO
 	  To compile this driver as a module, choose M here: the module
 	  will be called davinci_mdio.  This is recommended.
 
+config TI_DAVINCI_CPDMA
+	tristate "TI DaVinci CPDMA Support"
+	depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
+	help
+	  This driver supports TI's DaVinci CPDMA dma engine.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called davinci_cpdma.  This is recommended.
+
 config DM9000
 	tristate "DM9000 support"
 	depends on ARM || BLACKFIN || MIPS
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index d38a7ab..65da885 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_PHYLIB) += phy/
 
 obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
 obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
+obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o
 
 obj-$(CONFIG_E1000) += e1000/
 obj-$(CONFIG_E1000E) += e1000e/
diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c
new file mode 100644
index 0000000..e92b2b6
--- /dev/null
+++ b/drivers/net/davinci_cpdma.c
@@ -0,0 +1,965 @@
+/*
+ * Texas Instruments CPDMA Driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+
+#include "davinci_cpdma.h"
+
+/* DMA Registers */
+#define CPDMA_TXIDVER		0x00
+#define CPDMA_TXCONTROL		0x04
+#define CPDMA_TXTEARDOWN	0x08
+#define CPDMA_RXIDVER		0x10
+#define CPDMA_RXCONTROL		0x14
+#define CPDMA_SOFTRESET		0x1c
+#define CPDMA_RXTEARDOWN	0x18
+#define CPDMA_TXINTSTATRAW	0x80
+#define CPDMA_TXINTSTATMASKED	0x84
+#define CPDMA_TXINTMASKSET	0x88
+#define CPDMA_TXINTMASKCLEAR	0x8c
+#define CPDMA_MACINVECTOR	0x90
+#define CPDMA_MACEOIVECTOR	0x94
+#define CPDMA_RXINTSTATRAW	0xa0
+#define CPDMA_RXINTSTATMASKED	0xa4
+#define CPDMA_RXINTMASKSET	0xa8
+#define CPDMA_RXINTMASKCLEAR	0xac
+#define CPDMA_DMAINTSTATRAW	0xb0
+#define CPDMA_DMAINTSTATMASKED	0xb4
+#define CPDMA_DMAINTMASKSET	0xb8
+#define CPDMA_DMAINTMASKCLEAR	0xbc
+#define CPDMA_DMAINT_HOSTERR	BIT(1)
+
+/* the following exist only if has_ext_regs is set */
+#define CPDMA_DMACONTROL	0x20
+#define CPDMA_DMASTATUS		0x24
+#define CPDMA_RXBUFFOFS		0x28
+#define CPDMA_EM_CONTROL	0x2c
+
+/* Descriptor mode bits */
+#define CPDMA_DESC_SOP		BIT(31)
+#define CPDMA_DESC_EOP		BIT(30)
+#define CPDMA_DESC_OWNER	BIT(29)
+#define CPDMA_DESC_EOQ		BIT(28)
+#define CPDMA_DESC_TD_COMPLETE	BIT(27)
+#define CPDMA_DESC_PASS_CRC	BIT(26)
+
+#define CPDMA_TEARDOWN_VALUE	0xfffffffc
+
+struct cpdma_desc {
+	/* hardware fields */
+	u32			hw_next;
+	u32			hw_buffer;
+	u32			hw_len;
+	u32			hw_mode;
+	/* software fields */
+	void			*sw_token;
+	u32			sw_buffer;
+	u32			sw_len;
+};
+
+struct cpdma_desc_pool {
+	u32			phys;
+	void __iomem		*iomap;		/* ioremap map */
+	void			*cpumap;	/* dma_alloc map */
+	int			desc_size, mem_size;
+	int			num_desc, used_desc;
+	unsigned long		*bitmap;
+	struct device		*dev;
+	spinlock_t		lock;
+};
+
+enum cpdma_state {
+	CPDMA_STATE_IDLE,
+	CPDMA_STATE_ACTIVE,
+	CPDMA_STATE_TEARDOWN,
+};
+
+const char *cpdma_state_str[] = { "idle", "active", "teardown" };
+
+struct cpdma_ctlr {
+	enum cpdma_state	state;
+	struct cpdma_params	params;
+	struct device		*dev;
+	struct cpdma_desc_pool	*pool;
+	spinlock_t		lock;
+	struct cpdma_chan	*channels[2 * CPDMA_MAX_CHANNELS];
+};
+
+struct cpdma_chan {
+	enum cpdma_state		state;
+	struct cpdma_ctlr		*ctlr;
+	int				chan_num;
+	spinlock_t			lock;
+	struct cpdma_desc __iomem	*head, *tail;
+	int				count;
+	void __iomem			*hdp, *cp, *rxfree;
+	u32				mask;
+	cpdma_handler_fn		handler;
+	enum dma_data_direction		dir;
+	struct cpdma_chan_stats		stats;
+	/* offsets into dmaregs */
+	int	int_set, int_clear, td;
+};
+
+/* The following make access to common cpdma_ctlr params more readable */
+#define dmaregs		params.dmaregs
+#define num_chan	params.num_chan
+
+/* various accessors */
+#define dma_reg_read(ctlr, ofs)		__raw_readl((ctlr)->dmaregs + (ofs))
+#define chan_read(chan, fld)		__raw_readl((chan)->fld)
+#define desc_read(desc, fld)		__raw_readl(&(desc)->fld)
+#define dma_reg_write(ctlr, ofs, v)	__raw_writel(v, (ctlr)->dmaregs + (ofs))
+#define chan_write(chan, fld, v)	__raw_writel(v, (chan)->fld)
+#define desc_write(desc, fld, v)	__raw_writel((u32)(v), &(desc)->fld)
+
+/*
+ * Utility constructs for a cpdma descriptor pool.  Some devices (e.g. davinci
+ * emac) have dedicated on-chip memory for these descriptors.  Some other
+ * devices (e.g. cpsw switches) use plain old memory.  Descriptor pools
+ * abstract out these details
+ */
+static struct cpdma_desc_pool *
+cpdma_desc_pool_create(struct device *dev, u32 phys, int size, int align)
+{
+	int bitmap_size;
+	struct cpdma_desc_pool *pool;
+
+	pool = kzalloc(sizeof(*pool), GFP_KERNEL);
+	if (!pool)
+		return NULL;
+
+	spin_lock_init(&pool->lock);
+
+	pool->dev	= dev;
+	pool->mem_size	= size;
+	pool->desc_size	= ALIGN(sizeof(struct cpdma_desc), align);
+	pool->num_desc	= size / pool->desc_size;
+
+	bitmap_size  = (pool->num_desc / BITS_PER_LONG) * sizeof(long);
+	pool->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+	if (!pool->bitmap)
+		goto fail;
+
+	if (phys) {
+		pool->phys  = phys;
+		pool->iomap = ioremap(phys, size);
+	} else {
+		pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys,
+						  GFP_KERNEL);
+		pool->iomap = (void __force __iomem *)pool->cpumap;
+	}
+
+	if (pool->iomap)
+		return pool;
+
+fail:
+	kfree(pool->bitmap);
+	kfree(pool);
+	return NULL;
+}
+
+static void cpdma_desc_pool_destroy(struct cpdma_desc_pool *pool)
+{
+	unsigned long flags;
+
+	if (!pool)
+		return;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	WARN_ON(pool->used_desc);
+	kfree(pool->bitmap);
+	if (pool->cpumap) {
+		dma_free_coherent(pool->dev, pool->mem_size, pool->cpumap,
+				  pool->phys);
+	} else {
+		iounmap(pool->iomap);
+	}
+	spin_unlock_irqrestore(&pool->lock, flags);
+	kfree(pool);
+}
+
+static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool,
+		  struct cpdma_desc __iomem *desc)
+{
+	if (!desc)
+		return 0;
+	return pool->phys + (__force dma_addr_t)desc -
+			    (__force dma_addr_t)pool->iomap;
+}
+
+static inline struct cpdma_desc __iomem *
+desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma)
+{
+	return dma ? pool->iomap + dma - pool->phys : NULL;
+}
+
+static struct cpdma_desc __iomem *
+cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc)
+{
+	unsigned long flags;
+	int index;
+	struct cpdma_desc __iomem *desc = NULL;
+
+	spin_lock_irqsave(&pool->lock, flags);
+
+	index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0,
+					   num_desc, 0);
+	if (index < pool->num_desc) {
+		bitmap_set(pool->bitmap, index, num_desc);
+		desc = pool->iomap + pool->desc_size * index;
+		pool->used_desc++;
+	}
+
+	spin_unlock_irqrestore(&pool->lock, flags);
+	return desc;
+}
+
+static void cpdma_desc_free(struct cpdma_desc_pool *pool,
+			    struct cpdma_desc __iomem *desc, int num_desc)
+{
+	unsigned long flags, index;
+
+	index = ((unsigned long)desc - (unsigned long)pool->iomap) /
+		pool->desc_size;
+	spin_lock_irqsave(&pool->lock, flags);
+	bitmap_clear(pool->bitmap, index, num_desc);
+	pool->used_desc--;
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params)
+{
+	struct cpdma_ctlr *ctlr;
+
+	ctlr = kzalloc(sizeof(*ctlr), GFP_KERNEL);
+	if (!ctlr)
+		return NULL;
+
+	ctlr->state = CPDMA_STATE_IDLE;
+	ctlr->params = *params;
+	ctlr->dev = params->dev;
+	spin_lock_init(&ctlr->lock);
+
+	ctlr->pool = cpdma_desc_pool_create(ctlr->dev,
+					    ctlr->params.desc_mem_phys,
+					    ctlr->params.desc_mem_size,
+					    ctlr->params.desc_align);
+	if (!ctlr->pool) {
+		kfree(ctlr);
+		return NULL;
+	}
+
+	if (WARN_ON(ctlr->num_chan > CPDMA_MAX_CHANNELS))
+		ctlr->num_chan = CPDMA_MAX_CHANNELS;
+	return ctlr;
+}
+
+int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)
+{
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+	if (ctlr->state != CPDMA_STATE_IDLE) {
+		spin_unlock_irqrestore(&ctlr->lock, flags);
+		return -EBUSY;
+	}
+
+	if (ctlr->params.has_soft_reset) {
+		unsigned long timeout = jiffies + HZ/10;
+
+		dma_reg_write(ctlr, CPDMA_SOFTRESET, 1);
+		while (time_before(jiffies, timeout)) {
+			if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0)
+				break;
+		}
+		WARN_ON(!time_before(jiffies, timeout));
+	}
+
+	for (i = 0; i < ctlr->num_chan; i++) {
+		__raw_writel(0, ctlr->params.txhdp + 4 * i);
+		__raw_writel(0, ctlr->params.rxhdp + 4 * i);
+		__raw_writel(0, ctlr->params.txcp + 4 * i);
+		__raw_writel(0, ctlr->params.rxcp + 4 * i);
+	}
+
+	dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff);
+	dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff);
+
+	dma_reg_write(ctlr, CPDMA_TXCONTROL, 1);
+	dma_reg_write(ctlr, CPDMA_RXCONTROL, 1);
+
+	ctlr->state = CPDMA_STATE_ACTIVE;
+
+	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
+		if (ctlr->channels[i])
+			cpdma_chan_start(ctlr->channels[i]);
+	}
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	return 0;
+}
+
+int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
+{
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+	if (ctlr->state != CPDMA_STATE_ACTIVE) {
+		spin_unlock_irqrestore(&ctlr->lock, flags);
+		return -EINVAL;
+	}
+
+	ctlr->state = CPDMA_STATE_TEARDOWN;
+
+	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
+		if (ctlr->channels[i])
+			cpdma_chan_stop(ctlr->channels[i]);
+	}
+
+	dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff);
+	dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff);
+
+	dma_reg_write(ctlr, CPDMA_TXCONTROL, 0);
+	dma_reg_write(ctlr, CPDMA_RXCONTROL, 0);
+
+	ctlr->state = CPDMA_STATE_IDLE;
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	return 0;
+}
+
+int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr)
+{
+	struct device *dev = ctlr->dev;
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	dev_info(dev, "CPDMA: state: %s", cpdma_state_str[ctlr->state]);
+
+	dev_info(dev, "CPDMA: txidver: %x",
+		 dma_reg_read(ctlr, CPDMA_TXIDVER));
+	dev_info(dev, "CPDMA: txcontrol: %x",
+		 dma_reg_read(ctlr, CPDMA_TXCONTROL));
+	dev_info(dev, "CPDMA: txteardown: %x",
+		 dma_reg_read(ctlr, CPDMA_TXTEARDOWN));
+	dev_info(dev, "CPDMA: rxidver: %x",
+		 dma_reg_read(ctlr, CPDMA_RXIDVER));
+	dev_info(dev, "CPDMA: rxcontrol: %x",
+		 dma_reg_read(ctlr, CPDMA_RXCONTROL));
+	dev_info(dev, "CPDMA: softreset: %x",
+		 dma_reg_read(ctlr, CPDMA_SOFTRESET));
+	dev_info(dev, "CPDMA: rxteardown: %x",
+		 dma_reg_read(ctlr, CPDMA_RXTEARDOWN));
+	dev_info(dev, "CPDMA: txintstatraw: %x",
+		 dma_reg_read(ctlr, CPDMA_TXINTSTATRAW));
+	dev_info(dev, "CPDMA: txintstatmasked: %x",
+		 dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED));
+	dev_info(dev, "CPDMA: txintmaskset: %x",
+		 dma_reg_read(ctlr, CPDMA_TXINTMASKSET));
+	dev_info(dev, "CPDMA: txintmaskclear: %x",
+		 dma_reg_read(ctlr, CPDMA_TXINTMASKCLEAR));
+	dev_info(dev, "CPDMA: macinvector: %x",
+		 dma_reg_read(ctlr, CPDMA_MACINVECTOR));
+	dev_info(dev, "CPDMA: maceoivector: %x",
+		 dma_reg_read(ctlr, CPDMA_MACEOIVECTOR));
+	dev_info(dev, "CPDMA: rxintstatraw: %x",
+		 dma_reg_read(ctlr, CPDMA_RXINTSTATRAW));
+	dev_info(dev, "CPDMA: rxintstatmasked: %x",
+		 dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED));
+	dev_info(dev, "CPDMA: rxintmaskset: %x",
+		 dma_reg_read(ctlr, CPDMA_RXINTMASKSET));
+	dev_info(dev, "CPDMA: rxintmaskclear: %x",
+		 dma_reg_read(ctlr, CPDMA_RXINTMASKCLEAR));
+	dev_info(dev, "CPDMA: dmaintstatraw: %x",
+		 dma_reg_read(ctlr, CPDMA_DMAINTSTATRAW));
+	dev_info(dev, "CPDMA: dmaintstatmasked: %x",
+		 dma_reg_read(ctlr, CPDMA_DMAINTSTATMASKED));
+	dev_info(dev, "CPDMA: dmaintmaskset: %x",
+		 dma_reg_read(ctlr, CPDMA_DMAINTMASKSET));
+	dev_info(dev, "CPDMA: dmaintmaskclear: %x",
+		 dma_reg_read(ctlr, CPDMA_DMAINTMASKCLEAR));
+
+	if (!ctlr->params.has_ext_regs) {
+		dev_info(dev, "CPDMA: dmacontrol: %x",
+			 dma_reg_read(ctlr, CPDMA_DMACONTROL));
+		dev_info(dev, "CPDMA: dmastatus: %x",
+			 dma_reg_read(ctlr, CPDMA_DMASTATUS));
+		dev_info(dev, "CPDMA: rxbuffofs: %x",
+			 dma_reg_read(ctlr, CPDMA_RXBUFFOFS));
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++)
+		if (ctlr->channels[i])
+			cpdma_chan_dump(ctlr->channels[i]);
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	return 0;
+}
+
+int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)
+{
+	unsigned long flags;
+	int ret = 0, i;
+
+	if (!ctlr)
+		return -EINVAL;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+	if (ctlr->state != CPDMA_STATE_IDLE)
+		cpdma_ctlr_stop(ctlr);
+
+	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
+		if (ctlr->channels[i])
+			cpdma_chan_destroy(ctlr->channels[i]);
+	}
+
+	cpdma_desc_pool_destroy(ctlr->pool);
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	kfree(ctlr);
+	return ret;
+}
+
+int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
+{
+	unsigned long flags;
+	int i, reg;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+	if (ctlr->state != CPDMA_STATE_ACTIVE) {
+		spin_unlock_irqrestore(&ctlr->lock, flags);
+		return -EINVAL;
+	}
+
+	reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR;
+	dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR);
+
+	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
+		if (ctlr->channels[i])
+			cpdma_chan_int_ctrl(ctlr->channels[i], enable);
+	}
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	return 0;
+}
+
+void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr)
+{
+	dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0);
+}
+
+struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
+				     cpdma_handler_fn handler)
+{
+	struct cpdma_chan *chan;
+	int ret, offset = (chan_num % CPDMA_MAX_CHANNELS) * 4;
+	unsigned long flags;
+
+	if (__chan_linear(chan_num) >= ctlr->num_chan)
+		return NULL;
+
+	ret = -ENOMEM;
+	chan = kzalloc(sizeof(*chan), GFP_KERNEL);
+	if (!chan)
+		goto err_chan_alloc;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+	ret = -EBUSY;
+	if (ctlr->channels[chan_num])
+		goto err_chan_busy;
+
+	chan->ctlr	= ctlr;
+	chan->state	= CPDMA_STATE_IDLE;
+	chan->chan_num	= chan_num;
+	chan->handler	= handler;
+
+	if (is_rx_chan(chan)) {
+		chan->hdp	= ctlr->params.rxhdp + offset;
+		chan->cp	= ctlr->params.rxcp + offset;
+		chan->rxfree	= ctlr->params.rxfree + offset;
+		chan->int_set	= CPDMA_RXINTMASKSET;
+		chan->int_clear	= CPDMA_RXINTMASKCLEAR;
+		chan->td	= CPDMA_RXTEARDOWN;
+		chan->dir	= DMA_FROM_DEVICE;
+	} else {
+		chan->hdp	= ctlr->params.txhdp + offset;
+		chan->cp	= ctlr->params.txcp + offset;
+		chan->int_set	= CPDMA_TXINTMASKSET;
+		chan->int_clear	= CPDMA_TXINTMASKCLEAR;
+		chan->td	= CPDMA_TXTEARDOWN;
+		chan->dir	= DMA_TO_DEVICE;
+	}
+	chan->mask = BIT(chan_linear(chan));
+
+	spin_lock_init(&chan->lock);
+
+	ctlr->channels[chan_num] = chan;
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	return chan;
+
+err_chan_busy:
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	kfree(chan);
+err_chan_alloc:
+	return ERR_PTR(ret);
+}
+
+int cpdma_chan_destroy(struct cpdma_chan *chan)
+{
+	struct cpdma_ctlr *ctlr = chan->ctlr;
+	unsigned long flags;
+
+	if (!chan)
+		return -EINVAL;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+	if (chan->state != CPDMA_STATE_IDLE)
+		cpdma_chan_stop(chan);
+	ctlr->channels[chan->chan_num] = NULL;
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	kfree(chan);
+	return 0;
+}
+
+int cpdma_chan_get_stats(struct cpdma_chan *chan,
+			 struct cpdma_chan_stats *stats)
+{
+	unsigned long flags;
+	if (!chan)
+		return -EINVAL;
+	spin_lock_irqsave(&chan->lock, flags);
+	memcpy(stats, &chan->stats, sizeof(*stats));
+	spin_unlock_irqrestore(&chan->lock, flags);
+	return 0;
+}
+
+int cpdma_chan_dump(struct cpdma_chan *chan)
+{
+	unsigned long flags;
+	struct device *dev = chan->ctlr->dev;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	dev_info(dev, "channel %d (%s %d) state %s",
+		 chan->chan_num, is_rx_chan(chan) ? "rx" : "tx",
+		 chan_linear(chan), cpdma_state_str[chan->state]);
+	dev_info(dev, "\thdp: %x\n", chan_read(chan, hdp));
+	dev_info(dev, "\tcp: %x\n", chan_read(chan, cp));
+	if (chan->rxfree) {
+		dev_info(dev, "\trxfree: %x\n",
+			 chan_read(chan, rxfree));
+	}
+
+	dev_info(dev, "\tstats head_enqueue: %d\n",
+		 chan->stats.head_enqueue);
+	dev_info(dev, "\tstats tail_enqueue: %d\n",
+		 chan->stats.tail_enqueue);
+	dev_info(dev, "\tstats pad_enqueue: %d\n",
+		 chan->stats.pad_enqueue);
+	dev_info(dev, "\tstats misqueued: %d\n",
+		 chan->stats.misqueued);
+	dev_info(dev, "\tstats desc_alloc_fail: %d\n",
+		 chan->stats.desc_alloc_fail);
+	dev_info(dev, "\tstats pad_alloc_fail: %d\n",
+		 chan->stats.pad_alloc_fail);
+	dev_info(dev, "\tstats runt_receive_buff: %d\n",
+		 chan->stats.runt_receive_buff);
+	dev_info(dev, "\tstats runt_transmit_buff: %d\n",
+		 chan->stats.runt_transmit_buff);
+	dev_info(dev, "\tstats empty_dequeue: %d\n",
+		 chan->stats.empty_dequeue);
+	dev_info(dev, "\tstats busy_dequeue: %d\n",
+		 chan->stats.busy_dequeue);
+	dev_info(dev, "\tstats good_dequeue: %d\n",
+		 chan->stats.good_dequeue);
+	dev_info(dev, "\tstats requeue: %d\n",
+		 chan->stats.requeue);
+	dev_info(dev, "\tstats teardown_dequeue: %d\n",
+		 chan->stats.teardown_dequeue);
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+	return 0;
+}
+
+static void __cpdma_chan_submit(struct cpdma_chan *chan,
+				struct cpdma_desc __iomem *desc)
+{
+	struct cpdma_ctlr		*ctlr = chan->ctlr;
+	struct cpdma_desc __iomem	*prev = chan->tail;
+	struct cpdma_desc_pool		*pool = ctlr->pool;
+	dma_addr_t			desc_dma;
+	u32				mode;
+
+	desc_dma = desc_phys(pool, desc);
+
+	/* simple case - idle channel */
+	if (!chan->head) {
+		chan->stats.head_enqueue++;
+		chan->head = desc;
+		chan->tail = desc;
+		if (chan->state == CPDMA_STATE_ACTIVE)
+			chan_write(chan, hdp, desc_dma);
+		return;
+	}
+
+	/* first chain the descriptor at the tail of the list */
+	desc_write(prev, hw_next, desc_dma);
+	chan->tail = desc;
+	chan->stats.tail_enqueue++;
+
+	/* next check if EOQ has been triggered already */
+	mode = desc_read(prev, hw_mode);
+	if (((mode & (CPDMA_DESC_EOQ | CPDMA_DESC_OWNER)) == CPDMA_DESC_EOQ) &&
+	    (chan->state == CPDMA_STATE_ACTIVE)) {
+		desc_write(prev, hw_mode, mode & ~CPDMA_DESC_EOQ);
+		chan_write(chan, hdp, desc_dma);
+		chan->stats.misqueued++;
+	}
+}
+
+int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
+		      int len, gfp_t gfp_mask)
+{
+	struct cpdma_ctlr		*ctlr = chan->ctlr;
+	struct cpdma_desc __iomem	*desc;
+	dma_addr_t			buffer;
+	unsigned long			flags;
+	u32				mode;
+	int				ret = 0;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	if (chan->state == CPDMA_STATE_TEARDOWN) {
+		ret = -EINVAL;
+		goto unlock_ret;
+	}
+
+	desc = cpdma_desc_alloc(ctlr->pool, 1);
+	if (!desc) {
+		chan->stats.desc_alloc_fail++;
+		ret = -ENOMEM;
+		goto unlock_ret;
+	}
+
+	if (len < ctlr->params.min_packet_size) {
+		len = ctlr->params.min_packet_size;
+		chan->stats.runt_transmit_buff++;
+	}
+
+	buffer = dma_map_single(ctlr->dev, data, len, chan->dir);
+	mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
+
+	desc_write(desc, hw_next,   0);
+	desc_write(desc, hw_buffer, buffer);
+	desc_write(desc, hw_len,    len);
+	desc_write(desc, hw_mode,   mode | len);
+	desc_write(desc, sw_token,  token);
+	desc_write(desc, sw_buffer, buffer);
+	desc_write(desc, sw_len,    len);
+
+	__cpdma_chan_submit(chan, desc);
+
+	if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree)
+		chan_write(chan, rxfree, 1);
+
+	chan->count++;
+
+unlock_ret:
+	spin_unlock_irqrestore(&chan->lock, flags);
+	return ret;
+}
+
+static void __cpdma_chan_free(struct cpdma_chan *chan,
+			      struct cpdma_desc __iomem *desc,
+			      int outlen, int status)
+{
+	struct cpdma_ctlr		*ctlr = chan->ctlr;
+	struct cpdma_desc_pool		*pool = ctlr->pool;
+	dma_addr_t			buff_dma;
+	int				origlen;
+	void				*token;
+
+	token      = (void *)desc_read(desc, sw_token);
+	buff_dma   = desc_read(desc, sw_buffer);
+	origlen    = desc_read(desc, sw_len);
+
+	dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir);
+	cpdma_desc_free(pool, desc, 1);
+	(*chan->handler)(token, outlen, status);
+}
+
+static int __cpdma_chan_process(struct cpdma_chan *chan)
+{
+	struct cpdma_ctlr		*ctlr = chan->ctlr;
+	struct cpdma_desc __iomem	*desc;
+	int				status, outlen;
+	struct cpdma_desc_pool		*pool = ctlr->pool;
+	dma_addr_t			desc_dma;
+	unsigned long			flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	desc = chan->head;
+	if (!desc) {
+		chan->stats.empty_dequeue++;
+		status = -ENOENT;
+		goto unlock_ret;
+	}
+	desc_dma = desc_phys(pool, desc);
+
+	status	= __raw_readl(&desc->hw_mode);
+	outlen	= status & 0x7ff;
+	if (status & CPDMA_DESC_OWNER) {
+		chan->stats.busy_dequeue++;
+		status = -EBUSY;
+		goto unlock_ret;
+	}
+	status	= status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE);
+
+	chan->head = desc_from_phys(pool, desc_read(desc, hw_next));
+	chan_write(chan, cp, desc_dma);
+	chan->count--;
+	chan->stats.good_dequeue++;
+
+	if (status & CPDMA_DESC_EOQ) {
+		chan->stats.requeue++;
+		chan_write(chan, hdp, desc_phys(pool, chan->head));
+	}
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	__cpdma_chan_free(chan, desc, outlen, status);
+	return status;
+
+unlock_ret:
+	spin_unlock_irqrestore(&chan->lock, flags);
+	return status;
+}
+
+int cpdma_chan_process(struct cpdma_chan *chan, int quota)
+{
+	int used = 0, ret = 0;
+
+	if (chan->state != CPDMA_STATE_ACTIVE)
+		return -EINVAL;
+
+	while (used < quota) {
+		ret = __cpdma_chan_process(chan);
+		if (ret < 0)
+			break;
+		used++;
+	}
+	return used;
+}
+
+int cpdma_chan_start(struct cpdma_chan *chan)
+{
+	struct cpdma_ctlr	*ctlr = chan->ctlr;
+	struct cpdma_desc_pool	*pool = ctlr->pool;
+	unsigned long		flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+	if (chan->state != CPDMA_STATE_IDLE) {
+		spin_unlock_irqrestore(&chan->lock, flags);
+		return -EBUSY;
+	}
+	if (ctlr->state != CPDMA_STATE_ACTIVE) {
+		spin_unlock_irqrestore(&chan->lock, flags);
+		return -EINVAL;
+	}
+	dma_reg_write(ctlr, chan->int_set, chan->mask);
+	chan->state = CPDMA_STATE_ACTIVE;
+	if (chan->head) {
+		chan_write(chan, hdp, desc_phys(pool, chan->head));
+		if (chan->rxfree)
+			chan_write(chan, rxfree, chan->count);
+	}
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+	return 0;
+}
+
+int cpdma_chan_stop(struct cpdma_chan *chan)
+{
+	struct cpdma_ctlr	*ctlr = chan->ctlr;
+	struct cpdma_desc_pool	*pool = ctlr->pool;
+	unsigned long		flags;
+	int			ret;
+	unsigned long		timeout;
+
+	spin_lock_irqsave(&chan->lock, flags);
+	if (chan->state != CPDMA_STATE_ACTIVE) {
+		spin_unlock_irqrestore(&chan->lock, flags);
+		return -EINVAL;
+	}
+
+	chan->state = CPDMA_STATE_TEARDOWN;
+	dma_reg_write(ctlr, chan->int_clear, chan->mask);
+
+	/* trigger teardown */
+	dma_reg_write(ctlr, chan->td, chan->chan_num);
+
+	/* wait for teardown complete */
+	timeout = jiffies + HZ/10;	/* 100 msec */
+	while (time_before(jiffies, timeout)) {
+		u32 cp = chan_read(chan, cp);
+		if ((cp & CPDMA_TEARDOWN_VALUE) == CPDMA_TEARDOWN_VALUE)
+			break;
+		cpu_relax();
+	}
+	WARN_ON(!time_before(jiffies, timeout));
+	chan_write(chan, cp, CPDMA_TEARDOWN_VALUE);
+
+	/* handle completed packets */
+	do {
+		ret = __cpdma_chan_process(chan);
+		if (ret < 0)
+			break;
+	} while ((ret & CPDMA_DESC_TD_COMPLETE) == 0);
+
+	/* remaining packets haven't been tx/rx'ed, clean them up */
+	while (chan->head) {
+		struct cpdma_desc __iomem *desc = chan->head;
+		dma_addr_t next_dma;
+
+		next_dma = desc_read(desc, hw_next);
+		chan->head = desc_from_phys(pool, next_dma);
+		chan->stats.teardown_dequeue++;
+
+		/* issue callback without locks held */
+		spin_unlock_irqrestore(&chan->lock, flags);
+		__cpdma_chan_free(chan, desc, 0, -ENOSYS);
+		spin_lock_irqsave(&chan->lock, flags);
+	}
+
+	chan->state = CPDMA_STATE_IDLE;
+	spin_unlock_irqrestore(&chan->lock, flags);
+	return 0;
+}
+
+int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+	if (chan->state != CPDMA_STATE_ACTIVE) {
+		spin_unlock_irqrestore(&chan->lock, flags);
+		return -EINVAL;
+	}
+
+	dma_reg_write(chan->ctlr, enable ? chan->int_set : chan->int_clear,
+		      chan->mask);
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	return 0;
+}
+
+struct cpdma_control_info {
+	u32		reg;
+	u32		shift, mask;
+	int		access;
+#define ACCESS_RO	BIT(0)
+#define ACCESS_WO	BIT(1)
+#define ACCESS_RW	(ACCESS_RO | ACCESS_WO)
+};
+
+struct cpdma_control_info controls[] = {
+	[CPDMA_CMD_IDLE]	  = {CPDMA_DMACONTROL,	3,  1,      ACCESS_WO},
+	[CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL,	4,  1,      ACCESS_RW},
+	[CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL,	2,  1,      ACCESS_RW},
+	[CPDMA_RX_OWNERSHIP_FLIP] = {CPDMA_DMACONTROL,	1,  1,      ACCESS_RW},
+	[CPDMA_TX_PRIO_FIXED]	  = {CPDMA_DMACONTROL,	0,  1,      ACCESS_RW},
+	[CPDMA_STAT_IDLE]	  = {CPDMA_DMASTATUS,	31, 1,      ACCESS_RO},
+	[CPDMA_STAT_TX_ERR_CODE]  = {CPDMA_DMASTATUS,	20, 0xf,    ACCESS_RW},
+	[CPDMA_STAT_TX_ERR_CHAN]  = {CPDMA_DMASTATUS,	16, 0x7,    ACCESS_RW},
+	[CPDMA_STAT_RX_ERR_CODE]  = {CPDMA_DMASTATUS,	12, 0xf,    ACCESS_RW},
+	[CPDMA_STAT_RX_ERR_CHAN]  = {CPDMA_DMASTATUS,	8,  0x7,    ACCESS_RW},
+	[CPDMA_RX_BUFFER_OFFSET]  = {CPDMA_RXBUFFOFS,	0,  0xffff, ACCESS_RW},
+};
+
+int cpdma_control_get(struct cpdma_ctlr *ctlr, int control)
+{
+	unsigned long flags;
+	struct cpdma_control_info *info = &controls[control];
+	int ret;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	ret = -ENOTSUPP;
+	if (!ctlr->params.has_ext_regs)
+		goto unlock_ret;
+
+	ret = -EINVAL;
+	if (ctlr->state != CPDMA_STATE_ACTIVE)
+		goto unlock_ret;
+
+	ret = -ENOENT;
+	if (control < 0 || control >= ARRAY_SIZE(controls))
+		goto unlock_ret;
+
+	ret = -EPERM;
+	if ((info->access & ACCESS_RO) != ACCESS_RO)
+		goto unlock_ret;
+
+	ret = (dma_reg_read(ctlr, info->reg) >> info->shift) & info->mask;
+
+unlock_ret:
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	return ret;
+}
+
+int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value)
+{
+	unsigned long flags;
+	struct cpdma_control_info *info = &controls[control];
+	int ret;
+	u32 val;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	ret = -ENOTSUPP;
+	if (!ctlr->params.has_ext_regs)
+		goto unlock_ret;
+
+	ret = -EINVAL;
+	if (ctlr->state != CPDMA_STATE_ACTIVE)
+		goto unlock_ret;
+
+	ret = -ENOENT;
+	if (control < 0 || control >= ARRAY_SIZE(controls))
+		goto unlock_ret;
+
+	ret = -EPERM;
+	if ((info->access & ACCESS_WO) != ACCESS_WO)
+		goto unlock_ret;
+
+	val  = dma_reg_read(ctlr, info->reg);
+	val &= ~(info->mask << info->shift);
+	val |= (value & info->mask) << info->shift;
+	dma_reg_write(ctlr, info->reg, val);
+	ret = 0;
+
+unlock_ret:
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	return ret;
+}
diff --git a/drivers/net/davinci_cpdma.h b/drivers/net/davinci_cpdma.h
new file mode 100644
index 0000000..868e50e
--- /dev/null
+++ b/drivers/net/davinci_cpdma.h
@@ -0,0 +1,108 @@
+/*
+ * Texas Instruments CPDMA Driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __DAVINCI_CPDMA_H__
+#define __DAVINCI_CPDMA_H__
+
+#define CPDMA_MAX_CHANNELS	BITS_PER_LONG
+
+#define tx_chan_num(chan)	(chan)
+#define rx_chan_num(chan)	((chan) + CPDMA_MAX_CHANNELS)
+#define is_rx_chan(chan)	((chan)->chan_num >= CPDMA_MAX_CHANNELS)
+#define is_tx_chan(chan)	(!is_rx_chan(chan))
+#define __chan_linear(chan_num)	((chan_num) & (CPDMA_MAX_CHANNELS - 1))
+#define chan_linear(chan)	__chan_linear((chan)->chan_num)
+
+struct cpdma_params {
+	struct device		*dev;
+	void __iomem		*dmaregs;
+	void __iomem		*txhdp, *rxhdp, *txcp, *rxcp;
+	void __iomem		*rxthresh, *rxfree;
+	int			num_chan;
+	bool			has_soft_reset;
+	int			min_packet_size;
+	u32			desc_mem_phys;
+	int			desc_mem_size;
+	int			desc_align;
+
+	/*
+	 * Some instances of embedded cpdma controllers have extra control and
+	 * status registers.  The following flag enables access to these
+	 * "extended" registers.
+	 */
+	bool			has_ext_regs;
+};
+
+struct cpdma_chan_stats {
+	u32			head_enqueue;
+	u32			tail_enqueue;
+	u32			pad_enqueue;
+	u32			misqueued;
+	u32			desc_alloc_fail;
+	u32			pad_alloc_fail;
+	u32			runt_receive_buff;
+	u32			runt_transmit_buff;
+	u32			empty_dequeue;
+	u32			busy_dequeue;
+	u32			good_dequeue;
+	u32			requeue;
+	u32			teardown_dequeue;
+};
+
+struct cpdma_ctlr;
+struct cpdma_chan;
+
+typedef void (*cpdma_handler_fn)(void *token, int len, int status);
+
+struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params);
+int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr);
+int cpdma_ctlr_start(struct cpdma_ctlr *ctlr);
+int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr);
+int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr);
+
+struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
+				     cpdma_handler_fn handler);
+int cpdma_chan_destroy(struct cpdma_chan *chan);
+int cpdma_chan_start(struct cpdma_chan *chan);
+int cpdma_chan_stop(struct cpdma_chan *chan);
+int cpdma_chan_dump(struct cpdma_chan *chan);
+
+int cpdma_chan_get_stats(struct cpdma_chan *chan,
+			 struct cpdma_chan_stats *stats);
+int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
+		      int len, gfp_t gfp_mask);
+int cpdma_chan_process(struct cpdma_chan *chan, int quota);
+
+int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable);
+void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr);
+int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable);
+
+enum cpdma_control {
+	CPDMA_CMD_IDLE,			/* write-only */
+	CPDMA_COPY_ERROR_FRAMES,	/* read-write */
+	CPDMA_RX_OFF_LEN_UPDATE,	/* read-write */
+	CPDMA_RX_OWNERSHIP_FLIP,	/* read-write */
+	CPDMA_TX_PRIO_FIXED,		/* read-write */
+	CPDMA_STAT_IDLE,		/* read-only */
+	CPDMA_STAT_TX_ERR_CHAN,		/* read-only */
+	CPDMA_STAT_TX_ERR_CODE,		/* read-only */
+	CPDMA_STAT_RX_ERR_CHAN,		/* read-only */
+	CPDMA_STAT_RX_ERR_CODE,		/* read-only */
+	CPDMA_RX_BUFFER_OFFSET,		/* read-write */
+};
+
+int cpdma_control_get(struct cpdma_ctlr *ctlr, int control);
+int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value);
+
+#endif
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 09/10] net: davinci_emac: switch to new cpdma layer
  2010-09-15 14:11 [PATCH v4 00/10] split out emac cpdma and mdio for reuse Cyril Chemparathy
                   ` (7 preceding siblings ...)
  2010-09-15 14:11 ` [PATCH v4 08/10] net: davinci_emac: separate out cpdma code Cyril Chemparathy
@ 2010-09-15 14:11 ` Cyril Chemparathy
  2010-09-15 14:11 ` [PATCH v4 10/10] net: davinci_emac: cleanup unused cpdma code Cyril Chemparathy
  2010-09-15 14:54 ` [PATCH v4 00/10] split out emac cpdma and mdio for reuse Kevin Hilman
  10 siblings, 0 replies; 13+ messages in thread
From: Cyril Chemparathy @ 2010-09-15 14:11 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

This patch hooks up the emac driver with the newly separated cpdma driver.

Key differences introduced here:

 - The old buffer list scheme is no longer required

 - The original code maintained mac address per rx channel, even if only one
   rx channel was being used.  With this change, mac address is maintained
   device wide.  If support for multiple rx channels is added in future, this
   will need to be reworked a bit.

 - The new CPDMA code handles short packets better than before.  The
   earlier code was adjusting the length up, without ensuring that the tail
   end of the padding was cleared - a possible security issue.  This has been
   fixed to use skb_padto().

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Tested-by: Michael Williamson <michael.williamson@criticallink.com>
Tested-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 drivers/net/davinci_emac.c |  249 +++++++++++++++++++++++++++++---------------
 1 files changed, 164 insertions(+), 85 deletions(-)

diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index d4298cb..67dbcfb 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -63,6 +63,8 @@
 #include <asm/irq.h>
 #include <asm/page.h>
 
+#include "davinci_cpdma.h"
+
 static int debug_level;
 module_param(debug_level, int, 0);
 MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)");
@@ -113,6 +115,7 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_DEF_MAX_FRAME_SIZE		(1500 + 14 + 4 + 4)
 #define EMAC_DEF_TX_CH			(0) /* Default 0th channel */
 #define EMAC_DEF_RX_CH			(0) /* Default 0th channel */
+#define EMAC_DEF_RX_NUM_DESC		(128)
 #define EMAC_DEF_MAX_TX_CH		(1) /* Max TX channels configured */
 #define EMAC_DEF_MAX_RX_CH		(1) /* Max RX channels configured */
 #define EMAC_POLL_WEIGHT		(64) /* Default NAPI poll weight */
@@ -460,6 +463,9 @@ struct emac_priv {
 	u32 hw_ram_addr;
 	struct emac_txch *txch[EMAC_DEF_MAX_TX_CH];
 	struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH];
+	struct cpdma_ctlr *dma;
+	struct cpdma_chan *txchan;
+	struct cpdma_chan *rxchan;
 	u32 link; /* 1=link on, 0=link off */
 	u32 speed; /* 0=Auto Neg, 1=No PHY, 10,100, 1000 - mbps */
 	u32 duplex; /* Link duplex: 0=Half, 1=Full */
@@ -624,6 +630,8 @@ static void emac_dump_regs(struct emac_priv *priv)
 		emac_read(EMAC_RXMOFOVERRUNS));
 	dev_info(emac_dev, "EMAC: rx_dma_overruns:%d\n",
 		emac_read(EMAC_RXDMAOVERRUNS));
+
+	cpdma_ctlr_dump(priv->dma);
 }
 
 /**
@@ -1151,6 +1159,70 @@ static irqreturn_t emac_irq(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static struct sk_buff *emac_rx_alloc(struct emac_priv *priv)
+{
+	struct sk_buff *skb = dev_alloc_skb(priv->rx_buf_size);
+	if (WARN_ON(!skb))
+		return NULL;
+	skb->dev = priv->ndev;
+	skb_reserve(skb, NET_IP_ALIGN);
+	return skb;
+}
+
+static void emac_rx_handler(void *token, int len, int status)
+{
+	struct sk_buff		*skb = token;
+	struct net_device	*ndev = skb->dev;
+	struct emac_priv	*priv = netdev_priv(ndev);
+	struct device		*emac_dev = &ndev->dev;
+	int			ret;
+
+	/* free and bail if we are shutting down */
+	if (unlikely(!netif_running(ndev))) {
+		dev_kfree_skb_any(skb);
+		return;
+	}
+
+	/* recycle on recieve error */
+	if (status < 0) {
+		ndev->stats.rx_errors++;
+		goto recycle;
+	}
+
+	/* feed received packet up the stack */
+	skb_put(skb, len);
+	skb->protocol = eth_type_trans(skb, ndev);
+	netif_receive_skb(skb);
+	ndev->stats.rx_bytes += len;
+	ndev->stats.rx_packets++;
+
+	/* alloc a new packet for receive */
+	skb = emac_rx_alloc(priv);
+	if (!skb) {
+		if (netif_msg_rx_err(priv) && net_ratelimit())
+			dev_err(emac_dev, "failed rx buffer alloc\n");
+		return;
+	}
+
+recycle:
+	ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
+			skb_tailroom(skb), GFP_KERNEL);
+	if (WARN_ON(ret < 0))
+		dev_kfree_skb_any(skb);
+}
+
+static void emac_tx_handler(void *token, int len, int status)
+{
+	struct sk_buff		*skb = token;
+	struct net_device	*ndev = skb->dev;
+
+	if (unlikely(netif_queue_stopped(ndev)))
+		netif_start_queue(ndev);
+	ndev->stats.tx_packets++;
+	ndev->stats.tx_bytes += len;
+	dev_kfree_skb_any(skb);
+}
+
 /** EMAC on-chip buffer descriptor memory
  *
  * WARNING: Please note that the on chip memory is used for both TX and RX
@@ -1532,42 +1604,36 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
 	struct device *emac_dev = &ndev->dev;
 	int ret_code;
-	struct emac_netbufobj tx_buf; /* buffer obj-only single frame support */
-	struct emac_netpktobj tx_packet;  /* packet object */
 	struct emac_priv *priv = netdev_priv(ndev);
 
 	/* If no link, return */
 	if (unlikely(!priv->link)) {
 		if (netif_msg_tx_err(priv) && net_ratelimit())
 			dev_err(emac_dev, "DaVinci EMAC: No link to transmit");
-		return NETDEV_TX_BUSY;
+		goto fail_tx;
 	}
 
-	/* Build the buffer and packet objects - Since only single fragment is
-	 * supported, need not set length and token in both packet & object.
-	 * Doing so for completeness sake & to show that this needs to be done
-	 * in multifragment case
-	 */
-	tx_packet.buf_list = &tx_buf;
-	tx_packet.num_bufs = 1; /* only single fragment supported */
-	tx_packet.pkt_length = skb->len;
-	tx_packet.pkt_token = (void *)skb;
-	tx_buf.length = skb->len;
-	tx_buf.buf_token = (void *)skb;
-	tx_buf.data_ptr = skb->data;
-	ret_code = emac_send(priv, &tx_packet, EMAC_DEF_TX_CH);
+	ret_code = skb_padto(skb, EMAC_DEF_MIN_ETHPKTSIZE);
+	if (unlikely(ret_code < 0)) {
+		if (netif_msg_tx_err(priv) && net_ratelimit())
+			dev_err(emac_dev, "DaVinci EMAC: packet pad failed");
+		goto fail_tx;
+	}
+
+	ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len,
+				     GFP_KERNEL);
 	if (unlikely(ret_code != 0)) {
-		if (ret_code == EMAC_ERR_TX_OUT_OF_BD) {
-			if (netif_msg_tx_err(priv) && net_ratelimit())
-				dev_err(emac_dev, "DaVinci EMAC: xmit() fatal"\
-					" err. Out of TX BD's");
-			netif_stop_queue(priv->ndev);
-		}
-		ndev->stats.tx_dropped++;
-		return NETDEV_TX_BUSY;
+		if (netif_msg_tx_err(priv) && net_ratelimit())
+			dev_err(emac_dev, "DaVinci EMAC: desc submit failed");
+		goto fail_tx;
 	}
 
 	return NETDEV_TX_OK;
+
+fail_tx:
+	ndev->stats.tx_dropped++;
+	netif_stop_queue(ndev);
+	return NETDEV_TX_BUSY;
 }
 
 /**
@@ -1588,13 +1654,12 @@ static void emac_dev_tx_timeout(struct net_device *ndev)
 	if (netif_msg_tx_err(priv))
 		dev_err(emac_dev, "DaVinci EMAC: xmit timeout, restarting TX");
 
+	emac_dump_regs(priv);
+
 	ndev->stats.tx_errors++;
 	emac_int_disable(priv);
-	emac_stop_txch(priv, EMAC_DEF_TX_CH);
-	emac_cleanup_txch(priv, EMAC_DEF_TX_CH);
-	emac_init_txch(priv, EMAC_DEF_TX_CH);
-	emac_write(EMAC_TXHDP(0), 0);
-	emac_write(EMAC_TXINTMASKSET, BIT(EMAC_DEF_TX_CH));
+	cpdma_chan_stop(priv->txchan);
+	cpdma_chan_start(priv->txchan);
 	emac_int_enable(priv);
 }
 
@@ -1915,7 +1980,6 @@ static void emac_setmac(struct emac_priv *priv, u32 ch, char *mac_addr)
 static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
 {
 	struct emac_priv *priv = netdev_priv(ndev);
-	struct emac_rxch *rxch = priv->rxch[EMAC_DEF_RX_CH];
 	struct device *emac_dev = &priv->ndev->dev;
 	struct sockaddr *sa = addr;
 
@@ -1926,11 +1990,10 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
 	memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len);
 	memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len);
 
-	/* If the interface is down - rxch is NULL. */
 	/* MAC address is configured only after the interface is enabled. */
 	if (netif_running(ndev)) {
-		memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len);
-		emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr);
+		memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len);
+		emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr);
 	}
 
 	if (netif_msg_drv(priv))
@@ -2139,7 +2202,7 @@ end_emac_rx_bdproc:
  */
 static int emac_hw_enable(struct emac_priv *priv)
 {
-	u32 ch, val, mbp_enable, mac_control;
+	u32 val, mbp_enable, mac_control;
 
 	/* Soft reset */
 	emac_write(EMAC_SOFTRESET, 1);
@@ -2182,26 +2245,9 @@ static int emac_hw_enable(struct emac_priv *priv)
 	emac_write(EMAC_RXUNICASTCLEAR, EMAC_RX_UNICAST_CLEAR_ALL);
 	priv->rx_addr_type = (emac_read(EMAC_MACCONFIG) >> 8) & 0xFF;
 
-	val = emac_read(EMAC_TXCONTROL);
-	val |= EMAC_TX_CONTROL_TX_ENABLE_VAL;
-	emac_write(EMAC_TXCONTROL, val);
-	val = emac_read(EMAC_RXCONTROL);
-	val |= EMAC_RX_CONTROL_RX_ENABLE_VAL;
-	emac_write(EMAC_RXCONTROL, val);
 	emac_write(EMAC_MACINTMASKSET, EMAC_MAC_HOST_ERR_INTMASK_VAL);
 
-	for (ch = 0; ch < EMAC_DEF_MAX_TX_CH; ch++) {
-		emac_write(EMAC_TXHDP(ch), 0);
-		emac_write(EMAC_TXINTMASKSET, BIT(ch));
-	}
-	for (ch = 0; ch < EMAC_DEF_MAX_RX_CH; ch++) {
-		struct emac_rxch *rxch = priv->rxch[ch];
-		emac_setmac(priv, ch, rxch->mac_addr);
-		emac_write(EMAC_RXINTMASKSET, BIT(ch));
-		rxch->queue_active = 1;
-		emac_write(EMAC_RXHDP(ch),
-			   emac_virt_to_phys(rxch->active_queue_head, priv));
-	}
+	emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr);
 
 	/* Enable MII */
 	val = emac_read(EMAC_MACCONTROL);
@@ -2246,8 +2292,8 @@ static int emac_poll(struct napi_struct *napi, int budget)
 		mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC;
 
 	if (status & mask) {
-		num_tx_pkts = emac_tx_bdproc(priv, EMAC_DEF_TX_CH,
-					  EMAC_DEF_TX_MAX_SERVICE);
+		num_tx_pkts = cpdma_chan_process(priv->txchan,
+					      EMAC_DEF_TX_MAX_SERVICE);
 	} /* TX processing */
 
 	mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC;
@@ -2256,7 +2302,7 @@ static int emac_poll(struct napi_struct *napi, int budget)
 		mask = EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC;
 
 	if (status & mask) {
-		num_rx_pkts = emac_rx_bdproc(priv, EMAC_DEF_RX_CH, budget);
+		num_rx_pkts = cpdma_chan_process(priv->rxchan, budget);
 	} /* RX processing */
 
 	mask = EMAC_DM644X_MAC_IN_VECTOR_HOST_INT;
@@ -2397,9 +2443,9 @@ static int match_first_device(struct device *dev, void *data)
 static int emac_dev_open(struct net_device *ndev)
 {
 	struct device *emac_dev = &ndev->dev;
-	u32 rc, cnt, ch;
+	u32 cnt;
 	struct resource *res;
-	int q, m;
+	int q, m, ret;
 	int i = 0;
 	int k = 0;
 	struct emac_priv *priv = netdev_priv(ndev);
@@ -2411,29 +2457,21 @@ static int emac_dev_open(struct net_device *ndev)
 	/* Configuration items */
 	priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN;
 
-	/* Clear basic hardware */
-	for (ch = 0; ch < EMAC_MAX_TXRX_CHANNELS; ch++) {
-		emac_write(EMAC_TXHDP(ch), 0);
-		emac_write(EMAC_RXHDP(ch), 0);
-		emac_write(EMAC_RXHDP(ch), 0);
-		emac_write(EMAC_RXINTMASKCLEAR, EMAC_INT_MASK_CLEAR);
-		emac_write(EMAC_TXINTMASKCLEAR, EMAC_INT_MASK_CLEAR);
-	}
 	priv->mac_hash1 = 0;
 	priv->mac_hash2 = 0;
 	emac_write(EMAC_MACHASH1, 0);
 	emac_write(EMAC_MACHASH2, 0);
 
-	/* multi ch not supported - open 1 TX, 1RX ch by default */
-	rc = emac_init_txch(priv, EMAC_DEF_TX_CH);
-	if (0 != rc) {
-		dev_err(emac_dev, "DaVinci EMAC: emac_init_txch() failed");
-		return rc;
-	}
-	rc = emac_init_rxch(priv, EMAC_DEF_RX_CH, priv->mac_addr);
-	if (0 != rc) {
-		dev_err(emac_dev, "DaVinci EMAC: emac_init_rxch() failed");
-		return rc;
+	for (i = 0; i < EMAC_DEF_RX_NUM_DESC; i++) {
+		struct sk_buff *skb = emac_rx_alloc(priv);
+
+		if (!skb)
+			break;
+
+		ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
+					skb_tailroom(skb), GFP_KERNEL);
+		if (WARN_ON(ret < 0))
+			break;
 	}
 
 	/* Request IRQ */
@@ -2458,6 +2496,8 @@ static int emac_dev_open(struct net_device *ndev)
 		emac_set_coalesce(ndev, &coal);
 	}
 
+	cpdma_ctlr_start(priv->dma);
+
 	priv->phydev = NULL;
 	/* use the first phy on the bus if pdata did not give us a phy id */
 	if (!priv->phy_id) {
@@ -2545,10 +2585,7 @@ static int emac_dev_stop(struct net_device *ndev)
 
 	netif_carrier_off(ndev);
 	emac_int_disable(priv);
-	emac_stop_txch(priv, EMAC_DEF_TX_CH);
-	emac_stop_rxch(priv, EMAC_DEF_RX_CH);
-	emac_cleanup_txch(priv, EMAC_DEF_TX_CH);
-	emac_cleanup_rxch(priv, EMAC_DEF_RX_CH);
+	cpdma_ctlr_stop(priv->dma);
 	emac_write(EMAC_SOFTRESET, 1);
 
 	if (priv->phydev)
@@ -2653,9 +2690,10 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct net_device *ndev;
 	struct emac_priv *priv;
-	unsigned long size;
+	unsigned long size, hw_ram_addr;
 	struct emac_platform_data *pdata;
 	struct device *emac_dev;
+	struct cpdma_params dma_params;
 
 	/* obtain emac clock from kernel */
 	emac_clk = clk_get(&pdev->dev, NULL);
@@ -2731,11 +2769,40 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
 	priv->ctrl_ram_size = pdata->ctrl_ram_size;
 	priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset;
 
-	if (pdata->hw_ram_addr)
-		priv->hw_ram_addr = pdata->hw_ram_addr;
-	else
-		priv->hw_ram_addr = (u32 __force)res->start +
-					pdata->ctrl_ram_offset;
+	hw_ram_addr = pdata->hw_ram_addr;
+	if (!hw_ram_addr)
+		hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset;
+
+	memset(&dma_params, 0, sizeof(dma_params));
+	dma_params.dev			= emac_dev;
+	dma_params.dmaregs		= priv->emac_base;
+	dma_params.rxthresh		= priv->emac_base + 0x120;
+	dma_params.rxfree		= priv->emac_base + 0x140;
+	dma_params.txhdp		= priv->emac_base + 0x600;
+	dma_params.rxhdp		= priv->emac_base + 0x620;
+	dma_params.txcp			= priv->emac_base + 0x640;
+	dma_params.rxcp			= priv->emac_base + 0x660;
+	dma_params.num_chan		= EMAC_MAX_TXRX_CHANNELS;
+	dma_params.min_packet_size	= EMAC_DEF_MIN_ETHPKTSIZE;
+	dma_params.desc_mem_phys	= hw_ram_addr;
+	dma_params.desc_mem_size	= pdata->ctrl_ram_size;
+	dma_params.desc_align		= 16;
+
+	priv->dma = cpdma_ctlr_create(&dma_params);
+	if (!priv->dma) {
+		dev_err(emac_dev, "DaVinci EMAC: Error initializing DMA\n");
+		rc = -ENOMEM;
+		goto no_dma;
+	}
+
+	priv->txchan = cpdma_chan_create(priv->dma, tx_chan_num(EMAC_DEF_TX_CH),
+				       emac_tx_handler);
+	priv->rxchan = cpdma_chan_create(priv->dma, rx_chan_num(EMAC_DEF_RX_CH),
+				       emac_rx_handler);
+	if (WARN_ON(!priv->txchan || !priv->rxchan)) {
+		rc = -ENOMEM;
+		goto no_irq_res;
+	}
 
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res) {
@@ -2778,6 +2845,12 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
 netdev_reg_err:
 	clk_disable(emac_clk);
 no_irq_res:
+	if (priv->txchan)
+		cpdma_chan_destroy(priv->txchan);
+	if (priv->rxchan)
+		cpdma_chan_destroy(priv->rxchan);
+	cpdma_ctlr_destroy(priv->dma);
+no_dma:
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(res->start, res->end - res->start + 1);
 	iounmap(priv->remap_addr);
@@ -2806,6 +2879,12 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev)
 	platform_set_drvdata(pdev, NULL);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
+	if (priv->txchan)
+		cpdma_chan_destroy(priv->txchan);
+	if (priv->rxchan)
+		cpdma_chan_destroy(priv->rxchan);
+	cpdma_ctlr_destroy(priv->dma);
+
 	release_mem_region(res->start, res->end - res->start + 1);
 
 	unregister_netdev(ndev);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 10/10] net: davinci_emac: cleanup unused cpdma code
  2010-09-15 14:11 [PATCH v4 00/10] split out emac cpdma and mdio for reuse Cyril Chemparathy
                   ` (8 preceding siblings ...)
  2010-09-15 14:11 ` [PATCH v4 09/10] net: davinci_emac: switch to new cpdma layer Cyril Chemparathy
@ 2010-09-15 14:11 ` Cyril Chemparathy
  2010-09-15 14:54 ` [PATCH v4 00/10] split out emac cpdma and mdio for reuse Kevin Hilman
  10 siblings, 0 replies; 13+ messages in thread
From: Cyril Chemparathy @ 2010-09-15 14:11 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

Having switched over to the newly introduced cpdma layer, this patch now
removes a whole bunch of code that is now unused.  This patch has been
maintained separate strictly for reasons of readability.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Acked-by: David S. Miller <davem@davemloft.net>
Tested-by: Michael Williamson <michael.williamson@criticallink.com>
Tested-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 drivers/net/davinci_emac.c |  930 --------------------------------------------
 1 files changed, 0 insertions(+), 930 deletions(-)

diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 67dbcfb..2a628d1 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -127,7 +127,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 /* EMAC register related defines */
 #define EMAC_ALL_MULTI_REG_VALUE	(0xFFFFFFFF)
 #define EMAC_NUM_MULTICAST_BITS		(64)
-#define EMAC_TEARDOWN_VALUE		(0xFFFFFFFC)
 #define EMAC_TX_CONTROL_TX_ENABLE_VAL	(0x1)
 #define EMAC_RX_CONTROL_RX_ENABLE_VAL	(0x1)
 #define EMAC_MAC_HOST_ERR_INTMASK_VAL	(0x2)
@@ -214,24 +213,10 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_DEF_MAX_MULTICAST_ADDRESSES (64) /* Max mcast addr's */
 
 /* EMAC Peripheral Device Register Memory Layout structure */
-#define EMAC_TXIDVER		0x0
-#define EMAC_TXCONTROL		0x4
-#define EMAC_TXTEARDOWN		0x8
-#define EMAC_RXIDVER		0x10
-#define EMAC_RXCONTROL		0x14
-#define EMAC_RXTEARDOWN		0x18
-#define EMAC_TXINTSTATRAW	0x80
-#define EMAC_TXINTSTATMASKED	0x84
-#define EMAC_TXINTMASKSET	0x88
-#define EMAC_TXINTMASKCLEAR	0x8C
 #define EMAC_MACINVECTOR	0x90
 
 #define EMAC_DM646X_MACEOIVECTOR	0x94
 
-#define EMAC_RXINTSTATRAW	0xA0
-#define EMAC_RXINTSTATMASKED	0xA4
-#define EMAC_RXINTMASKSET	0xA8
-#define EMAC_RXINTMASKCLEAR	0xAC
 #define EMAC_MACINTSTATRAW	0xB0
 #define EMAC_MACINTSTATMASKED	0xB4
 #define EMAC_MACINTMASKSET	0xB8
@@ -258,12 +243,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_MACADDRHI		0x504
 #define EMAC_MACINDEX		0x508
 
-/* EMAC HDP and Completion registors */
-#define EMAC_TXHDP(ch)		(0x600 + (ch * 4))
-#define EMAC_RXHDP(ch)		(0x620 + (ch * 4))
-#define EMAC_TXCP(ch)		(0x640 + (ch * 4))
-#define EMAC_RXCP(ch)		(0x660 + (ch * 4))
-
 /* EMAC statistics registers */
 #define EMAC_RXGOODFRAMES	0x200
 #define EMAC_RXBCASTFRAMES	0x204
@@ -328,120 +307,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 /* EMAC Stats Clear Mask */
 #define EMAC_STATS_CLR_MASK    (0xFFFFFFFF)
 
-/** net_buf_obj: EMAC network bufferdata structure
- *
- * EMAC network buffer data structure
- */
-struct emac_netbufobj {
-	void *buf_token;
-	char *data_ptr;
-	int length;
-};
-
-/** net_pkt_obj: EMAC network packet data structure
- *
- * EMAC network packet data structure - supports buffer list (for future)
- */
-struct emac_netpktobj {
-	void *pkt_token; /* data token may hold tx/rx chan id */
-	struct emac_netbufobj *buf_list; /* array of network buffer objects */
-	int num_bufs;
-	int pkt_length;
-};
-
-/** emac_tx_bd: EMAC TX Buffer descriptor data structure
- *
- * EMAC TX Buffer descriptor data structure
- */
-struct emac_tx_bd {
-	int h_next;
-	int buff_ptr;
-	int off_b_len;
-	int mode; /* SOP, EOP, ownership, EOQ, teardown,Qstarv, length */
-	struct emac_tx_bd __iomem *next;
-	void *buf_token;
-};
-
-/** emac_txch: EMAC TX Channel data structure
- *
- * EMAC TX Channel data structure
- */
-struct emac_txch {
-	/* Config related */
-	u32 num_bd;
-	u32 service_max;
-
-	/* CPPI specific */
-	u32 alloc_size;
-	void __iomem *bd_mem;
-	struct emac_tx_bd __iomem *bd_pool_head;
-	struct emac_tx_bd __iomem *active_queue_head;
-	struct emac_tx_bd __iomem *active_queue_tail;
-	struct emac_tx_bd __iomem *last_hw_bdprocessed;
-	u32 queue_active;
-	u32 teardown_pending;
-	u32 *tx_complete;
-
-	/** statistics */
-	u32 proc_count;     /* TX: # of times emac_tx_bdproc is called */
-	u32 mis_queued_packets;
-	u32 queue_reinit;
-	u32 end_of_queue_add;
-	u32 out_of_tx_bd;
-	u32 no_active_pkts; /* IRQ when there were no packets to process */
-	u32 active_queue_count;
-};
-
-/** emac_rx_bd: EMAC RX Buffer descriptor data structure
- *
- * EMAC RX Buffer descriptor data structure
- */
-struct emac_rx_bd {
-	int h_next;
-	int buff_ptr;
-	int off_b_len;
-	int mode;
-	struct emac_rx_bd __iomem *next;
-	void *data_ptr;
-	void *buf_token;
-};
-
-/** emac_rxch: EMAC RX Channel data structure
- *
- * EMAC RX Channel data structure
- */
-struct emac_rxch {
-	/* configuration info */
-	u32 num_bd;
-	u32 service_max;
-	u32 buf_size;
-	char mac_addr[6];
-
-	/** CPPI specific */
-	u32 alloc_size;
-	void __iomem *bd_mem;
-	struct emac_rx_bd __iomem *bd_pool_head;
-	struct emac_rx_bd __iomem *active_queue_head;
-	struct emac_rx_bd __iomem *active_queue_tail;
-	u32 queue_active;
-	u32 teardown_pending;
-
-	/* packet and buffer objects */
-	struct emac_netpktobj pkt_queue;
-	struct emac_netbufobj buf_queue;
-
-	/** statistics */
-	u32 proc_count; /* number of times emac_rx_bdproc is called */
-	u32 processed_bd;
-	u32 recycled_bd;
-	u32 out_of_rx_bd;
-	u32 out_of_rx_buffers;
-	u32 queue_reinit;
-	u32 end_of_queue_add;
-	u32 end_of_queue;
-	u32 mis_queued_packets;
-};
-
 /* emac_priv: EMAC private data structure
  *
  * EMAC adapter private data structure
@@ -452,17 +317,10 @@ struct emac_priv {
 	struct platform_device *pdev;
 	struct napi_struct napi;
 	char mac_addr[6];
-	spinlock_t tx_lock;
-	spinlock_t rx_lock;
 	void __iomem *remap_addr;
 	u32 emac_base_phys;
 	void __iomem *emac_base;
 	void __iomem *ctrl_base;
-	void __iomem *emac_ctrl_ram;
-	u32 ctrl_ram_size;
-	u32 hw_ram_addr;
-	struct emac_txch *txch[EMAC_DEF_MAX_TX_CH];
-	struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH];
 	struct cpdma_ctlr *dma;
 	struct cpdma_chan *txchan;
 	struct cpdma_chan *rxchan;
@@ -491,18 +349,6 @@ struct emac_priv {
 static struct clk *emac_clk;
 static unsigned long emac_bus_frequency;
 
-#define emac_virt_to_phys(addr, priv) \
-	(((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \
-	+ priv->hw_ram_addr)
-
-/* Cache macros - Packet buffers would be from skb pool which is cached */
-#define EMAC_VIRT_NOCACHE(addr) (addr)
-
-/* DM644x does not have BD's in cached memory - so no cache functions */
-#define BD_CACHE_INVALIDATE(addr, size)
-#define BD_CACHE_WRITEBACK(addr, size)
-#define BD_CACHE_WRITEBACK_INVALIDATE(addr, size)
-
 /* EMAC TX Host Error description strings */
 static char *emac_txhost_errcodes[16] = {
 	"No error", "SOP error", "Ownership bit not set in SOP buffer",
@@ -545,20 +391,6 @@ static void emac_dump_regs(struct emac_priv *priv)
 			emac_ctrl_read(EMAC_CTRL_EWCTL),
 			emac_ctrl_read(EMAC_CTRL_EWINTTCNT));
 	}
-	dev_info(emac_dev, "EMAC: TXID: %08X %s, RXID: %08X %s\n",
-		emac_read(EMAC_TXIDVER),
-		((emac_read(EMAC_TXCONTROL)) ? "enabled" : "disabled"),
-		emac_read(EMAC_RXIDVER),
-		((emac_read(EMAC_RXCONTROL)) ? "enabled" : "disabled"));
-	dev_info(emac_dev, "EMAC: TXIntRaw:%08X, TxIntMasked: %08X, "\
-		"TxIntMasSet: %08X\n", emac_read(EMAC_TXINTSTATRAW),
-		emac_read(EMAC_TXINTSTATMASKED), emac_read(EMAC_TXINTMASKSET));
-	dev_info(emac_dev, "EMAC: RXIntRaw:%08X, RxIntMasked: %08X, "\
-		"RxIntMasSet: %08X\n", emac_read(EMAC_RXINTSTATRAW),
-		emac_read(EMAC_RXINTSTATMASKED), emac_read(EMAC_RXINTMASKSET));
-	dev_info(emac_dev, "EMAC: MacIntRaw:%08X, MacIntMasked: %08X, "\
-		"MacInVector=%08X\n", emac_read(EMAC_MACINTSTATRAW),
-		emac_read(EMAC_MACINTSTATMASKED), emac_read(EMAC_MACINVECTOR));
 	dev_info(emac_dev, "EMAC: EmuControl:%08X, FifoControl: %08X\n",
 		emac_read(EMAC_EMCONTROL), emac_read(EMAC_FIFOCONTROL));
 	dev_info(emac_dev, "EMAC: MBPEnable:%08X, RXUnicastSet: %08X, "\
@@ -567,8 +399,6 @@ static void emac_dump_regs(struct emac_priv *priv)
 	dev_info(emac_dev, "EMAC: MacControl:%08X, MacStatus: %08X, "\
 		"MacConfig=%08X\n", emac_read(EMAC_MACCONTROL),
 		emac_read(EMAC_MACSTATUS), emac_read(EMAC_MACCONFIG));
-	dev_info(emac_dev, "EMAC: TXHDP[0]:%08X, RXHDP[0]: %08X\n",
-		emac_read(EMAC_TXHDP(0)), emac_read(EMAC_RXHDP(0)));
 	dev_info(emac_dev, "EMAC Statistics\n");
 	dev_info(emac_dev, "EMAC: rx_good_frames:%d\n",
 		emac_read(EMAC_RXGOODFRAMES));
@@ -1223,373 +1053,6 @@ static void emac_tx_handler(void *token, int len, int status)
 	dev_kfree_skb_any(skb);
 }
 
-/** EMAC on-chip buffer descriptor memory
- *
- * WARNING: Please note that the on chip memory is used for both TX and RX
- * buffer descriptor queues and is equally divided between TX and RX desc's
- * If the number of TX or RX descriptors change this memory pointers need
- * to be adjusted. If external memory is allocated then these pointers can
- * pointer to the memory
- *
- */
-#define EMAC_TX_BD_MEM(priv)	((priv)->emac_ctrl_ram)
-#define EMAC_RX_BD_MEM(priv)	((priv)->emac_ctrl_ram + \
-				(((priv)->ctrl_ram_size) >> 1))
-
-/**
- * emac_init_txch: TX channel initialization
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- *
- * Called during device init to setup a TX channel (allocate buffer desc
- * create free pool and keep ready for transmission
- *
- * Returns success(0) or mem alloc failures error code
- */
-static int emac_init_txch(struct emac_priv *priv, u32 ch)
-{
-	struct device *emac_dev = &priv->ndev->dev;
-	u32 cnt, bd_size;
-	void __iomem *mem;
-	struct emac_tx_bd __iomem *curr_bd;
-	struct emac_txch *txch = NULL;
-
-	txch = kzalloc(sizeof(struct emac_txch), GFP_KERNEL);
-	if (NULL == txch) {
-		dev_err(emac_dev, "DaVinci EMAC: TX Ch mem alloc failed");
-		return -ENOMEM;
-	}
-	priv->txch[ch] = txch;
-	txch->service_max = EMAC_DEF_TX_MAX_SERVICE;
-	txch->active_queue_head = NULL;
-	txch->active_queue_tail = NULL;
-	txch->queue_active = 0;
-	txch->teardown_pending = 0;
-
-	/* allocate memory for TX CPPI channel on a 4 byte boundry */
-	txch->tx_complete = kzalloc(txch->service_max * sizeof(u32),
-				    GFP_KERNEL);
-	if (NULL == txch->tx_complete) {
-		dev_err(emac_dev, "DaVinci EMAC: Tx service mem alloc failed");
-		kfree(txch);
-		return -ENOMEM;
-	}
-
-	/* allocate buffer descriptor pool align every BD on four word
-	 * boundry for future requirements */
-	bd_size = (sizeof(struct emac_tx_bd) + 0xF) & ~0xF;
-	txch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size;
-	txch->alloc_size = (((bd_size * txch->num_bd) + 0xF) & ~0xF);
-
-	/* alloc TX BD memory */
-	txch->bd_mem = EMAC_TX_BD_MEM(priv);
-	__memzero((void __force *)txch->bd_mem, txch->alloc_size);
-
-	/* initialize the BD linked list */
-	mem = (void __force __iomem *)
-			(((u32 __force) txch->bd_mem + 0xF) & ~0xF);
-	txch->bd_pool_head = NULL;
-	for (cnt = 0; cnt < txch->num_bd; cnt++) {
-		curr_bd = mem + (cnt * bd_size);
-		curr_bd->next = txch->bd_pool_head;
-		txch->bd_pool_head = curr_bd;
-	}
-
-	/* reset statistics counters */
-	txch->out_of_tx_bd = 0;
-	txch->no_active_pkts = 0;
-	txch->active_queue_count = 0;
-
-	return 0;
-}
-
-/**
- * emac_cleanup_txch: Book-keep function to clean TX channel resources
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: TX channel number
- *
- * Called to clean up TX channel resources
- *
- */
-static void emac_cleanup_txch(struct emac_priv *priv, u32 ch)
-{
-	struct emac_txch *txch = priv->txch[ch];
-
-	if (txch) {
-		if (txch->bd_mem)
-			txch->bd_mem = NULL;
-		kfree(txch->tx_complete);
-		kfree(txch);
-		priv->txch[ch] = NULL;
-	}
-}
-
-/**
- * emac_net_tx_complete: TX packet completion function
- * @priv: The DaVinci EMAC private adapter structure
- * @net_data_tokens: packet token - skb pointer
- * @num_tokens: number of skb's to free
- * @ch: TX channel number
- *
- * Frees the skb once packet is transmitted
- *
- */
-static int emac_net_tx_complete(struct emac_priv *priv,
-				void **net_data_tokens,
-				int num_tokens, u32 ch)
-{
-	struct net_device *ndev = priv->ndev;
-	u32 cnt;
-
-	if (unlikely(num_tokens && netif_queue_stopped(ndev)))
-		netif_start_queue(ndev);
-	for (cnt = 0; cnt < num_tokens; cnt++) {
-		struct sk_buff *skb = (struct sk_buff *)net_data_tokens[cnt];
-		if (skb == NULL)
-			continue;
-		ndev->stats.tx_packets++;
-		ndev->stats.tx_bytes += skb->len;
-		dev_kfree_skb_any(skb);
-	}
-	return 0;
-}
-
-/**
- * emac_txch_teardown: TX channel teardown
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: TX channel number
- *
- * Called to teardown TX channel
- *
- */
-static void emac_txch_teardown(struct emac_priv *priv, u32 ch)
-{
-	struct device *emac_dev = &priv->ndev->dev;
-	u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */
-	struct emac_txch *txch = priv->txch[ch];
-	struct emac_tx_bd __iomem *curr_bd;
-
-	while ((emac_read(EMAC_TXCP(ch)) & EMAC_TEARDOWN_VALUE) !=
-	       EMAC_TEARDOWN_VALUE) {
-		/* wait till tx teardown complete */
-		cpu_relax(); /* TODO: check if this helps ... */
-		--teardown_cnt;
-		if (0 == teardown_cnt) {
-			dev_err(emac_dev, "EMAC: TX teardown aborted\n");
-			break;
-		}
-	}
-	emac_write(EMAC_TXCP(ch), EMAC_TEARDOWN_VALUE);
-
-	/* process sent packets and return skb's to upper layer */
-	if (1 == txch->queue_active) {
-		curr_bd = txch->active_queue_head;
-		while (curr_bd != NULL) {
-			dma_unmap_single(emac_dev, curr_bd->buff_ptr,
-				curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE,
-				DMA_TO_DEVICE);
-
-			emac_net_tx_complete(priv, (void __force *)
-					&curr_bd->buf_token, 1, ch);
-			if (curr_bd != txch->active_queue_tail)
-				curr_bd = curr_bd->next;
-			else
-				break;
-		}
-		txch->bd_pool_head = txch->active_queue_head;
-		txch->active_queue_head =
-		txch->active_queue_tail = NULL;
-	}
-}
-
-/**
- * emac_stop_txch: Stop TX channel operation
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: TX channel number
- *
- * Called to stop TX channel operation
- *
- */
-static void emac_stop_txch(struct emac_priv *priv, u32 ch)
-{
-	struct emac_txch *txch = priv->txch[ch];
-
-	if (txch) {
-		txch->teardown_pending = 1;
-		emac_write(EMAC_TXTEARDOWN, 0);
-		emac_txch_teardown(priv, ch);
-		txch->teardown_pending = 0;
-		emac_write(EMAC_TXINTMASKCLEAR, BIT(ch));
-	}
-}
-
-/**
- * emac_tx_bdproc: TX buffer descriptor (packet) processing
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: TX channel number to process buffer descriptors for
- * @budget: number of packets allowed to process
- * @pending: indication to caller that packets are pending to process
- *
- * Processes TX buffer descriptors after packets are transmitted - checks
- * ownership bit on the TX * descriptor and requeues it to free pool & frees
- * the SKB buffer. Only "budget" number of packets are processed and
- * indication of pending packets provided to the caller
- *
- * Returns number of packets processed
- */
-static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
-{
-	struct device *emac_dev = &priv->ndev->dev;
-	unsigned long flags;
-	u32 frame_status;
-	u32 pkts_processed = 0;
-	u32 tx_complete_cnt = 0;
-	struct emac_tx_bd __iomem *curr_bd;
-	struct emac_txch *txch = priv->txch[ch];
-	u32 *tx_complete_ptr = txch->tx_complete;
-
-	if (unlikely(1 == txch->teardown_pending)) {
-		if (netif_msg_tx_err(priv) && net_ratelimit()) {
-			dev_err(emac_dev, "DaVinci EMAC:emac_tx_bdproc: "\
-				"teardown pending\n");
-		}
-		return 0;  /* dont handle any pkt completions */
-	}
-
-	++txch->proc_count;
-	spin_lock_irqsave(&priv->tx_lock, flags);
-	curr_bd = txch->active_queue_head;
-	if (NULL == curr_bd) {
-		emac_write(EMAC_TXCP(ch),
-			   emac_virt_to_phys(txch->last_hw_bdprocessed, priv));
-		txch->no_active_pkts++;
-		spin_unlock_irqrestore(&priv->tx_lock, flags);
-		return 0;
-	}
-	BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-	frame_status = curr_bd->mode;
-	while ((curr_bd) &&
-	      ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) &&
-	      (pkts_processed < budget)) {
-		emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd, priv));
-		txch->active_queue_head = curr_bd->next;
-		if (frame_status & EMAC_CPPI_EOQ_BIT) {
-			if (curr_bd->next) {	/* misqueued packet */
-				emac_write(EMAC_TXHDP(ch), curr_bd->h_next);
-				++txch->mis_queued_packets;
-			} else {
-				txch->queue_active = 0; /* end of queue */
-			}
-		}
-
-		dma_unmap_single(emac_dev, curr_bd->buff_ptr,
-				curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE,
-				DMA_TO_DEVICE);
-
-		*tx_complete_ptr = (u32) curr_bd->buf_token;
-		++tx_complete_ptr;
-		++tx_complete_cnt;
-		curr_bd->next = txch->bd_pool_head;
-		txch->bd_pool_head = curr_bd;
-		--txch->active_queue_count;
-		pkts_processed++;
-		txch->last_hw_bdprocessed = curr_bd;
-		curr_bd = txch->active_queue_head;
-		if (curr_bd) {
-			BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-			frame_status = curr_bd->mode;
-		}
-	} /* end of pkt processing loop */
-
-	emac_net_tx_complete(priv,
-			     (void *)&txch->tx_complete[0],
-			     tx_complete_cnt, ch);
-	spin_unlock_irqrestore(&priv->tx_lock, flags);
-	return pkts_processed;
-}
-
-#define EMAC_ERR_TX_OUT_OF_BD -1
-
-/**
- * emac_send: EMAC Transmit function (internal)
- * @priv: The DaVinci EMAC private adapter structure
- * @pkt: packet pointer (contains skb ptr)
- * @ch: TX channel number
- *
- * Called by the transmit function to queue the packet in EMAC hardware queue
- *
- * Returns success(0) or error code (typically out of desc's)
- */
-static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch)
-{
-	unsigned long flags;
-	struct emac_tx_bd __iomem *curr_bd;
-	struct emac_txch *txch;
-	struct emac_netbufobj *buf_list;
-
-	txch = priv->txch[ch];
-	buf_list = pkt->buf_list;   /* get handle to the buffer array */
-
-	/* check packet size and pad if short */
-	if (pkt->pkt_length < EMAC_DEF_MIN_ETHPKTSIZE) {
-		buf_list->length += (EMAC_DEF_MIN_ETHPKTSIZE - pkt->pkt_length);
-		pkt->pkt_length = EMAC_DEF_MIN_ETHPKTSIZE;
-	}
-
-	spin_lock_irqsave(&priv->tx_lock, flags);
-	curr_bd = txch->bd_pool_head;
-	if (curr_bd == NULL) {
-		txch->out_of_tx_bd++;
-		spin_unlock_irqrestore(&priv->tx_lock, flags);
-		return EMAC_ERR_TX_OUT_OF_BD;
-	}
-
-	txch->bd_pool_head = curr_bd->next;
-	curr_bd->buf_token = buf_list->buf_token;
-	curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buf_list->data_ptr,
-			buf_list->length, DMA_TO_DEVICE);
-	curr_bd->off_b_len = buf_list->length;
-	curr_bd->h_next = 0;
-	curr_bd->next = NULL;
-	curr_bd->mode = (EMAC_CPPI_SOP_BIT | EMAC_CPPI_OWNERSHIP_BIT |
-			 EMAC_CPPI_EOP_BIT | pkt->pkt_length);
-
-	/* flush the packet from cache if write back cache is present */
-	BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-
-	/* send the packet */
-	if (txch->active_queue_head == NULL) {
-		txch->active_queue_head = curr_bd;
-		txch->active_queue_tail = curr_bd;
-		if (1 != txch->queue_active) {
-			emac_write(EMAC_TXHDP(ch),
-					emac_virt_to_phys(curr_bd, priv));
-			txch->queue_active = 1;
-		}
-		++txch->queue_reinit;
-	} else {
-		register struct emac_tx_bd __iomem *tail_bd;
-		register u32 frame_status;
-
-		tail_bd = txch->active_queue_tail;
-		tail_bd->next = curr_bd;
-		txch->active_queue_tail = curr_bd;
-		tail_bd = EMAC_VIRT_NOCACHE(tail_bd);
-		tail_bd->h_next = (int)emac_virt_to_phys(curr_bd, priv);
-		frame_status = tail_bd->mode;
-		if (frame_status & EMAC_CPPI_EOQ_BIT) {
-			emac_write(EMAC_TXHDP(ch),
-				emac_virt_to_phys(curr_bd, priv));
-			frame_status &= ~(EMAC_CPPI_EOQ_BIT);
-			tail_bd->mode = frame_status;
-			++txch->end_of_queue_add;
-		}
-	}
-	txch->active_queue_count++;
-	spin_unlock_irqrestore(&priv->tx_lock, flags);
-	return 0;
-}
-
 /**
  * emac_dev_xmit: EMAC Transmit function
  * @skb: SKB pointer
@@ -1664,207 +1127,6 @@ static void emac_dev_tx_timeout(struct net_device *ndev)
 }
 
 /**
- * emac_net_alloc_rx_buf: Allocate a skb for RX
- * @priv: The DaVinci EMAC private adapter structure
- * @buf_size: size of SKB data buffer to allocate
- * @data_token: data token returned (skb handle for storing in buffer desc)
- * @ch: RX channel number
- *
- * Called during RX channel setup - allocates skb buffer of required size
- * and provides the skb handle and allocated buffer data pointer to caller
- *
- * Returns skb data pointer or 0 on failure to alloc skb
- */
-static void *emac_net_alloc_rx_buf(struct emac_priv *priv, int buf_size,
-		void **data_token, u32 ch)
-{
-	struct net_device *ndev = priv->ndev;
-	struct device *emac_dev = &ndev->dev;
-	struct sk_buff *p_skb;
-
-	p_skb = dev_alloc_skb(buf_size);
-	if (unlikely(NULL == p_skb)) {
-		if (netif_msg_rx_err(priv) && net_ratelimit())
-			dev_err(emac_dev, "DaVinci EMAC: failed to alloc skb");
-		return NULL;
-	}
-
-	/* set device pointer in skb and reserve space for extra bytes */
-	p_skb->dev = ndev;
-	skb_reserve(p_skb, NET_IP_ALIGN);
-	*data_token = (void *) p_skb;
-	return p_skb->data;
-}
-
-/**
- * emac_init_rxch: RX channel initialization
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- * @param: mac address for RX channel
- *
- * Called during device init to setup a RX channel (allocate buffers and
- * buffer descriptors, create queue and keep ready for reception
- *
- * Returns success(0) or mem alloc failures error code
- */
-static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param)
-{
-	struct device *emac_dev = &priv->ndev->dev;
-	u32 cnt, bd_size;
-	void __iomem *mem;
-	struct emac_rx_bd __iomem *curr_bd;
-	struct emac_rxch *rxch = NULL;
-
-	rxch = kzalloc(sizeof(struct emac_rxch), GFP_KERNEL);
-	if (NULL == rxch) {
-		dev_err(emac_dev, "DaVinci EMAC: RX Ch mem alloc failed");
-		return -ENOMEM;
-	}
-	priv->rxch[ch] = rxch;
-	rxch->buf_size = priv->rx_buf_size;
-	rxch->service_max = EMAC_DEF_RX_MAX_SERVICE;
-	rxch->queue_active = 0;
-	rxch->teardown_pending = 0;
-
-	/* save mac address */
-	for (cnt = 0; cnt < 6; cnt++)
-		rxch->mac_addr[cnt] = param[cnt];
-
-	/* allocate buffer descriptor pool align every BD on four word
-	 * boundry for future requirements */
-	bd_size = (sizeof(struct emac_rx_bd) + 0xF) & ~0xF;
-	rxch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size;
-	rxch->alloc_size = (((bd_size * rxch->num_bd) + 0xF) & ~0xF);
-	rxch->bd_mem = EMAC_RX_BD_MEM(priv);
-	__memzero((void __force *)rxch->bd_mem, rxch->alloc_size);
-	rxch->pkt_queue.buf_list = &rxch->buf_queue;
-
-	/* allocate RX buffer and initialize the BD linked list */
-	mem = (void __force __iomem *)
-			(((u32 __force) rxch->bd_mem + 0xF) & ~0xF);
-	rxch->active_queue_head = NULL;
-	rxch->active_queue_tail = mem;
-	for (cnt = 0; cnt < rxch->num_bd; cnt++) {
-		curr_bd = mem + (cnt * bd_size);
-		/* for future use the last parameter contains the BD ptr */
-		curr_bd->data_ptr = emac_net_alloc_rx_buf(priv,
-				    rxch->buf_size,
-				    (void __force **)&curr_bd->buf_token,
-				    EMAC_DEF_RX_CH);
-		if (curr_bd->data_ptr == NULL) {
-			dev_err(emac_dev, "DaVinci EMAC: RX buf mem alloc " \
-				"failed for ch %d\n", ch);
-			kfree(rxch);
-			return -ENOMEM;
-		}
-
-		/* populate the hardware descriptor */
-		curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head,
-				priv);
-		curr_bd->buff_ptr = dma_map_single(emac_dev, curr_bd->data_ptr,
-				rxch->buf_size, DMA_FROM_DEVICE);
-		curr_bd->off_b_len = rxch->buf_size;
-		curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT;
-
-		/* write back to hardware memory */
-		BD_CACHE_WRITEBACK_INVALIDATE((u32) curr_bd,
-					      EMAC_BD_LENGTH_FOR_CACHE);
-		curr_bd->next = rxch->active_queue_head;
-		rxch->active_queue_head = curr_bd;
-	}
-
-	/* At this point rxCppi->activeQueueHead points to the first
-	   RX BD ready to be given to RX HDP and rxch->active_queue_tail
-	   points to the last RX BD
-	 */
-	return 0;
-}
-
-/**
- * emac_rxch_teardown: RX channel teardown
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- *
- * Called during device stop to teardown RX channel
- *
- */
-static void emac_rxch_teardown(struct emac_priv *priv, u32 ch)
-{
-	struct device *emac_dev = &priv->ndev->dev;
-	u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */
-
-	while ((emac_read(EMAC_RXCP(ch)) & EMAC_TEARDOWN_VALUE) !=
-	       EMAC_TEARDOWN_VALUE) {
-		/* wait till tx teardown complete */
-		cpu_relax(); /* TODO: check if this helps ... */
-		--teardown_cnt;
-		if (0 == teardown_cnt) {
-			dev_err(emac_dev, "EMAC: RX teardown aborted\n");
-			break;
-		}
-	}
-	emac_write(EMAC_RXCP(ch), EMAC_TEARDOWN_VALUE);
-}
-
-/**
- * emac_stop_rxch: Stop RX channel operation
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- *
- * Called during device stop to stop RX channel operation
- *
- */
-static void emac_stop_rxch(struct emac_priv *priv, u32 ch)
-{
-	struct emac_rxch *rxch = priv->rxch[ch];
-
-	if (rxch) {
-		rxch->teardown_pending = 1;
-		emac_write(EMAC_RXTEARDOWN, ch);
-		/* wait for teardown complete */
-		emac_rxch_teardown(priv, ch);
-		rxch->teardown_pending = 0;
-		emac_write(EMAC_RXINTMASKCLEAR, BIT(ch));
-	}
-}
-
-/**
- * emac_cleanup_rxch: Book-keep function to clean RX channel resources
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- *
- * Called during device stop to clean up RX channel resources
- *
- */
-static void emac_cleanup_rxch(struct emac_priv *priv, u32 ch)
-{
-	struct emac_rxch *rxch = priv->rxch[ch];
-	struct emac_rx_bd __iomem *curr_bd;
-
-	if (rxch) {
-		/* free the receive buffers previously allocated */
-		curr_bd = rxch->active_queue_head;
-		while (curr_bd) {
-			if (curr_bd->buf_token) {
-				dma_unmap_single(&priv->ndev->dev,
-					curr_bd->buff_ptr,
-					curr_bd->off_b_len
-						& EMAC_RX_BD_BUF_SIZE,
-					DMA_FROM_DEVICE);
-
-				dev_kfree_skb_any((struct sk_buff *)\
-						  curr_bd->buf_token);
-			}
-			curr_bd = curr_bd->next;
-		}
-		if (rxch->bd_mem)
-			rxch->bd_mem = NULL;
-		kfree(rxch);
-		priv->rxch[ch] = NULL;
-	}
-}
-
-/**
  * emac_set_type0addr: Set EMAC Type0 mac address
  * @priv: The DaVinci EMAC private adapter structure
  * @ch: RX channel number
@@ -2004,194 +1266,6 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
 }
 
 /**
- * emac_addbd_to_rx_queue: Recycle RX buffer descriptor
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number to process buffer descriptors for
- * @curr_bd: current buffer descriptor
- * @buffer: buffer pointer for descriptor
- * @buf_token: buffer token (stores skb information)
- *
- * Prepares the recycled buffer descriptor and addes it to hardware
- * receive queue - if queue empty this descriptor becomes the head
- * else addes the descriptor to end of queue
- *
- */
-static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch,
-		struct emac_rx_bd __iomem *curr_bd,
-		char *buffer, void *buf_token)
-{
-	struct emac_rxch *rxch = priv->rxch[ch];
-
-	/* populate the hardware descriptor */
-	curr_bd->h_next = 0;
-	curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buffer,
-				rxch->buf_size, DMA_FROM_DEVICE);
-	curr_bd->off_b_len = rxch->buf_size;
-	curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT;
-	curr_bd->next = NULL;
-	curr_bd->data_ptr = buffer;
-	curr_bd->buf_token = buf_token;
-
-	/* write back  */
-	BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-	if (rxch->active_queue_head == NULL) {
-		rxch->active_queue_head = curr_bd;
-		rxch->active_queue_tail = curr_bd;
-		if (0 != rxch->queue_active) {
-			emac_write(EMAC_RXHDP(ch),
-			   emac_virt_to_phys(rxch->active_queue_head, priv));
-			rxch->queue_active = 1;
-		}
-	} else {
-		struct emac_rx_bd __iomem *tail_bd;
-		u32 frame_status;
-
-		tail_bd = rxch->active_queue_tail;
-		rxch->active_queue_tail = curr_bd;
-		tail_bd->next = curr_bd;
-		tail_bd = EMAC_VIRT_NOCACHE(tail_bd);
-		tail_bd->h_next = emac_virt_to_phys(curr_bd, priv);
-		frame_status = tail_bd->mode;
-		if (frame_status & EMAC_CPPI_EOQ_BIT) {
-			emac_write(EMAC_RXHDP(ch),
-					emac_virt_to_phys(curr_bd, priv));
-			frame_status &= ~(EMAC_CPPI_EOQ_BIT);
-			tail_bd->mode = frame_status;
-			++rxch->end_of_queue_add;
-		}
-	}
-	++rxch->recycled_bd;
-}
-
-/**
- * emac_net_rx_cb: Prepares packet and sends to upper layer
- * @priv: The DaVinci EMAC private adapter structure
- * @net_pkt_list: Network packet list (received packets)
- *
- * Invalidates packet buffer memory and sends the received packet to upper
- * layer
- *
- * Returns success or appropriate error code (none as of now)
- */
-static int emac_net_rx_cb(struct emac_priv *priv,
-			  struct emac_netpktobj *net_pkt_list)
-{
-	struct net_device *ndev = priv->ndev;
-	struct sk_buff *p_skb = net_pkt_list->pkt_token;
-	/* set length of packet */
-	skb_put(p_skb, net_pkt_list->pkt_length);
-	p_skb->protocol = eth_type_trans(p_skb, priv->ndev);
-	netif_receive_skb(p_skb);
-	ndev->stats.rx_bytes += net_pkt_list->pkt_length;
-	ndev->stats.rx_packets++;
-	return 0;
-}
-
-/**
- * emac_rx_bdproc: RX buffer descriptor (packet) processing
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number to process buffer descriptors for
- * @budget: number of packets allowed to process
- * @pending: indication to caller that packets are pending to process
- *
- * Processes RX buffer descriptors - checks ownership bit on the RX buffer
- * descriptor, sends the receive packet to upper layer, allocates a new SKB
- * and recycles the buffer descriptor (requeues it in hardware RX queue).
- * Only "budget" number of packets are processed and indication of pending
- * packets provided to the caller.
- *
- * Returns number of packets processed (and indication of pending packets)
- */
-static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
-{
-	unsigned long flags;
-	u32 frame_status;
-	u32 pkts_processed = 0;
-	char *new_buffer;
-	struct emac_rx_bd __iomem *curr_bd;
-	struct emac_rx_bd __iomem *last_bd;
-	struct emac_netpktobj *curr_pkt, pkt_obj;
-	struct emac_netbufobj buf_obj;
-	struct emac_netbufobj *rx_buf_obj;
-	void *new_buf_token;
-	struct emac_rxch *rxch = priv->rxch[ch];
-
-	if (unlikely(1 == rxch->teardown_pending))
-		return 0;
-	++rxch->proc_count;
-	spin_lock_irqsave(&priv->rx_lock, flags);
-	pkt_obj.buf_list = &buf_obj;
-	curr_pkt = &pkt_obj;
-	curr_bd = rxch->active_queue_head;
-	BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-	frame_status = curr_bd->mode;
-
-	while ((curr_bd) &&
-	       ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) &&
-	       (pkts_processed < budget)) {
-
-		new_buffer = emac_net_alloc_rx_buf(priv, rxch->buf_size,
-					&new_buf_token, EMAC_DEF_RX_CH);
-		if (unlikely(NULL == new_buffer)) {
-			++rxch->out_of_rx_buffers;
-			goto end_emac_rx_bdproc;
-		}
-
-		/* populate received packet data structure */
-		rx_buf_obj = &curr_pkt->buf_list[0];
-		rx_buf_obj->data_ptr = (char *)curr_bd->data_ptr;
-		rx_buf_obj->length = curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE;
-		rx_buf_obj->buf_token = curr_bd->buf_token;
-
-		dma_unmap_single(&priv->ndev->dev, curr_bd->buff_ptr,
-				curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE,
-				DMA_FROM_DEVICE);
-
-		curr_pkt->pkt_token = curr_pkt->buf_list->buf_token;
-		curr_pkt->num_bufs = 1;
-		curr_pkt->pkt_length =
-			(frame_status & EMAC_RX_BD_PKT_LENGTH_MASK);
-		emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd, priv));
-		++rxch->processed_bd;
-		last_bd = curr_bd;
-		curr_bd = last_bd->next;
-		rxch->active_queue_head = curr_bd;
-
-		/* check if end of RX queue ? */
-		if (frame_status & EMAC_CPPI_EOQ_BIT) {
-			if (curr_bd) {
-				++rxch->mis_queued_packets;
-				emac_write(EMAC_RXHDP(ch),
-					   emac_virt_to_phys(curr_bd, priv));
-			} else {
-				++rxch->end_of_queue;
-				rxch->queue_active = 0;
-			}
-		}
-
-		/* recycle BD */
-		emac_addbd_to_rx_queue(priv, ch, last_bd, new_buffer,
-				       new_buf_token);
-
-		/* return the packet to the user - BD ptr passed in
-		 * last parameter for potential *future* use */
-		spin_unlock_irqrestore(&priv->rx_lock, flags);
-		emac_net_rx_cb(priv, curr_pkt);
-		spin_lock_irqsave(&priv->rx_lock, flags);
-		curr_bd = rxch->active_queue_head;
-		if (curr_bd) {
-			BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-			frame_status = curr_bd->mode;
-		}
-		++pkts_processed;
-	}
-
-end_emac_rx_bdproc:
-	spin_unlock_irqrestore(&priv->rx_lock, flags);
-	return pkts_processed;
-}
-
-/**
  * emac_hw_enable: Enable EMAC hardware for packet transmission/reception
  * @priv: The DaVinci EMAC private adapter structure
  *
@@ -2717,8 +1791,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
 	priv->ndev = ndev;
 	priv->msg_enable = netif_msg_init(debug_level, DAVINCI_EMAC_DEBUG);
 
-	spin_lock_init(&priv->tx_lock);
-	spin_lock_init(&priv->rx_lock);
 	spin_lock_init(&priv->lock);
 
 	pdata = pdev->dev.platform_data;
@@ -2766,8 +1838,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
 	ndev->base_addr = (unsigned long)priv->remap_addr;
 
 	priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset;
-	priv->ctrl_ram_size = pdata->ctrl_ram_size;
-	priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset;
 
 	hw_ram_addr = pdata->hw_ram_addr;
 	if (!hw_ram_addr)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 00/10] split out emac cpdma and mdio for reuse
  2010-09-15 14:11 [PATCH v4 00/10] split out emac cpdma and mdio for reuse Cyril Chemparathy
                   ` (9 preceding siblings ...)
  2010-09-15 14:11 ` [PATCH v4 10/10] net: davinci_emac: cleanup unused cpdma code Cyril Chemparathy
@ 2010-09-15 14:54 ` Kevin Hilman
  10 siblings, 0 replies; 13+ messages in thread
From: Kevin Hilman @ 2010-09-15 14:54 UTC (permalink / raw)
  To: Cyril Chemparathy
  Cc: netdev, davinci-linux-open-source, linux-omap,
	michael.williamson, caglarakyuz, bparrot

Cyril Chemparathy <cyril@ti.com> writes:

> Davinci's EMAC device has an in-built MDIO controller and a CPDMA engine.
> These hardware modules are not restricted to EMAC device alone.  For example,
> CPSW3G (3-port gigabit ethernet switch) hardware uses these very same modules
> internally.  This patch series separates out EMAC's MDIO and CPDMA
> functionality, allowing these individual pieces to be reused across TI
> hardware.  

[...]

> Changes from v3 (rolled in "post cpdma/mdio refactoring fixes" series):
>   1. allow forced 100/full mode instead of phy auto-detect
>   2. specify phy_id on boards that had a phy_mask defined earlier
>   3. requeue cpdma descriptors when EOQ at submit
>   4. use calculated mdio bus access times instead of hardcoded delays
>   5. work around emac soft-reset impact on mdio controller state
>   6. extend register dumps to include cpdma registers
>   7. updated sign offs and acks

Thanks Cyril for one more spin with these updates.  Queuing this one for
2.6.37 in davinci-next.

davinci git is now updated with this series (may take a bit to propagate
to kernel.org mirrors though)

Kevin

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v4 06/10] omap: cleanup unused davinci mdio arch code
  2010-09-14 21:10 Cyril Chemparathy
@ 2010-09-14 21:10 ` Cyril Chemparathy
  0 siblings, 0 replies; 13+ messages in thread
From: Cyril Chemparathy @ 2010-09-14 21:10 UTC (permalink / raw)
  To: netdev, davinci-linux-open-source, linux-omap
  Cc: michael.williamson, caglarakyuz, bparrot, Cyril Chemparathy

This patch removes davinci architecture code that has now been rendered
useless by the previous patches in the MDIO separation series.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Acked-by: David S. Miller <davem@davemloft.net>
Tested-by: Michael Williamson <michael.williamson@criticallink.com>
Tested-by: Caglar Akyuz <caglarakyuz@gmail.com>
---
 arch/arm/mach-omap2/board-am3517evm.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 5dd1b73..5225df6 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -39,7 +39,6 @@
 
 #include "mux.h"
 
-#define AM35XX_EVM_PHY_MASK		(0xF)
 #define AM35XX_EVM_MDIO_FREQUENCY	(1000000)
 
 static struct mdio_platform_data am3517_evm_mdio_pdata = {
@@ -64,8 +63,6 @@ static struct platform_device am3517_mdio_device = {
 };
 
 static struct emac_platform_data am3517_evm_emac_pdata = {
-	.phy_mask	= AM35XX_EVM_PHY_MASK,
-	.mdio_max_freq	= AM35XX_EVM_MDIO_FREQUENCY,
 	.rmii_en	= 1,
 };
 
@@ -135,7 +132,6 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
 	pdata->ctrl_reg_offset		= AM35XX_EMAC_CNTRL_OFFSET;
 	pdata->ctrl_mod_reg_offset	= AM35XX_EMAC_CNTRL_MOD_OFFSET;
 	pdata->ctrl_ram_offset		= AM35XX_EMAC_CNTRL_RAM_OFFSET;
-	pdata->mdio_reg_offset		= AM35XX_EMAC_MDIO_OFFSET;
 	pdata->ctrl_ram_size		= AM35XX_EMAC_CNTRL_RAM_SIZE;
 	pdata->version			= EMAC_VERSION_2;
 	pdata->hw_ram_addr		= AM35XX_EMAC_HW_RAM_ADDR;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2010-09-15 14:54 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-15 14:11 [PATCH v4 00/10] split out emac cpdma and mdio for reuse Cyril Chemparathy
2010-09-15 14:11 ` [PATCH v4 01/10] net: davinci_emac: separate out davinci mdio Cyril Chemparathy
2010-09-15 14:11 ` [PATCH v4 02/10] davinci: add mdio platform devices Cyril Chemparathy
2010-09-15 14:11 ` [PATCH v4 03/10] omap: " Cyril Chemparathy
2010-09-15 14:11 ` [PATCH v4 04/10] net: davinci_emac: switch to new mdio Cyril Chemparathy
2010-09-15 14:11 ` [PATCH v4 05/10] davinci: cleanup mdio arch code and switch to phy_id Cyril Chemparathy
2010-09-15 14:11 ` [PATCH v4 06/10] omap: cleanup unused davinci mdio arch code Cyril Chemparathy
2010-09-15 14:11 ` [PATCH v4 07/10] net: davinci_emac: cleanup unused mdio emac code Cyril Chemparathy
2010-09-15 14:11 ` [PATCH v4 08/10] net: davinci_emac: separate out cpdma code Cyril Chemparathy
2010-09-15 14:11 ` [PATCH v4 09/10] net: davinci_emac: switch to new cpdma layer Cyril Chemparathy
2010-09-15 14:11 ` [PATCH v4 10/10] net: davinci_emac: cleanup unused cpdma code Cyril Chemparathy
2010-09-15 14:54 ` [PATCH v4 00/10] split out emac cpdma and mdio for reuse Kevin Hilman
  -- strict thread matches above, loose matches on Subject: below --
2010-09-14 21:10 Cyril Chemparathy
2010-09-14 21:10 ` [PATCH v4 06/10] omap: cleanup unused davinci mdio arch code Cyril Chemparathy

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.