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

📄 pcf8593-rtc.c

📁 pcf8593实时时钟的驱动实例 Real Time Clock interface for Linux on CPE with FTRTC010
💻 C
📖 第 1 页 / 共 2 页
字号:
	return ret;	get_date_exit_error:	return ret;	}#if 0static void get_time(unsigned char *buf){		int i=0;			I2C_WR(I2C_DR, 0x67);	I2C_WR(I2C_CR, (I2C_ENABLE | I2C_TBEN | I2C_START));	i2c_wait_ack(); 	for(i = 0; i < 2; i++)	{		I2C_WR(I2C_CR, (I2C_ENABLE | I2C_TBEN));		i2c_check_ready();		buf[i] = Read_Endian(I2C_RD(I2C_DR));		//printk(" RTC %dth data = %x\n",i,buf[i]);	}										I2C_WR(I2C_CR, (I2C_ENABLE | I2C_TBEN | I2C_STOP | I2C_ACKNAK));	i2c_check_ready();	buf[i] = Read_Endian(I2C_RD(I2C_DR));	//printk(" RTC %dth data = %x\n",i,buf[i]);}			#endifstatic int set_date(unsigned char *buf){		int ret=-1,data_tmp;	unsigned char data=0; 	down(&pcf8593lock);	if(pcf8593_stop()<0)		goto set_date_error_exit;	if(I2C_Write(PCF8593_WRITE_ADDR,0x02,buf[0])<0)//seconds		goto set_date_error_exit;			if(I2C_Write(PCF8593_WRITE_ADDR,0x03,buf[1])<0)//minutes		goto set_date_error_exit;	data_tmp=I2C_Read(PCF8593_READ_ADDR,0x04)&0xc0;//hour	if(data_tmp==-1)		goto set_date_error_exit;	data=(unsigned char)data_tmp;	data=data|buf[2];	if(I2C_Write(PCF8593_WRITE_ADDR,0x04,data)<0)//hour		goto set_date_error_exit;		data=(buf[5]<<6)|buf[3];	if(I2C_Write(PCF8593_WRITE_ADDR,0x05,data)<0)//year/date		goto set_date_error_exit;		data=(buf[6]<<5)|buf[4];	if(I2C_Write(PCF8593_WRITE_ADDR,0x06,data)<0)//week/month		goto set_date_error_exit;	//start 8593	if(pcf8593_start()<0)		goto set_date_error_exit;		up(&pcf8593lock);	ret=0;	return ret;	set_date_error_exit:	up(&pcf8593lock);	return ret;}#if 0static void time_set_rtc(void){	unsigned char buf[7];	unsigned long current_time = xtime.tv_sec;	buf[0] = current_time / 3600;	buf[1] = current_time / 60;	buf[2] = current_time % 60;		set_time(buf);}#endif#if 0static void set_32kE(void){		I2C_WR(I2C_DR, 0x62);	I2C_WR(I2C_CR, (I2C_ENABLE | I2C_TBEN | I2C_START));	i2c_wait_ack(); 		I2C_WR(I2C_DR, 0x10);			I2C_WR(I2C_CR, (I2C_ENABLE | I2C_TBEN | I2C_STOP));	i2c_wait_ack();	}#endif#if 0static void set_time(unsigned char *buf){		int i=0;			I2C_WR(I2C_DR, 0x66);	I2C_WR(I2C_CR, (I2C_ENABLE | I2C_TBEN | I2C_START));	i2c_wait_ack(); 	for(i = 0; i < 2; i++)	{				I2C_WR(I2C_DR, Write_Endian(buf[i]));		I2C_WR(I2C_CR, (I2C_ENABLE | I2C_TBEN));		/* wait for ack */		i2c_wait_ack();				}	I2C_WR(I2C_DR, Write_Endian(buf[i]));			I2C_WR(I2C_CR, (I2C_ENABLE | I2C_TBEN | I2C_STOP));	i2c_wait_ack();	}static int Write_Alarm_Endian(unsigned char data){	short i=0,tmp=0,tmp_1=0;    	tmp_1 = ((data / 10) << 4) | (data % 10);    	for(i = 0; i < 8; i++)	    tmp |= ((tmp_1 >> i) & 0x1) << (7-i);	return tmp;		}static int Read_Alarm_Endian(unsigned char data){	short i=0,tmp=0,tmp_1=0;    	data &= 0xFE;//disable enable bit    	for(i = 0; i < 8; i++)	    tmp |= ((data >> i) & 0x1) << (7-i);	tmp_1 = ((tmp / 10) << 4) | (tmp % 10);	return tmp_1;		}#endif#if 0static void set_alarm_time(unsigned char *buf,unsigned char w_enable,unsigned char h_enable,unsigned char m_enable){		unsigned char i=0,flag[3];		flag[0]=w_enable;	flag[1]=h_enable;	flag[2]=m_enable;		i2c_write(0x62,0x4);		I2C_WR(I2C_DR, 0x68);	I2C_WR(I2C_CR, (I2C_ENABLE | I2C_TBEN | I2C_START));	i2c_wait_ack(); 	for(i = 0; i < 2; i++)	{				//printk("I2C_WR %d,%x,%x\n",buf[i],Alarm_Endian(buf[i]),Alarm_Endian(buf[i]) + flag[i]);		I2C_WR(I2C_DR, Write_Alarm_Endian(buf[i]) + flag[i]);		I2C_WR(I2C_CR, (I2C_ENABLE | I2C_TBEN));		/* wait for ack */		i2c_wait_ack();				}	//printk("I2C_WR %d,%x,%x\n",buf[i],Alarm_Endian(buf[i]),Alarm_Endian(buf[i]) + flag[i]);	I2C_WR(I2C_DR, Write_Alarm_Endian(buf[i]) + flag[i]);			I2C_WR(I2C_CR, (I2C_ENABLE | I2C_TBEN | I2C_STOP));	i2c_wait_ack();	}#endif#if 0static void get_alarm_time(unsigned char *buf){		int i=0,dd;			I2C_WR(I2C_DR, 0x69);	I2C_WR(I2C_CR, (I2C_ENABLE | I2C_TBEN | I2C_START));	i2c_wait_ack(); #if 0	for(i = 0; i < 2; i++)	{		I2C_WR(I2C_CR, (I2C_ENABLE | I2C_TBEN));		i2c_check_ready();		dd = I2C_RD(I2C_DR);		printk("ttt %x\n",dd);		buf[i] = Read_Alarm_Endian(dd);	}#endif										I2C_WR(I2C_CR, (I2C_ENABLE | I2C_TBEN | I2C_STOP | I2C_ACKNAK));	i2c_check_ready();	dd = I2C_RD(I2C_DR);	//printk("ttt %x\n",dd);	buf[i] = Read_Alarm_Endian(dd);}#endif/* * Converts seconds since 1970-01-01 00:00:00 to Gregorian date. *//*The function modified by hyyeah--9.3.2007 */static int decodetime (struct rtc_time *tval){	unsigned char buf[7];	unsigned short year=0;	unsigned char year_pcf8593=0;			down(&pcf8593lock);		if(get_date(buf)<0){		up(&pcf8593lock);		return -1;	}	up(&pcf8593lock);	tval->tm_sec = BCD_TO_BIN(buf[0]);	tval->tm_min = BCD_TO_BIN(buf[1]);	tval->tm_hour = BCD_TO_BIN(buf[2]);	tval->tm_mday = BCD_TO_BIN(buf[3]);	tval->tm_mon = BCD_TO_BIN(buf[4]);	/* In pcf8593 month range:1~12, but in struct tm or rtc_tm, range: 0~11.	    Note by hyyeah--8.31.2007 */	tval->tm_mon--;			/* Year and wday fields are not BCD code,so don't need transform. 	 *  Get tm_year field of struct time_rtc.	 *  Added by hyyeah--9.3.2007.	 */	if(get_year(&year,&year_pcf8593)<0)		return -1;	if(year_pcf8593!=buf[5]){		//year_change=1;		printk("Warning, the year[%d] has gone !!\n",year);		if(set_year(++year,buf[5])<0)			return -1;			}	//printk("get_current_year :%d\n",get_current_year());	//if(year_change){		//year_cnt++;		//year_change=0;	//}//	tval->tm_year=year+year_cnt-1900;	tval->tm_year=year-1900;			tval->tm_wday = buf[6]; 		#ifdef PCF8593_DEBUG	printk("Date(y/m/d):%d/%d/%d,week:%d, Time(h/m/s):%d/%d/%d\n",		   tval->tm_year,tval->tm_mon,tval->tm_mday,tval->tm_wday,tval->tm_hour,	 	   tval->tm_min,tval->tm_sec);#endif	return 0;}//static unsigned AIE_stat=0;//static unsigned saved_second=0; /* workaround for A320C *//*ijsung:currently only support alarm*/#if 0static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs){	/* wake up waiting process */	wake_up_interruptible(&rtc_wait);	kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);}#endifstatic int rtc_open(struct inode *inode, struct file *file){#if 0//ch by ljn	if (test_and_set_bit (1, &rtc_status))		return -EBUSY;	rtc_irq_data = 0;	return 0;#else	if(pcf8593_checkstatus()>=0)		return  0; 	else		return -EBUSY;#endif}static int rtc_release(struct inode *inode, struct file *file){#if 0//del by ljn	unsigned char buf[7];		spin_lock_irq (&rtc_lock);	set_alarm_time(buf,0,0,0);	spin_unlock_irq (&rtc_lock);	rtc_status = 0;#endif	return 0;}static int rtc_fasync (int fd, struct file *filp, int on){#if 0	return fasync_helper (fd, filp, on, &rtc_async_queue);#else	return 0;#endif}static unsigned int rtc_poll(struct file *file, poll_table *wait){	poll_wait (file, &rtc_wait, wait);	return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM;}static loff_t rtc_llseek(struct file *file, loff_t offset, int origin){	return -ESPIPE;}ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos){#if  0//del by ljn	DECLARE_WAITQUEUE(wait, current);	unsigned long data;	ssize_t retval;	if (count < sizeof(unsigned long))		return -EINVAL;	add_wait_queue(&rtc_wait, &wait);	set_current_state(TASK_INTERRUPTIBLE);	for (;;) {		spin_lock_irq (&rtc_lock);		data = rtc_irq_data;		if (data != 0) {			rtc_irq_data = 0;			break;		}		spin_unlock_irq (&rtc_lock);		if (file->f_flags & O_NONBLOCK) {			retval = -EAGAIN;			goto out;		}		if (signal_pending(current)) {			retval = -ERESTARTSYS;			goto out;		}		schedule();	}	spin_unlock_irq (&rtc_lock);	data -= 0x100;	/* the first IRQ wasn't actually missed */	retval = put_user(data, (unsigned long *)buf);	if (!retval)		retval = sizeof(unsigned long);out:	set_current_state(TASK_RUNNING);	remove_wait_queue(&rtc_wait, &wait);	return retval;#endifreturn 0;}static int rtc_ioctl(struct inode *inode, struct file *file,		     unsigned int cmd, unsigned long arg){	struct rtc_time tm;	switch (cmd) {	case RTC_8593_INIT:		if(pcf8593_init())		{			printk("RTC_8593_INIT okl!\n\r");			return 0;		}		else 		{			printk("RTC_8593_INIT failedl!\n\r");			return -1;		}		case RTC_RD_TIME:		if(decodetime(&tm)<0)			return -1;		break;	case RTC_SET_TIME:		{			unsigned char buf[7];			if (copy_from_user (&tm, (struct rtc_time*)arg, sizeof (tm)))				return -EFAULT;				/* Added by hyyeah--8.28.2007 */			//tm.tm_year += 1900;			if (tm.tm_year < 1970 || (unsigned)tm.tm_mon >=12 ||			    tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] +					(tm.tm_mon == 1 && is_leap(tm.tm_year))) ||			    (unsigned)tm.tm_hour >= 24 ||			    (unsigned)tm.tm_min >= 60 ||			    (unsigned)tm.tm_sec >= 60)				return -EINVAL;			/* In pcf8593 month range:1~12, but in struct tm or rtc_tm, range: 0~11.			    Added by hyyeah--8.31.2007 */			tm.tm_mon++;						buf[0] = BIN_TO_BCD(tm.tm_sec);			buf[1] = BIN_TO_BCD(tm.tm_min);			buf[2] = BIN_TO_BCD(tm.tm_hour)&0x3f;		       buf[3] = BIN_TO_BCD(tm.tm_mday)&0x3f;        		       buf[4] = BIN_TO_BCD(tm.tm_mon)&0x1f;			/* Added by hyyeah-8.28.2007 */			buf[5] = tm.tm_year&0x3;			if(set_year((unsigned short)tm.tm_year,buf[5])<0)				return -1;								       buf[6] = tm.tm_wday&0x7;				if(set_date(buf)<0)				return -1;						return 0;		}		#if 0	case RTC_AIE_OFF:		spin_lock_irq(&rtc_lock);		//AIE_stat=0;		//set_alarm_time(buf,0,0,0);		spin_unlock_irq(&rtc_lock);		return 0;	case RTC_AIE_ON:		spin_lock_irq(&rtc_lock);		//get_alarm_time(buf);		//set_alarm_time(buf,1,1,1);		//rtc_irq_data = 0;		spin_unlock_irq(&rtc_lock);		return 0;	case RTC_ALM_READ:		{				decodetime(&tm);		}		break;	case RTC_ALM_SET:		if (copy_from_user (&tm2, (struct rtc_time*)arg, sizeof (tm2)))			return -EFAULT;		buf[0]=tm2.tm_wday;		buf[1]=tm2.tm_hour;		buf[2]=tm2.tm_min;		set_alarm_time(buf,1,1,1);		return 0;	case RTC_IRQP_READ:		return put_user(rtc_freq, (unsigned long *)arg);	case RTC_IRQP_SET:		if (arg != 1) return -EINVAL;		return 0;	case RTC_EPOCH_READ:		return put_user (1970, (unsigned long *)arg);#endif	default:		return -EINVAL;	}	return copy_to_user ((void *)arg, &tm, sizeof (tm)) ? -EFAULT : 0;}static struct file_operations rtc_fops = {	owner:		THIS_MODULE,	llseek:		rtc_llseek,	read:		rtc_read,	poll:		       rtc_poll,	ioctl:		rtc_ioctl,	open:		rtc_open,	release:	       rtc_release,	fasync:		rtc_fasync,};static struct miscdevice ftrtc010rtc_miscdev = {	RTC_MINOR,	"rtc",	&rtc_fops};#if 0static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){	unsigned alarm_time;	unsigned char buf[7];		char *p = page;	int len;	struct rtc_time tm;	decodetime(&tm);	//printk("RTC ... %d\n",xtime.tv_sec);		p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n"			"rtc_date\t: %04d-%02d-%02d\n"			"rtc_epoch\t: %04d\n",			tm.tm_hour, tm.tm_min, tm.tm_sec,			tm.tm_year + 2000, tm.tm_mon, tm.tm_mday, 2000);	get_alarm_time(buf);//	p += sprintf(p, "alrm_time\t: %2dth day of week day\n"//			"alrm_date\t: N/A for FIC8120\n",//			tm.tm_wday);	p += sprintf(p, "alrm_time\t: Not be Set\n"			"alrm_date\t: Not be Set\n");	p += sprintf(p, "alarm_IRQ\t: %s\n", AIE_stat ? "yes" : "no" );	len = (p - page) - off;	if (len < 0)		len = 0;	*eof = (len <= count) ? 1 : 0;	*start = page + off;	return len;}#endifstatic int __init pcf8593rtc_init(void){	int ret;	if((ret=misc_register (&ftrtc010rtc_miscdev))<0)	{		printk("Can't register rtc device:PCF8593!\n");		return ret;	}#if 0//del by ljn	create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL);        cpe_int_set_irq(IRQ_RTCALARM, EDGE, H_ACTIVE);	ret = request_irq (IRQ_RTCALARM, rtc_interrupt, SA_INTERRUPT, "rtc Alrm", NULL);	if (ret) {		printk(KERN_ERR "rtc: IRQ %d already in use.\n", 17);		goto IRQ_RTCAlrm_failed;	}#endif#if 0	if(pcf8593_start()<0)	{		printk("Real Time Clock driver init failed!\n");			}#endif	init_MUTEX(&pcf8593lock);	/* Added by hyyeah for test--8.27.2007 *///if(pcf8593_init()<0)	//printk("Real Time Clock driver init failed!\n");		#ifdef DEBUG_KERNEL_BOOT_MSG	printk("Real time clock pcf8593 driver init ok!\n");	#else   printk(BOOT_SYM);#endif	//set_rtc = time_set_rtc;	return 0;#if 0IRQ_RTCAlrm_failed:	remove_proc_entry ("driver/rtc", NULL);	misc_deregister (&ftrtc010rtc_miscdev);	return ret;#endif	}static void __exit pcf8593rtc_exit(void){	/* Masked by hyyeah--8.24.2007 */	//remove_proc_entry ("driver/rtc", NULL);	misc_deregister (&ftrtc010rtc_miscdev);}module_init(pcf8593rtc_init);module_exit(pcf8593rtc_exit);MODULE_AUTHOR("I-Jui Sung <ijsung@faraday-tech.com>");MODULE_DESCRIPTION("CPE FTRTC010 Realtime Clock Driver (RTC)");MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;

⌨️ 快捷键说明

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