S3C2410+linux下的SPI驱动代码,开源到底


static int spi_open(struct inode *inode, struct file *file)
{
unsigned long temp1,temp2,temp4;
int i;
// printk("SPPRE = %ld,SPCON = %ld,SPPIN = %ld\n",rSPPRE0,rSPCON0,rSPPIN0);
// printk("CLKCON = 0x%X\n",rCLKCON); //for debug
temp4 = __raw_readl(S3C2410_GPEUP);
// temp4 &= ~(0x3800);
// temp4 |= 0x2000;
temp4 |= 0x1800;
__raw_writel(temp4,S3C2410_GPEUP);
printk("s3c2410_GPEUP value 0x%X\n",__raw_readl(S3C2410_GPEUP)); //for debug
temp1 = __raw_readl(S3C2410_GPECON);
temp1 &= 0xF03FFFFF;
temp1 |= 0xA800000 ;
__raw_writel(temp1,S3C2410_GPECON);
printk("s3c2410_GPECON value 0x%X\n",__raw_readl(S3C2410_GPECON)); //for debug
/*
temp3 = __raw_readl(S3C2410_GPGUP);
temp3 |= 0x04;
__raw_writel(temp3,S3C2410_GPGUP); //spi0 cs0 poll enable
*/
printk("s3c2410_GPGUP value 0x%X\n",__raw_readl(S3C2410_GPGUP)); //for debug
temp2 = __raw_readl(S3C2410_GPGCON);
temp2 &= 0xFFFFFDCF;
temp2 |= 0x50;
__raw_writel(temp2,S3C2410_GPGCON); //for spi0 cs0

printk("s3c2410_GPGCON value 0x%X\n",__raw_readl(S3C2410_GPGCON)); //for debug
rCLKCON |= 0x40000; //关键,必须先设置PCLK为SPI CLOCK,否则SPI相关的寄存器不能设置!!!
rSPPRE0 = 0x01; //设置SPI波特率
rSPCON0 = 0x19; //设置为查询方式
rSPPIN0 = 0x02;
for(i = 0 ;i < 10 ;i++)
{
rSPTDAT0 = 0xff;
} //初始化设备
return 0;
}
static int spi_release(struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t spi_read(struct file *file, char __user *buffer, long count, loff_t *ppos)
{
int i,j;
unsigned long csval,temp1;
unsigned char *kbuf = kmalloc(count,GFP_KERNEL), *ptr;
if (!kbuf)
return -ENOMEM;

if (copy_from_user(kbuf, buffer, count))
return -EFAULT;
ptr = kbuf;

csval = __raw_readl(S3C2410_GPGDAT); //set cs low
temp1 = csval & 0xFFFFFFFB;
__raw_writel(temp1,S3C2410_GPGDAT);
// printk("s3c2410_GPGDAT value 0x%X\n",__raw_readl(S3C2410_GPGDAT)); //for debug

for(i=0;i<4;i++)
{
// printk("tx times: 0x%X,txdata: 0x%2X\n",i,ptr);
if((rSPSTA0 & 0x01))
rSPTDAT0 = ptr;
for(j=0;j<50;j++);
}


for(i=3;i<count+1;i++) //接收的第一个字符都为0xff,人为去除
{
// rSPTDAT0 = 0xFF;
if((rSPSTA0 & 0x01))//{
ptr = rSPRDAT0;

for(j=0;j<50;j++);
// printk("rx times: 0x%X,rxdata: 0x%2X\n",i,ptr); }
}

csval = __raw_readl(S3C2410_GPGDAT); //set cs high
temp1 = csval | 0x04;
__raw_writel(temp1,S3C2410_GPGDAT);
// printk("s3c2410_GPGDAT value 0x%X\n",__raw_readl(S3C2410_GPGDAT)); //for debug

copy_to_user(buffer,kbuf,count);
kfree(kbuf);
return count;
}
static ssize_t spi_write(struct file *file, const char __user *buffer, long count, loff_t *ppos)
{
int i,j;
unsigned long csval,temp1;
unsigned char *kbuf = kmalloc(count,GFP_KERNEL), *ptr;
if (!kbuf)
return -ENOMEM;
if (copy_from_user(kbuf, buffer, count))
return -EFAULT;
ptr = kbuf;

csval = __raw_readl(S3C2410_GPGDAT); //set cs low
temp1 = csval & 0xFFFFFFFB;
__raw_writel(temp1,S3C2410_GPGDAT);
// printk("s3c2410_GPGDAT value 0x%X\n",__raw_readl(S3C2410_GPGDAT)); //for debug

for(i=0;i<count;i++)
{
// printk("txdata: 0x%2X\n",ptr);
if((rSPSTA0 & 0x01))
rSPTDAT0 = ptr;

for(j=0;j<50;j++);

}
// printk("txdata: 0x%02X 0x%02X 0x%02X 0x%02X\n",ptr[0],ptr[1],ptr[2],ptr[3]);
// printk("/******************/\n");
// printk("spi write debug\n");
csval = __raw_readl(S3C2410_GPGDAT); //set cs high
temp1 = csval | 0x04;
__raw_writel(temp1,S3C2410_GPGDAT);
// printk("s3c2410_GPGDAT value 0x%X\n",__raw_readl(S3C2410_GPGDAT)); //for debug

kfree(kbuf);
return count;
}

你可能感兴趣的:(linux)