RTC for 6.19
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
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEBqsFVZXh8s/0O5JiY6TcMGxwOjIFAmk8lp4ACgkQY6TcMGxw
OjLp8Q/9HL1Jxy8oXHfvnCCb1/2VPrkRaAEUGJKvbwEJRr7IOM4etyjX2LuCTex4
L5EQhoTZDhT75bIdVM67hhxswQ+LeBQiPy+kNBsGDPqhIIKx1Wf45Hk3UutJcXta
Y2FWkPw704WUtLI4oWGxhBgSCMp84lcgakNNITLGUcO2TeRaPqIimcU0p+0PgpZu
4YYuwu6lPQIK2UL2RcH9dzUiEArM0kkK619jsCvUKEZNI6KQi/8rbyybM6lmiyVp
FGHAx2Ttr5SIa+Us7TB2M9D+P1Cq06WgmDXClF1SXKUXPKT3Q5woGcjTOzH35Bbf
vw7nm4ouPe5EKy3ED7nXpXJacpxXvEUo4UKMN6CztAEAoxBsABJ1WjxuHq1bjT9R
7aSpkNGOMkjzLsD405XRA2oIH1Dp+ML2UAL4fOdu2Hy/cFBXoFqlGnK/mnbXyVMG
InCbY9HbeO/bOrp7/iKGQMj6Wz0T7TmH2MUT6FHqpk4cXbDW3lwifDJ6NrBafpVq
VxAsl1wZLeMT1ga8FJQJ2eITLT1QfvYaPNjZM4d9hCRJybst7sxNWxFNHhn/cGD/
Hdq9iVhU0yVO9HfBYZ7soLXrxg2ePcwsK3oBNvGmp+ZzLy5Jd0/VIE/F2/F+0yke
rfiEQwUNob7qqsBFT6ko9JiZ8dsAqKldd8f/jgIE+xfDhRbCnOU=
=oBij
-----END PGP SIGNATURE-----
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
...
master
commit
d324e9a915
|
|
@ -14,7 +14,7 @@ Description:
|
|||
for RTCs that support alarms
|
||||
|
||||
* 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
|
||||
alarm interrupt. (Prefer to use RTC_WKALM_*)
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ properties:
|
|||
reboot:
|
||||
$ref: /schemas/power/reset/apple,smc-reboot.yaml
|
||||
|
||||
rtc:
|
||||
$ref: /schemas/rtc/apple,smc-rtc.yaml
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
|
|
@ -80,5 +83,11 @@ examples:
|
|||
nvmem-cell-names = "shutdown_flag", "boot_stage",
|
||||
"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>;
|
||||
};
|
||||
|
|
@ -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
|
||||
|
|
@ -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:
|
||||
- Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
|
||||
|
||||
allOf:
|
||||
- $ref: rtc.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- renesas,r9a08g045-rtca3 # RZ/G3S
|
||||
- renesas,r9a09g057-rtca3 # RZ/V2H
|
||||
- const: renesas,rz-rtca3
|
||||
|
||||
reg:
|
||||
|
|
@ -48,8 +46,12 @@ properties:
|
|||
maxItems: 1
|
||||
|
||||
resets:
|
||||
items:
|
||||
- description: VBATTB module reset
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
reset-names:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
|
@ -61,6 +63,39 @@ required:
|
|||
- power-domains
|
||||
- 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
|
||||
|
||||
examples:
|
||||
|
|
@ -81,4 +116,5 @@ examples:
|
|||
clock-names = "bus", "counter";
|
||||
power-domains = <&cpg>;
|
||||
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/reset/apple,smc-reboot.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/spmi/apple,spmi.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/power/reset/macsmc-reboot.c
|
||||
F: drivers/pwm/pwm-apple.c
|
||||
F: drivers/rtc/rtc-macsmc.c
|
||||
F: drivers/soc/apple/*
|
||||
F: drivers/spi/spi-apple.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: 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
|
||||
M: Alban Bedel <albeu@free.fr>
|
||||
S: Maintained
|
||||
|
|
@ -18692,6 +18700,13 @@ S: Maintained
|
|||
F: drivers/video/fbdev/nvidia/
|
||||
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
|
||||
M: Daniel Dadap <ddadap@nvidia.com>
|
||||
L: platform-driver-x86@vger.kernel.org
|
||||
|
|
|
|||
|
|
@ -409,13 +409,22 @@ config RTC_DRV_MAX77686
|
|||
config RTC_DRV_SPACEMIT_P1
|
||||
tristate "SpacemiT P1 RTC"
|
||||
depends on ARCH_SPACEMIT || COMPILE_TEST
|
||||
select MFD_SPACEMIT_P1
|
||||
default ARCH_SPACEMIT
|
||||
depends on MFD_SPACEMIT_P1
|
||||
default MFD_SPACEMIT_P1
|
||||
help
|
||||
Enable support for the RTC function in the SpacemiT P1 PMIC.
|
||||
This driver can also be built as a module, which will be called
|
||||
"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
|
||||
tristate "Nuvoton NCT3018Y"
|
||||
depends on OF
|
||||
|
|
@ -1063,6 +1072,21 @@ config RTC_DRV_ALPHA
|
|||
Direct support for the real-time clock found on every Alpha
|
||||
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
|
||||
tristate "Dallas DS1216"
|
||||
depends on SNI_RM
|
||||
|
|
@ -1749,7 +1773,7 @@ config RTC_DRV_MC13XXX
|
|||
tristate "Freescale MC13xxx RTC"
|
||||
help
|
||||
This enables support for the RTCs found on Freescale's PMICs
|
||||
MC13783 and MC13892.
|
||||
MC13783, MC13892 and MC34708.
|
||||
|
||||
config RTC_DRV_MPC5121
|
||||
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
|
||||
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
|
||||
tristate "MStar MSC313 RTC"
|
||||
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_AT91RM9200)+= rtc-at91rm9200.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_BBNSM) += rtc-nxp-bbnsm.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_M48T86) += rtc-m48t86.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_MAX6900) += rtc-max6900.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_NCT6694) += rtc-nct6694.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_OPAL) += rtc-opal.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");
|
||||
aml_rtc_init(rtc);
|
||||
|
||||
device_init_wakeup(dev, true);
|
||||
devm_device_init_wakeup(dev);
|
||||
platform_set_drvdata(pdev, rtc);
|
||||
|
||||
rtc->rtc_dev = devm_rtc_allocate_device(dev);
|
||||
if (IS_ERR(rtc->rtc_dev)) {
|
||||
ret = PTR_ERR(rtc->rtc_dev);
|
||||
goto err_clk;
|
||||
}
|
||||
if (IS_ERR(rtc->rtc_dev))
|
||||
return PTR_ERR(rtc->rtc_dev);
|
||||
|
||||
ret = devm_request_irq(dev, rtc->irq, aml_rtc_handler,
|
||||
IRQF_ONESHOT, "aml-rtc alarm", rtc);
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "IRQ%d request failed, ret = %d\n",
|
||||
rtc->irq, ret);
|
||||
goto err_clk;
|
||||
return ret;
|
||||
}
|
||||
|
||||
rtc->rtc_dev->ops = &aml_rtc_ops;
|
||||
rtc->rtc_dev->range_min = 0;
|
||||
rtc->rtc_dev->range_max = U32_MAX;
|
||||
|
||||
ret = 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;
|
||||
return devm_rtc_register_device(rtc->rtc_dev);
|
||||
}
|
||||
|
||||
#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,
|
||||
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 = {
|
||||
};
|
||||
|
||||
|
|
@ -451,7 +430,6 @@ MODULE_DEVICE_TABLE(of, aml_rtc_device_id);
|
|||
|
||||
static struct platform_driver aml_rtc_driver = {
|
||||
.probe = aml_rtc_probe,
|
||||
.remove = aml_rtc_remove,
|
||||
.driver = {
|
||||
.name = "aml-rtc",
|
||||
.pm = &aml_rtc_pm_ops,
|
||||
|
|
|
|||
|
|
@ -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_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. */
|
||||
if (pdata->uie_unsupported)
|
||||
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));
|
||||
if (!hw_srnprot) {
|
||||
pr_err("failed to ioremap hw_srnprot\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
old = ioread32be(hw_srnprot);
|
||||
|
||||
/* 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);
|
||||
|
||||
static const struct i2c_device_id isl12026_id[] = {
|
||||
{ "isl12026" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, isl12026_id);
|
||||
|
||||
static struct i2c_driver isl12026_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-isl12026",
|
||||
|
|
@ -491,6 +497,7 @@ static struct i2c_driver isl12026_driver = {
|
|||
},
|
||||
.probe = isl12026_probe,
|
||||
.remove = isl12026_remove,
|
||||
.id_table = isl12026_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(isl12026_driver);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
return ret;
|
||||
|
||||
ret = regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg,
|
||||
MAX31335_STATUS1_A1F, 0);
|
||||
|
||||
return 0;
|
||||
return regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg,
|
||||
MAX31335_STATUS1_A1F, 0);
|
||||
}
|
||||
|
||||
static int max31335_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
goto err_nortc;
|
||||
|
||||
pdata->rtc->max_user_freq = 128;
|
||||
|
||||
pic32_rtc_setfreq(&pdev->dev, 1);
|
||||
ret = devm_request_irq(&pdev->dev, pdata->alarm_irq,
|
||||
pic32_rtc_alarmirq, 0,
|
||||
|
|
|
|||
|
|
@ -726,7 +726,7 @@ static int rtca3_probe(struct platform_device *pdev)
|
|||
if (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))
|
||||
return PTR_ERR(priv->rstc);
|
||||
|
||||
|
|
@ -772,7 +772,6 @@ static int rtca3_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(priv->rtc_dev);
|
||||
|
||||
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_max = RTC_TIMESTAMP_END_2099;
|
||||
|
||||
|
|
|
|||
|
|
@ -1023,8 +1023,6 @@ static int rv3028_probe(struct i2c_client *client)
|
|||
eeprom_cfg.priv = rv3028;
|
||||
devm_rtc_nvmem_register(rv3028->rtc, &eeprom_cfg);
|
||||
|
||||
rv3028->rtc->max_user_freq = 1;
|
||||
|
||||
#ifdef CONFIG_COMMON_CLK
|
||||
rv3028_clkout_register_clk(rv3028, client);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -968,8 +968,6 @@ static int rv3032_probe(struct i2c_client *client)
|
|||
eeprom_cfg.priv = rv3032;
|
||||
devm_rtc_nvmem_register(rv3032->rtc, &eeprom_cfg);
|
||||
|
||||
rv3032->rtc->max_user_freq = 1;
|
||||
|
||||
#ifdef CONFIG_COMMON_CLK
|
||||
rv3032_clkout_register_clk(rv3032, client);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -738,8 +738,6 @@ static int rv8803_probe(struct i2c_client *client)
|
|||
|
||||
devm_rtc_nvmem_register(rv8803->rtc, &nvmem_cfg);
|
||||
|
||||
rv8803->rtc->max_user_freq = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -324,8 +324,6 @@ static int rx6110_probe(struct rx6110_data *rx6110, struct device *dev)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
rx6110->rtc->max_user_freq = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -412,7 +412,6 @@ static int rx8010_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
rx8010->rtc->ops = &rx8010_rtc_ops;
|
||||
rx8010->rtc->max_user_freq = 1;
|
||||
rx8010->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||
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);
|
||||
}
|
||||
|
||||
rx8025->rtc->max_user_freq = 1;
|
||||
|
||||
set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rx8025->rtc->features);
|
||||
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rx8025->rtc->features);
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ struct s35390a {
|
|||
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_msg msg[] = {
|
||||
|
|
@ -83,7 +83,7 @@ static int s35390a_set_reg(struct s35390a *s35390a, int reg, char *buf, int len)
|
|||
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_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)
|
||||
{
|
||||
char buf[1];
|
||||
u8 buf[1];
|
||||
|
||||
if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf)) < 0)
|
||||
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 s35390a *s35390a = i2c_get_clientdata(client);
|
||||
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, "
|
||||
"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 s35390a *s35390a = i2c_get_clientdata(client);
|
||||
char buf[7], status;
|
||||
u8 buf[7], status;
|
||||
int i, err;
|
||||
|
||||
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 s35390a *s35390a = i2c_get_clientdata(client);
|
||||
char buf[3], sts = 0;
|
||||
u8 buf[3], sts = 0;
|
||||
int err, i;
|
||||
|
||||
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 s35390a *s35390a = i2c_get_clientdata(client);
|
||||
char buf[3], sts;
|
||||
u8 buf[3], sts;
|
||||
int i, err;
|
||||
|
||||
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 s35390a *s35390a = i2c_get_clientdata(client);
|
||||
char sts;
|
||||
u8 sts;
|
||||
int err;
|
||||
|
||||
switch (cmd) {
|
||||
|
|
@ -422,7 +422,7 @@ static int s35390a_probe(struct i2c_client *client)
|
|||
unsigned int i;
|
||||
struct s35390a *s35390a;
|
||||
struct rtc_device *rtc;
|
||||
char buf, status1;
|
||||
u8 buf, status1;
|
||||
struct device *dev = &client->dev;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
|
||||
|
|
|
|||
|
|
@ -40,8 +40,6 @@
|
|||
|
||||
#define RTC_DEF_DIVIDER (32768 - 1)
|
||||
#define RTC_DEF_TRIM 0
|
||||
#define RTC_FREQ 1024
|
||||
|
||||
|
||||
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->max_user_freq = RTC_FREQ;
|
||||
info->rtc->range_max = U32_MAX;
|
||||
|
||||
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);
|
||||
|
||||
rtc->rtc_dev->ops = &sh_rtc_ops;
|
||||
rtc->rtc_dev->max_user_freq = 256;
|
||||
|
||||
if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) {
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
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->range_max = U32_MAX;
|
||||
|
||||
info->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(info->clk))
|
||||
return PTR_ERR(info->clk);
|
||||
|
||||
ret = clk_prepare_enable(info->clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (dev_of_node(&pdev->dev)) {
|
||||
info->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(info->clk))
|
||||
return PTR_ERR(info->clk);
|
||||
}
|
||||
|
||||
/* set context info */
|
||||
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,
|
||||
IRQF_TRIGGER_HIGH, dev_name(&pdev->dev),
|
||||
&pdev->dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request interrupt: %d\n", ret);
|
||||
goto disable_clk;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret, "failed to request interrupt\n");
|
||||
|
||||
ret = devm_rtc_register_device(info->rtc);
|
||||
if (ret)
|
||||
goto disable_clk;
|
||||
return ret;
|
||||
|
||||
dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n");
|
||||
|
||||
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)
|
||||
{
|
||||
struct tegra_rtc_info *info = dev_get_drvdata(dev);
|
||||
|
|
@ -387,9 +377,8 @@ static int tegra_rtc_resume(struct device *dev)
|
|||
|
||||
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)
|
||||
{
|
||||
|
|
@ -399,12 +388,12 @@ static void tegra_rtc_shutdown(struct platform_device *pdev)
|
|||
|
||||
static struct platform_driver tegra_rtc_driver = {
|
||||
.probe = tegra_rtc_probe,
|
||||
.remove = tegra_rtc_remove,
|
||||
.shutdown = tegra_rtc_shutdown,
|
||||
.driver = {
|
||||
.name = "tegra_rtc",
|
||||
.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);
|
||||
|
|
|
|||
|
|
@ -324,7 +324,6 @@ struct ds1685_rtc_platform_data {
|
|||
#define RTC_SQW_2HZ 0x0f /* 0 1 1 1 1 */
|
||||
#define RTC_SQW_0HZ 0x00 /* 0 0 0 0 0 */
|
||||
#define RTC_SQW_32768HZ 32768 /* 1 - - - - */
|
||||
#define RTC_MAX_USER_FREQ 8192
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue