Commit 3d076fec authored by Linus Torvalds's avatar Linus Torvalds

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

Pull RTC updates from Alexandre Belloni:
 "New drivers:
   - Microchip PolarFire
   - Nuvoton NCT3018Y
   - TI K3 RTC

  Subsystem:
   - Replace flush_scheduled_work() with flush_work()
   - Remove deprecated ida_simple_get()/ida_simple_remove() calls

  Drivers:
   - use simple i2c probe where possible
   - sun6i: add R329 support
   - zynqmp: add calibration support
   - vr41xx: remove unused driver"

* tag 'rtc-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (31 commits)
  rtc: spear: set range max
  rtc: rtc-cmos: Do not check ACPI_FADT_LOW_POWER_S0
  rtc: zynqmp: initialize fract_tick
  rtc: Add NCT3018Y real time clock driver
  dt-bindings: rtc: nuvoton: add NCT3018Y Real Time Clock
  dt-bindings: rtc: nxp,pcf85063: Convert to DT schema
  dt-bindings: rtc: microcrystal,rv3032: Add missing type to 'trickle-voltage-millivolt'
  rtc: rx8025: fix 12/24 hour mode detection on RX-8035
  rtc: cros-ec: Only warn once in .remove() about notifier_chain problems
  rtc: vr41xx: remove driver
  rtc: mpfs: remove 'pending' variable from mpfs_rtc_wakeup_irq_handler()
  rtc: rv8803: fix missing unlock on error in rv8803_set_time()
  rtc: zynqmp: Add calibration set and get support
  rtc: zynqmp: Updated calibration value
  dt-bindings: rtc: zynqmp: Add clock information
  rtc: sun6i: add support for R329 RTC
  rtc: Directly use ida_alloc()/free()
  rtc: Introduce ti-k3-rtc
  dt-bindings: rtc: Add TI K3 RTC description
  dt-bindings: rtc: qcom-pm8xxx-rtc: Update the maintainers section
  ...
parents 4a935059 03c4cd6f
...@@ -32,6 +32,7 @@ properties: ...@@ -32,6 +32,7 @@ properties:
- 11000 - 11000
trickle-voltage-millivolt: trickle-voltage-millivolt:
$ref: /schemas/types.yaml#/definitions/uint32
enum: enum:
- 1750 - 1750
- 3000 - 3000
......
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/nuvoton,nct3018y.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NUVOTON NCT3018Y Real Time Clock
allOf:
- $ref: "rtc.yaml#"
maintainers:
- Medad CChien <ctcchien@nuvoton.com>
- Mia Lin <mimi05633@gmail.com>
properties:
compatible:
const: nuvoton,nct3018y
reg:
maxItems: 1
start-year: true
reset-source: true
required:
- compatible
- reg
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
rtc@6f {
compatible = "nuvoton,nct3018y";
reg = <0x6f>;
};
};
...
* NXP PCF85063 Real Time Clock
Required properties:
- compatible: Should one of contain:
"nxp,pca85073a",
"nxp,pcf85063",
"nxp,pcf85063a",
"nxp,pcf85063tp",
"microcrystal,rv8263"
- reg: I2C address for chip.
Optional property:
- quartz-load-femtofarads: The capacitive load of the quartz(x-tal),
expressed in femto Farad (fF). Valid values are 7000 and 12500.
Default value (if no value is specified) is 7000fF.
Optional child node:
- clock: Provide this if the square wave pin is used as boot-enabled fixed clock.
Example:
pcf85063: rtc@51 {
compatible = "nxp,pcf85063";
reg = <0x51>;
quartz-load-femtofarads = <12500>;
clock {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/nxp,pcf85063.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP PCF85063 Real Time Clock
maintainers:
- Alexander Stein <alexander.stein@ew.tq-group.com>
properties:
compatible:
enum:
- microcrystal,rv8263
- nxp,pcf85063
- nxp,pcf85063a
- nxp,pcf85063tp
- nxp,pca85073a
reg:
maxItems: 1
"#clock-cells":
const: 0
clock-output-names:
maxItems: 1
interrupts:
maxItems: 1
quartz-load-femtofarads:
description:
The capacitive load of the quartz(x-tal).
enum: [7000, 12500]
default: 7000
clock:
$ref: /schemas/clock/fixed-clock.yaml
description:
Provide this if the square wave pin is used as boot-enabled
fixed clock.
wakeup-source: true
allOf:
- $ref: rtc.yaml#
- if:
properties:
compatible:
contains:
enum:
- microcrystal,rv8263
then:
properties:
quartz-load-femtofarads: false
- if:
properties:
compatible:
contains:
enum:
- nxp,pcf85063
then:
properties:
quartz-load-femtofarads:
const: 7000
required:
- compatible
- reg
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
rtc@51 {
compatible = "nxp,pcf85063a";
reg = <0x51>;
quartz-load-femtofarads = <12500>;
clock {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
};
};
};
...@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# ...@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm PM8xxx PMIC RTC device title: Qualcomm PM8xxx PMIC RTC device
maintainers: maintainers:
- Satya Priya <skakit@codeaurora.org> - Satya Priya <quic_c_skakit@quicinc.com>
properties: properties:
compatible: compatible:
......
...@@ -14,6 +14,8 @@ For MediaTek PMIC wrapper bus bindings, see: ...@@ -14,6 +14,8 @@ For MediaTek PMIC wrapper bus bindings, see:
Required properties: Required properties:
- compatible: Should be one of follows - compatible: Should be one of follows
"mediatek,mt6323-rtc": for MT6323 PMIC "mediatek,mt6323-rtc": for MT6323 PMIC
"mediatek,mt6358-rtc": for MT6358 PMIC
"mediatek,mt6366-rtc", "mediatek,mt6358-rtc": for MT6366 PMIC
"mediatek,mt6397-rtc": for MT6397 PMIC "mediatek,mt6397-rtc": for MT6397 PMIC
Example: Example:
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/ti,k3-rtc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments K3 Real Time Clock
maintainers:
- Nishanth Menon <nm@ti.com>
description: |
This RTC appears in the AM62x family of SoCs.
allOf:
- $ref: "rtc.yaml#"
properties:
compatible:
enum:
- ti,am62-rtc
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: VBUS Interface clock
- description: 32k Clock source (external or internal).
clock-names:
items:
- const: vbus
- const: osc32k
power-domains:
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
rtc@2b1f0000 {
compatible = "ti,am62-rtc";
reg = <0x2b1f0000 0x100>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&bar 0>;
clocks = <&foo 0>, <&foo 1>;
clock-names = "vbus", "osc32k";
wakeup-source;
};
...@@ -23,8 +23,15 @@ properties: ...@@ -23,8 +23,15 @@ properties:
reg: reg:
maxItems: 1 maxItems: 1
clocks:
maxItems: 1
clock-names:
items:
- const: rtc
interrupts: interrupts:
minItems: 2 maxItems: 2
interrupt-names: interrupt-names:
items: items:
...@@ -39,6 +46,7 @@ properties: ...@@ -39,6 +46,7 @@ properties:
minimum: 0x1 minimum: 0x1
maximum: 0x1FFFFF maximum: 0x1FFFFF
default: 0x198233 default: 0x198233
deprecated: true
required: required:
- compatible - compatible
...@@ -61,5 +69,7 @@ examples: ...@@ -61,5 +69,7 @@ examples:
interrupts = <0 26 4>, <0 27 4>; interrupts = <0 26 4>, <0 27 4>;
interrupt-names = "alarm", "sec"; interrupt-names = "alarm", "sec";
calibration = <0x198233>; calibration = <0x198233>;
clock-names = "rtc";
clocks = <&rtc_clk>;
}; };
}; };
...@@ -2486,11 +2486,13 @@ S: Supported ...@@ -2486,11 +2486,13 @@ S: Supported
F: Documentation/devicetree/bindings/*/*/*npcm* F: Documentation/devicetree/bindings/*/*/*npcm*
F: Documentation/devicetree/bindings/*/*npcm* F: Documentation/devicetree/bindings/*/*npcm*
F: Documentation/devicetree/bindings/arm/npcm/* F: Documentation/devicetree/bindings/arm/npcm/*
F: Documentation/devicetree/bindings/rtc/nuvoton,nct3018y.yaml
F: arch/arm/boot/dts/nuvoton-npcm* F: arch/arm/boot/dts/nuvoton-npcm*
F: arch/arm/mach-npcm/ F: arch/arm/mach-npcm/
F: arch/arm64/boot/dts/nuvoton/ F: arch/arm64/boot/dts/nuvoton/
F: drivers/*/*npcm* F: drivers/*/*npcm*
F: drivers/*/*/*npcm* F: drivers/*/*/*npcm*
F: drivers/rtc/rtc-nct3018y.c
F: include/dt-bindings/clock/nuvoton,npcm7xx-clock.h F: include/dt-bindings/clock/nuvoton,npcm7xx-clock.h
F: include/dt-bindings/clock/nuvoton,npcm845-clk.h F: include/dt-bindings/clock/nuvoton,npcm845-clk.h
...@@ -17529,6 +17531,7 @@ F: drivers/char/hw_random/mpfs-rng.c ...@@ -17529,6 +17531,7 @@ F: drivers/char/hw_random/mpfs-rng.c
F: drivers/clk/microchip/clk-mpfs.c F: drivers/clk/microchip/clk-mpfs.c
F: drivers/mailbox/mailbox-mpfs.c F: drivers/mailbox/mailbox-mpfs.c
F: drivers/pci/controller/pcie-microchip-host.c F: drivers/pci/controller/pcie-microchip-host.c
F: drivers/rtc/rtc-mpfs.c
F: drivers/soc/microchip/ F: drivers/soc/microchip/
F: drivers/spi/spi-microchip-core.c F: drivers/spi/spi-microchip-core.c
F: drivers/usb/musb/mpfs.c F: drivers/usb/musb/mpfs.c
......
...@@ -383,6 +383,16 @@ config RTC_DRV_MAX77686 ...@@ -383,6 +383,16 @@ config RTC_DRV_MAX77686
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-max77686. will be called rtc-max77686.
config RTC_DRV_NCT3018Y
tristate "Nuvoton NCT3018Y"
depends on OF
help
If you say yes here you get support for the Nuvoton NCT3018Y I2C RTC
chip.
This driver can also be built as a module, if so, the module will be
called "rtc-nct3018y".
config RTC_DRV_RK808 config RTC_DRV_RK808
tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC" tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC"
depends on MFD_RK808 depends on MFD_RK808
...@@ -1478,16 +1488,6 @@ config RTC_DRV_SUNPLUS ...@@ -1478,16 +1488,6 @@ config RTC_DRV_SUNPLUS
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-sunplus. will be called rtc-sunplus.
config RTC_DRV_VR41XX
tristate "NEC VR41XX"
depends on CPU_VR41XX || COMPILE_TEST
help
If you say Y here you will get access to the real time clock
built into your NEC VR41XX CPU.
To compile this driver as a module, choose M here: the
module will be called rtc-vr41xx.
config RTC_DRV_PL030 config RTC_DRV_PL030
tristate "ARM AMBA PL030 RTC" tristate "ARM AMBA PL030 RTC"
depends on ARM_AMBA depends on ARM_AMBA
...@@ -1929,6 +1929,17 @@ config RTC_DRV_ASPEED ...@@ -1929,6 +1929,17 @@ config RTC_DRV_ASPEED
This driver can also be built as a module, if so, the module This driver can also be built as a module, if so, the module
will be called "rtc-aspeed". will be called "rtc-aspeed".
config RTC_DRV_TI_K3
tristate "TI K3 RTC"
depends on ARCH_K3 || COMPILE_TEST
select REGMAP_MMIO
help
If you say yes here you get support for the Texas Instruments's
Real Time Clock for K3 architecture.
This driver can also be built as a module, if so, the module
will be called "rtc-ti-k3".
comment "HID Sensor RTC drivers" comment "HID Sensor RTC drivers"
config RTC_DRV_HID_SENSOR_TIME config RTC_DRV_HID_SENSOR_TIME
...@@ -1973,4 +1984,14 @@ config RTC_DRV_MSC313 ...@@ -1973,4 +1984,14 @@ config RTC_DRV_MSC313
This driver can also be built as a module, if so, the module This driver can also be built as a module, if so, the module
will be called "rtc-msc313". will be called "rtc-msc313".
config RTC_DRV_POLARFIRE_SOC
tristate "Microchip PolarFire SoC built-in RTC"
depends on SOC_MICROCHIP_POLARFIRE
help
If you say yes here you will get support for the
built-in RTC on Polarfire SoC.
This driver can also be built as a module, if so, the module
will be called "rtc-mpfs".
endif # RTC_CLASS endif # RTC_CLASS
...@@ -112,6 +112,7 @@ obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o ...@@ -112,6 +112,7 @@ obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o
obj-$(CONFIG_RTC_DRV_MXC) += rtc-mxc.o obj-$(CONFIG_RTC_DRV_MXC) += rtc-mxc.o
obj-$(CONFIG_RTC_DRV_MXC_V2) += rtc-mxc_v2.o obj-$(CONFIG_RTC_DRV_MXC_V2) += rtc-mxc_v2.o
obj-$(CONFIG_RTC_DRV_GAMECUBE) += rtc-gamecube.o obj-$(CONFIG_RTC_DRV_GAMECUBE) += rtc-gamecube.o
obj-$(CONFIG_RTC_DRV_NCT3018Y) += rtc-nct3018y.o
obj-$(CONFIG_RTC_DRV_NTXEC) += rtc-ntxec.o obj-$(CONFIG_RTC_DRV_NTXEC) += rtc-ntxec.o
obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
obj-$(CONFIG_RTC_DRV_OPAL) += rtc-opal.o obj-$(CONFIG_RTC_DRV_OPAL) += rtc-opal.o
...@@ -130,6 +131,7 @@ obj-$(CONFIG_RTC_DRV_PIC32) += rtc-pic32.o ...@@ -130,6 +131,7 @@ obj-$(CONFIG_RTC_DRV_PIC32) += rtc-pic32.o
obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o
obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o
obj-$(CONFIG_RTC_DRV_PM8XXX) += rtc-pm8xxx.o obj-$(CONFIG_RTC_DRV_PM8XXX) += rtc-pm8xxx.o
obj-$(CONFIG_RTC_DRV_POLARFIRE_SOC) += rtc-mpfs.o
obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o
obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o
obj-$(CONFIG_RTC_DRV_R7301) += rtc-r7301.o obj-$(CONFIG_RTC_DRV_R7301) += rtc-r7301.o
...@@ -172,11 +174,11 @@ obj-$(CONFIG_RTC_DRV_SUNPLUS) += rtc-sunplus.o ...@@ -172,11 +174,11 @@ obj-$(CONFIG_RTC_DRV_SUNPLUS) += rtc-sunplus.o
obj-$(CONFIG_RTC_DRV_SUNXI) += rtc-sunxi.o obj-$(CONFIG_RTC_DRV_SUNXI) += rtc-sunxi.o
obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o
obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
obj-$(CONFIG_RTC_DRV_TI_K3) += rtc-ti-k3.o
obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o
obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o
obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o
obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o
obj-$(CONFIG_RTC_DRV_WILCO_EC) += rtc-wilco-ec.o obj-$(CONFIG_RTC_DRV_WILCO_EC) += rtc-wilco-ec.o
obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
......
...@@ -36,7 +36,7 @@ static void rtc_device_release(struct device *dev) ...@@ -36,7 +36,7 @@ static void rtc_device_release(struct device *dev)
cancel_work_sync(&rtc->irqwork); cancel_work_sync(&rtc->irqwork);
ida_simple_remove(&rtc_ida, rtc->id); ida_free(&rtc_ida, rtc->id);
mutex_destroy(&rtc->ops_lock); mutex_destroy(&rtc->ops_lock);
kfree(rtc); kfree(rtc);
} }
...@@ -262,7 +262,7 @@ static int rtc_device_get_id(struct device *dev) ...@@ -262,7 +262,7 @@ static int rtc_device_get_id(struct device *dev)
} }
if (id < 0) if (id < 0)
id = ida_simple_get(&rtc_ida, 0, 0, GFP_KERNEL); id = ida_alloc(&rtc_ida, GFP_KERNEL);
return id; return id;
} }
...@@ -368,7 +368,7 @@ struct rtc_device *devm_rtc_allocate_device(struct device *dev) ...@@ -368,7 +368,7 @@ struct rtc_device *devm_rtc_allocate_device(struct device *dev)
rtc = rtc_allocate_device(); rtc = rtc_allocate_device();
if (!rtc) { if (!rtc) {
ida_simple_remove(&rtc_ida, id); ida_free(&rtc_ida, id);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
......
...@@ -96,7 +96,7 @@ static int clear_uie(struct rtc_device *rtc) ...@@ -96,7 +96,7 @@ static int clear_uie(struct rtc_device *rtc)
} }
if (rtc->uie_task_active) { if (rtc->uie_task_active) {
spin_unlock_irq(&rtc->irq_lock); spin_unlock_irq(&rtc->irq_lock);
flush_scheduled_work(); flush_work(&rtc->uie_task);
spin_lock_irq(&rtc->irq_lock); spin_lock_irq(&rtc->irq_lock);
} }
rtc->uie_irq_active = 0; rtc->uie_irq_active = 0;
...@@ -566,9 +566,3 @@ void __init rtc_dev_init(void) ...@@ -566,9 +566,3 @@ void __init rtc_dev_init(void)
if (err < 0) if (err < 0)
pr_err("failed to allocate char dev region\n"); pr_err("failed to allocate char dev region\n");
} }
void __exit rtc_dev_exit(void)
{
if (rtc_devt)
unregister_chrdev_region(rtc_devt, RTC_DEV_MAX);
}
...@@ -817,8 +817,7 @@ static const struct regmap_config abb5zes3_rtc_regmap_config = { ...@@ -817,8 +817,7 @@ static const struct regmap_config abb5zes3_rtc_regmap_config = {
.val_bits = 8, .val_bits = 8,
}; };
static int abb5zes3_probe(struct i2c_client *client, static int abb5zes3_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct abb5zes3_rtc_data *data = NULL; struct abb5zes3_rtc_data *data = NULL;
struct device *dev = &client->dev; struct device *dev = &client->dev;
...@@ -945,7 +944,7 @@ static struct i2c_driver abb5zes3_driver = { ...@@ -945,7 +944,7 @@ static struct i2c_driver abb5zes3_driver = {
.pm = &abb5zes3_rtc_pm_ops, .pm = &abb5zes3_rtc_pm_ops,
.of_match_table = of_match_ptr(abb5zes3_dt_match), .of_match_table = of_match_ptr(abb5zes3_dt_match),
}, },
.probe = abb5zes3_probe, .probe_new = abb5zes3_probe,
.id_table = abb5zes3_id, .id_table = abb5zes3_id,
}; };
module_i2c_driver(abb5zes3_driver); module_i2c_driver(abb5zes3_driver);
......
...@@ -495,8 +495,7 @@ static void abeoz9_hwmon_register(struct device *dev, ...@@ -495,8 +495,7 @@ static void abeoz9_hwmon_register(struct device *dev,
#endif #endif
static int abeoz9_probe(struct i2c_client *client, static int abeoz9_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct abeoz9_rtc_data *data = NULL; struct abeoz9_rtc_data *data = NULL;
struct device *dev = &client->dev; struct device *dev = &client->dev;
...@@ -580,7 +579,7 @@ static struct i2c_driver abeoz9_driver = { ...@@ -580,7 +579,7 @@ static struct i2c_driver abeoz9_driver = {
.name = "rtc-ab-eoz9", .name = "rtc-ab-eoz9",
.of_match_table = of_match_ptr(abeoz9_dt_match), .of_match_table = of_match_ptr(abeoz9_dt_match),
}, },
.probe = abeoz9_probe, .probe_new = abeoz9_probe,
.id_table = abeoz9_id, .id_table = abeoz9_id,
}; };
......
...@@ -249,8 +249,7 @@ static void bq32k_sysfs_unregister(struct device *dev) ...@@ -249,8 +249,7 @@ static void bq32k_sysfs_unregister(struct device *dev)
device_remove_file(dev, &dev_attr_trickle_charge_bypass); device_remove_file(dev, &dev_attr_trickle_charge_bypass);
} }
static int bq32k_probe(struct i2c_client *client, static int bq32k_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct rtc_device *rtc; struct rtc_device *rtc;
...@@ -322,7 +321,7 @@ static struct i2c_driver bq32k_driver = { ...@@ -322,7 +321,7 @@ static struct i2c_driver bq32k_driver = {
.name = "bq32k", .name = "bq32k",
.of_match_table = of_match_ptr(bq32k_of_match), .of_match_table = of_match_ptr(bq32k_of_match),
}, },
.probe = bq32k_probe, .probe_new = bq32k_probe,
.remove = bq32k_remove, .remove = bq32k_remove,
.id_table = bq32k_id, .id_table = bq32k_id,
}; };
......
...@@ -1260,9 +1260,6 @@ static void use_acpi_alarm_quirks(void) ...@@ -1260,9 +1260,6 @@ static void use_acpi_alarm_quirks(void)
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
return; return;
if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0))
return;
if (!is_hpet_enabled()) if (!is_hpet_enabled())
return; return;
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
#ifdef CONFIG_RTC_INTF_DEV #ifdef CONFIG_RTC_INTF_DEV
extern void __init rtc_dev_init(void); extern void __init rtc_dev_init(void);
extern void __exit rtc_dev_exit(void);
extern void rtc_dev_prepare(struct rtc_device *rtc); extern void rtc_dev_prepare(struct rtc_device *rtc);
#else #else
...@@ -11,10 +10,6 @@ static inline void rtc_dev_init(void) ...@@ -11,10 +10,6 @@ static inline void rtc_dev_init(void)
{ {
} }
static inline void rtc_dev_exit(void)
{
}
static inline void rtc_dev_prepare(struct rtc_device *rtc) static inline void rtc_dev_prepare(struct rtc_device *rtc)
{ {
} }
......
...@@ -375,10 +375,8 @@ static int cros_ec_rtc_remove(struct platform_device *pdev) ...@@ -375,10 +375,8 @@ static int cros_ec_rtc_remove(struct platform_device *pdev)
ret = blocking_notifier_chain_unregister( ret = blocking_notifier_chain_unregister(
&cros_ec_rtc->cros_ec->event_notifier, &cros_ec_rtc->cros_ec->event_notifier,
&cros_ec_rtc->notifier); &cros_ec_rtc->notifier);
if (ret) { if (ret)
dev_err(dev, "failed to unregister notifier\n"); dev_err(dev, "failed to unregister notifier\n");
return ret;
}
return 0; return 0;
} }
......
...@@ -467,8 +467,7 @@ static const struct watchdog_ops ds1374_wdt_ops = { ...@@ -467,8 +467,7 @@ static const struct watchdog_ops ds1374_wdt_ops = {
* *
***************************************************************************** *****************************************************************************
*/ */
static int ds1374_probe(struct i2c_client *client, static int ds1374_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct ds1374 *ds1374; struct ds1374 *ds1374;
int ret; int ret;
...@@ -575,7 +574,7 @@ static struct i2c_driver ds1374_driver = { ...@@ -575,7 +574,7 @@ static struct i2c_driver ds1374_driver = {
.of_match_table = of_match_ptr(ds1374_of_match), .of_match_table = of_match_ptr(ds1374_of_match),
.pm = &ds1374_pm, .pm = &ds1374_pm,
}, },
.probe = ds1374_probe, .probe_new = ds1374_probe,
.remove = ds1374_remove, .remove = ds1374_remove,
.id_table = ds1374_id, .id_table = ds1374_id,
}; };
......
...@@ -106,8 +106,7 @@ static const struct rtc_class_ops ds1672_rtc_ops = { ...@@ -106,8 +106,7 @@ static const struct rtc_class_ops ds1672_rtc_ops = {
.set_time = ds1672_set_time, .set_time = ds1672_set_time,
}; };
static int ds1672_probe(struct i2c_client *client, static int ds1672_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
int err = 0; int err = 0;
struct rtc_device *rtc; struct rtc_device *rtc;
...@@ -150,7 +149,7 @@ static struct i2c_driver ds1672_driver = { ...@@ -150,7 +149,7 @@ static struct i2c_driver ds1672_driver = {
.name = "rtc-ds1672", .name = "rtc-ds1672",
.of_match_table = of_match_ptr(ds1672_of_match), .of_match_table = of_match_ptr(ds1672_of_match),
}, },
.probe = &ds1672_probe, .probe_new = ds1672_probe,
.id_table = ds1672_id, .id_table = ds1672_id,
}; };
......
...@@ -566,8 +566,7 @@ static const struct dev_pm_ops ds3232_pm_ops = { ...@@ -566,8 +566,7 @@ static const struct dev_pm_ops ds3232_pm_ops = {
#if IS_ENABLED(CONFIG_I2C) #if IS_ENABLED(CONFIG_I2C)
static int ds3232_i2c_probe(struct i2c_client *client, static int ds3232_i2c_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct regmap *regmap; struct regmap *regmap;
static const struct regmap_config config = { static const struct regmap_config config = {
...@@ -604,7 +603,7 @@ static struct i2c_driver ds3232_driver = { ...@@ -604,7 +603,7 @@ static struct i2c_driver ds3232_driver = {
.of_match_table = of_match_ptr(ds3232_of_match), .of_match_table = of_match_ptr(ds3232_of_match),
.pm = &ds3232_pm_ops, .pm = &ds3232_pm_ops,
}, },
.probe = ds3232_i2c_probe, .probe_new = ds3232_i2c_probe,
.id_table = ds3232_id, .id_table = ds3232_id,
}; };
......
...@@ -111,8 +111,7 @@ static const struct rtc_class_ops em3027_rtc_ops = { ...@@ -111,8 +111,7 @@ static const struct rtc_class_ops em3027_rtc_ops = {
.set_time = em3027_set_time, .set_time = em3027_set_time,
}; };
static int em3027_probe(struct i2c_client *client, static int em3027_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct rtc_device *rtc; struct rtc_device *rtc;
...@@ -148,7 +147,7 @@ static struct i2c_driver em3027_driver = { ...@@ -148,7 +147,7 @@ static struct i2c_driver em3027_driver = {
.name = "rtc-em3027", .name = "rtc-em3027",
.of_match_table = of_match_ptr(em3027_of_match), .of_match_table = of_match_ptr(em3027_of_match),
}, },
.probe = &em3027_probe, .probe_new = em3027_probe,
.id_table = em3027_id, .id_table = em3027_id,
}; };
......
...@@ -340,8 +340,7 @@ static const struct rtc_class_ops fm3130_rtc_ops = { ...@@ -340,8 +340,7 @@ static const struct rtc_class_ops fm3130_rtc_ops = {
static struct i2c_driver fm3130_driver; static struct i2c_driver fm3130_driver;
static int fm3130_probe(struct i2c_client *client, static int fm3130_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct fm3130 *fm3130; struct fm3130 *fm3130;
int err = -ENODEV; int err = -ENODEV;
...@@ -518,7 +517,7 @@ static struct i2c_driver fm3130_driver = { ...@@ -518,7 +517,7 @@ static struct i2c_driver fm3130_driver = {
.driver = { .driver = {
.name = "rtc-fm3130", .name = "rtc-fm3130",
}, },
.probe = fm3130_probe, .probe_new = fm3130_probe,
.id_table = fm3130_id, .id_table = fm3130_id,
}; };
......
...@@ -495,8 +495,7 @@ static int hym8563_resume(struct device *dev) ...@@ -495,8 +495,7 @@ static int hym8563_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(hym8563_pm_ops, hym8563_suspend, hym8563_resume); static SIMPLE_DEV_PM_OPS(hym8563_pm_ops, hym8563_suspend, hym8563_resume);
static int hym8563_probe(struct i2c_client *client, static int hym8563_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct hym8563 *hym8563; struct hym8563 *hym8563;
int ret; int ret;
...@@ -572,7 +571,7 @@ static struct i2c_driver hym8563_driver = { ...@@ -572,7 +571,7 @@ static struct i2c_driver hym8563_driver = {
.pm = &hym8563_pm_ops, .pm = &hym8563_pm_ops,
.of_match_table = hym8563_dt_idtable, .of_match_table = hym8563_dt_idtable,
}, },
.probe = hym8563_probe, .probe_new = hym8563_probe,
.id_table = hym8563_id, .id_table = hym8563_id,
}; };
......
...@@ -232,8 +232,7 @@ static const struct rtc_class_ops isl12022_rtc_ops = { ...@@ -232,8 +232,7 @@ static const struct rtc_class_ops isl12022_rtc_ops = {
.set_time = isl12022_rtc_set_time, .set_time = isl12022_rtc_set_time,
}; };
static int isl12022_probe(struct i2c_client *client, static int isl12022_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct isl12022 *isl12022; struct isl12022 *isl12022;
...@@ -275,7 +274,7 @@ static struct i2c_driver isl12022_driver = { ...@@ -275,7 +274,7 @@ static struct i2c_driver isl12022_driver = {
.of_match_table = of_match_ptr(isl12022_dt_match), .of_match_table = of_match_ptr(isl12022_dt_match),
#endif #endif
}, },
.probe = isl12022_probe, .probe_new = isl12022_probe,
.id_table = isl12022_id, .id_table = isl12022_id,
}; };
......
...@@ -880,10 +880,14 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -880,10 +880,14 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (rc) if (rc)
return rc; return rc;
if (client->irq > 0) if (client->irq > 0) {
rc = isl1208_setup_irq(client, client->irq); rc = isl1208_setup_irq(client, client->irq);
if (rc) if (rc)
return rc; return rc;
} else {
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, isl1208->rtc->features);
}
if (evdet_irq > 0 && evdet_irq != client->irq) if (evdet_irq > 0 && evdet_irq != client->irq)
rc = isl1208_setup_irq(client, evdet_irq); rc = isl1208_setup_irq(client, evdet_irq);
......
...@@ -197,8 +197,7 @@ static const struct rtc_class_ops max6900_rtc_ops = { ...@@ -197,8 +197,7 @@ static const struct rtc_class_ops max6900_rtc_ops = {
.set_time = max6900_rtc_set_time, .set_time = max6900_rtc_set_time,
}; };
static int static int max6900_probe(struct i2c_client *client)
max6900_probe(struct i2c_client *client, const struct i2c_device_id *id)
{ {
struct rtc_device *rtc; struct rtc_device *rtc;
...@@ -225,7 +224,7 @@ static struct i2c_driver max6900_driver = { ...@@ -225,7 +224,7 @@ static struct i2c_driver max6900_driver = {
.driver = { .driver = {
.name = "rtc-max6900", .name = "rtc-max6900",
}, },
.probe = max6900_probe, .probe_new = max6900_probe,
.id_table = max6900_id, .id_table = max6900_id,
}; };
......
...@@ -21,13 +21,13 @@ bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param), ...@@ -21,13 +21,13 @@ bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param),
unsigned long flags; unsigned long flags;
unsigned char seconds; unsigned char seconds;
for (i = 0; i < 10; i++) { for (i = 0; i < 100; i++) {
spin_lock_irqsave(&rtc_lock, flags); spin_lock_irqsave(&rtc_lock, flags);
/* /*
* Check whether there is an update in progress during which the * Check whether there is an update in progress during which the
* readout is unspecified. The maximum update time is ~2ms. Poll * readout is unspecified. The maximum update time is ~2ms. Poll
* every msec for completion. * every 100 usec for completion.
* *
* Store the second value before checking UIP so a long lasting * Store the second value before checking UIP so a long lasting
* NMI which happens to hit after the UIP check cannot make * NMI which happens to hit after the UIP check cannot make
...@@ -37,7 +37,7 @@ bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param), ...@@ -37,7 +37,7 @@ bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param),
if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) { if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) {
spin_unlock_irqrestore(&rtc_lock, flags); spin_unlock_irqrestore(&rtc_lock, flags);
mdelay(1); udelay(100);
continue; continue;
} }
...@@ -56,7 +56,7 @@ bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param), ...@@ -56,7 +56,7 @@ bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param),
*/ */
if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) { if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) {
spin_unlock_irqrestore(&rtc_lock, flags); spin_unlock_irqrestore(&rtc_lock, flags);
mdelay(1); udelay(100);
continue; continue;
} }
......
// SPDX-License-Identifier: GPL-2.0
/*
* Microchip MPFS RTC driver
*
* Copyright (c) 2021-2022 Microchip Corporation. All rights reserved.
*
* Author: Daire McNamara <daire.mcnamara@microchip.com>
* & Conor Dooley <conor.dooley@microchip.com>
*/
#include "linux/bits.h"
#include "linux/iopoll.h"
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_wakeirq.h>
#include <linux/slab.h>
#include <linux/rtc.h>
#define CONTROL_REG 0x00
#define MODE_REG 0x04
#define PRESCALER_REG 0x08
#define ALARM_LOWER_REG 0x0c
#define ALARM_UPPER_REG 0x10
#define COMPARE_LOWER_REG 0x14
#define COMPARE_UPPER_REG 0x18
#define DATETIME_LOWER_REG 0x20
#define DATETIME_UPPER_REG 0x24
#define CONTROL_RUNNING_BIT BIT(0)
#define CONTROL_START_BIT BIT(0)
#define CONTROL_STOP_BIT BIT(1)
#define CONTROL_ALARM_ON_BIT BIT(2)
#define CONTROL_ALARM_OFF_BIT BIT(3)
#define CONTROL_RESET_BIT BIT(4)
#define CONTROL_UPLOAD_BIT BIT(5)
#define CONTROL_DOWNLOAD_BIT BIT(6)
#define CONTROL_MATCH_BIT BIT(7)
#define CONTROL_WAKEUP_CLR_BIT BIT(8)
#define CONTROL_WAKEUP_SET_BIT BIT(9)
#define CONTROL_UPDATED_BIT BIT(10)
#define MODE_CLOCK_CALENDAR BIT(0)
#define MODE_WAKE_EN BIT(1)
#define MODE_WAKE_RESET BIT(2)
#define MODE_WAKE_CONTINUE BIT(3)
#define MAX_PRESCALER_COUNT GENMASK(25, 0)
#define DATETIME_UPPER_MASK GENMASK(29, 0)
#define ALARM_UPPER_MASK GENMASK(10, 0)
#define UPLOAD_TIMEOUT_US 50
struct mpfs_rtc_dev {
struct rtc_device *rtc;
void __iomem *base;
};
static void mpfs_rtc_start(struct mpfs_rtc_dev *rtcdev)
{
u32 ctrl;
ctrl = readl(rtcdev->base + CONTROL_REG);
ctrl &= ~CONTROL_STOP_BIT;
ctrl |= CONTROL_START_BIT;
writel(ctrl, rtcdev->base + CONTROL_REG);
}
static void mpfs_rtc_clear_irq(struct mpfs_rtc_dev *rtcdev)
{
u32 val = readl(rtcdev->base + CONTROL_REG);
val &= ~(CONTROL_ALARM_ON_BIT | CONTROL_STOP_BIT);
val |= CONTROL_ALARM_OFF_BIT;
writel(val, rtcdev->base + CONTROL_REG);
/*
* Ensure that the posted write to the CONTROL_REG register completed before
* returning from this function. Not doing this may result in the interrupt
* only being cleared some time after this function returns.
*/
(void)readl(rtcdev->base + CONTROL_REG);
}
static int mpfs_rtc_readtime(struct device *dev, struct rtc_time *tm)
{
struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
u64 time;
time = readl(rtcdev->base + DATETIME_LOWER_REG);
time |= ((u64)readl(rtcdev->base + DATETIME_UPPER_REG) & DATETIME_UPPER_MASK) << 32;
rtc_time64_to_tm(time, tm);
return 0;
}
static int mpfs_rtc_settime(struct device *dev, struct rtc_time *tm)
{
struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
u32 ctrl, prog;
u64 time;
int ret;
time = rtc_tm_to_time64(tm);
writel((u32)time, rtcdev->base + DATETIME_LOWER_REG);
writel((u32)(time >> 32) & DATETIME_UPPER_MASK, rtcdev->base + DATETIME_UPPER_REG);
ctrl = readl(rtcdev->base + CONTROL_REG);
ctrl &= ~CONTROL_STOP_BIT;
ctrl |= CONTROL_UPLOAD_BIT;
writel(ctrl, rtcdev->base + CONTROL_REG);
ret = read_poll_timeout(readl, prog, prog & CONTROL_UPLOAD_BIT, 0, UPLOAD_TIMEOUT_US,
false, rtcdev->base + CONTROL_REG);
if (ret) {
dev_err(dev, "timed out uploading time to rtc");
return ret;
}
mpfs_rtc_start(rtcdev);
return 0;
}
static int mpfs_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
u32 mode = readl(rtcdev->base + MODE_REG);
u64 time;
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);
rtc_time64_to_tm(time, &alrm->time);
return 0;
}
static int mpfs_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
u32 mode, ctrl;
u64 time;
/* Disable the alarm before updating */
ctrl = readl(rtcdev->base + CONTROL_REG);
ctrl |= CONTROL_ALARM_OFF_BIT;
writel(ctrl, rtcdev->base + CONTROL_REG);
time = rtc_tm_to_time64(&alrm->time);
writel((u32)time, rtcdev->base + ALARM_LOWER_REG);
writel((u32)(time >> 32) & ALARM_UPPER_MASK, rtcdev->base + ALARM_UPPER_REG);
/* Bypass compare register in alarm mode */
writel(GENMASK(31, 0), rtcdev->base + COMPARE_LOWER_REG);
writel(GENMASK(29, 0), rtcdev->base + COMPARE_UPPER_REG);
/* Configure the RTC to enable the alarm. */
ctrl = readl(rtcdev->base + CONTROL_REG);
mode = readl(rtcdev->base + MODE_REG);
if (alrm->enabled) {
mode = MODE_WAKE_EN | MODE_WAKE_CONTINUE;
/* Enable the alarm */
ctrl &= ~CONTROL_ALARM_OFF_BIT;
ctrl |= CONTROL_ALARM_ON_BIT;
}
ctrl &= ~CONTROL_STOP_BIT;
ctrl |= CONTROL_START_BIT;
writel(ctrl, rtcdev->base + CONTROL_REG);
writel(mode, rtcdev->base + MODE_REG);
return 0;
}
static int mpfs_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
u32 ctrl;
ctrl = readl(rtcdev->base + CONTROL_REG);
ctrl &= ~(CONTROL_ALARM_ON_BIT | CONTROL_ALARM_OFF_BIT | CONTROL_STOP_BIT);
if (enabled)
ctrl |= CONTROL_ALARM_ON_BIT;
else
ctrl |= CONTROL_ALARM_OFF_BIT;
writel(ctrl, rtcdev->base + CONTROL_REG);
return 0;
}
static inline struct clk *mpfs_rtc_init_clk(struct device *dev)
{
struct clk *clk;
int ret;
clk = devm_clk_get(dev, "rtc");
if (IS_ERR(clk))
return clk;
ret = clk_prepare_enable(clk);
if (ret)
return ERR_PTR(ret);
devm_add_action_or_reset(dev, (void (*) (void *))clk_disable_unprepare, clk);
return clk;
}
static irqreturn_t mpfs_rtc_wakeup_irq_handler(int irq, void *dev)
{
struct mpfs_rtc_dev *rtcdev = dev;
mpfs_rtc_clear_irq(rtcdev);
rtc_update_irq(rtcdev->rtc, 1, RTC_IRQF | RTC_AF);
return IRQ_HANDLED;
}
static const struct rtc_class_ops mpfs_rtc_ops = {
.read_time = mpfs_rtc_readtime,
.set_time = mpfs_rtc_settime,
.read_alarm = mpfs_rtc_readalarm,
.set_alarm = mpfs_rtc_setalarm,
.alarm_irq_enable = mpfs_rtc_alarm_irq_enable,
};
static int mpfs_rtc_probe(struct platform_device *pdev)
{
struct mpfs_rtc_dev *rtcdev;
struct clk *clk;
u32 prescaler;
int wakeup_irq, ret;
rtcdev = devm_kzalloc(&pdev->dev, sizeof(struct mpfs_rtc_dev), GFP_KERNEL);
if (!rtcdev)
return -ENOMEM;
platform_set_drvdata(pdev, rtcdev);
rtcdev->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtcdev->rtc))
return PTR_ERR(rtcdev->rtc);
rtcdev->rtc->ops = &mpfs_rtc_ops;
/* range is capped by alarm max, lower reg is 31:0 & upper is 10:0 */
rtcdev->rtc->range_max = GENMASK_ULL(42, 0);
clk = mpfs_rtc_init_clk(&pdev->dev);
if (IS_ERR(clk))
return PTR_ERR(clk);
rtcdev->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rtcdev->base)) {
dev_dbg(&pdev->dev, "invalid ioremap resources\n");
return PTR_ERR(rtcdev->base);
}
wakeup_irq = platform_get_irq(pdev, 0);
if (wakeup_irq <= 0) {
dev_dbg(&pdev->dev, "could not get wakeup irq\n");
return wakeup_irq;
}
ret = devm_request_irq(&pdev->dev, wakeup_irq, mpfs_rtc_wakeup_irq_handler, 0,
dev_name(&pdev->dev), rtcdev);
if (ret) {
dev_dbg(&pdev->dev, "could not request wakeup irq\n");
return ret;
}
/* prescaler hardware adds 1 to reg value */
prescaler = clk_get_rate(devm_clk_get(&pdev->dev, "rtcref")) - 1;
if (prescaler > MAX_PRESCALER_COUNT) {
dev_dbg(&pdev->dev, "invalid prescaler %d\n", prescaler);
return -EINVAL;
}
writel(prescaler, rtcdev->base + PRESCALER_REG);
dev_info(&pdev->dev, "prescaler set to: 0x%X \r\n", prescaler);
device_init_wakeup(&pdev->dev, true);
ret = dev_pm_set_wake_irq(&pdev->dev, wakeup_irq);
if (ret)
dev_err(&pdev->dev, "failed to enable irq wake\n");
return devm_rtc_register_device(rtcdev->rtc);
}
static int mpfs_rtc_remove(struct platform_device *pdev)
{
dev_pm_clear_wake_irq(&pdev->dev);
return 0;
}
static const struct of_device_id mpfs_rtc_of_match[] = {
{ .compatible = "microchip,mpfs-rtc" },
{ }
};
MODULE_DEVICE_TABLE(of, mpfs_rtc_of_match);
static struct platform_driver mpfs_rtc_driver = {
.probe = mpfs_rtc_probe,
.remove = mpfs_rtc_remove,
.driver = {
.name = "mpfs_rtc",
.of_match_table = mpfs_rtc_of_match,
},
};
module_platform_driver(mpfs_rtc_driver);
MODULE_DESCRIPTION("Real time clock for Microchip Polarfire SoC");
MODULE_AUTHOR("Daire McNamara <daire.mcnamara@microchip.com>");
MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");
MODULE_LICENSE("GPL");
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2022 Nuvoton Technology Corporation
#include <linux/bcd.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#define NCT3018Y_REG_SC 0x00 /* seconds */
#define NCT3018Y_REG_SCA 0x01 /* alarm */
#define NCT3018Y_REG_MN 0x02
#define NCT3018Y_REG_MNA 0x03 /* alarm */
#define NCT3018Y_REG_HR 0x04
#define NCT3018Y_REG_HRA 0x05 /* alarm */
#define NCT3018Y_REG_DW 0x06
#define NCT3018Y_REG_DM 0x07
#define NCT3018Y_REG_MO 0x08
#define NCT3018Y_REG_YR 0x09
#define NCT3018Y_REG_CTRL 0x0A /* timer control */
#define NCT3018Y_REG_ST 0x0B /* status */
#define NCT3018Y_REG_CLKO 0x0C /* clock out */
#define NCT3018Y_BIT_AF BIT(7)
#define NCT3018Y_BIT_ST BIT(7)
#define NCT3018Y_BIT_DM BIT(6)
#define NCT3018Y_BIT_HF BIT(5)
#define NCT3018Y_BIT_DSM BIT(4)
#define NCT3018Y_BIT_AIE BIT(3)
#define NCT3018Y_BIT_OFIE BIT(2)
#define NCT3018Y_BIT_CIE BIT(1)
#define NCT3018Y_BIT_TWO BIT(0)
#define NCT3018Y_REG_BAT_MASK 0x07
#define NCT3018Y_REG_CLKO_F_MASK 0x03 /* frequenc mask */
#define NCT3018Y_REG_CLKO_CKE 0x80 /* clock out enabled */
struct nct3018y {
struct rtc_device *rtc;
struct i2c_client *client;
#ifdef CONFIG_COMMON_CLK
struct clk_hw clkout_hw;
#endif
};
static int nct3018y_set_alarm_mode(struct i2c_client *client, bool on)
{
int err, flags;
dev_dbg(&client->dev, "%s:on:%d\n", __func__, on);
flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CTRL);
if (flags < 0) {
dev_dbg(&client->dev,
"Failed to read NCT3018Y_REG_CTRL\n");
return flags;
}
if (on)
flags |= NCT3018Y_BIT_AIE;
else
flags &= ~NCT3018Y_BIT_AIE;
flags |= NCT3018Y_BIT_CIE;
err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_CTRL, flags);
if (err < 0) {
dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_CTRL\n");
return err;
}
flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_ST);
if (flags < 0) {
dev_dbg(&client->dev,
"Failed to read NCT3018Y_REG_ST\n");
return flags;
}
flags &= ~(NCT3018Y_BIT_AF);
err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_ST, flags);
if (err < 0) {
dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_ST\n");
return err;
}
return 0;
}
static int nct3018y_get_alarm_mode(struct i2c_client *client, unsigned char *alarm_enable,
unsigned char *alarm_flag)
{
int flags;
if (alarm_enable) {
dev_dbg(&client->dev, "%s:NCT3018Y_REG_CTRL\n", __func__);
flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CTRL);
if (flags < 0)
return flags;
*alarm_enable = flags & NCT3018Y_BIT_AIE;
}
if (alarm_flag) {
dev_dbg(&client->dev, "%s:NCT3018Y_REG_ST\n", __func__);
flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_ST);
if (flags < 0)
return flags;
*alarm_flag = flags & NCT3018Y_BIT_AF;
}
dev_dbg(&client->dev, "%s:alarm_enable:%x alarm_flag:%x\n",
__func__, *alarm_enable, *alarm_flag);
return 0;
}
static irqreturn_t nct3018y_irq(int irq, void *dev_id)
{
struct nct3018y *nct3018y = i2c_get_clientdata(dev_id);
struct i2c_client *client = nct3018y->client;
int err;
unsigned char alarm_flag;
unsigned char alarm_enable;
dev_dbg(&client->dev, "%s:irq:%d\n", __func__, irq);
err = nct3018y_get_alarm_mode(nct3018y->client, &alarm_enable, &alarm_flag);
if (err)
return IRQ_NONE;
if (alarm_flag) {
dev_dbg(&client->dev, "%s:alarm flag:%x\n",
__func__, alarm_flag);
rtc_update_irq(nct3018y->rtc, 1, RTC_IRQF | RTC_AF);
nct3018y_set_alarm_mode(nct3018y->client, 0);
dev_dbg(&client->dev, "%s:IRQ_HANDLED\n", __func__);
return IRQ_HANDLED;
}
return IRQ_NONE;
}
/*
* In the routines that deal directly with the nct3018y hardware, we use
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
*/
static int nct3018y_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct i2c_client *client = to_i2c_client(dev);
unsigned char buf[10];
int err;
err = i2c_smbus_read_i2c_block_data(client, NCT3018Y_REG_ST, 1, buf);
if (err < 0)
return err;
if (!buf[0]) {
dev_dbg(&client->dev, " voltage <=1.7, date/time is not reliable.\n");
return -EINVAL;
}
err = i2c_smbus_read_i2c_block_data(client, NCT3018Y_REG_SC, sizeof(buf), buf);
if (err < 0)
return err;
tm->tm_sec = bcd2bin(buf[0] & 0x7F);
tm->tm_min = bcd2bin(buf[2] & 0x7F);
tm->tm_hour = bcd2bin(buf[4] & 0x3F);
tm->tm_wday = buf[6] & 0x07;
tm->tm_mday = bcd2bin(buf[7] & 0x3F);
tm->tm_mon = bcd2bin(buf[8] & 0x1F) - 1;
tm->tm_year = bcd2bin(buf[9]) + 100;
return 0;
}
static int nct3018y_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct i2c_client *client = to_i2c_client(dev);
unsigned char buf[4] = {0};
int err;
buf[0] = bin2bcd(tm->tm_sec);
err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_SC, buf[0]);
if (err < 0) {
dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_SC\n");
return err;
}
buf[0] = bin2bcd(tm->tm_min);
err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_MN, buf[0]);
if (err < 0) {
dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_MN\n");
return err;
}
buf[0] = bin2bcd(tm->tm_hour);
err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_HR, buf[0]);
if (err < 0) {
dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_HR\n");
return err;
}
buf[0] = tm->tm_wday & 0x07;
buf[1] = bin2bcd(tm->tm_mday);
buf[2] = bin2bcd(tm->tm_mon + 1);
buf[3] = bin2bcd(tm->tm_year - 100);
err = i2c_smbus_write_i2c_block_data(client, NCT3018Y_REG_DW,
sizeof(buf), buf);
if (err < 0) {
dev_dbg(&client->dev, "Unable to write for day and mon and year\n");
return -EIO;
}
return err;
}
static int nct3018y_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
{
struct i2c_client *client = to_i2c_client(dev);
unsigned char buf[5];
int err;
err = i2c_smbus_read_i2c_block_data(client, NCT3018Y_REG_SCA,
sizeof(buf), buf);
if (err < 0) {
dev_dbg(&client->dev, "Unable to read date\n");
return -EIO;
}
dev_dbg(&client->dev, "%s: raw data is sec=%02x, min=%02x hr=%02x\n",
__func__, buf[0], buf[2], buf[4]);
tm->time.tm_sec = bcd2bin(buf[0] & 0x7F);
tm->time.tm_min = bcd2bin(buf[2] & 0x7F);
tm->time.tm_hour = bcd2bin(buf[4] & 0x3F);
err = nct3018y_get_alarm_mode(client, &tm->enabled, &tm->pending);
if (err < 0)
return err;
dev_dbg(&client->dev, "%s:s=%d m=%d, hr=%d, enabled=%d, pending=%d\n",
__func__, tm->time.tm_sec, tm->time.tm_min,
tm->time.tm_hour, tm->enabled, tm->pending);
return 0;
}
static int nct3018y_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
{
struct i2c_client *client = to_i2c_client(dev);
int err;
dev_dbg(dev, "%s, sec=%d, min=%d hour=%d tm->enabled:%d\n",
__func__, tm->time.tm_sec, tm->time.tm_min, tm->time.tm_hour,
tm->enabled);
err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_SCA, bin2bcd(tm->time.tm_sec));
if (err < 0) {
dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_SCA\n");
return err;
}
err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_MNA, bin2bcd(tm->time.tm_min));
if (err < 0) {
dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_MNA\n");
return err;
}
err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_HRA, bin2bcd(tm->time.tm_hour));
if (err < 0) {
dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_HRA\n");
return err;
}
return nct3018y_set_alarm_mode(client, tm->enabled);
}
static int nct3018y_irq_enable(struct device *dev, unsigned int enabled)
{
dev_dbg(dev, "%s: alarm enable=%d\n", __func__, enabled);
return nct3018y_set_alarm_mode(to_i2c_client(dev), enabled);
}
static int nct3018y_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
struct i2c_client *client = to_i2c_client(dev);
int status, flags = 0;
switch (cmd) {
case RTC_VL_READ:
status = i2c_smbus_read_byte_data(client, NCT3018Y_REG_ST);
if (status < 0)
return status;
if (!(status & NCT3018Y_REG_BAT_MASK))
flags |= RTC_VL_DATA_INVALID;
return put_user(flags, (unsigned int __user *)arg);
default:
return -ENOIOCTLCMD;
}
}
#ifdef CONFIG_COMMON_CLK
/*
* Handling of the clkout
*/
#define clkout_hw_to_nct3018y(_hw) container_of(_hw, struct nct3018y, clkout_hw)
static const int clkout_rates[] = {
32768,
1024,
32,
1,
};
static unsigned long nct3018y_clkout_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct nct3018y *nct3018y = clkout_hw_to_nct3018y(hw);
struct i2c_client *client = nct3018y->client;
int flags;
flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CLKO);
if (flags < 0)
return 0;
flags &= NCT3018Y_REG_CLKO_F_MASK;
return clkout_rates[flags];
}
static long nct3018y_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
int i;
for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
if (clkout_rates[i] <= rate)
return clkout_rates[i];
return 0;
}
static int nct3018y_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct nct3018y *nct3018y = clkout_hw_to_nct3018y(hw);
struct i2c_client *client = nct3018y->client;
int i, flags;
flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CLKO);
if (flags < 0)
return flags;
for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
if (clkout_rates[i] == rate) {
flags &= ~NCT3018Y_REG_CLKO_F_MASK;
flags |= i;
return i2c_smbus_write_byte_data(client, NCT3018Y_REG_CLKO, flags);
}
return -EINVAL;
}
static int nct3018y_clkout_control(struct clk_hw *hw, bool enable)
{
struct nct3018y *nct3018y = clkout_hw_to_nct3018y(hw);
struct i2c_client *client = nct3018y->client;
int flags;
flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CLKO);
if (flags < 0)
return flags;
if (enable)
flags |= NCT3018Y_REG_CLKO_CKE;
else
flags &= ~NCT3018Y_REG_CLKO_CKE;
return i2c_smbus_write_byte_data(client, NCT3018Y_REG_CLKO, flags);
}
static int nct3018y_clkout_prepare(struct clk_hw *hw)
{
return nct3018y_clkout_control(hw, 1);
}
static void nct3018y_clkout_unprepare(struct clk_hw *hw)
{
nct3018y_clkout_control(hw, 0);
}
static int nct3018y_clkout_is_prepared(struct clk_hw *hw)
{
struct nct3018y *nct3018y = clkout_hw_to_nct3018y(hw);
struct i2c_client *client = nct3018y->client;
int flags;
flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CLKO);
if (flags < 0)
return flags;
return flags & NCT3018Y_REG_CLKO_CKE;
}
static const struct clk_ops nct3018y_clkout_ops = {
.prepare = nct3018y_clkout_prepare,
.unprepare = nct3018y_clkout_unprepare,
.is_prepared = nct3018y_clkout_is_prepared,
.recalc_rate = nct3018y_clkout_recalc_rate,
.round_rate = nct3018y_clkout_round_rate,
.set_rate = nct3018y_clkout_set_rate,
};
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 *clk;
struct clk_init_data init;
init.name = "nct3018y-clkout";
init.ops = &nct3018y_clkout_ops;
init.flags = 0;
init.parent_names = NULL;
init.num_parents = 0;
nct3018y->clkout_hw.init = &init;
/* optional override of the clockname */
of_property_read_string(node, "clock-output-names", &init.name);
/* register the clock */
clk = devm_clk_register(&client->dev, &nct3018y->clkout_hw);
if (!IS_ERR(clk))
of_clk_add_provider(node, of_clk_src_simple_get, clk);
return clk;
}
#endif
static const struct rtc_class_ops nct3018y_rtc_ops = {
.read_time = nct3018y_rtc_read_time,
.set_time = nct3018y_rtc_set_time,
.read_alarm = nct3018y_rtc_read_alarm,
.set_alarm = nct3018y_rtc_set_alarm,
.alarm_irq_enable = nct3018y_irq_enable,
.ioctl = nct3018y_ioctl,
};
static int nct3018y_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct nct3018y *nct3018y;
int err, flags;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BLOCK_DATA))
return -ENODEV;
nct3018y = devm_kzalloc(&client->dev, sizeof(struct nct3018y),
GFP_KERNEL);
if (!nct3018y)
return -ENOMEM;
i2c_set_clientdata(client, nct3018y);
nct3018y->client = client;
device_set_wakeup_capable(&client->dev, 1);
flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CTRL);
if (flags < 0) {
dev_dbg(&client->dev, "%s: read error\n", __func__);
return flags;
} else if (flags & NCT3018Y_BIT_TWO) {
dev_dbg(&client->dev, "%s: NCT3018Y_BIT_TWO is set\n", __func__);
}
flags = NCT3018Y_BIT_TWO;
err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_CTRL, flags);
if (err < 0) {
dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_CTRL\n");
return err;
}
flags = 0;
err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_ST, flags);
if (err < 0) {
dev_dbg(&client->dev, "%s: write error\n", __func__);
return err;
}
nct3018y->rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(nct3018y->rtc))
return PTR_ERR(nct3018y->rtc);
nct3018y->rtc->ops = &nct3018y_rtc_ops;
nct3018y->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
nct3018y->rtc->range_max = RTC_TIMESTAMP_END_2099;
if (client->irq > 0) {
err = devm_request_threaded_irq(&client->dev, client->irq,
NULL, nct3018y_irq,
IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
"nct3018y", client);
if (err) {
dev_dbg(&client->dev, "unable to request IRQ %d\n", client->irq);
return err;
}
} else {
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, nct3018y->rtc->features);
clear_bit(RTC_FEATURE_ALARM, nct3018y->rtc->features);
}
#ifdef CONFIG_COMMON_CLK
/* register clk in common clk framework */
nct3018y_clkout_register_clk(nct3018y);
#endif
return devm_rtc_register_device(nct3018y->rtc);
}
static const struct i2c_device_id nct3018y_id[] = {
{ "nct3018y", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, nct3018y_id);
static const struct of_device_id nct3018y_of_match[] = {
{ .compatible = "nuvoton,nct3018y" },
{}
};
MODULE_DEVICE_TABLE(of, nct3018y_of_match);
static struct i2c_driver nct3018y_driver = {
.driver = {
.name = "rtc-nct3018y",
.of_match_table = of_match_ptr(nct3018y_of_match),
},
.probe = nct3018y_probe,
.id_table = nct3018y_id,
};
module_i2c_driver(nct3018y_driver);
MODULE_AUTHOR("Medad CChien <ctcchien@nuvoton.com>");
MODULE_AUTHOR("Mia Lin <mimi05633@gmail.com>");
MODULE_DESCRIPTION("Nuvoton NCT3018Y RTC driver");
MODULE_LICENSE("GPL");
...@@ -390,8 +390,7 @@ static const struct regmap_config regmap_config = { ...@@ -390,8 +390,7 @@ static const struct regmap_config regmap_config = {
.max_register = 0x13, .max_register = 0x13,
}; };
static int pcf8523_probe(struct i2c_client *client, static int pcf8523_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct pcf8523 *pcf8523; struct pcf8523 *pcf8523;
struct rtc_device *rtc; struct rtc_device *rtc;
...@@ -485,7 +484,7 @@ static struct i2c_driver pcf8523_driver = { ...@@ -485,7 +484,7 @@ static struct i2c_driver pcf8523_driver = {
.name = "rtc-pcf8523", .name = "rtc-pcf8523",
.of_match_table = pcf8523_of_match, .of_match_table = pcf8523_of_match,
}, },
.probe = pcf8523_probe, .probe_new = pcf8523_probe,
.id_table = pcf8523_id, .id_table = pcf8523_id,
}; };
module_i2c_driver(pcf8523_driver); module_i2c_driver(pcf8523_driver);
......
...@@ -350,8 +350,7 @@ static const struct pcf85x63_config pcf_85363_config = { ...@@ -350,8 +350,7 @@ static const struct pcf85x63_config pcf_85363_config = {
.num_nvram = 2 .num_nvram = 2
}; };
static int pcf85363_probe(struct i2c_client *client, static int pcf85363_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct pcf85363 *pcf85363; struct pcf85363 *pcf85363;
const struct pcf85x63_config *config = &pcf_85363_config; const struct pcf85x63_config *config = &pcf_85363_config;
...@@ -436,7 +435,7 @@ static struct i2c_driver pcf85363_driver = { ...@@ -436,7 +435,7 @@ static struct i2c_driver pcf85363_driver = {
.name = "pcf85363", .name = "pcf85363",
.of_match_table = of_match_ptr(dev_ids), .of_match_table = of_match_ptr(dev_ids),
}, },
.probe = pcf85363_probe, .probe_new = pcf85363_probe,
}; };
module_i2c_driver(pcf85363_driver); module_i2c_driver(pcf85363_driver);
......
...@@ -509,8 +509,7 @@ static const struct rtc_class_ops pcf8563_rtc_ops = { ...@@ -509,8 +509,7 @@ static const struct rtc_class_ops pcf8563_rtc_ops = {
.alarm_irq_enable = pcf8563_irq_enable, .alarm_irq_enable = pcf8563_irq_enable,
}; };
static int pcf8563_probe(struct i2c_client *client, static int pcf8563_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct pcf8563 *pcf8563; struct pcf8563 *pcf8563;
int err; int err;
...@@ -606,7 +605,7 @@ static struct i2c_driver pcf8563_driver = { ...@@ -606,7 +605,7 @@ static struct i2c_driver pcf8563_driver = {
.name = "rtc-pcf8563", .name = "rtc-pcf8563",
.of_match_table = of_match_ptr(pcf8563_of_match), .of_match_table = of_match_ptr(pcf8563_of_match),
}, },
.probe = pcf8563_probe, .probe_new = pcf8563_probe,
.id_table = pcf8563_id, .id_table = pcf8563_id,
}; };
......
...@@ -275,8 +275,7 @@ static const struct rtc_class_ops pcf8583_rtc_ops = { ...@@ -275,8 +275,7 @@ static const struct rtc_class_ops pcf8583_rtc_ops = {
.set_time = pcf8583_rtc_set_time, .set_time = pcf8583_rtc_set_time,
}; };
static int pcf8583_probe(struct i2c_client *client, static int pcf8583_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct pcf8583 *pcf8583; struct pcf8583 *pcf8583;
...@@ -307,7 +306,7 @@ static struct i2c_driver pcf8583_driver = { ...@@ -307,7 +306,7 @@ static struct i2c_driver pcf8583_driver = {
.driver = { .driver = {
.name = "pcf8583", .name = "pcf8583",
}, },
.probe = pcf8583_probe, .probe_new = pcf8583_probe,
.id_table = pcf8583_id, .id_table = pcf8583_id,
}; };
......
...@@ -784,8 +784,7 @@ static const struct regmap_config config = { ...@@ -784,8 +784,7 @@ static const struct regmap_config config = {
#if IS_ENABLED(CONFIG_I2C) #if IS_ENABLED(CONFIG_I2C)
static int rv3029_i2c_probe(struct i2c_client *client, static int rv3029_i2c_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct regmap *regmap; struct regmap *regmap;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK |
...@@ -819,7 +818,7 @@ static struct i2c_driver rv3029_driver = { ...@@ -819,7 +818,7 @@ static struct i2c_driver rv3029_driver = {
.name = "rv3029", .name = "rv3029",
.of_match_table = of_match_ptr(rv3029_of_match), .of_match_table = of_match_ptr(rv3029_of_match),
}, },
.probe = rv3029_i2c_probe, .probe_new = rv3029_i2c_probe,
.id_table = rv3029_id, .id_table = rv3029_id,
}; };
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/bitfield.h>
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -33,6 +34,7 @@ ...@@ -33,6 +34,7 @@
#define RV8803_EXT 0x0D #define RV8803_EXT 0x0D
#define RV8803_FLAG 0x0E #define RV8803_FLAG 0x0E
#define RV8803_CTRL 0x0F #define RV8803_CTRL 0x0F
#define RV8803_OSC_OFFSET 0x2C
#define RV8803_EXT_WADA BIT(6) #define RV8803_EXT_WADA BIT(6)
...@@ -49,12 +51,15 @@ ...@@ -49,12 +51,15 @@
#define RV8803_CTRL_TIE BIT(4) #define RV8803_CTRL_TIE BIT(4)
#define RV8803_CTRL_UIE BIT(5) #define RV8803_CTRL_UIE BIT(5)
#define RX8803_CTRL_CSEL GENMASK(7, 6)
#define RX8900_BACKUP_CTRL 0x18 #define RX8900_BACKUP_CTRL 0x18
#define RX8900_FLAG_SWOFF BIT(2) #define RX8900_FLAG_SWOFF BIT(2)
#define RX8900_FLAG_VDETOFF BIT(3) #define RX8900_FLAG_VDETOFF BIT(3)
enum rv8803_type { enum rv8803_type {
rv_8803, rv_8803,
rx_8803,
rx_8804, rx_8804,
rx_8900 rx_8900
}; };
...@@ -64,6 +69,7 @@ struct rv8803_data { ...@@ -64,6 +69,7 @@ struct rv8803_data {
struct rtc_device *rtc; struct rtc_device *rtc;
struct mutex flags_lock; struct mutex flags_lock;
u8 ctrl; u8 ctrl;
u8 backup;
enum rv8803_type type; enum rv8803_type type;
}; };
...@@ -136,6 +142,44 @@ static int rv8803_write_regs(const struct i2c_client *client, ...@@ -136,6 +142,44 @@ static int rv8803_write_regs(const struct i2c_client *client,
return ret; return ret;
} }
static int rv8803_regs_init(struct rv8803_data *rv8803)
{
int ret;
ret = rv8803_write_reg(rv8803->client, RV8803_OSC_OFFSET, 0x00);
if (ret)
return ret;
ret = rv8803_write_reg(rv8803->client, RV8803_CTRL,
FIELD_PREP(RX8803_CTRL_CSEL, 1)); /* 2s */
if (ret)
return ret;
ret = rv8803_write_regs(rv8803->client, RV8803_ALARM_MIN, 3,
(u8[]){ 0, 0, 0 });
if (ret)
return ret;
return rv8803_write_reg(rv8803->client, RV8803_RAM, 0x00);
}
static int rv8803_regs_configure(struct rv8803_data *rv8803);
static int rv8803_regs_reset(struct rv8803_data *rv8803)
{
/*
* The RV-8803 resets all registers to POR defaults after voltage-loss,
* the Epson RTCs don't, so we manually reset the remainder here.
*/
if (rv8803->type == rx_8803 || rv8803->type == rx_8900) {
int ret = rv8803_regs_init(rv8803);
if (ret)
return ret;
}
return rv8803_regs_configure(rv8803);
}
static irqreturn_t rv8803_handle_irq(int irq, void *dev_id) static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
{ {
struct i2c_client *client = dev_id; struct i2c_client *client = dev_id;
...@@ -269,6 +313,14 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm) ...@@ -269,6 +313,14 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
return flags; return flags;
} }
if (flags & RV8803_FLAG_V2F) {
ret = rv8803_regs_reset(rv8803);
if (ret) {
mutex_unlock(&rv8803->flags_lock);
return ret;
}
}
ret = rv8803_write_reg(rv8803->client, RV8803_FLAG, ret = rv8803_write_reg(rv8803->client, RV8803_FLAG,
flags & ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F)); flags & ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F));
...@@ -498,18 +550,32 @@ static int rx8900_trickle_charger_init(struct rv8803_data *rv8803) ...@@ -498,18 +550,32 @@ static int rx8900_trickle_charger_init(struct rv8803_data *rv8803)
if (err < 0) if (err < 0)
return err; return err;
flags = ~(RX8900_FLAG_VDETOFF | RX8900_FLAG_SWOFF) & (u8)err; flags = (u8)err;
flags &= ~(RX8900_FLAG_VDETOFF | RX8900_FLAG_SWOFF);
if (of_property_read_bool(node, "epson,vdet-disable")) flags |= rv8803->backup;
flags |= RX8900_FLAG_VDETOFF;
if (of_property_read_bool(node, "trickle-diode-disable"))
flags |= RX8900_FLAG_SWOFF;
return i2c_smbus_write_byte_data(rv8803->client, RX8900_BACKUP_CTRL, return i2c_smbus_write_byte_data(rv8803->client, RX8900_BACKUP_CTRL,
flags); flags);
} }
/* configure registers with values different than the Power-On reset defaults */
static int rv8803_regs_configure(struct rv8803_data *rv8803)
{
int err;
err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA);
if (err)
return err;
err = rx8900_trickle_charger_init(rv8803);
if (err) {
dev_err(&rv8803->client->dev, "failed to init charger\n");
return err;
}
return 0;
}
static int rv8803_probe(struct i2c_client *client, static int rv8803_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -576,15 +642,15 @@ static int rv8803_probe(struct i2c_client *client, ...@@ -576,15 +642,15 @@ static int rv8803_probe(struct i2c_client *client,
if (!client->irq) if (!client->irq)
clear_bit(RTC_FEATURE_ALARM, rv8803->rtc->features); clear_bit(RTC_FEATURE_ALARM, rv8803->rtc->features);
err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA); if (of_property_read_bool(client->dev.of_node, "epson,vdet-disable"))
if (err) rv8803->backup |= RX8900_FLAG_VDETOFF;
return err;
err = rx8900_trickle_charger_init(rv8803); if (of_property_read_bool(client->dev.of_node, "trickle-diode-disable"))
if (err) { rv8803->backup |= RX8900_FLAG_SWOFF;
dev_err(&client->dev, "failed to init charger\n");
err = rv8803_regs_configure(rv8803);
if (err)
return err; return err;
}
rv8803->rtc->ops = &rv8803_rtc_ops; rv8803->rtc->ops = &rv8803_rtc_ops;
rv8803->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; rv8803->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
...@@ -603,7 +669,7 @@ static int rv8803_probe(struct i2c_client *client, ...@@ -603,7 +669,7 @@ static int rv8803_probe(struct i2c_client *client,
static const struct i2c_device_id rv8803_id[] = { static const struct i2c_device_id rv8803_id[] = {
{ "rv8803", rv_8803 }, { "rv8803", rv_8803 },
{ "rv8804", rx_8804 }, { "rv8804", rx_8804 },
{ "rx8803", rv_8803 }, { "rx8803", rx_8803 },
{ "rx8900", rx_8900 }, { "rx8900", rx_8900 },
{ } { }
}; };
...@@ -616,7 +682,7 @@ static const __maybe_unused struct of_device_id rv8803_of_match[] = { ...@@ -616,7 +682,7 @@ static const __maybe_unused struct of_device_id rv8803_of_match[] = {
}, },
{ {
.compatible = "epson,rx8803", .compatible = "epson,rx8803",
.data = (void *)rv_8803 .data = (void *)rx_8803
}, },
{ {
.compatible = "epson,rx8804", .compatible = "epson,rx8804",
......
...@@ -419,8 +419,7 @@ static struct regmap_config regmap_i2c_config = { ...@@ -419,8 +419,7 @@ static struct regmap_config regmap_i2c_config = {
.read_flag_mask = 0x80, .read_flag_mask = 0x80,
}; };
static int rx6110_i2c_probe(struct i2c_client *client, static int rx6110_i2c_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
struct rx6110_data *rx6110; struct rx6110_data *rx6110;
...@@ -464,7 +463,7 @@ static struct i2c_driver rx6110_i2c_driver = { ...@@ -464,7 +463,7 @@ static struct i2c_driver rx6110_i2c_driver = {
.name = RX6110_DRIVER_NAME, .name = RX6110_DRIVER_NAME,
.acpi_match_table = rx6110_i2c_acpi_match, .acpi_match_table = rx6110_i2c_acpi_match,
}, },
.probe = rx6110_i2c_probe, .probe_new = rx6110_i2c_probe,
.id_table = rx6110_i2c_id, .id_table = rx6110_i2c_id,
}; };
......
...@@ -55,6 +55,8 @@ ...@@ -55,6 +55,8 @@
#define RX8025_BIT_CTRL2_XST BIT(5) #define RX8025_BIT_CTRL2_XST BIT(5)
#define RX8025_BIT_CTRL2_VDET BIT(6) #define RX8025_BIT_CTRL2_VDET BIT(6)
#define RX8035_BIT_HOUR_1224 BIT(7)
/* Clock precision adjustment */ /* Clock precision adjustment */
#define RX8025_ADJ_RESOLUTION 3050 /* in ppb */ #define RX8025_ADJ_RESOLUTION 3050 /* in ppb */
#define RX8025_ADJ_DATA_MAX 62 #define RX8025_ADJ_DATA_MAX 62
...@@ -78,6 +80,7 @@ struct rx8025_data { ...@@ -78,6 +80,7 @@ struct rx8025_data {
struct rtc_device *rtc; struct rtc_device *rtc;
enum rx_model model; enum rx_model model;
u8 ctrl1; u8 ctrl1;
int is_24;
}; };
static s32 rx8025_read_reg(const struct i2c_client *client, u8 number) static s32 rx8025_read_reg(const struct i2c_client *client, u8 number)
...@@ -226,7 +229,7 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt) ...@@ -226,7 +229,7 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt)
dt->tm_sec = bcd2bin(date[RX8025_REG_SEC] & 0x7f); dt->tm_sec = bcd2bin(date[RX8025_REG_SEC] & 0x7f);
dt->tm_min = bcd2bin(date[RX8025_REG_MIN] & 0x7f); dt->tm_min = bcd2bin(date[RX8025_REG_MIN] & 0x7f);
if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224) if (rx8025->is_24)
dt->tm_hour = bcd2bin(date[RX8025_REG_HOUR] & 0x3f); dt->tm_hour = bcd2bin(date[RX8025_REG_HOUR] & 0x3f);
else else
dt->tm_hour = bcd2bin(date[RX8025_REG_HOUR] & 0x1f) % 12 dt->tm_hour = bcd2bin(date[RX8025_REG_HOUR] & 0x1f) % 12
...@@ -254,7 +257,7 @@ static int rx8025_set_time(struct device *dev, struct rtc_time *dt) ...@@ -254,7 +257,7 @@ static int rx8025_set_time(struct device *dev, struct rtc_time *dt)
*/ */
date[RX8025_REG_SEC] = bin2bcd(dt->tm_sec); date[RX8025_REG_SEC] = bin2bcd(dt->tm_sec);
date[RX8025_REG_MIN] = bin2bcd(dt->tm_min); date[RX8025_REG_MIN] = bin2bcd(dt->tm_min);
if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224) if (rx8025->is_24)
date[RX8025_REG_HOUR] = bin2bcd(dt->tm_hour); date[RX8025_REG_HOUR] = bin2bcd(dt->tm_hour);
else else
date[RX8025_REG_HOUR] = (dt->tm_hour >= 12 ? 0x20 : 0) date[RX8025_REG_HOUR] = (dt->tm_hour >= 12 ? 0x20 : 0)
...@@ -279,6 +282,7 @@ static int rx8025_init_client(struct i2c_client *client) ...@@ -279,6 +282,7 @@ static int rx8025_init_client(struct i2c_client *client)
struct rx8025_data *rx8025 = i2c_get_clientdata(client); struct rx8025_data *rx8025 = i2c_get_clientdata(client);
u8 ctrl[2], ctrl2; u8 ctrl[2], ctrl2;
int need_clear = 0; int need_clear = 0;
int hour_reg;
int err; int err;
err = rx8025_read_regs(client, RX8025_REG_CTRL1, 2, ctrl); err = rx8025_read_regs(client, RX8025_REG_CTRL1, 2, ctrl);
...@@ -303,6 +307,16 @@ static int rx8025_init_client(struct i2c_client *client) ...@@ -303,6 +307,16 @@ static int rx8025_init_client(struct i2c_client *client)
err = rx8025_write_reg(client, RX8025_REG_CTRL2, ctrl2); err = rx8025_write_reg(client, RX8025_REG_CTRL2, ctrl2);
} }
if (rx8025->model == model_rx_8035) {
/* In RX-8035, 12/24 flag is in the hour register */
hour_reg = rx8025_read_reg(client, RX8025_REG_HOUR);
if (hour_reg < 0)
return hour_reg;
rx8025->is_24 = (hour_reg & RX8035_BIT_HOUR_1224);
} else {
rx8025->is_24 = (ctrl[1] & RX8025_BIT_CTRL1_1224);
}
out: out:
return err; return err;
} }
...@@ -329,7 +343,7 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -329,7 +343,7 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t)
/* Hardware alarms precision is 1 minute! */ /* Hardware alarms precision is 1 minute! */
t->time.tm_sec = 0; t->time.tm_sec = 0;
t->time.tm_min = bcd2bin(ald[0] & 0x7f); t->time.tm_min = bcd2bin(ald[0] & 0x7f);
if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224) if (rx8025->is_24)
t->time.tm_hour = bcd2bin(ald[1] & 0x3f); t->time.tm_hour = bcd2bin(ald[1] & 0x3f);
else else
t->time.tm_hour = bcd2bin(ald[1] & 0x1f) % 12 t->time.tm_hour = bcd2bin(ald[1] & 0x1f) % 12
...@@ -350,7 +364,7 @@ static int rx8025_set_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -350,7 +364,7 @@ static int rx8025_set_alarm(struct device *dev, struct rtc_wkalrm *t)
int err; int err;
ald[0] = bin2bcd(t->time.tm_min); ald[0] = bin2bcd(t->time.tm_min);
if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224) if (rx8025->is_24)
ald[1] = bin2bcd(t->time.tm_hour); ald[1] = bin2bcd(t->time.tm_hour);
else else
ald[1] = (t->time.tm_hour >= 12 ? 0x20 : 0) ald[1] = (t->time.tm_hour >= 12 ? 0x20 : 0)
......
...@@ -248,8 +248,7 @@ static const struct rx85x1_config rx8571_config = { ...@@ -248,8 +248,7 @@ static const struct rx85x1_config rx8571_config = {
.num_nvram = 2 .num_nvram = 2
}; };
static int rx8581_probe(struct i2c_client *client, static int rx8581_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct rx8581 *rx8581; struct rx8581 *rx8581;
const struct rx85x1_config *config = &rx8581_config; const struct rx85x1_config *config = &rx8581_config;
...@@ -326,7 +325,7 @@ static struct i2c_driver rx8581_driver = { ...@@ -326,7 +325,7 @@ static struct i2c_driver rx8581_driver = {
.name = "rtc-rx8581", .name = "rtc-rx8581",
.of_match_table = of_match_ptr(rx8581_of_match), .of_match_table = of_match_ptr(rx8581_of_match),
}, },
.probe = rx8581_probe, .probe_new = rx8581_probe,
.id_table = rx8581_id, .id_table = rx8581_id,
}; };
......
...@@ -420,8 +420,7 @@ static const struct rtc_class_ops s35390a_rtc_ops = { ...@@ -420,8 +420,7 @@ static const struct rtc_class_ops s35390a_rtc_ops = {
.ioctl = s35390a_rtc_ioctl, .ioctl = s35390a_rtc_ioctl,
}; };
static int s35390a_probe(struct i2c_client *client, static int s35390a_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
int err, err_read; int err, err_read;
unsigned int i; unsigned int i;
...@@ -502,7 +501,7 @@ static struct i2c_driver s35390a_driver = { ...@@ -502,7 +501,7 @@ static struct i2c_driver s35390a_driver = {
.name = "rtc-s35390a", .name = "rtc-s35390a",
.of_match_table = of_match_ptr(s35390a_of_match), .of_match_table = of_match_ptr(s35390a_of_match),
}, },
.probe = s35390a_probe, .probe_new = s35390a_probe,
.id_table = s35390a_id, .id_table = s35390a_id,
}; };
......
...@@ -163,8 +163,7 @@ static const struct regmap_config regmap_config = { ...@@ -163,8 +163,7 @@ static const struct regmap_config regmap_config = {
.max_register = 0x11, .max_register = 0x11,
}; };
static int sd3078_probe(struct i2c_client *client, static int sd3078_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
int ret; int ret;
struct sd3078 *sd3078; struct sd3078 *sd3078;
...@@ -218,7 +217,7 @@ static struct i2c_driver sd3078_driver = { ...@@ -218,7 +217,7 @@ static struct i2c_driver sd3078_driver = {
.name = "sd3078", .name = "sd3078",
.of_match_table = of_match_ptr(rtc_dt_match), .of_match_table = of_match_ptr(rtc_dt_match),
}, },
.probe = sd3078_probe, .probe_new = sd3078_probe,
.id_table = sd3078_id, .id_table = sd3078_id,
}; };
......
...@@ -388,7 +388,7 @@ static int spear_rtc_probe(struct platform_device *pdev) ...@@ -388,7 +388,7 @@ static int spear_rtc_probe(struct platform_device *pdev)
config->rtc->ops = &spear_rtc_ops; config->rtc->ops = &spear_rtc_ops;
config->rtc->range_min = RTC_TIMESTAMP_BEGIN_0000; config->rtc->range_min = RTC_TIMESTAMP_BEGIN_0000;
config->rtc->range_min = RTC_TIMESTAMP_END_9999; config->rtc->range_max = RTC_TIMESTAMP_END_9999;
status = devm_rtc_register_device(config->rtc); status = devm_rtc_register_device(config->rtc);
if (status) if (status)
......
...@@ -875,6 +875,8 @@ static const struct of_device_id sun6i_rtc_dt_ids[] = { ...@@ -875,6 +875,8 @@ static const struct of_device_id sun6i_rtc_dt_ids[] = {
{ .compatible = "allwinner,sun50i-h6-rtc" }, { .compatible = "allwinner,sun50i-h6-rtc" },
{ .compatible = "allwinner,sun50i-h616-rtc", { .compatible = "allwinner,sun50i-h616-rtc",
.data = (void *)RTC_LINEAR_DAY }, .data = (void *)RTC_LINEAR_DAY },
{ .compatible = "allwinner,sun50i-r329-rtc",
.data = (void *)RTC_LINEAR_DAY },
{ /* sentinel */ }, { /* sentinel */ },
}; };
MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids);
......
// SPDX-License-Identifier: GPL-2.0
/*
* Texas Instruments K3 RTC driver
*
* Copyright (C) 2021-2022 Texas Instruments Incorporated - https://www.ti.com/
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/rtc.h>
/* Registers */
#define REG_K3RTC_S_CNT_LSW 0x08
#define REG_K3RTC_S_CNT_MSW 0x0c
#define REG_K3RTC_COMP 0x10
#define REG_K3RTC_ON_OFF_S_CNT_LSW 0x20
#define REG_K3RTC_ON_OFF_S_CNT_MSW 0x24
#define REG_K3RTC_SCRATCH0 0x30
#define REG_K3RTC_SCRATCH7 0x4c
#define REG_K3RTC_GENERAL_CTL 0x50
#define REG_K3RTC_IRQSTATUS_RAW_SYS 0x54
#define REG_K3RTC_IRQSTATUS_SYS 0x58
#define REG_K3RTC_IRQENABLE_SET_SYS 0x5c
#define REG_K3RTC_IRQENABLE_CLR_SYS 0x60
#define REG_K3RTC_SYNCPEND 0x68
#define REG_K3RTC_KICK0 0x70
#define REG_K3RTC_KICK1 0x74
/* Freeze when lsw is read and unfreeze when msw is read */
#define K3RTC_CNT_FMODE_S_CNT_VALUE (0x2 << 24)
/* Magic values for lock/unlock */
#define K3RTC_KICK0_UNLOCK_VALUE 0x83e70b13
#define K3RTC_KICK1_UNLOCK_VALUE 0x95a4f1e0
/* Multiplier for ppb conversions */
#define K3RTC_PPB_MULT (1000000000LL)
/* Min and max values supported with 'offset' interface (swapped sign) */
#define K3RTC_MIN_OFFSET (-277761)
#define K3RTC_MAX_OFFSET (277778)
/**
* struct ti_k3_rtc_soc_data - Private of compatible data for ti-k3-rtc
* @unlock_irq_erratum: Has erratum for unlock infinite IRQs (erratum i2327)
*/
struct ti_k3_rtc_soc_data {
const bool unlock_irq_erratum;
};
static const struct regmap_config ti_k3_rtc_regmap_config = {
.name = "peripheral-registers",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.max_register = REG_K3RTC_KICK1,
};
enum ti_k3_rtc_fields {
K3RTC_KICK0,
K3RTC_KICK1,
K3RTC_S_CNT_LSW,
K3RTC_S_CNT_MSW,
K3RTC_O32K_OSC_DEP_EN,
K3RTC_UNLOCK,
K3RTC_CNT_FMODE,
K3RTC_PEND,
K3RTC_RELOAD_FROM_BBD,
K3RTC_COMP,
K3RTC_ALM_S_CNT_LSW,
K3RTC_ALM_S_CNT_MSW,
K3RTC_IRQ_STATUS_RAW,
K3RTC_IRQ_STATUS,
K3RTC_IRQ_ENABLE_SET,
K3RTC_IRQ_ENABLE_CLR,
K3RTC_IRQ_STATUS_ALT,
K3RTC_IRQ_ENABLE_CLR_ALT,
K3_RTC_MAX_FIELDS
};
static const struct reg_field ti_rtc_reg_fields[] = {
[K3RTC_KICK0] = REG_FIELD(REG_K3RTC_KICK0, 0, 31),
[K3RTC_KICK1] = REG_FIELD(REG_K3RTC_KICK1, 0, 31),
[K3RTC_S_CNT_LSW] = REG_FIELD(REG_K3RTC_S_CNT_LSW, 0, 31),
[K3RTC_S_CNT_MSW] = REG_FIELD(REG_K3RTC_S_CNT_MSW, 0, 15),
[K3RTC_O32K_OSC_DEP_EN] = REG_FIELD(REG_K3RTC_GENERAL_CTL, 21, 21),
[K3RTC_UNLOCK] = REG_FIELD(REG_K3RTC_GENERAL_CTL, 23, 23),
[K3RTC_CNT_FMODE] = REG_FIELD(REG_K3RTC_GENERAL_CTL, 24, 25),
[K3RTC_PEND] = REG_FIELD(REG_K3RTC_SYNCPEND, 0, 1),
[K3RTC_RELOAD_FROM_BBD] = REG_FIELD(REG_K3RTC_SYNCPEND, 31, 31),
[K3RTC_COMP] = REG_FIELD(REG_K3RTC_COMP, 0, 31),
/* We use on to off as alarm trigger */
[K3RTC_ALM_S_CNT_LSW] = REG_FIELD(REG_K3RTC_ON_OFF_S_CNT_LSW, 0, 31),
[K3RTC_ALM_S_CNT_MSW] = REG_FIELD(REG_K3RTC_ON_OFF_S_CNT_MSW, 0, 15),
[K3RTC_IRQ_STATUS_RAW] = REG_FIELD(REG_K3RTC_IRQSTATUS_RAW_SYS, 0, 0),
[K3RTC_IRQ_STATUS] = REG_FIELD(REG_K3RTC_IRQSTATUS_SYS, 0, 0),
[K3RTC_IRQ_ENABLE_SET] = REG_FIELD(REG_K3RTC_IRQENABLE_SET_SYS, 0, 0),
[K3RTC_IRQ_ENABLE_CLR] = REG_FIELD(REG_K3RTC_IRQENABLE_CLR_SYS, 0, 0),
/* Off to on is alternate */
[K3RTC_IRQ_STATUS_ALT] = REG_FIELD(REG_K3RTC_IRQSTATUS_SYS, 1, 1),
[K3RTC_IRQ_ENABLE_CLR_ALT] = REG_FIELD(REG_K3RTC_IRQENABLE_CLR_SYS, 1, 1),
};
/**
* struct ti_k3_rtc - Private data for ti-k3-rtc
* @irq: IRQ
* @sync_timeout_us: data sync timeout period in uSec
* @rate_32k: 32k clock rate in Hz
* @rtc_dev: rtc device
* @regmap: rtc mmio regmap
* @r_fields: rtc register fields
* @soc: SoC compatible match data
*/
struct ti_k3_rtc {
unsigned int irq;
u32 sync_timeout_us;
unsigned long rate_32k;
struct rtc_device *rtc_dev;
struct regmap *regmap;
struct regmap_field *r_fields[K3_RTC_MAX_FIELDS];
const struct ti_k3_rtc_soc_data *soc;
};
static int k3rtc_field_read(struct ti_k3_rtc *priv, enum ti_k3_rtc_fields f)
{
int ret;
int val;
ret = regmap_field_read(priv->r_fields[f], &val);
/*
* We shouldn't be seeing regmap fail on us for mmio reads
* This is possible if clock context fails, but that isn't the case for us
*/
if (WARN_ON_ONCE(ret))
return ret;
return val;
}
static void k3rtc_field_write(struct ti_k3_rtc *priv, enum ti_k3_rtc_fields f, u32 val)
{
regmap_field_write(priv->r_fields[f], val);
}
/**
* k3rtc_fence - Ensure a register sync took place between the two domains
* @priv: pointer to priv data
*
* Return: 0 if the sync took place, else returns -ETIMEDOUT
*/
static int k3rtc_fence(struct ti_k3_rtc *priv)
{
int ret;
ret = regmap_field_read_poll_timeout(priv->r_fields[K3RTC_PEND], ret,
!ret, 2, priv->sync_timeout_us);
return ret;
}
static inline int k3rtc_check_unlocked(struct ti_k3_rtc *priv)
{
int ret;
ret = k3rtc_field_read(priv, K3RTC_UNLOCK);
if (ret < 0)
return ret;
return (ret) ? 0 : 1;
}
static int k3rtc_unlock_rtc(struct ti_k3_rtc *priv)
{
int ret;
ret = k3rtc_check_unlocked(priv);
if (!ret)
return ret;
k3rtc_field_write(priv, K3RTC_KICK0, K3RTC_KICK0_UNLOCK_VALUE);
k3rtc_field_write(priv, K3RTC_KICK1, K3RTC_KICK1_UNLOCK_VALUE);
/* Skip fence since we are going to check the unlock bit as fence */
ret = regmap_field_read_poll_timeout(priv->r_fields[K3RTC_UNLOCK], ret,
!ret, 2, priv->sync_timeout_us);
return ret;
}
static int k3rtc_configure(struct device *dev)
{
int ret;
struct ti_k3_rtc *priv = dev_get_drvdata(dev);
/*
* HWBUG: The compare state machine is broken if the RTC module
* is NOT unlocked in under one second of boot - which is pretty long
* time from the perspective of Linux driver (module load, u-boot
* shell all can take much longer than this.
*
* In such occurrence, it is assumed that the RTC module is unusable
*/
if (priv->soc->unlock_irq_erratum) {
ret = k3rtc_check_unlocked(priv);
/* If there is an error OR if we are locked, return error */
if (ret) {
dev_err(dev,
HW_ERR "Erratum i2327 unlock QUIRK! Cannot operate!!\n");
return -EFAULT;
}
} else {
/* May need to explicitly unlock first time */
ret = k3rtc_unlock_rtc(priv);
if (ret) {
dev_err(dev, "Failed to unlock(%d)!\n", ret);
return ret;
}
}
/* Enable Shadow register sync on 32k clock boundary */
k3rtc_field_write(priv, K3RTC_O32K_OSC_DEP_EN, 0x1);
/*
* Wait at least clock sync time before proceeding further programming.
* This ensures that the 32k based sync is active.
*/
usleep_range(priv->sync_timeout_us, priv->sync_timeout_us + 5);
/* We need to ensure fence here to make sure sync here */
ret = k3rtc_fence(priv);
if (ret) {
dev_err(dev,
"Failed fence osc_dep enable(%d) - is 32k clk working?!\n", ret);
return ret;
}
/*
* FMODE setting: Reading lower seconds will freeze value on higher
* seconds. This also implies that we must *ALWAYS* read lower seconds
* prior to reading higher seconds
*/
k3rtc_field_write(priv, K3RTC_CNT_FMODE, K3RTC_CNT_FMODE_S_CNT_VALUE);
/* Clear any spurious IRQ sources if any */
k3rtc_field_write(priv, K3RTC_IRQ_STATUS_ALT, 0x1);
k3rtc_field_write(priv, K3RTC_IRQ_STATUS, 0x1);
/* Disable all IRQs */
k3rtc_field_write(priv, K3RTC_IRQ_ENABLE_CLR_ALT, 0x1);
k3rtc_field_write(priv, K3RTC_IRQ_ENABLE_CLR, 0x1);
/* And.. Let us Sync the writes in */
return k3rtc_fence(priv);
}
static int ti_k3_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct ti_k3_rtc *priv = dev_get_drvdata(dev);
u32 seconds_lo, seconds_hi;
seconds_lo = k3rtc_field_read(priv, K3RTC_S_CNT_LSW);
seconds_hi = k3rtc_field_read(priv, K3RTC_S_CNT_MSW);
rtc_time64_to_tm((((time64_t)seconds_hi) << 32) | (time64_t)seconds_lo, tm);
return 0;
}
static int ti_k3_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct ti_k3_rtc *priv = dev_get_drvdata(dev);
time64_t seconds;
seconds = rtc_tm_to_time64(tm);
/*
* Read operation on LSW will freeze the RTC, so to update
* the time, we cannot use field operations. Just write since the
* reserved bits are ignored.
*/
regmap_write(priv->regmap, REG_K3RTC_S_CNT_LSW, seconds);
regmap_write(priv->regmap, REG_K3RTC_S_CNT_MSW, seconds >> 32);
return k3rtc_fence(priv);
}
static int ti_k3_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct ti_k3_rtc *priv = dev_get_drvdata(dev);
u32 reg;
u32 offset = enabled ? K3RTC_IRQ_ENABLE_SET : K3RTC_IRQ_ENABLE_CLR;
reg = k3rtc_field_read(priv, K3RTC_IRQ_ENABLE_SET);
if ((enabled && reg) || (!enabled && !reg))
return 0;
k3rtc_field_write(priv, offset, 0x1);
/*
* Ensure the write sync is through - NOTE: it should be OK to have
* ISR to fire as we are checking sync (which should be done in a 32k
* cycle or so).
*/
return k3rtc_fence(priv);
}
static int ti_k3_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct ti_k3_rtc *priv = dev_get_drvdata(dev);
u32 seconds_lo, seconds_hi;
seconds_lo = k3rtc_field_read(priv, K3RTC_ALM_S_CNT_LSW);
seconds_hi = k3rtc_field_read(priv, K3RTC_ALM_S_CNT_MSW);
rtc_time64_to_tm((((time64_t)seconds_hi) << 32) | (time64_t)seconds_lo, &alarm->time);
alarm->enabled = k3rtc_field_read(priv, K3RTC_IRQ_ENABLE_SET);
return 0;
}
static int ti_k3_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct ti_k3_rtc *priv = dev_get_drvdata(dev);
time64_t seconds;
int ret;
seconds = rtc_tm_to_time64(&alarm->time);
k3rtc_field_write(priv, K3RTC_ALM_S_CNT_LSW, seconds);
k3rtc_field_write(priv, K3RTC_ALM_S_CNT_MSW, (seconds >> 32));
/* Make sure the alarm time is synced in */
ret = k3rtc_fence(priv);
if (ret) {
dev_err(dev, "Failed to fence(%d)! Potential config issue?\n", ret);
return ret;
}
/* Alarm IRQ enable will do a sync */
return ti_k3_rtc_alarm_irq_enable(dev, alarm->enabled);
}
static int ti_k3_rtc_read_offset(struct device *dev, long *offset)
{
struct ti_k3_rtc *priv = dev_get_drvdata(dev);
u32 ticks_per_hr = priv->rate_32k * 3600;
int comp;
s64 tmp;
comp = k3rtc_field_read(priv, K3RTC_COMP);
/* Convert from RTC calibration register format to ppb format */
tmp = comp * (s64)K3RTC_PPB_MULT;
if (tmp < 0)
tmp -= ticks_per_hr / 2LL;
else
tmp += ticks_per_hr / 2LL;
tmp = div_s64(tmp, ticks_per_hr);
/* Offset value operates in negative way, so swap sign */
*offset = (long)-tmp;
return 0;
}
static int ti_k3_rtc_set_offset(struct device *dev, long offset)
{
struct ti_k3_rtc *priv = dev_get_drvdata(dev);
u32 ticks_per_hr = priv->rate_32k * 3600;
int comp;
s64 tmp;
/* Make sure offset value is within supported range */
if (offset < K3RTC_MIN_OFFSET || offset > K3RTC_MAX_OFFSET)
return -ERANGE;
/* Convert from ppb format to RTC calibration register format */
tmp = offset * (s64)ticks_per_hr;
if (tmp < 0)
tmp -= K3RTC_PPB_MULT / 2LL;
else
tmp += K3RTC_PPB_MULT / 2LL;
tmp = div_s64(tmp, K3RTC_PPB_MULT);
/* Offset value operates in negative way, so swap sign */
comp = (int)-tmp;
k3rtc_field_write(priv, K3RTC_COMP, comp);
return k3rtc_fence(priv);
}
static irqreturn_t ti_k3_rtc_interrupt(s32 irq, void *dev_id)
{
struct device *dev = dev_id;
struct ti_k3_rtc *priv = dev_get_drvdata(dev);
u32 reg;
int ret;
/*
* IRQ assertion can be very fast, however, the IRQ Status clear
* de-assert depends on 32k clock edge in the 32k domain
* If we clear the status prior to the first 32k clock edge,
* the status bit is cleared, but the IRQ stays re-asserted.
*
* To prevent this condition, we need to wait for clock sync time.
* We can either do that by polling the 32k observability signal for
* a toggle OR we could just sleep and let the processor do other
* stuff.
*/
usleep_range(priv->sync_timeout_us, priv->sync_timeout_us + 2);
/* Lets make sure that this is a valid interrupt */
reg = k3rtc_field_read(priv, K3RTC_IRQ_STATUS);
if (!reg) {
u32 raw = k3rtc_field_read(priv, K3RTC_IRQ_STATUS_RAW);
dev_err(dev,
HW_ERR
"Erratum i2327/IRQ trig: status: 0x%08x / 0x%08x\n", reg, raw);
return IRQ_NONE;
}
/*
* Write 1 to clear status reg
* We cannot use a field operation here due to a potential race between
* 32k domain and vbus domain.
*/
regmap_write(priv->regmap, REG_K3RTC_IRQSTATUS_SYS, 0x1);
/* Sync the write in */
ret = k3rtc_fence(priv);
if (ret) {
dev_err(dev, "Failed to fence irq status clr(%d)!\n", ret);
return IRQ_NONE;
}
/*
* Force the 32k status to be reloaded back in to ensure status is
* reflected back correctly.
*/
k3rtc_field_write(priv, K3RTC_RELOAD_FROM_BBD, 0x1);
/* Ensure the write sync is through */
ret = k3rtc_fence(priv);
if (ret) {
dev_err(dev, "Failed to fence reload from bbd(%d)!\n", ret);
return IRQ_NONE;
}
/* Now we ensure that the status bit is cleared */
ret = regmap_field_read_poll_timeout(priv->r_fields[K3RTC_IRQ_STATUS],
ret, !ret, 2, priv->sync_timeout_us);
if (ret) {
dev_err(dev, "Time out waiting for status clear\n");
return IRQ_NONE;
}
/* Notify RTC core on event */
rtc_update_irq(priv->rtc_dev, 1, RTC_IRQF | RTC_AF);
return IRQ_HANDLED;
}
static const struct rtc_class_ops ti_k3_rtc_ops = {
.read_time = ti_k3_rtc_read_time,
.set_time = ti_k3_rtc_set_time,
.read_alarm = ti_k3_rtc_read_alarm,
.set_alarm = ti_k3_rtc_set_alarm,
.read_offset = ti_k3_rtc_read_offset,
.set_offset = ti_k3_rtc_set_offset,
.alarm_irq_enable = ti_k3_rtc_alarm_irq_enable,
};
static int ti_k3_rtc_scratch_read(void *priv_data, unsigned int offset,
void *val, size_t bytes)
{
struct ti_k3_rtc *priv = (struct ti_k3_rtc *)priv_data;
return regmap_bulk_read(priv->regmap, REG_K3RTC_SCRATCH0 + offset, val, bytes / 4);
}
static int ti_k3_rtc_scratch_write(void *priv_data, unsigned int offset,
void *val, size_t bytes)
{
struct ti_k3_rtc *priv = (struct ti_k3_rtc *)priv_data;
int ret;
ret = regmap_bulk_write(priv->regmap, REG_K3RTC_SCRATCH0 + offset, val, bytes / 4);
if (ret)
return ret;
return k3rtc_fence(priv);
}
static struct nvmem_config ti_k3_rtc_nvmem_config = {
.name = "ti_k3_rtc_scratch",
.word_size = 4,
.stride = 4,
.size = REG_K3RTC_SCRATCH7 - REG_K3RTC_SCRATCH0 + 4,
.reg_read = ti_k3_rtc_scratch_read,
.reg_write = ti_k3_rtc_scratch_write,
};
static int k3rtc_get_32kclk(struct device *dev, struct ti_k3_rtc *priv)
{
int ret;
struct clk *clk;
clk = devm_clk_get(dev, "osc32k");
if (IS_ERR(clk))
return PTR_ERR(clk);
ret = clk_prepare_enable(clk);
if (ret)
return ret;
ret = devm_add_action_or_reset(dev, (void (*)(void *))clk_disable_unprepare, clk);
if (ret)
return ret;
priv->rate_32k = clk_get_rate(clk);
/* Make sure we are exact 32k clock. Else, try to compensate delay */
if (priv->rate_32k != 32768)
dev_warn(dev, "Clock rate %ld is not 32768! Could misbehave!\n",
priv->rate_32k);
/*
* Sync timeout should be two 32k clk sync cycles = ~61uS. We double
* it to comprehend intermediate bus segment and cpu frequency
* deltas
*/
priv->sync_timeout_us = (u32)(DIV_ROUND_UP_ULL(1000000, priv->rate_32k) * 4);
return ret;
}
static int k3rtc_get_vbusclk(struct device *dev, struct ti_k3_rtc *priv)
{
int ret;
struct clk *clk;
/* Note: VBUS isn't a context clock, it is needed for hardware operation */
clk = devm_clk_get(dev, "vbus");
if (IS_ERR(clk))
return PTR_ERR(clk);
ret = clk_prepare_enable(clk);
if (ret)
return ret;
return devm_add_action_or_reset(dev, (void (*)(void *))clk_disable_unprepare, clk);
}
static int ti_k3_rtc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct ti_k3_rtc *priv;
void __iomem *rtc_base;
int ret;
priv = devm_kzalloc(dev, sizeof(struct ti_k3_rtc), GFP_KERNEL);
if (!priv)
return -ENOMEM;
rtc_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rtc_base))
return PTR_ERR(rtc_base);
priv->regmap = devm_regmap_init_mmio(dev, rtc_base, &ti_k3_rtc_regmap_config);
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
ret = devm_regmap_field_bulk_alloc(dev, priv->regmap, priv->r_fields,
ti_rtc_reg_fields, K3_RTC_MAX_FIELDS);
if (ret)
return ret;
ret = k3rtc_get_32kclk(dev, priv);
if (ret)
return ret;
ret = k3rtc_get_vbusclk(dev, priv);
if (ret)
return ret;
ret = platform_get_irq(pdev, 0);
if (ret < 0)
return ret;
priv->irq = (unsigned int)ret;
priv->rtc_dev = devm_rtc_allocate_device(dev);
if (IS_ERR(priv->rtc_dev))
return PTR_ERR(priv->rtc_dev);
priv->soc = of_device_get_match_data(dev);
priv->rtc_dev->ops = &ti_k3_rtc_ops;
priv->rtc_dev->range_max = (1ULL << 48) - 1; /* 48Bit seconds */
ti_k3_rtc_nvmem_config.priv = priv;
ret = devm_request_threaded_irq(dev, priv->irq, NULL,
ti_k3_rtc_interrupt,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
dev_name(dev), dev);
if (ret) {
dev_err(dev, "Could not request IRQ: %d\n", ret);
return ret;
}
platform_set_drvdata(pdev, priv);
ret = k3rtc_configure(dev);
if (ret)
return ret;
if (device_property_present(dev, "wakeup-source"))
device_init_wakeup(dev, true);
else
device_set_wakeup_capable(dev, true);
ret = devm_rtc_register_device(priv->rtc_dev);
if (ret)
return ret;
return devm_rtc_nvmem_register(priv->rtc_dev, &ti_k3_rtc_nvmem_config);
}
static const struct ti_k3_rtc_soc_data ti_k3_am62_data = {
.unlock_irq_erratum = true,
};
static const struct of_device_id ti_k3_rtc_of_match_table[] = {
{.compatible = "ti,am62-rtc", .data = &ti_k3_am62_data},
{}
};
MODULE_DEVICE_TABLE(of, ti_k3_rtc_of_match_table);
static int __maybe_unused ti_k3_rtc_suspend(struct device *dev)
{
struct ti_k3_rtc *priv = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
enable_irq_wake(priv->irq);
return 0;
}
static int __maybe_unused ti_k3_rtc_resume(struct device *dev)
{
struct ti_k3_rtc *priv = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
disable_irq_wake(priv->irq);
return 0;
}
static SIMPLE_DEV_PM_OPS(ti_k3_rtc_pm_ops, ti_k3_rtc_suspend, ti_k3_rtc_resume);
static struct platform_driver ti_k3_rtc_driver = {
.probe = ti_k3_rtc_probe,
.driver = {
.name = "rtc-ti-k3",
.of_match_table = ti_k3_rtc_of_match_table,
.pm = &ti_k3_rtc_pm_ops,
},
};
module_platform_driver(ti_k3_rtc_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("TI K3 RTC driver");
MODULE_AUTHOR("Nishanth Menon");
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Driver for NEC VR4100 series Real Time Clock unit.
*
* Copyright (C) 2003-2008 Yoichi Yuasa <yuasa@linux-mips.org>
*/
#include <linux/compat.h>
#include <linux/err.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/log2.h>
#include <asm/div64.h>
MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
MODULE_LICENSE("GPL v2");
/* RTC 1 registers */
#define ETIMELREG 0x00
#define ETIMEMREG 0x02
#define ETIMEHREG 0x04
/* RFU */
#define ECMPLREG 0x08
#define ECMPMREG 0x0a
#define ECMPHREG 0x0c
/* RFU */
#define RTCL1LREG 0x10
#define RTCL1HREG 0x12
#define RTCL1CNTLREG 0x14
#define RTCL1CNTHREG 0x16
#define RTCL2LREG 0x18
#define RTCL2HREG 0x1a
#define RTCL2CNTLREG 0x1c
#define RTCL2CNTHREG 0x1e
/* RTC 2 registers */
#define TCLKLREG 0x00
#define TCLKHREG 0x02
#define TCLKCNTLREG 0x04
#define TCLKCNTHREG 0x06
/* RFU */
#define RTCINTREG 0x1e
#define TCLOCK_INT 0x08
#define RTCLONG2_INT 0x04
#define RTCLONG1_INT 0x02
#define ELAPSEDTIME_INT 0x01
#define RTC_FREQUENCY 32768
#define MAX_PERIODIC_RATE 6553
static void __iomem *rtc1_base;
static void __iomem *rtc2_base;
#define rtc1_read(offset) readw(rtc1_base + (offset))
#define rtc1_write(offset, value) writew((value), rtc1_base + (offset))
#define rtc2_read(offset) readw(rtc2_base + (offset))
#define rtc2_write(offset, value) writew((value), rtc2_base + (offset))
/* 32-bit compat for ioctls that nobody else uses */
#define RTC_EPOCH_READ32 _IOR('p', 0x0d, __u32)
static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */
static DEFINE_SPINLOCK(rtc_lock);
static char rtc_name[] = "RTC";
static unsigned long periodic_count;
static unsigned int alarm_enabled;
static int aie_irq;
static int pie_irq;
static inline time64_t read_elapsed_second(void)
{
unsigned long first_low, first_mid, first_high;
unsigned long second_low, second_mid, second_high;
do {
first_low = rtc1_read(ETIMELREG);
first_mid = rtc1_read(ETIMEMREG);
first_high = rtc1_read(ETIMEHREG);
second_low = rtc1_read(ETIMELREG);
second_mid = rtc1_read(ETIMEMREG);
second_high = rtc1_read(ETIMEHREG);
} while (first_low != second_low || first_mid != second_mid ||
first_high != second_high);
return ((u64)first_high << 17) | (first_mid << 1) | (first_low >> 15);
}
static inline void write_elapsed_second(time64_t sec)
{
spin_lock_irq(&rtc_lock);
rtc1_write(ETIMELREG, (uint16_t)(sec << 15));
rtc1_write(ETIMEMREG, (uint16_t)(sec >> 1));
rtc1_write(ETIMEHREG, (uint16_t)(sec >> 17));
spin_unlock_irq(&rtc_lock);
}
static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time)
{
time64_t epoch_sec, elapsed_sec;
epoch_sec = mktime64(epoch, 1, 1, 0, 0, 0);
elapsed_sec = read_elapsed_second();
rtc_time64_to_tm(epoch_sec + elapsed_sec, time);
return 0;
}
static int vr41xx_rtc_set_time(struct device *dev, struct rtc_time *time)
{
time64_t epoch_sec, current_sec;
epoch_sec = mktime64(epoch, 1, 1, 0, 0, 0);
current_sec = rtc_tm_to_time64(time);
write_elapsed_second(current_sec - epoch_sec);
return 0;
}
static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{
unsigned long low, mid, high;
struct rtc_time *time = &wkalrm->time;
spin_lock_irq(&rtc_lock);
low = rtc1_read(ECMPLREG);
mid = rtc1_read(ECMPMREG);
high = rtc1_read(ECMPHREG);
wkalrm->enabled = alarm_enabled;
spin_unlock_irq(&rtc_lock);
rtc_time64_to_tm((high << 17) | (mid << 1) | (low >> 15), time);
return 0;
}
static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{
time64_t alarm_sec;
alarm_sec = rtc_tm_to_time64(&wkalrm->time);
spin_lock_irq(&rtc_lock);
if (alarm_enabled)
disable_irq(aie_irq);
rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
if (wkalrm->enabled)
enable_irq(aie_irq);
alarm_enabled = wkalrm->enabled;
spin_unlock_irq(&rtc_lock);
return 0;
}
static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case RTC_EPOCH_READ:
return put_user(epoch, (unsigned long __user *)arg);
#ifdef CONFIG_64BIT
case RTC_EPOCH_READ32:
return put_user(epoch, (unsigned int __user *)arg);
#endif
case RTC_EPOCH_SET:
/* Doesn't support before 1900 */
if (arg < 1900)
return -EINVAL;
epoch = arg;
break;
default:
return -ENOIOCTLCMD;
}
return 0;
}
static int vr41xx_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
spin_lock_irq(&rtc_lock);
if (enabled) {
if (!alarm_enabled) {
enable_irq(aie_irq);
alarm_enabled = 1;
}
} else {
if (alarm_enabled) {
disable_irq(aie_irq);
alarm_enabled = 0;
}
}
spin_unlock_irq(&rtc_lock);
return 0;
}
static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id)
{
struct platform_device *pdev = (struct platform_device *)dev_id;
struct rtc_device *rtc = platform_get_drvdata(pdev);
rtc2_write(RTCINTREG, ELAPSEDTIME_INT);
rtc_update_irq(rtc, 1, RTC_AF);
return IRQ_HANDLED;
}
static irqreturn_t rtclong1_interrupt(int irq, void *dev_id)
{
struct platform_device *pdev = (struct platform_device *)dev_id;
struct rtc_device *rtc = platform_get_drvdata(pdev);
unsigned long count = periodic_count;
rtc2_write(RTCINTREG, RTCLONG1_INT);
rtc1_write(RTCL1LREG, count);
rtc1_write(RTCL1HREG, count >> 16);
rtc_update_irq(rtc, 1, RTC_PF);
return IRQ_HANDLED;
}
static const struct rtc_class_ops vr41xx_rtc_ops = {
.ioctl = vr41xx_rtc_ioctl,
.read_time = vr41xx_rtc_read_time,
.set_time = vr41xx_rtc_set_time,
.read_alarm = vr41xx_rtc_read_alarm,
.set_alarm = vr41xx_rtc_set_alarm,
.alarm_irq_enable = vr41xx_rtc_alarm_irq_enable,
};
static int rtc_probe(struct platform_device *pdev)
{
struct resource *res;
struct rtc_device *rtc;
int retval;
if (pdev->num_resources != 4)
return -EBUSY;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -EBUSY;
rtc1_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!rtc1_base)
return -EBUSY;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!res) {
retval = -EBUSY;
goto err_rtc1_iounmap;
}
rtc2_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!rtc2_base) {
retval = -EBUSY;
goto err_rtc1_iounmap;
}
rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc)) {
retval = PTR_ERR(rtc);
goto err_iounmap_all;
}
rtc->ops = &vr41xx_rtc_ops;
/* 48-bit counter at 32.768 kHz */
rtc->range_max = (1ULL << 33) - 1;
rtc->max_user_freq = MAX_PERIODIC_RATE;
spin_lock_irq(&rtc_lock);
rtc1_write(ECMPLREG, 0);
rtc1_write(ECMPMREG, 0);
rtc1_write(ECMPHREG, 0);
rtc1_write(RTCL1LREG, 0);
rtc1_write(RTCL1HREG, 0);
spin_unlock_irq(&rtc_lock);
aie_irq = platform_get_irq(pdev, 0);
if (aie_irq <= 0) {
retval = -EBUSY;
goto err_iounmap_all;
}
retval = devm_request_irq(&pdev->dev, aie_irq, elapsedtime_interrupt, 0,
"elapsed_time", pdev);
if (retval < 0)
goto err_iounmap_all;
pie_irq = platform_get_irq(pdev, 1);
if (pie_irq <= 0) {
retval = -EBUSY;
goto err_iounmap_all;
}
retval = devm_request_irq(&pdev->dev, pie_irq, rtclong1_interrupt, 0,
"rtclong1", pdev);
if (retval < 0)
goto err_iounmap_all;
platform_set_drvdata(pdev, rtc);
disable_irq(aie_irq);
disable_irq(pie_irq);
dev_info(&pdev->dev, "Real Time Clock of NEC VR4100 series\n");
retval = devm_rtc_register_device(rtc);
if (retval)
goto err_iounmap_all;
return 0;
err_iounmap_all:
rtc2_base = NULL;
err_rtc1_iounmap:
rtc1_base = NULL;
return retval;
}
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:RTC");
static struct platform_driver rtc_platform_driver = {
.probe = rtc_probe,
.driver = {
.name = rtc_name,
},
};
module_platform_driver(rtc_platform_driver);
...@@ -614,8 +614,7 @@ static void x1205_sysfs_unregister(struct device *dev) ...@@ -614,8 +614,7 @@ static void x1205_sysfs_unregister(struct device *dev)
} }
static int x1205_probe(struct i2c_client *client, static int x1205_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
int err = 0; int err = 0;
unsigned char sr; unsigned char sr;
...@@ -681,7 +680,7 @@ static struct i2c_driver x1205_driver = { ...@@ -681,7 +680,7 @@ static struct i2c_driver x1205_driver = {
.name = "rtc-x1205", .name = "rtc-x1205",
.of_match_table = x1205_dt_ids, .of_match_table = x1205_dt_ids,
}, },
.probe = x1205_probe, .probe_new = x1205_probe,
.remove = x1205_remove, .remove = x1205_remove,
.id_table = x1205_id, .id_table = x1205_id,
}; };
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* *
*/ */
#include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -36,17 +37,23 @@ ...@@ -36,17 +37,23 @@
#define RTC_OSC_EN BIT(24) #define RTC_OSC_EN BIT(24)
#define RTC_BATT_EN BIT(31) #define RTC_BATT_EN BIT(31)
#define RTC_CALIB_DEF 0x198233 #define RTC_CALIB_DEF 0x7FFF
#define RTC_CALIB_MASK 0x1FFFFF #define RTC_CALIB_MASK 0x1FFFFF
#define RTC_ALRM_MASK BIT(1) #define RTC_ALRM_MASK BIT(1)
#define RTC_MSEC 1000 #define RTC_MSEC 1000
#define RTC_FR_MASK 0xF0000
#define RTC_FR_MAX_TICKS 16
#define RTC_PPB 1000000000LL
#define RTC_MIN_OFFSET -32768000
#define RTC_MAX_OFFSET 32767000
struct xlnx_rtc_dev { struct xlnx_rtc_dev {
struct rtc_device *rtc; struct rtc_device *rtc;
void __iomem *reg_base; void __iomem *reg_base;
int alarm_irq; int alarm_irq;
int sec_irq; int sec_irq;
unsigned int calibval; struct clk *rtc_clk;
unsigned int freq;
}; };
static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm) static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm)
...@@ -61,13 +68,6 @@ static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm) ...@@ -61,13 +68,6 @@ static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm)
*/ */
new_time = rtc_tm_to_time64(tm) + 1; new_time = rtc_tm_to_time64(tm) + 1;
/*
* Writing into calibration register will clear the Tick Counter and
* force the next second to be signaled exactly in 1 second period
*/
xrtcdev->calibval &= RTC_CALIB_MASK;
writel(xrtcdev->calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
writel(new_time, xrtcdev->reg_base + RTC_SET_TM_WR); writel(new_time, xrtcdev->reg_base + RTC_SET_TM_WR);
/* /*
...@@ -173,15 +173,76 @@ static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev) ...@@ -173,15 +173,76 @@ static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev)
rtc_ctrl = readl(xrtcdev->reg_base + RTC_CTRL); rtc_ctrl = readl(xrtcdev->reg_base + RTC_CTRL);
rtc_ctrl |= RTC_BATT_EN; rtc_ctrl |= RTC_BATT_EN;
writel(rtc_ctrl, xrtcdev->reg_base + RTC_CTRL); writel(rtc_ctrl, xrtcdev->reg_base + RTC_CTRL);
}
/* static int xlnx_rtc_read_offset(struct device *dev, long *offset)
* Based on crystal freq of 33.330 KHz {
* set the seconds counter and enable, set fractions counter struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
* to default value suggested as per design spec unsigned long long rtc_ppb = RTC_PPB;
* to correct RTC delay in frequency over period of time. unsigned int tick_mult = do_div(rtc_ppb, xrtcdev->freq);
unsigned int calibval;
long offset_val;
calibval = readl(xrtcdev->reg_base + RTC_CALIB_RD);
/* Offset with seconds ticks */
offset_val = calibval & RTC_TICK_MASK;
offset_val = offset_val - RTC_CALIB_DEF;
offset_val = offset_val * tick_mult;
/* Offset with fractional ticks */
if (calibval & RTC_FR_EN)
offset_val += ((calibval & RTC_FR_MASK) >> RTC_FR_DATSHIFT)
* (tick_mult / RTC_FR_MAX_TICKS);
*offset = offset_val;
return 0;
}
static int xlnx_rtc_set_offset(struct device *dev, long offset)
{
struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
unsigned long long rtc_ppb = RTC_PPB;
unsigned int tick_mult = do_div(rtc_ppb, xrtcdev->freq);
unsigned char fract_tick = 0;
unsigned int calibval;
short int max_tick;
int fract_offset;
if (offset < RTC_MIN_OFFSET || offset > RTC_MAX_OFFSET)
return -ERANGE;
/* Number ticks for given offset */
max_tick = div_s64_rem(offset, tick_mult, &fract_offset);
/* Number fractional ticks for given offset */
if (fract_offset) {
if (fract_offset < 0) {
fract_offset = fract_offset + tick_mult;
max_tick--;
}
if (fract_offset > (tick_mult / RTC_FR_MAX_TICKS)) {
for (fract_tick = 1; fract_tick < 16; fract_tick++) {
if (fract_offset <=
(fract_tick *
(tick_mult / RTC_FR_MAX_TICKS)))
break;
}
}
}
/* Zynqmp RTC uses second and fractional tick
* counters for compensation
*/ */
xrtcdev->calibval &= RTC_CALIB_MASK; calibval = max_tick + RTC_CALIB_DEF;
writel(xrtcdev->calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
if (fract_tick)
calibval |= RTC_FR_EN;
calibval |= (fract_tick << RTC_FR_DATSHIFT);
writel(calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
return 0;
} }
static const struct rtc_class_ops xlnx_rtc_ops = { static const struct rtc_class_ops xlnx_rtc_ops = {
...@@ -190,6 +251,8 @@ static const struct rtc_class_ops xlnx_rtc_ops = { ...@@ -190,6 +251,8 @@ static const struct rtc_class_ops xlnx_rtc_ops = {
.read_alarm = xlnx_rtc_read_alarm, .read_alarm = xlnx_rtc_read_alarm,
.set_alarm = xlnx_rtc_set_alarm, .set_alarm = xlnx_rtc_set_alarm,
.alarm_irq_enable = xlnx_rtc_alarm_irq_enable, .alarm_irq_enable = xlnx_rtc_alarm_irq_enable,
.read_offset = xlnx_rtc_read_offset,
.set_offset = xlnx_rtc_set_offset,
}; };
static irqreturn_t xlnx_rtc_interrupt(int irq, void *id) static irqreturn_t xlnx_rtc_interrupt(int irq, void *id)
...@@ -255,10 +318,22 @@ static int xlnx_rtc_probe(struct platform_device *pdev) ...@@ -255,10 +318,22 @@ static int xlnx_rtc_probe(struct platform_device *pdev)
return ret; return ret;
} }
ret = of_property_read_u32(pdev->dev.of_node, "calibration", /* Getting the rtc_clk info */
&xrtcdev->calibval); xrtcdev->rtc_clk = devm_clk_get_optional(&pdev->dev, "rtc_clk");
if (ret) if (IS_ERR(xrtcdev->rtc_clk)) {
xrtcdev->calibval = RTC_CALIB_DEF; if (PTR_ERR(xrtcdev->rtc_clk) != -EPROBE_DEFER)
dev_warn(&pdev->dev, "Device clock not found.\n");
}
xrtcdev->freq = clk_get_rate(xrtcdev->rtc_clk);
if (!xrtcdev->freq) {
ret = of_property_read_u32(pdev->dev.of_node, "calibration",
&xrtcdev->freq);
if (ret)
xrtcdev->freq = RTC_CALIB_DEF;
}
ret = readl(xrtcdev->reg_base + RTC_CALIB_RD);
if (!ret)
writel(xrtcdev->freq, (xrtcdev->reg_base + RTC_CALIB_WR));
xlnx_init_rtc(xrtcdev); xlnx_init_rtc(xrtcdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment