1 /* 2 * Copyright (c) 2019 Elliot Berman 3 * 4 * Use of this source code is governed by a MIT-style 5 * license that can be found in the LICENSE file or at 6 * https://opensource.org/licenses/MIT 7 */ 8 9 #pragma once 10 11 #include <config.h> 12 13 #include <lk/reg.h> 14 #include <arch/arch_ops.h> 15 16 #if RISCV_M_MODE 17 18 // platform must define these 19 #ifndef ARCH_RISCV_CLINT_BASE 20 #error Platform must define ARCH_RISCV_CLINT_BASE 21 #endif 22 #ifndef ARCH_RISCV_MTIME_RATE 23 #error Platform must define ARCH_RISCV_MTIME_RATE 24 #endif 25 26 #define CLINT_MSIP(h) (ARCH_RISCV_CLINT_BASE + (4 * (h))) 27 #define CLINT_MTIMECMP(h) (ARCH_RISCV_CLINT_BASE + 0x4000 + (8 * (h))) 28 #define CLINT_MTIME (ARCH_RISCV_CLINT_BASE + 0xbff8) 29 clint_ipi_send(unsigned long target_hart)30static inline void clint_ipi_send(unsigned long target_hart) { 31 if (target_hart >= SMP_MAX_CPUS) 32 return; 33 34 *REG32(CLINT_MSIP(target_hart)) = 1; 35 } 36 clint_ipi_clear(unsigned long target_hart)37static inline void clint_ipi_clear(unsigned long target_hart) { 38 if (target_hart >= SMP_MAX_CPUS) 39 return; 40 41 *REG32(CLINT_MSIP(target_hart)) = 0; 42 } 43 clint_set_timer(uint64_t ticks)44static inline void clint_set_timer(uint64_t ticks) { 45 *REG64(CLINT_MTIMECMP(riscv_current_hart())) = ticks; 46 } 47 48 riscv_get_time(void)49static inline uint64_t riscv_get_time(void) { 50 return *REG64(CLINT_MTIME); 51 } 52 clint_send_ipis(const unsigned long * hart_mask)53static inline void clint_send_ipis(const unsigned long *hart_mask) { 54 unsigned long cur_hart = riscv_current_hart(), h, m = *hart_mask; 55 for (h = 0; h < SMP_MAX_CPUS && m; h++, m >>= 1) { 56 if ((m & 1) && (h != cur_hart)) { 57 clint_ipi_send(h); 58 } 59 } 60 61 if (*hart_mask & (1 << riscv_current_hart())) { 62 clint_ipi_send(cur_hart); 63 } 64 } 65 66 #endif 67