[RFC][PPC32] platform device / driver model usage

Kumar Gala galak at somerset.sps.mot.com
Thu Dec 9 15:56:03 EST 2004


Moves the MPC85xx to using the driver model instead of OCP for 
driver/device binding.  Transitioned the gianfar ethernet driver over as 
an example, this currently only works on the MPC8540ADS with TSEC1.  The 
patch is a work in progress to get feedback on.

This is based on patches from Jason McMullan at TimeSys.

I wanted to get feedback on the addition of a flags field to struct 
platform_device.  Also, if there was any issue with the addition of 
include/linux/fsl_devices.h.  Other comments are welcome.

thanks

- kumar

diff -Nru a/arch/ppc/platforms/85xx/Makefile b/arch/ppc/platforms/85xx/Makefile
--- a/arch/ppc/platforms/85xx/Makefile	2004-12-08 22:22:37 -06:00
+++ b/arch/ppc/platforms/85xx/Makefile	2004-12-08 22:22:37 -06:00
@@ -1,6 +1,7 @@
 #
 # Makefile for the PowerPC 85xx linux kernel.
 #
+obj-$(CONFIG_85xx)		+= mpc85xx.o
 
 obj-$(CONFIG_MPC8540_ADS)	+= mpc85xx_ads_common.o mpc8540_ads.o
 obj-$(CONFIG_MPC8555_CDS)	+= mpc85xx_cds_common.o
diff -Nru a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
--- a/arch/ppc/platforms/85xx/mpc8540_ads.c	2004-12-08 22:22:37 -06:00
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c	2004-12-08 22:22:37 -06:00
@@ -32,6 +32,7 @@
 #include <linux/serial_core.h>
 #include <linux/initrd.h>
 #include <linux/module.h>
+#include <linux/fsl_devices.h>
 
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -54,6 +55,14 @@
 #include <syslib/ppc85xx_common.h>
 #include <syslib/ppc85xx_setup.h>
 
+struct gianfar_platform_data mpc85xx_gianfar1_def = {
+	.flags = GFAR_HAS_PHY_INTR,
+	.interruptPHY = MPC85xx_IRQ_EXT5,
+	.phyid = 0,
+	.phydevice = "fsl-gianfar1",
+	.phyregidx = 1,
+};
+
 struct ocp_gfar_data mpc85xx_tsec1_def = {
 	.interruptTransmit = MPC85xx_IRQ_TSEC1_TX,
 	.interruptError = MPC85xx_IRQ_TSEC1_ERROR,
@@ -147,6 +156,8 @@
 		einfo = (struct ocp_gfar_data *) def->additions;
 		memcpy(einfo->mac_addr, binfo->bi_enet2addr, 6);
 	}
+
+	memcpy(mpc85xx_gianfar1_def.mac_addr, binfo->bi_enetaddr, 6);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
diff -Nru a/arch/ppc/platforms/85xx/mpc85xx.c b/arch/ppc/platforms/85xx/mpc85xx.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/85xx/mpc85xx.c	2004-12-08 22:22:37 -06:00
@@ -0,0 +1,243 @@
+/*
+ * arch/ppc/platforms/85xx/mpc85xx.c
+ *
+ * MPC85xx Device descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala at freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/fsl_devices.h>
+#include <asm/mpc85xx.h>
+
+/* These should be defined in platform code */
+extern struct gianfar_platform_data mpc85xx_gianfar1_def;
+
+/* We use offsets for IORESOURCE_MEM since we do not know at compile time
+ * what CCSRBAR is, platform code should fix this up in
+ * setup_arch
+ *
+ */
+
+static struct platform_device m_dev[] = {
+	[MPC85xx_TSEC1] = {
+		.name = "fsl-gianfar",
+		.id	= 1,
+		.flags	= GIANFAR_HAS_GIGABIT | GIANFAR_HAS_MULTI_INTR | GIANFAR_HAS_RMON | GIANFAR_HAS_COALESCE,
+		.num_resources	 = 4,
+		.dev.platform_data = &mpc85xx_gianfar1_def, 
+		.resource = (struct resource[]) {
+			{
+				.start	= MPC85xx_ENET1_OFFSET,
+				.end	= MPC85xx_ENET1_OFFSET + MPC85xx_ENET1_SIZE - 1,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name	= "tx",
+				.start	= MPC85xx_IRQ_TSEC1_TX,
+				.end	= MPC85xx_IRQ_TSEC1_TX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "rx",
+				.start	= MPC85xx_IRQ_TSEC1_RX,
+				.end	= MPC85xx_IRQ_TSEC1_RX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "error",
+				.start	= MPC85xx_IRQ_TSEC1_ERROR,
+				.end	= MPC85xx_IRQ_TSEC1_ERROR,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC85xx_TSEC2] = {
+		.name = "fsl-gianfar",
+		.id	= 2,
+		.flags	= GIANFAR_HAS_GIGABIT | GIANFAR_HAS_MULTI_INTR | GIANFAR_HAS_RMON | GIANFAR_HAS_COALESCE,
+		.num_resources	 = 4,
+		.resource = (struct resource[]) {
+			{
+				.start	= MPC85xx_ENET2_OFFSET,
+				.end	= MPC85xx_ENET2_OFFSET + MPC85xx_ENET2_SIZE - 1,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name	= "tx",
+				.start	= MPC85xx_IRQ_TSEC2_TX,
+				.end	= MPC85xx_IRQ_TSEC2_TX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "rx",
+				.start	= MPC85xx_IRQ_TSEC2_RX,
+				.end	= MPC85xx_IRQ_TSEC2_RX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "error",
+				.start	= MPC85xx_IRQ_TSEC2_ERROR,
+				.end	= MPC85xx_IRQ_TSEC2_ERROR,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC85xx_FEC] =	{
+		.name = "fsl-gianfar",
+		.id	= 3,
+		.num_resources	 = 2,
+		.resource = (struct resource[]) {
+			{
+				.start	= MPC85xx_ENET3_OFFSET,
+				.end	= MPC85xx_ENET3_OFFSET + MPC85xx_ENET3_SIZE - 1,
+				.flags	= IORESOURCE_MEM,
+
+			},
+			{
+				.start	= MPC85xx_IRQ_TSEC1_TX,
+				.end	= MPC85xx_IRQ_TSEC1_TX,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC85xx_IIC1] = {
+		.name = "fsl-i2c",
+		.id	= 1,
+		.flags	= FSL_I2C_SEPARATE_DFSRR,
+		.num_resources	 = 2,
+		.resource = (struct resource[]) {
+			{
+				.start	= MPC85xx_IIC1_OFFSET,
+				.end	= MPC85xx_IIC1_OFFSET + MPC85xx_IIC1_SIZE - 1,
+				.flags	= IORESOURCE_MEM,
+
+			},
+			{
+				.start	= MPC85xx_IRQ_IIC1,
+				.end	= MPC85xx_IRQ_IIC1,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC85xx_DMA0] = {
+		.name = "fsl-dma",
+		.id	= 0,
+		.num_resources	 = 2,
+		.resource = (struct resource[]) {
+			{
+				.start	= MPC85xx_DMA0_OFFSET,
+				.end	= MPC85xx_DMA0_OFFSET + MPC85xx_DMA0_SIZE - 1,
+				.flags	= IORESOURCE_MEM,
+
+			},
+			{
+				.start	= MPC85xx_IRQ_DMA0,
+				.end	= MPC85xx_IRQ_DMA0,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC85xx_DMA1] = {
+		.name = "fsl-dma",
+		.id	= 1,
+		.num_resources	 = 2,
+		.resource = (struct resource[]) {
+			{
+				.start	= MPC85xx_DMA1_OFFSET,
+				.end	= MPC85xx_DMA1_OFFSET + MPC85xx_DMA1_SIZE - 1,
+				.flags	= IORESOURCE_MEM,
+
+			},
+			{
+				.start	= MPC85xx_IRQ_DMA1,
+				.end	= MPC85xx_IRQ_DMA1,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC85xx_DMA2] = {
+		.name = "fsl-dma",
+		.id	= 2,
+		.num_resources	 = 2,
+		.resource = (struct resource[]) {
+			{
+				.start	= MPC85xx_DMA2_OFFSET,
+				.end	= MPC85xx_DMA2_OFFSET + MPC85xx_DMA2_SIZE - 1,
+				.flags	= IORESOURCE_MEM,
+
+			},
+			{
+				.start	= MPC85xx_IRQ_DMA2,
+				.end	= MPC85xx_IRQ_DMA2,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC85xx_DMA3] = {
+		.name = "fsl-dma",
+		.id	= 3,
+		.num_resources	 = 2,
+		.resource = (struct resource[]) {
+			{
+				.start	= MPC85xx_DMA3_OFFSET,
+				.end	= MPC85xx_DMA3_OFFSET + MPC85xx_DMA3_SIZE - 1,
+				.flags	= IORESOURCE_MEM,
+
+			},
+			{
+				.start	= MPC85xx_IRQ_DMA3,
+				.end	= MPC85xx_IRQ_DMA3,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+
+};
+
+static int
+mpc85xx_update_paddr(struct device *dev, void *arg)
+{
+	phys_addr_t ccsrbar;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct resource * r;
+
+	/* xxx - this only gets ioresource_mem 0 */
+	if (arg) {
+		ccsrbar = *(phys_addr_t *)arg;
+		r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		r->start += ccsrbar;
+		r->end += ccsrbar;
+	}
+	return 0;
+}
+
+static int __init mach_mpc85xx_init(void)
+{
+	phys_addr_t ccsr = CCSRBAR;
+	platform_device_register(&m_dev[MPC85xx_TSEC1]);
+#if 0
+	platform_device_register(&m_dev[MPC85xx_TSEC2]);
+	platform_device_register(&m_dev[MPC85xx_FEC]);
+#endif
+	platform_device_register(&m_dev[MPC85xx_IIC1]);
+	platform_device_register(&m_dev[MPC85xx_DMA0]);
+	platform_device_register(&m_dev[MPC85xx_DMA1]);
+	platform_device_register(&m_dev[MPC85xx_DMA2]);
+	platform_device_register(&m_dev[MPC85xx_DMA3]);
+
+	bus_for_each_dev(&platform_bus_type, NULL, &ccsr, mpc85xx_update_paddr);
+	return 0;
+}
+
+subsys_initcall(mach_mpc85xx_init);
+
diff -Nru a/drivers/base/platform.c b/drivers/base/platform.c
--- a/drivers/base/platform.c	2004-12-08 22:22:37 -06:00
+++ b/drivers/base/platform.c	2004-12-08 22:22:37 -06:00
@@ -58,6 +58,42 @@
 }
 
 /**
+ *	platform_get_resource_byname - get a resource for a device by name
+ *	@dev: platform device
+ *	@type: resource type
+ *	@name: resource name
+ */
+struct resource *
+platform_get_resource_byname(struct platform_device *dev, unsigned int type,
+		      char * name)
+{
+	int i;
+
+	for (i = 0; i < dev->num_resources; i++) {
+		struct resource *r = &dev->resource[i];
+
+		if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
+				 IORESOURCE_IRQ|IORESOURCE_DMA))
+		    == type)
+			if (!strcmp(r->name, name))
+				return r;
+	}
+	return NULL;
+}
+
+/**
+ *	platform_get_irq - get an IRQ for a device
+ *	@dev: platform device
+ *	@name: IRQ name
+ */
+int platform_get_irq_byname(struct platform_device *dev, char * name)
+{
+	struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name);
+
+	return r ? r->start : 0;
+}
+
+/**
  *	platform_add_devices - add a numbers of platform devices
  *	@devs: array of platform devices to add
  *	@num: number of platform devices in array
@@ -103,7 +139,8 @@
 	for (i = 0; i < pdev->num_resources; i++) {
 		struct resource *p, *r = &pdev->resource[i];
 
-		r->name = pdev->dev.bus_id;
+		if (r->name == NULL)
+			r->name = pdev->dev.bus_id;
 
 		p = NULL;
 		if (r->flags & IORESOURCE_MEM)
@@ -308,3 +345,5 @@
 EXPORT_SYMBOL_GPL(platform_device_unregister);
 EXPORT_SYMBOL_GPL(platform_get_irq);
 EXPORT_SYMBOL_GPL(platform_get_resource);
+EXPORT_SYMBOL_GPL(platform_get_irq_byname);
+EXPORT_SYMBOL_GPL(platform_get_resource_byname);
diff -Nru a/drivers/net/gianfar.c b/drivers/net/gianfar.c
--- a/drivers/net/gianfar.c	2004-12-08 22:22:37 -06:00
+++ b/drivers/net/gianfar.c	2004-12-08 22:22:37 -06:00
@@ -85,6 +85,7 @@
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
+#include <linux/device.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -93,6 +94,7 @@
 #include <linux/version.h>
 #include <linux/dma-mapping.h>
 #include <linux/crc32.h>
+#include <linux/fsl_devices.h>
 
 #include "gianfar.h"
 #include "gianfar_phy.h"
@@ -130,8 +132,12 @@
 static void adjust_link(struct net_device *dev);
 static void init_registers(struct net_device *dev);
 static int init_phy(struct net_device *dev);
+#if 0
 static int gfar_probe(struct ocp_device *ocpdev);
 static void gfar_remove(struct ocp_device *ocpdev);
+#endif
+static int gfar_probe(struct device *device);
+static int gfar_remove(struct device *device);
 void free_skb_resources(struct gfar_private *priv);
 static void gfar_set_multi(struct net_device *dev);
 static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
@@ -148,6 +154,7 @@
 MODULE_DESCRIPTION("Gianfar Ethernet Driver");
 MODULE_LICENSE("GPL");
 
+#if 0
 /* Called by the ocp code to initialize device data structures
  * required for bringing up the device
  * returns 0 on success */
@@ -196,7 +203,7 @@
 	priv = netdev_priv(dev);
 
 	/* Set the info in the priv to the current info */
-	priv->einfo = einfo;
+	priv->einfo = pdev;
 
 	/* get a pointer to the register memory */
 	priv->regs = (struct gfar *)
@@ -343,6 +350,223 @@
 	iounmap((void *) priv->phyregs);
 	free_netdev(dev);
 }
+#endif
+
+static int gfar_probe(struct device *device)
+{
+	u32 tempval;
+	struct platform_device *mdiodev;
+	struct net_device *dev = NULL;
+	struct gfar_private *priv = NULL;
+	struct platform_device *pdev = to_platform_device(device);
+	struct gianfar_platform_data *pdinfo;
+	struct resource *r;
+	int idx;
+	int err = 0;
+	int dev_ethtool_ops = 0;
+
+	pdinfo = (struct gianfar_platform_data *) pdev->dev.platform_data;
+
+	if (pdinfo == NULL) {
+		printk(KERN_ERR "gfar %d: Missing additional data!\n",
+		       pdev->id);
+
+		return -ENODEV;
+	}
+	
+	/* get a pointer to the register memory which can
+	 * configure the PHYs.  If it's different from this set,
+	 * get the device which has those regs */
+	if ((pdinfo->phyregidx >= 0) && 
+			(pdinfo->phyregidx != pdev->id)) {
+
+		/* xxx - broken, gregkh tells me device_find has locking issues */
+		/* only enable the 1st TSEC for now */
+		struct device *d = device_find(pdinfo->phydevice, &platform_bus_type);
+
+		mdiodev = to_platform_device(d);
+
+		/* If the device which holds the MDIO regs isn't
+		 * up, wait for it to come up */
+		if (mdiodev == NULL)
+			return -EAGAIN;
+	} else {
+		mdiodev = pdev;
+	}
+
+	/* Create an ethernet device instance */
+	dev = alloc_etherdev(sizeof (*priv));
+
+	if (dev == NULL)
+		return -ENOMEM;
+
+	priv = netdev_priv(dev);
+
+	/* fill out IRQ fields */
+
+	if (pdev->flags & GFAR_HAS_MULTI_INTR) {
+		priv->interruptTransmit = platform_get_irq_byname(pdev, "tx");
+		priv->interruptReceive = platform_get_irq_byname(pdev, "rx");
+		priv->interruptError = platform_get_irq_byname(pdev, "error");
+	} else {
+		priv->interruptTransmit = platform_get_irq(pdev, 0);
+	}
+
+	/* Set the info in the priv to the current info */
+	priv->einfo = pdev;
+	priv->pdinfo = pdinfo;
+
+	/* get a pointer to the register memory */
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->regs = (struct gfar *)
+		ioremap(r->start, sizeof (struct gfar));
+
+	if (priv->regs == NULL) {
+		err = -ENOMEM;
+		goto regs_fail;
+	}
+
+	/* Set the PHY base address */
+	r = platform_get_resource(mdiodev, IORESOURCE_MEM, 0);
+	priv->phyregs = (struct gfar *)
+	    ioremap(r->start, sizeof (struct gfar));
+
+	if (priv->phyregs == NULL) {
+		err = -ENOMEM;
+		goto phy_regs_fail;
+	}
+
+	spin_lock_init(&priv->lock);
+
+	dev_set_drvdata(device, dev);
+
+	/* Stop the DMA engine now, in case it was running before */
+	/* (The firmware could have used it, and left it running). */
+	/* To do this, we write Graceful Receive Stop and Graceful */
+	/* Transmit Stop, and then wait until the corresponding bits */
+	/* in IEVENT indicate the stops have completed. */
+	tempval = gfar_read(&priv->regs->dmactrl);
+	tempval &= ~(DMACTRL_GRS | DMACTRL_GTS);
+	gfar_write(&priv->regs->dmactrl, tempval);
+
+	tempval = gfar_read(&priv->regs->dmactrl);
+	tempval |= (DMACTRL_GRS | DMACTRL_GTS);
+	gfar_write(&priv->regs->dmactrl, tempval);
+
+	while (!(gfar_read(&priv->regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC)))
+		cpu_relax();
+
+	/* Reset MAC layer */
+	gfar_write(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
+
+	tempval = (MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
+	gfar_write(&priv->regs->maccfg1, tempval);
+
+	/* Initialize MACCFG2. */
+	gfar_write(&priv->regs->maccfg2, MACCFG2_INIT_SETTINGS);
+
+	/* Initialize ECNTRL */
+	gfar_write(&priv->regs->ecntrl, ECNTRL_INIT_SETTINGS);
+
+	/* Copy the station address into the dev structure, */
+	memcpy(dev->dev_addr, pdinfo->mac_addr, MAC_ADDR_LEN);
+
+	/* Set the dev->base_addr to the gfar reg region */
+	dev->base_addr = (unsigned long) (priv->regs);
+
+	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, device);
+
+	/* Fill in the dev structure */
+	dev->open = gfar_enet_open;
+	dev->hard_start_xmit = gfar_start_xmit;
+	dev->tx_timeout = gfar_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_GFAR_NAPI
+	dev->poll = gfar_poll;
+	dev->weight = GFAR_DEV_WEIGHT;
+#endif
+	dev->stop = gfar_close;
+	dev->get_stats = gfar_get_stats;
+	dev->change_mtu = gfar_change_mtu;
+	dev->mtu = 1500;
+	dev->set_multicast_list = gfar_set_multi;
+
+	/* Index into the array of possible ethtool
+	 * ops to catch all 4 possibilities */
+	if((priv->einfo->flags & GFAR_HAS_RMON) == 0)
+		dev_ethtool_ops += 1;
+
+	if((priv->einfo->flags & GFAR_HAS_COALESCE) == 0)
+		dev_ethtool_ops += 2;
+
+	dev->ethtool_ops = gfar_op_array[dev_ethtool_ops];
+
+	priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
+#ifdef CONFIG_GFAR_BUFSTASH
+	priv->rx_stash_size = STASH_LENGTH;
+#endif
+	priv->tx_ring_size = DEFAULT_TX_RING_SIZE;
+	priv->rx_ring_size = DEFAULT_RX_RING_SIZE;
+
+	priv->txcoalescing = DEFAULT_TX_COALESCE;
+	priv->txcount = DEFAULT_TXCOUNT;
+	priv->txtime = DEFAULT_TXTIME;
+	priv->rxcoalescing = DEFAULT_RX_COALESCE;
+	priv->rxcount = DEFAULT_RXCOUNT;
+	priv->rxtime = DEFAULT_RXTIME;
+
+	err = register_netdev(dev);
+
+	if (err) {
+		printk(KERN_ERR "%s: Cannot register net device, aborting.\n",
+				dev->name);
+		goto register_fail;
+	}
+
+	/* Print out the device info */
+	printk(KERN_INFO DEVICE_NAME, dev->name);
+	for (idx = 0; idx < 6; idx++)
+		printk("%2.2x%c", dev->dev_addr[idx], idx == 5 ? ' ' : ':');
+	printk("\n");
+
+	/* Even more device info helps when determining which kernel */
+	/* provided which set of benchmarks.  Since this is global for all */
+	/* devices, we only print it once */
+#ifdef CONFIG_GFAR_NAPI
+	printk(KERN_INFO "%s: Running with NAPI enabled\n", dev->name);
+#else
+	printk(KERN_INFO "%s: Running with NAPI disabled\n", dev->name);
+#endif
+	printk(KERN_INFO "%s: %d/%d RX/TX BD ring size\n",
+	       dev->name, priv->rx_ring_size, priv->tx_ring_size);
+
+	return 0;
+
+register_fail:
+	iounmap((void *) priv->phyregs);
+phy_regs_fail:
+	iounmap((void *) priv->regs);
+regs_fail:
+	free_netdev(dev);
+	return -ENOMEM;
+	return 0;
+}
+
+static int gfar_remove(struct device *device)
+{
+	struct net_device *dev = dev_get_drvdata(device);
+	struct gfar_private *priv = netdev_priv(dev);
+
+	dev_set_drvdata(device, NULL);
+
+	iounmap((void *) priv->regs);
+	iounmap((void *) priv->phyregs);
+	free_netdev(dev);
+
+	return 0;
+}
+
 
 /* Configure the PHY for dev.
  * returns 0 if success.  -1 if failure
@@ -381,7 +605,7 @@
 			ADVERTISED_1000baseT_Full);
 	mii_info->autoneg = 1;
 
-	mii_info->mii_id = priv->einfo->phyid;
+	mii_info->mii_id = priv->pdinfo->phyid;
 
 	mii_info->dev = dev;
 
@@ -549,15 +773,15 @@
 
 	/* Free the IRQs */
 	if (priv->einfo->flags & GFAR_HAS_MULTI_INTR) {
-		free_irq(priv->einfo->interruptError, dev);
-		free_irq(priv->einfo->interruptTransmit, dev);
-		free_irq(priv->einfo->interruptReceive, dev);
+		free_irq(priv->interruptError, dev);
+		free_irq(priv->interruptTransmit, dev);
+		free_irq(priv->interruptReceive, dev);
 	} else {
-		free_irq(priv->einfo->interruptTransmit, dev);
+		free_irq(priv->interruptTransmit, dev);
 	}
 
 	if (priv->einfo->flags & GFAR_HAS_PHY_INTR) {
-		free_irq(priv->einfo->interruptPHY, dev);
+		free_irq(priv->pdinfo->interruptPHY, dev);
 	} else {
 		del_timer_sync(&priv->phy_info_timer);
 	}
@@ -730,38 +954,38 @@
 	if (priv->einfo->flags & GFAR_HAS_MULTI_INTR) {
 		/* Install our interrupt handlers for Error, 
 		 * Transmit, and Receive */
-		if (request_irq(priv->einfo->interruptError, gfar_error,
+		if (request_irq(priv->interruptError, gfar_error,
 				0, "enet_error", dev) < 0) {
 			printk(KERN_ERR "%s: Can't get IRQ %d\n",
-			       dev->name, priv->einfo->interruptError);
+			       dev->name, priv->interruptError);
 
 			err = -1;
 			goto err_irq_fail;
 		}
 
-		if (request_irq(priv->einfo->interruptTransmit, gfar_transmit,
+		if (request_irq(priv->interruptTransmit, gfar_transmit,
 				0, "enet_tx", dev) < 0) {
 			printk(KERN_ERR "%s: Can't get IRQ %d\n",
-			       dev->name, priv->einfo->interruptTransmit);
+			       dev->name, priv->interruptTransmit);
 
 			err = -1;
 
 			goto tx_irq_fail;
 		}
 
-		if (request_irq(priv->einfo->interruptReceive, gfar_receive,
+		if (request_irq(priv->interruptReceive, gfar_receive,
 				0, "enet_rx", dev) < 0) {
 			printk(KERN_ERR "%s: Can't get IRQ %d (receive0)\n",
-			       dev->name, priv->einfo->interruptReceive);
+			       dev->name, priv->interruptReceive);
 
 			err = -1;
 			goto rx_irq_fail;
 		}
 	} else {
-		if (request_irq(priv->einfo->interruptTransmit, gfar_interrupt,
+		if (request_irq(priv->interruptTransmit, gfar_interrupt,
 				0, "gfar_interrupt", dev) < 0) {
 			printk(KERN_ERR "%s: Can't get IRQ %d\n",
-			       dev->name, priv->einfo->interruptError);
+			       dev->name, priv->interruptError);
 
 			err = -1;
 			goto err_irq_fail;
@@ -815,9 +1039,9 @@
 	return 0;
 
 rx_irq_fail:
-	free_irq(priv->einfo->interruptTransmit, dev);
+	free_irq(priv->interruptTransmit, dev);
 tx_irq_fail:
-	free_irq(priv->einfo->interruptError, dev);
+	free_irq(priv->interruptError, dev);
 err_irq_fail:
 rx_skb_fail:
 	free_skb_resources(priv);
@@ -1548,14 +1772,14 @@
 
 	/* Grab the PHY interrupt, if necessary/possible */
 	if (priv->einfo->flags & GFAR_HAS_PHY_INTR) {
-		if (request_irq(priv->einfo->interruptPHY, 
+		if (request_irq(priv->pdinfo->interruptPHY, 
 					phy_interrupt,
 					SA_SHIRQ, 
 					"phy_interrupt", 
 					mii_info->dev) < 0) {
 			printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n",
 					mii_info->dev->name,
-					priv->einfo->interruptPHY);
+					priv->pdinfo->interruptPHY);
 		} else {
 			mii_configure_phy_interrupt(priv->mii_info, 
 					MII_INTERRUPT_ENABLED);
@@ -1828,6 +2052,7 @@
 	return IRQ_HANDLED;
 }
 
+#if 0
 /* Structure for a device driver */
 static struct ocp_device_id gfar_ids[] = {
 	{.vendor = OCP_ANY_ID,.function = OCP_FUNC_GFAR},
@@ -1862,3 +2087,26 @@
 
 module_init(gfar_init);
 module_exit(gfar_exit);
+#endif 
+
+/* Structure for a device driver */
+static struct device_driver gfar_driver = {
+	.name = "fsl-gianfar",
+	.bus = &platform_bus_type,
+	.probe = gfar_probe,
+	.remove = gfar_remove,
+};
+
+static int __init gfar_init(void)
+{
+	return driver_register(&gfar_driver);
+}
+
+static void __exit gfar_exit(void)
+{
+	driver_unregister(&gfar_driver);
+}
+
+module_init(gfar_init);
+module_exit(gfar_exit);
+
diff -Nru a/drivers/net/gianfar.h b/drivers/net/gianfar.h
--- a/drivers/net/gianfar.h	2004-12-08 22:22:37 -06:00
+++ b/drivers/net/gianfar.h	2004-12-08 22:22:37 -06:00
@@ -510,7 +510,11 @@
 	unsigned int rxclean;
 
 	/* Info structure initialized by board setup code */
-	struct ocp_gfar_data *einfo;
+	unsigned int interruptTransmit;
+	unsigned int interruptReceive;
+	unsigned int interruptError;
+	struct platform_device *einfo;
+	struct gianfar_platform_data *pdinfo;
 
 	struct gfar_mii_info *mii_info;
 	int oldspeed;
diff -Nru a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h
--- a/include/asm-ppc/mpc85xx.h	2004-12-08 22:22:37 -06:00
+++ b/include/asm-ppc/mpc85xx.h	2004-12-08 22:22:37 -06:00
@@ -103,6 +103,14 @@
 #define MPC85xx_CPM_SIZE	(0x40000)
 #define MPC85xx_DMA_OFFSET	(0x21000)
 #define MPC85xx_DMA_SIZE	(0x01000)
+#define MPC85xx_DMA0_OFFSET	(0x21100)
+#define MPC85xx_DMA0_SIZE	(0x00080)
+#define MPC85xx_DMA1_OFFSET	(0x21180)
+#define MPC85xx_DMA1_SIZE	(0x00080)
+#define MPC85xx_DMA2_OFFSET	(0x21200)
+#define MPC85xx_DMA2_SIZE	(0x00080)
+#define MPC85xx_DMA3_OFFSET	(0x21280)
+#define MPC85xx_DMA3_SIZE	(0x00080)
 #define MPC85xx_ENET1_OFFSET	(0x24000)
 #define MPC85xx_ENET1_SIZE	(0x01000)
 #define MPC85xx_ENET2_OFFSET	(0x25000)
@@ -138,6 +146,17 @@
 #else
 #define CCSRBAR BOARD_CCSRBAR
 #endif
+
+enum mpc85xx_devices {
+	MPC85xx_TSEC1,
+	MPC85xx_TSEC2,
+	MPC85xx_FEC,
+	MPC85xx_IIC1,
+	MPC85xx_DMA0,
+	MPC85xx_DMA1,
+	MPC85xx_DMA2,
+	MPC85xx_DMA3,
+};
 
 #endif /* CONFIG_85xx */
 #endif /* __ASM_MPC85xx_H__ */
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	2004-12-08 22:22:37 -06:00
+++ b/include/linux/device.h	2004-12-08 22:22:37 -06:00
@@ -370,6 +370,7 @@
 	struct device	dev;
 	u32		num_resources;
 	struct resource	* resource;
+	u32		flags;
 };
 
 #define to_platform_device(x) container_of((x), struct platform_device, dev)
@@ -382,6 +383,8 @@
 
 extern struct resource *platform_get_resource(struct platform_device *, unsigned int, unsigned int);
 extern int platform_get_irq(struct platform_device *, unsigned int);
+extern struct resource *platform_get_resource_byname(struct platform_device *, unsigned int, char *);
+extern int platform_get_irq_byname(struct platform_device *, char *);
 extern int platform_add_devices(struct platform_device **, int);
 
 extern struct platform_device *platform_device_register_simple(char *, unsigned int, struct resource *, unsigned int);
diff -Nru a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/fsl_devices.h	2004-12-08 22:22:37 -06:00
@@ -0,0 +1,48 @@
+/*
+ * include/linux/fsl_devices.h
+ *
+ * Definitions for any platform device related flags or structures for 
+ * Freescale processor devices
+ *
+ * Maintainer: Kumar Gala (kumar.gala at freescale.com)
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc
+ *
+ * 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.
+ */
+
+#ifdef __KERNEL__
+#ifndef _FSL_DEVICE_H_
+#define _FSL_DEVICE_H_
+
+/* A table of information for supporting the Gianfar Ethernet Controller
+ * This helps identify which enet controller we are dealing with,
+ * and what type of enet controller it is
+ */
+struct gianfar_platform_data {
+	u32 flags;
+	u32 phyid;
+	uint interruptPHY;
+	uint phyregidx;
+	char * phydevice;
+	unsigned char mac_addr[6];
+};
+
+/* Flags related to gianfar device features */
+#define GIANFAR_HAS_GIGABIT		0x00000001
+#define GIANFAR_HAS_COALESCE		0x00000002
+#define GIANFAR_HAS_RMON		0x00000004
+#define GIANFAR_HAS_MULTI_INTR		0x00000008
+
+/* Flags in gianfar_platform_data */
+#define GIANFAR_PDATA_HAS_PHY_INTR	0x00000001	/* if not set use a timer */
+
+/* Flags related to I2C device features */
+#define FSL_I2C_SEPARATE_DFSRR		0x00000001
+#define FSL_I2C_CLOCK_5200		0x00000002
+
+#endif	/* _FSL_DEVICE_H_ */
+#endif	/* __KERNEL__ */



More information about the Linuxppc-embedded mailing list