⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi.c

📁 这是运行在S3C2440+linxu上的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 + -