source: rtems/bsps/sparc/shared/drvmgr/leon2_amba_bus.c @ d60d303c

5
Last change on this file since d60d303c was d60d303c, checked in by Sebastian Huber <sebastian.huber@…>, on 04/20/18 at 11:33:24

bsps/sparc: Move shared files to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

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