1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2025 Beijing Institute of Open Source Chip (BOSC) 4 */ 5 6 #include <assert.h> 7 #include <compiler.h> 8 #include <config.h> 9 #include <drivers/aplic.h> 10 #include <drivers/aplic_priv.h> 11 #include <io.h> 12 #include <kernel/interrupt.h> 13 #include <kernel/misc.h> 14 #include <kernel/panic.h> 15 #include <mm/core_memprot.h> 16 #include <mm/core_mmu.h> 17 #include <platform_config.h> 18 #include <stdlib.h> 19 #include <sys/queue.h> 20 #include <trace.h> 21 #include <types_ext.h> 22 #include <util.h> 23 24 static struct aplic_data aplic_data __nex_bss; 25 26 static void aplic_set_target(struct aplic_data *aplic, uint32_t source, 27 uint32_t hart_idx, uint32_t guest_idx, 28 uint32_t eiid) 29 { 30 vaddr_t target = 0; 31 uint32_t val = 0; 32 33 val = SHIFT_U32(hart_idx, APLIC_TARGET_HART_IDX_SHIFT) & 34 APLIC_TARGET_HART_IDX_MASK; 35 val |= SHIFT_U32(guest_idx, APLIC_TARGET_GUEST_IDX_SHIFT) & 36 APLIC_TARGET_GUEST_IDX_MASK; 37 val |= eiid & APLIC_TARGET_EIID_MASK; 38 39 target = aplic->aplic_base + APLIC_TARGET_BASE + 40 (source - 1) * sizeof(uint32_t); 41 io_write32(target, val); 42 } 43 44 static uint32_t __unused aplic_get_source_mode(struct aplic_data *aplic, 45 uint32_t source) 46 { 47 uint32_t sm = 0; 48 49 sm = io_read32(aplic->aplic_base + APLIC_SOURCECFG_BASE + 50 (source - 1) * sizeof(uint32_t)); 51 52 return sm & APLIC_SOURCECFG_SM_MASK; 53 } 54 55 static void aplic_init_base_addr(struct aplic_data *aplic, 56 paddr_t aplic_base_pa) 57 { 58 vaddr_t aplic_base = 0; 59 60 assert(cpu_mmu_enabled()); 61 62 aplic_base = core_mmu_get_va(aplic_base_pa, MEM_AREA_IO_SEC, 63 APLIC_SIZE); 64 if (!aplic_base) 65 panic(); 66 67 aplic->aplic_base = aplic_base; 68 aplic->size = APLIC_SIZE; 69 aplic->targets_mmode = false; 70 aplic->num_idc = 0; 71 aplic->num_source = APLIC_NUM_SOURCE; 72 } 73 74 static void aplic_op_configure(struct itr_chip *chip, size_t it, uint32_t type, 75 uint32_t prio __unused) 76 { 77 struct aplic_data *aplic = container_of(chip, struct aplic_data, chip); 78 size_t hartid = get_core_pos(); 79 80 if (aplic_is_bad_it(aplic, it)) 81 panic(); 82 83 aplic_disable_interrupt(aplic, it); 84 if (aplic_set_source_mode(aplic, it, type)) 85 panic(); 86 87 aplic_set_target(aplic, it, hartid, 0, it); 88 } 89 90 static void aplic_op_enable(struct itr_chip *chip, size_t it) 91 { 92 struct aplic_data *aplic = container_of(chip, struct aplic_data, chip); 93 94 if (aplic_is_bad_it(aplic, it)) 95 panic(); 96 97 aplic_enable_interrupt(aplic, it); 98 } 99 100 static void aplic_op_disable(struct itr_chip *chip, size_t it) 101 { 102 struct aplic_data *aplic = container_of(chip, struct aplic_data, chip); 103 104 if (aplic_is_bad_it(aplic, it)) 105 panic(); 106 107 aplic_disable_interrupt(aplic, it); 108 } 109 110 static void aplic_op_raise_pi(struct itr_chip *chip, size_t it) 111 { 112 struct aplic_data *aplic = container_of(chip, struct aplic_data, chip); 113 114 if (aplic_is_bad_it(aplic, it)) 115 panic(); 116 117 aplic_set_pending(aplic, it); 118 } 119 120 static const struct itr_ops aplic_ops = { 121 .configure = aplic_op_configure, 122 .enable = aplic_op_enable, 123 .disable = aplic_op_disable, 124 .mask = aplic_op_disable, 125 .unmask = aplic_op_enable, 126 .raise_pi = aplic_op_raise_pi, 127 }; 128 129 void aplic_init(paddr_t aplic_base_pa) 130 { 131 struct aplic_data *aplic = &aplic_data; 132 TEE_Result res = TEE_ERROR_GENERIC; 133 134 if (IS_ENABLED(CFG_DT)) { 135 res = aplic_init_from_device_tree(aplic); 136 if (res) 137 panic(); 138 } else { 139 aplic_init_base_addr(aplic, aplic_base_pa); 140 } 141 142 aplic->chip.ops = &aplic_ops; 143 144 io_write32(aplic->aplic_base + APLIC_DOMAINCFG, 145 APLIC_DOMAINCFG_IE | APLIC_DOMAINCFG_DM); 146 147 interrupt_main_init(&aplic_data.chip); 148 } 149 150 void aplic_init_per_hart(void) 151 { 152 } 153 154 void aplic_it_handle(void) 155 { 156 } 157 158 void aplic_dump_state(void) 159 { 160 } 161