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

📄 i2c_ds1337.c

📁 fresscale MX21 RTC实时种编程
💻 C
字号:
/******************************************************************************** File name :  ds1337.c**     ** Description :**      ds1337(Real Time clock) ** Usage :**      DS1337 Device Driver file for iMX21 Platform**  ** License : **      This program is free software; you can redistribute it and/or modify**      it under the terms of the GNU General Public License version 2 as**      published by the Free Software Foundation** Note: tm_year: from 2000;*******************************************************************************/#include <linux/kernel.h>#include <linux/module.h>#include <linux/compatmac.h>#include <linux/hdreg.h>#include <linux/vmalloc.h>#include <linux/fs.h>#include <linux/module.h>#include <linux/blkpg.h>#include <linux/i2c.h>#include <linux/i2c-algo-bit.h>#include <linux/i2c-id.h>#include <linux/slab.h>#include <asm/io.h>#include <linux/mm.h>#include <linux/wrapper.h>#include <asm/dma.h>#include <linux/miscdevice.h>#include <asm/arch/mx2.h>#include <linux/rtc.h>#include <linux/init.h>#define	 UINT8	unsigned char#define  SINT32	int#define  IIC_ADDR     0xd0#define  SCL         (1 << 27)#define  SDA         (1 << 18)#define DS1337_NAME		"ds1337"#define DS1337_VERSION	"version 0.1"#define DS1337_MAJOR	251#define RTC_SEC    0x00#define RTC_MIN    0x01#define RTC_HOUR   0x02#define RTC_DAY    0x03#define RTC_DATE   0x04#define RTC_MONTH  0x05#define RTC_YEAR   0x06#define RTC_CTRL   0x0e#define RTC_STATUS 0x0fstatic unsigned char days_in_mo[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};void delay500ns(){	int i;	for(i=0;i<100;i++);}void delay1us(){	delay500ns();	delay500ns();}void delay2us(){	delay1us();	delay1us();}void delay5us(){	delay2us();	delay2us();	delay1us();}void delay8us(){	delay5us();	delay2us();	delay1us();}void delay10us(){	delay5us();	delay5us();}SINT32 set_sda_input(){	/* 	 * PE3 : SDA	 * PE4 : SCL	 */	_reg_GPIO_DDIR(GPIOC) &= ~SDA;		return 0;}SINT32 set_sda_output(){		/* 	 * PE3 : SDA	 * PE4 : SCL	 */	_reg_GPIO_DDIR(GPIOC) |= SDA;		return 0;}SINT32 set_sda_value(UINT8 flag){		/* 	 * PE3 : SDA	 * PE4 : SCL	 */	 	if(flag)		_reg_GPIO_DR(GPIOC) |= SDA;	else		_reg_GPIO_DR(GPIOC) &= ~SDA;		return 0;}SINT32 set_scl_high(){		/* 	 * PE3 : SDA	 * PE4 : SCL	 */	_reg_GPIO_DR(GPIOB) |= SCL;		return 0;}SINT32 set_scl_low(){		/* 	 * PA15 : SDA	 * PA16 : SCL	 */	_reg_GPIO_DR(GPIOB) &= ~SCL;		return 0;}/* Read sda status */UINT8 get_sda_value(){	if(_reg_GPIO_SSR(GPIOC) & SDA)		return 0x01;	else		return 0x00;}/* SCCB write */	void sccb_write(UINT8 reg, UINT8 data){	int i;	UINT8 addr;			addr = IIC_ADDR;		set_sda_value(1);	set_scl_high();		delay10us();	set_sda_value(0);    // Issue start command		/* Send ID address */	for(i=0;i<8;i++)	{		delay10us();		set_scl_low();    // First clock start			delay500ns();		set_sda_value((addr >> (7-i)) & 0x01);			delay10us();		set_scl_high();   	}		delay10us();	set_scl_low();    // The Ninth clock start		delay1us();	set_sda_input();		delay8us();	set_scl_high();   // Dont't care bit		delay10us();	set_scl_low();		delay2us();	set_sda_output();		/* Send sub address */	for(i=0;i<8;i++)	{		delay500ns();		set_sda_value((reg >> (7-i)) & 0x01);			delay10us();		set_scl_high();   				delay10us();		set_scl_low();   	}		delay1us();	set_sda_input();		delay8us();	set_scl_high();   // Dont't care bit		delay10us();	set_scl_low();		delay2us();	set_sda_output();		/* Send sub address */	for(i=0;i<8;i++)	{					delay500ns();		set_sda_value((data >> (7-i)) & 0x01);			delay10us();		set_scl_high();   				delay10us();		set_scl_low();   	}		delay1us();	set_sda_input();		delay8us();	set_scl_high();   // Dont't care bit		delay10us();	set_scl_low();		delay2us();	set_sda_output();	set_sda_value(0);		delay10us();	set_scl_high(); 		delay10us();	set_sda_value(1);  // Stop		return;}/* SCCB read */	void sccb_read(UINT8 reg, UINT8 *data){	int i;	UINT8 addr, ret;		ret = 0;	*data = 0;		/* 2-phases write */		addr = IIC_ADDR;		set_sda_value(1);	set_scl_high();		delay10us();	set_sda_value(0);    // Issue start command		/* Send ID address */	for(i=0;i<8;i++)	{		delay10us();		set_scl_low();    // First clock start			delay500ns();		set_sda_value((addr >> (7-i)) & 0x01);			delay10us();		set_scl_high();   	}		delay10us();	set_scl_low();    // The Ninth clock start		delay1us();	set_sda_input();		delay8us();	set_scl_high();   // Dont't care bit		delay10us();	set_scl_low();		delay2us();	set_sda_output();		/* Send sub address */	for(i=0;i<8;i++)	{		delay500ns();		set_sda_value((reg >> (7-i)) & 0x01);			delay10us();		set_scl_high();   				delay10us();		set_scl_low();   	}		delay1us();	set_sda_input();		delay8us();	set_scl_high();   // Dont't care bit		delay10us();	set_scl_low();		delay2us();	set_sda_output();	set_sda_value(0);		delay10us();	set_scl_high(); 		delay10us();	set_sda_value(1);  // Stop 2-phases write		/****************************************************************/	/* 2-phases read */		addr = IIC_ADDR + 1;		set_sda_value(1);	set_scl_high();		delay10us();	set_sda_value(0);    // Issue start command		/* Send ID address */	for(i=0;i<8;i++)	{		delay10us();		set_scl_low();    // First clock start			delay500ns();		set_sda_value((addr >> (7-i)) & 0x01);			delay10us();		set_scl_high();   	}		delay10us();	set_scl_low();    // The Ninth clock start		delay1us();	set_sda_input();		delay8us();	set_scl_high();   // Dont't care bit	delay10us();		for(i=0;i<8;i++)	{		set_scl_low();		delay10us();		set_scl_high();			delay5us();		ret = get_sda_value();		*data |= (ret << (7-i));		delay5us();	}		set_scl_low();    // The Ninth clock start	delay1us();	set_sda_output();		delay500ns();	set_sda_value(1);		delay8us();	set_scl_high();   // Dont't care bit		delay10us();	set_scl_low();		delay5us();	set_sda_value(0);			delay10us();	set_scl_high(); 		delay10us();	set_sda_value(1);  // Stop 2-phases write}/* Initialize SCCB signal, simulation SCCB timing by GPIO */SINT32 sccb_init(){	/* 	 * PA15 : SDA	 * PA16 : SCL	 */	_reg_GPIO_GIUS(GPIOC) |= SDA;	_reg_GPIO_GIUS(GPIOB) |= SCL;		_reg_GPIO_OCR2(GPIOB) |= 0x00C00000;	_reg_GPIO_OCR2(GPIOC) |= 0x30;			_reg_GPIO_DDIR(GPIOC) |= SDA;	_reg_GPIO_DDIR(GPIOB) |= SCL;		set_sda_value(1);	set_scl_high();		return 0;}	///////////////////////////////////////////////////////////////////////////Read Regstatic unsigned char RtcReadReg(unsigned char addr){	unsigned char data;	sccb_read(addr, &data);	return data;}//Write Regstatic void RtcWriteReg(unsigned char addr,unsigned char data){	sccb_write(addr, data);}static unsigned char bin2int(unsigned char data){	return ((data&0x0f)+((data&0xf0)>>4)*10);}static unsigned char int2bin(unsigned char data){	return ((data%10)+((data/10)*16));}static void ds1337_rtc_init(void){	int ii = 0;	int jj = 0;	sccb_init();			//init i2c	while(0){		set_scl_high();		set_sda_value(1);printk("in loop,high\n");		delay10us();		set_scl_low();		set_sda_value(0);printk("in loop,low\n");		delay10us();		jj++;	}//	for(ii = 0; ii <= 0x0f; ii++){  //init ds1337 register all zero//		RtcWriteReg(ii, 0x0);//	}}static int ds1337_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	struct rtc_time wtime;	struct rtc_time rtc_tm;	unsigned char mon, mday, hrs, min, sec, leap_yr;	unsigned int yrs;//	printk("cmd = %d\n", cmd);	switch (cmd) {	case RTC_RD_TIME:///Read Date	{		wtime.tm_sec = bin2int(RtcReadReg(RTC_SEC));		wtime.tm_min = bin2int(RtcReadReg(RTC_MIN));		wtime.tm_hour = bin2int(RtcReadReg(RTC_HOUR));		wtime.tm_mday = bin2int(RtcReadReg(RTC_DATE));		wtime.tm_mon = bin2int(RtcReadReg(RTC_MONTH));		wtime.tm_year = bin2int(RtcReadReg(RTC_YEAR)); //from 970/*		printk("1 read: year = %d\n", wtime.tm_year);		printk("1 read: mon  = %d\n", wtime.tm_mon); 		printk("1 read: mday = %d\n", wtime.tm_mday);		printk("1 read: hour = %d\n", wtime.tm_hour);		printk("1 read: min  = %d\n", wtime.tm_min); 		printk("1 read: sec  = %d\n", wtime.tm_sec); */		break;	}	case RTC_SET_TIME:///Set Date	{		if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))			return -EFAULT;		yrs = rtc_tm.tm_year + 2000;		mon = rtc_tm.tm_mon;		mday = rtc_tm.tm_mday;		hrs = rtc_tm.tm_hour;		min = rtc_tm.tm_min;		sec = rtc_tm.tm_sec;				if (yrs < 2000)			return -EINVAL;					leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));				if ((mon > 12) || (mday == 0))			return -EINVAL;					if (mday > (days_in_mo[mon] + ((mon == 2) && leap_yr)))			return -EINVAL;					if ((hrs >= 24) || (min >= 60) || (sec >= 60))			return -EINVAL;		RtcWriteReg(RTC_YEAR, int2bin(rtc_tm.tm_year));		RtcWriteReg(RTC_MONTH, int2bin(rtc_tm.tm_mon));		RtcWriteReg(RTC_DATE, int2bin(rtc_tm.tm_mday));		RtcWriteReg(RTC_HOUR, int2bin(rtc_tm.tm_hour));		RtcWriteReg(RTC_MIN, int2bin(rtc_tm.tm_min));		RtcWriteReg(RTC_SEC, int2bin(rtc_tm.tm_sec));		return 0;	}	default:		return -EINVAL;	}	return copy_to_user((void *)arg, &wtime, sizeof(struct rtc_time)) ? -EFAULT : 0;}static int ds1337_open(struct inode *minode, struct file *mfile){//	printk("ds1337 open\n");	MOD_INC_USE_COUNT;	return 0;}static int ds1337_release(struct inode *minode, struct file *mfile){   	MOD_DEC_USE_COUNT;	return 0;}static struct file_operations device_fops = {	owner:      THIS_MODULE,	open:		ds1337_open,	release:	ds1337_release,	ioctl:		ds1337_ioctl,};static devfs_handle_t g_devfs_handle;static int g_rtc_major;static __init int ds1337_init(void){	int result;	/* register our character device */	result = devfs_register_chrdev(0, "ds1337", &device_fops);	if ( result < 0 )	{	        printk("ds1337 driver: Unable to register driver\n");	        return -ENODEV;	}	g_devfs_handle = devfs_register(NULL, "ds1337", DEVFS_FL_DEFAULT,	                              result, 0,	                              S_IFCHR | S_IRUSR | S_IWUSR,	                              &device_fops, NULL);    printk("make node for ds1337 with 'mknod ds1337 c %d 0'\n", result);	g_rtc_major = result;  	ds1337_rtc_init();	//register_chrdev(DS1337_MAJOR, DS1337_NAME, &device_fops);	//printk("%s %s initialized.\n", DS1337_NAME, DS1337_VERSION);    return 0;}static __exit void ds1337_exit(void){      if(g_rtc_major>0)      {          devfs_unregister_chrdev(g_rtc_major, DS1337_NAME);          devfs_unregister(g_devfs_handle);      }//	unregister_chrdev(DS1337_MAJOR, DS1337_NAME);//	printk("%s unregisterd.\n", DS1337_NAME);}module_init(ds1337_init);module_exit(ds1337_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("pyl");/*vim:ts=4*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -