summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMarkus Lidel <Markus.Lidel@shadowconnect.com>2006-02-03 03:04:29 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2006-02-03 08:32:07 -0800
commit8b3e09e19932835fb77c63aaf3b1af6117e78871 (patch)
treed98125db1fe2ee0c82426cac98c954cd62842e88 /drivers
parent15d8ec7d08fbb7876e292b42bc92da8d82df7ea9 (diff)
downloadlinux-8b3e09e19932835fb77c63aaf3b1af6117e78871.tar.bz2
[PATCH] I2O: fix and workaround for Motorola/Freescale controller
- This controller violates the I2O spec for the I/O registers. The patch contains a workaround which moves the registers to the proper location. (originally author: Matthew Starzewski) - If a message frame is beyond the mapped address range a error is returned. Signed-off-by: Markus Lidel <Markus.Lidel@shadowconnect.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/message/i2o/core.h3
-rw-r--r--drivers/message/i2o/pci.c18
2 files changed, 21 insertions, 0 deletions
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
index 90628562851e..184974cc734d 100644
--- a/drivers/message/i2o/core.h
+++ b/drivers/message/i2o/core.h
@@ -60,4 +60,7 @@ extern void i2o_iop_remove(struct i2o_controller *);
#define I2O_IN_PORT 0x40
#define I2O_OUT_PORT 0x44
+/* Motorola/Freescale specific register offset */
+#define I2O_MOTOROLA_PORT_OFFSET 0x10400
+
#define I2O_IRQ_OUTBOUND_POST 0x00000008
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index e2e3fc79c78a..4f1515cae5dc 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -168,6 +168,24 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
c->in_port = c->base.virt + I2O_IN_PORT;
c->out_port = c->base.virt + I2O_OUT_PORT;
+ /* Motorola/Freescale chip does not follow spec */
+ if (pdev->vendor == PCI_VENDOR_ID_MOTOROLA && pdev->device == 0x18c0) {
+ /* Check if CPU is enabled */
+ if (be32_to_cpu(readl(c->base.virt + 0x10000)) & 0x10000000) {
+ printk(KERN_INFO "%s: MPC82XX needs CPU running to "
+ "service I2O.\n", c->name);
+ i2o_pci_free(c);
+ return -ENODEV;
+ } else {
+ c->irq_status += I2O_MOTOROLA_PORT_OFFSET;
+ c->irq_mask += I2O_MOTOROLA_PORT_OFFSET;
+ c->in_port += I2O_MOTOROLA_PORT_OFFSET;
+ c->out_port += I2O_MOTOROLA_PORT_OFFSET;
+ printk(KERN_INFO "%s: MPC82XX workarounds activated.\n",
+ c->name);
+ }
+ }
+
if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) {
i2o_pci_free(c);
return -ENOMEM;