RTC for 6.9

Subsytem:
  - rtc_class is now const
 
 Drivers:
  - ds1511: driver cleanup, set date and time range and alarm offset limit
  - max31335: fix interrupt handler
  - pcf8523: improve suspend support
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEBqsFVZXh8s/0O5JiY6TcMGxwOjIFAmX8uCcACgkQY6TcMGxw
 OjI1hA//fK1Cs2eDL2E7e8bQCJtDJ+gdzVT210LwT9TCOgUV+arqLjF/i/pq8m5j
 CK/ukk5OLZL3v5dS7rsOZAiTg1N9Q+3SEoaTP029kRfA2SxOE2isR9W5nNAvyJC0
 L4Y4YEcEMsJpluK94G1/4ult1We9vCGSlqlNknChp3BL5ELxg7T/Ea5wda2OLSRx
 +ZgQpB6O+LIIQucm8mgCAlucMJrAj4+qEF7HO0AeElDh+md4OvjrF8Y30vTfs82L
 hGazWQgu8J4Jmy4u6q00s5IhfsvwNZVYgaASv8ivB8/9qgQLktZ6HFHRSwloRXg2
 o9OqcM/OR7Lw4taH/6pnVQ37UUAQ/Vy9QJy2GHza1uDzlBBjtqVz8zFqheu/rmnJ
 3AX7hlowBx9fPpxmStP2Ac9WIvtepV25eOlDDSlDiS8/4T/DRJHwpRQghSTDnFJ4
 fRU1HFbaj3ZKRgBzu5zJU4XvQO4X/DKxSHVMy+rVtsndWzDa8q11QZrQJAP4ZpLM
 /+zfar2RFnsnop1Dg9cz/hq0gWbQUMJ16qN3cFYl3jVVzC3JSld7B0+DhZdII1Lg
 YsCXuUQusnOTFm9GtyC6doHgmC3Dy2wentz6Vn6ynyBOR4NKjJPkI7PICdgzkIDi
 AJI9qSxQcT6gOSw2PAlzOcYb7AD3cOJCeg3ukt7aDl8S38RKR3w=
 =Is7n
 -----END PGP SIGNATURE-----

Merge tag 'rtc-6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux

Pull RTC updates from Alexandre Belloni:
 "Subsytem:
   - rtc_class is now const

  Drivers:
   - ds1511: cleanup, set date and time range and alarm offset limit
   - max31335: fix interrupt handler
   - pcf8523: improve suspend support"

* tag 'rtc-6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (28 commits)
  MAINTAINER: Include linux-arm-msm for Qualcomm RTC patches
  dt-bindings: rtc: zynqmp: Add support for Versal/Versal NET SoCs
  rtc: class: make rtc_class constant
  dt-bindings: rtc: abx80x: Improve checks on trickle charger constraints
  MAINTAINERS: adjust file entry in ARM/Mediatek RTC DRIVER
  rtc: nct3018y: fix possible NULL dereference
  rtc: max31335: fix interrupt status reg
  rtc: mt6397: select IRQ_DOMAIN instead of depending on it
  dt-bindings: rtc: abx80x: convert to yaml
  rtc: m41t80: Use the unified property API get the wakeup-source property
  dt-bindings: at91rm9260-rtt: add sam9x7 compatible
  dt-bindings: rtc: convert MT7622 RTC to the json-schema
  dt-bindings: rtc: convert MT2717 RTC to the json-schema
  rtc: pcf8523: add suspend handlers for alarm IRQ
  rtc: ds1511: set alarm offset limit
  rtc: ds1511: set range
  rtc: ds1511: drop inline/noinline hints
  rtc: ds1511: rename pdata
  rtc: ds1511: implement ds1511_rtc_read_alarm properly
  rtc: ds1511: remove partial alarm support
  ...
This commit is contained in:
Linus Torvalds 2024-03-21 17:16:46 -07:00
commit 3faae16b5a
20 changed files with 359 additions and 328 deletions

View file

@ -1,31 +0,0 @@
Abracon ABX80X I2C ultra low power RTC/Alarm chip
The Abracon ABX80X family consist of the ab0801, ab0803, ab0804, ab0805, ab1801,
ab1803, ab1804 and ab1805. The ab0805 is the superset of ab080x and the ab1805
is the superset of ab180x.
Required properties:
- "compatible": should one of:
"abracon,abx80x"
"abracon,ab0801"
"abracon,ab0803"
"abracon,ab0804"
"abracon,ab0805"
"abracon,ab1801"
"abracon,ab1803"
"abracon,ab1804"
"abracon,ab1805"
"microcrystal,rv1805"
Using "abracon,abx80x" will enable chip autodetection.
- "reg": I2C bus address of the device
Optional properties:
The abx804 and abx805 have a trickle charger that is able to charge the
connected battery or supercap. Both the following properties have to be defined
and valid to enable charging:
- "abracon,tc-diode": should be "standard" (0.6V) or "schottky" (0.3V)
- "abracon,tc-resistor": should be <0>, <3>, <6> or <11>. 0 disables the output
resistor, the other values are in kOhm.

View file

@ -0,0 +1,98 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/abracon,abx80x.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Abracon ABX80X I2C ultra low power RTC/Alarm chip
maintainers:
- linux-rtc@vger.kernel.org
properties:
compatible:
description:
The wildcard 'abracon,abx80x' may be used to support a mix
of different abracon rtc`s. In this case the driver
must perform auto-detection from ID register.
enum:
- abracon,abx80x
- abracon,ab0801
- abracon,ab0803
- abracon,ab0804
- abracon,ab0805
- abracon,ab1801
- abracon,ab1803
- abracon,ab1804
- abracon,ab1805
- microcrystal,rv1805
reg:
maxItems: 1
interrupts:
maxItems: 1
abracon,tc-diode:
description:
Trickle-charge diode type.
Required to enable charging backup battery.
Supported are 'standard' diodes with a 0.6V drop
and 'schottky' diodes with a 0.3V drop.
$ref: /schemas/types.yaml#/definitions/string
enum:
- standard
- schottky
abracon,tc-resistor:
description:
Trickle-charge resistor value in kOhm.
Required to enable charging backup battery.
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 3, 6, 11]
dependentRequired:
abracon,tc-diode: ["abracon,tc-resistor"]
abracon,tc-resistor: ["abracon,tc-diode"]
required:
- compatible
- reg
allOf:
- $ref: rtc.yaml#
- if:
properties:
compatible:
not:
contains:
enum:
- abracon,abx80x
- abracon,ab0804
- abracon,ab1804
- abracon,ab0805
- abracon,ab1805
then:
properties:
abracon,tc-diode: false
abracon,tc-resistor: false
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
rtc@69 {
compatible = "abracon,abx80x";
reg = <0x69>;
abracon,tc-diode = "schottky";
abracon,tc-resistor = <3>;
interrupts = <44 IRQ_TYPE_EDGE_FALLING>;
};
};

View file

@ -19,7 +19,9 @@ properties:
- items: - items:
- const: atmel,at91sam9260-rtt - const: atmel,at91sam9260-rtt
- items: - items:
- const: microchip,sam9x60-rtt - enum:
- microchip,sam9x60-rtt
- microchip,sam9x7-rtt
- const: atmel,at91sam9260-rtt - const: atmel,at91sam9260-rtt
- items: - items:
- const: microchip,sama7g5-rtt - const: microchip,sama7g5-rtt

View file

@ -0,0 +1,39 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/mediatek,mt2712-rtc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek MT2712 on-SoC RTC
allOf:
- $ref: rtc.yaml#
maintainers:
- Ran Bi <ran.bi@mediatek.com>
properties:
compatible:
const: mediatek,mt2712-rtc
reg:
maxItems: 1
interrupts:
maxItems: 1
required:
- reg
- interrupts
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
rtc@10011000 {
compatible = "mediatek,mt2712-rtc";
reg = <0x10011000 0x1000>;
interrupts = <GIC_SPI 239 IRQ_TYPE_LEVEL_LOW>;
};

View file

@ -0,0 +1,52 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/mediatek,mt7622-rtc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek MT7622 on-SoC RTC
allOf:
- $ref: rtc.yaml#
maintainers:
- Sean Wang <sean.wang@mediatek.com>
properties:
compatible:
items:
- const: mediatek,mt7622-rtc
- const: mediatek,soc-rtc
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
clock-names:
const: rtc
required:
- reg
- interrupts
- clocks
- clock-names
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/mt7622-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
rtc@10212800 {
compatible = "mediatek,mt7622-rtc", "mediatek,soc-rtc";
reg = <0x10212800 0x200>;
interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_LOW>;
clocks = <&topckgen CLK_TOP_RTC>;
clock-names = "rtc";
};

View file

@ -1,14 +0,0 @@
Device-Tree bindings for MediaTek SoC based RTC
Required properties:
- compatible : Should be "mediatek,mt2712-rtc" : for MT2712 SoC
- reg : Specifies base physical address and size of the registers;
- interrupts : Should contain the interrupt for RTC alarm;
Example:
rtc: rtc@10011000 {
compatible = "mediatek,mt2712-rtc";
reg = <0 0x10011000 0 0x1000>;
interrupts = <GIC_SPI 239 IRQ_TYPE_LEVEL_LOW>;
};

View file

@ -1,21 +0,0 @@
Device-Tree bindings for MediaTek SoC based RTC
Required properties:
- compatible : Should be
"mediatek,mt7622-rtc", "mediatek,soc-rtc" : for MT7622 SoC
- reg : Specifies base physical address and size of the registers;
- interrupts : Should contain the interrupt for RTC alarm;
- clocks : Specifies list of clock specifiers, corresponding to
entries in clock-names property;
- clock-names : Should contain "rtc" entries
Example:
rtc: rtc@10212800 {
compatible = "mediatek,mt7622-rtc",
"mediatek,soc-rtc";
reg = <0 0x10212800 0 0x200>;
interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_LOW>;
clocks = <&topckgen CLK_TOP_RTC>;
clock-names = "rtc";
};

View file

@ -18,7 +18,13 @@ allOf:
properties: properties:
compatible: compatible:
const: xlnx,zynqmp-rtc oneOf:
- const: xlnx,zynqmp-rtc
- items:
- enum:
- xlnx,versal-rtc
- xlnx,versal-net-rtc
- const: xlnx,zynqmp-rtc
reg: reg:
maxItems: 1 maxItems: 1
@ -48,6 +54,9 @@ properties:
default: 0x198233 default: 0x198233
deprecated: true deprecated: true
power-domains:
maxItems: 1
required: required:
- compatible - compatible
- reg - reg

View file

@ -2377,8 +2377,8 @@ M: Sean Wang <sean.wang@mediatek.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/rtc/rtc-mt2712.txt F: Documentation/devicetree/bindings/rtc/mediatek,mt2712-rtc.yaml
F: Documentation/devicetree/bindings/rtc/rtc-mt7622.txt F: Documentation/devicetree/bindings/rtc/mediatek,mt7622-rtc.yaml
F: drivers/rtc/rtc-mt2712.c F: drivers/rtc/rtc-mt2712.c
F: drivers/rtc/rtc-mt6397.c F: drivers/rtc/rtc-mt6397.c
F: drivers/rtc/rtc-mt7622.c F: drivers/rtc/rtc-mt7622.c
@ -2617,6 +2617,7 @@ F: drivers/pci/controller/dwc/pcie-qcom.c
F: drivers/phy/qualcomm/ F: drivers/phy/qualcomm/
F: drivers/power/*/msm* F: drivers/power/*/msm*
F: drivers/reset/reset-qcom-* F: drivers/reset/reset-qcom-*
F: drivers/rtc/rtc-pm8xxx.c
F: drivers/spi/spi-geni-qcom.c F: drivers/spi/spi-geni-qcom.c
F: drivers/spi/spi-qcom-qspi.c F: drivers/spi/spi-qcom-qspi.c
F: drivers/spi/spi-qup.c F: drivers/spi/spi-qup.c

View file

@ -1858,7 +1858,8 @@ config RTC_DRV_MT2712
config RTC_DRV_MT6397 config RTC_DRV_MT6397
tristate "MediaTek PMIC based RTC" tristate "MediaTek PMIC based RTC"
depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN) depends on MFD_MT6397 || COMPILE_TEST
select IRQ_DOMAIN
help help
This selects the MediaTek(R) RTC driver. RTC is part of MediaTek This selects the MediaTek(R) RTC driver. RTC is part of MediaTek
MT6397 PMIC. You should enable MT6397 PMIC MFD before select MT6397 PMIC. You should enable MT6397 PMIC MFD before select

View file

@ -21,7 +21,6 @@
#include "rtc-core.h" #include "rtc-core.h"
static DEFINE_IDA(rtc_ida); static DEFINE_IDA(rtc_ida);
struct class *rtc_class;
static void rtc_device_release(struct device *dev) static void rtc_device_release(struct device *dev)
{ {
@ -199,6 +198,11 @@ static SIMPLE_DEV_PM_OPS(rtc_class_dev_pm_ops, rtc_suspend, rtc_resume);
#define RTC_CLASS_DEV_PM_OPS NULL #define RTC_CLASS_DEV_PM_OPS NULL
#endif #endif
const struct class rtc_class = {
.name = "rtc",
.pm = RTC_CLASS_DEV_PM_OPS,
};
/* Ensure the caller will set the id before releasing the device */ /* Ensure the caller will set the id before releasing the device */
static struct rtc_device *rtc_allocate_device(void) static struct rtc_device *rtc_allocate_device(void)
{ {
@ -220,7 +224,7 @@ static struct rtc_device *rtc_allocate_device(void)
rtc->irq_freq = 1; rtc->irq_freq = 1;
rtc->max_user_freq = 64; rtc->max_user_freq = 64;
rtc->dev.class = rtc_class; rtc->dev.class = &rtc_class;
rtc->dev.groups = rtc_get_dev_attribute_groups(); rtc->dev.groups = rtc_get_dev_attribute_groups();
rtc->dev.release = rtc_device_release; rtc->dev.release = rtc_device_release;
@ -475,13 +479,14 @@ EXPORT_SYMBOL_GPL(devm_rtc_device_register);
static int __init rtc_init(void) static int __init rtc_init(void)
{ {
rtc_class = class_create("rtc"); int err;
if (IS_ERR(rtc_class)) {
pr_err("couldn't create class\n"); err = class_register(&rtc_class);
return PTR_ERR(rtc_class); if (err)
} return err;
rtc_class->pm = RTC_CLASS_DEV_PM_OPS;
rtc_dev_init(); rtc_dev_init();
return 0; return 0;
} }
subsys_initcall(rtc_init); subsys_initcall(rtc_init);

View file

@ -696,7 +696,7 @@ struct rtc_device *rtc_class_open(const char *name)
struct device *dev; struct device *dev;
struct rtc_device *rtc = NULL; struct rtc_device *rtc = NULL;
dev = class_find_device_by_name(rtc_class, name); dev = class_find_device_by_name(&rtc_class, name);
if (dev) if (dev)
rtc = to_rtc_device(dev); rtc = to_rtc_device(dev);

View file

@ -22,26 +22,24 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
enum ds1511reg { #define DS1511_SEC 0x0
DS1511_SEC = 0x0, #define DS1511_MIN 0x1
DS1511_MIN = 0x1, #define DS1511_HOUR 0x2
DS1511_HOUR = 0x2, #define DS1511_DOW 0x3
DS1511_DOW = 0x3, #define DS1511_DOM 0x4
DS1511_DOM = 0x4, #define DS1511_MONTH 0x5
DS1511_MONTH = 0x5, #define DS1511_YEAR 0x6
DS1511_YEAR = 0x6, #define DS1511_CENTURY 0x7
DS1511_CENTURY = 0x7, #define DS1511_AM1_SEC 0x8
DS1511_AM1_SEC = 0x8, #define DS1511_AM2_MIN 0x9
DS1511_AM2_MIN = 0x9, #define DS1511_AM3_HOUR 0xa
DS1511_AM3_HOUR = 0xa, #define DS1511_AM4_DATE 0xb
DS1511_AM4_DATE = 0xb, #define DS1511_WD_MSEC 0xc
DS1511_WD_MSEC = 0xc, #define DS1511_WD_SEC 0xd
DS1511_WD_SEC = 0xd, #define DS1511_CONTROL_A 0xe
DS1511_CONTROL_A = 0xe, #define DS1511_CONTROL_B 0xf
DS1511_CONTROL_B = 0xf, #define DS1511_RAMADDR_LSB 0x10
DS1511_RAMADDR_LSB = 0x10, #define DS1511_RAMDATA 0x13
DS1511_RAMDATA = 0x13
};
#define DS1511_BLF1 0x80 #define DS1511_BLF1 0x80
#define DS1511_BLF2 0x40 #define DS1511_BLF2 0x40
@ -61,35 +59,10 @@ enum ds1511reg {
#define DS1511_WDS 0x01 #define DS1511_WDS 0x01
#define DS1511_RAM_MAX 0x100 #define DS1511_RAM_MAX 0x100
#define RTC_CMD DS1511_CONTROL_B struct ds1511_data {
#define RTC_CMD1 DS1511_CONTROL_A
#define RTC_ALARM_SEC DS1511_AM1_SEC
#define RTC_ALARM_MIN DS1511_AM2_MIN
#define RTC_ALARM_HOUR DS1511_AM3_HOUR
#define RTC_ALARM_DATE DS1511_AM4_DATE
#define RTC_SEC DS1511_SEC
#define RTC_MIN DS1511_MIN
#define RTC_HOUR DS1511_HOUR
#define RTC_DOW DS1511_DOW
#define RTC_DOM DS1511_DOM
#define RTC_MON DS1511_MONTH
#define RTC_YEAR DS1511_YEAR
#define RTC_CENTURY DS1511_CENTURY
#define RTC_TIE DS1511_TIE
#define RTC_TE DS1511_TE
struct rtc_plat_data {
struct rtc_device *rtc; struct rtc_device *rtc;
void __iomem *ioaddr; /* virtual base address */ void __iomem *ioaddr; /* virtual base address */
int irq; int irq;
unsigned int irqen;
int alrm_sec;
int alrm_min;
int alrm_hour;
int alrm_mday;
spinlock_t lock; spinlock_t lock;
}; };
@ -98,95 +71,33 @@ static DEFINE_SPINLOCK(ds1511_lock);
static __iomem char *ds1511_base; static __iomem char *ds1511_base;
static u32 reg_spacing = 1; static u32 reg_spacing = 1;
static noinline void static void rtc_write(uint8_t val, uint32_t reg)
rtc_write(uint8_t val, uint32_t reg)
{ {
writeb(val, ds1511_base + (reg * reg_spacing)); writeb(val, ds1511_base + (reg * reg_spacing));
} }
static noinline uint8_t static uint8_t rtc_read(uint32_t reg)
rtc_read(enum ds1511reg reg)
{ {
return readb(ds1511_base + (reg * reg_spacing)); return readb(ds1511_base + (reg * reg_spacing));
} }
static inline void static void rtc_disable_update(void)
rtc_disable_update(void)
{ {
rtc_write((rtc_read(RTC_CMD) & ~RTC_TE), RTC_CMD); rtc_write((rtc_read(DS1511_CONTROL_B) & ~DS1511_TE), DS1511_CONTROL_B);
} }
static void static void rtc_enable_update(void)
rtc_enable_update(void)
{ {
rtc_write((rtc_read(RTC_CMD) | RTC_TE), RTC_CMD); rtc_write((rtc_read(DS1511_CONTROL_B) | DS1511_TE), DS1511_CONTROL_B);
} }
/*
* #define DS1511_WDOG_RESET_SUPPORT
*
* Uncomment this if you want to use these routines in
* some platform code.
*/
#ifdef DS1511_WDOG_RESET_SUPPORT
/*
* just enough code to set the watchdog timer so that it
* will reboot the system
*/
void
ds1511_wdog_set(unsigned long deciseconds)
{
/*
* the wdog timer can take 99.99 seconds
*/
deciseconds %= 10000;
/*
* set the wdog values in the wdog registers
*/
rtc_write(bin2bcd(deciseconds % 100), DS1511_WD_MSEC);
rtc_write(bin2bcd(deciseconds / 100), DS1511_WD_SEC);
/*
* set wdog enable and wdog 'steering' bit to issue a reset
*/
rtc_write(rtc_read(RTC_CMD) | DS1511_WDE | DS1511_WDS, RTC_CMD);
}
void
ds1511_wdog_disable(void)
{
/*
* clear wdog enable and wdog 'steering' bits
*/
rtc_write(rtc_read(RTC_CMD) & ~(DS1511_WDE | DS1511_WDS), RTC_CMD);
/*
* clear the wdog counter
*/
rtc_write(0, DS1511_WD_MSEC);
rtc_write(0, DS1511_WD_SEC);
}
#endif
/*
* set the rtc chip's idea of the time.
* stupidly, some callers call with year unmolested;
* and some call with year = year - 1900. thanks.
*/
static int ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm) static int ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
{ {
u8 mon, day, dow, hrs, min, sec, yrs, cen; u8 mon, day, dow, hrs, min, sec, yrs, cen;
unsigned long flags; unsigned long flags;
/*
* won't have to change this for a while
*/
if (rtc_tm->tm_year < 1900)
rtc_tm->tm_year += 1900;
if (rtc_tm->tm_year < 1970)
return -EINVAL;
yrs = rtc_tm->tm_year % 100; yrs = rtc_tm->tm_year % 100;
cen = rtc_tm->tm_year / 100; cen = 19 + rtc_tm->tm_year / 100;
mon = rtc_tm->tm_mon + 1; /* tm_mon starts at zero */ mon = rtc_tm->tm_mon + 1; /* tm_mon starts at zero */
day = rtc_tm->tm_mday; day = rtc_tm->tm_mday;
dow = rtc_tm->tm_wday & 0x7; /* automatic BCD */ dow = rtc_tm->tm_wday & 0x7; /* automatic BCD */
@ -194,15 +105,6 @@ static int ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
min = rtc_tm->tm_min; min = rtc_tm->tm_min;
sec = rtc_tm->tm_sec; sec = rtc_tm->tm_sec;
if ((mon > 12) || (day == 0))
return -EINVAL;
if (day > rtc_month_days(rtc_tm->tm_mon, rtc_tm->tm_year))
return -EINVAL;
if ((hrs >= 24) || (min >= 60) || (sec >= 60))
return -EINVAL;
/* /*
* each register is a different number of valid bits * each register is a different number of valid bits
*/ */
@ -216,14 +118,14 @@ static int ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
spin_lock_irqsave(&ds1511_lock, flags); spin_lock_irqsave(&ds1511_lock, flags);
rtc_disable_update(); rtc_disable_update();
rtc_write(cen, RTC_CENTURY); rtc_write(cen, DS1511_CENTURY);
rtc_write(yrs, RTC_YEAR); rtc_write(yrs, DS1511_YEAR);
rtc_write((rtc_read(RTC_MON) & 0xe0) | mon, RTC_MON); rtc_write((rtc_read(DS1511_MONTH) & 0xe0) | mon, DS1511_MONTH);
rtc_write(day, RTC_DOM); rtc_write(day, DS1511_DOM);
rtc_write(hrs, RTC_HOUR); rtc_write(hrs, DS1511_HOUR);
rtc_write(min, RTC_MIN); rtc_write(min, DS1511_MIN);
rtc_write(sec, RTC_SEC); rtc_write(sec, DS1511_SEC);
rtc_write(dow, RTC_DOW); rtc_write(dow, DS1511_DOW);
rtc_enable_update(); rtc_enable_update();
spin_unlock_irqrestore(&ds1511_lock, flags); spin_unlock_irqrestore(&ds1511_lock, flags);
@ -238,14 +140,14 @@ static int ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
spin_lock_irqsave(&ds1511_lock, flags); spin_lock_irqsave(&ds1511_lock, flags);
rtc_disable_update(); rtc_disable_update();
rtc_tm->tm_sec = rtc_read(RTC_SEC) & 0x7f; rtc_tm->tm_sec = rtc_read(DS1511_SEC) & 0x7f;
rtc_tm->tm_min = rtc_read(RTC_MIN) & 0x7f; rtc_tm->tm_min = rtc_read(DS1511_MIN) & 0x7f;
rtc_tm->tm_hour = rtc_read(RTC_HOUR) & 0x3f; rtc_tm->tm_hour = rtc_read(DS1511_HOUR) & 0x3f;
rtc_tm->tm_mday = rtc_read(RTC_DOM) & 0x3f; rtc_tm->tm_mday = rtc_read(DS1511_DOM) & 0x3f;
rtc_tm->tm_wday = rtc_read(RTC_DOW) & 0x7; rtc_tm->tm_wday = rtc_read(DS1511_DOW) & 0x7;
rtc_tm->tm_mon = rtc_read(RTC_MON) & 0x1f; rtc_tm->tm_mon = rtc_read(DS1511_MONTH) & 0x1f;
rtc_tm->tm_year = rtc_read(RTC_YEAR) & 0x7f; rtc_tm->tm_year = rtc_read(DS1511_YEAR) & 0x7f;
century = rtc_read(RTC_CENTURY); century = rtc_read(DS1511_CENTURY);
rtc_enable_update(); rtc_enable_update();
spin_unlock_irqrestore(&ds1511_lock, flags); spin_unlock_irqrestore(&ds1511_lock, flags);
@ -271,106 +173,67 @@ static int ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
return 0; return 0;
} }
/* static void ds1511_rtc_alarm_enable(unsigned int enabled)
* write the alarm register settings
*
* we only have the use to interrupt every second, otherwise
* known as the update interrupt, or the interrupt if the whole
* date/hours/mins/secs matches. the ds1511 has many more
* permutations, but the kernel doesn't.
*/
static void
ds1511_rtc_update_alarm(struct rtc_plat_data *pdata)
{ {
rtc_write(rtc_read(DS1511_CONTROL_B) | (enabled ? DS1511_TIE : 0), DS1511_CONTROL_B);
}
static int ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct ds1511_data *ds1511 = dev_get_drvdata(dev);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&pdata->lock, flags); spin_lock_irqsave(&ds1511->lock, flags);
rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? rtc_write(bin2bcd(alrm->time.tm_mday) & 0x3f, DS1511_AM4_DATE);
0x80 : bin2bcd(pdata->alrm_mday) & 0x3f, rtc_write(bin2bcd(alrm->time.tm_hour) & 0x3f, DS1511_AM3_HOUR);
RTC_ALARM_DATE); rtc_write(bin2bcd(alrm->time.tm_min) & 0x7f, DS1511_AM2_MIN);
rtc_write(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ? rtc_write(bin2bcd(alrm->time.tm_sec) & 0x7f, DS1511_AM1_SEC);
0x80 : bin2bcd(pdata->alrm_hour) & 0x3f, ds1511_rtc_alarm_enable(alrm->enabled);
RTC_ALARM_HOUR);
rtc_write(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ?
0x80 : bin2bcd(pdata->alrm_min) & 0x7f,
RTC_ALARM_MIN);
rtc_write(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ?
0x80 : bin2bcd(pdata->alrm_sec) & 0x7f,
RTC_ALARM_SEC);
rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD);
rtc_read(RTC_CMD1); /* clear interrupts */
spin_unlock_irqrestore(&pdata->lock, flags);
}
static int rtc_read(DS1511_CONTROL_A); /* clear interrupts */
ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) spin_unlock_irqrestore(&ds1511->lock, flags);
{
struct rtc_plat_data *pdata = dev_get_drvdata(dev);
if (pdata->irq <= 0)
return -EINVAL;
pdata->alrm_mday = alrm->time.tm_mday;
pdata->alrm_hour = alrm->time.tm_hour;
pdata->alrm_min = alrm->time.tm_min;
pdata->alrm_sec = alrm->time.tm_sec;
if (alrm->enabled)
pdata->irqen |= RTC_AF;
ds1511_rtc_update_alarm(pdata);
return 0; return 0;
} }
static int static int ds1511_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
ds1511_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{ {
struct rtc_plat_data *pdata = dev_get_drvdata(dev); alrm->time.tm_mday = bcd2bin(rtc_read(DS1511_AM4_DATE) & 0x3f);
alrm->time.tm_hour = bcd2bin(rtc_read(DS1511_AM3_HOUR) & 0x3f);
alrm->time.tm_min = bcd2bin(rtc_read(DS1511_AM2_MIN) & 0x7f);
alrm->time.tm_sec = bcd2bin(rtc_read(DS1511_AM1_SEC) & 0x7f);
alrm->enabled = !!(rtc_read(DS1511_CONTROL_B) & DS1511_TIE);
if (pdata->irq <= 0)
return -EINVAL;
alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday;
alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour;
alrm->time.tm_min = pdata->alrm_min < 0 ? 0 : pdata->alrm_min;
alrm->time.tm_sec = pdata->alrm_sec < 0 ? 0 : pdata->alrm_sec;
alrm->enabled = (pdata->irqen & RTC_AF) ? 1 : 0;
return 0; return 0;
} }
static irqreturn_t static irqreturn_t ds1511_interrupt(int irq, void *dev_id)
ds1511_interrupt(int irq, void *dev_id)
{ {
struct platform_device *pdev = dev_id; struct platform_device *pdev = dev_id;
struct rtc_plat_data *pdata = platform_get_drvdata(pdev); struct ds1511_data *ds1511 = platform_get_drvdata(pdev);
unsigned long events = 0; unsigned long events = 0;
spin_lock(&pdata->lock); spin_lock(&ds1511->lock);
/* /*
* read and clear interrupt * read and clear interrupt
*/ */
if (rtc_read(RTC_CMD1) & DS1511_IRQF) { if (rtc_read(DS1511_CONTROL_A) & DS1511_IRQF) {
events = RTC_IRQF; events = RTC_IRQF | RTC_AF;
if (rtc_read(RTC_ALARM_SEC) & 0x80) rtc_update_irq(ds1511->rtc, 1, events);
events |= RTC_UF;
else
events |= RTC_AF;
rtc_update_irq(pdata->rtc, 1, events);
} }
spin_unlock(&pdata->lock); spin_unlock(&ds1511->lock);
return events ? IRQ_HANDLED : IRQ_NONE; return events ? IRQ_HANDLED : IRQ_NONE;
} }
static int ds1511_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) static int ds1511_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{ {
struct rtc_plat_data *pdata = dev_get_drvdata(dev); struct ds1511_data *ds1511 = dev_get_drvdata(dev);
unsigned long flags;
spin_lock_irqsave(&ds1511->lock, flags);
ds1511_rtc_alarm_enable(enabled);
spin_unlock_irqrestore(&ds1511->lock, flags);
if (pdata->irq <= 0)
return -EINVAL;
if (enabled)
pdata->irqen |= RTC_AF;
else
pdata->irqen &= ~RTC_AF;
ds1511_rtc_update_alarm(pdata);
return 0; return 0;
} }
@ -408,7 +271,7 @@ static int ds1511_nvram_write(void *priv, unsigned int pos, void *buf,
static int ds1511_rtc_probe(struct platform_device *pdev) static int ds1511_rtc_probe(struct platform_device *pdev)
{ {
struct rtc_plat_data *pdata; struct ds1511_data *ds1511;
int ret = 0; int ret = 0;
struct nvmem_config ds1511_nvmem_cfg = { struct nvmem_config ds1511_nvmem_cfg = {
.name = "ds1511_nvram", .name = "ds1511_nvram",
@ -420,21 +283,21 @@ static int ds1511_rtc_probe(struct platform_device *pdev)
.priv = &pdev->dev, .priv = &pdev->dev,
}; };
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); ds1511 = devm_kzalloc(&pdev->dev, sizeof(*ds1511), GFP_KERNEL);
if (!pdata) if (!ds1511)
return -ENOMEM; return -ENOMEM;
ds1511_base = devm_platform_ioremap_resource(pdev, 0); ds1511_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ds1511_base)) if (IS_ERR(ds1511_base))
return PTR_ERR(ds1511_base); return PTR_ERR(ds1511_base);
pdata->ioaddr = ds1511_base; ds1511->ioaddr = ds1511_base;
pdata->irq = platform_get_irq(pdev, 0); ds1511->irq = platform_get_irq(pdev, 0);
/* /*
* turn on the clock and the crystal, etc. * turn on the clock and the crystal, etc.
*/ */
rtc_write(DS1511_BME, RTC_CMD); rtc_write(DS1511_BME, DS1511_CONTROL_B);
rtc_write(0, RTC_CMD1); rtc_write(0, DS1511_CONTROL_A);
/* /*
* clear the wdog counter * clear the wdog counter
*/ */
@ -448,38 +311,43 @@ static int ds1511_rtc_probe(struct platform_device *pdev)
/* /*
* check for a dying bat-tree * check for a dying bat-tree
*/ */
if (rtc_read(RTC_CMD1) & DS1511_BLF1) if (rtc_read(DS1511_CONTROL_A) & DS1511_BLF1)
dev_warn(&pdev->dev, "voltage-low detected.\n"); dev_warn(&pdev->dev, "voltage-low detected.\n");
spin_lock_init(&pdata->lock); spin_lock_init(&ds1511->lock);
platform_set_drvdata(pdev, pdata); platform_set_drvdata(pdev, ds1511);
pdata->rtc = devm_rtc_allocate_device(&pdev->dev); ds1511->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(pdata->rtc)) if (IS_ERR(ds1511->rtc))
return PTR_ERR(pdata->rtc); return PTR_ERR(ds1511->rtc);
pdata->rtc->ops = &ds1511_rtc_ops; ds1511->rtc->ops = &ds1511_rtc_ops;
ds1511->rtc->range_max = RTC_TIMESTAMP_END_2099;
ret = devm_rtc_register_device(pdata->rtc); ds1511->rtc->alarm_offset_max = 28 * 24 * 60 * 60 - 1;
if (ret)
return ret;
devm_rtc_nvmem_register(pdata->rtc, &ds1511_nvmem_cfg);
/* /*
* if the platform has an interrupt in mind for this device, * if the platform has an interrupt in mind for this device,
* then by all means, set it * then by all means, set it
*/ */
if (pdata->irq > 0) { if (ds1511->irq > 0) {
rtc_read(RTC_CMD1); rtc_read(DS1511_CONTROL_A);
if (devm_request_irq(&pdev->dev, pdata->irq, ds1511_interrupt, if (devm_request_irq(&pdev->dev, ds1511->irq, ds1511_interrupt,
IRQF_SHARED, pdev->name, pdev) < 0) { IRQF_SHARED, pdev->name, pdev) < 0) {
dev_warn(&pdev->dev, "interrupt not available.\n"); dev_warn(&pdev->dev, "interrupt not available.\n");
pdata->irq = 0; ds1511->irq = 0;
} }
} }
if (ds1511->irq == 0)
clear_bit(RTC_FEATURE_ALARM, ds1511->rtc->features);
ret = devm_rtc_register_device(ds1511->rtc);
if (ret)
return ret;
devm_rtc_nvmem_register(ds1511->rtc, &ds1511_nvmem_cfg);
return 0; return 0;
} }

View file

@ -909,10 +909,7 @@ static int m41t80_probe(struct i2c_client *client)
if (IS_ERR(m41t80_data->rtc)) if (IS_ERR(m41t80_data->rtc))
return PTR_ERR(m41t80_data->rtc); return PTR_ERR(m41t80_data->rtc);
#ifdef CONFIG_OF wakeup_source = device_property_read_bool(&client->dev, "wakeup-source");
wakeup_source = of_property_read_bool(client->dev.of_node,
"wakeup-source");
#endif
if (client->irq > 0) { if (client->irq > 0) {
unsigned long irqflags = IRQF_TRIGGER_LOW; unsigned long irqflags = IRQF_TRIGGER_LOW;

View file

@ -204,7 +204,7 @@ static bool max31335_volatile_reg(struct device *dev, unsigned int reg)
return true; return true;
/* interrupt status register */ /* interrupt status register */
if (reg == MAX31335_INT_EN1_A1IE) if (reg == MAX31335_STATUS1)
return true; return true;
/* temperature registers */ /* temperature registers */

View file

@ -102,6 +102,8 @@ static int nct3018y_get_alarm_mode(struct i2c_client *client, unsigned char *ala
if (flags < 0) if (flags < 0)
return flags; return flags;
*alarm_enable = flags & NCT3018Y_BIT_AIE; *alarm_enable = flags & NCT3018Y_BIT_AIE;
dev_dbg(&client->dev, "%s:alarm_enable:%x\n", __func__, *alarm_enable);
} }
if (alarm_flag) { if (alarm_flag) {
@ -110,11 +112,9 @@ static int nct3018y_get_alarm_mode(struct i2c_client *client, unsigned char *ala
if (flags < 0) if (flags < 0)
return flags; return flags;
*alarm_flag = flags & NCT3018Y_BIT_AF; *alarm_flag = flags & NCT3018Y_BIT_AF;
dev_dbg(&client->dev, "%s:alarm_flag:%x\n", __func__, *alarm_flag);
} }
dev_dbg(&client->dev, "%s:alarm_enable:%x alarm_flag:%x\n",
__func__, *alarm_enable, *alarm_flag);
return 0; return 0;
} }

View file

@ -370,6 +370,30 @@ static int pcf8523_rtc_set_offset(struct device *dev, long offset)
return regmap_write(pcf8523->regmap, PCF8523_REG_OFFSET, value); return regmap_write(pcf8523->regmap, PCF8523_REG_OFFSET, value);
} }
#ifdef CONFIG_PM_SLEEP
static int pcf8523_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
if (client->irq > 0 && device_may_wakeup(dev))
enable_irq_wake(client->irq);
return 0;
}
static int pcf8523_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
if (client->irq > 0 && device_may_wakeup(dev))
disable_irq_wake(client->irq);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(pcf8523_pm, pcf8523_suspend, pcf8523_resume);
static const struct rtc_class_ops pcf8523_rtc_ops = { static const struct rtc_class_ops pcf8523_rtc_ops = {
.read_time = pcf8523_rtc_read_time, .read_time = pcf8523_rtc_read_time,
.set_time = pcf8523_rtc_set_time, .set_time = pcf8523_rtc_set_time,
@ -487,6 +511,7 @@ static struct i2c_driver pcf8523_driver = {
.driver = { .driver = {
.name = "rtc-pcf8523", .name = "rtc-pcf8523",
.of_match_table = pcf8523_of_match, .of_match_table = pcf8523_of_match,
.pm = &pcf8523_pm,
}, },
.probe = pcf8523_probe, .probe = pcf8523_probe,
.id_table = pcf8523_id, .id_table = pcf8523_id,

View file

@ -42,7 +42,7 @@ static inline time64_t rtc_tm_sub(struct rtc_time *lhs, struct rtc_time *rhs)
#include <linux/timerqueue.h> #include <linux/timerqueue.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
extern struct class *rtc_class; extern const struct class rtc_class;
/* /*
* For these RTC methods the device parameter is the physical device * For these RTC methods the device parameter is the physical device

View file

@ -201,7 +201,7 @@ static int __init test_suspend(void)
} }
/* RTCs have initialized by now too ... can we use one? */ /* RTCs have initialized by now too ... can we use one? */
dev = class_find_device(rtc_class, NULL, NULL, has_wakealarm); dev = class_find_device(&rtc_class, NULL, NULL, has_wakealarm);
if (dev) { if (dev) {
rtc = rtc_class_open(dev_name(dev)); rtc = rtc_class_open(dev_name(dev));
put_device(dev); put_device(dev);

View file

@ -134,7 +134,7 @@ static struct class_interface alarmtimer_rtc_interface = {
static int alarmtimer_rtc_interface_setup(void) static int alarmtimer_rtc_interface_setup(void)
{ {
alarmtimer_rtc_interface.class = rtc_class; alarmtimer_rtc_interface.class = &rtc_class;
return class_interface_register(&alarmtimer_rtc_interface); return class_interface_register(&alarmtimer_rtc_interface);
} }
static void alarmtimer_rtc_interface_remove(void) static void alarmtimer_rtc_interface_remove(void)