mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 00:48:50 +00:00
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:
commit
3faae16b5a
20 changed files with 359 additions and 328 deletions
|
@ -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.
|
|
98
Documentation/devicetree/bindings/rtc/abracon,abx80x.yaml
Normal file
98
Documentation/devicetree/bindings/rtc/abracon,abx80x.yaml
Normal 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>;
|
||||||
|
};
|
||||||
|
};
|
|
@ -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
|
||||||
|
|
|
@ -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>;
|
||||||
|
};
|
|
@ -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";
|
||||||
|
};
|
|
@ -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>;
|
|
||||||
};
|
|
|
@ -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";
|
|
||||||
};
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue