spbx/roms/srcs/images/ethernet/gianfar_eth/init_drv.c

464 lines
11 KiB
C

#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/time.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/string.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include "bus.h"
#include "irq.h"
#define MAP_KEY_IRQ (0x02)
#define MAP_1MS_IRQ (0x03)
#define PROC_NAME ("fpga_irq")
enum IRQ_TYPE_NAME
{
MRS_KEY_IRQ = 0,
MRS_1MS_IRQ = 1,
};
typedef struct __EXT_IRQ_INFO__
{
int irqId;
int irqMap;
enum IRQ_TYPE_NAME irqType;
char irqName[32];
} EXT_IRQ_INFO, *PEXT_IRQ_INFO;
typedef int (*PEXT_1MSTIMER_RUNTIME)(void*);
typedef int (*PEXT_KEY_RUNTIME)(void*);
struct irq_hook
{
PEXT_1MSTIMER_RUNTIME hook;
void* data;
};
static EXT_IRQ_INFO g_IrqInfo[2];
static unsigned int g_IrqCnt = 0;
static unsigned int g_KeyCnt = 0;
static unsigned int* g_pIrqRegBase = NULL;
static struct irq_hook g_1MSIrqHooks[32];
static volatile unsigned int g_1MSPoolMap = 0xFFFFFFFF;
static struct irq_hook g_KeyIrqHooks[32];
static volatile unsigned int g_KeyPoolMap = 0xFFFFFFFF;
static unsigned int g_FPGAINfoOption = 0;
static struct tm g_LastKeyTime;
int register_ext_timer_irq(PEXT_1MSTIMER_RUNTIME phooks, void* data)
{
int ret = -ENOSPC;
int idx = 0;
if((idx = fls(g_1MSPoolMap) - 1) >= 0)
{
g_1MSPoolMap &= ~(1 << idx);
g_1MSIrqHooks[idx].hook = phooks;
g_1MSIrqHooks[idx].data = data;
ret = idx;
printk("ext_irq_poll_register %x\n", ret);
}
return ret;
}
EXPORT_SYMBOL(register_ext_timer_irq);
int unregister_ext_timer_irq(int idx)
{
int ret = -EINVAL;
printk("ext_irq_poll_unregister %x\n", idx);
if(!(g_1MSPoolMap & (1 << idx)))
{
g_1MSPoolMap |= (1 << idx);
}
return ret;
}
EXPORT_SYMBOL(unregister_ext_timer_irq);
int register_key_timer_irq(PEXT_KEY_RUNTIME phooks, void* data)
{
int ret = -ENOSPC;
int idx = 0;
if((idx = fls(g_KeyPoolMap) - 1) >= 0)
{
g_KeyPoolMap &= ~(1 << idx);
g_KeyIrqHooks[idx].hook = phooks;
g_KeyIrqHooks[idx].data = data;
ret = idx;
printk("key_irq_poll_register %x\n", ret);
}
return ret;
}
EXPORT_SYMBOL(register_key_timer_irq);
int unregister_key_timer_irq(int idx)
{
int ret = -EINVAL;
printk("key_irq_poll_unregister %x\n", idx);
if(!(g_KeyPoolMap & (1 << idx)))
{
g_KeyPoolMap |= (1 << idx);
}
return ret;
}
EXPORT_SYMBOL(unregister_key_timer_irq);
/** disable interrput **/
static void fpga_disable_irq(unsigned short irq)
{
unsigned short reg;
reg = read_fpga16(FPGA_INT_MASK_REG_OFFSET);
reg &= ~irq;
write_fpga16(FPGA_INT_MASK_REG_OFFSET, reg);
reg = read_fpga16(FPGA_INT_MASK_REG_OFFSET);
}
/** enable interrput **/
static void fpga_enable_irq(unsigned short irq)
{
unsigned short reg;
reg = read_fpga16(FPGA_INT_MASK_REG_OFFSET);
reg |= irq;
write_fpga16(FPGA_INT_MASK_REG_OFFSET, reg);
reg = read_fpga16(FPGA_INT_MASK_REG_OFFSET);
}
static unsigned short fpga_irq_clr(void)
{
unsigned short value;
value = read_fpga16(FPGA_INT_STATUS_REG_OFFSET);
value &= FPGA_INT_REG_MASK;
return value;
}
static void clr_int_status_bit(unsigned short value)
{
unsigned short reg;
reg = read_fpga16(FPGA_INT_STATUS_REG_OFFSET);
reg &= ~value;
write_fpga16(FPGA_INT_STATUS_REG_OFFSET, reg);
}
static unsigned short get_int_status_bit(void)
{
unsigned short value;
value = read_fpga16(FPGA_INT_STATUS_REG_OFFSET);
value &= FPGA_INT_REG_MASK;
return value;
}
static unsigned short get_gpio_data(void)
{
unsigned short value;
value = read_fpga16(FPGA_GPIO_DATA_OFFSET);
return value;
}
static irqreturn_t ext1ms_irq_handler(int irq, void* dev_id)
{
int i = -1;
unsigned int bits;
bits = ~g_1MSPoolMap;
while((i = fls(bits) - 1) >= 0)
{
bits &= ~(1 << i);
g_1MSIrqHooks[i].hook(g_1MSIrqHooks[i].data);
}
g_IrqCnt++;
// Reset Irq
in_be32((const volatile unsigned int*)&g_pIrqRegBase[MPIC_IACK_OFFSET]);
out_be32((volatile unsigned int*)&g_pIrqRegBase[MPIC_EOI_OFFSET],
MPIC_EOI_VALUE);
return IRQ_HANDLED;
}
static irqreturn_t key_irq_handler(int irq, void* dev_id)
{
unsigned short status, data;
int i = -1;
unsigned int bits;
struct timeval tv;
status = get_int_status_bit();
fpga_disable_irq(FPGA_INT_REG_MASK);
if(status & (FPGA_GPIO_STOP_BIT))
{
//ndelay(10000000);
data = get_gpio_data();
if(data & (FPGA_GPIO_STOP_BIT))
{
//printk("key stop detect\n");
do_gettimeofday(&tv);
time_to_tm(tv.tv_sec, 0, &g_LastKeyTime);
g_LastKeyTime.tm_yday = tv.tv_usec / 1000;
g_KeyCnt++;
bits = ~g_KeyPoolMap;
while((i = fls(bits) - 1) >= 0)
{
bits &= ~(1 << i);
g_KeyIrqHooks[i].hook(g_KeyIrqHooks[i].data);
}
}
}
clr_int_status_bit(FPGA_INT_REG_MASK);
in_be32((const volatile unsigned int*)&g_pIrqRegBase[MPIC_IACK_OFFSET]);
out_be32((volatile unsigned int*)&g_pIrqRegBase[MPIC_EOI_OFFSET],
MPIC_EOI_VALUE);
fpga_enable_irq(FPGA_GPIO_STOP_BIT);
return IRQ_HANDLED;
}
static int mpic_irq_init(enum IRQ_TYPE_NAME irqType,
irqreturn_t (*handler)(int irq, void* dev_id))
{
int ret = 0;
unsigned int count;
unsigned int value;
unsigned int vector;
value = g_pIrqRegBase[MPIC_EIVPR_OFFSET(g_IrqInfo[irqType].irqMap)];
vector = value & MPIC_EIVPR_VECTOR_MASK;
g_IrqInfo[irqType].irqId = irq_create_mapping(NULL, vector);
//printk("irq %d irq no: %d\n", g_IrqInfo[irqType].irqMap, g_IrqInfo[irqType].irqId);
value = (value & MPIC_EIVPR_VECTOR_MASK) | MPIC_EIVPR_MSK | MPIC_EIVPR_PRIORITY(
vector) ;
/*active high to low*/
g_pIrqRegBase[MPIC_EIVPR_OFFSET(g_IrqInfo[irqType].irqMap)] = value;
g_pIrqRegBase[MPIC_EIDR_OFFSET(g_IrqInfo[irqType].irqMap)] = MPIC_EIDR_VALUE;
g_pIrqRegBase[MPIC_CTPR_OFFSET] = MPIC_CTPR_VALUE;
g_pIrqRegBase[MPIC_GCR_OFFSET] |= MPIC_GCR_M;
/* start irq */
count = g_pIrqRegBase[MPIC_FRR_OFFSET];
count = (count & IRQ_NUM_MASK) >> 16 ;
while(count--)
{
in_be32((const volatile unsigned int*)&g_pIrqRegBase[MPIC_IACK_OFFSET]);
out_be32((volatile unsigned int*)&g_pIrqRegBase[MPIC_EOI_OFFSET],
MPIC_EOI_VALUE);
}
ret = request_irq(g_IrqInfo[irqType].irqId, handler, 0,
g_IrqInfo[irqType].irqName, 0);
g_pIrqRegBase[MPIC_MER_OFFSET] = MPIC_MER_VALUE;
g_pIrqRegBase[MPIC_CTPR_OFFSET] = MPIC_CTPR_VALUE;
/* start irq */
g_pIrqRegBase[MPIC_EIVPR_OFFSET(g_IrqInfo[irqType].irqMap)] &= ~ MPIC_EIVPR_MSK;
return ret;
}
static void mpic_irq_exit(enum IRQ_TYPE_NAME irqType)
{
mdelay(1);
g_pIrqRegBase[MPIC_EIVPR_OFFSET(g_IrqInfo[irqType].irqMap)] |= MPIC_EIVPR_MSK;
free_irq(g_IrqInfo[irqType].irqId, NULL);
}
static int fpga_irq_proc_show(struct seq_file* m, void* v)
{
seq_printf(m, "--------FPGA IRQ INFO--------\n");
seq_puts(m, "\n");
seq_puts(m, "+++++MRS_KEY_IRQ IRQ Info:+++++\n");
seq_printf(m, "IRQ ID: %u\n", g_IrqInfo[0].irqId);
seq_printf(m, "IRQ MAP ID: %u\n", g_IrqInfo[0].irqMap);
seq_printf(m, "IRQ TYPE: %u\n", g_IrqInfo[0].irqType);
seq_printf(m, "IRQ Name: %s\n", g_IrqInfo[0].irqName);
seq_printf(m, "IRQ HOOK MAP: 0x%08X\n", g_KeyPoolMap);
seq_printf(m, "IRQ Key Count: 0x%08X\n", g_KeyCnt);
if(g_KeyCnt > 0)
{
seq_printf(m, "At [%02d:%02d:%02d:%03d] Stop Key Pressed\n",
g_LastKeyTime.tm_hour, g_LastKeyTime.tm_min,
g_LastKeyTime.tm_sec, g_LastKeyTime.tm_yday);
}
seq_puts(m, "-----MRS_KEY_IRQ IRQ Info:-----\n");
seq_puts(m, "\n");
seq_puts(m, "+++++MRS_1MS_IRQ IRQ Info:+++++\n");
seq_printf(m, "IRQ ID: %u\n", g_IrqInfo[1].irqId);
seq_printf(m, "IRQ MAP ID: %u\n", g_IrqInfo[1].irqMap);
seq_printf(m, "IRQ TYPE: %u\n", g_IrqInfo[1].irqType);
seq_printf(m, "IRQ Name: %s\n", g_IrqInfo[1].irqName);
seq_printf(m, "IRQ HOOK MAP: 0x%08X\n", g_1MSPoolMap);
seq_printf(m, "IRQ 1MS Count: 0x%08X(%u)\n", g_IrqCnt, g_IrqCnt);
seq_puts(m, "-----MRS_1MS_IRQ IRQ Info:-----\n");
return 0;
}
static int fpga_irq_proc_open(struct inode* inode, struct file* file)
{
return single_open(file, fpga_irq_proc_show, NULL);
}
static ssize_t fpga_irq_write(struct file* file, const char __user* userbuf,
size_t count, loff_t* data)
{
char buf[20];
if(count >= sizeof(buf))
{
printk("Input Params Error:count = %d, max size = %d\n", count, sizeof(buf));
return -1;
}
if(copy_from_user(buf, userbuf, count))
{
printk("Copy Data To Kernel Error\n");
return -2;
}
buf[count] = '\0';
if(strict_strtoul(buf, 0, (long unsigned int*)&g_FPGAINfoOption))
{
return -3;
}
printk("Set Options To [%u]\n", g_FPGAINfoOption);
return count;
}
static const struct file_operations fpga_irq_proc_fops =
{
.open = fpga_irq_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = fpga_irq_write,
};
int mrs_irq_init(void)
{
int uRet = 0;
#ifdef PLATFORM_P1010
printk("Init PLATFORM P1010 Build:%s(%s)\n", __DATE__, __TIME__);
#else
printk("Init PLATFORM MPC8309 Build:%s(%s)\n", __DATE__, __TIME__);
#endif
proc_create(PROC_NAME, 0, NULL, &fpga_irq_proc_fops);
fpga_bus_init();
g_IrqInfo[0].irqId = -1;
g_IrqInfo[0].irqMap = MAP_KEY_IRQ;
g_IrqInfo[0].irqType = MRS_KEY_IRQ;
strcpy(g_IrqInfo[0].irqName, "MRS_KEY_IRQ");
g_IrqInfo[1].irqId = -1;
g_IrqInfo[1].irqMap = MAP_1MS_IRQ;
g_IrqInfo[1].irqType = MRS_1MS_IRQ;
strcpy(g_IrqInfo[1].irqName, "MRS_1MS_IRQ");
g_pIrqRegBase = (unsigned int*)ioremap(MPIC_REGS_BASE, MPIC_REG_MAP_SIZE);
// printk("g_pRegBase = 0x%08X, g_pIrqRegBase = 0x%08X\n", g_pIrqRegBase, g_pIrqRegBase);
/** disable all fpga interrupt **/
fpga_disable_irq(FPGA_INT_MASK);
/** enable the switch key **/
fpga_enable_irq(FPGA_GPIO_STOP_BIT);
/** enable board select interrupt **/
fpga_enable_irq(FPGA_GPIO_BD_SEL);
fpga_irq_clr();
mpic_irq_init(MRS_KEY_IRQ, key_irq_handler);
mpic_irq_init(MRS_1MS_IRQ, ext1ms_irq_handler);
return uRet;
}
void mrs_irq_exit(void)
{
#ifdef PLATFORM_P1010
printk("Exit PLATFORM P1010 Build:%s(%s)\n", __DATE__, __TIME__);
#else
printk("Exit PLATFORM MPC8309 Build:%s(%s)\n", __DATE__, __TIME__);
#endif
mpic_irq_exit(MRS_KEY_IRQ);
mpic_irq_exit(MRS_1MS_IRQ);
if(g_pIrqRegBase != NULL)
{
iounmap(g_pIrqRegBase);
g_pIrqRegBase = NULL;
}
fpga_bus_exit();
remove_proc_entry(PROC_NAME, NULL);
}