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

📄 ds1337.c

📁 实时时钟处理芯片ds1337驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/drivers/i2c/chips/ds1337.c * * Driver for Dallas Semiconductor DS1337 and DS1339 real time clock chip */#include <linux/module.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/i2c.h>#include <linux/i2c-sensor.h>#include <linux/string.h>#include <linux/rtc.h>		/* get the user-level API */#include <linux/bcd.h>#include <linux/list.h>#include <linux/interrupt.h>#include <asm/arch/io_registers.h>#include <asm/irq.h>#include <asm/arch/gio.h>#include <asm/arch/gios.h>#include <asm/arch/irqs.h>#include <linux/fb.h>#include <asm/uaccess.h>#include "ds1337.h"#undef dev_dbg #undef dev_err#define dev_printk(level, dev, format, arg...)	\	printk(level "%s %s: " format , (dev)->driver->name , (dev)->bus_id , ## arg)#define dev_dbg(dev, format, arg...)		\	dev_printk(KERN_DEBUG , dev , format , ## arg)#define dev_err(dev, format, arg...)		\	dev_printk(KERN_DEBUG , dev , format , ## arg)#define MOD_DESC "MAXIM DS1337 I2C serial real-time clock"MODULE_DESCRIPTION(MOD_DESC);MODULE_AUTHOR("Envision");MODULE_LICENSE("GPL");//Variables declarestatic u32 ds1337_opened = 0;static const char * pname = "DS1337:";/* * Functions declaration */static unsigned short normal_i2c[] = { 0x68,0x69, I2C_CLIENT_END };static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };//I2C_CLIENT_INSMOD;SENSORS_INSMOD_1(ds1337);static int ds1337_attach_adapter(struct i2c_adapter *adapter);static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind);static void ds1337_init_client(struct i2c_client *client);static int ds1337_detach_client(struct i2c_client *client);static irqreturn_t ds1337_isr(int irq, void *data, struct pt_regs *regs);/* * Driver data (common to all clients) */static struct i2c_driver ds1337_driver = {	.owner		= THIS_MODULE,	.name		= "ds1337",	.flags		= I2C_DF_NOTIFY,	.attach_adapter	= ds1337_attach_adapter,	.detach_client	= ds1337_detach_client,};/* * Client data (each client gets its own) */struct ds1337_data {	struct i2c_client client;	struct list_head list;};static struct i2c_client *ds1337_client; /* * Internal variables */static LIST_HEAD(ds1337_clients);//interrupt service program#define DS1337_DISABLE_IRQS	\		outw(inw(IO_GIO_IRQPORT) & ~(1 << GIO_RTC_INTA), IO_GIO_IRQPORT);#define DS1337_ENABLE_IRQS		\		outw(inw(IO_GIO_IRQPORT) |(1 << GIO_RTC_INTA), IO_GIO_IRQPORT);static irqreturn_t ds1337_isr(int irq, void *data, struct pt_regs *regs){	DS1337_DISABLE_IRQS;    //interrupt service program   printk("**********************************************\n");   printk("**********************************************\n");   printk("**********************************************\n");	DS1337_ENABLE_IRQS;	return IRQ_HANDLED;}static inline int ds1337_read(struct i2c_client *client, u8 reg, u8 *value){	s32 tmp = i2c_smbus_read_byte_data(client, reg);	if (tmp < 0)		return -EIO;	*value = tmp;	return 0;}static int ds1337_attach_adapter(struct i2c_adapter *adapter){    	return i2c_detect(adapter, &addr_data, ds1337_detect);}/* * The following function does more than just detection. If detection * succeeds, it also registers the new chip. */static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind){    struct i2c_client *new_client;	struct ds1337_data *data;	int err = 0;	const char *name = "";    /*	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |				     I2C_FUNC_I2C))		goto exit;*/    if (!(data = kmalloc(sizeof(struct ds1337_data), GFP_KERNEL))) {		err = -ENOMEM;		goto exit;	}    	memset(data, 0, sizeof(struct ds1337_data));	INIT_LIST_HEAD(&data->list);	/* The common I2C client data is placed right before the	 * DS1337-specific data. 	 */	new_client = &data->client;	i2c_set_clientdata(new_client, data);	new_client->addr = address;	new_client->adapter = adapter;	new_client->driver = &ds1337_driver;	new_client->flags = 0;    /*	 * Now we do the remaining detection. A negative kind means that	 * the driver was loaded with no force parameter (default), so we	 * must both detect and identify the chip. A zero kind means that	 * the driver was loaded with the force parameter, the detection	 * step shall be skipped. A positive kind means that the driver	 * was loaded with the force parameter and a given kind of chip is	 * requested, so both the detection and the identification steps	 * are skipped.	 *	 * For detection, we read registers that are most likely to cause	 * detection failure, i.e. those that have more bits with fixed	 * or reserved values.	 */	/* Default to an DS1337 if forced */	if (kind == 0)		kind = ds1337;	if (kind < 0) {		/* detection and identification */		u8 data;		/* Check that status register bits 6-2 are zero */		if ((ds1337_read(new_client, DS1337_REG_STATUS, &data) < 0) ||		    (data & 0x7c))			goto exit_free;		/* Check for a valid day register value */if ((ds1337_read(new_client, DS1337_REG_DAY, &data) < 0) ||		    (data == 0) || (data & 0xf8))			goto exit_free;		/* Check for a valid date register value */		if ((ds1337_read(new_client, DS1337_REG_DATE, &data) < 0) ||		    (data == 0) || (data & 0xc0) || ((data & 0x0f) > 9) ||		    (data >= 0x32))			goto exit_free;		/* Check for a valid month register value */		if ((ds1337_read(new_client, DS1337_REG_MONTH, &data) < 0) ||		    (data == 0) || (data & 0x60) || ((data & 0x0f) > 9) ||		    ((data >= 0x13) && (data <= 0x19)))			goto exit_free;		/* Check that control register bits 6-5 are zero */		if ((ds1337_read(new_client, DS1337_REG_CONTROL, &data) < 0) ||		    (data & 0x60))			goto exit_free;		kind = ds1337;	}    if (kind == ds1337)		name = "ds1337";	/* We can fill in the remaining client fields */	strlcpy(new_client->name, name, I2C_NAME_SIZE);	/* Tell the I2C layer a new client has arrived */	if ((err = i2c_attach_client(new_client)))		goto exit_free;    	/* Initialize the DS1337 chip */    ds1337_init_client(new_client);     	/* Add client to local list */	list_add(&data->list, &ds1337_clients);    ds1337_client = new_client;	return 0;exit_free:	kfree(data);exit:	return err;}static void ds1337_init_client(struct i2c_client *client){	s32 val;	/* Ensure that device is set in 24-hour mode */	val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR); //   printk("DS1337_REG_HOUR = 0x%x.\n", val);	if ((val >= 0) && (val & (1 << 6)))		i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,					  val & 0x3f);//initial values (for date-time register are 0,0,0,1,1,1,0)//initial alarms values are uncertain./*	u8 buf[7];		memset( buf, 0, sizeof(buf));	ds1337_read( ds1337_client, DS1337_REG_SECOND, &buf[0]);	ds1337_read( ds1337_client, DS1337_REG_MINUTE, &buf[1]);	ds1337_read( ds1337_client, DS1337_REG_HOUR, &buf[2]);	ds1337_read( ds1337_client, DS1337_REG_DAY, &buf[3]);	ds1337_read( ds1337_client, DS1337_REG_DATE, &buf[4]);	ds1337_read( ds1337_client, DS1337_REG_MONTH, &buf[5]);	ds1337_read( ds1337_client, DS1337_REG_YEAR, &buf[6]);printk(" %02x %02x %02x %02x %02x %02x %02x\n",		 buf[0], buf[1], buf[2], buf[3],		buf[4], buf[5], buf[6]);  */ 	//init the registers   //the initial time and date are 2005,01,01,00:00/*	i2c_smbus_write_byte_data(client,  DS1337_REG_SECOND, 0x00);	i2c_smbus_write_byte_data(client,  DS1337_REG_MINUTE, 0x00);	i2c_smbus_write_byte_data(client,  DS1337_REG_HOUR, 0x00);    i2c_smbus_write_byte_data(client,  DS1337_REG_DAY, 0x06);	i2c_smbus_write_byte_data(client,  DS1337_REG_DATE, 0x01);	i2c_smbus_write_byte_data(client,  DS1337_REG_MONTH, 0x01);	i2c_smbus_write_byte_data(client,  DS1337_REG_YEAR, 0x05);*/	//the alarm 1	//match day,hour,min,sec,the alarm produces INT/*	i2c_smbus_write_byte_data(client,  DS1337_REG_A1M_SECOND, 0x00);    i2c_smbus_write_byte_data(client,  DS1337_REG_A1M_MINUTE, 0x00);	i2c_smbus_write_byte_data(client,  DS1337_REG_A1M_HOUR, 0x00);    //the day matches month	i2c_smbus_write_byte_data(client,  DS1337_REG_A1M_DAY_DATE, 0x00);	//the alarm2	//match day,hour,min,the alarm produces INT	i2c_smbus_write_byte_data(client,  DS1337_REG_A2M_MINUTE, 0x00);	i2c_smbus_write_byte_data(client,  DS1337_REG_A2M_HOUR, 0x00);    //the day matches month	i2c_smbus_write_byte_data(client,  DS1337_REG_A2M_DAY_DATE, 0x00);	//control register	//OScillator starts,32.768khz,alarm1 matches ~INTA,alarm2 matchs SQW/~INTB	//both alarms do not initiate     i2c_smbus_write_byte_data(client,  DS1337_REG_CONTROL, RS2| RS1   );//initial status register,in order to use alarm function correctly     i2c_smbus_write_byte_data(client,  DS1337_REG_STATUS, 0   );*/  }static int ds1337_detach_client(struct i2c_client *client){    	int err;	struct ds1337_data *data = i2c_get_clientdata(client);	if ((err = i2c_detach_client(client))) {		dev_err(&client->dev, "Client deregistration failed, "			"client not detached.\n");		return err;	}	list_del(&data->list);	kfree(data);	return 0;}/* Start File Ops */static int ds1337_open(struct inode * inode, struct file * file){    	if (ds1337_opened) return -EBUSY;    file->private_data = (void*)ds1337_client;    ds1337_opened = 1;    return 0;}static int ds1337_release(struct inode * inode, struct file * file){   	if (!ds1337_opened) return -ERESTARTSYS;    ds1337_opened = 0;    file->private_data = NULL;    return 0;}static int ds1337_ioctl(struct inode * inode, struct file * file,unsigned int cmd, unsigned long arg){    int arg_size, ret = 0;    if (_IOC_TYPE(cmd) != DS1337_IOC_MAGIC)        return -EINVAL;    if (_IOC_NR(cmd) > DS1337_IOC_MAXNR)        return -EINVAL;    arg_size = _IOC_SIZE(cmd);    if (_IOC_DIR(cmd) & _IOC_READ)        ret = !access_ok(VERIFY_WRITE, (void *)arg, arg_size);    else if (_IOC_DIR(cmd) & _IOC_WRITE)        ret = !access_ok(VERIFY_READ, (void *)arg, arg_size);    if (ret) return ret;    switch (cmd)	{	    case DS1337_SET_TIME:		{            u8 buf[7];            struct date_time dt;         //   u8 hour;			copy_from_user(&dt, (void*) arg, sizeof(struct date_time));		              //check parameters		   if(DS1337_REG_SECOND & 0x80)           {			   printk("the second register is invalid\n");			   goto out;		   }		   if(DS1337_REG_MINUTE & 0x80)           {			   printk("the minute register is invalid\n");			   goto out;		   }           if(DS1337_REG_HOUR & 0x80)           {			   printk("the hour register is invalid\n");			   goto out;		   }		   if(DS1337_REG_DATE & 0xf8)           {			   printk("the date register is invalid\n");			   goto out;		   }           if(DS1337_REG_DAY & 0xc0)           {			   printk("the day register is invalid\n");			   goto out;		   }           if(DS1337_REG_MONTH & 0x60)           {			   printk("the MONTH register is invalid\n");			   goto out;		   }			buf[0] = BIN2BCD(dt.tm_sec);            buf[1] = BIN2BCD(dt.tm_min);            buf[2] = BIN2BCD(dt.tm_hour);       //     ds1337_read( ds1337_client, DS1337_REG_HOUR, &hour);            buf[3] = BIN2BCD(dt.tm_wday);	        buf[4] = BIN2BCD(dt.tm_mday);	        buf[5] = BIN2BCD(dt.tm_mon);            if(dt.tm_year >=100)		    {				   buf[5]|=(1<<7);				   dt.tm_year -=100;			}			buf[6] = BIN2BCD(dt.tm_year);                       //write registers		   i2c_smbus_write_byte_data(ds1337_client,  DS1337_REG_SECOND, buf[0]);	       i2c_smbus_write_byte_data(ds1337_client,  DS1337_REG_MINUTE, buf[1]);	       i2c_smbus_write_byte_data(ds1337_client,  DS1337_REG_HOUR, buf[2]);           i2c_smbus_write_byte_data(ds1337_client,  DS1337_REG_DAY, buf[3]);	       i2c_smbus_write_byte_data(ds1337_client,  DS1337_REG_DATE, buf[4]);

⌨️ 快捷键说明

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