diff options
Diffstat (limited to 'drivers/rtc/rtc-m41t80.c')
| -rw-r--r-- | drivers/rtc/rtc-m41t80.c | 104 | 
1 files changed, 45 insertions, 59 deletions
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index a5248aa1abf..7ff7427c2e6 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -66,8 +66,6 @@  #define M41T80_FEATURE_WD	(1 << 3)	/* Extra watchdog resolution */  #define M41T80_FEATURE_SQ_ALT	(1 << 4)	/* RSx bits are in reg 4 */ -#define DRV_VERSION "0.05" -  static DEFINE_MUTEX(m41t80_rtc_mutex);  static const struct i2c_device_id m41t80_id[] = {  	{ "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT }, @@ -80,6 +78,7 @@ static const struct i2c_device_id m41t80_id[] = {  	{ "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },  	{ "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },  	{ "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, +	{ "rv4162", M41T80_FEATURE_SQ | M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT },  	{ }  };  MODULE_DEVICE_TABLE(i2c, m41t80_id); @@ -232,7 +231,7 @@ static ssize_t m41t80_sysfs_show_flags(struct device *dev,  	val = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);  	if (val < 0) -		return -EIO; +		return val;  	return sprintf(buf, "%#x\n", val);  }  static DEVICE_ATTR(flags, S_IRUGO, m41t80_sysfs_show_flags, NULL); @@ -252,7 +251,7 @@ static ssize_t m41t80_sysfs_show_sqwfreq(struct device *dev,  		reg_sqw = M41T80_REG_WDAY;  	val = i2c_smbus_read_byte_data(client, reg_sqw);  	if (val < 0) -		return -EIO; +		return val;  	val = (val >> 4) & 0xf;  	switch (val) {  	case 0: @@ -271,7 +270,7 @@ static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev,  {  	struct i2c_client *client = to_i2c_client(dev);  	struct m41t80_data *clientdata = i2c_get_clientdata(client); -	int almon, sqw, reg_sqw; +	int almon, sqw, reg_sqw, rc;  	int val = simple_strtoul(buf, NULL, 0);  	if (!(clientdata->features & M41T80_FEATURE_SQ)) @@ -291,21 +290,30 @@ static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev,  	/* disable SQW, set SQW frequency & re-enable */  	almon = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);  	if (almon < 0) -		return -EIO; +		return almon;  	reg_sqw = M41T80_REG_SQW;  	if (clientdata->features & M41T80_FEATURE_SQ_ALT)  		reg_sqw = M41T80_REG_WDAY;  	sqw = i2c_smbus_read_byte_data(client, reg_sqw);  	if (sqw < 0) -		return -EIO; +		return sqw;  	sqw = (sqw & 0x0f) | (val << 4); -	if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, -				      almon & ~M41T80_ALMON_SQWE) < 0 || -	    i2c_smbus_write_byte_data(client, reg_sqw, sqw) < 0) -		return -EIO; -	if (val && i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, -					     almon | M41T80_ALMON_SQWE) < 0) -		return -EIO; + +	rc = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, +				      almon & ~M41T80_ALMON_SQWE); +	if (rc < 0) +		return rc; + +	if (val) { +		rc = i2c_smbus_write_byte_data(client, reg_sqw, sqw); +		if (rc < 0) +			return rc; + +		rc = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, +					     almon | M41T80_ALMON_SQWE); +		if (rc <0) +			return rc; +	}  	return count;  }  static DEVICE_ATTR(sqwfreq, S_IRUGO | S_IWUSR, @@ -629,40 +637,28 @@ static int m41t80_probe(struct i2c_client *client,  	struct m41t80_data *clientdata = NULL;  	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C -				     | I2C_FUNC_SMBUS_BYTE_DATA)) { -		rc = -ENODEV; -		goto exit; -	} - -	dev_info(&client->dev, -		 "chip found, driver version " DRV_VERSION "\n"); +				     | I2C_FUNC_SMBUS_BYTE_DATA)) +		return -ENODEV;  	clientdata = devm_kzalloc(&client->dev, sizeof(*clientdata),  				GFP_KERNEL); -	if (!clientdata) { -		rc = -ENOMEM; -		goto exit; -	} +	if (!clientdata) +		return -ENOMEM;  	clientdata->features = id->driver_data;  	i2c_set_clientdata(client, clientdata);  	rtc = devm_rtc_device_register(&client->dev, client->name,  					&m41t80_rtc_ops, THIS_MODULE); -	if (IS_ERR(rtc)) { -		rc = PTR_ERR(rtc); -		rtc = NULL; -		goto exit; -	} +	if (IS_ERR(rtc)) +		return PTR_ERR(rtc);  	clientdata->rtc = rtc;  	/* Make sure HT (Halt Update) bit is cleared */  	rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_HOUR); -	if (rc < 0) -		goto ht_err; -	if (rc & M41T80_ALHOUR_HT) { +	if (rc >= 0 && rc & M41T80_ALHOUR_HT) {  		if (clientdata->features & M41T80_FEATURE_HT) {  			m41t80_get_datetime(client, &tm);  			dev_info(&client->dev, "HT bit was set!\n"); @@ -673,53 +669,44 @@ static int m41t80_probe(struct i2c_client *client,  				 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,  				 tm.tm_min, tm.tm_sec);  		} -		if (i2c_smbus_write_byte_data(client, -					      M41T80_REG_ALARM_HOUR, -					      rc & ~M41T80_ALHOUR_HT) < 0) -			goto ht_err; +		rc = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_HOUR, +					      rc & ~M41T80_ALHOUR_HT); +	} + +	if (rc < 0) { +		dev_err(&client->dev, "Can't clear HT bit\n"); +		return rc;  	}  	/* Make sure ST (stop) bit is cleared */  	rc = i2c_smbus_read_byte_data(client, M41T80_REG_SEC); -	if (rc < 0) -		goto st_err; -	if (rc & M41T80_SEC_ST) { -		if (i2c_smbus_write_byte_data(client, M41T80_REG_SEC, -					      rc & ~M41T80_SEC_ST) < 0) -			goto st_err; +	if (rc >= 0 && rc & M41T80_SEC_ST) +		rc = i2c_smbus_write_byte_data(client, M41T80_REG_SEC, +					      rc & ~M41T80_SEC_ST); +	if (rc < 0) { +		dev_err(&client->dev, "Can't clear ST bit\n"); +		return rc;  	}  	rc = m41t80_sysfs_register(&client->dev);  	if (rc) -		goto exit; +		return rc;  #ifdef CONFIG_RTC_DRV_M41T80_WDT  	if (clientdata->features & M41T80_FEATURE_HT) {  		save_client = client;  		rc = misc_register(&wdt_dev);  		if (rc) -			goto exit; +			return rc;  		rc = register_reboot_notifier(&wdt_notifier);  		if (rc) {  			misc_deregister(&wdt_dev); -			goto exit; +			return rc;  		}  	}  #endif  	return 0; - -st_err: -	rc = -EIO; -	dev_err(&client->dev, "Can't clear ST bit\n"); -	goto exit; -ht_err: -	rc = -EIO; -	dev_err(&client->dev, "Can't clear HT bit\n"); -	goto exit; - -exit: -	return rc;  }  static int m41t80_remove(struct i2c_client *client) @@ -750,4 +737,3 @@ module_i2c_driver(m41t80_driver);  MODULE_AUTHOR("Alexander Bigga <ab@mycable.de>");  MODULE_DESCRIPTION("ST Microelectronics M41T80 series RTC I2C Client Driver");  MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION);  | 
