blob: 2863586dc1b97be39447a52f456fca8409aaf9fe [file] [log] [blame]
Daniel Hellstrom02e2a842010-01-25 09:54:51 +01001/* GRLIB AMBA Plug&Play information scanning implemented without
2 * using memory (stack) and one register window. The code scan
3 * the PnP info and inserts the AHB bridges/buses into register
4 * i0-i5.
5 * The code support
6 * - up to 6 AHB buses
7 * - multiple APB buses
8 * - support for AHB2AHB & L2CACHE bridges
9 *
10 * (C) Copyright 2010, 2015
11 * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
12 *
13 * SPDX-License-Identifier: GPL-2.0+
14 */
15
16#include <ambapp.h>
17
18 .seg "text"
19 .globl _nomem_amba_init
20 .globl _nomem_ambapp_find_buses
21 .globl _nomem_find_apb
22 .globl _nomem_find_ahb
23
24/* Overview
25 * ========
26 *
27 * _nomem_amba_init - Init AMBA bus and calls _nomem_ambapp_find_buses
28 * _nomem_ambapp_find_buses - Scan AMBA PnP info for AHB buses/bridges and
29 * place them in i0-i5, see below
30 * _nomem_find_apb - Find one APB device identified by VENDOR:DEVICE
31 * ID and an index.
32 * _nomem_find_ahb - Find one AHB Master or Slave device identified
33 * by VENDOR:DEVICE ID and an index.
34 * init_ahb_bridges - Local function. Clears i0-i5
35 * insert_ahb_bridge - Local function. Insert a new AHB bus into first
36 * free register in i0-i5. It also checks that the
37 * bus has not already been added.
38 * get_ahb_bridge - Local function. Get AHB bus from registers,
39 * return register iN, where N is defined by o0.
40 *
41 * The _nomem_find_apb and _nomem_find_ahb function requires that i0-i5
42 * are populated with the AHB buses of the system. The registers are
43 * initialized by _nomem_ambapp_find_buses.
44 *
45 * AHB Bus result and requirements of i0-i5
46 * ========================================
47 *
48 * i0: AHB BUS0 IOAREA, no parent bus
49 * i1: AHB BUS1 IOAREA, parent bus is always i0 (AHB BUS0) and bridge address
50 * i2: AHB BUS2 IOAREA, 3-bit parent bus number and bridge address
51 * i3: AHB BUS3 IOAREA, 3-bit parent bus number and bridge address
52 * i4: AHB BUS4 IOAREA, 3-bit parent bus number and bridge address
53 * i5: AHB BUS5 IOAREA, 3-bit parent bus number and bridge address
54 *
55 * AHB BUS
56 * -------
57 * Bits 31-20 (0xfff00000) contain the found bus I/O Area (AHB PnP area).
58 *
59 * 3-bit Parent bus
60 * ----------------
61 * Bits 2-0 (0x00000007) contain parent bus number. Zero if no parent
62 * bus, 1 = parent is AHB BUS 0 (i0), 2 = parent is AHB BUS 1 (i1)..
63 *
64 * Bridge Address
65 * --------------
66 * Bits 10-5 (0x000007e0) contain the index of the Bridge's PnP
67 * information on the parent. Since all bridges are found in the
68 * PnP information they all have a PnP entry. Together with the
69 * parent bus number the PnP entry can be found:
70 * PnPEntry = (BRIDGE_ADDRESS + (iN & 0xfff00000)) | 0x000ff800
71 * where N is the parent bus minus one.
72 *
73 */
74
75/* Function initializes the AHB Bridge I/O AREA storage. (Clears i0-i5)
76 *
77 * Arguments
78 * none
79 *
80 * Results
81 * none
82 *
83 * Clobbered
84 * none
85 */
86
87init_ahb_bridges:
88 mov %g0, %i0
89 mov %g0, %i1
90 mov %g0, %i2
91 mov %g0, %i3
92 mov %g0, %i4
93 retl
94 mov %g0, %i5
95
96/* Function returns AHB Bridge I/O AREA for specified bus.
97 *
98 * Arguments
99 * - o0 = bus number
100 *
101 * Results
102 * - o0 = I/O AREA
103 *
104 * Clobbered
105 * none
106 */
107get_ahb_bridge:
108 cmp %o0, 1
109 be,a L1
110 mov %i0, %o0
111
112 cmp %o0, 2
113 be,a L1
114 mov %i1, %o0
115
116 cmp %o0, 3
117 be,a L1
118 mov %i2, %o0
119
120 cmp %o0, 4
121 be,a L1
122 mov %i3, %o0
123
124 cmp %o0, 5
125 be,a L1
126 mov %i4, %o0
127
128 cmp %o0, 6
129 be,a L1
130 mov %i5, %o0
131
132 /* o0 > 6: only 6 buses supported */
133 mov %g0, %o0
134L1:
135 retl
136 nop
137
138/* Function adds a AHB Bridge I/O AREA to the i0-i5 registers if
139 * not already added. It stores the bus PnP start information.
140 *
141 * Arguments
142 * - o0 = AHB Bridge I/O area
143 *
144 * Results
145 * none
146 *
147 * Clobbered
148 * o2, o3
149 */
150insert_ahb_bridge:
151 /* Check that bridge hasn't already been added */
152 andn %o0, 0x7ff, %o2
153 andn %i0, 0x7ff, %o3
154 cmp %o3, %o2
155 be L2
156 andn %i1, 0x7ff, %o3
157 cmp %o3, %o2
158 be L2
159 andn %i2, 0x7ff, %o3
160 cmp %o3, %o2
161 be L2
162 andn %i3, 0x7ff, %o3
163 cmp %o3, %o2
164 be L2
165 andn %i4, 0x7ff, %o3
166 cmp %o3, %o2
167 be L2
168 andn %i5, 0x7ff, %o3
169 cmp %o3, %o2
170 be L2
171
172 /* Insert into first free posistion */
173 cmp %i0, %g0
174 be,a L2
175 mov %o0, %i0
176
177 cmp %i1, %g0
178 be,a L2
179 mov %o0, %i1
180
181 cmp %i2, %g0
182 be,a L2
183 mov %o0, %i2
184
185 cmp %i3, %g0
186 be,a L2
187 mov %o0, %i3
188
189 cmp %i4, %g0
190 be,a L2
191 mov %o0, %i4
192
193 cmp %i5, %g0
194 be,a L2
195 mov %o0, %i5
196L2:
197 retl
198 nop
199
200/* FUNCTION int _nomem_find_ahb_bus(
201 * unsigned int bridge,
202 * int vendor_device,
203 * int index,
204 * void **pconf,
205 * int not_used,
206 * int option
207 * )
208 *
209 * Scans the AHB Master or Slave area for a matching VENDOR:DEVICE, the
210 * index is decremented when a matching device is found but index is
211 * greater than zero. When index is zero and a matching DEVICE:VENDOR
212 * is found the AHB configuration address and AHB I/O area is returned.
213 *
214 * i0-i7,l0,l1,l2,l3,l4,g2,o6 is not available for use.
215 * o1,o5 Must be left untouched
216 *
217 * Results
218 * - o0 Number of found devices (1 or 0)
219 * - o2 is decremented for each matching VENDOR:DEVICE found, zero if found
220 * - o3 Address of the AHB PnP configuration entry (Only valid if o0=1)
221 *
222 * Clobbered
223 * - o3 (Clobbered when no device was found)
224 * - o4 (Number of Devices left to search)
225 * - o0 (Bus ID, PnP ID, Device)
226 */
227_nomem_find_ahb_bus:
228
229 /* Get the number of Slaves/Masters.
230 * Only AHB Bus 0 has 64 AHB Masters/Slaves the
231 * other AHB buses has 16 slaves and 16 masters.
232 */
233 add %g0, 16, %o4 /* Defaulting to 16 */
234 andcc %o0, 0x7, %g0 /* 3-bit bus id */
235 be,a .L_maxloops_detected
236 add %g0, 64, %o4 /* AHB Bus 0 has 64 AHB Masters/Slaves */
237.L_maxloops_detected:
238
239 /* Get start address of AHB Slave or AHB Master area depending on what
240 * we are searching for.
241 */
242 andn %o0, 0x7ff, %o0 /* Remove Bus ID and 5-bit AHB/AHB
243 * Bridge PnP Address to get I/O Area */
244 set AMBA_CONF_AREA, %o3
245 or %o3, %o0, %o3 /* Master area address */
246
247 cmp %o5, DEV_AHB_SLV
248 be,a .L_conf_area_calculated
249 or %o3, AMBA_AHB_SLAVE_CONF_AREA, %o3 /* Add 0x800 to get to slave area */
250.L_conf_area_calculated:
251
252 /* Iterate over all AHB device and try to find matching DEVICE:VENDOR
253 * o1 - VENDOR|DEVICE
254 * o2 - Index
255 * o3 - Current AHB Device Configuration address
256 * o5 - Type (leave untouched)
257 *
258 * o4 - Number of AHB device left to process
259 * o0 - tmp
260 */
261.L_process_one_conf:
262 ld [%o3], %o0
263 andn %o0, 0xfff, %o0
264 cmp %o0, 0 /* No device if zero */
265 beq .L_next_conf
266 cmp %o1, 0 /* If VENDOR:DEVICE==0, consider all matching */
267 beq .L_process_ahb_dev_found
268 cmp %o0, %o1 /* Does VENDOR and DEVICE Match? */
269 bne .L_next_conf
270 nop
271.L_process_ahb_dev_found:
272 /* Found a Matching VENDOR:DEVICE, index must also match */
273 cmp %o2, %g0
274 bne .L_next_conf
275 dec %o2
276 /* Index matches also, return happy with o3 set to AHB Conf Address */
277 mov %g0, %o2
278 retl
279 add %g0, 1, %o0
280
281.L_next_conf:
282 subcc %o4, 1, %o4 /* One device has been processed,
283 * Are there more devices to process? */
284 bne .L_process_one_conf
285 add %o3, AMBA_AHB_CONF_LENGH, %o3 /* Next Configuration entry */
286 /* No Matching device found */
287 retl
288 mov %g0, %o0
289
290/* FUNCTION int _nomem_find_ahb(
291 * int unused,
292 * int vendor_device,
293 * int index,
294 * void **pconf,
295 * int *ahb_bus_index,
296 * int option,
297 * )
298 *
299 * Find a AHB Master or AHB Slave device, it puts the address of the AHB PnP
300 * configuration in o3 (pconf), the I/O Area base address in o4 (pioarea).
301 *
302 * Calls _nomem_find_ahb_bus for every AHB bus.
303 *
304 * i0-i7, l0, l1, o6, g1, g4-g7 is not available for use.
305 *
306 * Arguments
307 * - o0 Unused
308 *
309 * Results
310 * - o0 Number of found devices (1 or 0)
311 * - o2 Decremented Index (Zero if found)
312 * - o3 Address of the AHB PnP configuration entry
313 * - o4 AHB Bus index the device was found on (if o0=1)
314 * - o5 Left untouched
315 *
316 * Clobbered
317 * - o0 (AHB Bridge and used by _nomem_find_ahb_bus)
318 * - o2 (index is decremented)
319 * - l2 (Current AHB Bus index)
320 * - g2 (return address)
321 */
322_nomem_find_ahb:
323 mov %o7, %g2 /* Save return address */
324 /* Scan all AHB Buses found for the AHB Master/Slave matching VENDOR:DEVICE */
325 clr %l2
326.L_search_next_ahb_bus:
327 add %l2, 1, %l2
328 call get_ahb_bridge /* Get bus %l0 I/O Area */
329 mov %l2, %o0
330 cmp %o0, %g0
331 be .L_no_device_found /* If no more AHB bus is left to be scanned, proceed */
332 nop
333 call _nomem_find_ahb_bus /* Scan AHB bus %o0 for VENDOR:DEVICE. Index in o3 is decremented */
334 nop
335 cmp %o0, %g0 /* If VENDOR:DEVICE was not found scan next AHB Bus */
336 be .L_search_next_ahb_bus /* Do next bus is o0=0 (not found) */
337 nop
338 /* The device was found, o0 is 1 */
339 mov %g2, %o7 /* Restore return address */
340 retl
341 mov %l2, %o4 /* The AHB bus index the device was found on */
342
343 /* No device found matching */
344.L_no_device_found:
345 mov %g2, %o7 /* Restore return address */
346 retl
347 mov %g0, %o0
348
349
350/* FUNCTION int _nomem_find_apb_bus(
351 * int apbmst,
352 * int vendor_device,
353 * int index,
354 * void **pconf
355 * )
356 *
357 * Find a APB Slave device, it puts the address of the APB PnP configuration
358 * in o3 (pconf).
359 *
360 * Calls _nomem_find_ahb_bus for every AHB bus searching for AHB/APB Bridges.
361 * The AHB/APB bridges are AHB Slaves with ID GAISLER_APBMST.
362 *
363 * Results
364 * - o0 Number of found devices (1 or 0)
365 * - o2 Decremented Index
366 * - o3 Address of the found APB device PnP configuration entry
367 *
368 * Clobbered
369 * - o5 PnP VENDOR:DEVICE ID
370 */
371
372_nomem_find_apb_bus:
373 set AMBA_CONF_AREA, %o3
374 or %o0, %o3, %o3 /* Calc start of APB device PnP info */
375 add %g0, 16, %o0 /* o0, number of APB Slaves left to scan */
376.L_process_one_apb_conf:
377 ld [%o3], %o5
378 andn %o5, 0xfff, %o5
379 cmp %o5, 0 /* No device if zero */
380 beq .L_process_apb_dev_not_found
381 cmp %o1, 0 /* If VENDOR:DEVICE == -1, consider all matching */
382 beq .L_process_apb_dev_found
383 cmp %o1, %o5 /* Found VENDOR:DEVICE */
384 bne .L_process_apb_dev_not_found
385 nop
386
387.L_process_apb_dev_found:
388 /* Found matching device, compare index */
389 cmp %o2, %g0
390 bne .L_process_apb_dev_not_found
391 dec %o2
392 /* Matching index and VENDOR:DEVICE */
393 retl
394 add %g0, 1, %o0
395
396.L_process_apb_dev_not_found:
397 subcc %o0, 1, %o0
398 bne .L_process_one_apb_conf
399 add %o3, 8, %o3
400 retl
401 mov %g0, %o0
402
403/* FUNCTION int _nomem_find_apb(
404 * int unused,
405 * int vendor_device,
406 * int index,
407 * void **pconf,
408 * int *ahb_bus_index
409 * )
410 *
411 * Find a APB Slave device, it puts the address of the APB PnP configuration
412 * in o3 (pconf), the APB Master I/O Area base address in o4 (papbarea).
413 *
414 * Calls _nomem_find_ahb_bus for every AHB bus searching for AHB/APB Bridges.
415 * The AHB/APB bridges are AHB Slaves with ID GAISLER_APBMST.
416 *
417 * i0-i7, l0, l1, o6 is not available for use.
418 *
419 * Arguments
420 * - o0 Unused
421 *
422 * Results
423 * - o0 Number of found devices (1 or 0)
424 * - o2 Decremented Index if not found
425 * - o3 Address of the APB PnP configuration entry
426 * - o4 AHB Bus index of APB Bridge/APB Device
427 *
428 * Clobbered
429 * - o0 (AHB Bridge)
430 * - o2 (index is decremented)
431 * - l2 (APB DEV Index [7..4] : APBMST AHB Index [3..0])
432 * - l3 (Current AHB Bus index)
433 * - l4 (temporary storage for APB VENDOR:DEVICE)
434 * - o5 (AHB Slave ID)
435 * - o0 (clobbered by _nomem_find_ahb_bus)
436 * - g2 (Return address)
437 */
438_nomem_find_apb:
439 /* Scan all AHB Buses found for AHB/APB Bridges */
440 mov %o7, %g2 /* Save return address */
441 mov %o1, %l4 /* Save APB VENDOR:DEVICE */
442 sll %o2, 4, %l2 /* APB MST index = 0 */
443 add %g0, 1, %l3 /* AHB Bus index = 0 */
444.L2_search_next_ahb_bus:
445 call get_ahb_bridge /* Get bus %l3 I/O Area */
446 mov %l3, %o0
447 cmp %o0, %g0
448 be .L2_no_device_found /* If no more AHB bus is left to be scanned, proceed */
449 add %g0, DEV_AHB_SLV, %o5 /* Search for AHB Slave */
450 sethi %hi(AMBA_PNP_ID(VENDOR_GAISLER, GAISLER_APBMST)), %o1
451 call _nomem_find_ahb_bus /* Scan AHB bus %o0 for VENDOR:DEVICE. Index in o3 is decremented */
452 and %l2, 0xf, %o2 /* Set APBMST index */
453 cmp %o0, %g0 /* If no AHB/APB Bridge was not found, scan next AHB Bus */
454 be .L_no_apb_bridge_found /* Do next bus */
455 nop
456
457 /* The AHB/APB Bridge was found.
458 * Search for the requested APB Device on the APB bus using
459 * find_apb_bus, it will decrement the index.
460 */
461 ld [%o3 + AMBA_AHB_MBAR0_OFS], %o3
462 sll %o3, 16, %o0
463 and %o0, %o3, %o0 /* Address AND Address Mask */
464 sethi %hi(0xfff00000), %o3
465 and %o0, %o3, %o0 /* AHB/APB Bridge address */
466
467 srl %l2, 4, %o2 /* APB DEV Index */
468 call _nomem_find_apb_bus
469 mov %l4, %o1 /* APB VENDOR:DEVICE */
470 cmp %o0, %g0
471 be .L_apb_dev_not_found
472 mov %g2, %o7 /* Restore return address */
473 /* APB Device found
474 * o0 1
475 * o2 Index is decremented to zero
476 * o3 APB configuration address,
477 * o4 APB Bridge Configuration address.
478 */
479 mov %g0, %o2
480 retl
481 mov %l3, %o4
482
483.L_apb_dev_not_found:
484 /* Update APB DEV Index by saving output from find_apb_bus
485 * (index parameter) into bits [31..4] in L2.
486 */
487 sll %o2, 4, %o2
488 and %l2, 0xf, %l2
489 or %o2, %l2, %l2
490 /* Try finding the next AHB/APB Bridge on the same AHB bus
491 * to find more APB devices
492 */
493 ba .L2_search_next_ahb_bus /* Find next AHB/APB bridge */
494 inc %l2
495
496.L_no_apb_bridge_found:
497 inc %l3 /* Next AHB Bus */
498 ba .L2_search_next_ahb_bus /* Process next AHB bus */
499 andn %l2, 0xf, %l2 /* Start at APB Bridge index 0 at every AHB Bus */
500 /* No device found matching */
501.L2_no_device_found:
502 mov %g2, %o7 /* Restore return address */
503 srl %l2, 4, %o2 /* APB DEV Index */
504 retl
505 mov %g0, %o0
506
507
508
509/* FUNCTION _nomem_amba_scan_gaisler_ahb2ahb_bridge(unsigned int bridge, int bus)
510 *
511 * Constraints:
512 * - o1 may not be used
513 * - o0, o2, o3 may be used.
514 *
515 * Arguments
516 * - o0 PnP Address of Bridge AHB device
517 * - o2 PnP ID of AHB device
518 *
519 * Results
520 * - o0 Address of new bus PnP area or a 1 if AHB device is no bridge
521 *
522 * Clobbered
523 * - o0, o2
524 *
525 */
526_nomem_amba_scan_gaisler_ahb2ahb_bridge:
527 andn %o2, 0xfff, %o2
528 sethi %hi(AMBA_PNP_ID(VENDOR_GAISLER,GAISLER_AHB2AHB)), %o3
529 cmp %o2, %o3
530 beq .L_is_ahb2ahb_bridge
531 nop
532
533 retl
534 add %g0, 1, %o0
535
536.L_is_ahb2ahb_bridge:
537 /* Found a GAISLER AHB2AHB bridge */
538 retl
539 ld [%o0 + AMBA_AHB_CUSTOM1_OFS], %o0 /* Get address of bridge PnP area */
540
541
542/* FUNCTION _nomem_amba_scan_gaisler_l2cache_bridge(unsigned int bridge, int bus)
543 *
544 * Constraints:
545 * - o1 may not be used
546 * - o0, o2, o3 may be used.
547 *
548 * Arguments
549 * - o0 PnP Address of Bridge AHB device
550 * - o2 PnP ID of AHB device
551 *
552 * Results
553 * - o0 Address of new bus PnP area or a 1 if AHB device is no bridge
554 *
555 * Clobbered
556 * - o0, o2
557 *
558 */
559_nomem_amba_scan_gaisler_l2cache_bridge:
560 andn %o2, 0xfff, %o2
561 sethi %hi(AMBA_PNP_ID(VENDOR_GAISLER,GAISLER_L2CACHE)), %o3
562 cmp %o2, %o3
563 beq .L_is_l2cache_bridge
564 nop
565
566 retl
567 add %g0, 1, %o0
568
569.L_is_l2cache_bridge:
570 /* Found a GAISLER l2cache bridge */
571 retl
572 ld [%o0 + AMBA_AHB_CUSTOM1_OFS], %o0 /* Get address of bridge PnP area */
573
574
575/* FUNCTION _nomem_amba_scan(unsigned int bridge, int bus)
576 *
577 * Constraints:
578 * i0-i7, l0 is used by caller
579 * o5-o7 may not be used.
580 *
581 * Arguments
582 * - o0 Bridge Information: I/O AREA and parent bus
583 * - o1 Bus
584 *
585 * Results
586 * - o0 Number of AHB bridges found
587 *
588 * Clobbered
589 * - o0 (Current AHB slave conf address)
590 * - o2 (Used by insert_bridge)
591 * - o3 (Used by insert_bridge)
592 * - l1 (Number of AHB Slaves left to process)
593 * - l2 (Current AHB slave conf address)
594 * - g2 (Return address)
595 */
596_nomem_amba_scan:
597 mov %o7, %g2 /* Save return address */
598 set 16, %l1
599 cmp %o1, 1
600 be,a .L2_maxloops_detected
601 add %g0, 64, %l1
602.L2_maxloops_detected:
603
604 /* Clear 3-bit parent bus from bridge to get I/O AREA, then or
605 * (AMBA_CONF_AREA | AMBA_AHB_SLAVE_CONF_AREA) to get first AHB slave
606 * conf address.
607 */
608 andn %o0, 0x7ff, %o0
609 set (AMBA_CONF_AREA | AMBA_AHB_SLAVE_CONF_AREA), %l2
610 or %o0, %l2, %l2
611
612 /* Scan AHB Slave area for AHB<->AHB bridges. For each AHB device
613 * all "bridge drivers" are called, the driver function interface:
614 *
615 * Input:
616 * - o0 PnP Address of Bridge AHB device
617 * - o2 PnP ID of AHB device
618 * Return values:
619 * - o0 Address of new bus PnP area, returning a 1 in o2 means not found
620 *
621 * Constraints:
622 * - o1 may not be used
623 * - o0, o2, o3 may be used.
624 *
625 */
626.L_scan_one_ahb_slave:
627 ld [%l2], %o2
628
629 cmp %o2, %g0
630 beq .L_scan_next_ahb_slave
631 nop
632
633 /* Call the GAISLER AHB2AHB bridge driver */
634 call _nomem_amba_scan_gaisler_ahb2ahb_bridge
635 mov %l2, %o0
636 cmp %o0, 1
637 bne .L_found_bridge
638 ld [%l2], %o2
639
640 /* Call the GAISLER L2CACHE bridge driver */
641 call _nomem_amba_scan_gaisler_l2cache_bridge
642 mov %l2, %o0
643 cmp %o0, 1
644 bne .L_found_bridge
645 ld [%l2], %o2
646
647 /* Insert next bridge "driver" function here */
648
649
650 /* The PnP ID did not match a bridge - a new bus was not found ==>
651 * step to next AHB device */
652 ba .L_scan_next_ahb_slave
653 nop
654
655 /* Add Found bus */
656.L_found_bridge:
657 and %l2, 0x7e0, %o2
658 or %o2, %o0, %o0 /* Add AHB/AHB Bridge PnP address */
659 call insert_ahb_bridge /* Insert Bridge into found buses storage */
660 or %o1, %o0, %o0 /* Add parent bus LSB 3-bits */
661
662.L_scan_next_ahb_slave:
663 /* More Slaves to process? */
664 subcc %l1, 1, %l1
665 bne .L_scan_one_ahb_slave
666 add %l2, AMBA_AHB_CONF_LENGH, %l2
667
668 /* No more AHB devices to process */
669 mov %g2, %o7 /* Restore return address */
670 retl
671 nop
672
673/* FUNCTION _nomem_ambapp_find_buses(unsigned int ioarea)
674 *
675 * Find AMBA AHB buses.
676 *
677 * Constraints:
678 * i6-i7, l7 is used by caller
679 *
680 * Arguments
681 * - o0 Bridge Information: I/O AREA and parent bus
682 *
683 * Results
684 * - o0 Number of AHB bridges found
685 * - i0-i5 initialized
686 *
687 * Clobbered
688 * - o0 (Current AHB slave conf address)
689 * - o2 (Used by insert_bridge)
690 * - o3 (Used by insert_bridge)
691 * - l0 (Current AHB Bus)
692 * - l1 (Used by nomem_amba_scan)
693 * - l2 (Used by nomem_amba_scan)
694 * - l3 (Used by nomem_amba_scan)
695 * - l4 (Used by nomem_amba_scan)
696 *
697 * - g1 (level 1 return address)
698 * - g2 (Used by nomem_amba_scan)
699 */
700_nomem_ambapp_find_buses:
701 mov %o7, %g1 /* Save return address */
702
703 /* Initialize AHB Bus storage */
704 call init_ahb_bridges
705 nop
706
707 /* Insert AHB Bus 0 */
708 call insert_ahb_bridge
709 nop /* Argument already prepared by caller */
710
711 /* Scan AHB Bus 0 for AHB Bridges */
712 call _nomem_amba_scan
713 add %g0, 1, %o1
714
715 /* Scan all AHB Buses found for more AHB Bridges */
716 add %g0, 2, %l0
717.L100_search_next_ahb_bus:
718 call get_ahb_bridge /* Get bus %l0 I/O Area */
719 mov %l0, %o0
720 cmp %o0, %g0
721 be .L100_return /* If no more AHB bus is left to be scanned, proceed */
722 nop
723 call _nomem_amba_scan /* Scan bus %l0 for AHB Bridges. i0-i7,l0 is used */
724 mov %l0, %o1 /* I/O AREA untouched in o0 */
725 ba .L100_search_next_ahb_bus /* Do next bus */
726 add %l0, 1, %l0
727
728.L100_return:
729 mov %g1, %o7
730 retl
731 nop
732
733
734/* FUNCTION _nomem_amba_init(unsigned int ioarea)
735 *
736 * Find all AHB buses
737 *
738 * Constraints:
739 * i6, i7, o6, o7, l7, l6, g3, g4, g5, g6, g7 is used by caller
740 *
741 * Arguments
742 * - o0 Bridge Information: I/O AREA and parent bus
743 *
744 * Results
745 * - o0 Number of AHB bridges found
746 *
747 * Clobbered
748 * - l0, l1, l2, l3, l4, g1, g2 (used by _nomem_ambapp_find_buses)
749 * - o0, o1, o2, o3 (Used as arguments)
750 * - o5 (return address)
751 * - g1 (level 1 return address)
752 * - g2 (level 2 return address)
753 */
754_nomem_amba_init:
755 mov %o7, %o5 /* Save return address, o5 not used */
756
757 /* Scan for buses, it will init i0-i5 */
758 call _nomem_ambapp_find_buses
759 nop
760
761 mov %o5, %o7
762 retl
763 nop
764
765/* Call tree and their return address register
766 *
767 *_nomem_amba_scan (g1)
768 * -> init_ahb_bridges (o7)
769 * -> insert_ahb_bridge (o7)
770 * -> _nomem_amba_scan (g2)
771 * -> insert_ahb_bridge (o7)
772 * -> get_ahb_bridge (o7)
773 *
774 *
775 * -> _nomem_find_apb (g2)
776 * -> get_ahb_bridge (o7)
777 * -> _nomem_find_ahb_bus (o7)
778 * -> _nomem_find_apb_bus (o7)
779 * -> _nomem_find_ahb (g2)
780 * -> get_ahb_bridge (o7)
781 * -> _nomem_find_ahb_bus (o7)
782 * -> mem_handler.func() (o7)
783 *
784 */