OSHW-DEIMOS/SOFTWARE/A64-TERES/linux-a64/drivers/soc/allwinner/pm/mem_int.c
Dimitar Gamishev f9b0e7a283 linux
2017-10-13 14:07:04 +03:00

174 lines
5.3 KiB
C
Executable File

/*
*********************************************************************************************************
* LINUX-KERNEL
* AllWinner Linux Platform Develop Kits
* Kernel Module
*
* (c) Copyright 2006-2011, kevin.z China
* All Rights Reserved
*
* File : mem_int.c
* By : gq.yang
* Version : v1.0
* Date : 2012-11-3 20:13
* Descript: interrupt for platform mem
* Update : date auther ver notes
*********************************************************************************************************
*/
#include "pm_i.h"
static void *GicDDisc;
static void *GicCDisc;
static u32 gic_d_len = 0;
static u32 gic_c_len = 0;
/*
*********************************************************************************************************
* STANDBY INTERRUPT INITIALISE
*
* Description: mem interrupt initialise.
*
* Arguments : none.
*
* Returns : 0/-1;
*********************************************************************************************************
*/
__s32 mem_int_init(void)
{
u32 *base = 0;
#ifdef CONFIG_ARCH_SUN8IW10P1
__u32 i = 0;
#endif
pm_get_dev_info("gic", 0, &base, &gic_d_len);
GicDDisc = base;
pm_get_dev_info("gic", 1, &base, &gic_c_len);
GicCDisc = base;
#ifdef CONFIG_ARCH_SUN8IW10P1
//printk("gic iar == 0x%x. \n", *(volatile __u32 *)(IO_ADDRESS(SUNXI_GIC_CPU_PBASE)+0x0c));
/* initialise interrupt enable and mask for mem */
/*
* Disable all interrupts. Leave the PPI and SGIs alone
* as these enables are banked registers.
*/
for (i = 4; i < (GIC_400_ENABLE_LEN); i += 4)
*(volatile __u32 *)(GicDDisc + GIC_DIST_ENABLE_CLEAR + i) = 0xffffffff;
/*config cpu interface*/
#if 0
*(volatile __u32 *)(GicCDisc + GIC_CPU_PRIMASK) = 0xf0;
*(volatile __u32 *)(GicCDisc + GIC_CPU_CTRL) = 0x1;
#endif
#if 1
/* clear external irq pending: needed */
for (i = 4; i < (GIC_400_ENABLE_LEN); i += 4)
*(volatile __u32 *)(GicDDisc + GIC_DIST_PENDING_CLEAR + i) = 0xffffffff;
#endif
//the print info just to check the pending state, actually, after u read iar, u need to access end of interrupt reg;
i = *(volatile __u32 *)(GicCDisc + 0x0c);
if(i != 0x3ff){
//u need to
*(volatile __u32 *)(GicCDisc + 0x10) = i;
printk("notice: gic iar == 0x%x. \n", i);
}
#endif
return 0;
}
/*
*********************************************************************************************************
* STANDBY INTERRUPT INITIALISE
*
* Description: mem interrupt exit.
*
* Arguments : none.
*
* Returns : 0/-1;
*********************************************************************************************************
*/
__s32 mem_int_exit(void)
{
#ifdef CONFIG_ARCH_SUN8IW10P1
int i = 0;
volatile __u32 enable_bit = 0;
//all the disable-int-src pending, need to be clear
for(i = 0; i < GIC_400_ENABLE_LEN; i += 4){
enable_bit = *(volatile __u32 *)(GicDDisc + GIC_DIST_ENABLE_SET + i);
*(volatile __u32 *)(GicDDisc + GIC_DIST_PENDING_CLEAR + i) &= (~enable_bit);
}
#endif
return 0;
}
/*
*********************************************************************************************************
* QUERY INTERRUPT
*
* Description: enable interrupt.
*
* Arguments : src interrupt source number.
*
* Returns : 0/-1;
*********************************************************************************************************
*/
__s32 mem_enable_int(enum interrupt_source_e src)
{
__u32 tmpGrp = (__u32)src >> 5;
__u32 tmpSrc = (__u32)src & 0x1f;
if(0 == src){
return -1;
}
//enable interrupt source
//printk("GicDDisc + GIC_DIST_ENABLE_SET + tmpGrp*4 = 0x%p. tmpGrp = 0x%x.\n", GicDDisc + GIC_DIST_ENABLE_SET + tmpGrp*4, tmpGrp);
//printk("GicDDisc + GIC_DIST_ENABLE_SET + tmpGrp*4 = 0x%x. tmpGrp = 0x%x.\n", *(volatile __u32 *)(GicDDisc + GIC_DIST_ENABLE_SET + tmpGrp*4), tmpGrp);
*(volatile __u32 *)(GicDDisc + GIC_DIST_ENABLE_SET + tmpGrp*4) |= (1<<tmpSrc);
//printk("GicDDisc + GIC_DIST_ENABLE_SET + tmpGrp*4 = 0x%p. tmpGrp = 0x%x.\n", GicDDisc + GIC_DIST_ENABLE_SET + tmpGrp*4, tmpGrp);
//printk("GicDDisc + GIC_DIST_ENABLE_SET + tmpGrp*4 = 0x%x. tmpGrp = 0x%x.\n", *(volatile __u32 *)(GicDDisc + GIC_DIST_ENABLE_SET + tmpGrp*4), tmpGrp);
//printk("tmpSrc = 0x%x. \n", tmpSrc);
//need to care mask or priority?
return 0;
}
/*
*********************************************************************************************************
* QUERY INTERRUPT
*
* Description: query interrupt.
*
* Arguments : src interrupt source number.
*
* Returns : 0/-1;
*********************************************************************************************************
*/
__s32 mem_query_int(enum interrupt_source_e src)
{
__s32 result = 0;
__u32 tmpGrp = (__u32)src >> 5;
__u32 tmpSrc = (__u32)src & 0x1f;
if(0 == src){
return -1;
}
result = *(volatile __u32 *)(GicDDisc + GIC_DIST_PENDING_SET + tmpGrp*4) & (1<<tmpSrc);
//printk("GicDDisc + GIC_DIST_PENDING_SET + tmpGrp*4 = 0x%x. tmpGrp = 0x%x.\n", GicDDisc + GIC_DIST_PENDING_SET + tmpGrp*4, tmpGrp);
//printk("tmpSrc = 0x%x. result = 0x%x. \n", tmpSrc, result);
return result? 0:-1;
}