| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | *  linux/arch/arm/kernel/dec21285.c: PCI functions for DC21285 | 
|  | 3 | * | 
|  | 4 | *  Copyright (C) 1998-2001 Russell King | 
|  | 5 | *  Copyright (C) 1998-2000 Phil Blundell | 
|  | 6 | * | 
|  | 7 | * This program is free software; you can redistribute it and/or modify | 
|  | 8 | * it under the terms of the GNU General Public License version 2 as | 
|  | 9 | * published by the Free Software Foundation. | 
|  | 10 | */ | 
|  | 11 | #include <linux/kernel.h> | 
|  | 12 | #include <linux/pci.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 13 | #include <linux/interrupt.h> | 
|  | 14 | #include <linux/mm.h> | 
|  | 15 | #include <linux/slab.h> | 
|  | 16 | #include <linux/init.h> | 
|  | 17 | #include <linux/ioport.h> | 
| Russell King | 2326eb98 | 2006-10-15 13:48:37 +0100 | [diff] [blame] | 18 | #include <linux/irq.h> | 
| Russell King | fced80c | 2008-09-06 12:10:45 +0100 | [diff] [blame] | 19 | #include <linux/io.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 20 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 21 | #include <asm/irq.h> | 
|  | 22 | #include <asm/system.h> | 
|  | 23 | #include <asm/mach/pci.h> | 
|  | 24 | #include <asm/hardware/dec21285.h> | 
|  | 25 |  | 
|  | 26 | #define MAX_SLOTS		21 | 
|  | 27 |  | 
|  | 28 | #define PCICMD_ABORT		((PCI_STATUS_REC_MASTER_ABORT| \ | 
|  | 29 | PCI_STATUS_REC_TARGET_ABORT)<<16) | 
|  | 30 |  | 
|  | 31 | #define PCICMD_ERROR_BITS	((PCI_STATUS_DETECTED_PARITY | \ | 
|  | 32 | PCI_STATUS_REC_MASTER_ABORT | \ | 
|  | 33 | PCI_STATUS_REC_TARGET_ABORT | \ | 
|  | 34 | PCI_STATUS_PARITY) << 16) | 
|  | 35 |  | 
|  | 36 | extern int setup_arm_irq(int, struct irqaction *); | 
|  | 37 | extern void pcibios_report_status(u_int status_mask, int warn); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 38 |  | 
|  | 39 | static unsigned long | 
|  | 40 | dc21285_base_address(struct pci_bus *bus, unsigned int devfn) | 
|  | 41 | { | 
|  | 42 | unsigned long addr = 0; | 
|  | 43 |  | 
|  | 44 | if (bus->number == 0) { | 
|  | 45 | if (PCI_SLOT(devfn) == 0) | 
|  | 46 | /* | 
|  | 47 | * For devfn 0, point at the 21285 | 
|  | 48 | */ | 
|  | 49 | addr = ARMCSR_BASE; | 
|  | 50 | else { | 
|  | 51 | devfn -= 1 << 3; | 
|  | 52 |  | 
|  | 53 | if (devfn < PCI_DEVFN(MAX_SLOTS, 0)) | 
|  | 54 | addr = PCICFG0_BASE | 0xc00000 | (devfn << 8); | 
|  | 55 | } | 
|  | 56 | } else | 
|  | 57 | addr = PCICFG1_BASE | (bus->number << 16) | (devfn << 8); | 
|  | 58 |  | 
|  | 59 | return addr; | 
|  | 60 | } | 
|  | 61 |  | 
|  | 62 | static int | 
|  | 63 | dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where, | 
|  | 64 | int size, u32 *value) | 
|  | 65 | { | 
|  | 66 | unsigned long addr = dc21285_base_address(bus, devfn); | 
|  | 67 | u32 v = 0xffffffff; | 
|  | 68 |  | 
|  | 69 | if (addr) | 
|  | 70 | switch (size) { | 
|  | 71 | case 1: | 
| Daniel Jacobowitz | 6a39dd6 | 2006-08-30 15:02:08 +0100 | [diff] [blame] | 72 | asm("ldrb	%0, [%1, %2]" | 
|  | 73 | : "=r" (v) : "r" (addr), "r" (where) : "cc"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 74 | break; | 
|  | 75 | case 2: | 
| Daniel Jacobowitz | 6a39dd6 | 2006-08-30 15:02:08 +0100 | [diff] [blame] | 76 | asm("ldrh	%0, [%1, %2]" | 
|  | 77 | : "=r" (v) : "r" (addr), "r" (where) : "cc"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 78 | break; | 
|  | 79 | case 4: | 
| Daniel Jacobowitz | 6a39dd6 | 2006-08-30 15:02:08 +0100 | [diff] [blame] | 80 | asm("ldr	%0, [%1, %2]" | 
|  | 81 | : "=r" (v) : "r" (addr), "r" (where) : "cc"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 82 | break; | 
|  | 83 | } | 
|  | 84 |  | 
|  | 85 | *value = v; | 
|  | 86 |  | 
|  | 87 | v = *CSR_PCICMD; | 
|  | 88 | if (v & PCICMD_ABORT) { | 
|  | 89 | *CSR_PCICMD = v & (0xffff|PCICMD_ABORT); | 
|  | 90 | return -1; | 
|  | 91 | } | 
|  | 92 |  | 
|  | 93 | return PCIBIOS_SUCCESSFUL; | 
|  | 94 | } | 
|  | 95 |  | 
|  | 96 | static int | 
|  | 97 | dc21285_write_config(struct pci_bus *bus, unsigned int devfn, int where, | 
|  | 98 | int size, u32 value) | 
|  | 99 | { | 
|  | 100 | unsigned long addr = dc21285_base_address(bus, devfn); | 
|  | 101 | u32 v; | 
|  | 102 |  | 
|  | 103 | if (addr) | 
|  | 104 | switch (size) { | 
|  | 105 | case 1: | 
| Daniel Jacobowitz | 6a39dd6 | 2006-08-30 15:02:08 +0100 | [diff] [blame] | 106 | asm("strb	%0, [%1, %2]" | 
|  | 107 | : : "r" (value), "r" (addr), "r" (where) | 
|  | 108 | : "cc"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 109 | break; | 
|  | 110 | case 2: | 
| Daniel Jacobowitz | 6a39dd6 | 2006-08-30 15:02:08 +0100 | [diff] [blame] | 111 | asm("strh	%0, [%1, %2]" | 
|  | 112 | : : "r" (value), "r" (addr), "r" (where) | 
|  | 113 | : "cc"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 114 | break; | 
|  | 115 | case 4: | 
| Daniel Jacobowitz | 6a39dd6 | 2006-08-30 15:02:08 +0100 | [diff] [blame] | 116 | asm("str	%0, [%1, %2]" | 
|  | 117 | : : "r" (value), "r" (addr), "r" (where) | 
|  | 118 | : "cc"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 119 | break; | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 | v = *CSR_PCICMD; | 
|  | 123 | if (v & PCICMD_ABORT) { | 
|  | 124 | *CSR_PCICMD = v & (0xffff|PCICMD_ABORT); | 
|  | 125 | return -1; | 
|  | 126 | } | 
|  | 127 |  | 
|  | 128 | return PCIBIOS_SUCCESSFUL; | 
|  | 129 | } | 
|  | 130 |  | 
|  | 131 | static struct pci_ops dc21285_ops = { | 
|  | 132 | .read	= dc21285_read_config, | 
|  | 133 | .write	= dc21285_write_config, | 
|  | 134 | }; | 
|  | 135 |  | 
|  | 136 | static struct timer_list serr_timer; | 
|  | 137 | static struct timer_list perr_timer; | 
|  | 138 |  | 
|  | 139 | static void dc21285_enable_error(unsigned long __data) | 
|  | 140 | { | 
|  | 141 | switch (__data) { | 
|  | 142 | case IRQ_PCI_SERR: | 
|  | 143 | del_timer(&serr_timer); | 
|  | 144 | break; | 
|  | 145 |  | 
|  | 146 | case IRQ_PCI_PERR: | 
|  | 147 | del_timer(&perr_timer); | 
|  | 148 | break; | 
|  | 149 | } | 
|  | 150 |  | 
|  | 151 | enable_irq(__data); | 
|  | 152 | } | 
|  | 153 |  | 
|  | 154 | /* | 
|  | 155 | * Warn on PCI errors. | 
|  | 156 | */ | 
| Linus Torvalds | 0cd61b6 | 2006-10-06 10:53:39 -0700 | [diff] [blame] | 157 | static irqreturn_t dc21285_abort_irq(int irq, void *dev_id) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 158 | { | 
|  | 159 | unsigned int cmd; | 
|  | 160 | unsigned int status; | 
|  | 161 |  | 
|  | 162 | cmd = *CSR_PCICMD; | 
|  | 163 | status = cmd >> 16; | 
|  | 164 | cmd = cmd & 0xffff; | 
|  | 165 |  | 
|  | 166 | if (status & PCI_STATUS_REC_MASTER_ABORT) { | 
|  | 167 | printk(KERN_DEBUG "PCI: master abort, pc=0x%08lx\n", | 
| Linus Torvalds | 0cd61b6 | 2006-10-06 10:53:39 -0700 | [diff] [blame] | 168 | instruction_pointer(get_irq_regs())); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 169 | cmd |= PCI_STATUS_REC_MASTER_ABORT << 16; | 
|  | 170 | } | 
|  | 171 |  | 
|  | 172 | if (status & PCI_STATUS_REC_TARGET_ABORT) { | 
|  | 173 | printk(KERN_DEBUG "PCI: target abort: "); | 
|  | 174 | pcibios_report_status(PCI_STATUS_REC_MASTER_ABORT | | 
|  | 175 | PCI_STATUS_SIG_TARGET_ABORT | | 
|  | 176 | PCI_STATUS_REC_TARGET_ABORT, 1); | 
|  | 177 | printk("\n"); | 
|  | 178 |  | 
|  | 179 | cmd |= PCI_STATUS_REC_TARGET_ABORT << 16; | 
|  | 180 | } | 
|  | 181 |  | 
|  | 182 | *CSR_PCICMD = cmd; | 
|  | 183 |  | 
|  | 184 | return IRQ_HANDLED; | 
|  | 185 | } | 
|  | 186 |  | 
| Linus Torvalds | 0cd61b6 | 2006-10-06 10:53:39 -0700 | [diff] [blame] | 187 | static irqreturn_t dc21285_serr_irq(int irq, void *dev_id) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 188 | { | 
|  | 189 | struct timer_list *timer = dev_id; | 
|  | 190 | unsigned int cntl; | 
|  | 191 |  | 
|  | 192 | printk(KERN_DEBUG "PCI: system error received: "); | 
|  | 193 | pcibios_report_status(PCI_STATUS_SIG_SYSTEM_ERROR, 1); | 
|  | 194 | printk("\n"); | 
|  | 195 |  | 
|  | 196 | cntl = *CSR_SA110_CNTL & 0xffffdf07; | 
|  | 197 | *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR; | 
|  | 198 |  | 
|  | 199 | /* | 
|  | 200 | * back off this interrupt | 
|  | 201 | */ | 
|  | 202 | disable_irq(irq); | 
|  | 203 | timer->expires = jiffies + HZ; | 
|  | 204 | add_timer(timer); | 
|  | 205 |  | 
|  | 206 | return IRQ_HANDLED; | 
|  | 207 | } | 
|  | 208 |  | 
| Linus Torvalds | 0cd61b6 | 2006-10-06 10:53:39 -0700 | [diff] [blame] | 209 | static irqreturn_t dc21285_discard_irq(int irq, void *dev_id) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 210 | { | 
|  | 211 | printk(KERN_DEBUG "PCI: discard timer expired\n"); | 
|  | 212 | *CSR_SA110_CNTL &= 0xffffde07; | 
|  | 213 |  | 
|  | 214 | return IRQ_HANDLED; | 
|  | 215 | } | 
|  | 216 |  | 
| Linus Torvalds | 0cd61b6 | 2006-10-06 10:53:39 -0700 | [diff] [blame] | 217 | static irqreturn_t dc21285_dparity_irq(int irq, void *dev_id) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 218 | { | 
|  | 219 | unsigned int cmd; | 
|  | 220 |  | 
|  | 221 | printk(KERN_DEBUG "PCI: data parity error detected: "); | 
|  | 222 | pcibios_report_status(PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY, 1); | 
|  | 223 | printk("\n"); | 
|  | 224 |  | 
|  | 225 | cmd = *CSR_PCICMD & 0xffff; | 
|  | 226 | *CSR_PCICMD = cmd | 1 << 24; | 
|  | 227 |  | 
|  | 228 | return IRQ_HANDLED; | 
|  | 229 | } | 
|  | 230 |  | 
| Linus Torvalds | 0cd61b6 | 2006-10-06 10:53:39 -0700 | [diff] [blame] | 231 | static irqreturn_t dc21285_parity_irq(int irq, void *dev_id) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 232 | { | 
|  | 233 | struct timer_list *timer = dev_id; | 
|  | 234 | unsigned int cmd; | 
|  | 235 |  | 
|  | 236 | printk(KERN_DEBUG "PCI: parity error detected: "); | 
|  | 237 | pcibios_report_status(PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY, 1); | 
|  | 238 | printk("\n"); | 
|  | 239 |  | 
|  | 240 | cmd = *CSR_PCICMD & 0xffff; | 
|  | 241 | *CSR_PCICMD = cmd | 1 << 31; | 
|  | 242 |  | 
|  | 243 | /* | 
|  | 244 | * back off this interrupt | 
|  | 245 | */ | 
|  | 246 | disable_irq(irq); | 
|  | 247 | timer->expires = jiffies + HZ; | 
|  | 248 | add_timer(timer); | 
|  | 249 |  | 
|  | 250 | return IRQ_HANDLED; | 
|  | 251 | } | 
|  | 252 |  | 
|  | 253 | int __init dc21285_setup(int nr, struct pci_sys_data *sys) | 
|  | 254 | { | 
|  | 255 | struct resource *res; | 
|  | 256 |  | 
|  | 257 | if (nr || !footbridge_cfn_mode()) | 
|  | 258 | return 0; | 
|  | 259 |  | 
| Russell King | d2a02b9 | 2006-03-20 19:46:41 +0000 | [diff] [blame] | 260 | res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 261 | if (!res) { | 
|  | 262 | printk("out of memory for root bus resources"); | 
|  | 263 | return 0; | 
|  | 264 | } | 
|  | 265 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 266 | res[0].flags = IORESOURCE_MEM; | 
|  | 267 | res[0].name  = "Footbridge non-prefetch"; | 
|  | 268 | res[1].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH; | 
|  | 269 | res[1].name  = "Footbridge prefetch"; | 
|  | 270 |  | 
|  | 271 | allocate_resource(&iomem_resource, &res[1], 0x20000000, | 
|  | 272 | 0xa0000000, 0xffffffff, 0x20000000, NULL, NULL); | 
|  | 273 | allocate_resource(&iomem_resource, &res[0], 0x40000000, | 
|  | 274 | 0x80000000, 0xffffffff, 0x40000000, NULL, NULL); | 
|  | 275 |  | 
|  | 276 | sys->resource[0] = &ioport_resource; | 
|  | 277 | sys->resource[1] = &res[0]; | 
|  | 278 | sys->resource[2] = &res[1]; | 
|  | 279 | sys->mem_offset  = DC21285_PCI_MEM; | 
|  | 280 |  | 
|  | 281 | return 1; | 
|  | 282 | } | 
|  | 283 |  | 
|  | 284 | struct pci_bus * __init dc21285_scan_bus(int nr, struct pci_sys_data *sys) | 
|  | 285 | { | 
|  | 286 | return pci_scan_bus(0, &dc21285_ops, sys); | 
|  | 287 | } | 
|  | 288 |  | 
|  | 289 | void __init dc21285_preinit(void) | 
|  | 290 | { | 
|  | 291 | unsigned int mem_size, mem_mask; | 
|  | 292 | int cfn_mode; | 
|  | 293 |  | 
|  | 294 | mem_size = (unsigned int)high_memory - PAGE_OFFSET; | 
|  | 295 | for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1) | 
|  | 296 | if (mem_mask >= mem_size) | 
|  | 297 | break; | 
|  | 298 |  | 
|  | 299 | /* | 
|  | 300 | * These registers need to be set up whether we're the | 
|  | 301 | * central function or not. | 
|  | 302 | */ | 
|  | 303 | *CSR_SDRAMBASEMASK    = (mem_mask - 1) & 0x0ffc0000; | 
|  | 304 | *CSR_SDRAMBASEOFFSET  = 0; | 
|  | 305 | *CSR_ROMBASEMASK      = 0x80000000; | 
|  | 306 | *CSR_CSRBASEMASK      = 0; | 
|  | 307 | *CSR_CSRBASEOFFSET    = 0; | 
|  | 308 | *CSR_PCIADDR_EXTN     = 0; | 
|  | 309 |  | 
|  | 310 | cfn_mode = __footbridge_cfn_mode(); | 
|  | 311 |  | 
|  | 312 | printk(KERN_INFO "PCI: DC21285 footbridge, revision %02lX, in " | 
|  | 313 | "%s mode\n", *CSR_CLASSREV & 0xff, cfn_mode ? | 
|  | 314 | "central function" : "addin"); | 
|  | 315 |  | 
|  | 316 | if (footbridge_cfn_mode()) { | 
|  | 317 | /* | 
|  | 318 | * Clear any existing errors - we aren't | 
|  | 319 | * interested in historical data... | 
|  | 320 | */ | 
|  | 321 | *CSR_SA110_CNTL	= (*CSR_SA110_CNTL & 0xffffde07) | | 
|  | 322 | SA110_CNTL_RXSERR; | 
|  | 323 | *CSR_PCICMD = (*CSR_PCICMD & 0xffff) | PCICMD_ERROR_BITS; | 
|  | 324 | } | 
|  | 325 |  | 
|  | 326 | init_timer(&serr_timer); | 
|  | 327 | init_timer(&perr_timer); | 
|  | 328 |  | 
|  | 329 | serr_timer.data = IRQ_PCI_SERR; | 
|  | 330 | serr_timer.function = dc21285_enable_error; | 
|  | 331 | perr_timer.data = IRQ_PCI_PERR; | 
|  | 332 | perr_timer.function = dc21285_enable_error; | 
|  | 333 |  | 
|  | 334 | /* | 
|  | 335 | * We don't care if these fail. | 
|  | 336 | */ | 
| Thomas Gleixner | 52e405e | 2006-07-03 02:20:05 +0200 | [diff] [blame] | 337 | request_irq(IRQ_PCI_SERR, dc21285_serr_irq, IRQF_DISABLED, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 338 | "PCI system error", &serr_timer); | 
| Thomas Gleixner | 52e405e | 2006-07-03 02:20:05 +0200 | [diff] [blame] | 339 | request_irq(IRQ_PCI_PERR, dc21285_parity_irq, IRQF_DISABLED, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 340 | "PCI parity error", &perr_timer); | 
| Thomas Gleixner | 52e405e | 2006-07-03 02:20:05 +0200 | [diff] [blame] | 341 | request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, IRQF_DISABLED, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 342 | "PCI abort", NULL); | 
| Thomas Gleixner | 52e405e | 2006-07-03 02:20:05 +0200 | [diff] [blame] | 343 | request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, IRQF_DISABLED, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 344 | "Discard timer", NULL); | 
| Thomas Gleixner | 52e405e | 2006-07-03 02:20:05 +0200 | [diff] [blame] | 345 | request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, IRQF_DISABLED, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 346 | "PCI data parity", NULL); | 
|  | 347 |  | 
|  | 348 | if (cfn_mode) { | 
|  | 349 | static struct resource csrio; | 
|  | 350 |  | 
|  | 351 | csrio.flags  = IORESOURCE_IO; | 
|  | 352 | csrio.name   = "Footbridge"; | 
|  | 353 |  | 
|  | 354 | allocate_resource(&ioport_resource, &csrio, 128, | 
|  | 355 | 0xff00, 0xffff, 128, NULL, NULL); | 
|  | 356 |  | 
|  | 357 | /* | 
|  | 358 | * Map our SDRAM at a known address in PCI space, just in case | 
|  | 359 | * the firmware had other ideas.  Using a nonzero base is | 
|  | 360 | * necessary, since some VGA cards forcefully use PCI addresses | 
|  | 361 | * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards). | 
|  | 362 | */ | 
|  | 363 | *CSR_PCICSRBASE       = 0xf4000000; | 
|  | 364 | *CSR_PCICSRIOBASE     = csrio.start; | 
|  | 365 | *CSR_PCISDRAMBASE     = __virt_to_bus(PAGE_OFFSET); | 
|  | 366 | *CSR_PCIROMBASE       = 0; | 
|  | 367 | *CSR_PCICMD = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | | 
|  | 368 | PCI_COMMAND_INVALIDATE | PCICMD_ERROR_BITS; | 
|  | 369 | } else if (footbridge_cfn_mode() != 0) { | 
|  | 370 | /* | 
|  | 371 | * If we are not compiled to accept "add-in" mode, then | 
|  | 372 | * we are using a constant virt_to_bus translation which | 
|  | 373 | * can not hope to cater for the way the host BIOS  has | 
|  | 374 | * set up the machine. | 
|  | 375 | */ | 
|  | 376 | panic("PCI: this kernel is compiled for central " | 
|  | 377 | "function mode only"); | 
|  | 378 | } | 
|  | 379 | } | 
|  | 380 |  | 
|  | 381 | void __init dc21285_postinit(void) | 
|  | 382 | { | 
|  | 383 | register_isa_ports(DC21285_PCI_MEM, DC21285_PCI_IO, 0); | 
|  | 384 | } |