mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-11 04:09:39 +08:00
Merge branch 'rtc-next' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git
This commit is contained in:
commit
bbb86850a8
@ -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:
|
||||
- const: atmel,at91sam9260-rtt
|
||||
- items:
|
||||
- const: microchip,sam9x60-rtt
|
||||
- enum:
|
||||
- microchip,sam9x60-rtt
|
||||
- microchip,sam9x7-rtt
|
||||
- const: atmel,at91sam9260-rtt
|
||||
- items:
|
||||
- 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:
|
||||
compatible:
|
||||
const: xlnx,zynqmp-rtc
|
||||
oneOf:
|
||||
- const: xlnx,zynqmp-rtc
|
||||
- items:
|
||||
- enum:
|
||||
- xlnx,versal-rtc
|
||||
- xlnx,versal-net-rtc
|
||||
- const: xlnx,zynqmp-rtc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@ -48,6 +54,9 @@ properties:
|
||||
default: 0x198233
|
||||
deprecated: true
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- 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-mediatek@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/rtc/rtc-mt2712.txt
|
||||
F: Documentation/devicetree/bindings/rtc/rtc-mt7622.txt
|
||||
F: Documentation/devicetree/bindings/rtc/mediatek,mt2712-rtc.yaml
|
||||
F: Documentation/devicetree/bindings/rtc/mediatek,mt7622-rtc.yaml
|
||||
F: drivers/rtc/rtc-mt2712.c
|
||||
F: drivers/rtc/rtc-mt6397.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/power/*/msm*
|
||||
F: drivers/reset/reset-qcom-*
|
||||
F: drivers/rtc/rtc-pm8xxx.c
|
||||
F: drivers/spi/spi-geni-qcom.c
|
||||
F: drivers/spi/spi-qcom-qspi.c
|
||||
F: drivers/spi/spi-qup.c
|
||||
|
@ -1858,7 +1858,8 @@ config RTC_DRV_MT2712
|
||||
|
||||
config RTC_DRV_MT6397
|
||||
tristate "MediaTek PMIC based RTC"
|
||||
depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN)
|
||||
depends on MFD_MT6397 || COMPILE_TEST
|
||||
select IRQ_DOMAIN
|
||||
help
|
||||
This selects the MediaTek(R) RTC driver. RTC is part of MediaTek
|
||||
MT6397 PMIC. You should enable MT6397 PMIC MFD before select
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "rtc-core.h"
|
||||
|
||||
static DEFINE_IDA(rtc_ida);
|
||||
struct class *rtc_class;
|
||||
|
||||
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
|
||||
#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 */
|
||||
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->max_user_freq = 64;
|
||||
rtc->dev.class = rtc_class;
|
||||
rtc->dev.class = &rtc_class;
|
||||
rtc->dev.groups = rtc_get_dev_attribute_groups();
|
||||
rtc->dev.release = rtc_device_release;
|
||||
|
||||
@ -475,13 +479,14 @@ EXPORT_SYMBOL_GPL(devm_rtc_device_register);
|
||||
|
||||
static int __init rtc_init(void)
|
||||
{
|
||||
rtc_class = class_create("rtc");
|
||||
if (IS_ERR(rtc_class)) {
|
||||
pr_err("couldn't create class\n");
|
||||
return PTR_ERR(rtc_class);
|
||||
}
|
||||
rtc_class->pm = RTC_CLASS_DEV_PM_OPS;
|
||||
int err;
|
||||
|
||||
err = class_register(&rtc_class);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
rtc_dev_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall(rtc_init);
|
||||
|
@ -696,7 +696,7 @@ struct rtc_device *rtc_class_open(const char *name)
|
||||
struct device *dev;
|
||||
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)
|
||||
rtc = to_rtc_device(dev);
|
||||
|
||||
|
@ -22,26 +22,24 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
enum ds1511reg {
|
||||
DS1511_SEC = 0x0,
|
||||
DS1511_MIN = 0x1,
|
||||
DS1511_HOUR = 0x2,
|
||||
DS1511_DOW = 0x3,
|
||||
DS1511_DOM = 0x4,
|
||||
DS1511_MONTH = 0x5,
|
||||
DS1511_YEAR = 0x6,
|
||||
DS1511_CENTURY = 0x7,
|
||||
DS1511_AM1_SEC = 0x8,
|
||||
DS1511_AM2_MIN = 0x9,
|
||||
DS1511_AM3_HOUR = 0xa,
|
||||
DS1511_AM4_DATE = 0xb,
|
||||
DS1511_WD_MSEC = 0xc,
|
||||
DS1511_WD_SEC = 0xd,
|
||||
DS1511_CONTROL_A = 0xe,
|
||||
DS1511_CONTROL_B = 0xf,
|
||||
DS1511_RAMADDR_LSB = 0x10,
|
||||
DS1511_RAMDATA = 0x13
|
||||
};
|
||||
#define DS1511_SEC 0x0
|
||||
#define DS1511_MIN 0x1
|
||||
#define DS1511_HOUR 0x2
|
||||
#define DS1511_DOW 0x3
|
||||
#define DS1511_DOM 0x4
|
||||
#define DS1511_MONTH 0x5
|
||||
#define DS1511_YEAR 0x6
|
||||
#define DS1511_CENTURY 0x7
|
||||
#define DS1511_AM1_SEC 0x8
|
||||
#define DS1511_AM2_MIN 0x9
|
||||
#define DS1511_AM3_HOUR 0xa
|
||||
#define DS1511_AM4_DATE 0xb
|
||||
#define DS1511_WD_MSEC 0xc
|
||||
#define DS1511_WD_SEC 0xd
|
||||
#define DS1511_CONTROL_A 0xe
|
||||
#define DS1511_CONTROL_B 0xf
|
||||
#define DS1511_RAMADDR_LSB 0x10
|
||||
#define DS1511_RAMDATA 0x13
|
||||
|
||||
#define DS1511_BLF1 0x80
|
||||
#define DS1511_BLF2 0x40
|
||||
@ -61,35 +59,10 @@ enum ds1511reg {
|
||||
#define DS1511_WDS 0x01
|
||||
#define DS1511_RAM_MAX 0x100
|
||||
|
||||
#define RTC_CMD DS1511_CONTROL_B
|
||||
#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 ds1511_data {
|
||||
struct rtc_device *rtc;
|
||||
void __iomem *ioaddr; /* virtual base address */
|
||||
int irq;
|
||||
unsigned int irqen;
|
||||
int alrm_sec;
|
||||
int alrm_min;
|
||||
int alrm_hour;
|
||||
int alrm_mday;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
@ -98,95 +71,33 @@ static DEFINE_SPINLOCK(ds1511_lock);
|
||||
static __iomem char *ds1511_base;
|
||||
static u32 reg_spacing = 1;
|
||||
|
||||
static noinline void
|
||||
rtc_write(uint8_t val, uint32_t reg)
|
||||
static void rtc_write(uint8_t val, uint32_t reg)
|
||||
{
|
||||
writeb(val, ds1511_base + (reg * reg_spacing));
|
||||
}
|
||||
|
||||
static noinline uint8_t
|
||||
rtc_read(enum ds1511reg reg)
|
||||
static uint8_t rtc_read(uint32_t reg)
|
||||
{
|
||||
return readb(ds1511_base + (reg * reg_spacing));
|
||||
}
|
||||
|
||||
static inline void
|
||||
rtc_disable_update(void)
|
||||
static 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
|
||||
rtc_enable_update(void)
|
||||
static 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)
|
||||
{
|
||||
u8 mon, day, dow, hrs, min, sec, yrs, cen;
|
||||
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;
|
||||
cen = rtc_tm->tm_year / 100;
|
||||
cen = 19 + rtc_tm->tm_year / 100;
|
||||
mon = rtc_tm->tm_mon + 1; /* tm_mon starts at zero */
|
||||
day = rtc_tm->tm_mday;
|
||||
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;
|
||||
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
|
||||
*/
|
||||
@ -216,14 +118,14 @@ static int ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
|
||||
|
||||
spin_lock_irqsave(&ds1511_lock, flags);
|
||||
rtc_disable_update();
|
||||
rtc_write(cen, RTC_CENTURY);
|
||||
rtc_write(yrs, RTC_YEAR);
|
||||
rtc_write((rtc_read(RTC_MON) & 0xe0) | mon, RTC_MON);
|
||||
rtc_write(day, RTC_DOM);
|
||||
rtc_write(hrs, RTC_HOUR);
|
||||
rtc_write(min, RTC_MIN);
|
||||
rtc_write(sec, RTC_SEC);
|
||||
rtc_write(dow, RTC_DOW);
|
||||
rtc_write(cen, DS1511_CENTURY);
|
||||
rtc_write(yrs, DS1511_YEAR);
|
||||
rtc_write((rtc_read(DS1511_MONTH) & 0xe0) | mon, DS1511_MONTH);
|
||||
rtc_write(day, DS1511_DOM);
|
||||
rtc_write(hrs, DS1511_HOUR);
|
||||
rtc_write(min, DS1511_MIN);
|
||||
rtc_write(sec, DS1511_SEC);
|
||||
rtc_write(dow, DS1511_DOW);
|
||||
rtc_enable_update();
|
||||
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);
|
||||
rtc_disable_update();
|
||||
|
||||
rtc_tm->tm_sec = rtc_read(RTC_SEC) & 0x7f;
|
||||
rtc_tm->tm_min = rtc_read(RTC_MIN) & 0x7f;
|
||||
rtc_tm->tm_hour = rtc_read(RTC_HOUR) & 0x3f;
|
||||
rtc_tm->tm_mday = rtc_read(RTC_DOM) & 0x3f;
|
||||
rtc_tm->tm_wday = rtc_read(RTC_DOW) & 0x7;
|
||||
rtc_tm->tm_mon = rtc_read(RTC_MON) & 0x1f;
|
||||
rtc_tm->tm_year = rtc_read(RTC_YEAR) & 0x7f;
|
||||
century = rtc_read(RTC_CENTURY);
|
||||
rtc_tm->tm_sec = rtc_read(DS1511_SEC) & 0x7f;
|
||||
rtc_tm->tm_min = rtc_read(DS1511_MIN) & 0x7f;
|
||||
rtc_tm->tm_hour = rtc_read(DS1511_HOUR) & 0x3f;
|
||||
rtc_tm->tm_mday = rtc_read(DS1511_DOM) & 0x3f;
|
||||
rtc_tm->tm_wday = rtc_read(DS1511_DOW) & 0x7;
|
||||
rtc_tm->tm_mon = rtc_read(DS1511_MONTH) & 0x1f;
|
||||
rtc_tm->tm_year = rtc_read(DS1511_YEAR) & 0x7f;
|
||||
century = rtc_read(DS1511_CENTURY);
|
||||
|
||||
rtc_enable_update();
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
static void ds1511_rtc_alarm_enable(unsigned int enabled)
|
||||
{
|
||||
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;
|
||||
|
||||
spin_lock_irqsave(&pdata->lock, flags);
|
||||
rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ?
|
||||
0x80 : bin2bcd(pdata->alrm_mday) & 0x3f,
|
||||
RTC_ALARM_DATE);
|
||||
rtc_write(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ?
|
||||
0x80 : bin2bcd(pdata->alrm_hour) & 0x3f,
|
||||
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);
|
||||
}
|
||||
spin_lock_irqsave(&ds1511->lock, flags);
|
||||
rtc_write(bin2bcd(alrm->time.tm_mday) & 0x3f, DS1511_AM4_DATE);
|
||||
rtc_write(bin2bcd(alrm->time.tm_hour) & 0x3f, DS1511_AM3_HOUR);
|
||||
rtc_write(bin2bcd(alrm->time.tm_min) & 0x7f, DS1511_AM2_MIN);
|
||||
rtc_write(bin2bcd(alrm->time.tm_sec) & 0x7f, DS1511_AM1_SEC);
|
||||
ds1511_rtc_alarm_enable(alrm->enabled);
|
||||
|
||||
static int
|
||||
ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
{
|
||||
struct rtc_plat_data *pdata = dev_get_drvdata(dev);
|
||||
rtc_read(DS1511_CONTROL_A); /* clear interrupts */
|
||||
spin_unlock_irqrestore(&ds1511->lock, flags);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int
|
||||
ds1511_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
static int 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;
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
ds1511_interrupt(int irq, void *dev_id)
|
||||
static irqreturn_t ds1511_interrupt(int irq, void *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;
|
||||
|
||||
spin_lock(&pdata->lock);
|
||||
spin_lock(&ds1511->lock);
|
||||
/*
|
||||
* read and clear interrupt
|
||||
*/
|
||||
if (rtc_read(RTC_CMD1) & DS1511_IRQF) {
|
||||
events = RTC_IRQF;
|
||||
if (rtc_read(RTC_ALARM_SEC) & 0x80)
|
||||
events |= RTC_UF;
|
||||
else
|
||||
events |= RTC_AF;
|
||||
rtc_update_irq(pdata->rtc, 1, events);
|
||||
if (rtc_read(DS1511_CONTROL_A) & DS1511_IRQF) {
|
||||
events = RTC_IRQF | RTC_AF;
|
||||
rtc_update_irq(ds1511->rtc, 1, events);
|
||||
}
|
||||
spin_unlock(&pdata->lock);
|
||||
spin_unlock(&ds1511->lock);
|
||||
return events ? IRQ_HANDLED : IRQ_NONE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
struct rtc_plat_data *pdata;
|
||||
struct ds1511_data *ds1511;
|
||||
int ret = 0;
|
||||
struct nvmem_config ds1511_nvmem_cfg = {
|
||||
.name = "ds1511_nvram",
|
||||
@ -420,21 +283,21 @@ static int ds1511_rtc_probe(struct platform_device *pdev)
|
||||
.priv = &pdev->dev,
|
||||
};
|
||||
|
||||
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
ds1511 = devm_kzalloc(&pdev->dev, sizeof(*ds1511), GFP_KERNEL);
|
||||
if (!ds1511)
|
||||
return -ENOMEM;
|
||||
|
||||
ds1511_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(ds1511_base))
|
||||
return PTR_ERR(ds1511_base);
|
||||
pdata->ioaddr = ds1511_base;
|
||||
pdata->irq = platform_get_irq(pdev, 0);
|
||||
ds1511->ioaddr = ds1511_base;
|
||||
ds1511->irq = platform_get_irq(pdev, 0);
|
||||
|
||||
/*
|
||||
* turn on the clock and the crystal, etc.
|
||||
*/
|
||||
rtc_write(DS1511_BME, RTC_CMD);
|
||||
rtc_write(0, RTC_CMD1);
|
||||
rtc_write(DS1511_BME, DS1511_CONTROL_B);
|
||||
rtc_write(0, DS1511_CONTROL_A);
|
||||
/*
|
||||
* clear the wdog counter
|
||||
*/
|
||||
@ -448,38 +311,43 @@ static int ds1511_rtc_probe(struct platform_device *pdev)
|
||||
/*
|
||||
* 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");
|
||||
|
||||
spin_lock_init(&pdata->lock);
|
||||
platform_set_drvdata(pdev, pdata);
|
||||
spin_lock_init(&ds1511->lock);
|
||||
platform_set_drvdata(pdev, ds1511);
|
||||
|
||||
pdata->rtc = devm_rtc_allocate_device(&pdev->dev);
|
||||
if (IS_ERR(pdata->rtc))
|
||||
return PTR_ERR(pdata->rtc);
|
||||
ds1511->rtc = devm_rtc_allocate_device(&pdev->dev);
|
||||
if (IS_ERR(ds1511->rtc))
|
||||
return PTR_ERR(ds1511->rtc);
|
||||
|
||||
pdata->rtc->ops = &ds1511_rtc_ops;
|
||||
|
||||
ret = devm_rtc_register_device(pdata->rtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
devm_rtc_nvmem_register(pdata->rtc, &ds1511_nvmem_cfg);
|
||||
ds1511->rtc->ops = &ds1511_rtc_ops;
|
||||
ds1511->rtc->range_max = RTC_TIMESTAMP_END_2099;
|
||||
ds1511->rtc->alarm_offset_max = 28 * 24 * 60 * 60 - 1;
|
||||
|
||||
/*
|
||||
* if the platform has an interrupt in mind for this device,
|
||||
* then by all means, set it
|
||||
*/
|
||||
if (pdata->irq > 0) {
|
||||
rtc_read(RTC_CMD1);
|
||||
if (devm_request_irq(&pdev->dev, pdata->irq, ds1511_interrupt,
|
||||
if (ds1511->irq > 0) {
|
||||
rtc_read(DS1511_CONTROL_A);
|
||||
if (devm_request_irq(&pdev->dev, ds1511->irq, ds1511_interrupt,
|
||||
IRQF_SHARED, pdev->name, pdev) < 0) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -909,10 +909,7 @@ static int m41t80_probe(struct i2c_client *client)
|
||||
if (IS_ERR(m41t80_data->rtc))
|
||||
return PTR_ERR(m41t80_data->rtc);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
wakeup_source = of_property_read_bool(client->dev.of_node,
|
||||
"wakeup-source");
|
||||
#endif
|
||||
wakeup_source = device_property_read_bool(&client->dev, "wakeup-source");
|
||||
if (client->irq > 0) {
|
||||
unsigned long irqflags = IRQF_TRIGGER_LOW;
|
||||
|
||||
|
@ -204,7 +204,7 @@ static bool max31335_volatile_reg(struct device *dev, unsigned int reg)
|
||||
return true;
|
||||
|
||||
/* interrupt status register */
|
||||
if (reg == MAX31335_INT_EN1_A1IE)
|
||||
if (reg == MAX31335_STATUS1)
|
||||
return true;
|
||||
|
||||
/* temperature registers */
|
||||
|
@ -102,6 +102,8 @@ static int nct3018y_get_alarm_mode(struct i2c_client *client, unsigned char *ala
|
||||
if (flags < 0)
|
||||
return flags;
|
||||
*alarm_enable = flags & NCT3018Y_BIT_AIE;
|
||||
dev_dbg(&client->dev, "%s:alarm_enable:%x\n", __func__, *alarm_enable);
|
||||
|
||||
}
|
||||
|
||||
if (alarm_flag) {
|
||||
@ -110,11 +112,9 @@ static int nct3018y_get_alarm_mode(struct i2c_client *client, unsigned char *ala
|
||||
if (flags < 0)
|
||||
return flags;
|
||||
*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;
|
||||
}
|
||||
|
||||
|
@ -370,6 +370,30 @@ static int pcf8523_rtc_set_offset(struct device *dev, long offset)
|
||||
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 = {
|
||||
.read_time = pcf8523_rtc_read_time,
|
||||
.set_time = pcf8523_rtc_set_time,
|
||||
@ -487,6 +511,7 @@ static struct i2c_driver pcf8523_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-pcf8523",
|
||||
.of_match_table = pcf8523_of_match,
|
||||
.pm = &pcf8523_pm,
|
||||
},
|
||||
.probe = pcf8523_probe,
|
||||
.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/workqueue.h>
|
||||
|
||||
extern struct class *rtc_class;
|
||||
extern const struct class rtc_class;
|
||||
|
||||
/*
|
||||
* 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? */
|
||||
dev = class_find_device(rtc_class, NULL, NULL, has_wakealarm);
|
||||
dev = class_find_device(&rtc_class, NULL, NULL, has_wakealarm);
|
||||
if (dev) {
|
||||
rtc = rtc_class_open(dev_name(dev));
|
||||
put_device(dev);
|
||||
|
@ -134,7 +134,7 @@ static struct class_interface alarmtimer_rtc_interface = {
|
||||
|
||||
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);
|
||||
}
|
||||
static void alarmtimer_rtc_interface_remove(void)
|
||||
|
Loading…
Reference in New Issue
Block a user