213 lines
6.1 KiB
C
213 lines
6.1 KiB
C
/*
|
|
* Copyright (c) 2007-2017 Allwinnertech Co., Ltd.
|
|
*
|
|
* This software is licensed under the terms of the GNU General Public
|
|
* License version 2, as published by the Free Software Foundation, and
|
|
* may be copied, distributed, and modified under those terms.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
*/
|
|
|
|
#include "pm_i.h"
|
|
|
|
#if defined CONFIG_ARCH_SUN9IW1P1 || defined CONFIG_ARCH_SUN8IW6P1
|
|
/*#if defined CONFIG_ARCH_SUN9IW1P1*/
|
|
|
|
#define readb(addr) (*((volatile unsigned char *)(addr)))
|
|
#define readw(addr) (*((volatile unsigned short *)(addr)))
|
|
#define readl(addr) (*((volatile unsigned long *)(addr)))
|
|
#define writeb(v, addr) (*((volatile unsigned char *)(addr)) = (unsigned char)(v))
|
|
#define writew(v, addr) (*((volatile unsigned short *)(addr)) = (unsigned short)(v))
|
|
#define writel(v, addr) (*((volatile unsigned long *)(addr)) = (unsigned long)(v))
|
|
|
|
static __u32 cpsr_backup;
|
|
|
|
/*
|
|
* CPU interrupt mask handling.
|
|
*/
|
|
|
|
static inline unsigned long mem_local_irq_save(void)
|
|
{
|
|
unsigned long flags;
|
|
|
|
asm volatile (" mrs %0, cpsr @ mem_local_irq_save\n"
|
|
" cpsid i" : "=r" (flags) : : "memory", "cc");
|
|
return flags;
|
|
}
|
|
|
|
static inline void mem_local_irq_enable(void)
|
|
{
|
|
asm volatile
|
|
(" cpsie i @ mem_local_irq_enable" : : : "memory",
|
|
"cc");
|
|
}
|
|
|
|
static inline void mem_local_irq_disable(void)
|
|
{
|
|
asm volatile
|
|
(" cpsid i @ mem_local_irq_disable" : : : "memory",
|
|
"cc");
|
|
}
|
|
|
|
/*
|
|
* restore saved IRQ & FIQ state
|
|
*/
|
|
static inline void mem_local_irq_restore(unsigned long flags)
|
|
{
|
|
asm volatile (" msr cpsr_c, %0 @ local_irq_restore" : : "r"
|
|
(flags)
|
|
: "memory", "cc");
|
|
}
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* INITIALIZE HWSPINLOCK
|
|
*
|
|
* Description: initialize hwspinlock.
|
|
*
|
|
* Arguments : none.
|
|
*
|
|
* Returns : 0 if initialize hwspinlock succeeded, others if failed.
|
|
*********************************************************************************************************
|
|
*/
|
|
__s32 hwspinlock_init(__u32 mmu_flag)
|
|
{
|
|
if (1 == mmu_flag) {
|
|
/*enable SPINLOCK clock and set reset as de-assert state. */
|
|
writel((CCU_CLK_NRESET |
|
|
readl(IO_ADDRESS
|
|
(CCU_MOD_CLK_AHB1_RESET_SPINLOCK))),
|
|
IO_ADDRESS(CCU_MOD_CLK_AHB1_RESET_SPINLOCK));
|
|
writel((CCU_CLK_ON |
|
|
readl(IO_ADDRESS
|
|
(CCU_MOD_CLK_AHB1_GATING_SPINLOCK))),
|
|
IO_ADDRESS(CCU_MOD_CLK_AHB1_GATING_SPINLOCK));
|
|
|
|
} else {
|
|
/*enable SPINLOCK clock and set reset as de-assert state. */
|
|
writel((CCU_CLK_NRESET |
|
|
readl(CCU_MOD_CLK_AHB1_RESET_SPINLOCK)),
|
|
CCU_MOD_CLK_AHB1_RESET_SPINLOCK);
|
|
writel((CCU_CLK_ON |
|
|
readl(CCU_MOD_CLK_AHB1_GATING_SPINLOCK)),
|
|
CCU_MOD_CLK_AHB1_GATING_SPINLOCK);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCK HWSPINLOCK WITH TIMEOUT
|
|
*
|
|
* Description: lock an hwspinlock with timeout limit.
|
|
*
|
|
* Arguments : hwid : an hwspinlock id which we want to lock.
|
|
*
|
|
* Returns : 0 if lock hwspinlock succeeded, other if failed.
|
|
*********************************************************************************************************
|
|
*/
|
|
__s32 hwspin_lock_timeout(__u32 hwid, __u32 timeout)
|
|
{
|
|
/*multipy 1024. */
|
|
__u32 expire = timeout << 10;
|
|
|
|
/*disable cpu interrupt, save cpsr to cpsr-table. */
|
|
cpsr_backup = mem_local_irq_save();
|
|
|
|
/*try to take spinlock */
|
|
while (readl(IO_ADDRESS(MEM_SPINLOCK_LOCK_REG(hwid))) ==
|
|
MEM_SPINLOCK_TAKEN) {
|
|
/*spinlock is busy */
|
|
if (expire == 0) {
|
|
mem_local_irq_restore(cpsr_backup);
|
|
printk("take hwspinlock timeout\n");
|
|
return -1;
|
|
}
|
|
expire--;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* UNLOCK HWSPINLOCK
|
|
*
|
|
* Description: unlock a specific hwspinlock.
|
|
*
|
|
* Arguments : hwid : an hwspinlock id which we want to unlock.
|
|
*
|
|
* Returns : 0 if unlock hwspinlock succeeded, other if failed.
|
|
*********************************************************************************************************
|
|
*/
|
|
__s32 hwspin_unlock(__u32 hwid)
|
|
{
|
|
/*untaken the spinlock */
|
|
writel(0x0, IO_ADDRESS(MEM_SPINLOCK_LOCK_REG(hwid)));
|
|
|
|
/*restore cpsr */
|
|
mem_local_irq_restore(cpsr_backup);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCK HWSPINLOCK WITH TIMEOUT
|
|
*
|
|
* Description: lock an hwspinlock with timeout limit.
|
|
*
|
|
* Arguments : hwid : an hwspinlock id which we want to lock.
|
|
*
|
|
* Returns : 0 if lock hwspinlock succeeded, other if failed.
|
|
*********************************************************************************************************
|
|
*/
|
|
__s32 hwspin_lock_timeout_nommu(__u32 hwid, __u32 timeout)
|
|
{
|
|
/*multipy 1024. */
|
|
__u32 expire = timeout << 10;
|
|
|
|
/*disable cpu interrupt, save cpsr to cpsr-table. */
|
|
cpsr_backup = mem_local_irq_save();
|
|
|
|
/*try to take spinlock */
|
|
while (readl(MEM_SPINLOCK_LOCK_REG(hwid)) == MEM_SPINLOCK_TAKEN) {
|
|
/*spinlock is busy */
|
|
if (expire == 0) {
|
|
mem_local_irq_restore(cpsr_backup);
|
|
/*printk_nommu("take hwspinlock timeout\n"); */
|
|
return -1;
|
|
}
|
|
expire--;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* UNLOCK HWSPINLOCK
|
|
*
|
|
* Description: unlock a specific hwspinlock.
|
|
*
|
|
* Arguments : hwid : an hwspinlock id which we want to unlock.
|
|
*
|
|
* Returns : 0 if unlock hwspinlock succeeded, other if failed.
|
|
*********************************************************************************************************
|
|
*/
|
|
__s32 hwspin_unlock_nommu(__u32 hwid)
|
|
{
|
|
/*untaken the spinlock */
|
|
writel(0x0, MEM_SPINLOCK_LOCK_REG(hwid));
|
|
|
|
/*restore cpsr */
|
|
mem_local_irq_restore(cpsr_backup);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif
|