diff --git a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml index 983ea80eaec9..dc71fd57834e 100644 --- a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml +++ b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml @@ -133,6 +133,11 @@ properties: required: - compatible + trickle-voltage-millivolt: + $ref: /schemas/rtc/rtc.yaml#/properties/trickle-voltage-millivolt + minimum: 1300 + maximum: 5000 + required: - compatible - mboxes @@ -144,6 +149,7 @@ examples: firmware { compatible = "raspberrypi,bcm2835-firmware", "simple-mfd"; mboxes = <&mailbox>; + trickle-voltage-millivolt = <3300>; firmware_clocks: clocks { compatible = "raspberrypi,firmware-clocks"; diff --git a/Documentation/devicetree/bindings/rtc/abracon,abx80x.yaml b/Documentation/devicetree/bindings/rtc/abracon,abx80x.yaml index 355b0598411a..d105570bcd5a 100644 --- a/Documentation/devicetree/bindings/rtc/abracon,abx80x.yaml +++ b/Documentation/devicetree/bindings/rtc/abracon,abx80x.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/rtc/abracon,abx80x.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Abracon ABX80X I2C ultra low power RTC/Alarm chip +title: Abracon ABX80X (I2C) and ABX81X (SPI) ultra low power RTC/Alarm chips maintainers: - linux-rtc@vger.kernel.org @@ -21,10 +21,12 @@ properties: - abracon,ab0803 - abracon,ab0804 - abracon,ab0805 + - abracon,ab0815 - abracon,ab1801 - abracon,ab1803 - abracon,ab1804 - abracon,ab1805 + - abracon,ab1815 - microcrystal,rv1805 reg: @@ -61,6 +63,7 @@ required: - reg allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml# - $ref: rtc.yaml# - if: properties: @@ -73,6 +76,8 @@ allOf: - abracon,ab1804 - abracon,ab0805 - abracon,ab1805 + - abracon,ab0815 + - abracon,ab1815 then: properties: abracon,tc-diode: false @@ -96,3 +101,14 @@ examples: interrupts = <44 IRQ_TYPE_EDGE_FALLING>; }; }; + + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + rtc@0 { + compatible = "abracon,ab1815"; + reg = <0>; + }; + }; diff --git a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml index f2b91186ed37..ebe35f893f8c 100644 --- a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml +++ b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml @@ -19,6 +19,7 @@ properties: - enum: - allwinner,sun6i-a31-rtc - allwinner,sun8i-a23-rtc + - allwinner,sun8i-b288-rtc - allwinner,sun8i-h3-rtc - allwinner,sun8i-r40-rtc - allwinner,sun8i-v3-rtc @@ -82,6 +83,7 @@ allOf: contains: enum: - allwinner,sun8i-a23-rtc + - allwinner,sun8i-b288-rtc - allwinner,sun8i-r40-rtc - allwinner,sun8i-v3-rtc @@ -162,6 +164,7 @@ allOf: compatible: contains: enum: + - allwinner,sun8i-b288-rtc - allwinner,sun8i-r40-rtc - allwinner,sun50i-h616-rtc - allwinner,sun50i-r329-rtc diff --git a/Documentation/devicetree/bindings/rtc/renesas,rzn1-rtc.yaml b/Documentation/devicetree/bindings/rtc/renesas,rzn1-rtc.yaml index ea7b039a91e7..5a869e6c0ae7 100644 --- a/Documentation/devicetree/bindings/rtc/renesas,rzn1-rtc.yaml +++ b/Documentation/devicetree/bindings/rtc/renesas,rzn1-rtc.yaml @@ -14,14 +14,16 @@ properties: oneOf: - items: - enum: - - renesas,r9a06g032-rtc - - const: renesas,rzn1-rtc + - renesas,r9a06g032-rtc # RZ/N1D + - const: renesas,rzn1-rtc # RZ/N1 - - const: renesas,r9a09g077-rtc + - const: renesas,r9a09g077-rtc # RZ/T2H - items: - - const: renesas,r9a09g087-rtc - - const: renesas,r9a09g077-rtc + - const: renesas,r9a09g087-rtc # RZ/N2H + - const: renesas,r9a09g077-rtc # RZ/T2H + + - const: renesas,r8a78000-rtc # R-Car X5H reg: maxItems: 1 @@ -49,11 +51,12 @@ properties: power-domains: maxItems: 1 + resets: + maxItems: 1 + required: - compatible - reg - - interrupts - - interrupt-names - clocks - clock-names - power-domains @@ -66,6 +69,7 @@ allOf: compatible: contains: enum: + - renesas,r8a78000-rtc - renesas,r9a09g077-rtc - renesas,r9a09g087-rtc then: @@ -75,6 +79,24 @@ allOf: clock-names: minItems: 2 + - if: + properties: + compatible: + contains: + const: renesas,r8a78000-rtc + then: + properties: + interrupts: false + interrupt-names: false + required: + - resets + else: + properties: + resets: false + required: + - interrupts + - interrupt-names + unevaluatedProperties: false examples: @@ -91,5 +113,4 @@ examples: clocks = <&sysctrl R9A06G032_HCLK_RTC>; clock-names = "hclk"; power-domains = <&sysctrl>; - start-year = <2000>; }; diff --git a/Documentation/devicetree/bindings/rtc/ricoh,r2223x.yaml b/Documentation/devicetree/bindings/rtc/ricoh,r2223x.yaml new file mode 100644 index 000000000000..e64a1ee378e6 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/ricoh,r2223x.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/rtc/ricoh,r2223x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Ricoh R2223x Real-Time Clock + +maintainers: + - Heiko Schocher + +allOf: + - $ref: rtc.yaml# + +properties: + compatible: + const: ricoh,r2223x + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + "#clock-cells": + const: 0 + + ricoh,eco-mode: + type: boolean + description: + Put the RTC into eco mode, which lowers its current consumption while + running from the backup supply. Set this on boards where the RTC is + expected to keep time on a small backup cell. + + start-year: true + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + rtc@32 { + compatible = "ricoh,r2223x"; + reg = <0x32>; + interrupts = <6 IRQ_TYPE_EDGE_FALLING>; + #clock-cells = <0>; + ricoh,eco-mode; + }; + }; diff --git a/Documentation/devicetree/bindings/rtc/rtc.yaml b/Documentation/devicetree/bindings/rtc/rtc.yaml index efb66df82782..e46d50b1063e 100644 --- a/Documentation/devicetree/bindings/rtc/rtc.yaml +++ b/Documentation/devicetree/bindings/rtc/rtc.yaml @@ -51,6 +51,7 @@ properties: if trickle charger should be enabled. trickle-voltage-millivolt: + $ref: /schemas/types.yaml#/definitions/uint32 description: Selected voltage for trickle charger. Should be given if trickle charger should be enabled and the trickle voltage is different diff --git a/Documentation/devicetree/bindings/rtc/sii,s35390a.yaml b/Documentation/devicetree/bindings/rtc/sii,s35390a.yaml new file mode 100644 index 000000000000..f86572e9faff --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/sii,s35390a.yaml @@ -0,0 +1,118 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/rtc/sii,s35390a.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: S-35390A 2-wire real-time clock + +maintainers: + - Markus Probst + +description: + The S-35390A is a CMOS 2-wire real-time clock IC which operates with the + very low current consumption in the wide range of operation voltage. + +allOf: + - $ref: rtc.yaml# + +properties: + compatible: + const: sii,s35390a + + reg: + maxItems: 1 + + interrupts: + minItems: 1 + maxItems: 2 + description: Supports up to 2 interrupt lines via the INT1 and INT2 pins. + + interrupt-names: + minItems: 1 + maxItems: 2 + items: + enum: + - int1 + - int2 + + wakeup-parent: true + + wakeup-source: true + + "#clock-cells": + const: 1 + +patternProperties: + "^pins": + type: object + additionalProperties: false + + patternProperties: + "-pins$": + $ref: /schemas/pinctrl/pinmux-node.yaml# + additionalProperties: false + + properties: + pins: + minItems: 1 + items: + enum: + - int1 + - int2 + + function: + description: | + Pin function: + - ignore: Preserve the previous state. + - disable: Disable pin output. + - wakeup: Output wakes up the system. + - clock: Output clock pulse. + - pmin1: Minute periodical output with 50% duty. + - pmin2: Minute periodical output L for 7.81 ms. + Can only be used with pin int1. + enum: + - ignore + - disable + - wakeup + - clock + - pmin1 + - pmin2 + + required: + - pins + - function + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + rtc@30 { + compatible = "sii,s35390a"; + reg = <0x30>; + pinctrl-0 = <&rtc_pins_default>; + pinctrl-names = "default"; + + interrupt-names = "int1"; + interrupts = <23>; + + rtc_pins_default: pins { + int1-pins { + pins = "int1"; + function = "wakeup"; + }; + int2-pins { + pins = "int2"; + function = "disable"; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml b/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml index f4d0eed98a08..0bdf0ab4ff97 100644 --- a/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml +++ b/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml @@ -81,8 +81,6 @@ properties: - ricoh,rv5c386 # I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC - ricoh,rv5c387a - # 2-wire CMOS real-time clock - - sii,s35390a # ST SPEAr Real-time Clock - st,spear600-rtc # VIA/Wondermedia VT8500 Real-time Clock diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c index 0aa322e9a2e7..443459c8c90f 100644 --- a/drivers/firmware/raspberrypi.c +++ b/drivers/firmware/raspberrypi.c @@ -24,6 +24,7 @@ static struct platform_device *rpi_hwmon; static struct platform_device *rpi_clk; +static struct platform_device *rpi_rtc; struct rpi_firmware { struct mbox_client cl; @@ -231,6 +232,26 @@ static void rpi_register_clk_driver(struct device *dev) -1, NULL, 0); } +static void rpi_register_rtc_driver(struct device *dev) +{ + struct platform_device *pdev; + + /* + * Check if our model of Raspberry Pi board is from the 5th gen + * as the RTC is only present on that model. + */ + if (!of_machine_is_compatible("brcm,bcm2712")) + return; + + pdev = platform_device_register_data(dev, "raspberrypi-rtc", + -1, NULL, 0); + + if (IS_ERR(pdev)) + return; + + rpi_rtc = pdev; +} + unsigned int rpi_firmware_clk_get_max_rate(struct rpi_firmware *fw, unsigned int id) { struct rpi_firmware_clk_rate_request msg = @@ -305,6 +326,7 @@ static int rpi_firmware_probe(struct platform_device *pdev) rpi_firmware_print_firmware_revision(fw); rpi_register_hwmon_driver(dev, fw); rpi_register_clk_driver(dev); + rpi_register_rtc_driver(dev); return 0; } @@ -327,6 +349,8 @@ static void rpi_firmware_remove(struct platform_device *pdev) rpi_hwmon = NULL; platform_device_unregister(rpi_clk); rpi_clk = NULL; + platform_device_unregister(rpi_rtc); + rpi_rtc = NULL; rpi_firmware_put(fw); } diff --git a/drivers/platform/x86/amd/pmc/pmc.c b/drivers/platform/x86/amd/pmc/pmc.c index ef07b24bfeba..67731cd7c02b 100644 --- a/drivers/platform/x86/amd/pmc/pmc.c +++ b/drivers/platform/x86/amd/pmc/pmc.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -649,7 +650,6 @@ static int amd_pmc_wa_irq1(struct amd_pmc_dev *pdev) static int amd_pmc_verify_czn_rtc(struct amd_pmc_dev *pdev, u32 *arg) { - struct rtc_device *rtc_device; time64_t then, now, duration; struct rtc_wkalrm alarm; struct rtc_time tm; @@ -665,7 +665,8 @@ static int amd_pmc_verify_czn_rtc(struct amd_pmc_dev *pdev, u32 *arg) if (pdev->major < 64 || (pdev->major == 64 && pdev->minor < 53)) return 0; - rtc_device = rtc_class_open("rtc0"); + struct rtc_device *rtc_device __free(rtc_class_close) = + rtc_class_open("rtc0"); if (!rtc_device) return 0; rc = rtc_read_next_alarm(rtc_device, &alarm); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 05b9233b9418..73ec9230edfd 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -30,6 +30,27 @@ config RTC_HCTOSYS the value read from a specified RTC device. This is useful to avoid unnecessary fsck runs at boot time, and to network better. +config RTC_HCTOSYS_TIME32_LIMIT + bool "Reject RTC dates after the 2038 cutoff" + depends on RTC_HCTOSYS && COMPAT_32BIT_TIME && !64BIT + default y + help + Reject RTC dates after 03:14:07 UTC on 19 January 2038 when + initializing the system clock in order to work around broken + RTC implementations that produce nondeterministic timestamps + without a working backup battery. + + A rejected date leaves system time unchanged, normally near + the Unix epoch, and the RTC's hctosys sysfs attribute reads + 0. Userspace must supply the time if no other source has + initialized it. + + Say Y here if the kernel may have to run old time32 userspace on + hardware that can produce unpredictable RTC timestamps. If the + kernel is intended to only run time64 compatible userspace and + continue working past 2038, you must pick N here in order to + have a working RTC_HCTOSYS functionality. + config RTC_HCTOSYS_DEVICE string "RTC used to set the system time" depends on RTC_HCTOSYS @@ -212,17 +233,6 @@ config RTC_DRV_ABEOZ9 This driver can also be built as a module. If so, the module will be called rtc-ab-e0z9. -config RTC_DRV_ABX80X - tristate "Abracon ABx80x" - select WATCHDOG_CORE if WATCHDOG - help - If you say yes here you get support for Abracon AB080X and AB180X - families of ultra-low-power battery- and capacitor-backed real-time - clock chips. - - This driver can also be built as a module. If so, the module - will be called rtc-abx80x. - config RTC_DRV_AC100 tristate "X-Powers AC100" depends on MFD_AC100 @@ -668,7 +678,9 @@ config RTC_DRV_RC5T619 config RTC_DRV_S35390A tristate "Seiko Instruments S-35390A" + select PINCTRL select BITREVERSE + select GENERIC_PINCONF help If you say yes here you will get support for the Seiko Instruments S-35390A. @@ -954,6 +966,20 @@ config RTC_I2C_AND_SPI comment "SPI and I2C RTC drivers" +config RTC_DRV_ABX80X + tristate "Abracon ABx80x" + depends on RTC_I2C_AND_SPI + select WATCHDOG_CORE if WATCHDOG + select REGMAP_I2C if I2C + select REGMAP_SPI if SPI_MASTER + help + If you say yes here you get support for Abracon AB080X, AB180X, + AB081X and AB181X families of ultra-low-power battery- and + capacitor-backed real-time clock chips. + + This driver can also be built as a module. If so, the module + will be called rtc-abx80x. + config RTC_DRV_DS3232 tristate "Dallas/Maxim DS3232/DS3234" depends on RTC_I2C_AND_SPI @@ -1999,6 +2025,18 @@ config RTC_DRV_R7301 This driver can also be built as a module. If so, the module will be called rtc-r7301. +config RTC_DRV_RPI + tristate "Raspberry Pi RTC" + depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE) + depends on ARCH_BCM2835 || COMPILE_TEST + default ARCH_BCM2835 + help + If you say yes here you get support for the RTC found on + Raspberry Pi 5th gen devices. + + This driver can also be built as a module. If so, the module + will be called rtc-raspberrypi. + config RTC_DRV_STM32 tristate "STM32 RTC" select REGMAP_MMIO diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 0347645b021f..46f1a0fc2416 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -144,6 +144,7 @@ obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o obj-$(CONFIG_RTC_DRV_R7301) += rtc-r7301.o obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o +obj-$(CONFIG_RTC_DRV_RPI) += rtc-raspberrypi.o obj-$(CONFIG_RTC_DRV_RC5T583) += rtc-rc5t583.o obj-$(CONFIG_RTC_DRV_RC5T619) += rtc-rc5t619.o obj-$(CONFIG_RTC_DRV_RK808) += rtc-rk808.o diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 01ba04028f1f..18ea141ab8c2 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -72,12 +72,14 @@ static void rtc_hctosys(struct rtc_device *rtc) tv64.tv_sec = rtc_tm_to_time64(&tm); -#if BITS_PER_LONG == 32 - if (tv64.tv_sec > INT_MAX) { + if (IS_ENABLED(CONFIG_RTC_HCTOSYS_TIME32_LIMIT) && + tv64.tv_sec > INT_MAX) { + dev_warn(rtc->dev.parent, + "hctosys: rejecting %ptR UTC due to CONFIG_RTC_HCTOSYS_TIME32_LIMIT=y\n", + &tm); err = -ERANGE; goto err_read; } -#endif err = do_settimeofday64(&tv64); diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c index 5486d9d0b1e5..1c69d0e2f940 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* - * A driver for the I2C members of the Abracon AB x8xx RTC family, - * and compatible: AB 1805 and AB 0805 + * A driver for the I2C and SPI members of the Abracon AB x8xx RTC family, + * and compatible: AB 1805, AB 0805, AB 1815 and AB 0815 * * Copyright 2014-2015 Macq S.A. * @@ -16,7 +16,9 @@ #include #include #include +#include #include +#include #include #define ABX8XX_REG_HTH 0x00 @@ -50,12 +52,18 @@ #define ABX8XX_CTRL2_RSVD BIT(5) #define ABX8XX_REG_IRQ 0x12 +#define ABX8XX_IRQ_EX1E BIT(0) +#define ABX8XX_IRQ_EX2E BIT(1) #define ABX8XX_IRQ_AIE BIT(2) +#define ABX8XX_IRQ_TIE BIT(3) +#define ABX8XX_IRQ_BLIE BIT(4) #define ABX8XX_IRQ_IM_1_4 (0x3 << 5) #define ABX8XX_REG_CD_TIMER_CTL 0x18 #define ABX8XX_REG_OSC 0x1c +#define ABX8XX_OSC_ACIE BIT(0) +#define ABX8XX_OSC_OFIE BIT(1) #define ABX8XX_OSC_FOS BIT(3) #define ABX8XX_OSC_BOS BIT(4) #define ABX8XX_OSC_ACAL_512 BIT(5) @@ -101,8 +109,8 @@ static u8 trickle_resistors[] = {0, 3, 6, 11}; -enum abx80x_chip {AB0801, AB0803, AB0804, AB0805, - AB1801, AB1803, AB1804, AB1805, RV1805, ABX80X}; +enum abx80x_chip {AB0801, AB0803, AB0804, AB0805, AB0815, + AB1801, AB1803, AB1804, AB1805, AB1815, RV1805, ABX80X}; struct abx80x_cap { u16 pn; @@ -115,61 +123,66 @@ static struct abx80x_cap abx80x_caps[] = { [AB0803] = {.pn = 0x0803}, [AB0804] = {.pn = 0x0804, .has_tc = true, .has_wdog = true}, [AB0805] = {.pn = 0x0805, .has_tc = true, .has_wdog = true}, + [AB0815] = {.pn = 0x0815, .has_tc = true, .has_wdog = true}, [AB1801] = {.pn = 0x1801}, [AB1803] = {.pn = 0x1803}, [AB1804] = {.pn = 0x1804, .has_tc = true, .has_wdog = true}, [AB1805] = {.pn = 0x1805, .has_tc = true, .has_wdog = true}, + [AB1815] = {.pn = 0x1815, .has_tc = true, .has_wdog = true}, [RV1805] = {.pn = 0x1805, .has_tc = true, .has_wdog = true}, [ABX80X] = {.pn = 0} }; struct abx80x_priv { struct rtc_device *rtc; - struct i2c_client *client; + struct regmap *regmap; struct watchdog_device wdog; + int irq; }; -static int abx80x_write_config_key(struct i2c_client *client, u8 key) +static int abx80x_write_config_key(struct device *dev, u8 key) { - if (i2c_smbus_write_byte_data(client, ABX8XX_REG_CFG_KEY, key) < 0) { - dev_err(&client->dev, "Unable to write configuration key\n"); + struct abx80x_priv *priv = dev_get_drvdata(dev); + + if (regmap_write(priv->regmap, ABX8XX_REG_CFG_KEY, key) < 0) { + dev_err(dev, "Unable to write configuration key\n"); return -EIO; } return 0; } -static int abx80x_is_rc_mode(struct i2c_client *client) +static int abx80x_is_rc_mode(struct device *dev) { - int flags = 0; + struct abx80x_priv *priv = dev_get_drvdata(dev); + unsigned int flags = 0; + int err; - flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSS); - if (flags < 0) { - dev_err(&client->dev, - "Failed to read autocalibration attribute\n"); - return flags; + err = regmap_read(priv->regmap, ABX8XX_REG_OSS, &flags); + if (err < 0) { + dev_err(dev, "Failed to read autocalibration attribute\n"); + return err; } return (flags & ABX8XX_OSS_OMODE) ? 1 : 0; } -static int abx80x_enable_trickle_charger(struct i2c_client *client, - u8 trickle_cfg) +static int abx80x_enable_trickle_charger(struct device *dev, u8 trickle_cfg) { + struct abx80x_priv *priv = dev_get_drvdata(dev); int err; /* * Write the configuration key register to enable access to the Trickle * register */ - if (abx80x_write_config_key(client, ABX8XX_CFG_KEY_MISC) < 0) + if (abx80x_write_config_key(dev, ABX8XX_CFG_KEY_MISC) < 0) return -EIO; - err = i2c_smbus_write_byte_data(client, ABX8XX_REG_TRICKLE, - ABX8XX_TRICKLE_CHARGE_ENABLE | - trickle_cfg); + err = regmap_write(priv->regmap, ABX8XX_REG_TRICKLE, + ABX8XX_TRICKLE_CHARGE_ENABLE | trickle_cfg); if (err < 0) { - dev_err(&client->dev, "Unable to write trickle register\n"); + dev_err(dev, "Unable to write trickle register\n"); return -EIO; } @@ -178,19 +191,20 @@ static int abx80x_enable_trickle_charger(struct i2c_client *client, static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm) { - struct i2c_client *client = to_i2c_client(dev); + struct abx80x_priv *priv = dev_get_drvdata(dev); unsigned char buf[8]; - int err, flags, rc_mode = 0; + unsigned int flags; + int err, rc_mode = 0; /* Read the Oscillator Failure only in XT mode */ - rc_mode = abx80x_is_rc_mode(client); + rc_mode = abx80x_is_rc_mode(dev); if (rc_mode < 0) return rc_mode; if (!rc_mode) { - flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSS); - if (flags < 0) - return flags; + err = regmap_read(priv->regmap, ABX8XX_REG_OSS, &flags); + if (err < 0) + return err; if (flags & ABX8XX_OSS_OF) { dev_err(dev, "Oscillator failure, data is invalid.\n"); @@ -198,10 +212,9 @@ static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm) } } - err = i2c_smbus_read_i2c_block_data(client, ABX8XX_REG_HTH, - sizeof(buf), buf); + err = regmap_bulk_read(priv->regmap, ABX8XX_REG_HTH, buf, sizeof(buf)); if (err < 0) { - dev_err(&client->dev, "Unable to read date\n"); + dev_err(dev, "Unable to read date\n"); return -EIO; } @@ -218,9 +231,9 @@ static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm) static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm) { - struct i2c_client *client = to_i2c_client(dev); + struct abx80x_priv *priv = dev_get_drvdata(dev); unsigned char buf[8]; - int err, flags; + int err; if (tm->tm_year < 100) return -EINVAL; @@ -234,37 +247,33 @@ static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm) buf[ABX8XX_REG_YR] = bin2bcd(tm->tm_year - 100); buf[ABX8XX_REG_WD] = tm->tm_wday; - err = i2c_smbus_write_i2c_block_data(client, ABX8XX_REG_HTH, - sizeof(buf), buf); + err = regmap_bulk_write(priv->regmap, ABX8XX_REG_HTH, buf, + sizeof(buf)); if (err < 0) { - dev_err(&client->dev, "Unable to write to date registers\n"); + dev_err(dev, "Unable to write to date registers\n"); return -EIO; } /* Clear the OF bit of Oscillator Status Register */ - flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSS); - if (flags < 0) - return flags; + err = regmap_update_bits(priv->regmap, ABX8XX_REG_OSS, ABX8XX_OSS_OF, 0); + if (err < 0) + dev_err(dev, "Unable to write oscillator status register\n"); - err = i2c_smbus_write_byte_data(client, ABX8XX_REG_OSS, - flags & ~ABX8XX_OSS_OF); - if (err < 0) { - dev_err(&client->dev, "Unable to write oscillator status register\n"); - return err; - } - - return 0; + return err; } static irqreturn_t abx80x_handle_irq(int irq, void *dev_id) { - struct i2c_client *client = dev_id; - struct abx80x_priv *priv = i2c_get_clientdata(client); + struct device *dev = dev_id; + struct abx80x_priv *priv = dev_get_drvdata(dev); struct rtc_device *rtc = priv->rtc; - int status; + unsigned int status, status_flags_clear; + int err; - status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS); - if (status < 0) + guard(rtc_ops)(rtc); + + err = regmap_read(priv->regmap, ABX8XX_REG_STATUS, &status); + if (err < 0) return IRQ_NONE; if (status & ABX8XX_STATUS_AF) @@ -275,31 +284,37 @@ static irqreturn_t abx80x_handle_irq(int irq, void *dev_id) * reset kicks in. */ if (status & ABX8XX_STATUS_WDT) - dev_alert(&client->dev, "watchdog timeout interrupt.\n"); + dev_alert(dev, "watchdog timeout interrupt.\n"); - i2c_smbus_write_byte_data(client, ABX8XX_REG_STATUS, 0); + status_flags_clear = status & (ABX8XX_STATUS_AF | ABX8XX_STATUS_WDT); - return IRQ_HANDLED; + if (status_flags_clear) { + regmap_write(priv->regmap, ABX8XX_REG_STATUS, + status & ~status_flags_clear); + return IRQ_HANDLED; + } + + return IRQ_NONE; } static int abx80x_read_alarm(struct device *dev, struct rtc_wkalrm *t) { - struct i2c_client *client = to_i2c_client(dev); + struct abx80x_priv *priv = dev_get_drvdata(dev); unsigned char buf[7]; - int irq_mask, err; + unsigned int irq_mask; + int err; - if (client->irq <= 0) + if (priv->irq <= 0) return -EINVAL; - err = i2c_smbus_read_i2c_block_data(client, ABX8XX_REG_ASC, - sizeof(buf), buf); + err = regmap_bulk_read(priv->regmap, ABX8XX_REG_ASC, buf, sizeof(buf)); if (err) return err; - irq_mask = i2c_smbus_read_byte_data(client, ABX8XX_REG_IRQ); - if (irq_mask < 0) - return irq_mask; + err = regmap_read(priv->regmap, ABX8XX_REG_IRQ, &irq_mask); + if (err < 0) + return err; t->time.tm_sec = bcd2bin(buf[0] & 0x7F); t->time.tm_min = bcd2bin(buf[1] & 0x7F); @@ -311,16 +326,16 @@ static int abx80x_read_alarm(struct device *dev, struct rtc_wkalrm *t) t->enabled = !!(irq_mask & ABX8XX_IRQ_AIE); t->pending = (buf[6] & ABX8XX_STATUS_AF) && t->enabled; - return err; + return 0; } static int abx80x_set_alarm(struct device *dev, struct rtc_wkalrm *t) { - struct i2c_client *client = to_i2c_client(dev); + struct abx80x_priv *priv = dev_get_drvdata(dev); u8 alarm[6]; int err; - if (client->irq <= 0) + if (priv->irq <= 0) return -EINVAL; alarm[0] = 0x0; @@ -330,17 +345,16 @@ static int abx80x_set_alarm(struct device *dev, struct rtc_wkalrm *t) alarm[4] = bin2bcd(t->time.tm_mday); alarm[5] = bin2bcd(t->time.tm_mon + 1); - err = i2c_smbus_write_i2c_block_data(client, ABX8XX_REG_AHTH, - sizeof(alarm), alarm); + err = regmap_bulk_write(priv->regmap, ABX8XX_REG_AHTH, + alarm, sizeof(alarm)); if (err < 0) { - dev_err(&client->dev, "Unable to write alarm registers\n"); + dev_err(dev, "Unable to write alarm registers\n"); return -EIO; } if (t->enabled) { - err = i2c_smbus_write_byte_data(client, ABX8XX_REG_IRQ, - (ABX8XX_IRQ_IM_1_4 | - ABX8XX_IRQ_AIE)); + err = regmap_write(priv->regmap, ABX8XX_REG_IRQ, + ABX8XX_IRQ_IM_1_4 | ABX8XX_IRQ_AIE); if (err) return err; } @@ -351,8 +365,8 @@ static int abx80x_set_alarm(struct device *dev, struct rtc_wkalrm *t) static int abx80x_rtc_set_autocalibration(struct device *dev, int autocalibration) { - struct i2c_client *client = to_i2c_client(dev); - int retval, flags = 0; + struct abx80x_priv *priv = dev_get_drvdata(dev); + unsigned int flags = 0; if ((autocalibration != 0) && (autocalibration != 1024) && (autocalibration != 512)) { @@ -360,10 +374,6 @@ static int abx80x_rtc_set_autocalibration(struct device *dev, return -EINVAL; } - flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSC); - if (flags < 0) - return flags; - if (autocalibration == 0) { flags &= ~(ABX8XX_OSC_ACAL_512 | ABX8XX_OSC_ACAL_1024); } else if (autocalibration == 1024) { @@ -375,23 +385,26 @@ static int abx80x_rtc_set_autocalibration(struct device *dev, flags |= (ABX8XX_OSC_ACAL_1024 | ABX8XX_OSC_ACAL_512); } + guard(rtc_ops)(priv->rtc); + /* Unlock write access to Oscillator Control Register */ - if (abx80x_write_config_key(client, ABX8XX_CFG_KEY_OSC) < 0) + if (abx80x_write_config_key(dev, ABX8XX_CFG_KEY_OSC) < 0) return -EIO; - retval = i2c_smbus_write_byte_data(client, ABX8XX_REG_OSC, flags); - - return retval; + return regmap_write_bits(priv->regmap, ABX8XX_REG_OSC, + ABX8XX_OSC_ACAL_1024 | ABX8XX_OSC_ACAL_512, + flags); } static int abx80x_rtc_get_autocalibration(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - int flags = 0, autocalibration; + struct abx80x_priv *priv = dev_get_drvdata(dev); + unsigned int flags = 0; + int autocalibration, err; - flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSC); - if (flags < 0) - return flags; + err = regmap_read(priv->regmap, ABX8XX_REG_OSC, &flags); + if (err < 0) + return err; if (flags & ABX8XX_OSC_ACAL_512) autocalibration = 512; @@ -442,8 +455,8 @@ static ssize_t oscillator_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev->parent); - int retval, flags, rc_mode = 0; + struct abx80x_priv *priv = dev_get_drvdata(dev->parent); + int retval, rc_mode = 0; if (strncmp(buf, "rc", 2) == 0) { rc_mode = 1; @@ -454,24 +467,16 @@ static ssize_t oscillator_store(struct device *dev, return -EINVAL; } - flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSC); - if (flags < 0) - return flags; - - if (rc_mode == 0) - flags &= ~(ABX8XX_OSC_OSEL); - else - flags |= (ABX8XX_OSC_OSEL); + guard(rtc_ops)(priv->rtc); /* Unlock write access on Oscillator Control register */ - if (abx80x_write_config_key(client, ABX8XX_CFG_KEY_OSC) < 0) + if (abx80x_write_config_key(dev->parent, ABX8XX_CFG_KEY_OSC) < 0) return -EIO; - retval = i2c_smbus_write_byte_data(client, ABX8XX_REG_OSC, flags); - if (retval < 0) { + retval = regmap_write_bits(priv->regmap, ABX8XX_REG_OSC, ABX8XX_OSC_OSEL, + rc_mode == 0 ? 0 : (ABX8XX_OSC_OSEL)); + if (retval < 0) dev_err(dev, "Failed to write Oscillator Control register\n"); - return retval; - } return retval ? retval : count; } @@ -480,9 +485,8 @@ static ssize_t oscillator_show(struct device *dev, struct device_attribute *attr, char *buf) { int rc_mode = 0; - struct i2c_client *client = to_i2c_client(dev->parent); - rc_mode = abx80x_is_rc_mode(client); + rc_mode = abx80x_is_rc_mode(dev->parent); if (rc_mode < 0) { dev_err(dev, "Failed to read RTC oscillator selection\n"); @@ -510,47 +514,39 @@ static const struct attribute_group rtc_calib_attr_group = { static int abx80x_alarm_irq_enable(struct device *dev, unsigned int enabled) { - struct i2c_client *client = to_i2c_client(dev); + struct abx80x_priv *priv = dev_get_drvdata(dev); int err; if (enabled) - err = i2c_smbus_write_byte_data(client, ABX8XX_REG_IRQ, - (ABX8XX_IRQ_IM_1_4 | - ABX8XX_IRQ_AIE)); + err = regmap_write(priv->regmap, ABX8XX_REG_IRQ, + ABX8XX_IRQ_IM_1_4 | ABX8XX_IRQ_AIE); else - err = i2c_smbus_write_byte_data(client, ABX8XX_REG_IRQ, - ABX8XX_IRQ_IM_1_4); + err = regmap_write(priv->regmap, ABX8XX_REG_IRQ, + ABX8XX_IRQ_IM_1_4); return err; } static int abx80x_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { - struct i2c_client *client = to_i2c_client(dev); - int status, tmp; + struct abx80x_priv *priv = dev_get_drvdata(dev); + unsigned int status; + int err, tmp; switch (cmd) { case RTC_VL_READ: - status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS); - if (status < 0) - return status; + err = regmap_read(priv->regmap, ABX8XX_REG_STATUS, &status); + if (err < 0) + return err; tmp = status & ABX8XX_STATUS_BLF ? RTC_VL_BACKUP_LOW : 0; return put_user(tmp, (unsigned int __user *)arg); case RTC_VL_CLR: - status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS); - if (status < 0) - return status; + err = regmap_update_bits(priv->regmap, ABX8XX_REG_STATUS, + ABX8XX_STATUS_BLF, 0); - status &= ~ABX8XX_STATUS_BLF; - - tmp = i2c_smbus_write_byte_data(client, ABX8XX_REG_STATUS, - status); - if (tmp < 0) - return tmp; - - return 0; + return err; default: return -ENOIOCTLCMD; @@ -566,9 +562,9 @@ static const struct rtc_class_ops abx80x_rtc_ops = { .ioctl = abx80x_ioctl, }; -static int abx80x_dt_trickle_cfg(struct i2c_client *client) +static int abx80x_dt_trickle_cfg(struct device *dev) { - struct device_node *np = client->dev.of_node; + struct device_node *np = dev->of_node; const char *diode; int trickle_cfg = 0; int i, ret; @@ -583,7 +579,7 @@ static int abx80x_dt_trickle_cfg(struct i2c_client *client) } else if (!strcmp(diode, "schottky")) { trickle_cfg |= ABX8XX_TRICKLE_SCHOTTKY_DIODE; } else { - dev_dbg(&client->dev, "Invalid tc-diode value: %s\n", diode); + dev_dbg(dev, "Invalid tc-diode value: %s\n", diode); return -EINVAL; } @@ -596,7 +592,7 @@ static int abx80x_dt_trickle_cfg(struct i2c_client *client) break; if (i == sizeof(trickle_resistors)) { - dev_dbg(&client->dev, "Invalid tc-resistor value: %u\n", tmp); + dev_dbg(dev, "Invalid tc-resistor value: %u\n", tmp); return -EINVAL; } @@ -617,11 +613,13 @@ static int __abx80x_wdog_set_timeout(struct watchdog_device *wdog, struct abx80x_priv *priv = watchdog_get_drvdata(wdog); u8 val = ABX8XX_WDT_WDS | timeout_bits(timeout); + guard(rtc_ops)(priv->rtc); + /* * Writing any timeout to the WDT register resets the watchdog timer. * Writing 0 disables it. */ - return i2c_smbus_write_byte_data(priv->client, ABX8XX_REG_WDT, val); + return regmap_write(priv->regmap, ABX8XX_REG_WDT, val); } static int abx80x_wdog_set_timeout(struct watchdog_device *wdog, @@ -666,9 +664,11 @@ static const struct watchdog_ops abx80x_wdog_ops = { .set_timeout = abx80x_wdog_set_timeout, }; -static int abx80x_setup_watchdog(struct abx80x_priv *priv) +static int abx80x_setup_watchdog(struct device *dev) { - priv->wdog.parent = &priv->client->dev; + struct abx80x_priv *priv = dev_get_drvdata(dev); + + priv->wdog.parent = dev; priv->wdog.ops = &abx80x_wdog_ops; priv->wdog.info = &abx80x_wdog_info; priv->wdog.min_timeout = 1; @@ -677,10 +677,10 @@ static int abx80x_setup_watchdog(struct abx80x_priv *priv) watchdog_set_drvdata(&priv->wdog, priv); - return devm_watchdog_register_device(&priv->client->dev, &priv->wdog); + return devm_watchdog_register_device(dev, &priv->wdog); } #else -static int abx80x_setup_watchdog(struct abx80x_priv *priv) +static int abx80x_setup_watchdog(struct device *dev) { return 0; } @@ -692,31 +692,29 @@ static int abx80x_nvmem_xfer(struct abx80x_priv *priv, unsigned int offset, int ret; while (bytes) { - u8 extram, reg, len, lower, upper; + u8 reg, len, lower, upper; lower = FIELD_GET(NVMEM_ADDR_LOWER, offset); upper = FIELD_GET(NVMEM_ADDR_UPPER, offset); - extram = FIELD_PREP(ABX8XX_EXTRAM_XADS, upper); reg = ABX8XX_SRAM_BASE + lower; len = min(lower + bytes, (size_t)ABX8XX_SRAM_WIN_SIZE) - lower; len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX); - ret = i2c_smbus_write_byte_data(priv->client, ABX8XX_REG_EXTRAM, - extram); + guard(rtc_ops)(priv->rtc); + + ret = regmap_update_bits(priv->regmap, ABX8XX_REG_EXTRAM, + ABX8XX_EXTRAM_XADS, upper); if (ret) return ret; if (write) { - ret = i2c_smbus_write_i2c_block_data(priv->client, reg, - len, val); + ret = regmap_bulk_write(priv->regmap, reg, val, len); if (ret) return ret; } else { - ret = i2c_smbus_read_i2c_block_data(priv->client, reg, - len, val); - if (ret <= 0) - return ret ? ret : -EIO; - len = ret; + ret = regmap_bulk_read(priv->regmap, reg, val, len); + if (ret) + return ret; } offset += len; @@ -752,6 +750,210 @@ static int abx80x_setup_nvmem(struct abx80x_priv *priv) return devm_rtc_nvmem_register(priv->rtc, &config); } +static const struct regmap_range abx80x_no_read_ranges[] = { + regmap_reg_range(0x1e, 0x1e), + regmap_reg_range(0x22, 0x25), + regmap_reg_range(0x31, 0x3e), +}; + +static const struct regmap_range abx80x_no_write_ranges[] = { + regmap_reg_range(0x1e, 0x1e), + regmap_reg_range(0x22, 0x25), + regmap_reg_range(ABX8XX_REG_ID0, ABX8XX_REG_ID0 + 6), + regmap_reg_range(0x31, 0x3e), +}; + +static const struct regmap_access_table abx80x_read_table = { + .no_ranges = abx80x_no_read_ranges, + .n_no_ranges = ARRAY_SIZE(abx80x_no_read_ranges), +}; + +static const struct regmap_access_table abx80x_write_table = { + .no_ranges = abx80x_no_write_ranges, + .n_no_ranges = ARRAY_SIZE(abx80x_no_write_ranges), +}; + +static int abx80x_probe(struct device *dev, struct regmap *regmap, int irq, + struct device_node *np, unsigned int part) +{ + struct abx80x_priv *priv; + int i, err, trickle_cfg = -EINVAL; + char buf[7]; + unsigned int partnumber; + unsigned int majrev, minrev; + unsigned int lot; + unsigned int wafer; + unsigned int uid; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + + priv->rtc = devm_rtc_allocate_device(dev); + if (IS_ERR(priv->rtc)) + return PTR_ERR(priv->rtc); + + priv->rtc->ops = &abx80x_rtc_ops; + priv->irq = irq; + priv->regmap = regmap; + + dev_set_drvdata(dev, priv); + + err = regmap_bulk_read(regmap, ABX8XX_REG_ID0, buf, sizeof(buf)); + if (err < 0) { + dev_err(dev, "Unable to read partnumber\n"); + return -EIO; + } + + partnumber = (buf[0] << 8) | buf[1]; + majrev = buf[2] >> 3; + minrev = buf[2] & 0x7; + lot = ((buf[4] & 0x80) << 2) | ((buf[6] & 0x80) << 1) | buf[3]; + uid = ((buf[4] & 0x7f) << 8) | buf[5]; + wafer = (buf[6] & 0x7c) >> 2; + dev_info(dev, "model %04x, revision %u.%u, lot %x, wafer %x, uid %x\n", + partnumber, majrev, minrev, lot, wafer, uid); + + err = regmap_update_bits(regmap, ABX8XX_REG_CTRL1, + ABX8XX_CTRL_12_24 | ABX8XX_CTRL_ARST | ABX8XX_CTRL_WRITE, + ABX8XX_CTRL_WRITE); + if (err < 0) { + dev_err(dev, "Unable to write control register\n"); + return -EIO; + } + + /* Configure RV1805 specifics */ + if (part == RV1805) { + /* + * Avoid accidentally entering test mode. This can happen + * on the RV1805 in case the reserved bit 5 in control2 + * register is set. RV-1805-C3 datasheet indicates that + * the bit should be cleared in section 11h - Control2. + */ + err = regmap_update_bits(regmap, ABX8XX_REG_CTRL2, + ABX8XX_CTRL2_RSVD, 0); + if (err < 0) { + dev_err(dev, "Unable to write control2 register\n"); + return -EIO; + } + + /* + * Write the configuration key register to enable access to + * the config2 register + */ + if (abx80x_write_config_key(dev, ABX8XX_CFG_KEY_MISC) < 0) + return -EIO; + + /* + * Avoid extra power leakage. The RV1805 uses smaller + * 10pin package and the EXTI input is not present. + * Disable it to avoid leakage. + */ + err = regmap_write_bits(regmap, ABX8XX_REG_OUT_CTRL, + ABX8XX_OUT_CTRL_EXDS, + ABX8XX_OUT_CTRL_EXDS); + if (err < 0) { + dev_err(dev, + "Unable to write output control register\n"); + return -EIO; + } + } + + /* part autodetection */ + if (part == ABX80X) { + for (i = 0; abx80x_caps[i].pn; i++) + if (partnumber == abx80x_caps[i].pn) + break; + if (abx80x_caps[i].pn == 0) { + dev_err(dev, "Unknown part: %04x\n", partnumber); + return -EINVAL; + } + part = i; + } + + if (partnumber != abx80x_caps[part].pn) { + dev_err(dev, "partnumber mismatch %04x != %04x\n", + partnumber, abx80x_caps[part].pn); + return -EINVAL; + } + + if (np && abx80x_caps[part].has_tc) + trickle_cfg = abx80x_dt_trickle_cfg(dev); + + if (trickle_cfg > 0) { + dev_info(dev, "Enabling trickle charger: %02x\n", trickle_cfg); + abx80x_enable_trickle_charger(dev, trickle_cfg); + } + + err = regmap_write(regmap, ABX8XX_REG_CD_TIMER_CTL, BIT(2)); + if (err) + return err; + + /* Disable unused interrupts */ + err = regmap_update_bits(regmap, ABX8XX_REG_IRQ, + ABX8XX_IRQ_EX1E | ABX8XX_IRQ_EX2E | + ABX8XX_IRQ_TIE | ABX8XX_IRQ_BLIE, 0); + if (err < 0) { + dev_err(dev, "Unable to update irq register\n"); + return -EIO; + } + + /* Unlock write access to Oscillator Control Register */ + if (abx80x_write_config_key(dev, ABX8XX_CFG_KEY_OSC) < 0) + return -EIO; + + err = regmap_write_bits(regmap, ABX8XX_REG_OSC, + ABX8XX_OSC_ACIE | ABX8XX_OSC_OFIE, 0); + if (err < 0) { + dev_err(dev, "Unable to update Oscillator Control register\n"); + return -EIO; + } + + if (abx80x_caps[part].has_wdog) { + err = abx80x_setup_watchdog(dev); + if (err) + return err; + } + + err = abx80x_setup_nvmem(priv); + if (err) + return err; + + if (priv->irq > 0) { + dev_info(dev, "IRQ %d supplied\n", priv->irq); + err = devm_request_threaded_irq(dev, priv->irq, NULL, + abx80x_handle_irq, + IRQF_SHARED | IRQF_ONESHOT, + "abx8xx", + dev); + if (err) { + dev_err(dev, "unable to request IRQ, alarms disabled\n"); + priv->irq = 0; + } + } + if (priv->irq <= 0) + clear_bit(RTC_FEATURE_ALARM, priv->rtc->features); + + err = rtc_add_group(priv->rtc, &rtc_calib_attr_group); + if (err) { + dev_err(dev, "Failed to create sysfs group: %d\n", err); + return err; + } + + return devm_rtc_register_device(priv->rtc); +} + +#if IS_ENABLED(CONFIG_I2C) + +static const struct regmap_config abx80x_regmap_config_i2c = { + .reg_bits = 8, + .val_bits = 8, + .max_register = ABX8XX_SRAM_BASE + ABX8XX_SRAM_WIN_SIZE - 1, + + .rd_table = &abx80x_read_table, + .wr_table = &abx80x_write_table, +}; + static const struct i2c_device_id abx80x_id[] = { { .name = "abx80x", .driver_data = ABX80X }, { .name = "ab0801", .driver_data = AB0801 }, @@ -767,185 +969,6 @@ static const struct i2c_device_id abx80x_id[] = { }; MODULE_DEVICE_TABLE(i2c, abx80x_id); -static int abx80x_probe(struct i2c_client *client) -{ - struct device_node *np = client->dev.of_node; - struct abx80x_priv *priv; - int i, data, err, trickle_cfg = -EINVAL; - char buf[7]; - unsigned int part = (uintptr_t)i2c_get_match_data(client); - unsigned int partnumber; - unsigned int majrev, minrev; - unsigned int lot; - unsigned int wafer; - unsigned int uid; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) - return -ENODEV; - - err = i2c_smbus_read_i2c_block_data(client, ABX8XX_REG_ID0, - sizeof(buf), buf); - if (err < 0) { - dev_err(&client->dev, "Unable to read partnumber\n"); - return -EIO; - } - - partnumber = (buf[0] << 8) | buf[1]; - majrev = buf[2] >> 3; - minrev = buf[2] & 0x7; - lot = ((buf[4] & 0x80) << 2) | ((buf[6] & 0x80) << 1) | buf[3]; - uid = ((buf[4] & 0x7f) << 8) | buf[5]; - wafer = (buf[6] & 0x7c) >> 2; - dev_info(&client->dev, "model %04x, revision %u.%u, lot %x, wafer %x, uid %x\n", - partnumber, majrev, minrev, lot, wafer, uid); - - data = i2c_smbus_read_byte_data(client, ABX8XX_REG_CTRL1); - if (data < 0) { - dev_err(&client->dev, "Unable to read control register\n"); - return -EIO; - } - - err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CTRL1, - ((data & ~(ABX8XX_CTRL_12_24 | - ABX8XX_CTRL_ARST)) | - ABX8XX_CTRL_WRITE)); - if (err < 0) { - dev_err(&client->dev, "Unable to write control register\n"); - return -EIO; - } - - /* Configure RV1805 specifics */ - if (part == RV1805) { - /* - * Avoid accidentally entering test mode. This can happen - * on the RV1805 in case the reserved bit 5 in control2 - * register is set. RV-1805-C3 datasheet indicates that - * the bit should be cleared in section 11h - Control2. - */ - data = i2c_smbus_read_byte_data(client, ABX8XX_REG_CTRL2); - if (data < 0) { - dev_err(&client->dev, - "Unable to read control2 register\n"); - return -EIO; - } - - err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CTRL2, - data & ~ABX8XX_CTRL2_RSVD); - if (err < 0) { - dev_err(&client->dev, - "Unable to write control2 register\n"); - return -EIO; - } - - /* - * Avoid extra power leakage. The RV1805 uses smaller - * 10pin package and the EXTI input is not present. - * Disable it to avoid leakage. - */ - data = i2c_smbus_read_byte_data(client, ABX8XX_REG_OUT_CTRL); - if (data < 0) { - dev_err(&client->dev, - "Unable to read output control register\n"); - return -EIO; - } - - /* - * Write the configuration key register to enable access to - * the config2 register - */ - if (abx80x_write_config_key(client, ABX8XX_CFG_KEY_MISC) < 0) - return -EIO; - - err = i2c_smbus_write_byte_data(client, ABX8XX_REG_OUT_CTRL, - data | ABX8XX_OUT_CTRL_EXDS); - if (err < 0) { - dev_err(&client->dev, - "Unable to write output control register\n"); - return -EIO; - } - } - - /* part autodetection */ - if (part == ABX80X) { - for (i = 0; abx80x_caps[i].pn; i++) - if (partnumber == abx80x_caps[i].pn) - break; - if (abx80x_caps[i].pn == 0) { - dev_err(&client->dev, "Unknown part: %04x\n", - partnumber); - return -EINVAL; - } - part = i; - } - - if (partnumber != abx80x_caps[part].pn) { - dev_err(&client->dev, "partnumber mismatch %04x != %04x\n", - partnumber, abx80x_caps[part].pn); - return -EINVAL; - } - - if (np && abx80x_caps[part].has_tc) - trickle_cfg = abx80x_dt_trickle_cfg(client); - - if (trickle_cfg > 0) { - dev_info(&client->dev, "Enabling trickle charger: %02x\n", - trickle_cfg); - abx80x_enable_trickle_charger(client, trickle_cfg); - } - - err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CD_TIMER_CTL, - BIT(2)); - if (err) - return err; - - priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - - priv->rtc = devm_rtc_allocate_device(&client->dev); - if (IS_ERR(priv->rtc)) - return PTR_ERR(priv->rtc); - - priv->rtc->ops = &abx80x_rtc_ops; - priv->client = client; - - i2c_set_clientdata(client, priv); - - if (abx80x_caps[part].has_wdog) { - err = abx80x_setup_watchdog(priv); - if (err) - return err; - } - - err = abx80x_setup_nvmem(priv); - if (err) - return err; - - if (client->irq > 0) { - dev_info(&client->dev, "IRQ %d supplied\n", client->irq); - err = devm_request_threaded_irq(&client->dev, client->irq, NULL, - abx80x_handle_irq, - IRQF_SHARED | IRQF_ONESHOT, - "abx8xx", - client); - if (err) { - dev_err(&client->dev, "unable to request IRQ, alarms disabled\n"); - client->irq = 0; - } - } - if (client->irq <= 0) - clear_bit(RTC_FEATURE_ALARM, priv->rtc->features); - - err = rtc_add_group(priv->rtc, &rtc_calib_attr_group); - if (err) { - dev_err(&client->dev, "Failed to create sysfs group: %d\n", - err); - return err; - } - - return devm_rtc_register_device(priv->rtc); -} - #ifdef CONFIG_OF static const struct of_device_id abx80x_of_match[] = { { @@ -993,16 +1016,160 @@ static const struct of_device_id abx80x_of_match[] = { MODULE_DEVICE_TABLE(of, abx80x_of_match); #endif +static int abx80x_i2c_probe(struct i2c_client *client) +{ + unsigned int part = (uintptr_t)i2c_get_match_data(client); + struct regmap *regmap; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; + + regmap = devm_regmap_init_i2c(client, &abx80x_regmap_config_i2c); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "Unable to allocate regmap\n"); + return PTR_ERR(regmap); + } + + return abx80x_probe(&client->dev, regmap, client->irq, + client->dev.of_node, part); +} + static struct i2c_driver abx80x_driver = { .driver = { .name = "rtc-abx80x", .of_match_table = of_match_ptr(abx80x_of_match), }, - .probe = abx80x_probe, + .probe = abx80x_i2c_probe, .id_table = abx80x_id, }; -module_i2c_driver(abx80x_driver); +static int abx80x_register_driver(void) +{ + return i2c_add_driver(&abx80x_driver); +} + +static void abx80x_unregister_driver(void) +{ + i2c_del_driver(&abx80x_driver); +} + +#else + +static int abx80x_register_driver(void) +{ + return 0; +} + +static void abx80x_unregister_driver(void) +{ +} + +#endif /* IS_ENABLED(CONFIG_I2C) */ + +#if IS_ENABLED(CONFIG_SPI_MASTER) + +static const struct regmap_config abx80x_regmap_config_spi = { + .reg_bits = 8, + .val_bits = 8, + .max_register = ABX8XX_SRAM_BASE + ABX8XX_SRAM_WIN_SIZE - 1, + + .rd_table = &abx80x_read_table, + .wr_table = &abx80x_write_table, + + .write_flag_mask = BIT(7), +}; + +static const struct spi_device_id abx81x_id[] = { + { "ab0815", AB0815 }, + { "ab1815", AB1815 }, + { } +}; +MODULE_DEVICE_TABLE(spi, abx81x_id); + +#ifdef CONFIG_OF +static const struct of_device_id abx81x_of_match[] = { + { + .compatible = "abracon,ab0815", + .data = (void *)AB0815 + }, + { + .compatible = "abracon,ab1815", + .data = (void *)AB1815 + }, + { } +}; +MODULE_DEVICE_TABLE(of, abx81x_of_match); +#endif + +static int abx81x_spi_probe(struct spi_device *spi) +{ + unsigned int part = (uintptr_t)spi_get_device_match_data(spi); + struct regmap *regmap; + + regmap = devm_regmap_init_spi(spi, &abx80x_regmap_config_spi); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "Unable to allocate regmap\n"); + return PTR_ERR(regmap); + } + + return abx80x_probe(&spi->dev, regmap, spi->irq, + spi->dev.of_node, part); +} + +static struct spi_driver abx81x_driver = { + .driver = { + .name = "rtc-abx81x", + .of_match_table = of_match_ptr(abx81x_of_match), + }, + .probe = abx81x_spi_probe, + .id_table = abx81x_id, +}; + +static int abx81x_register_driver(void) +{ + return spi_register_driver(&abx81x_driver); +} + +static void abx81x_unregister_driver(void) +{ + spi_unregister_driver(&abx81x_driver); +} + +#else + +static int abx81x_register_driver(void) +{ + return 0; +} + +static void abx81x_unregister_driver(void) +{ +} + +#endif /* IS_ENABLED(CONFIG_SPI_MASTER) */ + +static int __init abx80x_init(void) +{ + int ret; + + ret = abx80x_register_driver(); + if (ret) + return ret; + + ret = abx81x_register_driver(); + if (ret) + abx80x_unregister_driver(); + + return ret; +} +module_init(abx80x_init); + +static void __exit abx80x_exit(void) +{ + abx81x_unregister_driver(); + abx80x_unregister_driver(); +} +module_exit(abx80x_exit); MODULE_AUTHOR("Philippe De Muyter "); MODULE_AUTHOR("Alexandre Belloni "); diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c index c579c4bf5578..c6fca15af241 100644 --- a/drivers/rtc/rtc-ac100.c +++ b/drivers/rtc/rtc-ac100.c @@ -516,12 +516,12 @@ static irqreturn_t ac100_rtc_irq(int irq, void *data) unsigned int val = 0; int ret; - rtc_lock(chip->rtc); + guard(rtc_ops)(chip->rtc); /* read status */ ret = regmap_read(regmap, AC100_ALM_INT_STA, &val); if (ret) - goto out; + return IRQ_HANDLED; if (val & AC100_ALM_INT_ENABLE) { /* signal rtc framework */ @@ -530,16 +530,14 @@ static irqreturn_t ac100_rtc_irq(int irq, void *data) /* clear status */ ret = regmap_write(regmap, AC100_ALM_INT_STA, val); if (ret) - goto out; + return IRQ_HANDLED; /* disable interrupt */ ret = ac100_rtc_alarm_irq_enable(chip->dev, 0); if (ret) - goto out; + return IRQ_HANDLED; } -out: - rtc_unlock(chip->rtc); return IRQ_HANDLED; } diff --git a/drivers/rtc/rtc-asm9260.c b/drivers/rtc/rtc-asm9260.c index 705470ae8428..422c2e5d83aa 100644 --- a/drivers/rtc/rtc-asm9260.c +++ b/drivers/rtc/rtc-asm9260.c @@ -116,15 +116,13 @@ static irqreturn_t asm9260_rtc_irq(int irq, void *dev_id) u32 isr; unsigned long events = 0; - rtc_lock(priv->rtc); + guard(rtc_ops)(priv->rtc); isr = ioread32(priv->iobase + HW_CIIR); if (!isr) { - rtc_unlock(priv->rtc); return IRQ_NONE; } iowrite32(0, priv->iobase + HW_CIIR); - rtc_unlock(priv->rtc); events |= RTC_AF | RTC_IRQF; diff --git a/drivers/rtc/rtc-atcrtc100.c b/drivers/rtc/rtc-atcrtc100.c index 9808fc2c5a49..2433df386c40 100644 --- a/drivers/rtc/rtc-atcrtc100.c +++ b/drivers/rtc/rtc-atcrtc100.c @@ -147,7 +147,7 @@ static void atcrtc_alarm_clear(struct work_struct *work) container_of(work, struct atcrtc_dev, rtc_work); int ret; - rtc_lock(rtc->rtc_dev); + guard(rtc_ops)(rtc->rtc_dev); if (!rtc->alarm_en) { ret = atcrtc_check_write_done(rtc); @@ -159,7 +159,6 @@ static void atcrtc_alarm_clear(struct work_struct *work) 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) diff --git a/drivers/rtc/rtc-bd70528.c b/drivers/rtc/rtc-bd70528.c index fd415e327ea6..dd5569d17567 100644 --- a/drivers/rtc/rtc-bd70528.c +++ b/drivers/rtc/rtc-bd70528.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -328,6 +329,10 @@ static int bd70528_probe(struct platform_device *pdev) device_set_wakeup_capable(&pdev->dev, true); device_wakeup_enable(&pdev->dev); + ret = devm_pm_set_wake_irq(&pdev->dev, irq); + if (ret) + return ret; + rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc)) { dev_err(&pdev->dev, "RTC device creation failed\n"); diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c index 573231613e52..0f50cfce88cb 100644 --- a/drivers/rtc/rtc-bq32k.c +++ b/drivers/rtc/rtc-bq32k.c @@ -210,7 +210,7 @@ static ssize_t bq32k_sysfs_show_tricklecharge_bypass(struct device *dev, if (error) return error; - return sprintf(buf, "%d\n", (reg & BQ32K_TCFE) ? 1 : 0); + return sysfs_emit(buf, "%d\n", (reg & BQ32K_TCFE) ? 1 : 0); } static ssize_t bq32k_sysfs_store_tricklecharge_bypass(struct device *dev, diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index fa04ece151b8..209aa4ec732c 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -57,7 +57,28 @@ */ static bool use_acpi_alarm; -module_param(use_acpi_alarm, bool, 0444); +static bool use_acpi_alarm_explicit; + +static int set_use_acpi_alarm(const char *val, const struct kernel_param *kp) +{ + int ret; + + ret = param_set_bool(val, kp); + if (!ret) + use_acpi_alarm_explicit = true; + + return ret; +} + +static const struct kernel_param_ops use_acpi_alarm_ops = { + .flags = KERNEL_PARAM_OPS_FL_NOARG, + .set = set_use_acpi_alarm, + .get = param_get_bool, +}; + +param_check_bool(use_acpi_alarm, &use_acpi_alarm); +module_param_cb(use_acpi_alarm, &use_acpi_alarm_ops, &use_acpi_alarm, 0444); +__MODULE_PARM_TYPE(use_acpi_alarm, "bool"); static inline int cmos_use_acpi_alarm(void) { @@ -758,7 +779,9 @@ static u32 rtc_handler(void *context) unsigned char rtc_intr; unsigned long flags; - + /* Quiesce this event before rtc->irqwork can arm the next one. */ + acpi_clear_event(ACPI_EVENT_RTC); + acpi_disable_event(ACPI_EVENT_RTC, 0); /* * Always update rtc irq when ACPI is used as RTC Alarm. * Or else, ACPI SCI is enabled during suspend/resume only, @@ -781,8 +804,6 @@ static u32 rtc_handler(void *context) } pm_wakeup_hard_event(dev); - acpi_clear_event(ACPI_EVENT_RTC); - acpi_disable_event(ACPI_EVENT_RTC, 0); return ACPI_INTERRUPT_HANDLED; } @@ -822,6 +843,9 @@ static void rtc_wake_off(struct device *dev) #ifdef CONFIG_X86 static void use_acpi_alarm_quirks(void) { + if (use_acpi_alarm_explicit) + return; + if (acpi_gbl_FADT.flags & ACPI_FADT_FIXED_RTC) return; diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index d4de401548b4..19a32d3476b5 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -440,7 +440,7 @@ static void ds1305_work(struct work_struct *work) int status; /* lock to protect ds1305->ctrl */ - rtc_lock(ds1305->rtc); + guard(rtc_ops)(ds1305->rtc); /* Disable the IRQ, and clear its status ... for now, we "know" * that if more than one alarm is active, they're in sync. @@ -458,8 +458,6 @@ static void ds1305_work(struct work_struct *work) if (status < 0) dev_dbg(&spi->dev, "clear irq --> %d\n", status); - rtc_unlock(ds1305->rtc); - if (!test_bit(FLAG_EXITING, &ds1305->flags)) enable_irq(spi->irq); diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 522f7eef3b4a..206a79d28568 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -579,28 +579,27 @@ static irqreturn_t rx8130_irq(int irq, void *dev_id) u8 ctl[3]; int ret; - rtc_lock(ds1307->rtc); + guard(rtc_ops)(ds1307->rtc); /* Read control registers. */ ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, sizeof(ctl)); if (ret < 0) - goto out; + return IRQ_HANDLED; + if (!(ctl[1] & RX8130_REG_FLAG_AF)) - goto out; + return IRQ_HANDLED; + ctl[1] &= ~RX8130_REG_FLAG_AF; ctl[2] &= ~RX8130_REG_CONTROL0_AIE; ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl, sizeof(ctl)); if (ret < 0) - goto out; + return IRQ_HANDLED; rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF); -out: - rtc_unlock(ds1307->rtc); - return IRQ_HANDLED; } @@ -1381,7 +1380,7 @@ static ssize_t ds3231_hwmon_show_temp(struct device *dev, if (ret) return ret; - return sprintf(buf, "%d\n", temp); + return sysfs_emit(buf, "%d\n", temp); } static SENSOR_DEVICE_ATTR(temp1_input, 0444, ds3231_hwmon_show_temp, NULL, 0); @@ -1891,7 +1890,6 @@ static int ds1307_probe(struct i2c_client *client) if (!ds1307) return -ENOMEM; - dev_set_drvdata(&client->dev, ds1307); ds1307->dev = &client->dev; ds1307->name = client->name; diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index 54f6af7886a8..0ec5eaba6bd4 100644 --- a/drivers/rtc/rtc-ds1343.c +++ b/drivers/rtc/rtc-ds1343.c @@ -94,9 +94,9 @@ static ssize_t ds1343_show_glitchfilter(struct device *dev, glitch_filt_status = !!(data & DS1343_EGFIL); if (glitch_filt_status) - return sprintf(buf, "enabled\n"); + return sysfs_emit(buf, "enabled\n"); else - return sprintf(buf, "disabled\n"); + return sysfs_emit(buf, "disabled\n"); } static ssize_t ds1343_store_glitchfilter(struct device *dev, @@ -180,7 +180,7 @@ static ssize_t ds1343_show_tricklecharger(struct device *dev, } } - return sprintf(buf, "%s %s\n", diodes, resistors); + return sysfs_emit(buf, "%s %s\n", diodes, resistors); } static DEVICE_ATTR(trickle_charger, 0444, ds1343_show_tricklecharger, NULL); @@ -312,11 +312,11 @@ static irqreturn_t ds1343_thread(int irq, void *dev_id) unsigned int stat; int res = 0; - rtc_lock(priv->rtc); + guard(rtc_ops)(priv->rtc); res = regmap_read(priv->map, DS1343_STATUS_REG, &stat); if (res) - goto out; + return IRQ_HANDLED; if (stat & DS1343_IRQF0) { stat &= ~DS1343_IRQF0; @@ -328,8 +328,6 @@ static irqreturn_t ds1343_thread(int irq, void *dev_id) DS1343_A0IE, 0); } -out: - rtc_unlock(priv->rtc); return IRQ_HANDLED; } diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 5fc8e36b1abf..3d0f491d0e88 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -666,7 +666,7 @@ ds1685_rtc_irq_handler(int irq, void *dev_id) if (unlikely(!rtc)) return IRQ_HANDLED; - rtc_lock(rtc->dev); + guard(rtc_ops)(rtc->dev); /* Ctrlb holds the interrupt-enable bits and ctrlc the flag bits. */ ctrlb = rtc->read(rtc, RTC_CTRL_B); @@ -711,7 +711,6 @@ ds1685_rtc_irq_handler(int irq, void *dev_id) } } rtc_update_irq(rtc->dev, num_irqs, events); - rtc_unlock(rtc->dev); return events ? IRQ_HANDLED : IRQ_NONE; } @@ -989,8 +988,8 @@ ds1685_rtc_sysfs_battery_show(struct device *dev, ctrld = rtc->read(rtc, RTC_CTRL_D); - return sprintf(buf, "%s\n", - (ctrld & RTC_CTRL_D_VRT) ? "ok" : "not ok or N/A"); + return sysfs_emit(buf, "%s\n", + (ctrld & RTC_CTRL_D_VRT) ? "ok" : "not ok or N/A"); } static DEVICE_ATTR(battery, S_IRUGO, ds1685_rtc_sysfs_battery_show, NULL); @@ -1011,8 +1010,8 @@ ds1685_rtc_sysfs_auxbatt_show(struct device *dev, ctrl4a = rtc->read(rtc, RTC_EXT_CTRL_4A); ds1685_rtc_switch_to_bank0(rtc); - return sprintf(buf, "%s\n", - (ctrl4a & RTC_CTRL_4A_VRT2) ? "ok" : "not ok or N/A"); + return sysfs_emit(buf, "%s\n", + (ctrl4a & RTC_CTRL_4A_VRT2) ? "ok" : "not ok or N/A"); } static DEVICE_ATTR(auxbatt, S_IRUGO, ds1685_rtc_sysfs_auxbatt_show, NULL); @@ -1033,7 +1032,7 @@ ds1685_rtc_sysfs_serial_show(struct device *dev, ds1685_rtc_get_ssn(rtc, ssn); ds1685_rtc_switch_to_bank0(rtc); - return sprintf(buf, "%8phC\n", ssn); + return sysfs_emit(buf, "%8phC\n", ssn); } static DEVICE_ATTR(serial, S_IRUGO, ds1685_rtc_sysfs_serial_show, NULL); @@ -1367,7 +1366,7 @@ module_platform_driver(ds1685_rtc_driver); void __noreturn ds1685_rtc_poweroff(struct platform_device *pdev) { - u8 ctrla, ctrl4a, ctrl4b; + u8 ctrla, ctrlb, ctrl4a, ctrl4b; struct ds1685_priv *rtc; /* Check for valid RTC data, else, spin forever. */ @@ -1394,6 +1393,8 @@ ds1685_rtc_poweroff(struct platform_device *pdev) ctrla &= ~(RTC_CTRL_A_DV2); rtc->write(rtc, RTC_CTRL_A, ctrla); + ctrlb = rtc->read(rtc, RTC_CTRL_B); + /* * Read Control 4A and check the status of the auxillary * battery. This must be present and working (VRT2 = 1) @@ -1408,25 +1409,35 @@ ds1685_rtc_poweroff(struct platform_device *pdev) /* * The auxillary battery is present and working. - * Enable extended functions (ABE=1), enable - * wake-up (WIE=1), and enable kickstart (KSE=1) - * in Control 4B. + * Enable extended functions (ABE=1) and kickstart + * (KSE=1) in Control 4B. Enable wake-up (WIE=1) only + * if an alarm is set, else stale alarm registers + * can power the system back on. */ ctrl4b = rtc->read(rtc, RTC_EXT_CTRL_4B); - ctrl4b |= (RTC_CTRL_4B_ABE | RTC_CTRL_4B_WIE | - RTC_CTRL_4B_KSE); + ctrl4b |= (RTC_CTRL_4B_ABE | RTC_CTRL_4B_KSE); + if (ctrlb & RTC_CTRL_B_AIE) + ctrl4b |= RTC_CTRL_4B_WIE; + else + ctrl4b &= ~(RTC_CTRL_4B_WIE); rtc->write(rtc, RTC_EXT_CTRL_4B, ctrl4b); } - /* Set PAB to 1 in Control 4A to power the system down. */ + /* + * Set PAB to 1 in Control 4A to power the system down. PAB + * is cleared again while KF and KSE, or WF and WIE, are set, + * so keep clearing the flags and setting PAB until power is + * gone. We do not switch back to bank0. + */ dev_warn(&pdev->dev, "Powerdown.\n"); - msleep(20); - rtc->write(rtc, RTC_EXT_CTRL_4A, - (ctrl4a | RTC_CTRL_4A_PAB)); - - /* Spin ... we do not switch back to bank0. */ - while(1); - unreachable(); + mdelay(20); + while (1) { + ctrl4a = rtc->read(rtc, RTC_EXT_CTRL_4A); + rtc->write(rtc, RTC_EXT_CTRL_4A, + (ctrl4a & ~RTC_CTRL_4A_RWK_MASK) | + RTC_CTRL_4A_PAB); + mdelay(100); + } } } EXPORT_SYMBOL_GPL(ds1685_rtc_poweroff); diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index d1ef9e0dad34..f6407c631d6d 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -389,45 +389,39 @@ static irqreturn_t ds3232_irq(int irq, void *dev_id) int ret; int stat, control; - rtc_lock(ds3232->rtc); + guard(rtc_ops)(ds3232->rtc); ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat); if (ret) - goto unlock; + return IRQ_HANDLED; if (stat & DS3232_REG_SR_A1F) { ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control); if (ret) { dev_warn(ds3232->dev, "Read Control Register error %d\n", ret); - } else { - /* disable alarm1 interrupt */ - control &= ~(DS3232_REG_CR_A1IE); - ret = regmap_write(ds3232->regmap, DS3232_REG_CR, - control); - if (ret) { - dev_warn(ds3232->dev, - "Write Control Register error %d\n", - ret); - goto unlock; - } - - /* clear the alarm pend flag */ - stat &= ~DS3232_REG_SR_A1F; - ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat); - if (ret) { - dev_warn(ds3232->dev, - "Write Status Register error %d\n", - ret); - goto unlock; - } - - rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF); + return IRQ_HANDLED; + } + /* disable alarm1 interrupt */ + control &= ~(DS3232_REG_CR_A1IE); + ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control); + if (ret) { + dev_warn(ds3232->dev, + "Write Control Register error %d\n", ret); + return IRQ_HANDLED; } - } -unlock: - rtc_unlock(ds3232->rtc); + /* clear the alarm pend flag */ + stat &= ~DS3232_REG_SR_A1F; + ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat); + if (ret) { + dev_warn(ds3232->dev, + "Write Status Register error %d\n", ret); + return IRQ_HANDLED; + } + + rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF); + } return IRQ_HANDLED; } diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index 507c9f22036c..f105aba28459 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c @@ -93,7 +93,7 @@ static ssize_t comp_preload_show(struct device *dev, ep93xx_rtc_get_swcomp(dev->parent, &preload, NULL); - return sprintf(buf, "%d\n", preload); + return sysfs_emit(buf, "%d\n", preload); } static DEVICE_ATTR_RO(comp_preload); @@ -104,7 +104,7 @@ static ssize_t comp_delete_show(struct device *dev, ep93xx_rtc_get_swcomp(dev->parent, NULL, &delete); - return sprintf(buf, "%d\n", delete); + return sysfs_emit(buf, "%d\n", delete); } static DEVICE_ATTR_RO(comp_delete); diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c index 98fa0f518303..c66d4a85f23c 100644 --- a/drivers/rtc/rtc-ftrtc010.c +++ b/drivers/rtc/rtc-ftrtc010.c @@ -72,7 +72,7 @@ static int ftrtc010_rtc_read_time(struct device *dev, struct rtc_time *tm) days = readl(rtc->rtc_base + FTRTC010_RTC_DAYS); offset = readl(rtc->rtc_base + FTRTC010_RTC_RECORD); - time = offset + days * 86400 + hour * 3600 + min * 60 + sec; + time = offset + (timeu64_t)days * 86400 + hour * 3600 + min * 60 + sec; rtc_time64_to_tm(time, tm); @@ -92,7 +92,7 @@ static int ftrtc010_rtc_set_time(struct device *dev, struct rtc_time *tm) hour = readl(rtc->rtc_base + FTRTC010_RTC_HOUR); day = readl(rtc->rtc_base + FTRTC010_RTC_DAYS); - offset = time - (day * 86400 + hour * 3600 + min * 60 + sec); + offset = time - ((timeu64_t)day * 86400 + hour * 3600 + min * 60 + sec); writel(offset, rtc->rtc_base + FTRTC010_RTC_RECORD); writel(0x01, rtc->rtc_base + FTRTC010_RTC_CR); @@ -119,51 +119,33 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev) return -ENOMEM; platform_set_drvdata(pdev, rtc); - rtc->pclk = devm_clk_get(dev, "PCLK"); - if (IS_ERR(rtc->pclk)) { + rtc->pclk = devm_clk_get_enabled(dev, "PCLK"); + if (IS_ERR_OR_NULL(rtc->pclk)) { dev_err(dev, "could not get PCLK\n"); - } else { - ret = clk_prepare_enable(rtc->pclk); - if (ret) { - dev_err(dev, "failed to enable PCLK\n"); - return ret; - } + return PTR_ERR_OR_ZERO(rtc->pclk); } - rtc->extclk = devm_clk_get(dev, "EXTCLK"); - if (IS_ERR(rtc->extclk)) { + rtc->extclk = devm_clk_get_enabled(dev, "EXTCLK"); + if (IS_ERR_OR_NULL(rtc->extclk)) { dev_err(dev, "could not get EXTCLK\n"); - } else { - ret = clk_prepare_enable(rtc->extclk); - if (ret) { - dev_err(dev, "failed to enable EXTCLK\n"); - goto err_disable_pclk; - } + return PTR_ERR_OR_ZERO(rtc->extclk); } rtc->rtc_irq = platform_get_irq(pdev, 0); - if (rtc->rtc_irq < 0) { - ret = rtc->rtc_irq; - goto err_disable_extclk; - } + if (rtc->rtc_irq < 0) + return rtc->rtc_irq; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENODEV; - goto err_disable_extclk; - } + if (!res) + return -ENODEV; rtc->rtc_base = devm_ioremap(dev, res->start, resource_size(res)); - if (!rtc->rtc_base) { - ret = -ENOMEM; - goto err_disable_extclk; - } + if (!rtc->rtc_base) + return -ENOMEM; rtc_dev = devm_rtc_allocate_device(dev); - if (IS_ERR(rtc_dev)) { - ret = PTR_ERR(rtc_dev); - goto err_disable_extclk; - } + if (IS_ERR(rtc_dev)) + return PTR_ERR(rtc_dev); rtc_dev->ops = &ftrtc010_rtc_ops; @@ -178,25 +160,13 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev) ret = devm_request_irq(dev, rtc->rtc_irq, ftrtc010_rtc_interrupt, IRQF_SHARED, pdev->name, dev); if (unlikely(ret)) - goto err_disable_extclk; + return ret; - return devm_rtc_register_device(rtc_dev); + ret = devm_rtc_register_device(rtc_dev); + if (ret) + return ret; -err_disable_extclk: - clk_disable_unprepare(rtc->extclk); -err_disable_pclk: - clk_disable_unprepare(rtc->pclk); - return ret; -} - -static void ftrtc010_rtc_remove(struct platform_device *pdev) -{ - struct ftrtc010_rtc *rtc = platform_get_drvdata(pdev); - - if (!IS_ERR(rtc->extclk)) - clk_disable_unprepare(rtc->extclk); - if (!IS_ERR(rtc->pclk)) - clk_disable_unprepare(rtc->pclk); + return 0; } static const struct of_device_id ftrtc010_rtc_dt_match[] = { @@ -212,7 +182,6 @@ static struct platform_driver ftrtc010_rtc_driver = { .of_match_table = ftrtc010_rtc_dt_match, }, .probe = ftrtc010_rtc_probe, - .remove = ftrtc010_rtc_remove, }; module_platform_driver_probe(ftrtc010_rtc_driver, ftrtc010_rtc_probe); diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c index 1d52cc3def02..e3d7ca477e75 100644 --- a/drivers/rtc/rtc-hym8563.c +++ b/drivers/rtc/rtc-hym8563.c @@ -417,7 +417,7 @@ static irqreturn_t hym8563_irq(int irq, void *dev_id) struct i2c_client *client = hym8563->client; int data, ret; - rtc_lock(hym8563->rtc); + guard(rtc_ops)(hym8563->rtc); /* Clear the alarm flag */ @@ -425,7 +425,7 @@ static irqreturn_t hym8563_irq(int irq, void *dev_id) if (data < 0) { dev_err(&client->dev, "%s: error reading i2c data %d\n", __func__, data); - goto out; + return IRQ_HANDLED; } data &= ~HYM8563_CTL2_AF; @@ -436,8 +436,6 @@ static irqreturn_t hym8563_irq(int irq, void *dev_id) __func__, ret); } -out: - rtc_unlock(hym8563->rtc); return IRQ_HANDLED; } diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index 9bdd5d121571..ee2eb8c475ea 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -615,8 +615,8 @@ static ssize_t timestamp0_show(struct device *dev, if (sr) return sr; - return sprintf(buf, "%llu\n", - (unsigned long long)rtc_tm_to_time64(&tm)); + return sysfs_emit(buf, "%llu\n", + (unsigned long long)rtc_tm_to_time64(&tm)); }; static DEVICE_ATTR_RW(timestamp0); @@ -709,7 +709,7 @@ isl1208_sysfs_show_atrim(struct device *dev, if (atr < 0) return atr; - return sprintf(buf, "%d.%.2d pF\n", atr >> 2, (atr & 0x3) * 25); + return sysfs_emit(buf, "%d.%.2d pF\n", atr >> 2, (atr & 0x3) * 25); } static DEVICE_ATTR(atrim, S_IRUGO, isl1208_sysfs_show_atrim, NULL); @@ -722,7 +722,7 @@ isl1208_sysfs_show_dtrim(struct device *dev, if (dtr < 0) return dtr; - return sprintf(buf, "%d ppm\n", dtr - 100); + return sysfs_emit(buf, "%d ppm\n", dtr - 100); } static DEVICE_ATTR(dtrim, S_IRUGO, isl1208_sysfs_show_dtrim, NULL); @@ -735,7 +735,7 @@ isl1208_sysfs_show_usr(struct device *dev, if (usr < 0) return usr; - return sprintf(buf, "0x%.4x\n", usr); + return sysfs_emit(buf, "0x%.4x\n", usr); } static ssize_t diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index ec86ca3f2c4c..1385cb43864b 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -162,19 +162,15 @@ static irqreturn_t m41t80_handle_irq(int irq, void *dev_id) unsigned long events = 0; int flags, flags_afe; - rtc_lock(m41t80->rtc); + guard(rtc_ops)(m41t80->rtc); flags_afe = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON); - if (flags_afe < 0) { - rtc_unlock(m41t80->rtc); + if (flags_afe < 0) return IRQ_NONE; - } flags = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS); - if (flags <= 0) { - rtc_unlock(m41t80->rtc); + if (flags <= 0) return IRQ_NONE; - } if (flags & M41T80_FLAGS_AF) { flags &= ~M41T80_FLAGS_AF; @@ -189,8 +185,6 @@ static irqreturn_t m41t80_handle_irq(int irq, void *dev_id) flags_afe); } - rtc_unlock(m41t80->rtc); - return IRQ_HANDLED; } diff --git a/drivers/rtc/rtc-mcp795.c b/drivers/rtc/rtc-mcp795.c index e12f0f806ec4..9b5b36b88122 100644 --- a/drivers/rtc/rtc-mcp795.c +++ b/drivers/rtc/rtc-mcp795.c @@ -352,7 +352,7 @@ static irqreturn_t mcp795_irq(int irq, void *data) struct rtc_device *rtc = spi_get_drvdata(spi); int ret; - rtc_lock(rtc); + guard(rtc_ops)(rtc); /* Disable alarm. * There is no need to clear ALM0IF (Alarm 0 Interrupt Flag) bit, @@ -364,7 +364,6 @@ static irqreturn_t mcp795_irq(int irq, void *data) "Failed to disable alarm in IRQ (ret=%d)\n", ret); rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF); - rtc_unlock(rtc); return IRQ_HANDLED; } diff --git a/drivers/rtc/rtc-mpfs.c b/drivers/rtc/rtc-mpfs.c index 60596b0ea9d8..6616ca1f02c7 100644 --- a/drivers/rtc/rtc-mpfs.c +++ b/drivers/rtc/rtc-mpfs.c @@ -131,8 +131,8 @@ static int mpfs_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) alrm->enabled = mode & MODE_WAKE_EN; - time = (u64)readl(rtcdev->base + ALARM_LOWER_REG) << 32; - time |= (readl(rtcdev->base + ALARM_UPPER_REG) & ALARM_UPPER_MASK); + time = readl(rtcdev->base + ALARM_LOWER_REG); + time |= ((u64)readl(rtcdev->base + ALARM_UPPER_REG) & ALARM_UPPER_MASK) << 32; rtc_time64_to_tm(time, &alrm->time); return 0; diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c index 3d857681f760..d6e156516aa6 100644 --- a/drivers/rtc/rtc-mt6397.c +++ b/drivers/rtc/rtc-mt6397.c @@ -4,6 +4,8 @@ * Author: Tianping.Fang */ +#include +#include #include #include #include @@ -243,10 +245,91 @@ static const struct rtc_class_ops mtk_rtc_ops = { .set_alarm = mtk_rtc_set_alarm, }; +/* + * The spare byte of each of these registers, in the order a board addresses + * them as RTC_NEW_SPARE0 to RTC_NEW_SPARE3. + */ +static const u32 mtk_rtc_spare_reg[] = { + RTC_AL_HOU, RTC_AL_DOM, RTC_AL_DOW, RTC_AL_MTH, +}; + +static int mtk_rtc_nvram_read(void *priv, unsigned int offset, void *val, + size_t bytes) +{ + struct mt6397_rtc *rtc = priv; + u8 *buf = val; + u32 data; + int ret = 0; + + if (offset >= ARRAY_SIZE(mtk_rtc_spare_reg) || + bytes > ARRAY_SIZE(mtk_rtc_spare_reg) - offset) + return -EINVAL; + + mutex_lock(&rtc->lock); + + while (bytes--) { + ret = regmap_read(rtc->regmap, + rtc->addr_base + mtk_rtc_spare_reg[offset++], + &data); + if (ret) + break; + + *buf++ = FIELD_GET(RTC_SPARE_MASK, data); + } + + mutex_unlock(&rtc->lock); + + return ret; +} + +static int mtk_rtc_nvram_write(void *priv, unsigned int offset, void *val, + size_t bytes) +{ + struct mt6397_rtc *rtc = priv; + u8 *buf = val; + int ret = 0; + + if (offset >= ARRAY_SIZE(mtk_rtc_spare_reg) || + bytes > ARRAY_SIZE(mtk_rtc_spare_reg) - offset) + return -EINVAL; + + mutex_lock(&rtc->lock); + + while (bytes--) { + ret = regmap_update_bits(rtc->regmap, + rtc->addr_base + mtk_rtc_spare_reg[offset++], + RTC_SPARE_MASK, + FIELD_PREP(RTC_SPARE_MASK, *buf++)); + if (ret) + goto out; + } + + /* + * None of it reaches the always-on domain until the write trigger, + * which commits every pending alarm register at once -- so this runs + * under the same lock the alarm paths take, rather than landing in + * the middle of one of them. + */ + ret = mtk_rtc_write_trigger(rtc); +out: + mutex_unlock(&rtc->lock); + + return ret; +} + static int mtk_rtc_probe(struct platform_device *pdev) { struct resource *res; struct mt6397_chip *mt6397_chip = dev_get_drvdata(pdev->dev.parent); + struct nvmem_config nvmem_cfg = { + .name = "mt6397_rtc_spare", + .word_size = 1, + .stride = 1, + .size = ARRAY_SIZE(mtk_rtc_spare_reg), + .type = NVMEM_TYPE_BATTERY_BACKED, + .reg_read = mtk_rtc_nvram_read, + .reg_write = mtk_rtc_nvram_write, + }; struct mt6397_rtc *rtc; int ret; @@ -293,7 +376,13 @@ static int mtk_rtc_probe(struct platform_device *pdev) rtc->rtc_dev->start_secs = mktime64(1968, 1, 2, 0, 0, 0); rtc->rtc_dev->set_start_time = true; - return devm_rtc_register_device(rtc->rtc_dev); + ret = devm_rtc_register_device(rtc->rtc_dev); + if (ret) + return ret; + + nvmem_cfg.priv = rtc; + + return devm_rtc_nvmem_register(rtc->rtc_dev, &nvmem_cfg); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/rtc/rtc-nct3018y.c b/drivers/rtc/rtc-nct3018y.c index 2f7ad57057a4..194ba077363a 100644 --- a/drivers/rtc/rtc-nct3018y.c +++ b/drivers/rtc/rtc-nct3018y.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,7 @@ #define NCT3018Y_REG_CTRL 0x0A /* timer control */ #define NCT3018Y_REG_ST 0x0B /* status */ #define NCT3018Y_REG_CLKO 0x0C /* clock out */ +#define NCT3018Y_REG_INTR_CTRL 0x12 /* intrusion control */ #define NCT3018Y_REG_PART 0x21 /* part info */ #define NCT3018Y_BIT_AF BIT(7) @@ -34,6 +36,7 @@ #define NCT3018Y_BIT_OFIE BIT(2) #define NCT3018Y_BIT_CIE BIT(1) #define NCT3018Y_BIT_TWO BIT(0) +#define NCT3018Y_BIT_INTRUSION BIT(1) /* in NCT3018Y_REG_INTR_CTRL */ #define NCT3018Y_REG_BAT_MASK 0x07 #define NCT3018Y_REG_CLKO_F_MASK 0x03 /* frequenc mask */ @@ -491,6 +494,95 @@ static const struct rtc_class_ops nct3018y_rtc_ops = { .ioctl = nct3018y_ioctl, }; +#if IS_REACHABLE(CONFIG_HWMON) + +static umode_t nct3018y_hwmon_is_visible(const void *data, + enum hwmon_sensor_types type, + u32 attr, int channel) +{ + if (type == hwmon_intrusion && attr == hwmon_intrusion_alarm) + return 0644; + + return 0; +} + +static int nct3018y_hwmon_read(struct device *dev, + enum hwmon_sensor_types type, u32 attr, + int channel, long *val) +{ + struct nct3018y *nct3018y = dev_get_drvdata(dev); + int flags; + + flags = i2c_smbus_read_byte_data(nct3018y->client, + NCT3018Y_REG_INTR_CTRL); + if (flags < 0) + return flags; + + *val = !!(flags & NCT3018Y_BIT_INTRUSION); + + return 0; +} + +static int nct3018y_hwmon_write(struct device *dev, + enum hwmon_sensor_types type, u32 attr, + int channel, long val) +{ + struct nct3018y *nct3018y = dev_get_drvdata(dev); + int flags; + + /* The alarm latches until it is cleared, and only clearing is a + * meaningful thing to ask for. + */ + if (val) + return -EINVAL; + + flags = i2c_smbus_read_byte_data(nct3018y->client, + NCT3018Y_REG_INTR_CTRL); + if (flags < 0) + return flags; + + return i2c_smbus_write_byte_data(nct3018y->client, + NCT3018Y_REG_INTR_CTRL, + flags & ~NCT3018Y_BIT_INTRUSION); +} + +static const struct hwmon_channel_info * const nct3018y_hwmon_info[] = { + HWMON_CHANNEL_INFO(intrusion, HWMON_INTRUSION_ALARM), + NULL +}; + +static const struct hwmon_ops nct3018y_hwmon_ops = { + .is_visible = nct3018y_hwmon_is_visible, + .read = nct3018y_hwmon_read, + .write = nct3018y_hwmon_write, +}; + +static const struct hwmon_chip_info nct3018y_hwmon_chip_info = { + .ops = &nct3018y_hwmon_ops, + .info = nct3018y_hwmon_info, +}; + +static void nct3018y_hwmon_register(struct nct3018y *nct3018y) +{ + struct device *dev; + + dev = devm_hwmon_device_register_with_info(&nct3018y->client->dev, + "nct3018y", nct3018y, + &nct3018y_hwmon_chip_info, + NULL); + if (IS_ERR(dev)) + dev_warn(&nct3018y->client->dev, + "unable to register hwmon device %ld\n", PTR_ERR(dev)); +} + +#else + +static void nct3018y_hwmon_register(struct nct3018y *nct3018y) +{ +} + +#endif /* IS_REACHABLE(CONFIG_HWMON) */ + static int nct3018y_probe(struct i2c_client *client) { struct nct3018y *nct3018y; @@ -568,6 +660,8 @@ static int nct3018y_probe(struct i2c_client *client) nct3018y_clkout_register_clk(nct3018y); #endif + nct3018y_hwmon_register(nct3018y); + return devm_rtc_register_device(nct3018y->rtc); } diff --git a/drivers/rtc/rtc-nct6694.c b/drivers/rtc/rtc-nct6694.c index 35401a0d9cf5..1cf9b672256a 100644 --- a/drivers/rtc/rtc-nct6694.c +++ b/drivers/rtc/rtc-nct6694.c @@ -210,20 +210,16 @@ static irqreturn_t nct6694_irq(int irq, void *dev_id) }; int ret; - rtc_lock(data->rtc); + guard(rtc_ops)(data->rtc); sts->irq_en = NCT6694_RTC_IRQ_EN; sts->irq_pend = NCT6694_RTC_IRQ_STS; ret = nct6694_write_msg(data->nct6694, &cmd_hd, sts); - if (ret) { - rtc_unlock(data->rtc); + if (ret) return IRQ_NONE; - } rtc_update_irq(data->rtc, 1, RTC_IRQF | RTC_AF); - rtc_unlock(data->rtc); - return IRQ_HANDLED; } diff --git a/drivers/rtc/rtc-nvidia-vrs10.c b/drivers/rtc/rtc-nvidia-vrs10.c index b15796698558..caac63f4e0fc 100644 --- a/drivers/rtc/rtc-nvidia-vrs10.c +++ b/drivers/rtc/rtc-nvidia-vrs10.c @@ -358,11 +358,8 @@ static irqreturn_t nvvrs_rtc_irq_handler(int irq, void *data) if (ret < 0) return IRQ_NONE; - if (ret & NVVRS_INT_SRC1_RTC_MASK) { - rtc_lock(info->rtc); + if (ret & NVVRS_INT_SRC1_RTC_MASK) rtc_update_irq(info->rtc, 1, RTC_IRQF | RTC_AF); - rtc_unlock(info->rtc); - } /* Clear all interrupts */ if (nvvrs_pseq_irq_clear(info) < 0) diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 0f90065e352c..18492165a19f 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -408,7 +408,7 @@ static struct omap_rtc *omap_rtc_power_off_rtc; * generates pmic_pwr_enable control, which can be used to control an external * PMIC. */ -int omap_rtc_power_off_program(struct device *dev) +int omap_rtc_power_off_program(void) { struct omap_rtc *rtc = omap_rtc_power_off_rtc; struct rtc_time tm; @@ -481,10 +481,9 @@ EXPORT_SYMBOL(omap_rtc_power_off_program); */ static void omap_rtc_power_off(void) { - struct rtc_device *rtc = omap_rtc_power_off_rtc->rtc; u32 val; - omap_rtc_power_off_program(rtc->dev.parent); + omap_rtc_power_off_program(); /* Set PMIC power enable and EXT_WAKEUP in case PB power on is used */ omap_rtc_power_off_rtc->type->unlock(omap_rtc_power_off_rtc); diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index e714661e61a9..22c626d57090 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -310,7 +310,8 @@ static irqreturn_t pcf2123_rtc_irq(int irq, void *dev) unsigned int val = 0; int ret = IRQ_NONE; - rtc_lock(pcf2123->rtc); + guard(rtc_ops)(pcf2123->rtc); + regmap_read(pcf2123->map, PCF2123_REG_CTRL2, &val); /* Alarm? */ @@ -323,8 +324,6 @@ static irqreturn_t pcf2123_rtc_irq(int irq, void *dev) rtc_update_irq(pcf2123->rtc, 1, RTC_IRQF | RTC_AF); } - rtc_unlock(pcf2123->rtc); - return ret; } diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index ff2023908f5a..49542cc53411 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -972,7 +972,7 @@ static ssize_t timestamp_show(struct device *dev, if (ret) return ret; } - return sprintf(buf, "%llu\n", (unsigned long long)ts); + return sysfs_emit(buf, "%llu\n", (unsigned long long)ts); } static ssize_t timestamp0_show(struct device *dev, diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index 8cb9ffc73f6d..32952e73f2f1 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -44,6 +44,7 @@ #define PCF85063_REG_CTRL2 0x01 #define PCF85063_CTRL2_AF BIT(6) #define PCF85063_CTRL2_AIE BIT(7) +#define PCF85063_CTRL2_TF BIT(3) #define PCF85063_REG_OFFSET 0x02 #define PCF85063_OFFSET_SIGN_BIT 6 /* 2's complement sign bit */ @@ -63,6 +64,14 @@ #define PCF85063_REG_ALM_S 0x0b #define PCF85063_AEN BIT(7) +#define PCF85063_REG_TIMER_VALUE 0x10 +#define PCF85063_REG_TIMER_MODE 0x11 +#define PCF85063_TIMER_MODE_TI_TP BIT(0) +#define PCF85063_TIMER_MODE_TIE BIT(1) +#define PCF85063_TIMER_MODE_TE BIT(2) +#define PCF85063_TIMER_MODE_TCF_MASK GENMASK(4, 3) +#define PCF85063_TIMER_MODE_TCF_1HZ (2 << 3) + struct pcf85063_config { struct regmap_config regmap; unsigned has_alarms:1; @@ -188,20 +197,75 @@ static int pcf85063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) return 0; } +/* + * The chip has no dedicated 1 Hz update interrupt. Drive the countdown timer + * at 1 Hz to emulate it, so the RTC core can offload UIE to the hardware + * instead of polling. A free-running timer is left untouched to preserve its + * phase across the per-second re-arming done by the core. + */ +static int pcf85063_set_timer_1hz(struct pcf85063 *pcf85063, bool enable) +{ + unsigned int mask = PCF85063_TIMER_MODE_TCF_MASK | + PCF85063_TIMER_MODE_TIE | + PCF85063_TIMER_MODE_TI_TP | + PCF85063_TIMER_MODE_TE; + unsigned int mode = 0; + unsigned int cur; + int ret; + + if (enable) + mode = PCF85063_TIMER_MODE_TCF_1HZ | PCF85063_TIMER_MODE_TIE | + PCF85063_TIMER_MODE_TI_TP | PCF85063_TIMER_MODE_TE; + + ret = regmap_read(pcf85063->regmap, PCF85063_REG_TIMER_MODE, &cur); + if (ret) + return ret; + + if ((cur & mask) == mode) + return 0; + + /* Stop the counter before changing its reload value. */ + ret = regmap_update_bits(pcf85063->regmap, PCF85063_REG_TIMER_MODE, + PCF85063_TIMER_MODE_TE, 0); + if (ret) + return ret; + + if (enable) { + ret = regmap_write(pcf85063->regmap, PCF85063_REG_TIMER_VALUE, 1); + if (ret) + return ret; + + /* Clear TF but preserve AF */ + ret = regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, + PCF85063_CTRL2_TF | PCF85063_CTRL2_AF, PCF85063_CTRL2_AF); + if (ret) + return ret; + } + + return regmap_update_bits(pcf85063->regmap, PCF85063_REG_TIMER_MODE, + mask, mode); +} + static int pcf85063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct pcf85063 *pcf85063 = dev_get_drvdata(dev); u8 buf[5]; int ret; + ret = pcf85063_set_timer_1hz(pcf85063, pcf85063->rtc->uie_rtctimer.enabled); + if (ret) + return ret; + buf[0] = bin2bcd(alrm->time.tm_sec); buf[1] = bin2bcd(alrm->time.tm_min); buf[2] = bin2bcd(alrm->time.tm_hour); buf[3] = bin2bcd(alrm->time.tm_mday); buf[4] = PCF85063_AEN; /* Do not match on week day */ + /* Preserve TF */ ret = regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, - PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF, 0); + PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF | PCF85063_CTRL2_TF, + PCF85063_CTRL2_TF); if (ret) return ret; @@ -211,23 +275,33 @@ static int pcf85063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) return ret; return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, - PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF, - alrm->enabled ? PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF : PCF85063_CTRL2_AF); + PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF | PCF85063_CTRL2_TF, + pcf85063->rtc->aie_timer.enabled ? + PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF | PCF85063_CTRL2_TF : + PCF85063_CTRL2_AF | PCF85063_CTRL2_TF); } static int pcf85063_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct pcf85063 *pcf85063 = dev_get_drvdata(dev); + int ret; + + ret = pcf85063_set_timer_1hz(pcf85063, pcf85063->rtc->uie_rtctimer.enabled); + if (ret) + return ret; return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, - PCF85063_CTRL2_AIE, - enabled ? PCF85063_CTRL2_AIE : 0); + PCF85063_CTRL2_AIE | PCF85063_CTRL2_TF, + pcf85063->rtc->aie_timer.enabled ? + PCF85063_CTRL2_AIE | PCF85063_CTRL2_TF : PCF85063_CTRL2_TF); } static irqreturn_t pcf85063_rtc_handle_irq(int irq, void *dev_id) { struct pcf85063 *pcf85063 = dev_id; + unsigned long events = RTC_IRQF; + irqreturn_t ret = IRQ_NONE; unsigned int val; int err; @@ -236,14 +310,33 @@ static irqreturn_t pcf85063_rtc_handle_irq(int irq, void *dev_id) return IRQ_NONE; if (val & PCF85063_CTRL2_AF) { - rtc_update_irq(pcf85063->rtc, 1, RTC_IRQF | RTC_AF); - regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, - PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF, - 0); - return IRQ_HANDLED; + events |= RTC_AF; + val &= ~PCF85063_CTRL2_AF; + ret = IRQ_HANDLED; + } else { + /* Preserve AF if it comes after the above regmap_read() */ + val |= PCF85063_CTRL2_AF; } - return IRQ_NONE; + if (val & PCF85063_CTRL2_TF) { + events |= RTC_UF; + val &= ~PCF85063_CTRL2_TF; + ret = IRQ_HANDLED; + } else { + /* + * While not documented, TF demonstrates the same + * write-1-to-preserve semantics as AF in real HW + */ + val |= PCF85063_CTRL2_TF; + } + + if (ret == IRQ_HANDLED) { + regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, + PCF85063_CTRL2_AF | PCF85063_CTRL2_TF, val); + rtc_update_irq(pcf85063->rtc, 1, events); + } + + return ret; } static int pcf85063_read_offset(struct device *dev, long *offset) @@ -432,7 +525,8 @@ static int pcf85063_clkout_set_rate(struct clk_hw *hw, unsigned long rate, if (clkout_rates[i] == rate) return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, - PCF85063_REG_CLKO_F_MASK, i); + PCF85063_REG_CLKO_F_MASK | PCF85063_CTRL2_AF | PCF85063_CTRL2_TF, + i | PCF85063_CTRL2_AF | PCF85063_CTRL2_TF); return -EINVAL; } @@ -461,7 +555,8 @@ static int pcf85063_clkout_control(struct clk_hw *hw, bool enable) } return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2, - PCF85063_REG_CLKO_F_MASK, buf); + PCF85063_REG_CLKO_F_MASK | PCF85063_CTRL2_AF | PCF85063_CTRL2_TF, + buf | PCF85063_CTRL2_AF | PCF85063_CTRL2_TF); } static int pcf85063_clkout_prepare(struct clk_hw *hw) @@ -495,12 +590,13 @@ static const struct clk_ops pcf85063_clkout_ops = { .set_rate = pcf85063_clkout_set_rate, }; -static struct clk *pcf85063_clkout_register_clk(struct pcf85063 *pcf85063) +static int pcf85063_clkout_register_clk(struct pcf85063 *pcf85063) { - struct clk *clk; + struct device *dev = pcf85063->rtc->dev.parent; struct clk_init_data init = {}; - struct device_node *node = pcf85063->rtc->dev.parent->of_node; + struct device_node *node = dev->of_node; struct device_node *fixed_clock; + int ret; fixed_clock = of_get_child_by_name(node, "clock"); if (fixed_clock) { @@ -510,7 +606,7 @@ static struct clk *pcf85063_clkout_register_clk(struct pcf85063 *pcf85063) * registered automatically when being referenced. */ of_node_put(fixed_clock); - return NULL; + return 0; } init.name = "pcf85063-clkout"; @@ -524,12 +620,12 @@ static struct clk *pcf85063_clkout_register_clk(struct pcf85063 *pcf85063) of_property_read_string(node, "clock-output-names", &init.name); /* register the clock */ - clk = devm_clk_register(&pcf85063->rtc->dev, &pcf85063->clkout_hw); + ret = devm_clk_hw_register(dev, &pcf85063->clkout_hw); + if (ret) + return ret; - if (!IS_ERR(clk)) - of_clk_add_provider(node, of_clk_src_simple_get, clk); - - return clk; + return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, + &pcf85063->clkout_hw); } #endif @@ -607,6 +703,7 @@ static int pcf85063_probe(struct device *dev, struct regmap *regmap, int irq, dev_warn(&pcf85063->rtc->dev, "unable to request IRQ, alarms disabled\n"); } else { + set_bit(RTC_FEATURE_UPDATE_INTERRUPT, pcf85063->rtc->features); set_bit(RTC_FEATURE_ALARM, pcf85063->rtc->features); device_init_wakeup(dev, true); err = dev_pm_set_wake_irq(dev, irq); diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 7eebdb058067..3801acc9ac8d 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -479,7 +479,8 @@ static int pcf8563_probe(struct i2c_client *client) dev_dbg(&client->dev, "%s\n", __func__); - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C) && + !i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) return -ENODEV; pcf8563 = devm_kzalloc(&client->dev, sizeof(struct pcf8563), @@ -531,7 +532,7 @@ static int pcf8563_probe(struct i2c_client *client) err = devm_request_threaded_irq(&client->dev, client->irq, NULL, pcf8563_irq, IRQF_SHARED | IRQF_ONESHOT | irqflags, - pcf8563_driver.driver.name, client); + pcf8563_driver.driver.name, pcf8563); if (err) { dev_err(&client->dev, "unable to request IRQ %d\n", client->irq); diff --git a/drivers/rtc/rtc-raspberrypi.c b/drivers/rtc/rtc-raspberrypi.c new file mode 100644 index 000000000000..0547a96c62ac --- /dev/null +++ b/drivers/rtc/rtc-raspberrypi.c @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/** + * rtc-raspberrypi.c + * + * RTC driver using firmware mailbox + * Supports battery backed RTC and wake alarms + * + * Based on rtc-meson-vrtc by Neil Armstrong + * + * Copyright (c) 2023, Raspberry Pi Ltd. + */ + +#include +#include +#include +#include +#include + +#define RTC_TIME 0 +#define RTC_ALARM 1 +#define RTC_ALARM_PENDING 2 +#define RTC_ALARM_ENABLE 3 +#define RTC_BBAT_CHG_VOLTS 4 +#define RTC_BBAT_CHG_VOLTS_MIN 5 +#define RTC_BBAT_CHG_VOLTS_MAX 6 +#define RTC_BBAT_VOLTS 7 + +struct rpi_rtc_data { + struct rtc_device *rtc; + struct rpi_firmware *fw; + u32 bbat_vchg_millivolts; + u32 bbat_vchg_min_millivolts; + u32 bbat_vchg_max_millivolts; +}; + +struct rpi_rtc_reg { + __le32 reg; + __le32 val; +} __packed; + +static int rpi_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct rpi_rtc_data *rtc = dev_get_drvdata(dev); + struct rpi_rtc_reg data = { + .reg = cpu_to_le32(RTC_TIME) + }; + int err; + + err = rpi_firmware_property(rtc->fw, RPI_FIRMWARE_GET_RTC_REG, + &data, sizeof(data)); + rtc_time64_to_tm(le32_to_cpu(data.val), tm); + return err; +} + +static int rpi_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct rpi_rtc_data *rtc = dev_get_drvdata(dev); + struct rpi_rtc_reg data = { + .reg = cpu_to_le32(RTC_TIME), + .val = cpu_to_le32(rtc_tm_to_time64(tm)) + }; + + return rpi_firmware_property(rtc->fw, RPI_FIRMWARE_SET_RTC_REG, + &data, sizeof(data)); +} + +static int rpi_rtc_alarm_irq_is_enabled(struct device *dev, unsigned char *enabled) +{ + struct rpi_rtc_data *rtc = dev_get_drvdata(dev); + struct rpi_rtc_reg data = { + .reg = cpu_to_le32(RTC_ALARM_ENABLE) + }; + int err; + + err = rpi_firmware_property(rtc->fw, RPI_FIRMWARE_GET_RTC_REG, + &data, sizeof(data)); + *enabled = le32_to_cpu(data.val) & 0x1; + return err; +} + +static int rpi_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct rpi_rtc_data *rtc = dev_get_drvdata(dev); + struct rpi_rtc_reg data = { + .reg = cpu_to_le32(RTC_ALARM_ENABLE), + .val = cpu_to_le32(enabled) + }; + + return rpi_firmware_property(rtc->fw, RPI_FIRMWARE_SET_RTC_REG, + &data, sizeof(data)); +} + +static int rpi_rtc_alarm_clear_pending(struct device *dev) +{ + struct rpi_rtc_data *rtc = dev_get_drvdata(dev); + struct rpi_rtc_reg data = { + .reg = cpu_to_le32(RTC_ALARM_PENDING), + .val = cpu_to_le32(1) + }; + + return rpi_firmware_property(rtc->fw, RPI_FIRMWARE_SET_RTC_REG, + &data, sizeof(data)); +} + +static int rpi_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct rpi_rtc_data *rtc = dev_get_drvdata(dev); + struct rpi_rtc_reg data = { + .reg = cpu_to_le32(RTC_ALARM) + }; + int err; + + err = rpi_rtc_alarm_irq_is_enabled(dev, &alarm->enabled); + if (!err) + err = rpi_firmware_property(rtc->fw, RPI_FIRMWARE_GET_RTC_REG, + &data, sizeof(data)); + rtc_time64_to_tm(le32_to_cpu(data.val), &alarm->time); + + return err; +} + +static int rpi_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct rpi_rtc_data *rtc = dev_get_drvdata(dev); + struct rpi_rtc_reg data = { + .reg = cpu_to_le32(RTC_ALARM), + .val = cpu_to_le32(rtc_tm_to_time64(&alarm->time)) + }; + int err; + + err = rpi_rtc_alarm_clear_pending(dev); + + if (!err) + err = rpi_firmware_property(rtc->fw, RPI_FIRMWARE_SET_RTC_REG, + &data, sizeof(data)); + + if (!err) + err = rpi_rtc_alarm_irq_enable(dev, alarm->enabled); + + return err; +} + +static const struct rtc_class_ops rpi_rtc_ops = { + .read_time = rpi_rtc_read_time, + .set_time = rpi_rtc_set_time, + .read_alarm = rpi_rtc_read_alarm, + .set_alarm = rpi_rtc_set_alarm, + .alarm_irq_enable = rpi_rtc_alarm_irq_enable, +}; + +static void rpi_rtc_set_limits(struct device *dev) +{ + struct rpi_rtc_data *rtc = dev_get_drvdata(dev); + struct rpi_rtc_reg data = { + .reg = cpu_to_le32(RTC_BBAT_CHG_VOLTS_MIN) + }; + + int err = rpi_firmware_property(rtc->fw, RPI_FIRMWARE_GET_RTC_REG, + &data, sizeof(data)); + if (!err) + rtc->bbat_vchg_min_millivolts = le32_to_cpu(data.val) / 1000U; + else + dev_warn(dev, "failed to get minimum trickle charge voltage\n"); + + data.reg = cpu_to_le32(RTC_BBAT_CHG_VOLTS_MAX); + data.val = cpu_to_le32(0); + err = rpi_firmware_property(rtc->fw, RPI_FIRMWARE_GET_RTC_REG, + &data, sizeof(data)); + if (!err) + rtc->bbat_vchg_max_millivolts = le32_to_cpu(data.val) / 1000U; + else + dev_warn(dev, "failed to get maximum trickle charge voltage\n"); +} + +static void rpi_rtc_set_charge_voltage(struct device *dev) +{ + struct rpi_rtc_data *rtc = dev_get_drvdata(dev); + struct rpi_rtc_reg data = { + .reg = cpu_to_le32(RTC_BBAT_CHG_VOLTS), + .val = cpu_to_le32(rtc->bbat_vchg_millivolts * 1000U) + }; + int err; + + if (rtc->bbat_vchg_millivolts != 0 && + (rtc->bbat_vchg_millivolts < rtc->bbat_vchg_min_millivolts || + rtc->bbat_vchg_millivolts > rtc->bbat_vchg_max_millivolts)) { + dev_warn(dev, "trickle charge voltage %umV is outside of the supported range (%umV - %umV)\n", + rtc->bbat_vchg_millivolts, + rtc->bbat_vchg_min_millivolts, + rtc->bbat_vchg_max_millivolts); + return; + } + + err = rpi_firmware_property(rtc->fw, RPI_FIRMWARE_SET_RTC_REG, + &data, sizeof(data)); + + if (err) + dev_err(dev, "failed to set trickle charge voltage to %umV: %d\n", + rtc->bbat_vchg_millivolts, err); + else if (rtc->bbat_vchg_millivolts) + dev_info(dev, "trickle charging enabled at %umV\n", + rtc->bbat_vchg_millivolts); +} + +static int rpi_rtc_probe(struct platform_device *pdev) +{ + struct rpi_rtc_data *rtc; + struct device *dev = &pdev->dev; + struct rpi_firmware *firmware; + int ret; + + // Get the firmware device from the parent device + firmware = devm_rpi_firmware_get(dev, dev->parent->of_node); + + if (!firmware) + return -EPROBE_DEFER; + + rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL); + if (!rtc) + return -ENOMEM; + + rtc->fw = firmware; + + ret = devm_device_init_wakeup(dev); + if (ret) + return ret; + + platform_set_drvdata(pdev, rtc); + + rtc->rtc = devm_rtc_allocate_device(dev); + if (IS_ERR(rtc->rtc)) + return PTR_ERR(rtc->rtc); + + rtc->rtc->range_max = U32_MAX; /* 2106-02-07 */ + + set_bit(RTC_FEATURE_ALARM_WAKEUP_ONLY, rtc->rtc->features); + clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtc->features); + + rtc->rtc->ops = &rpi_rtc_ops; + + rpi_rtc_alarm_clear_pending(dev); + + /* + * The trickle-voltage property lives on the parent firmware node + * because we deliberately do not create a DT child node just to + * instantiate this driver (see DT maintainer guidance). + * The firmware driver registers us as a platform device at runtime. + */ + rtc->bbat_vchg_millivolts = 0; + of_property_read_u32(dev->parent->of_node, "trickle-voltage-millivolt", + &rtc->bbat_vchg_millivolts); + + rpi_rtc_set_limits(dev); + rpi_rtc_set_charge_voltage(dev); + + return devm_rtc_register_device(rtc->rtc); +} + +static const struct platform_device_id raspberrypi_rtc_id[] = { + { "raspberrypi-rtc" }, + { } +}; +MODULE_DEVICE_TABLE(platform, raspberrypi_rtc_id); + +static struct platform_driver rpi_rtc_driver = { + .driver = { + .name = "raspberrypi-rtc", + }, + .id_table = raspberrypi_rtc_id, + .probe = rpi_rtc_probe +}; + +module_platform_driver(rpi_rtc_driver); + +MODULE_AUTHOR("Jonathan Bell "); +MODULE_AUTHOR("Sander Speetjens "); +MODULE_DESCRIPTION("Raspberry Pi RTC driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 24bd795d9d95..a4bd042908b8 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -52,6 +52,7 @@ #define RS5C_REG_CTRL2 15 # define RS5C372_CTRL2_24 (1 << 5) # define RS5C_CTRL2_XSTP (1 << 4) /* only if !R2x2x */ +# define R2223x_CTRL2_ECO (1 << 7) /* only if R2223x */ # define R2x2x_CTRL2_VDET (1 << 6) /* only if R2x2x */ # define R2x2x_CTRL2_XSTP (1 << 5) /* only if R2x2x */ # define R2x2x_CTRL2_PON (1 << 4) /* only if R2x2x */ @@ -68,6 +69,7 @@ enum rtc_type { rtc_undef = 0, rtc_r2025sd, rtc_r2221tl, + rtc_r2223x, rtc_rs5c372a, rtc_rs5c372b, rtc_rv5c386, @@ -77,6 +79,7 @@ enum rtc_type { static const struct i2c_device_id rs5c372_id[] = { { .name = "r2025sd", .driver_data = rtc_r2025sd }, { .name = "r2221tl", .driver_data = rtc_r2221tl }, + { .name = "r2223x", .driver_data = rtc_r2223x }, { .name = "rs5c372a", .driver_data = rtc_rs5c372a }, { .name = "rs5c372b", .driver_data = rtc_rs5c372b }, { .name = "rv5c386", .driver_data = rtc_rv5c386 }, @@ -94,6 +97,10 @@ static const __maybe_unused struct of_device_id rs5c372_of_match[] = { .compatible = "ricoh,r2221tl", .data = (void *)rtc_r2221tl }, + { + .compatible = "ricoh,r2223x", + .data = (void *)rtc_r2223x + }, { .compatible = "ricoh,rs5c372a", .data = (void *)rtc_rs5c372a @@ -221,8 +228,10 @@ static int rs5c372_rtc_read_time(struct device *dev, struct rtc_time *tm) switch (rs5c->type) { case rtc_r2025sd: case rtc_r2221tl: + case rtc_r2223x: if ((rs5c->type == rtc_r2025sd && !(ctrl2 & R2x2x_CTRL2_XSTP)) || - (rs5c->type == rtc_r2221tl && (ctrl2 & R2x2x_CTRL2_XSTP))) { + ((rs5c->type == rtc_r2221tl || rs5c->type == rtc_r2223x) && + (ctrl2 & R2x2x_CTRL2_XSTP))) { dev_warn(&client->dev, "rtc oscillator interruption detected. Please reset the rtc clock.\n"); return -EINVAL; } @@ -292,6 +301,7 @@ static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm) switch (rs5c->type) { case rtc_r2025sd: case rtc_r2221tl: + case rtc_r2223x: ctrl2 &= ~(R2x2x_CTRL2_VDET | R2x2x_CTRL2_PON); if (rs5c->type == rtc_r2025sd) ctrl2 |= R2x2x_CTRL2_XSTP; @@ -511,8 +521,10 @@ static int rs5c372_ioctl(struct device *dev, unsigned int cmd, unsigned long arg switch (rs5c->type) { case rtc_r2025sd: case rtc_r2221tl: + case rtc_r2223x: if ((rs5c->type == rtc_r2025sd && !(ctrl2 & R2x2x_CTRL2_XSTP)) || - (rs5c->type == rtc_r2221tl && (ctrl2 & R2x2x_CTRL2_XSTP))) { + ((rs5c->type == rtc_r2221tl || rs5c->type == rtc_r2223x) && + (ctrl2 & R2x2x_CTRL2_XSTP))) { flags |= RTC_VL_DATA_INVALID; } if (ctrl2 & R2x2x_CTRL2_VDET) @@ -527,7 +539,8 @@ static int rs5c372_ioctl(struct device *dev, unsigned int cmd, unsigned long arg return put_user(flags, (unsigned int __user *)arg); case RTC_VL_CLR: /* clear VDET bit */ - if (rs5c->type == rtc_r2025sd || rs5c->type == rtc_r2221tl) { + if (rs5c->type == rtc_r2025sd || rs5c->type == rtc_r2221tl || + rs5c->type == rtc_r2223x) { ctrl2 &= ~R2x2x_CTRL2_VDET; if (i2c_smbus_write_byte_data(rs5c->client, addr, ctrl2) < 0) { dev_dbg(&rs5c->client->dev, "%s: write error in line %i\n", @@ -554,6 +567,7 @@ static int rs5c372_read_offset(struct device *dev, long *offset) switch (rs5c->type) { case rtc_r2221tl: + case rtc_r2223x: ppb_per_step = val & R2221TL_TRIM_DEV ? 1017 : 3051; break; case rtc_rs5c372a: @@ -600,6 +614,7 @@ static int rs5c372_set_offset(struct device *dev, long offset) } break; case rtc_r2221tl: + case rtc_r2223x: /* * Check if it is possible to use high resolution mode (DEV=1). * In this mode, the minimum resolution is 2 / (32768 * 20 * 3), @@ -684,7 +699,7 @@ static ssize_t rs5c372_sysfs_show_trim(struct device *dev, if (err) return err; - return sprintf(buf, "%d\n", trim); + return sysfs_emit(buf, "%d\n", trim); } static DEVICE_ATTR(trim, S_IRUGO, rs5c372_sysfs_show_trim, NULL); @@ -697,7 +712,7 @@ static ssize_t rs5c372_sysfs_show_osc(struct device *dev, if (err) return err; - return sprintf(buf, "%d.%03d KHz\n", osc / 1000, osc % 1000); + return sysfs_emit(buf, "%d.%03d KHz\n", osc / 1000, osc % 1000); } static DEVICE_ATTR(osc, S_IRUGO, rs5c372_sysfs_show_osc, NULL); @@ -750,6 +765,7 @@ static int rs5c_oscillator_setup(struct rs5c372 *rs5c372) return ret; break; case rtc_r2221tl: + case rtc_r2223x: if (!(buf[1] & R2x2x_CTRL2_XSTP)) return ret; break; @@ -768,6 +784,7 @@ static int rs5c_oscillator_setup(struct rs5c372 *rs5c372) break; case rtc_r2025sd: case rtc_r2221tl: + case rtc_r2223x: case rtc_rv5c386: case rtc_rv5c387a: buf[0] |= RV5C387_CTRL1_24; @@ -791,6 +808,24 @@ static int rs5c_oscillator_setup(struct rs5c372 *rs5c372) return 0; } +static int rs5c372_set_eco_mode(struct rs5c372 *rs5c372, bool eco) +{ + struct i2c_client *client = rs5c372->client; + int ctrl2; + + ctrl2 = i2c_smbus_read_byte_data(client, RS5C_ADDR(RS5C_REG_CTRL2)); + if (ctrl2 < 0) + return ctrl2; + + if (eco) + ctrl2 |= R2223x_CTRL2_ECO; + else + ctrl2 &= ~R2223x_CTRL2_ECO; + + return i2c_smbus_write_byte_data(client, RS5C_ADDR(RS5C_REG_CTRL2), + ctrl2); +} + static int rs5c372_probe(struct i2c_client *client) { int err = 0; @@ -847,6 +882,7 @@ static int rs5c372_probe(struct i2c_client *client) break; case rtc_r2025sd: case rtc_r2221tl: + case rtc_r2223x: case rtc_rv5c386: case rtc_rv5c387a: if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24) @@ -876,6 +912,7 @@ static int rs5c372_probe(struct i2c_client *client) ({ char *s; switch (rs5c372->type) { case rtc_r2025sd: s = "r2025sd"; break; case rtc_r2221tl: s = "r2221tl"; break; + case rtc_r2223x: s = "r2223x"; break; case rtc_rs5c372a: s = "rs5c372a"; break; case rtc_rs5c372b: s = "rs5c372b"; break; case rtc_rv5c386: s = "rv5c386"; break; @@ -885,6 +922,15 @@ static int rs5c372_probe(struct i2c_client *client) rs5c372->time24 ? "24hr" : "am/pm" ); + if (rs5c372->type == rtc_r2223x) { + bool eco = device_property_read_bool(&client->dev, + "ricoh,eco-mode"); + + err = rs5c372_set_eco_mode(rs5c372, eco); + if (err < 0) + goto exit; + } + /* REVISIT use client->irq to register alarm irq ... */ rs5c372->rtc = devm_rtc_device_register(&client->dev, rs5c372_driver.driver.name, diff --git a/drivers/rtc/rtc-rv3028.c b/drivers/rtc/rtc-rv3028.c index d25e33d0835e..b3a5b1ef33d1 100644 --- a/drivers/rtc/rtc-rv3028.c +++ b/drivers/rtc/rtc-rv3028.c @@ -147,8 +147,8 @@ static ssize_t timestamp0_show(struct device *dev, if (ret) return ret; - return sprintf(buf, "%llu\n", - (unsigned long long)rtc_tm_to_time64(&tm)); + return sysfs_emit(buf, "%llu\n", + (unsigned long long)rtc_tm_to_time64(&tm)); }; static DEVICE_ATTR_RW(timestamp0); @@ -164,7 +164,7 @@ static ssize_t timestamp0_count_show(struct device *dev, if (ret) return ret; - return sprintf(buf, "%u\n", count); + return sysfs_emit(buf, "%u\n", count); }; static DEVICE_ATTR_RO(timestamp0_count); diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index 98953af2a24a..33b73bbcaf52 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c @@ -270,19 +270,17 @@ static irqreturn_t rv3029_handle_irq(int irq, void *dev_id) unsigned long events = 0; int ret; - rtc_lock(rv3029->rtc); + guard(rtc_ops)(rv3029->rtc); ret = regmap_read(rv3029->regmap, RV3029_IRQ_CTRL, &controls); if (ret) { dev_warn(dev, "Read IRQ Control Register error %d\n", ret); - rtc_unlock(rv3029->rtc); return IRQ_NONE; } ret = regmap_read(rv3029->regmap, RV3029_IRQ_FLAGS, &flags); if (ret) { dev_warn(dev, "Read IRQ Flags Register error %d\n", ret); - rtc_unlock(rv3029->rtc); return IRQ_NONE; } @@ -297,7 +295,6 @@ static irqreturn_t rv3029_handle_irq(int irq, void *dev_id) regmap_write(rv3029->regmap, RV3029_IRQ_FLAGS, flags); regmap_write(rv3029->regmap, RV3029_IRQ_CTRL, controls); } - rtc_unlock(rv3029->rtc); return IRQ_HANDLED; } @@ -604,7 +601,7 @@ static ssize_t rv3029_hwmon_show_temp(struct device *dev, if (ret < 0) return ret; - return sprintf(buf, "%d\n", temp_mC); + return sysfs_emit(buf, "%d\n", temp_mC); } static ssize_t rv3029_hwmon_set_update_interval(struct device *dev, @@ -657,7 +654,7 @@ static ssize_t rv3029_hwmon_show_update_interval(struct device *dev, interval_ms = 0; } - return sprintf(buf, "%d\n", interval_ms); + return sysfs_emit(buf, "%d\n", interval_ms); } static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, rv3029_hwmon_show_temp, diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c index ce3954132336..0a9be6ea62d0 100644 --- a/drivers/rtc/rtc-rx8010.c +++ b/drivers/rtc/rtc-rx8010.c @@ -73,11 +73,10 @@ static irqreturn_t rx8010_irq_1_handler(int irq, void *dev_id) struct rx8010_data *rx8010 = i2c_get_clientdata(client); int flagreg, err; - rtc_lock(rx8010->rtc); + guard(rtc_ops)(rx8010->rtc); err = regmap_read(rx8010->regs, RX8010_FLAG, &flagreg); if (err) { - rtc_unlock(rx8010->rtc); return IRQ_NONE; } @@ -100,7 +99,6 @@ static irqreturn_t rx8010_irq_1_handler(int irq, void *dev_id) } err = regmap_write(rx8010->regs, RX8010_FLAG, flagreg); - rtc_unlock(rx8010->rtc); return err ? IRQ_NONE : IRQ_HANDLED; } diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index 5eeaa929f3ef..96a04c977d0f 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c @@ -180,10 +180,11 @@ static irqreturn_t rx8025_handle_irq(int irq, void *dev_id) struct rx8025_data *rx8025 = i2c_get_clientdata(client); int status, xstp; - rtc_lock(rx8025->rtc); + guard(rtc_ops)(rx8025->rtc); + status = rx8025_read_reg(client, RX8025_REG_CTRL2); if (status < 0) - goto out; + return IRQ_HANDLED; xstp = rx8025_is_osc_stopped(rx8025->model, status); if (xstp) @@ -201,13 +202,10 @@ static irqreturn_t rx8025_handle_irq(int irq, void *dev_id) status &= RX8025_BIT_CTRL2_DAFG; if (rx8025_write_reg(client, RX8025_REG_CTRL1, rx8025->ctrl1 & ~RX8025_BIT_CTRL1_DALE)) - goto out; + return IRQ_HANDLED; rtc_update_irq(rx8025->rtc, 1, RTC_AF | RTC_IRQF); } -out: - rtc_unlock(rx8025->rtc); - return IRQ_HANDLED; } @@ -488,7 +486,7 @@ static ssize_t rx8025_sysfs_show_clock_adjust(struct device *dev, if (err) return err; - return sprintf(buf, "%ld\n", -adj); + return sysfs_emit(buf, "%ld\n", -adj); } static ssize_t rx8025_sysfs_store_clock_adjust(struct device *dev, diff --git a/drivers/rtc/rtc-rzn1.c b/drivers/rtc/rtc-rzn1.c index b9d69ebdd224..1db518ab3a3a 100644 --- a/drivers/rtc/rtc-rzn1.c +++ b/drivers/rtc/rtc-rzn1.c @@ -68,6 +68,7 @@ struct rzn1_rtc_data { bool has_subu; + bool broken_irqs; }; struct rzn1_rtc { @@ -396,6 +397,11 @@ static const struct rtc_class_ops rzn1_rtc_ops_scmp = { .alarm_irq_enable = rzn1_rtc_alarm_irq_enable, }; +static const struct rtc_class_ops rzn1_rtc_ops_scmp_no_alarm = { + .read_time = rzn1_rtc_read_time, + .set_time = rzn1_rtc_set_time, +}; + static void rzn1_rtc_disable_hardware(void *data) { struct device *dev = data; @@ -431,10 +437,6 @@ static int rzn1_rtc_probe(struct platform_device *pdev) if (IS_ERR(rtc->base)) return dev_err_probe(dev, PTR_ERR(rtc->base), "Missing reg\n"); - irq = platform_get_irq_byname(pdev, "alarm"); - if (irq < 0) - return irq; - rtc->rtcdev = devm_rtc_allocate_device(dev); if (IS_ERR(rtc->rtcdev)) return PTR_ERR(rtc->rtcdev); @@ -503,25 +505,40 @@ static int rzn1_rtc_probe(struct platform_device *pdev) spin_lock_init(&rtc->ctl1_access_lock); - ret = devm_request_irq(dev, irq, rzn1_rtc_alarm_irq, 0, "RZN1 RTC Alarm", rtc); - if (ret) - return dev_err_probe(dev, ret, "RTC alarm interrupt not available\n"); - - irq = platform_get_irq_byname_optional(pdev, "pps"); - if (irq == -EPROBE_DEFER) - return irq; - if (irq >= 0) - ret = devm_request_irq(dev, irq, rzn1_rtc_1s_irq, 0, "RZN1 RTC 1s", rtc); - - if (irq < 0 || ret) { - set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->rtcdev->features); + if (data->broken_irqs) { + /* All known broken irqs are on SCMP only variants */ + rtc->rtcdev->ops = &rzn1_rtc_ops_scmp_no_alarm; clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtcdev->features); - dev_warn(dev, "RTC pps interrupt not available. Alarm has only minute accuracy\n"); + } else { + irq = platform_get_irq_byname(pdev, "alarm"); + if (irq < 0) + return irq; + + ret = devm_request_irq(dev, irq, rzn1_rtc_alarm_irq, 0, "RZN1 RTC Alarm", rtc); + if (ret) + return dev_err_probe(dev, ret, "RTC alarm interrupt not available\n"); + + irq = platform_get_irq_byname_optional(pdev, "pps"); + if (irq == -EPROBE_DEFER) + return irq; + if (irq >= 0) + ret = devm_request_irq(dev, irq, rzn1_rtc_1s_irq, 0, "RZN1 RTC 1s", rtc); + + if (irq < 0 || ret) { + set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->rtcdev->features); + clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtcdev->features); + dev_warn(dev, "RTC pps interrupt not available. Alarm has only minute accuracy\n"); + } } return devm_rtc_register_device(rtc->rtcdev); } +static const struct rzn1_rtc_data rzn1_rtc_r8a78000_data = { + .has_subu = false, + .broken_irqs = true, +}; + static const struct rzn1_rtc_data rzn1_rtc_rzt2h_data = { .has_subu = false, }; @@ -531,6 +548,7 @@ static const struct rzn1_rtc_data rzn1_rtc_rzn1_data = { }; static const struct of_device_id rzn1_rtc_of_match[] = { + { .compatible = "renesas,r8a78000-rtc", .data = &rzn1_rtc_r8a78000_data }, { .compatible = "renesas,r9a09g077-rtc", .data = &rzn1_rtc_rzt2h_data }, { .compatible = "renesas,rzn1-rtc", .data = &rzn1_rtc_rzn1_data }, { /* sentinel */ } diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index b72eef4fb099..d3e829052927 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -5,6 +5,7 @@ * Copyright (c) 2007 Byron Bradley */ +#include #include #include #include @@ -12,11 +13,17 @@ #include #include #include +#include +#include +#include + +#define DRIVER_NAME "rtc-s35390a" #define S35390A_CMD_STATUS1 0 #define S35390A_CMD_STATUS2 1 #define S35390A_CMD_TIME1 2 #define S35390A_CMD_TIME2 3 +#define S35390A_CMD_INT1_REG1 4 #define S35390A_CMD_INT2_REG1 5 #define S35390A_CMD_FREE_REG 7 @@ -36,19 +43,38 @@ #define S35390A_FLAG_POC BIT(0) #define S35390A_FLAG_BLD BIT(1) #define S35390A_FLAG_INT2 BIT(2) +#define S35390A_FLAG_INT1 BIT(3) #define S35390A_FLAG_24H BIT(6) #define S35390A_FLAG_RESET BIT(7) /* flag for STATUS2 */ #define S35390A_FLAG_TEST BIT(0) +#define S35390A_INT_MODE_NOINTR 0x00 + /* INT2 pin output mode */ #define S35390A_INT2_MODE_MASK 0x0E -#define S35390A_INT2_MODE_NOINTR 0x00 #define S35390A_INT2_MODE_ALARM BIT(1) /* INT2AE */ #define S35390A_INT2_MODE_PMIN_EDG BIT(2) /* INT2ME */ #define S35390A_INT2_MODE_FREQ BIT(3) /* INT2FE */ -#define S35390A_INT2_MODE_PMIN (BIT(3) | BIT(2)) /* INT2FE | INT2ME */ +#define S35390A_INT2_MODE_PMIN1 (BIT(3) | BIT(2)) /* INT2FE | INT2ME */ + +/* INT1 pin output mode */ +#define S35390A_INT1_MODE_MASK 0xF0 +#define S35390A_INT1_MODE_ALARM BIT(5) /* INT1AE */ +#define S35390A_INT1_MODE_PMIN_EDG BIT(6) /* INT1ME */ +#define S35390A_INT1_MODE_FREQ BIT(7) /* INT1FE */ +#define S35390A_INT1_MODE_PMIN1 (BIT(7) | BIT(6)) /* INT1FE | INT1ME */ +#define S35390A_INT1_MODE_PMIN2 (BIT(7) | BIT(6) | BIT(5)) /* INT1FE | INT1ME | INT1AE */ +#define S35390A_INT1_MODE_32768KHZ BIT(4) /* 32kE */ + +#define S35390A_FUNC_IGNORE 0x00 +#define S35390A_FUNC_DISABLE 0x01 +#define S35390A_FUNC_WAKEUP 0x02 +#define S35390A_FUNC_CLOCK 0x03 +#define S35390A_FUNC_PMIN1 0x04 +#define S35390A_FUNC_PMIN2 0x05 + static const struct i2c_device_id s35390a_id[] = { { .name = "s35390a" }, @@ -64,7 +90,10 @@ MODULE_DEVICE_TABLE(of, s35390a_of_match); struct s35390a { struct i2c_client *client[8]; - int twentyfourhour; + struct rtc_device *rtc; + + struct mutex pinfunction_lock; /* lock preventing concurrent access of pin function */ + int pinfunction[2]; }; static int s35390a_set_reg(struct s35390a *s35390a, int reg, u8 *buf, int len) @@ -102,9 +131,8 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, u8 *buf, int len) return 0; } -static int s35390a_init(struct s35390a *s35390a) +static int s35390a_init(struct s35390a *s35390a, u8 *sts) { - u8 buf; int ret; unsigned initcount = 0; @@ -117,17 +145,17 @@ static int s35390a_init(struct s35390a *s35390a) * The 24H bit is kept over reset, so set it already here. */ initialize: - buf = S35390A_FLAG_RESET | S35390A_FLAG_24H; - ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1); + *sts = S35390A_FLAG_RESET | S35390A_FLAG_24H; + ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, sts, 1); if (ret < 0) return ret; - ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1); + ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, sts, 1); if (ret < 0) return ret; - if (buf & (S35390A_FLAG_POC | S35390A_FLAG_BLD)) { + if (*sts & (S35390A_FLAG_POC | S35390A_FLAG_BLD)) { /* Try up to five times to reset the chip */ if (initcount < 5) { ++initcount; @@ -167,23 +195,9 @@ static int s35390a_read_status(struct s35390a *s35390a, char *status1) return 0; } -static int s35390a_disable_test_mode(struct s35390a *s35390a) +static char s35390a_hr2reg(int hour, bool twentyfourhour) { - u8 buf[1]; - - if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf)) < 0) - return -EIO; - - if (!(buf[0] & S35390A_FLAG_TEST)) - return 0; - - buf[0] &= ~S35390A_FLAG_TEST; - return s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf)); -} - -static char s35390a_hr2reg(struct s35390a *s35390a, int hour) -{ - if (s35390a->twentyfourhour) + if (twentyfourhour) return bin2bcd(hour); if (hour < 12) @@ -192,11 +206,11 @@ static char s35390a_hr2reg(struct s35390a *s35390a, int hour) return 0x40 | bin2bcd(hour - 12); } -static int s35390a_reg2hr(struct s35390a *s35390a, char reg) +static int s35390a_reg2hr(char reg, bool twentyfourhour) { unsigned hour; - if (s35390a->twentyfourhour) + if (twentyfourhour) return bcd2bin(reg & 0x3f); hour = bcd2bin(reg & 0x3f); @@ -210,7 +224,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; + int i, err; u8 buf[7], status; dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d mday=%d, " @@ -218,14 +232,18 @@ static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm) tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); - if (s35390a_read_status(s35390a, &status) == 1) - s35390a_init(s35390a); + err = s35390a_read_status(s35390a, &status); + if (err == 1) + err = s35390a_init(s35390a, &status); + + if (err < 0) + return err; buf[S35390A_BYTE_YEAR] = bin2bcd(tm->tm_year - 100); buf[S35390A_BYTE_MONTH] = bin2bcd(tm->tm_mon + 1); buf[S35390A_BYTE_DAY] = bin2bcd(tm->tm_mday); buf[S35390A_BYTE_WDAY] = bin2bcd(tm->tm_wday); - buf[S35390A_BYTE_HOURS] = s35390a_hr2reg(s35390a, tm->tm_hour); + buf[S35390A_BYTE_HOURS] = s35390a_hr2reg(tm->tm_hour, status & S35390A_FLAG_24H); buf[S35390A_BYTE_MINS] = bin2bcd(tm->tm_min); buf[S35390A_BYTE_SECS] = bin2bcd(tm->tm_sec); @@ -243,8 +261,11 @@ static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm) u8 buf[7], status; int i, err; - if (s35390a_read_status(s35390a, &status) == 1) + err = s35390a_read_status(s35390a, &status); + if (err == 1) return -EINVAL; + if (err < 0) + return err; err = s35390a_get_reg(s35390a, S35390A_CMD_TIME1, buf, sizeof(buf)); if (err < 0) @@ -256,7 +277,7 @@ static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_sec = bcd2bin(buf[S35390A_BYTE_SECS]); tm->tm_min = bcd2bin(buf[S35390A_BYTE_MINS]); - tm->tm_hour = s35390a_reg2hr(s35390a, buf[S35390A_BYTE_HOURS]); + tm->tm_hour = s35390a_reg2hr(buf[S35390A_BYTE_HOURS], status & S35390A_FLAG_24H); tm->tm_wday = bcd2bin(buf[S35390A_BYTE_WDAY]); tm->tm_mday = bcd2bin(buf[S35390A_BYTE_DAY]); tm->tm_mon = bcd2bin(buf[S35390A_BYTE_MONTH]) - 1; @@ -270,11 +291,44 @@ static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm) return 0; } +static int s35390a_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct s35390a *s35390a = dev_get_drvdata(dev); + u8 sts; + int err; + + guard(mutex)(&s35390a->pinfunction_lock); + + err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); + if (err < 0) + return err; + + if (enabled) { + if (s35390a->pinfunction[0] == S35390A_FUNC_WAKEUP) + sts = (sts & ~S35390A_INT1_MODE_MASK) | S35390A_INT1_MODE_ALARM; + + if (s35390a->pinfunction[1] == S35390A_FUNC_WAKEUP) + sts = (sts & ~S35390A_INT2_MODE_MASK) | S35390A_INT2_MODE_ALARM; + } else { + if (s35390a->pinfunction[0] == S35390A_FUNC_WAKEUP) + sts = (sts & ~S35390A_INT1_MODE_MASK) | S35390A_INT_MODE_NOINTR; + + if (s35390a->pinfunction[1] == S35390A_FUNC_WAKEUP) + sts = (sts & ~S35390A_INT2_MODE_MASK) | S35390A_INT_MODE_NOINTR; + } + + err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); + if (err < 0) + return err; + + return 0; +} + 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); - u8 buf[3], sts = 0; + u8 buf[3], status1, status2 = 0; int err, i; dev_dbg(&client->dev, "%s: alm is secs=%d, mins=%d, hours=%d mday=%d, "\ @@ -282,23 +336,25 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday, alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday); + guard(mutex)(&s35390a->pinfunction_lock); + + err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &status2, sizeof(status2)); + if (err < 0) + return err; + /* disable interrupt (which deasserts the irq line) */ - err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); + if (s35390a->pinfunction[0] == S35390A_FUNC_WAKEUP) + status2 = (status2 & ~S35390A_INT1_MODE_MASK) | S35390A_INT_MODE_NOINTR; + + if (s35390a->pinfunction[1] == S35390A_FUNC_WAKEUP) + status2 = (status2 & ~S35390A_INT2_MODE_MASK) | S35390A_INT_MODE_NOINTR; + + err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &status2, sizeof(status2)); if (err < 0) return err; /* clear pending interrupt (in STATUS1 only), if any */ - err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts)); - if (err < 0) - return err; - - if (alm->enabled) - sts = S35390A_INT2_MODE_ALARM; - else - sts = S35390A_INT2_MODE_NOINTR; - - /* set interrupt mode*/ - err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); + err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &status1, sizeof(status1)); if (err < 0) return err; @@ -307,8 +363,8 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) else buf[S35390A_ALRM_BYTE_WDAY] = 0; - buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a, - alm->time.tm_hour) | 0x80; + buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(alm->time.tm_hour, + status1 & S35390A_FLAG_24H) | 0x80; buf[S35390A_ALRM_BYTE_MINS] = bin2bcd(alm->time.tm_min) | 0x80; if (alm->time.tm_hour >= 12) @@ -317,35 +373,71 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) for (i = 0; i < 3; ++i) buf[i] = bitrev8(buf[i]); - err = s35390a_set_reg(s35390a, S35390A_CMD_INT2_REG1, buf, - sizeof(buf)); + if (alm->enabled) { + /* set interrupt mode */ + if (s35390a->pinfunction[0] == S35390A_FUNC_WAKEUP) + status2 = (status2 & ~S35390A_INT1_MODE_MASK) | S35390A_INT1_MODE_ALARM; - return err; + if (s35390a->pinfunction[1] == S35390A_FUNC_WAKEUP) + status2 = (status2 & ~S35390A_INT2_MODE_MASK) | S35390A_INT2_MODE_ALARM; + + err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &status2, sizeof(status2)); + if (err < 0) + return err; + } + + if (s35390a->pinfunction[0] == S35390A_FUNC_WAKEUP) { + err = s35390a_set_reg(s35390a, S35390A_CMD_INT1_REG1, buf, sizeof(buf)); + if (err < 0) + return err; + } + + if (s35390a->pinfunction[1] == S35390A_FUNC_WAKEUP) { + err = s35390a_set_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf)); + if (err < 0) + return err; + } + + return 0; } 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); - u8 buf[3], sts; - int i, err; + u8 buf[3], status1, status2; + int i, err, reg; - err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); + guard(mutex)(&s35390a->pinfunction_lock); + + err = s35390a_read_status(s35390a, &status1); + if (err == 1) + return -EINVAL; if (err < 0) return err; - if ((sts & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) { + err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &status2, sizeof(status2)); + if (err < 0) + return err; + + if (s35390a->pinfunction[1] == S35390A_FUNC_WAKEUP && + (status2 & S35390A_INT2_MODE_MASK) == S35390A_INT2_MODE_ALARM) { + reg = S35390A_CMD_INT2_REG1; + } else if (s35390a->pinfunction[0] == S35390A_FUNC_WAKEUP && + (status2 & S35390A_INT1_MODE_MASK) == S35390A_INT1_MODE_ALARM) { + reg = S35390A_CMD_INT1_REG1; + } else { /* * When the alarm isn't enabled, the register to configure * the alarm time isn't accessible. */ alm->enabled = 0; return 0; - } else { - alm->enabled = 1; } - err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf)); + alm->enabled = 1; + + err = s35390a_get_reg(s35390a, reg, buf, sizeof(buf)); if (err < 0) return err; @@ -354,7 +446,7 @@ static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) buf[i] = bitrev8(buf[i]); /* - * B0 of the three matching registers is an enable flag. Iff it is set + * B0 of the three matching registers is an enable flag. If it is set * the configured value is used for matching. */ if (buf[S35390A_ALRM_BYTE_WDAY] & 0x80) @@ -363,8 +455,8 @@ static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) if (buf[S35390A_ALRM_BYTE_HOURS] & 0x80) alm->time.tm_hour = - s35390a_reg2hr(s35390a, - buf[S35390A_ALRM_BYTE_HOURS] & ~0x80); + s35390a_reg2hr(buf[S35390A_ALRM_BYTE_HOURS] & ~0x80, + status1 & S35390A_FLAG_24H); if (buf[S35390A_ALRM_BYTE_MINS] & 0x80) alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS] & ~0x80); @@ -398,7 +490,7 @@ static int s35390a_rtc_ioctl(struct device *dev, unsigned int cmd, break; case RTC_VL_CLR: /* update flag and clear register */ - err = s35390a_init(s35390a); + err = s35390a_init(s35390a, &sts); if (err < 0) return err; break; @@ -410,11 +502,12 @@ static int s35390a_rtc_ioctl(struct device *dev, unsigned int cmd, } static const struct rtc_class_ops s35390a_rtc_ops = { - .read_time = s35390a_rtc_read_time, - .set_time = s35390a_rtc_set_time, - .set_alarm = s35390a_rtc_set_alarm, - .read_alarm = s35390a_rtc_read_alarm, - .ioctl = s35390a_rtc_ioctl, + .read_time = s35390a_rtc_read_time, + .set_time = s35390a_rtc_set_time, + .set_alarm = s35390a_rtc_set_alarm, + .read_alarm = s35390a_rtc_read_alarm, + .alarm_irq_enable = s35390a_rtc_alarm_irq_enable, + .ioctl = s35390a_rtc_ioctl, }; static int s35390a_nvmem_read(void *priv, unsigned int offset, void *val, @@ -434,13 +527,168 @@ static int s35390a_nvmem_write(void *priv, unsigned int offset, void *val, return s35390a_set_reg(s35390a, S35390A_CMD_FREE_REG, val, bytes); } +static const struct pinctrl_pin_desc s35390a_pins_desc[] = { + PINCTRL_PIN(0, "int1"), + PINCTRL_PIN(1, "int2"), +}; + +static const unsigned int int1_pins[] = { 0 }; +static const unsigned int int2_pins[] = { 1 }; + +static const struct pingroup s35390a_pin_groups[] = { + PINCTRL_PINGROUP("int1_grp", int1_pins, ARRAY_SIZE(int1_pins)), + PINCTRL_PINGROUP("int2_grp", int2_pins, ARRAY_SIZE(int2_pins)), +}; + +static int s35390a_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(s35390a_pin_groups); +} + +static const char *s35390a_pinctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned int group) +{ + return s35390a_pin_groups[group].name; +} + +static int s35390a_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector, + const unsigned int **pins, unsigned int *npins) +{ + *pins = s35390a_pin_groups[selector].pins; + *npins = s35390a_pin_groups[selector].npins; + return 0; +} + +static const char * const all_groups[] = { "int1_grp", "int2_grp" }; +static const char * const int1_groups[] = { "int1_grp" }; + +static const struct pinfunction s35390a_functions[] = { + [S35390A_FUNC_IGNORE] = PINCTRL_PINFUNCTION("ignore", all_groups, ARRAY_SIZE(all_groups)), + [S35390A_FUNC_DISABLE] = PINCTRL_PINFUNCTION("disable", all_groups, ARRAY_SIZE(all_groups)), + [S35390A_FUNC_WAKEUP] = PINCTRL_PINFUNCTION("wakeup", all_groups, ARRAY_SIZE(all_groups)), + [S35390A_FUNC_CLOCK] = PINCTRL_PINFUNCTION("clock", all_groups, ARRAY_SIZE(all_groups)), + [S35390A_FUNC_PMIN1] = PINCTRL_PINFUNCTION("pmin1", all_groups, ARRAY_SIZE(all_groups)), + [S35390A_FUNC_PMIN2] = PINCTRL_PINFUNCTION("pmin2", int1_groups, ARRAY_SIZE(int1_groups)), +}; + +static int s35390a_pinctrl_get_functions_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(s35390a_functions); +} + +static const char *s35390a_pinctrl_get_function_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + return s35390a_functions[selector].name; +} + +static int s35390a_pinctrl_get_function_groups(struct pinctrl_dev *pctldev, unsigned int selector, + const char * const **groups, + unsigned int * const ngroups) +{ + *groups = s35390a_functions[selector].groups; + *ngroups = s35390a_functions[selector].ngroups; + return 0; +} + +static int s35390a_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned int function, + unsigned int group) +{ + int err; + u8 status2, flag, mask; + struct s35390a *s35390a = pinctrl_dev_get_drvdata(pctldev); + + mask = group == 0 ? S35390A_INT1_MODE_MASK : S35390A_INT2_MODE_MASK; + + guard(mutex)(&s35390a->pinfunction_lock); + + dev_dbg(&s35390a->client[0]->dev, "%s: function=%d group=%d\n", + __func__, function, group); + + if (function == s35390a->pinfunction[group]) + return 0; + + if (function != S35390A_FUNC_IGNORE) { + err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &status2, 1); + if (err < 0) { + dev_err(&s35390a->client[0]->dev, "error reading status\n"); + return err; + } + + switch (function) { + case S35390A_FUNC_DISABLE: + case S35390A_FUNC_CLOCK: /* not implemented */ + status2 = (status2 & ~mask) | S35390A_INT_MODE_NOINTR; + break; + case S35390A_FUNC_WAKEUP: + flag = group == 0 ? S35390A_INT1_MODE_ALARM : S35390A_INT2_MODE_ALARM; + + if ((status2 & mask) != flag) + status2 = (status2 & ~mask) | S35390A_INT_MODE_NOINTR; + + break; + case S35390A_FUNC_PMIN1: + flag = group == 0 ? S35390A_INT1_MODE_PMIN1 : S35390A_INT2_MODE_PMIN1; + status2 = (status2 & ~mask) | flag; + break; + + /* INT1 only modes */ + case S35390A_FUNC_PMIN2: + if (group == 1) + return -EINVAL; + + status2 = (status2 & ~mask) | S35390A_INT1_MODE_PMIN2; + break; + } + + err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &status2, 1); + if (err < 0) { + dev_err(&s35390a->client[0]->dev, "error setting interrupts\n"); + return err; + } + } + + s35390a->pinfunction[group] = function; + + return 0; +} + +static const struct pinctrl_ops s35390a_pinctrl_ops = { + .get_groups_count = s35390a_pinctrl_get_groups_count, + .get_group_name = s35390a_pinctrl_get_group_name, + .get_group_pins = s35390a_pinctrl_get_group_pins, +#if IS_ENABLED(CONFIG_OF) + .dt_node_to_map = pinconf_generic_dt_node_to_map_all, + .dt_free_map = pinconf_generic_dt_free_map +#endif +}; + +static const struct pinmux_ops s35390a_pinmux_ops = { + .get_functions_count = s35390a_pinctrl_get_functions_count, + .get_function_name = s35390a_pinctrl_get_function_name, + .get_function_groups = s35390a_pinctrl_get_function_groups, + .set_mux = s35390a_pinctrl_set_mux, + .strict = true, +}; + +static struct pinctrl_desc s35390a_pinctrl_desc = { + .name = DRIVER_NAME, + .pins = s35390a_pins_desc, + .npins = ARRAY_SIZE(s35390a_pins_desc), + .pctlops = &s35390a_pinctrl_ops, + .pmxops = &s35390a_pinmux_ops, + .owner = THIS_MODULE, +}; + static int s35390a_probe(struct i2c_client *client) { - int err, err_read; + int err; unsigned int i; struct s35390a *s35390a; struct rtc_device *rtc; - u8 buf, status1; + struct pinctrl_dev *pctl; + u8 status1, status2; + bool irq = false; struct device *dev = &client->dev; struct nvmem_config nvmem_cfg = { .name = "s35390a_nvram", @@ -451,6 +699,7 @@ static int s35390a_probe(struct i2c_client *client) .reg_read = s35390a_nvmem_read, .reg_write = s35390a_nvmem_write, }; + int fallback[ARRAY_SIZE(s35390a_pin_groups)]; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; @@ -459,7 +708,11 @@ static int s35390a_probe(struct i2c_client *client) if (!s35390a) return -ENOMEM; + mutex_init(&s35390a->pinfunction_lock); + memset(s35390a->pinfunction, -1, sizeof(s35390a->pinfunction)); + s35390a->client[0] = client; + i2c_set_clientdata(client, s35390a); /* This chip uses multiple addresses, use dummy devices for them */ @@ -474,39 +727,35 @@ static int s35390a_probe(struct i2c_client *client) } } + err = s35390a_read_status(s35390a, &status1); + if (err < 0) { + dev_err(dev, "error resetting chip\n"); + return err; + } + + err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &status2, sizeof(status2)); + if (err < 0) + return dev_err_probe(dev, err, "disabling alarm and test mode failed\n"); + + if (status1 & S35390A_FLAG_INT1) { + status2 = (status2 & ~S35390A_INT1_MODE_MASK) | S35390A_INT_MODE_NOINTR; + irq = true; + } + + if (status1 & S35390A_FLAG_INT2) { + status2 = (status2 & ~S35390A_INT2_MODE_MASK) | S35390A_INT_MODE_NOINTR; + irq = true; + } + + status2 &= ~S35390A_FLAG_TEST; + err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &status2, sizeof(status2)); + if (err < 0) + return dev_err_probe(dev, err, "disabling alarm and test mode failed\n"); + rtc = devm_rtc_allocate_device(dev); if (IS_ERR(rtc)) return PTR_ERR(rtc); - err_read = s35390a_read_status(s35390a, &status1); - if (err_read < 0) { - dev_err(dev, "error resetting chip\n"); - return err_read; - } - - if (status1 & S35390A_FLAG_24H) - s35390a->twentyfourhour = 1; - else - s35390a->twentyfourhour = 0; - - if (status1 & S35390A_FLAG_INT2) { - /* disable alarm (and maybe test mode) */ - buf = 0; - err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1); - if (err < 0) { - dev_err(dev, "error disabling alarm"); - return err; - } - } else { - err = s35390a_disable_test_mode(s35390a); - if (err < 0) { - dev_err(dev, "error disabling test mode\n"); - return err; - } - } - - device_set_wakeup_capable(dev, 1); - rtc->ops = &s35390a_rtc_ops; rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; rtc->range_max = RTC_TIMESTAMP_END_2099; @@ -514,9 +763,43 @@ static int s35390a_probe(struct i2c_client *client) set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features); clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features); - if (status1 & S35390A_FLAG_INT2) + s35390a->rtc = rtc; + + device_set_wakeup_capable(dev, 1); + + if (irq) rtc_update_irq(rtc, 1, RTC_AF); + err = devm_pinctrl_register_and_init(dev, &s35390a_pinctrl_desc, s35390a, &pctl); + if (err) + return dev_err_probe(dev, err, "pinctrl register failed\n"); + + err = pinctrl_enable(pctl); + if (err) + return dev_err_probe(dev, err, "pinctrl enable failed\n"); + + /* If no pinmux function is defined in DT, fallback to previous behaviour */ + + if (dmi_match(DMI_SYS_VENDOR, "Synology Inc.")) { + /* + * Synology uses interrupt signal 1 for wakeup. Since pinctrl cannot be + * configured on ACPI, we check against the dmi sys vendor. + */ + fallback[0] = S35390A_FUNC_WAKEUP; + fallback[1] = S35390A_FUNC_DISABLE; + } else { + fallback[0] = S35390A_FUNC_IGNORE; + fallback[1] = S35390A_FUNC_WAKEUP; + } + + for (i = 0; i < ARRAY_SIZE(s35390a_pin_groups); i++) { + if (s35390a->pinfunction[i] == -1) { + err = s35390a_pinctrl_set_mux(pctl, fallback[i], i); + if (err) + return err; + } + } + nvmem_cfg.priv = s35390a; err = devm_rtc_nvmem_register(rtc, &nvmem_cfg); if (err) @@ -527,7 +810,7 @@ static int s35390a_probe(struct i2c_client *client) static struct i2c_driver s35390a_driver = { .driver = { - .name = "rtc-s35390a", + .name = DRIVER_NAME, .of_match_table = of_match_ptr(s35390a_of_match), }, .probe = s35390a_probe, diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index d4ebf3eb54aa..1c4e4bd7afe4 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -465,7 +465,7 @@ static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id) const struct stm32_rtc_events *evts = &rtc->data->events; unsigned int status, cr; - rtc_lock(rtc->rtc_dev); + guard(rtc_ops)(rtc->rtc_dev); status = readl_relaxed(rtc->base + regs->sr); cr = readl_relaxed(rtc->base + regs->cr); @@ -482,8 +482,6 @@ static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id) stm32_rtc_clear_event_flags(rtc, evts->alra); } - rtc_unlock(rtc->rtc_dev); - return IRQ_HANDLED; } diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index 7fc60880e409..c6916edbf400 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -231,6 +231,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node, const char *iosc_name = "rtc-int-osc"; const char *clkout_name = "osc32k-out"; const char *parents[2]; + struct resource res; u32 reg; rtc = kzalloc_obj(*rtc); @@ -267,9 +268,6 @@ static void __init sun6i_rtc_clk_init(struct device_node *node, } writel(reg, rtc->base + SUN6I_LOSC_CTRL); - /* Yes, I know, this is ugly. */ - sun6i_rtc = rtc; - of_property_read_string_index(node, "clock-output-names", 2, &iosc_name); @@ -280,7 +278,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node, 300000000); if (IS_ERR(rtc->int_osc)) { pr_crit("Couldn't register the internal oscillator\n"); - goto err; + goto err_unmap; } parents[0] = clk_hw_get_name(rtc->int_osc); @@ -309,7 +307,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node, &rtc->lock); if (IS_ERR(rtc->ext_losc)) { pr_crit("Couldn't register the LOSC external gate\n"); - goto err_register; + goto err_losc; } clk_data->num = 3; @@ -317,12 +315,22 @@ static void __init sun6i_rtc_clk_init(struct device_node *node, clk_data->hws[1] = __clk_get_hw(rtc->ext_losc); clk_data->hws[2] = rtc->int_osc; of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + /* Yes, I know, this is ugly. */ + sun6i_rtc = rtc; return; +err_losc: + clk_unregister(rtc->losc); err_register: clk_hw_unregister_fixed_rate(rtc->int_osc); +err_unmap: + iounmap(rtc->base); + of_address_to_resource(node, 0, &res); + release_mem_region(res.start, resource_size(&res)); err: kfree(clk_data); + kfree(rtc); } static const struct sun6i_rtc_clk_data sun6i_a31_rtc_data = { @@ -350,6 +358,10 @@ static void __init sun8i_a23_rtc_clk_init(struct device_node *node) CLK_OF_DECLARE_DRIVER(sun8i_a23_rtc_clk, "allwinner,sun8i-a23-rtc", sun8i_a23_rtc_clk_init); +/* The B288 RTC clocks are the same as the A23's */ +CLK_OF_DECLARE_DRIVER(sun8i_b288_rtc_clk, "allwinner,sun8i-b288-rtc", + sun8i_a23_rtc_clk_init); + static const struct sun6i_rtc_clk_data sun8i_h3_rtc_data = { .rc_osc_rate = 16000000, .fixed_prescaler = 32, @@ -859,6 +871,7 @@ static int sun6i_rtc_probe(struct platform_device *pdev) static const struct of_device_id sun6i_rtc_dt_ids[] = { { .compatible = "allwinner,sun6i-a31-rtc" }, { .compatible = "allwinner,sun8i-a23-rtc" }, + { .compatible = "allwinner,sun8i-b288-rtc" }, { .compatible = "allwinner,sun8i-h3-rtc" }, { .compatible = "allwinner,sun8i-r40-rtc" }, { .compatible = "allwinner,sun8i-v3-rtc" }, diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index bb1a5c86f621..6ca6ff45945e 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c @@ -575,7 +575,7 @@ static ssize_t x1205_sysfs_show_atrim(struct device *dev, if (err) return err; - return sprintf(buf, "%d.%02d pF\n", atrim / 1000, atrim % 1000); + return sysfs_emit(buf, "%d.%02d pF\n", atrim / 1000, atrim % 1000); } static DEVICE_ATTR(atrim, S_IRUGO, x1205_sysfs_show_atrim, NULL); @@ -588,7 +588,7 @@ static ssize_t x1205_sysfs_show_dtrim(struct device *dev, if (err) return err; - return sprintf(buf, "%d ppm\n", dtrim); + return sysfs_emit(buf, "%d ppm\n", dtrim); } static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL); diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c index dc52a2197d24..82979122417d 100644 --- a/drivers/soc/ti/pm33xx.c +++ b/drivers/soc/ti/pm33xx.c @@ -174,7 +174,7 @@ static struct wkup_m3_wakeup_src rtc_wake_src(void) static int am33xx_rtc_only_idle(unsigned long wfi_flags) { - omap_rtc_power_off_program(&omap_rtc->dev); + omap_rtc_power_off_program(); am33xx_do_wfi_sram(wfi_flags); return 0; } diff --git a/include/linux/mfd/mt6397/rtc.h b/include/linux/mfd/mt6397/rtc.h index 27883af44f87..f4da579ec638 100644 --- a/include/linux/mfd/mt6397/rtc.h +++ b/include/linux/mfd/mt6397/rtc.h @@ -49,6 +49,13 @@ #define RTC_AL_SEC 0x0018 +/* The high byte of four of the alarms is spare, always-on storage */ +#define RTC_AL_HOU 0x001c +#define RTC_AL_DOM 0x001e +#define RTC_AL_DOW 0x0020 +#define RTC_AL_MTH 0x0022 +#define RTC_SPARE_MASK GENMASK(15, 8) + #define RTC_AL_SEC_MASK 0x003f #define RTC_AL_MIN_MASK 0x003f #define RTC_AL_HOU_MASK 0x001f diff --git a/include/linux/rtc.h b/include/linux/rtc.h index c09fc22819d0..169d93520dbd 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -13,6 +13,7 @@ #define _LINUX_RTC_H_ +#include #include #include #include @@ -167,6 +168,9 @@ struct rtc_device { #define rtc_lock(d) mutex_lock(&d->ops_lock) #define rtc_unlock(d) mutex_unlock(&d->ops_lock) +DEFINE_GUARD(rtc_ops, struct rtc_device *, mutex_lock(&_T->ops_lock), + mutex_unlock(&_T->ops_lock)) + /* useful timestamps */ #define RTC_TIMESTAMP_BEGIN_0000 -62167219200ULL /* 0000-01-01 00:00:00 */ #define RTC_TIMESTAMP_BEGIN_1900 -2208988800LL /* 1900-01-01 00:00:00 */ @@ -201,6 +205,7 @@ extern void rtc_update_irq(struct rtc_device *rtc, extern struct rtc_device *rtc_class_open(const char *name); extern void rtc_class_close(struct rtc_device *rtc); +DEFINE_FREE(rtc_class_close, struct rtc_device *, if (_T) rtc_class_close(_T)); extern int rtc_irq_set_state(struct rtc_device *rtc, int enabled); extern int rtc_irq_set_freq(struct rtc_device *rtc, int freq); diff --git a/include/linux/rtc/rtc-omap.h b/include/linux/rtc/rtc-omap.h index 9f03a329e63f..d6ec7c4daea6 100644 --- a/include/linux/rtc/rtc-omap.h +++ b/include/linux/rtc/rtc-omap.h @@ -3,5 +3,5 @@ #ifndef _LINUX_RTCOMAP_H_ #define _LINUX_RTCOMAP_H_ -int omap_rtc_power_off_program(struct device *dev); +int omap_rtc_power_off_program(void); #endif /* _LINUX_RTCOMAP_H_ */ diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h index 975bef529854..8c3d43977a03 100644 --- a/include/soc/bcm2835/raspberrypi-firmware.h +++ b/include/soc/bcm2835/raspberrypi-firmware.h @@ -75,6 +75,7 @@ enum rpi_firmware_property_tag { RPI_FIRMWARE_GET_THROTTLED = 0x00030046, RPI_FIRMWARE_GET_CLOCK_MEASURED = 0x00030047, RPI_FIRMWARE_NOTIFY_REBOOT = 0x00030048, + RPI_FIRMWARE_GET_RTC_REG = 0x00030087, RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001, RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002, RPI_FIRMWARE_SET_VOLTAGE = 0x00038003, @@ -92,6 +93,7 @@ enum rpi_firmware_property_tag { RPI_FIRMWARE_SET_POE_HAT_VAL = 0x00030050, RPI_FIRMWARE_NOTIFY_XHCI_RESET = 0x00030058, RPI_FIRMWARE_NOTIFY_DISPLAY_DONE = 0x00030066, + RPI_FIRMWARE_SET_RTC_REG = 0x00038087, /* Dispmanx TAGS */ RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001, diff --git a/tools/testing/selftests/rtc/rtctest.c b/tools/testing/selftests/rtc/rtctest.c index 8047d9879039..552191fe1ca0 100644 --- a/tools/testing/selftests/rtc/rtctest.c +++ b/tools/testing/selftests/rtc/rtctest.c @@ -49,7 +49,7 @@ TEST_F(rtc, date_read) { struct rtc_time rtc_tm; if (self->fd == -1 && errno == ENOENT) - SKIP(return, "Skipping test since %s does not exist", rtc_file); + SKIP(return, "%s does not exist", rtc_file); ASSERT_NE(-1, self->fd); /* Read the RTC time/date */ @@ -116,9 +116,10 @@ TEST_F_TIMEOUT(rtc, date_read_loop, READ_LOOP_DURATION_SEC + 2) { long iter_count = 0; struct rtc_time rtc_tm; time_t start_rtc_read, prev_rtc_read; + struct timespec prev_mono, cur_mono; if (self->fd == -1 && errno == ENOENT) - SKIP(return, "Skipping test since %s does not exist", rtc_file); + SKIP(return, "%s does not exist", rtc_file); ASSERT_NE(-1, self->fd); TH_LOG("Continuously reading RTC time for %ds (with %dms breaks after every read).", @@ -126,25 +127,31 @@ TEST_F_TIMEOUT(rtc, date_read_loop, READ_LOOP_DURATION_SEC + 2) { rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm); ASSERT_NE(-1, rc); + clock_gettime(CLOCK_MONOTONIC, &prev_mono); start_rtc_read = rtc_time_to_timestamp(&rtc_tm); prev_rtc_read = start_rtc_read; do { time_t rtc_read; + time_t delta_s = 0; rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm); ASSERT_NE(-1, rc); + clock_gettime(CLOCK_MONOTONIC, &cur_mono); rtc_read = rtc_time_to_timestamp(&rtc_tm); + delta_s = cur_mono.tv_sec - prev_mono.tv_sec; + /* Time should not go backwards */ ASSERT_LE(prev_rtc_read, rtc_read); - /* Time should not increase more then 1s at a time */ - ASSERT_GE(prev_rtc_read + 1, rtc_read); + /* Time should not increase more then elapsed time + 1s */ + ASSERT_GE(prev_rtc_read + delta_s + 1, rtc_read); /* Sleep 11ms to avoid killing / overheating the RTC */ nanosleep_with_retries(READ_LOOP_SLEEP_MS * 1000000); prev_rtc_read = rtc_read; + prev_mono = cur_mono; iter_count++; } while (prev_rtc_read <= start_rtc_read + READ_LOOP_DURATION_SEC); @@ -156,15 +163,14 @@ TEST_F_TIMEOUT(rtc, uie_read, NUM_UIE + 2) { unsigned long data; if (self->fd == -1 && errno == ENOENT) - SKIP(return, "Skipping test since %s does not exist", rtc_file); + SKIP(return, "%s does not exist", rtc_file); ASSERT_NE(-1, self->fd); /* Turn on update interrupts */ rc = ioctl(self->fd, RTC_UIE_ON, 0); if (rc == -1) { ASSERT_EQ(EINVAL, errno); - TH_LOG("skip update IRQs not supported."); - return; + SKIP(return, "update IRQs are not supported."); } for (i = 0; i < NUM_UIE; i++) { @@ -185,15 +191,14 @@ TEST_F(rtc, uie_select) { unsigned long data; if (self->fd == -1 && errno == ENOENT) - SKIP(return, "Skipping test since %s does not exist", rtc_file); + SKIP(return, "%s does not exist", rtc_file); ASSERT_NE(-1, self->fd); /* Turn on update interrupts */ rc = ioctl(self->fd, RTC_UIE_ON, 0); if (rc == -1) { ASSERT_EQ(EINVAL, errno); - TH_LOG("skip update IRQs not supported."); - return; + SKIP(return, "update IRQs are not supported."); } for (i = 0; i < NUM_UIE; i++) { @@ -229,14 +234,14 @@ TEST_F(rtc, alarm_alm_set) { enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN; if (self->fd == -1 && errno == ENOENT) - SKIP(return, "Skipping test since %s does not exist", rtc_file); + SKIP(return, "%s does not exist", rtc_file); ASSERT_NE(-1, self->fd); alarm_state = get_rtc_alarm_state(self->fd, 1); if (alarm_state == RTC_ALARM_DISABLED) - SKIP(return, "Skipping test since alarms are not supported."); + SKIP(return, "alarms are not supported."); if (alarm_state == RTC_ALARM_RES_MINUTE) - SKIP(return, "Skipping test since alarms has only minute granularity."); + SKIP(return, "alarms has only minute granularity."); rc = ioctl(self->fd, RTC_RD_TIME, &tm); ASSERT_NE(-1, rc); @@ -252,8 +257,7 @@ TEST_F(rtc, alarm_alm_set) { */ ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state); ASSERT_EQ(EINVAL, errno); - TH_LOG("skip alarms are not supported."); - return; + SKIP(return, "alarms are not supported."); } rc = ioctl(self->fd, RTC_ALM_READ, &tm); @@ -299,14 +303,14 @@ TEST_F(rtc, alarm_wkalm_set) { enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN; if (self->fd == -1 && errno == ENOENT) - SKIP(return, "Skipping test since %s does not exist", rtc_file); + SKIP(return, "%s does not exist", rtc_file); ASSERT_NE(-1, self->fd); alarm_state = get_rtc_alarm_state(self->fd, 1); if (alarm_state == RTC_ALARM_DISABLED) - SKIP(return, "Skipping test since alarms are not supported."); + SKIP(return, "alarms are not supported."); if (alarm_state == RTC_ALARM_RES_MINUTE) - SKIP(return, "Skipping test since alarms has only minute granularity."); + SKIP(return, "alarms has only minute granularity."); rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time); ASSERT_NE(-1, rc); @@ -324,8 +328,7 @@ TEST_F(rtc, alarm_wkalm_set) { */ ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state); ASSERT_EQ(EINVAL, errno); - TH_LOG("skip alarms are not supported."); - return; + SKIP(return, "alarms are not supported."); } rc = ioctl(self->fd, RTC_WKALM_RD, &alarm); @@ -363,12 +366,12 @@ TEST_F_TIMEOUT(rtc, alarm_alm_set_minute, 65) { enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN; if (self->fd == -1 && errno == ENOENT) - SKIP(return, "Skipping test since %s does not exist", rtc_file); + SKIP(return, "%s does not exist", rtc_file); ASSERT_NE(-1, self->fd); alarm_state = get_rtc_alarm_state(self->fd, 0); if (alarm_state == RTC_ALARM_DISABLED) - SKIP(return, "Skipping test since alarms are not supported."); + SKIP(return, "alarms are not supported."); rc = ioctl(self->fd, RTC_RD_TIME, &tm); ASSERT_NE(-1, rc); @@ -384,8 +387,7 @@ TEST_F_TIMEOUT(rtc, alarm_alm_set_minute, 65) { */ ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state); ASSERT_EQ(EINVAL, errno); - TH_LOG("skip alarms are not supported."); - return; + SKIP(return, "alarms are not supported."); } rc = ioctl(self->fd, RTC_ALM_READ, &tm); @@ -431,12 +433,12 @@ TEST_F_TIMEOUT(rtc, alarm_wkalm_set_minute, 65) { enum rtc_alarm_state alarm_state = RTC_ALARM_UNKNOWN; if (self->fd == -1 && errno == ENOENT) - SKIP(return, "Skipping test since %s does not exist", rtc_file); + SKIP(return, "%s does not exist", rtc_file); ASSERT_NE(-1, self->fd); alarm_state = get_rtc_alarm_state(self->fd, 0); if (alarm_state == RTC_ALARM_DISABLED) - SKIP(return, "Skipping test since alarms are not supported."); + SKIP(return, "alarms are not supported."); rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time); ASSERT_NE(-1, rc); @@ -454,8 +456,7 @@ TEST_F_TIMEOUT(rtc, alarm_wkalm_set_minute, 65) { */ ASSERT_EQ(RTC_ALARM_UNKNOWN, alarm_state); ASSERT_EQ(EINVAL, errno); - TH_LOG("skip alarms are not supported."); - return; + SKIP(return, "alarms are not supported."); } rc = ioctl(self->fd, RTC_WKALM_RD, &alarm); @@ -502,8 +503,7 @@ int main(int argc, char **argv) if (access(rtc_file, R_OK) == 0) ret = test_harness_run(argc, argv); else - ksft_exit_skip("[SKIP]: Cannot access rtc file %s - Exiting\n", - rtc_file); + ksft_exit_skip("Cannot access rtc file %s - Exiting\n", rtc_file); return ret; }