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:
Linus Torvalds 2023-09-07 16:07:35 -07:00
commit ff6e6ded54
59 changed files with 1337 additions and 619 deletions

View file

@ -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

View 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>;
};
};
...

View file

@ -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>;
...
};

View file

@ -18,6 +18,7 @@ properties:
- nxp,pca2129
- nxp,pcf2127
- nxp,pcf2129
- nxp,pcf2131
reg:
maxItems: 1

View 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>;
};
...

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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);

View file

@ -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>

View file

@ -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,
},
};

View file

@ -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,
},
};

View file

@ -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,
},
};

View file

@ -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,
},
};

View file

@ -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()) {

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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];

View file

@ -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>

View file

@ -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;
}

View file

@ -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>

View file

@ -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);

View file

@ -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,
};

View file

@ -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);
}

View file

@ -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)

View file

@ -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>

View file

@ -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>

View file

@ -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,
};

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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)

View file

@ -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,

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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"

View file

@ -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;

View file

@ -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)

View file

@ -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>

View file

@ -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);

View file

@ -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>

View file

@ -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>

View file

@ -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);

View file

@ -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>

View file

@ -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,

View file

@ -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>

View file

@ -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;
}

View file

@ -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);

View file

@ -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>

View file

@ -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>

View file

@ -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;

View file

@ -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,

View file

@ -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;
}

View file

@ -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,

View file

@ -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

View file

@ -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;