MPC8280 Linux Kernel Patch

Srivatsan srivatsan at deccanetworld.com
Fri Dec 10 02:13:54 EST 2004


Greetings to all.


Can anyone give me pointers where I can find patch for supporting
MPC8280 processor for Linuxppc Kernel 2.4.20(has support for MPC8260)? 

The help would be highly appreciated.

With Best Regards,
C.R.Srivatsan

-----Original Message-----
From: linuxppc-embedded-bounces at ozlabs.org
[mailto:linuxppc-embedded-bounces at ozlabs.org] On Behalf Of
linuxppc-embedded-request at ozlabs.org
Sent: Thursday, December 09, 2004 10:26 AM
To: linuxppc-embedded at ozlabs.org
Subject: Linuxppc-embedded Digest, Vol 4, Issue 13

Send Linuxppc-embedded mailing list submissions to
	linuxppc-embedded at ozlabs.org

To subscribe or unsubscribe via the World Wide Web, visit
	https://ozlabs.org/mailman/listinfo/linuxppc-embedded
or, via email, send a message with subject or body 'help' to
	linuxppc-embedded-request at ozlabs.org

You can reach the person managing the list at
	linuxppc-embedded-owner at ozlabs.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Linuxppc-embedded digest..."


Today's Topics:

   1. Linux PCI support on Ocotea (Chris Love)
   2. Re: Linux PCI support on Ocotea (Matt Porter)
   3. Re: Linux PCI support on Ocotea (Chris Love)
   4. [RFC][PPC32] platform device / driver model usage (Kumar Gala)


----------------------------------------------------------------------

Message: 1
Date: Wed, 08 Dec 2004 17:10:54 -0800
From: Chris Love <love at ccpu.com>
Subject: Linux PCI support on Ocotea
To: linuxppc-embedded at ozlabs.org
Message-ID: <41B7A61E.9000602 at ccpu.com>
Content-Type: text/plain; charset=us-ascii; format=flowed

Hi folks,

We have an Ocotea reference board (PPC 440GX) w/256M and have
tried running both stable 2.4.26 and 2.6.10-rc3 kernels from
penguinppc.org.  For now the bootloader is still PIBS, though
we'll get U-Boot installed shortly.

As a first experiment we've tried installing a legacy card
with an Intel 82559 device on it.  The warning seen from
pci_setup_device() suggests that PCI config space wasn't
read cleanly: a header type of 0x7f is encountered.  Nothing
shows up under /proc/bus/pci. The card we'd actually like to
install has a transparent bridge (Intel 21152) and other devices
behind the bridge.  Both cards are PCI-33 versus PCI-X.

To ask some really stupid questions first: what is the state of
PCI support with linux on this board?  Have others tried to do
something like this with 33/66 Mhz PCI devices or am I in
uncharted waters?

Of the PCI #defines in platforms/ocotea.h I can correlate most
with data from the user's manual, but not the following:

#define OCOTEA_PCI_LOWER_IO     0x00000000
#define OCOTEA_PCI_UPPER_IO     0x0000ffff
#define OCOTEA_PCI_LOWER_MEM    0x80000000
#define OCOTEA_PCI_UPPER_MEM    0xffffefff

Is there some documentation I'm missing on these values?

Thanks in advance for any suggestions,

	Chris
-- 
Chris Love      // Continuous Computing Corporation
love at ccpu.com  // http://www.ccpu.com


------------------------------

Message: 2
Date: Wed, 8 Dec 2004 18:49:58 -0700
From: Matt Porter <mporter at kernel.crashing.org>
Subject: Re: Linux PCI support on Ocotea
To: Chris Love <love at ccpu.com>
Cc: linuxppc-embedded at ozlabs.org
Message-ID: <20041208184958.A22430 at home.com>
Content-Type: text/plain; charset=us-ascii

On Wed, Dec 08, 2004 at 05:10:54PM -0800, Chris Love wrote:
> Hi folks,
> 
> We have an Ocotea reference board (PPC 440GX) w/256M and have
> tried running both stable 2.4.26 and 2.6.10-rc3 kernels from
> penguinppc.org.  For now the bootloader is still PIBS, though
> we'll get U-Boot installed shortly.
> 
> As a first experiment we've tried installing a legacy card
> with an Intel 82559 device on it.  The warning seen from
> pci_setup_device() suggests that PCI config space wasn't
> read cleanly: a header type of 0x7f is encountered.  Nothing
> shows up under /proc/bus/pci. The card we'd actually like to
> install has a transparent bridge (Intel 21152) and other devices
> behind the bridge.  Both cards are PCI-33 versus PCI-X.

Sounds like something is wrong with your hardware configuration.

> To ask some really stupid questions first: what is the state of
> PCI support with linux on this board?  Have others tried to do
> something like this with 33/66 Mhz PCI devices or am I in
> uncharted waters?

No, this works fine for many other people, so don't get too worried.
Do verify that you have jumpered for 33Mhz operation since you
are using a 33Mhz device. PIBS should warn you about this and
advise to make the change, but maybe you have a different
version than I've seen. What rev. ocotea board and version of
PIBS do you have?

> Of the PCI #defines in platforms/ocotea.h I can correlate most
> with data from the user's manual, but not the following:
> 
> #define OCOTEA_PCI_LOWER_IO     0x00000000
> #define OCOTEA_PCI_UPPER_IO     0x0000ffff
> #define OCOTEA_PCI_LOWER_MEM    0x80000000
> #define OCOTEA_PCI_UPPER_MEM    0xffffefff
> 
> Is there some documentation I'm missing on these values?

The code is self-documenting as they say. :) These are the address
ranges used by the pci_auto code to assign base addresses to each
BAR that is encountered.

-Matt


------------------------------

Message: 3
Date: Wed, 08 Dec 2004 18:20:29 -0800
From: Chris Love <love at ccpu.com>
Subject: Re: Linux PCI support on Ocotea
To: Matt Porter <mporter at kernel.crashing.org>
Cc: linuxppc-embedded at ozlabs.org
Message-ID: <41B7B66D.2000409 at ccpu.com>
Content-Type: text/plain; charset=us-ascii; format=flowed



Matt Porter wrote:
> On Wed, Dec 08, 2004 at 05:10:54PM -0800, Chris Love wrote:
> 
>>Hi folks,
>>
>>We have an Ocotea reference board (PPC 440GX) w/256M and have
>>tried running both stable 2.4.26 and 2.6.10-rc3 kernels from
>>penguinppc.org.  For now the bootloader is still PIBS, though
>>we'll get U-Boot installed shortly.
>>
>>As a first experiment we've tried installing a legacy card
>>with an Intel 82559 device on it.  The warning seen from
>>pci_setup_device() suggests that PCI config space wasn't
>>read cleanly: a header type of 0x7f is encountered.  Nothing
>>shows up under /proc/bus/pci. The card we'd actually like to
>>install has a transparent bridge (Intel 21152) and other devices
>>behind the bridge.  Both cards are PCI-33 versus PCI-X.
> 
> 
> Sounds like something is wrong with your hardware configuration.
> 
> 
>>To ask some really stupid questions first: what is the state of
>>PCI support with linux on this board?  Have others tried to do
>>something like this with 33/66 Mhz PCI devices or am I in
>>uncharted waters?
> 
> 
> No, this works fine for many other people, so don't get too worried.
> Do verify that you have jumpered for 33Mhz operation since you
> are using a 33Mhz device. PIBS should warn you about this and
> advise to make the change, but maybe you have a different
> version than I've seen. What rev. ocotea board and version of
> PIBS do you have?

Hi Matt,

PIBS version text is "Version 1.80 JUNE/17/2004".
Ocotea rev appears to be rev 5.

Changing the settings for the U80 switches did the trick, at
least as far as silencing the PIBS warning and enumerating the bus
by Linux.

Thanks for the suggestion; this was lurking on the board schematics.

	Chris
-- 
Chris Love      // Continuous Computing Corporation
love at ccpu.com  // http://www.ccpu.com


------------------------------

Message: 4
Date: Wed, 8 Dec 2004 22:56:03 -0600 (CST)
From: Kumar Gala <galak at somerset.sps.mot.com>
Subject: [RFC][PPC32] platform device / driver model usage
To: linux-kernel at vger.kernel.org
Cc: linuxppc-embedded at ozlabs.org
Message-ID:
	<Pine.LNX.4.61.0412082233440.14848 at blarg.somerset.sps.mot.com>
Content-Type: TEXT/PLAIN; charset=US-ASCII

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__ */


------------------------------

_______________________________________________
Linuxppc-embedded mailing list
Linuxppc-embedded at ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded

End of Linuxppc-embedded Digest, Vol 4, Issue 13
************************************************




********************************DISCLAIMER**********************************

This e-mail and any attachment is for authorised use by the intended
recipient(s) only. It may contain proprietary material, confidential
information and/or be subject to legal privilege of Deccanet Designs Ltd.
If you have received this message in error, please notify the originator
immediately. If you are not the intended recipient, you are notified that
you are strictly prohibited from retaining, using, copying, altering or
disclosing the contents of this message.

****************************************************************************


More information about the Linuxppc-embedded mailing list