[41c9282] | 1 | /* |
---|
[9ea65119] | 2 | * AMBA Plug & Play Bus Driver |
---|
[41c9282] | 3 | * |
---|
| 4 | * This driver hook performs bus scanning. |
---|
| 5 | * |
---|
[9ea65119] | 6 | * COPYRIGHT (c) 2011. |
---|
| 7 | * Aeroflex Gaisler |
---|
[41c9282] | 8 | * |
---|
| 9 | * The license and distribution terms for this file may be |
---|
| 10 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 11 | * http://www.rtems.org/license/LICENSE. |
---|
[41c9282] | 12 | */ |
---|
| 13 | |
---|
[0b83afe9] | 14 | #include <bsp.h> |
---|
[46d7fa5] | 15 | #include <bsp/fatal.h> |
---|
[f71f3d31] | 16 | #include <leon.h> |
---|
[31720925] | 17 | #include <grlib/ambapp.h> |
---|
[2c07f24] | 18 | #include <rtems/score/memory.h> |
---|
[a4fa007b] | 19 | #include <rtems/sysinit.h> |
---|
[41c9282] | 20 | |
---|
[2c07f24] | 21 | #include <string.h> |
---|
| 22 | |
---|
[5da315ff] | 23 | unsigned int leon3_timer_prescaler __attribute__((weak)) = 0; |
---|
| 24 | int leon3_timer_core_index __attribute__((weak)) = 0; |
---|
| 25 | |
---|
[9ea65119] | 26 | /* AMBA Plug&Play information description. |
---|
| 27 | * |
---|
| 28 | * After software has scanned AMBA PnP it builds a tree to make |
---|
| 29 | * it easier for drivers to work with the bus architecture. |
---|
| 30 | */ |
---|
[2c07f24] | 31 | static struct ambapp_bus ambapp_plb_instance; |
---|
| 32 | |
---|
| 33 | static void *ambapp_plb_alloc( size_t size ) |
---|
| 34 | { |
---|
| 35 | return _Memory_Allocate( _Memory_Get(), size, CPU_HEAP_ALIGNMENT ); |
---|
| 36 | } |
---|
| 37 | |
---|
| 38 | struct ambapp_bus *ambapp_plb( void ) |
---|
| 39 | { |
---|
| 40 | struct ambapp_bus *plb; |
---|
| 41 | |
---|
| 42 | plb = &ambapp_plb_instance; |
---|
| 43 | |
---|
| 44 | if ( plb->root == NULL ) { |
---|
| 45 | struct ambapp_context ctx; |
---|
| 46 | |
---|
| 47 | ctx.copy_from_device = (ambapp_memcpy_t) memcpy; |
---|
| 48 | ctx.alloc = ambapp_plb_alloc; |
---|
| 49 | |
---|
| 50 | /* Scan AMBA Plug&Play read-only information. The routine builds a PnP |
---|
| 51 | * tree into ambapp_plb in RAM, after this we never access the PnP |
---|
| 52 | * information in hardware directly any more. |
---|
| 53 | * Since on Processor Local Bus (PLB) memory mapping is 1:1 |
---|
| 54 | */ |
---|
| 55 | ambapp_scan( plb, LEON3_IO_AREA, &ctx, NULL ); |
---|
| 56 | } |
---|
| 57 | |
---|
| 58 | return plb; |
---|
| 59 | } |
---|
[41c9282] | 60 | |
---|
[e428dc4a] | 61 | /* If RTEMS_DRVMGR_STARTUP is defined extra code is added that |
---|
| 62 | * registers the GRLIB AMBA PnP bus driver as root driver. |
---|
| 63 | */ |
---|
| 64 | #ifdef RTEMS_DRVMGR_STARTUP |
---|
| 65 | #include <drvmgr/drvmgr.h> |
---|
[31720925] | 66 | #include <grlib/ambapp_bus_grlib.h> |
---|
[e428dc4a] | 67 | |
---|
| 68 | /* Driver resources configuration for AMBA root bus. It is declared weak |
---|
| 69 | * so that the user may override it, if the defualt settings are not |
---|
| 70 | * enough. |
---|
| 71 | */ |
---|
| 72 | struct drvmgr_bus_res grlib_drv_resources __attribute__((weak)) = |
---|
| 73 | { |
---|
| 74 | .next = NULL, |
---|
| 75 | .resource = |
---|
| 76 | { |
---|
[bef5e23e] | 77 | DRVMGR_RES_EMPTY, |
---|
[e428dc4a] | 78 | } |
---|
| 79 | }; |
---|
| 80 | |
---|
| 81 | /* GRLIB AMBA bus configuration (the LEON3 root bus configuration) */ |
---|
[2c07f24] | 82 | struct grlib_config grlib_bus_config; |
---|
| 83 | |
---|
| 84 | static void ambapp_grlib_root_initialize( void ) |
---|
[e428dc4a] | 85 | { |
---|
[2c07f24] | 86 | /* Register Root bus, Use GRLIB AMBA PnP bus as root bus for LEON3 */ |
---|
| 87 | grlib_bus_config.abus = ambapp_plb(); |
---|
| 88 | grlib_bus_config.resources = &grlib_drv_resources; |
---|
| 89 | ambapp_grlib_root_register(&grlib_bus_config); |
---|
| 90 | } |
---|
| 91 | |
---|
| 92 | RTEMS_SYSINIT_ITEM( |
---|
| 93 | ambapp_grlib_root_initialize, |
---|
| 94 | RTEMS_SYSINIT_BSP_START, |
---|
| 95 | RTEMS_SYSINIT_ORDER_SECOND |
---|
[e428dc4a] | 96 | }; |
---|
| 97 | #endif |
---|
| 98 | |
---|
[53ad908] | 99 | rtems_interrupt_lock LEON3_IrqCtrl_Lock = |
---|
| 100 | RTEMS_INTERRUPT_LOCK_INITIALIZER("LEON3 IrqCtrl"); |
---|
[2cb0877] | 101 | |
---|
[41c9282] | 102 | /* Pointers to Interrupt Controller configuration registers */ |
---|
[226d48d8] | 103 | volatile struct irqmp_regs *LEON3_IrqCtrl_Regs; |
---|
[5564b5a] | 104 | struct ambapp_dev *LEON3_IrqCtrl_Adev; |
---|
[9fe249d] | 105 | volatile struct gptimer_regs *LEON3_Timer_Regs; |
---|
[5564b5a] | 106 | struct ambapp_dev *LEON3_Timer_Adev; |
---|
[41c9282] | 107 | |
---|
| 108 | /* |
---|
[d17733c] | 109 | * amba_initialize |
---|
[41c9282] | 110 | * |
---|
[d17733c] | 111 | * Must be called just before drivers are initialized. |
---|
[44b06ca] | 112 | * Used to scan system bus. Probes for AHB masters, AHB slaves and |
---|
[41c9282] | 113 | * APB slaves. Addresses to configuration areas of the AHB masters, |
---|
[44b06ca] | 114 | * AHB slaves, APB slaves and APB master are storeds in |
---|
[41c9282] | 115 | * amba_ahb_masters, amba_ahb_slaves and amba. |
---|
| 116 | */ |
---|
| 117 | |
---|
[a4fa007b] | 118 | static void amba_initialize(void) |
---|
[41c9282] | 119 | { |
---|
[3722ff5a] | 120 | int icsel; |
---|
[9ea65119] | 121 | struct ambapp_dev *adev; |
---|
[2c07f24] | 122 | struct ambapp_bus *plb; |
---|
[03bfdbb] | 123 | |
---|
[2c07f24] | 124 | plb = ambapp_plb(); |
---|
[41c9282] | 125 | |
---|
[684b54a] | 126 | /* Find LEON3 Interrupt controller */ |
---|
[2c07f24] | 127 | adev = (void *)ambapp_for_each(plb, (OPTIONS_ALL|OPTIONS_APB_SLVS), |
---|
[9ea65119] | 128 | VENDOR_GAISLER, GAISLER_IRQMP, |
---|
| 129 | ambapp_find_by_idx, NULL); |
---|
| 130 | if (adev == NULL) { |
---|
[684b54a] | 131 | /* PANIC IRQ controller not found! |
---|
| 132 | * |
---|
| 133 | * What else can we do but stop ... |
---|
| 134 | */ |
---|
[46d7fa5] | 135 | bsp_fatal(LEON3_FATAL_NO_IRQMP_CONTROLLER); |
---|
[41c9282] | 136 | } |
---|
[44b06ca] | 137 | |
---|
[226d48d8] | 138 | LEON3_IrqCtrl_Regs = (volatile struct irqmp_regs *)DEV_TO_APB(adev)->start; |
---|
[5564b5a] | 139 | LEON3_IrqCtrl_Adev = adev; |
---|
[3722ff5a] | 140 | if ((LEON3_IrqCtrl_Regs->ampctrl >> 28) > 0) { |
---|
| 141 | /* IRQ Controller has support for multiple IRQ Controllers, each |
---|
| 142 | * CPU can be routed to different Controllers, we find out which |
---|
| 143 | * controller by looking at the IRQCTRL Select Register for this CPU. |
---|
| 144 | * Each Controller is located at a 4KByte offset. |
---|
| 145 | */ |
---|
| 146 | icsel = LEON3_IrqCtrl_Regs->icsel[LEON3_Cpu_Index/8]; |
---|
| 147 | icsel = (icsel >> ((7 - (LEON3_Cpu_Index & 0x7)) * 4)) & 0xf; |
---|
| 148 | LEON3_IrqCtrl_Regs += icsel; |
---|
| 149 | } |
---|
[ead16ae1] | 150 | LEON3_IrqCtrl_Regs->mask[LEON3_Cpu_Index] = 0; |
---|
| 151 | LEON3_IrqCtrl_Regs->force[LEON3_Cpu_Index] = 0; |
---|
| 152 | LEON3_IrqCtrl_Regs->iclear = 0xffffffff; |
---|
[684b54a] | 153 | |
---|
[95518e59] | 154 | /* Init Extended IRQ controller if available */ |
---|
| 155 | leon3_ext_irq_init(); |
---|
| 156 | |
---|
[ad6a58d] | 157 | /* find GP Timer */ |
---|
[2c07f24] | 158 | adev = (void *)ambapp_for_each(plb, (OPTIONS_ALL|OPTIONS_APB_SLVS), |
---|
[9ea65119] | 159 | VENDOR_GAISLER, GAISLER_GPTIMER, |
---|
[5da315ff] | 160 | ambapp_find_by_idx, &leon3_timer_core_index); |
---|
[9ea65119] | 161 | if (adev) { |
---|
[226d48d8] | 162 | LEON3_Timer_Regs = (volatile struct gptimer_regs *)DEV_TO_APB(adev)->start; |
---|
[5564b5a] | 163 | LEON3_Timer_Adev = adev; |
---|
[9ea65119] | 164 | |
---|
| 165 | /* Register AMBA Bus Frequency */ |
---|
[0a2096b] | 166 | ambapp_freq_init( |
---|
[2c07f24] | 167 | plb, |
---|
[5564b5a] | 168 | LEON3_Timer_Adev, |
---|
[0a2096b] | 169 | (LEON3_Timer_Regs->scaler_reload + 1) |
---|
| 170 | * LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER |
---|
| 171 | ); |
---|
[5da315ff] | 172 | /* Set user prescaler configuration. Use this to increase accuracy of timer |
---|
| 173 | * and accociated services like cpucounter. |
---|
| 174 | * Note that minimum value is the number of timer instances present in |
---|
| 175 | * GRTIMER/GPTIMER hardware. See HW manual. |
---|
| 176 | */ |
---|
| 177 | if (leon3_timer_prescaler) |
---|
| 178 | LEON3_Timer_Regs->scaler_reload = leon3_timer_prescaler; |
---|
[ad6a58d] | 179 | } |
---|
[41c9282] | 180 | } |
---|
[a4fa007b] | 181 | |
---|
| 182 | RTEMS_SYSINIT_ITEM( |
---|
| 183 | amba_initialize, |
---|
[2c07f24] | 184 | RTEMS_SYSINIT_BSP_EARLY, |
---|
| 185 | RTEMS_SYSINIT_ORDER_MIDDLE |
---|
[a4fa007b] | 186 | ); |
---|