oleavr-rgl-a500-mini-linux-.../drivers/soc/allwinner/pm_legacy/mem_int.c
Ole André Vadla Ravnås 169c65d57e Initial commit
2022-05-07 01:01:45 +02:00

182 lines
5.5 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.
*
*/
/*
*********************************************************************************************************
* 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;
/*
*********************************************************************************************************
* STANDBY INTERRUPT INITIALISE
*
* Description: mem interrupt initialise.
*
* Arguments : none.
*
* Returns : 0/-1;
*********************************************************************************************************
*/
__s32 mem_int_init(void)
{
__u32 i = 0;
GicDDisc = (void *)IO_ADDRESS(SUNXI_GIC_DIST_PBASE);
GicCDisc = (void *)IO_ADDRESS(SUNXI_GIC_CPU_PBASE);
/* 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);
}
return 0;
}
/*
*********************************************************************************************************
* STANDBY INTERRUPT INITIALISE
*
* Description: mem interrupt exit.
*
* Arguments : none.
*
* Returns : 0/-1;
*********************************************************************************************************
*/
__s32 mem_int_exit(void)
{
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);
}
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;
GicDDisc = (void *)IO_ADDRESS(SUNXI_GIC_DIST_PBASE);
GicCDisc = (void *)IO_ADDRESS(SUNXI_GIC_CPU_PBASE);
if (0 == src) {
return -1;
}
/* enable interrupt source */
*(volatile __u32 *)(GicDDisc + GIC_DIST_ENABLE_SET + tmpGrp * 4) |=
(1 << tmpSrc);
/* printk("GicDDisc + GIC_DIST_ENABLE_SET + tmpGrp*4 = 0x%x. tmpGrp = 0x%x.\n", 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;
GicDDisc = (void *)IO_ADDRESS(SUNXI_GIC_DIST_PBASE);
GicCDisc = (void *)IO_ADDRESS(SUNXI_GIC_CPU_PBASE);
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;
}