📄 spi.c
字号:
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/config.h>
#include <linux/module.h>
#ifdef CONFIG_SMP
#define __SMP__
#endif
/***************************************************/
#include <linux/kernel.h> /*printk()*/
#include <asm/uaccess.h> /*copy_to_user(),copy_from_user()*/
#include <linux/fs.h> /*struct file_operations,register_chrdv()*/
#include <linux/sched.h> /*和任务有关系*/
#include <linux/types.h> /*u8,u16,u32...*/
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/delay.h>
#include <linux/version.h>
//wushuai//#include <linux/iobuf.h>
#include <linux/major.h>
#include <linux/capability.h>
#include <linux/smp_lock.h>
#include <linux/fs.h>
#include <linux/mm.h>
//wushuai//#include <asm/arch/cpu_s3c2410.h>
#include <asm/io.h>
#include <linux/sched.h>
#include <linux/module.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/mm.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/cdev.h>#include <asm/io.h>#include <asm/system.h>#include <asm/uaccess.h>
int *spi_gpdcon=NULL;//GPD Part define
//unsigned long spi_gpddat;
//unsigned long spi_gpdup;
int *spi_gpecon=NULL;//GPE Part define
//unsigned long spi_gpedat;
//unsigned long spi_gpeup;
int *spi_gpfcon=NULL;//GPF Part define
//unsigned long spi_gpfdat;
//unsigned long spi_gpfup;
int *spi_gpgcon=NULL;//GPF Part define
//unsigned long spi_gpgdat;
//unsigned long spi_gpgup;
int spi_spcon0;//SPI Part define
int spi_spsta0;
int spi_sppin0;
int spi_sppre0;
int spi_sptdat0;
int spi_sprdat0;
/*****************************************************/
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);
struct spi_dev
{
struct cdev cdev; /*cdev结构体*/
};
struct spi_dev *spi_devp; /*设备结构体指针*/
/**********************************************************/
static const struct file_operations spi_fops =
{
.owner=THIS_MODULE,
.open=spi_open,
.release=spi_release,
.write=spi_write,
};
static int spi_major = 55;
#define spi_name "S3C2410_SPI"
//wushuai//#define spi_minor 1
#if 0
#ifdef CONFIG_DEVFS_FS
static devfs_handle_t devfs_spi_dir,devfs_spiraw;
#endif
#endif
/********************************************************/
static int spi_open(struct inode *inode,struct file *filp)
{
int value,i;
printk("<1>***************************\n");
printk("<1>spi open program begin..\n");
printk("<1>now,GPE port init...\n");
filp->private_data =spi_devp;
/*配置SCK0,MOSI0,MISO0*/
*spi_gpecon &=0xF03FFFFF;//GPECON-11(SPISCK0),12(SPIMOSI0),13(SPIMISO0)=00
*spi_gpecon |=0x0A800000;//GPECON-11(SPISCK0),12(SPIMOSI0),13(SPIMISO0)=10
value=(int)(*spi_gpecon);
printk("spi_gpecon=0x%x\n",value);
/*上拉MISO0和MOSI0,不上拉SCK0*/
*(spi_gpecon+ 2)&=(0xC7FF);
*(spi_gpecon+ 2)|=0x2000;//GPEUP-13=1 GPEUP-11,12=0
value=(int)(*(spi_gpecon+ 2));
printk("spi_gpeup=0x%x\n",value);
/*配置SS0(GPD1),SS1(GPD0),设置为输出口*/
*spi_gpdcon &=0xFFFFFC03;//GPDCON-1(SS1),2(SS2),3(DRY1),4(DRY2)=00
*spi_gpdcon |=0x00000014;//GPDCON-1(SS1),2(SS2),3(DRY1),4(DRY2)=01(OUTPUT),01(OUTPUT),00(INPUT),00(INPUT)
printk("spi_gpdcon=0x%x\n",*spi_gpdcon);
/*置位SS0,SS1,片选信号都无效*/
*(spi_gpdcon+1)|=0x0006;//GPDCON-1(SS1),2(SS2)=1
printk("spi_gpddat=0x%x\n",*(spi_gpdcon+1));
/*上拉SS0,SS1*/
*(spi_gpdcon+2)&=0xFFF9;//GPDUP-1(SS1),2(SS2)=0
printk("spi_gpdup=0x%x\n",*(spi_gpdcon+2));
/*蜂鸣器名叫一声*/
*spi_gpgcon&=0xCFFFF ;
*spi_gpgcon|=0x10000;/*GPG8为output模式*/
printk("spi_gpgcon=0x%x\n",*spi_gpgcon);
*(spi_gpgcon+2)&=0xFEFF;//high//
*(spi_gpgcon+1)|=0x100; /*置高GPG8号管脚*/
printk("spi_gpgdat=0x%x\n",*(spi_gpgcon+1));
msleep(100);
*(spi_gpgcon+1)&=0xEFF; /*置低GPG8号管脚*/
printk("spi_gpgdat=0x%x\n",*(spi_gpgcon+1));
printk("<1>GPE&GPD port init end!\n");
printk("<1>****************************\n");
/*SS1被选中*/
*(spi_gpdcon+1)&=0xFFFD;//GPDDAT-1(SS1)=0
return 0;
}
static int spi_release(struct inode *inode,struct file *filp)
{
/*
MOD_DEC_USE_COUNT;
*/
printk("<1>release\n");
return 0;
}
static ssize_t spi_write(struct file *filp,const char *buf,size_t count,loff_t *f_ops)
{
int i=0,j;
int config;
char string;
//char buffer[20];
char str[20];
char *txStr,*rxStr;
volatile char *spiTxStr,*spiRxStr;
volatile int endSpiTx;
printk("<1>SPI polling TX/RX Test...\n");
printk("<1>Connet SPIMOSI0 into SPIMISO0\n");
struct spi_dev *dev = filp->private_data; /*获得设备结构体指针*/
//spiTxStr=&buffer[0];
endSpiTx=0;
//*spiTxStr=0x8;
//*(spiTxStr+1)=0x18;
//*(spiTxStr+2)=0xc0;
//*(spiTxStr+3)='\0';
spiTxStr="ABCDEFG";
spiRxStr=str;
txStr=(char *)spiTxStr;
rxStr=(char *)spiRxStr;
spi_sppre0=0xFF;//SPI Baud Rate Prescaler Register,Baud Rate=PCLK/2/(Prescaler value+1)
printk("spi_sppre0=0x%x\n",spi_sppre0);
//polling,en-sck,master,low,format A,nomal
spi_spcon0=(0<<6)|(0<<5)|(1<<4)|(1<<3)|(1<<2)|(0<<1)|(0<<0);
//config=(*spi_spcon0);
printk("spi_spcon0=0x%x\n",spi_spcon0);
spi_sppin0=(0<<2)|(0<<0);
//Multi Master error detect disable,reserved,release
//config=(int)(*(spi_spcon0+2));
printk("spi_sppin0=0x%x\n",spi_sppin0);
while(endSpiTx==0)
{
//if(spi_sta1&amt;0x1)
if((spi_spsta0&0x01)==1) //data Tx/Rx ready
{
if(*spiTxStr !='\0')
{
spi_sptdat0=*spiTxStr++;/*传送第一个字节,指针指到下一个字节*/
string=spi_sptdat0;
printk("transmit char=%c\n",string);
}
else
endSpiTx=1;
spi_sptdat0=0xFF;
for(j=0;j<0xFF;j++);
while(!(spi_spsta0&0x1))
printk("no ready!\r\n");
// while((spi_sta1&amt;0x1)==0)
// ;//check Rx ready state
str[i]=spi_sprdat0;
printk("receive char=0x%x\r\n",str[i]);
i++;
}
}
spi_spcon0=(0<<5)|(0<<4)|(1<<2)|(0<<1)|(0<<0);
//Polling,dis-sck,master,low,format A,nomal
spiRxStr[i-1]='\0';//remove last dummy data &amt; attach End of String(Null)
printk("Tx string=%s\n",txStr);
printk("Rx string=%s\n",rxStr);
/*
if(strcmp(rxStr,txStr)==0)
printk("transmit and receive is ok!\n");
else
printk("ERROR!\n");
*/
return 0;
}
/*初始化并注册cdev*/static void spi_setup_cdev(struct spi_dev *dev, int index)
{ int err, devno = MKDEV(spi_major, index);
cdev_init(&dev->cdev, &spi_fops);
dev->cdev.owner = THIS_MODULE; dev->cdev.ops = &spi_fops;
err = cdev_add(&dev->cdev, devno, 1); if (err) printk(KERN_NOTICE "Error %d adding spi %d", err, index);
}
static int __init spi_init(void)
{
int result;
dev_t devno = MKDEV(spi_major, 0);
/* 申请设备号*/ if (spi_major)
result = register_chrdev_region(devno, 1, "spi");
else /* 动态申请设备号 */ { result = alloc_chrdev_region(&devno, 0, 1, "spi");
spi_major = MAJOR(devno);
} if (result < 0) return result; /* 动态申请设备结构体的内存*/ spi_devp = kmalloc(sizeof(struct spi_dev), GFP_KERNEL);
if (!spi_devp) /*申请失败*/
{ result = - ENOMEM; goto fail_malloc; } memset(spi_devp, 0, sizeof(struct spi_dev));
spi_setup_cdev(spi_devp, 0);
#if 0
#ifdef CONFIG_DEVFS_FS
devfs_spi_dir = devfs_mk_dir(NULL,"spi",NULL);
devfs_spiraw = devfs_register(devfs_spi_dir,"0",DEVFS_FL_DEFAULT,spi_major,spi_minor,S_IFCHR | S_IRUSR | S_IWUSR,&spi_fops,NULL);
#endif
#endif
spi_gpdcon = (volatile int *)ioremap (0x56000030,12);
//spi_gpddat = *(volatile unsigned long *)ioremap (0x56000034,4);
//spi_gpdup = *(volatile unsigned long *)ioremap (0x56000038,4);
spi_gpecon = (volatile int *)ioremap (0x56000040,12);
//spi_gpedat = *(volatile unsigned long *)ioremap (0x56000044,4);
//spi_gpeup = *(volatile unsigned long *)ioremap (0x56000048,4);
spi_gpfcon = (volatile int *)ioremap (0x56000050,12);
//spi_gpfdat = *(volatile unsigned long *)ioremap (0x56000054,4);
//spi_gpfup = *(volatile unsigned long *)ioremap (0x56000058,4);
spi_gpgcon =(volatile int *)ioremap (0x56000060,12);
//spi_gpgdat = *(volatile unsigned long *)ioremap (0x56000064,4);
//spi_gpgup = *(volatile unsigned long *)ioremap (0x56000068,4);
spi_spcon0 =* (volatile int *)ioremap(0x59000000,4);
spi_spsta0 = *(volatile int *)ioremap(0x59000004,4);
spi_sppin0 = *(volatile int *)ioremap(0x59000008,4);
spi_sppre0 = *(volatile int *)ioremap(0x5900000c,4);
spi_sptdat0 = *(volatile int *)ioremap(0x59000010,4);
spi_sprdat0 = *(volatile int *)ioremap(0x59000014,4);
printk("Init spi success!\n");
return 0;
printk("<1>initialized!\n");
return 0; fail_malloc: unregister_chrdev_region(devno, 1);
return result;
}
static void __exit spi_exit(void)
{
#if 0
#ifdef CONFIG_DEVFS_FS
devfs_unregister(devfs_spiraw);
devfs_unregister(devfs_spi_dir);
#endif
#endif
unregister_chrdev(spi_major,spi_name);
}
module_init(spi_init);
module_exit(spi_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("HHT<likehht@sohu.com>");
MODULE_DESCRIPTION("SPI_driver for S3C2410");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -