2023-11-15 09:50:20 +08:00

316 lines
6.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <ucps2-intrin.h>
#include "spinlock.h"
#define OSP_APE_SPAIN_LOCK_ADDR (0x931FF00-0x400)
#define SPINLOCK_BIT_MAP_ADDR (0x931fb40)
#define DEBUG_NR 16
unsigned int spin_debug_switch = 0;
unsigned int g_unspinlock_loop = 0;
unsigned int g_ddr_spinlock_loop = 0;
typedef unsigned int uint32_t;
#define spin_do_write(a,v) __ucps2_store_ext_mem((void *)(a), (uint32_t)v, f_W)
#define spin_do_read(ptr) __ucps2_load_ext_mem_v((char*)(ptr), f_W)
unsigned int g_spinlock_count[DEBUG_NR] = {0};
unsigned int g_unspinlock_count[DEBUG_NR] = {0};
unsigned int g_spinlock_loop[DEBUG_NR] = {0};
unsigned int g_spin_count[DEBUG_NR] = {0};
unsigned char *use_flag = (char*)SPINLOCK_BIT_MAP_ADDR;
spin_debug_t *spin_debug_info;
static int test_bit(void *s,unsigned int index)
{
unsigned char *f_bit = s;
f_bit += index >>3;
return ((*f_bit&(1 <<((index%8)))) != 0);
}
static void set_bit(void *s,unsigned int index)
{
unsigned char *f_bit = s;
f_bit += index >> 3;
*f_bit |= 1<<(index%8);
}
static void clear_bit(void *s,unsigned int index)
{
unsigned char *f_bit = s;
f_bit += index >> 3;
*f_bit &= ~(1 <<(index%8));
}
/*
函数:smart_spin_debug_init
参数:lock_idx
参数范围1--15
*/
int smart_spin_debug_init(int lock_idx,unsigned int debug_base_addr, int len_bytes)
{
if((lock_idx < 1)||(lock_idx > 15))
{
return -1;
}
if(debug_base_addr <= 0x10000000)
{
return -1;
}
if (len_bytes < 16)
{
return -2;
}
spin_debug_switch = 1;
spin_debug_info = (spin_debug_t *)debug_base_addr;
return 0;
}
void spin_debug(void * addr , uint32_t v)
{
if(spin_debug_switch == 1)
{
spin_do_write(addr, v);
__ucps2_synch(0);
}
}
int smart_spinlock_init(int lock_index)
{
int i;
if((lock_index < 1)||(lock_index > 15))
{
return -1;
}
if(test_bit(use_flag,lock_index))
{
return -2; //
}
set_bit(use_flag,lock_index);
*(volatile unsigned int *)(OSP_APE_SPAIN_LOCK_ADDR+lock_index*4) = 0;
return 0;
}
void smart_spinlock(int lock_index)
{
spinlock_t lockval;
spinlock_t *lock;
int ret;
int owner;
int next;
if (lock_index > SLOCK_MAX)
{
return;
}
else
{
lock = (spinlock_t*)(OSP_APE_SPAIN_LOCK_ADDR+lock_index*4);
}
while (1)
{
lockval.slock = __ucps2_atomicld((int *)lock, f_W);
next = ((lockval.slock >> 16) & 0x0000ffff);
owner = next;
next++;
lockval.slock &=0x0000ffff;
lockval.slock |= ((next & 0xffff) << 16);
ret = __ucps2_atomicst((int *)lock, lockval.slock, f_W);
if (1 == ret)
{
break;
}
else
{
g_spin_count[lock_index]++;
spin_debug(&(spin_debug_info->spin_per_ape.g_spin_count) , g_spin_count[lock_index]);
}
}
do
{
lockval.slock = __ucps2_atomicld((int *)lock, f_W);
g_spinlock_loop[lock_index]++;
spin_debug(&(spin_debug_info->spin_per_ape.spinlock_loop) , g_spinlock_loop[lock_index]);
} while (owner != ((lockval.slock & 0x0000ffff)));
g_spinlock_count[lock_index]++;
spin_debug(&(spin_debug_info->spin_per_ape.spinlock_count) , g_spinlock_count[lock_index]);
}
void smart_spinunlock(int lock_index)
{
spinlock_t lockval;
int ret;
int atomfail_unlock = 0;
spinlock_t * lock;
unsigned int temp_owner = 0;
if (lock_index > SLOCK_MAX)
{
return;
}
else
{
lock = (spinlock_t*)(OSP_APE_SPAIN_LOCK_ADDR+lock_index*4);
}
while (1)
{
lockval.slock = __ucps2_atomicld((int *)lock, f_W);
temp_owner = (lockval.slock & 0x0000ffff);
temp_owner ++;
lockval.slock &= 0xffff0000;
lockval.slock |= (temp_owner & 0x0000ffff);
ret = __ucps2_atomicst((int *)lock, lockval.slock, f_W);
if (1 == ret)
{
break;
}
else
{
// g_unspinlock_loop++;
// spin_debug(&(spin_debug_info->spin_per_ape.unspinlock_loop) , g_unspinlock_loop);
}
}
g_unspinlock_count[lock_index]++;
spin_debug(&(spin_debug_info->spin_per_ape.unspinlock_count) , g_unspinlock_count[lock_index]);
}
/*
参数:lock_idx
参数范围1--15
*/
int smart_get_spin_loop_cnt(int lock_idx)
{
return g_spinlock_loop[lock_idx];
}
/*
参数:lock_idx
参数范围1--15
*/
int smart_get_spin_cnt(int lock_idx)
{
return g_spin_count[lock_idx];
}
/*
参数:lock_idx
参数范围1--15
*/
int smart_get_spinlock_cnt(int lock_idx)
{
return g_spinlock_count[lock_idx];
}
/*
参数:lock_idx
参数范围1--15
*/
int smart_get_unspinlock_cnt(int lock_idx)
{
return g_unspinlock_count[lock_idx];
}
int smart_ddr_spinlock_init(ddr_spinlock_t *val)
{
int i;
int init_val = 0;
if(spin_do_read(val->flag_addr) == 0xab3f)
{
return -2;
}
spin_do_write(val->flag_addr,0xab3f);
spin_do_write(val->lock_addr,0);
return 0;
}
void smart_ddr_spinlock(ddr_spinlock_t *val)
{
spinlock_t lockval;
volatile unsigned int *lock;
int ret;
int owner;
int next;
int loop;
lock = (volatile unsigned int*)(val->lock_addr);
while (1)
{
lockval.slock = __ucps2_atomicld((int *)lock, f_W);
next = ((lockval.slock >> 16) & 0x0000ffff);
owner = next;
next++;
lockval.slock &=0x0000ffff;
lockval.slock |= ((next & 0xffff) << 16);
ret = __ucps2_atomicst((int *)lock, lockval.slock, f_W);
if (1 == ret)
{
break;
}
else
{
}
}
do
{
lockval.slock = __ucps2_atomicld((int *)lock, f_W);
g_ddr_spinlock_loop++;
} while (owner != ((lockval.slock & 0x0000ffff)));
}
void smart_ddr_spinunlock(ddr_spinlock_t *val)
{
spinlock_t lockval;
int ret;
volatile unsigned int * lock;
unsigned int temp_owner = 0;
lock =(volatile unsigned int*)val->lock_addr;
while (1)
{
lockval.slock = __ucps2_atomicld((int *)lock, f_W);
temp_owner = (lockval.slock & 0x0000ffff);
temp_owner ++;
lockval.slock &= 0xffff0000;
lockval.slock |= (temp_owner & 0x0000ffff);
ret = __ucps2_atomicst((int *)lock, lockval.slock, f_W);
if (1 == ret)
{
break;
}
else
{
// g_ddr_unspinlock_loop++;
// spin_do_write(val->unlock_loop_addr,g_ddr_unspinlock_loop);
}
}
}