rpms/kernel/devel linux-2.6-efika-before-chrp.patch, NONE, 1.1 linux-2.6-mpc52xx-ata.patch, NONE, 1.1 linux-2.6-of_platform-uevent.patch, NONE, 1.1 linux-2.6-ohci-multi-init.patch, NONE, 1.1 linux-2.6-ohci-platform-bus.patch, NONE, 1.1 kernel-2.6.spec, 1.2880, 1.2881

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Sun Dec 17 17:29:09 UTC 2006


Author: dwmw2

Update of /cvs/dist/rpms/kernel/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv20035

Modified Files:
	kernel-2.6.spec 
Added Files:
	linux-2.6-efika-before-chrp.patch linux-2.6-mpc52xx-ata.patch 
	linux-2.6-of_platform-uevent.patch 
	linux-2.6-ohci-multi-init.patch 
	linux-2.6-ohci-platform-bus.patch 
Log Message:
Add efika support

linux-2.6-efika-before-chrp.patch:
 Makefile |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

--- NEW FILE linux-2.6-efika-before-chrp.patch ---
--- linux-2.6.19.ppc/arch/powerpc/platforms/Makefile~	2006-12-17 14:55:49.000000000 +0000
+++ linux-2.6.19.ppc/arch/powerpc/platforms/Makefile	2006-12-17 17:16:52.000000000 +0000
@@ -5,9 +5,9 @@ ifeq ($(CONFIG_PPC64),y)
 obj-$(CONFIG_PPC_PMAC)		+= powermac/
 endif
 endif
+obj-$(CONFIG_PPC_MPC52xx)	+= 52xx/
 obj-$(CONFIG_PPC_CHRP)		+= chrp/
 obj-$(CONFIG_4xx)		+= 4xx/
-obj-$(CONFIG_PPC_MPC52xx)	+= 52xx/
 obj-$(CONFIG_PPC_83xx)		+= 83xx/
 obj-$(CONFIG_PPC_85xx)		+= 85xx/
 obj-$(CONFIG_PPC_86xx)		+= 86xx/

linux-2.6-mpc52xx-ata.patch:
 Kconfig        |    9 
 Makefile       |    1 
 pata_mpc52xx.c |  563 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 573 insertions(+)

--- NEW FILE linux-2.6-mpc52xx-ata.patch ---
>From c735e6a135eca729c062d4d340ab409c9234fd40 Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt at 246tNt.com>
Date: Fri, 8 Dec 2006 00:08:14 +0100
Subject: [PATCH] libata: Add support for the MPC52xx ATA controller

This patch adds initial libata support for the Freescale
MPC5200 integrated IDE controller.

Signed-off-by: Sylvain Munaut <tnt at 246tNt.com>
---
 drivers/ata/Kconfig        |    9 +
 drivers/ata/Makefile       |    1 
 drivers/ata/pata_mpc52xx.c |  563 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 573 insertions(+), 0 deletions(-)

diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 984ab28..ec7c271 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -337,6 +337,15 @@ config PATA_MARVELL
 
 	  If unsure, say N.
 
+config PATA_MPC52xx
+	tristate "Freescale MPC52xx SoC internal IDE"
+	depends on PPC_MPC52xx
+	help
+	  This option enables support for integrated IDE controller
+	  of the Freescale MPC52xx SoC.
+
+	  If unsure, say N.
+
 config PATA_MPIIX
 	tristate "Intel PATA MPIIX support"
 	depends on PCI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index bc3d81a..3081e1f 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_PATA_NETCELL)	+= pata_netce
 obj-$(CONFIG_PATA_NS87410)	+= pata_ns87410.o
 obj-$(CONFIG_PATA_OPTI)		+= pata_opti.o
 obj-$(CONFIG_PATA_OPTIDMA)	+= pata_optidma.o
+obj-$(CONFIG_PATA_MPC52xx)	+= pata_mpc52xx.o
 obj-$(CONFIG_PATA_MARVELL)	+= pata_marvell.o
 obj-$(CONFIG_PATA_MPIIX)	+= pata_mpiix.o
 obj-$(CONFIG_PATA_OLDPIIX)	+= pata_oldpiix.o
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
new file mode 100644
index 0000000..8b7019a
--- /dev/null
+++ b/drivers/ata/pata_mpc52xx.c
@@ -0,0 +1,563 @@
+/*
+ * drivers/ata/pata_mpc52xx.c
+ *
+ * libata driver for the Freescale MPC52xx on-chip IDE interface
+ *
+ * Copyright (C) 2006 Sylvain Munaut <tnt at 246tNt.com>
+ * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/libata.h>
+
+#include <asm/io.h>
+#include <asm/types.h>
+#include <asm/prom.h>
+#include <asm/of_platform.h>
+#include <asm/mpc52xx.h>
+
+
+#define DRV_NAME	"mpc52xx_ata"
+#define DRV_VERSION	"0.1.0"
+
+
+/* Private structures used by the driver */
+struct mpc52xx_ata_timings {
+	u32	pio1;
+	u32	pio2;
+};
+
+struct mpc52xx_ata_priv {
+	unsigned int			ipb_period;
+	struct mpc52xx_ata __iomem *	ata_regs;
+	int				ata_irq;
+	struct mpc52xx_ata_timings	timings[2];
+	int				csel;
+};
+
+
+/* ATAPI-4 PIO specs (in ns) */
+static const int ataspec_t0[5]    = {600, 383, 240, 180, 120};
+static const int ataspec_t1[5]    = { 70,  50,  30,  30,  25};
+static const int ataspec_t2_8[5]  = {290, 290, 290,  80,  70};
+static const int ataspec_t2_16[5] = {165, 125, 100,  80,  70};
+static const int ataspec_t2i[5]   = {  0,   0,   0,  70,  25};
+static const int ataspec_t4[5]    = { 30,  20,  15,  10,  10};
+static const int ataspec_ta[5]    = { 35,  35,  35,  35,  35};
+
+#define CALC_CLKCYC(c,v) ((((v)+(c)-1)/(c)))
+
+
+/* Bit definitions inside the registers */
+#define MPC52xx_ATA_HOSTCONF_SMR	0x80000000UL /* State machine reset */
+#define MPC52xx_ATA_HOSTCONF_FR		0x40000000UL /* FIFO Reset */
+#define MPC52xx_ATA_HOSTCONF_IE		0x02000000UL /* Enable interrupt in PIO */
+#define MPC52xx_ATA_HOSTCONF_IORDY	0x01000000UL /* Drive supports IORDY protocol */
+
+#define MPC52xx_ATA_HOSTSTAT_TIP	0x80000000UL /* Transaction in progress */
+#define MPC52xx_ATA_HOSTSTAT_UREP	0x40000000UL /* UDMA Read Extended Pause */
+#define MPC52xx_ATA_HOSTSTAT_RERR	0x02000000UL /* Read Error */
+#define MPC52xx_ATA_HOSTSTAT_WERR	0x01000000UL /* Write Error */
+
+#define MPC52xx_ATA_FIFOSTAT_EMPTY	0x01 /* FIFO Empty */
+
+#define MPC52xx_ATA_DMAMODE_WRITE	0x01 /* Write DMA */
+#define MPC52xx_ATA_DMAMODE_READ	0x02 /* Read DMA */
+#define MPC52xx_ATA_DMAMODE_UDMA	0x04 /* UDMA enabled */
+#define MPC52xx_ATA_DMAMODE_IE		0x08 /* Enable drive interrupt to CPU in DMA mode */
+#define MPC52xx_ATA_DMAMODE_FE		0x10 /* FIFO Flush enable in Rx mode */
+#define MPC52xx_ATA_DMAMODE_FR		0x20 /* FIFO Reset */
+#define MPC52xx_ATA_DMAMODE_HUT		0x40 /* Host UDMA burst terminate */
+
+
+/* Structure of the hardware registers */
+struct mpc52xx_ata {
+
+	/* Host interface registers */
+	u32 config;		/* ATA + 0x00 Host configuration */
+	u32 host_status;	/* ATA + 0x04 Host controller status */
+	u32 pio1;		/* ATA + 0x08 PIO Timing 1 */
+	u32 pio2;		/* ATA + 0x0c PIO Timing 2 */
+	u32 mdma1;		/* ATA + 0x10 MDMA Timing 1 */
+	u32 mdma2;		/* ATA + 0x14 MDMA Timing 2 */
+	u32 udma1;		/* ATA + 0x18 UDMA Timing 1 */
+	u32 udma2;		/* ATA + 0x1c UDMA Timing 2 */
+	u32 udma3;		/* ATA + 0x20 UDMA Timing 3 */
+	u32 udma4;		/* ATA + 0x24 UDMA Timing 4 */
+	u32 udma5;		/* ATA + 0x28 UDMA Timing 5 */
+	u32 share_cnt;		/* ATA + 0x2c ATA share counter */
+	u32 reserved0[3];
+
+	/* FIFO registers */
+	u32 fifo_data;		/* ATA + 0x3c */
+	u8  fifo_status_frame;	/* ATA + 0x40 */
+	u8  fifo_status;	/* ATA + 0x41 */
+	u16 reserved7[1];
+	u8  fifo_control;	/* ATA + 0x44 */
+	u8  reserved8[5];
+	u16 fifo_alarm;		/* ATA + 0x4a */
+	u16 reserved9;
+	u16 fifo_rdp;		/* ATA + 0x4e */
+	u16 reserved10;
+	u16 fifo_wrp;		/* ATA + 0x52 */
+	u16 reserved11;
+	u16 fifo_lfrdp;		/* ATA + 0x56 */
+	u16 reserved12;
+	u16 fifo_lfwrp;		/* ATA + 0x5a */
+
+	/* Drive TaskFile registers */
+	u8  tf_control;		/* ATA + 0x5c TASKFILE Control/Alt Status */
+	u8  reserved13[3];
+	u16 tf_data;		/* ATA + 0x60 TASKFILE Data */
+	u16 reserved14;
+	u8  tf_features;	/* ATA + 0x64 TASKFILE Features/Error */
+	u8  reserved15[3];
+	u8  tf_sec_count;	/* ATA + 0x68 TASKFILE Sector Count */
+	u8  reserved16[3];
+	u8  tf_sec_num;		/* ATA + 0x6c TASKFILE Sector Number */
+	u8  reserved17[3];
+	u8  tf_cyl_low;		/* ATA + 0x70 TASKFILE Cylinder Low */
+	u8  reserved18[3];
+	u8  tf_cyl_high;	/* ATA + 0x74 TASKFILE Cylinder High */
+	u8  reserved19[3];
+	u8  tf_dev_head;	/* ATA + 0x78 TASKFILE Device/Head */
+	u8  reserved20[3];
+	u8  tf_command;		/* ATA + 0x7c TASKFILE Command/Status */
+	u8  dma_mode;		/* ATA + 0x7d ATA Host DMA Mode configuration */
+	u8  reserved21[2];
+};
+
+
+/* ======================================================================== */
+/* Aux fns                                                                  */
+/* ======================================================================== */
+
+
+/* MPC52xx low level hw control */
+
+static int
+mpc52xx_ata_compute_pio_timings(struct mpc52xx_ata_priv *priv, int dev, int pio)
+{
+	struct mpc52xx_ata_timings *timing = &priv->timings[dev];
+	unsigned int ipb_period = priv->ipb_period;
+	unsigned int t0, t1, t2_8, t2_16, t2i, t4, ta;
+
+	if ((pio<0) || (pio>4))
+		return -EINVAL;
+
+	t0	= CALC_CLKCYC(ipb_period, 1000 * ataspec_t0[pio]);
+	t1	= CALC_CLKCYC(ipb_period, 1000 * ataspec_t1[pio]);
+	t2_8	= CALC_CLKCYC(ipb_period, 1000 * ataspec_t2_8[pio]);
+	t2_16	= CALC_CLKCYC(ipb_period, 1000 * ataspec_t2_16[pio]);
+	t2i	= CALC_CLKCYC(ipb_period, 1000 * ataspec_t2i[pio]);
+	t4	= CALC_CLKCYC(ipb_period, 1000 * ataspec_t4[pio]);
+	ta	= CALC_CLKCYC(ipb_period, 1000 * ataspec_ta[pio]);
+
+	timing->pio1 = (t0 << 24) | (t2_8 << 16) | (t2_16 << 8) | (t2i);
+	timing->pio2 = (t4 << 24) | (t1 << 16) | (ta << 8);
+
+	return 0;
+}
+
+static void
+mpc52xx_ata_apply_timings(struct mpc52xx_ata_priv *priv, int device)
+{
+	struct mpc52xx_ata __iomem *regs = priv->ata_regs;
+	struct mpc52xx_ata_timings *timing = &priv->timings[device];
+
+	out_be32(&regs->pio1,  timing->pio1);
+	out_be32(&regs->pio2,  timing->pio2);
+	out_be32(&regs->mdma1, 0);
+	out_be32(&regs->mdma2, 0);
+	out_be32(&regs->udma1, 0);
+	out_be32(&regs->udma2, 0);
+	out_be32(&regs->udma3, 0);
+	out_be32(&regs->udma4, 0);
+	out_be32(&regs->udma5, 0);
+
+	priv->csel = device;
+}
+
+static int
+mpc52xx_ata_hw_init(struct mpc52xx_ata_priv *priv)
+{
+	struct mpc52xx_ata __iomem *regs = priv->ata_regs;
+	int tslot;
+
+	/* Clear share_cnt (all sample code do this ...) */
+	out_be32(&regs->share_cnt, 0);
+
+	/* Configure and reset host */
+	out_be32(&regs->config,
+			MPC52xx_ATA_HOSTCONF_IE |
+			MPC52xx_ATA_HOSTCONF_IORDY |
+			MPC52xx_ATA_HOSTCONF_SMR |
+			MPC52xx_ATA_HOSTCONF_FR);
+
+	udelay(10);
+
+	out_be32(&regs->config,
+			MPC52xx_ATA_HOSTCONF_IE |
+			MPC52xx_ATA_HOSTCONF_IORDY);
+
+	/* Set the time slot to 1us */
+	tslot = CALC_CLKCYC(priv->ipb_period, 1000000);
+	out_be32(&regs->share_cnt, tslot << 16 );
+
+	/* Init timings to PIO0 */
+	memset(priv->timings, 0x00, 2*sizeof(struct mpc52xx_ata_timings));
+
+	mpc52xx_ata_compute_pio_timings(priv, 0, 0);
+	mpc52xx_ata_compute_pio_timings(priv, 1, 0);
+
+	mpc52xx_ata_apply_timings(priv, 0);
+
+	return 0;
+}
+
+
+/* ======================================================================== */
+/* libata driver                                                            */
+/* ======================================================================== */
+
+static void
+mpc52xx_ata_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+	struct mpc52xx_ata_priv *priv = ap->host->private_data;
+	int pio, rv;
+
+	pio = adev->pio_mode - XFER_PIO_0;
+
+	rv = mpc52xx_ata_compute_pio_timings(priv, adev->devno, pio);
+
+	if (rv) {
+		printk(KERN_ERR DRV_NAME
+			": Trying to select invalid PIO mode %d\n", pio);
+		return;
+	}
+
+	mpc52xx_ata_apply_timings(priv, adev->devno);
+}
+static void
+mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device)
+{
+	struct mpc52xx_ata_priv *priv = ap->host->private_data;
+
+	if (device != priv->csel)
+		mpc52xx_ata_apply_timings(priv, device);
+
+	ata_std_dev_select(ap,device);
+}
+
+static void
+mpc52xx_ata_error_handler(struct ata_port *ap)
+{
+	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
+			ata_std_postreset);
+}
+
+
+
+static struct scsi_host_template mpc52xx_ata_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
+	.queuecommand		= ata_scsi_queuecmd,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.dma_boundary		= ATA_DMA_BOUNDARY,
+	.slave_configure	= ata_scsi_slave_config,
+	.bios_param		= ata_std_bios_param,
+};
+
+static struct ata_port_operations mpc52xx_ata_port_ops = {
+	.port_disable		= ata_port_disable,
+	.set_piomode		= mpc52xx_ata_set_piomode,
+	.dev_select		= mpc52xx_ata_dev_select,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= mpc52xx_ata_error_handler,
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+	.data_xfer		= ata_mmio_data_xfer,
+	.irq_handler		= ata_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
+	.port_start		= ata_port_start,
+	.port_stop		= ata_port_stop,
+	.host_stop		= ata_host_stop,
+};
+
+static struct ata_probe_ent mpc52xx_ata_probe_ent = {
+	.port_ops	= &mpc52xx_ata_port_ops,
+	.sht		= &mpc52xx_ata_sht,
+	.n_ports	= 1,
+	.pio_mask	= 0x1f,		/* Up to PIO4 */
+	.mwdma_mask	= 0x00,		/* No MWDMA   */
+	.udma_mask	= 0x00,		/* No UDMA    */
+	.port_flags	= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_MMIO,
+	.irq_flags	= 0,
+};
+
+static int __devinit
+mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv)
+{
+	struct ata_probe_ent *ae = &mpc52xx_ata_probe_ent;
+	struct ata_ioports *aio = &ae->port[0];
+	int rv;
+
+	INIT_LIST_HEAD(&ae->node);
+	ae->dev = dev;
+	ae->irq = priv->ata_irq;
+
+	aio->cmd_addr		= 0;	/* Don't have a classic reg block */
+	aio->altstatus_addr	= (unsigned long)&priv->ata_regs->tf_control;
+	aio->ctl_addr		= (unsigned long)&priv->ata_regs->tf_control;
+	aio->data_addr		= (unsigned long)&priv->ata_regs->tf_data;
+	aio->error_addr		= (unsigned long)&priv->ata_regs->tf_features;
+	aio->feature_addr	= (unsigned long)&priv->ata_regs->tf_features;
+	aio->nsect_addr		= (unsigned long)&priv->ata_regs->tf_sec_count;
+	aio->lbal_addr		= (unsigned long)&priv->ata_regs->tf_sec_num;
+	aio->lbam_addr		= (unsigned long)&priv->ata_regs->tf_cyl_low;
+	aio->lbah_addr		= (unsigned long)&priv->ata_regs->tf_cyl_high;
+	aio->device_addr	= (unsigned long)&priv->ata_regs->tf_dev_head;
+	aio->status_addr	= (unsigned long)&priv->ata_regs->tf_command;
+	aio->command_addr	= (unsigned long)&priv->ata_regs->tf_command;
+
+	ae->private_data = priv;
+
+	rv = ata_device_add(ae);
+
+	return rv ? 0 : -EINVAL;
+}
+
+static struct mpc52xx_ata_priv *
+mpc52xx_ata_remove_one(struct device *dev)
+{
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct mpc52xx_ata_priv *priv = host->private_data;
+
+	ata_host_remove(host);
+
+	return priv;
+}
+
+
+/* ======================================================================== */
+/* OF Platform driver                                                       */
+/* ======================================================================== */
+
+static int __devinit
+mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match)
+{
+	unsigned int ipb_freq;
+	struct resource res_mem;
+	int ata_irq = NO_IRQ;
+	struct mpc52xx_ata __iomem *ata_regs = NULL;
+	struct mpc52xx_ata_priv *priv = NULL;
+	int rv;
+
+	/* Get ipb frequency */
+	ipb_freq = mpc52xx_find_ipb_freq(op->node);
+	if (!ipb_freq) {
+		printk(KERN_ERR DRV_NAME ": "
+			"Unable to find IPB Bus frequency\n" );
+		return -ENODEV;
+	}
+
+	/* Get IRQ and register */
+	rv = of_address_to_resource(op->node, 0, &res_mem);
+	if (rv) {
+		printk(KERN_ERR DRV_NAME ": "
+			"Error while parsing device node resource\n" );
+		return rv;
+	}
+
+	ata_irq = irq_of_parse_and_map(op->node, 0);
+	if (ata_irq == NO_IRQ) {
+		printk(KERN_ERR DRV_NAME ": "
+			"Error while mapping the irq\n");
+		return -EINVAL;
+	}
+
+	/* Request mem region */
+	if (!request_mem_region(res_mem.start,
+				sizeof(struct mpc52xx_ata), DRV_NAME)) {
+		printk(KERN_ERR DRV_NAME ": "
+			"Error while requesting mem region\n");
+		irq_dispose_mapping(ata_irq);
+		return -EBUSY;
+	}
+
+	/* Remap registers */
+	ata_regs = ioremap(res_mem.start, sizeof(struct mpc52xx_ata));
+	if (!ata_regs) {
+		printk(KERN_ERR DRV_NAME ": "
+			"Error while mapping register set\n");
+		rv = -ENOMEM;
+		goto err;
+	}
+
+	/* Prepare our private structure */
+	priv = kmalloc(sizeof(struct mpc52xx_ata_priv), GFP_ATOMIC);
+	if (!priv) {
+		printk(KERN_ERR DRV_NAME ": "
+			"Error while allocating private structure\n");
+		rv = -ENOMEM;
+		goto err;
+	}
+
+	priv->ipb_period = 1000000000 / (ipb_freq / 1000);
+	priv->ata_regs = ata_regs;
+	priv->ata_irq = ata_irq;
+	priv->csel = -1;
+
+	/* Init the hw */
+	rv = mpc52xx_ata_hw_init(priv);
+	if (rv) {
+		printk(KERN_ERR DRV_NAME ": Error during HW init\n");
+		goto err;
+	}
+
+	/* Register ourselves to libata */
+	rv = mpc52xx_ata_init_one(&op->dev, priv);
+	if (rv) {
+		printk(KERN_ERR DRV_NAME ": "
+			"Error while registering to ATA layer\n");
+		return rv;
+	}
+
+	/* Done */
+	return 0;
+
+	/* Error path */
+err:
+	kfree(priv);
+
+	if (ata_regs)
+		iounmap(ata_regs);
+
+	release_mem_region(res_mem.start, sizeof(struct mpc52xx_ata));
+
+	irq_dispose_mapping(ata_irq);
+
+	return rv;
+}
+
+static int
+mpc52xx_ata_remove(struct of_device *op)
+{
+	struct mpc52xx_ata_priv *priv;
+	struct resource res_mem;
+	int rv;
+
+	/* Unregister */
+	priv = mpc52xx_ata_remove_one(&op->dev);
+
+	/* Free everything */
+	iounmap(priv->ata_regs);
+
+	rv = of_address_to_resource(op->node, 0, &res_mem);
+	if (rv) {
+		printk(KERN_ERR DRV_NAME ": "
+			"Error while parsing device node resource\n");
+		printk(KERN_ERR DRV_NAME ": "
+			"Zone may not be properly released\n");
+	} else
+		release_mem_region(res_mem.start, sizeof(struct mpc52xx_ata));
+
+	irq_dispose_mapping(priv->ata_irq);
+
+	kfree(priv);
+
+	return 0;
+}
+
+
+#ifdef CONFIG_PM
+
+static int
+mpc52xx_ata_suspend(struct of_device *op, pm_message_t state)
+{
+	return 0;	/* FIXME : What to do here ? */
+}
+
+static int
+mpc52xx_ata_resume(struct of_device *op)
+{
+	return 0;	/* FIXME : What to do here ? */
+}
+
+#endif
+
+
+static struct of_device_id mpc52xx_ata_of_match[] = {
+	{
+		.compatible = "mpc5200-ata",
+	},
+	{
+		.compatible = "mpc52xx-ata",
+	},
+	{},
+};
+
+
+static struct of_platform_driver mpc52xx_ata_of_platform_driver = {
+	.owner		= THIS_MODULE,
+	.name		= DRV_NAME,
+	.match_table	= mpc52xx_ata_of_match,
+	.probe		= mpc52xx_ata_probe,
+	.remove		= mpc52xx_ata_remove,
+#ifdef CONFIG_PM
+	.suspend	= mpc52xx_ata_suspend,
+	.resume		= mpc52xx_ata_resume,
+#endif
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+
+/* ======================================================================== */
+/* Module                                                                   */
+/* ======================================================================== */
+
+static int __init
+mpc52xx_ata_init(void)
+{
+	printk(KERN_INFO "ata: MPC52xx IDE/ATA libata driver\n");
+	return of_register_platform_driver(&mpc52xx_ata_of_platform_driver);
+}
+
+static void __exit
+mpc52xx_ata_exit(void)
+{
+	of_unregister_platform_driver(&mpc52xx_ata_of_platform_driver);
+}
+
+module_init(mpc52xx_ata_init);
+module_exit(mpc52xx_ata_exit);
+
+MODULE_AUTHOR("Sylvain Munaut <tnt at 246tNt.com>");
+MODULE_DESCRIPTION("Freescale MPC52xx IDE/ATA libata driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, mpc52xx_ata_of_match);
+MODULE_VERSION(DRV_VERSION);
+
-- 
1.4.2


linux-2.6-of_platform-uevent.patch:
 of_platform.c |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 70 insertions(+)

--- NEW FILE linux-2.6-of_platform-uevent.patch ---
>From 6f004b2fa4f9b6e5692084f7301271503788c05c Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt at 246tNt.com>
Date: Sat, 9 Dec 2006 02:06:55 +0100
Subject: [PATCH] powerpc: Add support for uevent to of_platform

This adds a proper uevent handler to the of_platform bus. This
allows autoloading of modules (or at least should ;).
It's _heavily_ based on the macio counterpart.

Signed-off-by: Sylvain Munaut <tnt at 246tNt.com>
---
 arch/powerpc/kernel/of_platform.c |   70 +++++++++++++++++++++++++++++++++++++
 1 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index b3189d0..f000023 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -73,6 +73,75 @@ static int of_platform_bus_match(struct 
 	return of_match_device(matches, of_dev) != NULL;
 }
 
+static int of_platform_uevent(struct device *dev, char **envp, int num_envp,
+                              char *buffer, int buffer_size)
+{
+	struct of_device *of;
+	const char *compat;
+	char *compat2;
+	char compat_buf[128];	/* need to be size of 'compatible' */
+
+	int i = 0;
+	int length = 0, cplen, sl, seen = 0;
+
+	if (!dev)
+		return -ENODEV;
+
+	of = to_of_device(dev);
+	if (!of)
+		return -ENODEV;
+
+	/* stuff we want to pass to /sbin/hotplug */
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "OF_NAME=%s", of->node->name))
+		return -ENOMEM;
+
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "OF_TYPE=%s", of->node->type))
+		return -ENOMEM;
+
+        /* Since the compatible field can contain pretty much anything
+         * it's not really legal to split it out with commas. We split it
+         * up using a number of environment variables instead. */
+
+	compat = get_property(of->node, "compatible", &cplen);
+	compat2 = compat_buf;
+	if (compat)
+		memcpy(compat2, compat, cplen);
+	while (compat && *compat && cplen > 0) {
+		if (add_uevent_var(envp, num_envp, &i,
+				   buffer, buffer_size, &length,
+				   "OF_COMPATIBLE_%d=%s", seen, compat))
+			return -ENOMEM;
+
+		sl = strlen (compat) + 1;
+		compat += sl;
+		compat2 += sl;
+		cplen -= sl;
+		seen++;
+		compat2[-1] = 'C'; 
+	}
+	compat2[seen?-1:0] = 0;
+
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "OF_COMPATIBLE_N=%d", seen))
+		return -ENOMEM;
+
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "MODALIAS=of:N%sT%sC%s",
+			   of->node->name, of->node->type,
+			   compat_buf))
+		return -ENOMEM;
+
+	envp[i] = NULL;
+
+	return 0;
+}
+
 static int of_platform_device_probe(struct device *dev)
 {
 	int error = -ENODEV;
@@ -132,6 +201,7 @@ static int of_platform_device_resume(str
 struct bus_type of_platform_bus_type = {
        .name	= "of_platform",
        .match	= of_platform_bus_match,
+       .uevent	= of_platform_uevent,
        .probe	= of_platform_device_probe,
        .remove	= of_platform_device_remove,
        .suspend	= of_platform_device_suspend,
-- 
1.4.2


linux-2.6-ohci-multi-init.patch:
 ohci-at91.c    |   15 ---------
 ohci-au1xxx.c  |   16 ----------
 ohci-ep93xx.c  |   12 -------
 ohci-hcd.c     |   91 +++++++++++++++++++++++++++++++++++++++++++++++++--------
 ohci-lh7a404.c |   16 ----------
 ohci-omap.c    |   19 -----------
 ohci-pci.c     |   20 ------------
 ohci-pnx4008.c |   12 -------
 ohci-ppc-soc.c |   16 ----------
 ohci-pxa27x.c  |   16 ----------
 ohci-s3c2410.c |   12 -------
 ohci-sa1111.c  |   16 ----------
 12 files changed, 79 insertions(+), 182 deletions(-)

--- NEW FILE linux-2.6-ohci-multi-init.patch ---
>From e7b5f22b56d5d941cde3a76e62e5984ba155c241 Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt at 246tNt.com>
Date: Wed, 13 Dec 2006 20:35:37 +0100
Subject: [PATCH] ohci: Rework bus glue integration to allow several at once

The previous model had the module_init & module_exit function in the
bus glue .c files themselves. That's a problem if several glues need
to be selected at once and the driver is built has module. This case
is quite common in embedded system where you want to handle both the
integrated ohci controller and some extra controller on PCI.

The ohci-hcd.c file now provide the module_init & module_exit and
appropriate driver registering/unregistering is done conditionally,
using #ifdefs.

Signed-off-by: Sylvain Munaut <tnt at 246tNt.com>
Acked-by: David Brownell <dbrownell at users.sourceforge.net>
---
 drivers/usb/host/ohci-at91.c    |   15 ------
 drivers/usb/host/ohci-au1xxx.c  |   16 ------
 drivers/usb/host/ohci-ep93xx.c  |   12 -----
 drivers/usb/host/ohci-hcd.c     |   98 +++++++++++++++++++++++++++++++++------
 drivers/usb/host/ohci-lh7a404.c |   16 ------
 drivers/usb/host/ohci-omap.c    |   19 --------
 drivers/usb/host/ohci-pci.c     |   20 --------
 drivers/usb/host/ohci-pnx4008.c |   12 -----
 drivers/usb/host/ohci-pnx8550.c |   16 ------
 drivers/usb/host/ohci-ppc-soc.c |   16 ------
 drivers/usb/host/ohci-pxa27x.c  |   16 ------
 drivers/usb/host/ohci-s3c2410.c |   12 -----
 drivers/usb/host/ohci-sa1111.c  |   16 ------
 13 files changed, 83 insertions(+), 201 deletions(-)

diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index cc40551..53f62cf 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -320,18 +320,3 @@ static struct platform_driver ohci_hcd_a
 	},
 };
 
-static int __init ohci_hcd_at91_init (void)
-{
-	if (usb_disabled())
-		return -ENODEV;
-
-	return platform_driver_register(&ohci_hcd_at91_driver);
-}
-
-static void __exit ohci_hcd_at91_cleanup (void)
-{
-	platform_driver_unregister(&ohci_hcd_at91_driver);
-}
-
-module_init (ohci_hcd_at91_init);
-module_exit (ohci_hcd_at91_cleanup);
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index e70b243..663a060 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -345,19 +345,3 @@ static struct platform_driver ohci_hcd_a
 	},
 };
 
-static int __init ohci_hcd_au1xxx_init (void)
-{
-	pr_debug (DRIVER_INFO " (Au1xxx)");
-	pr_debug ("block sizes: ed %d td %d\n",
-		sizeof (struct ed), sizeof (struct td));
-
-	return platform_driver_register(&ohci_hcd_au1xxx_driver);
-}
-
-static void __exit ohci_hcd_au1xxx_cleanup (void)
-{
-	platform_driver_unregister(&ohci_hcd_au1xxx_driver);
-}
-
-module_init (ohci_hcd_au1xxx_init);
-module_exit (ohci_hcd_au1xxx_cleanup);
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index 43ae696..e9974c3 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -214,15 +214,3 @@ #endif
 	},
 };
 
-static int __init ohci_hcd_ep93xx_init(void)
-{
-	return platform_driver_register(&ohci_hcd_ep93xx_driver);
-}
-
-static void __exit ohci_hcd_ep93xx_cleanup(void)
-{
-	platform_driver_unregister(&ohci_hcd_ep93xx_driver);
-}
-
-module_init(ohci_hcd_ep93xx_init);
-module_exit(ohci_hcd_ep93xx_cleanup);
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index c1c1d87..9926b8f 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -855,59 +855,126 @@ MODULE_LICENSE ("GPL");
 
 #ifdef CONFIG_PCI
 #include "ohci-pci.c"
+#define PCI_DRIVER		ohci_pci_driver
 #endif
 
 #ifdef CONFIG_SA1111
 #include "ohci-sa1111.c"
+#define SA1111_DRIVER		ohci_hcd_sa1111_driver
 #endif
 
 #ifdef CONFIG_ARCH_S3C2410
 #include "ohci-s3c2410.c"
+#define PLATFORM_DRIVER		ohci_hcd_s3c2410_driver
 #endif
 
 #ifdef CONFIG_ARCH_OMAP
 #include "ohci-omap.c"
+#define PLATFORM_DRIVER		ohci_hcd_omap_driver
 #endif
 
 #ifdef CONFIG_ARCH_LH7A404
 #include "ohci-lh7a404.c"
+#define PLATFORM_DRIVER		ohci_hcd_lh7a404_driver
 #endif
 
 #ifdef CONFIG_PXA27x
 #include "ohci-pxa27x.c"
+#define PLATFORM_DRIVER		ohci_hcd_pxa27x_driver
 #endif
 
 #ifdef CONFIG_ARCH_EP93XX
 #include "ohci-ep93xx.c"
+#define PLATFORM_DRIVER		ohci_hcd_ep93xx_driver
 #endif
 
 #ifdef CONFIG_SOC_AU1X00
 #include "ohci-au1xxx.c"
+#define PLATFORM_DRIVER		ohci_hcd_au1xxx_driver
 #endif
 
 #ifdef CONFIG_USB_OHCI_HCD_PPC_SOC
 #include "ohci-ppc-soc.c"
+#define PLATFORM_DRIVER		ohci_hcd_ppc_soc_driver
 #endif
 
 #ifdef CONFIG_ARCH_AT91
 #include "ohci-at91.c"
+#define PLATFORM_DRIVER		ohci_hcd_at91_driver
 #endif
 
 #ifdef CONFIG_ARCH_PNX4008
 #include "ohci-pnx4008.c"
+#define PLATFORM_DRIVER		usb_hcd_pnx4008_driver
 #endif
 
-#if !(defined(CONFIG_PCI) \
-      || defined(CONFIG_SA1111) \
-      || defined(CONFIG_ARCH_S3C2410) \
-      || defined(CONFIG_ARCH_OMAP) \
-      || defined (CONFIG_ARCH_LH7A404) \
-      || defined (CONFIG_PXA27x) \
-      || defined (CONFIG_ARCH_EP93XX) \
-      || defined (CONFIG_SOC_AU1X00) \
-      || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
-      || defined (CONFIG_ARCH_AT91) \
-      || defined (CONFIG_ARCH_PNX4008) \
-	)
+
+#if	!defined(PCI_DRIVER) &&		\
+	!defined(PLATFORM_DRIVER) &&	\
+	!defined(SA1111_DRIVER)
 #error "missing bus glue for ohci-hcd"
 #endif
+
+static int __init ohci_hcd_mod_init(void)
+{
+	int retval = 0;
+	int ls = 0;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	printk (KERN_DEBUG "%s: " DRIVER_INFO "\n", hcd_name);
+	pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
+		sizeof (struct ed), sizeof (struct td));
+
+#ifdef PLATFORM_DRIVER
+	retval = platform_driver_register(&PLATFORM_DRIVER);
+	if (retval < 0)
+		return retval;
+	ls++;
+#endif
+
+#ifdef SA1111_DRIVER
+	retval = sa1111_driver_register(&SA1111_DRIVER);
+	if (retval < 0)
+		goto error;
+	ls++;
+#endif
+
+#ifdef PCI_DRIVER
+	retval = pci_register_driver(&PCI_DRIVER);
+	if (retval < 0)
+		goto error;
+	ls++;
+#endif
+
+	return retval;
+
+	/* Error path */
+error:
+#ifdef PLATFORM_DRIVER
+	if (ls--)
+		platform_driver_unregister(&PLATFORM_DRIVER);
+#endif
+#ifdef SA1111_DRIVER
+	if (ls--)
+		sa1111_driver_unregister(&SA1111_DRIVER);
+#endif
+	return retval;
+}
+module_init(ohci_hcd_mod_init);
+
+static void __exit ohci_hcd_mod_exit(void)
+{
+#ifdef PCI_DRIVER
+	pci_unregister_driver(&PCI_DRIVER);
+#endif
+#ifdef SA1111_DRIVER
+	sa1111_driver_unregister(&SA1111_DRIVER);
+#endif
+#ifdef PLATFORM_DRIVER
+	platform_driver_unregister(&PLATFORM_DRIVER);
+#endif
+}
+module_exit(ohci_hcd_mod_exit);
+
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
index e9807cf..4a043ab 100644
--- a/drivers/usb/host/ohci-lh7a404.c
+++ b/drivers/usb/host/ohci-lh7a404.c
@@ -251,19 +251,3 @@ static struct platform_driver ohci_hcd_l
 	},
 };
 
-static int __init ohci_hcd_lh7a404_init (void)
-{
-	pr_debug (DRIVER_INFO " (LH7A404)");
-	pr_debug ("block sizes: ed %d td %d\n",
-		sizeof (struct ed), sizeof (struct td));
-
-	return platform_driver_register(&ohci_hcd_lh7a404_driver);
-}
-
-static void __exit ohci_hcd_lh7a404_cleanup (void)
-{
-	platform_driver_unregister(&ohci_hcd_lh7a404_driver);
-}
-
-module_init (ohci_hcd_lh7a404_init);
-module_exit (ohci_hcd_lh7a404_cleanup);
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 27be1f9..5cfa3d1 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -544,22 +544,3 @@ #endif
 	},
 };
 
-static int __init ohci_hcd_omap_init (void)
-{
-	printk (KERN_DEBUG "%s: " DRIVER_INFO " (OMAP)\n", hcd_name);
-	if (usb_disabled())
-		return -ENODEV;
-
-	pr_debug("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
-		sizeof (struct ed), sizeof (struct td));
-
-	return platform_driver_register(&ohci_hcd_omap_driver);
-}
-
-static void __exit ohci_hcd_omap_cleanup (void)
-{
-	platform_driver_unregister(&ohci_hcd_omap_driver);
-}
-
-module_init (ohci_hcd_omap_init);
-module_exit (ohci_hcd_omap_cleanup);
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 649cdfe..bc7f173 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -311,23 +311,3 @@ #endif
 	.shutdown =	usb_hcd_pci_shutdown,
 };
 
- 
-static int __init ohci_hcd_pci_init (void) 
-{
-	printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name);
-	if (usb_disabled())
-		return -ENODEV;
-
-	pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
-		sizeof (struct ed), sizeof (struct td));
-	return pci_register_driver (&ohci_pci_driver);
-}
-module_init (ohci_hcd_pci_init);
-
-/*-------------------------------------------------------------------------*/
-
-static void __exit ohci_hcd_pci_cleanup (void) 
-{	
-	pci_unregister_driver (&ohci_pci_driver);
-}
-module_exit (ohci_hcd_pci_cleanup);
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
index 3a8cbfb..893b172 100644
--- a/drivers/usb/host/ohci-pnx4008.c
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -465,15 +465,3 @@ static struct platform_driver usb_hcd_pn
 	.remove = usb_hcd_pnx4008_remove,
 };
 
-static int __init usb_hcd_pnx4008_init(void)
-{
-	return platform_driver_register(&usb_hcd_pnx4008_driver);
-}
-
-static void __exit usb_hcd_pnx4008_cleanup(void)
-{
-	return platform_driver_unregister(&usb_hcd_pnx4008_driver);
-}
-
-module_init(usb_hcd_pnx4008_init);
-module_exit(usb_hcd_pnx4008_cleanup);
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index c7ce8e6..1a2e177 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -208,19 +208,3 @@ #endif
 	},
 };
 
-static int __init ohci_hcd_ppc_soc_init(void)
-{
-	pr_debug(DRIVER_INFO " (PPC SOC)\n");
-	pr_debug("block sizes: ed %d td %d\n", sizeof(struct ed),
-							sizeof(struct td));
-
-	return platform_driver_register(&ohci_hcd_ppc_soc_driver);
-}
-
-static void __exit ohci_hcd_ppc_soc_cleanup(void)
-{
-	platform_driver_unregister(&ohci_hcd_ppc_soc_driver);
-}
-
-module_init(ohci_hcd_ppc_soc_init);
-module_exit(ohci_hcd_ppc_soc_cleanup);
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 3bbea84..f1563dc 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -369,19 +369,3 @@ #endif
 	},
 };
 
-static int __init ohci_hcd_pxa27x_init (void)
-{
-	pr_debug (DRIVER_INFO " (pxa27x)");
-	pr_debug ("block sizes: ed %d td %d\n",
-		sizeof (struct ed), sizeof (struct td));
-
-	return platform_driver_register(&ohci_hcd_pxa27x_driver);
-}
-
-static void __exit ohci_hcd_pxa27x_cleanup (void)
-{
-	platform_driver_unregister(&ohci_hcd_pxa27x_driver);
-}
-
-module_init (ohci_hcd_pxa27x_init);
-module_exit (ohci_hcd_pxa27x_cleanup);
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index b350d45..6829814 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -501,15 +501,3 @@ static struct platform_driver ohci_hcd_s
 	},
 };
 
-static int __init ohci_hcd_s3c2410_init (void)
-{
-	return platform_driver_register(&ohci_hcd_s3c2410_driver);
-}
-
-static void __exit ohci_hcd_s3c2410_cleanup (void)
-{
-	platform_driver_unregister(&ohci_hcd_s3c2410_driver);
-}
-
-module_init (ohci_hcd_s3c2410_init);
-module_exit (ohci_hcd_s3c2410_cleanup);
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index fe0090e..0f48f2d 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -269,19 +269,3 @@ static struct sa1111_driver ohci_hcd_sa1
 	.remove		= ohci_hcd_sa1111_drv_remove,
 };
 
-static int __init ohci_hcd_sa1111_init (void)
-{
-	dbg (DRIVER_INFO " (SA-1111)");
-	dbg ("block sizes: ed %d td %d",
-		sizeof (struct ed), sizeof (struct td));
-
-	return sa1111_driver_register(&ohci_hcd_sa1111_driver);
-}
-
-static void __exit ohci_hcd_sa1111_cleanup (void)
-{
-	sa1111_driver_unregister(&ohci_hcd_sa1111_driver);
-}
-
-module_init (ohci_hcd_sa1111_init);
-module_exit (ohci_hcd_sa1111_cleanup);
-- 
1.4.2


linux-2.6-ohci-platform-bus.patch:
 Kconfig       |   23 +++++
 ohci-hcd.c    |   20 +++++
 ohci-ppc-of.c |  232 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 274 insertions(+), 1 deletion(-)

--- NEW FILE linux-2.6-ohci-platform-bus.patch ---
>From 3e717fc663ab3fa8a55ef40ee96110901593c704 Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt at 246tNt.com>
Date: Wed, 13 Dec 2006 21:03:30 +0100
Subject: [PATCH] ohci: Add support for OHCI controller on the of_platform bus

PPC embedded systems can have a ohci controller builtin. In the
new model, it will end up as a driver on the of_platform bus,
this patches takes care of them.

Signed-off-by: Sylvain Munaut <tnt at 246tNt.com>
Acked-by: David Brownell <dbrownell at users.sourceforge.net>
---
 drivers/usb/host/Kconfig       |   23 ++++
 drivers/usb/host/ohci-hcd.c    |   20 +++
 drivers/usb/host/ohci-ppc-of.c |  232 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 274 insertions(+), 1 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 8325998..6271187 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -112,9 +112,30 @@ config USB_OHCI_HCD_PPC_SOC
 	  Enables support for the USB controller on the MPC52xx or
 	  STB03xxx processor chip.  If unsure, say Y.
 
+config USB_OHCI_HCD_PPC_OF
+	bool "OHCI support for PPC USB controller on OF platform bus"
+	depends on USB_OHCI_HCD && PPC_OF
+	default y
+	---help---
+	  Enables support for the USB controller PowerPC present on the
+	  OpenFirmware platform bus.
+
+config USB_OHCI_HCD_PPC_OF_BE
+	bool "Support big endian HC"
+	depends on USB_OHCI_HCD_PPC_OF
+	default y
+	select USB_OHCI_BIG_ENDIAN_DESC
+	select USB_OHCI_BIG_ENDIAN_MMIO
+
+config USB_OHCI_HCD_PPC_OF_LE
+	bool "Support little endian HC"
+	depends on USB_OHCI_HCD_PPC_OF
+	default n
+	select USB_OHCI_LITTLE_ENDIAN
+
 config USB_OHCI_HCD_PCI
 	bool "OHCI support for PCI-bus USB controllers"
-	depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx)
+	depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx || USB_OHCI_HCD_PPC_OF)
 	default y
 	select USB_OHCI_LITTLE_ENDIAN
 	---help---
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 9926b8f..c6ae1ff 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -914,8 +914,14 @@ #define PLATFORM_DRIVER		usb_hcd_pnx4008
 #endif
 
 
+#ifdef CONFIG_USB_OHCI_HCD_PPC_OF
+#include "ohci-ppc-of.c"
+#define OF_PLATFORM_DRIVER	ohci_hcd_ppc_of_driver
+#endif
+
 #if	!defined(PCI_DRIVER) &&		\
 	!defined(PLATFORM_DRIVER) &&	\
+	!defined(OF_PLATFORM_DRIVER) &&	\
 	!defined(SA1111_DRIVER)
 #error "missing bus glue for ohci-hcd"
 #endif
@@ -939,6 +945,13 @@ #ifdef PLATFORM_DRIVER
 	ls++;
 #endif
 
+#ifdef OF_PLATFORM_DRIVER
+	retval = of_register_platform_driver(&OF_PLATFORM_DRIVER);
+	if (retval < 0)
+		goto error;
+	ls++;
+#endif
+
 #ifdef SA1111_DRIVER
 	retval = sa1111_driver_register(&SA1111_DRIVER);
 	if (retval < 0)
@@ -961,6 +974,10 @@ #ifdef PLATFORM_DRIVER
 	if (ls--)
 		platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
+#ifdef OF_PLATFORM_DRIVER
+	if (ls--)
+		of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
+#endif
 #ifdef SA1111_DRIVER
 	if (ls--)
 		sa1111_driver_unregister(&SA1111_DRIVER);
@@ -977,6 +994,9 @@ #endif
 #ifdef SA1111_DRIVER
 	sa1111_driver_unregister(&SA1111_DRIVER);
 #endif
+#ifdef OF_PLATFORM_DRIVER
+	of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
+#endif
 #ifdef PLATFORM_DRIVER
 	platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
new file mode 100644
index 0000000..84b555b
--- /dev/null
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -0,0 +1,232 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg at vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell at users.sourceforge.net>
+ * (C) Copyright 2002 Hewlett-Packard Company
+ * (C) Copyright 2006 Sylvain Munaut <tnt at 246tNt.com>
+ *
+ * Bus glue for OHCI HC on the of_platform bus
+ *
+ * Modified for of_platform bus from ohci-sa1111.c
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/signal.h>
+
+#include <asm/of_platform.h>
+#include <asm/prom.h>
+
+
+static int __devinit
+ohci_ppc_of_start(struct usb_hcd *hcd)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+	int		ret;
+
+	if ((ret = ohci_init(ohci)) < 0)
+		return ret;
+
+	if ((ret = ohci_run(ohci)) < 0) {
+		err("can't start %s", ohci_to_hcd(ohci)->self.bus_name);
+		ohci_stop(hcd);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct hc_driver ohci_ppc_of_hc_driver = {
+	.description =		hcd_name,
+	.product_desc =		"OF OHCI",
+	.hcd_priv_size =	sizeof(struct ohci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq =			ohci_irq,
+	.flags =		HCD_USB11 | HCD_MEMORY,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.start =		ohci_ppc_of_start,
+	.stop =			ohci_stop,
+	.shutdown = 		ohci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue =		ohci_urb_enqueue,
+	.urb_dequeue =		ohci_urb_dequeue,
+	.endpoint_disable =	ohci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number =	ohci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data =	ohci_hub_status_data,
+	.hub_control =		ohci_hub_control,
+	.hub_irq_enable =	ohci_rhsc_enable,
+#ifdef	CONFIG_PM
+	.bus_suspend =		ohci_bus_suspend,
+	.bus_resume =		ohci_bus_resume,
+#endif
+	.start_port_reset =	ohci_start_port_reset,
+};
+
+
+static int __devinit
+ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match)
+{
+	struct device_node *dn = op->node;
+	struct usb_hcd *hcd;
+	struct ohci_hcd	*ohci;
+	struct resource res;
+	int irq;
+
+	int rv;
+	int is_bigendian;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	is_bigendian = 
+		device_is_compatible(dn, "ohci-bigendian") ||
+		device_is_compatible(dn, "ohci-be");;
+
+	dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n");
+
+	rv = of_address_to_resource(dn, 0, &res);
+	if (rv)
+		return rv;
+
+	hcd = usb_create_hcd(&ohci_ppc_of_hc_driver, &op->dev, "PPC-OF USB");
+	if (!hcd)
+		return -ENOMEM;
+
+	hcd->rsrc_start = res.start;
+	hcd->rsrc_len = res.end - res.start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		printk(KERN_ERR __FILE__ ": request_mem_region failed\n");
+		rv = -EBUSY;
+		goto err_rmr;
+	}
+
+	irq = irq_of_parse_and_map(dn, 0);
+	if (irq == NO_IRQ) {
+		printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n");
+		rv = -EBUSY;
+		goto err_irq;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		printk(KERN_ERR __FILE__ ": ioremap failed\n");
+		rv = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	ohci = hcd_to_ohci(hcd);
+	if (is_bigendian)
+		ohci->flags |= OHCI_BIG_ENDIAN;
+
+	ohci_hcd_init(ohci);
+
+	rv = usb_add_hcd(hcd, irq, 0);
+	if (rv == 0)
+		return 0;
+
+	iounmap(hcd->regs);
+err_ioremap:
+	irq_dispose_mapping(irq);
+err_irq:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_rmr:
+ 	usb_put_hcd(hcd);
+
+	return rv;
+}
+
+static int ohci_hcd_ppc_of_remove(struct of_device *op)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+	dev_set_drvdata(&op->dev, NULL);
+
+	dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n");
+
+	usb_remove_hcd(hcd);
+
+	iounmap(hcd->regs);
+	irq_dispose_mapping(hcd->irq);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+static int ohci_hcd_ppc_of_shutdown(struct of_device *op)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+
+        if (hcd->driver->shutdown)
+                hcd->driver->shutdown(hcd);
+
+	return 0;
+}
+
+
+static struct of_device_id ohci_hcd_ppc_of_match[] = {
+#ifdef CONFIG_USB_OHCI_HCD_PPC_OF_BE
+	{
+		.name = "usb",
+		.compatible = "ohci-bigendian",
+	},
+	{
+		.name = "usb",
+		.compatible = "ohci-be",
+	},
+#endif
+#ifdef CONFIG_USB_OHCI_HCD_PPC_OF_LE
+	{
+		.name = "usb",
+		.compatible = "ohci-littledian",
+	},
+	{
+		.name = "usb",
+		.compatible = "ohci-le",
+	},
+#endif
+	{},
+};
+MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match); 
+
+#if	!defined(CONFIG_USB_OHCI_HCD_PPC_OF_BE) && \
+	!defined(CONFIG_USB_OHCI_HCD_PPC_OF_LE)
+#error "No endianess selected for ppc-of-ohci"
+#endif
+
+
+static struct of_platform_driver ohci_hcd_ppc_of_driver = {
+	.name		= "ppc-of-ohci",
+	.match_table	= ohci_hcd_ppc_of_match,
+	.probe		= ohci_hcd_ppc_of_probe,
+	.remove		= ohci_hcd_ppc_of_remove,
+	.shutdown 	= ohci_hcd_ppc_of_shutdown,
+#ifdef CONFIG_PM
+	/*.suspend	= ohci_hcd_ppc_soc_drv_suspend,*/
+	/*.resume	= ohci_hcd_ppc_soc_drv_resume,*/
+#endif
+	.driver		= {
+		.name	= "ppc-of-ohci",
+		.owner	= THIS_MODULE,
+	},
+};
+
-- 
1.4.2



Index: kernel-2.6.spec
===================================================================
RCS file: /cvs/dist/rpms/kernel/devel/kernel-2.6.spec,v
retrieving revision 1.2880
retrieving revision 1.2881
diff -u -r1.2880 -r1.2881
--- kernel-2.6.spec	17 Dec 2006 13:14:58 -0000	1.2880
+++ kernel-2.6.spec	17 Dec 2006 17:29:06 -0000	1.2881
@@ -318,7 +318,13 @@
 Patch301: linux-2.6-cell-mambo-drivers.patch
 Patch302: linux-2.6-systemsim-work.patch
 Patch303: linux-2.6-ppc32-ucmpdi2.patch
+Patch304: linux-2.6-of_platform-uevent.patch
 Patch310: linux-2.6-g5-therm-shutdown.patch
+# Efika support
+Patch311: linux-2.6-ohci-multi-init.patch
+Patch312: linux-2.6-ohci-platform-bus.patch
+Patch313: linux-2.6-mpc52xx-ata.patch
+Patch314: linux-2.6-efika-before-chrp.patch
 
 # 400 - 499   ia64
 
@@ -744,9 +750,18 @@
 %patch302 -p1
 # Temporary hack to work around GCC PR #25724 / #21237
 %patch303 -p1
+# uevent support for of_platform device
+%patch304 -p1
 # Alleviate G5 thermal shutdown problems
 %patch310 -p1
-
+# OHCI bus glue rework to allow several at once
+%patch311 -p1
+# OHCI of_device support
+%patch312 -p1
+# MPC52xx PATA
+%patch313 -p1
+# Probe for Efika before CHRP
+%patch314 -p1
 
 # S390
 
@@ -1790,6 +1805,7 @@
 
 %changelog
 * Sun Dec 17 2006 David Woodhouse <dwmw2 at redhat.com>
+- Enable Efika platform support
 - Temporarily provide __ucmpdi2 on ppc32 to work around GCC PR #25724
 
 * Thu Dec 14 2006 Dave Jones <davej at redhat.com>




More information about the fedora-cvs-commits mailing list