diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-05-09 05:35:27 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-05-09 05:35:27 -0400 |
commit | ca3dd88e411648c76e1911a729440e3763ba5049 (patch) | |
tree | e874ed0c1e91269aa514a443358d4f3738bcb244 /arch/sparc64/kernel | |
parent | de372ecd80a42c4fb485c7232475301a18d05184 (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>
Diffstat (limited to 'arch/sparc64/kernel')
-rw-r--r-- | arch/sparc64/kernel/pci_common.c | 194 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_fire.c | 135 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_impl.h | 6 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_psycho.c | 119 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sabre.c | 288 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_schizo.c | 122 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 86 |
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 | |||
19 | static 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 | |||
30 | static 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 | |||
47 | static 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 | |||
104 | static 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 | |||
143 | struct pci_ops sun4u_pci_ops = { | ||
144 | .read = sun4u_read_pci_cfg, | ||
145 | .write = sun4u_write_pci_cfg, | ||
146 | }; | ||
147 | |||
148 | static 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 | |||
184 | static 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 | |||
207 | struct pci_ops sun4v_pci_ops = { | ||
208 | .read = sun4v_read_pci_cfg, | ||
209 | .write = sun4v_write_pci_cfg, | ||
210 | }; | ||
17 | 211 | ||
18 | void pci_get_pbm_props(struct pci_pbm_info *pbm) | 212 | void 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 | |||
46 | static 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 | |||
60 | static 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 | |||
117 | static 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 | |||
157 | static struct pci_ops pci_fire_ops = { | ||
158 | .read = fire_read_pci_cfg, | ||
159 | .write = fire_write_pci_cfg, | ||
160 | }; | ||
161 | |||
162 | static void pci_fire_scan_bus(struct pci_pbm_info *pbm) | 30 | static 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); | |||
156 | extern void pci_config_write16(u16 *addr, u16 val); | 159 | extern void pci_config_write16(u16 *addr, u16 val); |
157 | extern void pci_config_write32(u32 *addr, u32 val); | 160 | extern void pci_config_write32(u32 *addr, u32 val); |
158 | 161 | ||
162 | extern struct pci_ops sun4u_pci_ops; | ||
163 | extern 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 | ||
97 | static 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 | |||
107 | static 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 | |||
166 | static 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 | |||
208 | static 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. */ |
214 | enum psycho_error_type { | 98 | enum 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 | |||
223 | static int hummingbird_p; | 208 | static int hummingbird_p; |
224 | static struct pci_bus *sabre_root_bus; | 209 | static struct pci_bus *sabre_root_bus; |
225 | 210 | ||
226 | static 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 | |||
238 | static 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 | |||
248 | static 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 | |||
261 | static 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 | |||
318 | static 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 | |||
399 | static 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 | |||
440 | static 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 | |||
491 | static 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. */ |
497 | static void sabre_check_iommu_error(struct pci_pbm_info *pbm, | 212 | static 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. */ | ||
108 | static 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 | |||
120 | static 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 | |||
178 | static 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 | |||
221 | static 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. */ |
227 | enum schizo_error_type { | 108 | enum 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 | ||
596 | static 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 | |||
604 | static 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 | |||
645 | static 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 | |||
673 | static struct pci_ops pci_sun4v_ops = { | ||
674 | .read = pci_sun4v_read_pci_cfg, | ||
675 | .write = pci_sun4v_write_pci_cfg, | ||
676 | }; | ||
677 | |||
678 | |||
679 | static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm) | 596 | static 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 | ||