source: rtems/c/src/lib/libbsp/sparc/shared/amba/ambapp.c @ 2eb4aba9

4.104.114.84.95
Last change on this file since 2eb4aba9 was 2eb4aba9, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 6, 2007 at 12:01:53 AM

2007-09-05 Daniel Hellstrom <daniel@…>

  • shared/amba/ambapp.c, shared/include/ambapp.h: New files.
  • Property mode set to 100644
File size: 15.7 KB
Line 
1/*
2 *  AMBA Plag & Play Bus Driver
3 *
4 *  This driver hook performs bus scanning.
5 *
6 *  COPYRIGHT (c) 2004.
7 *  Gaisler Research
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.rtems.com/license/LICENSE.
12 *
13 *  $Id$
14 */
15
16#include <bsp.h>
17#include <rtems/bspIo.h>
18#include <ambapp.h>
19
20#define amba_insert_device(tab, address) \
21{ \
22  if (*(address)) \
23  { \
24    (tab)->addr[(tab)->devnr] = (address); \
25    (tab)->devnr ++; \
26  } \
27} while(0)
28
29#define amba_insert_apb_device(tab, address, apbmst) \
30{ \
31  if (*(address)) \
32  { \
33    (tab)->addr[(tab)->devnr] = (address); \
34                (tab)->apbmst[(tab)->devnr] = (apbmst); \
35    (tab)->devnr ++; \
36  } \
37} while(0)
38
39static unsigned int
40addr_from (struct amba_mmap *mmaps, unsigned int address)
41{
42  /* no translation? */
43  if (!mmaps)
44    return address;
45
46  while (mmaps->size) {
47    if ((address >= mmaps->remote_amba_adr)
48        && (address <= (mmaps->remote_amba_adr + (mmaps->size - 1)))) {
49      return (address - mmaps->remote_amba_adr) + mmaps->cpu_adr;
50    }
51    mmaps++;
52  }
53  return 1;
54}
55
56
57void
58amba_scan (amba_confarea_type * amba_conf, unsigned int ioarea,
59           struct amba_mmap *mmaps)
60{
61  unsigned int *cfg_area;       /* address to configuration area */
62  unsigned int mbar, conf, custom;
63  int i, j;
64  unsigned int apbmst;
65  int maxloops = amba_conf->notroot ? 16 : 64; /* scan first bus for 64 devices, rest for 16 devices */
66
67  amba_conf->ahbmst.devnr = 0;
68  amba_conf->ahbslv.devnr = 0;
69  amba_conf->apbslv.devnr = 0;
70  cfg_area = (unsigned int *) (ioarea | AMBA_CONF_AREA);
71  amba_conf->ioarea = ioarea;
72  amba_conf->mmaps = mmaps;
73
74  for (i = 0; i < maxloops; i++) {
75    amba_insert_device (&amba_conf->ahbmst, cfg_area);
76    cfg_area += AMBA_AHB_CONF_WORDS;
77  }
78
79  cfg_area =
80    (unsigned int *) (ioarea | AMBA_CONF_AREA | AMBA_AHB_SLAVE_CONF_AREA);
81  for (i = 0; i < maxloops; i++) {
82    amba_insert_device (&amba_conf->ahbslv, cfg_area);
83    cfg_area += AMBA_AHB_CONF_WORDS;
84  }
85
86  for (i = 0; i < amba_conf->ahbslv.devnr; i++){
87    conf = amba_get_confword(amba_conf->ahbslv, i, 0);
88    mbar = amba_ahb_get_membar(amba_conf->ahbslv, i, 0);
89    if ( (amba_vendor(conf) == VENDOR_GAISLER) && (amba_device(conf) == GAISLER_AHB2AHB) ){
90      /* Found AHB->AHB bus bridge, scan it if more free amba_confarea_type:s available
91       * Custom config 1 contain ioarea.
92       */
93      custom = amba_ahb_get_custom(amba_conf->ahbslv,i,1);
94     
95      if ( amba_ver(conf) && amba_conf->next ){
96        amba_conf->next->notroot = 1;
97        amba_scan(amba_conf->next,custom,mmaps);
98      }
99    }else if ((amba_vendor(conf) == VENDOR_GAISLER) && (amba_device(conf) == GAISLER_APBMST))
100    {
101      apbmst = amba_membar_start(mbar);
102                        if ( (apbmst=addr_from(mmaps,apbmst)) == 1 )
103                                continue; /* no available memory translation available, will not be able to access
104                                           * Plug&Play information for this AHB/APB bridge. Skip it.
105                                           */
106                        cfg_area = (unsigned int *)( apbmst | AMBA_CONF_AREA);
107      for (j=0; (amba_conf->apbslv.devnr<AMBA_APB_SLAVES) && (j<AMBA_APB_SLAVES); j++){
108        amba_insert_apb_device(&amba_conf->apbslv, cfg_area, apbmst);
109        cfg_area += AMBA_APB_CONF_WORDS;
110      }
111    }
112  }
113}
114
115void
116amba_print_dev(int devno, unsigned int conf){
117        int irq = amba_irq(conf);
118        if ( irq > 0 ){
119                printk("%x.%x.%x: irq %d\n",devno,amba_vendor(conf),amba_device(conf),irq);
120        }else{
121                printk("%x.%x.%x: no irq\n",devno,amba_vendor(conf),amba_device(conf));
122        }
123}
124
125void 
126amba_apb_print_dev(int devno, unsigned int conf, unsigned int address){
127        int irq = amba_irq(conf);
128        if ( irq > 0 ){
129                printk("%x.%x.%x: irq %d, apb: 0x%lx\n",devno,amba_vendor(conf),amba_device(conf),irq,address);
130        }else{
131                printk("%x.%x.%x: no irq, apb: 0x%lx\n",devno,amba_vendor(conf),amba_device(conf),address);
132        }
133}
134
135/* Print AMBA Plug&Play info on terminal */
136void
137amba_print_conf (amba_confarea_type * amba_conf)
138{
139        int i,base=0;
140        unsigned int conf, iobar, address;
141        unsigned int apbmst;
142       
143        /* print all ahb masters */
144        printk("--- AMBA AHB Masters ---\n");
145        for(i=0; i<amba_conf->ahbmst.devnr; i++){
146                conf = amba_get_confword(amba_conf->ahbmst, i, 0);
147                amba_print_dev(i,conf);
148        }
149       
150        /* print all ahb slaves */
151        printk("--- AMBA AHB Slaves ---\n");
152        for(i=0; i<amba_conf->ahbslv.devnr; i++){
153                conf = amba_get_confword(amba_conf->ahbslv, i, 0);
154                amba_print_dev(i,conf);
155        }
156
157        /* print all apb slaves */
158        apbmst = 0;
159        for(i=0; i<amba_conf->apbslv.devnr; i++){
160                if ( apbmst != amba_conf->apbslv.apbmst[i] ){
161                        apbmst = amba_conf->apbslv.apbmst[i];
162                        printk("--- AMBA APB Slaves on 0x%x ---\n",apbmst);
163                        base=i;
164                }
165                conf = amba_get_confword(amba_conf->apbslv, i, 0);
166    iobar = amba_apb_get_membar(amba_conf->apbslv, i);
167    address = amba_iobar_start(amba_conf->apbslv.apbmst[i], iobar);
168                amba_apb_print_dev(i-base,conf,address);
169        }
170       
171}
172/**** APB Slaves ****/
173
174/* Return number of APB Slave devices which has given vendor and device */
175int
176amba_get_number_apbslv_devices (amba_confarea_type * amba_conf, int vendor,
177                                int device)
178{
179  unsigned int conf;
180  int cnt, i;
181
182  for (cnt = i = 0; i < amba_conf->apbslv.devnr; i++) {
183    conf = amba_get_confword (amba_conf->apbslv, i, 0);
184    if ((amba_vendor (conf) == vendor) && (amba_device (conf) == device))
185      cnt++;
186  }
187  return cnt;
188}
189
190/* Get First APB Slave device of this vendor&device id */
191int
192amba_find_apbslv (amba_confarea_type * amba_conf, int vendor, int device,
193                  amba_apb_device * dev)
194{
195  unsigned int conf, iobar;
196  int i;
197
198  for (i = 0; i < amba_conf->apbslv.devnr; i++) {
199    conf = amba_get_confword (amba_conf->apbslv, i, 0);
200    if ((amba_vendor (conf) == vendor) && (amba_device (conf) == device)) {
201      iobar = amba_apb_get_membar (amba_conf->apbslv, i);
202      dev->start = amba_iobar_start (amba_conf->apbslv.apbmst[i], iobar);
203      dev->irq = amba_irq (conf);
204      return 1;
205    }
206  }
207  return 0;
208}
209
210/* Get APB Slave device of this vendor&device id. (setting nr to 0 is eqivalent to calling amba_find_apbslv() ) */
211int
212amba_find_next_apbslv (amba_confarea_type * amba_conf, int vendor, int device,
213                       amba_apb_device * dev, int index)
214{
215  unsigned int conf, iobar;
216  int cnt, i;
217
218  for (cnt = i = 0; i < amba_conf->apbslv.devnr; i++) {
219    conf = amba_get_confword (amba_conf->apbslv, i, 0);
220    if ((amba_vendor (conf) == vendor) && (amba_device (conf) == device)) {
221      if (cnt == index) {
222        /* found device */
223        iobar = amba_apb_get_membar (amba_conf->apbslv, i);
224        dev->start = amba_iobar_start (amba_conf->apbslv.apbmst[i], iobar);
225        dev->irq = amba_irq (conf);
226        return 1;
227      }
228      cnt++;
229    }
230  }
231  return 0;
232}
233
234/* Get first nr APB Slave devices, put them into dev (which is an array of nr length) */
235int
236amba_find_apbslvs (amba_confarea_type * amba_conf, int vendor, int device,
237                   amba_apb_device * devs, int maxno)
238{
239  unsigned int conf, iobar;
240  int cnt, i;
241
242  for (cnt = i = 0; (i < amba_conf->apbslv.devnr) && (cnt < maxno); i++) {
243    conf = amba_get_confword (amba_conf->apbslv, i, 0);
244    if ((amba_vendor (conf) == vendor) && (amba_device (conf) == device)) {
245      /* found device */
246      iobar = amba_apb_get_membar (amba_conf->apbslv, i);
247      devs[cnt].start = amba_iobar_start (amba_conf->apbslv.apbmst[i], iobar);
248      devs[cnt].irq = amba_irq (conf);
249      cnt++;
250    }
251  }
252  return cnt;
253}
254
255/***** AHB SLAVES *****/
256
257/* Return number of AHB Slave devices which has given vendor and device */
258int
259amba_get_number_ahbslv_devices (amba_confarea_type * amba_conf, int vendor,
260                                int device)
261{
262  unsigned int conf;
263  int cnt, i;
264
265  for (cnt = i = 0; i < amba_conf->ahbslv.devnr; i++) {
266    conf = amba_get_confword (amba_conf->ahbslv, i, 0);
267    if ((amba_vendor (conf) == vendor) && (amba_device (conf) == device))
268      cnt++;
269  }
270  return cnt;
271}
272
273/* Get First AHB Slave device of this vendor&device id */
274int
275amba_find_ahbslv (amba_confarea_type * amba_conf, int vendor, int device,
276                  amba_ahb_device * dev)
277{
278  unsigned int conf, mbar, addr;
279  int j, i;
280
281  for (i = 0; i < amba_conf->ahbslv.devnr; i++) {
282    conf = amba_get_confword (amba_conf->ahbslv, i, 0);
283    if ((amba_vendor (conf) == vendor) && (amba_device (conf) == device)) {
284      for (j = 0; j < 4; j++) {
285        mbar = amba_ahb_get_membar (amba_conf->ahbslv, i, j);
286        addr = amba_membar_start (mbar);
287        if (amba_membar_type (mbar) == AMBA_TYPE_AHBIO) {
288          addr = AMBA_TYPE_AHBIO_ADDR (addr, amba_conf->ioarea);
289        } else {                /* convert address if needed */
290          if ((addr = addr_from (amba_conf->mmaps, addr)) == 1) {
291            addr = 0;           /* no available memory translation available, will not be able to access
292                                 * Plug&Play information for this AHB address. Skip it.
293                                 */
294          }
295        }
296        dev->start[j] = addr;
297      }
298      dev->irq = amba_irq (conf);
299      dev->ver = amba_ver (conf);
300      return 1;
301    }
302  }
303  return 0;
304}
305
306/* Get AHB Slave device of this vendor&device id. (setting nr to 0 is eqivalent to calling amba_find_ahbslv() ) */
307int
308amba_find_next_ahbslv (amba_confarea_type * amba_conf, int vendor, int device,
309                       amba_ahb_device * dev, int index)
310{
311  unsigned int conf, mbar, addr;
312  int i, j, cnt;
313
314  for (cnt = i = 0; i < amba_conf->ahbslv.devnr; i++) {
315    conf = amba_get_confword (amba_conf->ahbslv, i, 0);
316    if ((amba_vendor (conf) == vendor) && (amba_device (conf) == device)) {
317      if (cnt == index) {
318        for (j = 0; j < 4; j++) {
319          mbar = amba_ahb_get_membar (amba_conf->ahbslv, i, j);
320          addr = amba_membar_start (mbar);
321          if (amba_membar_type (mbar) == AMBA_TYPE_AHBIO) {
322            addr = AMBA_TYPE_AHBIO_ADDR (addr, amba_conf->ioarea);
323          } else {
324            /* convert address if needed */
325            if ((addr = addr_from (amba_conf->mmaps, addr)) == 1) {
326              addr = 0;         /* no available memory translation available, will not be able to access
327                                 * Plug&Play information for this AHB address. Skip it.
328                                 */
329            }
330          }
331          dev->start[j] = addr;
332        }
333        dev->irq = amba_irq (conf);
334        dev->ver = amba_ver (conf);
335        return 1;
336      }
337      cnt++;
338    }
339  }
340  return 0;
341}
342
343/* Get first nr AHB Slave devices, put them into dev (which is an array of nr length) */
344int
345amba_find_ahbslvs (amba_confarea_type * amba_conf, int vendor, int device,
346                   amba_ahb_device * devs, int maxno)
347{
348  unsigned int conf, mbar, addr;
349  int i, j, cnt;
350
351  for (cnt = i = 0; (i < amba_conf->ahbslv.devnr) && (maxno < cnt); i++) {
352    conf = amba_get_confword (amba_conf->ahbslv, i, 0);
353    if ((amba_vendor (conf) == vendor) && (amba_device (conf) == device)) {
354      for (j = 0; j < 4; j++) {
355        mbar = amba_ahb_get_membar (amba_conf->ahbslv, i, j);
356        addr = amba_membar_start (mbar);
357        if (amba_membar_type (mbar) == AMBA_TYPE_AHBIO) {
358          addr = AMBA_TYPE_AHBIO_ADDR (addr, amba_conf->ioarea);
359        } else {
360          /* convert address if needed */
361          if ((addr = addr_from (amba_conf->mmaps, addr)) == 1) {
362            addr = 0;           /* no available memory translation available, will not be able to access
363                                 * Plug&Play information for this AHB address. Skip it.
364                                 */
365          }
366        }
367        devs[cnt].start[j] = addr;
368      }
369      devs[cnt].irq = amba_irq (conf);
370      devs[cnt].ver = amba_ver (conf);
371      cnt++;
372    }
373  }
374  return cnt;
375}
376
377
378/***** AHB Masters *****/
379
380/* Return number of AHB Slave devices which has given vendor and device */
381int
382amba_get_number_ahbmst_devices (amba_confarea_type * amba_conf, int vendor,
383                                int device)
384{
385  unsigned int conf;
386  int cnt, i;
387
388  for (cnt = i = 0; i < amba_conf->ahbmst.devnr; i++) {
389    conf = amba_get_confword (amba_conf->ahbmst, i, 0);
390    if ((amba_vendor (conf) == vendor) && (amba_device (conf) == device))
391      cnt++;
392  }
393  return cnt;
394}
395
396/* Get First AHB Slave device of this vendor&device id */
397int
398amba_find_ahbmst (amba_confarea_type * amba_conf, int vendor, int device,
399                  amba_ahb_device * dev)
400{
401  unsigned int conf, mbar, addr;
402  int j, i;
403
404  for (i = 0; i < amba_conf->ahbmst.devnr; i++) {
405    conf = amba_get_confword (amba_conf->ahbslv, i, 0);
406    if ((amba_vendor (conf) == vendor) && (amba_device (conf) == device)) {
407      for (j = 0; j < 4; j++) {
408        mbar = amba_ahb_get_membar (amba_conf->ahbmst, i, j);
409        addr = amba_membar_start (mbar);
410        if (amba_membar_type (mbar) == AMBA_TYPE_AHBIO) {
411          addr = AMBA_TYPE_AHBIO_ADDR (addr, amba_conf->ioarea);
412        } else {
413          /* convert address if needed */
414          if ((addr = addr_from (amba_conf->mmaps, addr)) == 1) {
415            addr = 0;           /* no available memory translation available, will not be able to access
416                                 * Plug&Play information for this AHB address. Skip it.
417                                 */
418          }
419        }
420        dev->start[j] = addr;
421      }
422      dev->irq = amba_irq (conf);
423      dev->ver = amba_ver (conf);
424      return 1;
425    }
426  }
427  return 0;
428}
429
430/* Get AHB Slave device of this vendor&device id. (setting nr to 0 is eqivalent to calling amba_find_ahbslv() ) */
431int
432amba_find_next_ahbmst (amba_confarea_type * amba_conf, int vendor, int device,
433                       amba_ahb_device * dev, int index)
434{
435  unsigned int conf, mbar, addr;
436  int i, j, cnt;
437
438  for (cnt = i = 0; i < amba_conf->ahbmst.devnr; i++) {
439    conf = amba_get_confword (amba_conf->ahbmst, i, 0);
440    if ((amba_vendor (conf) == vendor) && (amba_device (conf) == device)) {
441      if (cnt == index) {
442        for (j = 0; j < 4; j++) {
443          mbar = amba_ahb_get_membar (amba_conf->ahbmst, i, j);
444          addr = amba_membar_start (mbar);
445          if (amba_membar_type (mbar) == AMBA_TYPE_AHBIO) {
446            addr = AMBA_TYPE_AHBIO_ADDR (addr, amba_conf->ioarea);
447          } else {
448            /* convert address if needed */
449            if ((addr = addr_from (amba_conf->mmaps, addr)) == 1) {
450              addr = 0;         /* no available memory translation available, will not be able to access
451                                 * Plug&Play information for this AHB address. Skip it.
452                                 */
453            }
454          }
455          dev->start[j] = addr;
456        }
457        dev->irq = amba_irq (conf);
458        dev->ver = amba_ver (conf);
459        return 1;
460      }
461      cnt++;
462    }
463  }
464  return 0;
465}
466
467/* Get first nr AHB Slave devices, put them into dev (which is an array of nr length) */
468int
469amba_find_ahbmsts (amba_confarea_type * amba_conf, int vendor, int device,
470                   amba_ahb_device * devs, int maxno)
471{
472  unsigned int conf, mbar, addr;
473  int i, j, cnt;
474
475  for (cnt = i = 0; (i < amba_conf->ahbmst.devnr) && (maxno < cnt); i++) {
476    conf = amba_get_confword (amba_conf->ahbslv, i, 0);
477    if ((amba_vendor (conf) == vendor) && (amba_device (conf) == device)) {
478      for (j = 0; j < 4; j++) {
479        mbar = amba_ahb_get_membar (amba_conf->ahbmst, i, j);
480        addr = amba_membar_start (mbar);
481        if (amba_membar_type (mbar) == AMBA_TYPE_AHBIO) {
482          addr = AMBA_TYPE_AHBIO_ADDR (addr, amba_conf->ioarea);
483        } else {
484          /* convert address if needed */
485          if ((addr = addr_from (amba_conf->mmaps, addr)) == 1) {
486            addr = 0;           /* no available memory translation available, will not be able to access
487                                 * Plug&Play information for this AHB address. Skip it.
488                                 */
489          }
490        }
491        devs[cnt].start[j] = addr;
492      }
493      devs[cnt].irq = amba_irq (conf);
494      devs[cnt].ver = amba_ver (conf);
495      cnt++;
496    }
497  }
498  return cnt;
499}
Note: See TracBrowser for help on using the repository browser.