1/* 2 * Copyright 2018, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the GNU General Public License version 2. Note that NO WARRANTY is provided. 8 * See "LICENSE_GPLv2.txt" for details. 9 * 10 * @TAG(DATA61_GPL) 11 */ 12 13/* 14 * 15 * Copyright 2016, 2017 Hesham Almatary, Data61/CSIRO <hesham.almatary@data61.csiro.au> 16 * Copyright 2015, 2016 Hesham Almatary <heshamelmatary@gmail.com> 17 */ 18 19#include <types.h> 20#include <util.h> 21#include <machine/io.h> 22#include <kernel/vspace.h> 23#include <arch/machine.h> 24#include <arch/kernel/vspace.h> 25#include <plat/machine.h> 26#include <linker.h> 27#include <plat/machine/devices.h> 28#include <plat/machine/hardware.h> 29#include <arch/sbi.h> 30 31#define MAX_AVAIL_P_REGS 2 32 33#define RESET_CYCLES ((CONFIG_SPIKE_CLOCK_FREQ / MS_IN_S) * CONFIG_TIMER_TICK_MS) 34 35/* Available physical memory regions on platform (RAM minus kernel image). */ 36/* NOTE: Regions are not allowed to be adjacent! */ 37 38static word_t BOOT_DATA num_avail_p_regs = 0; 39static p_region_t BOOT_DATA avail_p_regs[MAX_AVAIL_P_REGS]; 40 41BOOT_CODE int get_num_avail_p_regs(void) 42{ 43 return num_avail_p_regs; 44} 45 46BOOT_CODE p_region_t get_avail_p_reg(unsigned int i) 47{ 48 return avail_p_regs[i]; 49} 50 51BOOT_CODE bool_t add_avail_p_reg(p_region_t reg) 52{ 53 if (num_avail_p_regs == MAX_AVAIL_P_REGS) { 54 return false; 55 } 56 avail_p_regs[num_avail_p_regs] = reg; 57 num_avail_p_regs++; 58 return true; 59} 60 61/** 62 DONT_TRANSLATE 63 */ 64interrupt_t 65getActiveIRQ(void) 66{ 67 68 uint64_t temp = 0; 69 asm volatile ("csrr %0, scause":"=r" (temp)::); 70 71 if (!(temp & BIT(CONFIG_WORD_SIZE - 1))) { 72 return irqInvalid; 73 } 74 75 return (temp & 0xf); 76} 77 78/* Check for pending IRQ */ 79bool_t isIRQPending(void) 80{ 81 return (getActiveIRQ() != irqInvalid); 82} 83 84/* Enable or disable irq according to the 'disable' flag. */ 85/** 86 DONT_TRANSLATE 87*/ 88void 89maskInterrupt(bool_t disable, interrupt_t irq) 90{ 91 if (disable) { 92 if (irq > 1) { 93 clear_sie_mask(BIT(irq)); 94 } 95 } else { 96 /* FIXME: currently only account for user/supervisor and timer interrupts */ 97 if (irq == 4 /* user timer */ || irq == 5 /* supervisor timer */) { 98 set_sie_mask(BIT(irq)); 99 } else { 100 /* TODO: account for external and PLIC interrupts */ 101 } 102 } 103} 104 105/* Determine if the given IRQ should be reserved by the kernel. */ 106bool_t CONST 107isReservedIRQ(irq_t irq) 108{ 109 printf("isReservedIRQ \n"); 110 return false; 111} 112 113/* Handle a platform-reserved IRQ. */ 114void 115handleReservedIRQ(irq_t irq) 116{ 117 printf("handleReservedIRQ \n"); 118} 119 120void 121ackInterrupt(irq_t irq) 122{ 123 // don't ack the kernel timer interrupt, see the comment in resetTimer 124 // to understand why 125 if (irq != KERNEL_TIMER_IRQ) { 126 clear_sip_mask(BIT(irq)); 127 } 128 //set_csr(scause, 0); 129 130 if (irq == 1) { 131 sbi_clear_ipi(); 132 } 133} 134 135static inline uint64_t get_cycles(void) 136#if __riscv_xlen == 32 137{ 138 uint32_t nH, nL; 139 __asm__ __volatile__ ( 140 "rdtimeh %0\n" 141 "rdtime %1\n" 142 : "=r" (nH), "=r" (nL)); 143 return ((uint64_t) ((uint64_t) nH << 32)) | (nL); 144} 145#else 146{ 147 uint64_t n; 148 __asm__ __volatile__ ( 149 "rdtime %0" 150 : "=r" (n)); 151 return n; 152} 153#endif 154 155static inline int read_current_timer(unsigned long *timer_val) 156{ 157 *timer_val = get_cycles(); 158 return 0; 159} 160 161void 162resetTimer(void) 163{ 164 uint64_t target; 165 // ack the timer interrupt. we do this here as due to slow simulation platform there 166 // is a race between us setting the new interrupt here, and the ackInterrupt call in 167 // handleInterrupt that will happen at some point after this call to resetTimer 168 clear_sip_mask(KERNEL_TIMER_IRQ); 169 // repeatedly try and set the timer in a loop as otherwise there is a race and we 170 // may set a timeout in the past, resulting in it never getting triggered 171 do { 172 target = get_cycles() + RESET_CYCLES; 173 sbi_set_timer(target); 174 } while (get_cycles() > target); 175} 176 177/** 178 DONT_TRANSLATE 179 */ 180BOOT_CODE void 181initTimer(void) 182{ 183 sbi_set_timer(get_cycles() + RESET_CYCLES); 184} 185 186void plat_cleanL2Range(paddr_t start, paddr_t end) 187{ 188} 189void plat_invalidateL2Range(paddr_t start, paddr_t end) 190{ 191} 192 193void plat_cleanInvalidateL2Range(paddr_t start, paddr_t end) 194{ 195} 196 197/** 198 DONT_TRANSLATE 199 */ 200BOOT_CODE void 201initL2Cache(void) 202{ 203} 204 205/** 206 DONT_TRANSLATE 207 */ 208BOOT_CODE void 209initIRQController(void) 210{ 211 /* Do nothing */ 212} 213 214void 215handleSpuriousIRQ(void) 216{ 217 /* Do nothing */ 218 printf("Superior IRQ!! \n"); 219} 220