aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-11-11 01:25:10 -0500
committerPaul Mackerras <paulus@samba.org>2006-12-04 04:38:52 -0500
commit4cb3cee03d558fd457cb58f56c80a2a09a66110c (patch)
treefe903107d098871a7babc1e3432448758c542cde /arch/powerpc
parentd03f387eb321189bc2ba278b6ca82f1a45cf19d6 (diff)
[POWERPC] Allow hooking of PCI MMIO & PIO accessors on 64 bits
This patch reworks the way iSeries hooks on PCI IO operations (both MMIO and PIO) and provides a generic way for other platforms to do so (we have need to do that for various other platforms). While reworking the IO ops, I ended up doing some spring cleaning in io.h and eeh.h which I might want to split into 2 or 3 patches (among others, eeh.h had a lot of useless stuff in it). A side effect is that EEH for PIO should work now (it used to pass IO ports down to the eeh address check functions which is bogus). Also, new are MMIO "repeat" ops, which other archs like ARM already had, and that we have too now: readsb, readsw, readsl, writesb, writesw, writesl. In the long run, I might also make EEH use the hooks instead of wrapping at the toplevel, which would make things even cleaner and relegate EEH completely in platforms/iseries, but we have to measure the performance impact there (though it's really only on MMIO reads) Since I also need to hook on ioremap, I shuffled the functions a bit there. I introduced ioremap_flags() to use by drivers who want to pass explicit flags to ioremap (and it can be hooked). The old __ioremap() is still there as a low level and cannot be hooked, thus drivers who use it should migrate unless they know they want the low level version. The patch "arch provides generic iomap missing accessors" (should be number 4 in this series) is a pre-requisite to provide full iomap API support with this patch. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/Kconfig10
-rw-r--r--arch/powerpc/kernel/Makefile6
-rw-r--r--arch/powerpc/kernel/io.c18
-rw-r--r--arch/powerpc/kernel/pci_64.c2
-rw-r--r--arch/powerpc/kernel/setup_64.c7
-rw-r--r--arch/powerpc/mm/pgtable_64.c46
-rw-r--r--arch/powerpc/platforms/iseries/pci.c370
-rw-r--r--arch/powerpc/platforms/iseries/setup.c12
8 files changed, 224 insertions, 247 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 3d26ba7ad76d..3e89d9d34937 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -394,6 +394,7 @@ config PPC_PSERIES
394config PPC_ISERIES 394config PPC_ISERIES
395 bool "IBM Legacy iSeries" 395 bool "IBM Legacy iSeries"
396 depends on PPC_MULTIPLATFORM && PPC64 396 depends on PPC_MULTIPLATFORM && PPC64
397 select PPC_INDIRECT_IO
397 398
398config PPC_CHRP 399config PPC_CHRP
399 bool "Common Hardware Reference Platform (CHRP) based machines" 400 bool "Common Hardware Reference Platform (CHRP) based machines"
@@ -548,6 +549,15 @@ config PPC_970_NAP
548 bool 549 bool
549 default n 550 default n
550 551
552config PPC_INDIRECT_IO
553 bool
554 select GENERIC_IOMAP
555 default n
556
557config GENERIC_IOMAP
558 bool
559 default n
560
551source "drivers/cpufreq/Kconfig" 561source "drivers/cpufreq/Kconfig"
552 562
553config CPU_FREQ_PMAC 563config CPU_FREQ_PMAC
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index eba8d118e214..600954df07ae 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -62,7 +62,7 @@ obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o
62module-$(CONFIG_PPC64) += module_64.o 62module-$(CONFIG_PPC64) += module_64.o
63obj-$(CONFIG_MODULES) += $(module-y) 63obj-$(CONFIG_MODULES) += $(module-y)
64 64
65pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o iomap.o 65pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o
66pci32-$(CONFIG_PPC32) := pci_32.o 66pci32-$(CONFIG_PPC32) := pci_32.o
67obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) 67obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y)
68kexec-$(CONFIG_PPC64) := machine_kexec_64.o 68kexec-$(CONFIG_PPC64) := machine_kexec_64.o
@@ -71,6 +71,10 @@ obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y)
71obj-$(CONFIG_AUDIT) += audit.o 71obj-$(CONFIG_AUDIT) += audit.o
72obj64-$(CONFIG_AUDIT) += compat_audit.o 72obj64-$(CONFIG_AUDIT) += compat_audit.o
73 73
74ifneq ($(CONFIG_PPC_INDIRECT_IO),y)
75pci64-$(CONFIG_PPC64) += iomap.o
76endif
77
74ifeq ($(CONFIG_PPC_ISERIES),y) 78ifeq ($(CONFIG_PPC_ISERIES),y)
75$(obj)/head_64.o: $(obj)/lparmap.s 79$(obj)/head_64.o: $(obj)/lparmap.s
76AFLAGS_head_64.o += -I$(obj) 80AFLAGS_head_64.o += -I$(obj)
diff --git a/arch/powerpc/kernel/io.c b/arch/powerpc/kernel/io.c
index e98180686b35..c1aa07524c26 100644
--- a/arch/powerpc/kernel/io.c
+++ b/arch/powerpc/kernel/io.c
@@ -25,13 +25,11 @@
25#include <asm/firmware.h> 25#include <asm/firmware.h>
26#include <asm/bug.h> 26#include <asm/bug.h>
27 27
28void _insb(volatile u8 __iomem *port, void *buf, long count) 28void _insb(const volatile u8 __iomem *port, void *buf, long count)
29{ 29{
30 u8 *tbuf = buf; 30 u8 *tbuf = buf;
31 u8 tmp; 31 u8 tmp;
32 32
33 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
34
35 if (unlikely(count <= 0)) 33 if (unlikely(count <= 0))
36 return; 34 return;
37 asm volatile("sync"); 35 asm volatile("sync");
@@ -48,8 +46,6 @@ void _outsb(volatile u8 __iomem *port, const void *buf, long count)
48{ 46{
49 const u8 *tbuf = buf; 47 const u8 *tbuf = buf;
50 48
51 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
52
53 if (unlikely(count <= 0)) 49 if (unlikely(count <= 0))
54 return; 50 return;
55 asm volatile("sync"); 51 asm volatile("sync");
@@ -60,13 +56,11 @@ void _outsb(volatile u8 __iomem *port, const void *buf, long count)
60} 56}
61EXPORT_SYMBOL(_outsb); 57EXPORT_SYMBOL(_outsb);
62 58
63void _insw_ns(volatile u16 __iomem *port, void *buf, long count) 59void _insw_ns(const volatile u16 __iomem *port, void *buf, long count)
64{ 60{
65 u16 *tbuf = buf; 61 u16 *tbuf = buf;
66 u16 tmp; 62 u16 tmp;
67 63
68 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
69
70 if (unlikely(count <= 0)) 64 if (unlikely(count <= 0))
71 return; 65 return;
72 asm volatile("sync"); 66 asm volatile("sync");
@@ -83,8 +77,6 @@ void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count)
83{ 77{
84 const u16 *tbuf = buf; 78 const u16 *tbuf = buf;
85 79
86 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
87
88 if (unlikely(count <= 0)) 80 if (unlikely(count <= 0))
89 return; 81 return;
90 asm volatile("sync"); 82 asm volatile("sync");
@@ -95,13 +87,11 @@ void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count)
95} 87}
96EXPORT_SYMBOL(_outsw_ns); 88EXPORT_SYMBOL(_outsw_ns);
97 89
98void _insl_ns(volatile u32 __iomem *port, void *buf, long count) 90void _insl_ns(const volatile u32 __iomem *port, void *buf, long count)
99{ 91{
100 u32 *tbuf = buf; 92 u32 *tbuf = buf;
101 u32 tmp; 93 u32 tmp;
102 94
103 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
104
105 if (unlikely(count <= 0)) 95 if (unlikely(count <= 0))
106 return; 96 return;
107 asm volatile("sync"); 97 asm volatile("sync");
@@ -118,8 +108,6 @@ void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count)
118{ 108{
119 const u32 *tbuf = buf; 109 const u32 *tbuf = buf;
120 110
121 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
122
123 if (unlikely(count <= 0)) 111 if (unlikely(count <= 0))
124 return; 112 return;
125 asm volatile("sync"); 113 asm volatile("sync");
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index d800e19ea564..afee470de924 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -1137,7 +1137,7 @@ int unmap_bus_range(struct pci_bus *bus)
1137 1137
1138 if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) 1138 if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
1139 return 1; 1139 return 1;
1140 if (iounmap_explicit((void __iomem *) start_virt, size)) 1140 if (__iounmap_explicit((void __iomem *) start_virt, size))
1141 return 1; 1141 return 1;
1142 1142
1143 return 0; 1143 return 0;
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index f7ad64acf47e..f602a53b1b79 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -599,3 +599,10 @@ void __init setup_per_cpu_areas(void)
599 } 599 }
600} 600}
601#endif 601#endif
602
603
604#ifdef CONFIG_PPC_INDIRECT_IO
605struct ppc_pci_io ppc_pci_io;
606EXPORT_SYMBOL(ppc_pci_io);
607#endif /* CONFIG_PPC_INDIRECT_IO */
608
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index ac64f4aaa509..e9b21846ccbd 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -129,22 +129,12 @@ static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa,
129 return (void __iomem *) (ea + (addr & ~PAGE_MASK)); 129 return (void __iomem *) (ea + (addr & ~PAGE_MASK));
130} 130}
131 131
132
133void __iomem *
134ioremap(unsigned long addr, unsigned long size)
135{
136 return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED);
137}
138
139void __iomem * __ioremap(unsigned long addr, unsigned long size, 132void __iomem * __ioremap(unsigned long addr, unsigned long size,
140 unsigned long flags) 133 unsigned long flags)
141{ 134{
142 unsigned long pa, ea; 135 unsigned long pa, ea;
143 void __iomem *ret; 136 void __iomem *ret;
144 137
145 if (firmware_has_feature(FW_FEATURE_ISERIES))
146 return (void __iomem *)addr;
147
148 /* 138 /*
149 * Choose an address to map it to. 139 * Choose an address to map it to.
150 * Once the imalloc system is running, we use it. 140 * Once the imalloc system is running, we use it.
@@ -178,6 +168,25 @@ void __iomem * __ioremap(unsigned long addr, unsigned long size,
178 return ret; 168 return ret;
179} 169}
180 170
171
172void __iomem * ioremap(unsigned long addr, unsigned long size)
173{
174 unsigned long flags = _PAGE_NO_CACHE | _PAGE_GUARDED;
175
176 if (ppc_md.ioremap)
177 return ppc_md.ioremap(addr, size, flags);
178 return __ioremap(addr, size, flags);
179}
180
181void __iomem * ioremap_flags(unsigned long addr, unsigned long size,
182 unsigned long flags)
183{
184 if (ppc_md.ioremap)
185 return ppc_md.ioremap(addr, size, flags);
186 return __ioremap(addr, size, flags);
187}
188
189
181#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK)) 190#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
182 191
183int __ioremap_explicit(unsigned long pa, unsigned long ea, 192int __ioremap_explicit(unsigned long pa, unsigned long ea,
@@ -235,13 +244,10 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea,
235 * 244 *
236 * XXX what about calls before mem_init_done (ie python_countermeasures()) 245 * XXX what about calls before mem_init_done (ie python_countermeasures())
237 */ 246 */
238void iounmap(volatile void __iomem *token) 247void __iounmap(void __iomem *token)
239{ 248{
240 void *addr; 249 void *addr;
241 250
242 if (firmware_has_feature(FW_FEATURE_ISERIES))
243 return;
244
245 if (!mem_init_done) 251 if (!mem_init_done)
246 return; 252 return;
247 253
@@ -250,6 +256,14 @@ void iounmap(volatile void __iomem *token)
250 im_free(addr); 256 im_free(addr);
251} 257}
252 258
259void iounmap(void __iomem *token)
260{
261 if (ppc_md.iounmap)
262 ppc_md.iounmap(token);
263 else
264 __iounmap(token);
265}
266
253static int iounmap_subset_regions(unsigned long addr, unsigned long size) 267static int iounmap_subset_regions(unsigned long addr, unsigned long size)
254{ 268{
255 struct vm_struct *area; 269 struct vm_struct *area;
@@ -268,7 +282,7 @@ static int iounmap_subset_regions(unsigned long addr, unsigned long size)
268 return 0; 282 return 0;
269} 283}
270 284
271int iounmap_explicit(volatile void __iomem *start, unsigned long size) 285int __iounmap_explicit(void __iomem *start, unsigned long size)
272{ 286{
273 struct vm_struct *area; 287 struct vm_struct *area;
274 unsigned long addr; 288 unsigned long addr;
@@ -303,8 +317,10 @@ int iounmap_explicit(volatile void __iomem *start, unsigned long size)
303} 317}
304 318
305EXPORT_SYMBOL(ioremap); 319EXPORT_SYMBOL(ioremap);
320EXPORT_SYMBOL(ioremap_flags);
306EXPORT_SYMBOL(__ioremap); 321EXPORT_SYMBOL(__ioremap);
307EXPORT_SYMBOL(iounmap); 322EXPORT_SYMBOL(iounmap);
323EXPORT_SYMBOL(__iounmap);
308 324
309void __iomem * reserve_phb_iospace(unsigned long size) 325void __iomem * reserve_phb_iospace(unsigned long size)
310{ 326{
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index a90ae42a7bc2..4a06d9c34986 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -156,53 +156,6 @@ static void pci_Log_Error(char *Error_Text, int Bus, int SubBus,
156} 156}
157 157
158/* 158/*
159 * iSeries_pcibios_init
160 *
161 * Description:
162 * This function checks for all possible system PCI host bridges that connect
163 * PCI buses. The system hypervisor is queried as to the guest partition
164 * ownership status. A pci_controller is built for any bus which is partially
165 * owned or fully owned by this guest partition.
166 */
167void iSeries_pcibios_init(void)
168{
169 struct pci_controller *phb;
170 struct device_node *root = of_find_node_by_path("/");
171 struct device_node *node = NULL;
172
173 if (root == NULL) {
174 printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
175 "of device tree\n");
176 return;
177 }
178 while ((node = of_get_next_child(root, node)) != NULL) {
179 HvBusNumber bus;
180 const u32 *busp;
181
182 if ((node->type == NULL) || (strcmp(node->type, "pci") != 0))
183 continue;
184
185 busp = get_property(node, "bus-range", NULL);
186 if (busp == NULL)
187 continue;
188 bus = *busp;
189 printk("bus %d appears to exist\n", bus);
190 phb = pcibios_alloc_controller(node);
191 if (phb == NULL)
192 continue;
193
194 phb->pci_mem_offset = phb->local_number = bus;
195 phb->first_busno = bus;
196 phb->last_busno = bus;
197 phb->ops = &iSeries_pci_ops;
198 }
199
200 of_node_put(root);
201
202 pci_devs_phb_init();
203}
204
205/*
206 * iSeries_pci_final_fixup(void) 159 * iSeries_pci_final_fixup(void)
207 */ 160 */
208void __init iSeries_pci_final_fixup(void) 161void __init iSeries_pci_final_fixup(void)
@@ -438,11 +391,7 @@ static inline struct device_node *xlate_iomm_address(
438/* 391/*
439 * Read MM I/O Instructions for the iSeries 392 * Read MM I/O Instructions for the iSeries
440 * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal 393 * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal
441 * else, data is returned in big Endian format. 394 * else, data is returned in Big Endian format.
442 *
443 * iSeries_Read_Byte = Read Byte ( 8 bit)
444 * iSeries_Read_Word = Read Word (16 bit)
445 * iSeries_Read_Long = Read Long (32 bit)
446 */ 395 */
447static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) 396static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
448{ 397{
@@ -462,14 +411,15 @@ static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
462 num_printed = 0; 411 num_printed = 0;
463 } 412 }
464 if (num_printed++ < 10) 413 if (num_printed++ < 10)
465 printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", IoAddress); 414 printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n",
415 IoAddress);
466 return 0xff; 416 return 0xff;
467 } 417 }
468 do { 418 do {
469 HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); 419 HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
470 } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0); 420 } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);
471 421
472 return (u8)ret.value; 422 return ret.value;
473} 423}
474 424
475static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) 425static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
@@ -490,7 +440,8 @@ static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
490 num_printed = 0; 440 num_printed = 0;
491 } 441 }
492 if (num_printed++ < 10) 442 if (num_printed++ < 10)
493 printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", IoAddress); 443 printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n",
444 IoAddress);
494 return 0xffff; 445 return 0xffff;
495 } 446 }
496 do { 447 do {
@@ -498,7 +449,7 @@ static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
498 BarOffset, 0); 449 BarOffset, 0);
499 } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0); 450 } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
500 451
501 return swab16((u16)ret.value); 452 return ret.value;
502} 453}
503 454
504static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) 455static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
@@ -519,7 +470,8 @@ static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
519 num_printed = 0; 470 num_printed = 0;
520 } 471 }
521 if (num_printed++ < 10) 472 if (num_printed++ < 10)
522 printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", IoAddress); 473 printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n",
474 IoAddress);
523 return 0xffffffff; 475 return 0xffffffff;
524 } 476 }
525 do { 477 do {
@@ -527,15 +479,12 @@ static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
527 BarOffset, 0); 479 BarOffset, 0);
528 } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0); 480 } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);
529 481
530 return swab32((u32)ret.value); 482 return ret.value;
531} 483}
532 484
533/* 485/*
534 * Write MM I/O Instructions for the iSeries 486 * Write MM I/O Instructions for the iSeries
535 * 487 *
536 * iSeries_Write_Byte = Write Byte (8 bit)
537 * iSeries_Write_Word = Write Word(16 bit)
538 * iSeries_Write_Long = Write Long(32 bit)
539 */ 488 */
540static void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress) 489static void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
541{ 490{
@@ -581,11 +530,12 @@ static void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
581 num_printed = 0; 530 num_printed = 0;
582 } 531 }
583 if (num_printed++ < 10) 532 if (num_printed++ < 10)
584 printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", IoAddress); 533 printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n",
534 IoAddress);
585 return; 535 return;
586 } 536 }
587 do { 537 do {
588 rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0); 538 rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, data, 0);
589 } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0); 539 } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
590} 540}
591 541
@@ -607,231 +557,221 @@ static void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
607 num_printed = 0; 557 num_printed = 0;
608 } 558 }
609 if (num_printed++ < 10) 559 if (num_printed++ < 10)
610 printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", IoAddress); 560 printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n",
561 IoAddress);
611 return; 562 return;
612 } 563 }
613 do { 564 do {
614 rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0); 565 rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, data, 0);
615 } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0); 566 } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
616} 567}
617 568
618extern unsigned char __raw_readb(const volatile void __iomem *addr) 569static u8 iseries_readb(const volatile void __iomem *addr)
619{ 570{
620 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 571 return iSeries_Read_Byte(addr);
621
622 return *(volatile unsigned char __force *)addr;
623} 572}
624EXPORT_SYMBOL(__raw_readb);
625 573
626extern unsigned short __raw_readw(const volatile void __iomem *addr) 574static u16 iseries_readw(const volatile void __iomem *addr)
627{ 575{
628 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 576 return le16_to_cpu(iSeries_Read_Word(addr));
629
630 return *(volatile unsigned short __force *)addr;
631} 577}
632EXPORT_SYMBOL(__raw_readw);
633 578
634extern unsigned int __raw_readl(const volatile void __iomem *addr) 579static u32 iseries_readl(const volatile void __iomem *addr)
635{ 580{
636 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 581 return le32_to_cpu(iSeries_Read_Long(addr));
637
638 return *(volatile unsigned int __force *)addr;
639} 582}
640EXPORT_SYMBOL(__raw_readl);
641 583
642extern unsigned long __raw_readq(const volatile void __iomem *addr) 584static u16 iseries_readw_be(const volatile void __iomem *addr)
643{ 585{
644 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 586 return iSeries_Read_Word(addr);
645
646 return *(volatile unsigned long __force *)addr;
647} 587}
648EXPORT_SYMBOL(__raw_readq);
649 588
650extern void __raw_writeb(unsigned char v, volatile void __iomem *addr) 589static u32 iseries_readl_be(const volatile void __iomem *addr)
651{ 590{
652 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 591 return iSeries_Read_Long(addr);
653
654 *(volatile unsigned char __force *)addr = v;
655} 592}
656EXPORT_SYMBOL(__raw_writeb);
657 593
658extern void __raw_writew(unsigned short v, volatile void __iomem *addr) 594static void iseries_writeb(u8 data, volatile void __iomem *addr)
659{ 595{
660 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 596 iSeries_Write_Byte(data, addr);
661
662 *(volatile unsigned short __force *)addr = v;
663} 597}
664EXPORT_SYMBOL(__raw_writew);
665 598
666extern void __raw_writel(unsigned int v, volatile void __iomem *addr) 599static void iseries_writew(u16 data, volatile void __iomem *addr)
667{ 600{
668 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 601 iSeries_Write_Word(cpu_to_le16(data), addr);
669
670 *(volatile unsigned int __force *)addr = v;
671} 602}
672EXPORT_SYMBOL(__raw_writel);
673 603
674extern void __raw_writeq(unsigned long v, volatile void __iomem *addr) 604static void iseries_writel(u32 data, volatile void __iomem *addr)
675{ 605{
676 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 606 iSeries_Write_Long(cpu_to_le32(data), addr);
677
678 *(volatile unsigned long __force *)addr = v;
679} 607}
680EXPORT_SYMBOL(__raw_writeq);
681 608
682int in_8(const volatile unsigned char __iomem *addr) 609static void iseries_writew_be(u16 data, volatile void __iomem *addr)
683{ 610{
684 if (firmware_has_feature(FW_FEATURE_ISERIES)) 611 iSeries_Write_Word(data, addr);
685 return iSeries_Read_Byte(addr);
686 return __in_8(addr);
687} 612}
688EXPORT_SYMBOL(in_8);
689 613
690void out_8(volatile unsigned char __iomem *addr, int val) 614static void iseries_writel_be(u32 data, volatile void __iomem *addr)
691{ 615{
692 if (firmware_has_feature(FW_FEATURE_ISERIES)) 616 iSeries_Write_Long(data, addr);
693 iSeries_Write_Byte(val, addr);
694 else
695 __out_8(addr, val);
696} 617}
697EXPORT_SYMBOL(out_8);
698 618
699int in_le16(const volatile unsigned short __iomem *addr) 619static void iseries_readsb(const volatile void __iomem *addr, void *buf,
620 unsigned long count)
700{ 621{
701 if (firmware_has_feature(FW_FEATURE_ISERIES)) 622 u8 *dst = buf;
702 return iSeries_Read_Word(addr); 623 while(count-- > 0)
703 return __in_le16(addr); 624 *(dst++) = iSeries_Read_Byte(addr);
704} 625}
705EXPORT_SYMBOL(in_le16);
706 626
707int in_be16(const volatile unsigned short __iomem *addr) 627static void iseries_readsw(const volatile void __iomem *addr, void *buf,
628 unsigned long count)
708{ 629{
709 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 630 u16 *dst = buf;
710 631 while(count-- > 0)
711 return __in_be16(addr); 632 *(dst++) = iSeries_Read_Word(addr);
712} 633}
713EXPORT_SYMBOL(in_be16);
714 634
715void out_le16(volatile unsigned short __iomem *addr, int val) 635static void iseries_readsl(const volatile void __iomem *addr, void *buf,
636 unsigned long count)
716{ 637{
717 if (firmware_has_feature(FW_FEATURE_ISERIES)) 638 u32 *dst = buf;
718 iSeries_Write_Word(val, addr); 639 while(count-- > 0)
719 else 640 *(dst++) = iSeries_Read_Long(addr);
720 __out_le16(addr, val);
721} 641}
722EXPORT_SYMBOL(out_le16);
723 642
724void out_be16(volatile unsigned short __iomem *addr, int val) 643static void iseries_writesb(volatile void __iomem *addr, const void *buf,
644 unsigned long count)
725{ 645{
726 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 646 const u8 *src = buf;
727 647 while(count-- > 0)
728 __out_be16(addr, val); 648 iSeries_Write_Byte(*(src++), addr);
729} 649}
730EXPORT_SYMBOL(out_be16);
731 650
732unsigned in_le32(const volatile unsigned __iomem *addr) 651static void iseries_writesw(volatile void __iomem *addr, const void *buf,
652 unsigned long count)
733{ 653{
734 if (firmware_has_feature(FW_FEATURE_ISERIES)) 654 const u16 *src = buf;
735 return iSeries_Read_Long(addr); 655 while(count-- > 0)
736 return __in_le32(addr); 656 iSeries_Write_Word(*(src++), addr);
737} 657}
738EXPORT_SYMBOL(in_le32);
739 658
740unsigned in_be32(const volatile unsigned __iomem *addr) 659static void iseries_writesl(volatile void __iomem *addr, const void *buf,
660 unsigned long count)
741{ 661{
742 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 662 const u32 *src = buf;
743 663 while(count-- > 0)
744 return __in_be32(addr); 664 iSeries_Write_Long(*(src++), addr);
745} 665}
746EXPORT_SYMBOL(in_be32);
747 666
748void out_le32(volatile unsigned __iomem *addr, int val) 667static void iseries_memset_io(volatile void __iomem *addr, int c,
668 unsigned long n)
749{ 669{
750 if (firmware_has_feature(FW_FEATURE_ISERIES)) 670 volatile char __iomem *d = addr;
751 iSeries_Write_Long(val, addr);
752 else
753 __out_le32(addr, val);
754}
755EXPORT_SYMBOL(out_le32);
756 671
757void out_be32(volatile unsigned __iomem *addr, int val) 672 while (n-- > 0)
758{ 673 iSeries_Write_Byte(c, d++);
759 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
760
761 __out_be32(addr, val);
762} 674}
763EXPORT_SYMBOL(out_be32);
764 675
765unsigned long in_le64(const volatile unsigned long __iomem *addr) 676static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src,
677 unsigned long n)
766{ 678{
767 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 679 char *d = dest;
680 const volatile char __iomem *s = src;
768 681
769 return __in_le64(addr); 682 while (n-- > 0)
683 *d++ = iSeries_Read_Byte(s++);
770} 684}
771EXPORT_SYMBOL(in_le64);
772 685
773unsigned long in_be64(const volatile unsigned long __iomem *addr) 686static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src,
687 unsigned long n)
774{ 688{
775 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 689 const char *s = src;
690 volatile char __iomem *d = dest;
776 691
777 return __in_be64(addr); 692 while (n-- > 0)
693 iSeries_Write_Byte(*s++, d++);
778} 694}
779EXPORT_SYMBOL(in_be64);
780
781void out_le64(volatile unsigned long __iomem *addr, unsigned long val)
782{
783 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
784 695
785 __out_le64(addr, val); 696/* We only set MMIO ops. The default PIO ops will be default
786} 697 * to the MMIO ops + pci_io_base which is 0 on iSeries as
787EXPORT_SYMBOL(out_le64); 698 * expected so both should work.
699 *
700 * Note that we don't implement the readq/writeq versions as
701 * I don't know of an HV call for doing so. Thus, the default
702 * operation will be used instead, which will fault a the value
703 * return by iSeries for MMIO addresses always hits a non mapped
704 * area. This is as good as the BUG() we used to have there.
705 */
706static struct ppc_pci_io __initdata iseries_pci_io = {
707 .readb = iseries_readb,
708 .readw = iseries_readw,
709 .readl = iseries_readl,
710 .readw_be = iseries_readw_be,
711 .readl_be = iseries_readl_be,
712 .writeb = iseries_writeb,
713 .writew = iseries_writew,
714 .writel = iseries_writel,
715 .writew_be = iseries_writew_be,
716 .writel_be = iseries_writel_be,
717 .readsb = iseries_readsb,
718 .readsw = iseries_readsw,
719 .readsl = iseries_readsl,
720 .writesb = iseries_writesb,
721 .writesw = iseries_writesw,
722 .writesl = iseries_writesl,
723 .memset_io = iseries_memset_io,
724 .memcpy_fromio = iseries_memcpy_fromio,
725 .memcpy_toio = iseries_memcpy_toio,
726};
788 727
789void out_be64(volatile unsigned long __iomem *addr, unsigned long val) 728/*
729 * iSeries_pcibios_init
730 *
731 * Description:
732 * This function checks for all possible system PCI host bridges that connect
733 * PCI buses. The system hypervisor is queried as to the guest partition
734 * ownership status. A pci_controller is built for any bus which is partially
735 * owned or fully owned by this guest partition.
736 */
737void __init iSeries_pcibios_init(void)
790{ 738{
791 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 739 struct pci_controller *phb;
740 struct device_node *root = of_find_node_by_path("/");
741 struct device_node *node = NULL;
792 742
793 __out_be64(addr, val); 743 /* Install IO hooks */
794} 744 ppc_pci_io = iseries_pci_io;
795EXPORT_SYMBOL(out_be64);
796 745
797void memset_io(volatile void __iomem *addr, int c, unsigned long n) 746 if (root == NULL) {
798{ 747 printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
799 if (firmware_has_feature(FW_FEATURE_ISERIES)) { 748 "of device tree\n");
800 volatile char __iomem *d = addr; 749 return;
750 }
751 while ((node = of_get_next_child(root, node)) != NULL) {
752 HvBusNumber bus;
753 const u32 *busp;
801 754
802 while (n-- > 0) { 755 if ((node->type == NULL) || (strcmp(node->type, "pci") != 0))
803 iSeries_Write_Byte(c, d++); 756 continue;
804 }
805 } else
806 eeh_memset_io(addr, c, n);
807}
808EXPORT_SYMBOL(memset_io);
809 757
810void memcpy_fromio(void *dest, const volatile void __iomem *src, 758 busp = get_property(node, "bus-range", NULL);
811 unsigned long n) 759 if (busp == NULL)
812{ 760 continue;
813 if (firmware_has_feature(FW_FEATURE_ISERIES)) { 761 bus = *busp;
814 char *d = dest; 762 printk("bus %d appears to exist\n", bus);
815 const volatile char __iomem *s = src; 763 phb = pcibios_alloc_controller(node);
764 if (phb == NULL)
765 continue;
816 766
817 while (n-- > 0) { 767 phb->pci_mem_offset = phb->local_number = bus;
818 *d++ = iSeries_Read_Byte(s++); 768 phb->first_busno = bus;
819 } 769 phb->last_busno = bus;
820 } else 770 phb->ops = &iSeries_pci_ops;
821 eeh_memcpy_fromio(dest, src, n); 771 }
822}
823EXPORT_SYMBOL(memcpy_fromio);
824 772
825void memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n) 773 of_node_put(root);
826{
827 if (firmware_has_feature(FW_FEATURE_ISERIES)) {
828 const char *s = src;
829 volatile char __iomem *d = dest;
830 774
831 while (n-- > 0) { 775 pci_devs_phb_init();
832 iSeries_Write_Byte(*s++, d++);
833 }
834 } else
835 eeh_memcpy_toio(dest, src, n);
836} 776}
837EXPORT_SYMBOL(memcpy_toio); 777
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index cd8965ec9ddb..2f16d9330cfe 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -617,6 +617,16 @@ static void iseries_dedicated_idle(void)
617void __init iSeries_init_IRQ(void) { } 617void __init iSeries_init_IRQ(void) { }
618#endif 618#endif
619 619
620static void __iomem *iseries_ioremap(unsigned long address, unsigned long size,
621 unsigned long flags)
622{
623 return (void __iomem *)address;
624}
625
626static void iseries_iounmap(void __iomem *token)
627{
628}
629
620/* 630/*
621 * iSeries has no legacy IO, anything calling this function has to 631 * iSeries has no legacy IO, anything calling this function has to
622 * fail or bad things will happen 632 * fail or bad things will happen
@@ -655,6 +665,8 @@ define_machine(iseries) {
655 .progress = iSeries_progress, 665 .progress = iSeries_progress,
656 .probe = iseries_probe, 666 .probe = iseries_probe,
657 .check_legacy_ioport = iseries_check_legacy_ioport, 667 .check_legacy_ioport = iseries_check_legacy_ioport,
668 .ioremap = iseries_ioremap,
669 .iounmap = iseries_iounmap,
658 /* XXX Implement enable_pmcs for iSeries */ 670 /* XXX Implement enable_pmcs for iSeries */
659}; 671};
660 672