📄 switch.c
字号:
/* FJ:SupportForTARBO-20020617-V01L01 */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/irq.h>
#include <asm/frvirq.h>
#include <asm/uaccess.h>
#include <asm/smplock.h>
#include "switch.h"
int __init fpga_sw_init(void);
static void fpga_sw_inthdr(int irq, void *dev_id, struct pt_regs *regs);
static int fpga_sw_open(struct inode *inode, struct file *file);
static int fpga_sw_release(struct inode *inode, struct file *file);
static int fpga_sw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
static void fpga_sw_task(unsigned long data);
static inline u16 read_tarboio_register(volatile unsigned short *x);
static inline void write_tarboio_register(volatile unsigned short *x, unsigned short v);
DECLARE_TASKLET(fpga_sw_tasklet, fpga_sw_task, 0);
DECLARE_WAIT_QUEUE_HEAD(wake_fpga_sw_que);
static spinlock_t fr400_sw_lock = SPIN_LOCK_UNLOCKED;
static volatile unsigned short fpga_sw_buff;
static struct file_operations fpga_sw_fops = {
ioctl: fpga_sw_ioctl, // ioctl entry
open: fpga_sw_open, // open entry
release: fpga_sw_release,// release entry
};
/*
* FPGA SW driver user interface
*/
/* Open a FPGA SW device. */
static int fpga_sw_open(struct inode *inode, struct file *file)
{
return 0;
}
/* Last close of a FPGA SW for Linux device */
static int fpga_sw_release(struct inode *inode, struct file *file)
{
return 0;
}
static int fpga_sw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int data;
unsigned long flags;
unsigned short irq;
switch (cmd) { /* If SW flag is ON, read sw register and return */
case FPGA_PUSW_READ :
data = SW_PUSW_READ();
if (data) {
/* push SW is ON */
*(int *)arg = data;
return 0;
}
irq = FPGA_PUSW_IRQ;
break;
case FPGA_RSW8_READ :
data = SW_RSW8_READ();
if (data) {
/* Rocker SW8 is ON */
*(int *)arg = data;
return 0;
}
irq = FPGA_RSW8_IRQ;
break;
case FPGA_RSW9_READ :
data = SW_RSW9_READ();
if (data) {
/* Rocker SW9 is ON */
*(int *)arg = data;
return 0;
}
irq = FPGA_RSW9_IRQ;
break;
case FPGA_SW_READ :
data = SW_READ();
if (data) {
/* SW is ON */
*(int *)arg = data;
return 0;
}
irq = FPGA_SW_IRQ;
break;
default :
printk("FPGA SW: invalid command.\n");
return -EINVAL;
}
/*
* SW is OFF
*/
/* Enable SW interrupt */
spin_lock_irqsave(&fr400_sw_lock, flags);
{
fpga_sw_buff = 0xFFFF;
enable_irq(FRV_K_IRQ_SW2_6);
enable_irq(FRV_K_IRQ_SW9);
enable_irq(FRV_K_IRQ_SW8);
}
spin_unlock_irqrestore(&fr400_sw_lock, flags);
/* Wait SW interrupt */
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(5);
/* Disable SW interrupt */
spin_lock_irqsave(&fr400_sw_lock, flags);
{
data = fpga_sw_buff;
}
spin_unlock_irqrestore(&mbfr400_sw_lock, flags);
if (data == 0xFFFF) {
disable_irq(FRV_K_IRQ_SW2_6);
disable_irq(FRV_K_IRQ_SW9);
disable_irq(FRV_K_IRQ_SW8);
*(int *)arg = data;
}
else if (cmd == FPGA_PUSW_READ)
*(int *)arg = ((data>>10) & 0x001F);
else if (cmd == FPGA_RSW8_READ)
*(int *)arg = ((data>> 5) & 0x001F);
else if (cmd == FPGA_RSW9_READ)
*(int *)arg = ((data ) & 0x001F);
else if (cmd == FPGA_SW_READ)
*(int *)arg = ((data ) & 0x7FFF);
return 0;
}
/*
* FPGA SW driver initilaize routie
*/
int __init fpga_sw_init(void)
{
unsigned long flags;
printk(KERN_INFO "PDK 2.0 FPGA SW interface: v1.00\n");
if(devfs_register_chrdev(FPGA_SW_MAJOR,"fpga_sw", &fpga_sw_fops)) {
printk("PDK 2.0 FPGA SW interface: unable to get major %d\n", FPGA_SW_MAJOR);
return -EIO;
}
spin_lock_irqsave(&fr400_sw_lock, flags);
request_irq(FRV_K_IRQ_SW2_6, fpga_sw_inthdr, SA_INTERRUPT, "fr400_sw2_6", NULL);
request_irq(FRV_K_IRQ_SW9, fpga_sw_inthdr, SA_INTERRUPT, "fr400_sw9", NULL);
request_irq(FRV_K_IRQ_SW8, fpga_sw_inthdr, SA_INTERRUPT, "fr400_sw8", NULL);
disable_irq(FRV_K_IRQ_SW2_6);
disable_irq(FRV_K_IRQ_SW9);
disable_irq(FRV_K_IRQ_SW8);
spin_unlock_irqrestore(&fr400_sw_lock, flags);
return 0;
}
/*
* FPGA SW driver interrupt handler
*/
static void fpga_sw_inthdr(int irq, void *dev_id, struct pt_regs *regs)
{
disable_irq(FRV_K_IRQ_SW2_6);
disable_irq(FRV_K_IRQ_SW9);
disable_irq(FRV_K_IRQ_SW8);
tasklet_schedule(&fpga_sw_tasklet);
return;
}
/*
* FPGA SW driver task
*/
static void fpga_sw_task(unsigned long data)
{
unsigned long flags, i;
spin_lock_irqsave(&fr400_sw_lock, flags);
{
for(i=0;i<1000;i++){
fpga_sw_buff = SW_READ();
if(fpga_sw_buff!=0x7FFF) break;
}
}
spin_unlock_irqrestore(&mbfr400_sw_lock, flags);
return;
}
static inline u16 read_tarboio_register(volatile unsigned short *x)
{
unsigned short v;
v = *((volatile unsigned short *)(x));
__asm__ __volatile__("membar");
return v;
}
static inline void write_tarboio_register(volatile unsigned short *x, unsigned short v)
{
*((volatile unsigned short *)(x)) = (v);
__asm__ __volatile__("membar");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -