diff options
Diffstat (limited to 'arch/powerpc/platforms/maple/pci.c')
-rw-r--r-- | arch/powerpc/platforms/maple/pci.c | 70 |
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; | |||
38 | static int __init fixup_one_level_bus_range(struct device_node *node, int higher) | 38 | static 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 | */ |
66 | static void __init fixup_bus_range(struct device_node *bridge) | 66 | static 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) \ | 84 | static 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) \ | 91 | static 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 | ||
93 | static unsigned long u3_agp_cfg_access(struct pci_controller* hose, | 99 | static 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 | ||
191 | static 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) \ | 196 | static 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 | ||
193 | static unsigned long u3_ht_cfg_access(struct pci_controller* hose, | 201 | static 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 | ||
204 | static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, | 212 | static 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); |