summaryrefslogtreecommitdiff
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig3
-rw-r--r--drivers/rtc/class.c4
-rw-r--r--drivers/rtc/dev.c11
-rw-r--r--drivers/rtc/interface.c2
-rw-r--r--drivers/rtc/rtc-abx80x.c5
-rw-r--r--drivers/rtc/rtc-ac100.c75
-rw-r--r--drivers/rtc/rtc-armada38x.c9
-rw-r--r--drivers/rtc/rtc-cmos.c156
-rw-r--r--drivers/rtc/rtc-ds1390.c2
-rw-r--r--drivers/rtc/rtc-loongson.c71
-rw-r--r--drivers/rtc/rtc-m41t80.c8
-rw-r--r--drivers/rtc/rtc-max31335.c6
-rw-r--r--drivers/rtc/rtc-max77686.c14
-rw-r--r--drivers/rtc/rtc-ntxec.c2
-rw-r--r--drivers/rtc/rtc-optee.c5
-rw-r--r--drivers/rtc/rtc-pcf2127.c23
-rw-r--r--drivers/rtc/rtc-pcf8563.c2
-rw-r--r--drivers/rtc/rtc-pic32.c3
-rw-r--r--drivers/rtc/rtc-rs5c372.c7
-rw-r--r--drivers/rtc/rtc-rv8803.c8
-rw-r--r--drivers/rtc/rtc-rx8025.c4
-rw-r--r--drivers/rtc/rtc-s35390a.c32
-rw-r--r--drivers/rtc/rtc-sun6i.c4
-rw-r--r--drivers/rtc/rtc-ti-k3.c10
-rw-r--r--drivers/rtc/rtc-zynqmp.c75
25 files changed, 262 insertions, 279 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 7ac18985e438..364afc73f8ab 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -418,6 +418,7 @@ config RTC_DRV_SPACEMIT_P1
config RTC_DRV_NVIDIA_VRS10
tristate "NVIDIA VRS10 RTC device"
+ depends on ARCH_TEGRA || COMPILE_TEST
help
If you say yes here you will get support for the battery backed RTC device
of NVIDIA VRS (Voltage Regulator Specification). The RTC is connected via
@@ -1985,7 +1986,7 @@ config RTC_DRV_XGENE
config RTC_DRV_PIC32
tristate "Microchip PIC32 RTC"
- depends on MACH_PIC32
+ depends on MACH_PIC32 || COMPILE_TEST
default y
help
If you say yes here you get support for the PIC32 RTC module.
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index b1a2be1f9e3b..01ba04028f1f 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -208,7 +208,7 @@ static struct rtc_device *rtc_allocate_device(void)
{
struct rtc_device *rtc;
- rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
+ rtc = kzalloc_obj(*rtc);
if (!rtc)
return NULL;
@@ -410,7 +410,7 @@ int __devm_rtc_register_device(struct module *owner, struct rtc_device *rtc)
/* Check to see if there is an ALARM already set in hw */
err = __rtc_read_alarm(rtc, &alrm);
- if (!err && !rtc_valid_tm(&alrm.time))
+ if (!err)
rtc_initialize_alarm(rtc, &alrm);
rtc_dev_prepare(rtc);
diff --git a/drivers/rtc/dev.c b/drivers/rtc/dev.c
index baf1a8ca8b2b..8ba7c25d2565 100644
--- a/drivers/rtc/dev.c
+++ b/drivers/rtc/dev.c
@@ -195,7 +195,16 @@ static __poll_t rtc_dev_poll(struct file *file, poll_table *wait)
poll_wait(file, &rtc->irq_queue, wait);
- data = rtc->irq_data;
+ /*
+ * This read can race with the write in rtc_handle_legacy_irq().
+ *
+ * - If this check misses a zero to non-zero transition the next check
+ * will pick it up (rtc_handle_legacy_irq() wakes up rtc->irq_queue).
+ * - Non-zero to non-zero transition misses do not change return value.
+ * - And a non-zero to zero transition is unlikely to be missed, since
+ * it occurs on rtc_dev_read(), during which polling is not expected.
+ */
+ data = data_race(rtc->irq_data);
return (data != 0) ? (EPOLLIN | EPOLLRDNORM) : 0;
}
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index b8b298efd9a9..1906f4884a83 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -457,7 +457,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
* are in, we can return -ETIME to signal that the timer has already
* expired, which is true in both cases.
*/
- if ((scheduled - now) <= 1) {
+ if (!err && (scheduled - now) <= 1) {
err = __rtc_read_time(rtc, &tm);
if (err)
return err;
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
index 3fee27914ba8..00d7de64ed3e 100644
--- a/drivers/rtc/rtc-abx80x.c
+++ b/drivers/rtc/rtc-abx80x.c
@@ -772,8 +772,7 @@ static int abx80x_probe(struct i2c_client *client)
struct abx80x_priv *priv;
int i, data, err, trickle_cfg = -EINVAL;
char buf[7];
- const struct i2c_device_id *id = i2c_match_id(abx80x_id, client);
- unsigned int part = id->driver_data;
+ unsigned int part = (uintptr_t)i2c_get_match_data(client);
unsigned int partnumber;
unsigned int majrev, minrev;
unsigned int lot;
@@ -933,6 +932,8 @@ static int abx80x_probe(struct i2c_client *client)
client->irq = 0;
}
}
+ if (client->irq <= 0)
+ clear_bit(RTC_FEATURE_ALARM, priv->rtc->features);
err = rtc_add_group(priv->rtc, &rtc_calib_attr_group);
if (err) {
diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c
index 33626311fa78..bba7115ff3ad 100644
--- a/drivers/rtc/rtc-ac100.c
+++ b/drivers/rtc/rtc-ac100.c
@@ -140,42 +140,16 @@ static unsigned long ac100_clkout_recalc_rate(struct clk_hw *hw,
AC100_CLKOUT_DIV_WIDTH);
}
-static long ac100_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long prate)
-{
- unsigned long best_rate = 0, tmp_rate, tmp_prate;
- int i;
-
- if (prate == AC100_RTC_32K_RATE)
- return divider_round_rate(hw, rate, &prate, NULL,
- AC100_CLKOUT_DIV_WIDTH,
- CLK_DIVIDER_POWER_OF_TWO);
-
- for (i = 0; ac100_clkout_prediv[i].div; i++) {
- tmp_prate = DIV_ROUND_UP(prate, ac100_clkout_prediv[i].val);
- tmp_rate = divider_round_rate(hw, rate, &tmp_prate, NULL,
- AC100_CLKOUT_DIV_WIDTH,
- CLK_DIVIDER_POWER_OF_TWO);
-
- if (tmp_rate > rate)
- continue;
- if (rate - tmp_rate < best_rate - tmp_rate)
- best_rate = tmp_rate;
- }
-
- return best_rate;
-}
-
static int ac100_clkout_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
- struct clk_hw *best_parent;
+ int i, ret, num_parents = clk_hw_get_num_parents(hw);
+ struct clk_hw *best_parent = NULL;
unsigned long best = 0;
- int i, num_parents = clk_hw_get_num_parents(hw);
for (i = 0; i < num_parents; i++) {
struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i);
- unsigned long tmp, prate;
+ unsigned long prate;
/*
* The clock has two parents, one is a fixed clock which is
@@ -199,13 +173,40 @@ static int ac100_clkout_determine_rate(struct clk_hw *hw,
prate = clk_hw_get_rate(parent);
- tmp = ac100_clkout_round_rate(hw, req->rate, prate);
-
- if (tmp > req->rate)
- continue;
- if (req->rate - tmp < req->rate - best) {
- best = tmp;
- best_parent = parent;
+ if (prate == AC100_RTC_32K_RATE) {
+ struct clk_rate_request div_req = *req;
+
+ div_req.best_parent_rate = prate;
+
+ ret = divider_determine_rate(hw, &div_req, NULL,
+ AC100_CLKOUT_DIV_WIDTH,
+ CLK_DIVIDER_POWER_OF_TWO);
+ if (ret != 0 || div_req.rate > req->rate) {
+ continue;
+ } else if (req->rate - div_req.rate < req->rate - best) {
+ best = div_req.rate;
+ best_parent = parent;
+ }
+ } else {
+ int j;
+
+ for (j = 0; ac100_clkout_prediv[j].div; j++) {
+ struct clk_rate_request div_req = *req;
+ unsigned long tmp_prate;
+
+ tmp_prate = DIV_ROUND_UP(prate, ac100_clkout_prediv[j].div);
+ div_req.best_parent_rate = tmp_prate;
+
+ ret = divider_determine_rate(hw, &div_req, NULL,
+ AC100_CLKOUT_DIV_WIDTH,
+ CLK_DIVIDER_POWER_OF_TWO);
+ if (ret != 0 || div_req.rate > req->rate) {
+ continue;
+ } else if (req->rate - div_req.rate < req->rate - best) {
+ best = div_req.rate;
+ best_parent = parent;
+ }
+ }
}
}
@@ -213,7 +214,7 @@ static int ac100_clkout_determine_rate(struct clk_hw *hw,
return -EINVAL;
req->best_parent_hw = best_parent;
- req->best_parent_rate = best;
+ req->best_parent_rate = clk_hw_get_rate(best_parent);
req->rate = best;
return 0;
diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c
index 713fa0d077cd..245290ae1a8d 100644
--- a/drivers/rtc/rtc-armada38x.c
+++ b/drivers/rtc/rtc-armada38x.c
@@ -72,8 +72,8 @@ struct armada38x_rtc {
spinlock_t lock;
int irq;
bool initialized;
- struct value_to_freq *val_to_freq;
const struct armada38x_rtc_data *data;
+ struct value_to_freq val_to_freq[];
};
#define ALARM1 0
@@ -490,18 +490,13 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev)
{
struct armada38x_rtc *rtc;
- rtc = devm_kzalloc(&pdev->dev, sizeof(struct armada38x_rtc),
+ rtc = devm_kzalloc(&pdev->dev, struct_size(rtc, val_to_freq, SAMPLE_NR),
GFP_KERNEL);
if (!rtc)
return -ENOMEM;
rtc->data = of_device_get_match_data(&pdev->dev);
- rtc->val_to_freq = devm_kcalloc(&pdev->dev, SAMPLE_NR,
- sizeof(struct value_to_freq), GFP_KERNEL);
- if (!rtc->val_to_freq)
- return -ENOMEM;
-
spin_lock_init(&rtc->lock);
rtc->regs = devm_platform_ioremap_resource_byname(pdev, "rtc");
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 0743c6acd6e2..f89ab58f5048 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -27,6 +27,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/acpi.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -215,6 +216,11 @@ static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
/*----------------------------------------------------------------*/
+static bool cmos_no_alarm(struct cmos_rtc *cmos)
+{
+ return !is_valid_irq(cmos->irq) && !cmos_use_acpi_alarm();
+}
+
static int cmos_read_time(struct device *dev, struct rtc_time *t)
{
int ret;
@@ -286,7 +292,7 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
};
/* This not only a rtc_op, but also called directly */
- if (!is_valid_irq(cmos->irq))
+ if (cmos_no_alarm(cmos))
return -ETIMEDOUT;
/* Basic alarms only support hour, minute, and seconds fields.
@@ -519,7 +525,7 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
int ret;
/* This not only a rtc_op, but also called directly */
- if (!is_valid_irq(cmos->irq))
+ if (cmos_no_alarm(cmos))
return -EIO;
ret = cmos_validate_alarm(dev, t);
@@ -816,6 +822,9 @@ static void rtc_wake_off(struct device *dev)
#ifdef CONFIG_X86
static void use_acpi_alarm_quirks(void)
{
+ if (acpi_gbl_FADT.flags & ACPI_FADT_FIXED_RTC)
+ return;
+
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_INTEL:
if (dmi_get_bios_year() < 2015)
@@ -829,8 +838,6 @@ static void use_acpi_alarm_quirks(void)
default:
return;
}
- if (!is_hpet_enabled())
- return;
use_acpi_alarm = true;
}
@@ -1094,7 +1101,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq);
goto cleanup1;
}
- } else {
+ } else if (!cmos_use_acpi_alarm()) {
clear_bit(RTC_FEATURE_ALARM, cmos_rtc.rtc->features);
}
@@ -1119,7 +1126,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
acpi_rtc_event_setup(dev);
dev_info(dev, "%s%s, %d bytes nvram%s\n",
- !is_valid_irq(rtc_irq) ? "no alarms" :
+ cmos_no_alarm(&cmos_rtc) ? "no alarms" :
cmos_rtc.mon_alrm ? "alarms up to one year" :
cmos_rtc.day_alrm ? "alarms up to one month" :
"alarms up to one day",
@@ -1145,7 +1152,7 @@ cleanup0:
static void cmos_do_shutdown(int rtc_irq)
{
spin_lock_irq(&rtc_lock);
- if (is_valid_irq(rtc_irq))
+ if (!cmos_no_alarm(&cmos_rtc))
cmos_irq_disable(&cmos_rtc, RTC_IRQMASK);
spin_unlock_irq(&rtc_lock);
}
@@ -1369,85 +1376,6 @@ static int __maybe_unused cmos_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(cmos_pm_ops, cmos_suspend, cmos_resume);
-/*----------------------------------------------------------------*/
-
-/* On non-x86 systems, a "CMOS" RTC lives most naturally on platform_bus.
- * ACPI systems always list these as PNPACPI devices, and pre-ACPI PCs
- * probably list them in similar PNPBIOS tables; so PNP is more common.
- *
- * We don't use legacy "poke at the hardware" probing. Ancient PCs that
- * predate even PNPBIOS should set up platform_bus devices.
- */
-
-#ifdef CONFIG_PNP
-
-#include <linux/pnp.h>
-
-static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
-{
- int irq;
-
- if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0)) {
- irq = 0;
-#ifdef CONFIG_X86
- /* Some machines contain a PNP entry for the RTC, but
- * don't define the IRQ. It should always be safe to
- * hardcode it on systems with a legacy PIC.
- */
- if (nr_legacy_irqs())
- irq = RTC_IRQ;
-#endif
- } else {
- irq = pnp_irq(pnp, 0);
- }
-
- return cmos_do_probe(&pnp->dev, pnp_get_resource(pnp, IORESOURCE_IO, 0), irq);
-}
-
-static void cmos_pnp_remove(struct pnp_dev *pnp)
-{
- cmos_do_remove(&pnp->dev);
-}
-
-static void cmos_pnp_shutdown(struct pnp_dev *pnp)
-{
- struct device *dev = &pnp->dev;
- struct cmos_rtc *cmos = dev_get_drvdata(dev);
-
- if (system_state == SYSTEM_POWER_OFF) {
- int retval = cmos_poweroff(dev);
-
- if (cmos_aie_poweroff(dev) < 0 && !retval)
- return;
- }
-
- cmos_do_shutdown(cmos->irq);
-}
-
-static const struct pnp_device_id rtc_ids[] = {
- { .id = "PNP0b00", },
- { .id = "PNP0b01", },
- { .id = "PNP0b02", },
- { },
-};
-MODULE_DEVICE_TABLE(pnp, rtc_ids);
-
-static struct pnp_driver cmos_pnp_driver = {
- .name = driver_name,
- .id_table = rtc_ids,
- .probe = cmos_pnp_probe,
- .remove = cmos_pnp_remove,
- .shutdown = cmos_pnp_shutdown,
-
- /* flag ensures resume() gets called, and stops syslog spam */
- .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
- .driver = {
- .pm = &cmos_pm_ops,
- },
-};
-
-#endif /* CONFIG_PNP */
-
#ifdef CONFIG_OF
static const struct of_device_id of_cmos_match[] = {
{
@@ -1476,6 +1404,14 @@ static __init void cmos_of_init(struct platform_device *pdev)
#else
static inline void cmos_of_init(struct platform_device *pdev) {}
#endif
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id acpi_cmos_rtc_ids[] = {
+ ACPI_CMOS_RTC_IDS
+};
+MODULE_DEVICE_TABLE(acpi, acpi_cmos_rtc_ids);
+#endif
+
/*----------------------------------------------------------------*/
/* Platform setup should have set up an RTC device, when PNP is
@@ -1493,9 +1429,18 @@ static int __init cmos_platform_probe(struct platform_device *pdev)
resource = platform_get_resource(pdev, IORESOURCE_IO, 0);
else
resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
+ irq = platform_get_irq_optional(pdev, 0);
+ if (irq < 0) {
irq = -1;
+#ifdef CONFIG_X86
+ /*
+ * On some x86 systems, the IRQ is not defined, but it should
+ * always be safe to hardcode it on systems with a legacy PIC.
+ */
+ if (nr_legacy_irqs())
+ irq = RTC_IRQ;
+#endif
+ }
return cmos_do_probe(&pdev->dev, resource, irq);
}
@@ -1530,48 +1475,31 @@ static struct platform_driver cmos_platform_driver = {
.name = driver_name,
.pm = &cmos_pm_ops,
.of_match_table = of_match_ptr(of_cmos_match),
+ .acpi_match_table = ACPI_PTR(acpi_cmos_rtc_ids),
}
};
-#ifdef CONFIG_PNP
-static bool pnp_driver_registered;
-#endif
static bool platform_driver_registered;
static int __init cmos_init(void)
{
- int retval = 0;
+ int retval;
-#ifdef CONFIG_PNP
- retval = pnp_register_driver(&cmos_pnp_driver);
- if (retval == 0)
- pnp_driver_registered = true;
-#endif
+ if (cmos_rtc.dev)
+ return 0;
- if (!cmos_rtc.dev) {
- retval = platform_driver_probe(&cmos_platform_driver,
- cmos_platform_probe);
- if (retval == 0)
- platform_driver_registered = true;
- }
+ retval = platform_driver_probe(&cmos_platform_driver, cmos_platform_probe);
+ if (retval)
+ return retval;
- if (retval == 0)
- return 0;
+ platform_driver_registered = true;
-#ifdef CONFIG_PNP
- if (pnp_driver_registered)
- pnp_unregister_driver(&cmos_pnp_driver);
-#endif
- return retval;
+ return 0;
}
module_init(cmos_init);
static void __exit cmos_exit(void)
{
-#ifdef CONFIG_PNP
- if (pnp_driver_registered)
- pnp_unregister_driver(&cmos_pnp_driver);
-#endif
if (platform_driver_registered)
platform_driver_unregister(&cmos_platform_driver);
}
diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c
index f46428ca77cc..f7afd6bdeb4a 100644
--- a/drivers/rtc/rtc-ds1390.c
+++ b/drivers/rtc/rtc-ds1390.c
@@ -134,7 +134,7 @@ static int ds1390_read_time(struct device *dev, struct rtc_time *dt)
chip->txrx_buf[0] = DS1390_REG_SECONDS;
/* do the i/o */
- status = spi_write_then_read(spi, chip->txrx_buf, 1, chip->txrx_buf, 8);
+ status = spi_write_then_read(spi, chip->txrx_buf, 1, chip->txrx_buf, 7);
if (status != 0)
return status;
diff --git a/drivers/rtc/rtc-loongson.c b/drivers/rtc/rtc-loongson.c
index 2ca7ffd5d7a9..066f0644d1c3 100644
--- a/drivers/rtc/rtc-loongson.c
+++ b/drivers/rtc/rtc-loongson.c
@@ -66,7 +66,8 @@
* According to the LS1C manual, RTC_CTRL and alarm-related registers are not defined.
* Accessing the relevant registers will cause the system to hang.
*/
-#define LS1C_RTC_CTRL_WORKAROUND BIT(0)
+#define LOONGSON_RTC_CTRL_WORKAROUND BIT(0)
+#define LOONGSON_RTC_ALARM_WORKAROUND BIT(1)
struct loongson_rtc_config {
u32 pm_offset; /* Offset of PM domain, for RTC alarm wakeup */
@@ -89,7 +90,7 @@ static const struct loongson_rtc_config ls1b_rtc_config = {
static const struct loongson_rtc_config ls1c_rtc_config = {
.pm_offset = 0,
- .flags = LS1C_RTC_CTRL_WORKAROUND,
+ .flags = LOONGSON_RTC_CTRL_WORKAROUND | LOONGSON_RTC_ALARM_WORKAROUND,
};
static const struct loongson_rtc_config generic_rtc_config = {
@@ -97,6 +98,11 @@ static const struct loongson_rtc_config generic_rtc_config = {
.flags = 0,
};
+static const struct loongson_rtc_config ls2k0300_rtc_config = {
+ .pm_offset = 0x0,
+ .flags = LOONGSON_RTC_ALARM_WORKAROUND,
+};
+
static const struct loongson_rtc_config ls2k1000_rtc_config = {
.pm_offset = 0x800,
.flags = 0,
@@ -153,7 +159,7 @@ static int loongson_rtc_set_enabled(struct device *dev)
{
struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
- if (priv->config->flags & LS1C_RTC_CTRL_WORKAROUND)
+ if (priv->config->flags & LOONGSON_RTC_CTRL_WORKAROUND)
return 0;
/* Enable RTC TOY counters and crystal */
@@ -167,7 +173,7 @@ static bool loongson_rtc_get_enabled(struct device *dev)
u32 ctrl_data;
struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
- if (priv->config->flags & LS1C_RTC_CTRL_WORKAROUND)
+ if (priv->config->flags & LOONGSON_RTC_CTRL_WORKAROUND)
return true;
ret = regmap_read(priv->regmap, RTC_CTRL_REG, &ctrl_data);
@@ -299,9 +305,41 @@ static const struct rtc_class_ops loongson_rtc_ops = {
.alarm_irq_enable = loongson_rtc_alarm_irq_enable,
};
+static int loongson_rtc_alarm_setting(struct platform_device *pdev, void __iomem *regs)
+{
+ int ret = 0, alarm_irq;
+ struct device *dev = &pdev->dev;
+ struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
+
+ if (priv->config->flags & LOONGSON_RTC_ALARM_WORKAROUND) {
+ /* Loongson-1C/Loongson-2K0300 RTC does not support alarm */
+ clear_bit(RTC_FEATURE_ALARM, priv->rtcdev->features);
+ return 0;
+ }
+
+ /* Get RTC alarm irq */
+ alarm_irq = platform_get_irq(pdev, 0);
+ if (alarm_irq < 0)
+ return alarm_irq;
+
+ ret = devm_request_irq(dev, alarm_irq, loongson_rtc_isr, 0, "loongson-alarm",
+ priv);
+ if (ret < 0)
+ return ret;
+
+ priv->pm_base = regs - priv->config->pm_offset;
+ device_init_wakeup(dev, true);
+
+ if (has_acpi_companion(dev))
+ acpi_install_fixed_event_handler(ACPI_EVENT_RTC,
+ loongson_rtc_handler, priv);
+
+ return ret;
+}
+
static int loongson_rtc_probe(struct platform_device *pdev)
{
- int ret, alarm_irq;
+ int ret;
void __iomem *regs;
struct loongson_rtc_priv *priv;
struct device *dev = &pdev->dev;
@@ -330,25 +368,9 @@ static int loongson_rtc_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(priv->rtcdev),
"devm_rtc_allocate_device failed\n");
- /* Get RTC alarm irq */
- alarm_irq = platform_get_irq(pdev, 0);
- if (alarm_irq > 0) {
- ret = devm_request_irq(dev, alarm_irq, loongson_rtc_isr,
- 0, "loongson-alarm", priv);
- if (ret < 0)
- return dev_err_probe(dev, ret, "Unable to request irq %d\n",
- alarm_irq);
-
- priv->pm_base = regs - priv->config->pm_offset;
- device_init_wakeup(dev, true);
-
- if (has_acpi_companion(dev))
- acpi_install_fixed_event_handler(ACPI_EVENT_RTC,
- loongson_rtc_handler, priv);
- } else {
- /* Loongson-1C RTC does not support alarm */
- clear_bit(RTC_FEATURE_ALARM, priv->rtcdev->features);
- }
+ ret = loongson_rtc_alarm_setting(pdev, regs);
+ if (ret)
+ return ret;
/* Loongson RTC does not support UIE */
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, priv->rtcdev->features);
@@ -379,6 +401,7 @@ static const struct of_device_id loongson_rtc_of_match[] = {
{ .compatible = "loongson,ls1b-rtc", .data = &ls1b_rtc_config },
{ .compatible = "loongson,ls1c-rtc", .data = &ls1c_rtc_config },
{ .compatible = "loongson,ls7a-rtc", .data = &generic_rtc_config },
+ { .compatible = "loongson,ls2k0300-rtc", .data = &ls2k0300_rtc_config },
{ .compatible = "loongson,ls2k1000-rtc", .data = &ls2k1000_rtc_config },
{ /* sentinel */ }
};
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 740cab013f59..b26afef37d9c 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -924,13 +924,7 @@ static int m41t80_probe(struct i2c_client *client)
return -ENOMEM;
m41t80_data->client = client;
- if (client->dev.of_node) {
- m41t80_data->features = (unsigned long)
- of_device_get_match_data(&client->dev);
- } else {
- const struct i2c_device_id *id = i2c_match_id(m41t80_id, client);
- m41t80_data->features = id->driver_data;
- }
+ m41t80_data->features = (unsigned long)i2c_get_match_data(client);
i2c_set_clientdata(client, m41t80_data);
m41t80_data->rtc = devm_rtc_allocate_device(&client->dev);
diff --git a/drivers/rtc/rtc-max31335.c b/drivers/rtc/rtc-max31335.c
index 23b7bf16b4cd..952b455071d6 100644
--- a/drivers/rtc/rtc-max31335.c
+++ b/drivers/rtc/rtc-max31335.c
@@ -591,7 +591,7 @@ static struct nvmem_config max31335_nvmem_cfg = {
.size = MAX31335_RAM_SIZE,
};
-#if IS_REACHABLE(HWMON)
+#if IS_REACHABLE(CONFIG_HWMON)
static int max31335_read_temp(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
@@ -672,7 +672,7 @@ static int max31335_clkout_register(struct device *dev)
static int max31335_probe(struct i2c_client *client)
{
struct max31335_data *max31335;
-#if IS_REACHABLE(HWMON)
+#if IS_REACHABLE(CONFIG_HWMON)
struct device *hwmon;
#endif
const struct chip_desc *match;
@@ -727,7 +727,7 @@ static int max31335_probe(struct i2c_client *client)
return dev_err_probe(&client->dev, ret,
"cannot register rtc nvmem\n");
-#if IS_REACHABLE(HWMON)
+#if IS_REACHABLE(CONFIG_HWMON)
if (max31335->chip->temp_reg) {
hwmon = devm_hwmon_device_register_with_info(&client->dev, client->name, max31335,
&max31335_chip_info, NULL);
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index 69ea3ce75b5a..3cdfd78a07cc 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -686,6 +686,11 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info)
return ret;
}
+static void max77686_rtc_release_dev(void *client)
+{
+ i2c_unregister_device(client);
+}
+
static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
{
struct device *parent = info->dev->parent;
@@ -713,12 +718,17 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
goto add_rtc_irq;
}
- client = devm_i2c_new_dummy_device(info->dev, parent_i2c->adapter,
- info->drv_data->rtc_i2c_addr);
+ client = i2c_new_ancillary_device(parent_i2c, "rtc",
+ info->drv_data->rtc_i2c_addr);
if (IS_ERR(client))
return dev_err_probe(info->dev, PTR_ERR(client),
"Failed to allocate I2C device for RTC\n");
+ ret = devm_add_action_or_reset(info->dev, max77686_rtc_release_dev,
+ client);
+ if (ret)
+ return ret;
+
info->rtc_regmap = devm_regmap_init_i2c(client,
info->drv_data->regmap_config);
if (IS_ERR(info->rtc_regmap))
diff --git a/drivers/rtc/rtc-ntxec.c b/drivers/rtc/rtc-ntxec.c
index 850ca49186fd..d28ddb34e19e 100644
--- a/drivers/rtc/rtc-ntxec.c
+++ b/drivers/rtc/rtc-ntxec.c
@@ -110,7 +110,7 @@ static int ntxec_rtc_probe(struct platform_device *pdev)
struct rtc_device *dev;
struct ntxec_rtc *rtc;
- pdev->dev.of_node = pdev->dev.parent->of_node;
+ device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc)
diff --git a/drivers/rtc/rtc-optee.c b/drivers/rtc/rtc-optee.c
index eefde789d194..6c908c0d861a 100644
--- a/drivers/rtc/rtc-optee.c
+++ b/drivers/rtc/rtc-optee.c
@@ -541,10 +541,7 @@ static int optee_rtc_read_info(struct device *dev, struct rtc_device *rtc,
static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
{
- if (ver->impl_id == TEE_IMPL_ID_OPTEE)
- return 1;
- else
- return 0;
+ return (ver->impl_id == TEE_IMPL_ID_OPTEE);
}
static int optee_rtc_probe(struct tee_client_device *rtc_device)
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index bb4fe81d3d62..e4785c5a55d0 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -1449,10 +1449,10 @@ static const struct regmap_bus pcf2127_i2c_regmap = {
static struct i2c_driver pcf2127_i2c_driver;
static const struct i2c_device_id pcf2127_i2c_id[] = {
- { "pcf2127", PCF2127 },
- { "pcf2129", PCF2129 },
- { "pca2129", PCF2129 },
- { "pcf2131", PCF2131 },
+ { "pcf2127", (kernel_ulong_t)&pcf21xx_cfg[PCF2127] },
+ { "pcf2129", (kernel_ulong_t)&pcf21xx_cfg[PCF2129] },
+ { "pca2129", (kernel_ulong_t)&pcf21xx_cfg[PCF2129] },
+ { "pcf2131", (kernel_ulong_t)&pcf21xx_cfg[PCF2131] },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcf2127_i2c_id);
@@ -1469,18 +1469,9 @@ static int pcf2127_i2c_probe(struct i2c_client *client)
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
- if (client->dev.of_node) {
- variant = of_device_get_match_data(&client->dev);
- if (!variant)
- return -ENODEV;
- } else {
- enum pcf21xx_type type =
- i2c_match_id(pcf2127_i2c_id, client)->driver_data;
-
- if (type >= PCF21XX_LAST_ID)
- return -ENODEV;
- variant = &pcf21xx_cfg[type];
- }
+ variant = i2c_get_match_data(client);
+ if (!variant)
+ return -ENODEV;
config.max_register = variant->max_register,
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index 4e61011fb7a9..b281e9489df1 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -424,7 +424,7 @@ static const struct clk_ops pcf8563_clkout_ops = {
static struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563)
{
- struct device_node *node = pcf8563->rtc->dev.of_node;
+ struct device_node *node = pcf8563->rtc->dev.parent->of_node;
struct clk_init_data init;
struct clk *clk;
int ret;
diff --git a/drivers/rtc/rtc-pic32.c b/drivers/rtc/rtc-pic32.c
index 52c11532bc3a..3c7a38a4ac08 100644
--- a/drivers/rtc/rtc-pic32.c
+++ b/drivers/rtc/rtc-pic32.c
@@ -15,8 +15,7 @@
#include <linux/clk.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
-
-#include <asm/mach-pic32/pic32.h>
+#include <linux/platform_data/pic32.h>
#define PIC32_RTCCON 0x00
#define PIC32_RTCCON_ON BIT(15)
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index f8fab0205f8c..936f4f05c8c7 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -825,12 +825,7 @@ static int rs5c372_probe(struct i2c_client *client)
rs5c372->client = client;
i2c_set_clientdata(client, rs5c372);
- if (client->dev.of_node) {
- rs5c372->type = (uintptr_t)of_device_get_match_data(&client->dev);
- } else {
- const struct i2c_device_id *id = i2c_match_id(rs5c372_id, client);
- rs5c372->type = id->driver_data;
- }
+ rs5c372->type = (uintptr_t)i2c_get_match_data(client);
/* we read registers 0x0f then 0x00-0x0f; skip the first one */
rs5c372->regs = &rs5c372->buf[1];
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index 4e9e04cbec89..2bf988a89fd7 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -667,13 +667,7 @@ static int rv8803_probe(struct i2c_client *client)
mutex_init(&rv8803->flags_lock);
rv8803->client = client;
- if (client->dev.of_node) {
- rv8803->type = (uintptr_t)of_device_get_match_data(&client->dev);
- } else {
- const struct i2c_device_id *id = i2c_match_id(rv8803_id, client);
-
- rv8803->type = id->driver_data;
- }
+ rv8803->type = (uintptr_t)i2c_get_match_data(client);
i2c_set_clientdata(client, rv8803);
flags = rv8803_read_reg(client, RV8803_FLAG);
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index ced6e7adfe8d..c57081f9e02b 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -522,7 +522,6 @@ static const struct attribute_group rx8025_attr_group = {
static int rx8025_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_match_id(rx8025_id, client);
struct i2c_adapter *adapter = client->adapter;
struct rx8025_data *rx8025;
int err = 0;
@@ -540,8 +539,7 @@ static int rx8025_probe(struct i2c_client *client)
i2c_set_clientdata(client, rx8025);
- if (id)
- rx8025->model = id->driver_data;
+ rx8025->model = (uintptr_t)i2c_get_match_data(client);
err = rx8025_init_client(client);
if (err)
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index 07bd983b5692..a4678d7c6cf6 100644
--- a/drivers/rtc/rtc-s35390a.c
+++ b/drivers/rtc/rtc-s35390a.c
@@ -18,6 +18,7 @@
#define S35390A_CMD_TIME1 2
#define S35390A_CMD_TIME2 3
#define S35390A_CMD_INT2_REG1 5
+#define S35390A_CMD_FREE_REG 7
#define S35390A_BYTE_YEAR 0
#define S35390A_BYTE_MONTH 1
@@ -416,6 +417,23 @@ static const struct rtc_class_ops s35390a_rtc_ops = {
.ioctl = s35390a_rtc_ioctl,
};
+static int s35390a_nvmem_read(void *priv, unsigned int offset, void *val,
+ size_t bytes)
+{
+ struct s35390a *s35390a = priv;
+
+ /* The offset is ignored because the NVMEM region is only 1 byte */
+ return s35390a_get_reg(s35390a, S35390A_CMD_FREE_REG, val, bytes);
+}
+
+static int s35390a_nvmem_write(void *priv, unsigned int offset, void *val,
+ size_t bytes)
+{
+ struct s35390a *s35390a = priv;
+
+ return s35390a_set_reg(s35390a, S35390A_CMD_FREE_REG, val, bytes);
+}
+
static int s35390a_probe(struct i2c_client *client)
{
int err, err_read;
@@ -424,6 +442,15 @@ static int s35390a_probe(struct i2c_client *client)
struct rtc_device *rtc;
u8 buf, status1;
struct device *dev = &client->dev;
+ struct nvmem_config nvmem_cfg = {
+ .name = "s35390a_nvram",
+ .type = NVMEM_TYPE_BATTERY_BACKED,
+ .word_size = 1,
+ .stride = 1,
+ .size = 1,
+ .reg_read = s35390a_nvmem_read,
+ .reg_write = s35390a_nvmem_write,
+ };
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
@@ -490,6 +517,11 @@ static int s35390a_probe(struct i2c_client *client)
if (status1 & S35390A_FLAG_INT2)
rtc_update_irq(rtc, 1, RTC_AF);
+ nvmem_cfg.priv = s35390a;
+ err = devm_rtc_nvmem_register(rtc, &nvmem_cfg);
+ if (err)
+ return err;
+
return devm_rtc_register_device(rtc);
}
diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index e5e6013d080e..7fc60880e409 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -233,12 +233,12 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,
const char *parents[2];
u32 reg;
- rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
+ rtc = kzalloc_obj(*rtc);
if (!rtc)
return;
rtc->data = data;
- clk_data = kzalloc(struct_size(clk_data, hws, 3), GFP_KERNEL);
+ clk_data = kzalloc_flex(*clk_data, hws, 3);
if (!clk_data) {
kfree(rtc);
return;
diff --git a/drivers/rtc/rtc-ti-k3.c b/drivers/rtc/rtc-ti-k3.c
index ec759d8f7023..e801f5b9d757 100644
--- a/drivers/rtc/rtc-ti-k3.c
+++ b/drivers/rtc/rtc-ti-k3.c
@@ -640,10 +640,18 @@ static int __maybe_unused ti_k3_rtc_suspend(struct device *dev)
static int __maybe_unused ti_k3_rtc_resume(struct device *dev)
{
struct ti_k3_rtc *priv = dev_get_drvdata(dev);
+ int ret = 0;
+
+ if (k3rtc_check_unlocked(priv)) {
+ /* RTC locked implies low power mode exit where RTC loses context */
+ ret = k3rtc_configure(dev);
+ if (ret)
+ return ret;
+ }
if (device_may_wakeup(dev))
disable_irq_wake(priv->irq);
- return 0;
+ return ret;
}
static SIMPLE_DEV_PM_OPS(ti_k3_rtc_pm_ops, ti_k3_rtc_suspend, ti_k3_rtc_resume);
diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c
index 3baa2b481d9f..2ae54804b87a 100644
--- a/drivers/rtc/rtc-zynqmp.c
+++ b/drivers/rtc/rtc-zynqmp.c
@@ -43,9 +43,7 @@
#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
+#define RTC_PPB 1000000000
struct xlnx_rtc_dev {
struct rtc_device *rtc;
@@ -178,21 +176,28 @@ static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev)
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;
+ unsigned int calibval, fract_data, fract_part;
+ int freq = xrtcdev->freq;
+ int max_tick, tick_mult;
long offset_val;
+ /* Tick to offset multiplier */
+ tick_mult = DIV_ROUND_CLOSEST(RTC_PPB, freq);
+
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;
+ max_tick = calibval & RTC_TICK_MASK;
+ offset_val = max_tick - freq;
+ /* Convert to ppb */
+ 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);
+ if (calibval & RTC_FR_EN) {
+ fract_data = (calibval & RTC_FR_MASK) >> RTC_FR_DATSHIFT;
+ fract_part = DIV_ROUND_UP(tick_mult, RTC_FR_MAX_TICKS);
+ offset_val += (fract_part * fract_data);
+ }
+
*offset = offset_val;
return 0;
@@ -201,44 +206,38 @@ static int xlnx_rtc_read_offset(struct device *dev, long *offset)
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;
+ int max_tick, tick_mult, fract_offset, fract_part;
+ int freq = xrtcdev->freq;
unsigned int calibval;
- short int max_tick;
- int fract_offset;
+ int fract_data = 0;
- if (offset < RTC_MIN_OFFSET || offset > RTC_MAX_OFFSET)
- return -ERANGE;
+ /* Tick to offset multiplier */
+ tick_mult = DIV_ROUND_CLOSEST(RTC_PPB, freq);
/* Number ticks for given offset */
max_tick = div_s64_rem(offset, tick_mult, &fract_offset);
+ if (freq + max_tick > RTC_TICK_MASK || (freq + max_tick < 1))
+ return -ERANGE;
+
/* Number fractional ticks for given offset */
if (fract_offset) {
- if (fract_offset < 0) {
- fract_offset = fract_offset + tick_mult;
+ fract_part = DIV_ROUND_UP(tick_mult, RTC_FR_MAX_TICKS);
+ fract_data = fract_offset / fract_part;
+ /* Subtract one from max_tick while adding fract_offset */
+ if (fract_offset < 0 && fract_data) {
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;
- }
+ fract_data += RTC_FR_MAX_TICKS;
}
}
/* Zynqmp RTC uses second and fractional tick
* counters for compensation
*/
- calibval = max_tick + RTC_CALIB_DEF;
+ calibval = max_tick + freq;
- if (fract_tick)
- calibval |= RTC_FR_EN;
-
- calibval |= (fract_tick << RTC_FR_DATSHIFT);
+ if (fract_data)
+ calibval |= (RTC_FR_EN | (fract_data << RTC_FR_DATSHIFT));
writel(calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
@@ -345,7 +344,15 @@ static int xlnx_rtc_probe(struct platform_device *pdev)
&xrtcdev->freq);
if (ret)
xrtcdev->freq = RTC_CALIB_DEF;
+ } else {
+ xrtcdev->freq--;
}
+
+ if (xrtcdev->freq > RTC_TICK_MASK) {
+ dev_err(&pdev->dev, "Invalid RTC calibration value\n");
+ return -EINVAL;
+ }
+
ret = readl(xrtcdev->reg_base + RTC_CALIB_RD);
if (!ret)
writel(xrtcdev->freq, (xrtcdev->reg_base + RTC_CALIB_WR));