aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/maple/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/maple/pci.c')
-rw-r--r--arch/powerpc/platforms/maple/pci.c70
1 files changed, 42 insertions, 28 deletions
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 63a1670d3bfd..c3aa46b8e2b9 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -38,16 +38,16 @@ static struct pci_controller *u3_agp, *u3_ht;
38static int __init fixup_one_level_bus_range(struct device_node *node, int higher) 38static int __init fixup_one_level_bus_range(struct device_node *node, int higher)
39{ 39{
40 for (; node != 0;node = node->sibling) { 40 for (; node != 0;node = node->sibling) {
41 int * bus_range; 41 const int *bus_range;
42 unsigned int *class_code; 42 const unsigned int *class_code;
43 int len; 43 int len;
44 44
45 /* For PCI<->PCI bridges or CardBus bridges, we go down */ 45 /* For PCI<->PCI bridges or CardBus bridges, we go down */
46 class_code = (unsigned int *) get_property(node, "class-code", NULL); 46 class_code = get_property(node, "class-code", NULL);
47 if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && 47 if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
48 (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) 48 (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
49 continue; 49 continue;
50 bus_range = (int *) get_property(node, "bus-range", &len); 50 bus_range = get_property(node, "bus-range", &len);
51 if (bus_range != NULL && len > 2 * sizeof(int)) { 51 if (bus_range != NULL && len > 2 * sizeof(int)) {
52 if (bus_range[1] > higher) 52 if (bus_range[1] > higher)
53 higher = bus_range[1]; 53 higher = bus_range[1];
@@ -65,30 +65,36 @@ static int __init fixup_one_level_bus_range(struct device_node *node, int higher
65 */ 65 */
66static void __init fixup_bus_range(struct device_node *bridge) 66static void __init fixup_bus_range(struct device_node *bridge)
67{ 67{
68 int * bus_range; 68 int *bus_range;
69 struct property *prop;
69 int len; 70 int len;
70 71
71 /* Lookup the "bus-range" property for the hose */ 72 /* Lookup the "bus-range" property for the hose */
72 bus_range = (int *) get_property(bridge, "bus-range", &len); 73 prop = of_find_property(bridge, "bus-range", &len);
73 if (bus_range == NULL || len < 2 * sizeof(int)) { 74 if (prop == NULL || prop->value == NULL || len < 2 * sizeof(int)) {
74 printk(KERN_WARNING "Can't get bus-range for %s\n", 75 printk(KERN_WARNING "Can't get bus-range for %s\n",
75 bridge->full_name); 76 bridge->full_name);
76 return; 77 return;
77 } 78 }
79 bus_range = (int *)prop->value;
78 bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]); 80 bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
79} 81}
80 82
81 83
82#define U3_AGP_CFA0(devfn, off) \ 84static unsigned long u3_agp_cfa0(u8 devfn, u8 off)
83 ((1 << (unsigned long)PCI_SLOT(dev_fn)) \ 85{
84 | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \ 86 return (1 << (unsigned long)PCI_SLOT(devfn)) |
85 | (((unsigned long)(off)) & 0xFCUL)) 87 ((unsigned long)PCI_FUNC(devfn) << 8) |
88 ((unsigned long)off & 0xFCUL);
89}
86 90
87#define U3_AGP_CFA1(bus, devfn, off) \ 91static unsigned long u3_agp_cfa1(u8 bus, u8 devfn, u8 off)
88 ((((unsigned long)(bus)) << 16) \ 92{
89 |(((unsigned long)(devfn)) << 8) \ 93 return ((unsigned long)bus << 16) |
90 |(((unsigned long)(off)) & 0xFCUL) \ 94 ((unsigned long)devfn << 8) |
91 |1UL) 95 ((unsigned long)off & 0xFCUL) |
96 1UL;
97}
92 98
93static unsigned long u3_agp_cfg_access(struct pci_controller* hose, 99static unsigned long u3_agp_cfg_access(struct pci_controller* hose,
94 u8 bus, u8 dev_fn, u8 offset) 100 u8 bus, u8 dev_fn, u8 offset)
@@ -98,9 +104,9 @@ static unsigned long u3_agp_cfg_access(struct pci_controller* hose,
98 if (bus == hose->first_busno) { 104 if (bus == hose->first_busno) {
99 if (dev_fn < (11 << 3)) 105 if (dev_fn < (11 << 3))
100 return 0; 106 return 0;
101 caddr = U3_AGP_CFA0(dev_fn, offset); 107 caddr = u3_agp_cfa0(dev_fn, offset);
102 } else 108 } else
103 caddr = U3_AGP_CFA1(bus, dev_fn, offset); 109 caddr = u3_agp_cfa1(bus, dev_fn, offset);
104 110
105 /* Uninorth will return garbage if we don't read back the value ! */ 111 /* Uninorth will return garbage if we don't read back the value ! */
106 do { 112 do {
@@ -182,13 +188,15 @@ static struct pci_ops u3_agp_pci_ops =
182 u3_agp_write_config 188 u3_agp_write_config
183}; 189};
184 190
191static unsigned long u3_ht_cfa0(u8 devfn, u8 off)
192{
193 return (devfn << 8) | off;
194}
185 195
186#define U3_HT_CFA0(devfn, off) \ 196static unsigned long u3_ht_cfa1(u8 bus, u8 devfn, u8 off)
187 ((((unsigned long)devfn) << 8) | offset) 197{
188#define U3_HT_CFA1(bus, devfn, off) \ 198 return u3_ht_cfa0(devfn, off) + (bus << 16) + 0x01000000UL;
189 (U3_HT_CFA0(devfn, off) \ 199}
190 + (((unsigned long)bus) << 16) \
191 + 0x01000000UL)
192 200
193static unsigned long u3_ht_cfg_access(struct pci_controller* hose, 201static unsigned long u3_ht_cfg_access(struct pci_controller* hose,
194 u8 bus, u8 devfn, u8 offset) 202 u8 bus, u8 devfn, u8 offset)
@@ -196,9 +204,9 @@ static unsigned long u3_ht_cfg_access(struct pci_controller* hose,
196 if (bus == hose->first_busno) { 204 if (bus == hose->first_busno) {
197 if (PCI_SLOT(devfn) == 0) 205 if (PCI_SLOT(devfn) == 0)
198 return 0; 206 return 0;
199 return ((unsigned long)hose->cfg_data) + U3_HT_CFA0(devfn, offset); 207 return ((unsigned long)hose->cfg_data) + u3_ht_cfa0(devfn, offset);
200 } else 208 } else
201 return ((unsigned long)hose->cfg_data) + U3_HT_CFA1(bus, devfn, offset); 209 return ((unsigned long)hose->cfg_data) + u3_ht_cfa1(bus, devfn, offset);
202} 210}
203 211
204static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, 212static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
@@ -211,6 +219,9 @@ static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
211 if (hose == NULL) 219 if (hose == NULL)
212 return PCIBIOS_DEVICE_NOT_FOUND; 220 return PCIBIOS_DEVICE_NOT_FOUND;
213 221
222 if (offset > 0xff)
223 return PCIBIOS_BAD_REGISTER_NUMBER;
224
214 addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); 225 addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
215 if (!addr) 226 if (!addr)
216 return PCIBIOS_DEVICE_NOT_FOUND; 227 return PCIBIOS_DEVICE_NOT_FOUND;
@@ -243,6 +254,9 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
243 if (hose == NULL) 254 if (hose == NULL)
244 return PCIBIOS_DEVICE_NOT_FOUND; 255 return PCIBIOS_DEVICE_NOT_FOUND;
245 256
257 if (offset > 0xff)
258 return PCIBIOS_BAD_REGISTER_NUMBER;
259
246 addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); 260 addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
247 if (!addr) 261 if (!addr)
248 return PCIBIOS_DEVICE_NOT_FOUND; 262 return PCIBIOS_DEVICE_NOT_FOUND;
@@ -314,12 +328,12 @@ static int __init add_bridge(struct device_node *dev)
314 int len; 328 int len;
315 struct pci_controller *hose; 329 struct pci_controller *hose;
316 char* disp_name; 330 char* disp_name;
317 int *bus_range; 331 const int *bus_range;
318 int primary = 1; 332 int primary = 1;
319 333
320 DBG("Adding PCI host bridge %s\n", dev->full_name); 334 DBG("Adding PCI host bridge %s\n", dev->full_name);
321 335
322 bus_range = (int *) get_property(dev, "bus-range", &len); 336 bus_range = get_property(dev, "bus-range", &len);
323 if (bus_range == NULL || len < 2 * sizeof(int)) { 337 if (bus_range == NULL || len < 2 * sizeof(int)) {
324 printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", 338 printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
325 dev->full_name); 339 dev->full_name);