blob: bd4b7517aa83c5ad6bb4ae9ca6d88c68ce7f89c9 [file] [log] [blame]
/*
* arch/arm/mach-zx297520v2/zx297520v2-clock.c
*
* Copyright (C) 2015 ZTE-TSP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include <linux/kernel.h>
#include <mach/board.h>
#include <mach/iomap.h>
#include <mach/debug.h>
#include <linux/io.h>
#include <mach/spinlock.h>
#include <mach/pcu.h>
//#include <mach/rpmsg.h>
#include <linux/mutex.h>
#define USE_HW_SPINLOCK 1
#if USE_HW_SPINLOCK
#define MACH_NR_SFLOCKS SFLOCK_NUM
#define MACH_NR_HWLOCKS HWLOCK_NUM
#define SELF_CORE_ID CORE_ID_AP
/* now use 8*MACH_NR_SFLOCKS bytes */
#define SOFTLOCK_DESC_BASE (SPINLOCK_SOFTLOCK_BASE)
#define SPINLOCK_DEBUG 1
#if SPINLOCK_DEBUG
#define zspinlock_debug(fmt, ...) \
printk(KERN_INFO fmt, ##__VA_ARGS__)
#else
#define zspinlock_debug(fmt, ...)
#endif
#define zspinlock_assert(_EXP) ZDRV_ASSERT(_EXP)
static DEFINE_MUTEX(zspinlock_mutex);
static unsigned long s_hwSpinlockMsr;
/****************************************************************************
* Types
****************************************************************************/
struct zte_softlock_desc {
unsigned long used;
unsigned long owner;
};
/**************************************************************************
* Global Variables *
**************************************************************************/
static volatile struct zte_softlock_desc *softlock_desc[MACH_NR_SFLOCKS];
static const void __iomem __force *hwlock_regs[MACH_NR_HWLOCKS] =
{
SHARED_DEVICE_REG1,
SHARED_DEVICE_REG2,
SHARED_DEVICE_REG3,
SHARED_DEVICE_REG4
};
extern void msleep(unsigned int msecs);
/*******************************************************************************
* Function: _hw_spin_lock
* Description:»ñȡӲ¼þËø£¬id 0~3
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
static void _hw_spin_lock(unsigned long hwid)
{
unsigned long tmp;
unsigned long msr;
local_irq_save(msr);
s_hwSpinlockMsr = msr;
while(ioread32(hwlock_regs[hwid])&0x1);
tmp = ioread32(hwlock_regs[hwid]);
tmp &= 0x00ffffff;
tmp |= (SELF_CORE_ID&0xff)<<24;
iowrite32(tmp, hwlock_regs[hwid]);
}
/*******************************************************************************
* Function: _hw_spin_unlock
* Description:ÊÍ·ÅÓ²¼þËø£¬id 0~3
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
static void _hw_spin_unlock(unsigned long hwid)
{
unsigned long tmp;
if(SELF_CORE_ID != (ioread32(hwlock_regs[hwid])&0xff000000)>>24){
zspinlock_assert(0);
}
tmp = ioread32(hwlock_regs[hwid]);
tmp &= 0x00fffffe;
iowrite32(tmp, hwlock_regs[hwid]);
local_irq_restore(s_hwSpinlockMsr);
}
/*******************************************************************************
* Function: hw_spin_lock
* Description:»ñȡӲ¼þËø£¬id 0~2£¬
* id 3±£Áô¸øÈí¼þËøÊ¹Óã¬ÍⲿÇý¶¯²»¿ÉÓá£
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
void hw_spin_lock(emhw_lock_id hwid)
{
_hw_spin_lock(hwid);
// zspinlock_debug("cpu %d gets %d hardware lock!/n",SELF_CORE_ID,hwid);
}
/*******************************************************************************
* Function: hw_spin_unlock
* Description:Çý¶¯ÊÍ·ÅÓ²¼þËø£¬id 0~2
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
void hw_spin_unlock(emhw_lock_id hwid)
{
_hw_spin_unlock(hwid);
// zspinlock_debug("cpu %d releases %d hardware lock!/n",SELF_CORE_ID,hwid);
}
/*******************************************************************************
* Function: soft_spin_lock
* Description:Çý¶¯»ñµÃÈí¼þËø½Ó¿Ú
* Parameters:
* Input: sfid: Èí¼þËøid¡£
* coreid: ±£³ÖidºÅΪsfidÈí¼þËøµÄcpuid¡£
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
void soft_spin_lock(emsf_lock_id sfid)
{
static unsigned long lock_count = 0;
softlock_loop:
while(softlock_desc[sfid]->owner != SELF_CORE_ID && softlock_desc[sfid]->used)
{
lock_count++;
if(lock_count == 1000)
{
lock_count = 0;
msleep(5);
}
}
_hw_spin_lock(SOFTLOCK_HWLOCK);
if(softlock_desc[sfid]->owner != SELF_CORE_ID && softlock_desc[sfid]->used)
{
_hw_spin_unlock(SOFTLOCK_HWLOCK);
goto softlock_loop;
}
softlock_desc[sfid]->used ++;
softlock_desc[sfid]->owner = SELF_CORE_ID;
_hw_spin_unlock(SOFTLOCK_HWLOCK);
//zspinlock_debug("cpu %d releases %d software lock!/n",SELF_CORE_ID,sfid);
}
/*******************************************************************************
* Function: soft_spin_unlock
* Description:Óësoft_spin_lock¶ÔÓ¦µÄÊÍ·ÅÈí¼þËø½Ó¿Ú¡£
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
void soft_spin_unlock(emsf_lock_id sfid)
{
if(softlock_desc[sfid]->used){
if(SELF_CORE_ID != softlock_desc[sfid]->owner){
zspinlock_assert(0);
}
_hw_spin_lock(SOFTLOCK_HWLOCK);
softlock_desc[sfid]->used --;
if(softlock_desc[sfid]->used == 0) {
softlock_desc[sfid]->owner = 0x0;
}
_hw_spin_unlock(SOFTLOCK_HWLOCK);
//zspinlock_debug("cpu %d releases %d software lock!/n",SELF_CORE_ID,sfid);
}
}
/*******************************************************************************
* Function: soft_spin_lock_psm
* Description:Çý¶¯»ñµÃÈí¼þËø½Ó¿Ú
* Parameters:
* Input: sfid: Èí¼þËøid¡£
* coreid: ±£³ÖidºÅΪsfidÈí¼þËøµÄcpuid¡£
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
void soft_spin_lock_psm(emsf_lock_id sfid)
{
softlock_loop:
while(softlock_desc[sfid]->owner != SELF_CORE_ID && softlock_desc[sfid]->used)
{
}
_hw_spin_lock(SOFTLOCK_HWLOCK);
if(softlock_desc[sfid]->owner != SELF_CORE_ID && softlock_desc[sfid]->used)
{
_hw_spin_unlock(SOFTLOCK_HWLOCK);
goto softlock_loop;
}
softlock_desc[sfid]->used ++;
softlock_desc[sfid]->owner = SELF_CORE_ID;
_hw_spin_unlock(SOFTLOCK_HWLOCK);
//zspinlock_debug("cpu %d releases %d software lock!/n",SELF_CORE_ID,sfid);
}
/*******************************************************************************
* Function: soft_spin_unlock_psm
* Description:Óësoft_spin_lock_psm¶ÔÓ¦µÄÊÍ·ÅÈí¼þËø½Ó¿Ú¡£
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
void soft_spin_unlock_psm(emsf_lock_id sfid)
{
soft_spin_unlock(sfid);
}
/*******************************************************************************
* Function: reg_spin_lock
* Description:Çý¶¯»ñµÃ¼Ä´æÆ÷Ëø½Ó¿Ú
* Parameters:
* Input:
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
void reg_spin_lock(void)
{
_hw_spin_lock(REGLOCK_HWLOCK);
softlock_desc[REG_SFLOCK]->owner = SELF_CORE_ID;
}
/*******************************************************************************
* Function: reg_spin_unlock
* Description:Óëreg_spin_lock¶ÔÓ¦µÄÊͷżĴæÆ÷Ëø½Ó¿Ú¡£
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
void reg_spin_unlock(void)
{
softlock_desc[REG_SFLOCK]->owner = 0x0;
_hw_spin_unlock(REGLOCK_HWLOCK);
}
/*******************************************************************************
* Function: softspinlock_init
* Description:Èí¼þËø³õʼ»¯¡£
* Parameters:
* Input:
*
* Output:
*
* Returns:
*
*
* Others:
********************************************************************************/
int softspinlock_init(void)
{
int i;
for(i = 0; i<MACH_NR_SFLOCKS; i++){
softlock_desc[i] =
(struct zte_softlock_desc *)(SOFTLOCK_DESC_BASE +i*sizeof(struct zte_softlock_desc));
//softlock_desc[i]->used = 0;
//softlock_desc[i]->owner= CORE_ID_NUM;
}
zspinlock_debug("softspinlock init success base=0x%x!",(int)SOFTLOCK_DESC_BASE);
return 0;
}
//arch_initcall(softspinlock_init);
#else
int softspinlock_init(void){return 0;}
void reg_spin_lock(void){}
void reg_spin_unlock(void){}
void soft_spin_lock(emsf_lock_id sfid){}
void soft_spin_unlock(emsf_lock_id sfid){}
void soft_spin_lock_psm(emsf_lock_id sfid){}
void soft_spin_unlock_psm(emsf_lock_id sfid){}
void hw_spin_lock(emhw_lock_id hwid){}
void hw_spin_unlock(emhw_lock_id hwid){}
#endif