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

4.115
Last change on this file since 4a7d1026 was 4a7d1026, checked in by Daniel Hellstrom <daniel@…>, on 04/13/15 at 08:25:52

sparc bsps: updated license to rtems.org

  • Property mode set to 100644
File size: 18.8 KB
Line 
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.org/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 ambapp_priv *priv;
149        int irq;
150
151        priv = dev->parent->priv;
152
153        /* Get IRQ number from index and device information */
154        irq = ambapp_int_get(dev, index);
155        if ( irq < 0 )
156                return DRVMGR_EINVAL;
157
158        DBG("Register interrupt on 0x%x for dev 0x%x (IRQ: %d)\n",
159                (unsigned int)dev->parent->dev, (unsigned int)dev, irq);
160
161        if ( priv->config->ops->int_register ) {
162                /* Let device override driver default */
163                return priv->config->ops->int_register(dev, irq, info, isr, arg);
164        } else {
165                return DRVMGR_ENOSYS;
166        }
167}
168
169int ambapp_int_unregister(
170        struct drvmgr_dev *dev,
171        int index,
172        drvmgr_isr isr,
173        void *arg)
174{
175        struct ambapp_priv *priv;
176        int irq;
177
178        priv = dev->parent->priv;
179
180        /* Get IRQ number from index and device information */
181        irq = ambapp_int_get(dev, index);
182        if ( irq < 0 )
183                return DRVMGR_EINVAL;
184
185        DBG("Unregister interrupt on 0x%x for dev 0x%x (IRQ: %d)\n",
186                (unsigned int)dev->parent->dev, (unsigned int)dev, irq);
187
188        if ( priv->config->ops->int_unregister ) {
189                /* Let device override driver default */
190                return priv->config->ops->int_unregister(dev, irq, isr, arg);
191        } else {
192                return DRVMGR_ENOSYS;
193        }
194}
195
196int ambapp_int_clear(
197        struct drvmgr_dev *dev,
198        int index)
199{
200        struct ambapp_priv *priv;
201        int irq;
202
203        priv = dev->parent->priv;
204
205        /* Get IRQ number from index and device information */
206        irq = ambapp_int_get(dev, index);
207        if ( irq < 0 )
208                return -1;
209
210        DBG("Clear interrupt on 0x%x for dev 0x%x (IRQ: %d)\n",
211                (unsigned int)dev->parent->dev, (unsigned int)dev, irq);
212
213        if ( priv->config->ops->int_clear ) {
214                /* Let device override driver default */
215                return priv->config->ops->int_clear(dev, irq);
216        } else {
217                return DRVMGR_ENOSYS;
218        }
219}
220
221int ambapp_int_mask(
222        struct drvmgr_dev *dev,
223        int index)
224{
225        struct ambapp_priv *priv;
226        int irq;
227
228        priv = dev->parent->priv;
229
230        /* Get IRQ number from index and device information */
231        irq = ambapp_int_get(dev, index);
232        if ( irq < 0 )
233                return -1;
234
235        DBG("MASK interrupt on 0x%x for dev 0x%x (IRQ: %d)\n",
236                (unsigned int)dev->parent->dev, (unsigned int)dev, irq);
237
238        if ( priv->config->ops->int_mask ) {
239                /* Let device override driver default */
240                return priv->config->ops->int_mask(dev, irq);
241        } else {
242                return DRVMGR_ENOSYS;
243        }
244}
245
246int ambapp_int_unmask(
247        struct drvmgr_dev *dev,
248        int index)
249{
250        struct ambapp_priv *priv;
251        int irq;
252
253        priv = dev->parent->priv;
254
255        /* Get IRQ number from index and device information */
256        irq = ambapp_int_get(dev, index);
257        if ( irq < 0 )
258                return DRVMGR_EINVAL;
259
260        DBG("UNMASK interrupt on 0x%x for dev 0x%x (IRQ: %d)\n",
261                (unsigned int)dev->parent->dev, (unsigned int)dev, irq);
262
263        if ( priv->config->ops->int_unmask ) {
264                /* Let device override driver default */
265                return priv->config->ops->int_unmask(dev, irq);
266        } else {
267                return DRVMGR_ENOSYS;
268        }
269}
270
271/* Assign frequency to an AMBA Bus */
272void ambapp_bus_freq_register(
273        struct drvmgr_dev *dev,
274        int amba_interface,
275        unsigned int freq_hz
276        )
277{
278        struct ambapp_priv *priv = (struct ambapp_priv *)dev->parent->priv;
279        struct ambapp_dev *adev;
280        struct amba_dev_info *pnp = dev->businfo;
281
282        if ( freq_hz == 0 )
283                return;
284
285        if ( amba_interface == DEV_AHB_MST ) {
286                adev = (struct ambapp_dev *)
287                        ((unsigned int)pnp->info.ahb_mst -
288                                sizeof(struct ambapp_dev));
289        } else if ( amba_interface == DEV_AHB_SLV ) {
290                adev = (struct ambapp_dev *)
291                        ((unsigned int)pnp->info.ahb_slv -
292                                sizeof(struct ambapp_dev));
293        } else if ( amba_interface == DEV_APB_SLV ) {
294                adev = (struct ambapp_dev *)
295                        ((unsigned int)pnp->info.apb_slv -
296                                sizeof(struct ambapp_dev));
297        } else {
298                return;
299        }
300
301        /* Calculate Top bus frequency from lower part. The frequency comes
302         * from some kind of hardware able to report local bus frequency.
303         */
304        ambapp_freq_init(priv->config->abus, adev, freq_hz);
305}
306
307int ambapp_bus_freq_get(
308        struct drvmgr_dev *dev,
309        int options,
310        unsigned int *freq_hz)
311{
312        struct ambapp_priv *priv = (struct ambapp_priv *)dev->parent->priv;
313        struct ambapp_dev *adev;
314        struct amba_dev_info *pnp = dev->businfo;
315
316        if ( options == DEV_AHB_MST ) {
317                adev = (struct ambapp_dev *)
318                        ((unsigned int)pnp->info.ahb_mst -
319                                sizeof(struct ambapp_dev));
320        } else if ( options == DEV_AHB_SLV ) {
321                adev = (struct ambapp_dev *)
322                        ((unsigned int)pnp->info.ahb_slv -
323                                sizeof(struct ambapp_dev));
324        } else if ( options == DEV_APB_SLV ) {
325                adev = (struct ambapp_dev *)
326                        ((unsigned int)pnp->info.apb_slv -
327                                sizeof(struct ambapp_dev));
328        } else {
329                *freq_hz = 0;
330                return -1;
331        }
332
333        /* Calculate core/bus frequency from top most bus frequency. */
334        *freq_hz = ambapp_freq_get(priv->config->abus, adev);
335        if ( *freq_hz == 0 )
336                return -1;
337        return 0;
338}
339
340int ambapp_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params)
341{
342        struct ambapp_priv *priv = dev->parent->priv;
343
344        if ( priv->config->ops->get_params ) {
345                /* Let device override driver default */
346                return priv->config->ops->get_params(dev, params);
347        } else {
348                return -1;
349        }
350}
351
352#ifdef AMBAPPBUS_INFO_AVAIL
353void ambapp_dev_info(
354        struct drvmgr_dev *dev,
355        void (*print_line)(void *p, char *str),
356        void *p)
357{
358        struct amba_dev_info *devinfo;
359        struct ambapp_core *core;
360        char buf[64];
361        int ver, i;
362        char *str1, *str2, *str3;
363        unsigned int ahbmst_freq, ahbslv_freq, apbslv_freq;
364
365        if (!dev)
366                return;
367
368        devinfo = (struct amba_dev_info *)dev->businfo;
369        if (!devinfo)
370                return;
371        core = &devinfo->info;
372
373        print_line(p, "AMBA PnP DEVICE");
374
375        str1 = ambapp_vendor_id2str(devinfo->id.vendor);
376        if (str1 == NULL)
377                str1 = "unknown";
378        sprintf(buf, "VENDOR ID:   0x%04x  (%s)", devinfo->id.vendor, str1);
379        print_line(p, buf);
380
381        str1 = ambapp_device_id2str(devinfo->id.vendor, devinfo->id.device);
382        if (str1 == NULL)
383                str1 = "unknown";
384        sprintf(buf, "DEVICE ID:   0x%04x  (%s)", devinfo->id.device, str1);
385        print_line(p, buf);
386
387        ahbmst_freq = ahbslv_freq = apbslv_freq = 0;
388        ver = 0;
389        str1 = str2 = str3 = "";
390        if (core->ahb_mst) {
391                str1 = "AHBMST ";
392                ver = core->ahb_mst->ver;
393                ambapp_bus_freq_get(dev, DEV_AHB_MST, &ahbmst_freq);
394        }
395        if (core->ahb_slv) {
396                str2 = "AHBSLV ";
397                ver = core->ahb_slv->ver;
398                ambapp_bus_freq_get(dev, DEV_AHB_SLV, &ahbslv_freq);
399        }
400        if (core->apb_slv) {
401                str3 = "APBSLV";
402                ver = core->apb_slv->ver;
403                ambapp_bus_freq_get(dev, DEV_APB_SLV, &apbslv_freq);
404        }
405
406        sprintf(buf, "IRQ:         %d", ambapp_int_get(dev, 0));
407        print_line(p, buf);
408
409        sprintf(buf, "VERSION:     0x%x", ver);
410        print_line(p, buf);
411
412        sprintf(buf, "ambapp_core: %p", core);
413        print_line(p, buf);
414
415        sprintf(buf, "interfaces:  %s%s%s", str1, str2, str3);
416        print_line(p, buf);
417
418        if (ahbmst_freq != 0) {
419                sprintf(buf, "AHBMST FREQ: %dkHz", ahbmst_freq/1000);
420                print_line(p, buf);
421        }
422
423        if (ahbslv_freq != 0) {
424                sprintf(buf, "AHBSLV FREQ: %dkHz", ahbslv_freq/1000);
425                print_line(p, buf);
426        }
427
428        if (apbslv_freq != 0) {
429                sprintf(buf, "APBSLV FREQ: %dkHz", apbslv_freq/1000);
430                print_line(p, buf);
431        }
432
433        if (core->ahb_slv) {
434                for(i=0; i<4; i++) {
435                        if (core->ahb_slv->type[i] == AMBA_TYPE_AHBIO)
436                                str1 = " ahbio";
437                        else if (core->ahb_slv->type[i] == AMBA_TYPE_MEM)
438                                str1 = "ahbmem";
439                        else
440                                continue;
441                        sprintf(buf, " %s[%d]:  0x%08x-0x%08x", str1, i,
442                                core->ahb_slv->start[i],
443                                core->ahb_slv->start[i]+core->ahb_slv->mask[i]-1);
444                        print_line(p, buf);
445                }
446        }
447        if (core->apb_slv) {
448                sprintf(buf, "       apb:  0x%08x-0x%08x",
449                        core->apb_slv->start,
450                        core->apb_slv->start + core->apb_slv->mask - 1);
451                print_line(p, buf);
452        }
453}
454#endif
455
456/* Fix device in last stage */
457static int ambapp_dev_fixup(struct drvmgr_dev *dev, struct amba_dev_info *pnp)
458{
459        /* OCCAN speciality:
460         *  Mulitple cores are supported through the same amba AHB interface.
461         *  The number of "sub cores" can be detected by decoding the AMBA
462         *  Plug&Play version information. verion = ncores. A maximum of 8
463         *  sub cores are supported, each separeated with 0x100 inbetween.
464         *
465         *  Now, lets detect sub cores.
466         */
467        if ( (pnp->info.device == GAISLER_CANAHB) && (pnp->info.vendor == VENDOR_GAISLER) ) {
468                struct drvmgr_dev *newdev;
469                struct amba_dev_info *pnpinfo;
470                int subcores;
471                int core;
472
473                subcores = (pnp->info.ahb_slv->ver & 0x7) + 1;
474                for(core = 1; core < subcores; core++) {
475                        drvmgr_alloc_dev(&newdev, sizeof(*pnpinfo));
476                        memcpy(newdev, dev, sizeof(*newdev));
477                        pnpinfo = (struct amba_dev_info *)(newdev+1);
478                        memcpy(pnpinfo, pnp, sizeof(*pnp));
479                        pnpinfo->info.index = core;
480                        pnpinfo->info.irq += core;
481                        newdev->businfo = (void *)pnpinfo;
482
483                        /* Register device */
484                        drvmgr_dev_register(newdev);
485                }
486        } else if ( (pnp->info.device == GAISLER_GPIO) && (pnp->info.vendor == VENDOR_GAISLER) ) {
487                /* PIO[N] is connected to IRQ[N]. */
488                pnp->info.irq = 0;
489        }
490        return 0;
491}
492
493struct ambapp_dev_reg_struct {
494        struct ambapp_bus       *abus;
495        struct drvmgr_bus       *bus;
496        struct ambapp_dev       *ahb_mst;
497        struct ambapp_dev       *ahb_slv;
498        struct ambapp_dev       *apb_slv;
499};
500
501static void ambapp_core_register(
502        struct ambapp_dev       *ahb_mst,
503        struct ambapp_dev       *ahb_slv,
504        struct ambapp_dev       *apb_slv,
505        struct ambapp_dev_reg_struct *arg
506        )
507{
508        struct drvmgr_dev *newdev;
509        struct amba_dev_info *pnpinfo;
510        unsigned short device;
511        unsigned char vendor;
512        int namelen;
513        char buf[64];
514
515        if ( ahb_mst ) {
516                device = ahb_mst->device;
517                vendor = ahb_mst->vendor;
518        }else if ( ahb_slv ) {
519                device = ahb_slv->device;
520                vendor = ahb_slv->vendor;
521        }else if( apb_slv ) {
522                device = apb_slv->device;
523                vendor = apb_slv->vendor;
524        } else {
525                DBG("NO DEV!\n");
526                return;
527        }
528
529        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);
530
531        /* Get unique device name from AMBA data base by combining VENDOR and
532         * DEVICE short names
533         */
534        namelen = ambapp_vendev_id2str(vendor, device, buf);
535
536        /* Allocate a device */         
537        drvmgr_alloc_dev(&newdev, sizeof(struct amba_dev_info) + namelen);
538        pnpinfo = (struct amba_dev_info *)(newdev + 1);
539        newdev->parent = arg->bus; /* Ourselfs */
540        newdev->minor_drv = 0;
541        newdev->minor_bus = 0;
542        newdev->priv = NULL;
543        newdev->drv = NULL;
544        if (namelen > 0) {
545                newdev->name = (char *)(pnpinfo + 1);
546                strcpy(newdev->name, buf);
547        } else {
548                newdev->name = NULL;
549        }
550        newdev->next_in_drv = NULL;
551        newdev->bus = NULL;
552
553        /* Init PnP information, Assign Core interfaces with this device */
554        pnpinfo->id.vendor = vendor;
555        pnpinfo->id.device = device;
556        pnpinfo->info.vendor = vendor;
557        pnpinfo->info.device = device;
558        pnpinfo->info.index = 0;
559        if ( ahb_mst ) {
560                pnpinfo->info.ahb_mst = (struct ambapp_ahb_info *)
561                                                ahb_mst->devinfo;
562                ambapp_alloc_dev(ahb_mst, (void *)newdev);
563                if ( pnpinfo->info.ahb_mst->irq )
564                        pnpinfo->info.irq = pnpinfo->info.ahb_mst->irq;
565        }
566        if ( ahb_slv ) {
567                pnpinfo->info.ahb_slv = (struct ambapp_ahb_info *)
568                                        ahb_slv->devinfo;
569                ambapp_alloc_dev(ahb_slv, (void *)newdev);
570                if ( pnpinfo->info.ahb_slv->irq )
571                        pnpinfo->info.irq = pnpinfo->info.ahb_slv->irq;
572        }
573        if ( apb_slv ) {
574                pnpinfo->info.apb_slv = (struct ambapp_apb_info *)
575                                        apb_slv->devinfo;
576                ambapp_alloc_dev(apb_slv, (void *)newdev);
577                if ( pnpinfo->info.apb_slv->irq )
578                        pnpinfo->info.irq = pnpinfo->info.apb_slv->irq;
579        }
580        if ( pnpinfo->info.irq == 0 )
581                pnpinfo->info.irq = -1; /* indicate no IRQ */
582
583        /* Connect device with PnP information */
584        newdev->businfo = (void *)pnpinfo;
585
586        ambapp_dev_fixup(newdev, pnpinfo);
587
588        /* Register New Device */
589        drvmgr_dev_register(newdev);
590}
591
592/* Register one AMBA device */
593static int ambapp_dev_register(struct ambapp_dev *dev, int index, void *arg)
594{
595        struct ambapp_dev_reg_struct *p = arg;
596
597#ifdef DEBUG
598        char *type;
599
600        if ( dev->dev_type == DEV_AHB_MST )
601                type = "AHB MST";
602        else if ( dev->dev_type == DEV_AHB_SLV )
603                type = "AHB SLV";
604        else if ( dev->dev_type == DEV_APB_SLV )
605                type = "APB SLV";
606       
607        DBG("Found [%d:%x:%x], %s\n", index, dev->vendor, dev->device, type);
608#endif
609
610        if ( dev->dev_type == DEV_AHB_MST ) {
611                if ( p->ahb_mst ) {
612                        /* This should not happen */
613                        printk("ambapp_dev_register: ahb_mst not NULL!\n");
614                        exit(1);
615                }
616
617                /* Remember AHB Master */
618                p->ahb_mst = dev;
619
620                /* Find AHB Slave and APB slave for this Core */
621                ambapp_for_each(p->abus, (OPTIONS_AHB_SLVS|OPTIONS_APB_SLVS|OPTIONS_FREE), dev->vendor, dev->device, ambapp_dev_register, p);
622
623                ambapp_core_register(p->ahb_mst, p->ahb_slv, p->apb_slv, p);
624                p->ahb_mst = p->ahb_slv = p->apb_slv = NULL;
625                return 0;
626
627        } else if ( dev->dev_type == DEV_AHB_SLV ) {
628                if ( p->ahb_slv ) {
629                        /* Already got our AHB Slave interface */
630                        return 0;
631                }
632
633                /* Remember AHB Slave */
634                p->ahb_slv = dev;
635
636                if ( p->ahb_mst ) {
637                        /* Continue searching for APB Slave */
638                        return 0;
639                } else {
640                        /* Find APB Slave interface for this Core */
641                        ambapp_for_each(p->abus, (OPTIONS_APB_SLVS|OPTIONS_FREE), dev->vendor, dev->device, ambapp_dev_register, p);
642
643                        ambapp_core_register(p->ahb_mst, p->ahb_slv, p->apb_slv, p);
644                        p->ahb_mst = p->ahb_slv = p->apb_slv = NULL;
645                        return 0;
646                }
647        } else if ( dev->dev_type == DEV_APB_SLV ) {
648                if ( p->apb_slv ) {
649                        /* This should not happen */
650                        printk("ambapp_dev_register: apb_slv not NULL!\n");
651                        exit(1);
652                }
653                /* Remember APB Slave */
654                p->apb_slv = dev;
655
656                if ( p->ahb_mst || p->ahb_slv ) {
657                        /* Stop scanning */
658                        return 1;
659                } else {
660                        ambapp_core_register(p->ahb_mst, p->ahb_slv, p->apb_slv, p);
661                        p->ahb_mst = p->ahb_slv = p->apb_slv = NULL;
662                        return 0;
663                }
664        }
665
666        return 0;
667}
668
669/* Register all AMBA devices available on the AMBAPP bus */
670static int ambapp_ids_register(struct drvmgr_bus *bus)
671{
672        struct ambapp_priv *priv = bus->priv;
673        struct ambapp_bus *abus;
674        struct ambapp_dev_reg_struct arg;
675
676        DBG("ambapp_ids_register:\n");
677
678        memset(&arg, 0, sizeof(arg));
679
680        abus = priv->config->abus;
681        arg.abus = abus;
682        arg.bus = bus;
683
684        /* Combine the AHB MST, AHB SLV and APB SLV interfaces of a core. A core has often more than
685         * one interface. A core can not have more than one interface of the same type.
686         */
687        ambapp_for_each(abus, (OPTIONS_ALL_DEVS|OPTIONS_FREE), -1, -1, ambapp_dev_register, &arg);
688
689#ifdef DEBUG
690        ambapp_print(abus->root, 1);
691#endif
692
693        return DRVMGR_OK;
694}
695
696/*** DEVICE FUNCTIONS ***/
697
698int ambapp_bus_register(struct drvmgr_dev *dev, struct ambapp_config *config)
699{
700        struct ambapp_priv *priv;
701
702        if ( !config || !config->ops )
703                return DRVMGR_OK;
704
705        DBG("AMBAPP BUS: initializing\n");
706
707        /* Register BUS */
708        drvmgr_alloc_bus(&dev->bus, sizeof(struct ambapp_priv));
709        priv = (struct ambapp_priv *)(dev->bus + 1);
710        priv->config = config;
711        if ( priv->config->bus_type == DRVMGR_BUS_TYPE_AMBAPP_DIST )
712                dev->bus->bus_type = DRVMGR_BUS_TYPE_AMBAPP_DIST;
713        else if ( priv->config->bus_type == DRVMGR_BUS_TYPE_AMBAPP_RMAP )
714                dev->bus->bus_type = DRVMGR_BUS_TYPE_AMBAPP_RMAP;
715        else
716                dev->bus->bus_type = DRVMGR_BUS_TYPE_AMBAPP;
717        dev->bus->next = NULL;
718        dev->bus->dev = dev;
719        dev->bus->priv = priv;
720        dev->bus->children = NULL;
721        dev->bus->ops = &ambapp_bus_ops;
722        dev->bus->funcs = config->funcs;
723        dev->bus->dev_cnt = 0;
724        dev->bus->reslist = NULL;
725        dev->bus->maps_up = config->maps_up;
726        dev->bus->maps_down = config->maps_down;
727
728        /* Add resource configuration */
729        if ( priv->config->resources )
730                drvmgr_bus_res_add(dev->bus, priv->config->resources);
731
732        drvmgr_bus_register(dev->bus);
733
734        return DRVMGR_OK;
735}
736
737/*** BUS INITIALIZE FUNCTIONS ***/
738
739/* Initialize the bus, register devices on this bus */
740int ambapp_bus_init1(struct drvmgr_bus *bus)
741{
742        /* Initialize the bus, register devices on this bus */
743        return ambapp_ids_register(bus);
744}
745
746int ambapp_bus_remove(struct drvmgr_bus *bus)
747{
748        return DRVMGR_OK;
749}
Note: See TracBrowser for help on using the repository browser.