1 // Copyright (C) 2022 Beken Corporation 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <common/bk_include.h> 16 #include <common/bk_typedef.h> 17 #include "spinlock.h" 18 19 #if 0 /* dual core have the separated memory space. */ 20 #ifdef CONFIG_DUAL_CORE 21 #define CONFIG_CPU_NUM 2 22 #else 23 #define CONFIG_CPU_NUM 1 24 #endif 25 #endif 26 27 extern void arch_fence(void); 28 extern u32 arch_atomic_set(u32 * lock_addr); 29 extern void arch_atomic_clear(u32 * lock_addr); 30 31 extern u32 arch_int_lock(void); 32 extern void arch_int_restore(u32 int_flag); 33 34 typedef struct 35 { 36 // u32 cpu_id; 37 u32 nest_cnt; 38 u32 int_flag; 39 } cpu_info_t; 40 41 //static cpu_info_t cpu_info[CONFIG_CPU_NUM]; 42 /* dual core have the separated memory space, so don't need cpu_info array for each core. */ 43 static cpu_info_t cpu_info = { .nest_cnt = 0, .int_flag = 0 }; 44 45 #if 0 46 void init_cpu_info(void) 47 { 48 u32 i; 49 50 for(i = 0; i < CONFIG_CPU_NUM; i++) 51 { 52 cpu_info[i].cpu_id = i; 53 cpu_info[i].int_flag = 0; 54 cpu_info[i].nest_cnt = 0; 55 } 56 } 57 #endif 58 get_cur_cpu(void)59static cpu_info_t * get_cur_cpu(void) 60 { 61 #if 0 62 #ifdef CONFIG_SLAVE_CORE 63 64 return &cpu_info[1]; 65 66 #endif 67 68 return &cpu_info[0]; 69 #else 70 return &cpu_info; 71 #endif 72 } 73 push_disable_int_flag(void)74static void push_disable_int_flag(void) 75 { 76 cpu_info_t *cur_cpu = get_cur_cpu(); 77 u32 int_flag = arch_int_lock(); 78 79 if(cur_cpu->nest_cnt == 0) 80 cur_cpu->int_flag = int_flag; 81 82 cur_cpu->nest_cnt++; 83 } 84 pop_int_flag(void)85static void pop_int_flag(void) 86 { 87 cpu_info_t * cur_cpu = get_cur_cpu(); 88 89 if(cur_cpu->nest_cnt < 1) 90 { 91 /* 92 * FATAL ERROR!!! 93 */ 94 return; 95 } 96 97 cur_cpu->nest_cnt--; 98 99 if(cur_cpu->nest_cnt == 0) 100 arch_int_restore(cur_cpu->int_flag); 101 } 102 103 #ifdef CONFIG_DUAL_CORE spinlock_owner(spinlock_t * slock)104static u32 spinlock_owner(spinlock_t *slock) 105 { 106 if(slock->locked == 0) 107 return 0; 108 109 if(slock->owner_cpu != get_cur_cpu()) 110 return 0; 111 112 return 1; 113 } 114 #endif 115 spinlock_init(spinlock_t * slock)116void spinlock_init(spinlock_t *slock) 117 { 118 slock->owner_cpu = NULL; 119 slock->locked = 0; 120 } 121 spinlock_acquire(spinlock_t * slock)122void spinlock_acquire(spinlock_t *slock) 123 { 124 push_disable_int_flag(); 125 126 #ifdef CONFIG_DUAL_CORE 127 if(spinlock_owner(slock)) 128 { 129 /* 130 * FATAL ERROR!!! 131 */ 132 133 BK_LOG_RAW("FATAL ERROR in %s\r\n", __func__); 134 pop_int_flag(); 135 return; 136 137 } 138 139 while( arch_atomic_set(&slock->locked) ) ; 140 141 arch_fence(); 142 143 slock->owner_cpu = get_cur_cpu(); 144 #endif 145 } 146 spinlock_release(spinlock_t * slock)147void spinlock_release(spinlock_t *slock) 148 { 149 #ifdef CONFIG_DUAL_CORE 150 if(!spinlock_owner(slock)) 151 { 152 /* 153 * FATAL ERROR!!! 154 */ 155 156 BK_LOG_RAW("FATAL ERROR in %s\r\n", __func__); 157 return; 158 } 159 160 slock->owner_cpu = NULL; 161 162 arch_fence(); 163 164 arch_atomic_clear(&slock->locked); 165 #endif 166 167 pop_int_flag(); 168 } 169 170