diff options
Diffstat (limited to 'drivers/rtc/rtc-rs5c372.c')
| -rw-r--r-- | drivers/rtc/rtc-rs5c372.c | 116 | 
1 files changed, 37 insertions, 79 deletions
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 90cf0a6ff23..ccf54f06396 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -14,6 +14,7 @@  #include <linux/rtc.h>  #include <linux/bcd.h>  #include <linux/slab.h> +#include <linux/module.h>  #define DRV_VERSION "0.6" @@ -67,6 +68,7 @@  enum rtc_type {  	rtc_undef = 0,  	rtc_r2025sd, +	rtc_r2221tl,  	rtc_rs5c372a,  	rtc_rs5c372b,  	rtc_rv5c386, @@ -75,6 +77,7 @@ enum rtc_type {  static const struct i2c_device_id rs5c372_id[] = {  	{ "r2025sd", rtc_r2025sd }, +	{ "r2221tl", rtc_r2221tl },  	{ "rs5c372a", rtc_rs5c372a },  	{ "rs5c372b", rtc_rs5c372b },  	{ "rv5c386", rtc_rv5c386 }, @@ -103,7 +106,12 @@ static int rs5c_get_regs(struct rs5c372 *rs5c)  {  	struct i2c_client	*client = rs5c->client;  	struct i2c_msg		msgs[] = { -		{ client->addr, I2C_M_RD, sizeof rs5c->buf, rs5c->buf }, +		{ +			.addr = client->addr, +			.flags = I2C_M_RD, +			.len = sizeof(rs5c->buf), +			.buf = rs5c->buf +		},  	};  	/* This implements the third reading method from the datasheet, using @@ -207,7 +215,7 @@ static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)  static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)  {  	struct rs5c372	*rs5c = i2c_get_clientdata(client); -	unsigned char	buf[8]; +	unsigned char	buf[7];  	int		addr;  	dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " @@ -281,10 +289,8 @@ static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm)  	return rs5c372_set_datetime(to_i2c_client(dev), tm);  } -#if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE) -static int -rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) +static int rs5c_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)  {  	struct i2c_client	*client = to_i2c_client(dev);  	struct rs5c372		*rs5c = i2c_get_clientdata(client); @@ -292,49 +298,22 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)  	int			status, addr;  	buf = rs5c->regs[RS5C_REG_CTRL1]; -	switch (cmd) { -	case RTC_UIE_OFF: -	case RTC_UIE_ON: -		/* some 327a modes use a different IRQ pin for 1Hz irqs */ -		if (rs5c->type == rtc_rs5c372a -				&& (buf & RS5C372A_CTRL1_SL1)) -			return -ENOIOCTLCMD; -	case RTC_AIE_OFF: -	case RTC_AIE_ON: -		/* these irq management calls only make sense for chips -		 * which are wired up to an IRQ. -		 */ -		if (!rs5c->has_irq) -			return -ENOIOCTLCMD; -		break; -	default: -		return -ENOIOCTLCMD; -	} + +	if (!rs5c->has_irq) +		return -EINVAL;  	status = rs5c_get_regs(rs5c);  	if (status < 0)  		return status;  	addr = RS5C_ADDR(RS5C_REG_CTRL1); -	switch (cmd) { -	case RTC_AIE_OFF:	/* alarm off */ -		buf &= ~RS5C_CTRL1_AALE; -		break; -	case RTC_AIE_ON:	/* alarm on */ +	if (enabled)  		buf |= RS5C_CTRL1_AALE; -		break; -	case RTC_UIE_OFF:	/* update off */ -		buf &= ~RS5C_CTRL1_CT_MASK; -		break; -	case RTC_UIE_ON:	/* update on */ -		buf &= ~RS5C_CTRL1_CT_MASK; -		buf |= RS5C_CTRL1_CT4; -		break; -	} +	else +		buf &= ~RS5C_CTRL1_AALE;  	if (i2c_smbus_write_byte_data(client, addr, buf) < 0) { -		printk(KERN_WARNING "%s: can't update alarm\n", -			rs5c->rtc->name); +		dev_warn(dev, "can't update alarm\n");  		status = -EIO;  	} else  		rs5c->regs[RS5C_REG_CTRL1] = buf; @@ -342,10 +321,6 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)  	return status;  } -#else -#define	rs5c_rtc_ioctl	NULL -#endif -  /* NOTE:  Since RTC_WKALM_{RD,SET} were originally defined for EFI,   * which only exposes a polled programming interface; and since @@ -407,7 +382,7 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)  		addr = RS5C_ADDR(RS5C_REG_CTRL1);  		buf[0] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE;  		if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) { -			pr_debug("%s: can't disable alarm\n", rs5c->rtc->name); +			dev_dbg(dev, "can't disable alarm\n");  			return -EIO;  		}  		rs5c->regs[RS5C_REG_CTRL1] = buf[0]; @@ -421,7 +396,7 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)  	for (i = 0; i < sizeof(buf); i++) {  		addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i);  		if (i2c_smbus_write_byte_data(client, addr, buf[i]) < 0) { -			pr_debug("%s: can't set alarm time\n", rs5c->rtc->name); +			dev_dbg(dev, "can't set alarm time\n");  			return -EIO;  		}  	} @@ -431,8 +406,7 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)  		addr = RS5C_ADDR(RS5C_REG_CTRL1);  		buf[0] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE;  		if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) -			printk(KERN_WARNING "%s: can't enable alarm\n", -				rs5c->rtc->name); +			dev_warn(dev, "can't enable alarm\n");  		rs5c->regs[RS5C_REG_CTRL1] = buf[0];  	} @@ -461,11 +435,11 @@ static int rs5c372_rtc_proc(struct device *dev, struct seq_file *seq)  static const struct rtc_class_ops rs5c372_rtc_ops = {  	.proc		= rs5c372_rtc_proc, -	.ioctl		= rs5c_rtc_ioctl,  	.read_time	= rs5c372_rtc_read_time,  	.set_time	= rs5c372_rtc_set_time,  	.read_alarm	= rs5c_read_alarm,  	.set_alarm	= rs5c_set_alarm, +	.alarm_irq_enable = rs5c_rtc_alarm_irq_enable,  };  #if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE) @@ -557,6 +531,7 @@ static int rs5c_oscillator_setup(struct rs5c372 *rs5c372)  		rs5c372->time24 = 1;  		break;  	case rtc_r2025sd: +	case rtc_r2221tl:  	case rtc_rv5c386:  	case rtc_rv5c387a:  		buf[0] |= RV5C387_CTRL1_24; @@ -607,7 +582,9 @@ static int rs5c372_probe(struct i2c_client *client,  		}  	} -	if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) { +	rs5c372 = devm_kzalloc(&client->dev, sizeof(struct rs5c372), +				GFP_KERNEL); +	if (!rs5c372) {  		err = -ENOMEM;  		goto exit;  	} @@ -622,7 +599,7 @@ static int rs5c372_probe(struct i2c_client *client,  	err = rs5c_get_regs(rs5c372);  	if (err < 0) -		goto exit_kfree; +		goto exit;  	/* clock may be set for am/pm or 24 hr time */  	switch (rs5c372->type) { @@ -635,6 +612,7 @@ static int rs5c372_probe(struct i2c_client *client,  			rs5c372->time24 = 1;  		break;  	case rtc_r2025sd: +	case rtc_r2221tl:  	case rtc_rv5c386:  	case rtc_rv5c387a:  		if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24) @@ -645,7 +623,7 @@ static int rs5c372_probe(struct i2c_client *client,  		break;  	default:  		dev_err(&client->dev, "unknown RTC type\n"); -		goto exit_kfree; +		goto exit;  	}  	/* if the oscillator lost power and no other software (like @@ -657,7 +635,7 @@ static int rs5c372_probe(struct i2c_client *client,  	err = rs5c_oscillator_setup(rs5c372);  	if (unlikely(err < 0)) {  		dev_err(&client->dev, "setup error\n"); -		goto exit_kfree; +		goto exit;  	}  	if (rs5c372_get_datetime(client, &tm) < 0) @@ -666,6 +644,7 @@ static int rs5c372_probe(struct i2c_client *client,  	dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n",  			({ char *s; switch (rs5c372->type) {  			case rtc_r2025sd:	s = "r2025sd"; break; +			case rtc_r2221tl:	s = "r2221tl"; break;  			case rtc_rs5c372a:	s = "rs5c372a"; break;  			case rtc_rs5c372b:	s = "rs5c372b"; break;  			case rtc_rv5c386:	s = "rv5c386"; break; @@ -676,38 +655,28 @@ static int rs5c372_probe(struct i2c_client *client,  			);  	/* REVISIT use client->irq to register alarm irq ... */ - -	rs5c372->rtc = rtc_device_register(rs5c372_driver.driver.name, -				&client->dev, &rs5c372_rtc_ops, THIS_MODULE); +	rs5c372->rtc = devm_rtc_device_register(&client->dev, +					rs5c372_driver.driver.name, +					&rs5c372_rtc_ops, THIS_MODULE);  	if (IS_ERR(rs5c372->rtc)) {  		err = PTR_ERR(rs5c372->rtc); -		goto exit_kfree; +		goto exit;  	}  	err = rs5c_sysfs_register(&client->dev);  	if (err) -		goto exit_devreg; +		goto exit;  	return 0; -exit_devreg: -	rtc_device_unregister(rs5c372->rtc); - -exit_kfree: -	kfree(rs5c372); -  exit:  	return err;  }  static int rs5c372_remove(struct i2c_client *client)  { -	struct rs5c372 *rs5c372 = i2c_get_clientdata(client); - -	rtc_device_unregister(rs5c372->rtc);  	rs5c_sysfs_unregister(&client->dev); -	kfree(rs5c372);  	return 0;  } @@ -720,18 +689,7 @@ static struct i2c_driver rs5c372_driver = {  	.id_table	= rs5c372_id,  }; -static __init int rs5c372_init(void) -{ -	return i2c_add_driver(&rs5c372_driver); -} - -static __exit void rs5c372_exit(void) -{ -	i2c_del_driver(&rs5c372_driver); -} - -module_init(rs5c372_init); -module_exit(rs5c372_exit); +module_i2c_driver(rs5c372_driver);  MODULE_AUTHOR(  		"Pavel Mironchik <pmironchik@optifacio.net>, "  | 
