diff options
Diffstat (limited to 'drivers/rtc')
37 files changed, 222 insertions, 66 deletions
| diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 5faafb4aa55c..cca650b2e0b9 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -274,10 +274,9 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)  			return err;  		/* full-function RTCs won't have such missing fields */ -		if (rtc_valid_tm(&alarm->time) == 0) { -			rtc_add_offset(rtc, &alarm->time); -			return 0; -		} +		err = rtc_valid_tm(&alarm->time); +		if (!err) +			goto done;  		/* get the "after" timestamp, to detect wrapped fields */  		err = rtc_read_time(rtc, &now); @@ -379,6 +378,8 @@ done:  	if (err && alarm->enabled)  		dev_warn(&rtc->dev, "invalid alarm value: %ptR\n",  			 &alarm->time); +	else +		rtc_add_offset(rtc, &alarm->time);  	return err;  } diff --git a/drivers/rtc/lib_test.c b/drivers/rtc/lib_test.c index 3893a202e9ea..c30c759662e3 100644 --- a/drivers/rtc/lib_test.c +++ b/drivers/rtc/lib_test.c @@ -97,4 +97,5 @@ static struct kunit_suite rtc_lib_test_suite = {  kunit_test_suite(rtc_lib_test_suite); +MODULE_DESCRIPTION("KUnit test for RTC lib functions");  MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c index 100062001831..684f9898d768 100644 --- a/drivers/rtc/rtc-ab-b5ze-s3.c +++ b/drivers/rtc/rtc-ab-b5ze-s3.c @@ -933,7 +933,7 @@ MODULE_DEVICE_TABLE(of, abb5zes3_dt_match);  #endif  static const struct i2c_device_id abb5zes3_id[] = { -	{ "abb5zes3", 0 }, +	{ "abb5zes3" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, abb5zes3_id); diff --git a/drivers/rtc/rtc-ab-eoz9.c b/drivers/rtc/rtc-ab-eoz9.c index 04e1b8e93bc1..02f7d0711287 100644 --- a/drivers/rtc/rtc-ab-eoz9.c +++ b/drivers/rtc/rtc-ab-eoz9.c @@ -575,7 +575,7 @@ MODULE_DEVICE_TABLE(of, abeoz9_dt_match);  #endif  static const struct i2c_device_id abeoz9_id[] = { -	{ "abeoz9", 0 }, +	{ "abeoz9" },  	{ }  }; diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c index fde2b8054c2e..1298962402ff 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -705,14 +705,18 @@ static int abx80x_nvmem_xfer(struct abx80x_priv *priv, unsigned int offset,  		if (ret)  			return ret; -		if (write) +		if (write) {  			ret = i2c_smbus_write_i2c_block_data(priv->client, reg,  							     len, val); -		else +			if (ret) +				return ret; +		} else {  			ret = i2c_smbus_read_i2c_block_data(priv->client, reg,  							    len, val); -		if (ret) -			return ret; +			if (ret <= 0) +				return ret ? ret : -EIO; +			len = ret; +		}  		offset += len;  		val += len; diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c index 591e42391747..7ad34539be4d 100644 --- a/drivers/rtc/rtc-bq32k.c +++ b/drivers/rtc/rtc-bq32k.c @@ -304,7 +304,7 @@ static void bq32k_remove(struct i2c_client *client)  }  static const struct i2c_device_id bq32k_id[] = { -	{ "bq32000", 0 }, +	{ "bq32000" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, bq32k_id); diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 7d99cd2c37a0..35dca2accbb8 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -643,11 +643,10 @@ static int cmos_nvram_read(void *priv, unsigned int off, void *val,  			   size_t count)  {  	unsigned char *buf = val; -	int	retval;  	off += NVRAM_OFFSET;  	spin_lock_irq(&rtc_lock); -	for (retval = 0; count; count--, off++, retval++) { +	for (; count; count--, off++) {  		if (off < 128)  			*buf++ = CMOS_READ(off);  		else if (can_bank2) @@ -657,7 +656,7 @@ static int cmos_nvram_read(void *priv, unsigned int off, void *val,  	}  	spin_unlock_irq(&rtc_lock); -	return retval; +	return count ? -EIO : 0;  }  static int cmos_nvram_write(void *priv, unsigned int off, void *val, @@ -665,7 +664,6 @@ static int cmos_nvram_write(void *priv, unsigned int off, void *val,  {  	struct cmos_rtc	*cmos = priv;  	unsigned char	*buf = val; -	int		retval;  	/* NOTE:  on at least PCs and Ataris, the boot firmware uses a  	 * checksum on part of the NVRAM data.  That's currently ignored @@ -674,7 +672,7 @@ static int cmos_nvram_write(void *priv, unsigned int off, void *val,  	 */  	off += NVRAM_OFFSET;  	spin_lock_irq(&rtc_lock); -	for (retval = 0; count; count--, off++, retval++) { +	for (; count; count--, off++) {  		/* don't trash RTC registers */  		if (off == cmos->day_alrm  				|| off == cmos->mon_alrm @@ -689,7 +687,7 @@ static int cmos_nvram_write(void *priv, unsigned int off, void *val,  	}  	spin_unlock_irq(&rtc_lock); -	return retval; +	return count ? -EIO : 0;  }  /*----------------------------------------------------------------*/ diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 506b7d1c2397..872e0b679be4 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -65,6 +65,7 @@ enum ds_type {  #	define DS1340_BIT_CENTURY_EN	0x80	/* in REG_HOUR */  #	define DS1340_BIT_CENTURY	0x40	/* in REG_HOUR */  #define DS1307_REG_WDAY		0x03	/* 01-07 */ +#	define MCP794XX_BIT_OSCRUN	BIT(5)  #	define MCP794XX_BIT_VBATEN	0x08  #define DS1307_REG_MDAY		0x04	/* 01-31 */  #define DS1307_REG_MONTH	0x05	/* 01-12 */ @@ -242,6 +243,10 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)  	    regs[DS1307_REG_MIN] & M41T0_BIT_OF) {  		dev_warn_once(dev, "oscillator failed, set time!\n");  		return -EINVAL; +	} else if (ds1307->type == mcp794xx && +	    !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_OSCRUN)) { +		dev_warn_once(dev, "oscillator failed, set time!\n"); +		return -EINVAL;  	}  	tmp = regs[DS1307_REG_SECS]; @@ -354,7 +359,7 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)  	regs[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1);  	/* assume 20YY not 19YY */ -	tmp = t->tm_year - 100; +	tmp = t->tm_year % 100;  	regs[DS1307_REG_YEAR] = bin2bcd(tmp);  	if (chip->century_enable_bit) diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 4a5005cb23f5..c2359eb86bc9 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -52,7 +52,7 @@  #define DS1374_REG_TCR		0x09 /* Trickle Charge */  static const struct i2c_device_id ds1374_id[] = { -	{ "ds1374", 0 }, +	{ "ds1374" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, ds1374_id); diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index 641799f30baa..6e5314215d00 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c @@ -133,7 +133,7 @@ static int ds1672_probe(struct i2c_client *client)  }  static const struct i2c_device_id ds1672_id[] = { -	{ "ds1672", 0 }, +	{ "ds1672" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, ds1672_id); diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index 1485a6ae51e6..dd37b055693c 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -586,7 +586,7 @@ static int ds3232_i2c_probe(struct i2c_client *client)  }  static const struct i2c_device_id ds3232_id[] = { -	{ "ds3232", 0 }, +	{ "ds3232" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, ds3232_id); diff --git a/drivers/rtc/rtc-em3027.c b/drivers/rtc/rtc-em3027.c index fc772eae5da5..dc1ccbc65dcb 100644 --- a/drivers/rtc/rtc-em3027.c +++ b/drivers/rtc/rtc-em3027.c @@ -129,7 +129,7 @@ static int em3027_probe(struct i2c_client *client)  }  static const struct i2c_device_id em3027_id[] = { -	{ "em3027", 0 }, +	{ "em3027" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, em3027_id); diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index 400ce4ad0c49..f82728ebac0c 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c @@ -53,7 +53,7 @@ struct fm3130 {  	int			data_valid;  };  static const struct i2c_device_id fm3130_id[] = { -	{ "fm3130", 0 }, +	{ "fm3130" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, fm3130_id); diff --git a/drivers/rtc/rtc-goldfish.c b/drivers/rtc/rtc-goldfish.c index 59c0f38cc08d..53ec7173c28e 100644 --- a/drivers/rtc/rtc-goldfish.c +++ b/drivers/rtc/rtc-goldfish.c @@ -203,4 +203,5 @@ static struct platform_driver goldfish_rtc = {  module_platform_driver(goldfish_rtc); +MODULE_DESCRIPTION("Android Goldfish Real Time Clock driver");  MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c index b018535c842b..63f11ea3589d 100644 --- a/drivers/rtc/rtc-hym8563.c +++ b/drivers/rtc/rtc-hym8563.c @@ -559,8 +559,8 @@ static int hym8563_probe(struct i2c_client *client)  }  static const struct i2c_device_id hym8563_id[] = { -	{ "hym8563", 0 }, -	{}, +	{ "hym8563" }, +	{}  };  MODULE_DEVICE_TABLE(i2c, hym8563_id); diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index 4eef7afcc8bc..6fa9a68af9d9 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c @@ -366,7 +366,7 @@ static const struct of_device_id isl12022_dt_match[] = {  MODULE_DEVICE_TABLE(of, isl12022_dt_match);  static const struct i2c_device_id isl12022_id[] = { -	{ "isl12022", 0 }, +	{ "isl12022" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, isl12022_id); diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index e50c23ee1646..7b82e4a14b7a 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -7,6 +7,7 @@  #include <linux/bcd.h>  #include <linux/clk.h> +#include <linux/delay.h>  #include <linux/i2c.h>  #include <linux/module.h>  #include <linux/of.h> @@ -628,6 +629,18 @@ isl1208_rtc_interrupt(int irq, void *data)  	struct isl1208_state *isl1208 = i2c_get_clientdata(client);  	int handled = 0, sr, err; +	if (!isl1208->config->has_tamper) { +		/* +		 * The INT# output is pulled low 250ms after the alarm is +		 * triggered. After the INT# output is pulled low, it is low for +		 * at least 250ms, even if the correct action is taken to clear +		 * it. It is impossible to clear ALM if it is still active. The +		 * host must wait for the RTC to progress past the alarm time +		 * plus the 250ms delay before clearing ALM. +		 */ +		msleep(250); +	} +  	/*  	 * I2C reads get NAK'ed if we read straight away after an interrupt?  	 * Using a mdelay/msleep didn't seem to help either, so we work around @@ -650,6 +663,13 @@ isl1208_rtc_interrupt(int irq, void *data)  		rtc_update_irq(isl1208->rtc, 1, RTC_IRQF | RTC_AF); +		/* Disable the alarm */ +		err = isl1208_rtc_toggle_alarm(client, 0); +		if (err) +			return err; + +		fsleep(275); +  		/* Clear the alarm */  		sr &= ~ISL1208_REG_SR_ALM;  		sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr); @@ -658,11 +678,6 @@ isl1208_rtc_interrupt(int irq, void *data)  				__func__);  		else  			handled = 1; - -		/* Disable the alarm */ -		err = isl1208_rtc_toggle_alarm(client, 0); -		if (err) -			return err;  	}  	if (isl1208->config->has_tamper && (sr & ISL1208_REG_SR_EVT)) { @@ -775,14 +790,13 @@ static int isl1208_nvmem_read(void *priv, unsigned int off, void *buf,  {  	struct isl1208_state *isl1208 = priv;  	struct i2c_client *client = to_i2c_client(isl1208->rtc->dev.parent); -	int ret;  	/* nvmem sanitizes offset/count for us, but count==0 is possible */  	if (!count)  		return count; -	ret = isl1208_i2c_read_regs(client, ISL1208_REG_USR1 + off, buf, + +	return isl1208_i2c_read_regs(client, ISL1208_REG_USR1 + off, buf,  				    count); -	return ret == 0 ? count : ret;  }  static int isl1208_nvmem_write(void *priv, unsigned int off, void *buf, @@ -790,15 +804,13 @@ static int isl1208_nvmem_write(void *priv, unsigned int off, void *buf,  {  	struct isl1208_state *isl1208 = priv;  	struct i2c_client *client = to_i2c_client(isl1208->rtc->dev.parent); -	int ret;  	/* nvmem sanitizes off/count for us, but count==0 is possible */  	if (!count)  		return count; -	ret = isl1208_i2c_set_regs(client, ISL1208_REG_USR1 + off, buf, -				   count); -	return ret == 0 ? count : ret; +	return isl1208_i2c_set_regs(client, ISL1208_REG_USR1 + off, buf, +				   count);  }  static const struct nvmem_config isl1208_nvmem_config = { diff --git a/drivers/rtc/rtc-max31335.c b/drivers/rtc/rtc-max31335.c index a2441e5c2c74..9a456f537d3b 100644 --- a/drivers/rtc/rtc-max31335.c +++ b/drivers/rtc/rtc-max31335.c @@ -669,7 +669,7 @@ static int max31335_probe(struct i2c_client *client)  }  static const struct i2c_device_id max31335_id[] = { -	{ "max31335", 0 }, +	{ "max31335" },  	{ }  }; diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index 31b910e4d91a..7be31fce5bc7 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c @@ -215,7 +215,7 @@ static int max6900_probe(struct i2c_client *client)  }  static const struct i2c_device_id max6900_id[] = { -	{ "max6900", 0 }, +	{ "max6900" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, max6900_id); diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index 28858fcaea8f..71eafe4fbc72 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -403,5 +403,6 @@ static struct platform_driver mpc5121_rtc_driver = {  module_platform_driver(mpc5121_rtc_driver); +MODULE_DESCRIPTION("Freescale MPC5121 built-in RTC driver");  MODULE_LICENSE("GPL");  MODULE_AUTHOR("John Rigby <[email protected]>"); diff --git a/drivers/rtc/rtc-nct3018y.c b/drivers/rtc/rtc-nct3018y.c index 7a8b4de893b8..76c5f464b2da 100644 --- a/drivers/rtc/rtc-nct3018y.c +++ b/drivers/rtc/rtc-nct3018y.c @@ -567,7 +567,7 @@ static int nct3018y_probe(struct i2c_client *client)  }  static const struct i2c_device_id nct3018y_id[] = { -	{ "nct3018y", 0 }, +	{ "nct3018y" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, nct3018y_id); diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index c6155c48a4ac..e6b2a9c15b54 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -1027,4 +1027,5 @@ static struct platform_driver omap_rtc_driver = {  module_platform_driver(omap_rtc_driver);  MODULE_AUTHOR("George G. Davis (and others)"); +MODULE_DESCRIPTION("TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx RTC driver");  MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index 98b77f790b0c..2c63c0ffd05a 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c @@ -495,7 +495,7 @@ static int pcf8523_probe(struct i2c_client *client)  }  static const struct i2c_device_id pcf8523_id[] = { -	{ "pcf8523", 0 }, +	{ "pcf8523" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, pcf8523_id); diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 1949d7473310..647d52f1f5c5 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -594,9 +594,9 @@ static int pcf8563_probe(struct i2c_client *client)  }  static const struct i2c_device_id pcf8563_id[] = { -	{ "pcf8563", 0 }, -	{ "rtc8564", 0 }, -	{ "pca8565", 0 }, +	{ "pcf8563" }, +	{ "rtc8564" }, +	{ "pca8565" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, pcf8563_id); diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index a7e0fc360b6a..652b9dfa7566 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c @@ -297,7 +297,7 @@ static int pcf8583_probe(struct i2c_client *client)  }  static const struct i2c_device_id pcf8583_id[] = { -	{ "pcf8583", 0 }, +	{ "pcf8583" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, pcf8583_id); diff --git a/drivers/rtc/rtc-rc5t583.c b/drivers/rtc/rtc-rc5t583.c index 6f4bf919827a..115c46f862f9 100644 --- a/drivers/rtc/rtc-rc5t583.c +++ b/drivers/rtc/rtc-rc5t583.c @@ -308,4 +308,5 @@ static struct platform_driver rc5t583_rtc_driver = {  module_platform_driver(rc5t583_rtc_driver);  MODULE_ALIAS("platform:rtc-rc5t583");  MODULE_AUTHOR("Venu Byravarasu <[email protected]>"); +MODULE_DESCRIPTION("RICOH 5T583 RTC driver");  MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index 4a81feeb00ff..83331d1fcab0 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c @@ -807,8 +807,8 @@ static int rv3029_i2c_probe(struct i2c_client *client)  }  static const struct i2c_device_id rv3029_id[] = { -	{ "rv3029", 0 }, -	{ "rv3029c2", 0 }, +	{ "rv3029" }, +	{ "rv3029c2" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, rv3029_id); diff --git a/drivers/rtc/rtc-rx6110.c b/drivers/rtc/rtc-rx6110.c index af6dd6ccbe3b..7c423d672adb 100644 --- a/drivers/rtc/rtc-rx6110.c +++ b/drivers/rtc/rtc-rx6110.c @@ -451,7 +451,7 @@ static const struct acpi_device_id rx6110_i2c_acpi_match[] = {  MODULE_DEVICE_TABLE(acpi, rx6110_i2c_acpi_match);  static const struct i2c_device_id rx6110_i2c_id[] = { -	{ "rx6110", 0 }, +	{ "rx6110" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, rx6110_i2c_id); diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c index f44e212c07de..2b6198d1cf81 100644 --- a/drivers/rtc/rtc-rx8010.c +++ b/drivers/rtc/rtc-rx8010.c @@ -50,7 +50,7 @@  #define RX8010_ALARM_AE		BIT(7)  static const struct i2c_device_id rx8010_id[] = { -	{ "rx8010", 0 }, +	{ "rx8010" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, rx8010_id); diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index 48efd61a114d..b18c12887bdc 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -307,7 +307,7 @@ static int rx8581_probe(struct i2c_client *client)  }  static const struct i2c_device_id rx8581_id[] = { -	{ "rx8581", 0 }, +	{ "rx8581" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, rx8581_id); diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 90a3028ac574..2d6b655a4b25 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -50,7 +50,7 @@  #define S35390A_INT2_MODE_PMIN		(BIT(3) | BIT(2)) /* INT2FE | INT2ME */  static const struct i2c_device_id s35390a_id[] = { -	{ "s35390a", 0 }, +	{ "s35390a" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, s35390a_id); diff --git a/drivers/rtc/rtc-sd3078.c b/drivers/rtc/rtc-sd3078.c index 7760394ccd2d..fe27b54beaad 100644 --- a/drivers/rtc/rtc-sd3078.c +++ b/drivers/rtc/rtc-sd3078.c @@ -201,7 +201,7 @@ static int sd3078_probe(struct i2c_client *client)  }  static const struct i2c_device_id sd3078_id[] = { -	{"sd3078", 0}, +	{ "sd3078" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, sd3078_id); diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index 76753c71d92e..98b07969609d 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -5,6 +5,7 @@   */  #include <linux/bcd.h> +#include <linux/bitfield.h>  #include <linux/clk.h>  #include <linux/errno.h>  #include <linux/iopoll.h> @@ -83,6 +84,18 @@  #define STM32_RTC_VERR_MAJREV_SHIFT	4  #define STM32_RTC_VERR_MAJREV		GENMASK(7, 4) +/* STM32_RTC_SECCFGR bit fields */ +#define STM32_RTC_SECCFGR		0x20 +#define STM32_RTC_SECCFGR_ALRA_SEC	BIT(0) +#define STM32_RTC_SECCFGR_INIT_SEC	BIT(14) +#define STM32_RTC_SECCFGR_SEC		BIT(15) + +/* STM32_RTC_RXCIDCFGR bit fields */ +#define STM32_RTC_RXCIDCFGR(x)		(0x80 + 0x4 * (x)) +#define STM32_RTC_RXCIDCFGR_CFEN	BIT(0) +#define STM32_RTC_RXCIDCFGR_CID		GENMASK(6, 4) +#define STM32_RTC_RXCIDCFGR_CID1	1 +  /* STM32_RTC_WPR key constants */  #define RTC_WPR_1ST_KEY			0xCA  #define RTC_WPR_2ND_KEY			0x53 @@ -120,6 +133,7 @@ struct stm32_rtc_data {  	bool has_pclk;  	bool need_dbp;  	bool need_accuracy; +	bool rif_protected;  };  struct stm32_rtc { @@ -134,6 +148,14 @@ struct stm32_rtc {  	int irq_alarm;  }; +struct stm32_rtc_rif_resource { +	unsigned int num; +	u32 bit; +}; + +static const struct stm32_rtc_rif_resource STM32_RTC_RES_ALRA = {0, STM32_RTC_SECCFGR_ALRA_SEC}; +static const struct stm32_rtc_rif_resource STM32_RTC_RES_INIT = {5, STM32_RTC_SECCFGR_INIT_SEC}; +  static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc)  {  	const struct stm32_rtc_registers *regs = &rtc->data->regs; @@ -553,6 +575,7 @@ static const struct stm32_rtc_data stm32_rtc_data = {  	.has_pclk = false,  	.need_dbp = true,  	.need_accuracy = false, +	.rif_protected = false,  	.regs = {  		.tr = 0x00,  		.dr = 0x04, @@ -575,6 +598,7 @@ static const struct stm32_rtc_data stm32h7_rtc_data = {  	.has_pclk = true,  	.need_dbp = true,  	.need_accuracy = false, +	.rif_protected = false,  	.regs = {  		.tr = 0x00,  		.dr = 0x04, @@ -606,6 +630,7 @@ static const struct stm32_rtc_data stm32mp1_data = {  	.has_pclk = true,  	.need_dbp = false,  	.need_accuracy = true, +	.rif_protected = false,  	.regs = {  		.tr = 0x00,  		.dr = 0x04, @@ -624,14 +649,57 @@ static const struct stm32_rtc_data stm32mp1_data = {  	.clear_events = stm32mp1_rtc_clear_events,  }; +static const struct stm32_rtc_data stm32mp25_data = { +	.has_pclk = true, +	.need_dbp = false, +	.need_accuracy = true, +	.rif_protected = true, +	.regs = { +		.tr = 0x00, +		.dr = 0x04, +		.cr = 0x18, +		.isr = 0x0C, /* named RTC_ICSR on stm32mp25 */ +		.prer = 0x10, +		.alrmar = 0x40, +		.wpr = 0x24, +		.sr = 0x50, +		.scr = 0x5C, +		.verr = 0x3F4, +	}, +	.events = { +		.alra = STM32_RTC_SR_ALRA, +	}, +	.clear_events = stm32mp1_rtc_clear_events, +}; +  static const struct of_device_id stm32_rtc_of_match[] = {  	{ .compatible = "st,stm32-rtc", .data = &stm32_rtc_data },  	{ .compatible = "st,stm32h7-rtc", .data = &stm32h7_rtc_data },  	{ .compatible = "st,stm32mp1-rtc", .data = &stm32mp1_data }, +	{ .compatible = "st,stm32mp25-rtc", .data = &stm32mp25_data },  	{}  };  MODULE_DEVICE_TABLE(of, stm32_rtc_of_match); +static int stm32_rtc_check_rif(struct stm32_rtc *stm32_rtc, +			       struct stm32_rtc_rif_resource res) +{ +	u32 rxcidcfgr = readl_relaxed(stm32_rtc->base + STM32_RTC_RXCIDCFGR(res.num)); +	u32 seccfgr; + +	/* Check if RTC available for our CID */ +	if ((rxcidcfgr & STM32_RTC_RXCIDCFGR_CFEN) && +	    (FIELD_GET(STM32_RTC_RXCIDCFGR_CID, rxcidcfgr) != STM32_RTC_RXCIDCFGR_CID1)) +		return -EACCES; + +	/* Check if RTC available for non secure world */ +	seccfgr = readl_relaxed(stm32_rtc->base + STM32_RTC_SECCFGR); +	if ((seccfgr & STM32_RTC_SECCFGR_SEC) | (seccfgr & res.bit)) +		return -EACCES; + +	return 0; +} +  static int stm32_rtc_init(struct platform_device *pdev,  			  struct stm32_rtc *rtc)  { @@ -787,6 +855,16 @@ static int stm32_rtc_probe(struct platform_device *pdev)  		regmap_update_bits(rtc->dbp, rtc->dbp_reg,  				   rtc->dbp_mask, rtc->dbp_mask); +	if (rtc->data->rif_protected) { +		ret = stm32_rtc_check_rif(rtc, STM32_RTC_RES_INIT); +		if (!ret) +			ret = stm32_rtc_check_rif(rtc, STM32_RTC_RES_ALRA); +		if (ret) { +			dev_err(&pdev->dev, "Failed to probe RTC due to RIF configuration\n"); +			goto err; +		} +	} +  	/*  	 * After a system reset, RTC_ISR.INITS flag can be read to check if  	 * the calendar has been initialized or not. INITS flag is reset by a diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 411ff66c0468..2ea1bbfbbc2a 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -466,4 +466,5 @@ static struct platform_driver tps65910_rtc_driver = {  module_platform_driver(tps65910_rtc_driver);  MODULE_ALIAS("platform:tps65910-rtc");  MODULE_AUTHOR("Venu Byravarasu <[email protected]>"); +MODULE_DESCRIPTION("TI TPS65910 RTC driver");  MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-tps6594.c b/drivers/rtc/rtc-tps6594.c index 838ae8562a35..e69667634137 100644 --- a/drivers/rtc/rtc-tps6594.c +++ b/drivers/rtc/rtc-tps6594.c @@ -42,6 +42,11 @@  // Multiplier for ppb conversions  #define PPB_MULT NANO +struct tps6594_rtc { +	struct rtc_device *rtc_dev; +	int irq; +}; +  static int tps6594_rtc_alarm_irq_enable(struct device *dev,  					unsigned int enabled)  { @@ -325,11 +330,11 @@ static int tps6594_rtc_set_offset(struct device *dev, long offset)  	return tps6594_rtc_set_calibration(dev, calibration);  } -static irqreturn_t tps6594_rtc_interrupt(int irq, void *rtc) +static irqreturn_t tps6594_rtc_interrupt(int irq, void *data)  { -	struct device *dev = rtc; +	struct device *dev = data;  	struct tps6594 *tps = dev_get_drvdata(dev->parent); -	struct rtc_device *rtc_dev = dev_get_drvdata(dev); +	struct tps6594_rtc *rtc = dev_get_drvdata(dev);  	int ret;  	u32 rtc_reg; @@ -337,7 +342,7 @@ static irqreturn_t tps6594_rtc_interrupt(int irq, void *rtc)  	if (ret)  		return IRQ_NONE; -	rtc_update_irq(rtc_dev, 1, RTC_IRQF | RTC_AF); +	rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);  	return IRQ_HANDLED;  } @@ -356,7 +361,7 @@ static int tps6594_rtc_probe(struct platform_device *pdev)  {  	struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);  	struct device *dev = &pdev->dev; -	struct rtc_device *rtc; +	struct tps6594_rtc *rtc;  	int irq;  	int ret; @@ -364,9 +369,9 @@ static int tps6594_rtc_probe(struct platform_device *pdev)  	if (!rtc)  		return -ENOMEM; -	rtc = devm_rtc_allocate_device(dev); -	if (IS_ERR(rtc)) -		return PTR_ERR(rtc); +	rtc->rtc_dev = devm_rtc_allocate_device(dev); +	if (IS_ERR(rtc->rtc_dev)) +		return PTR_ERR(rtc->rtc_dev);  	// Enable crystal oscillator.  	ret = regmap_set_bits(tps->regmap, TPS6594_REG_RTC_CTRL_2, @@ -415,6 +420,8 @@ static int tps6594_rtc_probe(struct platform_device *pdev)  	if (irq < 0)  		return dev_err_probe(dev, irq, "Failed to get irq\n"); +	rtc->irq = irq; +  	ret = devm_request_threaded_irq(dev, irq, NULL, tps6594_rtc_interrupt,  					IRQF_ONESHOT, TPS6594_IRQ_NAME_ALARM,  					dev); @@ -427,13 +434,56 @@ static int tps6594_rtc_probe(struct platform_device *pdev)  		return dev_err_probe(dev, ret,  				     "Failed to init rtc as wakeup source\n"); -	rtc->ops = &tps6594_rtc_ops; -	rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; -	rtc->range_max = RTC_TIMESTAMP_END_2099; +	rtc->rtc_dev->ops = &tps6594_rtc_ops; +	rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000; +	rtc->rtc_dev->range_max = RTC_TIMESTAMP_END_2099; + +	return devm_rtc_register_device(rtc->rtc_dev); +} + +static int tps6594_rtc_resume(struct device *dev) +{ +	struct tps6594 *tps = dev_get_drvdata(dev->parent); +	struct tps6594_rtc *rtc = dev_get_drvdata(dev); +	int ret; + +	ret = regmap_test_bits(tps->regmap, TPS6594_REG_INT_STARTUP, +			       TPS6594_BIT_RTC_INT); +	if (ret < 0) { +		dev_err(dev, "failed to read REG_INT_STARTUP: %d\n", ret); +		goto out; +	} + +	if (ret > 0) { +		/* +		 * If the alarm bit is set, it means that the IRQ has been +		 * fired. But, the kernel may not have woke up yet when it +		 * happened. So, we have to clear it. +		 */ +		ret = regmap_write(tps->regmap, TPS6594_REG_RTC_STATUS, +				   TPS6594_BIT_ALARM); +		if (ret < 0) +			dev_err(dev, "error clearing alarm bit: %d", ret); -	return devm_rtc_register_device(rtc); +		rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF); +	} +out: +	disable_irq_wake(rtc->irq); + +	return 0;  } +static int tps6594_rtc_suspend(struct device *dev) +{ +	struct tps6594_rtc *rtc = dev_get_drvdata(dev); + +	enable_irq_wake(rtc->irq); + +	return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(tps6594_rtc_pm_ops, tps6594_rtc_suspend, tps6594_rtc_resume); +  static const struct platform_device_id tps6594_rtc_id_table[] = {  	{ "tps6594-rtc", },  	{} @@ -444,6 +494,7 @@ static struct platform_driver tps6594_rtc_driver = {  	.probe		= tps6594_rtc_probe,  	.driver		= {  		.name	= "tps6594-rtc", +		.pm = pm_sleep_ptr(&tps6594_rtc_pm_ops),  	},  	.id_table = tps6594_rtc_id_table,  }; diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 13f8ce08243c..2cfacdd37e09 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -685,4 +685,5 @@ static struct platform_driver twl4030rtc_driver = {  module_platform_driver(twl4030rtc_driver);  MODULE_AUTHOR("Texas Instruments, MontaVista Software"); +MODULE_DESCRIPTION("TI TWL4030/TWL5030/TWL6030/TPS659x0 RTC driver");  MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index 807f953ae0ae..4bcd7ca32f27 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c @@ -663,7 +663,7 @@ static void x1205_remove(struct i2c_client *client)  }  static const struct i2c_device_id x1205_id[] = { -	{ "x1205", 0 }, +	{ "x1205" },  	{ }  };  MODULE_DEVICE_TABLE(i2c, x1205_id); |