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

5
Last change on this file since c29eb085 was c29eb085, checked in by Sebastian Huber <sebastian.huber@…>, on 07/11/17 at 12:15:47

bsps/sparc: Fix ambapp_int_set_affinity()

Update #3059.

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