Merge tag 'rtc-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux

Pull RTC updates from Alexandre Belloni:
 "The RZN1 driver got a fairly comprehensive cleanup. More DT binding
  are converted to DT schema, leaving only 5 remaining files to convert.

  Subsystem:
   - patchwork project is moving to kernel.org
   - fully initialize clk_init_data
   - add missing MODULE_DEVICE_TABLE()
   - DT bindings conversions to DT schema

  Drivers:
   - ds1307: fix WADA bit for alarms on RX8130
   - rzn1: add support for RZ/T2H and RZ/N2H, many fixes"

* tag 'rtc-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (42 commits)
  MAINTAINERS: update rtc subsystem patchwork location
  rtc: msc313: Select by default on MSTARV7
  rtc: microcrystal: Make sure clk_init_data is fully initialized
  rtc: philips: Make sure clk_init_data is fully initialized
  rtc: nct3018y: Make sure clk_init_data is fully initialized
  rtc: m41t80: Make sure clk_init_data is fully initialized
  rtc: hym8563: Make sure clk_init_data is fully initialized
  rtc: rzn1: Add support for Renesas RZ/T2H and RZ/N2H SoCs
  rtc: rzn1: Drop trailing comma from OF match table sentinel
  rtc: rzn1: Add OF match data to gate SUBU register access
  rtc: rzn1: use FIELD_PREP/FIELD_GET and GENMASK for register access
  rtc: rzn1: Consistently use dev_err_probe()
  rtc: rzn1: Use temporary variable for struct device
  rtc: rzn1: Dynamically calculate synchronization delay based on clock rate
  rtc: rzn1: Replace remove callback with devm_add_action_or_reset()
  rtc: rzn1: Use pm_runtime_put_sync()
  rtc: Kconfig: Broaden RTC_DRV_RZN1 dependency to ARCH_RENESAS
  rtc: rzn1: Fix malformed MODULE_AUTHOR string
  rtc: rzn1: Disable alarm interrupt before reprogramming alarm registers
  rtc: rzn1: Fix alarm range check truncation on 32-bit systems
  ...
This commit is contained in:
Linus Torvalds
2026-08-28 09:53:43 -07:00
31 changed files with 507 additions and 295 deletions

View File

@@ -1,21 +0,0 @@
* Microchip PIC32 Real Time Clock and Calendar
The RTCC keeps time in hours, minutes, and seconds, and one half second. It
provides a calendar in weekday, date, month, and year. It also provides a
configurable alarm.
Required properties:
- compatible: should be: "microchip,pic32mzda-rtc"
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: RTC alarm/event interrupt
- clocks: clock phandle
Example:
rtc: rtc@1f8c0000 {
compatible = "microchip,pic32mzda-rtc";
reg = <0x1f8c0000 0x60>;
interrupts = <166 IRQ_TYPE_EDGE_RISING>;
clocks = <&PBCLK6>;
};

View File

@@ -0,0 +1,50 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/microchip,pic32mzda-rtc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Microchip PIC32 Real Time Clock and Calendar
maintainers:
- Alexandre Belloni <alexandre.belloni@bootlin.com>
description: |
The Microchip PIC32 Real Time Clock and Calendar (RTCC) keeps time in hours,
minutes, seconds, and one half second. It also provides a calendar with
weekday, date, month, and year, along with a configurable alarm.
allOf:
- $ref: rtc.yaml#
properties:
compatible:
const: microchip,pic32mzda-rtc
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
rtc@1f8c0000 {
compatible = "microchip,pic32mzda-rtc";
reg = <0x1f8c0000 0x60>;
interrupts = <166 IRQ_TYPE_EDGE_RISING>;
clocks = <&PBCLK6>;
};

View File

@@ -9,15 +9,19 @@ title: Renesas RZ/N1 SoCs Real-Time Clock
maintainers:
- Miquel Raynal <miquel.raynal@bootlin.com>
allOf:
- $ref: rtc.yaml#
properties:
compatible:
items:
- enum:
- renesas,r9a06g032-rtc
- const: renesas,rzn1-rtc
oneOf:
- items:
- enum:
- renesas,r9a06g032-rtc
- const: renesas,rzn1-rtc
- const: renesas,r9a09g077-rtc
- items:
- const: renesas,r9a09g087-rtc
- const: renesas,r9a09g077-rtc
reg:
maxItems: 1
@@ -54,6 +58,23 @@ required:
- clock-names
- power-domains
allOf:
- $ref: rtc.yaml#
- if:
properties:
compatible:
contains:
enum:
- renesas,r9a09g077-rtc
- renesas,r9a09g087-rtc
then:
properties:
clocks:
minItems: 2
clock-names:
minItems: 2
unevaluatedProperties: false
examples:

View File

@@ -1,27 +0,0 @@
Motorola mc146818 compatible RTC
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Required properties:
- compatible : "motorola,mc146818"
- reg : should contain registers location and length.
Optional properties:
- interrupts : should contain interrupt.
- ctrl-reg : Contains the initial value of the control register also
called "Register B".
- freq-reg : Contains the initial value of the frequency register also
called "Register A".
"Register A" and "B" are usually initialized by the firmware (BIOS for
instance). If this is not done, it can be performed by the driver.
ISA Example:
rtc@70 {
compatible = "motorola,mc146818";
interrupts = <8 3>;
interrupt-parent = <&ioapic1>;
ctrl-reg = <2>;
freq-reg = <0x26>;
reg = <1 0x70 2>;
};

View File

@@ -0,0 +1,63 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/rtc-cmos.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Motorola mc146818 compatible RTC
maintainers:
- Alexandre Belloni <alexandre.belloni@bootlin.com>
properties:
compatible:
oneOf:
- const: motorola,mc146818
- items:
- const: intel,ce4100-rtc
- const: motorola,mc146818
reg:
maxItems: 1
interrupts:
maxItems: 1
ctrl-reg:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Initial value of the control register
(also known as Register B).
freq-reg:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Initial value of the frequency register
(also known as Register A).
required:
- compatible
- reg
allOf:
- $ref: rtc.yaml#
unevaluatedProperties: false
examples:
- |
bus {
#address-cells = <2>;
#size-cells = <1>;
rtc@1,70 {
compatible = "motorola,mc146818";
reg = <0x1 0x70 0x2>;
interrupts = <8 3>;
ctrl-reg = <2>;
freq-reg = <0x26>;
};
};

View File

@@ -1,53 +0,0 @@
TI Real Time Clock
Required properties:
- compatible:
- "ti,da830-rtc" - for RTC IP used similar to that on DA8xx SoC family.
- "ti,am3352-rtc" - for RTC IP used similar to that on AM335x SoC family.
This RTC IP has special WAKE-EN Register to enable
Wakeup generation for event Alarm. It can also be
used to control an external PMIC via the
pmic_power_en pin.
- "ti,am4372-rtc" - for RTC IP used similar to that on AM437X SoC family.
- reg: Address range of rtc register set
- interrupts: rtc timer, alarm interrupts in order
Optional properties:
- system-power-controller: whether the rtc is controlling the system power
through pmic_power_en
- clocks: Any internal or external clocks feeding in to rtc
- clock-names: Corresponding names of the clocks
- pinctrl-0: a phandle pointing to the pin settings for the device
- pinctrl-names: should be "default"
Optional subnodes:
- generic pinctrl node
Required pinctrl subnodes properties:
- pins - Names of ext_wakeup pins to configure
Optional pinctrl subnodes properties:
- input-enable - Enables ext_wakeup
- ti,active-high - Set input active high (by default active low)
Example:
rtc@1c23000 {
compatible = "ti,da830-rtc";
reg = <0x23000 0x1000>;
interrupts = <19
19>;
interrupt-parent = <&intc>;
system-power-controller;
clocks = <&clk_32k_rtc>, <&clk_32768_ck>;
clock-names = "ext-clk", "int-clk";
pinctrl-0 = <&ext_wakeup>;
pinctrl-names = "default";
ext_wakeup: ext-wakeup {
pins = "ext_wakeup0";
input-enable;
ti,active-high;
};
};

View File

@@ -1,32 +0,0 @@
Palmas RTC controller bindings
Required properties:
- compatible:
- "ti,palmas-rtc" for palma series of the RTC controller
- interrupts: Interrupt number of RTC submodule on device.
Optional properties:
- ti,backup-battery-chargeable: The Palmas series device like TPS65913 or
TPS80036 supports the backup battery for powering the RTC when main
battery is removed or in very low power state. The backup battery
can be chargeable or non-chargeable. This flag will tells whether
battery is chargeable or not. If charging battery then driver can
enable the charging.
- ti,backup-battery-charge-high-current: Enable high current charging in
backup battery. Device supports the < 100uA and > 100uA charging.
The high current will be > 100uA. Absence of this property will
charge battery to lower current i.e. < 100uA.
Example:
palmas: tps65913@58 {
...
palmas_rtc: rtc {
compatible = "ti,palmas-rtc";
interrupt-parent = <&palmas>;
interrupts = <8 0>;
ti,backup-battery-chargeable;
ti,backup-battery-charge-high-current;
};
...
};

View File

@@ -0,0 +1,140 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/ti,omap-rtc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments OMAP Real Time Clock
maintainers:
- Keerthy <j-keerthy@ti.com>
- Afzal Mohammed <afzal@ti.com>
description:
The OMAP RTC is a year/month/day/hours/minutes/seconds BCD clock with
century-range alarm matching, driven by the 32kHz clock.
properties:
compatible:
oneOf:
- const: ti,da830-rtc
- items:
- const: ti,am3352-rtc
- const: ti,da830-rtc
- items:
- const: ti,am4372-rtc
- const: ti,am3352-rtc
- const: ti,da830-rtc
reg:
maxItems: 1
interrupts:
minItems: 2
maxItems: 2
system-power-controller:
type: boolean
description:
Indicates that this RTC controls system power via the pmic_power_en pin.
clocks:
minItems: 1
maxItems: 2
clock-names:
minItems: 1
items:
- enum: [ext-clk, int-clk]
- const: int-clk
pinctrl-0:
description:
Phandle to pin configuration for the external wakeup pins.
pinctrl-names:
minItems: 1
ti,hwmods:
$ref: /schemas/types.yaml#/definitions/string
description:
Name of the hwmod associated with the RTC.
const: rtc
deprecated: true
patternProperties:
"^ext-wakeup(-[0-9]+)?$":
type: object
description:
Child node describing external wakeup pin configuration.
properties:
pins:
pattern: '^ext_wakeup[0-3]$'
input-enable:
type: boolean
description:
Enables the external wakeup input on the selected pin.
ti,active-high:
type: boolean
description:
Sets the wakeup input polarity to active high. By default the
input is active low.
required:
- pins
additionalProperties: false
required:
- compatible
- reg
- interrupts
allOf:
- $ref: rtc.yaml#
- if:
not:
properties:
compatible:
contains:
const: ti,am3352-rtc
then:
properties:
system-power-controller: false
patternProperties:
"^ext-wakeup(-[0-9]+)?$": false
unevaluatedProperties: false
examples:
- |
rtc@23000 {
compatible = "ti,da830-rtc";
reg = <0x23000 0x1000>;
interrupts = <19>, <19>;
clocks = <&clk_32768_ck>;
clock-names = "int-clk";
};
- |
rtc@0 {
compatible = "ti,am3352-rtc", "ti,da830-rtc";
reg = <0x0 0x1000>;
interrupts = <75>, <76>;
system-power-controller;
clocks = <&clk_32k_rtc>, <&clk_32768_ck>;
clock-names = "ext-clk", "int-clk";
pinctrl-0 = <&ext_wakeup>;
pinctrl-names = "default";
ext-wakeup {
pins = "ext_wakeup0";
input-enable;
ti,active-high;
};
};

View File

@@ -0,0 +1,57 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/ti,palmas-rtc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments Palmas RTC
maintainers:
- Eduard Bostina <egbostina@gmail.com>
allOf:
- $ref: /schemas/rtc/rtc.yaml#
properties:
compatible:
const: ti,palmas-rtc
interrupts:
maxItems: 1
wakeup-source: true
ti,backup-battery-chargeable:
type: boolean
description:
The backup battery can be chargeable or non-chargeable. This flag
indicates whether the battery is chargeable. If present, the driver
can enable charging.
ti,backup-battery-charge-high-current:
type: boolean
description:
Enable high current charging in the backup battery.
Device supports the < 100uA and > 100uA charging. The high current will
be > 100uA. Absence of this property will charge battery to lower
current i.e. < 100uA.
required:
- compatible
- interrupts
unevaluatedProperties: false
examples:
- |
pmic {
#address-cells = <1>;
#size-cells = <0>;
rtc {
compatible = "ti,palmas-rtc";
interrupts = <8 0>;
ti,backup-battery-chargeable;
ti,backup-battery-charge-high-current;
};
};

View File

@@ -22949,7 +22949,7 @@ REAL TIME CLOCK (RTC) SUBSYSTEM
M: Alexandre Belloni <alexandre.belloni@bootlin.com>
L: linux-rtc@vger.kernel.org
S: Maintained
Q: http://patchwork.ozlabs.org/project/rtc-linux/list/
Q: https://patchwork.kernel.org/project/linux-rtc/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git
F: Documentation/admin-guide/rtc.rst
F: Documentation/devicetree/bindings/rtc/

View File

@@ -1635,10 +1635,11 @@ config RTC_DRV_RS5C313
config RTC_DRV_RZN1
tristate "Renesas RZ/N1 RTC"
depends on ARCH_RZN1 || COMPILE_TEST
depends on ARCH_RENESAS || COMPILE_TEST
depends on OF && HAS_IOMEM
help
If you say yes here you get support for the Renesas RZ/N1 RTC.
If you say yes here you get support for the RTC initially found on
Renesas RZ/N1 SoCs.
config RTC_DRV_GENERIC
tristate "Generic RTC support"
@@ -2106,7 +2107,8 @@ config RTC_DRV_MACSMC
config RTC_DRV_MSC313
tristate "MStar MSC313 RTC"
depends on ARCH_MSTARV7 || COMPILE_TEST
depends on ARCH_MSTARV7 || COMPILE_TEST
default ARCH_MSTARV7
help
If you say yes here you get support for the Mstar MSC313e On-Chip
Real Time Clock.

View File

@@ -549,6 +549,7 @@ static const struct i2c_device_id abeoz9_id[] = {
{ .name = "abeoz9" },
{ }
};
MODULE_DEVICE_TABLE(i2c, abeoz9_id);
static struct i2c_driver abeoz9_driver = {
.driver = {

View File

@@ -413,6 +413,7 @@ static const __maybe_unused struct of_device_id brcmstb_waketmr_of_match[] = {
{ .compatible = "brcm,brcmstb-waketimer" },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, brcmstb_waketmr_of_match);
static struct platform_driver brcmstb_waketmr_driver = {
.probe = brcmstb_waketmr_probe,

View File

@@ -661,7 +661,7 @@ static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t)
if (ret < 0)
return ret;
ctl[0] &= RX8130_REG_EXTENSION_WADA;
ctl[0] |= RX8130_REG_EXTENSION_WADA;
ctl[1] &= ~RX8130_REG_FLAG_AF;
ctl[2] &= ~RX8130_REG_CONTROL0_AIE;

View File

@@ -120,7 +120,7 @@ static ssize_t ds1343_store_glitchfilter(struct device *dev,
return count;
}
static DEVICE_ATTR(glitch_filter, S_IRUGO | S_IWUSR, ds1343_show_glitchfilter,
static DEVICE_ATTR(glitch_filter, 0644, ds1343_show_glitchfilter,
ds1343_store_glitchfilter);
static int ds1343_nvram_write(void *priv, unsigned int off, void *val,
@@ -183,7 +183,7 @@ static ssize_t ds1343_show_tricklecharger(struct device *dev,
return sprintf(buf, "%s %s\n", diodes, resistors);
}
static DEVICE_ATTR(trickle_charger, S_IRUGO, ds1343_show_tricklecharger, NULL);
static DEVICE_ATTR(trickle_charger, 0444, ds1343_show_tricklecharger, NULL);
static struct attribute *ds1343_attrs[] = {
&dev_attr_glitch_filter.attr,

View File

@@ -355,9 +355,7 @@ static int gamecube_rtc_probe(struct platform_device *pdev)
rtc->range_max = U32_MAX;
rtc->ops = &gamecube_rtc_ops;
devm_rtc_register_device(rtc);
return 0;
return devm_rtc_register_device(rtc);
}
static const struct of_device_id gamecube_rtc_of_match[] = {

View File

@@ -376,8 +376,8 @@ static struct clk *hym8563_clkout_register_clk(struct hym8563 *hym8563)
{
struct i2c_client *client = hym8563->client;
struct device_node *node = client->dev.of_node;
struct clk_init_data init = {};
struct clk *clk;
struct clk_init_data init;
int ret;
ret = i2c_smbus_write_byte_data(client, HYM8563_CLKOUT,

View File

@@ -574,8 +574,8 @@ static struct clk *m41t80_sqw_register_clk(struct m41t80_data *m41t80)
struct i2c_client *client = m41t80->client;
struct device_node *node = client->dev.of_node;
struct device_node *fixed_clock;
struct clk_init_data init = {};
struct clk *clk;
struct clk_init_data init;
int ret;
fixed_clock = of_get_child_by_name(node, "clock");

View File

@@ -219,17 +219,15 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
if (IS_ERR(pdata->ioaddr))
return PTR_ERR(pdata->ioaddr);
pdata->clk = devm_clk_get(&pdev->dev, NULL);
/* Not all SoCs require a clock.*/
if (!IS_ERR(pdata->clk))
clk_prepare_enable(pdata->clk);
pdata->clk = devm_clk_get_optional_prepared(&pdev->dev, NULL);
if (IS_ERR(pdata->clk))
return PTR_ERR(pdata->clk);
/* make sure the 24 hour mode is enabled */
rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
if (rtc_time & RTC_HOURS_12H_MODE) {
dev_err(&pdev->dev, "12 Hour mode is enabled but not supported.\n");
ret = -EINVAL;
goto out;
return -EINVAL;
}
/* make sure it is actually functional */
@@ -238,8 +236,7 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
if (rtc_time == 0x01000000) {
dev_err(&pdev->dev, "internal RTC not ticking\n");
ret = -ENODEV;
goto out;
return -ENODEV;
}
}
@@ -249,8 +246,7 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
pdata->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(pdata->rtc)) {
ret = PTR_ERR(pdata->rtc);
goto out;
return PTR_ERR(pdata->rtc);
}
if (pdata->irq >= 0) {
@@ -264,7 +260,7 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
}
if (pdata->irq >= 0)
device_init_wakeup(&pdev->dev, true);
devm_device_init_wakeup(&pdev->dev);
else
clear_bit(RTC_FEATURE_ALARM, pdata->rtc->features);
@@ -275,24 +271,10 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
ret = devm_rtc_register_device(pdata->rtc);
if (!ret)
return 0;
out:
if (!IS_ERR(pdata->clk))
clk_disable_unprepare(pdata->clk);
return ret;
}
static void __exit mv_rtc_remove(struct platform_device *pdev)
{
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
if (pdata->irq >= 0)
device_init_wakeup(&pdev->dev, false);
if (!IS_ERR(pdata->clk))
clk_disable_unprepare(pdata->clk);
}
#ifdef CONFIG_OF
static const struct of_device_id rtc_mv_of_match_table[] = {
{ .compatible = "marvell,orion-rtc", },
@@ -323,14 +305,7 @@ static int mv_rtc_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(mv_rtc_pm_ops, mv_rtc_suspend, mv_rtc_resume);
/*
* mv_rtc_remove() lives in .exit.text. For drivers registered via
* module_platform_driver_probe() this is ok because they cannot get unbound at
* runtime. So mark the driver struct with __refdata to prevent modpost
* triggering a section mismatch warning.
*/
static struct platform_driver mv_rtc_driver __refdata = {
.remove = __exit_p(mv_rtc_remove),
static struct platform_driver mv_rtc_driver = {
.driver = {
.name = "rtc-mv",
.of_match_table = of_match_ptr(rtc_mv_of_match_table),

View File

@@ -459,8 +459,8 @@ static struct clk *nct3018y_clkout_register_clk(struct nct3018y *nct3018y)
{
struct i2c_client *client = nct3018y->client;
struct device_node *node = client->dev.of_node;
struct clk_init_data init = {};
struct clk *clk;
struct clk_init_data init;
init.name = "nct3018y-clkout";
init.ops = &nct3018y_clkout_ops;

View File

@@ -1184,12 +1184,7 @@ static int pcf2127_configure_interrupt_pins(struct device *dev)
if (ret)
return ret;
ret = regmap_write(pcf2127->regmap,
PCF2131_REG_INT_A_MASK2, 0);
if (ret)
return ret;
return ret;
return regmap_write(pcf2127->regmap, PCF2131_REG_INT_A_MASK2, 0);
}
static int pcf2127_probe(struct device *dev, struct regmap *regmap,

View File

@@ -498,7 +498,7 @@ static const struct clk_ops pcf85063_clkout_ops = {
static struct clk *pcf85063_clkout_register_clk(struct pcf85063 *pcf85063)
{
struct clk *clk;
struct clk_init_data init;
struct clk_init_data init = {};
struct device_node *node = pcf85063->rtc->dev.parent->of_node;
struct device_node *fixed_clock;

View File

@@ -426,8 +426,8 @@ static int pcf85363_probe(struct i2c_client *client)
err = pcf85363_load_capacitance(pcf85363, client->dev.of_node);
if (err < 0)
dev_warn(&client->dev, "failed to set xtal load capacitance: %d",
err);
return dev_err_probe(&client->dev, err,
"failed to set xtal load capacitance\n");
pcf85363->rtc->ops = &rtc_ops;
pcf85363->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
@@ -436,9 +436,16 @@ static int pcf85363_probe(struct i2c_client *client)
wakeup_source = device_property_read_bool(&client->dev,
"wakeup-source");
if (client->irq > 0 || wakeup_source) {
regmap_write(pcf85363->regmap, CTRL_FLAGS, 0);
regmap_update_bits(pcf85363->regmap, CTRL_PIN_IO,
PIN_IO_INTAPM, PIN_IO_INTA_OUT);
err = regmap_write(pcf85363->regmap, CTRL_FLAGS, 0);
if (err)
return dev_err_probe(&client->dev, err,
"failed to clear flags\n");
err = regmap_update_bits(pcf85363->regmap, CTRL_PIN_IO,
PIN_IO_INTAPM, PIN_IO_INTA_OUT);
if (err)
return dev_err_probe(&client->dev, err,
"failed to set interrupt pin mode\n");
}
if (client->irq > 0) {

View File

@@ -425,7 +425,7 @@ static const struct clk_ops pcf8563_clkout_ops = {
static struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563)
{
struct device_node *node = pcf8563->rtc->dev.parent->of_node;
struct clk_init_data init;
struct clk_init_data init = {};
struct clk *clk;
int ret;
@@ -449,7 +449,9 @@ static struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563)
clk = devm_clk_register(&pcf8563->rtc->dev, &pcf8563->clkout_hw);
if (!IS_ERR(clk))
of_clk_add_provider(node, of_clk_src_simple_get, clk);
devm_of_clk_add_hw_provider(pcf8563->rtc->dev.parent,
of_clk_hw_simple_get,
&pcf8563->clkout_hw);
return clk;
}

View File

@@ -816,7 +816,7 @@ static int rv3028_clkout_register_clk(struct rv3028_data *rv3028,
{
int ret;
struct clk *clk;
struct clk_init_data init;
struct clk_init_data init = {};
struct device_node *node = client->dev.of_node;
ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,

View File

@@ -752,7 +752,7 @@ static int rv3032_clkout_register_clk(struct rv3032_data *rv3032,
{
int ret;
struct clk *clk;
struct clk_init_data init;
struct clk_init_data init = {};
struct device_node *node = client->dev.of_node;
ret = regmap_update_bits(rv3032->regmap, RV3032_TLSB, RV3032_TLSB_CLKF, 0);

View File

@@ -12,10 +12,13 @@
*/
#include <linux/bcd.h>
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/init.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/rtc.h>
@@ -38,14 +41,18 @@
#define RZN1_RTC_CTL2_STOPPED (RZN1_RTC_CTL2_WAIT | RZN1_RTC_CTL2_WST)
#define RZN1_RTC_TIME 0x30
#define RZN1_RTC_TIME_MIN_SHIFT 8
#define RZN1_RTC_TIME_HOUR_SHIFT 16
#define RZN1_RTC_TIME_SEC GENMASK(7, 0)
#define RZN1_RTC_TIME_MIN GENMASK(15, 8)
#define RZN1_RTC_TIME_HOUR GENMASK(23, 16)
#define RZN1_RTC_CAL 0x34
#define RZN1_RTC_CAL_DAY_SHIFT 8
#define RZN1_RTC_CAL_MON_SHIFT 16
#define RZN1_RTC_CAL_YEAR_SHIFT 24
#define RZN1_RTC_CAL_WDAY GENMASK(7, 0)
#define RZN1_RTC_CAL_DAY GENMASK(15, 8)
#define RZN1_RTC_CAL_MON GENMASK(23, 16)
#define RZN1_RTC_CAL_YEAR GENMASK(31, 24)
#define RZN1_RTC_SUBU 0x38
#define RZN1_RTC_SUBU_RTCA0FX GENMASK(5, 0)
#define RZN1_RTC_SUBU_DEV BIT(7)
#define RZN1_RTC_SUBU_DECR BIT(6)
@@ -59,6 +66,10 @@
#define RZN1_RTC_TIMEC 0x68
#define RZN1_RTC_CALC 0x6c
struct rzn1_rtc_data {
bool has_subu;
};
struct rzn1_rtc {
struct rtc_device *rtcdev;
void __iomem *base;
@@ -69,6 +80,7 @@ struct rzn1_rtc {
*/
spinlock_t ctl1_access_lock;
struct rtc_time tm_alarm;
unsigned long sync_time;
};
static void rzn1_rtc_get_time_snapshot(struct rzn1_rtc *rtc, struct rtc_time *tm)
@@ -76,15 +88,15 @@ static void rzn1_rtc_get_time_snapshot(struct rzn1_rtc *rtc, struct rtc_time *tm
u32 val;
val = readl(rtc->base + RZN1_RTC_TIMEC);
tm->tm_sec = bcd2bin(val);
tm->tm_min = bcd2bin(val >> RZN1_RTC_TIME_MIN_SHIFT);
tm->tm_hour = bcd2bin(val >> RZN1_RTC_TIME_HOUR_SHIFT);
tm->tm_sec = bcd2bin(FIELD_GET(RZN1_RTC_TIME_SEC, val));
tm->tm_min = bcd2bin(FIELD_GET(RZN1_RTC_TIME_MIN, val));
tm->tm_hour = bcd2bin(FIELD_GET(RZN1_RTC_TIME_HOUR, val));
val = readl(rtc->base + RZN1_RTC_CALC);
tm->tm_wday = val & 0x0f;
tm->tm_mday = bcd2bin(val >> RZN1_RTC_CAL_DAY_SHIFT);
tm->tm_mon = bcd2bin(val >> RZN1_RTC_CAL_MON_SHIFT) - 1;
tm->tm_year = bcd2bin(val >> RZN1_RTC_CAL_YEAR_SHIFT) + 100;
tm->tm_wday = FIELD_GET(RZN1_RTC_CAL_WDAY, val);
tm->tm_mday = bcd2bin(FIELD_GET(RZN1_RTC_CAL_DAY, val));
tm->tm_mon = bcd2bin(FIELD_GET(RZN1_RTC_CAL_MON, val)) - 1;
tm->tm_year = bcd2bin(FIELD_GET(RZN1_RTC_CAL_YEAR, val)) + 100;
}
static int rzn1_rtc_read_time(struct device *dev, struct rtc_time *tm)
@@ -119,23 +131,23 @@ static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm)
/* Hold the counter if it was counting up */
writel(RZN1_RTC_CTL2_WAIT, rtc->base + RZN1_RTC_CTL2);
/* Wait for the counter to stop: two 32k clock cycles */
usleep_range(61, 100);
/* Wait 2-4 RTC_PCLK clock cycles for the counter to stop */
usleep_range(rtc->sync_time, rtc->sync_time * 2);
ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL2, val,
val & RZN1_RTC_CTL2_WST, 0, 100);
if (ret)
return ret;
}
val = bin2bcd(tm->tm_sec);
val |= bin2bcd(tm->tm_min) << RZN1_RTC_TIME_MIN_SHIFT;
val |= bin2bcd(tm->tm_hour) << RZN1_RTC_TIME_HOUR_SHIFT;
val = FIELD_PREP(RZN1_RTC_TIME_SEC, bin2bcd(tm->tm_sec)) |
FIELD_PREP(RZN1_RTC_TIME_MIN, bin2bcd(tm->tm_min)) |
FIELD_PREP(RZN1_RTC_TIME_HOUR, bin2bcd(tm->tm_hour));
writel(val, rtc->base + RZN1_RTC_TIME);
val = tm->tm_wday;
val |= bin2bcd(tm->tm_mday) << RZN1_RTC_CAL_DAY_SHIFT;
val |= bin2bcd(tm->tm_mon + 1) << RZN1_RTC_CAL_MON_SHIFT;
val |= bin2bcd(tm->tm_year - 100) << RZN1_RTC_CAL_YEAR_SHIFT;
val = FIELD_PREP(RZN1_RTC_CAL_WDAY, tm->tm_wday) |
FIELD_PREP(RZN1_RTC_CAL_DAY, bin2bcd(tm->tm_mday)) |
FIELD_PREP(RZN1_RTC_CAL_MON, bin2bcd(tm->tm_mon + 1)) |
FIELD_PREP(RZN1_RTC_CAL_YEAR, bin2bcd(tm->tm_year - 100));
writel(val, rtc->base + RZN1_RTC_CAL);
writel(0, rtc->base + RZN1_RTC_CTL2);
@@ -234,13 +246,24 @@ static int rzn1_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
if (ret)
return ret;
ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
alrm->enabled = !!(ctl1 & (RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE));
min = readl(rtc->base + RZN1_RTC_ALM);
hour = readl(rtc->base + RZN1_RTC_ALH);
wday = readl(rtc->base + RZN1_RTC_ALW);
tm->tm_sec = 0;
tm->tm_min = bcd2bin(min);
tm->tm_hour = bcd2bin(hour);
/*
* If wday is zero, no bit is set in RZN1_RTC_ALW. This is the
* register's power-on reset value.
*/
wday = readl(rtc->base + RZN1_RTC_ALW);
if (!wday)
return 0;
delta_days = ((fls(wday) - 1) - tm->tm_wday + 7) % 7;
tm->tm_wday = fls(wday) - 1;
@@ -249,9 +272,6 @@ static int rzn1_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
rtc_time64_to_tm(alarm, tm);
}
ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
alrm->enabled = !!(ctl1 & (RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE));
return 0;
}
@@ -259,8 +279,7 @@ static int rzn1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct rzn1_rtc *rtc = dev_get_drvdata(dev);
struct rtc_time *tm = &alrm->time, tm_now;
unsigned long alarm, farest;
unsigned int days_ahead, wday;
time64_t alarm, farest;
int ret;
ret = rzn1_rtc_read_time(dev, &tm_now);
@@ -270,16 +289,17 @@ static int rzn1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
/* We cannot set alarms more than one week ahead */
farest = rtc_tm_to_time64(&tm_now) + rtc->rtcdev->alarm_offset_max;
alarm = rtc_tm_to_time64(tm);
if (time_after(alarm, farest))
if (alarm > farest)
return -ERANGE;
/* Convert alarm day into week day */
days_ahead = tm->tm_mday - tm_now.tm_mday;
wday = (tm_now.tm_wday + days_ahead) % 7;
/* Disable alarm interrupts before reprogramming the alarm. */
ret = rzn1_rtc_alarm_irq_enable(dev, 0);
if (ret)
return ret;
writel(bin2bcd(tm->tm_min), rtc->base + RZN1_RTC_ALM);
writel(bin2bcd(tm->tm_hour), rtc->base + RZN1_RTC_ALH);
writel(BIT(wday), rtc->base + RZN1_RTC_ALW);
writel(BIT(tm->tm_wday), rtc->base + RZN1_RTC_ALW);
rtc->tm_alarm = alrm->time;
@@ -298,12 +318,12 @@ static int rzn1_rtc_read_offset(struct device *dev, long *offset)
val = readl(rtc->base + RZN1_RTC_SUBU);
ppb_per_step = val & RZN1_RTC_SUBU_DEV ? 1017 : 3051;
subtract = val & RZN1_RTC_SUBU_DECR;
val &= 0x3F;
val = FIELD_GET(RZN1_RTC_SUBU_RTCA0FX, val);
if (!val)
*offset = 0;
else if (subtract)
*offset = -(((~val) & 0x3F) + 1) * ppb_per_step;
*offset = -(((~val) & RZN1_RTC_SUBU_RTCA0FX) + 1) * ppb_per_step;
else
*offset = (val - 1) * ppb_per_step;
@@ -345,7 +365,7 @@ static int rzn1_rtc_set_offset(struct device *dev, long offset)
subu |= steps + 1;
} else {
subu |= RZN1_RTC_SUBU_DECR;
subu |= (~(-steps - 1)) & 0x3F;
subu |= (~(-steps - 1)) & RZN1_RTC_SUBU_RTCA0FX;
}
ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL2, ctl2,
@@ -376,15 +396,32 @@ static const struct rtc_class_ops rzn1_rtc_ops_scmp = {
.alarm_irq_enable = rzn1_rtc_alarm_irq_enable,
};
static void rzn1_rtc_disable_hardware(void *data)
{
struct device *dev = data;
struct rzn1_rtc *rtc = dev_get_drvdata(dev);
/* Disable all interrupts */
writel(0, rtc->base + RZN1_RTC_CTL1);
pm_runtime_put_sync(dev);
}
static int rzn1_rtc_probe(struct platform_device *pdev)
{
const struct rzn1_rtc_data *data;
struct device *dev = &pdev->dev;
unsigned long rate = 32768;
struct rzn1_rtc *rtc;
u32 val, scmp_val = 0;
struct clk *xtal;
unsigned long rate;
int irq, ret;
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
data = of_device_get_match_data(dev);
if (!data)
return -ENODEV;
rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc)
return -ENOMEM;
@@ -392,13 +429,13 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
rtc->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rtc->base))
return dev_err_probe(&pdev->dev, PTR_ERR(rtc->base), "Missing reg\n");
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(&pdev->dev);
rtc->rtcdev = devm_rtc_allocate_device(dev);
if (IS_ERR(rtc->rtcdev))
return PTR_ERR(rtc->rtcdev);
@@ -406,38 +443,47 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
rtc->rtcdev->range_max = RTC_TIMESTAMP_END_2099;
rtc->rtcdev->alarm_offset_max = 7 * 86400;
ret = devm_pm_runtime_enable(&pdev->dev);
ret = devm_pm_runtime_enable(dev);
if (ret < 0)
return ret;
ret = pm_runtime_resume_and_get(&pdev->dev);
ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
return ret;
ret = devm_add_action_or_reset(dev, rzn1_rtc_disable_hardware, dev);
if (ret)
return ret;
/* Only switch to scmp if we have an xtal clock with a valid rate and != 32768 */
xtal = devm_clk_get_optional(&pdev->dev, "xtal");
xtal = devm_clk_get_optional(dev, "xtal");
if (IS_ERR(xtal)) {
ret = PTR_ERR(xtal);
goto dis_runtime_pm;
return PTR_ERR(xtal);
} else if (xtal) {
rate = clk_get_rate(xtal);
if (rate < 32000 || rate > BIT(22)) {
ret = -EOPNOTSUPP;
goto dis_runtime_pm;
}
if (rate < 32000 || rate > BIT(22))
return -EOPNOTSUPP;
if (rate != 32768)
if (rate != 32768 || !data->has_subu)
scmp_val = RZN1_RTC_CTL0_SLSB_SCMP;
} else if (!data->has_subu) {
/* xtal is NULL here */
return dev_err_probe(dev, -EOPNOTSUPP,
"No valid XTAL provided and SUBU mode not supported\n");
}
/* Calculate the duration of two RTC_PCLK clock cycles */
rtc->sync_time = DIV_ROUND_UP(2 * USEC_PER_SEC, rate);
/* Disable controller during SUBU/SCMP setup */
val = readl(rtc->base + RZN1_RTC_CTL0) & ~RZN1_RTC_CTL0_CE;
writel(val, rtc->base + RZN1_RTC_CTL0);
/* Wait 2-4 32k clock cycles for the disabled controller */
/* Wait 2-4 RTC_PCLK clock cycles for the disabled controller to stop */
ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL0, val,
!(val & RZN1_RTC_CTL0_CEST), 62, 123);
!(val & RZN1_RTC_CTL0_CEST), rtc->sync_time,
rtc->sync_time * 2);
if (ret)
goto dis_runtime_pm;
return ret;
/* Set desired modes leaving the controller disabled */
writel(RZN1_RTC_CTL0_AMPM | scmp_val, rtc->base + RZN1_RTC_CTL0);
@@ -457,53 +503,42 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
spin_lock_init(&rtc->ctl1_access_lock);
ret = devm_request_irq(&pdev->dev, irq, rzn1_rtc_alarm_irq, 0, "RZN1 RTC Alarm", rtc);
if (ret) {
dev_err(&pdev->dev, "RTC alarm interrupt not available\n");
goto dis_runtime_pm;
}
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(&pdev->dev, irq, rzn1_rtc_1s_irq, 0, "RZN1 RTC 1s", rtc);
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(&pdev->dev, "RTC pps interrupt not available. Alarm has only minute accuracy\n");
dev_warn(dev, "RTC pps interrupt not available. Alarm has only minute accuracy\n");
}
ret = devm_rtc_register_device(rtc->rtcdev);
if (ret)
goto dis_runtime_pm;
return 0;
dis_runtime_pm:
pm_runtime_put(&pdev->dev);
return ret;
return devm_rtc_register_device(rtc->rtcdev);
}
static void rzn1_rtc_remove(struct platform_device *pdev)
{
struct rzn1_rtc *rtc = platform_get_drvdata(pdev);
static const struct rzn1_rtc_data rzn1_rtc_rzt2h_data = {
.has_subu = false,
};
/* Disable all interrupts */
writel(0, rtc->base + RZN1_RTC_CTL1);
pm_runtime_put(&pdev->dev);
}
static const struct rzn1_rtc_data rzn1_rtc_rzn1_data = {
.has_subu = true,
};
static const struct of_device_id rzn1_rtc_of_match[] = {
{ .compatible = "renesas,rzn1-rtc" },
{},
{ .compatible = "renesas,r9a09g077-rtc", .data = &rzn1_rtc_rzt2h_data },
{ .compatible = "renesas,rzn1-rtc", .data = &rzn1_rtc_rzn1_data },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, rzn1_rtc_of_match);
static struct platform_driver rzn1_rtc_driver = {
.probe = rzn1_rtc_probe,
.remove = rzn1_rtc_remove,
.driver = {
.name = "rzn1-rtc",
.of_match_table = rzn1_rtc_of_match,
@@ -512,6 +547,6 @@ static struct platform_driver rzn1_rtc_driver = {
module_platform_driver(rzn1_rtc_driver);
MODULE_AUTHOR("Michel Pollet <buserror@gmail.com>");
MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com");
MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
MODULE_DESCRIPTION("RZ/N1 RTC driver");
MODULE_LICENSE("GPL");

View File

@@ -366,6 +366,7 @@ static const struct of_device_id rtc_dt_ids[] = {
{ .compatible = "nxp,s32g2-rtc", .data = &rtc_s32g2_data },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, rtc_dt_ids);
static DEFINE_SIMPLE_DEV_PM_OPS(s32g_rtc_pm_ops,
s32g_rtc_suspend, s32g_rtc_resume);

View File

@@ -57,8 +57,9 @@ static int p1_rtc_read_time(struct device *dev, struct rtc_time *t)
u8 time[6];
int ret;
if (!regmap_test_bits(regmap, RTC_CTRL, RTC_EN))
return -EINVAL; /* RTC is disabled */
ret = regmap_test_bits(regmap, RTC_CTRL, RTC_EN);
if (ret <= 0)
return ret ?: -EINVAL; /* RTC is disabled or error */
ret = regmap_bulk_read(regmap, RTC_TIME, time, sizeof(time));
if (ret)

View File

@@ -18,7 +18,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
@@ -212,11 +211,9 @@ static int st_rtc_probe(struct platform_device *pdev)
if (IS_ERR(rtc->ioaddr))
return PTR_ERR(rtc->ioaddr);
rtc->irq = irq_of_parse_and_map(np, 0);
if (!rtc->irq) {
dev_err(&pdev->dev, "IRQ missing or invalid\n");
return -EINVAL;
}
rtc->irq = platform_get_irq(pdev, 0);
if (rtc->irq < 0)
return rtc->irq;
ret = devm_request_irq(&pdev->dev, rtc->irq, st_rtc_handler,
IRQF_NO_AUTOEN, pdev->name, rtc);

View File

@@ -334,10 +334,9 @@ static int xlnx_rtc_probe(struct platform_device *pdev)
/* Getting the rtc info */
xrtcdev->rtc_clk = devm_clk_get_optional(&pdev->dev, "rtc");
if (IS_ERR(xrtcdev->rtc_clk)) {
if (PTR_ERR(xrtcdev->rtc_clk) != -EPROBE_DEFER)
dev_warn(&pdev->dev, "Device clock not found.\n");
}
if (IS_ERR(xrtcdev->rtc_clk))
return dev_err_probe(&pdev->dev, PTR_ERR(xrtcdev->rtc_clk),
"Failed to get rtc clock\n");
xrtcdev->freq = clk_get_rate(xrtcdev->rtc_clk);
if (!xrtcdev->freq) {
ret = of_property_read_u32(pdev->dev.of_node, "calibration",