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:
- 11000
trickle-voltage-millivolt:
$ref: /schemas/types.yaml#/definitions/uint32
enum:
- 1750
- 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#
title: Qualcomm PM8xxx PMIC RTC device
maintainers:
- Satya Priya <skakit@codeaurora.org>
- Satya Priya <quic_c_skakit@quicinc.com>
properties:
compatible:
......
......@@ -14,6 +14,8 @@ For MediaTek PMIC wrapper bus bindings, see:
Required properties:
- compatible: Should be one of follows
"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
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:
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
items:
- const: rtc
interrupts:
minItems: 2
maxItems: 2
interrupt-names:
items:
......@@ -39,6 +46,7 @@ properties:
minimum: 0x1
maximum: 0x1FFFFF
default: 0x198233
deprecated: true
required:
- compatible
......@@ -61,5 +69,7 @@ examples:
interrupts = <0 26 4>, <0 27 4>;
interrupt-names = "alarm", "sec";
calibration = <0x198233>;
clock-names = "rtc";
clocks = <&rtc_clk>;
};
};
......@@ -2486,11 +2486,13 @@ S: Supported
F: Documentation/devicetree/bindings/*/*/*npcm*
F: Documentation/devicetree/bindings/*/*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/mach-npcm/
F: arch/arm64/boot/dts/nuvoton/
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,npcm845-clk.h
......@@ -17529,6 +17531,7 @@ F: drivers/char/hw_random/mpfs-rng.c
F: drivers/clk/microchip/clk-mpfs.c
F: drivers/mailbox/mailbox-mpfs.c
F: drivers/pci/controller/pcie-microchip-host.c
F: drivers/rtc/rtc-mpfs.c
F: drivers/soc/microchip/
F: drivers/spi/spi-microchip-core.c
F: drivers/usb/musb/mpfs.c
......
......@@ -383,6 +383,16 @@ config RTC_DRV_MAX77686
This driver can also be built as a module. If so, the module
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
tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC"
depends on MFD_RK808
......@@ -1478,16 +1488,6 @@ config RTC_DRV_SUNPLUS
This driver can also be built as a module. If so, the module
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
tristate "ARM AMBA PL030 RTC"
depends on ARM_AMBA
......@@ -1929,6 +1929,17 @@ config RTC_DRV_ASPEED
This driver can also be built as a module, if so, the module
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"
config RTC_DRV_HID_SENSOR_TIME
......@@ -1973,4 +1984,14 @@ config RTC_DRV_MSC313
This driver can also be built as a module, if so, the module
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
......@@ -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_V2) += rtc-mxc_v2.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_OMAP) += rtc-omap.o
obj-$(CONFIG_RTC_DRV_OPAL) += rtc-opal.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_PL031) += rtc-pl031.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_PXA) += rtc-pxa.o
obj-$(CONFIG_RTC_DRV_R7301) += rtc-r7301.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_TEGRA) += rtc-tegra.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_TPS65910) += rtc-tps65910.o
obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.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_WILCO_EC) += rtc-wilco-ec.o
obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
......
......@@ -36,7 +36,7 @@ static void rtc_device_release(struct device *dev)
cancel_work_sync(&rtc->irqwork);
ida_simple_remove(&rtc_ida, rtc->id);
ida_free(&rtc_ida, rtc->id);
mutex_destroy(&rtc->ops_lock);
kfree(rtc);
}
......@@ -262,7 +262,7 @@ static int rtc_device_get_id(struct device *dev)
}
if (id < 0)
id = ida_simple_get(&rtc_ida, 0, 0, GFP_KERNEL);
id = ida_alloc(&rtc_ida, GFP_KERNEL);
return id;
}
......@@ -368,7 +368,7 @@ struct rtc_device *devm_rtc_allocate_device(struct device *dev)
rtc = rtc_allocate_device();
if (!rtc) {
ida_simple_remove(&rtc_ida, id);
ida_free(&rtc_ida, id);
return ERR_PTR(-ENOMEM);
}
......
......@@ -96,7 +96,7 @@ static int clear_uie(struct rtc_device *rtc)
}
if (rtc->uie_task_active) {
spin_unlock_irq(&rtc->irq_lock);
flush_scheduled_work();
flush_work(&rtc->uie_task);
spin_lock_irq(&rtc->irq_lock);
}
rtc->uie_irq_active = 0;
......@@ -566,9 +566,3 @@ void __init rtc_dev_init(void)
if (err < 0)
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 = {
.val_bits = 8,
};
static int abb5zes3_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int abb5zes3_probe(struct i2c_client *client)
{
struct abb5zes3_rtc_data *data = NULL;
struct device *dev = &client->dev;
......@@ -945,7 +944,7 @@ static struct i2c_driver abb5zes3_driver = {
.pm = &abb5zes3_rtc_pm_ops,
.of_match_table = of_match_ptr(abb5zes3_dt_match),
},
.probe = abb5zes3_probe,
.probe_new = abb5zes3_probe,
.id_table = abb5zes3_id,
};
module_i2c_driver(abb5zes3_driver);
......
......@@ -495,8 +495,7 @@ static void abeoz9_hwmon_register(struct device *dev,
#endif
static int abeoz9_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int abeoz9_probe(struct i2c_client *client)
{
struct abeoz9_rtc_data *data = NULL;
struct device *dev = &client->dev;
......@@ -580,7 +579,7 @@ static struct i2c_driver abeoz9_driver = {
.name = "rtc-ab-eoz9",
.of_match_table = of_match_ptr(abeoz9_dt_match),
},
.probe = abeoz9_probe,
.probe_new = abeoz9_probe,
.id_table = abeoz9_id,
};
......
......@@ -249,8 +249,7 @@ static void bq32k_sysfs_unregister(struct device *dev)
device_remove_file(dev, &dev_attr_trickle_charge_bypass);
}
static int bq32k_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int bq32k_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct rtc_device *rtc;
......@@ -322,7 +321,7 @@ static struct i2c_driver bq32k_driver = {
.name = "bq32k",
.of_match_table = of_match_ptr(bq32k_of_match),
},
.probe = bq32k_probe,
.probe_new = bq32k_probe,
.remove = bq32k_remove,
.id_table = bq32k_id,
};
......
......@@ -1260,9 +1260,6 @@ static void use_acpi_alarm_quirks(void)
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
return;
if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0))
return;
if (!is_hpet_enabled())
return;
......
......@@ -2,7 +2,6 @@
#ifdef CONFIG_RTC_INTF_DEV
extern void __init rtc_dev_init(void);
extern void __exit rtc_dev_exit(void);
extern void rtc_dev_prepare(struct rtc_device *rtc);
#else
......@@ -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)
{
}
......
......@@ -375,10 +375,8 @@ static int cros_ec_rtc_remove(struct platform_device *pdev)
ret = blocking_notifier_chain_unregister(
&cros_ec_rtc->cros_ec->event_notifier,
&cros_ec_rtc->notifier);
if (ret) {
if (ret)
dev_err(dev, "failed to unregister notifier\n");
return ret;
}
return 0;
}
......
......@@ -467,8 +467,7 @@ static const struct watchdog_ops ds1374_wdt_ops = {
*
*****************************************************************************
*/
static int ds1374_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int ds1374_probe(struct i2c_client *client)
{
struct ds1374 *ds1374;
int ret;
......@@ -575,7 +574,7 @@ static struct i2c_driver ds1374_driver = {
.of_match_table = of_match_ptr(ds1374_of_match),
.pm = &ds1374_pm,
},
.probe = ds1374_probe,
.probe_new = ds1374_probe,
.remove = ds1374_remove,
.id_table = ds1374_id,
};
......
......@@ -106,8 +106,7 @@ static const struct rtc_class_ops ds1672_rtc_ops = {
.set_time = ds1672_set_time,
};
static int ds1672_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int ds1672_probe(struct i2c_client *client)
{
int err = 0;
struct rtc_device *rtc;
......@@ -150,7 +149,7 @@ static struct i2c_driver ds1672_driver = {
.name = "rtc-ds1672",
.of_match_table = of_match_ptr(ds1672_of_match),
},
.probe = &ds1672_probe,
.probe_new = ds1672_probe,
.id_table = ds1672_id,
};
......
......@@ -566,8 +566,7 @@ static const struct dev_pm_ops ds3232_pm_ops = {
#if IS_ENABLED(CONFIG_I2C)
static int ds3232_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int ds3232_i2c_probe(struct i2c_client *client)
{
struct regmap *regmap;
static const struct regmap_config config = {
......@@ -604,7 +603,7 @@ static struct i2c_driver ds3232_driver = {
.of_match_table = of_match_ptr(ds3232_of_match),
.pm = &ds3232_pm_ops,
},
.probe = ds3232_i2c_probe,
.probe_new = ds3232_i2c_probe,
.id_table = ds3232_id,
};
......
......@@ -111,8 +111,7 @@ static const struct rtc_class_ops em3027_rtc_ops = {
.set_time = em3027_set_time,
};
static int em3027_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int em3027_probe(struct i2c_client *client)
{
struct rtc_device *rtc;
......@@ -148,7 +147,7 @@ static struct i2c_driver em3027_driver = {
.name = "rtc-em3027",
.of_match_table = of_match_ptr(em3027_of_match),
},
.probe = &em3027_probe,
.probe_new = em3027_probe,
.id_table = em3027_id,
};
......
......@@ -340,8 +340,7 @@ static const struct rtc_class_ops fm3130_rtc_ops = {
static struct i2c_driver fm3130_driver;
static int fm3130_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int fm3130_probe(struct i2c_client *client)
{
struct fm3130 *fm3130;
int err = -ENODEV;
......@@ -518,7 +517,7 @@ static struct i2c_driver fm3130_driver = {
.driver = {
.name = "rtc-fm3130",
},
.probe = fm3130_probe,
.probe_new = fm3130_probe,
.id_table = fm3130_id,
};
......
......@@ -495,8 +495,7 @@ static int hym8563_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(hym8563_pm_ops, hym8563_suspend, hym8563_resume);
static int hym8563_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int hym8563_probe(struct i2c_client *client)
{
struct hym8563 *hym8563;
int ret;
......@@ -572,7 +571,7 @@ static struct i2c_driver hym8563_driver = {
.pm = &hym8563_pm_ops,
.of_match_table = hym8563_dt_idtable,
},
.probe = hym8563_probe,
.probe_new = hym8563_probe,
.id_table = hym8563_id,
};
......
......@@ -232,8 +232,7 @@ static const struct rtc_class_ops isl12022_rtc_ops = {
.set_time = isl12022_rtc_set_time,
};
static int isl12022_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int isl12022_probe(struct i2c_client *client)
{
struct isl12022 *isl12022;
......@@ -275,7 +274,7 @@ static struct i2c_driver isl12022_driver = {
.of_match_table = of_match_ptr(isl12022_dt_match),
#endif
},
.probe = isl12022_probe,
.probe_new = isl12022_probe,
.id_table = isl12022_id,
};
......
......@@ -880,10 +880,14 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (rc)
return rc;
if (client->irq > 0)
if (client->irq > 0) {
rc = isl1208_setup_irq(client, client->irq);
if (rc)
return rc;
if (rc)
return rc;
} else {
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, isl1208->rtc->features);
}
if (evdet_irq > 0 && evdet_irq != client->irq)
rc = isl1208_setup_irq(client, evdet_irq);
......
......@@ -197,8 +197,7 @@ static const struct rtc_class_ops max6900_rtc_ops = {
.set_time = max6900_rtc_set_time,
};
static int
max6900_probe(struct i2c_client *client, const struct i2c_device_id *id)
static int max6900_probe(struct i2c_client *client)
{
struct rtc_device *rtc;
......@@ -225,7 +224,7 @@ static struct i2c_driver max6900_driver = {
.driver = {
.name = "rtc-max6900",
},
.probe = max6900_probe,
.probe_new = max6900_probe,
.id_table = max6900_id,
};
......
......@@ -21,13 +21,13 @@ bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param),
unsigned long flags;
unsigned char seconds;
for (i = 0; i < 10; i++) {
for (i = 0; i < 100; i++) {
spin_lock_irqsave(&rtc_lock, flags);
/*
* Check whether there is an update in progress during which the
* 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
* 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),
if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) {
spin_unlock_irqrestore(&rtc_lock, flags);
mdelay(1);
udelay(100);
continue;
}
......@@ -56,7 +56,7 @@ bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param),
*/
if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) {
spin_unlock_irqrestore(&rtc_lock, flags);
mdelay(1);
udelay(100);
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");
This diff is collapsed.
......@@ -390,8 +390,7 @@ static const struct regmap_config regmap_config = {
.max_register = 0x13,
};
static int pcf8523_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int pcf8523_probe(struct i2c_client *client)
{
struct pcf8523 *pcf8523;
struct rtc_device *rtc;
......@@ -485,7 +484,7 @@ static struct i2c_driver pcf8523_driver = {
.name = "rtc-pcf8523",
.of_match_table = pcf8523_of_match,
},
.probe = pcf8523_probe,
.probe_new = pcf8523_probe,
.id_table = pcf8523_id,
};
module_i2c_driver(pcf8523_driver);
......
......@@ -350,8 +350,7 @@ static const struct pcf85x63_config pcf_85363_config = {
.num_nvram = 2
};
static int pcf85363_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int pcf85363_probe(struct i2c_client *client)
{
struct pcf85363 *pcf85363;
const struct pcf85x63_config *config = &pcf_85363_config;
......@@ -436,7 +435,7 @@ static struct i2c_driver pcf85363_driver = {
.name = "pcf85363",
.of_match_table = of_match_ptr(dev_ids),
},
.probe = pcf85363_probe,
.probe_new = pcf85363_probe,
};
module_i2c_driver(pcf85363_driver);
......
......@@ -509,8 +509,7 @@ static const struct rtc_class_ops pcf8563_rtc_ops = {
.alarm_irq_enable = pcf8563_irq_enable,
};
static int pcf8563_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int pcf8563_probe(struct i2c_client *client)
{
struct pcf8563 *pcf8563;
int err;
......@@ -606,7 +605,7 @@ static struct i2c_driver pcf8563_driver = {
.name = "rtc-pcf8563",
.of_match_table = of_match_ptr(pcf8563_of_match),
},
.probe = pcf8563_probe,
.probe_new = pcf8563_probe,
.id_table = pcf8563_id,
};
......
......@@ -275,8 +275,7 @@ static const struct rtc_class_ops pcf8583_rtc_ops = {
.set_time = pcf8583_rtc_set_time,
};
static int pcf8583_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int pcf8583_probe(struct i2c_client *client)
{
struct pcf8583 *pcf8583;
......@@ -307,7 +306,7 @@ static struct i2c_driver pcf8583_driver = {
.driver = {
.name = "pcf8583",
},
.probe = pcf8583_probe,
.probe_new = pcf8583_probe,
.id_table = pcf8583_id,
};
......
......@@ -784,8 +784,7 @@ static const struct regmap_config config = {
#if IS_ENABLED(CONFIG_I2C)
static int rv3029_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int rv3029_i2c_probe(struct i2c_client *client)
{
struct regmap *regmap;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK |
......@@ -819,7 +818,7 @@ static struct i2c_driver rv3029_driver = {
.name = "rv3029",
.of_match_table = of_match_ptr(rv3029_of_match),
},
.probe = rv3029_i2c_probe,
.probe_new = rv3029_i2c_probe,
.id_table = rv3029_id,
};
......
......@@ -9,6 +9,7 @@
#include <linux/bcd.h>
#include <linux/bitops.h>
#include <linux/bitfield.h>
#include <linux/log2.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
......@@ -33,6 +34,7 @@
#define RV8803_EXT 0x0D
#define RV8803_FLAG 0x0E
#define RV8803_CTRL 0x0F
#define RV8803_OSC_OFFSET 0x2C
#define RV8803_EXT_WADA BIT(6)
......@@ -49,12 +51,15 @@
#define RV8803_CTRL_TIE BIT(4)
#define RV8803_CTRL_UIE BIT(5)
#define RX8803_CTRL_CSEL GENMASK(7, 6)
#define RX8900_BACKUP_CTRL 0x18
#define RX8900_FLAG_SWOFF BIT(2)
#define RX8900_FLAG_VDETOFF BIT(3)
enum rv8803_type {
rv_8803,
rx_8803,
rx_8804,
rx_8900
};
......@@ -64,6 +69,7 @@ struct rv8803_data {
struct rtc_device *rtc;
struct mutex flags_lock;
u8 ctrl;
u8 backup;
enum rv8803_type type;
};
......@@ -136,6 +142,44 @@ static int rv8803_write_regs(const struct i2c_client *client,
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)
{
struct i2c_client *client = dev_id;
......@@ -269,6 +313,14 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
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,
flags & ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F));
......@@ -498,18 +550,32 @@ static int rx8900_trickle_charger_init(struct rv8803_data *rv8803)
if (err < 0)
return err;
flags = ~(RX8900_FLAG_VDETOFF | RX8900_FLAG_SWOFF) & (u8)err;
if (of_property_read_bool(node, "epson,vdet-disable"))
flags |= RX8900_FLAG_VDETOFF;
if (of_property_read_bool(node, "trickle-diode-disable"))
flags |= RX8900_FLAG_SWOFF;
flags = (u8)err;
flags &= ~(RX8900_FLAG_VDETOFF | RX8900_FLAG_SWOFF);
flags |= rv8803->backup;
return i2c_smbus_write_byte_data(rv8803->client, RX8900_BACKUP_CTRL,
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,
const struct i2c_device_id *id)
{
......@@ -576,15 +642,15 @@ static int rv8803_probe(struct i2c_client *client,
if (!client->irq)
clear_bit(RTC_FEATURE_ALARM, rv8803->rtc->features);
err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA);
if (err)
return err;
if (of_property_read_bool(client->dev.of_node, "epson,vdet-disable"))
rv8803->backup |= RX8900_FLAG_VDETOFF;
err = rx8900_trickle_charger_init(rv8803);
if (err) {
dev_err(&client->dev, "failed to init charger\n");
if (of_property_read_bool(client->dev.of_node, "trickle-diode-disable"))
rv8803->backup |= RX8900_FLAG_SWOFF;
err = rv8803_regs_configure(rv8803);
if (err)
return err;
}
rv8803->rtc->ops = &rv8803_rtc_ops;
rv8803->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
......@@ -603,7 +669,7 @@ static int rv8803_probe(struct i2c_client *client,
static const struct i2c_device_id rv8803_id[] = {
{ "rv8803", rv_8803 },
{ "rv8804", rx_8804 },
{ "rx8803", rv_8803 },
{ "rx8803", rx_8803 },
{ "rx8900", rx_8900 },
{ }
};
......@@ -616,7 +682,7 @@ static const __maybe_unused struct of_device_id rv8803_of_match[] = {
},
{
.compatible = "epson,rx8803",
.data = (void *)rv_8803
.data = (void *)rx_8803
},
{
.compatible = "epson,rx8804",
......
......@@ -419,8 +419,7 @@ static struct regmap_config regmap_i2c_config = {
.read_flag_mask = 0x80,
};
static int rx6110_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int rx6110_i2c_probe(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
struct rx6110_data *rx6110;
......@@ -464,7 +463,7 @@ static struct i2c_driver rx6110_i2c_driver = {
.name = RX6110_DRIVER_NAME,
.acpi_match_table = rx6110_i2c_acpi_match,
},
.probe = rx6110_i2c_probe,
.probe_new = rx6110_i2c_probe,
.id_table = rx6110_i2c_id,
};
......
......@@ -55,6 +55,8 @@
#define RX8025_BIT_CTRL2_XST BIT(5)
#define RX8025_BIT_CTRL2_VDET BIT(6)
#define RX8035_BIT_HOUR_1224 BIT(7)
/* Clock precision adjustment */
#define RX8025_ADJ_RESOLUTION 3050 /* in ppb */
#define RX8025_ADJ_DATA_MAX 62
......@@ -78,6 +80,7 @@ struct rx8025_data {
struct rtc_device *rtc;
enum rx_model model;
u8 ctrl1;
int is_24;
};
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)
dt->tm_sec = bcd2bin(date[RX8025_REG_SEC] & 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);
else
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)
*/
date[RX8025_REG_SEC] = bin2bcd(dt->tm_sec);
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);
else
date[RX8025_REG_HOUR] = (dt->tm_hour >= 12 ? 0x20 : 0)
......@@ -279,6 +282,7 @@ static int rx8025_init_client(struct i2c_client *client)
struct rx8025_data *rx8025 = i2c_get_clientdata(client);
u8 ctrl[2], ctrl2;
int need_clear = 0;
int hour_reg;
int err;
err = rx8025_read_regs(client, RX8025_REG_CTRL1, 2, ctrl);
......@@ -303,6 +307,16 @@ static int rx8025_init_client(struct i2c_client *client)
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:
return err;
}
......@@ -329,7 +343,7 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t)
/* Hardware alarms precision is 1 minute! */
t->time.tm_sec = 0;
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);
else
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)
int err;
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);
else
ald[1] = (t->time.tm_hour >= 12 ? 0x20 : 0)
......
......@@ -248,8 +248,7 @@ static const struct rx85x1_config rx8571_config = {
.num_nvram = 2
};
static int rx8581_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int rx8581_probe(struct i2c_client *client)
{
struct rx8581 *rx8581;
const struct rx85x1_config *config = &rx8581_config;
......@@ -326,7 +325,7 @@ static struct i2c_driver rx8581_driver = {
.name = "rtc-rx8581",
.of_match_table = of_match_ptr(rx8581_of_match),
},
.probe = rx8581_probe,
.probe_new = rx8581_probe,
.id_table = rx8581_id,
};
......
......@@ -420,8 +420,7 @@ static const struct rtc_class_ops s35390a_rtc_ops = {
.ioctl = s35390a_rtc_ioctl,
};
static int s35390a_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int s35390a_probe(struct i2c_client *client)
{
int err, err_read;
unsigned int i;
......@@ -502,7 +501,7 @@ static struct i2c_driver s35390a_driver = {
.name = "rtc-s35390a",
.of_match_table = of_match_ptr(s35390a_of_match),
},
.probe = s35390a_probe,
.probe_new = s35390a_probe,
.id_table = s35390a_id,
};
......
......@@ -163,8 +163,7 @@ static const struct regmap_config regmap_config = {
.max_register = 0x11,
};
static int sd3078_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int sd3078_probe(struct i2c_client *client)
{
int ret;
struct sd3078 *sd3078;
......@@ -218,7 +217,7 @@ static struct i2c_driver sd3078_driver = {
.name = "sd3078",
.of_match_table = of_match_ptr(rtc_dt_match),
},
.probe = sd3078_probe,
.probe_new = sd3078_probe,
.id_table = sd3078_id,
};
......
......@@ -388,7 +388,7 @@ static int spear_rtc_probe(struct platform_device *pdev)
config->rtc->ops = &spear_rtc_ops;
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);
if (status)
......
......@@ -875,6 +875,8 @@ static const struct of_device_id sun6i_rtc_dt_ids[] = {
{ .compatible = "allwinner,sun50i-h6-rtc" },
{ .compatible = "allwinner,sun50i-h616-rtc",
.data = (void *)RTC_LINEAR_DAY },
{ .compatible = "allwinner,sun50i-r329-rtc",
.data = (void *)RTC_LINEAR_DAY },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids);
......
This diff is collapsed.
// 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)
}
static int x1205_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int x1205_probe(struct i2c_client *client)
{
int err = 0;
unsigned char sr;
......@@ -681,7 +680,7 @@ static struct i2c_driver x1205_driver = {
.name = "rtc-x1205",
.of_match_table = x1205_dt_ids,
},
.probe = x1205_probe,
.probe_new = x1205_probe,
.remove = x1205_remove,
.id_table = x1205_id,
};
......
......@@ -6,6 +6,7 @@
*
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/io.h>
......@@ -36,17 +37,23 @@
#define RTC_OSC_EN BIT(24)
#define RTC_BATT_EN BIT(31)
#define RTC_CALIB_DEF 0x198233
#define RTC_CALIB_DEF 0x7FFF
#define RTC_CALIB_MASK 0x1FFFFF
#define RTC_ALRM_MASK BIT(1)
#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 rtc_device *rtc;
void __iomem *reg_base;
int alarm_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)
......@@ -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;
/*
* 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);
/*
......@@ -173,15 +173,76 @@ static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev)
rtc_ctrl = readl(xrtcdev->reg_base + RTC_CTRL);
rtc_ctrl |= RTC_BATT_EN;
writel(rtc_ctrl, xrtcdev->reg_base + RTC_CTRL);
}
/*
* Based on crystal freq of 33.330 KHz
* set the seconds counter and enable, set fractions counter
* to default value suggested as per design spec
* to correct RTC delay in frequency over period of time.
static int xlnx_rtc_read_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 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;
writel(xrtcdev->calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
calibval = max_tick + RTC_CALIB_DEF;
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 = {
......@@ -190,6 +251,8 @@ static const struct rtc_class_ops xlnx_rtc_ops = {
.read_alarm = xlnx_rtc_read_alarm,
.set_alarm = xlnx_rtc_set_alarm,
.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)
......@@ -255,10 +318,22 @@ static int xlnx_rtc_probe(struct platform_device *pdev)
return ret;
}
ret = of_property_read_u32(pdev->dev.of_node, "calibration",
&xrtcdev->calibval);
if (ret)
xrtcdev->calibval = RTC_CALIB_DEF;
/* Getting the rtc_clk info */
xrtcdev->rtc_clk = devm_clk_get_optional(&pdev->dev, "rtc_clk");
if (IS_ERR(xrtcdev->rtc_clk)) {
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);
......
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