mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 10:01:39 -05:00
Merge tag 'rtc-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni:
"Subsystem:
- stop setting max_user_freq from the individual drivers as this has
not been hardware related for a while
New drivers:
- Andes ATCRTC100
- Apple SMC
- Nvidia VRS
Drivers:
- renesas-rtca3: add RZ/V2H support
- tegra: add ACPI support"
* tag 'rtc-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (34 commits)
rtc: spacemit: MFD_SPACEMIT_P1 as dependencies
rtc: atcrtc100: Fix signedness bug in probe()
rtc: max31335: Fix ignored return value in set_alarm
rtc: gamecube: Check the return value of ioremap()
Documentation: ABI: testing: Fix "upto" typo in rtc-cdev
rtc: Add new rtc-macsmc driver for Apple Silicon Macs
dt-bindings: rtc: Add Apple SMC RTC
MAINTAINERS: drop unneeded file entry in NVIDIA VRS RTC DRIVER
rtc: isl12026: Add id_table
rtc: renesas-rtca3: Add support for multiple reset lines
dt-bindings: rtc: renesas,rz-rtca3: Add RZ/V2H support
rtc: tegra: Replace deprecated SIMPLE_DEV_PM_OPS
rtc: tegra: Add ACPI support
rtc: tegra: Use devm_clk_get_enabled() in probe
rtc: Kconfig: add MC34708 to mc13xxx help text
rtc: s35390a: use u8 instead of char for register buffer
rtc: nvvrs: add NVIDIA VRS RTC device driver
dt-bindings: rtc: Document NVIDIA VRS RTC
rtc: atcrtc100: Add ATCRTC100 RTC driver
MAINTAINERS: Add entry for ATCRTC100 RTC driver
...
This commit is contained in:
@@ -14,7 +14,7 @@ Description:
|
|||||||
for RTCs that support alarms
|
for RTCs that support alarms
|
||||||
|
|
||||||
* RTC_ALM_READ, RTC_ALM_SET: Read or set the alarm time for
|
* RTC_ALM_READ, RTC_ALM_SET: Read or set the alarm time for
|
||||||
RTCs that support alarms. Can be set upto 24 hours in the
|
RTCs that support alarms. Can be set up to 24 hours in the
|
||||||
future. Requires a separate RTC_AIE_ON call to enable the
|
future. Requires a separate RTC_AIE_ON call to enable the
|
||||||
alarm interrupt. (Prefer to use RTC_WKALM_*)
|
alarm interrupt. (Prefer to use RTC_WKALM_*)
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ properties:
|
|||||||
reboot:
|
reboot:
|
||||||
$ref: /schemas/power/reset/apple,smc-reboot.yaml
|
$ref: /schemas/power/reset/apple,smc-reboot.yaml
|
||||||
|
|
||||||
|
rtc:
|
||||||
|
$ref: /schemas/rtc/apple,smc-rtc.yaml
|
||||||
|
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
||||||
required:
|
required:
|
||||||
@@ -80,5 +83,11 @@ examples:
|
|||||||
nvmem-cell-names = "shutdown_flag", "boot_stage",
|
nvmem-cell-names = "shutdown_flag", "boot_stage",
|
||||||
"boot_error_count", "panic_count";
|
"boot_error_count", "panic_count";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
rtc {
|
||||||
|
compatible = "apple,smc-rtc";
|
||||||
|
nvmem-cells = <&rtc_offset>;
|
||||||
|
nvmem-cell-names = "rtc_offset";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/rtc/andestech,atcrtc100.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Andes ATCRTC100 Real-Time Clock
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- CL Wang <cl634@andestech.com>
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: rtc.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- andestech,atcrtc100
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
items:
|
||||||
|
- description: Periodic timekeeping interrupt
|
||||||
|
- description: RTC alarm interrupt
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- interrupts
|
||||||
|
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
|
|
||||||
|
rtc@f0300000 {
|
||||||
|
compatible = "andestech,atcrtc100";
|
||||||
|
reg = <0xf0300000 0x100>;
|
||||||
|
interrupts = <1 IRQ_TYPE_LEVEL_HIGH>, <2 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
};
|
||||||
35
Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml
Normal file
35
Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/rtc/apple,smc-rtc.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Apple SMC RTC
|
||||||
|
|
||||||
|
description:
|
||||||
|
Apple Silicon Macs (M1, etc.) have an RTC that is part of the PMU IC,
|
||||||
|
but most of the PMU functionality is abstracted out by the SMC.
|
||||||
|
An additional RTC offset stored inside NVMEM is required to compute
|
||||||
|
the current date/time.
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Sven Peter <sven@kernel.org>
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: apple,smc-rtc
|
||||||
|
|
||||||
|
nvmem-cells:
|
||||||
|
items:
|
||||||
|
- description: 48bit RTC offset, specified in 32768 (2^15) Hz clock ticks
|
||||||
|
|
||||||
|
nvmem-cell-names:
|
||||||
|
items:
|
||||||
|
- const: rtc_offset
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- nvmem-cells
|
||||||
|
- nvmem-cell-names
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
59
Documentation/devicetree/bindings/rtc/nvidia,vrs-10.yaml
Normal file
59
Documentation/devicetree/bindings/rtc/nvidia,vrs-10.yaml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/rtc/nvidia,vrs-10.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: NVIDIA Voltage Regulator Specification Real Time Clock
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Shubhi Garg <shgarg@nvidia.com>
|
||||||
|
|
||||||
|
description:
|
||||||
|
NVIDIA VRS-10 (Voltage Regulator Specification) is a Power Management IC
|
||||||
|
(PMIC) that implements a power sequencing solution with I2C interface.
|
||||||
|
The device includes a real-time clock (RTC) with 32kHz clock output and
|
||||||
|
backup battery support, alarm functionality for system wake-up from
|
||||||
|
suspend and shutdown states, OTP memory for power sequencing configuration,
|
||||||
|
and an interrupt controller for managing VRS events.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: nvidia,vrs-10
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
interrupt-controller: true
|
||||||
|
|
||||||
|
'#interrupt-cells':
|
||||||
|
const: 2
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- interrupts
|
||||||
|
- interrupt-controller
|
||||||
|
- '#interrupt-cells'
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
|
i2c {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
pmic@3c {
|
||||||
|
compatible = "nvidia,vrs-10";
|
||||||
|
reg = <0x3c>;
|
||||||
|
interrupt-parent = <&pmc>;
|
||||||
|
interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
|
||||||
|
interrupt-controller;
|
||||||
|
#interrupt-cells = <2>;
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -9,14 +9,12 @@ title: Renesas RTCA-3 Real Time Clock
|
|||||||
maintainers:
|
maintainers:
|
||||||
- Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
|
- Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
|
||||||
|
|
||||||
allOf:
|
|
||||||
- $ref: rtc.yaml#
|
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
items:
|
items:
|
||||||
- enum:
|
- enum:
|
||||||
- renesas,r9a08g045-rtca3 # RZ/G3S
|
- renesas,r9a08g045-rtca3 # RZ/G3S
|
||||||
|
- renesas,r9a09g057-rtca3 # RZ/V2H
|
||||||
- const: renesas,rz-rtca3
|
- const: renesas,rz-rtca3
|
||||||
|
|
||||||
reg:
|
reg:
|
||||||
@@ -48,8 +46,12 @@ properties:
|
|||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
resets:
|
resets:
|
||||||
items:
|
minItems: 1
|
||||||
- description: VBATTB module reset
|
maxItems: 2
|
||||||
|
|
||||||
|
reset-names:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 2
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
@@ -61,6 +63,39 @@ required:
|
|||||||
- power-domains
|
- power-domains
|
||||||
- resets
|
- resets
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: rtc.yaml#
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
const: renesas,r9a08g045-rtca3
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
resets:
|
||||||
|
items:
|
||||||
|
- description: VBATTB module reset
|
||||||
|
reset-names:
|
||||||
|
const: vbattb
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
const: renesas,r9a09g057-rtca3
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
resets:
|
||||||
|
items:
|
||||||
|
- description: RTC reset
|
||||||
|
- description: Reset for the RTEST registers
|
||||||
|
reset-names:
|
||||||
|
items:
|
||||||
|
- const: rtc
|
||||||
|
- const: rtest
|
||||||
|
required:
|
||||||
|
- reset-names
|
||||||
|
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
@@ -81,4 +116,5 @@ examples:
|
|||||||
clock-names = "bus", "counter";
|
clock-names = "bus", "counter";
|
||||||
power-domains = <&cpg>;
|
power-domains = <&cpg>;
|
||||||
resets = <&cpg R9A08G045_VBAT_BRESETN>;
|
resets = <&cpg R9A08G045_VBAT_BRESETN>;
|
||||||
|
reset-names = "vbattb";
|
||||||
};
|
};
|
||||||
|
|||||||
15
MAINTAINERS
15
MAINTAINERS
@@ -2475,6 +2475,7 @@ F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
|
|||||||
F: Documentation/devicetree/bindings/power/apple*
|
F: Documentation/devicetree/bindings/power/apple*
|
||||||
F: Documentation/devicetree/bindings/power/reset/apple,smc-reboot.yaml
|
F: Documentation/devicetree/bindings/power/reset/apple,smc-reboot.yaml
|
||||||
F: Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml
|
F: Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml
|
||||||
|
F: Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml
|
||||||
F: Documentation/devicetree/bindings/spi/apple,spi.yaml
|
F: Documentation/devicetree/bindings/spi/apple,spi.yaml
|
||||||
F: Documentation/devicetree/bindings/spmi/apple,spmi.yaml
|
F: Documentation/devicetree/bindings/spmi/apple,spmi.yaml
|
||||||
F: Documentation/devicetree/bindings/usb/apple,dwc3.yaml
|
F: Documentation/devicetree/bindings/usb/apple,dwc3.yaml
|
||||||
@@ -2501,6 +2502,7 @@ F: drivers/nvmem/apple-spmi-nvmem.c
|
|||||||
F: drivers/pinctrl/pinctrl-apple-gpio.c
|
F: drivers/pinctrl/pinctrl-apple-gpio.c
|
||||||
F: drivers/power/reset/macsmc-reboot.c
|
F: drivers/power/reset/macsmc-reboot.c
|
||||||
F: drivers/pwm/pwm-apple.c
|
F: drivers/pwm/pwm-apple.c
|
||||||
|
F: drivers/rtc/rtc-macsmc.c
|
||||||
F: drivers/soc/apple/*
|
F: drivers/soc/apple/*
|
||||||
F: drivers/spi/spi-apple.c
|
F: drivers/spi/spi-apple.c
|
||||||
F: drivers/spmi/spmi-apple-controller.c
|
F: drivers/spmi/spmi-apple-controller.c
|
||||||
@@ -4015,6 +4017,12 @@ F: drivers/power/reset/atc260x-poweroff.c
|
|||||||
F: drivers/regulator/atc260x-regulator.c
|
F: drivers/regulator/atc260x-regulator.c
|
||||||
F: include/linux/mfd/atc260x/*
|
F: include/linux/mfd/atc260x/*
|
||||||
|
|
||||||
|
ATCRTC100 RTC DRIVER
|
||||||
|
M: CL Wang <cl634@andestech.com>
|
||||||
|
S: Supported
|
||||||
|
F: Documentation/devicetree/bindings/rtc/andestech,atcrtc100.yaml
|
||||||
|
F: drivers/rtc/rtc-atcrtc100.c
|
||||||
|
|
||||||
ATHEROS 71XX/9XXX GPIO DRIVER
|
ATHEROS 71XX/9XXX GPIO DRIVER
|
||||||
M: Alban Bedel <albeu@free.fr>
|
M: Alban Bedel <albeu@free.fr>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
@@ -18692,6 +18700,13 @@ S: Maintained
|
|||||||
F: drivers/video/fbdev/nvidia/
|
F: drivers/video/fbdev/nvidia/
|
||||||
F: drivers/video/fbdev/riva/
|
F: drivers/video/fbdev/riva/
|
||||||
|
|
||||||
|
NVIDIA VRS RTC DRIVER
|
||||||
|
M: Shubhi Garg <shgarg@nvidia.com>
|
||||||
|
L: linux-tegra@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
F: Documentation/devicetree/bindings/rtc/nvidia,vrs-10.yaml
|
||||||
|
F: drivers/rtc/rtc-nvidia-vrs10.c
|
||||||
|
|
||||||
NVIDIA WMI EC BACKLIGHT DRIVER
|
NVIDIA WMI EC BACKLIGHT DRIVER
|
||||||
M: Daniel Dadap <ddadap@nvidia.com>
|
M: Daniel Dadap <ddadap@nvidia.com>
|
||||||
L: platform-driver-x86@vger.kernel.org
|
L: platform-driver-x86@vger.kernel.org
|
||||||
|
|||||||
@@ -409,13 +409,22 @@ config RTC_DRV_MAX77686
|
|||||||
config RTC_DRV_SPACEMIT_P1
|
config RTC_DRV_SPACEMIT_P1
|
||||||
tristate "SpacemiT P1 RTC"
|
tristate "SpacemiT P1 RTC"
|
||||||
depends on ARCH_SPACEMIT || COMPILE_TEST
|
depends on ARCH_SPACEMIT || COMPILE_TEST
|
||||||
select MFD_SPACEMIT_P1
|
depends on MFD_SPACEMIT_P1
|
||||||
default ARCH_SPACEMIT
|
default MFD_SPACEMIT_P1
|
||||||
help
|
help
|
||||||
Enable support for the RTC function in the SpacemiT P1 PMIC.
|
Enable support for the RTC function in the SpacemiT P1 PMIC.
|
||||||
This driver can also be built as a module, which will be called
|
This driver can also be built as a module, which will be called
|
||||||
"spacemit-p1-rtc".
|
"spacemit-p1-rtc".
|
||||||
|
|
||||||
|
config RTC_DRV_NVIDIA_VRS10
|
||||||
|
tristate "NVIDIA VRS10 RTC device"
|
||||||
|
help
|
||||||
|
If you say yes here you will get support for the battery backed RTC device
|
||||||
|
of NVIDIA VRS (Voltage Regulator Specification). The RTC is connected via
|
||||||
|
I2C interface and supports alarm functionality.
|
||||||
|
This driver can also be built as a module. If so, the module will be called
|
||||||
|
rtc-nvidia-vrs10.
|
||||||
|
|
||||||
config RTC_DRV_NCT3018Y
|
config RTC_DRV_NCT3018Y
|
||||||
tristate "Nuvoton NCT3018Y"
|
tristate "Nuvoton NCT3018Y"
|
||||||
depends on OF
|
depends on OF
|
||||||
@@ -1063,6 +1072,21 @@ config RTC_DRV_ALPHA
|
|||||||
Direct support for the real-time clock found on every Alpha
|
Direct support for the real-time clock found on every Alpha
|
||||||
system, specifically MC146818 compatibles. If in doubt, say Y.
|
system, specifically MC146818 compatibles. If in doubt, say Y.
|
||||||
|
|
||||||
|
config RTC_DRV_ATCRTC100
|
||||||
|
tristate "Andes ATCRTC100"
|
||||||
|
depends on ARCH_ANDES || COMPILE_TEST
|
||||||
|
select REGMAP_MMIO
|
||||||
|
help
|
||||||
|
If you say yes here you will get support for the Andes ATCRTC100
|
||||||
|
RTC driver.
|
||||||
|
|
||||||
|
This driver provides support for the Andes ATCRTC100 real-time clock
|
||||||
|
device. It allows setting and retrieving the time and date, as well
|
||||||
|
as setting alarms.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the module will
|
||||||
|
be called rtc-atcrtc100.
|
||||||
|
|
||||||
config RTC_DRV_DS1216
|
config RTC_DRV_DS1216
|
||||||
tristate "Dallas DS1216"
|
tristate "Dallas DS1216"
|
||||||
depends on SNI_RM
|
depends on SNI_RM
|
||||||
@@ -1749,7 +1773,7 @@ config RTC_DRV_MC13XXX
|
|||||||
tristate "Freescale MC13xxx RTC"
|
tristate "Freescale MC13xxx RTC"
|
||||||
help
|
help
|
||||||
This enables support for the RTCs found on Freescale's PMICs
|
This enables support for the RTCs found on Freescale's PMICs
|
||||||
MC13783 and MC13892.
|
MC13783, MC13892 and MC34708.
|
||||||
|
|
||||||
config RTC_DRV_MPC5121
|
config RTC_DRV_MPC5121
|
||||||
tristate "Freescale MPC5121 built-in RTC"
|
tristate "Freescale MPC5121 built-in RTC"
|
||||||
@@ -2074,6 +2098,17 @@ config RTC_DRV_WILCO_EC
|
|||||||
This can also be built as a module. If so, the module will
|
This can also be built as a module. If so, the module will
|
||||||
be named "rtc_wilco_ec".
|
be named "rtc_wilco_ec".
|
||||||
|
|
||||||
|
config RTC_DRV_MACSMC
|
||||||
|
tristate "Apple Mac System Management Controller RTC"
|
||||||
|
depends on MFD_MACSMC
|
||||||
|
help
|
||||||
|
If you say yes here you get support for RTC functions
|
||||||
|
inside Apple SPMI PMUs accessed through the SoC's
|
||||||
|
System Management Controller
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the
|
||||||
|
module will be called rtc-macsmc.
|
||||||
|
|
||||||
config RTC_DRV_MSC313
|
config RTC_DRV_MSC313
|
||||||
tristate "MStar MSC313 RTC"
|
tristate "MStar MSC313 RTC"
|
||||||
depends on ARCH_MSTARV7 || COMPILE_TEST
|
depends on ARCH_MSTARV7 || COMPILE_TEST
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ obj-$(CONFIG_RTC_DRV_ASM9260) += rtc-asm9260.o
|
|||||||
obj-$(CONFIG_RTC_DRV_ASPEED) += rtc-aspeed.o
|
obj-$(CONFIG_RTC_DRV_ASPEED) += rtc-aspeed.o
|
||||||
obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
|
obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
|
||||||
obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
|
obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
|
||||||
|
obj-$(CONFIG_RTC_DRV_ATCRTC100) += rtc-atcrtc100.o
|
||||||
obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o
|
obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o
|
||||||
obj-$(CONFIG_RTC_DRV_BBNSM) += rtc-nxp-bbnsm.o
|
obj-$(CONFIG_RTC_DRV_BBNSM) += rtc-nxp-bbnsm.o
|
||||||
obj-$(CONFIG_RTC_DRV_BD70528) += rtc-bd70528.o
|
obj-$(CONFIG_RTC_DRV_BD70528) += rtc-bd70528.o
|
||||||
@@ -93,6 +94,7 @@ obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o
|
|||||||
obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
|
obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
|
||||||
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
|
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
|
||||||
obj-$(CONFIG_RTC_DRV_MA35D1) += rtc-ma35d1.o
|
obj-$(CONFIG_RTC_DRV_MA35D1) += rtc-ma35d1.o
|
||||||
|
obj-$(CONFIG_RTC_DRV_MACSMC) += rtc-macsmc.o
|
||||||
obj-$(CONFIG_RTC_DRV_MAX31335) += rtc-max31335.o
|
obj-$(CONFIG_RTC_DRV_MAX31335) += rtc-max31335.o
|
||||||
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
|
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
|
||||||
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
|
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
|
||||||
@@ -121,6 +123,7 @@ obj-$(CONFIG_RTC_DRV_GAMECUBE) += rtc-gamecube.o
|
|||||||
obj-$(CONFIG_RTC_DRV_NCT3018Y) += rtc-nct3018y.o
|
obj-$(CONFIG_RTC_DRV_NCT3018Y) += rtc-nct3018y.o
|
||||||
obj-$(CONFIG_RTC_DRV_NCT6694) += rtc-nct6694.o
|
obj-$(CONFIG_RTC_DRV_NCT6694) += rtc-nct6694.o
|
||||||
obj-$(CONFIG_RTC_DRV_NTXEC) += rtc-ntxec.o
|
obj-$(CONFIG_RTC_DRV_NTXEC) += rtc-ntxec.o
|
||||||
|
obj-$(CONFIG_RTC_DRV_NVIDIA_VRS10)+= rtc-nvidia-vrs10.o
|
||||||
obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
|
obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
|
||||||
obj-$(CONFIG_RTC_DRV_OPAL) += rtc-opal.o
|
obj-$(CONFIG_RTC_DRV_OPAL) += rtc-opal.o
|
||||||
obj-$(CONFIG_RTC_DRV_OPTEE) += rtc-optee.o
|
obj-$(CONFIG_RTC_DRV_OPTEE) += rtc-optee.o
|
||||||
|
|||||||
@@ -361,39 +361,26 @@ static int aml_rtc_probe(struct platform_device *pdev)
|
|||||||
"failed to get_enable rtc sys clk\n");
|
"failed to get_enable rtc sys clk\n");
|
||||||
aml_rtc_init(rtc);
|
aml_rtc_init(rtc);
|
||||||
|
|
||||||
device_init_wakeup(dev, true);
|
devm_device_init_wakeup(dev);
|
||||||
platform_set_drvdata(pdev, rtc);
|
platform_set_drvdata(pdev, rtc);
|
||||||
|
|
||||||
rtc->rtc_dev = devm_rtc_allocate_device(dev);
|
rtc->rtc_dev = devm_rtc_allocate_device(dev);
|
||||||
if (IS_ERR(rtc->rtc_dev)) {
|
if (IS_ERR(rtc->rtc_dev))
|
||||||
ret = PTR_ERR(rtc->rtc_dev);
|
return PTR_ERR(rtc->rtc_dev);
|
||||||
goto err_clk;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = devm_request_irq(dev, rtc->irq, aml_rtc_handler,
|
ret = devm_request_irq(dev, rtc->irq, aml_rtc_handler,
|
||||||
IRQF_ONESHOT, "aml-rtc alarm", rtc);
|
IRQF_ONESHOT, "aml-rtc alarm", rtc);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err_probe(dev, ret, "IRQ%d request failed, ret = %d\n",
|
dev_err_probe(dev, ret, "IRQ%d request failed, ret = %d\n",
|
||||||
rtc->irq, ret);
|
rtc->irq, ret);
|
||||||
goto err_clk;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtc->rtc_dev->ops = &aml_rtc_ops;
|
rtc->rtc_dev->ops = &aml_rtc_ops;
|
||||||
rtc->rtc_dev->range_min = 0;
|
rtc->rtc_dev->range_min = 0;
|
||||||
rtc->rtc_dev->range_max = U32_MAX;
|
rtc->rtc_dev->range_max = U32_MAX;
|
||||||
|
|
||||||
ret = devm_rtc_register_device(rtc->rtc_dev);
|
return devm_rtc_register_device(rtc->rtc_dev);
|
||||||
if (ret) {
|
|
||||||
dev_err_probe(&pdev->dev, ret, "Failed to register RTC device: %d\n", ret);
|
|
||||||
goto err_clk;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
err_clk:
|
|
||||||
clk_disable_unprepare(rtc->sys_clk);
|
|
||||||
device_init_wakeup(dev, false);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
@@ -421,14 +408,6 @@ static int aml_rtc_resume(struct device *dev)
|
|||||||
static SIMPLE_DEV_PM_OPS(aml_rtc_pm_ops,
|
static SIMPLE_DEV_PM_OPS(aml_rtc_pm_ops,
|
||||||
aml_rtc_suspend, aml_rtc_resume);
|
aml_rtc_suspend, aml_rtc_resume);
|
||||||
|
|
||||||
static void aml_rtc_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct aml_rtc_data *rtc = dev_get_drvdata(&pdev->dev);
|
|
||||||
|
|
||||||
clk_disable_unprepare(rtc->sys_clk);
|
|
||||||
device_init_wakeup(&pdev->dev, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct aml_rtc_config a5_rtc_config = {
|
static const struct aml_rtc_config a5_rtc_config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -451,7 +430,6 @@ MODULE_DEVICE_TABLE(of, aml_rtc_device_id);
|
|||||||
|
|
||||||
static struct platform_driver aml_rtc_driver = {
|
static struct platform_driver aml_rtc_driver = {
|
||||||
.probe = aml_rtc_probe,
|
.probe = aml_rtc_probe,
|
||||||
.remove = aml_rtc_remove,
|
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "aml-rtc",
|
.name = "aml-rtc",
|
||||||
.pm = &aml_rtc_pm_ops,
|
.pm = &aml_rtc_pm_ops,
|
||||||
|
|||||||
381
drivers/rtc/rtc-atcrtc100.c
Normal file
381
drivers/rtc/rtc-atcrtc100.c
Normal file
@@ -0,0 +1,381 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
/*
|
||||||
|
* Driver for Andes ATCRTC100 real time clock.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 Andes Technology Corporation
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/bitfield.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/math64.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/pm_wakeirq.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/rtc.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
|
||||||
|
/* Register Offsets */
|
||||||
|
#define RTC_ID 0x00 /* ID and Revision Register */
|
||||||
|
#define RTC_RSV 0x04 /* Reserved Register */
|
||||||
|
#define RTC_CNT 0x10 /* Counter Register */
|
||||||
|
#define RTC_ALM 0x14 /* Alarm Register */
|
||||||
|
#define RTC_CR 0x18 /* Control Register */
|
||||||
|
#define RTC_STA 0x1C /* Status Register */
|
||||||
|
#define RTC_TRIM 0x20 /* Digital Trimming Register */
|
||||||
|
|
||||||
|
/* RTC_ID Register */
|
||||||
|
#define ID_MSK GENMASK(31, 8)
|
||||||
|
#define ID_ATCRTC100 0x030110
|
||||||
|
|
||||||
|
/* RTC_CNT and RTC_ALM Register Fields */
|
||||||
|
#define SEC_MSK GENMASK(5, 0)
|
||||||
|
#define MIN_MSK GENMASK(11, 6)
|
||||||
|
#define HOUR_MSK GENMASK(16, 12)
|
||||||
|
#define DAY_MSK GENMASK(31, 17)
|
||||||
|
#define RTC_SEC_GET(x) FIELD_GET(SEC_MSK, x)
|
||||||
|
#define RTC_MIN_GET(x) FIELD_GET(MIN_MSK, x)
|
||||||
|
#define RTC_HOUR_GET(x) FIELD_GET(HOUR_MSK, x)
|
||||||
|
#define RTC_DAY_GET(x) FIELD_GET(DAY_MSK, x)
|
||||||
|
#define RTC_SEC_SET(x) FIELD_PREP(SEC_MSK, x)
|
||||||
|
#define RTC_MIN_SET(x) FIELD_PREP(MIN_MSK, x)
|
||||||
|
#define RTC_HOUR_SET(x) FIELD_PREP(HOUR_MSK, x)
|
||||||
|
#define RTC_DAY_SET(x) FIELD_PREP(DAY_MSK, x)
|
||||||
|
|
||||||
|
/* RTC_CR Register Bits */
|
||||||
|
#define RTC_EN BIT(0) /* RTC Enable */
|
||||||
|
#define ALARM_WAKEUP BIT(1) /* Alarm Wakeup Enable */
|
||||||
|
#define ALARM_INT BIT(2) /* Alarm Interrupt Enable */
|
||||||
|
#define DAY_INT BIT(3) /* Day Interrupt Enable */
|
||||||
|
#define HOUR_INT BIT(4) /* Hour Interrupt Enable */
|
||||||
|
#define MIN_INT BIT(5) /* Minute Interrupt Enable */
|
||||||
|
#define SEC_INT BIT(6) /* Second Periodic Interrupt Enable */
|
||||||
|
#define HSEC_INT BIT(7) /* Half-Second Periodic Interrupt Enable */
|
||||||
|
|
||||||
|
/* RTC_STA Register Bits */
|
||||||
|
#define WRITE_DONE BIT(16) /* Register write completion status */
|
||||||
|
|
||||||
|
/* Time conversion macro */
|
||||||
|
#define ATCRTC_TIME_TO_SEC(D, H, M, S) \
|
||||||
|
((time64_t)(D) * 86400 + (H) * 3600 + (M) * 60 + (S))
|
||||||
|
|
||||||
|
/* Timeout for waiting for the write_done bit */
|
||||||
|
#define ATCRTC_TIMEOUT_US 1000000
|
||||||
|
#define ATCRTC_TIMEOUT_USLEEP_MIN 20
|
||||||
|
#define ATCRTC_TIMEOUT_USLEEP_MAX 30
|
||||||
|
|
||||||
|
struct atcrtc_dev {
|
||||||
|
struct rtc_device *rtc_dev;
|
||||||
|
struct regmap *regmap;
|
||||||
|
struct work_struct rtc_work;
|
||||||
|
unsigned int alarm_irq;
|
||||||
|
bool alarm_en;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_config atcrtc_regmap_config = {
|
||||||
|
.reg_bits = 32,
|
||||||
|
.reg_stride = 4,
|
||||||
|
.val_bits = 32,
|
||||||
|
.max_register = RTC_TRIM,
|
||||||
|
.cache_type = REGCACHE_NONE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* atcrtc_check_write_done - Wait for RTC registers to be synchronized.
|
||||||
|
* @rtc: Pointer to the atcrtc_dev structure.
|
||||||
|
*
|
||||||
|
* The WriteDone bit in the status register indicates the synchronization
|
||||||
|
* progress of RTC register updates. This bit is cleared to zero whenever
|
||||||
|
* any RTC control register (Counter, Alarm, Control, etc.) is written.
|
||||||
|
* It returns to one only after all previous updates have been fully
|
||||||
|
* synchronized to the RTC clock domain. This function polls the WriteDone
|
||||||
|
* bit with a timeout to ensure the device is ready for the next operation.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, or -EBUSY on timeout.
|
||||||
|
*/
|
||||||
|
static int atcrtc_check_write_done(struct atcrtc_dev *rtc)
|
||||||
|
{
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Using read_poll_timeout is more efficient than a manual loop
|
||||||
|
* with usleep_range.
|
||||||
|
*/
|
||||||
|
return regmap_read_poll_timeout(rtc->regmap, RTC_STA, val,
|
||||||
|
val & WRITE_DONE,
|
||||||
|
ATCRTC_TIMEOUT_USLEEP_MIN,
|
||||||
|
ATCRTC_TIMEOUT_US);
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t atcrtc_alarm_isr(int irq, void *dev)
|
||||||
|
{
|
||||||
|
struct atcrtc_dev *rtc = dev;
|
||||||
|
unsigned int status;
|
||||||
|
|
||||||
|
regmap_read(rtc->regmap, RTC_STA, &status);
|
||||||
|
if (status & ALARM_INT) {
|
||||||
|
regmap_write(rtc->regmap, RTC_STA, ALARM_INT);
|
||||||
|
rtc->alarm_en = false;
|
||||||
|
schedule_work(&rtc->rtc_work);
|
||||||
|
rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
return IRQ_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int atcrtc_alarm_irq_enable(struct device *dev, unsigned int enable)
|
||||||
|
{
|
||||||
|
struct atcrtc_dev *rtc = dev_get_drvdata(dev);
|
||||||
|
unsigned int mask;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = atcrtc_check_write_done(rtc);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
mask = ALARM_WAKEUP | ALARM_INT;
|
||||||
|
regmap_update_bits(rtc->regmap, RTC_CR, mask, enable ? mask : 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void atcrtc_alarm_clear(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct atcrtc_dev *rtc =
|
||||||
|
container_of(work, struct atcrtc_dev, rtc_work);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
rtc_lock(rtc->rtc_dev);
|
||||||
|
|
||||||
|
if (!rtc->alarm_en) {
|
||||||
|
ret = atcrtc_check_write_done(rtc);
|
||||||
|
if (ret)
|
||||||
|
dev_info(&rtc->rtc_dev->dev,
|
||||||
|
"failed to sync before clearing alarm: %d\n",
|
||||||
|
ret);
|
||||||
|
else
|
||||||
|
regmap_update_bits(rtc->regmap, RTC_CR,
|
||||||
|
ALARM_WAKEUP | ALARM_INT, 0);
|
||||||
|
}
|
||||||
|
rtc_unlock(rtc->rtc_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int atcrtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||||
|
{
|
||||||
|
struct atcrtc_dev *rtc = dev_get_drvdata(dev);
|
||||||
|
time64_t time;
|
||||||
|
unsigned int rtc_cnt;
|
||||||
|
|
||||||
|
if (!regmap_test_bits(rtc->regmap, RTC_CR, RTC_EN))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
regmap_read(rtc->regmap, RTC_CNT, &rtc_cnt);
|
||||||
|
time = ATCRTC_TIME_TO_SEC(RTC_DAY_GET(rtc_cnt),
|
||||||
|
RTC_HOUR_GET(rtc_cnt),
|
||||||
|
RTC_MIN_GET(rtc_cnt),
|
||||||
|
RTC_SEC_GET(rtc_cnt));
|
||||||
|
rtc_time64_to_tm(time, tm);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int atcrtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
|
{
|
||||||
|
struct atcrtc_dev *rtc = dev_get_drvdata(dev);
|
||||||
|
time64_t time;
|
||||||
|
unsigned int counter;
|
||||||
|
unsigned int day;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
time = rtc_tm_to_time64(tm);
|
||||||
|
day = div_s64(time, 86400);
|
||||||
|
counter = RTC_DAY_SET(day) |
|
||||||
|
RTC_HOUR_SET(tm->tm_hour) |
|
||||||
|
RTC_MIN_SET(tm->tm_min) |
|
||||||
|
RTC_SEC_SET(tm->tm_sec);
|
||||||
|
ret = atcrtc_check_write_done(rtc);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
regmap_write(rtc->regmap, RTC_CNT, counter);
|
||||||
|
|
||||||
|
ret = atcrtc_check_write_done(rtc);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
regmap_update_bits(rtc->regmap, RTC_CR, RTC_EN, RTC_EN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int atcrtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
|
||||||
|
{
|
||||||
|
struct atcrtc_dev *rtc = dev_get_drvdata(dev);
|
||||||
|
struct rtc_time *tm = &wkalrm->time;
|
||||||
|
unsigned int rtc_alarm;
|
||||||
|
|
||||||
|
wkalrm->enabled = regmap_test_bits(rtc->regmap, RTC_CR, ALARM_INT);
|
||||||
|
regmap_read(rtc->regmap, RTC_ALM, &rtc_alarm);
|
||||||
|
tm->tm_hour = RTC_HOUR_GET(rtc_alarm);
|
||||||
|
tm->tm_min = RTC_MIN_GET(rtc_alarm);
|
||||||
|
tm->tm_sec = RTC_SEC_GET(rtc_alarm);
|
||||||
|
|
||||||
|
/* The RTC alarm does not support day/month/year fields */
|
||||||
|
tm->tm_mday = -1;
|
||||||
|
tm->tm_mon = -1;
|
||||||
|
tm->tm_year = -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int atcrtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
|
||||||
|
{
|
||||||
|
struct atcrtc_dev *rtc = dev_get_drvdata(dev);
|
||||||
|
struct rtc_time *tm = &wkalrm->time;
|
||||||
|
unsigned int rtc_alarm;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Disable alarm first before setting a new one */
|
||||||
|
ret = atcrtc_alarm_irq_enable(dev, 0);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
rtc->alarm_en = false;
|
||||||
|
|
||||||
|
rtc_alarm = RTC_SEC_SET(tm->tm_sec) |
|
||||||
|
RTC_MIN_SET(tm->tm_min) |
|
||||||
|
RTC_HOUR_SET(tm->tm_hour);
|
||||||
|
|
||||||
|
ret = atcrtc_check_write_done(rtc);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
regmap_write(rtc->regmap, RTC_ALM, rtc_alarm);
|
||||||
|
|
||||||
|
rtc->alarm_en = wkalrm->enabled;
|
||||||
|
ret = atcrtc_alarm_irq_enable(dev, wkalrm->enabled);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct rtc_class_ops rtc_ops = {
|
||||||
|
.read_time = atcrtc_read_time,
|
||||||
|
.set_time = atcrtc_set_time,
|
||||||
|
.read_alarm = atcrtc_read_alarm,
|
||||||
|
.set_alarm = atcrtc_set_alarm,
|
||||||
|
.alarm_irq_enable = atcrtc_alarm_irq_enable,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int atcrtc_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct atcrtc_dev *atcrtc_dev;
|
||||||
|
void __iomem *reg_base;
|
||||||
|
unsigned int rtc_id;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
atcrtc_dev = devm_kzalloc(&pdev->dev, sizeof(*atcrtc_dev), GFP_KERNEL);
|
||||||
|
if (!atcrtc_dev)
|
||||||
|
return -ENOMEM;
|
||||||
|
platform_set_drvdata(pdev, atcrtc_dev);
|
||||||
|
|
||||||
|
reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||||
|
if (IS_ERR(reg_base))
|
||||||
|
return dev_err_probe(&pdev->dev, PTR_ERR(reg_base),
|
||||||
|
"Failed to map I/O space\n");
|
||||||
|
|
||||||
|
atcrtc_dev->regmap = devm_regmap_init_mmio(&pdev->dev,
|
||||||
|
reg_base,
|
||||||
|
&atcrtc_regmap_config);
|
||||||
|
if (IS_ERR(atcrtc_dev->regmap))
|
||||||
|
return dev_err_probe(&pdev->dev, PTR_ERR(atcrtc_dev->regmap),
|
||||||
|
"Failed to initialize regmap\n");
|
||||||
|
|
||||||
|
regmap_read(atcrtc_dev->regmap, RTC_ID, &rtc_id);
|
||||||
|
if (FIELD_GET(ID_MSK, rtc_id) != ID_ATCRTC100)
|
||||||
|
return dev_err_probe(&pdev->dev, -ENODEV,
|
||||||
|
"Failed to initialize RTC: unsupported hardware ID 0x%x\n",
|
||||||
|
rtc_id);
|
||||||
|
|
||||||
|
ret = platform_get_irq(pdev, 1);
|
||||||
|
if (ret < 0)
|
||||||
|
return dev_err_probe(&pdev->dev, ret,
|
||||||
|
"Failed to get IRQ for alarm\n");
|
||||||
|
atcrtc_dev->alarm_irq = ret;
|
||||||
|
|
||||||
|
ret = devm_request_irq(&pdev->dev,
|
||||||
|
atcrtc_dev->alarm_irq,
|
||||||
|
atcrtc_alarm_isr,
|
||||||
|
0,
|
||||||
|
"atcrtc_alarm",
|
||||||
|
atcrtc_dev);
|
||||||
|
if (ret)
|
||||||
|
return dev_err_probe(&pdev->dev, ret,
|
||||||
|
"Failed to request IRQ %d for alarm\n",
|
||||||
|
atcrtc_dev->alarm_irq);
|
||||||
|
|
||||||
|
atcrtc_dev->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
|
||||||
|
if (IS_ERR(atcrtc_dev->rtc_dev))
|
||||||
|
return dev_err_probe(&pdev->dev, PTR_ERR(atcrtc_dev->rtc_dev),
|
||||||
|
"Failed to allocate RTC device\n");
|
||||||
|
|
||||||
|
set_bit(RTC_FEATURE_ALARM, atcrtc_dev->rtc_dev->features);
|
||||||
|
ret = device_init_wakeup(&pdev->dev, true);
|
||||||
|
if (ret)
|
||||||
|
return dev_err_probe(&pdev->dev, ret,
|
||||||
|
"Failed to initialize wake capability\n");
|
||||||
|
|
||||||
|
ret = dev_pm_set_wake_irq(&pdev->dev, atcrtc_dev->alarm_irq);
|
||||||
|
if (ret) {
|
||||||
|
device_init_wakeup(&pdev->dev, false);
|
||||||
|
return dev_err_probe(&pdev->dev, ret,
|
||||||
|
"Failed to set wake IRQ\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
atcrtc_dev->rtc_dev->ops = &rtc_ops;
|
||||||
|
|
||||||
|
INIT_WORK(&atcrtc_dev->rtc_work, atcrtc_alarm_clear);
|
||||||
|
return devm_rtc_register_device(atcrtc_dev->rtc_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int atcrtc_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct atcrtc_dev *rtc = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (device_may_wakeup(dev))
|
||||||
|
disable_irq_wake(rtc->alarm_irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int atcrtc_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct atcrtc_dev *rtc = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (device_may_wakeup(dev))
|
||||||
|
enable_irq_wake(rtc->alarm_irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEFINE_SIMPLE_DEV_PM_OPS(atcrtc_pm_ops, atcrtc_suspend, atcrtc_resume);
|
||||||
|
|
||||||
|
static const struct of_device_id atcrtc_dt_match[] = {
|
||||||
|
{ .compatible = "andestech,atcrtc100" },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, atcrtc_dt_match);
|
||||||
|
|
||||||
|
static struct platform_driver atcrtc_platform_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "atcrtc100",
|
||||||
|
.of_match_table = atcrtc_dt_match,
|
||||||
|
.pm = pm_sleep_ptr(&atcrtc_pm_ops),
|
||||||
|
},
|
||||||
|
.probe = atcrtc_probe,
|
||||||
|
};
|
||||||
|
|
||||||
|
module_platform_driver(atcrtc_platform_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("CL Wang <cl634@andestech.com>");
|
||||||
|
MODULE_DESCRIPTION("Andes ATCRTC100 driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
@@ -1268,9 +1268,6 @@ ds1685_rtc_probe(struct platform_device *pdev)
|
|||||||
rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||||
rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
|
rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
|
||||||
|
|
||||||
/* Maximum periodic rate is 8192Hz (0.122070ms). */
|
|
||||||
rtc_dev->max_user_freq = RTC_MAX_USER_FREQ;
|
|
||||||
|
|
||||||
/* See if the platform doesn't support UIE. */
|
/* See if the platform doesn't support UIE. */
|
||||||
if (pdata->uie_unsupported)
|
if (pdata->uie_unsupported)
|
||||||
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc_dev->features);
|
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc_dev->features);
|
||||||
|
|||||||
@@ -242,6 +242,10 @@ static int gamecube_rtc_read_offset_from_sram(struct priv *d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
hw_srnprot = ioremap(res.start, resource_size(&res));
|
hw_srnprot = ioremap(res.start, resource_size(&res));
|
||||||
|
if (!hw_srnprot) {
|
||||||
|
pr_err("failed to ioremap hw_srnprot\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
old = ioread32be(hw_srnprot);
|
old = ioread32be(hw_srnprot);
|
||||||
|
|
||||||
/* TODO: figure out why we use this magic constant. I obtained it by
|
/* TODO: figure out why we use this magic constant. I obtained it by
|
||||||
|
|||||||
@@ -484,6 +484,12 @@ static const struct of_device_id isl12026_dt_match[] = {
|
|||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, isl12026_dt_match);
|
MODULE_DEVICE_TABLE(of, isl12026_dt_match);
|
||||||
|
|
||||||
|
static const struct i2c_device_id isl12026_id[] = {
|
||||||
|
{ "isl12026" },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(i2c, isl12026_id);
|
||||||
|
|
||||||
static struct i2c_driver isl12026_driver = {
|
static struct i2c_driver isl12026_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "rtc-isl12026",
|
.name = "rtc-isl12026",
|
||||||
@@ -491,6 +497,7 @@ static struct i2c_driver isl12026_driver = {
|
|||||||
},
|
},
|
||||||
.probe = isl12026_probe,
|
.probe = isl12026_probe,
|
||||||
.remove = isl12026_remove,
|
.remove = isl12026_remove,
|
||||||
|
.id_table = isl12026_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_i2c_driver(isl12026_driver);
|
module_i2c_driver(isl12026_driver);
|
||||||
|
|||||||
140
drivers/rtc/rtc-macsmc.c
Normal file
140
drivers/rtc/rtc-macsmc.c
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only OR MIT
|
||||||
|
/*
|
||||||
|
* Apple SMC RTC driver
|
||||||
|
* Copyright The Asahi Linux Contributors
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/mfd/macsmc.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/nvmem-consumer.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/rtc.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
/* 48-bit RTC */
|
||||||
|
#define RTC_BYTES 6
|
||||||
|
#define RTC_BITS (8 * RTC_BYTES)
|
||||||
|
|
||||||
|
/* 32768 Hz clock */
|
||||||
|
#define RTC_SEC_SHIFT 15
|
||||||
|
|
||||||
|
struct macsmc_rtc {
|
||||||
|
struct device *dev;
|
||||||
|
struct apple_smc *smc;
|
||||||
|
struct rtc_device *rtc_dev;
|
||||||
|
struct nvmem_cell *rtc_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int macsmc_rtc_get_time(struct device *dev, struct rtc_time *tm)
|
||||||
|
{
|
||||||
|
struct macsmc_rtc *rtc = dev_get_drvdata(dev);
|
||||||
|
u64 ctr = 0, off = 0;
|
||||||
|
time64_t now;
|
||||||
|
void *p_off;
|
||||||
|
size_t len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = apple_smc_read(rtc->smc, SMC_KEY(CLKM), &ctr, RTC_BYTES);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (ret != RTC_BYTES)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
p_off = nvmem_cell_read(rtc->rtc_offset, &len);
|
||||||
|
if (IS_ERR(p_off))
|
||||||
|
return PTR_ERR(p_off);
|
||||||
|
if (len < RTC_BYTES) {
|
||||||
|
kfree(p_off);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&off, p_off, RTC_BYTES);
|
||||||
|
kfree(p_off);
|
||||||
|
|
||||||
|
/* Sign extend from 48 to 64 bits, then arithmetic shift right 15 bits to get seconds */
|
||||||
|
now = sign_extend64(ctr + off, RTC_BITS - 1) >> RTC_SEC_SHIFT;
|
||||||
|
rtc_time64_to_tm(now, tm);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int macsmc_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
|
{
|
||||||
|
struct macsmc_rtc *rtc = dev_get_drvdata(dev);
|
||||||
|
u64 ctr = 0, off = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = apple_smc_read(rtc->smc, SMC_KEY(CLKM), &ctr, RTC_BYTES);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (ret != RTC_BYTES)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
/* This sets the offset such that the set second begins now */
|
||||||
|
off = (rtc_tm_to_time64(tm) << RTC_SEC_SHIFT) - ctr;
|
||||||
|
return nvmem_cell_write(rtc->rtc_offset, &off, RTC_BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct rtc_class_ops macsmc_rtc_ops = {
|
||||||
|
.read_time = macsmc_rtc_get_time,
|
||||||
|
.set_time = macsmc_rtc_set_time,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int macsmc_rtc_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct apple_smc *smc = dev_get_drvdata(pdev->dev.parent);
|
||||||
|
struct macsmc_rtc *rtc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MFD will probe this device even without a node in the device tree,
|
||||||
|
* thus bail out early if the SMC on the current machines does not
|
||||||
|
* support RTC and has no node in the device tree.
|
||||||
|
*/
|
||||||
|
if (!pdev->dev.of_node)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
|
||||||
|
if (!rtc)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
rtc->dev = &pdev->dev;
|
||||||
|
rtc->smc = smc;
|
||||||
|
|
||||||
|
rtc->rtc_offset = devm_nvmem_cell_get(&pdev->dev, "rtc_offset");
|
||||||
|
if (IS_ERR(rtc->rtc_offset))
|
||||||
|
return dev_err_probe(&pdev->dev, PTR_ERR(rtc->rtc_offset),
|
||||||
|
"Failed to get rtc_offset NVMEM cell\n");
|
||||||
|
|
||||||
|
rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
|
||||||
|
if (IS_ERR(rtc->rtc_dev))
|
||||||
|
return PTR_ERR(rtc->rtc_dev);
|
||||||
|
|
||||||
|
rtc->rtc_dev->ops = &macsmc_rtc_ops;
|
||||||
|
rtc->rtc_dev->range_min = S64_MIN >> (RTC_SEC_SHIFT + (64 - RTC_BITS));
|
||||||
|
rtc->rtc_dev->range_max = S64_MAX >> (RTC_SEC_SHIFT + (64 - RTC_BITS));
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, rtc);
|
||||||
|
|
||||||
|
return devm_rtc_register_device(rtc->rtc_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id macsmc_rtc_of_table[] = {
|
||||||
|
{ .compatible = "apple,smc-rtc", },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, macsmc_rtc_of_table);
|
||||||
|
|
||||||
|
static struct platform_driver macsmc_rtc_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "macsmc-rtc",
|
||||||
|
.of_match_table = macsmc_rtc_of_table,
|
||||||
|
},
|
||||||
|
.probe = macsmc_rtc_probe,
|
||||||
|
};
|
||||||
|
module_platform_driver(macsmc_rtc_driver);
|
||||||
|
|
||||||
|
MODULE_LICENSE("Dual MIT/GPL");
|
||||||
|
MODULE_DESCRIPTION("Apple SMC RTC driver");
|
||||||
|
MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
|
||||||
@@ -391,10 +391,8 @@ static int max31335_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg,
|
return regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg,
|
||||||
MAX31335_STATUS1_A1F, 0);
|
MAX31335_STATUS1_A1F, 0);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int max31335_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
static int max31335_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||||
|
|||||||
542
drivers/rtc/rtc-nvidia-vrs10.c
Normal file
542
drivers/rtc/rtc-nvidia-vrs10.c
Normal file
@@ -0,0 +1,542 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* NVIDIA Voltage Regulator Specification RTC
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||||
|
* All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/bits.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/rtc.h>
|
||||||
|
|
||||||
|
#define NVVRS_REG_VENDOR_ID 0x00
|
||||||
|
#define NVVRS_REG_MODEL_REV 0x01
|
||||||
|
|
||||||
|
/* Interrupts registers */
|
||||||
|
#define NVVRS_REG_INT_SRC1 0x10
|
||||||
|
#define NVVRS_REG_INT_SRC2 0x11
|
||||||
|
#define NVVRS_REG_INT_VENDOR 0x12
|
||||||
|
|
||||||
|
/* Control Registers */
|
||||||
|
#define NVVRS_REG_CTL_1 0x28
|
||||||
|
#define NVVRS_REG_CTL_2 0x29
|
||||||
|
|
||||||
|
/* RTC Registers */
|
||||||
|
#define NVVRS_REG_RTC_T3 0x70
|
||||||
|
#define NVVRS_REG_RTC_T2 0x71
|
||||||
|
#define NVVRS_REG_RTC_T1 0x72
|
||||||
|
#define NVVRS_REG_RTC_T0 0x73
|
||||||
|
#define NVVRS_REG_RTC_A3 0x74
|
||||||
|
#define NVVRS_REG_RTC_A2 0x75
|
||||||
|
#define NVVRS_REG_RTC_A1 0x76
|
||||||
|
#define NVVRS_REG_RTC_A0 0x77
|
||||||
|
|
||||||
|
/* Interrupt Mask */
|
||||||
|
#define NVVRS_INT_SRC1_RSTIRQ_MASK BIT(0)
|
||||||
|
#define NVVRS_INT_SRC1_OSC_MASK BIT(1)
|
||||||
|
#define NVVRS_INT_SRC1_EN_MASK BIT(2)
|
||||||
|
#define NVVRS_INT_SRC1_RTC_MASK BIT(3)
|
||||||
|
#define NVVRS_INT_SRC1_PEC_MASK BIT(4)
|
||||||
|
#define NVVRS_INT_SRC1_WDT_MASK BIT(5)
|
||||||
|
#define NVVRS_INT_SRC1_EM_PD_MASK BIT(6)
|
||||||
|
#define NVVRS_INT_SRC1_INTERNAL_MASK BIT(7)
|
||||||
|
#define NVVRS_INT_SRC2_PBSP_MASK BIT(0)
|
||||||
|
#define NVVRS_INT_SRC2_ECC_DED_MASK BIT(1)
|
||||||
|
#define NVVRS_INT_SRC2_TSD_MASK BIT(2)
|
||||||
|
#define NVVRS_INT_SRC2_LDO_MASK BIT(3)
|
||||||
|
#define NVVRS_INT_SRC2_BIST_MASK BIT(4)
|
||||||
|
#define NVVRS_INT_SRC2_RT_CRC_MASK BIT(5)
|
||||||
|
#define NVVRS_INT_SRC2_VENDOR_MASK BIT(7)
|
||||||
|
#define NVVRS_INT_VENDOR0_MASK BIT(0)
|
||||||
|
#define NVVRS_INT_VENDOR1_MASK BIT(1)
|
||||||
|
#define NVVRS_INT_VENDOR2_MASK BIT(2)
|
||||||
|
#define NVVRS_INT_VENDOR3_MASK BIT(3)
|
||||||
|
#define NVVRS_INT_VENDOR4_MASK BIT(4)
|
||||||
|
#define NVVRS_INT_VENDOR5_MASK BIT(5)
|
||||||
|
#define NVVRS_INT_VENDOR6_MASK BIT(6)
|
||||||
|
#define NVVRS_INT_VENDOR7_MASK BIT(7)
|
||||||
|
|
||||||
|
/* Controller Register Mask */
|
||||||
|
#define NVVRS_REG_CTL_1_FORCE_SHDN (BIT(0) | BIT(1))
|
||||||
|
#define NVVRS_REG_CTL_1_FORCE_ACT BIT(2)
|
||||||
|
#define NVVRS_REG_CTL_1_FORCE_INT BIT(3)
|
||||||
|
#define NVVRS_REG_CTL_2_EN_PEC BIT(0)
|
||||||
|
#define NVVRS_REG_CTL_2_REQ_PEC BIT(1)
|
||||||
|
#define NVVRS_REG_CTL_2_RTC_PU BIT(2)
|
||||||
|
#define NVVRS_REG_CTL_2_RTC_WAKE BIT(3)
|
||||||
|
#define NVVRS_REG_CTL_2_RST_DLY 0xF0
|
||||||
|
|
||||||
|
#define ALARM_RESET_VAL 0xffffffff
|
||||||
|
#define NVVRS_MIN_MODEL_REV 0x40
|
||||||
|
|
||||||
|
enum nvvrs_irq_regs {
|
||||||
|
NVVRS_IRQ_REG_INT_SRC1 = 0,
|
||||||
|
NVVRS_IRQ_REG_INT_SRC2 = 1,
|
||||||
|
NVVRS_IRQ_REG_INT_VENDOR = 2,
|
||||||
|
NVVRS_IRQ_REG_COUNT = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nvvrs_rtc_info {
|
||||||
|
struct device *dev;
|
||||||
|
struct i2c_client *client;
|
||||||
|
struct rtc_device *rtc;
|
||||||
|
unsigned int irq;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int nvvrs_update_bits(struct nvvrs_rtc_info *info, u8 reg,
|
||||||
|
u8 mask, u8 value)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u8 val;
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_byte_data(info->client, reg);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
val = (u8)ret;
|
||||||
|
val &= ~mask;
|
||||||
|
val |= (value & mask);
|
||||||
|
|
||||||
|
return i2c_smbus_write_byte_data(info->client, reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvvrs_rtc_write_alarm(struct i2c_client *client, u8 *time)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A3, time[3]);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A2, time[2]);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A1, time[1]);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A0, time[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvvrs_rtc_enable_alarm(struct nvvrs_rtc_info *info)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Set RTC_WAKE bit for autonomous wake from sleep */
|
||||||
|
ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_WAKE,
|
||||||
|
NVVRS_REG_CTL_2_RTC_WAKE);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Set RTC_PU bit for autonomous wake from shutdown */
|
||||||
|
ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_PU,
|
||||||
|
NVVRS_REG_CTL_2_RTC_PU);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvvrs_rtc_disable_alarm(struct nvvrs_rtc_info *info)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = info->client;
|
||||||
|
u8 val[4];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Clear RTC_WAKE bit */
|
||||||
|
ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_WAKE,
|
||||||
|
0);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Clear RTC_PU bit */
|
||||||
|
ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_PU,
|
||||||
|
0);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Write ALARM_RESET_VAL in RTC Alarm register to disable alarm */
|
||||||
|
val[0] = 0xff;
|
||||||
|
val[1] = 0xff;
|
||||||
|
val[2] = 0xff;
|
||||||
|
val[3] = 0xff;
|
||||||
|
|
||||||
|
ret = nvvrs_rtc_write_alarm(client, val);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvvrs_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||||
|
{
|
||||||
|
struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
|
||||||
|
time64_t secs = 0;
|
||||||
|
int ret;
|
||||||
|
u8 val;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Multi-byte transfers are not supported with PEC enabled
|
||||||
|
* Read MSB first to avoid coherency issues
|
||||||
|
*/
|
||||||
|
ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T3);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
val = (u8)ret;
|
||||||
|
secs |= (time64_t)val << 24;
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T2);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
val = (u8)ret;
|
||||||
|
secs |= (time64_t)val << 16;
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T1);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
val = (u8)ret;
|
||||||
|
secs |= (time64_t)val << 8;
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T0);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
val = (u8)ret;
|
||||||
|
secs |= val;
|
||||||
|
|
||||||
|
rtc_time64_to_tm(secs, tm);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvvrs_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
|
{
|
||||||
|
struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
|
||||||
|
time64_t secs;
|
||||||
|
u8 time[4];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
secs = rtc_tm_to_time64(tm);
|
||||||
|
time[0] = secs & 0xff;
|
||||||
|
time[1] = (secs >> 8) & 0xff;
|
||||||
|
time[2] = (secs >> 16) & 0xff;
|
||||||
|
time[3] = (secs >> 24) & 0xff;
|
||||||
|
|
||||||
|
ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T3, time[3]);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T2, time[2]);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T1, time[1]);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T0, time[0]);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvvrs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
|
{
|
||||||
|
struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
|
||||||
|
time64_t alarm_val = 0;
|
||||||
|
int ret;
|
||||||
|
u8 val;
|
||||||
|
|
||||||
|
/* Multi-byte transfers are not supported with PEC enabled */
|
||||||
|
ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A3);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
val = (u8)ret;
|
||||||
|
alarm_val |= (time64_t)val << 24;
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A2);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
val = (u8)ret;
|
||||||
|
alarm_val |= (time64_t)val << 16;
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A1);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
val = (u8)ret;
|
||||||
|
alarm_val |= (time64_t)val << 8;
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A0);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
val = (u8)ret;
|
||||||
|
alarm_val |= val;
|
||||||
|
|
||||||
|
if (alarm_val == ALARM_RESET_VAL)
|
||||||
|
alrm->enabled = 0;
|
||||||
|
else
|
||||||
|
alrm->enabled = 1;
|
||||||
|
|
||||||
|
rtc_time64_to_tm(alarm_val, &alrm->time);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvvrs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
|
{
|
||||||
|
struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
|
||||||
|
time64_t secs;
|
||||||
|
u8 time[4];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!alrm->enabled) {
|
||||||
|
ret = nvvrs_rtc_disable_alarm(info);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nvvrs_rtc_enable_alarm(info);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
secs = rtc_tm_to_time64(&alrm->time);
|
||||||
|
time[0] = secs & 0xff;
|
||||||
|
time[1] = (secs >> 8) & 0xff;
|
||||||
|
time[2] = (secs >> 16) & 0xff;
|
||||||
|
time[3] = (secs >> 24) & 0xff;
|
||||||
|
|
||||||
|
ret = nvvrs_rtc_write_alarm(info->client, time);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvvrs_pseq_irq_clear(struct nvvrs_rtc_info *info)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (i = 0; i < NVVRS_IRQ_REG_COUNT; i++) {
|
||||||
|
ret = i2c_smbus_read_byte_data(info->client,
|
||||||
|
NVVRS_REG_INT_SRC1 + i);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(info->dev, "Failed to read INT_SRC%d : %d\n",
|
||||||
|
i + 1, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = i2c_smbus_write_byte_data(info->client,
|
||||||
|
NVVRS_REG_INT_SRC1 + i,
|
||||||
|
(u8)ret);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(info->dev, "Failed to clear INT_SRC%d : %d\n",
|
||||||
|
i + 1, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t nvvrs_rtc_irq_handler(int irq, void *data)
|
||||||
|
{
|
||||||
|
struct nvvrs_rtc_info *info = data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Check for RTC alarm interrupt */
|
||||||
|
ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_INT_SRC1);
|
||||||
|
if (ret < 0)
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
|
if (ret & NVVRS_INT_SRC1_RTC_MASK) {
|
||||||
|
rtc_lock(info->rtc);
|
||||||
|
rtc_update_irq(info->rtc, 1, RTC_IRQF | RTC_AF);
|
||||||
|
rtc_unlock(info->rtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear all interrupts */
|
||||||
|
if (nvvrs_pseq_irq_clear(info) < 0)
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvvrs_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This hardware does not support enabling/disabling the alarm IRQ
|
||||||
|
* independently. The alarm is disabled by clearing the alarm time
|
||||||
|
* via set_alarm().
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct rtc_class_ops nvvrs_rtc_ops = {
|
||||||
|
.read_time = nvvrs_rtc_read_time,
|
||||||
|
.set_time = nvvrs_rtc_set_time,
|
||||||
|
.read_alarm = nvvrs_rtc_read_alarm,
|
||||||
|
.set_alarm = nvvrs_rtc_set_alarm,
|
||||||
|
.alarm_irq_enable = nvvrs_rtc_alarm_irq_enable,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int nvvrs_pseq_vendor_info(struct nvvrs_rtc_info *info)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = info->client;
|
||||||
|
u8 vendor_id, model_rev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_byte_data(client, NVVRS_REG_VENDOR_ID);
|
||||||
|
if (ret < 0)
|
||||||
|
return dev_err_probe(&client->dev, ret,
|
||||||
|
"Failed to read Vendor ID\n");
|
||||||
|
|
||||||
|
vendor_id = (u8)ret;
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_byte_data(client, NVVRS_REG_MODEL_REV);
|
||||||
|
if (ret < 0)
|
||||||
|
return dev_err_probe(&client->dev, ret,
|
||||||
|
"Failed to read Model Revision\n");
|
||||||
|
|
||||||
|
model_rev = (u8)ret;
|
||||||
|
|
||||||
|
if (model_rev < NVVRS_MIN_MODEL_REV) {
|
||||||
|
return dev_err_probe(&client->dev, -ENODEV,
|
||||||
|
"Chip revision 0x%02x is not supported!\n",
|
||||||
|
model_rev);
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_dbg(&client->dev, "NVVRS Vendor ID: 0x%02x, Model Rev: 0x%02x\n",
|
||||||
|
vendor_id, model_rev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvvrs_rtc_probe(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct nvvrs_rtc_info *info;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
|
||||||
|
if (!info)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (client->irq <= 0)
|
||||||
|
return dev_err_probe(&client->dev, -EINVAL, "No IRQ specified\n");
|
||||||
|
|
||||||
|
info->irq = client->irq;
|
||||||
|
info->dev = &client->dev;
|
||||||
|
client->flags |= I2C_CLIENT_PEC;
|
||||||
|
i2c_set_clientdata(client, info);
|
||||||
|
info->client = client;
|
||||||
|
|
||||||
|
/* Check vendor info */
|
||||||
|
if (nvvrs_pseq_vendor_info(info) < 0)
|
||||||
|
return dev_err_probe(&client->dev, -EINVAL,
|
||||||
|
"Failed to get vendor info\n");
|
||||||
|
|
||||||
|
/* Clear any pending IRQs before requesting IRQ handler */
|
||||||
|
if (nvvrs_pseq_irq_clear(info) < 0)
|
||||||
|
return dev_err_probe(&client->dev, -EINVAL,
|
||||||
|
"Failed to clear interrupts\n");
|
||||||
|
|
||||||
|
/* Allocate RTC device */
|
||||||
|
info->rtc = devm_rtc_allocate_device(info->dev);
|
||||||
|
if (IS_ERR(info->rtc))
|
||||||
|
return PTR_ERR(info->rtc);
|
||||||
|
|
||||||
|
info->rtc->ops = &nvvrs_rtc_ops;
|
||||||
|
info->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||||
|
info->rtc->range_max = RTC_TIMESTAMP_END_2099;
|
||||||
|
|
||||||
|
/* Request RTC IRQ */
|
||||||
|
ret = devm_request_threaded_irq(info->dev, info->irq, NULL,
|
||||||
|
nvvrs_rtc_irq_handler, IRQF_ONESHOT,
|
||||||
|
"nvvrs-rtc", info);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err_probe(info->dev, ret, "Failed to request RTC IRQ\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RTC as a wakeup source */
|
||||||
|
devm_device_init_wakeup(info->dev);
|
||||||
|
|
||||||
|
return devm_rtc_register_device(info->rtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static int nvvrs_rtc_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (device_may_wakeup(dev)) {
|
||||||
|
/* Set RTC_WAKE bit for auto wake system from suspend state */
|
||||||
|
ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2,
|
||||||
|
NVVRS_REG_CTL_2_RTC_WAKE,
|
||||||
|
NVVRS_REG_CTL_2_RTC_WAKE);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(info->dev, "Failed to set RTC_WAKE bit (%d)\n",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return enable_irq_wake(info->irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvvrs_rtc_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (device_may_wakeup(dev)) {
|
||||||
|
/* Clear FORCE_ACT bit */
|
||||||
|
ret = nvvrs_update_bits(info, NVVRS_REG_CTL_1,
|
||||||
|
NVVRS_REG_CTL_1_FORCE_ACT, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(info->dev, "Failed to clear FORCE_ACT bit (%d)\n",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return disable_irq_wake(info->irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
static SIMPLE_DEV_PM_OPS(nvvrs_rtc_pm_ops, nvvrs_rtc_suspend, nvvrs_rtc_resume);
|
||||||
|
|
||||||
|
static const struct of_device_id nvvrs_rtc_of_match[] = {
|
||||||
|
{ .compatible = "nvidia,vrs-10" },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, nvvrs_rtc_of_match);
|
||||||
|
|
||||||
|
static struct i2c_driver nvvrs_rtc_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "rtc-nvidia-vrs10",
|
||||||
|
.pm = &nvvrs_rtc_pm_ops,
|
||||||
|
.of_match_table = nvvrs_rtc_of_match,
|
||||||
|
},
|
||||||
|
.probe = nvvrs_rtc_probe,
|
||||||
|
};
|
||||||
|
|
||||||
|
module_i2c_driver(nvvrs_rtc_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Shubhi Garg <shgarg@nvidia.com>");
|
||||||
|
MODULE_DESCRIPTION("NVIDIA Voltage Regulator Specification RTC driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
@@ -340,8 +340,6 @@ static int pic32_rtc_probe(struct platform_device *pdev)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto err_nortc;
|
goto err_nortc;
|
||||||
|
|
||||||
pdata->rtc->max_user_freq = 128;
|
|
||||||
|
|
||||||
pic32_rtc_setfreq(&pdev->dev, 1);
|
pic32_rtc_setfreq(&pdev->dev, 1);
|
||||||
ret = devm_request_irq(&pdev->dev, pdata->alarm_irq,
|
ret = devm_request_irq(&pdev->dev, pdata->alarm_irq,
|
||||||
pic32_rtc_alarmirq, 0,
|
pic32_rtc_alarmirq, 0,
|
||||||
|
|||||||
@@ -726,7 +726,7 @@ static int rtca3_probe(struct platform_device *pdev)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
priv->rstc = devm_reset_control_get_shared(dev, NULL);
|
priv->rstc = devm_reset_control_array_get_shared(dev);
|
||||||
if (IS_ERR(priv->rstc))
|
if (IS_ERR(priv->rstc))
|
||||||
return PTR_ERR(priv->rstc);
|
return PTR_ERR(priv->rstc);
|
||||||
|
|
||||||
@@ -772,7 +772,6 @@ static int rtca3_probe(struct platform_device *pdev)
|
|||||||
return PTR_ERR(priv->rtc_dev);
|
return PTR_ERR(priv->rtc_dev);
|
||||||
|
|
||||||
priv->rtc_dev->ops = &rtca3_ops;
|
priv->rtc_dev->ops = &rtca3_ops;
|
||||||
priv->rtc_dev->max_user_freq = 256;
|
|
||||||
priv->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
priv->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||||
priv->rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
|
priv->rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
|
||||||
|
|
||||||
|
|||||||
@@ -1023,8 +1023,6 @@ static int rv3028_probe(struct i2c_client *client)
|
|||||||
eeprom_cfg.priv = rv3028;
|
eeprom_cfg.priv = rv3028;
|
||||||
devm_rtc_nvmem_register(rv3028->rtc, &eeprom_cfg);
|
devm_rtc_nvmem_register(rv3028->rtc, &eeprom_cfg);
|
||||||
|
|
||||||
rv3028->rtc->max_user_freq = 1;
|
|
||||||
|
|
||||||
#ifdef CONFIG_COMMON_CLK
|
#ifdef CONFIG_COMMON_CLK
|
||||||
rv3028_clkout_register_clk(rv3028, client);
|
rv3028_clkout_register_clk(rv3028, client);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -968,8 +968,6 @@ static int rv3032_probe(struct i2c_client *client)
|
|||||||
eeprom_cfg.priv = rv3032;
|
eeprom_cfg.priv = rv3032;
|
||||||
devm_rtc_nvmem_register(rv3032->rtc, &eeprom_cfg);
|
devm_rtc_nvmem_register(rv3032->rtc, &eeprom_cfg);
|
||||||
|
|
||||||
rv3032->rtc->max_user_freq = 1;
|
|
||||||
|
|
||||||
#ifdef CONFIG_COMMON_CLK
|
#ifdef CONFIG_COMMON_CLK
|
||||||
rv3032_clkout_register_clk(rv3032, client);
|
rv3032_clkout_register_clk(rv3032, client);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -738,8 +738,6 @@ static int rv8803_probe(struct i2c_client *client)
|
|||||||
|
|
||||||
devm_rtc_nvmem_register(rv8803->rtc, &nvmem_cfg);
|
devm_rtc_nvmem_register(rv8803->rtc, &nvmem_cfg);
|
||||||
|
|
||||||
rv8803->rtc->max_user_freq = 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -324,8 +324,6 @@ static int rx6110_probe(struct rx6110_data *rx6110, struct device *dev)
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
rx6110->rtc->max_user_freq = 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -412,7 +412,6 @@ static int rx8010_probe(struct i2c_client *client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
rx8010->rtc->ops = &rx8010_rtc_ops;
|
rx8010->rtc->ops = &rx8010_rtc_ops;
|
||||||
rx8010->rtc->max_user_freq = 1;
|
|
||||||
rx8010->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
rx8010->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||||
rx8010->rtc->range_max = RTC_TIMESTAMP_END_2099;
|
rx8010->rtc->range_max = RTC_TIMESTAMP_END_2099;
|
||||||
|
|
||||||
|
|||||||
@@ -565,8 +565,6 @@ static int rx8025_probe(struct i2c_client *client)
|
|||||||
clear_bit(RTC_FEATURE_ALARM, rx8025->rtc->features);
|
clear_bit(RTC_FEATURE_ALARM, rx8025->rtc->features);
|
||||||
}
|
}
|
||||||
|
|
||||||
rx8025->rtc->max_user_freq = 1;
|
|
||||||
|
|
||||||
set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rx8025->rtc->features);
|
set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rx8025->rtc->features);
|
||||||
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rx8025->rtc->features);
|
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rx8025->rtc->features);
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ struct s35390a {
|
|||||||
int twentyfourhour;
|
int twentyfourhour;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int s35390a_set_reg(struct s35390a *s35390a, int reg, char *buf, int len)
|
static int s35390a_set_reg(struct s35390a *s35390a, int reg, u8 *buf, int len)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = s35390a->client[reg];
|
struct i2c_client *client = s35390a->client[reg];
|
||||||
struct i2c_msg msg[] = {
|
struct i2c_msg msg[] = {
|
||||||
@@ -83,7 +83,7 @@ static int s35390a_set_reg(struct s35390a *s35390a, int reg, char *buf, int len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len)
|
static int s35390a_get_reg(struct s35390a *s35390a, int reg, u8 *buf, int len)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = s35390a->client[reg];
|
struct i2c_client *client = s35390a->client[reg];
|
||||||
struct i2c_msg msg[] = {
|
struct i2c_msg msg[] = {
|
||||||
@@ -168,7 +168,7 @@ static int s35390a_read_status(struct s35390a *s35390a, char *status1)
|
|||||||
|
|
||||||
static int s35390a_disable_test_mode(struct s35390a *s35390a)
|
static int s35390a_disable_test_mode(struct s35390a *s35390a)
|
||||||
{
|
{
|
||||||
char buf[1];
|
u8 buf[1];
|
||||||
|
|
||||||
if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf)) < 0)
|
if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf)) < 0)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@@ -210,7 +210,7 @@ static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
struct s35390a *s35390a = i2c_get_clientdata(client);
|
struct s35390a *s35390a = i2c_get_clientdata(client);
|
||||||
int i;
|
int i;
|
||||||
char buf[7], status;
|
u8 buf[7], status;
|
||||||
|
|
||||||
dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d mday=%d, "
|
dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d mday=%d, "
|
||||||
"mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec,
|
"mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec,
|
||||||
@@ -239,7 +239,7 @@ static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
struct s35390a *s35390a = i2c_get_clientdata(client);
|
struct s35390a *s35390a = i2c_get_clientdata(client);
|
||||||
char buf[7], status;
|
u8 buf[7], status;
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
if (s35390a_read_status(s35390a, &status) == 1)
|
if (s35390a_read_status(s35390a, &status) == 1)
|
||||||
@@ -273,7 +273,7 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
|
|||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
struct s35390a *s35390a = i2c_get_clientdata(client);
|
struct s35390a *s35390a = i2c_get_clientdata(client);
|
||||||
char buf[3], sts = 0;
|
u8 buf[3], sts = 0;
|
||||||
int err, i;
|
int err, i;
|
||||||
|
|
||||||
dev_dbg(&client->dev, "%s: alm is secs=%d, mins=%d, hours=%d mday=%d, "\
|
dev_dbg(&client->dev, "%s: alm is secs=%d, mins=%d, hours=%d mday=%d, "\
|
||||||
@@ -326,7 +326,7 @@ static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
|
|||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
struct s35390a *s35390a = i2c_get_clientdata(client);
|
struct s35390a *s35390a = i2c_get_clientdata(client);
|
||||||
char buf[3], sts;
|
u8 buf[3], sts;
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
|
err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
|
||||||
@@ -383,7 +383,7 @@ static int s35390a_rtc_ioctl(struct device *dev, unsigned int cmd,
|
|||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
struct s35390a *s35390a = i2c_get_clientdata(client);
|
struct s35390a *s35390a = i2c_get_clientdata(client);
|
||||||
char sts;
|
u8 sts;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
@@ -422,7 +422,7 @@ static int s35390a_probe(struct i2c_client *client)
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct s35390a *s35390a;
|
struct s35390a *s35390a;
|
||||||
struct rtc_device *rtc;
|
struct rtc_device *rtc;
|
||||||
char buf, status1;
|
u8 buf, status1;
|
||||||
struct device *dev = &client->dev;
|
struct device *dev = &client->dev;
|
||||||
|
|
||||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
|
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
|
||||||
|
|||||||
@@ -40,8 +40,6 @@
|
|||||||
|
|
||||||
#define RTC_DEF_DIVIDER (32768 - 1)
|
#define RTC_DEF_DIVIDER (32768 - 1)
|
||||||
#define RTC_DEF_TRIM 0
|
#define RTC_DEF_TRIM 0
|
||||||
#define RTC_FREQ 1024
|
|
||||||
|
|
||||||
|
|
||||||
static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
|
static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
@@ -202,7 +200,6 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
info->rtc->ops = &sa1100_rtc_ops;
|
info->rtc->ops = &sa1100_rtc_ops;
|
||||||
info->rtc->max_user_freq = RTC_FREQ;
|
|
||||||
info->rtc->range_max = U32_MAX;
|
info->rtc->range_max = U32_MAX;
|
||||||
|
|
||||||
ret = devm_rtc_register_device(info->rtc);
|
ret = devm_rtc_register_device(info->rtc);
|
||||||
|
|||||||
@@ -423,7 +423,6 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
|
|||||||
writeb(tmp, rtc->regbase + RCR1);
|
writeb(tmp, rtc->regbase + RCR1);
|
||||||
|
|
||||||
rtc->rtc_dev->ops = &sh_rtc_ops;
|
rtc->rtc_dev->ops = &sh_rtc_ops;
|
||||||
rtc->rtc_dev->max_user_freq = 256;
|
|
||||||
|
|
||||||
if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) {
|
if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) {
|
||||||
rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900;
|
rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900;
|
||||||
|
|||||||
@@ -274,6 +274,12 @@ static const struct of_device_id tegra_rtc_dt_match[] = {
|
|||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, tegra_rtc_dt_match);
|
MODULE_DEVICE_TABLE(of, tegra_rtc_dt_match);
|
||||||
|
|
||||||
|
static const struct acpi_device_id tegra_rtc_acpi_match[] = {
|
||||||
|
{ "NVDA0280" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(acpi, tegra_rtc_acpi_match);
|
||||||
|
|
||||||
static int tegra_rtc_probe(struct platform_device *pdev)
|
static int tegra_rtc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct tegra_rtc_info *info;
|
struct tegra_rtc_info *info;
|
||||||
@@ -300,13 +306,11 @@ static int tegra_rtc_probe(struct platform_device *pdev)
|
|||||||
info->rtc->ops = &tegra_rtc_ops;
|
info->rtc->ops = &tegra_rtc_ops;
|
||||||
info->rtc->range_max = U32_MAX;
|
info->rtc->range_max = U32_MAX;
|
||||||
|
|
||||||
info->clk = devm_clk_get(&pdev->dev, NULL);
|
if (dev_of_node(&pdev->dev)) {
|
||||||
if (IS_ERR(info->clk))
|
info->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||||
return PTR_ERR(info->clk);
|
if (IS_ERR(info->clk))
|
||||||
|
return PTR_ERR(info->clk);
|
||||||
ret = clk_prepare_enable(info->clk);
|
}
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
/* set context info */
|
/* set context info */
|
||||||
info->pdev = pdev;
|
info->pdev = pdev;
|
||||||
@@ -324,32 +328,18 @@ static int tegra_rtc_probe(struct platform_device *pdev)
|
|||||||
ret = devm_request_irq(&pdev->dev, info->irq, tegra_rtc_irq_handler,
|
ret = devm_request_irq(&pdev->dev, info->irq, tegra_rtc_irq_handler,
|
||||||
IRQF_TRIGGER_HIGH, dev_name(&pdev->dev),
|
IRQF_TRIGGER_HIGH, dev_name(&pdev->dev),
|
||||||
&pdev->dev);
|
&pdev->dev);
|
||||||
if (ret) {
|
if (ret)
|
||||||
dev_err(&pdev->dev, "failed to request interrupt: %d\n", ret);
|
return dev_err_probe(&pdev->dev, ret, "failed to request interrupt\n");
|
||||||
goto disable_clk;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = devm_rtc_register_device(info->rtc);
|
ret = devm_rtc_register_device(info->rtc);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto disable_clk;
|
return ret;
|
||||||
|
|
||||||
dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n");
|
dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
disable_clk:
|
|
||||||
clk_disable_unprepare(info->clk);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra_rtc_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct tegra_rtc_info *info = platform_get_drvdata(pdev);
|
|
||||||
|
|
||||||
clk_disable_unprepare(info->clk);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
|
||||||
static int tegra_rtc_suspend(struct device *dev)
|
static int tegra_rtc_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct tegra_rtc_info *info = dev_get_drvdata(dev);
|
struct tegra_rtc_info *info = dev_get_drvdata(dev);
|
||||||
@@ -387,9 +377,8 @@ static int tegra_rtc_resume(struct device *dev)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static SIMPLE_DEV_PM_OPS(tegra_rtc_pm_ops, tegra_rtc_suspend, tegra_rtc_resume);
|
static DEFINE_SIMPLE_DEV_PM_OPS(tegra_rtc_pm_ops, tegra_rtc_suspend, tegra_rtc_resume);
|
||||||
|
|
||||||
static void tegra_rtc_shutdown(struct platform_device *pdev)
|
static void tegra_rtc_shutdown(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
@@ -399,12 +388,12 @@ static void tegra_rtc_shutdown(struct platform_device *pdev)
|
|||||||
|
|
||||||
static struct platform_driver tegra_rtc_driver = {
|
static struct platform_driver tegra_rtc_driver = {
|
||||||
.probe = tegra_rtc_probe,
|
.probe = tegra_rtc_probe,
|
||||||
.remove = tegra_rtc_remove,
|
|
||||||
.shutdown = tegra_rtc_shutdown,
|
.shutdown = tegra_rtc_shutdown,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "tegra_rtc",
|
.name = "tegra_rtc",
|
||||||
.of_match_table = tegra_rtc_dt_match,
|
.of_match_table = tegra_rtc_dt_match,
|
||||||
.pm = &tegra_rtc_pm_ops,
|
.acpi_match_table = tegra_rtc_acpi_match,
|
||||||
|
.pm = pm_sleep_ptr(&tegra_rtc_pm_ops),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
module_platform_driver(tegra_rtc_driver);
|
module_platform_driver(tegra_rtc_driver);
|
||||||
|
|||||||
@@ -324,7 +324,6 @@ struct ds1685_rtc_platform_data {
|
|||||||
#define RTC_SQW_2HZ 0x0f /* 0 1 1 1 1 */
|
#define RTC_SQW_2HZ 0x0f /* 0 1 1 1 1 */
|
||||||
#define RTC_SQW_0HZ 0x00 /* 0 0 0 0 0 */
|
#define RTC_SQW_0HZ 0x00 /* 0 0 0 0 0 */
|
||||||
#define RTC_SQW_32768HZ 32768 /* 1 - - - - */
|
#define RTC_SQW_32768HZ 32768 /* 1 - - - - */
|
||||||
#define RTC_MAX_USER_FREQ 8192
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user