Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:08

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  LEON2 Hardcoded bus driver.
0004  *
0005  *  COPYRIGHT (c) 2008.
0006  *  Cobham Gaisler AB.
0007  *
0008  *  Bus driver for a hardcoded setup. LEON2 systems have some
0009  *  cores always present, here called "Standard Cores". In 
0010  *  addtion to the standard cores there are often extra cores
0011  *  that can be defined using the "Custom Cores" mechanism.
0012  *
0013  *  A Core is described by assigning a base register and 
0014  *  IRQ0..IRQ15 using the leon2_core structure.
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 #include <stdio.h>
0039 #include <stdlib.h>
0040 #include <string.h>
0041 
0042 #include <drvmgr/drvmgr.h>
0043 #include <drvmgr/leon2_amba_bus.h>
0044 
0045 #include <bsp.h>
0046 #include <rtems/bspIo.h>
0047 
0048 #define DBG(args...)
0049 /*#define DBG(args...) printk(args)*/
0050 
0051 struct drvmgr_drv leon2_bus_drv;
0052 
0053 int leon2_amba_bus_init1(struct drvmgr_bus *bus);
0054 int leon2_amba_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev);
0055 int leon2_amba_int_register(
0056     struct drvmgr_dev *dev,
0057     int index,
0058     const char *info,
0059     drvmgr_isr isr,
0060     void *arg);
0061 int leon2_amba_int_unregister(
0062     struct drvmgr_dev *dev,
0063     int index,
0064     drvmgr_isr isr,
0065     void *arg);
0066 int leon2_amba_int_clear(
0067     struct drvmgr_dev *dev,
0068     int index);
0069 int leon2_amba_int_mask(
0070     struct drvmgr_dev *dev,
0071     int index);
0072 int leon2_amba_int_unmask(
0073     struct drvmgr_dev *dev,
0074     int index);
0075 
0076 /* LEON2 bus operations */
0077 struct drvmgr_bus_ops leon2_amba_bus_ops =
0078 {
0079     .init = {
0080         leon2_amba_bus_init1,
0081         NULL,
0082         NULL,
0083         NULL
0084     },
0085     .remove = NULL,
0086     .unite      = leon2_amba_unite,
0087     .int_register   = leon2_amba_int_register,
0088     .int_unregister = leon2_amba_int_unregister,
0089     .int_clear  = leon2_amba_int_clear,
0090     .int_mask   = leon2_amba_int_mask,
0091     .int_unmask = leon2_amba_int_unmask,
0092     .get_params = NULL,
0093 };
0094 
0095 struct leon2_isr_handler {
0096     void (*handler)(int irq, void *arg);
0097     void *arg;
0098 };
0099 
0100 /* Standard LEON2 configuration */
0101 
0102 struct drvmgr_key leon2_timers[] =
0103 {
0104     {"REG0", DRVMGR_KT_INT, {0x80000040}},
0105     {"IRQ0", DRVMGR_KT_INT, {8}},
0106     {"IRQ1", DRVMGR_KT_INT, {9}},
0107     DRVMGR_KEY_EMPTY
0108 };
0109 
0110 struct drvmgr_key leon2_uart1[] =
0111 {
0112     {"REG0", DRVMGR_KT_INT, {0x80000070}},
0113     {"IRQ0", DRVMGR_KT_INT, {3}},
0114     DRVMGR_KEY_EMPTY
0115 };
0116 
0117 struct drvmgr_key leon2_uart2[] =
0118 {
0119     {"REG0", DRVMGR_KT_INT, {0x80000080}},
0120     {"IRQ0", DRVMGR_KT_INT, {2}},
0121     DRVMGR_KEY_EMPTY
0122 };
0123 
0124 struct drvmgr_key leon2_irqctrl[] =
0125 {
0126     {"REG0", DRVMGR_KT_INT, {0x80000090}},
0127     DRVMGR_KEY_EMPTY
0128 };
0129 
0130 struct drvmgr_key leon2_gpio0[] =
0131 {
0132     {"REG0", DRVMGR_KT_INT, {0x800000A0}},
0133     {"IRQ0", DRVMGR_KT_INT, {4}},
0134     {"IRQ1", DRVMGR_KT_INT, {5}},
0135     {"IRQ2", DRVMGR_KT_INT, {6}},
0136     {"IRQ3", DRVMGR_KT_INT, {7}},
0137     DRVMGR_KEY_EMPTY
0138 };
0139 
0140 struct leon2_core leon2_std_cores[] = 
0141 {
0142     {{LEON2_AMBA_TIMER_ID}, "Timers", &leon2_timers[0]},
0143     {{LEON2_AMBA_UART_ID}, "Uart1", &leon2_uart1[0]},
0144     {{LEON2_AMBA_UART_ID}, "Uart2", &leon2_uart2[0]},
0145     {{LEON2_AMBA_IRQCTRL_ID}, "IRQCtrl", &leon2_irqctrl[0]},
0146     {{LEON2_AMBA_GPIO_ID}, "GPIO", &leon2_gpio0[0]},
0147     EMPTY_LEON2_CORE
0148 };
0149 
0150 static struct leon2_bus *leon2_bus_config = NULL;
0151 static struct drvmgr_bus_res *leon2_bus_res = NULL;
0152 
0153 int leon2_root_register(
0154     struct leon2_bus *bus_config,
0155     struct drvmgr_bus_res *resources)
0156 {
0157     /* Save the configuration for later */
0158     leon2_bus_config = bus_config;
0159     leon2_bus_res = resources;
0160 
0161     /* Register root device driver */
0162     drvmgr_root_drv_register(&leon2_bus_drv);
0163 
0164     return 0;
0165 }
0166 
0167 static int leon2_amba_dev_register(
0168     struct drvmgr_bus *bus,
0169     struct leon2_core *core,
0170     int index)
0171 {
0172     struct drvmgr_dev *newdev;
0173     struct leon2_amba_dev_info *info;
0174     union drvmgr_key_value *value;
0175     char irq_name[8];
0176     int i;
0177 
0178     /* Allocate new device and businfo */
0179     drvmgr_alloc_dev(&newdev, sizeof(struct leon2_amba_dev_info));
0180     info = (struct leon2_amba_dev_info *)(newdev + 1);
0181 
0182     /* Set Core ID */
0183     info->core_id = core->id.core_id;
0184 
0185     /* Get information from bus configuration */
0186     value = drvmgr_key_val_get(core->keys, "REG0", DRVMGR_KT_INT);
0187     if ( !value ) {
0188         printk("leon2_amba_dev_register: Failed getting resource REG0\n");
0189         info->reg_base = 0x00000000;
0190     } else {
0191         DBG("leon2_amba_dev_register: REG0: 0x%08x\n", value->i);
0192         info->reg_base = value->i;
0193     }
0194 
0195     strcpy(irq_name, "IRQ");
0196     for(i=0; i<16; i++){
0197         if ( i < 10 ){
0198             irq_name[3] = '0' + i;
0199             irq_name[4] = '\0';
0200         } else {
0201             irq_name[3] = '1';
0202             irq_name[4] = '0' + (i-10);
0203             irq_name[5] = '\0';
0204         }
0205 
0206         value = drvmgr_key_val_get(core->keys, irq_name, DRVMGR_KT_INT);
0207         if ( !value ) {
0208             DBG("leon2_amba_dev_register: Failed getting resource IRQ%d for REG 0x%x\n", i, info->reg_base);
0209             info->irqs[i] = 0;
0210         } else {
0211             DBG("leon2_amba_dev_register: IRQ%d: %d\n", i, value->i);
0212             info->irqs[i] = value->i;
0213         }
0214     }
0215 
0216     /* Init new device */
0217     newdev->next = NULL;
0218     newdev->parent = bus; /* Ourselfs */
0219     newdev->minor_drv = 0;
0220     newdev->minor_bus = 0;
0221     newdev->businfo = (void *)info;
0222     newdev->priv = NULL;
0223     newdev->drv = NULL;
0224     newdev->name = core->name;
0225     newdev->next_in_drv = NULL;
0226     newdev->bus = NULL;
0227 
0228     /* Register new device */
0229     drvmgr_dev_register(newdev);
0230 
0231     return 0;
0232 }
0233 
0234 static int leon2_amba_init1(struct drvmgr_dev *dev)
0235 {
0236     /* Init our own device */
0237     dev->priv = NULL;
0238     dev->name = "LEON2 AMBA";
0239 
0240     /* Init the bus */
0241     drvmgr_alloc_bus(&dev->bus, 0);
0242     dev->bus->bus_type = DRVMGR_BUS_TYPE_LEON2_AMBA;
0243     dev->bus->next = NULL;
0244     dev->bus->dev = dev;
0245     dev->bus->priv = NULL;
0246     dev->bus->children = NULL;
0247     dev->bus->ops = &leon2_amba_bus_ops;
0248     dev->bus->dev_cnt = 0;
0249     dev->bus->reslist = NULL;
0250     dev->bus->maps_up = leon2_bus_config->maps_up;
0251     dev->bus->maps_down = leon2_bus_config->maps_down;
0252     drvmgr_bus_register(dev->bus);
0253 
0254     return DRVMGR_OK;
0255 }
0256 
0257 static int leon2_amba_init2(struct drvmgr_dev *dev)
0258 {
0259     return DRVMGR_OK;
0260 }
0261 
0262 static int leon2_amba_remove(struct drvmgr_dev *dev)
0263 {
0264     return DRVMGR_OK;
0265 }
0266 
0267 int leon2_amba_bus_init1(struct drvmgr_bus *bus)
0268 {
0269     struct leon2_core *core;
0270     int i;
0271 
0272     if ( leon2_bus_res )
0273         drvmgr_bus_res_add(bus, leon2_bus_res);
0274 
0275     /**** REGISTER NEW DEVICES ****/
0276     i=0;
0277     core = leon2_bus_config->std_cores;
0278     if ( core ) {
0279         while ( core->id.core_id ) {
0280             if ( leon2_amba_dev_register(bus, core, i) ) {
0281                 return RTEMS_UNSATISFIED;
0282             }
0283             i++;
0284             core++;
0285         }
0286     }
0287     core = leon2_bus_config->custom_cores;
0288     if ( core ) {
0289         while ( core->id.core_id ) {
0290             if ( leon2_amba_dev_register(bus, core, i) ) {
0291                 return RTEMS_UNSATISFIED;
0292             }
0293             i++;
0294             core++;
0295         }
0296     }
0297 
0298     return 0;
0299 }
0300 
0301 int leon2_amba_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev)
0302 {
0303     struct leon2_amba_dev_info *info;
0304     struct leon2_amba_drv_info *adrv;
0305     struct leon2_amba_dev_id *id;
0306 
0307     if ( !drv || !dev || !dev->parent )
0308         return 0;
0309 
0310     if ( (drv->bus_type!=DRVMGR_BUS_TYPE_LEON2_AMBA) || (dev->parent->bus_type != DRVMGR_BUS_TYPE_LEON2_AMBA) ) {
0311         return 0;
0312     }
0313 
0314     info = (struct leon2_amba_dev_info *)dev->businfo;
0315     if ( !info ) 
0316         return 0;
0317 
0318     /* Get LEON2 AMBA driver info */
0319     adrv = (struct leon2_amba_drv_info *)drv;
0320     id = adrv->ids;
0321     if ( !id )
0322         return 0;
0323 
0324     while ( id->core_id ) {
0325         if ( id->core_id == info->core_id ) {
0326             /* Driver is suitable for device, Unite them */
0327             return 1;
0328         }
0329         id++;
0330     }
0331 
0332     return 0;
0333 }
0334 
0335 static int leon2_amba_get_irq(struct drvmgr_dev *dev, int index)
0336 {
0337     int irq;
0338     struct leon2_amba_dev_info *info;
0339 
0340     if ( !dev || (index > 15) )
0341         return -1;
0342 
0343     /* Relative (positive) or absolute (negative) IRQ number */
0344     if ( index >= 0 ) {
0345         /* IRQ Index relative to Cores base IRQ */
0346 
0347         /* Get IRQ array configured by user */
0348         info = (struct leon2_amba_dev_info *)dev->businfo;
0349         irq = info->irqs[index];
0350         if ( irq == 0 )
0351             return -1;
0352     } else {
0353         /* Absolute IRQ number */
0354         irq = -index;
0355     }
0356     return irq;
0357 }
0358 
0359 int leon2_amba_int_register
0360     (
0361     struct drvmgr_dev *dev,
0362     int index,
0363     const char *info,
0364     drvmgr_isr isr,
0365     void *arg
0366     )
0367 {
0368     int irq;
0369 
0370     irq = leon2_amba_get_irq(dev, index);
0371     if ( irq < 0 )
0372         return -1;
0373 
0374     DBG("Registering IRQ %d to func 0x%x arg 0x%x\n", irq, (unsigned int)isr, (unsigned int)arg);
0375 
0376     return rtems_interrupt_handler_install(irq, info, RTEMS_INTERRUPT_SHARED, isr, arg);
0377 }
0378 
0379 int leon2_amba_int_unregister
0380     (
0381     struct drvmgr_dev *dev,
0382     int index,
0383     drvmgr_isr isr,
0384     void *arg
0385     )
0386 {
0387     int irq;
0388 
0389     irq = leon2_amba_get_irq(dev, index);
0390     if ( irq < 0 )
0391         return -1;
0392 
0393     DBG("Unregistering IRQ %d to func 0x%x arg 0x%x\n", irq, (unsigned int)handler, (unsigned int)arg);
0394 
0395     return rtems_interrupt_handler_remove(irq, isr, arg);
0396 }
0397 
0398 int leon2_amba_int_clear
0399     (
0400     struct drvmgr_dev *dev,
0401     int index
0402     )
0403 {
0404     int irq;
0405 
0406     irq = leon2_amba_get_irq(dev, index);
0407     if ( irq < 0 )
0408         return -1;
0409 
0410     if (rtems_interrupt_clear(irq) != RTEMS_SUCCESSFUL) {
0411         return DRVMGR_FAIL;
0412     }
0413 
0414     return DRVMGR_OK;
0415 }
0416 
0417 int leon2_amba_int_mask
0418     (
0419     struct drvmgr_dev *dev,
0420     int index
0421     )
0422 {
0423     int irq;
0424 
0425     irq = leon2_amba_get_irq(dev, index);
0426     if ( irq < 0 )
0427         return -1;
0428 
0429     if (rtems_interrupt_vector_disable(irq) != RTEMS_SUCCESSFUL) {
0430         return DRVMGR_FAIL;
0431     }
0432 
0433     return DRVMGR_OK;
0434 }
0435 
0436 int leon2_amba_int_unmask
0437     (
0438     struct drvmgr_dev *dev,
0439     int index
0440     )
0441 {
0442     int irq;
0443 
0444     irq = leon2_amba_get_irq(dev, index);
0445     if ( irq < 0 )
0446         return -1;
0447 
0448     if (rtems_interrupt_vector_enable(irq) != RTEMS_SUCCESSFUL) {
0449         return DRVMGR_FAIL;
0450     }
0451 
0452     return DRVMGR_OK;
0453 }
0454 
0455 struct drvmgr_drv_ops leon2_amba_ops = 
0456 {
0457     .init = {leon2_amba_init1, leon2_amba_init2, NULL, NULL},
0458     .remove = leon2_amba_remove,
0459     .info = NULL
0460 };
0461 
0462 struct drvmgr_drv leon2_bus_drv =
0463 {
0464     DRVMGR_OBJ_DRV,         /* Driver */
0465     NULL,               /* Next driver */
0466     NULL,               /* Device list */
0467     DRIVER_LEON2_AMBA_ID,       /* Driver ID */
0468     "LEON2_AMBA_DRV",       /* Must be placed at top bus */
0469     DRVMGR_BUS_TYPE_ROOT,       /* Bus Type */
0470     &leon2_amba_ops,        /* Bus Operations */
0471     NULL,               /* Funcs */
0472     0,              /* Device Count */
0473     0,              /* Private structure size */
0474 };