diff options
author | Ishizaki Kou <kou.ishizaki@toshiba.co.jp> | 2007-03-02 02:59:25 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-03-07 12:09:33 -0500 |
commit | 8388374f1cd45ef67039d3ea128d250fac484df3 (patch) | |
tree | 6fee84637f5172705708ea220d73c99c3521c25a /arch/powerpc | |
parent | c99176a230097b076c2f98e4bf963399fe114ffd (diff) |
[POWERPC] Celleb: bug fix caused by not casting pointer types
This fixes a bug caused by changes of pointer type in
commit f1fda89522c5aaa1bd4ef69605e85e6ee9c85faf.
hose->cfg_addr type is "volatile unsigned int __iomem *", so
"hose->cfg_addr + X" will not make an intended address.
This patch also adds comments for usage of cfg_addr and cfg_data in
pci_controller structure. We use them in irregular way, and the
original code is short of explanations about them.
Signed-off-by: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
Acked-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/platforms/celleb/scc_epci.c | 82 |
1 files changed, 61 insertions, 21 deletions
diff --git a/arch/powerpc/platforms/celleb/scc_epci.c b/arch/powerpc/platforms/celleb/scc_epci.c index c11b39c3776a..fb23d53eb09c 100644 --- a/arch/powerpc/platforms/celleb/scc_epci.c +++ b/arch/powerpc/platforms/celleb/scc_epci.c | |||
@@ -43,11 +43,34 @@ | |||
43 | 43 | ||
44 | #define iob() __asm__ __volatile__("eieio; sync":::"memory") | 44 | #define iob() __asm__ __volatile__("eieio; sync":::"memory") |
45 | 45 | ||
46 | static inline volatile void __iomem *celleb_epci_get_epci_base( | ||
47 | struct pci_controller *hose) | ||
48 | { | ||
49 | /* | ||
50 | * Note: | ||
51 | * Celleb epci uses cfg_addr as a base address for | ||
52 | * epci control registers. | ||
53 | */ | ||
54 | |||
55 | return hose->cfg_addr; | ||
56 | } | ||
57 | |||
58 | static inline volatile void __iomem *celleb_epci_get_epci_cfg( | ||
59 | struct pci_controller *hose) | ||
60 | { | ||
61 | /* | ||
62 | * Note: | ||
63 | * Celleb epci uses cfg_data as a base address for | ||
64 | * configuration area for epci devices. | ||
65 | */ | ||
66 | |||
67 | return hose->cfg_data; | ||
68 | } | ||
46 | 69 | ||
47 | #if 0 /* test code for epci dummy read */ | 70 | #if 0 /* test code for epci dummy read */ |
48 | static void celleb_epci_dummy_read(struct pci_dev *dev) | 71 | static void celleb_epci_dummy_read(struct pci_dev *dev) |
49 | { | 72 | { |
50 | void __iomem *epci_base; | 73 | volatile void __iomem *epci_base; |
51 | struct device_node *node; | 74 | struct device_node *node; |
52 | struct pci_controller *hose; | 75 | struct pci_controller *hose; |
53 | u32 val; | 76 | u32 val; |
@@ -58,7 +81,7 @@ static void celleb_epci_dummy_read(struct pci_dev *dev) | |||
58 | if (!hose) | 81 | if (!hose) |
59 | return; | 82 | return; |
60 | 83 | ||
61 | epci_base = hose->cfg_addr; | 84 | epci_base = celleb_epci_get_epci_base(hose); |
62 | 85 | ||
63 | val = in_be32(epci_base + SCC_EPCI_WATRP); | 86 | val = in_be32(epci_base + SCC_EPCI_WATRP); |
64 | iosync(); | 87 | iosync(); |
@@ -70,19 +93,20 @@ static void celleb_epci_dummy_read(struct pci_dev *dev) | |||
70 | static inline void clear_and_disable_master_abort_interrupt( | 93 | static inline void clear_and_disable_master_abort_interrupt( |
71 | struct pci_controller *hose) | 94 | struct pci_controller *hose) |
72 | { | 95 | { |
73 | void __iomem *addr; | 96 | volatile void __iomem *epci_base, *reg; |
74 | addr = hose->cfg_addr + PCI_COMMAND; | 97 | epci_base = celleb_epci_get_epci_base(hose); |
75 | out_be32(addr, in_be32(addr) | (PCI_STATUS_REC_MASTER_ABORT << 16)); | 98 | reg = epci_base + PCI_COMMAND; |
99 | out_be32(reg, in_be32(reg) | (PCI_STATUS_REC_MASTER_ABORT << 16)); | ||
76 | } | 100 | } |
77 | 101 | ||
78 | static int celleb_epci_check_abort(struct pci_controller *hose, | 102 | static int celleb_epci_check_abort(struct pci_controller *hose, |
79 | void __iomem *addr) | 103 | volatile void __iomem *addr) |
80 | { | 104 | { |
81 | void __iomem *reg, *epci_base; | 105 | volatile void __iomem *reg, *epci_base; |
82 | u32 val; | 106 | u32 val; |
83 | 107 | ||
84 | iob(); | 108 | iob(); |
85 | epci_base = hose->cfg_addr; | 109 | epci_base = celleb_epci_get_epci_base(hose); |
86 | 110 | ||
87 | reg = epci_base + PCI_COMMAND; | 111 | reg = epci_base + PCI_COMMAND; |
88 | val = in_be32(reg); | 112 | val = in_be32(reg); |
@@ -108,20 +132,21 @@ static int celleb_epci_check_abort(struct pci_controller *hose, | |||
108 | return PCIBIOS_SUCCESSFUL; | 132 | return PCIBIOS_SUCCESSFUL; |
109 | } | 133 | } |
110 | 134 | ||
111 | static void __iomem *celleb_epci_make_config_addr(struct pci_controller *hose, | 135 | static volatile void __iomem *celleb_epci_make_config_addr( |
136 | struct pci_controller *hose, | ||
112 | unsigned int devfn, int where) | 137 | unsigned int devfn, int where) |
113 | { | 138 | { |
114 | void __iomem *addr; | 139 | volatile void __iomem *addr; |
115 | struct pci_bus *bus = hose->bus; | 140 | struct pci_bus *bus = hose->bus; |
116 | 141 | ||
117 | if (bus->self) | 142 | if (bus->self) |
118 | addr = hose->cfg_data + | 143 | addr = celleb_epci_get_epci_cfg(hose) + |
119 | (((bus->number & 0xff) << 16) | 144 | (((bus->number & 0xff) << 16) |
120 | | ((devfn & 0xff) << 8) | 145 | | ((devfn & 0xff) << 8) |
121 | | (where & 0xff) | 146 | | (where & 0xff) |
122 | | 0x01000000); | 147 | | 0x01000000); |
123 | else | 148 | else |
124 | addr = hose->cfg_data + | 149 | addr = celleb_epci_get_epci_cfg(hose) + |
125 | (((devfn & 0xff) << 8) | (where & 0xff)); | 150 | (((devfn & 0xff) << 8) | (where & 0xff)); |
126 | 151 | ||
127 | pr_debug("EPCI: config_addr = 0x%p\n", addr); | 152 | pr_debug("EPCI: config_addr = 0x%p\n", addr); |
@@ -132,7 +157,7 @@ static void __iomem *celleb_epci_make_config_addr(struct pci_controller *hose, | |||
132 | static int celleb_epci_read_config(struct pci_bus *bus, | 157 | static int celleb_epci_read_config(struct pci_bus *bus, |
133 | unsigned int devfn, int where, int size, u32 * val) | 158 | unsigned int devfn, int where, int size, u32 * val) |
134 | { | 159 | { |
135 | void __iomem *addr; | 160 | volatile void __iomem *epci_base, *addr; |
136 | struct device_node *node; | 161 | struct device_node *node; |
137 | struct pci_controller *hose; | 162 | struct pci_controller *hose; |
138 | 163 | ||
@@ -142,13 +167,14 @@ static int celleb_epci_read_config(struct pci_bus *bus, | |||
142 | node = (struct device_node *)bus->sysdata; | 167 | node = (struct device_node *)bus->sysdata; |
143 | hose = pci_find_hose_for_OF_device(node); | 168 | hose = pci_find_hose_for_OF_device(node); |
144 | 169 | ||
145 | if (!hose->cfg_data) | 170 | if (!celleb_epci_get_epci_cfg(hose)) |
146 | return PCIBIOS_DEVICE_NOT_FOUND; | 171 | return PCIBIOS_DEVICE_NOT_FOUND; |
147 | 172 | ||
148 | if (bus->number == hose->first_busno && devfn == 0) { | 173 | if (bus->number == hose->first_busno && devfn == 0) { |
149 | /* EPCI controller self */ | 174 | /* EPCI controller self */ |
150 | 175 | ||
151 | addr = hose->cfg_addr + where; | 176 | epci_base = celleb_epci_get_epci_base(hose); |
177 | addr = epci_base + where; | ||
152 | 178 | ||
153 | switch (size) { | 179 | switch (size) { |
154 | case 1: | 180 | case 1: |
@@ -185,7 +211,7 @@ static int celleb_epci_read_config(struct pci_bus *bus, | |||
185 | } | 211 | } |
186 | 212 | ||
187 | pr_debug("EPCI: " | 213 | pr_debug("EPCI: " |
188 | "addr=0x%lx, devfn=0x%x, where=0x%x, size=0x%x, val=0x%x\n", | 214 | "addr=0x%p, devfn=0x%x, where=0x%x, size=0x%x, val=0x%x\n", |
189 | addr, devfn, where, size, *val); | 215 | addr, devfn, where, size, *val); |
190 | 216 | ||
191 | return celleb_epci_check_abort(hose, NULL); | 217 | return celleb_epci_check_abort(hose, NULL); |
@@ -194,7 +220,7 @@ static int celleb_epci_read_config(struct pci_bus *bus, | |||
194 | static int celleb_epci_write_config(struct pci_bus *bus, | 220 | static int celleb_epci_write_config(struct pci_bus *bus, |
195 | unsigned int devfn, int where, int size, u32 val) | 221 | unsigned int devfn, int where, int size, u32 val) |
196 | { | 222 | { |
197 | void __iomem *addr; | 223 | volatile void __iomem *epci_base, *addr; |
198 | struct device_node *node; | 224 | struct device_node *node; |
199 | struct pci_controller *hose; | 225 | struct pci_controller *hose; |
200 | 226 | ||
@@ -204,13 +230,15 @@ static int celleb_epci_write_config(struct pci_bus *bus, | |||
204 | node = (struct device_node *)bus->sysdata; | 230 | node = (struct device_node *)bus->sysdata; |
205 | hose = pci_find_hose_for_OF_device(node); | 231 | hose = pci_find_hose_for_OF_device(node); |
206 | 232 | ||
207 | if (!hose->cfg_data) | 233 | |
234 | if (!celleb_epci_get_epci_cfg(hose)) | ||
208 | return PCIBIOS_DEVICE_NOT_FOUND; | 235 | return PCIBIOS_DEVICE_NOT_FOUND; |
209 | 236 | ||
210 | if (bus->number == hose->first_busno && devfn == 0) { | 237 | if (bus->number == hose->first_busno && devfn == 0) { |
211 | /* EPCI controller self */ | 238 | /* EPCI controller self */ |
212 | 239 | ||
213 | addr = hose->cfg_addr + where; | 240 | epci_base = celleb_epci_get_epci_base(hose); |
241 | addr = epci_base + where; | ||
214 | 242 | ||
215 | switch (size) { | 243 | switch (size) { |
216 | case 1: | 244 | case 1: |
@@ -258,10 +286,10 @@ struct pci_ops celleb_epci_ops = { | |||
258 | static int __devinit celleb_epci_init(struct pci_controller *hose) | 286 | static int __devinit celleb_epci_init(struct pci_controller *hose) |
259 | { | 287 | { |
260 | u32 val; | 288 | u32 val; |
261 | void __iomem *reg, *epci_base; | 289 | volatile void __iomem *reg, *epci_base; |
262 | int hwres = 0; | 290 | int hwres = 0; |
263 | 291 | ||
264 | epci_base = hose->cfg_addr; | 292 | epci_base = celleb_epci_get_epci_base(hose); |
265 | 293 | ||
266 | /* PCI core reset(Internal bus and PCI clock) */ | 294 | /* PCI core reset(Internal bus and PCI clock) */ |
267 | reg = epci_base + SCC_EPCI_CKCTRL; | 295 | reg = epci_base + SCC_EPCI_CKCTRL; |
@@ -382,6 +410,18 @@ int __devinit celleb_setup_epci(struct device_node *node, | |||
382 | 410 | ||
383 | pr_debug("PCI: celleb_setup_epci()\n"); | 411 | pr_debug("PCI: celleb_setup_epci()\n"); |
384 | 412 | ||
413 | /* | ||
414 | * Note: | ||
415 | * Celleb epci uses cfg_addr and cfg_data member of | ||
416 | * pci_controller structure in irregular way. | ||
417 | * | ||
418 | * cfg_addr is used to map for control registers of | ||
419 | * celleb epci. | ||
420 | * | ||
421 | * cfg_data is used for configuration area of devices | ||
422 | * on Celleb epci buses. | ||
423 | */ | ||
424 | |||
385 | if (of_address_to_resource(node, 0, &r)) | 425 | if (of_address_to_resource(node, 0, &r)) |
386 | goto error; | 426 | goto error; |
387 | hose->cfg_addr = ioremap(r.start, (r.end - r.start + 1)); | 427 | hose->cfg_addr = ioremap(r.start, (r.end - r.start + 1)); |