#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/string.h>
#include <linux/device.h>
#include <linux/spinlock.h>
#define DBG(msg...) do{ \
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"
static DECLARE_WAIT_QUEUE_HEAD(spi_waitq);
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_t count,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 Part define
volatile unsigned long *spi_gpfdat=NULL;
volatile unsigned long *spi_gpfup=NULL;
volatile unsigned long *spi_gpgcon=NULL;//GPG Part define
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 =
static irqreturn_t spi_interrupt(int irq,void *dev_id,struct pt_regs *regs)
wake_up_interruptible(&spi_waitq);
static int spi_open(struct inode *inode,struct file *filp)
if(down_interruptible(&sem))
filp->private_data =&spiCdev;
static int spi_release(struct inode *inode,struct file *filp)
static void writeByte(const char c)
wait_event_interruptible(spi_waitq,ack);
static char readByte(void)
*spi_sptdat1 = (char)0xff;
wait_event_interruptible(spi_waitq,ack);
static ssize_t spi_read(struct file *filp,char __user *buf,size_t count,loff_t *f_ops)
static ssize_t spi_write(struct file *filp,const char __user *buf,size_t count,loff_t *f_ops)
DBG("spi write!,count=%d\n",count);
kbuf=kmalloc(count,GFP_KERNEL);
if(copy_from_user(kbuf,buf,count))
printk("no enough memory!\n");
DBG("write 0xX!\n",*kbuf);
static ssize_t spi_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long data)
static int __init spi_init(void)
devno = MKDEV(spi_major, 0);
result = register_chrdev_region(devno, 1, DEVICE_NAME);
result = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME);
spi_major = MAJOR(devno);
cdev_init(&spiCdev, &spi_fops); spiCdev.owner = THIS_MODULE; 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);
iounmap (s3c2440_clkcon);
MODULE_DESCRIPTION("SPI driver for S3C2440");