diff options
-rw-r--r-- | arch/ia64/kernel/setup.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 1f5c26dbe705..e256b114bf4e 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c | |||
@@ -244,28 +244,31 @@ find_initrd (void) | |||
244 | static void __init | 244 | static void __init |
245 | io_port_init (void) | 245 | io_port_init (void) |
246 | { | 246 | { |
247 | extern unsigned long ia64_iobase; | ||
248 | unsigned long phys_iobase; | 247 | unsigned long phys_iobase; |
249 | 248 | ||
250 | /* | 249 | /* |
251 | * Set `iobase' to the appropriate address in region 6 (uncached access range). | 250 | * Set `iobase' based on the EFI memory map or, failing that, the |
251 | * value firmware left in ar.k0. | ||
252 | * | 252 | * |
253 | * The EFI memory map is the "preferred" location to get the I/O port space base, | 253 | * Note that in ia32 mode, IN/OUT instructions use ar.k0 to compute |
254 | * rather the relying on AR.KR0. This should become more clear in future SAL | 254 | * the port's virtual address, so ia32_load_state() loads it with a |
255 | * specs. We'll fall back to getting it out of AR.KR0 if no appropriate entry is | 255 | * user virtual address. But in ia64 mode, glibc uses the |
256 | * found in the memory map. | 256 | * *physical* address in ar.k0 to mmap the appropriate area from |
257 | * /dev/mem, and the inX()/outX() interfaces use MMIO. In both | ||
258 | * cases, user-mode can only use the legacy 0-64K I/O port space. | ||
259 | * | ||
260 | * ar.k0 is not involved in kernel I/O port accesses, which can use | ||
261 | * any of the I/O port spaces and are done via MMIO using the | ||
262 | * virtual mmio_base from the appropriate io_space[]. | ||
257 | */ | 263 | */ |
258 | phys_iobase = efi_get_iobase(); | 264 | phys_iobase = efi_get_iobase(); |
259 | if (phys_iobase) | 265 | if (!phys_iobase) { |
260 | /* set AR.KR0 since this is all we use it for anyway */ | ||
261 | ia64_set_kr(IA64_KR_IO_BASE, phys_iobase); | ||
262 | else { | ||
263 | phys_iobase = ia64_get_kr(IA64_KR_IO_BASE); | 266 | phys_iobase = ia64_get_kr(IA64_KR_IO_BASE); |
264 | printk(KERN_INFO "No I/O port range found in EFI memory map, falling back " | 267 | printk(KERN_INFO "No I/O port range found in EFI memory map, " |
265 | "to AR.KR0\n"); | 268 | "falling back to AR.KR0 (0x%lx)\n", phys_iobase); |
266 | printk(KERN_INFO "I/O port base = 0x%lx\n", phys_iobase); | ||
267 | } | 269 | } |
268 | ia64_iobase = (unsigned long) ioremap(phys_iobase, 0); | 270 | ia64_iobase = (unsigned long) ioremap(phys_iobase, 0); |
271 | ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase)); | ||
269 | 272 | ||
270 | /* setup legacy IO port space */ | 273 | /* setup legacy IO port space */ |
271 | io_space[0].mmio_base = ia64_iobase; | 274 | io_space[0].mmio_base = ia64_iobase; |