diff options
Diffstat (limited to 'drivers/bcma/scan.c')
-rw-r--r-- | drivers/bcma/scan.c | 230 |
1 files changed, 118 insertions, 112 deletions
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index 40d7dcce8933..4012d8d93e91 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c | |||
@@ -200,16 +200,124 @@ static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr, | |||
200 | return addrl; | 200 | return addrl; |
201 | } | 201 | } |
202 | 202 | ||
203 | static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, | ||
204 | struct bcma_device *core) | ||
205 | { | ||
206 | s32 tmp; | ||
207 | u8 i, j; | ||
208 | s32 cia, cib; | ||
209 | u8 ports[2], wrappers[2]; | ||
210 | |||
211 | /* get CIs */ | ||
212 | cia = bcma_erom_get_ci(bus, eromptr); | ||
213 | if (cia < 0) { | ||
214 | bcma_erom_push_ent(eromptr); | ||
215 | if (bcma_erom_is_end(bus, eromptr)) | ||
216 | return -ESPIPE; | ||
217 | return -EILSEQ; | ||
218 | } | ||
219 | cib = bcma_erom_get_ci(bus, eromptr); | ||
220 | if (cib < 0) | ||
221 | return -EILSEQ; | ||
222 | |||
223 | /* parse CIs */ | ||
224 | core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT; | ||
225 | core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT; | ||
226 | core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT; | ||
227 | ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT; | ||
228 | ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT; | ||
229 | wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT; | ||
230 | wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT; | ||
231 | core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT; | ||
232 | |||
233 | if (((core->id.manuf == BCMA_MANUF_ARM) && | ||
234 | (core->id.id == 0xFFF)) || | ||
235 | (ports[1] == 0)) { | ||
236 | bcma_erom_skip_component(bus, eromptr); | ||
237 | return -ENXIO; | ||
238 | } | ||
239 | |||
240 | /* check if component is a core at all */ | ||
241 | if (wrappers[0] + wrappers[1] == 0) { | ||
242 | /* we could save addrl of the router | ||
243 | if (cid == BCMA_CORE_OOB_ROUTER) | ||
244 | */ | ||
245 | bcma_erom_skip_component(bus, eromptr); | ||
246 | return -ENXIO; | ||
247 | } | ||
248 | |||
249 | if (bcma_erom_is_bridge(bus, eromptr)) { | ||
250 | bcma_erom_skip_component(bus, eromptr); | ||
251 | return -ENXIO; | ||
252 | } | ||
253 | |||
254 | /* get & parse master ports */ | ||
255 | for (i = 0; i < ports[0]; i++) { | ||
256 | u32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr); | ||
257 | if (mst_port_d < 0) | ||
258 | return -EILSEQ; | ||
259 | } | ||
260 | |||
261 | /* get & parse slave ports */ | ||
262 | for (i = 0; i < ports[1]; i++) { | ||
263 | for (j = 0; ; j++) { | ||
264 | tmp = bcma_erom_get_addr_desc(bus, eromptr, | ||
265 | SCAN_ADDR_TYPE_SLAVE, i); | ||
266 | if (tmp < 0) { | ||
267 | /* no more entries for port _i_ */ | ||
268 | /* pr_debug("erom: slave port %d " | ||
269 | * "has %d descriptors\n", i, j); */ | ||
270 | break; | ||
271 | } else { | ||
272 | if (i == 0 && j == 0) | ||
273 | core->addr = tmp; | ||
274 | } | ||
275 | } | ||
276 | } | ||
277 | |||
278 | /* get & parse master wrappers */ | ||
279 | for (i = 0; i < wrappers[0]; i++) { | ||
280 | for (j = 0; ; j++) { | ||
281 | tmp = bcma_erom_get_addr_desc(bus, eromptr, | ||
282 | SCAN_ADDR_TYPE_MWRAP, i); | ||
283 | if (tmp < 0) { | ||
284 | /* no more entries for port _i_ */ | ||
285 | /* pr_debug("erom: master wrapper %d " | ||
286 | * "has %d descriptors\n", i, j); */ | ||
287 | break; | ||
288 | } else { | ||
289 | if (i == 0 && j == 0) | ||
290 | core->wrap = tmp; | ||
291 | } | ||
292 | } | ||
293 | } | ||
294 | |||
295 | /* get & parse slave wrappers */ | ||
296 | for (i = 0; i < wrappers[1]; i++) { | ||
297 | u8 hack = (ports[1] == 1) ? 0 : 1; | ||
298 | for (j = 0; ; j++) { | ||
299 | tmp = bcma_erom_get_addr_desc(bus, eromptr, | ||
300 | SCAN_ADDR_TYPE_SWRAP, i + hack); | ||
301 | if (tmp < 0) { | ||
302 | /* no more entries for port _i_ */ | ||
303 | /* pr_debug("erom: master wrapper %d " | ||
304 | * has %d descriptors\n", i, j); */ | ||
305 | break; | ||
306 | } else { | ||
307 | if (wrappers[0] == 0 && !i && !j) | ||
308 | core->wrap = tmp; | ||
309 | } | ||
310 | } | ||
311 | } | ||
312 | return 0; | ||
313 | } | ||
314 | |||
203 | int bcma_bus_scan(struct bcma_bus *bus) | 315 | int bcma_bus_scan(struct bcma_bus *bus) |
204 | { | 316 | { |
205 | u32 erombase; | 317 | u32 erombase; |
206 | u32 __iomem *eromptr, *eromend; | 318 | u32 __iomem *eromptr, *eromend; |
207 | 319 | ||
208 | s32 cia, cib; | ||
209 | u8 ports[2], wrappers[2]; | ||
210 | |||
211 | s32 tmp; | 320 | s32 tmp; |
212 | u8 i, j; | ||
213 | 321 | ||
214 | int err; | 322 | int err; |
215 | 323 | ||
@@ -236,112 +344,13 @@ int bcma_bus_scan(struct bcma_bus *bus) | |||
236 | INIT_LIST_HEAD(&core->list); | 344 | INIT_LIST_HEAD(&core->list); |
237 | core->bus = bus; | 345 | core->bus = bus; |
238 | 346 | ||
239 | /* get CIs */ | 347 | err = bcma_get_next_core(bus, &eromptr, core); |
240 | cia = bcma_erom_get_ci(bus, &eromptr); | 348 | if (err == -ENXIO) |
241 | if (cia < 0) { | ||
242 | bcma_erom_push_ent(&eromptr); | ||
243 | if (bcma_erom_is_end(bus, &eromptr)) | ||
244 | break; | ||
245 | err= -EILSEQ; | ||
246 | goto out; | ||
247 | } | ||
248 | cib = bcma_erom_get_ci(bus, &eromptr); | ||
249 | if (cib < 0) { | ||
250 | err= -EILSEQ; | ||
251 | goto out; | ||
252 | } | ||
253 | |||
254 | /* parse CIs */ | ||
255 | core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT; | ||
256 | core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT; | ||
257 | core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT; | ||
258 | ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT; | ||
259 | ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT; | ||
260 | wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT; | ||
261 | wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT; | ||
262 | core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT; | ||
263 | |||
264 | if (((core->id.manuf == BCMA_MANUF_ARM) && | ||
265 | (core->id.id == 0xFFF)) || | ||
266 | (ports[1] == 0)) { | ||
267 | bcma_erom_skip_component(bus, &eromptr); | ||
268 | continue; | ||
269 | } | ||
270 | |||
271 | /* check if component is a core at all */ | ||
272 | if (wrappers[0] + wrappers[1] == 0) { | ||
273 | /* we could save addrl of the router | ||
274 | if (cid == BCMA_CORE_OOB_ROUTER) | ||
275 | */ | ||
276 | bcma_erom_skip_component(bus, &eromptr); | ||
277 | continue; | ||
278 | } | ||
279 | |||
280 | if (bcma_erom_is_bridge(bus, &eromptr)) { | ||
281 | bcma_erom_skip_component(bus, &eromptr); | ||
282 | continue; | 349 | continue; |
283 | } | 350 | else if (err == -ESPIPE) |
284 | 351 | break; | |
285 | /* get & parse master ports */ | 352 | else if (err < 0) |
286 | for (i = 0; i < ports[0]; i++) { | 353 | return err; |
287 | u32 mst_port_d = bcma_erom_get_mst_port(bus, &eromptr); | ||
288 | if (mst_port_d < 0) { | ||
289 | err= -EILSEQ; | ||
290 | goto out; | ||
291 | } | ||
292 | } | ||
293 | |||
294 | /* get & parse slave ports */ | ||
295 | for (i = 0; i < ports[1]; i++) { | ||
296 | for (j = 0; ; j++) { | ||
297 | tmp = bcma_erom_get_addr_desc(bus, &eromptr, | ||
298 | SCAN_ADDR_TYPE_SLAVE, i); | ||
299 | if (tmp < 0) { | ||
300 | /* no more entries for port _i_ */ | ||
301 | /* pr_debug("erom: slave port %d " | ||
302 | * "has %d descriptors\n", i, j); */ | ||
303 | break; | ||
304 | } else { | ||
305 | if (i == 0 && j == 0) | ||
306 | core->addr = tmp; | ||
307 | } | ||
308 | } | ||
309 | } | ||
310 | |||
311 | /* get & parse master wrappers */ | ||
312 | for (i = 0; i < wrappers[0]; i++) { | ||
313 | for (j = 0; ; j++) { | ||
314 | tmp = bcma_erom_get_addr_desc(bus, &eromptr, | ||
315 | SCAN_ADDR_TYPE_MWRAP, i); | ||
316 | if (tmp < 0) { | ||
317 | /* no more entries for port _i_ */ | ||
318 | /* pr_debug("erom: master wrapper %d " | ||
319 | * "has %d descriptors\n", i, j); */ | ||
320 | break; | ||
321 | } else { | ||
322 | if (i == 0 && j == 0) | ||
323 | core->wrap = tmp; | ||
324 | } | ||
325 | } | ||
326 | } | ||
327 | |||
328 | /* get & parse slave wrappers */ | ||
329 | for (i = 0; i < wrappers[1]; i++) { | ||
330 | u8 hack = (ports[1] == 1) ? 0 : 1; | ||
331 | for (j = 0; ; j++) { | ||
332 | tmp = bcma_erom_get_addr_desc(bus, &eromptr, | ||
333 | SCAN_ADDR_TYPE_SWRAP, i + hack); | ||
334 | if (tmp < 0) { | ||
335 | /* no more entries for port _i_ */ | ||
336 | /* pr_debug("erom: master wrapper %d " | ||
337 | * has %d descriptors\n", i, j); */ | ||
338 | break; | ||
339 | } else { | ||
340 | if (wrappers[0] == 0 && !i && !j) | ||
341 | core->wrap = tmp; | ||
342 | } | ||
343 | } | ||
344 | } | ||
345 | 354 | ||
346 | pr_info("Core %d found: %s " | 355 | pr_info("Core %d found: %s " |
347 | "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", | 356 | "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", |
@@ -351,9 +360,6 @@ int bcma_bus_scan(struct bcma_bus *bus) | |||
351 | 360 | ||
352 | core->core_index = bus->nr_cores++; | 361 | core->core_index = bus->nr_cores++; |
353 | list_add(&core->list, &bus->cores); | 362 | list_add(&core->list, &bus->cores); |
354 | continue; | ||
355 | out: | ||
356 | return err; | ||
357 | } | 363 | } |
358 | 364 | ||
359 | return 0; | 365 | return 0; |