diff options
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/rtc-da9063.c | 19 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1307.c | 44 | ||||
| -rw-r--r-- | drivers/rtc/rtc-rk808.c | 48 | 
3 files changed, 61 insertions, 50 deletions
| diff --git a/drivers/rtc/rtc-da9063.c b/drivers/rtc/rtc-da9063.c index 284b587da65c..d6c853bbfa9f 100644 --- a/drivers/rtc/rtc-da9063.c +++ b/drivers/rtc/rtc-da9063.c @@ -483,24 +483,23 @@ static int da9063_rtc_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, rtc); +	rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, DA9063_DRVNAME_RTC, +					   &da9063_rtc_ops, THIS_MODULE); +	if (IS_ERR(rtc->rtc_dev)) +		return PTR_ERR(rtc->rtc_dev); + +	da9063_data_to_tm(data, &rtc->alarm_time, rtc); +	rtc->rtc_sync = false; +  	irq_alarm = platform_get_irq_byname(pdev, "ALARM");  	ret = devm_request_threaded_irq(&pdev->dev, irq_alarm, NULL,  					da9063_alarm_event,  					IRQF_TRIGGER_LOW | IRQF_ONESHOT,  					"ALARM", rtc); -	if (ret) { +	if (ret)  		dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n",  			irq_alarm, ret); -		return ret; -	} - -	rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, DA9063_DRVNAME_RTC, -					   &da9063_rtc_ops, THIS_MODULE); -	if (IS_ERR(rtc->rtc_dev)) -		return PTR_ERR(rtc->rtc_dev); -	da9063_data_to_tm(data, &rtc->alarm_time, rtc); -	rtc->rtc_sync = false;  	return ret;  } diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 188006c55ce0..aa705bb4748c 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -15,9 +15,6 @@  #include <linux/i2c.h>  #include <linux/init.h>  #include <linux/module.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> -#include <linux/pm_wakeirq.h>  #include <linux/rtc/ds1307.h>  #include <linux/rtc.h>  #include <linux/slab.h> @@ -117,7 +114,6 @@ struct ds1307 {  #define HAS_ALARM	1		/* bit 1 == irq claimed */  	struct i2c_client	*client;  	struct rtc_device	*rtc; -	int			wakeirq;  	s32 (*read_block_data)(const struct i2c_client *client, u8 command,  			       u8 length, u8 *values);  	s32 (*write_block_data)(const struct i2c_client *client, u8 command, @@ -1138,7 +1134,10 @@ read_rtc:  				bin2bcd(tmp));  	} -	device_set_wakeup_capable(&client->dev, want_irq); +	if (want_irq) { +		device_set_wakeup_capable(&client->dev, true); +		set_bit(HAS_ALARM, &ds1307->flags); +	}  	ds1307->rtc = devm_rtc_device_register(&client->dev, client->name,  				rtc_ops, THIS_MODULE);  	if (IS_ERR(ds1307->rtc)) { @@ -1146,43 +1145,19 @@ read_rtc:  	}  	if (want_irq) { -		struct device_node *node = client->dev.of_node; -  		err = devm_request_threaded_irq(&client->dev,  						client->irq, NULL, irq_handler,  						IRQF_SHARED | IRQF_ONESHOT,  						ds1307->rtc->name, client);  		if (err) {  			client->irq = 0; +			device_set_wakeup_capable(&client->dev, false); +			clear_bit(HAS_ALARM, &ds1307->flags);  			dev_err(&client->dev, "unable to request IRQ!\n"); -			goto no_irq; -		} - -		set_bit(HAS_ALARM, &ds1307->flags); -		dev_dbg(&client->dev, "got IRQ %d\n", client->irq); - -		/* Currently supported by OF code only! */ -		if (!node) -			goto no_irq; - -		err = of_irq_get(node, 1); -		if (err <= 0) { -			if (err == -EPROBE_DEFER) -				goto exit; -			goto no_irq; -		} -		ds1307->wakeirq = err; - -		err = dev_pm_set_dedicated_wake_irq(&client->dev, -						    ds1307->wakeirq); -		if (err) { -			dev_err(&client->dev, "unable to setup wakeIRQ %d!\n", -				err); -			goto exit; -		} +		} else +			dev_dbg(&client->dev, "got IRQ %d\n", client->irq);  	} -no_irq:  	if (chip->nvram_size) {  		ds1307->nvram = devm_kzalloc(&client->dev, @@ -1226,9 +1201,6 @@ static int ds1307_remove(struct i2c_client *client)  {  	struct ds1307 *ds1307 = i2c_get_clientdata(client); -	if (ds1307->wakeirq) -		dev_pm_clear_wake_irq(&client->dev); -  	if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags))  		sysfs_remove_bin_file(&client->dev.kobj, ds1307->nvram); diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c index 91ca0bc1b484..35c9aada07c8 100644 --- a/drivers/rtc/rtc-rk808.c +++ b/drivers/rtc/rtc-rk808.c @@ -56,6 +56,42 @@ struct rk808_rtc {  	int irq;  }; +/* + * The Rockchip calendar used by the RK808 counts November with 31 days. We use + * these translation functions to convert its dates to/from the Gregorian + * calendar used by the rest of the world. We arbitrarily define Jan 1st, 2016 + * as the day when both calendars were in sync, and treat all other dates + * relative to that. + * NOTE: Other system software (e.g. firmware) that reads the same hardware must + * implement this exact same conversion algorithm, with the same anchor date. + */ +static time64_t nov2dec_transitions(struct rtc_time *tm) +{ +	return (tm->tm_year + 1900) - 2016 + (tm->tm_mon + 1 > 11 ? 1 : 0); +} + +static void rockchip_to_gregorian(struct rtc_time *tm) +{ +	/* If it's Nov 31st, rtc_tm_to_time64() will count that like Dec 1st */ +	time64_t time = rtc_tm_to_time64(tm); +	rtc_time64_to_tm(time + nov2dec_transitions(tm) * 86400, tm); +} + +static void gregorian_to_rockchip(struct rtc_time *tm) +{ +	time64_t extra_days = nov2dec_transitions(tm); +	time64_t time = rtc_tm_to_time64(tm); +	rtc_time64_to_tm(time - extra_days * 86400, tm); + +	/* Compensate if we went back over Nov 31st (will work up to 2381) */ +	if (nov2dec_transitions(tm) < extra_days) { +		if (tm->tm_mon + 1 == 11) +			tm->tm_mday++;	/* This may result in 31! */ +		else +			rtc_time64_to_tm(time - (extra_days - 1) * 86400, tm); +	} +} +  /* Read current time and date in RTC */  static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)  { @@ -101,9 +137,10 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)  	tm->tm_mon = (bcd2bin(rtc_data[4] & MONTHS_REG_MSK)) - 1;  	tm->tm_year = (bcd2bin(rtc_data[5] & YEARS_REG_MSK)) + 100;  	tm->tm_wday = bcd2bin(rtc_data[6] & WEEKS_REG_MSK); +	rockchip_to_gregorian(tm);  	dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",  		1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, -		tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec); +		tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);  	return ret;  } @@ -116,6 +153,10 @@ static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm)  	u8 rtc_data[NUM_TIME_REGS];  	int ret; +	dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", +		1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, +		tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec); +	gregorian_to_rockchip(tm);  	rtc_data[0] = bin2bcd(tm->tm_sec);  	rtc_data[1] = bin2bcd(tm->tm_min);  	rtc_data[2] = bin2bcd(tm->tm_hour); @@ -123,9 +164,6 @@ static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm)  	rtc_data[4] = bin2bcd(tm->tm_mon + 1);  	rtc_data[5] = bin2bcd(tm->tm_year - 100);  	rtc_data[6] = bin2bcd(tm->tm_wday); -	dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", -		1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, -		tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec);  	/* Stop RTC while updating the RTC registers */  	ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, @@ -170,6 +208,7 @@ static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)  	alrm->time.tm_mday = bcd2bin(alrm_data[3] & DAYS_REG_MSK);  	alrm->time.tm_mon = (bcd2bin(alrm_data[4] & MONTHS_REG_MSK)) - 1;  	alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100; +	rockchip_to_gregorian(&alrm->time);  	ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg);  	if (ret) { @@ -227,6 +266,7 @@ static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)  		alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,  		alrm->time.tm_min, alrm->time.tm_sec); +	gregorian_to_rockchip(&alrm->time);  	alrm_data[0] = bin2bcd(alrm->time.tm_sec);  	alrm_data[1] = bin2bcd(alrm->time.tm_min);  	alrm_data[2] = bin2bcd(alrm->time.tm_hour); |