source: rtems/c/src/lib/libbsp/sparc/shared/drvmgr/leon2_amba_bus.c @ 62fb1778

4.11
Last change on this file since 62fb1778 was 62fb1778, checked in by Daniel Hellstrom <daniel@…>, on Feb 11, 2015 at 11:55:32 AM

LEON2: fix build warnings

  • Property mode set to 100644
File size: 9.1 KB
Line 
1/*  LEON2 Hardcoded bus driver.
2 *
3 *  COPYRIGHT (c) 2008.
4 *  Cobham Gaisler AB.
5 *
6 *  Bus driver for a hardcoded setup. LEON2 systems have some
7 *  cores always present, here called "Standard Cores". In
8 *  addtion to the standard cores there are often extra cores
9 *  that can be defined using the "Custom Cores" mechanism.
10 *
11 *  A Core is described by assigning a base register and
12 *  IRQ0..IRQ15 using the leon2_core structure.
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.com/license/LICENSE.
17 */
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
23#include <drvmgr/drvmgr.h>
24#include <drvmgr/leon2_amba_bus.h>
25
26#include <bsp.h>
27
28#define DBG(args...)
29/*#define DBG(args...) printk(args)*/
30
31struct drvmgr_drv leon2_bus_drv;
32
33int leon2_amba_bus_init1(struct drvmgr_bus *bus);
34int leon2_amba_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev);
35int leon2_amba_int_register(
36        struct drvmgr_dev *dev,
37        int index,
38        const char *info,
39        drvmgr_isr isr,
40        void *arg);
41int leon2_amba_int_unregister(
42        struct drvmgr_dev *dev,
43        int index,
44        drvmgr_isr isr,
45        void *arg);
46int leon2_amba_int_clear(
47        struct drvmgr_dev *dev,
48        int index);
49int leon2_amba_int_mask(
50        struct drvmgr_dev *dev,
51        int index);
52int leon2_amba_int_unmask(
53        struct drvmgr_dev *dev,
54        int index);
55
56/* LEON2 bus operations */
57struct drvmgr_bus_ops leon2_amba_bus_ops =
58{
59        .init = {
60                leon2_amba_bus_init1,
61                NULL,
62                NULL,
63                NULL
64        },
65        .remove = NULL,
66        .unite          = leon2_amba_unite,
67        .int_register   = leon2_amba_int_register,
68        .int_unregister = leon2_amba_int_unregister,
69        .int_clear      = leon2_amba_int_clear,
70        .int_mask       = leon2_amba_int_mask,
71        .int_unmask     = leon2_amba_int_unmask,
72        .get_params     = NULL,
73};
74
75struct leon2_isr_handler {
76        void (*handler)(int irq, void *arg);
77        void *arg;
78};
79
80/* Standard LEON2 configuration */
81
82struct drvmgr_key leon2_timers[] =
83{
84        {"REG0", KEY_TYPE_INT, {0x80000040}},
85        {"IRQ0", KEY_TYPE_INT, {8}},
86        {"IRQ1", KEY_TYPE_INT, {9}},
87        KEY_EMPTY
88};
89
90struct drvmgr_key leon2_uart1[] =
91{
92        {"REG0", KEY_TYPE_INT, {0x80000070}},
93        {"IRQ0", KEY_TYPE_INT, {3}},
94        KEY_EMPTY
95};
96
97struct drvmgr_key leon2_uart2[] =
98{
99        {"REG0", KEY_TYPE_INT, {0x80000080}},
100        {"IRQ0", KEY_TYPE_INT, {2}},
101        KEY_EMPTY
102};
103
104struct drvmgr_key leon2_irqctrl[] =
105{
106        {"REG0", KEY_TYPE_INT, {0x80000090}},
107        KEY_EMPTY
108};
109
110struct drvmgr_key leon2_gpio0[] =
111{
112        {"REG0", KEY_TYPE_INT, {0x800000A0}},
113        {"IRQ0", KEY_TYPE_INT, {4}},
114        {"IRQ1", KEY_TYPE_INT, {5}},
115        {"IRQ2", KEY_TYPE_INT, {6}},
116        {"IRQ3", KEY_TYPE_INT, {7}},
117        KEY_EMPTY
118};
119
120struct leon2_core leon2_std_cores[] = 
121{
122        {{LEON2_AMBA_TIMER_ID}, "Timers", &leon2_timers[0]},
123        {{LEON2_AMBA_UART_ID}, "Uart1", &leon2_uart1[0]},
124        {{LEON2_AMBA_UART_ID}, "Uart2", &leon2_uart2[0]},
125        {{LEON2_AMBA_IRQCTRL_ID}, "IRQCtrl", &leon2_irqctrl[0]},
126        {{LEON2_AMBA_GPIO_ID}, "GPIO", &leon2_gpio0[0]},
127        EMPTY_LEON2_CORE
128};
129
130static struct leon2_bus *leon2_bus_config = NULL;
131static struct drvmgr_bus_res *leon2_bus_res = NULL;
132
133int leon2_root_register(
134        struct leon2_bus *bus_config,
135        struct drvmgr_bus_res *resources)
136{
137        /* Save the configuration for later */
138        leon2_bus_config = bus_config;
139        leon2_bus_res = resources;
140
141        /* Register root device driver */
142        drvmgr_root_drv_register(&leon2_bus_drv);
143
144        return 0;
145}
146
147static int leon2_amba_dev_register(
148        struct drvmgr_bus *bus,
149        struct leon2_core *core,
150        int index)
151{
152        struct drvmgr_dev *newdev;
153        struct leon2_amba_dev_info *info;
154        union drvmgr_key_value *value;
155        char irq_name[8];
156        int i;
157
158        /* Allocate new device and businfo */
159        drvmgr_alloc_dev(&newdev, sizeof(struct leon2_amba_dev_info));
160        info = (struct leon2_amba_dev_info *)(newdev + 1);
161
162        /* Set Core ID */
163        info->core_id = core->id.core_id;
164
165        /* Get information from bus configuration */
166        value = drvmgr_key_val_get(core->keys, "REG0", KEY_TYPE_INT);
167        if ( !value ) {
168                printk("leon2_amba_dev_register: Failed getting resource REG0\n");
169                info->reg_base = 0x00000000;
170        } else {
171                DBG("leon2_amba_dev_register: REG0: 0x%08x\n", value->i);
172                info->reg_base = value->i;
173        }
174
175        strcpy(irq_name, "IRQ");
176        for(i=0; i<16; i++){
177                if ( i < 10 ){
178                        irq_name[3] = '0' + i;
179                        irq_name[4] = '\0';
180                } else {
181                        irq_name[3] = '1';
182                        irq_name[4] = '0' + (i-10);
183                        irq_name[5] = '\0';
184                }
185
186                value = drvmgr_key_val_get(core->keys, irq_name, KEY_TYPE_INT);
187                if ( !value ) {
188                        DBG("leon2_amba_dev_register: Failed getting resource IRQ%d for REG 0x%x\n", i, info->reg_base);
189                        info->irqs[i] = 0;
190                } else {
191                        DBG("leon2_amba_dev_register: IRQ%d: %d\n", i, value->i);
192                        info->irqs[i] = value->i;
193                }
194        }
195
196        /* Init new device */
197        newdev->next = NULL;
198        newdev->parent = bus; /* Ourselfs */
199        newdev->minor_drv = 0;
200        newdev->minor_bus = 0;
201        newdev->businfo = (void *)info;
202        newdev->priv = NULL;
203        newdev->drv = NULL;
204        newdev->name = core->name;
205        newdev->next_in_drv = NULL;
206        newdev->bus = NULL;
207
208        /* Register new device */
209        drvmgr_dev_register(newdev);
210
211        return 0;
212}
213
214static int leon2_amba_init1(struct drvmgr_dev *dev)
215{
216        /* Init our own device */
217        dev->priv = NULL;
218        dev->name = "LEON2 AMBA";
219
220        /* Init the bus */
221        drvmgr_alloc_bus(&dev->bus, 0);
222        dev->bus->bus_type = DRVMGR_BUS_TYPE_LEON2_AMBA;
223        dev->bus->next = NULL;
224        dev->bus->dev = dev;
225        dev->bus->priv = NULL;
226        dev->bus->children = NULL;
227        dev->bus->ops = &leon2_amba_bus_ops;
228        dev->bus->dev_cnt = 0;
229        dev->bus->reslist = NULL;
230        dev->bus->maps_up = leon2_bus_config->maps_up;
231        dev->bus->maps_down = leon2_bus_config->maps_down;
232        drvmgr_bus_register(dev->bus);
233
234        return DRVMGR_OK;
235}
236
237static int leon2_amba_init2(struct drvmgr_dev *dev)
238{
239        return DRVMGR_OK;
240}
241
242static int leon2_amba_remove(struct drvmgr_dev *dev)
243{
244        return DRVMGR_OK;
245}
246
247int leon2_amba_bus_init1(struct drvmgr_bus *bus)
248{
249        struct leon2_core *core;
250        int i;
251
252        if ( leon2_bus_res )
253                drvmgr_bus_res_add(bus, leon2_bus_res);
254
255        /**** REGISTER NEW DEVICES ****/
256        i=0;
257        core = leon2_bus_config->std_cores;
258        if ( core ) {
259                while ( core->id.core_id ) {
260                        if ( leon2_amba_dev_register(bus, core, i) ) {
261                                return RTEMS_UNSATISFIED;
262                        }
263                        i++;
264                        core++;
265                }
266        }
267        core = leon2_bus_config->custom_cores;
268        if ( core ) {
269                while ( core->id.core_id ) {
270                        if ( leon2_amba_dev_register(bus, core, i) ) {
271                                return RTEMS_UNSATISFIED;
272                        }
273                        i++;
274                        core++;
275                }
276        }
277
278        return 0;
279}
280
281int leon2_amba_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev)
282{
283        struct leon2_amba_dev_info *info;
284        struct leon2_amba_drv_info *adrv;
285        struct leon2_amba_dev_id *id;
286
287        if ( !drv || !dev || !dev->parent )
288                return 0;
289
290        if ( (drv->bus_type!=DRVMGR_BUS_TYPE_LEON2_AMBA) || (dev->parent->bus_type != DRVMGR_BUS_TYPE_LEON2_AMBA) ) {
291                return 0;
292        }
293
294        info = (struct leon2_amba_dev_info *)dev->businfo;
295        if ( !info ) 
296                return 0;
297
298        /* Get LEON2 AMBA driver info */
299        adrv = (struct leon2_amba_drv_info *)drv;
300        id = adrv->ids;
301        if ( !id )
302                return 0;
303
304        while ( id->core_id ) {
305                if ( id->core_id == info->core_id ) {
306                        /* Driver is suitable for device, Unite them */
307                        return 1;
308                }
309                id++;
310        }
311
312        return 0;
313}
314
315static int leon2_amba_get_irq(struct drvmgr_dev *dev, int index)
316{
317        int irq;
318        struct leon2_amba_dev_info *info;
319
320        if ( !dev || (index > 15) )
321                return -1;
322
323        /* Relative (positive) or absolute (negative) IRQ number */
324        if ( index >= 0 ) {
325                /* IRQ Index relative to Cores base IRQ */
326
327                /* Get IRQ array configured by user */
328                info = (struct leon2_amba_dev_info *)dev->businfo;
329                irq = info->irqs[index];
330                if ( irq == 0 )
331                        return -1;
332        } else {
333                /* Absolute IRQ number */
334                irq = -index;
335        }
336        return irq;
337}
338
339int leon2_amba_int_register
340        (
341        struct drvmgr_dev *dev,
342        int index,
343        const char *info,
344        drvmgr_isr isr,
345        void *arg
346        )
347{
348        int irq;
349
350        irq = leon2_amba_get_irq(dev, index);
351        if ( irq < 0 )
352                return -1;
353
354        DBG("Registering IRQ %d to func 0x%x arg 0x%x\n", irq, (unsigned int)isr, (unsigned int)arg);
355
356        return BSP_shared_interrupt_register(irq, info, isr, arg);
357}
358
359int leon2_amba_int_unregister
360        (
361        struct drvmgr_dev *dev,
362        int index,
363        drvmgr_isr isr,
364        void *arg
365        )
366{
367        int irq;
368
369        irq = leon2_amba_get_irq(dev, index);
370        if ( irq < 0 )
371                return -1;
372
373        DBG("Unregistering IRQ %d to func 0x%x arg 0x%x\n", irq, (unsigned int)handler, (unsigned int)arg);
374
375        return BSP_shared_interrupt_unregister(irq, isr, arg);
376}
377
378int leon2_amba_int_clear
379        (
380        struct drvmgr_dev *dev,
381        int index
382        )
383{
384        int irq;
385
386        irq = leon2_amba_get_irq(dev, index);
387        if ( irq < 0 )
388                return -1;
389
390        BSP_shared_interrupt_clear(irq);
391
392        return DRVMGR_OK;
393}
394
395int leon2_amba_int_mask
396        (
397        struct drvmgr_dev *dev,
398        int index
399        )
400{
401        int irq;
402
403        irq = leon2_amba_get_irq(dev, index);
404        if ( irq < 0 )
405                return -1;
406
407        BSP_shared_interrupt_mask(irq);
408
409        return DRVMGR_OK;
410}
411
412int leon2_amba_int_unmask
413        (
414        struct drvmgr_dev *dev,
415        int index
416        )
417{
418        int irq;
419
420        irq = leon2_amba_get_irq(dev, index);
421        if ( irq < 0 )
422                return -1;
423
424        BSP_shared_interrupt_unmask(irq);
425
426        return DRVMGR_OK;
427}
428
429struct drvmgr_drv_ops leon2_amba_ops = 
430{
431        .init = {leon2_amba_init1, leon2_amba_init2, NULL, NULL},
432        .remove = leon2_amba_remove,
433        .info = NULL
434};
435
436struct drvmgr_drv leon2_bus_drv =
437{
438        DRVMGR_OBJ_DRV,                 /* Driver */
439        NULL,                           /* Next driver */
440        NULL,                           /* Device list */
441        DRIVER_LEON2_AMBA_ID,           /* Driver ID */
442        "LEON2_AMBA_DRV",               /* Must be placed at top bus */
443        DRVMGR_BUS_TYPE_ROOT,           /* Bus Type */
444        &leon2_amba_ops,                /* Bus Operations */
445        NULL,                           /* Funcs */
446        0,                              /* Device Count */
447        0,                              /* Private structure size */
448};
Note: See TracBrowser for help on using the repository browser.