diff options
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/Kconfig | 17 | ||||
| -rw-r--r-- | drivers/rtc/Makefile | 1 | ||||
| -rw-r--r-- | drivers/rtc/interface.c | 34 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ab-eoz9.c | 135 | ||||
| -rw-r--r-- | drivers/rtc/rtc-bd70528.c | 104 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1307.c | 56 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1511.c | 6 | ||||
| -rw-r--r-- | drivers/rtc/rtc-fsl-ftm-alarm.c | 1 | ||||
| -rw-r--r-- | drivers/rtc/rtc-hid-sensor-time.c | 4 | ||||
| -rw-r--r-- | drivers/rtc/rtc-imx-sc.c | 11 | ||||
| -rw-r--r-- | drivers/rtc/rtc-imxdi.c | 4 | ||||
| -rw-r--r-- | drivers/rtc/rtc-m48t59.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-mxc.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ntxec.c | 145 | ||||
| -rw-r--r-- | drivers/rtc/rtc-omap.c | 5 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pcf85063.c | 7 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pcf8523.c | 196 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pm8xxx.c | 11 | ||||
| -rw-r--r-- | drivers/rtc/rtc-rv3028.c | 4 | ||||
| -rw-r--r-- | drivers/rtc/rtc-rx6110.c | 7 | ||||
| -rw-r--r-- | drivers/rtc/rtc-s5m.c | 6 | ||||
| -rw-r--r-- | drivers/rtc/rtc-spear.c | 6 | ||||
| -rw-r--r-- | drivers/rtc/rtc-tps65910.c | 1 | ||||
| -rw-r--r-- | drivers/rtc/sysfs.c | 2 | 
24 files changed, 612 insertions, 155 deletions
| diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index ce723dc54aa4..d8c13fded164 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -501,11 +501,11 @@ config RTC_DRV_M41T80_WDT  	  watchdog timer in the ST M41T60 and M41T80 RTC chips series.  config RTC_DRV_BD70528 -	tristate "ROHM BD70528 PMIC RTC" -	depends on MFD_ROHM_BD70528 && (BD70528_WATCHDOG || !BD70528_WATCHDOG) +	tristate "ROHM BD70528, BD71815 and BD71828 PMIC RTC" +	depends on MFD_ROHM_BD71828 || MFD_ROHM_BD70528 && (BD70528_WATCHDOG || !BD70528_WATCHDOG)  	help  	  If you say Y here you will get support for the RTC -	  block on ROHM BD70528 and BD71828 Power Management IC. +	  block on ROHM BD70528, BD71815 and BD71828 Power Management IC.  	  This driver can also be built as a module. If so, the module  	  will be called rtc-bd70528. @@ -1296,6 +1296,14 @@ config RTC_DRV_CROS_EC  	  This driver can also be built as a module. If so, the module  	  will be called rtc-cros-ec. +config RTC_DRV_NTXEC +	tristate "Netronix embedded controller RTC" +	depends on MFD_NTXEC +	help +	  Say yes here if you want to support the RTC functionality of the +	  embedded controller found in certain e-book readers designed by the +	  original design manufacturer Netronix. +  comment "on-CPU RTC drivers"  config RTC_DRV_ASM9260 @@ -1331,6 +1339,7 @@ config RTC_DRV_DIGICOLOR  config RTC_DRV_IMXDI  	tristate "Freescale IMX DryIce Real Time Clock"  	depends on ARCH_MXC +	depends on OF  	help  	   Support for Freescale IMX DryIce RTC @@ -1898,7 +1907,7 @@ config RTC_DRV_HID_SENSOR_TIME  config RTC_DRV_GOLDFISH  	tristate "Goldfish Real Time Clock" -	depends on OF && HAS_IOMEM +	depends on HAS_IOMEM  	help  	  Say yes to enable RTC driver for the Goldfish based virtual platform. diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 4e930183c170..2dd0dd956b0e 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -108,6 +108,7 @@ obj-$(CONFIG_RTC_DRV_MT7622)	+= rtc-mt7622.o  obj-$(CONFIG_RTC_DRV_MV)	+= rtc-mv.o  obj-$(CONFIG_RTC_DRV_MXC)	+= rtc-mxc.o  obj-$(CONFIG_RTC_DRV_MXC_V2)	+= rtc-mxc_v2.o +obj-$(CONFIG_RTC_DRV_NTXEC)	+= rtc-ntxec.o  obj-$(CONFIG_RTC_DRV_OMAP)	+= rtc-omap.o  obj-$(CONFIG_RTC_DRV_OPAL)	+= rtc-opal.o  obj-$(CONFIG_RTC_DRV_PALMAS)	+= rtc-palmas.o diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index dcb34c73319e..9a2bd4947007 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -545,7 +545,7 @@ EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable);  int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled)  { -	int rc = 0, err; +	int err;  	err = mutex_lock_interruptible(&rtc->ops_lock);  	if (err) @@ -561,17 +561,21 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled)  	if (rtc->uie_rtctimer.enabled == enabled)  		goto out; -	if (rtc->uie_unsupported) { -		err = -EINVAL; -		goto out; +	if (rtc->uie_unsupported || !test_bit(RTC_FEATURE_ALARM, rtc->features)) { +		mutex_unlock(&rtc->ops_lock); +#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL +		return rtc_dev_update_irq_enable_emul(rtc, enabled); +#else +		return -EINVAL; +#endif  	}  	if (enabled) {  		struct rtc_time tm;  		ktime_t now, onesec; -		rc = __rtc_read_time(rtc, &tm); -		if (rc) +		err = __rtc_read_time(rtc, &tm); +		if (err)  			goto out;  		onesec = ktime_set(1, 0);  		now = rtc_tm_to_ktime(tm); @@ -585,24 +589,6 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled)  out:  	mutex_unlock(&rtc->ops_lock); -	/* -	 * __rtc_read_time() failed, this probably means that the RTC time has -	 * never been set or less probably there is a transient error on the -	 * bus. In any case, avoid enabling emulation has this will fail when -	 * reading the time too. -	 */ -	if (rc) -		return rc; - -#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL -	/* -	 * Enable emulation if the driver returned -EINVAL to signal that it has -	 * been configured without interrupts or they are not available at the -	 * moment. -	 */ -	if (err == -EINVAL) -		err = rtc_dev_update_irq_enable_emul(rtc, enabled); -#endif  	return err;  }  EXPORT_SYMBOL_GPL(rtc_update_irq_enable); diff --git a/drivers/rtc/rtc-ab-eoz9.c b/drivers/rtc/rtc-ab-eoz9.c index b20d8f26dcdb..a9b355510cd4 100644 --- a/drivers/rtc/rtc-ab-eoz9.c +++ b/drivers/rtc/rtc-ab-eoz9.c @@ -11,6 +11,7 @@  #include <linux/bcd.h>  #include <linux/of.h>  #include <linux/regmap.h> +#include <linux/bitfield.h>  #include <linux/hwmon.h>  #include <linux/hwmon-sysfs.h> @@ -57,6 +58,24 @@  #define ABEOZ9_SEC_LEN			7 +#define ABEOZ9_REG_ALARM_SEC		0x10 +#define ABEOZ9_BIT_ALARM_SEC		GENMASK(6, 0) +#define ABEOZ9_REG_ALARM_MIN		0x11 +#define ABEOZ9_BIT_ALARM_MIN		GENMASK(6, 0) +#define ABEOZ9_REG_ALARM_HOURS		0x12 +#define ABEOZ9_BIT_ALARM_HOURS_PM	BIT(5) +#define ABEOZ9_BIT_ALARM_HOURS		GENMASK(4, 0) +#define ABEOZ9_REG_ALARM_DAYS		0x13 +#define ABEOZ9_BIT_ALARM_DAYS		GENMASK(5, 0) +#define ABEOZ9_REG_ALARM_WEEKDAYS	0x14 +#define ABEOZ9_BIT_ALARM_WEEKDAYS	GENMASK(2, 0) +#define ABEOZ9_REG_ALARM_MONTHS		0x15 +#define ABEOZ9_BIT_ALARM_MONTHS		GENMASK(4, 0) +#define ABEOZ9_REG_ALARM_YEARS		0x16 + +#define ABEOZ9_ALARM_LEN		7 +#define ABEOZ9_BIT_ALARM_AE		BIT(7) +  #define ABEOZ9_REG_REG_TEMP		0x20  #define ABEOZ953_TEMP_MAX		120  #define ABEOZ953_TEMP_MIN		-60 @@ -186,6 +205,98 @@ static int abeoz9_rtc_set_time(struct device *dev, struct rtc_time *tm)  	return abeoz9_reset_validity(regmap);  } +static int abeoz9_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ +	struct abeoz9_rtc_data *data = dev_get_drvdata(dev); +	struct regmap *regmap = data->regmap; +	u8 regs[ABEOZ9_ALARM_LEN]; +	u8 val[2]; +	int ret; + +	ret = abeoz9_check_validity(dev); +	if (ret) +		return ret; + +	ret = regmap_bulk_read(regmap, ABEOZ9_REG_CTRL_INT, val, sizeof(val)); +	if (ret) +		return ret; + +	alarm->enabled = val[0] & ABEOZ9_REG_CTRL_INT_AIE; +	alarm->pending = val[1] & ABEOZ9_REG_CTRL_INT_FLAG_AF; + +	ret = regmap_bulk_read(regmap, ABEOZ9_REG_ALARM_SEC, regs, sizeof(regs)); +	if (ret) +		return ret; + +	alarm->time.tm_sec = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_SEC, regs[0])); +	alarm->time.tm_min = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_MIN, regs[1])); +	alarm->time.tm_hour = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_HOURS, regs[2])); +	if (FIELD_GET(ABEOZ9_BIT_ALARM_HOURS_PM, regs[2])) +		alarm->time.tm_hour += 12; + +	alarm->time.tm_mday = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_DAYS, regs[3])); + +	return 0; +} + +static int abeoz9_rtc_alarm_irq_enable(struct device *dev, u32 enable) +{ +	struct abeoz9_rtc_data *data = dev_get_drvdata(dev); + +	return regmap_update_bits(data->regmap, ABEOZ9_REG_CTRL_INT, +				  ABEOZ9_REG_CTRL_INT_AIE, +				  FIELD_PREP(ABEOZ9_REG_CTRL_INT_AIE, enable)); +} + +static int abeoz9_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ +	struct abeoz9_rtc_data *data = dev_get_drvdata(dev); +	u8 regs[ABEOZ9_ALARM_LEN] = {0}; +	int ret; + +	ret = regmap_update_bits(data->regmap, ABEOZ9_REG_CTRL_INT_FLAG, +				 ABEOZ9_REG_CTRL_INT_FLAG_AF, 0); +	if (ret) +		return ret; + +	regs[0] = ABEOZ9_BIT_ALARM_AE | FIELD_PREP(ABEOZ9_BIT_ALARM_SEC, +						   bin2bcd(alarm->time.tm_sec)); +	regs[1] = ABEOZ9_BIT_ALARM_AE | FIELD_PREP(ABEOZ9_BIT_ALARM_MIN, +						   bin2bcd(alarm->time.tm_min)); +	regs[2] = ABEOZ9_BIT_ALARM_AE | FIELD_PREP(ABEOZ9_BIT_ALARM_HOURS, +						   bin2bcd(alarm->time.tm_hour)); +	regs[3] = ABEOZ9_BIT_ALARM_AE | FIELD_PREP(ABEOZ9_BIT_ALARM_DAYS, +						   bin2bcd(alarm->time.tm_mday)); + +	ret = regmap_bulk_write(data->regmap, ABEOZ9_REG_ALARM_SEC, regs, +				sizeof(regs)); +	if (ret) +		return ret; + +	return abeoz9_rtc_alarm_irq_enable(dev, alarm->enabled); +} + +static irqreturn_t abeoz9_rtc_irq(int irq, void *dev) +{ +	struct abeoz9_rtc_data *data = dev_get_drvdata(dev); +	unsigned int val; +	int ret; + +	ret = regmap_read(data->regmap, ABEOZ9_REG_CTRL_INT_FLAG, &val); +	if (ret) +		return IRQ_NONE; + +	if (!FIELD_GET(ABEOZ9_REG_CTRL_INT_FLAG_AF, val)) +		return IRQ_NONE; + +	regmap_update_bits(data->regmap, ABEOZ9_REG_CTRL_INT_FLAG, +			   ABEOZ9_REG_CTRL_INT_FLAG_AF, 0); + +	rtc_update_irq(data->rtc, 1, RTC_IRQF | RTC_AF); + +	return IRQ_HANDLED; +} +  static int abeoz9_trickle_parse_dt(struct device_node *node)  {  	u32 ohms = 0; @@ -258,12 +369,16 @@ static int abeoz9_rtc_setup(struct device *dev, struct device_node *node)  static const struct rtc_class_ops rtc_ops = {  	.read_time = abeoz9_rtc_get_time, -	.set_time  = abeoz9_rtc_set_time, +	.set_time = abeoz9_rtc_set_time, +	.read_alarm = abeoz9_rtc_read_alarm, +	.set_alarm = abeoz9_rtc_set_alarm, +	.alarm_irq_enable = abeoz9_rtc_alarm_irq_enable,  };  static const struct regmap_config abeoz9_rtc_regmap_config = {  	.reg_bits = 8,  	.val_bits = 8, +	.max_register = 0x3f,  };  #if IS_REACHABLE(CONFIG_HWMON) @@ -419,6 +534,24 @@ static int abeoz9_probe(struct i2c_client *client,  	data->rtc->ops = &rtc_ops;  	data->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;  	data->rtc->range_max = RTC_TIMESTAMP_END_2099; +	data->rtc->uie_unsupported = 1; +	clear_bit(RTC_FEATURE_ALARM, data->rtc->features); + +	if (client->irq > 0) { +		ret = devm_request_threaded_irq(dev, client->irq, NULL, +						abeoz9_rtc_irq, +						IRQF_TRIGGER_LOW | IRQF_ONESHOT, +						dev_name(dev), dev); +		if (ret) { +			dev_err(dev, "failed to request alarm irq\n"); +			return ret; +		} +	} + +	if (client->irq > 0 || device_property_read_bool(dev, "wakeup-source")) { +		ret = device_init_wakeup(dev, true); +		set_bit(RTC_FEATURE_ALARM, data->rtc->features); +	}  	ret = devm_rtc_register_device(data->rtc);  	if (ret) diff --git a/drivers/rtc/rtc-bd70528.c b/drivers/rtc/rtc-bd70528.c index 17cb67f5bf6e..6454afca02a6 100644 --- a/drivers/rtc/rtc-bd70528.c +++ b/drivers/rtc/rtc-bd70528.c @@ -6,6 +6,7 @@  #include <linux/bcd.h>  #include <linux/mfd/rohm-bd70528.h> +#include <linux/mfd/rohm-bd71815.h>  #include <linux/mfd/rohm-bd71828.h>  #include <linux/module.h>  #include <linux/of.h> @@ -14,6 +15,12 @@  #include <linux/rtc.h>  /* + * On BD71828 and BD71815 the ALM0 MASK is 14 bytes after the ALM0 + * block start + */ +#define BD718XX_ALM_EN_OFFSET 14 + +/*   * We read regs RTC_SEC => RTC_YEAR   * this struct is ordered according to chip registers.   * Keep it u8 only (or packed) to avoid padding issues. @@ -52,8 +59,10 @@ struct bd70528_rtc_alm {  struct bd70528_rtc {  	struct rohm_regmap_dev *parent; +	struct regmap *regmap;  	struct device *dev;  	u8 reg_time_start; +	u8 bd718xx_alm_block_start;  	bool has_rtc_timers;  }; @@ -234,10 +243,9 @@ static int bd71828_set_alarm(struct device *dev, struct rtc_wkalrm *a)  	int ret;  	struct bd71828_rtc_alm alm;  	struct bd70528_rtc *r = dev_get_drvdata(dev); -	struct rohm_regmap_dev *parent = r->parent; -	ret = regmap_bulk_read(parent->regmap, BD71828_REG_RTC_ALM_START, -			       &alm, sizeof(alm)); +	ret = regmap_bulk_read(r->regmap, r->bd718xx_alm_block_start, &alm, +			       sizeof(alm));  	if (ret) {  		dev_err(dev, "Failed to read alarm regs\n");  		return ret; @@ -250,8 +258,8 @@ static int bd71828_set_alarm(struct device *dev, struct rtc_wkalrm *a)  	else  		alm.alm_mask |= BD70528_MASK_ALM_EN; -	ret = regmap_bulk_write(parent->regmap, BD71828_REG_RTC_ALM_START, -				&alm, sizeof(alm)); +	ret = regmap_bulk_write(r->regmap, r->bd718xx_alm_block_start, &alm, +				sizeof(alm));  	if (ret)  		dev_err(dev, "Failed to set alarm time\n"); @@ -265,17 +273,16 @@ static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a)  	struct bd70528_rtc_alm alm;  	int ret;  	struct bd70528_rtc *r = dev_get_drvdata(dev); -	struct rohm_regmap_dev *parent = r->parent; -	ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_WAKE_START, -			       &wake, sizeof(wake)); +	ret = regmap_bulk_read(r->regmap, BD70528_REG_RTC_WAKE_START, &wake, +			       sizeof(wake));  	if (ret) {  		dev_err(dev, "Failed to read wake regs\n");  		return ret;  	} -	ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_ALM_START, -			       &alm, sizeof(alm)); +	ret = regmap_bulk_read(r->regmap, BD70528_REG_RTC_ALM_START, &alm, +			       sizeof(alm));  	if (ret) {  		dev_err(dev, "Failed to read alarm regs\n");  		return ret; @@ -292,15 +299,14 @@ static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a)  		wake.ctrl &= ~BD70528_MASK_WAKE_EN;  	} -	ret = regmap_bulk_write(parent->regmap, -				BD70528_REG_RTC_WAKE_START, &wake, +	ret = regmap_bulk_write(r->regmap, BD70528_REG_RTC_WAKE_START, &wake,  				sizeof(wake));  	if (ret) {  		dev_err(dev, "Failed to set wake time\n");  		return ret;  	} -	ret = regmap_bulk_write(parent->regmap, BD70528_REG_RTC_ALM_START, -				&alm, sizeof(alm)); +	ret = regmap_bulk_write(r->regmap, BD70528_REG_RTC_ALM_START, &alm, +				sizeof(alm));  	if (ret)  		dev_err(dev, "Failed to set alarm time\n"); @@ -312,10 +318,9 @@ static int bd71828_read_alarm(struct device *dev, struct rtc_wkalrm *a)  	int ret;  	struct bd71828_rtc_alm alm;  	struct bd70528_rtc *r = dev_get_drvdata(dev); -	struct rohm_regmap_dev *parent = r->parent; -	ret = regmap_bulk_read(parent->regmap, BD71828_REG_RTC_ALM_START, -			       &alm, sizeof(alm)); +	ret = regmap_bulk_read(r->regmap, r->bd718xx_alm_block_start, &alm, +			       sizeof(alm));  	if (ret) {  		dev_err(dev, "Failed to read alarm regs\n");  		return ret; @@ -336,10 +341,9 @@ static int bd70528_read_alarm(struct device *dev, struct rtc_wkalrm *a)  	struct bd70528_rtc_alm alm;  	int ret;  	struct bd70528_rtc *r = dev_get_drvdata(dev); -	struct rohm_regmap_dev *parent = r->parent; -	ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_ALM_START, -			       &alm, sizeof(alm)); +	ret = regmap_bulk_read(r->regmap, BD70528_REG_RTC_ALM_START, &alm, +			       sizeof(alm));  	if (ret) {  		dev_err(dev, "Failed to read alarm regs\n");  		return ret; @@ -360,14 +364,12 @@ static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t)  	int ret, tmpret, old_states;  	struct bd70528_rtc_data rtc_data;  	struct bd70528_rtc *r = dev_get_drvdata(dev); -	struct rohm_regmap_dev *parent = r->parent;  	ret = bd70528_disable_rtc_based_timers(r, &old_states);  	if (ret)  		return ret; -	tmpret = regmap_bulk_read(parent->regmap, -				  r->reg_time_start, &rtc_data, +	tmpret = regmap_bulk_read(r->regmap, r->reg_time_start, &rtc_data,  				  sizeof(rtc_data));  	if (tmpret) {  		dev_err(dev, "Failed to read RTC time registers\n"); @@ -375,8 +377,7 @@ static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t)  	}  	tm2rtc(t, &rtc_data); -	tmpret = regmap_bulk_write(parent->regmap, -				   r->reg_time_start, &rtc_data, +	tmpret = regmap_bulk_write(r->regmap, r->reg_time_start, &rtc_data,  				   sizeof(rtc_data));  	if (tmpret) {  		dev_err(dev, "Failed to set RTC time\n"); @@ -410,13 +411,11 @@ static int bd70528_set_time(struct device *dev, struct rtc_time *t)  static int bd70528_get_time(struct device *dev, struct rtc_time *t)  {  	struct bd70528_rtc *r = dev_get_drvdata(dev); -	struct rohm_regmap_dev *parent = r->parent;  	struct bd70528_rtc_data rtc_data;  	int ret;  	/* read the RTC date and time registers all at once */ -	ret = regmap_bulk_read(parent->regmap, -			       r->reg_time_start, &rtc_data, +	ret = regmap_bulk_read(r->regmap, r->reg_time_start, &rtc_data,  			       sizeof(rtc_data));  	if (ret) {  		dev_err(dev, "Failed to read RTC time (err %d)\n", ret); @@ -443,7 +442,7 @@ static int bd70528_alm_enable(struct device *dev, unsigned int enabled)  		dev_err(dev, "Failed to change wake state\n");  		goto out_unlock;  	} -	ret = regmap_update_bits(r->parent->regmap, BD70528_REG_RTC_ALM_MASK, +	ret = regmap_update_bits(r->regmap, BD70528_REG_RTC_ALM_MASK,  				 BD70528_MASK_ALM_EN, enableval);  	if (ret)  		dev_err(dev, "Failed to change alarm state\n"); @@ -462,8 +461,9 @@ static int bd71828_alm_enable(struct device *dev, unsigned int enabled)  	if (!enabled)  		enableval = 0; -	ret = regmap_update_bits(r->parent->regmap, BD71828_REG_RTC_ALM0_MASK, -				 BD70528_MASK_ALM_EN, enableval); +	ret = regmap_update_bits(r->regmap, r->bd718xx_alm_block_start + +				 BD718XX_ALM_EN_OFFSET, BD70528_MASK_ALM_EN, +				 enableval);  	if (ret)  		dev_err(dev, "Failed to change alarm state\n"); @@ -498,7 +498,6 @@ static int bd70528_probe(struct platform_device *pdev)  {  	struct bd70528_rtc *bd_rtc;  	const struct rtc_class_ops *rtc_ops; -	struct rohm_regmap_dev *parent;  	const char *irq_name;  	int ret;  	struct rtc_device *rtc; @@ -508,20 +507,25 @@ static int bd70528_probe(struct platform_device *pdev)  	u8 hour_reg;  	enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data; -	parent = dev_get_drvdata(pdev->dev.parent); -	if (!parent) { -		dev_err(&pdev->dev, "No MFD driver data\n"); -		return -EINVAL; -	}  	bd_rtc = devm_kzalloc(&pdev->dev, sizeof(*bd_rtc), GFP_KERNEL);  	if (!bd_rtc)  		return -ENOMEM; -	bd_rtc->parent = parent; +	bd_rtc->regmap = dev_get_regmap(pdev->dev.parent, NULL); +	if (!bd_rtc->regmap) { +		dev_err(&pdev->dev, "No regmap\n"); +		return -EINVAL; +	} +  	bd_rtc->dev = &pdev->dev;  	switch (chip) {  	case ROHM_CHIP_TYPE_BD70528: +		bd_rtc->parent = dev_get_drvdata(pdev->dev.parent); +		if (!bd_rtc->parent) { +			dev_err(&pdev->dev, "No MFD data\n"); +			return -EINVAL; +		}  		irq_name = "bd70528-rtc-alm";  		bd_rtc->has_rtc_timers = true;  		bd_rtc->reg_time_start = BD70528_REG_RTC_START; @@ -529,9 +533,28 @@ static int bd70528_probe(struct platform_device *pdev)  		enable_main_irq = true;  		rtc_ops = &bd70528_rtc_ops;  		break; +	case ROHM_CHIP_TYPE_BD71815: +		irq_name = "bd71815-rtc-alm-0"; +		bd_rtc->reg_time_start = BD71815_REG_RTC_START; + +		/* +		 * See also BD718XX_ALM_EN_OFFSET: +		 * This works for BD71828 and BD71815 as they have same offset +		 * between ALM0 start and ALM0_MASK. If new ICs are to be +		 * added this requires proper check as ALM0_MASK is not located +		 * at the end of ALM0 block - but after all ALM blocks so if +		 * amount of ALMs differ the offset to enable/disable is likely +		 * to be incorrect and enable/disable must be given as own +		 * reg address here. +		 */ +		bd_rtc->bd718xx_alm_block_start = BD71815_REG_RTC_ALM_START; +		hour_reg = BD71815_REG_HOUR; +		rtc_ops = &bd71828_rtc_ops; +		break;  	case ROHM_CHIP_TYPE_BD71828:  		irq_name = "bd71828-rtc-alm-0";  		bd_rtc->reg_time_start = BD71828_REG_RTC_START; +		bd_rtc->bd718xx_alm_block_start = BD71828_REG_RTC_ALM_START;  		hour_reg = BD71828_REG_RTC_HOUR;  		rtc_ops = &bd71828_rtc_ops;  		break; @@ -547,7 +570,7 @@ static int bd70528_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, bd_rtc); -	ret = regmap_read(parent->regmap, hour_reg, &hr); +	ret = regmap_read(bd_rtc->regmap, hour_reg, &hr);  	if (ret) {  		dev_err(&pdev->dev, "Failed to reag RTC clock\n"); @@ -595,7 +618,7 @@ static int bd70528_probe(struct platform_device *pdev)  	 *  from sub-registers when IRQ is disabled or freed.  	 */  	if (enable_main_irq) { -		ret = regmap_update_bits(parent->regmap, +		ret = regmap_update_bits(bd_rtc->regmap,  				 BD70528_REG_INT_MAIN_MASK,  				 BD70528_INT_RTC_MASK, 0);  		if (ret) { @@ -610,6 +633,7 @@ static int bd70528_probe(struct platform_device *pdev)  static const struct platform_device_id bd718x7_rtc_id[] = {  	{ "bd70528-rtc", ROHM_CHIP_TYPE_BD70528 },  	{ "bd71828-rtc", ROHM_CHIP_TYPE_BD71828 }, +	{ "bd71815-rtc", ROHM_CHIP_TYPE_BD71815 },  	{ },  };  MODULE_DEVICE_TABLE(platform, bd718x7_rtc_id); diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index cd8e438bc9c4..336cb9aa5e33 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -169,9 +169,6 @@ enum ds_type {  struct ds1307 {  	enum ds_type		type; -	unsigned long		flags; -#define HAS_NVRAM	0		/* bit 0 == sysfs file active */ -#define HAS_ALARM	1		/* bit 1 == irq claimed */  	struct device		*dev;  	struct regmap		*regmap;  	const char		*name; @@ -296,7 +293,11 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)  	t->tm_min = bcd2bin(regs[DS1307_REG_MIN] & 0x7f);  	tmp = regs[DS1307_REG_HOUR] & 0x3f;  	t->tm_hour = bcd2bin(tmp); -	t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1; +	/* rx8130 is bit position, not BCD */ +	if (ds1307->type == rx_8130) +		t->tm_wday = fls(regs[DS1307_REG_WDAY] & 0x7f); +	else +		t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1;  	t->tm_mday = bcd2bin(regs[DS1307_REG_MDAY] & 0x3f);  	tmp = regs[DS1307_REG_MONTH] & 0x1f;  	t->tm_mon = bcd2bin(tmp) - 1; @@ -343,7 +344,11 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)  	regs[DS1307_REG_SECS] = bin2bcd(t->tm_sec);  	regs[DS1307_REG_MIN] = bin2bcd(t->tm_min);  	regs[DS1307_REG_HOUR] = bin2bcd(t->tm_hour); -	regs[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1); +	/* rx8130 is bit position, not BCD */ +	if (ds1307->type == rx_8130) +		regs[DS1307_REG_WDAY] = 1 << t->tm_wday; +	else +		regs[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1);  	regs[DS1307_REG_MDAY] = bin2bcd(t->tm_mday);  	regs[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1); @@ -411,9 +416,6 @@ static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t)  	int			ret;  	u8			regs[9]; -	if (!test_bit(HAS_ALARM, &ds1307->flags)) -		return -EINVAL; -  	/* read all ALARM1, ALARM2, and status registers at once */  	ret = regmap_bulk_read(ds1307->regmap, DS1339_REG_ALARM1_SECS,  			       regs, sizeof(regs)); @@ -454,9 +456,6 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t)  	u8			control, status;  	int			ret; -	if (!test_bit(HAS_ALARM, &ds1307->flags)) -		return -EINVAL; -  	dev_dbg(dev, "%s secs=%d, mins=%d, "  		"hours=%d, mday=%d, enabled=%d, pending=%d\n",  		"alarm set", t->time.tm_sec, t->time.tm_min, @@ -512,9 +511,6 @@ static int ds1307_alarm_irq_enable(struct device *dev, unsigned int enabled)  {  	struct ds1307		*ds1307 = dev_get_drvdata(dev); -	if (!test_bit(HAS_ALARM, &ds1307->flags)) -		return -ENOTTY; -  	return regmap_update_bits(ds1307->regmap, DS1337_REG_CONTROL,  				  DS1337_BIT_A1IE,  				  enabled ? DS1337_BIT_A1IE : 0); @@ -592,9 +588,6 @@ static int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t)  	u8 ald[3], ctl[3];  	int ret; -	if (!test_bit(HAS_ALARM, &ds1307->flags)) -		return -EINVAL; -  	/* Read alarm registers. */  	ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_ALARM_MIN, ald,  			       sizeof(ald)); @@ -634,9 +627,6 @@ static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t)  	u8 ald[3], ctl[3];  	int ret; -	if (!test_bit(HAS_ALARM, &ds1307->flags)) -		return -EINVAL; -  	dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d "  		"enabled=%d pending=%d\n", __func__,  		t->time.tm_sec, t->time.tm_min, t->time.tm_hour, @@ -681,9 +671,6 @@ static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled)  	struct ds1307 *ds1307 = dev_get_drvdata(dev);  	int ret, reg; -	if (!test_bit(HAS_ALARM, &ds1307->flags)) -		return -EINVAL; -  	ret = regmap_read(ds1307->regmap, RX8130_REG_CONTROL0, ®);  	if (ret < 0)  		return ret; @@ -735,9 +722,6 @@ static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t)  	u8 regs[10];  	int ret; -	if (!test_bit(HAS_ALARM, &ds1307->flags)) -		return -EINVAL; -  	/* Read control and alarm 0 registers. */  	ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs,  			       sizeof(regs)); @@ -793,9 +777,6 @@ static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t)  	unsigned char regs[10];  	int wday, ret; -	if (!test_bit(HAS_ALARM, &ds1307->flags)) -		return -EINVAL; -  	wday = mcp794xx_alm_weekday(dev, &t->time);  	if (wday < 0)  		return wday; @@ -842,9 +823,6 @@ static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled)  {  	struct ds1307 *ds1307 = dev_get_drvdata(dev); -	if (!test_bit(HAS_ALARM, &ds1307->flags)) -		return -EINVAL; -  	return regmap_update_bits(ds1307->regmap, MCP794XX_REG_CONTROL,  				  MCP794XX_BIT_ALM0_EN,  				  enabled ? MCP794XX_BIT_ALM0_EN : 0); @@ -1641,7 +1619,7 @@ static int ds3231_clks_register(struct ds1307 *ds1307)  		 * Interrupt signal due to alarm conditions and square-wave  		 * output share same pin, so don't initialize both.  		 */ -		if (i == DS3231_CLK_SQW && test_bit(HAS_ALARM, &ds1307->flags)) +		if (i == DS3231_CLK_SQW && test_bit(RTC_FEATURE_ALARM, ds1307->rtc->features))  			continue;  		init.name = ds3231_clks_names[i]; @@ -1964,15 +1942,15 @@ static int ds1307_probe(struct i2c_client *client,  			     bin2bcd(tmp));  	} -	if (want_irq || ds1307_can_wakeup_device) { -		device_set_wakeup_capable(ds1307->dev, true); -		set_bit(HAS_ALARM, &ds1307->flags); -	} -  	ds1307->rtc = devm_rtc_allocate_device(ds1307->dev);  	if (IS_ERR(ds1307->rtc))  		return PTR_ERR(ds1307->rtc); +	if (want_irq || ds1307_can_wakeup_device) +		device_set_wakeup_capable(ds1307->dev, true); +	else +		clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features); +  	if (ds1307_can_wakeup_device && !want_irq) {  		dev_info(ds1307->dev,  			 "'wakeup-source' is set, request for an IRQ is disabled!\n"); @@ -1988,7 +1966,7 @@ static int ds1307_probe(struct i2c_client *client,  		if (err) {  			client->irq = 0;  			device_set_wakeup_capable(ds1307->dev, false); -			clear_bit(HAS_ALARM, &ds1307->flags); +			clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);  			dev_err(ds1307->dev, "unable to request IRQ!\n");  		} else {  			dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq); diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index bda884333082..1109cad83838 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -104,12 +104,6 @@ rtc_write(uint8_t val, uint32_t reg)  	writeb(val, ds1511_base + (reg * reg_spacing));  } -static inline void -rtc_write_alarm(uint8_t val, enum ds1511reg reg) -{ -	rtc_write((val | 0x80), reg); -} -  static noinline uint8_t  rtc_read(enum ds1511reg reg)  { diff --git a/drivers/rtc/rtc-fsl-ftm-alarm.c b/drivers/rtc/rtc-fsl-ftm-alarm.c index 57cc09d0a806..c0df49fb978c 100644 --- a/drivers/rtc/rtc-fsl-ftm-alarm.c +++ b/drivers/rtc/rtc-fsl-ftm-alarm.c @@ -310,6 +310,7 @@ static const struct of_device_id ftm_rtc_match[] = {  	{ .compatible = "fsl,lx2160a-ftm-alarm", },  	{ },  }; +MODULE_DEVICE_TABLE(of, ftm_rtc_match);  static const struct acpi_device_id ftm_imx_acpi_ids[] = {  	{"NXP0014",}, diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c index 1b42ee0758d2..47cd12db2356 100644 --- a/drivers/rtc/rtc-hid-sensor-time.c +++ b/drivers/rtc/rtc-hid-sensor-time.c @@ -238,7 +238,9 @@ static int hid_time_probe(struct platform_device *pdev)  	ret = hid_sensor_parse_common_attributes(hsdev,  				HID_USAGE_SENSOR_TIME, -				&time_state->common_attributes); +				&time_state->common_attributes, +				NULL, +				0);  	if (ret) {  		dev_err(&pdev->dev, "failed to setup common attributes!\n");  		return ret; diff --git a/drivers/rtc/rtc-imx-sc.c b/drivers/rtc/rtc-imx-sc.c index cc9fbab49999..814d516645e2 100644 --- a/drivers/rtc/rtc-imx-sc.c +++ b/drivers/rtc/rtc-imx-sc.c @@ -80,16 +80,6 @@ static int imx_sc_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)  	return imx_scu_irq_group_enable(SC_IRQ_GROUP_RTC, SC_IRQ_RTC, enable);  } -static int imx_sc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ -	/* -	 * SCU firmware does NOT provide read alarm API, but .read_alarm -	 * callback is required by RTC framework to support alarm function, -	 * so just return here. -	 */ -	return 0; -} -  static int imx_sc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)  {  	struct imx_sc_msg_timer_rtc_set_alarm msg; @@ -127,7 +117,6 @@ static int imx_sc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)  static const struct rtc_class_ops imx_sc_rtc_ops = {  	.read_time = imx_sc_rtc_read_time,  	.set_time = imx_sc_rtc_set_time, -	.read_alarm = imx_sc_rtc_read_alarm,  	.set_alarm = imx_sc_rtc_set_alarm,  	.alarm_irq_enable = imx_sc_rtc_alarm_irq_enable,  }; diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index c2692da74e09..c1806f4d68e7 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -840,19 +840,17 @@ static int __exit dryice_rtc_remove(struct platform_device *pdev)  	return 0;  } -#ifdef CONFIG_OF  static const struct of_device_id dryice_dt_ids[] = {  	{ .compatible = "fsl,imx25-rtc" },  	{ /* sentinel */ }  };  MODULE_DEVICE_TABLE(of, dryice_dt_ids); -#endif  static struct platform_driver dryice_rtc_driver = {  	.driver = {  		   .name = "imxdi_rtc", -		   .of_match_table = of_match_ptr(dryice_dt_ids), +		   .of_match_table = dryice_dt_ids,  		   },  	.remove = __exit_p(dryice_rtc_remove),  }; diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 1d2e99a70fce..f0f6b9b6daec 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -421,7 +421,7 @@ static int m48t59_rtc_probe(struct platform_device *pdev)  	/* Try to get irq number. We also can work in  	 * the mode without IRQ.  	 */ -	m48t59->irq = platform_get_irq(pdev, 0); +	m48t59->irq = platform_get_irq_optional(pdev, 0);  	if (m48t59->irq <= 0)  		m48t59->irq = NO_IRQ; diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index db57dda7ab97..0f08f22df869 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c @@ -415,7 +415,7 @@ static int mxc_rtc_probe(struct platform_device *pdev)  static struct platform_driver mxc_rtc_driver = {  	.driver = {  		   .name	= "mxc_rtc", -		   .of_match_table = of_match_ptr(imx_rtc_dt_ids), +		   .of_match_table = imx_rtc_dt_ids,  	},  	.probe = mxc_rtc_probe,  }; diff --git a/drivers/rtc/rtc-ntxec.c b/drivers/rtc/rtc-ntxec.c new file mode 100644 index 000000000000..850ca49186fd --- /dev/null +++ b/drivers/rtc/rtc-ntxec.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * The Netronix embedded controller is a microcontroller found in some + * e-book readers designed by the original design manufacturer Netronix, Inc. + * It contains RTC, battery monitoring, system power management, and PWM + * functionality. + * + * This driver implements access to the RTC time and date. + * + * Copyright 2020 Jonathan Neuschäfer <j.neuschaefer@gmx.net> + */ + +#include <linux/mfd/ntxec.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/rtc.h> +#include <linux/types.h> + +struct ntxec_rtc { +	struct device *dev; +	struct ntxec *ec; +}; + +#define NTXEC_REG_WRITE_YEAR	0x10 +#define NTXEC_REG_WRITE_MONTH	0x11 +#define NTXEC_REG_WRITE_DAY	0x12 +#define NTXEC_REG_WRITE_HOUR	0x13 +#define NTXEC_REG_WRITE_MINUTE	0x14 +#define NTXEC_REG_WRITE_SECOND	0x15 + +#define NTXEC_REG_READ_YEAR_MONTH	0x20 +#define NTXEC_REG_READ_MDAY_HOUR	0x21 +#define NTXEC_REG_READ_MINUTE_SECOND	0x23 + +static int ntxec_read_time(struct device *dev, struct rtc_time *tm) +{ +	struct ntxec_rtc *rtc = dev_get_drvdata(dev); +	unsigned int value; +	int res; + +retry: +	res = regmap_read(rtc->ec->regmap, NTXEC_REG_READ_MINUTE_SECOND, &value); +	if (res < 0) +		return res; + +	tm->tm_min = value >> 8; +	tm->tm_sec = value & 0xff; + +	res = regmap_read(rtc->ec->regmap, NTXEC_REG_READ_MDAY_HOUR, &value); +	if (res < 0) +		return res; + +	tm->tm_mday = value >> 8; +	tm->tm_hour = value & 0xff; + +	res = regmap_read(rtc->ec->regmap, NTXEC_REG_READ_YEAR_MONTH, &value); +	if (res < 0) +		return res; + +	tm->tm_year = (value >> 8) + 100; +	tm->tm_mon = (value & 0xff) - 1; + +	/* +	 * Read the minutes/seconds field again. If it changed since the first +	 * read, we can't assume that the values read so far are consistent, +	 * and should start from the beginning. +	 */ +	res = regmap_read(rtc->ec->regmap, NTXEC_REG_READ_MINUTE_SECOND, &value); +	if (res < 0) +		return res; + +	if (tm->tm_min != value >> 8 || tm->tm_sec != (value & 0xff)) +		goto retry; + +	return 0; +} + +static int ntxec_set_time(struct device *dev, struct rtc_time *tm) +{ +	struct ntxec_rtc *rtc = dev_get_drvdata(dev); + +	/* +	 * To avoid time overflows while we're writing the full date/time, +	 * set the seconds field to zero before doing anything else. For the +	 * next 59 seconds (plus however long it takes until the RTC's next +	 * update of the second field), the seconds field will not overflow +	 * into the other fields. +	 */ +	struct reg_sequence regs[] = { +		{ NTXEC_REG_WRITE_SECOND, ntxec_reg8(0) }, +		{ NTXEC_REG_WRITE_YEAR, ntxec_reg8(tm->tm_year - 100) }, +		{ NTXEC_REG_WRITE_MONTH, ntxec_reg8(tm->tm_mon + 1) }, +		{ NTXEC_REG_WRITE_DAY, ntxec_reg8(tm->tm_mday) }, +		{ NTXEC_REG_WRITE_HOUR, ntxec_reg8(tm->tm_hour) }, +		{ NTXEC_REG_WRITE_MINUTE, ntxec_reg8(tm->tm_min) }, +		{ NTXEC_REG_WRITE_SECOND, ntxec_reg8(tm->tm_sec) }, +	}; + +	return regmap_multi_reg_write(rtc->ec->regmap, regs, ARRAY_SIZE(regs)); +} + +static const struct rtc_class_ops ntxec_rtc_ops = { +	.read_time = ntxec_read_time, +	.set_time = ntxec_set_time, +}; + +static int ntxec_rtc_probe(struct platform_device *pdev) +{ +	struct rtc_device *dev; +	struct ntxec_rtc *rtc; + +	pdev->dev.of_node = pdev->dev.parent->of_node; + +	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); +	if (!rtc) +		return -ENOMEM; + +	rtc->dev = &pdev->dev; +	rtc->ec = dev_get_drvdata(pdev->dev.parent); +	platform_set_drvdata(pdev, rtc); + +	dev = devm_rtc_allocate_device(&pdev->dev); +	if (IS_ERR(dev)) +		return PTR_ERR(dev); + +	dev->ops = &ntxec_rtc_ops; +	dev->range_min = RTC_TIMESTAMP_BEGIN_2000; +	dev->range_max = 9025257599LL; /* 2255-12-31 23:59:59 */ + +	return devm_rtc_register_device(dev); +} + +static struct platform_driver ntxec_rtc_driver = { +	.driver = { +		.name = "ntxec-rtc", +	}, +	.probe = ntxec_rtc_probe, +}; +module_platform_driver(ntxec_rtc_driver); + +MODULE_AUTHOR("Jonathan Neuschäfer <j.neuschaefer@gmx.net>"); +MODULE_DESCRIPTION("RTC driver for Netronix EC"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ntxec-rtc"); diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index dc7db2477f88..d46e0f0cc502 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -786,8 +786,7 @@ static int omap_rtc_probe(struct platform_device *pdev)  	/* enable RTC functional clock */  	if (rtc->type->has_32kclk_en) {  		reg = rtc_read(rtc, OMAP_RTC_OSC_REG); -		rtc_writel(rtc, OMAP_RTC_OSC_REG, -				reg | OMAP_RTC_OSC_32KCLK_EN); +		rtc_write(rtc, OMAP_RTC_OSC_REG, reg | OMAP_RTC_OSC_32KCLK_EN);  	}  	/* clear old status */ @@ -845,7 +844,7 @@ static int omap_rtc_probe(struct platform_device *pdev)  		reg = rtc_read(rtc, OMAP_RTC_OSC_REG);  		reg &= ~OMAP_RTC_OSC_OSC32K_GZ_DISABLE;  		reg |= OMAP_RTC_OSC_32KCLK_EN | OMAP_RTC_OSC_SEL_32KCLK_SRC; -		rtc_writel(rtc, OMAP_RTC_OSC_REG, reg); +		rtc_write(rtc, OMAP_RTC_OSC_REG, reg);  	}  	rtc->type->lock(rtc); diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index aef6c1ee8bb0..82becae14229 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -478,6 +478,7 @@ static struct clk *pcf85063_clkout_register_clk(struct pcf85063 *pcf85063)  {  	struct clk *clk;  	struct clk_init_data init; +	struct device_node *node = pcf85063->rtc->dev.parent->of_node;  	init.name = "pcf85063-clkout";  	init.ops = &pcf85063_clkout_ops; @@ -487,15 +488,13 @@ static struct clk *pcf85063_clkout_register_clk(struct pcf85063 *pcf85063)  	pcf85063->clkout_hw.init = &init;  	/* optional override of the clockname */ -	of_property_read_string(pcf85063->rtc->dev.of_node, -				"clock-output-names", &init.name); +	of_property_read_string(node, "clock-output-names", &init.name);  	/* register the clock */  	clk = devm_clk_register(&pcf85063->rtc->dev, &pcf85063->clkout_hw);  	if (!IS_ERR(clk)) -		of_clk_add_provider(pcf85063->rtc->dev.of_node, -				    of_clk_src_simple_get, clk); +		of_clk_add_provider(node, of_clk_src_simple_get, clk);  	return clk;  } diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index 5e1e7b2a8c9a..740e2136ca98 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c @@ -8,12 +8,15 @@  #include <linux/module.h>  #include <linux/rtc.h>  #include <linux/of.h> - -#define DRIVER_NAME "rtc-pcf8523" +#include <linux/pm_wakeirq.h>  #define REG_CONTROL1 0x00  #define REG_CONTROL1_CAP_SEL BIT(7)  #define REG_CONTROL1_STOP    BIT(5) +#define REG_CONTROL1_AIE    BIT(1) + +#define REG_CONTROL2 0x01 +#define REG_CONTROL2_AF BIT(3)  #define REG_CONTROL3 0x02  #define REG_CONTROL3_PM_BLD BIT(7) /* battery low detection disabled */ @@ -32,9 +35,22 @@  #define REG_MONTHS   0x08  #define REG_YEARS    0x09 +#define REG_MINUTE_ALARM	0x0a +#define REG_HOUR_ALARM		0x0b +#define REG_DAY_ALARM		0x0c +#define REG_WEEKDAY_ALARM	0x0d +#define ALARM_DIS BIT(7) +  #define REG_OFFSET   0x0e  #define REG_OFFSET_MODE BIT(7) +#define REG_TMR_CLKOUT_CTRL 0x0f + +struct pcf8523 { +	struct rtc_device *rtc; +	struct i2c_client *client; +}; +  static int pcf8523_read(struct i2c_client *client, u8 reg, u8 *valuep)  {  	struct i2c_msg msgs[2]; @@ -140,6 +156,27 @@ static int pcf8523_set_pm(struct i2c_client *client, u8 pm)  	return 0;  } +static irqreturn_t pcf8523_irq(int irq, void *dev_id) +{ +	struct pcf8523 *pcf8523 = i2c_get_clientdata(dev_id); +	u8 value; +	int err; + +	err = pcf8523_read(pcf8523->client, REG_CONTROL2, &value); +	if (err < 0) +		return IRQ_HANDLED; + +	if (value & REG_CONTROL2_AF) { +		value &= ~REG_CONTROL2_AF; +		pcf8523_write(pcf8523->client, REG_CONTROL2, value); +		rtc_update_irq(pcf8523->rtc, 1, RTC_IRQF | RTC_AF); + +		return IRQ_HANDLED; +	} + +	return IRQ_NONE; +} +  static int pcf8523_stop_rtc(struct i2c_client *client)  {  	u8 value; @@ -259,11 +296,118 @@ static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)  	return pcf8523_start_rtc(client);  } +static int pcf8523_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm) +{ +	struct i2c_client *client = to_i2c_client(dev); +	u8 start = REG_MINUTE_ALARM, regs[4]; +	struct i2c_msg msgs[2]; +	u8 value; +	int err; + +	msgs[0].addr = client->addr; +	msgs[0].flags = 0; +	msgs[0].len = 1; +	msgs[0].buf = &start; + +	msgs[1].addr = client->addr; +	msgs[1].flags = I2C_M_RD; +	msgs[1].len = sizeof(regs); +	msgs[1].buf = regs; + +	err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); +	if (err < 0) +		return err; + +	tm->time.tm_sec = 0; +	tm->time.tm_min = bcd2bin(regs[0] & 0x7F); +	tm->time.tm_hour = bcd2bin(regs[1] & 0x3F); +	tm->time.tm_mday = bcd2bin(regs[2] & 0x3F); +	tm->time.tm_wday = bcd2bin(regs[3] & 0x7); + +	err = pcf8523_read(client, REG_CONTROL1, &value); +	if (err < 0) +		return err; +	tm->enabled = !!(value & REG_CONTROL1_AIE); + +	err = pcf8523_read(client, REG_CONTROL2, &value); +	if (err < 0) +		return err; +	tm->pending = !!(value & REG_CONTROL2_AF); + +	return 0; +} + +static int pcf8523_irq_enable(struct device *dev, unsigned int enabled) +{ +	struct i2c_client *client = to_i2c_client(dev); +	u8 value; +	int err; + +	err = pcf8523_read(client, REG_CONTROL1, &value); +	if (err < 0) +		return err; + +	value &= REG_CONTROL1_AIE; + +	if (enabled) +		value |= REG_CONTROL1_AIE; + +	err = pcf8523_write(client, REG_CONTROL1, value); +	if (err < 0) +		return err; + +	return 0; +} + +static int pcf8523_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm) +{ +	struct i2c_client *client = to_i2c_client(dev); +	struct i2c_msg msg; +	u8 regs[5]; +	int err; + +	err = pcf8523_irq_enable(dev, 0); +	if (err) +		return err; + +	err = pcf8523_write(client, REG_CONTROL2, 0); +	if (err < 0) +		return err; + +	/* The alarm has no seconds, round up to nearest minute */ +	if (tm->time.tm_sec) { +		time64_t alarm_time = rtc_tm_to_time64(&tm->time); + +		alarm_time += 60 - tm->time.tm_sec; +		rtc_time64_to_tm(alarm_time, &tm->time); +	} + +	regs[0] = REG_MINUTE_ALARM; +	regs[1] = bin2bcd(tm->time.tm_min); +	regs[2] = bin2bcd(tm->time.tm_hour); +	regs[3] = bin2bcd(tm->time.tm_mday); +	regs[4] = ALARM_DIS; +	msg.addr = client->addr; +	msg.flags = 0; +	msg.len = sizeof(regs); +	msg.buf = regs; +	err = i2c_transfer(client->adapter, &msg, 1); +	if (err < 0) +		return err; + +	if (tm->enabled) +		return pcf8523_irq_enable(dev, tm->enabled); + +	return 0; +} +  #ifdef CONFIG_RTC_INTF_DEV  static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd,  			     unsigned long arg)  {  	struct i2c_client *client = to_i2c_client(dev); +	unsigned int flags = 0; +	u8 value;  	int ret;  	switch (cmd) { @@ -272,9 +416,16 @@ static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd,  		if (ret < 0)  			return ret;  		if (ret) -			ret = RTC_VL_BACKUP_LOW; +			flags |= RTC_VL_BACKUP_LOW; -		return put_user(ret, (unsigned int __user *)arg); +		ret = pcf8523_read(client, REG_SECONDS, &value); +		if (ret < 0) +			return ret; + +		if (value & REG_SECONDS_OS) +			flags |= RTC_VL_DATA_INVALID; + +		return put_user(flags, (unsigned int __user *)arg);  	default:  		return -ENOIOCTLCMD; @@ -322,6 +473,9 @@ static int pcf8523_rtc_set_offset(struct device *dev, long offset)  static const struct rtc_class_ops pcf8523_rtc_ops = {  	.read_time = pcf8523_rtc_read_time,  	.set_time = pcf8523_rtc_set_time, +	.read_alarm = pcf8523_rtc_read_alarm, +	.set_alarm = pcf8523_rtc_set_alarm, +	.alarm_irq_enable = pcf8523_irq_enable,  	.ioctl = pcf8523_rtc_ioctl,  	.read_offset = pcf8523_rtc_read_offset,  	.set_offset = pcf8523_rtc_set_offset, @@ -330,12 +484,21 @@ static const struct rtc_class_ops pcf8523_rtc_ops = {  static int pcf8523_probe(struct i2c_client *client,  			 const struct i2c_device_id *id)  { +	struct pcf8523 *pcf8523;  	struct rtc_device *rtc; +	bool wakeup_source = false;  	int err;  	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))  		return -ENODEV; +	pcf8523 = devm_kzalloc(&client->dev, sizeof(struct pcf8523), GFP_KERNEL); +	if (!pcf8523) +		return -ENOMEM; + +	i2c_set_clientdata(client, pcf8523); +	pcf8523->client = client; +  	err = pcf8523_load_capacitance(client);  	if (err < 0)  		dev_warn(&client->dev, "failed to set xtal load capacitance: %d", @@ -349,9 +512,32 @@ static int pcf8523_probe(struct i2c_client *client,  	if (IS_ERR(rtc))  		return PTR_ERR(rtc); +	pcf8523->rtc = rtc;  	rtc->ops = &pcf8523_rtc_ops;  	rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;  	rtc->range_max = RTC_TIMESTAMP_END_2099; +	rtc->uie_unsupported = 1; + +	if (client->irq > 0) { +		err = pcf8523_write(client, REG_TMR_CLKOUT_CTRL, 0x38); +		if (err < 0) +			return err; + +		err = devm_request_threaded_irq(&client->dev, client->irq, +						NULL, pcf8523_irq, +						IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_LOW, +						dev_name(&rtc->dev), client); +		if (err) +			return err; + +		dev_pm_set_wake_irq(&client->dev, client->irq); +	} + +#ifdef CONFIG_OF +	wakeup_source = of_property_read_bool(client->dev.of_node, "wakeup-source"); +#endif +	if (client->irq > 0 || wakeup_source) +		device_init_wakeup(&client->dev, true);  	return devm_rtc_register_device(rtc);  } @@ -373,7 +559,7 @@ MODULE_DEVICE_TABLE(of, pcf8523_of_match);  static struct i2c_driver pcf8523_driver = {  	.driver = { -		.name = DRIVER_NAME, +		.name = "rtc-pcf8523",  		.of_match_table = of_match_ptr(pcf8523_of_match),  	},  	.probe = pcf8523_probe, diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index eb206597a8fa..29a1c65661e9 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -445,6 +445,16 @@ static const struct pm8xxx_rtc_regs pm8941_regs = {  	.alarm_en	= BIT(7),  }; +static const struct pm8xxx_rtc_regs pmk8350_regs = { +	.ctrl		= 0x6146, +	.write		= 0x6140, +	.read		= 0x6148, +	.alarm_rw	= 0x6240, +	.alarm_ctrl	= 0x6246, +	.alarm_ctrl2	= 0x6248, +	.alarm_en	= BIT(7), +}; +  /*   * Hardcoded RTC bases until IORESOURCE_REG mapping is figured out   */ @@ -453,6 +463,7 @@ static const struct of_device_id pm8xxx_id_table[] = {  	{ .compatible = "qcom,pm8018-rtc", .data = &pm8921_regs },  	{ .compatible = "qcom,pm8058-rtc", .data = &pm8058_regs },  	{ .compatible = "qcom,pm8941-rtc", .data = &pm8941_regs }, +	{ .compatible = "qcom,pmk8350-rtc", .data = &pmk8350_regs },  	{ },  };  MODULE_DEVICE_TABLE(of, pm8xxx_id_table); diff --git a/drivers/rtc/rtc-rv3028.c b/drivers/rtc/rtc-rv3028.c index 0c48d980d06a..12c807306893 100644 --- a/drivers/rtc/rtc-rv3028.c +++ b/drivers/rtc/rtc-rv3028.c @@ -320,7 +320,7 @@ static int rv3028_get_time(struct device *dev, struct rtc_time *tm)  	tm->tm_sec  = bcd2bin(date[RV3028_SEC] & 0x7f);  	tm->tm_min  = bcd2bin(date[RV3028_MIN] & 0x7f);  	tm->tm_hour = bcd2bin(date[RV3028_HOUR] & 0x3f); -	tm->tm_wday = ilog2(date[RV3028_WDAY] & 0x7f); +	tm->tm_wday = date[RV3028_WDAY] & 0x7f;  	tm->tm_mday = bcd2bin(date[RV3028_DAY] & 0x3f);  	tm->tm_mon  = bcd2bin(date[RV3028_MONTH] & 0x1f) - 1;  	tm->tm_year = bcd2bin(date[RV3028_YEAR]) + 100; @@ -337,7 +337,7 @@ static int rv3028_set_time(struct device *dev, struct rtc_time *tm)  	date[RV3028_SEC]   = bin2bcd(tm->tm_sec);  	date[RV3028_MIN]   = bin2bcd(tm->tm_min);  	date[RV3028_HOUR]  = bin2bcd(tm->tm_hour); -	date[RV3028_WDAY]  = 1 << (tm->tm_wday); +	date[RV3028_WDAY]  = tm->tm_wday;  	date[RV3028_DAY]   = bin2bcd(tm->tm_mday);  	date[RV3028_MONTH] = bin2bcd(tm->tm_mon + 1);  	date[RV3028_YEAR]  = bin2bcd(tm->tm_year - 100); diff --git a/drivers/rtc/rtc-rx6110.c b/drivers/rtc/rtc-rx6110.c index 79161d4c6ce4..f4d425002f7f 100644 --- a/drivers/rtc/rtc-rx6110.c +++ b/drivers/rtc/rtc-rx6110.c @@ -447,6 +447,12 @@ static int rx6110_i2c_probe(struct i2c_client *client,  	return rx6110_probe(rx6110, &client->dev);  } +static const struct acpi_device_id rx6110_i2c_acpi_match[] = { +	{ "SECC6110" }, +	{ } +}; +MODULE_DEVICE_TABLE(acpi, rx6110_i2c_acpi_match); +  static const struct i2c_device_id rx6110_i2c_id[] = {  	{ "rx6110", 0 },  	{ } @@ -456,6 +462,7 @@ MODULE_DEVICE_TABLE(i2c, rx6110_i2c_id);  static struct i2c_driver rx6110_i2c_driver = {  	.driver = {  		.name = RX6110_DRIVER_NAME, +		.acpi_match_table = rx6110_i2c_acpi_match,  	},  	.probe		= rx6110_i2c_probe,  	.id_table	= rx6110_i2c_id, diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index 80b66f16db89..038269a6b08c 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -713,16 +713,10 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)  static int s5m_rtc_probe(struct platform_device *pdev)  {  	struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent); -	struct sec_platform_data *pdata = s5m87xx->pdata;  	struct s5m_rtc_info *info;  	const struct regmap_config *regmap_cfg;  	int ret, alarm_irq; -	if (!pdata) { -		dev_err(pdev->dev.parent, "Platform data not supplied\n"); -		return -ENODEV; -	} -  	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);  	if (!info)  		return -ENOMEM; diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index 833daeb7b60e..ee721e53c155 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c @@ -153,12 +153,12 @@ static void rtc_wait_not_busy(struct spear_rtc_config *config)  static irqreturn_t spear_rtc_irq(int irq, void *dev_id)  {  	struct spear_rtc_config *config = dev_id; -	unsigned long flags, events = 0; +	unsigned long events = 0;  	unsigned int irq_data; -	spin_lock_irqsave(&config->lock, flags); +	spin_lock(&config->lock);  	irq_data = readl(config->ioaddr + STATUS_REG); -	spin_unlock_irqrestore(&config->lock, flags); +	spin_unlock(&config->lock);  	if ((irq_data & RTC_INT_MASK)) {  		spear_rtc_clear_interrupt(config); diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 288abb1abdb8..bc89c62ccb9b 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -18,6 +18,7 @@  #include <linux/rtc.h>  #include <linux/bcd.h>  #include <linux/math64.h> +#include <linux/property.h>  #include <linux/platform_device.h>  #include <linux/interrupt.h>  #include <linux/mfd/tps65910.h> diff --git a/drivers/rtc/sysfs.c b/drivers/rtc/sysfs.c index 8a957d31a1a4..74026f67fdfb 100644 --- a/drivers/rtc/sysfs.c +++ b/drivers/rtc/sysfs.c @@ -273,7 +273,7 @@ static bool rtc_does_wakealarm(struct rtc_device *rtc)  	if (!device_can_wakeup(rtc->dev.parent))  		return false; -	return rtc->ops->set_alarm != NULL; +	return !!test_bit(RTC_FEATURE_ALARM, rtc->features);  }  static umode_t rtc_attr_is_visible(struct kobject *kobj, | 
