patch-2.3.23 linux/arch/arm/kernel/dec21285.c
Next file: linux/arch/arm/kernel/dma-dummy.c
Previous file: linux/arch/arm/kernel/debug-armv.S
Back to the patch index
Back to the overall index
- Lines: 481
- Date:
Wed Oct 20 16:29:08 1999
- Orig file:
v2.3.22/linux/arch/arm/kernel/dec21285.c
- Orig date:
Tue Aug 31 17:29:12 1999
diff -u --recursive --new-file v2.3.22/linux/arch/arm/kernel/dec21285.c linux/arch/arm/kernel/dec21285.c
@@ -13,241 +13,318 @@
#include <linux/init.h>
#include <linux/ioport.h>
+#include <asm/dec21285.h>
+#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
-#include <asm/hardware.h>
#define MAX_SLOTS 21
-extern void pcibios_fixup_ebsa285(struct pci_dev *dev);
-extern void pcibios_init_ebsa285(void);
+extern int setup_arm_irq(int, struct irqaction *);
+extern void pcibios_report_device_errors(void);
+extern int (*pci_irq_fixup)(struct pci_dev *dev);
-int
-pcibios_present(void)
+static unsigned long
+dc21285_base_address(struct pci_dev *dev, int where)
{
- return 1;
+ unsigned long addr = 0;
+ unsigned int devfn = dev->devfn;
+
+ if (dev->bus->number != 0)
+ addr = PCICFG1_BASE | (dev->bus->number << 16) | (devfn << 8);
+ else if (devfn < PCI_DEVFN(MAX_SLOTS, 0))
+ addr = PCICFG0_BASE | 0xc00000 | (devfn << 8);
+
+ return addr;
}
-static unsigned long
-pcibios_base_address(unsigned char bus, unsigned char dev_fn)
+static int
+dc21285_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
- if (bus == 0) {
- int slot = PCI_SLOT(dev_fn);
-
- if (slot < MAX_SLOTS)
- return PCICFG0_BASE + 0xc00000 +
- (slot << 11) + (PCI_FUNC(dev_fn) << 8);
- else
- return 0;
- } else
- return PCICFG1_BASE | (bus << 16) | (dev_fn << 8);
-}
-
-int
-pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
- unsigned char where, unsigned char *val)
-{
- unsigned long addr = pcibios_base_address(bus, dev_fn);
- unsigned char v;
-
- if (addr)
- __asm__("ldr%?b %0, [%1, %2]"
- : "=r" (v)
- : "r" (addr), "r" (where));
+ unsigned long addr = dc21285_base_address(dev, where);
+ u8 v;
+
+ if (addr)
+ asm("ldr%?b %0, [%1, %2]"
+ : "=r" (v) : "r" (addr), "r" (where));
else
v = 0xff;
- *val = v;
+
+ *value = v;
+
return PCIBIOS_SUCCESSFUL;
}
-int
-pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
- unsigned char where, unsigned short *val)
+static int
+dc21285_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
- unsigned long addr = pcibios_base_address(bus, dev_fn);
- unsigned short v;
+ unsigned long addr = dc21285_base_address(dev, where);
+ u16 v;
if (addr)
- __asm__("ldr%?h %0, [%1, %2]"
- : "=r" (v)
- : "r" (addr), "r" (where));
+ asm("ldr%?h %0, [%1, %2]"
+ : "=r" (v) : "r" (addr), "r" (where));
else
v = 0xffff;
- *val = v;
+
+ *value = v;
+
return PCIBIOS_SUCCESSFUL;
}
-int
-pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
- unsigned char where, unsigned int *val)
+static int
+dc21285_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
- unsigned long addr = pcibios_base_address(bus, dev_fn);
- unsigned int v;
+ unsigned long addr = dc21285_base_address(dev, where);
+ u32 v;
if (addr)
- __asm__("ldr%? %0, [%1, %2]"
- : "=r" (v)
- : "r" (addr), "r" (where));
+ asm("ldr%? %0, [%1, %2]"
+ : "=r" (v) : "r" (addr), "r" (where));
else
v = 0xffffffff;
- *val = v;
+
+ *value = v;
+
return PCIBIOS_SUCCESSFUL;
}
-int
-pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
- unsigned char where, unsigned char val)
+static int
+dc21285_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
- unsigned long addr = pcibios_base_address(bus, dev_fn);
+ unsigned long addr = dc21285_base_address(dev, where);
if (addr)
- __asm__("str%?b %0, [%1, %2]"
- : : "r" (val), "r" (addr), "r" (where));
+ asm("str%?b %0, [%1, %2]"
+ : : "r" (value), "r" (addr), "r" (where));
+
return PCIBIOS_SUCCESSFUL;
}
-int
-pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
- unsigned char where, unsigned short val)
+static int
+dc21285_write_config_word(struct pci_dev *dev, int where, u16 value)
{
- unsigned long addr = pcibios_base_address(bus, dev_fn);
+ unsigned long addr = dc21285_base_address(dev, where);
if (addr)
- __asm__("str%?h %0, [%1, %2]"
- : : "r" (val), "r" (addr), "r" (where));
+ asm("str%?h %0, [%1, %2]"
+ : : "r" (value), "r" (addr), "r" (where));
+
return PCIBIOS_SUCCESSFUL;
}
-int
-pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
- unsigned char where, unsigned int val)
+static int
+dc21285_write_config_dword(struct pci_dev *dev, int where, u32 value)
{
- unsigned long addr = pcibios_base_address(bus, dev_fn);
+ unsigned long addr = dc21285_base_address(dev, where);
if (addr)
- __asm__("str%? %0, [%1, %2]"
- : : "r" (val), "r" (addr), "r" (where));
+ asm("str%? %0, [%1, %2]"
+ : : "r" (value), "r" (addr), "r" (where));
+
return PCIBIOS_SUCCESSFUL;
}
-void __init pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned short set)
+static struct pci_ops dc21285_ops = {
+ dc21285_read_config_byte,
+ dc21285_read_config_word,
+ dc21285_read_config_dword,
+ dc21285_write_config_byte,
+ dc21285_write_config_word,
+ dc21285_write_config_dword,
+};
+
+/*
+ * Warn on PCI errors.
+ */
+static void
+dc21285_error(int irq, void *dev_id, struct pt_regs *regs)
+{
+ static unsigned long next_warn;
+ unsigned long cmd = *CSR_PCICMD & 0x0000ffff;
+ unsigned long ctrl = (*CSR_SA110_CNTL) & 0xffffde07;
+ unsigned long irqstatus = *CSR_IRQ_RAWSTATUS;
+ int warn = time_after_eq(jiffies, next_warn);
+
+ ctrl |= SA110_CNTL_DISCARDTIMER;
+
+ if (warn) {
+ next_warn = jiffies + HZ;
+ printk(KERN_DEBUG "PCI: ");
+ }
+
+ if (irqstatus & (1 << 31)) {
+ if (warn)
+ printk("parity error ");
+ cmd |= 1 << 31;
+ }
+
+ if (irqstatus & (1 << 30)) {
+ if (warn)
+ printk("target abort ");
+ cmd |= 1 << 28;
+ }
+
+ if (irqstatus & (1 << 29)) {
+ if (warn)
+ printk("master abort ");
+ cmd |= 1 << 29;
+ }
+
+ if (irqstatus & (1 << 28)) {
+ if (warn)
+ printk("data parity error ");
+ cmd |= 1 << 24;
+ }
+
+ if (irqstatus & (1 << 27)) {
+ if (warn)
+ printk("discard timer expired ");
+ ctrl &= ~SA110_CNTL_DISCARDTIMER;
+ }
+
+ if (irqstatus & (1 << 23)) {
+ if (warn)
+ printk("system error ");
+ ctrl |= SA110_CNTL_RXSERR;
+ }
+
+ if (warn)
+ printk("pc=[<%08lX>]\n", instruction_pointer(regs));
+
+ pcibios_report_device_errors();
+
+ *CSR_PCICMD = cmd;
+ *CSR_SA110_CNTL = ctrl;
+}
+
+static struct irqaction dc21285_error_action = {
+ dc21285_error, SA_INTERRUPT, 0, "PCI error", NULL, NULL
+};
+
+static int irqmap_ebsa[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 };
+
+static int __init ebsa_irqval(struct pci_dev *dev)
{
- unsigned short cmd;
+ u8 pin;
+
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- cmd = (cmd & ~clear) | set;
- pci_write_config_word(dev, PCI_COMMAND, cmd);
+ return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3];
}
-void __init pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int addr)
+static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
+
+static int __init cats_irqval(struct pci_dev *dev)
{
- int reg = PCI_BASE_ADDRESS_0 + (idx << 2);
+ if (dev->irq >= 128)
+ return 16 + (dev->irq & 0x1f);
- pci_write_config_dword(dev, reg, addr);
- pci_read_config_dword(dev, reg, &addr);
+ switch (dev->irq) {
+ case 1 ... 4:
+ return irqmap_cats[dev->irq - 1];
- dev->base_address[idx] = addr;
+ default:
+ printk("PCI: device %02x:%02x has unknown irq line %x\n",
+ dev->bus->number, dev->devfn, dev->irq);
+ case 0:
+ break;
+ }
+ return 0;
}
-void __init pcibios_fixup(void)
+static int __init netwinder_irqval(struct pci_dev *dev)
{
- struct pci_dev *dev;
+#define DEV(v,d) ((v)<<16|(d))
+ switch (DEV(dev->vendor, dev->device)) {
+ case DEV(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142):
+ return IRQ_NETWINDER_ETHER100;
+
+ case DEV(PCI_VENDOR_ID_WINBOND2, 0x5a5a):
+ return IRQ_NETWINDER_ETHER10;
- for (dev = pci_devices; dev; dev = dev->next) {
- pcibios_fixup_ebsa285(dev);
+ case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553):
+ return 0;
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_LINE, dev->irq);
+ case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105):
+ return IRQ_ISA_HARDDISK1;
- printk(KERN_DEBUG
- "PCI: %02x:%02x [%04x/%04x] on irq %d\n",
+ case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000):
+ return IRQ_NETWINDER_VGA;
+
+ default:
+ printk(KERN_ERR "PCI: %02X:%02X [%04X:%04X] unknown device\n",
dev->bus->number, dev->devfn,
- dev->vendor, dev->device, dev->irq);
+ dev->vendor, dev->device);
+ return 0;
}
-
- hw_init();
}
-void __init pcibios_init(void)
+struct pci_ops * __init dc21285_init(int pass)
{
- unsigned int mem_size = (unsigned int)high_memory - PAGE_OFFSET;
+ unsigned int mem_size;
unsigned long cntl;
- *CSR_SDRAMBASEMASK = (mem_size - 1) & 0x0ffc0000;
- *CSR_SDRAMBASEOFFSET = 0;
- *CSR_ROMBASEMASK = 0x80000000;
- *CSR_CSRBASEMASK = 0;
- *CSR_CSRBASEOFFSET = 0;
- *CSR_PCIADDR_EXTN = 0;
+ if (pass == 0) {
+ mem_size = (unsigned int)high_memory - PAGE_OFFSET;
+ *CSR_SDRAMBASEMASK = (mem_size - 1) & 0x0ffc0000;
+ *CSR_SDRAMBASEOFFSET = 0;
+ *CSR_ROMBASEMASK = 0x80000000;
+ *CSR_CSRBASEMASK = 0;
+ *CSR_CSRBASEOFFSET = 0;
+ *CSR_PCIADDR_EXTN = 0;
#ifdef CONFIG_HOST_FOOTBRIDGE
- /*
- * Against my better judgement, Philip Blundell still seems
- * to be saying that we should initialise the PCI stuff here
- * when the PCI_CFN bit is not set, dispite my comment below,
- * which he decided to remove. If it is not set, then
- * the card is in add-in mode, and we're in a machine where
- * the bus is set up by 'others'.
- *
- * We should therefore not mess about with the mapping in
- * anyway, and we should not be using the virt_to_bus functions
- * that exist in the HOST architecture mode (since they assume
- * a fixed mapping).
- *
- * Instead, you should be using ADDIN mode, which allows for
- * this situation. This does assume that you have correctly
- * initialised the PCI bus, which you must have done to get
- * your PC booted.
- *
- * Unfortunately, he seems to be blind to this. I guess he'll
- * also remove all this.
- *
- * And THIS COMMENT STAYS, even if this gets patched, thank
- * you.
- */
-
- /*
- * Map our SDRAM at a known address in PCI space, just in case
- * the firmware had other ideas. Using a nonzero base is
- * necessary, since some VGA cards forcefully use PCI addresses
- * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards).
- *
- * NOTE! If you need to chec the PCI_CFN bit in the SA110
- * control register then you've configured the kernel wrong.
- * If you're not using host mode, then DO NOT set
- * CONFIG_HOST_FOOTBRIDGE, but use CONFIG_ADDIN_FOOTBRIDGE
- * instead. In this case, you MUST supply some firmware
- * to allow your PC to boot, plus we should not modify the
- * mappings that the PC BIOS has set up for us.
- */
- *CSR_PCICACHELINESIZE = 0x00002008;
- *CSR_PCICSRBASE = 0;
- *CSR_PCICSRIOBASE = 0;
- *CSR_PCISDRAMBASE = virt_to_bus((void *)PAGE_OFFSET);
- *CSR_PCIROMBASE = 0;
- *CSR_PCICMD = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
- PCI_COMMAND_MASTER | PCI_COMMAND_FAST_BACK |
- PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY |
- (1 << 31) | (1 << 29) | (1 << 28) | (1 << 24);
+ /*
+ * Map our SDRAM at a known address in PCI space, just in case
+ * the firmware had other ideas. Using a nonzero base is
+ * necessary, since some VGA cards forcefully use PCI addresses
+ * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards).
+ */
+ *CSR_PCICACHELINESIZE = 0x00002008;
+ *CSR_PCICSRBASE = 0;
+ *CSR_PCICSRIOBASE = 0;
+ *CSR_PCISDRAMBASE = virt_to_bus((void *)PAGE_OFFSET);
+ *CSR_PCIROMBASE = 0;
+ *CSR_PCICMD = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER | PCI_COMMAND_FAST_BACK |
+ PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY |
+ (1 << 31) | (1 << 29) | (1 << 28) | (1 << 24);
#endif
- /*
- * Clear any existing errors - we aren't
- * interested in historical data...
- */
- cntl = *CSR_SA110_CNTL & 0xffffde07;
- *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR;
-
- pcibios_init_ebsa285();
+ printk(KERN_DEBUG"PCI: DC21285 footbridge, revision %02lX\n",
+ *CSR_CLASSREV & 0xff);
- printk(KERN_DEBUG"PCI: DEC21285 revision %02lX\n", *CSR_CLASSREV & 0xff);
-}
-
-void __init pcibios_fixup_bus(struct pci_bus *bus)
-{
-}
+ switch (machine_arch_type) {
+ case MACH_TYPE_EBSA285:
+ pci_irq_fixup = ebsa_irqval;
+ break;
+
+ case MACH_TYPE_CATS:
+ pci_irq_fixup = cats_irqval;
+ break;
+
+ case MACH_TYPE_NETWINDER:
+ pci_irq_fixup = netwinder_irqval;
+ break;
+ }
+
+ return &dc21285_ops;
+ } else {
+ /*
+ * Clear any existing errors - we aren't
+ * interested in historical data...
+ */
+ cntl = *CSR_SA110_CNTL & 0xffffde07;
+ *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR;
+ cntl = *CSR_PCICMD & 0x0000ffff;
+ *CSR_PCICMD = cntl | 1 << 31 | 1 << 29 | 1 << 28 | 1 << 24;
+
+ /*
+ * Initialise PCI error IRQ after we've finished probing
+ */
+ setup_arm_irq(IRQ_PCI_ERR, &dc21285_error_action);
-char * __init pcibios_setup(char *str)
-{
- return str;
+ return NULL;
+ }
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)