S3C2440 SPI驱动简单测试

来源:互联网 发布:网络机房相关证书 编辑:程序博客网 时间:2024/05/29 04:30
http://www.cnblogs.com/nkzc/archive/2010/07/21/1781959.html
http://apps.hi.baidu.com/share/detail/23661495

#include <linux/irq.h>
#include<linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include<linux/interrupt.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/gpio.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include<linux/spinlock.h>
#include <linux/clk.h>
#include <asm/system.h>
#include <asm/signal.h>
#include <asm/io.h>

#define DBG(msg...) do{ \
if(debug)\
printk(KERN_INFO msg);\
}while(0)
static int debug=1;
static int spi_major=0;
module_param(spi_major,int,S_IRUGO);

static struct class *spi_class;
static struct semaphore sem;                                           
//static struct clk *spi_clock;
#define DEVICE_NAME "tq2440_spi"
struct cdev spiCdev;
static DECLARE_WAIT_QUEUE_HEAD(spi_waitq);
static int ack=0;
static int spi_open(struct inode *,struct file *);
static int spi_release(struct inode *,struct file *);
static ssize_t spi_write(struct file *filp,const char*buf,size_t count,loff_t *f_ops);
static ssize_t spi_read(struct file *filp,char *buf,size_tcount,loff_t *f_ops);
static ssize_t spi_ioctl(struct inode *inode,struct file*filp,unsigned int cmd,unsigned long data);

volatile unsigned long *spi_gpfcon=NULL;//GPF Partdefine
volatile unsigned long *spi_gpfdat=NULL;
volatile unsigned long *spi_gpfup=NULL;

volatile unsigned long *spi_gpgcon=NULL;//GPG Partdefine
volatile unsigned long *spi_gpgdat=NULL;
volatile unsigned long *spi_gpgup=NULL;

volatile unsigned long *s3c2440_clkcon;
volatile unsigned long *spi_spcon1;//SPI Part define
volatile unsigned long *spi_spsta1;
volatile unsigned long *spi_sppin1;
volatile unsigned long *spi_sppre1;
volatile unsigned long *spi_sptdat1;
volatile unsigned long *spi_sprdat1;

static const struct file_operations spi_fops= 
{
.owner=THIS_MODULE,
.open=spi_open,
.read=spi_read,
.ioctl=spi_ioctl,
.release=spi_release,
.write=spi_write,
};
static irqreturn_t spi_interrupt(int irq,void *dev_id,structpt_regs *regs)
{
ack=1;
DBG("irq\n");
wake_up_interruptible(&spi_waitq);
return IRQ_HANDLED;
}
static int spi_open(struct inode *inode,struct file*filp)
{
if(down_interruptible(&sem))
return -ERESTARTSYS;
filp->private_data=&spiCdev;
return 0;
}


static int spi_release(struct inode *inode,struct file*filp)
{
up(&sem);
DBG("release\n");
return 0;
}


static void writeByte(const char c)
{
*spi_sptdat1 = c;
wait_event_interruptible(spi_waitq,ack);
ack=0;
}

static char readByte(void)
{

char ch = 0;
*spi_sptdat1 = (char)0xff;
wait_event_interruptible(spi_waitq,ack);
ack=0;
ch=*spi_sprdat1;
return ch;
}
static ssize_t spi_read(struct file *filp,char __user*buf,size_t count,loff_t *f_ops)
{
char ch;
DBG("spi read!\n");
ch=readByte();
copy_to_user(buf,&ch,1);
return 1;
}

static ssize_t spi_write(struct file *filp,const char __user*buf,size_t count,loff_t *f_ops)
{
int i;
char *kbuf;
DBG("spi write!,count=%d\n",count);
kbuf=kmalloc(count,GFP_KERNEL);
if(copy_from_user(kbuf,buf,count))
{
printk("no enough memory!\n");
return -1;
}
for(i=0;i<count;i++)
{
writeByte(*kbuf);
DBG("write 0xX!\n",*kbuf);
kbuf++;
}
kfree(kbuf);
kbuf=NULL;
return count;
}

static ssize_t spi_ioctl(struct inode *inode,struct file*filp,unsigned int cmd,unsigned long data)
{
return 0;
}


static int __init spi_init(void)
{
int result;
int ret;
dev_t devno;
init_MUTEX(&sem);
if(spi_major)
{
devno = MKDEV(spi_major, 0);
result = register_chrdev_region(devno, 1, DEVICE_NAME);
}
  else
{
result = alloc_chrdev_region(&devno, 0, 1,DEVICE_NAME);
spi_major = MAJOR(devno);
}
if (result < 0)
    return result;   
   cdev_init(&spiCdev,&spi_fops);
  spiCdev.owner = THIS_MODULE;
spiCdev.ops = &spi_fops;
if (cdev_add(&spiCdev, devno, 1))
printk(KERN_NOTICE "Error adding spi %d\n", 0);
s3c2440_clkcon = (unsigned long *)ioremap(0x4C00000c,3);
spi_spcon1 = (unsigned long *)ioremap(0x59000020,1);
spi_spsta1 = (unsigned long *)ioremap(0x59000024,1);
spi_sppin1 = (unsigned long *)ioremap(0x59000028,1);
spi_sppre1 = (unsigned long *)ioremap(0x5900002c,1);
spi_sptdat1 = (unsigned long *)ioremap(0x59000030,1);
spi_sprdat1 = (unsigned long *)ioremap(0x59000034,1);

*s3c2440_clkcon |=0x40000;
s3c2410_gpio_cfgpin(S3C2410_GPG5,S3C2410_GPG5_SPIMISO1);
s3c2410_gpio_cfgpin(S3C2410_GPG6,S3C2410_GPG6_SPIMOSI1);
s3c2410_gpio_cfgpin(S3C2410_GPG7,S3C2410_GPG7_SPICLK1);
s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_nSS1);
s3c2410_gpio_pullup(S3C2410_GPG5,1);
s3c2410_gpio_pullup(S3C2410_GPG6,1);
s3c2410_gpio_pullup(S3C2410_GPG7,1);
 
writel(0x18,spi_sppre1);
/
iounmap (s3c2440_clkcon);
iounmap (spi_spcon1);
iounmap (spi_spsta1);
iounmap (spi_sppin1);
iounmap (spi_sppre1);
iounmap (spi_sptdat1);
iounmap (spi_sprdat1);
printk("spi_exit!\n");
}

module_init(spi_init);
module_exit(spi_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("syw");
MODULE_DESCRIPTION("SPI driver for S3C2440");

0 0
原创粉丝点击