aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-05-09 05:35:27 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-05-09 05:35:27 -0400
commitca3dd88e411648c76e1911a729440e3763ba5049 (patch)
treee874ed0c1e91269aa514a443358d4f3738bcb244
parentde372ecd80a42c4fb485c7232475301a18d05184 (diff)
[SPARC64] PCI: Consolidate PCI access code into pci_common.c
All the sun4u controllers do the same thing to compute the physical I/O address to poke, and we can move the sun4v code into this common location too. This one needs a bit of testing, in particular the Sabre code had some funny stuff that would break up u16 and/or u32 accesses into pieces and I didn't think that was needed any more. If it is we need to find out why and add back code to do it again. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc64/kernel/pci_common.c194
-rw-r--r--arch/sparc64/kernel/pci_fire.c135
-rw-r--r--arch/sparc64/kernel/pci_impl.h6
-rw-r--r--arch/sparc64/kernel/pci_psycho.c119
-rw-r--r--arch/sparc64/kernel/pci_sabre.c288
-rw-r--r--arch/sparc64/kernel/pci_schizo.c122
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c86
7 files changed, 210 insertions, 740 deletions
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index 76faaa8135dd..f974fefc3ebc 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -14,6 +14,200 @@
14#include <asm/oplib.h> 14#include <asm/oplib.h>
15 15
16#include "pci_impl.h" 16#include "pci_impl.h"
17#include "pci_sun4v.h"
18
19static int config_out_of_range(struct pci_pbm_info *pbm,
20 unsigned long bus,
21 unsigned long devfn,
22 unsigned long reg)
23{
24 if (bus < pbm->pci_first_busno ||
25 bus > pbm->pci_last_busno)
26 return 1;
27 return 0;
28}
29
30static void *sun4u_config_mkaddr(struct pci_pbm_info *pbm,
31 unsigned long bus,
32 unsigned long devfn,
33 unsigned long reg)
34{
35 unsigned long rbits = pbm->config_space_reg_bits;
36
37 if (config_out_of_range(pbm, bus, devfn, reg))
38 return NULL;
39
40 reg = (reg & ((1 << rbits) - 1));
41 devfn <<= rbits;
42 bus <<= rbits + 8;
43
44 return (void *) (pbm->config_space | bus | devfn | reg);
45}
46
47static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
48 int where, int size, u32 *value)
49{
50 struct pci_pbm_info *pbm = bus_dev->sysdata;
51 unsigned char bus = bus_dev->number;
52 u32 *addr;
53 u16 tmp16;
54 u8 tmp8;
55
56 if (bus_dev == pbm->pci_bus && devfn == 0x00)
57 return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
58 size, value);
59
60 switch (size) {
61 case 1:
62 *value = 0xff;
63 break;
64 case 2:
65 *value = 0xffff;
66 break;
67 case 4:
68 *value = 0xffffffff;
69 break;
70 }
71
72 addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
73 if (!addr)
74 return PCIBIOS_SUCCESSFUL;
75
76 switch (size) {
77 case 1:
78 pci_config_read8((u8 *)addr, &tmp8);
79 *value = (u32) tmp8;
80 break;
81
82 case 2:
83 if (where & 0x01) {
84 printk("pci_read_config_word: misaligned reg [%x]\n",
85 where);
86 return PCIBIOS_SUCCESSFUL;
87 }
88 pci_config_read16((u16 *)addr, &tmp16);
89 *value = (u32) tmp16;
90 break;
91
92 case 4:
93 if (where & 0x03) {
94 printk("pci_read_config_dword: misaligned reg [%x]\n",
95 where);
96 return PCIBIOS_SUCCESSFUL;
97 }
98 pci_config_read32(addr, value);
99 break;
100 }
101 return PCIBIOS_SUCCESSFUL;
102}
103
104static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
105 int where, int size, u32 value)
106{
107 struct pci_pbm_info *pbm = bus_dev->sysdata;
108 unsigned char bus = bus_dev->number;
109 u32 *addr;
110
111 if (bus_dev == pbm->pci_bus && devfn == 0x00)
112 return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
113 size, value);
114 addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
115 if (!addr)
116 return PCIBIOS_SUCCESSFUL;
117
118 switch (size) {
119 case 1:
120 pci_config_write8((u8 *)addr, value);
121 break;
122
123 case 2:
124 if (where & 0x01) {
125 printk("pci_write_config_word: misaligned reg [%x]\n",
126 where);
127 return PCIBIOS_SUCCESSFUL;
128 }
129 pci_config_write16((u16 *)addr, value);
130 break;
131
132 case 4:
133 if (where & 0x03) {
134 printk("pci_write_config_dword: misaligned reg [%x]\n",
135 where);
136 return PCIBIOS_SUCCESSFUL;
137 }
138 pci_config_write32(addr, value);
139 }
140 return PCIBIOS_SUCCESSFUL;
141}
142
143struct pci_ops sun4u_pci_ops = {
144 .read = sun4u_read_pci_cfg,
145 .write = sun4u_write_pci_cfg,
146};
147
148static int sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
149 int where, int size, u32 *value)
150{
151 struct pci_pbm_info *pbm = bus_dev->sysdata;
152 u32 devhandle = pbm->devhandle;
153 unsigned int bus = bus_dev->number;
154 unsigned int device = PCI_SLOT(devfn);
155 unsigned int func = PCI_FUNC(devfn);
156 unsigned long ret;
157
158 if (bus_dev == pbm->pci_bus && devfn == 0x00)
159 return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
160 size, value);
161 if (config_out_of_range(pbm, bus, devfn, where)) {
162 ret = ~0UL;
163 } else {
164 ret = pci_sun4v_config_get(devhandle,
165 HV_PCI_DEVICE_BUILD(bus, device, func),
166 where, size);
167 }
168 switch (size) {
169 case 1:
170 *value = ret & 0xff;
171 break;
172 case 2:
173 *value = ret & 0xffff;
174 break;
175 case 4:
176 *value = ret & 0xffffffff;
177 break;
178 };
179
180
181 return PCIBIOS_SUCCESSFUL;
182}
183
184static int sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
185 int where, int size, u32 value)
186{
187 struct pci_pbm_info *pbm = bus_dev->sysdata;
188 u32 devhandle = pbm->devhandle;
189 unsigned int bus = bus_dev->number;
190 unsigned int device = PCI_SLOT(devfn);
191 unsigned int func = PCI_FUNC(devfn);
192 unsigned long ret;
193
194 if (bus_dev == pbm->pci_bus && devfn == 0x00)
195 return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
196 size, value);
197 if (config_out_of_range(pbm, bus, devfn, where)) {
198 /* Do nothing. */
199 } else {
200 ret = pci_sun4v_config_put(devhandle,
201 HV_PCI_DEVICE_BUILD(bus, device, func),
202 where, size, value);
203 }
204 return PCIBIOS_SUCCESSFUL;
205}
206
207struct pci_ops sun4v_pci_ops = {
208 .read = sun4v_read_pci_cfg,
209 .write = sun4v_write_pci_cfg,
210};
17 211
18void pci_get_pbm_props(struct pci_pbm_info *pbm) 212void pci_get_pbm_props(struct pci_pbm_info *pbm)
19{ 213{
diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c
index 2e0eb4ee8f71..9198c1a0f7a5 100644
--- a/arch/sparc64/kernel/pci_fire.c
+++ b/arch/sparc64/kernel/pci_fire.c
@@ -27,138 +27,6 @@
27 "i" (ASI_PHYS_BYPASS_EC_E) \ 27 "i" (ASI_PHYS_BYPASS_EC_E) \
28 : "memory") 28 : "memory")
29 29
30/* Fire config space address format is nearly identical to
31 * that of SCHIZO and PSYCHO, except that in order to accomodate
32 * PCI-E extended config space the encoding can handle 12 bits
33 * of register address:
34 *
35 * 32 28 27 20 19 15 14 12 11 2 1 0
36 * -------------------------------------------------
37 * |0 0 0 0 0| bus | device | function | reg | 0 0 |
38 * -------------------------------------------------
39 */
40#define FIRE_CONFIG_BASE(PBM) ((PBM)->config_space)
41#define FIRE_CONFIG_ENCODE(BUS, DEVFN, REG) \
42 (((unsigned long)(BUS) << 20) | \
43 ((unsigned long)(DEVFN) << 12) | \
44 ((unsigned long)(REG)))
45
46static void *fire_pci_config_mkaddr(struct pci_pbm_info *pbm,
47 unsigned char bus,
48 unsigned int devfn,
49 int where)
50{
51 if (!pbm)
52 return NULL;
53 return (void *)
54 (FIRE_CONFIG_BASE(pbm) |
55 FIRE_CONFIG_ENCODE(bus, devfn, where));
56}
57
58/* FIRE PCI configuration space accessors. */
59
60static int fire_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
61 int where, int size, u32 *value)
62{
63 struct pci_pbm_info *pbm = bus_dev->sysdata;
64 unsigned char bus = bus_dev->number;
65 u32 *addr;
66 u16 tmp16;
67 u8 tmp8;
68
69 if (bus_dev == pbm->pci_bus && devfn == 0x00)
70 return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
71 size, value);
72 switch (size) {
73 case 1:
74 *value = 0xff;
75 break;
76 case 2:
77 *value = 0xffff;
78 break;
79 case 4:
80 *value = 0xffffffff;
81 break;
82 }
83
84 addr = fire_pci_config_mkaddr(pbm, bus, devfn, where);
85 if (!addr)
86 return PCIBIOS_SUCCESSFUL;
87
88 switch (size) {
89 case 1:
90 pci_config_read8((u8 *)addr, &tmp8);
91 *value = tmp8;
92 break;
93
94 case 2:
95 if (where & 0x01) {
96 printk("pci_read_config_word: misaligned reg [%x]\n",
97 where);
98 return PCIBIOS_SUCCESSFUL;
99 }
100 pci_config_read16((u16 *)addr, &tmp16);
101 *value = tmp16;
102 break;
103
104 case 4:
105 if (where & 0x03) {
106 printk("pci_read_config_dword: misaligned reg [%x]\n",
107 where);
108 return PCIBIOS_SUCCESSFUL;
109 }
110
111 pci_config_read32(addr, value);
112 break;
113 }
114 return PCIBIOS_SUCCESSFUL;
115}
116
117static int fire_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
118 int where, int size, u32 value)
119{
120 struct pci_pbm_info *pbm = bus_dev->sysdata;
121 unsigned char bus = bus_dev->number;
122 u32 *addr;
123
124 if (bus_dev == pbm->pci_bus && devfn == 0x00)
125 return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
126 size, value);
127 addr = fire_pci_config_mkaddr(pbm, bus, devfn, where);
128 if (!addr)
129 return PCIBIOS_SUCCESSFUL;
130
131 switch (size) {
132 case 1:
133 pci_config_write8((u8 *)addr, value);
134 break;
135
136 case 2:
137 if (where & 0x01) {
138 printk("pci_write_config_word: misaligned reg [%x]\n",
139 where);
140 return PCIBIOS_SUCCESSFUL;
141 }
142 pci_config_write16((u16 *)addr, value);
143 break;
144
145 case 4:
146 if (where & 0x03) {
147 printk("pci_write_config_dword: misaligned reg [%x]\n",
148 where);
149 return PCIBIOS_SUCCESSFUL;
150 }
151
152 pci_config_write32(addr, value);
153 }
154 return PCIBIOS_SUCCESSFUL;
155}
156
157static struct pci_ops pci_fire_ops = {
158 .read = fire_read_pci_cfg,
159 .write = fire_write_pci_cfg,
160};
161
162static void pci_fire_scan_bus(struct pci_pbm_info *pbm) 30static void pci_fire_scan_bus(struct pci_pbm_info *pbm)
163{ 31{
164 pbm->pci_bus = pci_scan_one_pbm(pbm); 32 pbm->pci_bus = pci_scan_one_pbm(pbm);
@@ -314,7 +182,8 @@ static void pci_fire_pbm_init(struct pci_controller_info *p,
314 pci_pbm_root = pbm; 182 pci_pbm_root = pbm;
315 183
316 pbm->scan_bus = pci_fire_scan_bus; 184 pbm->scan_bus = pci_fire_scan_bus;
317 pbm->pci_ops = &pci_fire_ops; 185 pbm->pci_ops = &sun4u_pci_ops;
186 pbm->config_space_reg_bits = 12;
318 187
319 pbm->index = pci_num_pbms++; 188 pbm->index = pci_num_pbms++;
320 189
diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h
index 8e38023868aa..f660c2b685eb 100644
--- a/arch/sparc64/kernel/pci_impl.h
+++ b/arch/sparc64/kernel/pci_impl.h
@@ -77,6 +77,9 @@ struct pci_pbm_info {
77 /* Base of PCI Config space, can be per-PBM or shared. */ 77 /* Base of PCI Config space, can be per-PBM or shared. */
78 unsigned long config_space; 78 unsigned long config_space;
79 79
80 /* This will be 12 on PCI-E controllers, 8 elsewhere. */
81 unsigned long config_space_reg_bits;
82
80 /* State of 66MHz capabilities on this PBM. */ 83 /* State of 66MHz capabilities on this PBM. */
81 int is_66mhz_capable; 84 int is_66mhz_capable;
82 int all_devs_66mhz; 85 int all_devs_66mhz;
@@ -156,4 +159,7 @@ extern void pci_config_write8(u8 *addr, u8 val);
156extern void pci_config_write16(u16 *addr, u16 val); 159extern void pci_config_write16(u16 *addr, u16 val);
157extern void pci_config_write32(u32 *addr, u32 val); 160extern void pci_config_write32(u32 *addr, u32 val);
158 161
162extern struct pci_ops sun4u_pci_ops;
163extern struct pci_ops sun4v_pci_ops;
164
159#endif /* !(PCI_IMPL_H) */ 165#endif /* !(PCI_IMPL_H) */
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index 2edcb1dd13c3..598393a2df16 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -94,122 +94,6 @@ static void *psycho_pci_config_mkaddr(struct pci_pbm_info *pbm,
94 PSYCHO_CONFIG_ENCODE(bus, devfn, where)); 94 PSYCHO_CONFIG_ENCODE(bus, devfn, where));
95} 95}
96 96
97static int psycho_out_of_range(struct pci_pbm_info *pbm,
98 unsigned char bus,
99 unsigned char devfn)
100{
101 return ((bus == pbm->pci_first_busno) &&
102 PCI_SLOT(devfn) > 8);
103}
104
105/* PSYCHO PCI configuration space accessors. */
106
107static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
108 int where, int size, u32 *value)
109{
110 struct pci_pbm_info *pbm = bus_dev->sysdata;
111 unsigned char bus = bus_dev->number;
112 u32 *addr;
113 u16 tmp16;
114 u8 tmp8;
115
116 if (bus_dev == pbm->pci_bus && devfn == 0x00)
117 return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
118 size, value);
119
120 switch (size) {
121 case 1:
122 *value = 0xff;
123 break;
124 case 2:
125 *value = 0xffff;
126 break;
127 case 4:
128 *value = 0xffffffff;
129 break;
130 }
131
132 addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
133 if (!addr)
134 return PCIBIOS_SUCCESSFUL;
135
136 if (psycho_out_of_range(pbm, bus, devfn))
137 return PCIBIOS_SUCCESSFUL;
138 switch (size) {
139 case 1:
140 pci_config_read8((u8 *)addr, &tmp8);
141 *value = (u32) tmp8;
142 break;
143
144 case 2:
145 if (where & 0x01) {
146 printk("pci_read_config_word: misaligned reg [%x]\n",
147 where);
148 return PCIBIOS_SUCCESSFUL;
149 }
150 pci_config_read16((u16 *)addr, &tmp16);
151 *value = (u32) tmp16;
152 break;
153
154 case 4:
155 if (where & 0x03) {
156 printk("pci_read_config_dword: misaligned reg [%x]\n",
157 where);
158 return PCIBIOS_SUCCESSFUL;
159 }
160 pci_config_read32(addr, value);
161 break;
162 }
163 return PCIBIOS_SUCCESSFUL;
164}
165
166static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
167 int where, int size, u32 value)
168{
169 struct pci_pbm_info *pbm = bus_dev->sysdata;
170 unsigned char bus = bus_dev->number;
171 u32 *addr;
172
173 if (bus_dev == pbm->pci_bus && devfn == 0x00)
174 return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
175 size, value);
176 addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
177 if (!addr)
178 return PCIBIOS_SUCCESSFUL;
179
180 if (psycho_out_of_range(pbm, bus, devfn))
181 return PCIBIOS_SUCCESSFUL;
182
183 switch (size) {
184 case 1:
185 pci_config_write8((u8 *)addr, value);
186 break;
187
188 case 2:
189 if (where & 0x01) {
190 printk("pci_write_config_word: misaligned reg [%x]\n",
191 where);
192 return PCIBIOS_SUCCESSFUL;
193 }
194 pci_config_write16((u16 *)addr, value);
195 break;
196
197 case 4:
198 if (where & 0x03) {
199 printk("pci_write_config_dword: misaligned reg [%x]\n",
200 where);
201 return PCIBIOS_SUCCESSFUL;
202 }
203 pci_config_write32(addr, value);
204 }
205 return PCIBIOS_SUCCESSFUL;
206}
207
208static struct pci_ops psycho_ops = {
209 .read = psycho_read_pci_cfg,
210 .write = psycho_write_pci_cfg,
211};
212
213/* PSYCHO error handling support. */ 97/* PSYCHO error handling support. */
214enum psycho_error_type { 98enum psycho_error_type {
215 UE_ERR, CE_ERR, PCI_ERR 99 UE_ERR, CE_ERR, PCI_ERR
@@ -1089,7 +973,8 @@ static void psycho_pbm_init(struct pci_controller_info *p,
1089 pci_pbm_root = pbm; 973 pci_pbm_root = pbm;
1090 974
1091 pbm->scan_bus = psycho_scan_bus; 975 pbm->scan_bus = psycho_scan_bus;
1092 pbm->pci_ops = &psycho_ops; 976 pbm->pci_ops = &sun4u_pci_ops;
977 pbm->config_space_reg_bits = 8;
1093 978
1094 pbm->index = pci_num_pbms++; 979 pbm->index = pci_num_pbms++;
1095 980
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 4cefe6e83b24..e2377796de89 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -205,294 +205,9 @@
205#define SABRE_MEMSPACE 0x100000000UL 205#define SABRE_MEMSPACE 0x100000000UL
206#define SABRE_MEMSPACE_SIZE 0x07fffffffUL 206#define SABRE_MEMSPACE_SIZE 0x07fffffffUL
207 207
208/* UltraSparc-IIi Programmer's Manual, page 325, PCI
209 * configuration space address format:
210 *
211 * 32 24 23 16 15 11 10 8 7 2 1 0
212 * ---------------------------------------------------------
213 * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 |
214 * ---------------------------------------------------------
215 */
216#define SABRE_CONFIG_BASE(PBM) \
217 ((PBM)->config_space | (1UL << 24))
218#define SABRE_CONFIG_ENCODE(BUS, DEVFN, REG) \
219 (((unsigned long)(BUS) << 16) | \
220 ((unsigned long)(DEVFN) << 8) | \
221 ((unsigned long)(REG)))
222
223static int hummingbird_p; 208static int hummingbird_p;
224static struct pci_bus *sabre_root_bus; 209static struct pci_bus *sabre_root_bus;
225 210
226static void *sabre_pci_config_mkaddr(struct pci_pbm_info *pbm,
227 unsigned char bus,
228 unsigned int devfn,
229 int where)
230{
231 if (!pbm)
232 return NULL;
233 return (void *)
234 (SABRE_CONFIG_BASE(pbm) |
235 SABRE_CONFIG_ENCODE(bus, devfn, where));
236}
237
238static int sabre_out_of_range(unsigned char devfn)
239{
240 if (hummingbird_p)
241 return 0;
242
243 return (((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) ||
244 ((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) > 1)) ||
245 (PCI_SLOT(devfn) > 1));
246}
247
248static int __sabre_out_of_range(struct pci_pbm_info *pbm,
249 unsigned char bus,
250 unsigned char devfn)
251{
252 if (hummingbird_p)
253 return 0;
254
255 return ((pbm->parent == 0) ||
256 ((pbm == &pbm->parent->pbm_A) &&
257 (bus == pbm->pci_first_busno) &&
258 PCI_SLOT(devfn) > 8));
259}
260
261static int __sabre_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
262 int where, int size, u32 *value)
263{
264 struct pci_pbm_info *pbm = bus_dev->sysdata;
265 unsigned char bus = bus_dev->number;
266 u32 *addr;
267 u16 tmp16;
268 u8 tmp8;
269
270 switch (size) {
271 case 1:
272 *value = 0xff;
273 break;
274 case 2:
275 *value = 0xffff;
276 break;
277 case 4:
278 *value = 0xffffffff;
279 break;
280 }
281
282 addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
283 if (!addr)
284 return PCIBIOS_SUCCESSFUL;
285
286 if (__sabre_out_of_range(pbm, bus, devfn))
287 return PCIBIOS_SUCCESSFUL;
288
289 switch (size) {
290 case 1:
291 pci_config_read8((u8 *) addr, &tmp8);
292 *value = tmp8;
293 break;
294
295 case 2:
296 if (where & 0x01) {
297 printk("pci_read_config_word: misaligned reg [%x]\n",
298 where);
299 return PCIBIOS_SUCCESSFUL;
300 }
301 pci_config_read16((u16 *) addr, &tmp16);
302 *value = tmp16;
303 break;
304
305 case 4:
306 if (where & 0x03) {
307 printk("pci_read_config_dword: misaligned reg [%x]\n",
308 where);
309 return PCIBIOS_SUCCESSFUL;
310 }
311 pci_config_read32(addr, value);
312 break;
313 }
314
315 return PCIBIOS_SUCCESSFUL;
316}
317
318static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn,
319 int where, int size, u32 *value)
320{
321 struct pci_pbm_info *pbm = bus->sysdata;
322
323 if (bus == pbm->pci_bus && devfn == 0x00)
324 return pci_host_bridge_read_pci_cfg(bus, devfn, where,
325 size, value);
326
327 if (!bus->number && sabre_out_of_range(devfn)) {
328 switch (size) {
329 case 1:
330 *value = 0xff;
331 break;
332 case 2:
333 *value = 0xffff;
334 break;
335 case 4:
336 *value = 0xffffffff;
337 break;
338 }
339 return PCIBIOS_SUCCESSFUL;
340 }
341
342 if (bus->number || PCI_SLOT(devfn))
343 return __sabre_read_pci_cfg(bus, devfn, where, size, value);
344
345 /* When accessing PCI config space of the PCI controller itself (bus
346 * 0, device slot 0, function 0) there are restrictions. Each
347 * register must be accessed as it's natural size. Thus, for example
348 * the Vendor ID must be accessed as a 16-bit quantity.
349 */
350
351 switch (size) {
352 case 1:
353 if (where < 8) {
354 u32 tmp32;
355 u16 tmp16;
356
357 __sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32);
358 tmp16 = (u16) tmp32;
359 if (where & 1)
360 *value = tmp16 >> 8;
361 else
362 *value = tmp16 & 0xff;
363 } else
364 return __sabre_read_pci_cfg(bus, devfn, where, 1, value);
365 break;
366
367 case 2:
368 if (where < 8)
369 return __sabre_read_pci_cfg(bus, devfn, where, 2, value);
370 else {
371 u32 tmp32;
372 u8 tmp8;
373
374 __sabre_read_pci_cfg(bus, devfn, where, 1, &tmp32);
375 tmp8 = (u8) tmp32;
376 *value = tmp8;
377 __sabre_read_pci_cfg(bus, devfn, where + 1, 1, &tmp32);
378 tmp8 = (u8) tmp32;
379 *value |= tmp8 << 8;
380 }
381 break;
382
383 case 4: {
384 u32 tmp32;
385 u16 tmp16;
386
387 sabre_read_pci_cfg(bus, devfn, where, 2, &tmp32);
388 tmp16 = (u16) tmp32;
389 *value = tmp16;
390 sabre_read_pci_cfg(bus, devfn, where + 2, 2, &tmp32);
391 tmp16 = (u16) tmp32;
392 *value |= tmp16 << 16;
393 break;
394 }
395 }
396 return PCIBIOS_SUCCESSFUL;
397}
398
399static int __sabre_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
400 int where, int size, u32 value)
401{
402 struct pci_pbm_info *pbm = bus_dev->sysdata;
403 unsigned char bus = bus_dev->number;
404 u32 *addr;
405
406 addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
407 if (!addr)
408 return PCIBIOS_SUCCESSFUL;
409
410 if (__sabre_out_of_range(pbm, bus, devfn))
411 return PCIBIOS_SUCCESSFUL;
412
413 switch (size) {
414 case 1:
415 pci_config_write8((u8 *) addr, value);
416 break;
417
418 case 2:
419 if (where & 0x01) {
420 printk("pci_write_config_word: misaligned reg [%x]\n",
421 where);
422 return PCIBIOS_SUCCESSFUL;
423 }
424 pci_config_write16((u16 *) addr, value);
425 break;
426
427 case 4:
428 if (where & 0x03) {
429 printk("pci_write_config_dword: misaligned reg [%x]\n",
430 where);
431 return PCIBIOS_SUCCESSFUL;
432 }
433 pci_config_write32(addr, value);
434 break;
435 }
436
437 return PCIBIOS_SUCCESSFUL;
438}
439
440static int sabre_write_pci_cfg(struct pci_bus *bus, unsigned int devfn,
441 int where, int size, u32 value)
442{
443 struct pci_pbm_info *pbm = bus->sysdata;
444
445 if (bus == pbm->pci_bus && devfn == 0x00)
446 return pci_host_bridge_write_pci_cfg(bus, devfn, where,
447 size, value);
448
449 if (bus->number)
450 return __sabre_write_pci_cfg(bus, devfn, where, size, value);
451
452 if (sabre_out_of_range(devfn))
453 return PCIBIOS_SUCCESSFUL;
454
455 switch (size) {
456 case 1:
457 if (where < 8) {
458 u32 tmp32;
459 u16 tmp16;
460
461 __sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32);
462 tmp16 = (u16) tmp32;
463 if (where & 1) {
464 value &= 0x00ff;
465 value |= tmp16 << 8;
466 } else {
467 value &= 0xff00;
468 value |= tmp16;
469 }
470 tmp32 = (u32) tmp16;
471 return __sabre_write_pci_cfg(bus, devfn, where & ~1, 2, tmp32);
472 } else
473 return __sabre_write_pci_cfg(bus, devfn, where, 1, value);
474 break;
475 case 2:
476 if (where < 8)
477 return __sabre_write_pci_cfg(bus, devfn, where, 2, value);
478 else {
479 __sabre_write_pci_cfg(bus, devfn, where, 1, value & 0xff);
480 __sabre_write_pci_cfg(bus, devfn, where + 1, 1, value >> 8);
481 }
482 break;
483 case 4:
484 sabre_write_pci_cfg(bus, devfn, where, 2, value & 0xffff);
485 sabre_write_pci_cfg(bus, devfn, where + 2, 2, value >> 16);
486 break;
487 }
488 return PCIBIOS_SUCCESSFUL;
489}
490
491static struct pci_ops sabre_ops = {
492 .read = sabre_read_pci_cfg,
493 .write = sabre_write_pci_cfg,
494};
495
496/* SABRE error handling support. */ 211/* SABRE error handling support. */
497static void sabre_check_iommu_error(struct pci_pbm_info *pbm, 212static void sabre_check_iommu_error(struct pci_pbm_info *pbm,
498 unsigned long afsr, 213 unsigned long afsr,
@@ -1010,7 +725,8 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct pci_pbm_info *p
1010 printk("%s: SABRE PCI Bus Module\n", pbm->name); 725 printk("%s: SABRE PCI Bus Module\n", pbm->name);
1011 726
1012 pbm->scan_bus = sabre_scan_bus; 727 pbm->scan_bus = sabre_scan_bus;
1013 pbm->pci_ops = &sabre_ops; 728 pbm->pci_ops = &sun4u_pci_ops;
729 pbm->config_space_reg_bits = 8;
1014 730
1015 pbm->index = pci_num_pbms++; 731 pbm->index = pci_num_pbms++;
1016 732
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index e375d72b8eed..ae76898bbe2b 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -104,125 +104,6 @@ static void *schizo_pci_config_mkaddr(struct pci_pbm_info *pbm,
104 SCHIZO_CONFIG_ENCODE(bus, devfn, where)); 104 SCHIZO_CONFIG_ENCODE(bus, devfn, where));
105} 105}
106 106
107/* Just make sure the bus number is in range. */
108static int schizo_out_of_range(struct pci_pbm_info *pbm,
109 unsigned char bus,
110 unsigned char devfn)
111{
112 if (bus < pbm->pci_first_busno ||
113 bus > pbm->pci_last_busno)
114 return 1;
115 return 0;
116}
117
118/* SCHIZO PCI configuration space accessors. */
119
120static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
121 int where, int size, u32 *value)
122{
123 struct pci_pbm_info *pbm = bus_dev->sysdata;
124 unsigned char bus = bus_dev->number;
125 u32 *addr;
126 u16 tmp16;
127 u8 tmp8;
128
129 if (bus_dev == pbm->pci_bus && devfn == 0x00)
130 return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
131 size, value);
132 switch (size) {
133 case 1:
134 *value = 0xff;
135 break;
136 case 2:
137 *value = 0xffff;
138 break;
139 case 4:
140 *value = 0xffffffff;
141 break;
142 }
143
144 addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);
145 if (!addr)
146 return PCIBIOS_SUCCESSFUL;
147
148 if (schizo_out_of_range(pbm, bus, devfn))
149 return PCIBIOS_SUCCESSFUL;
150 switch (size) {
151 case 1:
152 pci_config_read8((u8 *)addr, &tmp8);
153 *value = tmp8;
154 break;
155
156 case 2:
157 if (where & 0x01) {
158 printk("pci_read_config_word: misaligned reg [%x]\n",
159 where);
160 return PCIBIOS_SUCCESSFUL;
161 }
162 pci_config_read16((u16 *)addr, &tmp16);
163 *value = tmp16;
164 break;
165
166 case 4:
167 if (where & 0x03) {
168 printk("pci_read_config_dword: misaligned reg [%x]\n",
169 where);
170 return PCIBIOS_SUCCESSFUL;
171 }
172 pci_config_read32(addr, value);
173 break;
174 }
175 return PCIBIOS_SUCCESSFUL;
176}
177
178static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
179 int where, int size, u32 value)
180{
181 struct pci_pbm_info *pbm = bus_dev->sysdata;
182 unsigned char bus = bus_dev->number;
183 u32 *addr;
184
185 if (bus_dev == pbm->pci_bus && devfn == 0x00)
186 return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
187 size, value);
188 addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);
189 if (!addr)
190 return PCIBIOS_SUCCESSFUL;
191
192 if (schizo_out_of_range(pbm, bus, devfn))
193 return PCIBIOS_SUCCESSFUL;
194
195 switch (size) {
196 case 1:
197 pci_config_write8((u8 *)addr, value);
198 break;
199
200 case 2:
201 if (where & 0x01) {
202 printk("pci_write_config_word: misaligned reg [%x]\n",
203 where);
204 return PCIBIOS_SUCCESSFUL;
205 }
206 pci_config_write16((u16 *)addr, value);
207 break;
208
209 case 4:
210 if (where & 0x03) {
211 printk("pci_write_config_dword: misaligned reg [%x]\n",
212 where);
213 return PCIBIOS_SUCCESSFUL;
214 }
215
216 pci_config_write32(addr, value);
217 }
218 return PCIBIOS_SUCCESSFUL;
219}
220
221static struct pci_ops schizo_ops = {
222 .read = schizo_read_pci_cfg,
223 .write = schizo_write_pci_cfg,
224};
225
226/* SCHIZO error handling support. */ 107/* SCHIZO error handling support. */
227enum schizo_error_type { 108enum schizo_error_type {
228 UE_ERR, CE_ERR, PCI_ERR, SAFARI_ERR 109 UE_ERR, CE_ERR, PCI_ERR, SAFARI_ERR
@@ -1494,7 +1375,8 @@ static void schizo_pbm_init(struct pci_controller_info *p,
1494 pci_pbm_root = pbm; 1375 pci_pbm_root = pbm;
1495 1376
1496 pbm->scan_bus = schizo_scan_bus; 1377 pbm->scan_bus = schizo_scan_bus;
1497 pbm->pci_ops = &schizo_ops; 1378 pbm->pci_ops = &sun4u_pci_ops;
1379 pbm->config_space_reg_bits = 8;
1498 1380
1499 pbm->index = pci_num_pbms++; 1381 pbm->index = pci_num_pbms++;
1500 1382
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 0c76a8891a96..34df4047587a 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -593,89 +593,6 @@ const struct pci_iommu_ops pci_sun4v_iommu_ops = {
593 .dma_sync_sg_for_cpu = pci_4v_dma_sync_sg_for_cpu, 593 .dma_sync_sg_for_cpu = pci_4v_dma_sync_sg_for_cpu,
594}; 594};
595 595
596static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func)
597{
598 if (bus < pbm->pci_first_busno ||
599 bus > pbm->pci_last_busno)
600 return 1;
601 return 0;
602}
603
604static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
605 int where, int size, u32 *value)
606{
607 struct pci_pbm_info *pbm = bus_dev->sysdata;
608 u32 devhandle = pbm->devhandle;
609 unsigned int bus = bus_dev->number;
610 unsigned int device = PCI_SLOT(devfn);
611 unsigned int func = PCI_FUNC(devfn);
612 unsigned long ret;
613
614 if (bus_dev == pbm->pci_bus && devfn == 0x00)
615 return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
616 size, value);
617 if (pci_sun4v_out_of_range(pbm, bus, device, func)) {
618 ret = ~0UL;
619 } else {
620 ret = pci_sun4v_config_get(devhandle,
621 HV_PCI_DEVICE_BUILD(bus, device, func),
622 where, size);
623#if 0
624 printk("rcfg: [%x:%x:%x:%d]=[%lx]\n",
625 devhandle, HV_PCI_DEVICE_BUILD(bus, device, func),
626 where, size, ret);
627#endif
628 }
629 switch (size) {
630 case 1:
631 *value = ret & 0xff;
632 break;
633 case 2:
634 *value = ret & 0xffff;
635 break;
636 case 4:
637 *value = ret & 0xffffffff;
638 break;
639 };
640
641
642 return PCIBIOS_SUCCESSFUL;
643}
644
645static int pci_sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
646 int where, int size, u32 value)
647{
648 struct pci_pbm_info *pbm = bus_dev->sysdata;
649 u32 devhandle = pbm->devhandle;
650 unsigned int bus = bus_dev->number;
651 unsigned int device = PCI_SLOT(devfn);
652 unsigned int func = PCI_FUNC(devfn);
653 unsigned long ret;
654
655 if (bus_dev == pbm->pci_bus && devfn == 0x00)
656 return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
657 size, value);
658 if (pci_sun4v_out_of_range(pbm, bus, device, func)) {
659 /* Do nothing. */
660 } else {
661 ret = pci_sun4v_config_put(devhandle,
662 HV_PCI_DEVICE_BUILD(bus, device, func),
663 where, size, value);
664#if 0
665 printk("wcfg: [%x:%x:%x:%d] v[%x] == [%lx]\n",
666 devhandle, HV_PCI_DEVICE_BUILD(bus, device, func),
667 where, size, value, ret);
668#endif
669 }
670 return PCIBIOS_SUCCESSFUL;
671}
672
673static struct pci_ops pci_sun4v_ops = {
674 .read = pci_sun4v_read_pci_cfg,
675 .write = pci_sun4v_write_pci_cfg,
676};
677
678
679static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm) 596static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm)
680{ 597{
681 struct property *prop; 598 struct property *prop;
@@ -1238,7 +1155,8 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
1238 pci_pbm_root = pbm; 1155 pci_pbm_root = pbm;
1239 1156
1240 pbm->scan_bus = pci_sun4v_scan_bus; 1157 pbm->scan_bus = pci_sun4v_scan_bus;
1241 pbm->pci_ops = &pci_sun4v_ops; 1158 pbm->pci_ops = &sun4v_pci_ops;
1159 pbm->config_space_reg_bits = 12;
1242 1160
1243 pbm->index = pci_num_pbms++; 1161 pbm->index = pci_num_pbms++;
1244 1162