1 /*
2  * Copyright (c) 2011 Aeroflex Gaisler
3  *
4  * BSD license:
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 
26 #include <asm-leon/amba.h>
27 #undef AMBA_TYPE_AHBIO_ADDR
28 #include <asm-leon/lambapp.h>
29 #include <string.h>
30 
31 #define AMBA_CONF_AREA 0xff000
32 #define AMBA_AHB_SLAVE_CONF_AREA (1 << 11)
33 #define AMBA_APB_SLAVES 16
34 
35 #define DPRINTF(p)  printf p
36 
37 /* Allocate */
38 struct ambapp_dev_hdr *
ambapp_alloc_dev_struct(int dev_type)39 ambapp_alloc_dev_struct (int dev_type)
40 {
41   int size = sizeof (struct ambapp_dev_hdr);
42   struct ambapp_dev_hdr *dev;
43 
44   if (dev_type == DEV_APB_SLV)
45     {
46       size += sizeof (struct ambapp_apb_info);
47     }
48   else
49     {
50       /* AHB */
51       size += sizeof (struct ambapp_ahb_info);
52     }
53   dev = malloc (size);
54   if (dev == NULL)
55     return NULL;
56   memset (dev, 0, size);
57   dev->devinfo = (void *) (dev + 1);
58   dev->dev_type = dev_type;
59   return dev;
60 }
61 
62 unsigned int
ambapp_addr_from(struct ambapp_mmap * mmaps,unsigned int address)63 ambapp_addr_from (struct ambapp_mmap *mmaps, unsigned int address)
64 {
65   /* no translation? */
66   if (!mmaps)
67     return address;
68 
69   while (mmaps->size)
70     {
71       if ((address >= mmaps->remote_adr)
72 	  && (address <= (mmaps->remote_adr + (mmaps->size - 1))))
73 	{
74 	  return (address - mmaps->remote_adr) + mmaps->local_adr;
75 	}
76       mmaps++;
77     }
78   return 1;
79 }
80 
81 void
ambapp_ahb_dev_init(unsigned int ioarea,struct ambapp_mmap * mmaps,struct ambapp_pnp_ahb * ahb,struct ambapp_dev_hdr * dev)82 ambapp_ahb_dev_init (unsigned int ioarea,
83 		     struct ambapp_mmap *mmaps,
84 		     struct ambapp_pnp_ahb *ahb, struct ambapp_dev_hdr *dev)
85 {
86   int bar;
87   struct ambapp_ahb_info *ahb_info;
88   unsigned int addr, mask, mbar;
89 
90   /* Setup device struct */
91   dev->vendor = ambapp_pnp_vendor (ahb->id);
92   dev->device = ambapp_pnp_device (ahb->id);
93   ahb_info = dev->devinfo;
94   ahb_info->ver = ambapp_pnp_ver (ahb->id);
95   ahb_info->irq = ambapp_pnp_irq (ahb->id);
96   ahb_info->custom[0] = (unsigned int) ahb->custom[0];
97   ahb_info->custom[1] = (unsigned int) ahb->custom[1];
98   ahb_info->custom[2] = (unsigned int) ahb->custom[2];
99 
100   DPRINTF (("+AHB device %d:%d\n", dev->device, dev->vendor));
101 
102   /* Memory BARs */
103   for (bar = 0; bar < 4; bar++)
104     {
105       mbar = ahb->mbar[bar];
106       if (mbar == 0)
107 	{
108 	  addr = 0;
109 	  mask = 0;
110 	}
111       else
112 	{
113 	  addr = ambapp_pnp_start (mbar);
114 	  if (ambapp_pnp_mbar_type (mbar) == AMBA_TYPE_AHBIO)
115 	    {
116 	      /* AHB I/O area is releative IO_AREA */
117 	      addr = AMBA_TYPE_AHBIO_ADDR (addr, ioarea);
118 	      mask =
119 		(((unsigned int) (ambapp_pnp_mbar_mask ((~mbar)) << 8) |
120 		  0xff)) + 1;
121 	    }
122 	  else
123 	    {
124 	      /* AHB memory area, absolute address */
125 	      addr = ambapp_addr_from (mmaps, addr);
126 	      mask =
127 		(~((unsigned int) (ambapp_pnp_mbar_mask (mbar) << 20))) + 1;
128 	    }
129 	}
130       ahb_info->start[bar] = addr;
131       ahb_info->mask[bar] = mask;
132     }
133 }
134 
135 void
ambapp_apb_dev_init(unsigned int base,struct ambapp_mmap * mmaps,struct ambapp_pnp_apb * apb,struct ambapp_dev_hdr * dev)136 ambapp_apb_dev_init (unsigned int base,
137 		     struct ambapp_mmap *mmaps,
138 		     struct ambapp_pnp_apb *apb, struct ambapp_dev_hdr *dev)
139 {
140   struct ambapp_apb_info *apb_info;
141 
142   /* Setup device struct */
143   dev->vendor = ambapp_pnp_vendor (apb->id);
144   dev->device = ambapp_pnp_device (apb->id);
145   apb_info = dev->devinfo;
146   apb_info->ver = ambapp_pnp_ver (apb->id);
147   apb_info->irq = ambapp_pnp_irq (apb->id);
148   apb_info->start = ambapp_pnp_apb_start (apb->iobar, base);
149   apb_info->mask = ambapp_pnp_apb_mask (apb->iobar);
150 
151   DPRINTF (("+APB device %d:%d\n", dev->device, dev->vendor));
152 
153 
154 }
155 
156 #define MAX_NUM_BUSES 16
157 void
ambapp_add_scanned_bus(unsigned int * ioareas,unsigned int ioarea)158 ambapp_add_scanned_bus (unsigned int *ioareas, unsigned int ioarea)
159 {
160   int i;
161   for (i = 0; i < MAX_NUM_BUSES; i++)
162     {
163       if (ioareas[i] == 0)
164 	{
165 	  ioareas[i] = ioarea;
166 	  return;
167 	}
168     }
169 }
170 
171 int
ambapp_has_been_scanned(unsigned int * ioareas,unsigned int ioarea)172 ambapp_has_been_scanned (unsigned int *ioareas, unsigned int ioarea)
173 {
174   int i;
175   if (!ioareas)
176     return 0;
177 
178   for (i = 0; i < MAX_NUM_BUSES; i++)
179     {
180       if (ioareas[i] == 0)
181 	{
182 	  break;
183 	}
184       else if (ioareas[i] == ioarea)
185 	{
186 	  return 1;
187 	}
188     }
189   return 0;
190 }
191 
192 int
ambapp_scan(unsigned int ioarea,struct ambapp_dev_hdr * parent,struct ambapp_mmap * mmaps,void * (* memfunc)(void * dest,const void * src,int n),struct ambapp_dev_hdr ** root,void * internal)193 ambapp_scan (unsigned int ioarea,
194 	     struct ambapp_dev_hdr *parent,
195 	     struct ambapp_mmap *mmaps,
196 	     void *(*memfunc) (void *dest, const void *src, int n),
197 	     struct ambapp_dev_hdr **root, void *internal)
198 {
199   struct ambapp_pnp_ahb *ahb, ahb_buf;
200   struct ambapp_pnp_apb *apb, apb_buf;
201   struct ambapp_dev_hdr *dev, *prev, *prevapb, *apbdev;
202   struct ambapp_ahb_info *ahb_info;
203   int maxloops = 64;
204   unsigned int apbbase, bridge_address;
205   int i, j;
206 
207   DPRINTF (("Scan at 0x%08x\n", ioarea));
208 
209   /* Default to memcpy() */
210   if (!memfunc)
211     memfunc = (void *(*)(void *dest, const void *src, int n)) memcpy;
212 
213   *root = NULL;
214 
215   if (parent)
216     {
217       /* scan first bus for 64 devices, rest for 16 devices */
218       maxloops = 16;
219     }
220   else
221     {
222       DPRINTF (("+(malloc:"));
223       internal = malloc (sizeof (unsigned int) * MAX_NUM_BUSES);
224       DPRINTF (("0x%x)\n", internal));
225 
226       if (!internal)
227 	return -1;
228       memset (internal, 0, sizeof (unsigned int) * MAX_NUM_BUSES);
229 
230       ambapp_add_scanned_bus (internal, ioarea);
231     }
232 
233   prev = parent;
234 
235   /* AHB MASTERS */
236   ahb = (struct ambapp_pnp_ahb *) (ioarea | AMBA_CONF_AREA);
237   for (i = 0; i < maxloops; i++)
238     {
239       memfunc (&ahb_buf, ahb, sizeof (struct ambapp_pnp_ahb));
240       if (ahb_buf.id != 0)
241 	{
242 	  /* A AHB device present here */
243 	  dev = ambapp_alloc_dev_struct (DEV_AHB_MST);
244 	  if (!dev)
245 	    return -1;
246 
247 	  ambapp_ahb_dev_init (ioarea, mmaps, &ahb_buf, dev);
248 
249 	  if (*root == NULL)
250 	    *root = dev;
251 
252 	  if (prev != parent)
253 	    prev->next = dev;
254 	  dev->prev = prev;
255 	  prev = dev;
256 	}
257       ahb++;
258     }
259 
260   /* AHB SLAVES */
261   ahb =
262     (struct ambapp_pnp_ahb *) (ioarea | AMBA_CONF_AREA |
263 			       AMBA_AHB_SLAVE_CONF_AREA);
264   for (i = 0; i < maxloops; i++)
265     {
266       memfunc (&ahb_buf, ahb, sizeof (struct ambapp_pnp_ahb));
267       if (ahb_buf.id != 0)
268 	{
269 	  /* A AHB device present here */
270 	  dev = ambapp_alloc_dev_struct (DEV_AHB_SLV);
271 	  if (!dev)
272 	    return -1;
273 
274 	  ambapp_ahb_dev_init (ioarea, mmaps, &ahb_buf, dev);
275 
276 	  if (prev != parent)
277 	    prev->next = dev;
278 	  dev->prev = prev;
279 	  prev = dev;
280 
281 	  /* Is it a AHB/AHB Bridge ? */
282 	  if ((dev->device == GAISLER_AHB2AHB)
283 	      && (dev->vendor == VENDOR_GAISLER))
284 	    {
285 	      /* AHB/AHB Bridge Found, recurse down the Bridge */
286 	      ahb_info = dev->devinfo;
287 	      if (ahb_info->ver)
288 		{
289 		  bridge_address =
290 		    ambapp_addr_from (mmaps, ahb_info->custom[1]);
291 
292 		  DPRINTF (("+(AHBAHB:0x%x)\n", bridge_address));
293 
294 		  /* Makes sure bus only scanned once */
295 		  if (ambapp_has_been_scanned (internal, bridge_address) ==
296 		      NULL)
297 		    {
298 		      ambapp_add_scanned_bus (internal, bridge_address);
299 		      if (ambapp_scan
300 			  (bridge_address, dev, mmaps, memfunc,
301 			   &dev->children, internal))
302 			return -1;
303 		    }
304 		}
305 	    }
306 	  else if ((dev->device == GAISLER_APBMST)
307 		   && (dev->vendor == VENDOR_GAISLER))
308 	    {
309 	      /* AHB/APB Bridge Found, add the APB devices to this AHB Slave's children */
310 	      prevapb = dev;
311 	      ahb_info = dev->devinfo;
312 	      apbbase = ahb_info->start[0];
313 	      apb = (struct ambapp_pnp_apb *) (apbbase | AMBA_CONF_AREA);
314 	      for (j = 0; j < AMBA_APB_SLAVES; j++)
315 		{
316 		  memfunc (&apb_buf, apb, sizeof (struct ambapp_pnp_apb));
317 		  if (apb_buf.id)
318 		    {
319 		      apbdev = ambapp_alloc_dev_struct (DEV_APB_SLV);
320 		      if (!dev)
321 			return -1;
322 
323 		      ambapp_apb_dev_init (apbbase, mmaps, &apb_buf, apbdev);
324 
325 		      if (prevapb != dev)
326 			prevapb->next = apbdev;
327 		      else
328 			dev->children = apbdev;
329 		      apbdev->prev = prevapb;
330 		      prevapb = apbdev;
331 		    }
332 		  apb++;
333 		}
334 	    }
335 	}
336       ahb++;
337     }
338 
339   if (parent == NULL)
340     {
341       free (internal);
342     }
343 
344   return 0;
345 }
346 
347 /* Match search options againt device */
348 int
ambapp_dev_match_options(struct ambapp_dev_hdr * dev,unsigned int options,int vendor,int device)349 ambapp_dev_match_options (struct ambapp_dev_hdr *dev, unsigned int options,
350 			  int vendor, int device)
351 {
352   if ((((options & (OPTIONS_ALL_DEVS)) == OPTIONS_ALL_DEVS) ||	/* Match TYPE */
353        ((options & OPTIONS_AHB_MSTS) && (dev->dev_type == DEV_AHB_MST)) || ((options & OPTIONS_AHB_SLVS) && (dev->dev_type == DEV_AHB_SLV)) || ((options & OPTIONS_APB_SLVS) && (dev->dev_type == DEV_APB_SLV))) && ((vendor == -1) || (vendor == dev->vendor)) &&	/* Match ID */
354       ((device == -1) || (device == dev->device)) && (((options & OPTIONS_ALL) == OPTIONS_ALL) ||	/* Match Allocated State */
355 						      ((options &
356 							OPTIONS_FREE)
357 						       && DEV_IS_FREE (dev))
358 						      ||
359 						      ((options &
360 							OPTIONS_ALLOCATED)
361 						       &&
362 						       DEV_IS_ALLOCATED
363 						       (dev))))
364     {
365       return 1;
366     }
367   return 0;
368 }
369 
370 /* If device is an APB bridge all devices on the APB bridge is processed */
371 static int
ambapp_for_each_apb(struct ambapp_dev_hdr * dev,unsigned int options,int vendor,int device,int maxdepth,ambapp_func_t func,void * arg)372 ambapp_for_each_apb (struct ambapp_dev_hdr *dev,
373 		     unsigned int options,
374 		     int vendor,
375 		     int device, int maxdepth, ambapp_func_t func, void *arg)
376 {
377   int index;
378   struct ambapp_dev_hdr *apbslv;
379 
380   if (maxdepth < 0)
381     return 0;
382 
383   if (dev->children && (dev->children->dev_type == DEV_APB_SLV))
384     {
385       /* Found a APB Bridge */
386       index = 0;
387       apbslv = dev->children;
388       while (apbslv)
389 	{
390 	  if (ambapp_dev_match_options (apbslv, options, vendor, device) == 1)
391 	    {
392 	      if (func (apbslv, index, maxdepth, arg) == 1)
393 		return 1;	/* Signalled stopped */
394 	    }
395 	  index++;
396 	  apbslv = apbslv->next;
397 	}
398     }
399   return 0;
400 }
401 
402 /* Traverse the prescanned device information */
403 int
ambapp_for_each(struct ambapp_dev_hdr * root,unsigned int options,int vendor,int device,int maxdepth,ambapp_func_t func,void * arg)404 ambapp_for_each (struct ambapp_dev_hdr *root,
405 		 unsigned int options,
406 		 int vendor,
407 		 int device, int maxdepth, ambapp_func_t func, void *arg)
408 {
409   struct ambapp_dev_hdr *dev;
410   int ahb_slave = 0;
411   int index;
412 
413   if (maxdepth < 0)
414     return 0;
415 
416   /* Start at device 'root' and process downwards.
417    *
418    * Breadth first search, search order
419    * 1. AHB MSTS
420    * 2. AHB SLVS
421    * 3. APB SLVS on primary bus
422    * 4. AHB/AHB secondary... -> step to 1.
423    */
424 
425   /* AHB MST / AHB SLV */
426   if (options & (OPTIONS_AHB_MSTS | OPTIONS_AHB_SLVS | OPTIONS_DEPTH_FIRST))
427     {
428       index = 0;
429       dev = root;
430       while (dev)
431 	{
432 	  if ((dev->dev_type == DEV_AHB_SLV) && !ahb_slave)
433 	    {
434 	      /* First AHB Slave */
435 	      ahb_slave = 1;
436 	      index = 0;
437 	    }
438 
439 	  /* Conditions must be fullfilled for function to be called */
440 	  if (ambapp_dev_match_options (dev, options, vendor, device) == 1)
441 	    {
442 	      /* Correct device and vendor ID */
443 	      if (func (dev, index, maxdepth, arg) == 1)
444 		return 1;	/* Signalled stopped */
445 	    }
446 
447 	  if ((options & OPTIONS_DEPTH_FIRST) && (options & OPTIONS_APB_SLVS))
448 	    {
449 	      /* Check is APB bridge, and process all APB Slaves in that case */
450 	      if (ambapp_for_each_apb
451 		  (dev, options, vendor, device, (maxdepth - 1), func,
452 		   arg) == 1)
453 		return 1;	/* Signalled stopped */
454 	    }
455 
456 	  if (options & OPTIONS_DEPTH_FIRST)
457 	    {
458 	      if (dev->children && (dev->children->dev_type != DEV_APB_SLV))
459 		{
460 		  /* Found AHB Bridge, recurse */
461 		  if (ambapp_for_each
462 		      (dev->children, options, vendor, device, (maxdepth - 1),
463 		       func, arg) == 1)
464 		    return 1;
465 		}
466 	    }
467 
468 	  index++;
469 	  dev = dev->next;
470 	}
471     }
472 
473   /* Find APB Bridges */
474   if ((options & OPTIONS_APB_SLVS) && !(options & OPTIONS_DEPTH_FIRST))
475     {
476       dev = root;
477       while (dev)
478 	{
479 	  /* Check is APB bridge, and process all APB Slaves in that case */
480 	  if (ambapp_for_each_apb
481 	      (dev, options, vendor, device, (maxdepth - 1), func, arg) == 1)
482 	    return 1;		/* Signalled stopped */
483 	  dev = dev->next;
484 	}
485     }
486 
487   /* Find AHB Bridges */
488   if (!(options & OPTIONS_DEPTH_FIRST))
489     {
490       dev = root;
491       while (dev)
492 	{
493 	  if (dev->children && (dev->children->dev_type != DEV_APB_SLV))
494 	    {
495 	      /* Found AHB Bridge, recurse */
496 	      if (ambapp_for_each
497 		  (dev->children, options, vendor, device, (maxdepth - 1),
498 		   func, arg) == 1)
499 		return 1;
500 	    }
501 	  dev = dev->next;
502 	}
503     }
504 
505   return 0;
506 }
507 
508 int
ambapp_alloc_dev(struct ambapp_dev_hdr * dev,void * owner)509 ambapp_alloc_dev (struct ambapp_dev_hdr *dev, void *owner)
510 {
511   if (dev->owner)
512     return -1;
513   dev->owner = owner;
514   return 0;
515 }
516 
517 void
ambapp_free_dev(struct ambapp_dev_hdr * dev)518 ambapp_free_dev (struct ambapp_dev_hdr *dev)
519 {
520   dev->owner = NULL;
521 }
522 
523 struct ambapp_dev_find_match_arg
524 {
525   int index;
526   int count;
527   int type;
528   void *dev;
529 };
530 
531 /* AMBA PP find routines */
532 int
ambapp_dev_find_match(struct ambapp_dev_hdr * dev,int index,int maxdepth,void * arg)533 ambapp_dev_find_match (struct ambapp_dev_hdr *dev, int index, int maxdepth,
534 		       void *arg)
535 {
536   struct ambapp_dev_find_match_arg *p = arg;
537 
538   if (p->index == 0)
539     {
540       /* Found controller, stop */
541       if (p->type == DEV_APB_SLV)
542 	{
543 	  *(struct ambapp_apb_info *) p->dev =
544 	    *(struct ambapp_apb_info *) dev->devinfo;
545 	  p->dev = ((struct ambapp_apb_info *) p->dev) + 1;
546 	}
547       else
548 	{
549 	  *(struct ambapp_ahb_info *) p->dev =
550 	    *(struct ambapp_ahb_info *) dev->devinfo;
551 	  p->dev = ((struct ambapp_ahb_info *) p->dev) + 1;
552 	}
553       p->count--;
554       if (p->count < 1)
555 	return 1;
556     }
557   else
558     {
559       p->index--;
560     }
561   return 0;
562 }
563 
564 int
ambapp_find_apbslvs_next(struct ambapp_dev_hdr * root,int vendor,int device,struct ambapp_apb_info * dev,int index,int maxno)565 ambapp_find_apbslvs_next (struct ambapp_dev_hdr *root, int vendor, int device,
566 			  struct ambapp_apb_info *dev, int index, int maxno)
567 {
568   struct ambapp_dev_find_match_arg arg;
569 
570   arg.index = index;
571   arg.count = maxno;
572   arg.type = DEV_APB_SLV;	/* APB */
573   arg.dev = dev;
574 
575   ambapp_for_each (root, (OPTIONS_ALL | OPTIONS_APB_SLVS), vendor, device, 10,
576 		   ambapp_dev_find_match, &arg);
577 
578   return maxno - arg.count;
579 }
580 
581 int
ambapp_find_apbslv(struct ambapp_dev_hdr * root,int vendor,int device,struct ambapp_apb_info * dev)582 ambapp_find_apbslv (struct ambapp_dev_hdr *root, int vendor, int device,
583 		    struct ambapp_apb_info *dev)
584 {
585   return ambapp_find_apbslvs_next (root, vendor, device, dev, 0, 1);
586 }
587 
588 int
ambapp_find_apbslv_next(struct ambapp_dev_hdr * root,int vendor,int device,struct ambapp_apb_info * dev,int index)589 ambapp_find_apbslv_next (struct ambapp_dev_hdr *root, int vendor, int device,
590 			 struct ambapp_apb_info *dev, int index)
591 {
592   return ambapp_find_apbslvs_next (root, vendor, device, dev, index, 1);
593 }
594 
595 int
ambapp_find_apbslvs(struct ambapp_dev_hdr * root,int vendor,int device,struct ambapp_apb_info * dev,int maxno)596 ambapp_find_apbslvs (struct ambapp_dev_hdr *root, int vendor, int device,
597 		     struct ambapp_apb_info *dev, int maxno)
598 {
599   return ambapp_find_apbslvs_next (root, vendor, device, dev, 0, maxno);
600 }
601 
602 int
ambapp_find_ahbslvs_next(struct ambapp_dev_hdr * root,int vendor,int device,struct ambapp_ahb_info * dev,int index,int maxno)603 ambapp_find_ahbslvs_next (struct ambapp_dev_hdr *root, int vendor, int device,
604 			  struct ambapp_ahb_info *dev, int index, int maxno)
605 {
606   struct ambapp_dev_find_match_arg arg;
607 
608   arg.index = index;
609   arg.count = maxno;
610   arg.type = DEV_AHB_SLV;	/* AHB SLV */
611   arg.dev = dev;
612 
613   ambapp_for_each (root, (OPTIONS_ALL | OPTIONS_AHB_SLVS), vendor, device, 10,
614 		   ambapp_dev_find_match, &arg);
615 
616   return maxno - arg.count;
617 }
618 
619 int
ambapp_find_ahbslv_next(struct ambapp_dev_hdr * root,int vendor,int device,struct ambapp_ahb_info * dev,int index)620 ambapp_find_ahbslv_next (struct ambapp_dev_hdr *root, int vendor, int device,
621 			 struct ambapp_ahb_info *dev, int index)
622 {
623   return ambapp_find_ahbslvs_next (root, vendor, device, dev, index, 1);
624 }
625 
626 int
ambapp_find_ahbslv(struct ambapp_dev_hdr * root,int vendor,int device,struct ambapp_ahb_info * dev)627 ambapp_find_ahbslv (struct ambapp_dev_hdr *root, int vendor, int device,
628 		    struct ambapp_ahb_info *dev)
629 {
630   return ambapp_find_ahbslvs_next (root, vendor, device, dev, 0, 1);
631 }
632 
633 int
ambapp_find_ahbslvs(struct ambapp_dev_hdr * root,int vendor,int device,struct ambapp_ahb_info * dev,int maxno)634 ambapp_find_ahbslvs (struct ambapp_dev_hdr *root, int vendor, int device,
635 		     struct ambapp_ahb_info *dev, int maxno)
636 {
637   return ambapp_find_ahbslvs_next (root, vendor, device, dev, 0, maxno);
638 }
639 
640 struct ambapp_dev_hdr *
ambapp_find_parent(struct ambapp_dev_hdr * dev)641 ambapp_find_parent (struct ambapp_dev_hdr *dev)
642 {
643   while (dev->prev)
644     {
645       if (dev == dev->prev->children)
646 	{
647 	  return dev->prev;
648 	}
649       dev = dev->prev;
650     }
651   return NULL;
652 }
653 
654 
655 struct ambapp_dev_hdr *ambapp_root = NULL;
656 extern unsigned int console;
657 extern unsigned int rtc;
658 
659 void
pnpinit(void)660 pnpinit (void)
661 {
662   struct ambapp_apb_info dev;
663   int n;
664   ambapp_scan (LEON3_IO_AREA, NULL, NULL, NULL, &ambapp_root, NULL);
665   if ((n =
666        ambapp_find_apbslv (ambapp_root, VENDOR_GAISLER, GAISLER_APBUART,
667 			   &dev)) == 1)
668     {
669       console = dev.start;
670       DPRINTF (("Found abuart at 0x%x\n", console));
671     }
672   if ((n =
673        ambapp_find_apbslv (ambapp_root, VENDOR_GAISLER, GAISLER_GPTIMER,
674 			   &dev)) == 1)
675     {
676       rtc = dev.start + 0x10;
677       DPRINTF (("Found rtc at 0x%x\n", rtc));
678     }
679 }
680