#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include <linux/errno.h>
#include <linux/kdev_t.h>
#include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/time.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <asm/io.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#define GPG_CON 0x56000060
#define GPG_DAT 0x56000064
#define GPG_UP 0x56000068
#define GPF_CON 0x56000050
#define GPF_DAT 0x56000054
#define GPF_UP 0x56000058
#define SPCON_1 0x59000020
#define SPSTA_1 0x59000024
#define SPPIN_1 0x59000028
#define SPPRE_1 0X5900002C
#define SPTDAT_1 0x59000030
#define SPRDAT_1 0x59000034
#define CLKCON_ 0x4C00000C
//#define liic_NOT_DEBUG 1 //将该句屏蔽掉的话才可以print打印,调试
#ifdef liic_NOT_DEBUG
#define printk(fmt,args...) //不打印
#endif
MODULE_AUTHOR("zhangxb");
MODULE_LICENSE("GPL");//代替mknode时必须加上这句
#define DEVICE_NAME "lspi" //注册设备的名称
#define DEVICE_NAME_CLASS "lspi_c" //注册dev的
#define DEV_MAJOR 211 //设备号1
#define DEV_MINOR 0 //设备号2
int SendMode=1; //工作模式,0是查询,1是中断
int irqStateFlag=0;//是否已注册中断标志flag
int spiIntAck=0; //中断产生标志flag
#define ReadBuffNum 65 //定义缓冲区大小,实际缓存要减一,65=64+1
char __user ReadBuf[ReadBuffNum]=""; //缓冲区
int ReadBuffStartP=0; //缓冲数据开始指针
int ReadBuffEndP=0; //缓冲数据结束指针
unsigned long S3C2402_GPGCON; //io管脚控制寄存器
unsigned long S3C2402_GPGDAT; //io数据内容
unsigned long S3C2402_GPGUP; //io管脚上拉
unsigned long S3C2402_GPFCON; //io管脚控制寄存器
unsigned long S3C2402_GPFDAT; //io数据内容
unsigned long S3C2402_GPFUP; //io管脚上拉
unsigned long S3C2402_SPCON1; //spi控制寄存器
unsigned long S3C2402_SPSTA1; //状态寄存器
unsigned long S3C2402_SPPIN1; //引脚控制寄存器
unsigned long S3C2402_SPPRE1; //波特率寄存器
unsigned long S3C2402_SPTDAT1; //发送数据寄存器
unsigned long S3C2402_SPRDAT1; //接收数据寄存器
unsigned long ADDR_CLKCON; //系统时钟寄存器
struct spi_dev{//设备结构体,用于注册设备用
wait_queue_head_t rq; // 读取等待队列
uint8_t *buffer;
uint32_t size;
uint32_t index;
struct semaphore sem;
struct cdev cdev;
};
struct spi_dev *my_dev;
//内核映射函数
static void address_map(void)
{
S3C2402_GPGCON =(unsigned long)ioremap(GPG_CON,4);
S3C2402_GPGDAT =(unsigned long)ioremap(GPG_DAT,4);
S3C2402_GPGUP =(unsigned long)ioremap(GPG_UP,4);
S3C2402_GPFCON =(unsigned long)ioremap(GPF_CON,4);
S3C2402_GPFDAT =(unsigned long)ioremap(GPF_DAT,4);
S3C2402_GPFUP =(unsigned long)ioremap(GPF_UP,4);
S3C2402_SPCON1 =(unsigned long)ioremap(SPCON_1,4);
S3C2402_SPSTA1 =(unsigned long)ioremap(SPSTA_1,4);
S3C2402_SPPIN1 =(unsigned long)ioremap(SPPIN_1,4);
S3C2402_SPPRE1 =(unsigned long)ioremap(SPPRE_1,4);
S3C2402_SPTDAT1=(unsigned long)ioremap(SPTDAT_1,4);
S3C2402_SPRDAT1=(unsigned long)ioremap(SPRDAT_1,4);
ADDR_CLKCON =(unsigned long)ioremap(CLKCON_,4);
};
//解除内核映射函数
static void address_unmap(void)
{
iounmap(S3C2402_GPGCON);
iounmap(S3C2402_GPGDAT);
iounmap(S3C2402_GPGUP);
iounmap(S3C2402_GPFCON);
iounmap(S3C2402_GPFDAT);
iounmap(S3C2402_GPFUP);
iounmap(S3C2402_SPCON1);
iounmap(S3C2402_SPSTA1);
iounmap(S3C2402_SPPIN1);
iounmap(S3C2402_SPPRE1);
iounmap(S3C2402_SPTDAT1);
iounmap(S3C2402_SPRDAT1);
iounmap(ADDR_CLKCON);
};
//将接收的数据放入缓冲区
int ReadBuffAddData(unsigned char BateData)
{
if(BateData==0xFF)
return 0;
ReadBuf[ReadBuffEndP]=BateData;
ReadBuffEndP++;
if(ReadBuffEndP>=ReadBuffNum)
ReadBuffEndP=0;
if(ReadBuffEndP==ReadBuffStartP)
{
ReadBuffStartP++;
if(ReadBuffStartP>=ReadBuffNum)
ReadBuffStartP=0;
}
return 1;
};
//从缓冲区取出一定量数据
int ReadBuffGetOut(char __user *OutPutDatas,int count)
{
int i;
for(i=0;i<count;i++)
{
if(ReadBuffStartP==ReadBuffEndP)
break;
*(OutPutDatas+i)=ReadBuf[ReadBuffStartP];
ReadBuffStartP++;
if(ReadBuffStartP>=ReadBuffNum)
ReadBuffStartP=0;
};
return i;
};
//中断处理函数
irqreturn_t interrupt_handle( int irq, void* dev_id, struct pt_regs* regs )
{
//printk("intrrupt:\n" );
spiIntAck=1;//中断标志位写1
ReadBuffAddData(ioread32(S3C2402_SPRDAT1));
return IRQ_HANDLED;
};
//将寄存器的值打印出来,调试用
PrintRegister()
{
udelay(1);
printk("GUP:%x GON:%x GTA:%x ",ioread32(S3C2402_GPGUP),ioread32(S3C2402_GPGCON),ioread32(S3C2402_GPGDAT));
printk("CLK:%x CON:%x ",ioread32(ADDR_CLKCON),ioread32(S3C2402_SPCON1));
printk("TDA:%x RDA:%x ",ioread32(S3C2402_SPTDAT1),ioread32(S3C2402_SPRDAT1));
printk("STA:%x PIN:%x PRE:%x\n",ioread32(S3C2402_SPSTA1),ioread32(S3C2402_SPPIN1),ioread32(S3C2402_SPPRE1));
}
//状态寄存器只有3个有效位,只读,第0个是判断中断标志位的
#define SPI_TXRX_READY (((ioread32(S3C2402_SPSTA1))&0x01)==0x01) //查询用
//初始化SPI寄存器
SPI_InitSet()
{
unsigned int RegData;
int i=0;
address_map();
//配置时钟
iowrite32(ioread32(ADDR_CLKCON) | (1<<18),ADDR_CLKCON);
//配置spi的io口,3根线都要配置
RegData=(ioread32(S3C2402_GPGCON)|0x0000FC00);
iowrite32(RegData,S3C2402_GPGCON);
RegData=((ioread32(S3C2402_GPGUP)&0xFF1F)|0x0060);
iowrite32(RegData,S3C2402_GPGUP);
RegData=(ioread32(S3C2402_GPFCON)&0xFCF3)|0x0108;
iowrite32(RegData,S3C2402_GPFCON);
RegData=(ioread32(S3C2402_GPFUP)&0xED);
iowrite32(RegData,S3C2402_GPFUP);
RegData=(ioread32(S3C2402_GPFDAT)|0x10);
iowrite32(RegData,S3C2402_GPFDAT);
//配置为1MHz传输速度,Value=PCLK/(2*SPICLK)-1=50MHz/(2*1MHz)-1=24=0x18;不可超过25MHz
iowrite32(0x18,S3C2402_SPPRE1);
//00X11000,无,00查询模式(01中断),SCK有效,主模式,高态有效active hign,格式A,正常模式
RegData=((0<<0) | (0<<1) | (0<<2) | (1<<3) | (1<<4) | ((SendMode>0)<<5) | (0<<6) );
iowrite32(RegData,S3C2402_SPCON1);
if(SendMode>0 && irqStateFlag!=1)//注册中断,irqs.c有中断表
{
int ret = request_irq( IRQ_SPI1, interrupt_handle,IRQF_DISABLED, DEVICE_NAME, NULL );//(void)*dev,
irqStateFlag=1;
}
//引脚控制寄存器只有两位有效,第0位0 释放,第2位0 通用无效
RegData=((0<<2) | (0<<0));
iowrite32(RegData,S3C2402_SPPIN1);
//PrintRegister();//打印寄存器值。
}
static int spi_open(struct inode *inode,struct file *filp)
{
//printk("readta:%x\n",ReadBuffEndP);
return 0;
}
//中断防阻塞等待
int SPI24C08While(int *FlagAddr)
{
while(1)
{
if((*FlagAddr)!=0)break;//检测到标志位变化,表示已经发生了中断
else
{
set_current_state(TASK_INTERRUPTIBLE);//防止阻塞
schedule_timeout(1);//设置阻塞时间
}
}
};
static int spi_release(struct inode *inode,struct file *filp)
{
return 0;
}
static ssize_t spi_read(struct file *filp,const char *buf,size_t count,loff_t *f_ops)
{
int ReadNum=0;
char __user ReadDatas[65]="";