316 lines
6.5 KiB
C
316 lines
6.5 KiB
C
#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);
|
||
|
||
}
|
||
}
|
||
|
||
|
||
}
|