//map the spinlock device into memory and reset it errval_t spinlock_init(void) { if (locks_initialized) { printf("spinlock_init: already initialized; skipping.\n"); return SYS_ERR_OK; } lvaddr_t base = paging_map_device(OMAP44XX_MAP_L4_CFG_SPINLOCK, OMAP44XX_MAP_L4_CFG_SPINLOCK_SIZE); // paging_map_device returns an address pointing to the beginning of // a section, need to add the offset for within the section again uint32_t offset = (OMAP44XX_MAP_L4_CFG_SPINLOCK & ARM_L1_SECTION_MASK); printf("spinlock_init: base = 0x%"PRIxLVADDR" 0x%"PRIxLVADDR"\n", base, base + offset); omap44xx_spinlock_initialize(&spinlock, (mackerel_addr_t)base + offset); omap44xx_spinlock_sysconfig_softreset_wrf(&spinlock, 1);//reset module (XXX probably not needed) printf("testing spinlock: first read (should be 0): 0x%x\n", omap44xx_spinlock_lock_reg_i_taken_rdf(&spinlock, 2)); printf("testing spinlock: second read (should be 1): 0x%x\n", omap44xx_spinlock_lock_reg_i_taken_rdf(&spinlock, 2)); omap44xx_spinlock_lock_reg_i_taken_wrf(&spinlock, 2, 0);//clear lock locks_initialized = true; printf("spinlock_init: done.\n"); return SYS_ERR_OK; }
void pic_init(void) { static const uintptr_t PIC_BASE = 0x14000000; arm_icp_pic0_source_t sources = { .SOFTINT = 1, .UARTINT0 = 1, .UARTINT1 = 1, .KBDINT = 1, .MOUSEINT = 1, .TIMERINT0 = 1, .TIMERINT1 = 1, .TIMERINT2 = 1, .RTCINT = 1, .LM_LLINT0 = 1, .LM_LLINT1 = 1, .CLCDCINT = 1, .MMCIINT0 = 1, .MMCIINT1 = 1, .AACIINT = 1, .CPPLDINT = 1, .ETH_INT = 1, .TS_PENINT = 1 }; pic_primary_irqs.val = sources; lvaddr_t pic_base = paging_map_device(PIC_BASE, 0x00100000); arm_icp_pic0_initialize(&pic, (mackerel_addr_t)pic_base); pic_disable_all_irqs(); } void pic_set_irq_enabled(uint32_t irq, bool en) { uint32_t m = 1u << irq; if (irq < 32 && (pic_primary_irqs.raw & m) == m) { if (en) { m |= arm_icp_pic0_PIC_IRQ_ENABLESET_rd_raw(&pic); arm_icp_pic0_PIC_IRQ_ENABLESET_wr_raw(&pic, m); } else { arm_icp_pic0_PIC_IRQ_ENABLECLR_wr_raw(&pic, m); } } else { panic("Unknown IRQ source %"PRIu32, irq); } }
static lvaddr_t pit_map_resources(void) { static lvaddr_t timer_base = 0; if (timer_base == 0) { timer_base = paging_map_device(PIT_BASE, ARM_L1_SECTION_BYTES); } return timer_base; }
static lvaddr_t pit_map_resources(void) { static lvaddr_t timer_base = 0; if (timer_base == 0) { timer_base = paging_map_device(PIT_BASE, 0x100000); } return timer_base; }
/** \brief Map timer device ONCE to virtual memory */ static lvaddr_t pit_map_resources(void) { static lvaddr_t timer_base = 0; //Initialized once by the compiler if (timer_base == 0) { timer_base = paging_map_device(PIT_BASE, 0x100000) + (PIT_BASE & 0x000ffffful); //Base mapping + offset } return timer_base; }
errval_t serial_init(unsigned port) { if (port < NUM_PORTS) { assert(ports[port].base == 0); lvaddr_t base = paging_map_device(0xc0030000ul + port * 0x01000000, 0x00100000); ixp2800_uart_init(&ports[port], base + 0x30000); return SYS_ERR_OK; } else { return SYS_ERR_SERIAL_PORT_INVALID; } }
void scu_enable(void) { lvaddr_t scu_base = paging_map_device(TSC_BASE, ARM_L1_SECTION_BYTES); a9scu_initialize(&scu, (mackerel_addr_t)scu_base); //enable SCU a9scu_SCUControl_t ctrl_reg = a9scu_SCUControl_rd(&scu); ctrl_reg |= 0x1; a9scu_SCUControl_wr(&scu, ctrl_reg); //(should invalidate d-cache here) }
/* * Initialize the global interrupt controller * * There are three types of interrupts * 1) Software generated Interrupts (SGI) - IDs 0-15 * 2) Private Peripheral Interrupts (PPI) - IDs 16-31 * 3) Shared Peripheral Interrups (SPI) - IDs 32... */ void gic_init(void) { lvaddr_t gic_dist_base = paging_map_device( platform_get_distributor_address(), DIST_SIZE ); lvaddr_t gic_cpu_base = paging_map_device( platform_get_gic_cpu_address(), CPU_SIZE ); pl130_gic_initialize(&gic, (mackerel_addr_t)gic_dist_base, (mackerel_addr_t)gic_cpu_base ); // read GIC configuration gic_config = pl130_gic_ICDICTR_rd(&gic); // ARM GIC 2.0 TRM, Table 4-6 // This is the number of ICDISERs, i.e. #SPIs // Number of SGIs (0-15) and PPIs (16-31) is fixed uint32_t it_num_lines_tmp = pl130_gic_ICDICTR_it_lines_num_extract(gic_config); it_num_lines = 32*(it_num_lines_tmp + 1); MSG("%d interrupt lines detected\n", it_num_lines); cpu_number = pl130_gic_ICDICTR_cpu_number_extract(gic_config) + 1; // set priority mask of cpu interface, currently set to lowest priority // to accept all interrupts pl130_gic_ICCPMR_wr(&gic, 0xff); // set binary point to define split of group- and subpriority // currently we allow for 8 subpriorities pl130_gic_ICCBPR_wr(&gic, 0x2); // enable interrupt forwarding to processor pl130_gic_ICCICR_enable_wrf(&gic, 0x1); // Distributor: // enable interrupt forwarding from distributor to cpu interface pl130_gic_ICDDCR_enable_wrf(&gic, 0x1); MSG("gic_init done\n"); }
/* * Initialize a serial port */ errval_t serial_init(unsigned port, bool hwinit) { if (port < NUM_PORTS) { lvaddr_t base = paging_map_device(UART0_VBASE + port*UART_MAPPING_DIFF, UART_DEVICE_BYTES); if (hwinit) { pl011_uart_init(&ports[port], base + UART0_SECTION_OFFSET + port*UART_MAPPING_DIFF); } return SYS_ERR_OK; } else { return SYS_ERR_SERIAL_PORT_INVALID; } }
void write_sysflags_reg(uint32_t regval) { if (sysflagset_base == 0) { printf("SYSFLAGSET_BASE is at 0x%x\n", SYSFLAGSET_BASE); sysflagset_base = paging_map_device(SYSFLAGSET_BASE, ARM_L1_SECTION_BYTES); printf(".. mapped to 0x%"PRIxLVADDR"\n", sysflagset_base); } lvaddr_t sysflags = sysflagset_base + SYSFLAGSET_OFFSET; printf(".. using address 0x%p\n", sysflags); *((uint32_t *)sysflags)= regval; }
/* * Re-initialize UARTs after the MMU is on. */ void omap_uart_init(unsigned port, bool initialize_hw) { assert( port < NUM_PORTS ); // Ensure port has already been initialized early assert( port_sizes[port] != 0 ); assert( port_addrs[port] != 0 ); lvaddr_t base = paging_map_device( port_addrs[port], port_sizes[port] ); MSG(port, "base = 0x%"PRIxLVADDR"\n", base); omap_uart_initialize(&ports[port], (mackerel_addr_t) base); if (initialize_hw && !port_inited[port]) { omap_uart_hw_init(&ports[port]); port_inited[port] = true; } MSG(port,"done.\n"); }
void tsc_init(void) { lvaddr_t timer_base = paging_map_device(TSC_BASE, ARM_L1_SECTION_BYTES); cortex_a9_pit_initialize(&tsc, (mackerel_addr_t)timer_base+TSC_OFFSET); // write load uint32_t load = ~0ul; cortex_a9_pit_TimerLoad_wr(&tsc, load); //configure tsc cortex_a9_pit_TimerControl_prescale_wrf(&tsc, 0); cortex_a9_pit_TimerControl_int_enable_wrf(&tsc, 0); cortex_a9_pit_TimerControl_auto_reload_wrf(&tsc, 1); cortex_a9_pit_TimerControl_timer_enable_wrf(&tsc, 1); }
/** \brief Initialize interrupt controller. Disable all irqs. */ void pic_init(void) { //Base address for programmable interrupt controller static const uintptr_t PIC_BASE = 0xd6000000; //Enable irq for timer, uart and error sum (or of all interrupts) pic_primary_irqs = ixp2800_icp_pic0_source_default; pic_primary_irqs = ixp2800_icp_pic0_source_TIMER_UFLW_insert(pic_primary_irqs, 1); pic_primary_irqs = ixp2800_icp_pic0_source_UART_INT_insert(pic_primary_irqs, 1); pic_primary_irqs = ixp2800_icp_pic0_source_ERROR_SUM_insert(pic_primary_irqs, 1); //Map to virtual memory and initialize lvaddr_t pic_base = paging_map_device(PIC_BASE, 0x00100000); ixp2800_icp_pic0_initialize(&pic, (mackerel_addr_t)pic_base); pic_disable_all_irqs(); }
/** * \brief Reinitialize console UART after setting up the MMU * This function is needed in milestone 1. */ void serial_map_registers(void) { if (uart_initialized) { printf("omap serial map registers: serial registers already mapped, skipping\n"); return; } lvaddr_t base = paging_map_device(UART_BASE, UART_SIZE); // paging_map_device returns an address pointing to the beginning of // a section, need to add the offset for within the section again uint32_t offset = (UART_BASE & ARM_L1_SECTION_MASK); printf("omap serial_map_registers: base = 0x%"PRIxLVADDR" 0x%"PRIxLVADDR"\n", base, base + offset); set_register_addresses(base + offset); uart_initialized = true; printf("omap serial_map_registers: done.\n"); return; }
void gic_init(void) { lvaddr_t gic_base = paging_map_device(PIC_BASE, ARM_L1_SECTION_BYTES); pl130_gic_initialize(&gic, (mackerel_addr_t)gic_base + DIST_OFFSET, (mackerel_addr_t)gic_base + CPU_OFFSET); //read GIC configuration gic_config = pl130_gic_ICDICTR_rd(&gic); it_num_lines = pl130_gic_ICDICTR_it_lines_num_extract(gic_config); cpu_number = pl130_gic_ICDICTR_cpu_number_extract(gic_config); sec_extn_implemented = pl130_gic_ICDICTR_TZ_extract(gic_config); gic_cpu_interface_init(); if(hal_cpu_is_bsp()) { gic_distributor_init(); } }
/** * \brief Boot an arm app core * * \param core_id ID of the core to try booting * \param entry Entry address for new kernel in the destination * architecture's lvaddr_t * * \returns Zero on successful boot, non-zero (error code) on failure */ int start_aps_arm_start(uint8_t core_id, lvaddr_t entry) { //printf("----> %s (%s:%d): core_id=%u entry=0x%lx\n", // __FUNCTION__, __FILE__, __LINE__, // core_id, entry); /* pointer to the pseudo-lock used to detect boot up of new core */ volatile uint32_t *ap_wait = (uint32_t*)local_phys_to_mem(AP_WAIT_PHYS); *ap_wait = AP_STARTING_UP; cp15_invalidate_d_cache(); // map AUX_CORE_BOOT section static lvaddr_t aux_core_boot = 0; if (aux_core_boot == 0) aux_core_boot = paging_map_device(AUX_CORE_BOOT_SECT, ARM_L1_SECTION_BYTES); volatile lvaddr_t *aux_core_boot_0, *aux_core_boot_1; // The AUX_CORE_BOOT_0 register is used to store the startup state aux_core_boot_0 = (void *)(aux_core_boot + AUX_CORE_BOOT_0_OFFSET); aux_core_boot_1 = (void *)(aux_core_boot + AUX_CORE_BOOT_1_OFFSET); //write entry address of new kernel to SYSFLAG reg // Set address where the other core should jump debug(SUBSYS_STARTUP, "setting AUX_CORE_BOOT_1 to 0x%"PRIxLVADDR"\n", entry); *aux_core_boot_1 = entry; // Tell ROM code to start other core debug(SUBSYS_STARTUP, "AUX_CORE_BOOT_0 |= 1<< 2\n"); *aux_core_boot_0 |= 1 << 2; // send signal to app core to start debug(SUBSYS_STARTUP, "sending event to other core(s?)\n"); __asm__ volatile ("SEV"); debug(SUBSYS_STARTUP, "waiting for response\n"); while (*aux_core_boot_0 != 2<<2) ; debug(SUBSYS_STARTUP, "booted CPU%hhu\n", core_id); return 0; }
void gic_map_and_init(pl130_gic_t *gic) { lvaddr_t gic_base = paging_map_device(GIC_BASE, LARGE_PAGE_SIZE); pl130_gic_initialize(gic, (mackerel_addr_t)gic_base + DIST_OFFSET, (mackerel_addr_t)gic_base + CPU_OFFSET); }
void gic_map_and_init(pl130_gic_t *gic) { lvaddr_t gic_base = paging_map_device(GIC_BASE, ARM_L1_SECTION_BYTES); pl130_gic_initialize(gic, (mackerel_addr_t)gic_base + DIST_OFFSET, (mackerel_addr_t)gic_base + CPU_OFFSET); }