source: rtems/c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus.c @ e05c265

4.115
Last change on this file since e05c265 was e05c265, checked in by Daniel Hellstrom <daniel@…>, on 12/15/11 at 16:00:38

LEON3: implemented AMBA PnP Bus Driver for Driver Manager

  • Property mode set to 100644
File size: 19.0 KB
RevLine 
[e05c265]1/*  General part of a AMBA Plug & Play bus driver.
2 *
3 *  COPYRIGHT (c) 2008.
4 *  Cobham Gaisler AB.
5 *
6 *  The license and distribution terms for this file may be
7 *  found in the file LICENSE in this distribution or at
8 *  http://www.rtems.com/license/LICENSE.
9 *
10 *  This is the general part of the different AMBA Plug & Play
11 *  drivers. The drivers are wrappers around this driver, making
12 *  the code size smaller for systems with multiple AMBA Plug &
13 *  Play buses.
14 *
15 *  The BSP define APBUART_INFO_AVAIL in order to add the info routine
16 *  used for debugging.
17 */
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
23#include <drvmgr/drvmgr.h>
24#include <drvmgr/ambapp_bus.h>
25
26#include <bsp.h>
27#include <ambapp.h>
28
29/*#define DEBUG 1*/
30#define DBG(args...)
31/*#define DBG(args...) printk(args)*/
32
33struct grlib_gptimer_regs {
34        volatile unsigned int scaler_value;   /* common timer registers */
35        volatile unsigned int scaler_reload;
36        volatile unsigned int status;
37        volatile unsigned int notused;
38};
39
40/* AMBA IMPLEMENTATION */
41
42int ambapp_bus_init1(struct drvmgr_bus *bus);
43int ambapp_bus_remove(struct drvmgr_bus *bus);
44int ambapp_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev);
45int ambapp_int_register(struct drvmgr_dev *dev, int index, const char *info, drvmgr_isr isr, void *arg);
46int ambapp_int_unregister(struct drvmgr_dev *dev, int index, drvmgr_isr isr, void *arg);
47int ambapp_int_clear(struct drvmgr_dev *dev, int index);
48int ambapp_int_mask(struct drvmgr_dev *dev, int index);
49int ambapp_int_unmask(struct drvmgr_dev *dev, int index);
50int ambapp_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params);
51int ambapp_bus_freq_get(
52        struct drvmgr_dev *dev,
53        int options,
54        unsigned int *freq_hz);
55void ambapp_dev_info(struct drvmgr_dev *, void (*print)(void *p, char *str), void *p);
56
57struct drvmgr_bus_ops ambapp_bus_ops =
58{
59        .init           =
60        {
61                /* init1 */ ambapp_bus_init1,
62                /* init2 */ NULL,
63                /* init3 */ NULL,
64                /* init4 */ NULL
65        },
66        .remove         = ambapp_bus_remove,
67        .unite          = ambapp_unite,
68        .int_register   = ambapp_int_register,
69        .int_unregister = ambapp_int_unregister,
70        .int_clear      = ambapp_int_clear,
71        .int_mask       = ambapp_int_mask,
72        .int_unmask     = ambapp_int_unmask,
73        .get_params     = ambapp_get_params,
74        .freq_get       = ambapp_bus_freq_get,
75#ifdef AMBAPPBUS_INFO_AVAIL
76        .info_dev       = ambapp_dev_info,
77#endif
78};
79
80struct ambapp_priv {
81        struct ambapp_config            *config;
82};
83
84int ambapp_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev)
85{
86        struct amba_drv_info *adrv;
87        struct amba_dev_id *id;
88        struct amba_dev_info *amba;
89
90        if ( !drv || !dev || !dev->parent )
91                return 0;
92
93        if ( ! (((drv->bus_type == DRVMGR_BUS_TYPE_AMBAPP) && (dev->parent->bus_type == DRVMGR_BUS_TYPE_AMBAPP)) ||
94               ((drv->bus_type == DRVMGR_BUS_TYPE_AMBAPP_RMAP) && (dev->parent->bus_type == DRVMGR_BUS_TYPE_AMBAPP_RMAP)) ||
95               ((drv->bus_type == DRVMGR_BUS_TYPE_AMBAPP_DIST) && (dev->parent->bus_type == DRVMGR_BUS_TYPE_AMBAPP_DIST)))
96           ) {
97                return 0;
98        }
99
100        amba = (struct amba_dev_info *)dev->businfo;
101        if ( !amba )
102                return 0;
103
104        adrv = (struct amba_drv_info *)drv;
105        id = adrv->ids;
106        if ( !id )
107                return 0;
108        while( id->vendor != 0 ) {
109                if ( (id->vendor == amba->id.vendor) &&
110                      (id->device == amba->id.device) ) {
111                        /* Unite device and driver */
112                        DBG("DRV 0x%x and DEV 0x%x united\n", (unsigned int)drv, (unsigned int)dev);
113                        return 1;
114                }
115                id++;
116        }
117
118        return 0;
119}
120
121static int ambapp_int_get(struct drvmgr_dev *dev, int index)
122{
123        int irq;
124
125        /* Relative (positive) or absolute (negative) IRQ number */
126        if ( index >= 0 ) {
127                /* IRQ Index relative to Cores base IRQ */
128
129                /* Get Base IRQ */
130                irq = ((struct amba_dev_info *)dev->businfo)->info.irq;
131                if ( irq < 0 )
132                        return -1;
133                irq += index;
134        } else {
135                /* Absolute IRQ number */
136                irq = -index;
137        }
138        return irq;
139}
140
141int ambapp_int_register(
142        struct drvmgr_dev *dev,
143        int index,
144        const char *info,
145        drvmgr_isr isr,
146        void *arg)
147{
148        struct drvmgr_dev *busdev;
149        struct ambapp_priv *priv;
150        int irq;
151
152        busdev = dev->parent->dev;
153        priv = dev->parent->priv;
154
155        /* Get IRQ number from index and device information */
156        irq = ambapp_int_get(dev, index);
157        if ( irq < 0 )
158                return DRVMGR_EINVAL;
159
160        DBG("Register interrupt on 0x%x for dev 0x%x (IRQ: %d)\n", (unsigned int)busdev, (unsigned int)dev, irq);
161
162        if ( priv->config->ops->int_register ) {
163                /* Let device override driver default */
164                return priv->config->ops->int_register(dev, irq, info, isr, arg);
165        } else {
166                return DRVMGR_ENOSYS;
167        }
168}
169
170int ambapp_int_unregister(
171        struct drvmgr_dev *dev,
172        int index,
173        drvmgr_isr isr,
174        void *arg)
175{
176        struct drvmgr_dev *busdev;
177        struct ambapp_priv *priv;
178        int irq;
179
180        busdev = dev->parent->dev;
181        priv = dev->parent->priv;
182
183        /* Get IRQ number from index and device information */
184        irq = ambapp_int_get(dev, index);
185        if ( irq < 0 )
186                return DRVMGR_EINVAL;
187
188        DBG("Unregister interrupt on 0x%x for dev 0x%x (IRQ: %d)\n", (unsigned int)busdev, (unsigned int)dev, irq);
189
190        if ( priv->config->ops->int_unregister ) {
191                /* Let device override driver default */
192                return priv->config->ops->int_unregister(dev, irq, isr, arg);
193        } else {
194                return DRVMGR_ENOSYS;
195        }
196}
197
198int ambapp_int_clear(
199        struct drvmgr_dev *dev,
200        int index)
201{
202        struct drvmgr_dev *busdev;
203        struct ambapp_priv *priv;
204        int irq;
205
206        busdev = dev->parent->dev;
207        priv = dev->parent->priv;
208
209        /* Get IRQ number from index and device information */
210        irq = ambapp_int_get(dev, index);
211        if ( irq < 0 )
212                return -1;
213
214        DBG("Clear interrupt on 0x%x for dev 0x%x (IRQ: %d)\n", (unsigned int)busdev, (unsigned int)dev, irq);
215
216        if ( priv->config->ops->int_clear ) {
217                /* Let device override driver default */
218                return priv->config->ops->int_clear(dev, irq);
219        } else {
220                return DRVMGR_ENOSYS;
221        }
222}
223
224int ambapp_int_mask(
225        struct drvmgr_dev *dev,
226        int index)
227{
228        struct drvmgr_dev *busdev;
229        struct ambapp_priv *priv;
230        int irq;
231
232        busdev = dev->parent->dev;
233        priv = dev->parent->priv;
234
235        /* Get IRQ number from index and device information */
236        irq = ambapp_int_get(dev, index);
237        if ( irq < 0 )
238                return -1;
239
240        DBG("MASK interrupt on 0x%x for dev 0x%x (IRQ: %d)\n", (unsigned int)busdev, (unsigned int)dev, irq);
241
242        if ( priv->config->ops->int_mask ) {
243                /* Let device override driver default */
244                return priv->config->ops->int_mask(dev, irq);
245        } else {
246                return DRVMGR_ENOSYS;
247        }
248}
249
250int ambapp_int_unmask(
251        struct drvmgr_dev *dev,
252        int index)
253{
254        struct drvmgr_dev *busdev;
255        struct ambapp_priv *priv;
256        int irq;
257
258        busdev = dev->parent->dev;
259        priv = dev->parent->priv;
260
261        /* Get IRQ number from index and device information */
262        irq = ambapp_int_get(dev, index);
263        if ( irq < 0 )
264                return DRVMGR_EINVAL;
265
266        DBG("UNMASK interrupt on 0x%x for dev 0x%x (IRQ: %d)\n", (unsigned int)busdev, (unsigned int)dev, irq);
267
268        if ( priv->config->ops->int_unmask ) {
269                /* Let device override driver default */
270                return priv->config->ops->int_unmask(dev, irq);
271        } else {
272                return DRVMGR_ENOSYS;
273        }
274}
275
276/* Assign frequency to an AMBA Bus */
277void ambapp_bus_freq_register(
278        struct drvmgr_dev *dev,
279        int amba_interface,
280        unsigned int freq_hz
281        )
282{
283        struct ambapp_priv *priv = (struct ambapp_priv *)dev->parent->priv;
284        struct ambapp_dev *adev;
285        struct amba_dev_info *pnp = dev->businfo;
286
287        if ( freq_hz == 0 )
288                return;
289
290        if ( amba_interface == DEV_AHB_MST ) {
291                adev = (struct ambapp_dev *)
292                        ((unsigned int)pnp->info.ahb_mst -
293                                sizeof(struct ambapp_dev));
294        } else if ( amba_interface == DEV_AHB_SLV ) {
295                adev = (struct ambapp_dev *)
296                        ((unsigned int)pnp->info.ahb_slv -
297                                sizeof(struct ambapp_dev));
298        } else if ( amba_interface == DEV_APB_SLV ) {
299                adev = (struct ambapp_dev *)
300                        ((unsigned int)pnp->info.apb_slv -
301                                sizeof(struct ambapp_dev));
302        } else {
303                return;
304        }
305
306        /* Calculate Top bus frequency from lower part. The frequency comes
307         * from some kind of hardware able to report local bus frequency.
308         */
309        ambapp_freq_init(priv->config->abus, adev, freq_hz);
310}
311
312int ambapp_bus_freq_get(
313        struct drvmgr_dev *dev,
314        int options,
315        unsigned int *freq_hz)
316{
317        struct ambapp_priv *priv = (struct ambapp_priv *)dev->parent->priv;
318        struct ambapp_dev *adev;
319        struct amba_dev_info *pnp = dev->businfo;
320
321        if ( options == DEV_AHB_MST ) {
322                adev = (struct ambapp_dev *)
323                        ((unsigned int)pnp->info.ahb_mst -
324                                sizeof(struct ambapp_dev));
325        } else if ( options == DEV_AHB_SLV ) {
326                adev = (struct ambapp_dev *)
327                        ((unsigned int)pnp->info.ahb_slv -
328                                sizeof(struct ambapp_dev));
329        } else if ( options == DEV_APB_SLV ) {
330                adev = (struct ambapp_dev *)
331                        ((unsigned int)pnp->info.apb_slv -
332                                sizeof(struct ambapp_dev));
333        } else {
334                *freq_hz = 0;
335                return -1;
336        }
337
338        /* Calculate core/bus frequency from top most bus frequency. */
339        *freq_hz = ambapp_freq_get(priv->config->abus, adev);
340        if ( *freq_hz == 0 )
341                return -1;
342        return 0;
343}
344
345int ambapp_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params)
346{
347        struct ambapp_priv *priv = dev->parent->priv;
348
349        if ( priv->config->ops->get_params ) {
350                /* Let device override driver default */
351                return priv->config->ops->get_params(dev, params);
352        } else {
353                return -1;
354        }
355}
356
357#ifdef AMBAPPBUS_INFO_AVAIL
358void ambapp_dev_info(
359        struct drvmgr_dev *dev,
360        void (*print_line)(void *p, char *str),
361        void *p)
362{
363        struct amba_dev_info *devinfo;
364        struct ambapp_core *core;
365        char buf[64];
366        int ver, i;
367        char *str1, *str2, *str3;
368        unsigned int ahbmst_freq, ahbslv_freq, apbslv_freq;
369
370        if (!dev)
371                return;
372
373        devinfo = (struct amba_dev_info *)dev->businfo;
374        if (!devinfo)
375                return;
376        core = &devinfo->info;
377
378        print_line(p, "AMBA PnP DEVICE");
379
380        str1 = ambapp_vendor_id2str(devinfo->id.vendor);
381        if (str1 == NULL)
382                str1 = "unknown";
383        sprintf(buf, "VENDOR ID:   0x%04x  (%s)", devinfo->id.vendor, str1);
384        print_line(p, buf);
385
386        str1 = ambapp_device_id2str(devinfo->id.vendor, devinfo->id.device);
387        if (str1 == NULL)
388                str1 = "unknown";
389        sprintf(buf, "DEVICE ID:   0x%04x  (%s)", devinfo->id.device, str1);
390        print_line(p, buf);
391
392        ahbmst_freq = ahbslv_freq = apbslv_freq = 0;
393        ver = 0;
394        str1 = str2 = str3 = "";
395        if (core->ahb_mst) {
396                str1 = "AHBMST ";
397                ver = core->ahb_mst->ver;
398                ambapp_bus_freq_get(dev, DEV_AHB_MST, &ahbmst_freq);
399        }
400        if (core->ahb_slv) {
401                str2 = "AHBSLV ";
402                ver = core->ahb_slv->ver;
403                ambapp_bus_freq_get(dev, DEV_AHB_SLV, &ahbslv_freq);
404        }
405        if (core->apb_slv) {
406                str3 = "APBSLV";
407                ver = core->apb_slv->ver;
408                ambapp_bus_freq_get(dev, DEV_APB_SLV, &apbslv_freq);
409        }
410
411        sprintf(buf, "IRQ:         %d", ambapp_int_get(dev, 0));
412        print_line(p, buf);
413
414        sprintf(buf, "VERSION:     0x%x", ver);
415        print_line(p, buf);
416
417        sprintf(buf, "ambapp_core: %p", core);
418        print_line(p, buf);
419
420        sprintf(buf, "interfaces:  %s%s%s", str1, str2, str3);
421        print_line(p, buf);
422
423        if (ahbmst_freq != 0) {
424                sprintf(buf, "AHBMST FREQ: %dkHz", ahbmst_freq/1000);
425                print_line(p, buf);
426        }
427
428        if (ahbslv_freq != 0) {
429                sprintf(buf, "AHBSLV FREQ: %dkHz", ahbslv_freq/1000);
430                print_line(p, buf);
431        }
432
433        if (apbslv_freq != 0) {
434                sprintf(buf, "APBSLV FREQ: %dkHz", apbslv_freq/1000);
435                print_line(p, buf);
436        }
437
438        if (core->ahb_slv) {
439                for(i=0; i<4; i++) {
440                        if (core->ahb_slv->type[i] == AMBA_TYPE_AHBIO)
441                                str1 = " ahbio";
442                        else if (core->ahb_slv->type[i] == AMBA_TYPE_MEM)
443                                str1 = "ahbmem";
444                        else
445                                continue;
446                        sprintf(buf, " %s[%d]:  0x%08x-0x%08x", str1, i,
447                                core->ahb_slv->start[i],
448                                core->ahb_slv->start[i]+core->ahb_slv->mask[i]-1);
449                        print_line(p, buf);
450                }
451        }
452        if (core->apb_slv) {
453                sprintf(buf, "       apb:  0x%08x-0x%08x",
454                        core->apb_slv->start,
455                        core->apb_slv->start + core->apb_slv->mask - 1);
456                print_line(p, buf);
457        }
458}
459#endif
460
461/* Fix device in last stage */
462int ambapp_dev_fixup(struct drvmgr_dev *dev, struct amba_dev_info *pnp)
463{
464        /* OCCAN speciality:
465         *  Mulitple cores are supported through the same amba AHB interface.
466         *  The number of "sub cores" can be detected by decoding the AMBA
467         *  Plug&Play version information. verion = ncores. A maximum of 8
468         *  sub cores are supported, each separeated with 0x100 inbetween.
469         *
470         *  Now, lets detect sub cores.
471         */
472        if ( (pnp->info.device == GAISLER_CANAHB) && (pnp->info.vendor == VENDOR_GAISLER) ) {
473                struct drvmgr_dev *newdev;
474                struct amba_dev_info *pnpinfo;
475                int subcores;
476                int core;
477
478                subcores = (pnp->info.ahb_slv->ver & 0x7) + 1;
479                for(core = 1; core < subcores; core++) {
480                        drvmgr_alloc_dev(&newdev, sizeof(*pnpinfo));
481                        memcpy(newdev, dev, sizeof(*newdev));
482                        pnpinfo = (struct amba_dev_info *)(newdev+1);
483                        memcpy(pnpinfo, pnp, sizeof(*pnp));
484                        pnpinfo->info.index = core;
485                        pnpinfo->info.irq += core;
486                        newdev->businfo = (void *)pnpinfo;
487
488                        /* Register device */
489                        drvmgr_dev_register(newdev);
490                }
491        } else if ( (pnp->info.device == GAISLER_GPIO) && (pnp->info.vendor == VENDOR_GAISLER) ) {
492                /* PIO[N] is connected to IRQ[N]. */
493                pnp->info.irq = 0;
494        }
495        return 0;
496}
497
498struct ambapp_dev_reg_struct {
499        struct ambapp_bus               *abus;
500        struct drvmgr_bus       *bus;
501        struct ambapp_dev               *ahb_mst;
502        struct ambapp_dev               *ahb_slv;
503        struct ambapp_dev               *apb_slv;
504};
505
506void ambapp_core_register(
507        struct ambapp_dev       *ahb_mst,
508        struct ambapp_dev       *ahb_slv,
509        struct ambapp_dev       *apb_slv,
510        struct ambapp_dev_reg_struct *arg
511        )
512{
513        struct drvmgr_dev *newdev;
514        struct amba_dev_info *pnpinfo;
515        unsigned short device;
516        unsigned char vendor;
517        int namelen;
518        char buf[64];
519
520        if ( ahb_mst ) {
521                device = ahb_mst->device;
522                vendor = ahb_mst->vendor;
523        }else if ( ahb_slv ) {
524                device = ahb_slv->device;
525                vendor = ahb_slv->vendor;
526        }else if( apb_slv ) {
527                device = apb_slv->device;
528                vendor = apb_slv->vendor;
529        } else {
530                DBG("NO DEV!\n");
531                return;
532        }
533
534        DBG("CORE REGISTER DEV [%x:%x] MST: 0x%x, SLV: 0x%x, APB: 0x%x\n", vendor, device, (unsigned int)ahb_mst, (unsigned int)ahb_slv, (unsigned int)apb_slv);
535
536        /* Get unique device name from AMBA data base by combining VENDOR and
537         * DEVICE short names
538         */
539        namelen = ambapp_vendev_id2str(vendor, device, buf);
540
541        /* Allocate a device */         
542        drvmgr_alloc_dev(&newdev, sizeof(struct amba_dev_info) + namelen);
543        pnpinfo = (struct amba_dev_info *)(newdev + 1);
544        newdev->parent = arg->bus; /* Ourselfs */
545        newdev->minor_drv = 0;
546        newdev->minor_bus = 0;
547        newdev->priv = NULL;
548        newdev->drv = NULL;
549        if (namelen > 0) {
550                newdev->name = (char *)(pnpinfo + 1);
551                strcpy(newdev->name, buf);
552        } else {
553                newdev->name = NULL;
554        }
555        newdev->next_in_drv = NULL;
556        newdev->bus = NULL;
557
558        /* Init PnP information, Assign Core interfaces with this device */
559        pnpinfo->id.vendor = vendor;
560        pnpinfo->id.device = device;
561        pnpinfo->info.vendor = vendor;
562        pnpinfo->info.device = device;
563        pnpinfo->info.index = 0;
564        if ( ahb_mst ) {
565                pnpinfo->info.ahb_mst = (struct ambapp_ahb_info *)
566                                                ahb_mst->devinfo;
567                ambapp_alloc_dev(ahb_mst, (void *)newdev);
568                if ( pnpinfo->info.ahb_mst->irq )
569                        pnpinfo->info.irq = pnpinfo->info.ahb_mst->irq;
570        }
571        if ( ahb_slv ) {
572                pnpinfo->info.ahb_slv = (struct ambapp_ahb_info *)
573                                        ahb_slv->devinfo;
574                ambapp_alloc_dev(ahb_slv, (void *)newdev);
575                if ( pnpinfo->info.ahb_slv->irq )
576                        pnpinfo->info.irq = pnpinfo->info.ahb_slv->irq;
577        }
578        if ( apb_slv ) {
579                pnpinfo->info.apb_slv = (struct ambapp_apb_info *)
580                                        apb_slv->devinfo;
581                ambapp_alloc_dev(apb_slv, (void *)newdev);
582                if ( pnpinfo->info.apb_slv->irq )
583                        pnpinfo->info.irq = pnpinfo->info.apb_slv->irq;
584        }
585        if ( pnpinfo->info.irq == 0 )
586                pnpinfo->info.irq = -1; /* indicate no IRQ */
587
588        /* Connect device with PnP information */
589        newdev->businfo = (void *)pnpinfo;
590
591        ambapp_dev_fixup(newdev, pnpinfo);
592
593        /* Register New Device */
594        drvmgr_dev_register(newdev);
595}
596
597/* Register one AMBA device */
598int ambapp_dev_register(struct ambapp_dev *dev, int index, void *arg)
599{
600        struct ambapp_dev_reg_struct *p = arg;
601
602#ifdef DEBUG
603        char *type;
604
605        if ( dev->dev_type == DEV_AHB_MST )
606                type = "AHB MST";
607        else if ( dev->dev_type == DEV_AHB_SLV )
608                type = "AHB SLV";
609        else if ( dev->dev_type == DEV_APB_SLV )
610                type = "APB SLV";
611       
612        DBG("Found [%d:%x:%x], %s\n", index, dev->vendor, dev->device, type);
613#endif
614
615        if ( dev->dev_type == DEV_AHB_MST ) {
616                if ( p->ahb_mst ) {
617                        /* This should not happen */
618                        printk("ambapp_dev_register: ahb_mst not NULL!\n");
619                        exit(1);
620                }
621
622                /* Remember AHB Master */
623                p->ahb_mst = dev;
624
625                /* Find AHB Slave and APB slave for this Core */
626                ambapp_for_each(p->abus, (OPTIONS_AHB_SLVS|OPTIONS_APB_SLVS|OPTIONS_FREE), dev->vendor, dev->device, ambapp_dev_register, p);
627
628                ambapp_core_register(p->ahb_mst, p->ahb_slv, p->apb_slv, p);
629                p->ahb_mst = p->ahb_slv = p->apb_slv = NULL;
630                return 0;
631
632        } else if ( dev->dev_type == DEV_AHB_SLV ) {
633                if ( p->ahb_slv ) {
634                        /* Already got our AHB Slave interface */
635                        return 0;
636                }
637
638                /* Remember AHB Slave */
639                p->ahb_slv = dev;
640
641                if ( p->ahb_mst ) {
642                        /* Continue searching for APB Slave */
643                        return 0;
644                } else {
645                        /* Find APB Slave interface for this Core */
646                        ambapp_for_each(p->abus, (OPTIONS_APB_SLVS|OPTIONS_FREE), dev->vendor, dev->device, ambapp_dev_register, p);
647
648                        ambapp_core_register(p->ahb_mst, p->ahb_slv, p->apb_slv, p);
649                        p->ahb_mst = p->ahb_slv = p->apb_slv = NULL;
650                        return 0;
651                }
652        } else if ( dev->dev_type == DEV_APB_SLV ) {
653                if ( p->apb_slv ) {
654                        /* This should not happen */
655                        printk("ambapp_dev_register: apb_slv not NULL!\n");
656                        exit(1);
657                }
658                /* Remember APB Slave */
659                p->apb_slv = dev;
660
661                if ( p->ahb_mst || p->ahb_slv ) {
662                        /* Stop scanning */
663                        return 1;
664                } else {
665                        ambapp_core_register(p->ahb_mst, p->ahb_slv, p->apb_slv, p);
666                        p->ahb_mst = p->ahb_slv = p->apb_slv = NULL;
667                        return 0;
668                }
669        }
670
671        return 0;
672}
673
674/* Register all AMBA devices available on the AMBAPP bus */
675int ambapp_ids_register(struct drvmgr_bus *bus)
676{
677        struct ambapp_priv *priv = bus->priv;
678        struct ambapp_bus *abus;
679        struct ambapp_dev_reg_struct arg;
680
681        DBG("ambapp_ids_register:\n");
682
683        memset(&arg, 0, sizeof(arg));
684
685        abus = priv->config->abus;
686        arg.abus = abus;
687        arg.bus = bus;
688
689        /* Combine the AHB MST, AHB SLV and APB SLV interfaces of a core. A core has often more than
690         * one interface. A core can not have more than one interface of the same type.
691         */
692        ambapp_for_each(abus, (OPTIONS_ALL_DEVS|OPTIONS_FREE), -1, -1, ambapp_dev_register, &arg);
693
694#ifdef DEBUG
695        ambapp_print(abus->root, 1);
696#endif
697
698        return DRVMGR_OK;
699}
700
701/*** DEVICE FUNCTIONS ***/
702
703int ambapp_bus_register(struct drvmgr_dev *dev, struct ambapp_config *config)
704{
705        struct ambapp_priv *priv;
706
707        if ( !config || !config->ops )
708                return DRVMGR_OK;
709
710        DBG("AMBAPP BUS: initializing\n");
711
712        /* Register BUS */
713        drvmgr_alloc_bus(&dev->bus, sizeof(struct ambapp_priv));
714        priv = (struct ambapp_priv *)(dev->bus + 1);
715        priv->config = config;
716        if ( priv->config->bus_type == DRVMGR_BUS_TYPE_AMBAPP_DIST )
717                dev->bus->bus_type = DRVMGR_BUS_TYPE_AMBAPP_DIST;
718        else if ( priv->config->bus_type == DRVMGR_BUS_TYPE_AMBAPP_RMAP )
719                dev->bus->bus_type = DRVMGR_BUS_TYPE_AMBAPP_RMAP;
720        else
721                dev->bus->bus_type = DRVMGR_BUS_TYPE_AMBAPP;
722        dev->bus->next = NULL;
723        dev->bus->dev = dev;
724        dev->bus->priv = priv;
725        dev->bus->children = NULL;
726        dev->bus->ops = &ambapp_bus_ops;
727        dev->bus->funcs = config->funcs;
728        dev->bus->dev_cnt = 0;
729        dev->bus->reslist = NULL;
730        dev->bus->maps_up = config->maps_up;
731        dev->bus->maps_down = config->maps_down;
732
733        /* Add resource configuration */
734        if ( priv->config->resources )
735                drvmgr_bus_res_add(dev->bus, priv->config->resources);
736
737        drvmgr_bus_register(dev->bus);
738
739        return DRVMGR_OK;
740}
741
742/*** BUS INITIALIZE FUNCTIONS ***/
743
744/* Initialize the bus, register devices on this bus */
745int ambapp_bus_init1(struct drvmgr_bus *bus)
746{
747        /* Initialize the bus, register devices on this bus */
748        return ambapp_ids_register(bus);
749}
750
751int ambapp_bus_remove(struct drvmgr_bus *bus)
752{
753        return DRVMGR_OK;
754}
Note: See TracBrowser for help on using the repository browser.