mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
RTC for 6.6
Subsystem: - Add a way for drivers to tell the core the supported alarm range is smaller than the date range. This is not used yet but will be useful for the alarmtimers in the next release. - fix Wvoid-pointer-to-enum-cast warnings - remove redundant of_match_ptr() - stop warning for invalid alarms when the alarm is disabled Drivers: - isl12022: allow setting the trip level for battery level detection - pcf2127: add support for PCF2131 and multiple timestamps - stm32: time precision improvement, many fixes - twl: NVRAM support -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEBqsFVZXh8s/0O5JiY6TcMGxwOjIFAmT6M14ACgkQY6TcMGxw OjKE3Q/+N7OMaTeJcqk1c5JEFZukOIYGZnogDSAvOF5mP9Y0TBlc/+UD5V6SgPLG B0oQfAEbYoo5e9VRCawIXBuE1fFA4AsHd6yc4395pEB5OZPpYcdvEWHfB1MQCKSy /sQ2xeevdOLtpHxqjK2cN1crlWOo1YACuUoXgN1IvOgtLC7NKxH77q+I9gvhNWiy P/U9gCRR7ji/GZ5LssOi9+rTj5gi8eeW6R9WzPfARAljGZwgMY2dzZWDmmq5gKJn VTLeoxbvsMNgM5G72sUlSBeeN1lPFIIknx3+DU4+v9JqSklI1GarySfnFqRqIDp6 JQKicAfv+PXbrqJliUGUvU5O0JTDjpsRI23ridKQ/jFaBkk8k26jXehK5IYUBO+A xvIsTZgSn53oGMoAZFSUGTIC4m0KDCQ6Wu0rCDr1OCecds2ueYfBHfCOj5rNvBdE ZAb/m0tquX5hkVuLqGt7Wn32PdpsPA9noz4cdgtDkNLL2juEYwBHUUBnuuHsEEzR dDoKdcm3q+KA9PEW0ftLb069UQ1ddca2Y8Mxp79Xt3mQhg28BMWV9h9qyPdicS5W Cti54qplG7EP5SRqsyqh6KH91ZfJFMbyb+ivEEQlYeOK45IFLkGXjVBZmHRPuZaV tjbNkp74asaftpMIB9kiW82JdJDUNGKYjYbSyssAWABTDbRlpGc= =4kkJ -----END PGP SIGNATURE----- Merge tag 'rtc-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux Pull RTC updates from Alexandre Belloni: "Subsystem: - Add a way for drivers to tell the core the supported alarm range is smaller than the date range. This is not used yet but will be useful for the alarmtimers in the next release. - fix Wvoid-pointer-to-enum-cast warnings - remove redundant of_match_ptr() - stop warning for invalid alarms when the alarm is disabled Drivers: - isl12022: allow setting the trip level for battery level detection - pcf2127: add support for PCF2131 and multiple timestamps - stm32: time precision improvement, many fixes - twl: NVRAM support" * tag 'rtc-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (73 commits) dt-bindings: rtc: ds3231: Remove text binding rtc: wm8350: remove unnecessary messages rtc: twl: remove unnecessary messages rtc: sun6i: remove unnecessary message rtc: stop warning for invalid alarms when the alarm is disabled rtc: twl: add NVRAM support rtc: pcf85363: Allow to wake up system without IRQ rtc: m48t86: add DT support for m48t86 dt-bindings: rtc: Add ST M48T86 rtc: pcf2127: remove useless check rtc: rzn1: Report maximum alarm limit to rtc core rtc: ds1305: Report maximum alarm limit to rtc core rtc: tps6586x: Report maximum alarm limit to rtc core rtc: cmos: Report supported alarm limit to rtc infrastructure rtc: cros-ec: Detect and report supported alarm window size rtc: Add support for limited alarm timer offsets rtc: isl1208: Fix incorrect logic in isl1208_set_xtoscb() MAINTAINERS: remove obsolete pattern in RTC SUBSYSTEM section rtc: tps65910: Remove redundant dev_warn() and do not check for 0 return after calling platform_get_irq() rtc: omap: Do not check for 0 return after calling platform_get_irq() ...
This commit is contained in:
commit
ff6e6ded54
@ -14,13 +14,17 @@ maintainers:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- atmel,at91rm9200-rtc
|
||||
- atmel,at91sam9x5-rtc
|
||||
- atmel,sama5d4-rtc
|
||||
- atmel,sama5d2-rtc
|
||||
- microchip,sam9x60-rtc
|
||||
- microchip,sama7g5-rtc
|
||||
oneOf:
|
||||
- enum:
|
||||
- atmel,at91rm9200-rtc
|
||||
- atmel,at91sam9x5-rtc
|
||||
- atmel,sama5d4-rtc
|
||||
- atmel,sama5d2-rtc
|
||||
- microchip,sam9x60-rtc
|
||||
- microchip,sama7g5-rtc
|
||||
- items:
|
||||
- const: microchip,sam9x7-rtc
|
||||
- const: microchip,sam9x60-rtc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
64
Documentation/devicetree/bindings/rtc/intersil,isl12022.yaml
Normal file
64
Documentation/devicetree/bindings/rtc/intersil,isl12022.yaml
Normal file
@ -0,0 +1,64 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/rtc/intersil,isl12022.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Intersil ISL12022 Real-time Clock
|
||||
|
||||
maintainers:
|
||||
- Alexandre Belloni <alexandre.belloni@bootlin.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: isil,isl12022
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 0
|
||||
|
||||
isil,battery-trip-levels-microvolt:
|
||||
description:
|
||||
The battery voltages at which the first alarm and second alarm
|
||||
should trigger (normally ~85% and ~75% of nominal V_BAT).
|
||||
items:
|
||||
- enum: [2125000, 2295000, 2550000, 2805000, 3060000, 4250000, 4675000]
|
||||
- enum: [1875000, 2025000, 2250000, 2475000, 2700000, 3750000, 4125000]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- $ref: rtc.yaml#
|
||||
# If #clock-cells is present, interrupts must not be present
|
||||
- if:
|
||||
required:
|
||||
- '#clock-cells'
|
||||
then:
|
||||
properties:
|
||||
interrupts: false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
rtc@6f {
|
||||
compatible = "isil,isl12022";
|
||||
reg = <0x6f>;
|
||||
interrupts-extended = <&gpio1 5 IRQ_TYPE_LEVEL_LOW>;
|
||||
isil,battery-trip-levels-microvolt = <2550000>, <2250000>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -1,38 +0,0 @@
|
||||
* Maxim DS3231 Real Time Clock
|
||||
|
||||
Required properties:
|
||||
- compatible: Should contain "maxim,ds3231".
|
||||
- reg: I2C address for chip.
|
||||
|
||||
Optional property:
|
||||
- #clock-cells: Should be 1.
|
||||
- clock-output-names:
|
||||
overwrite the default clock names "ds3231_clk_sqw" and "ds3231_clk_32khz".
|
||||
|
||||
Each clock is assigned an identifier and client nodes can use this identifier
|
||||
to specify the clock which they consume. Following indices are allowed:
|
||||
- 0: square-wave output on the SQW pin
|
||||
- 1: square-wave output on the 32kHz pin
|
||||
|
||||
- interrupts: rtc alarm/event interrupt. When this property is selected,
|
||||
clock on the SQW pin cannot be used.
|
||||
|
||||
Example:
|
||||
|
||||
ds3231: ds3231@51 {
|
||||
compatible = "maxim,ds3231";
|
||||
reg = <0x68>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
device1 {
|
||||
...
|
||||
clocks = <&ds3231 0>;
|
||||
...
|
||||
};
|
||||
|
||||
device2 {
|
||||
...
|
||||
clocks = <&ds3231 1>;
|
||||
...
|
||||
};
|
@ -18,6 +18,7 @@ properties:
|
||||
- nxp,pca2129
|
||||
- nxp,pcf2127
|
||||
- nxp,pcf2129
|
||||
- nxp,pcf2131
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
38
Documentation/devicetree/bindings/rtc/st,m48t86.yaml
Normal file
38
Documentation/devicetree/bindings/rtc/st,m48t86.yaml
Normal file
@ -0,0 +1,38 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/rtc/st,m48t86.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ST M48T86 / Dallas DS12887 RTC with SRAM
|
||||
|
||||
maintainers:
|
||||
- Alexandre Belloni <alexandre.belloni@bootlin.com>
|
||||
|
||||
allOf:
|
||||
- $ref: rtc.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- st,m48t86
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: index register
|
||||
- description: data register
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
rtc@10800000 {
|
||||
compatible = "st,m48t86";
|
||||
reg = <0x10800000 0x1>, <0x11700000 0x1>;
|
||||
};
|
||||
|
||||
...
|
@ -45,8 +45,6 @@ properties:
|
||||
- isil,isl1208
|
||||
# Intersil ISL1218 Low Power RTC with Battery Backed SRAM
|
||||
- isil,isl1218
|
||||
# Intersil ISL12022 Real-time Clock
|
||||
- isil,isl12022
|
||||
# Real Time Clock Module with I2C-Bus
|
||||
- microcrystal,rv3029
|
||||
# Real Time Clock
|
||||
|
@ -18084,7 +18084,6 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git
|
||||
F: Documentation/admin-guide/rtc.rst
|
||||
F: Documentation/devicetree/bindings/rtc/
|
||||
F: drivers/rtc/
|
||||
F: include/linux/platform_data/rtc-*
|
||||
F: include/linux/rtc.h
|
||||
F: include/linux/rtc/
|
||||
F: include/uapi/linux/rtc.h
|
||||
|
@ -904,9 +904,9 @@ config RTC_DRV_PCF2127
|
||||
select REGMAP_SPI if SPI_MASTER
|
||||
select WATCHDOG_CORE if WATCHDOG
|
||||
help
|
||||
If you say yes here you get support for the NXP PCF2127/29 RTC
|
||||
If you say yes here you get support for the NXP PCF2127/29/31 RTC
|
||||
chips with integrated quartz crystal for industrial applications.
|
||||
Both chips also have watchdog timer and tamper switch detection
|
||||
These chips also have watchdog timer and tamper switch detection
|
||||
features.
|
||||
|
||||
PCF2127 has an additional feature of 512 bytes battery backed
|
||||
@ -1196,6 +1196,7 @@ config RTC_DRV_MSM6242
|
||||
config RTC_DRV_BQ4802
|
||||
tristate "TI BQ4802"
|
||||
depends on HAS_IOMEM && HAS_IOPORT
|
||||
depends on SPARC || COMPILE_TEST
|
||||
help
|
||||
If you say Y here you will get support for the TI
|
||||
BQ4802 RTC chip.
|
||||
|
@ -376,7 +376,7 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
|
||||
err = rtc_valid_tm(&alarm->time);
|
||||
|
||||
done:
|
||||
if (err)
|
||||
if (err && alarm->enabled)
|
||||
dev_warn(&rtc->dev, "invalid alarm value: %ptR\n",
|
||||
&alarm->time);
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/kstrtox.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/watchdog.h>
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
@ -474,7 +473,6 @@ static const struct armada38x_rtc_data armada8k_data = {
|
||||
.alarm = ALARM2,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id armada38x_rtc_of_match_table[] = {
|
||||
{
|
||||
.compatible = "marvell,armada-380-rtc",
|
||||
@ -487,7 +485,6 @@ static const struct of_device_id armada38x_rtc_of_match_table[] = {
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table);
|
||||
#endif
|
||||
|
||||
static __init int armada38x_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
@ -577,7 +574,7 @@ static struct platform_driver armada38x_rtc_driver = {
|
||||
.driver = {
|
||||
.name = "armada38x-rtc",
|
||||
.pm = &armada38x_rtc_pm_ops,
|
||||
.of_match_table = of_match_ptr(armada38x_rtc_of_match_table),
|
||||
.of_match_table = armada38x_rtc_of_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -118,7 +118,7 @@ MODULE_DEVICE_TABLE(of, aspeed_rtc_match);
|
||||
static struct platform_driver aspeed_rtc_driver = {
|
||||
.driver = {
|
||||
.name = "aspeed-rtc",
|
||||
.of_match_table = of_match_ptr(aspeed_rtc_match),
|
||||
.of_match_table = aspeed_rtc_match,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rtc.h>
|
||||
@ -642,7 +641,7 @@ static struct platform_driver at91_rtc_driver = {
|
||||
.driver = {
|
||||
.name = "at91_rtc",
|
||||
.pm = &at91_rtc_pm_ops,
|
||||
.of_match_table = of_match_ptr(at91_rtc_dt_ids),
|
||||
.of_match_table = at91_rtc_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -534,7 +534,7 @@ static struct platform_driver at91_rtc_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-at91sam9",
|
||||
.pm = &at91_rtc_pm_ops,
|
||||
.of_match_table = of_match_ptr(at91_rtc_dt_ids),
|
||||
.of_match_table = at91_rtc_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -913,6 +913,10 @@ static inline void cmos_check_acpi_rtc_status(struct device *dev,
|
||||
#define INITSECTION __init
|
||||
#endif
|
||||
|
||||
#define SECS_PER_DAY (24 * 60 * 60)
|
||||
#define SECS_PER_MONTH (28 * SECS_PER_DAY)
|
||||
#define SECS_PER_YEAR (365 * SECS_PER_DAY)
|
||||
|
||||
static int INITSECTION
|
||||
cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
||||
{
|
||||
@ -1019,6 +1023,13 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
||||
goto cleanup0;
|
||||
}
|
||||
|
||||
if (cmos_rtc.mon_alrm)
|
||||
cmos_rtc.rtc->alarm_offset_max = SECS_PER_YEAR - 1;
|
||||
else if (cmos_rtc.day_alrm)
|
||||
cmos_rtc.rtc->alarm_offset_max = SECS_PER_MONTH - 1;
|
||||
else
|
||||
cmos_rtc.rtc->alarm_offset_max = SECS_PER_DAY - 1;
|
||||
|
||||
rename_region(ports, dev_name(&cmos_rtc.rtc->dev));
|
||||
|
||||
if (!mc146818_does_rtc_work()) {
|
||||
|
@ -182,21 +182,15 @@ static int cros_ec_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
|
||||
ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM, alarm_offset);
|
||||
if (ret < 0) {
|
||||
if (ret == -EINVAL && alarm_offset >= SECS_PER_DAY) {
|
||||
/*
|
||||
* RTC chips on some older Chromebooks can only handle
|
||||
* alarms up to 24h in the future. Try to set an alarm
|
||||
* below that limit to avoid suspend failures.
|
||||
*/
|
||||
ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM,
|
||||
SECS_PER_DAY - 1);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "error setting alarm in %u seconds: %d\n",
|
||||
alarm_offset, ret);
|
||||
return ret;
|
||||
}
|
||||
dev_err(dev, "error setting alarm in %u seconds: %d\n",
|
||||
alarm_offset, ret);
|
||||
/*
|
||||
* The EC code returns -EINVAL if the alarm time is too
|
||||
* far in the future. Convert it to the expected error code.
|
||||
*/
|
||||
if (ret == -EINVAL)
|
||||
ret = -ERANGE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -355,6 +349,20 @@ static int cros_ec_rtc_probe(struct platform_device *pdev)
|
||||
cros_ec_rtc->rtc->ops = &cros_ec_rtc_ops;
|
||||
cros_ec_rtc->rtc->range_max = U32_MAX;
|
||||
|
||||
/*
|
||||
* The RTC on some older Chromebooks can only handle alarms less than
|
||||
* 24 hours in the future. The only way to find out is to try to set an
|
||||
* alarm further in the future. If that fails, assume that the RTC
|
||||
* connected to the EC can only handle less than 24 hours of alarm
|
||||
* window.
|
||||
*/
|
||||
ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM, SECS_PER_DAY * 2);
|
||||
if (ret == -EINVAL)
|
||||
cros_ec_rtc->rtc->alarm_offset_max = SECS_PER_DAY - 1;
|
||||
|
||||
(void)cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM,
|
||||
EC_RTC_ALARM_CLEAR);
|
||||
|
||||
ret = devm_rtc_register_device(cros_ec_rtc->rtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_wakeirq.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/slab.h>
|
||||
@ -496,6 +497,12 @@ static int da9063_rtc_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n",
|
||||
irq_alarm, ret);
|
||||
|
||||
ret = dev_pm_set_wake_irq(&pdev->dev, irq_alarm);
|
||||
if (ret)
|
||||
dev_warn(&pdev->dev,
|
||||
"Failed to set IRQ %d as a wake IRQ: %d\n",
|
||||
irq_alarm, ret);
|
||||
|
||||
device_init_wakeup(&pdev->dev, true);
|
||||
|
||||
return devm_rtc_register_device(rtc->rtc_dev);
|
||||
|
@ -336,8 +336,8 @@ static int ds1305_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
|
||||
/* make sure alarm fires within the next 24 hours */
|
||||
if (later <= now)
|
||||
return -EINVAL;
|
||||
if ((later - now) > 24 * 60 * 60)
|
||||
return -EDOM;
|
||||
if ((later - now) > ds1305->rtc->alarm_offset_max)
|
||||
return -ERANGE;
|
||||
|
||||
/* disable alarm if needed */
|
||||
if (ds1305->ctrl[0] & DS1305_AEI0) {
|
||||
@ -691,6 +691,7 @@ static int ds1305_probe(struct spi_device *spi)
|
||||
ds1305->rtc->ops = &ds1305_ops;
|
||||
ds1305->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||
ds1305->rtc->range_max = RTC_TIMESTAMP_END_2099;
|
||||
ds1305->rtc->alarm_offset_max = 24 * 60 * 60;
|
||||
|
||||
ds1305_nvmem_cfg.priv = ds1305;
|
||||
status = devm_rtc_register_device(ds1305->rtc);
|
||||
|
@ -1744,7 +1744,7 @@ static int ds1307_probe(struct i2c_client *client)
|
||||
|
||||
match = device_get_match_data(&client->dev);
|
||||
if (match) {
|
||||
ds1307->type = (enum ds_type)match;
|
||||
ds1307->type = (uintptr_t)match;
|
||||
chip = &chips[ds1307->type];
|
||||
} else if (id) {
|
||||
chip = &chips[id->driver_data];
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -7,9 +7,8 @@
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/platform_data/rtc-ds2404.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/io.h>
|
||||
@ -27,164 +26,140 @@
|
||||
#define DS2404_CLK 1
|
||||
#define DS2404_DQ 2
|
||||
|
||||
struct ds2404_gpio {
|
||||
const char *name;
|
||||
unsigned int gpio;
|
||||
};
|
||||
|
||||
struct ds2404 {
|
||||
struct ds2404_gpio *gpio;
|
||||
struct device *dev;
|
||||
struct gpio_desc *rst_gpiod;
|
||||
struct gpio_desc *clk_gpiod;
|
||||
struct gpio_desc *dq_gpiod;
|
||||
struct rtc_device *rtc;
|
||||
};
|
||||
|
||||
static struct ds2404_gpio ds2404_gpio[] = {
|
||||
{ "RTC RST", 0 },
|
||||
{ "RTC CLK", 0 },
|
||||
{ "RTC DQ", 0 },
|
||||
};
|
||||
|
||||
static int ds2404_gpio_map(struct ds2404 *chip, struct platform_device *pdev,
|
||||
struct ds2404_platform_data *pdata)
|
||||
static int ds2404_gpio_map(struct ds2404 *chip, struct platform_device *pdev)
|
||||
{
|
||||
int i, err;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
ds2404_gpio[DS2404_RST].gpio = pdata->gpio_rst;
|
||||
ds2404_gpio[DS2404_CLK].gpio = pdata->gpio_clk;
|
||||
ds2404_gpio[DS2404_DQ].gpio = pdata->gpio_dq;
|
||||
/* This will de-assert RESET, declare this GPIO as GPIOD_ACTIVE_LOW */
|
||||
chip->rst_gpiod = devm_gpiod_get(dev, "rst", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(chip->rst_gpiod))
|
||||
return PTR_ERR(chip->rst_gpiod);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ds2404_gpio); i++) {
|
||||
err = gpio_request(ds2404_gpio[i].gpio, ds2404_gpio[i].name);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "error mapping gpio %s: %d\n",
|
||||
ds2404_gpio[i].name, err);
|
||||
goto err_request;
|
||||
}
|
||||
if (i != DS2404_DQ)
|
||||
gpio_direction_output(ds2404_gpio[i].gpio, 1);
|
||||
}
|
||||
chip->clk_gpiod = devm_gpiod_get(dev, "clk", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(chip->clk_gpiod))
|
||||
return PTR_ERR(chip->clk_gpiod);
|
||||
|
||||
chip->dq_gpiod = devm_gpiod_get(dev, "dq", GPIOD_ASIS);
|
||||
if (IS_ERR(chip->dq_gpiod))
|
||||
return PTR_ERR(chip->dq_gpiod);
|
||||
|
||||
chip->gpio = ds2404_gpio;
|
||||
return 0;
|
||||
|
||||
err_request:
|
||||
while (--i >= 0)
|
||||
gpio_free(ds2404_gpio[i].gpio);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ds2404_gpio_unmap(void *data)
|
||||
static void ds2404_reset(struct ds2404 *chip)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ds2404_gpio); i++)
|
||||
gpio_free(ds2404_gpio[i].gpio);
|
||||
}
|
||||
|
||||
static void ds2404_reset(struct device *dev)
|
||||
{
|
||||
gpio_set_value(ds2404_gpio[DS2404_RST].gpio, 0);
|
||||
gpiod_set_value(chip->rst_gpiod, 1);
|
||||
udelay(1000);
|
||||
gpio_set_value(ds2404_gpio[DS2404_RST].gpio, 1);
|
||||
gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 0);
|
||||
gpio_direction_output(ds2404_gpio[DS2404_DQ].gpio, 0);
|
||||
gpiod_set_value(chip->rst_gpiod, 0);
|
||||
gpiod_set_value(chip->clk_gpiod, 0);
|
||||
gpiod_direction_output(chip->dq_gpiod, 0);
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
static void ds2404_write_byte(struct device *dev, u8 byte)
|
||||
static void ds2404_write_byte(struct ds2404 *chip, u8 byte)
|
||||
{
|
||||
int i;
|
||||
|
||||
gpio_direction_output(ds2404_gpio[DS2404_DQ].gpio, 1);
|
||||
gpiod_direction_output(chip->dq_gpiod, 1);
|
||||
for (i = 0; i < 8; i++) {
|
||||
gpio_set_value(ds2404_gpio[DS2404_DQ].gpio, byte & (1 << i));
|
||||
gpiod_set_value(chip->dq_gpiod, byte & (1 << i));
|
||||
udelay(10);
|
||||
gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 1);
|
||||
gpiod_set_value(chip->clk_gpiod, 1);
|
||||
udelay(10);
|
||||
gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 0);
|
||||
gpiod_set_value(chip->clk_gpiod, 0);
|
||||
udelay(10);
|
||||
}
|
||||
}
|
||||
|
||||
static u8 ds2404_read_byte(struct device *dev)
|
||||
static u8 ds2404_read_byte(struct ds2404 *chip)
|
||||
{
|
||||
int i;
|
||||
u8 ret = 0;
|
||||
|
||||
gpio_direction_input(ds2404_gpio[DS2404_DQ].gpio);
|
||||
gpiod_direction_input(chip->dq_gpiod);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 0);
|
||||
gpiod_set_value(chip->clk_gpiod, 0);
|
||||
udelay(10);
|
||||
if (gpio_get_value(ds2404_gpio[DS2404_DQ].gpio))
|
||||
if (gpiod_get_value(chip->dq_gpiod))
|
||||
ret |= 1 << i;
|
||||
gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 1);
|
||||
gpiod_set_value(chip->clk_gpiod, 1);
|
||||
udelay(10);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ds2404_read_memory(struct device *dev, u16 offset,
|
||||
static void ds2404_read_memory(struct ds2404 *chip, u16 offset,
|
||||
int length, u8 *out)
|
||||
{
|
||||
ds2404_reset(dev);
|
||||
ds2404_write_byte(dev, DS2404_READ_MEMORY_CMD);
|
||||
ds2404_write_byte(dev, offset & 0xff);
|
||||
ds2404_write_byte(dev, (offset >> 8) & 0xff);
|
||||
ds2404_reset(chip);
|
||||
ds2404_write_byte(chip, DS2404_READ_MEMORY_CMD);
|
||||
ds2404_write_byte(chip, offset & 0xff);
|
||||
ds2404_write_byte(chip, (offset >> 8) & 0xff);
|
||||
while (length--)
|
||||
*out++ = ds2404_read_byte(dev);
|
||||
*out++ = ds2404_read_byte(chip);
|
||||
}
|
||||
|
||||
static void ds2404_write_memory(struct device *dev, u16 offset,
|
||||
static void ds2404_write_memory(struct ds2404 *chip, u16 offset,
|
||||
int length, u8 *out)
|
||||
{
|
||||
int i;
|
||||
u8 ta01, ta02, es;
|
||||
|
||||
ds2404_reset(dev);
|
||||
ds2404_write_byte(dev, DS2404_WRITE_SCRATCHPAD_CMD);
|
||||
ds2404_write_byte(dev, offset & 0xff);
|
||||
ds2404_write_byte(dev, (offset >> 8) & 0xff);
|
||||
ds2404_reset(chip);
|
||||
ds2404_write_byte(chip, DS2404_WRITE_SCRATCHPAD_CMD);
|
||||
ds2404_write_byte(chip, offset & 0xff);
|
||||
ds2404_write_byte(chip, (offset >> 8) & 0xff);
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
ds2404_write_byte(dev, out[i]);
|
||||
ds2404_write_byte(chip, out[i]);
|
||||
|
||||
ds2404_reset(dev);
|
||||
ds2404_write_byte(dev, DS2404_READ_SCRATCHPAD_CMD);
|
||||
ds2404_reset(chip);
|
||||
ds2404_write_byte(chip, DS2404_READ_SCRATCHPAD_CMD);
|
||||
|
||||
ta01 = ds2404_read_byte(dev);
|
||||
ta02 = ds2404_read_byte(dev);
|
||||
es = ds2404_read_byte(dev);
|
||||
ta01 = ds2404_read_byte(chip);
|
||||
ta02 = ds2404_read_byte(chip);
|
||||
es = ds2404_read_byte(chip);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (out[i] != ds2404_read_byte(dev)) {
|
||||
dev_err(dev, "read invalid data\n");
|
||||
if (out[i] != ds2404_read_byte(chip)) {
|
||||
dev_err(chip->dev, "read invalid data\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ds2404_reset(dev);
|
||||
ds2404_write_byte(dev, DS2404_COPY_SCRATCHPAD_CMD);
|
||||
ds2404_write_byte(dev, ta01);
|
||||
ds2404_write_byte(dev, ta02);
|
||||
ds2404_write_byte(dev, es);
|
||||
ds2404_reset(chip);
|
||||
ds2404_write_byte(chip, DS2404_COPY_SCRATCHPAD_CMD);
|
||||
ds2404_write_byte(chip, ta01);
|
||||
ds2404_write_byte(chip, ta02);
|
||||
ds2404_write_byte(chip, es);
|
||||
|
||||
gpio_direction_input(ds2404_gpio[DS2404_DQ].gpio);
|
||||
while (gpio_get_value(ds2404_gpio[DS2404_DQ].gpio))
|
||||
while (gpiod_get_value(chip->dq_gpiod))
|
||||
;
|
||||
}
|
||||
|
||||
static void ds2404_enable_osc(struct device *dev)
|
||||
static void ds2404_enable_osc(struct ds2404 *chip)
|
||||
{
|
||||
u8 in[1] = { 0x10 }; /* enable oscillator */
|
||||
ds2404_write_memory(dev, 0x201, 1, in);
|
||||
|
||||
ds2404_write_memory(chip, 0x201, 1, in);
|
||||
}
|
||||
|
||||
static int ds2404_read_time(struct device *dev, struct rtc_time *dt)
|
||||
{
|
||||
struct ds2404 *chip = dev_get_drvdata(dev);
|
||||
unsigned long time = 0;
|
||||
__le32 hw_time = 0;
|
||||
|
||||
ds2404_read_memory(dev, 0x203, 4, (u8 *)&hw_time);
|
||||
ds2404_read_memory(chip, 0x203, 4, (u8 *)&hw_time);
|
||||
time = le32_to_cpu(hw_time);
|
||||
|
||||
rtc_time64_to_tm(time, dt);
|
||||
@ -193,8 +168,9 @@ static int ds2404_read_time(struct device *dev, struct rtc_time *dt)
|
||||
|
||||
static int ds2404_set_time(struct device *dev, struct rtc_time *dt)
|
||||
{
|
||||
struct ds2404 *chip = dev_get_drvdata(dev);
|
||||
u32 time = cpu_to_le32(rtc_tm_to_time64(dt));
|
||||
ds2404_write_memory(dev, 0x203, 4, (u8 *)&time);
|
||||
ds2404_write_memory(chip, 0x203, 4, (u8 *)&time);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -205,7 +181,6 @@ static const struct rtc_class_ops ds2404_rtc_ops = {
|
||||
|
||||
static int rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ds2404_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct ds2404 *chip;
|
||||
int retval = -EBUSY;
|
||||
|
||||
@ -213,22 +188,16 @@ static int rtc_probe(struct platform_device *pdev)
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->dev = &pdev->dev;
|
||||
|
||||
chip->rtc = devm_rtc_allocate_device(&pdev->dev);
|
||||
if (IS_ERR(chip->rtc))
|
||||
return PTR_ERR(chip->rtc);
|
||||
|
||||
retval = ds2404_gpio_map(chip, pdev, pdata);
|
||||
retval = ds2404_gpio_map(chip, pdev);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
retval = devm_add_action_or_reset(&pdev->dev, ds2404_gpio_unmap, chip);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
dev_info(&pdev->dev, "using GPIOs RST:%d, CLK:%d, DQ:%d\n",
|
||||
chip->gpio[DS2404_RST].gpio, chip->gpio[DS2404_CLK].gpio,
|
||||
chip->gpio[DS2404_DQ].gpio);
|
||||
|
||||
platform_set_drvdata(pdev, chip);
|
||||
|
||||
chip->rtc->ops = &ds2404_rtc_ops;
|
||||
@ -238,7 +207,7 @@ static int rtc_probe(struct platform_device *pdev)
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
ds2404_enable_osc(&pdev->dev);
|
||||
ds2404_enable_osc(chip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -11,11 +11,8 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fsl/ftm.h>
|
||||
#include <linux/rtc.h>
|
||||
|
@ -9,6 +9,8 @@
|
||||
*/
|
||||
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/i2c.h>
|
||||
@ -31,6 +33,8 @@
|
||||
#define ISL12022_REG_SR 0x07
|
||||
#define ISL12022_REG_INT 0x08
|
||||
|
||||
#define ISL12022_REG_PWR_VBAT 0x0a
|
||||
|
||||
#define ISL12022_REG_BETA 0x0d
|
||||
#define ISL12022_REG_TEMP_L 0x28
|
||||
|
||||
@ -41,6 +45,12 @@
|
||||
#define ISL12022_SR_LBAT75 (1 << 1)
|
||||
|
||||
#define ISL12022_INT_WRTC (1 << 6)
|
||||
#define ISL12022_INT_FO_MASK GENMASK(3, 0)
|
||||
#define ISL12022_INT_FO_OFF 0x0
|
||||
#define ISL12022_INT_FO_32K 0x1
|
||||
|
||||
#define ISL12022_REG_VB85_MASK GENMASK(5, 3)
|
||||
#define ISL12022_REG_VB75_MASK GENMASK(2, 0)
|
||||
|
||||
#define ISL12022_BETA_TSE (1 << 7)
|
||||
|
||||
@ -141,12 +151,6 @@ static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (buf[ISL12022_REG_SR] & (ISL12022_SR_LBAT85 | ISL12022_SR_LBAT75)) {
|
||||
dev_warn(dev,
|
||||
"voltage dropped below %u%%, date and time is not reliable.\n",
|
||||
buf[ISL12022_REG_SR] & ISL12022_SR_LBAT85 ? 85 : 75);
|
||||
}
|
||||
|
||||
dev_dbg(dev,
|
||||
"raw data is sec=%02x, min=%02x, hr=%02x, mday=%02x, mon=%02x, year=%02x, wday=%02x, sr=%02x, int=%02x",
|
||||
buf[ISL12022_REG_SC],
|
||||
@ -204,7 +208,34 @@ static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
return regmap_bulk_write(regmap, ISL12022_REG_SC, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
static int isl12022_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct regmap *regmap = dev_get_drvdata(dev);
|
||||
u32 user, val;
|
||||
int ret;
|
||||
|
||||
switch (cmd) {
|
||||
case RTC_VL_READ:
|
||||
ret = regmap_read(regmap, ISL12022_REG_SR, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
user = 0;
|
||||
if (val & ISL12022_SR_LBAT85)
|
||||
user |= RTC_VL_BACKUP_LOW;
|
||||
|
||||
if (val & ISL12022_SR_LBAT75)
|
||||
user |= RTC_VL_BACKUP_EMPTY;
|
||||
|
||||
return put_user(user, (u32 __user *)arg);
|
||||
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops isl12022_rtc_ops = {
|
||||
.ioctl = isl12022_rtc_ioctl,
|
||||
.read_time = isl12022_rtc_read_time,
|
||||
.set_time = isl12022_rtc_set_time,
|
||||
};
|
||||
@ -215,10 +246,88 @@ static const struct regmap_config regmap_config = {
|
||||
.use_single_write = true,
|
||||
};
|
||||
|
||||
static int isl12022_register_clock(struct device *dev)
|
||||
{
|
||||
struct regmap *regmap = dev_get_drvdata(dev);
|
||||
struct clk_hw *hw;
|
||||
int ret;
|
||||
|
||||
if (!device_property_present(dev, "#clock-cells")) {
|
||||
/*
|
||||
* Disabling the F_OUT pin reduces the power
|
||||
* consumption in battery mode by ~25%.
|
||||
*/
|
||||
regmap_update_bits(regmap, ISL12022_REG_INT, ISL12022_INT_FO_MASK,
|
||||
ISL12022_INT_FO_OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!IS_ENABLED(CONFIG_COMMON_CLK))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* For now, only support a fixed clock of 32768Hz (the reset default).
|
||||
*/
|
||||
ret = regmap_update_bits(regmap, ISL12022_REG_INT,
|
||||
ISL12022_INT_FO_MASK, ISL12022_INT_FO_32K);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hw = devm_clk_hw_register_fixed_rate(dev, "isl12022", NULL, 0, 32768);
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
|
||||
static const u32 trip_levels[2][7] = {
|
||||
{ 2125000, 2295000, 2550000, 2805000, 3060000, 4250000, 4675000 },
|
||||
{ 1875000, 2025000, 2250000, 2475000, 2700000, 3750000, 4125000 },
|
||||
};
|
||||
|
||||
static void isl12022_set_trip_levels(struct device *dev)
|
||||
{
|
||||
struct regmap *regmap = dev_get_drvdata(dev);
|
||||
u32 levels[2] = {0, 0};
|
||||
int ret, i, j, x[2];
|
||||
u8 val, mask;
|
||||
|
||||
device_property_read_u32_array(dev, "isil,battery-trip-levels-microvolt",
|
||||
levels, 2);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
for (j = 0; j < ARRAY_SIZE(trip_levels[i]) - 1; j++) {
|
||||
if (levels[i] <= trip_levels[i][j])
|
||||
break;
|
||||
}
|
||||
x[i] = j;
|
||||
}
|
||||
|
||||
val = FIELD_PREP(ISL12022_REG_VB85_MASK, x[0]) |
|
||||
FIELD_PREP(ISL12022_REG_VB75_MASK, x[1]);
|
||||
mask = ISL12022_REG_VB85_MASK | ISL12022_REG_VB75_MASK;
|
||||
|
||||
ret = regmap_update_bits(regmap, ISL12022_REG_PWR_VBAT, mask, val);
|
||||
if (ret)
|
||||
dev_warn(dev, "unable to set battery alarm levels: %d\n", ret);
|
||||
|
||||
/*
|
||||
* Force a write of the TSE bit in the BETA register, in order
|
||||
* to trigger an update of the LBAT75 and LBAT85 bits in the
|
||||
* status register. In battery backup mode, those bits have
|
||||
* another meaning, so without this, they may contain stale
|
||||
* values for up to a minute after power-on.
|
||||
*/
|
||||
regmap_write_bits(regmap, ISL12022_REG_BETA,
|
||||
ISL12022_BETA_TSE, ISL12022_BETA_TSE);
|
||||
}
|
||||
|
||||
static int isl12022_probe(struct i2c_client *client)
|
||||
{
|
||||
struct rtc_device *rtc;
|
||||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
|
||||
return -ENODEV;
|
||||
@ -231,6 +340,11 @@ static int isl12022_probe(struct i2c_client *client)
|
||||
|
||||
dev_set_drvdata(&client->dev, regmap);
|
||||
|
||||
ret = isl12022_register_clock(&client->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
isl12022_set_trip_levels(&client->dev);
|
||||
isl12022_hwmon_register(&client->dev);
|
||||
|
||||
rtc = devm_rtc_allocate_device(&client->dev);
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/nvmem-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@ -429,7 +428,7 @@ static void isl12026_force_power_modes(struct i2c_client *client)
|
||||
}
|
||||
}
|
||||
|
||||
static int isl12026_probe_new(struct i2c_client *client)
|
||||
static int isl12026_probe(struct i2c_client *client)
|
||||
{
|
||||
struct isl12026 *priv;
|
||||
int ret;
|
||||
@ -490,7 +489,7 @@ static struct i2c_driver isl12026_driver = {
|
||||
.name = "rtc-isl12026",
|
||||
.of_match_table = isl12026_dt_match,
|
||||
},
|
||||
.probe = isl12026_probe_new,
|
||||
.probe = isl12026_probe,
|
||||
.remove = isl12026_remove,
|
||||
};
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
@ -188,7 +188,7 @@ isl1208_i2c_validate_client(struct i2c_client *client)
|
||||
static int isl1208_set_xtoscb(struct i2c_client *client, int sr, int xtosb_val)
|
||||
{
|
||||
/* Do nothing if bit is already set to desired value */
|
||||
if ((sr & ISL1208_REG_SR_XTOSCB) == xtosb_val)
|
||||
if (!!(sr & ISL1208_REG_SR_XTOSCB) == xtosb_val)
|
||||
return 0;
|
||||
|
||||
if (xtosb_val)
|
||||
@ -862,17 +862,9 @@ isl1208_probe(struct i2c_client *client)
|
||||
i2c_set_clientdata(client, isl1208);
|
||||
|
||||
/* Determine which chip we have */
|
||||
if (client->dev.of_node) {
|
||||
isl1208->config = of_device_get_match_data(&client->dev);
|
||||
if (!isl1208->config)
|
||||
return -ENODEV;
|
||||
} else {
|
||||
const struct i2c_device_id *id = i2c_match_id(isl1208_id, client);
|
||||
|
||||
if (!id)
|
||||
return -ENODEV;
|
||||
isl1208->config = (struct isl1208_config *)id->driver_data;
|
||||
}
|
||||
isl1208->config = i2c_get_match_data(client);
|
||||
if (!isl1208->config)
|
||||
return -ENODEV;
|
||||
|
||||
rc = isl1208_clk_present(client, "xin");
|
||||
if (rc < 0)
|
||||
@ -952,7 +944,6 @@ isl1208_probe(struct i2c_client *client)
|
||||
rc = isl1208_setup_irq(client, client->irq);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
} else {
|
||||
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, isl1208->rtc->features);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_wakeirq.h>
|
||||
#include <linux/property.h>
|
||||
@ -349,7 +349,7 @@ static int jz4740_rtc_probe(struct platform_device *pdev)
|
||||
if (!rtc)
|
||||
return -ENOMEM;
|
||||
|
||||
rtc->type = (enum jz4740_rtc_type)device_get_match_data(dev);
|
||||
rtc->type = (uintptr_t)device_get_match_data(dev);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
|
@ -9,9 +9,8 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
|
@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bcd.h>
|
||||
@ -269,9 +270,16 @@ static int m48t86_rtc_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id m48t86_rtc_of_ids[] = {
|
||||
{ .compatible = "st,m48t86" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, m48t86_rtc_of_ids);
|
||||
|
||||
static struct platform_driver m48t86_rtc_platform_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-m48t86",
|
||||
.of_match_table = m48t86_rtc_of_ids,
|
||||
},
|
||||
.probe = m48t86_rtc_probe,
|
||||
};
|
||||
|
@ -11,10 +11,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <linux/mfd/mt6397/core.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/rtc.h>
|
||||
|
@ -7,9 +7,9 @@
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include <linux/pm_wakeirq.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#define RTC_INPUT_CLK_32768HZ (0x00 << 5)
|
||||
#define RTC_INPUT_CLK_32000HZ (0x01 << 5)
|
||||
|
@ -538,7 +538,7 @@ MODULE_DEVICE_TABLE(of, nct3018y_of_match);
|
||||
static struct i2c_driver nct3018y_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-nct3018y",
|
||||
.of_match_table = of_match_ptr(nct3018y_of_match),
|
||||
.of_match_table = nct3018y_of_match,
|
||||
},
|
||||
.probe = nct3018y_probe,
|
||||
.id_table = nct3018y_id,
|
||||
|
@ -747,12 +747,12 @@ static int omap_rtc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
rtc->irq_timer = platform_get_irq(pdev, 0);
|
||||
if (rtc->irq_timer <= 0)
|
||||
return -ENOENT;
|
||||
if (rtc->irq_timer < 0)
|
||||
return rtc->irq_timer;
|
||||
|
||||
rtc->irq_alarm = platform_get_irq(pdev, 1);
|
||||
if (rtc->irq_alarm <= 0)
|
||||
return -ENOENT;
|
||||
if (rtc->irq_alarm < 0)
|
||||
return rtc->irq_alarm;
|
||||
|
||||
rtc->clk = devm_clk_get(&pdev->dev, "ext-clk");
|
||||
if (!IS_ERR(rtc->clk))
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,7 @@
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pm_wakeirq.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
@ -514,49 +514,40 @@ static struct clk *pcf85063_clkout_register_clk(struct pcf85063 *pcf85063)
|
||||
}
|
||||
#endif
|
||||
|
||||
enum pcf85063_type {
|
||||
PCF85063,
|
||||
PCF85063TP,
|
||||
PCF85063A,
|
||||
RV8263,
|
||||
PCF85063_LAST_ID
|
||||
};
|
||||
|
||||
static struct pcf85063_config pcf85063_cfg[] = {
|
||||
[PCF85063] = {
|
||||
.regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 0x0a,
|
||||
},
|
||||
},
|
||||
[PCF85063TP] = {
|
||||
.regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 0x0a,
|
||||
},
|
||||
},
|
||||
[PCF85063A] = {
|
||||
.regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 0x11,
|
||||
},
|
||||
.has_alarms = 1,
|
||||
},
|
||||
[RV8263] = {
|
||||
.regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 0x11,
|
||||
},
|
||||
.has_alarms = 1,
|
||||
.force_cap_7000 = 1,
|
||||
static const struct pcf85063_config config_pcf85063 = {
|
||||
.regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 0x0a,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct i2c_device_id pcf85063_ids[];
|
||||
static const struct pcf85063_config config_pcf85063tp = {
|
||||
.regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 0x0a,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct pcf85063_config config_pcf85063a = {
|
||||
.regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 0x11,
|
||||
},
|
||||
.has_alarms = 1,
|
||||
};
|
||||
|
||||
static const struct pcf85063_config config_rv8263 = {
|
||||
.regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 0x11,
|
||||
},
|
||||
.has_alarms = 1,
|
||||
.force_cap_7000 = 1,
|
||||
};
|
||||
|
||||
static int pcf85063_probe(struct i2c_client *client)
|
||||
{
|
||||
@ -579,17 +570,9 @@ static int pcf85063_probe(struct i2c_client *client)
|
||||
if (!pcf85063)
|
||||
return -ENOMEM;
|
||||
|
||||
if (client->dev.of_node) {
|
||||
config = of_device_get_match_data(&client->dev);
|
||||
if (!config)
|
||||
return -ENODEV;
|
||||
} else {
|
||||
enum pcf85063_type type =
|
||||
i2c_match_id(pcf85063_ids, client)->driver_data;
|
||||
if (type >= PCF85063_LAST_ID)
|
||||
return -ENODEV;
|
||||
config = &pcf85063_cfg[type];
|
||||
}
|
||||
config = i2c_get_match_data(client);
|
||||
if (!config)
|
||||
return -ENODEV;
|
||||
|
||||
pcf85063->regmap = devm_regmap_init_i2c(client, &config->regmap);
|
||||
if (IS_ERR(pcf85063->regmap))
|
||||
@ -655,22 +638,22 @@ static int pcf85063_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id pcf85063_ids[] = {
|
||||
{ "pca85073a", PCF85063A },
|
||||
{ "pcf85063", PCF85063 },
|
||||
{ "pcf85063tp", PCF85063TP },
|
||||
{ "pcf85063a", PCF85063A },
|
||||
{ "rv8263", RV8263 },
|
||||
{ "pca85073a", .driver_data = (kernel_ulong_t)&config_pcf85063a },
|
||||
{ "pcf85063", .driver_data = (kernel_ulong_t)&config_pcf85063 },
|
||||
{ "pcf85063tp", .driver_data = (kernel_ulong_t)&config_pcf85063tp },
|
||||
{ "pcf85063a", .driver_data = (kernel_ulong_t)&config_pcf85063a },
|
||||
{ "rv8263", .driver_data = (kernel_ulong_t)&config_rv8263 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pcf85063_ids);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id pcf85063_of_match[] = {
|
||||
{ .compatible = "nxp,pca85073a", .data = &pcf85063_cfg[PCF85063A] },
|
||||
{ .compatible = "nxp,pcf85063", .data = &pcf85063_cfg[PCF85063] },
|
||||
{ .compatible = "nxp,pcf85063tp", .data = &pcf85063_cfg[PCF85063TP] },
|
||||
{ .compatible = "nxp,pcf85063a", .data = &pcf85063_cfg[PCF85063A] },
|
||||
{ .compatible = "microcrystal,rv8263", .data = &pcf85063_cfg[RV8263] },
|
||||
{ .compatible = "nxp,pca85073a", .data = &config_pcf85063a },
|
||||
{ .compatible = "nxp,pcf85063", .data = &config_pcf85063 },
|
||||
{ .compatible = "nxp,pcf85063tp", .data = &config_pcf85063tp },
|
||||
{ .compatible = "nxp,pcf85063a", .data = &config_pcf85063a },
|
||||
{ .compatible = "microcrystal,rv8263", .data = &config_rv8263 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pcf85063_of_match);
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/*
|
||||
@ -403,6 +402,7 @@ static int pcf85363_probe(struct i2c_client *client)
|
||||
},
|
||||
};
|
||||
int ret, i, err;
|
||||
bool wakeup_source;
|
||||
|
||||
if (data)
|
||||
config = data;
|
||||
@ -432,25 +432,36 @@ static int pcf85363_probe(struct i2c_client *client)
|
||||
pcf85363->rtc->ops = &rtc_ops;
|
||||
pcf85363->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||
pcf85363->rtc->range_max = RTC_TIMESTAMP_END_2099;
|
||||
clear_bit(RTC_FEATURE_ALARM, pcf85363->rtc->features);
|
||||
|
||||
wakeup_source = device_property_read_bool(&client->dev,
|
||||
"wakeup-source");
|
||||
if (client->irq > 0 || wakeup_source) {
|
||||
regmap_write(pcf85363->regmap, CTRL_FLAGS, 0);
|
||||
regmap_update_bits(pcf85363->regmap, CTRL_PIN_IO,
|
||||
PIN_IO_INTA_OUT, PIN_IO_INTAPM);
|
||||
}
|
||||
|
||||
if (client->irq > 0) {
|
||||
unsigned long irqflags = IRQF_TRIGGER_LOW;
|
||||
|
||||
if (dev_fwnode(&client->dev))
|
||||
irqflags = 0;
|
||||
|
||||
regmap_write(pcf85363->regmap, CTRL_FLAGS, 0);
|
||||
regmap_update_bits(pcf85363->regmap, CTRL_PIN_IO,
|
||||
PIN_IO_INTA_OUT, PIN_IO_INTAPM);
|
||||
ret = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL, pcf85363_rtc_handle_irq,
|
||||
irqflags | IRQF_ONESHOT,
|
||||
"pcf85363", client);
|
||||
if (ret)
|
||||
dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
|
||||
else
|
||||
set_bit(RTC_FEATURE_ALARM, pcf85363->rtc->features);
|
||||
if (ret) {
|
||||
dev_warn(&client->dev,
|
||||
"unable to request IRQ, alarms disabled\n");
|
||||
client->irq = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (client->irq > 0 || wakeup_source) {
|
||||
device_init_wakeup(&client->dev, true);
|
||||
set_bit(RTC_FEATURE_ALARM, pcf85363->rtc->features);
|
||||
} else {
|
||||
clear_bit(RTC_FEATURE_ALARM, pcf85363->rtc->features);
|
||||
}
|
||||
|
||||
ret = devm_rtc_register_device(pcf85363->rtc);
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include "rtc-sa1100.h"
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
/*
|
||||
* Ricoh has a family of I2C based RTCs, which differ only slightly from
|
||||
@ -826,8 +826,7 @@ static int rs5c372_probe(struct i2c_client *client)
|
||||
rs5c372->client = client;
|
||||
i2c_set_clientdata(client, rs5c372);
|
||||
if (client->dev.of_node) {
|
||||
rs5c372->type = (enum rtc_type)
|
||||
of_device_get_match_data(&client->dev);
|
||||
rs5c372->type = (uintptr_t)of_device_get_match_data(&client->dev);
|
||||
} else {
|
||||
const struct i2c_device_id *id = i2c_match_id(rs5c372_id, client);
|
||||
rs5c372->type = id->driver_data;
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
@ -855,11 +855,68 @@ static const struct regmap_config regmap_config = {
|
||||
.max_register = 0x37,
|
||||
};
|
||||
|
||||
static u8 rv3028_set_trickle_charger(struct rv3028_data *rv3028,
|
||||
struct i2c_client *client)
|
||||
{
|
||||
int ret, val_old, val;
|
||||
u32 ohms, chargeable;
|
||||
|
||||
ret = regmap_read(rv3028->regmap, RV3028_BACKUP, &val_old);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* mask out only trickle charger bits */
|
||||
val_old = val_old & (RV3028_BACKUP_TCE | RV3028_BACKUP_TCR_MASK);
|
||||
val = val_old;
|
||||
|
||||
/* setup trickle charger */
|
||||
if (!device_property_read_u32(&client->dev, "trickle-resistor-ohms",
|
||||
&ohms)) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rv3028_trickle_resistors); i++)
|
||||
if (ohms == rv3028_trickle_resistors[i])
|
||||
break;
|
||||
|
||||
if (i < ARRAY_SIZE(rv3028_trickle_resistors)) {
|
||||
/* enable trickle charger and its resistor */
|
||||
val = RV3028_BACKUP_TCE | i;
|
||||
} else {
|
||||
dev_warn(&client->dev, "invalid trickle resistor value\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!device_property_read_u32(&client->dev, "aux-voltage-chargeable",
|
||||
&chargeable)) {
|
||||
switch (chargeable) {
|
||||
case 0:
|
||||
val &= ~RV3028_BACKUP_TCE;
|
||||
break;
|
||||
case 1:
|
||||
val |= RV3028_BACKUP_TCE;
|
||||
break;
|
||||
default:
|
||||
dev_warn(&client->dev,
|
||||
"unsupported aux-voltage-chargeable value\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* only update EEPROM if changes are necessary */
|
||||
if (val_old != val) {
|
||||
ret = rv3028_update_cfg(rv3028, RV3028_BACKUP, RV3028_BACKUP_TCE |
|
||||
RV3028_BACKUP_TCR_MASK, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rv3028_probe(struct i2c_client *client)
|
||||
{
|
||||
struct rv3028_data *rv3028;
|
||||
int ret, status;
|
||||
u32 ohms;
|
||||
struct nvmem_config nvmem_cfg = {
|
||||
.name = "rv3028_nvram",
|
||||
.word_size = 1,
|
||||
@ -937,24 +994,9 @@ static int rv3028_probe(struct i2c_client *client)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* setup trickle charger */
|
||||
if (!device_property_read_u32(&client->dev, "trickle-resistor-ohms",
|
||||
&ohms)) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rv3028_trickle_resistors); i++)
|
||||
if (ohms == rv3028_trickle_resistors[i])
|
||||
break;
|
||||
|
||||
if (i < ARRAY_SIZE(rv3028_trickle_resistors)) {
|
||||
ret = rv3028_update_cfg(rv3028, RV3028_BACKUP, RV3028_BACKUP_TCE |
|
||||
RV3028_BACKUP_TCR_MASK, RV3028_BACKUP_TCE | i);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
dev_warn(&client->dev, "invalid trickle resistor value\n");
|
||||
}
|
||||
}
|
||||
ret = rv3028_set_trickle_charger(rv3028, client);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rtc_add_group(rv3028->rtc, &rv3028_attr_group);
|
||||
if (ret)
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
#define RV8803_I2C_TRY_COUNT 4
|
||||
@ -645,8 +645,7 @@ static int rv8803_probe(struct i2c_client *client)
|
||||
mutex_init(&rv8803->flags_lock);
|
||||
rv8803->client = client;
|
||||
if (client->dev.of_node) {
|
||||
rv8803->type = (enum rv8803_type)
|
||||
of_device_get_match_data(&client->dev);
|
||||
rv8803->type = (uintptr_t)of_device_get_match_data(&client->dev);
|
||||
} else {
|
||||
const struct i2c_device_id *id = i2c_match_id(rv8803_id, client);
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/log2.h>
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/rtc.h>
|
||||
@ -227,7 +227,7 @@ static int rzn1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
return ret;
|
||||
|
||||
/* We cannot set alarms more than one week ahead */
|
||||
farest = rtc_tm_to_time64(&tm_now) + (7 * 86400);
|
||||
farest = rtc_tm_to_time64(&tm_now) + rtc->rtcdev->alarm_offset_max;
|
||||
alarm = rtc_tm_to_time64(tm);
|
||||
if (time_after(alarm, farest))
|
||||
return -ERANGE;
|
||||
@ -351,6 +351,7 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
|
||||
|
||||
rtc->rtcdev->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||
rtc->rtcdev->range_max = RTC_TIMESTAMP_END_2099;
|
||||
rtc->rtcdev->alarm_offset_max = 7 * 86400;
|
||||
rtc->rtcdev->ops = &rzn1_rtc_ops;
|
||||
set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->rtcdev->features);
|
||||
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtcdev->features);
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include <linux/log2.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
|
@ -6,11 +6,13 @@
|
||||
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_wakeirq.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/rtc.h>
|
||||
@ -89,6 +91,9 @@
|
||||
/* Max STM32 RTC register offset is 0x3FC */
|
||||
#define UNDEF_REG 0xFFFF
|
||||
|
||||
/* STM32 RTC driver time helpers */
|
||||
#define SEC_PER_DAY (24 * 60 * 60)
|
||||
|
||||
struct stm32_rtc;
|
||||
|
||||
struct stm32_rtc_registers {
|
||||
@ -114,6 +119,7 @@ struct stm32_rtc_data {
|
||||
void (*clear_events)(struct stm32_rtc *rtc, unsigned int flags);
|
||||
bool has_pclk;
|
||||
bool need_dbp;
|
||||
bool need_accuracy;
|
||||
};
|
||||
|
||||
struct stm32_rtc {
|
||||
@ -158,10 +164,9 @@ static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
|
||||
* slowest rtc_ck frequency may be 32kHz and highest should be
|
||||
* 1MHz, we poll every 10 us with a timeout of 100ms.
|
||||
*/
|
||||
return readl_relaxed_poll_timeout_atomic(
|
||||
rtc->base + regs->isr,
|
||||
isr, (isr & STM32_RTC_ISR_INITF),
|
||||
10, 100000);
|
||||
return readl_relaxed_poll_timeout_atomic(rtc->base + regs->isr, isr,
|
||||
(isr & STM32_RTC_ISR_INITF),
|
||||
10, 100000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -425,40 +430,42 @@ static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_rtc_valid_alrm(struct stm32_rtc *rtc, struct rtc_time *tm)
|
||||
static int stm32_rtc_valid_alrm(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
const struct stm32_rtc_registers *regs = &rtc->data->regs;
|
||||
int cur_day, cur_mon, cur_year, cur_hour, cur_min, cur_sec;
|
||||
unsigned int dr = readl_relaxed(rtc->base + regs->dr);
|
||||
unsigned int tr = readl_relaxed(rtc->base + regs->tr);
|
||||
|
||||
cur_day = (dr & STM32_RTC_DR_DATE) >> STM32_RTC_DR_DATE_SHIFT;
|
||||
cur_mon = (dr & STM32_RTC_DR_MONTH) >> STM32_RTC_DR_MONTH_SHIFT;
|
||||
cur_year = (dr & STM32_RTC_DR_YEAR) >> STM32_RTC_DR_YEAR_SHIFT;
|
||||
cur_sec = (tr & STM32_RTC_TR_SEC) >> STM32_RTC_TR_SEC_SHIFT;
|
||||
cur_min = (tr & STM32_RTC_TR_MIN) >> STM32_RTC_TR_MIN_SHIFT;
|
||||
cur_hour = (tr & STM32_RTC_TR_HOUR) >> STM32_RTC_TR_HOUR_SHIFT;
|
||||
static struct rtc_time now;
|
||||
time64_t max_alarm_time64;
|
||||
int max_day_forward;
|
||||
int next_month;
|
||||
int next_year;
|
||||
|
||||
/*
|
||||
* Assuming current date is M-D-Y H:M:S.
|
||||
* RTC alarm can't be set on a specific month and year.
|
||||
* So the valid alarm range is:
|
||||
* M-D-Y H:M:S < alarm <= (M+1)-D-Y H:M:S
|
||||
* with a specific case for December...
|
||||
*/
|
||||
if ((((tm->tm_year > cur_year) &&
|
||||
(tm->tm_mon == 0x1) && (cur_mon == 0x12)) ||
|
||||
((tm->tm_year == cur_year) &&
|
||||
(tm->tm_mon <= cur_mon + 1))) &&
|
||||
((tm->tm_mday > cur_day) ||
|
||||
((tm->tm_mday == cur_day) &&
|
||||
((tm->tm_hour > cur_hour) ||
|
||||
((tm->tm_hour == cur_hour) && (tm->tm_min > cur_min)) ||
|
||||
((tm->tm_hour == cur_hour) && (tm->tm_min == cur_min) &&
|
||||
(tm->tm_sec >= cur_sec))))))
|
||||
return 0;
|
||||
stm32_rtc_read_time(dev, &now);
|
||||
|
||||
return -EINVAL;
|
||||
/*
|
||||
* Find the next month and the year of the next month.
|
||||
* Note: tm_mon and next_month are from 0 to 11
|
||||
*/
|
||||
next_month = now.tm_mon + 1;
|
||||
if (next_month == 12) {
|
||||
next_month = 0;
|
||||
next_year = now.tm_year + 1;
|
||||
} else {
|
||||
next_year = now.tm_year;
|
||||
}
|
||||
|
||||
/* Find the maximum limit of alarm in days. */
|
||||
max_day_forward = rtc_month_days(now.tm_mon, now.tm_year)
|
||||
- now.tm_mday
|
||||
+ min(rtc_month_days(next_month, next_year), now.tm_mday);
|
||||
|
||||
/* Convert to timestamp and compare the alarm time and its upper limit */
|
||||
max_alarm_time64 = rtc_tm_to_time64(&now) + max_day_forward * SEC_PER_DAY;
|
||||
return rtc_tm_to_time64(tm) <= max_alarm_time64 ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
@ -469,17 +476,17 @@ static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
unsigned int cr, isr, alrmar;
|
||||
int ret = 0;
|
||||
|
||||
tm2bcd(tm);
|
||||
|
||||
/*
|
||||
* RTC alarm can't be set on a specific date, unless this date is
|
||||
* up to the same day of month next month.
|
||||
*/
|
||||
if (stm32_rtc_valid_alrm(rtc, tm) < 0) {
|
||||
if (stm32_rtc_valid_alrm(dev, tm) < 0) {
|
||||
dev_err(dev, "Alarm can be set only on upcoming month.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tm2bcd(tm);
|
||||
|
||||
alrmar = 0;
|
||||
/* tm_year and tm_mon are not used because not supported by RTC */
|
||||
alrmar |= (tm->tm_mday << STM32_RTC_ALRMXR_DATE_SHIFT) &
|
||||
@ -545,6 +552,7 @@ static void stm32_rtc_clear_events(struct stm32_rtc *rtc,
|
||||
static const struct stm32_rtc_data stm32_rtc_data = {
|
||||
.has_pclk = false,
|
||||
.need_dbp = true,
|
||||
.need_accuracy = false,
|
||||
.regs = {
|
||||
.tr = 0x00,
|
||||
.dr = 0x04,
|
||||
@ -566,6 +574,7 @@ static const struct stm32_rtc_data stm32_rtc_data = {
|
||||
static const struct stm32_rtc_data stm32h7_rtc_data = {
|
||||
.has_pclk = true,
|
||||
.need_dbp = true,
|
||||
.need_accuracy = false,
|
||||
.regs = {
|
||||
.tr = 0x00,
|
||||
.dr = 0x04,
|
||||
@ -596,6 +605,7 @@ static void stm32mp1_rtc_clear_events(struct stm32_rtc *rtc,
|
||||
static const struct stm32_rtc_data stm32mp1_data = {
|
||||
.has_pclk = true,
|
||||
.need_dbp = false,
|
||||
.need_accuracy = true,
|
||||
.regs = {
|
||||
.tr = 0x00,
|
||||
.dr = 0x04,
|
||||
@ -628,7 +638,7 @@ static int stm32_rtc_init(struct platform_device *pdev,
|
||||
const struct stm32_rtc_registers *regs = &rtc->data->regs;
|
||||
unsigned int prer, pred_a, pred_s, pred_a_max, pred_s_max, cr;
|
||||
unsigned int rate;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
rate = clk_get_rate(rtc->rtc_ck);
|
||||
|
||||
@ -636,18 +646,32 @@ static int stm32_rtc_init(struct platform_device *pdev,
|
||||
pred_a_max = STM32_RTC_PRER_PRED_A >> STM32_RTC_PRER_PRED_A_SHIFT;
|
||||
pred_s_max = STM32_RTC_PRER_PRED_S >> STM32_RTC_PRER_PRED_S_SHIFT;
|
||||
|
||||
for (pred_a = pred_a_max; pred_a + 1 > 0; pred_a--) {
|
||||
pred_s = (rate / (pred_a + 1)) - 1;
|
||||
if (rate > (pred_a_max + 1) * (pred_s_max + 1)) {
|
||||
dev_err(&pdev->dev, "rtc_ck rate is too high: %dHz\n", rate);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (((pred_s + 1) * (pred_a + 1)) == rate)
|
||||
break;
|
||||
if (rtc->data->need_accuracy) {
|
||||
for (pred_a = 0; pred_a <= pred_a_max; pred_a++) {
|
||||
pred_s = (rate / (pred_a + 1)) - 1;
|
||||
|
||||
if (pred_s <= pred_s_max && ((pred_s + 1) * (pred_a + 1)) == rate)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (pred_a = pred_a_max; pred_a + 1 > 0; pred_a--) {
|
||||
pred_s = (rate / (pred_a + 1)) - 1;
|
||||
|
||||
if (((pred_s + 1) * (pred_a + 1)) == rate)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Can't find a 1Hz, so give priority to RTC power consumption
|
||||
* by choosing the higher possible value for prediv_a
|
||||
*/
|
||||
if ((pred_s > pred_s_max) || (pred_a > pred_a_max)) {
|
||||
if (pred_s > pred_s_max || pred_a > pred_a_max) {
|
||||
pred_a = pred_a_max;
|
||||
pred_s = (rate / (pred_a + 1)) - 1;
|
||||
|
||||
@ -656,6 +680,20 @@ static int stm32_rtc_init(struct platform_device *pdev,
|
||||
"fast" : "slow");
|
||||
}
|
||||
|
||||
cr = readl_relaxed(rtc->base + regs->cr);
|
||||
|
||||
prer = readl_relaxed(rtc->base + regs->prer);
|
||||
prer &= STM32_RTC_PRER_PRED_S | STM32_RTC_PRER_PRED_A;
|
||||
|
||||
pred_s = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) &
|
||||
STM32_RTC_PRER_PRED_S;
|
||||
pred_a = (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) &
|
||||
STM32_RTC_PRER_PRED_A;
|
||||
|
||||
/* quit if there is nothing to initialize */
|
||||
if ((cr & STM32_RTC_CR_FMT) == 0 && prer == (pred_s | pred_a))
|
||||
return 0;
|
||||
|
||||
stm32_rtc_wpr_unlock(rtc);
|
||||
|
||||
ret = stm32_rtc_enter_init_mode(rtc);
|
||||
@ -665,13 +703,10 @@ static int stm32_rtc_init(struct platform_device *pdev,
|
||||
goto end;
|
||||
}
|
||||
|
||||
prer = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) & STM32_RTC_PRER_PRED_S;
|
||||
writel_relaxed(prer, rtc->base + regs->prer);
|
||||
prer |= (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) & STM32_RTC_PRER_PRED_A;
|
||||
writel_relaxed(prer, rtc->base + regs->prer);
|
||||
writel_relaxed(pred_s, rtc->base + regs->prer);
|
||||
writel_relaxed(pred_a | pred_s, rtc->base + regs->prer);
|
||||
|
||||
/* Force 24h time format */
|
||||
cr = readl_relaxed(rtc->base + regs->cr);
|
||||
cr &= ~STM32_RTC_CR_FMT;
|
||||
writel_relaxed(cr, rtc->base + regs->cr);
|
||||
|
||||
@ -730,16 +765,13 @@ static int stm32_rtc_probe(struct platform_device *pdev)
|
||||
rtc->rtc_ck = devm_clk_get(&pdev->dev, NULL);
|
||||
} else {
|
||||
rtc->pclk = devm_clk_get(&pdev->dev, "pclk");
|
||||
if (IS_ERR(rtc->pclk)) {
|
||||
dev_err(&pdev->dev, "no pclk clock");
|
||||
return PTR_ERR(rtc->pclk);
|
||||
}
|
||||
if (IS_ERR(rtc->pclk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(rtc->pclk), "no pclk clock");
|
||||
|
||||
rtc->rtc_ck = devm_clk_get(&pdev->dev, "rtc_ck");
|
||||
}
|
||||
if (IS_ERR(rtc->rtc_ck)) {
|
||||
dev_err(&pdev->dev, "no rtc_ck clock");
|
||||
return PTR_ERR(rtc->rtc_ck);
|
||||
}
|
||||
if (IS_ERR(rtc->rtc_ck))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(rtc->rtc_ck), "no rtc_ck clock");
|
||||
|
||||
if (rtc->data->has_pclk) {
|
||||
ret = clk_prepare_enable(rtc->pclk);
|
||||
@ -859,7 +891,6 @@ static void stm32_rtc_remove(struct platform_device *pdev)
|
||||
device_init_wakeup(&pdev->dev, false);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int stm32_rtc_suspend(struct device *dev)
|
||||
{
|
||||
struct stm32_rtc *rtc = dev_get_drvdata(dev);
|
||||
@ -890,10 +921,10 @@ static int stm32_rtc_resume(struct device *dev)
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(stm32_rtc_pm_ops,
|
||||
stm32_rtc_suspend, stm32_rtc_resume);
|
||||
static const struct dev_pm_ops stm32_rtc_pm_ops = {
|
||||
NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32_rtc_suspend, stm32_rtc_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver stm32_rtc_driver = {
|
||||
.probe = stm32_rtc_probe,
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/stmp_device.h>
|
||||
#include <linux/stmp3xxx_rtc_wdt.h>
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/slab.h>
|
||||
@ -847,8 +846,6 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_info(&pdev->dev, "RTC enabled\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -244,7 +244,7 @@ static int sp_rtc_probe(struct platform_device *plat_dev)
|
||||
|
||||
sp_rtc->irq = platform_get_irq(plat_dev, 0);
|
||||
if (sp_rtc->irq < 0)
|
||||
return dev_err_probe(&plat_dev->dev, sp_rtc->irq, "platform_get_irq failed\n");
|
||||
return sp_rtc->irq;
|
||||
|
||||
ret = devm_request_irq(&plat_dev->dev, sp_rtc->irq, sp_rtc_irq_handler,
|
||||
IRQF_TRIGGER_RISING, "rtc irq", plat_dev);
|
||||
|
@ -14,8 +14,6 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/types.h>
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sys_soc.h>
|
||||
#include <linux/property.h>
|
||||
|
@ -252,6 +252,7 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)
|
||||
|
||||
rtc->rtc->ops = &tps6586x_rtc_ops;
|
||||
rtc->rtc->range_max = (1ULL << 30) - 1; /* 30-bit seconds */
|
||||
rtc->rtc->alarm_offset_max = ALM1_VALID_RANGE_IN_SEC;
|
||||
rtc->rtc->start_secs = mktime64(2009, 1, 1, 0, 0, 0);
|
||||
rtc->rtc->set_start_time = true;
|
||||
|
||||
|
@ -406,11 +406,8 @@ static int tps65910_rtc_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, tps_rtc);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq <= 0) {
|
||||
dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n",
|
||||
irq);
|
||||
return -ENXIO;
|
||||
}
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
tps65910_rtc_interrupt, IRQF_TRIGGER_LOW,
|
||||
|
@ -487,11 +487,24 @@ static const struct rtc_class_ops twl_rtc_ops = {
|
||||
.alarm_irq_enable = twl_rtc_alarm_irq_enable,
|
||||
};
|
||||
|
||||
static int twl_nvram_read(void *priv, unsigned int offset, void *val,
|
||||
size_t bytes)
|
||||
{
|
||||
return twl_i2c_read((long)priv, val, offset, bytes);
|
||||
}
|
||||
|
||||
static int twl_nvram_write(void *priv, unsigned int offset, void *val,
|
||||
size_t bytes)
|
||||
{
|
||||
return twl_i2c_write((long)priv, val, offset, bytes);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static int twl_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct twl_rtc *twl_rtc;
|
||||
struct nvmem_config nvmem_cfg;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
int ret = -EINVAL;
|
||||
int irq = platform_get_irq(pdev, 0);
|
||||
@ -542,7 +555,6 @@ static int twl_rtc_probe(struct platform_device *pdev)
|
||||
REG_INT_MSK_STS_A);
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "Enabling TWL-RTC\n");
|
||||
ret = twl_rtc_write_u8(twl_rtc, BIT_RTC_CTRL_REG_STOP_RTC_M,
|
||||
REG_RTC_CTRL_REG);
|
||||
if (ret < 0)
|
||||
@ -564,11 +576,8 @@ static int twl_rtc_probe(struct platform_device *pdev)
|
||||
|
||||
twl_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
|
||||
&twl_rtc_ops, THIS_MODULE);
|
||||
if (IS_ERR(twl_rtc->rtc)) {
|
||||
dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
|
||||
PTR_ERR(twl_rtc->rtc));
|
||||
if (IS_ERR(twl_rtc->rtc))
|
||||
return PTR_ERR(twl_rtc->rtc);
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
twl_rtc_interrupt,
|
||||
@ -579,6 +588,30 @@ static int twl_rtc_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(&nvmem_cfg, 0, sizeof(nvmem_cfg));
|
||||
nvmem_cfg.name = "twl-secured-";
|
||||
nvmem_cfg.type = NVMEM_TYPE_BATTERY_BACKED;
|
||||
nvmem_cfg.reg_read = twl_nvram_read,
|
||||
nvmem_cfg.reg_write = twl_nvram_write,
|
||||
nvmem_cfg.word_size = 1;
|
||||
nvmem_cfg.stride = 1;
|
||||
if (twl_class_is_4030()) {
|
||||
/* 20 bytes SECURED_REG area */
|
||||
nvmem_cfg.size = 20;
|
||||
nvmem_cfg.priv = (void *)TWL_MODULE_SECURED_REG;
|
||||
devm_rtc_nvmem_register(twl_rtc->rtc, &nvmem_cfg);
|
||||
/* 8 bytes BACKUP area */
|
||||
nvmem_cfg.name = "twl-backup-";
|
||||
nvmem_cfg.size = 8;
|
||||
nvmem_cfg.priv = (void *)TWL4030_MODULE_BACKUP;
|
||||
devm_rtc_nvmem_register(twl_rtc->rtc, &nvmem_cfg);
|
||||
} else {
|
||||
/* 8 bytes SECURED_REG area */
|
||||
nvmem_cfg.size = 8;
|
||||
nvmem_cfg.priv = (void *)TWL_MODULE_SECURED_REG;
|
||||
devm_rtc_nvmem_register(twl_rtc->rtc, &nvmem_cfg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -386,8 +386,6 @@ static int wm8350_rtc_probe(struct platform_device *pdev)
|
||||
/* enable the RTC if it's not already enabled */
|
||||
power5 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5);
|
||||
if (!(power5 & WM8350_RTC_TICK_ENA)) {
|
||||
dev_info(wm8350->dev, "Starting RTC\n");
|
||||
|
||||
wm8350_reg_unlock(wm8350);
|
||||
|
||||
ret = wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5,
|
||||
@ -426,11 +424,8 @@ static int wm8350_rtc_probe(struct platform_device *pdev)
|
||||
|
||||
wm_rtc->rtc = devm_rtc_device_register(&pdev->dev, "wm8350",
|
||||
&wm8350_rtc_ops, THIS_MODULE);
|
||||
if (IS_ERR(wm_rtc->rtc)) {
|
||||
ret = PTR_ERR(wm_rtc->rtc);
|
||||
dev_err(&pdev->dev, "failed to register RTC: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(wm_rtc->rtc))
|
||||
return PTR_ERR(wm_rtc->rtc);
|
||||
|
||||
ret = wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC,
|
||||
wm8350_rtc_update_handler, 0,
|
||||
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* ds2404.h - platform data structure for the DS2404 RTC.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2012 Sven Schnelle <svens@stackframe.org>
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_DS2404_H
|
||||
#define __LINUX_DS2404_H
|
||||
|
||||
struct ds2404_platform_data {
|
||||
|
||||
unsigned int gpio_rst;
|
||||
unsigned int gpio_clk;
|
||||
unsigned int gpio_dq;
|
||||
};
|
||||
#endif
|
@ -146,6 +146,7 @@ struct rtc_device {
|
||||
|
||||
time64_t range_min;
|
||||
timeu64_t range_max;
|
||||
timeu64_t alarm_offset_max;
|
||||
time64_t start_secs;
|
||||
time64_t offset_secs;
|
||||
bool set_start_time;
|
||||
|
Loading…
Reference in New Issue
Block a user