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

5
Last change on this file since 8570ad2 was 8570ad2, checked in by Daniel Hellstrom <daniel@…>, on 08/24/17 at 14:02:33

leon,ambapp_bus: make unreferenced global function static

Fixes #3072

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