** (c) Copyright 1999 SuSE GmbH
** (c) Copyright 1999,2000 Hewlett-Packard Company
** (c) Copyright 2000 Grant Grundler
+** (c) Copyright 2006 Helge Deller
**
** 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
** for PCI drivers devices which implement/use MMIO registers.
*/
-#include <linux/config.h>
#include <linux/delay.h>
#include <linux/types.h>
#include <linux/kernel.h>
** bus number for each dino.
*/
-#define is_card_dino(id) ((id)->hw_type == HPHW_A_DMA)
+#define is_card_dino(id) ((id)->hw_type == HPHW_A_DMA)
+#define is_cujo(id) ((id)->hversion == 0x682)
#define DINO_IAR0 0x004
#define DINO_IODC_ADDR 0x008
#define DINO_IRQS 11 /* bits 0-10 are architected */
#define DINO_IRR_MASK 0x5ff /* only 10 bits are implemented */
+#define DINO_LOCAL_IRQS (DINO_IRQS+1)
#define DINO_MASK_IRQ(x) (1<<(x))
unsigned long txn_addr; /* EIR addr to generate interrupt */
u32 txn_data; /* EIR data assign to each dino */
u32 imr; /* IRQ's which are enabled */
- int global_irq[12]; /* map IMR bit to global irq */
+ int global_irq[DINO_LOCAL_IRQS]; /* map IMR bit to global irq */
#ifdef DINO_DEBUG
unsigned int dino_irr0; /* save most recent IRQ line stat */
#endif
static void dino_disable_irq(unsigned int irq)
{
- struct dino_device *dino_dev = irq_desc[irq].handler_data;
- int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
+ struct dino_device *dino_dev = irq_desc[irq].chip_data;
+ int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
static void dino_enable_irq(unsigned int irq)
{
- struct dino_device *dino_dev = irq_desc[irq].handler_data;
- int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
+ struct dino_device *dino_dev = irq_desc[irq].chip_data;
+ int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
u32 tmp;
DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
* ilr_loop counter is a kluge to prevent a "stuck" IRQ line from
* wedging the CPU. Could be removed or made optional at some point.
*/
-static irqreturn_t
-dino_isr(int irq, void *intr_dev, struct pt_regs *regs)
+static irqreturn_t dino_isr(int irq, void *intr_dev)
{
struct dino_device *dino_dev = intr_dev;
u32 mask;
int irq = dino_dev->global_irq[local_irq];
DBG(KERN_DEBUG "%s(%d, %p) mask 0x%x\n",
__FUNCTION__, irq, intr_dev, mask);
- __do_IRQ(irq, regs);
+ __do_IRQ(irq);
mask &= ~(1 << local_irq);
} while (mask);
dino_assign_irq(dino, irq, &dev->irq);
}
+
+/*
+ * Cirrus 6832 Cardbus reports wrong irq on RDI Tadpole PARISC Laptop (deller@gmx.de)
+ * (the irqs are off-by-one, not sure yet if this is a cirrus, dino-hardware or dino-driver problem...)
+ */
+static void __devinit quirk_cirrus_cardbus(struct pci_dev *dev)
+{
+ u8 new_irq = dev->irq - 1;
+ printk(KERN_INFO "PCI: Cirrus Cardbus IRQ fixup for %s, from %d to %d\n",
+ pci_name(dev), dev->irq, new_irq);
+ dev->irq = new_irq;
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6832, quirk_cirrus_cardbus );
+
+
static void __init
dino_bios_init(void)
{
printk(KERN_WARNING "Device %s has unassigned IRQ\n", pci_name(dev));
#endif
} else {
-
/* Adjust INT_LINE for that busses region */
dino_assign_irq(dino_dev, dev->irq, &dev->irq);
}
if((io_addr & (1 << i)) == 0)
continue;
- start = (unsigned long)(signed int)(0xf0000000 | (i << 23));
+ start = F_EXTEND(0xf0000000UL) | (i << 23);
end = start + 8 * 1024 * 1024 - 1;
DBG("DINO RANGE %d is at 0x%lx-0x%lx\n", count,
/* allocate I/O Port resource region */
res = &dino_dev->hba.io_space;
- if (dev->id.hversion == 0x680 || is_card_dino(&dev->id)) {
+ if (!is_cujo(&dev->id)) {
res->name = "Dino I/O Port";
} else {
res->name = "Cujo I/O Port";
if (is_card_dino(&dev->id)) {
version = "3.x (card mode)";
} else {
- if(dev->id.hversion == 0x680) {
+ if (!is_cujo(&dev->id)) {
if (dev->id.hversion_rev < 4) {
version = dino_vers[dev->id.hversion_rev];
}
*/
}
- dino_dev = kmalloc(sizeof(struct dino_device), GFP_KERNEL);
+ dino_dev = kzalloc(sizeof(struct dino_device), GFP_KERNEL);
if (!dino_dev) {
printk("dino_init_chip - couldn't alloc dino_device\n");
return 1;
}
- memset(dino_dev, 0, sizeof(struct dino_device));
-
dino_dev->hba.dev = dev;
- dino_dev->hba.base_addr = ioremap(hpa, 4096);
+ dino_dev->hba.base_addr = ioremap_nocache(hpa, 4096);
dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */
spin_lock_init(&dino_dev->dinosaur_pen);
dino_dev->hba.iommu = ccio_get_iommu(dev);