diff options
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/rtc/class.c | 4 | ||||
| -rw-r--r-- | drivers/rtc/dev.c | 11 | ||||
| -rw-r--r-- | drivers/rtc/interface.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-abx80x.c | 5 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ac100.c | 75 | ||||
| -rw-r--r-- | drivers/rtc/rtc-armada38x.c | 9 | ||||
| -rw-r--r-- | drivers/rtc/rtc-cmos.c | 156 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1390.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-loongson.c | 71 | ||||
| -rw-r--r-- | drivers/rtc/rtc-m41t80.c | 8 | ||||
| -rw-r--r-- | drivers/rtc/rtc-max31335.c | 6 | ||||
| -rw-r--r-- | drivers/rtc/rtc-max77686.c | 14 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ntxec.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-optee.c | 5 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pcf2127.c | 23 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pcf8563.c | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pic32.c | 3 | ||||
| -rw-r--r-- | drivers/rtc/rtc-rs5c372.c | 7 | ||||
| -rw-r--r-- | drivers/rtc/rtc-rv8803.c | 8 | ||||
| -rw-r--r-- | drivers/rtc/rtc-rx8025.c | 4 | ||||
| -rw-r--r-- | drivers/rtc/rtc-s35390a.c | 32 | ||||
| -rw-r--r-- | drivers/rtc/rtc-sun6i.c | 4 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ti-k3.c | 10 | ||||
| -rw-r--r-- | drivers/rtc/rtc-zynqmp.c | 75 |
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)); |
