diff options
Diffstat (limited to 'drivers/rtc')
127 files changed, 4115 insertions, 1239 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index c63e32d012f2..838bdc138ffe 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -182,6 +182,16 @@ config RTC_DRV_88PM80X This driver can also be built as a module. If so, the module will be called rtc-88pm80x. +config RTC_DRV_88PM886 + tristate "Marvell 88PM886 RTC driver" + depends on MFD_88PM886_PMIC + help + If you say yes here you will get support for the RTC function in the + Marvell 88PM886 chip. + + This driver can also be built as a module. If so, the module + will be called rtc-88pm886. + config RTC_DRV_ABB5ZES3 select REGMAP_I2C tristate "Abracon AB-RTCMC-32.768kHz-B5ZE-S3" @@ -496,6 +506,7 @@ config RTC_DRV_PCF85363 config RTC_DRV_PCF8563 tristate "Philips PCF8563/Epson RTC8564" + select REGMAP_I2C help If you say yes here you get support for the Philips PCF8563 RTC chip. The Epson RTC8564 @@ -664,6 +675,16 @@ config RTC_DRV_RX8010 This driver can also be built as a module. If so, the module will be called rtc-rx8010. +config RTC_DRV_RX8111 + tristate "Epson RX8111" + select REGMAP_I2C + depends on I2C + help + If you say yes here you will get support for the Epson RX8111 RTC. + + This driver can also be built as a module. If so, the module will be + called rtc-rx8111. + config RTC_DRV_RX8581 tristate "Epson RX-8571/RX-8581" select REGMAP_I2C @@ -733,6 +754,16 @@ config RTC_DRV_S5M This driver can also be built as a module. If so, the module will be called rtc-s5m. +config RTC_DRV_SD2405AL + tristate "DFRobot SD2405AL" + select REGMAP_I2C + help + If you say yes here you will get support for the + DFRobot SD2405AL I2C RTC Module. + + This driver can also be built as a module. If so, the module + will be called rtc-sd2405al. + config RTC_DRV_SD3078 tristate "ZXW Shenzhen whwave SD3078" select REGMAP_I2C @@ -1285,18 +1316,11 @@ config RTC_DRV_SC27XX config RTC_DRV_SPEAR tristate "SPEAR ST RTC" depends on PLAT_SPEAR || COMPILE_TEST - default y + default PLAT_SPEAR help If you say Y here you will get support for the RTC found on spear -config RTC_DRV_PCF50633 - depends on MFD_PCF50633 - tristate "NXP PCF50633 RTC" - help - If you say yes here you get support for the RTC subsystem of the - NXP PCF50633 used in embedded systems. - config RTC_DRV_AB8500 tristate "ST-Ericsson AB8500 RTC" depends on AB8500_CORE @@ -1817,6 +1841,17 @@ config RTC_DRV_BBNSM This driver can also be built as a module, if so, the module will be called "rtc-bbnsm". +config RTC_DRV_IMX_BBM_SCMI + depends on IMX_SCMI_BBM_EXT || COMPILE_TEST + default y if ARCH_MXC + tristate "NXP i.MX BBM SCMI RTC support" + help + If you say yes here you get support for the NXP i.MX BBSM SCMI + RTC module. + + To compile this driver as a module, choose M here: the + module will be called rtc-imx-sm-bbm. + config RTC_DRV_IMX_SC depends on IMX_SCU depends on HAVE_ARM_SMCCC @@ -1913,6 +1948,12 @@ config RTC_DRV_STM32 tristate "STM32 RTC" select REGMAP_MMIO depends on ARCH_STM32 || COMPILE_TEST + depends on OF + depends on PINCTRL + select PINMUX + select PINCONF + select GENERIC_PINCONF + depends on COMMON_CLK help If you say yes here you get support for the STM32 On-Chip Real Time Clock. @@ -1968,6 +2009,16 @@ config RTC_DRV_MA35D1 This driver can also be built as a module, if so, the module will be called "rtc-ma35d1". +config RTC_DRV_RENESAS_RTCA3 + tristate "Renesas RTCA-3 RTC" + depends on ARCH_RENESAS + help + If you say yes here you get support for the Renesas RTCA-3 RTC + available on the Renesas RZ/G3S SoC. + + This driver can also be built as a module, if so, the module + will be called "rtc-rtca3". + comment "HID Sensor RTC drivers" config RTC_DRV_HID_SENSOR_TIME @@ -2033,4 +2084,16 @@ config RTC_DRV_SSD202D This driver can also be built as a module, if so, the module will be called "rtc-ssd20xd". +config RTC_DRV_AMLOGIC_A4 + tristate "Amlogic RTC" + depends on ARCH_MESON || COMPILE_TEST + select REGMAP_MMIO + default y + help + If you say yes here you get support for the RTC block on the + Amlogic A113L2(A4) and A113X2(A5) SoCs. + + This driver can also be built as a module. If so, the module + will be called "rtc-amlogic-a4". + endif # RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 6efff381c484..31473b3276d9 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -21,11 +21,13 @@ obj-$(CONFIG_RTC_LIB_KUNIT_TEST) += lib_test.o obj-$(CONFIG_RTC_DRV_88PM80X) += rtc-88pm80x.o obj-$(CONFIG_RTC_DRV_88PM860X) += rtc-88pm860x.o +obj-$(CONFIG_RTC_DRV_88PM886) += rtc-88pm886.o obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o obj-$(CONFIG_RTC_DRV_ABB5ZES3) += rtc-ab-b5ze-s3.o obj-$(CONFIG_RTC_DRV_ABEOZ9) += rtc-ab-eoz9.o obj-$(CONFIG_RTC_DRV_ABX80X) += rtc-abx80x.o obj-$(CONFIG_RTC_DRV_AC100) += rtc-ac100.o +obj-$(CONFIG_RTC_DRV_AMLOGIC_A4) += rtc-amlogic-a4.o obj-$(CONFIG_RTC_DRV_ARMADA38X) += rtc-armada38x.o obj-$(CONFIG_RTC_DRV_AS3722) += rtc-as3722.o obj-$(CONFIG_RTC_DRV_ASM9260) += rtc-asm9260.o @@ -74,6 +76,7 @@ obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o obj-$(CONFIG_RTC_DRV_HYM8563) += rtc-hym8563.o obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o obj-$(CONFIG_RTC_DRV_IMX_SC) += rtc-imx-sc.o +obj-$(CONFIG_RTC_DRV_IMX_BBM_SCMI) += rtc-imx-sm-bbm.o obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o obj-$(CONFIG_RTC_DRV_ISL12026) += rtc-isl12026.o obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o @@ -123,7 +126,6 @@ obj-$(CONFIG_RTC_DRV_PALMAS) += rtc-palmas.o obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o -obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o obj-$(CONFIG_RTC_DRV_PCF85363) += rtc-pcf85363.o @@ -154,14 +156,17 @@ obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o obj-$(CONFIG_RTC_DRV_RX6110) += rtc-rx6110.o obj-$(CONFIG_RTC_DRV_RX8010) += rtc-rx8010.o obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o +obj-$(CONFIG_RTC_DRV_RX8111) += rtc-rx8111.o obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o obj-$(CONFIG_RTC_DRV_RZN1) += rtc-rzn1.o +obj-$(CONFIG_RTC_DRV_RENESAS_RTCA3) += rtc-renesas-rtca3.o obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o obj-$(CONFIG_RTC_DRV_S5M) += rtc-s5m.o obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o obj-$(CONFIG_RTC_DRV_SC27XX) += rtc-sc27xx.o -obj-$(CONFIG_RTC_DRV_SD3078) += rtc-sd3078.o +obj-$(CONFIG_RTC_DRV_SD2405AL) += rtc-sd2405al.o +obj-$(CONFIG_RTC_DRV_SD3078) += rtc-sd3078.o obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index e31fa0ad127e..b88cd4fb295b 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -240,8 +240,7 @@ static struct rtc_device *rtc_allocate_device(void) /* Init uie timer */ rtc_timer_init(&rtc->uie_rtctimer, rtc_uie_update_irq, rtc); /* Init pie timer */ - hrtimer_init(&rtc->pie_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - rtc->pie_timer.function = rtc_pie_update_irq; + hrtimer_setup(&rtc->pie_timer, rtc_pie_update_irq, CLOCK_MONOTONIC, HRTIMER_MODE_REL); rtc->pie_enabled = 0; set_bit(RTC_FEATURE_ALARM, rtc->features); diff --git a/drivers/rtc/dev.c b/drivers/rtc/dev.c index 4aad9bb99868..0eeae5bcc3aa 100644 --- a/drivers/rtc/dev.c +++ b/drivers/rtc/dev.c @@ -90,7 +90,7 @@ static int clear_uie(struct rtc_device *rtc) rtc->stop_uie_polling = 1; if (rtc->uie_timer_active) { spin_unlock_irq(&rtc->irq_lock); - del_timer_sync(&rtc->uie_timer); + timer_delete_sync(&rtc->uie_timer); spin_lock_irq(&rtc->irq_lock); rtc->uie_timer_active = 0; } @@ -523,7 +523,6 @@ static int rtc_dev_release(struct inode *inode, struct file *file) static const struct file_operations rtc_dev_fops = { .owner = THIS_MODULE, - .llseek = no_llseek, .read = rtc_dev_read, .poll = rtc_dev_poll, .unlocked_ioctl = rtc_dev_ioctl, diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 5faafb4aa55c..aaf76406cd7d 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -274,10 +274,9 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) return err; /* full-function RTCs won't have such missing fields */ - if (rtc_valid_tm(&alarm->time) == 0) { - rtc_add_offset(rtc, &alarm->time); - return 0; - } + err = rtc_valid_tm(&alarm->time); + if (!err) + goto done; /* get the "after" timestamp, to detect wrapped fields */ err = rtc_read_time(rtc, &now); @@ -379,6 +378,8 @@ done: if (err && alarm->enabled) dev_warn(&rtc->dev, "invalid alarm value: %ptR\n", &alarm->time); + else + rtc_add_offset(rtc, &alarm->time); return err; } @@ -903,13 +904,18 @@ void rtc_timer_do_work(struct work_struct *work) struct timerqueue_node *next; ktime_t now; struct rtc_time tm; + int err; struct rtc_device *rtc = container_of(work, struct rtc_device, irqwork); mutex_lock(&rtc->ops_lock); again: - __rtc_read_time(rtc, &tm); + err = __rtc_read_time(rtc, &tm); + if (err) { + mutex_unlock(&rtc->ops_lock); + return; + } now = rtc_tm_to_ktime(tm); while ((next = timerqueue_getnext(&rtc->timerqueue))) { if (next->expires > now) diff --git a/drivers/rtc/lib_test.c b/drivers/rtc/lib_test.c index 225c859d6da5..c30c759662e3 100644 --- a/drivers/rtc/lib_test.c +++ b/drivers/rtc/lib_test.c @@ -27,17 +27,17 @@ static void advance_date(int *year, int *month, int *mday, int *yday) } /* - * Checks every day in a 160000 years interval starting on 1970-01-01 + * Check every day in specified number of years interval starting on 1970-01-01 * against the expected result. */ -static void rtc_time64_to_tm_test_date_range(struct kunit *test) +static void rtc_time64_to_tm_test_date_range(struct kunit *test, int years) { /* - * 160000 years = (160000 / 400) * 400 years - * = (160000 / 400) * 146097 days - * = (160000 / 400) * 146097 * 86400 seconds + * years = (years / 400) * 400 years + * = (years / 400) * 146097 days + * = (years / 400) * 146097 * 86400 seconds */ - time64_t total_secs = ((time64_t) 160000) / 400 * 146097 * 86400; + time64_t total_secs = ((time64_t)years) / 400 * 146097 * 86400; int year = 1970; int month = 1; @@ -66,8 +66,27 @@ static void rtc_time64_to_tm_test_date_range(struct kunit *test) } } +/* + * Checks every day in a 160000 years interval starting on 1970-01-01 + * against the expected result. + */ +static void rtc_time64_to_tm_test_date_range_160000(struct kunit *test) +{ + rtc_time64_to_tm_test_date_range(test, 160000); +} + +/* + * Checks every day in a 1000 years interval starting on 1970-01-01 + * against the expected result. + */ +static void rtc_time64_to_tm_test_date_range_1000(struct kunit *test) +{ + rtc_time64_to_tm_test_date_range(test, 1000); +} + static struct kunit_case rtc_lib_test_cases[] = { - KUNIT_CASE(rtc_time64_to_tm_test_date_range), + KUNIT_CASE(rtc_time64_to_tm_test_date_range_1000), + KUNIT_CASE_SLOW(rtc_time64_to_tm_test_date_range_160000), {} }; @@ -78,4 +97,5 @@ static struct kunit_suite rtc_lib_test_suite = { kunit_test_suite(rtc_lib_test_suite); +MODULE_DESCRIPTION("KUnit test for RTC lib functions"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index f40cc06b0979..a3e52a5a708f 100644 --- a/drivers/rtc/rtc-88pm80x.c +++ b/drivers/rtc/rtc-88pm80x.c @@ -308,7 +308,7 @@ static int pm80x_rtc_probe(struct platform_device *pdev) /* remember whether this power up is caused by PMIC RTC or not */ info->rtc_dev->dev.platform_data = &pdata->rtc_wakeup; - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); return 0; out_rtc: @@ -329,7 +329,7 @@ static struct platform_driver pm80x_rtc_driver = { .pm = &pm80x_rtc_pm_ops, }, .probe = pm80x_rtc_probe, - .remove_new = pm80x_rtc_remove, + .remove = pm80x_rtc_remove, }; module_platform_driver(pm80x_rtc_driver); diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index 0f124ed5b3e5..964cd048fcdb 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c @@ -326,7 +326,7 @@ static int pm860x_rtc_probe(struct platform_device *pdev) schedule_delayed_work(&info->calib_work, VRTC_CALIB_INTERVAL); #endif /* VRTC_CALIBRATION */ - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); return 0; } @@ -371,7 +371,7 @@ static struct platform_driver pm860x_rtc_driver = { .pm = &pm860x_rtc_pm_ops, }, .probe = pm860x_rtc_probe, - .remove_new = pm860x_rtc_remove, + .remove = pm860x_rtc_remove, }; module_platform_driver(pm860x_rtc_driver); diff --git a/drivers/rtc/rtc-88pm886.c b/drivers/rtc/rtc-88pm886.c new file mode 100644 index 000000000000..57e9b0a66eed --- /dev/null +++ b/drivers/rtc/rtc-88pm886.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include <linux/limits.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> + +#include <linux/mfd/88pm886.h> + +/* + * Time is calculated as the sum of a 32-bit read-only advancing counter and a + * writeable constant offset stored in the chip's spare registers. + */ + +static int pm886_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct regmap *regmap = dev_get_drvdata(dev); + u32 time; + u32 buf; + int ret; + + ret = regmap_bulk_read(regmap, PM886_REG_RTC_SPARE1, &buf, 4); + if (ret) + return ret; + time = buf; + + ret = regmap_bulk_read(regmap, PM886_REG_RTC_CNT1, &buf, 4); + if (ret) + return ret; + time += buf; + + rtc_time64_to_tm(time, tm); + + return 0; +} + +static int pm886_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct regmap *regmap = dev_get_drvdata(dev); + u32 buf; + int ret; + + ret = regmap_bulk_read(regmap, PM886_REG_RTC_CNT1, &buf, 4); + if (ret) + return ret; + + buf = rtc_tm_to_time64(tm) - buf; + + return regmap_bulk_write(regmap, PM886_REG_RTC_SPARE1, &buf, 4); +} + +static const struct rtc_class_ops pm886_rtc_ops = { + .read_time = pm886_rtc_read_time, + .set_time = pm886_rtc_set_time, +}; + +static int pm886_rtc_probe(struct platform_device *pdev) +{ + struct pm886_chip *chip = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + struct rtc_device *rtc; + int ret; + + platform_set_drvdata(pdev, chip->regmap); + + rtc = devm_rtc_allocate_device(dev); + if (IS_ERR(rtc)) + return dev_err_probe(dev, PTR_ERR(rtc), + "Failed to allocate RTC device\n"); + + rtc->ops = &pm886_rtc_ops; + rtc->range_max = U32_MAX; + + ret = devm_rtc_register_device(rtc); + if (ret) + return dev_err_probe(dev, ret, "Failed to register RTC device\n"); + + return 0; +} + +static const struct platform_device_id pm886_rtc_id_table[] = { + { "88pm886-rtc", }, + { } +}; +MODULE_DEVICE_TABLE(platform, pm886_rtc_id_table); + +static struct platform_driver pm886_rtc_driver = { + .driver = { + .name = "88pm886-rtc", + }, + .probe = pm886_rtc_probe, + .id_table = pm886_rtc_id_table, +}; +module_platform_driver(pm886_rtc_driver); + +MODULE_DESCRIPTION("Marvell 88PM886 RTC driver"); +MODULE_AUTHOR("Karel Balej <balejk@matfyz.cz>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c index 100062001831..684f9898d768 100644 --- a/drivers/rtc/rtc-ab-b5ze-s3.c +++ b/drivers/rtc/rtc-ab-b5ze-s3.c @@ -933,7 +933,7 @@ MODULE_DEVICE_TABLE(of, abb5zes3_dt_match); #endif static const struct i2c_device_id abb5zes3_id[] = { - { "abb5zes3", 0 }, + { "abb5zes3" }, { } }; MODULE_DEVICE_TABLE(i2c, abb5zes3_id); diff --git a/drivers/rtc/rtc-ab-eoz9.c b/drivers/rtc/rtc-ab-eoz9.c index 04e1b8e93bc1..de002f7a39bf 100644 --- a/drivers/rtc/rtc-ab-eoz9.c +++ b/drivers/rtc/rtc-ab-eoz9.c @@ -64,7 +64,7 @@ #define ABEOZ9_BIT_ALARM_MIN GENMASK(6, 0) #define ABEOZ9_REG_ALARM_HOURS 0x12 #define ABEOZ9_BIT_ALARM_HOURS_PM BIT(5) -#define ABEOZ9_BIT_ALARM_HOURS GENMASK(4, 0) +#define ABEOZ9_BIT_ALARM_HOURS GENMASK(5, 0) #define ABEOZ9_REG_ALARM_DAYS 0x13 #define ABEOZ9_BIT_ALARM_DAYS GENMASK(5, 0) #define ABEOZ9_REG_ALARM_WEEKDAYS 0x14 @@ -231,8 +231,6 @@ static int abeoz9_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) alarm->time.tm_sec = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_SEC, regs[0])); alarm->time.tm_min = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_MIN, regs[1])); alarm->time.tm_hour = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_HOURS, regs[2])); - if (FIELD_GET(ABEOZ9_BIT_ALARM_HOURS_PM, regs[2])) - alarm->time.tm_hour += 12; alarm->time.tm_mday = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_DAYS, regs[3])); @@ -396,13 +394,6 @@ static int abeoz9z3_temp_read(struct device *dev, if (ret < 0) return ret; - if ((val & ABEOZ9_REG_CTRL_STATUS_V1F) || - (val & ABEOZ9_REG_CTRL_STATUS_V2F)) { - dev_err(dev, - "thermometer might be disabled due to low voltage\n"); - return -EINVAL; - } - switch (attr) { case hwmon_temp_input: ret = regmap_read(regmap, ABEOZ9_REG_REG_TEMP, &val); @@ -435,29 +426,9 @@ static umode_t abeoz9_is_visible(const void *data, } } -static const u32 abeoz9_chip_config[] = { - HWMON_C_REGISTER_TZ, - 0 -}; - -static const struct hwmon_channel_info abeoz9_chip = { - .type = hwmon_chip, - .config = abeoz9_chip_config, -}; - -static const u32 abeoz9_temp_config[] = { - HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN, - 0 -}; - -static const struct hwmon_channel_info abeoz9_temp = { - .type = hwmon_temp, - .config = abeoz9_temp_config, -}; - static const struct hwmon_channel_info * const abeoz9_info[] = { - &abeoz9_chip, - &abeoz9_temp, + HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN), NULL }; @@ -575,7 +546,7 @@ MODULE_DEVICE_TABLE(of, abeoz9_dt_match); #endif static const struct i2c_device_id abeoz9_id[] = { - { "abeoz9", 0 }, + { "abeoz9" }, { } }; diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index 75bb2ac9005c..ed2b6b8bb3bf 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -361,7 +361,7 @@ static int ab8500_rtc_probe(struct platform_device *pdev) return -ENODEV; } - device_init_wakeup(&pdev->dev, true); + devm_device_init_wakeup(&pdev->dev); rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc)) @@ -375,7 +375,7 @@ static int ab8500_rtc_probe(struct platform_device *pdev) if (err < 0) return err; - dev_pm_set_wake_irq(&pdev->dev, irq); + devm_pm_set_wake_irq(&pdev->dev, irq); platform_set_drvdata(pdev, rtc); set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features); @@ -392,18 +392,11 @@ static int ab8500_rtc_probe(struct platform_device *pdev) return devm_rtc_register_device(rtc); } -static void ab8500_rtc_remove(struct platform_device *pdev) -{ - dev_pm_clear_wake_irq(&pdev->dev); - device_init_wakeup(&pdev->dev, false); -} - static struct platform_driver ab8500_rtc_driver = { .driver = { .name = "ab8500-rtc", }, .probe = ab8500_rtc_probe, - .remove_new = ab8500_rtc_remove, .id_table = ab85xx_rtc_ids, }; diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c index fde2b8054c2e..3fee27914ba8 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -39,7 +39,7 @@ #define ABX8XX_REG_STATUS 0x0f #define ABX8XX_STATUS_AF BIT(2) #define ABX8XX_STATUS_BLF BIT(4) -#define ABX8XX_STATUS_WDT BIT(6) +#define ABX8XX_STATUS_WDT BIT(5) #define ABX8XX_REG_CTRL1 0x10 #define ABX8XX_CTRL_WRITE BIT(0) @@ -705,14 +705,18 @@ static int abx80x_nvmem_xfer(struct abx80x_priv *priv, unsigned int offset, if (ret) return ret; - if (write) + if (write) { ret = i2c_smbus_write_i2c_block_data(priv->client, reg, len, val); - else + if (ret) + return ret; + } else { ret = i2c_smbus_read_i2c_block_data(priv->client, reg, len, val); - if (ret) - return ret; + if (ret <= 0) + return ret ? ret : -EIO; + len = ret; + } offset += len; val += len; diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c index fa642bba3cee..33626311fa78 100644 --- a/drivers/rtc/rtc-ac100.c +++ b/drivers/rtc/rtc-ac100.c @@ -628,7 +628,7 @@ MODULE_DEVICE_TABLE(of, ac100_rtc_match); static struct platform_driver ac100_rtc_driver = { .probe = ac100_rtc_probe, - .remove_new = ac100_rtc_remove, + .remove = ac100_rtc_remove, .driver = { .name = "ac100-rtc", .of_match_table = of_match_ptr(ac100_rtc_match), diff --git a/drivers/rtc/rtc-amlogic-a4.c b/drivers/rtc/rtc-amlogic-a4.c new file mode 100644 index 000000000000..09d78c2cc691 --- /dev/null +++ b/drivers/rtc/rtc-amlogic-a4.c @@ -0,0 +1,465 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR MIT) +/* + * Copyright (C) 2024 Amlogic, Inc. All rights reserved + * Author: Yiting Deng <yiting.deng@amlogic.com> + */ + +#include <linux/bitfield.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/rtc.h> +#include <linux/time64.h> + +/* rtc oscillator rate */ +#define OSC_32K 32768 +#define OSC_24M 24000000 + +#define RTC_CTRL (0x0 << 2) /* Control RTC */ +#define RTC_ALRM0_EN BIT(0) +#define RTC_OSC_SEL BIT(8) +#define RTC_ENABLE BIT(12) + +#define RTC_COUNTER_REG (0x1 << 2) /* Program RTC counter initial value */ + +#define RTC_ALARM0_REG (0x2 << 2) /* Program RTC alarm0 value */ + +#define RTC_SEC_ADJUST_REG (0x6 << 2) /* Control second-based timing adjustment */ +#define RTC_MATCH_COUNTER GENMASK(18, 0) +#define RTC_SEC_ADJUST_CTRL GENMASK(20, 19) +#define RTC_ADJ_VALID BIT(23) + +#define RTC_INT_MASK (0x8 << 2) /* RTC interrupt mask */ +#define RTC_ALRM0_IRQ_MSK BIT(0) + +#define RTC_INT_CLR (0x9 << 2) /* Clear RTC interrupt */ +#define RTC_ALRM0_IRQ_CLR BIT(0) + +#define RTC_OSCIN_CTRL0 (0xa << 2) /* Control RTC clk from 24M */ +#define RTC_OSCIN_CTRL1 (0xb << 2) /* Control RTC clk from 24M */ +#define RTC_OSCIN_IN_EN BIT(31) +#define RTC_OSCIN_OUT_CFG GENMASK(29, 28) +#define RTC_OSCIN_OUT_N0M0 GENMASK(11, 0) +#define RTC_OSCIN_OUT_N1M1 GENMASK(23, 12) + +#define RTC_INT_STATUS (0xc << 2) /* RTC interrupt status */ +#define RTC_ALRM0_IRQ_STATUS BIT(0) + +#define RTC_REAL_TIME (0xd << 2) /* RTC time value */ + +#define RTC_OSCIN_OUT_32K_N0 0x2dc +#define RTC_OSCIN_OUT_32K_N1 0x2db +#define RTC_OSCIN_OUT_32K_M0 0x1 +#define RTC_OSCIN_OUT_32K_M1 0x2 + +#define RTC_SWALLOW_SECOND 0x2 +#define RTC_INSERT_SECOND 0x3 + +struct aml_rtc_config { + bool gray_stored; +}; + +struct aml_rtc_data { + struct regmap *map; + struct rtc_device *rtc_dev; + int irq; + struct clk *rtc_clk; + struct clk *sys_clk; + int rtc_enabled; + const struct aml_rtc_config *config; +}; + +static const struct regmap_config aml_rtc_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = RTC_REAL_TIME, +}; + +static inline u32 gray_to_binary(u32 gray) +{ + u32 bcd = gray; + int size = sizeof(bcd) * 8; + int i; + + for (i = 0; (1 << i) < size; i++) + bcd ^= bcd >> (1 << i); + + return bcd; +} + +static inline u32 binary_to_gray(u32 bcd) +{ + return bcd ^ (bcd >> 1); +} + +static int aml_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct aml_rtc_data *rtc = dev_get_drvdata(dev); + u32 time_sec; + + /* if RTC disabled, read time failed */ + if (!rtc->rtc_enabled) + return -EINVAL; + + regmap_read(rtc->map, RTC_REAL_TIME, &time_sec); + if (rtc->config->gray_stored) + time_sec = gray_to_binary(time_sec); + rtc_time64_to_tm(time_sec, tm); + dev_dbg(dev, "%s: read time = %us\n", __func__, time_sec); + + return 0; +} + +static int aml_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct aml_rtc_data *rtc = dev_get_drvdata(dev); + u32 time_sec; + + /* if RTC disabled, first enable it */ + if (!rtc->rtc_enabled) { + regmap_write_bits(rtc->map, RTC_CTRL, RTC_ENABLE, RTC_ENABLE); + usleep_range(100, 200); + rtc->rtc_enabled = regmap_test_bits(rtc->map, RTC_CTRL, RTC_ENABLE); + if (!rtc->rtc_enabled) + return -EINVAL; + } + + time_sec = rtc_tm_to_time64(tm); + if (rtc->config->gray_stored) + time_sec = binary_to_gray(time_sec); + regmap_write(rtc->map, RTC_COUNTER_REG, time_sec); + dev_dbg(dev, "%s: set time = %us\n", __func__, time_sec); + + return 0; +} + +static int aml_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct aml_rtc_data *rtc = dev_get_drvdata(dev); + time64_t alarm_sec; + + /* if RTC disabled, set alarm failed */ + if (!rtc->rtc_enabled) + return -EINVAL; + + regmap_update_bits(rtc->map, RTC_CTRL, + RTC_ALRM0_EN, RTC_ALRM0_EN); + regmap_update_bits(rtc->map, RTC_INT_MASK, + RTC_ALRM0_IRQ_MSK, 0); + + alarm_sec = rtc_tm_to_time64(&alarm->time); + if (rtc->config->gray_stored) + alarm_sec = binary_to_gray(alarm_sec); + regmap_write(rtc->map, RTC_ALARM0_REG, alarm_sec); + + dev_dbg(dev, "%s: alarm->enabled=%d alarm_set=%llds\n", __func__, + alarm->enabled, alarm_sec); + + return 0; +} + +static int aml_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct aml_rtc_data *rtc = dev_get_drvdata(dev); + u32 alarm_sec; + int alarm_enable; + int alarm_mask; + + /* if RTC disabled, read alarm failed */ + if (!rtc->rtc_enabled) + return -EINVAL; + + regmap_read(rtc->map, RTC_ALARM0_REG, &alarm_sec); + if (rtc->config->gray_stored) + alarm_sec = gray_to_binary(alarm_sec); + rtc_time64_to_tm(alarm_sec, &alarm->time); + + alarm_enable = regmap_test_bits(rtc->map, RTC_CTRL, RTC_ALRM0_EN); + alarm_mask = regmap_test_bits(rtc->map, RTC_INT_MASK, RTC_ALRM0_IRQ_MSK); + alarm->enabled = (alarm_enable && !alarm_mask) ? 1 : 0; + dev_dbg(dev, "%s: alarm->enabled=%d alarm=%us\n", __func__, + alarm->enabled, alarm_sec); + + return 0; +} + +static int aml_rtc_read_offset(struct device *dev, long *offset) +{ + struct aml_rtc_data *rtc = dev_get_drvdata(dev); + u32 reg_val; + long val; + int sign, match_counter, enable; + + /* if RTC disabled, read offset failed */ + if (!rtc->rtc_enabled) + return -EINVAL; + + regmap_read(rtc->map, RTC_SEC_ADJUST_REG, ®_val); + enable = FIELD_GET(RTC_ADJ_VALID, reg_val); + if (!enable) { + val = 0; + } else { + sign = FIELD_GET(RTC_SEC_ADJUST_CTRL, reg_val); + match_counter = FIELD_GET(RTC_MATCH_COUNTER, reg_val); + val = 1000000000 / (match_counter + 1); + if (sign == RTC_SWALLOW_SECOND) + val = -val; + } + *offset = val; + + return 0; +} + +static int aml_rtc_set_offset(struct device *dev, long offset) +{ + struct aml_rtc_data *rtc = dev_get_drvdata(dev); + int sign = 0; + int match_counter = 0; + int enable = 0; + u32 reg_val; + + /* if RTC disabled, set offset failed */ + if (!rtc->rtc_enabled) + return -EINVAL; + + if (offset) { + enable = 1; + sign = offset < 0 ? RTC_SWALLOW_SECOND : RTC_INSERT_SECOND; + match_counter = 1000000000 / abs(offset) - 1; + if (match_counter < 0 || match_counter > RTC_MATCH_COUNTER) + return -EINVAL; + } + + reg_val = FIELD_PREP(RTC_ADJ_VALID, enable) | + FIELD_PREP(RTC_SEC_ADJUST_CTRL, sign) | + FIELD_PREP(RTC_MATCH_COUNTER, match_counter); + regmap_write(rtc->map, RTC_SEC_ADJUST_REG, reg_val); + + return 0; +} + +static int aml_rtc_alarm_enable(struct device *dev, unsigned int enabled) +{ + struct aml_rtc_data *rtc = dev_get_drvdata(dev); + + if (enabled) { + regmap_update_bits(rtc->map, RTC_CTRL, + RTC_ALRM0_EN, RTC_ALRM0_EN); + regmap_update_bits(rtc->map, RTC_INT_MASK, + RTC_ALRM0_IRQ_MSK, 0); + } else { + regmap_update_bits(rtc->map, RTC_INT_MASK, + RTC_ALRM0_IRQ_MSK, RTC_ALRM0_IRQ_MSK); + regmap_update_bits(rtc->map, RTC_CTRL, + RTC_ALRM0_EN, 0); + } + + return 0; +} + +static const struct rtc_class_ops aml_rtc_ops = { + .read_time = aml_rtc_read_time, + .set_time = aml_rtc_set_time, + .read_alarm = aml_rtc_read_alarm, + .set_alarm = aml_rtc_set_alarm, + .alarm_irq_enable = aml_rtc_alarm_enable, + .read_offset = aml_rtc_read_offset, + .set_offset = aml_rtc_set_offset, +}; + +static irqreturn_t aml_rtc_handler(int irq, void *data) +{ + struct aml_rtc_data *rtc = (struct aml_rtc_data *)data; + + regmap_write(rtc->map, RTC_ALARM0_REG, 0); + regmap_write(rtc->map, RTC_INT_CLR, RTC_ALRM0_IRQ_STATUS); + + rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); + + return IRQ_HANDLED; +} + +static void aml_rtc_init(struct aml_rtc_data *rtc) +{ + u32 reg_val = 0; + + rtc->rtc_enabled = regmap_test_bits(rtc->map, RTC_CTRL, RTC_ENABLE); + if (!rtc->rtc_enabled) { + if (clk_get_rate(rtc->rtc_clk) == OSC_24M) { + /* select 24M oscillator */ + regmap_write_bits(rtc->map, RTC_CTRL, RTC_OSC_SEL, RTC_OSC_SEL); + + /* + * Set RTC oscillator to freq_out to freq_in/((N0*M0+N1*M1)/(M0+M1)) + * Enable clock_in gate of oscillator 24MHz + * Set N0 to 733, N1 to 732 + */ + reg_val = FIELD_PREP(RTC_OSCIN_IN_EN, 1) + | FIELD_PREP(RTC_OSCIN_OUT_CFG, 1) + | FIELD_PREP(RTC_OSCIN_OUT_N0M0, RTC_OSCIN_OUT_32K_N0) + | FIELD_PREP(RTC_OSCIN_OUT_N1M1, RTC_OSCIN_OUT_32K_N1); + regmap_write_bits(rtc->map, RTC_OSCIN_CTRL0, RTC_OSCIN_IN_EN + | RTC_OSCIN_OUT_CFG | RTC_OSCIN_OUT_N0M0 + | RTC_OSCIN_OUT_N1M1, reg_val); + + /* Set M0 to 2, M1 to 3, so freq_out = 32768 Hz*/ + reg_val = FIELD_PREP(RTC_OSCIN_OUT_N0M0, RTC_OSCIN_OUT_32K_M0) + | FIELD_PREP(RTC_OSCIN_OUT_N1M1, RTC_OSCIN_OUT_32K_M1); + regmap_write_bits(rtc->map, RTC_OSCIN_CTRL1, RTC_OSCIN_OUT_N0M0 + | RTC_OSCIN_OUT_N1M1, reg_val); + } else { + /* select 32K oscillator */ + regmap_write_bits(rtc->map, RTC_CTRL, RTC_OSC_SEL, 0); + } + } + regmap_write_bits(rtc->map, RTC_INT_MASK, + RTC_ALRM0_IRQ_MSK, RTC_ALRM0_IRQ_MSK); + regmap_write_bits(rtc->map, RTC_CTRL, RTC_ALRM0_EN, 0); +} + +static int aml_rtc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct aml_rtc_data *rtc; + void __iomem *base; + int ret = 0; + + rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL); + if (!rtc) + return -ENOMEM; + + rtc->config = of_device_get_match_data(dev); + if (!rtc->config) + return -ENODEV; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), "resource ioremap failed\n"); + + rtc->map = devm_regmap_init_mmio(dev, base, &aml_rtc_regmap_config); + if (IS_ERR(rtc->map)) + return dev_err_probe(dev, PTR_ERR(rtc->map), "regmap init failed\n"); + + rtc->irq = platform_get_irq(pdev, 0); + if (rtc->irq < 0) + return rtc->irq; + + rtc->rtc_clk = devm_clk_get(dev, "osc"); + if (IS_ERR(rtc->rtc_clk)) + return dev_err_probe(dev, PTR_ERR(rtc->rtc_clk), + "failed to find rtc clock\n"); + if (clk_get_rate(rtc->rtc_clk) != OSC_32K && clk_get_rate(rtc->rtc_clk) != OSC_24M) + return dev_err_probe(dev, -EINVAL, "Invalid clock configuration\n"); + + rtc->sys_clk = devm_clk_get_enabled(dev, "sys"); + if (IS_ERR(rtc->sys_clk)) + return dev_err_probe(dev, PTR_ERR(rtc->sys_clk), + "failed to get_enable rtc sys clk\n"); + aml_rtc_init(rtc); + + device_init_wakeup(dev, true); + platform_set_drvdata(pdev, rtc); + + rtc->rtc_dev = devm_rtc_allocate_device(dev); + if (IS_ERR(rtc->rtc_dev)) { + ret = PTR_ERR(rtc->rtc_dev); + goto err_clk; + } + + ret = devm_request_irq(dev, rtc->irq, aml_rtc_handler, + IRQF_ONESHOT, "aml-rtc alarm", rtc); + if (ret) { + dev_err_probe(dev, ret, "IRQ%d request failed, ret = %d\n", + rtc->irq, ret); + goto err_clk; + } + + rtc->rtc_dev->ops = &aml_rtc_ops; + rtc->rtc_dev->range_min = 0; + rtc->rtc_dev->range_max = U32_MAX; + + ret = devm_rtc_register_device(rtc->rtc_dev); + if (ret) { + dev_err_probe(&pdev->dev, ret, "Failed to register RTC device: %d\n", ret); + goto err_clk; + } + + return 0; +err_clk: + clk_disable_unprepare(rtc->sys_clk); + device_init_wakeup(dev, false); + + return ret; +} + +#ifdef CONFIG_PM_SLEEP +static int aml_rtc_suspend(struct device *dev) +{ + struct aml_rtc_data *rtc = dev_get_drvdata(dev); + + if (device_may_wakeup(dev)) + enable_irq_wake(rtc->irq); + + return 0; +} + +static int aml_rtc_resume(struct device *dev) +{ + struct aml_rtc_data *rtc = dev_get_drvdata(dev); + + if (device_may_wakeup(dev)) + disable_irq_wake(rtc->irq); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(aml_rtc_pm_ops, + aml_rtc_suspend, aml_rtc_resume); + +static void aml_rtc_remove(struct platform_device *pdev) +{ + struct aml_rtc_data *rtc = dev_get_drvdata(&pdev->dev); + + clk_disable_unprepare(rtc->sys_clk); + device_init_wakeup(&pdev->dev, false); +} + +static const struct aml_rtc_config a5_rtc_config = { +}; + +static const struct aml_rtc_config a4_rtc_config = { + .gray_stored = true, +}; + +static const struct of_device_id aml_rtc_device_id[] = { + { + .compatible = "amlogic,a4-rtc", + .data = &a4_rtc_config, + }, + { + .compatible = "amlogic,a5-rtc", + .data = &a5_rtc_config, + }, + { } +}; +MODULE_DEVICE_TABLE(of, aml_rtc_device_id); + +static struct platform_driver aml_rtc_driver = { + .probe = aml_rtc_probe, + .remove = aml_rtc_remove, + .driver = { + .name = "aml-rtc", + .pm = &aml_rtc_pm_ops, + .of_match_table = aml_rtc_device_id, + }, +}; + +module_platform_driver(aml_rtc_driver); +MODULE_DESCRIPTION("Amlogic RTC driver"); +MODULE_AUTHOR("Yiting Deng <yiting.deng@amlogic.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c index 569c1054d6b0..713fa0d077cd 100644 --- a/drivers/rtc/rtc-armada38x.c +++ b/drivers/rtc/rtc-armada38x.c @@ -527,7 +527,7 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); if (rtc->irq != -1) - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); else clear_bit(RTC_FEATURE_ALARM, rtc->rtc_dev->features); diff --git a/drivers/rtc/rtc-as3722.c b/drivers/rtc/rtc-as3722.c index 0f21af27f4cf..9682d6457b7f 100644 --- a/drivers/rtc/rtc-as3722.c +++ b/drivers/rtc/rtc-as3722.c @@ -187,7 +187,7 @@ static int as3722_rtc_probe(struct platform_device *pdev) return ret; } - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); as3722_rtc->rtc = devm_rtc_device_register(&pdev->dev, "as3722-rtc", &as3722_rtc_ops, THIS_MODULE); diff --git a/drivers/rtc/rtc-asm9260.c b/drivers/rtc/rtc-asm9260.c index a83b47e0d8f5..705470ae8428 100644 --- a/drivers/rtc/rtc-asm9260.c +++ b/drivers/rtc/rtc-asm9260.c @@ -325,7 +325,7 @@ MODULE_DEVICE_TABLE(of, asm9260_dt_ids); static struct platform_driver asm9260_rtc_driver = { .probe = asm9260_rtc_probe, - .remove_new = asm9260_rtc_remove, + .remove = asm9260_rtc_remove, .driver = { .name = "asm9260-rtc", .of_match_table = asm9260_dt_ids, diff --git a/drivers/rtc/rtc-aspeed.c b/drivers/rtc/rtc-aspeed.c index 880b015eebaf..0d0053b52f9b 100644 --- a/drivers/rtc/rtc-aspeed.c +++ b/drivers/rtc/rtc-aspeed.c @@ -8,7 +8,6 @@ #include <linux/io.h> struct aspeed_rtc { - struct rtc_device *rtc_dev; void __iomem *base; }; @@ -85,6 +84,7 @@ static const struct rtc_class_ops aspeed_rtc_ops = { static int aspeed_rtc_probe(struct platform_device *pdev) { struct aspeed_rtc *rtc; + struct rtc_device *rtc_dev; rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); if (!rtc) @@ -94,17 +94,17 @@ static int aspeed_rtc_probe(struct platform_device *pdev) if (IS_ERR(rtc->base)) return PTR_ERR(rtc->base); - rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev); - if (IS_ERR(rtc->rtc_dev)) - return PTR_ERR(rtc->rtc_dev); + rtc_dev = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc_dev)) + return PTR_ERR(rtc_dev); platform_set_drvdata(pdev, rtc); - rtc->rtc_dev->ops = &aspeed_rtc_ops; - rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900; - rtc->rtc_dev->range_max = 38814989399LL; /* 3199-12-31 23:59:59 */ + rtc_dev->ops = &aspeed_rtc_ops; + rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900; + rtc_dev->range_max = 38814989399LL; /* 3199-12-31 23:59:59 */ - return devm_rtc_register_device(rtc->rtc_dev); + return devm_rtc_register_device(rtc_dev); } static const struct of_device_id aspeed_rtc_match[] = { diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index c16fe711a0d9..f6b0102a843a 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -528,7 +528,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) * being wake-capable; if it didn't, do that here. */ if (!device_can_wakeup(&pdev->dev)) - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); if (at91_rtc_config->has_correction) rtc->ops = &sama5d4_rtc_ops; @@ -640,7 +640,7 @@ static SIMPLE_DEV_PM_OPS(at91_rtc_pm_ops, at91_rtc_suspend, at91_rtc_resume); * triggering a section mismatch warning. */ static struct platform_driver at91_rtc_driver __refdata = { - .remove_new = __exit_p(at91_rtc_remove), + .remove = __exit_p(at91_rtc_remove), .shutdown = at91_rtc_shutdown, .driver = { .name = "at91_rtc", diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index f93bee96e362..38991cca5930 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c @@ -353,7 +353,7 @@ static int at91_rtc_probe(struct platform_device *pdev) /* platform setup code should have handled this; sigh */ if (!device_can_wakeup(&pdev->dev)) - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); platform_set_drvdata(pdev, rtc); @@ -368,6 +368,7 @@ static int at91_rtc_probe(struct platform_device *pdev) return ret; rtc->gpbr = syscon_node_to_regmap(args.np); + of_node_put(args.np); rtc->gpbr_offset = args.args[0]; if (IS_ERR(rtc->gpbr)) { dev_err(&pdev->dev, "failed to retrieve gpbr regmap, aborting.\n"); @@ -529,7 +530,7 @@ MODULE_DEVICE_TABLE(of, at91_rtc_dt_ids); static struct platform_driver at91_rtc_driver = { .probe = at91_rtc_probe, - .remove_new = at91_rtc_remove, + .remove = at91_rtc_remove, .shutdown = at91_rtc_shutdown, .driver = { .name = "rtc-at91sam9", diff --git a/drivers/rtc/rtc-bd70528.c b/drivers/rtc/rtc-bd70528.c index 59b627fc1ecf..954ac4ef53e8 100644 --- a/drivers/rtc/rtc-bd70528.c +++ b/drivers/rtc/rtc-bd70528.c @@ -236,7 +236,6 @@ static int bd70528_probe(struct platform_device *pdev) { struct bd70528_rtc *bd_rtc; const struct rtc_class_ops *rtc_ops; - const char *irq_name; int ret; struct rtc_device *rtc; int irq; @@ -259,7 +258,6 @@ static int bd70528_probe(struct platform_device *pdev) switch (chip) { case ROHM_CHIP_TYPE_BD71815: - irq_name = "bd71815-rtc-alm-0"; bd_rtc->reg_time_start = BD71815_REG_RTC_START; /* @@ -276,7 +274,6 @@ static int bd70528_probe(struct platform_device *pdev) hour_reg = BD71815_REG_HOUR; break; case ROHM_CHIP_TYPE_BD71828: - irq_name = "bd71828-rtc-alm-0"; bd_rtc->reg_time_start = BD71828_REG_RTC_START; bd_rtc->bd718xx_alm_block_start = BD71828_REG_RTC_ALM_START; hour_reg = BD71828_REG_RTC_HOUR; @@ -286,7 +283,7 @@ static int bd70528_probe(struct platform_device *pdev) return -ENOENT; } - irq = platform_get_irq_byname(pdev, irq_name); + irq = platform_get_irq_byname(pdev, "bd70528-rtc-alm-0"); if (irq < 0) return irq; diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c index 591e42391747..7ad34539be4d 100644 --- a/drivers/rtc/rtc-bq32k.c +++ b/drivers/rtc/rtc-bq32k.c @@ -304,7 +304,7 @@ static void bq32k_remove(struct i2c_client *client) } static const struct i2c_device_id bq32k_id[] = { - { "bq32000", 0 }, + { "bq32000" }, { } }; MODULE_DEVICE_TABLE(i2c, bq32k_id); diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c index 1a65a4e0dc00..fb47c32ab5ff 100644 --- a/drivers/rtc/rtc-brcmstb-waketimer.c +++ b/drivers/rtc/rtc-brcmstb-waketimer.c @@ -17,7 +17,6 @@ #include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm.h> -#include <linux/pm_wakeup.h> #include <linux/reboot.h> #include <linux/rtc.h> #include <linux/stat.h> @@ -417,7 +416,7 @@ static const __maybe_unused struct of_device_id brcmstb_waketmr_of_match[] = { static struct platform_driver brcmstb_waketmr_driver = { .probe = brcmstb_waketmr_probe, - .remove_new = brcmstb_waketmr_remove, + .remove = brcmstb_waketmr_remove, .driver = { .name = "brcmstb-waketimer", .pm = &brcmstb_waketmr_pm_ops, diff --git a/drivers/rtc/rtc-cadence.c b/drivers/rtc/rtc-cadence.c index 4ca60b519836..8634eea799ab 100644 --- a/drivers/rtc/rtc-cadence.c +++ b/drivers/rtc/rtc-cadence.c @@ -359,7 +359,7 @@ static void cdns_rtc_remove(struct platform_device *pdev) struct cdns_rtc *crtc = platform_get_drvdata(pdev); cdns_rtc_alarm_irq_enable(&pdev->dev, 0); - device_init_wakeup(&pdev->dev, 0); + device_init_wakeup(&pdev->dev, false); clk_disable_unprepare(crtc->pclk); clk_disable_unprepare(crtc->ref_clk); @@ -402,7 +402,7 @@ static struct platform_driver cdns_rtc_driver = { .pm = &cdns_rtc_pm_ops, }, .probe = cdns_rtc_probe, - .remove_new = cdns_rtc_remove, + .remove = cdns_rtc_remove, }; module_platform_driver(cdns_rtc_driver); diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 7d99cd2c37a0..8172869bd3d7 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -151,11 +151,6 @@ static inline int hpet_set_periodic_freq(unsigned long freq) return 0; } -static inline int hpet_rtc_dropped_irq(void) -{ - return 0; -} - static inline int hpet_rtc_timer_init(void) { return 0; @@ -643,21 +638,19 @@ static int cmos_nvram_read(void *priv, unsigned int off, void *val, size_t count) { unsigned char *buf = val; - int retval; off += NVRAM_OFFSET; - spin_lock_irq(&rtc_lock); - for (retval = 0; count; count--, off++, retval++) { + for (; count; count--, off++, buf++) { + guard(spinlock_irq)(&rtc_lock); if (off < 128) - *buf++ = CMOS_READ(off); + *buf = CMOS_READ(off); else if (can_bank2) - *buf++ = cmos_read_bank2(off); + *buf = cmos_read_bank2(off); else - break; + return -EIO; } - spin_unlock_irq(&rtc_lock); - return retval; + return 0; } static int cmos_nvram_write(void *priv, unsigned int off, void *val, @@ -665,7 +658,6 @@ static int cmos_nvram_write(void *priv, unsigned int off, void *val, { struct cmos_rtc *cmos = priv; unsigned char *buf = val; - int retval; /* NOTE: on at least PCs and Ataris, the boot firmware uses a * checksum on part of the NVRAM data. That's currently ignored @@ -673,23 +665,23 @@ static int cmos_nvram_write(void *priv, unsigned int off, void *val, * NVRAM to update, updating checksums is also part of its job. */ off += NVRAM_OFFSET; - spin_lock_irq(&rtc_lock); - for (retval = 0; count; count--, off++, retval++) { + for (; count; count--, off++, buf++) { /* don't trash RTC registers */ if (off == cmos->day_alrm || off == cmos->mon_alrm || off == cmos->century) - buf++; - else if (off < 128) - CMOS_WRITE(*buf++, off); + continue; + + guard(spinlock_irq)(&rtc_lock); + if (off < 128) + CMOS_WRITE(*buf, off); else if (can_bank2) - cmos_write_bank2(*buf++, off); + cmos_write_bank2(*buf, off); else - break; + return -EIO; } - spin_unlock_irq(&rtc_lock); - return retval; + return 0; } /*----------------------------------------------------------------*/ @@ -867,7 +859,7 @@ static void acpi_cmos_wake_setup(struct device *dev) dev_info(dev, "RTC can wake from S4\n"); /* RTC always wakes from S1/S2/S3, and often S4/STD */ - device_init_wakeup(dev, 1); + device_init_wakeup(dev, true); } static void cmos_check_acpi_rtc_status(struct device *dev, @@ -1530,7 +1522,7 @@ static void cmos_platform_shutdown(struct platform_device *pdev) MODULE_ALIAS("platform:rtc_cmos"); static struct platform_driver cmos_platform_driver = { - .remove_new = cmos_platform_remove, + .remove = cmos_platform_remove, .shutdown = cmos_platform_shutdown, .driver = { .name = driver_name, diff --git a/drivers/rtc/rtc-cpcap.c b/drivers/rtc/rtc-cpcap.c index afc8fcba8f88..568a89e79c11 100644 --- a/drivers/rtc/rtc-cpcap.c +++ b/drivers/rtc/rtc-cpcap.c @@ -295,7 +295,7 @@ static int cpcap_rtc_probe(struct platform_device *pdev) } disable_irq(rtc->update_irq); - err = device_init_wakeup(dev, 1); + err = device_init_wakeup(dev, true); if (err) { dev_err(dev, "wakeup initialization failed (%d)\n", err); /* ignore error and continue without wakeup support */ diff --git a/drivers/rtc/rtc-cros-ec.c b/drivers/rtc/rtc-cros-ec.c index 0cd397c04ff0..e956505a06fb 100644 --- a/drivers/rtc/rtc-cros-ec.c +++ b/drivers/rtc/rtc-cros-ec.c @@ -5,6 +5,7 @@ // Author: Stephen Barber <smbarber@chromium.org> #include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/platform_data/cros_ec_commands.h> #include <linux/platform_data/cros_ec_proto.h> @@ -34,21 +35,18 @@ struct cros_ec_rtc { static int cros_ec_rtc_get(struct cros_ec_device *cros_ec, u32 command, u32 *response) { + DEFINE_RAW_FLEX(struct cros_ec_command, msg, data, + sizeof(struct ec_response_rtc)); int ret; - struct { - struct cros_ec_command msg; - struct ec_response_rtc data; - } __packed msg; - memset(&msg, 0, sizeof(msg)); - msg.msg.command = command; - msg.msg.insize = sizeof(msg.data); + msg->command = command; + msg->insize = sizeof(struct ec_response_rtc); - ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); + ret = cros_ec_cmd_xfer_status(cros_ec, msg); if (ret < 0) return ret; - *response = msg.data.time; + *response = ((struct ec_response_rtc *)msg->data)->time; return 0; } @@ -56,18 +54,15 @@ static int cros_ec_rtc_get(struct cros_ec_device *cros_ec, u32 command, static int cros_ec_rtc_set(struct cros_ec_device *cros_ec, u32 command, u32 param) { + DEFINE_RAW_FLEX(struct cros_ec_command, msg, data, + sizeof(struct ec_response_rtc)); int ret; - struct { - struct cros_ec_command msg; - struct ec_response_rtc data; - } __packed msg; - memset(&msg, 0, sizeof(msg)); - msg.msg.command = command; - msg.msg.outsize = sizeof(msg.data); - msg.data.time = param; + msg->command = command; + msg->outsize = sizeof(struct ec_response_rtc); + ((struct ec_response_rtc *)msg->data)->time = param; - ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); + ret = cros_ec_cmd_xfer_status(cros_ec, msg); if (ret < 0) return ret; return 0; @@ -336,7 +331,7 @@ static int cros_ec_rtc_probe(struct platform_device *pdev) return ret; } - ret = device_init_wakeup(&pdev->dev, 1); + ret = device_init_wakeup(&pdev->dev, true); if (ret) { dev_err(&pdev->dev, "failed to initialize wakeup\n"); return ret; @@ -392,13 +387,20 @@ static void cros_ec_rtc_remove(struct platform_device *pdev) dev_err(dev, "failed to unregister notifier\n"); } +static const struct platform_device_id cros_ec_rtc_id[] = { + { DRV_NAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(platform, cros_ec_rtc_id); + static struct platform_driver cros_ec_rtc_driver = { .probe = cros_ec_rtc_probe, - .remove_new = cros_ec_rtc_remove, + .remove = cros_ec_rtc_remove, .driver = { .name = DRV_NAME, .pm = &cros_ec_rtc_pm_ops, }, + .id_table = cros_ec_rtc_id, }; module_platform_driver(cros_ec_rtc_driver); @@ -406,4 +408,3 @@ module_platform_driver(cros_ec_rtc_driver); MODULE_DESCRIPTION("RTC driver for Chrome OS ECs"); MODULE_AUTHOR("Stephen Barber <smbarber@chromium.org>"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c index 844168fcae1e..05adec6b77bf 100644 --- a/drivers/rtc/rtc-da9055.c +++ b/drivers/rtc/rtc-da9055.c @@ -288,7 +288,7 @@ static int da9055_rtc_probe(struct platform_device *pdev) if (ret & DA9055_RTC_ALM_EN) rtc->alarm_enable = 1; - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &da9055_rtc_ops, THIS_MODULE); diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 506b7d1c2397..5efbe69bf5ca 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -65,6 +65,7 @@ enum ds_type { # define DS1340_BIT_CENTURY_EN 0x80 /* in REG_HOUR */ # define DS1340_BIT_CENTURY 0x40 /* in REG_HOUR */ #define DS1307_REG_WDAY 0x03 /* 01-07 */ +# define MCP794XX_BIT_OSCRUN BIT(5) # define MCP794XX_BIT_VBATEN 0x08 #define DS1307_REG_MDAY 0x04 /* 01-31 */ #define DS1307_REG_MONTH 0x05 /* 01-12 */ @@ -242,6 +243,10 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t) regs[DS1307_REG_MIN] & M41T0_BIT_OF) { dev_warn_once(dev, "oscillator failed, set time!\n"); return -EINVAL; + } else if (ds1307->type == mcp794xx && + !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_OSCRUN)) { + dev_warn_once(dev, "oscillator failed, set time!\n"); + return -EINVAL; } tmp = regs[DS1307_REG_SECS]; @@ -354,7 +359,7 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) regs[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1); /* assume 20YY not 19YY */ - tmp = t->tm_year - 100; + tmp = t->tm_year % 100; regs[DS1307_REG_YEAR] = bin2bcd(tmp); if (chip->century_enable_bit) @@ -1802,10 +1807,8 @@ static int ds1307_probe(struct i2c_client *client) * For some variants, be sure alarms can trigger when we're * running on Vbackup (BBSQI/BBSQW) */ - if (want_irq || ds1307_can_wakeup_device) { + if (want_irq || ds1307_can_wakeup_device) regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit; - regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); - } regmap_write(ds1307->regmap, DS1337_REG_CONTROL, regs[0]); diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index ed5a6ba89a3e..aa9500791b7e 100644 --- a/drivers/rtc/rtc-ds1343.c +++ b/drivers/rtc/rtc-ds1343.c @@ -427,18 +427,13 @@ static int ds1343_probe(struct spi_device *spi) "unable to request irq for rtc ds1343\n"); } else { device_init_wakeup(&spi->dev, true); - dev_pm_set_wake_irq(&spi->dev, spi->irq); + devm_pm_set_wake_irq(&spi->dev, spi->irq); } } return 0; } -static void ds1343_remove(struct spi_device *spi) -{ - dev_pm_clear_wake_irq(&spi->dev); -} - #ifdef CONFIG_PM_SLEEP static int ds1343_suspend(struct device *dev) @@ -471,7 +466,6 @@ static struct spi_driver ds1343_driver = { .pm = &ds1343_pm, }, .probe = ds1343_probe, - .remove = ds1343_remove, .id_table = ds1343_id, }; diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 4a5005cb23f5..c2359eb86bc9 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -52,7 +52,7 @@ #define DS1374_REG_TCR 0x09 /* Trickle Charge */ static const struct i2c_device_id ds1374_id[] = { - { "ds1374", 0 }, + { "ds1374" }, { } }; MODULE_DEVICE_TABLE(i2c, ds1374_id); diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index 641799f30baa..6e5314215d00 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c @@ -133,7 +133,7 @@ static int ds1672_probe(struct i2c_client *client) } static const struct i2c_device_id ds1672_id[] = { - { "ds1672", 0 }, + { "ds1672" }, { } }; MODULE_DEVICE_TABLE(i2c, ds1672_id); diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 04dbf35cf3b7..38e25f63597a 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -1354,7 +1354,7 @@ static struct platform_driver ds1685_rtc_driver = { .name = "rtc-ds1685", }, .probe = ds1685_rtc_probe, - .remove_new = ds1685_rtc_remove, + .remove = ds1685_rtc_remove, }; module_platform_driver(ds1685_rtc_driver); /* ----------------------------------------------------------------------- */ diff --git a/drivers/rtc/rtc-ds2404.c b/drivers/rtc/rtc-ds2404.c index 3231fd9f61da..217694eca36c 100644 --- a/drivers/rtc/rtc-ds2404.c +++ b/drivers/rtc/rtc-ds2404.c @@ -31,7 +31,6 @@ struct ds2404 { struct gpio_desc *rst_gpiod; struct gpio_desc *clk_gpiod; struct gpio_desc *dq_gpiod; - struct rtc_device *rtc; }; static int ds2404_gpio_map(struct ds2404 *chip, struct platform_device *pdev) @@ -182,6 +181,7 @@ static const struct rtc_class_ops ds2404_rtc_ops = { static int rtc_probe(struct platform_device *pdev) { struct ds2404 *chip; + struct rtc_device *rtc; int retval = -EBUSY; chip = devm_kzalloc(&pdev->dev, sizeof(struct ds2404), GFP_KERNEL); @@ -190,9 +190,9 @@ static int rtc_probe(struct platform_device *pdev) chip->dev = &pdev->dev; - chip->rtc = devm_rtc_allocate_device(&pdev->dev); - if (IS_ERR(chip->rtc)) - return PTR_ERR(chip->rtc); + rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); retval = ds2404_gpio_map(chip, pdev); if (retval) @@ -200,10 +200,10 @@ static int rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, chip); - chip->rtc->ops = &ds2404_rtc_ops; - chip->rtc->range_max = U32_MAX; + rtc->ops = &ds2404_rtc_ops; + rtc->range_max = U32_MAX; - retval = devm_rtc_register_device(chip->rtc); + retval = devm_rtc_register_device(rtc); if (retval) return retval; diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index 1485a6ae51e6..18f35823b4b5 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -339,29 +339,9 @@ static int ds3232_hwmon_read(struct device *dev, return err; } -static u32 ds3232_hwmon_chip_config[] = { - HWMON_C_REGISTER_TZ, - 0 -}; - -static const struct hwmon_channel_info ds3232_hwmon_chip = { - .type = hwmon_chip, - .config = ds3232_hwmon_chip_config, -}; - -static u32 ds3232_hwmon_temp_config[] = { - HWMON_T_INPUT, - 0 -}; - -static const struct hwmon_channel_info ds3232_hwmon_temp = { - .type = hwmon_temp, - .config = ds3232_hwmon_temp_config, -}; - static const struct hwmon_channel_info * const ds3232_hwmon_info[] = { - &ds3232_hwmon_chip, - &ds3232_hwmon_temp, + HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), NULL }; @@ -508,7 +488,7 @@ static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq, return ret; if (ds3232->irq > 0) - device_init_wakeup(dev, 1); + device_init_wakeup(dev, true); ds3232_hwmon_register(dev, name); @@ -586,7 +566,7 @@ static int ds3232_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id ds3232_id[] = { - { "ds3232", 0 }, + { "ds3232" }, { } }; MODULE_DEVICE_TABLE(i2c, ds3232_id); diff --git a/drivers/rtc/rtc-em3027.c b/drivers/rtc/rtc-em3027.c index fc772eae5da5..dc1ccbc65dcb 100644 --- a/drivers/rtc/rtc-em3027.c +++ b/drivers/rtc/rtc-em3027.c @@ -129,7 +129,7 @@ static int em3027_probe(struct i2c_client *client) } static const struct i2c_device_id em3027_id[] = { - { "em3027", 0 }, + { "em3027" }, { } }; MODULE_DEVICE_TABLE(i2c, em3027_id); diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index 1fdd20d01560..dcdcdd06f30d 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c @@ -28,7 +28,6 @@ struct ep93xx_rtc { void __iomem *mmio_base; - struct rtc_device *rtc; }; static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload, @@ -123,6 +122,7 @@ static const struct attribute_group ep93xx_rtc_sysfs_files = { static int ep93xx_rtc_probe(struct platform_device *pdev) { struct ep93xx_rtc *ep93xx_rtc; + struct rtc_device *rtc; int err; ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL); @@ -135,18 +135,18 @@ static int ep93xx_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ep93xx_rtc); - ep93xx_rtc->rtc = devm_rtc_allocate_device(&pdev->dev); - if (IS_ERR(ep93xx_rtc->rtc)) - return PTR_ERR(ep93xx_rtc->rtc); + rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); - ep93xx_rtc->rtc->ops = &ep93xx_rtc_ops; - ep93xx_rtc->rtc->range_max = U32_MAX; + rtc->ops = &ep93xx_rtc_ops; + rtc->range_max = U32_MAX; - err = rtc_add_group(ep93xx_rtc->rtc, &ep93xx_rtc_sysfs_files); + err = rtc_add_group(rtc, &ep93xx_rtc_sysfs_files); if (err) return err; - return devm_rtc_register_device(ep93xx_rtc->rtc); + return devm_rtc_register_device(rtc); } static const struct of_device_id ep93xx_rtc_of_ids[] = { diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index 400ce4ad0c49..f82728ebac0c 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c @@ -53,7 +53,7 @@ struct fm3130 { int data_valid; }; static const struct i2c_device_id fm3130_id[] = { - { "fm3130", 0 }, + { "fm3130" }, { } }; MODULE_DEVICE_TABLE(i2c, fm3130_id); diff --git a/drivers/rtc/rtc-fsl-ftm-alarm.c b/drivers/rtc/rtc-fsl-ftm-alarm.c index a72c4ad0cec6..c8015f04c71f 100644 --- a/drivers/rtc/rtc-fsl-ftm-alarm.c +++ b/drivers/rtc/rtc-fsl-ftm-alarm.c @@ -309,7 +309,7 @@ static const struct of_device_id ftm_rtc_match[] = { }; MODULE_DEVICE_TABLE(of, ftm_rtc_match); -static const struct acpi_device_id ftm_imx_acpi_ids[] = { +static const struct acpi_device_id ftm_imx_acpi_ids[] __maybe_unused = { {"NXP0014",}, { } }; diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c index 8bfe7378f653..02608d378495 100644 --- a/drivers/rtc/rtc-ftrtc010.c +++ b/drivers/rtc/rtc-ftrtc010.c @@ -28,7 +28,6 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRV_NAME); struct ftrtc010_rtc { - struct rtc_device *rtc_dev; void __iomem *rtc_base; int rtc_irq; struct clk *pclk; @@ -113,6 +112,7 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev) struct ftrtc010_rtc *rtc; struct device *dev = &pdev->dev; struct resource *res; + struct rtc_device *rtc_dev; int ret; rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); @@ -160,29 +160,28 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev) goto err_disable_extclk; } - rtc->rtc_dev = devm_rtc_allocate_device(dev); - if (IS_ERR(rtc->rtc_dev)) { - ret = PTR_ERR(rtc->rtc_dev); + rtc_dev = devm_rtc_allocate_device(dev); + if (IS_ERR(rtc_dev)) { + ret = PTR_ERR(rtc_dev); goto err_disable_extclk; } - rtc->rtc_dev->ops = &ftrtc010_rtc_ops; + rtc_dev->ops = &ftrtc010_rtc_ops; sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND); min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE); hour = readl(rtc->rtc_base + FTRTC010_RTC_HOUR); days = readl(rtc->rtc_base + FTRTC010_RTC_DAYS); - rtc->rtc_dev->range_min = (u64)days * 86400 + hour * 3600 + - min * 60 + sec; - rtc->rtc_dev->range_max = U32_MAX + rtc->rtc_dev->range_min; + rtc_dev->range_min = (u64)days * 86400 + hour * 3600 + min * 60 + sec; + rtc_dev->range_max = U32_MAX + rtc_dev->range_min; ret = devm_request_irq(dev, rtc->rtc_irq, ftrtc010_rtc_interrupt, IRQF_SHARED, pdev->name, dev); if (unlikely(ret)) goto err_disable_extclk; - return devm_rtc_register_device(rtc->rtc_dev); + return devm_rtc_register_device(rtc_dev); err_disable_extclk: clk_disable_unprepare(rtc->extclk); @@ -214,7 +213,7 @@ static struct platform_driver ftrtc010_rtc_driver = { .of_match_table = ftrtc010_rtc_dt_match, }, .probe = ftrtc010_rtc_probe, - .remove_new = ftrtc010_rtc_remove, + .remove = ftrtc010_rtc_remove, }; module_platform_driver_probe(ftrtc010_rtc_driver, ftrtc010_rtc_probe); diff --git a/drivers/rtc/rtc-goldfish.c b/drivers/rtc/rtc-goldfish.c index 59c0f38cc08d..53ec7173c28e 100644 --- a/drivers/rtc/rtc-goldfish.c +++ b/drivers/rtc/rtc-goldfish.c @@ -203,4 +203,5 @@ static struct platform_driver goldfish_rtc = { module_platform_driver(goldfish_rtc); +MODULE_DESCRIPTION("Android Goldfish Real Time Clock driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c index b81cea505ee9..6228d0b2486e 100644 --- a/drivers/rtc/rtc-hid-sensor-time.c +++ b/drivers/rtc/rtc-hid-sensor-time.c @@ -319,11 +319,11 @@ static struct platform_driver hid_time_platform_driver = { .name = KBUILD_MODNAME, }, .probe = hid_time_probe, - .remove_new = hid_time_remove, + .remove = hid_time_remove, }; module_platform_driver(hid_time_platform_driver); MODULE_DESCRIPTION("HID Sensor Time"); MODULE_AUTHOR("Alexander Holler <holler@ahsoftware.de>"); MODULE_LICENSE("GPL"); -MODULE_IMPORT_NS(IIO_HID); +MODULE_IMPORT_NS("IIO_HID"); diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c index b018535c842b..63f11ea3589d 100644 --- a/drivers/rtc/rtc-hym8563.c +++ b/drivers/rtc/rtc-hym8563.c @@ -559,8 +559,8 @@ static int hym8563_probe(struct i2c_client *client) } static const struct i2c_device_id hym8563_id[] = { - { "hym8563", 0 }, - {}, + { "hym8563" }, + {} }; MODULE_DEVICE_TABLE(i2c, hym8563_id); diff --git a/drivers/rtc/rtc-imx-sm-bbm.c b/drivers/rtc/rtc-imx-sm-bbm.c new file mode 100644 index 000000000000..daa472be7c80 --- /dev/null +++ b/drivers/rtc/rtc-imx-sm-bbm.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP. + */ + +#include <linux/jiffies.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> +#include <linux/scmi_protocol.h> +#include <linux/scmi_imx_protocol.h> + +struct scmi_imx_bbm { + const struct scmi_imx_bbm_proto_ops *ops; + struct rtc_device *rtc_dev; + struct scmi_protocol_handle *ph; + struct notifier_block nb; +}; + +static int scmi_imx_bbm_read_time(struct device *dev, struct rtc_time *tm) +{ + struct scmi_imx_bbm *bbnsm = dev_get_drvdata(dev); + struct scmi_protocol_handle *ph = bbnsm->ph; + u64 val; + int ret; + + ret = bbnsm->ops->rtc_time_get(ph, 0, &val); + if (ret) + return ret; + + rtc_time64_to_tm(val, tm); + + return 0; +} + +static int scmi_imx_bbm_set_time(struct device *dev, struct rtc_time *tm) +{ + struct scmi_imx_bbm *bbnsm = dev_get_drvdata(dev); + struct scmi_protocol_handle *ph = bbnsm->ph; + u64 val; + + val = rtc_tm_to_time64(tm); + + return bbnsm->ops->rtc_time_set(ph, 0, val); +} + +static int scmi_imx_bbm_alarm_irq_enable(struct device *dev, unsigned int enable) +{ + struct scmi_imx_bbm *bbnsm = dev_get_drvdata(dev); + struct scmi_protocol_handle *ph = bbnsm->ph; + + /* scmi_imx_bbm_set_alarm enables the irq, just handle disable here */ + if (!enable) + return bbnsm->ops->rtc_alarm_set(ph, 0, false, 0); + + return 0; +} + +static int scmi_imx_bbm_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct scmi_imx_bbm *bbnsm = dev_get_drvdata(dev); + struct scmi_protocol_handle *ph = bbnsm->ph; + struct rtc_time *alrm_tm = &alrm->time; + u64 val; + + val = rtc_tm_to_time64(alrm_tm); + + return bbnsm->ops->rtc_alarm_set(ph, 0, true, val); +} + +static const struct rtc_class_ops smci_imx_bbm_rtc_ops = { + .read_time = scmi_imx_bbm_read_time, + .set_time = scmi_imx_bbm_set_time, + .set_alarm = scmi_imx_bbm_set_alarm, + .alarm_irq_enable = scmi_imx_bbm_alarm_irq_enable, +}; + +static int scmi_imx_bbm_rtc_notifier(struct notifier_block *nb, unsigned long event, void *data) +{ + struct scmi_imx_bbm *bbnsm = container_of(nb, struct scmi_imx_bbm, nb); + struct scmi_imx_bbm_notif_report *r = data; + + if (r->is_rtc) + rtc_update_irq(bbnsm->rtc_dev, 1, RTC_AF | RTC_IRQF); + else + pr_err("Unexpected bbm event: %s\n", __func__); + + return 0; +} + +static int scmi_imx_bbm_rtc_init(struct scmi_device *sdev) +{ + const struct scmi_handle *handle = sdev->handle; + struct device *dev = &sdev->dev; + struct scmi_imx_bbm *bbnsm = dev_get_drvdata(dev); + int ret; + + bbnsm->rtc_dev = devm_rtc_allocate_device(dev); + if (IS_ERR(bbnsm->rtc_dev)) + return PTR_ERR(bbnsm->rtc_dev); + + bbnsm->rtc_dev->ops = &smci_imx_bbm_rtc_ops; + bbnsm->rtc_dev->range_max = U32_MAX; + + bbnsm->nb.notifier_call = &scmi_imx_bbm_rtc_notifier; + ret = handle->notify_ops->devm_event_notifier_register(sdev, SCMI_PROTOCOL_IMX_BBM, + SCMI_EVENT_IMX_BBM_RTC, + NULL, &bbnsm->nb); + if (ret) + return ret; + + return devm_rtc_register_device(bbnsm->rtc_dev); +} + +static int scmi_imx_bbm_rtc_probe(struct scmi_device *sdev) +{ + const struct scmi_handle *handle = sdev->handle; + struct device *dev = &sdev->dev; + struct scmi_protocol_handle *ph; + struct scmi_imx_bbm *bbnsm; + int ret; + + if (!handle) + return -ENODEV; + + bbnsm = devm_kzalloc(dev, sizeof(*bbnsm), GFP_KERNEL); + if (!bbnsm) + return -ENOMEM; + + bbnsm->ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_IMX_BBM, &ph); + if (IS_ERR(bbnsm->ops)) + return PTR_ERR(bbnsm->ops); + + bbnsm->ph = ph; + + device_init_wakeup(dev, true); + + dev_set_drvdata(dev, bbnsm); + + ret = scmi_imx_bbm_rtc_init(sdev); + if (ret) + device_init_wakeup(dev, false); + + return ret; +} + +static const struct scmi_device_id scmi_id_table[] = { + { SCMI_PROTOCOL_IMX_BBM, "imx-bbm-rtc" }, + { }, +}; +MODULE_DEVICE_TABLE(scmi, scmi_id_table); + +static struct scmi_driver scmi_imx_bbm_rtc_driver = { + .name = "scmi-imx-bbm-rtc", + .probe = scmi_imx_bbm_rtc_probe, + .id_table = scmi_id_table, +}; +module_scmi_driver(scmi_imx_bbm_rtc_driver); + +MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>"); +MODULE_DESCRIPTION("IMX SM BBM RTC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 284011c419db..ca4a0af95e8c 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -860,7 +860,7 @@ static struct platform_driver dryice_rtc_driver __refdata = { .name = "imxdi_rtc", .of_match_table = dryice_dt_ids, }, - .remove_new = __exit_p(dryice_rtc_remove), + .remove = __exit_p(dryice_rtc_remove), }; module_platform_driver_probe(dryice_rtc_driver, dryice_rtc_probe); diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index 4eef7afcc8bc..9b44839a7402 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c @@ -21,7 +21,7 @@ #include <asm/byteorder.h> -/* ISL register offsets */ +/* RTC - Real time clock registers */ #define ISL12022_REG_SC 0x00 #define ISL12022_REG_MN 0x01 #define ISL12022_REG_HR 0x02 @@ -30,21 +30,36 @@ #define ISL12022_REG_YR 0x05 #define ISL12022_REG_DW 0x06 +/* CSR - Control and status registers */ #define ISL12022_REG_SR 0x07 #define ISL12022_REG_INT 0x08 - #define ISL12022_REG_PWR_VBAT 0x0a - #define ISL12022_REG_BETA 0x0d + +/* ALARM - Alarm registers */ +#define ISL12022_REG_SCA0 0x10 +#define ISL12022_REG_MNA0 0x11 +#define ISL12022_REG_HRA0 0x12 +#define ISL12022_REG_DTA0 0x13 +#define ISL12022_REG_MOA0 0x14 +#define ISL12022_REG_DWA0 0x15 +#define ISL12022_ALARM ISL12022_REG_SCA0 +#define ISL12022_ALARM_LEN (ISL12022_REG_DWA0 - ISL12022_REG_SCA0 + 1) + +/* TEMP - Temperature sensor registers */ #define ISL12022_REG_TEMP_L 0x28 /* ISL register bits */ #define ISL12022_HR_MIL (1 << 7) /* military or 24 hour time */ +#define ISL12022_SR_ALM (1 << 4) #define ISL12022_SR_LBAT85 (1 << 2) #define ISL12022_SR_LBAT75 (1 << 1) +#define ISL12022_INT_ARST (1 << 7) #define ISL12022_INT_WRTC (1 << 6) +#define ISL12022_INT_IM (1 << 5) +#define ISL12022_INT_FOBATB (1 << 4) #define ISL12022_INT_FO_MASK GENMASK(3, 0) #define ISL12022_INT_FO_OFF 0x0 #define ISL12022_INT_FO_32K 0x1 @@ -52,8 +67,19 @@ #define ISL12022_REG_VB85_MASK GENMASK(5, 3) #define ISL12022_REG_VB75_MASK GENMASK(2, 0) +#define ISL12022_ALARM_ENABLE (1 << 7) /* for all ALARM registers */ + #define ISL12022_BETA_TSE (1 << 7) +static struct i2c_driver isl12022_driver; + +struct isl12022 { + struct rtc_device *rtc; + struct regmap *regmap; + int irq; + bool irq_enabled; +}; + static umode_t isl12022_hwmon_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel) @@ -116,7 +142,8 @@ static const struct hwmon_chip_info isl12022_hwmon_chip_info = { static void isl12022_hwmon_register(struct device *dev) { - struct regmap *regmap = dev_get_drvdata(dev); + struct isl12022 *isl12022 = dev_get_drvdata(dev); + struct regmap *regmap = isl12022->regmap; struct device *hwmon; int ret; @@ -143,8 +170,9 @@ static void isl12022_hwmon_register(struct device *dev) */ static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm) { - struct regmap *regmap = dev_get_drvdata(dev); - uint8_t buf[ISL12022_REG_INT + 1]; + struct isl12022 *isl12022 = dev_get_drvdata(dev); + struct regmap *regmap = isl12022->regmap; + u8 buf[ISL12022_REG_INT + 1]; int ret; ret = regmap_bulk_read(regmap, ISL12022_REG_SC, buf, sizeof(buf)); @@ -178,9 +206,10 @@ static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm) static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm) { - struct regmap *regmap = dev_get_drvdata(dev); + struct isl12022 *isl12022 = dev_get_drvdata(dev); + struct regmap *regmap = isl12022->regmap; int ret; - uint8_t buf[ISL12022_REG_DW + 1]; + u8 buf[ISL12022_REG_DW + 1]; dev_dbg(dev, "%s: %ptR\n", __func__, tm); @@ -208,9 +237,198 @@ static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm) return regmap_bulk_write(regmap, ISL12022_REG_SC, buf, sizeof(buf)); } +static int isl12022_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct rtc_time *tm = &alarm->time; + struct isl12022 *isl12022 = dev_get_drvdata(dev); + struct regmap *regmap = isl12022->regmap; + u8 buf[ISL12022_ALARM_LEN]; + unsigned int i, yr; + int ret; + + ret = regmap_bulk_read(regmap, ISL12022_ALARM, buf, sizeof(buf)); + if (ret) { + dev_dbg(dev, "%s: reading ALARM registers failed\n", + __func__); + return ret; + } + + /* The alarm doesn't store the year so get it from the rtc section */ + ret = regmap_read(regmap, ISL12022_REG_YR, &yr); + if (ret) { + dev_dbg(dev, "%s: reading YR register failed\n", __func__); + return ret; + } + + dev_dbg(dev, + "%s: sc=%02x, mn=%02x, hr=%02x, dt=%02x, mo=%02x, dw=%02x yr=%u\n", + __func__, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], yr); + + tm->tm_sec = bcd2bin(buf[ISL12022_REG_SCA0 - ISL12022_ALARM] & 0x7F); + tm->tm_min = bcd2bin(buf[ISL12022_REG_MNA0 - ISL12022_ALARM] & 0x7F); + tm->tm_hour = bcd2bin(buf[ISL12022_REG_HRA0 - ISL12022_ALARM] & 0x3F); + tm->tm_mday = bcd2bin(buf[ISL12022_REG_DTA0 - ISL12022_ALARM] & 0x3F); + tm->tm_mon = bcd2bin(buf[ISL12022_REG_MOA0 - ISL12022_ALARM] & 0x1F) - 1; + tm->tm_wday = buf[ISL12022_REG_DWA0 - ISL12022_ALARM] & 0x07; + tm->tm_year = bcd2bin(yr) + 100; + + for (i = 0; i < ISL12022_ALARM_LEN; i++) { + if (buf[i] & ISL12022_ALARM_ENABLE) { + alarm->enabled = 1; + break; + } + } + + dev_dbg(dev, "%s: %ptR\n", __func__, tm); + + return 0; +} + +static int isl12022_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct rtc_time *alarm_tm = &alarm->time; + struct isl12022 *isl12022 = dev_get_drvdata(dev); + struct regmap *regmap = isl12022->regmap; + u8 regs[ISL12022_ALARM_LEN] = { 0, }; + struct rtc_time rtc_tm; + int ret, enable, dw; + + ret = isl12022_rtc_read_time(dev, &rtc_tm); + if (ret) + return ret; + + /* If the alarm time is before the current time disable the alarm */ + if (!alarm->enabled || rtc_tm_sub(alarm_tm, &rtc_tm) <= 0) + enable = 0; + else + enable = ISL12022_ALARM_ENABLE; + + /* + * Set non-matching day of the week to safeguard against early false + * matching while setting all the alarm registers (this rtc lacks a + * general alarm/irq enable/disable bit). + */ + ret = regmap_read(regmap, ISL12022_REG_DW, &dw); + if (ret) { + dev_dbg(dev, "%s: reading DW failed\n", __func__); + return ret; + } + /* ~4 days into the future should be enough to avoid match */ + dw = ((dw + 4) % 7) | ISL12022_ALARM_ENABLE; + ret = regmap_write(regmap, ISL12022_REG_DWA0, dw); + if (ret) { + dev_dbg(dev, "%s: writing DWA0 failed\n", __func__); + return ret; + } + + /* Program the alarm and enable it for each setting */ + regs[ISL12022_REG_SCA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_sec) | enable; + regs[ISL12022_REG_MNA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_min) | enable; + regs[ISL12022_REG_HRA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_hour) | enable; + regs[ISL12022_REG_DTA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_mday) | enable; + regs[ISL12022_REG_MOA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_mon + 1) | enable; + regs[ISL12022_REG_DWA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_wday & 7) | enable; + + /* write ALARM registers */ + ret = regmap_bulk_write(regmap, ISL12022_ALARM, ®s, sizeof(regs)); + if (ret) { + dev_dbg(dev, "%s: writing ALARM registers failed\n", __func__); + return ret; + } + + return 0; +} + +static irqreturn_t isl12022_rtc_interrupt(int irq, void *data) +{ + struct isl12022 *isl12022 = data; + struct rtc_device *rtc = isl12022->rtc; + struct device *dev = &rtc->dev; + struct regmap *regmap = isl12022->regmap; + u32 val = 0; + unsigned long events = 0; + int ret; + + ret = regmap_read(regmap, ISL12022_REG_SR, &val); + if (ret) { + dev_dbg(dev, "%s: reading SR failed\n", __func__); + return IRQ_HANDLED; + } + + if (val & ISL12022_SR_ALM) + events |= RTC_IRQF | RTC_AF; + + if (events & RTC_AF) + dev_dbg(dev, "alarm!\n"); + + if (!events) + return IRQ_NONE; + + rtc_update_irq(rtc, 1, events); + return IRQ_HANDLED; +} + +static int isl12022_rtc_alarm_irq_enable(struct device *dev, + unsigned int enabled) +{ + struct isl12022 *isl12022 = dev_get_drvdata(dev); + + /* Make sure enabled is 0 or 1 */ + enabled = !!enabled; + + if (isl12022->irq_enabled == enabled) + return 0; + + if (enabled) + enable_irq(isl12022->irq); + else + disable_irq(isl12022->irq); + + isl12022->irq_enabled = enabled; + + return 0; +} + +static int isl12022_setup_irq(struct device *dev, int irq) +{ + struct isl12022 *isl12022 = dev_get_drvdata(dev); + struct regmap *regmap = isl12022->regmap; + unsigned int reg_mask, reg_val; + u8 buf[ISL12022_ALARM_LEN] = { 0, }; + int ret; + + /* Clear and disable all alarm registers */ + ret = regmap_bulk_write(regmap, ISL12022_ALARM, buf, sizeof(buf)); + if (ret) + return ret; + + /* + * Enable automatic reset of ALM bit and enable single event interrupt + * mode. + */ + reg_mask = ISL12022_INT_ARST | ISL12022_INT_IM | ISL12022_INT_FO_MASK; + reg_val = ISL12022_INT_ARST | ISL12022_INT_FO_OFF; + ret = regmap_write_bits(regmap, ISL12022_REG_INT, + reg_mask, reg_val); + if (ret) + return ret; + + ret = devm_request_threaded_irq(dev, irq, NULL, + isl12022_rtc_interrupt, + IRQF_SHARED | IRQF_ONESHOT, + isl12022_driver.driver.name, + isl12022); + if (ret) + return dev_err_probe(dev, ret, "Unable to request irq %d\n", irq); + + isl12022->irq = irq; + return 0; +} + static int isl12022_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { - struct regmap *regmap = dev_get_drvdata(dev); + struct isl12022 *isl12022 = dev_get_drvdata(dev); + struct regmap *regmap = isl12022->regmap; u32 user, val; int ret; @@ -238,6 +456,9 @@ static const struct rtc_class_ops isl12022_rtc_ops = { .ioctl = isl12022_rtc_ioctl, .read_time = isl12022_rtc_read_time, .set_time = isl12022_rtc_set_time, + .read_alarm = isl12022_rtc_read_alarm, + .set_alarm = isl12022_rtc_set_alarm, + .alarm_irq_enable = isl12022_rtc_alarm_irq_enable, }; static const struct regmap_config regmap_config = { @@ -248,7 +469,8 @@ static const struct regmap_config regmap_config = { static int isl12022_register_clock(struct device *dev) { - struct regmap *regmap = dev_get_drvdata(dev); + struct isl12022 *isl12022 = dev_get_drvdata(dev); + struct regmap *regmap = isl12022->regmap; struct clk_hw *hw; int ret; @@ -288,7 +510,8 @@ static const u32 trip_levels[2][7] = { static void isl12022_set_trip_levels(struct device *dev) { - struct regmap *regmap = dev_get_drvdata(dev); + struct isl12022 *isl12022 = dev_get_drvdata(dev); + struct regmap *regmap = isl12022->regmap; u32 levels[2] = {0, 0}; int ret, i, j, x[2]; u8 val, mask; @@ -325,6 +548,7 @@ static void isl12022_set_trip_levels(struct device *dev) static int isl12022_probe(struct i2c_client *client) { + struct isl12022 *isl12022; struct rtc_device *rtc; struct regmap *regmap; int ret; @@ -332,13 +556,17 @@ static int isl12022_probe(struct i2c_client *client) if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; + /* Allocate driver state */ + isl12022 = devm_kzalloc(&client->dev, sizeof(*isl12022), GFP_KERNEL); + if (!isl12022) + return -ENOMEM; + regmap = devm_regmap_init_i2c(client, ®map_config); - if (IS_ERR(regmap)) { - dev_err(&client->dev, "regmap allocation failed\n"); - return PTR_ERR(regmap); - } + if (IS_ERR(regmap)) + return dev_err_probe(&client->dev, PTR_ERR(regmap), "regmap allocation failed\n"); + isl12022->regmap = regmap; - dev_set_drvdata(&client->dev, regmap); + dev_set_drvdata(&client->dev, isl12022); ret = isl12022_register_clock(&client->dev); if (ret) @@ -350,11 +578,20 @@ static int isl12022_probe(struct i2c_client *client) rtc = devm_rtc_allocate_device(&client->dev); if (IS_ERR(rtc)) return PTR_ERR(rtc); + isl12022->rtc = rtc; rtc->ops = &isl12022_rtc_ops; rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; rtc->range_max = RTC_TIMESTAMP_END_2099; + if (client->irq > 0) { + ret = isl12022_setup_irq(&client->dev, client->irq); + if (ret) + return ret; + } else { + clear_bit(RTC_FEATURE_ALARM, rtc->features); + } + return devm_rtc_register_device(rtc); } @@ -366,7 +603,7 @@ static const struct of_device_id isl12022_dt_match[] = { MODULE_DEVICE_TABLE(of, isl12022_dt_match); static const struct i2c_device_id isl12022_id[] = { - { "isl12022", 0 }, + { "isl12022" }, { } }; MODULE_DEVICE_TABLE(i2c, isl12022_id); diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index e50c23ee1646..f71a6bb77b2a 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -7,6 +7,7 @@ #include <linux/bcd.h> #include <linux/clk.h> +#include <linux/delay.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/of.h> @@ -628,6 +629,18 @@ isl1208_rtc_interrupt(int irq, void *data) struct isl1208_state *isl1208 = i2c_get_clientdata(client); int handled = 0, sr, err; + if (!isl1208->config->has_tamper) { + /* + * The INT# output is pulled low 250ms after the alarm is + * triggered. After the INT# output is pulled low, it is low for + * at least 250ms, even if the correct action is taken to clear + * it. It is impossible to clear ALM if it is still active. The + * host must wait for the RTC to progress past the alarm time + * plus the 250ms delay before clearing ALM. + */ + msleep(250); + } + /* * I2C reads get NAK'ed if we read straight away after an interrupt? * Using a mdelay/msleep didn't seem to help either, so we work around @@ -650,6 +663,13 @@ isl1208_rtc_interrupt(int irq, void *data) rtc_update_irq(isl1208->rtc, 1, RTC_IRQF | RTC_AF); + /* Disable the alarm */ + err = isl1208_rtc_toggle_alarm(client, 0); + if (err) + return err; + + fsleep(275); + /* Clear the alarm */ sr &= ~ISL1208_REG_SR_ALM; sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr); @@ -658,11 +678,6 @@ isl1208_rtc_interrupt(int irq, void *data) __func__); else handled = 1; - - /* Disable the alarm */ - err = isl1208_rtc_toggle_alarm(client, 0); - if (err) - return err; } if (isl1208->config->has_tamper && (sr & ISL1208_REG_SR_EVT)) { @@ -775,14 +790,13 @@ static int isl1208_nvmem_read(void *priv, unsigned int off, void *buf, { struct isl1208_state *isl1208 = priv; struct i2c_client *client = to_i2c_client(isl1208->rtc->dev.parent); - int ret; /* nvmem sanitizes offset/count for us, but count==0 is possible */ if (!count) return count; - ret = isl1208_i2c_read_regs(client, ISL1208_REG_USR1 + off, buf, + + return isl1208_i2c_read_regs(client, ISL1208_REG_USR1 + off, buf, count); - return ret == 0 ? count : ret; } static int isl1208_nvmem_write(void *priv, unsigned int off, void *buf, @@ -790,15 +804,13 @@ static int isl1208_nvmem_write(void *priv, unsigned int off, void *buf, { struct isl1208_state *isl1208 = priv; struct i2c_client *client = to_i2c_client(isl1208->rtc->dev.parent); - int ret; /* nvmem sanitizes off/count for us, but count==0 is possible */ if (!count) return count; - ret = isl1208_i2c_set_regs(client, ISL1208_REG_USR1 + off, buf, - count); - return ret == 0 ? count : ret; + return isl1208_i2c_set_regs(client, ISL1208_REG_USR1 + off, buf, + count); } static const struct nvmem_config isl1208_nvmem_config = { @@ -818,7 +830,7 @@ static int isl1208_setup_irq(struct i2c_client *client, int irq) isl1208_driver.driver.name, client); if (!rc) { - device_init_wakeup(&client->dev, 1); + device_init_wakeup(&client->dev, true); enable_irq_wake(irq); } else { dev_err(&client->dev, diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c index bafa7d1b9b88..44bba356268c 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c @@ -367,7 +367,7 @@ static int jz4740_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); - device_init_wakeup(dev, 1); + device_init_wakeup(dev, true); ret = dev_pm_set_wake_irq(dev, irq); if (ret) diff --git a/drivers/rtc/rtc-loongson.c b/drivers/rtc/rtc-loongson.c index e8ffc1ab90b0..97e5625c064c 100644 --- a/drivers/rtc/rtc-loongson.c +++ b/drivers/rtc/rtc-loongson.c @@ -114,6 +114,13 @@ static irqreturn_t loongson_rtc_isr(int irq, void *id) struct loongson_rtc_priv *priv = (struct loongson_rtc_priv *)id; rtc_update_irq(priv->rtcdev, 1, RTC_AF | RTC_IRQF); + + /* + * The TOY_MATCH0_REG should be cleared 0 here, + * otherwise the interrupt cannot be cleared. + */ + regmap_write(priv->regmap, TOY_MATCH0_REG, 0); + return IRQ_HANDLED; } @@ -131,11 +138,7 @@ static u32 loongson_rtc_handler(void *id) writel(RTC_STS, priv->pm_base + PM1_STS_REG); spin_unlock(&priv->lock); - /* - * The TOY_MATCH0_REG should be cleared 0 here, - * otherwise the interrupt cannot be cleared. - */ - return regmap_write(priv->regmap, TOY_MATCH0_REG, 0); + return ACPI_INTERRUPT_HANDLED; } static int loongson_rtc_set_enabled(struct device *dev) @@ -329,7 +332,7 @@ static int loongson_rtc_probe(struct platform_device *pdev) alarm_irq); priv->pm_base = regs - priv->config->pm_offset; - device_init_wakeup(dev, 1); + device_init_wakeup(dev, true); if (has_acpi_companion(dev)) acpi_install_fixed_event_handler(ACPI_EVENT_RTC, @@ -360,7 +363,7 @@ static void loongson_rtc_remove(struct platform_device *pdev) acpi_remove_fixed_event_handler(ACPI_EVENT_RTC, loongson_rtc_handler); - device_init_wakeup(dev, 0); + device_init_wakeup(dev, false); loongson_rtc_alarm_irq_enable(dev, 0); } @@ -381,7 +384,7 @@ MODULE_DEVICE_TABLE(acpi, loongson_rtc_acpi_match); static struct platform_driver loongson_rtc_driver = { .probe = loongson_rtc_probe, - .remove_new = loongson_rtc_remove, + .remove = loongson_rtc_remove, .driver = { .name = "loongson-rtc", .of_match_table = loongson_rtc_of_match, diff --git a/drivers/rtc/rtc-lp8788.c b/drivers/rtc/rtc-lp8788.c index c0b8fbce1082..0793d70507f7 100644 --- a/drivers/rtc/rtc-lp8788.c +++ b/drivers/rtc/rtc-lp8788.c @@ -293,7 +293,7 @@ static int lp8788_rtc_probe(struct platform_device *pdev) rtc->alarm = lp->pdata ? lp->pdata->alarm_sel : DEFAULT_ALARM_SEL; platform_set_drvdata(pdev, rtc); - device_init_wakeup(dev, 1); + device_init_wakeup(dev, true); rtc->rdev = devm_rtc_device_register(dev, "lp8788_rtc", &lp8788_rtc_ops, THIS_MODULE); diff --git a/drivers/rtc/rtc-lpc24xx.c b/drivers/rtc/rtc-lpc24xx.c index df17c48ff086..2dcdc77ff646 100644 --- a/drivers/rtc/rtc-lpc24xx.c +++ b/drivers/rtc/rtc-lpc24xx.c @@ -285,7 +285,7 @@ MODULE_DEVICE_TABLE(of, lpc24xx_rtc_match); static struct platform_driver lpc24xx_rtc_driver = { .probe = lpc24xx_rtc_probe, - .remove_new = lpc24xx_rtc_remove, + .remove = lpc24xx_rtc_remove, .driver = { .name = "lpc24xx-rtc", .of_match_table = lpc24xx_rtc_match, diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c index 76ad7031a13d..74280bffe1b0 100644 --- a/drivers/rtc/rtc-lpc32xx.c +++ b/drivers/rtc/rtc-lpc32xx.c @@ -257,7 +257,7 @@ static int lpc32xx_rtc_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "Can't request interrupt.\n"); rtc->irq = -1; } else { - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); } } diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 0013bff0447d..1f58ae8b151e 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -850,7 +850,6 @@ static const struct file_operations wdt_fops = { .write = wdt_write, .open = wdt_open, .release = wdt_release, - .llseek = no_llseek, }; static struct miscdevice wdt_dev = { diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index f0f6b9b6daec..4e608bc8bbd3 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -71,7 +71,7 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) /* Issue the READ command */ M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL); - tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR)); + tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR)) + pdata->yy_offset; /* tm_mon is 0-11 */ tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1; tm->tm_mday = bcd2bin(M48T59_READ(M48T59_MDAY)); @@ -82,10 +82,6 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) dev_dbg(dev, "Century bit is enabled\n"); tm->tm_year += 100; /* one century */ } -#ifdef CONFIG_SPARC - /* Sun SPARC machines count years since 1968 */ - tm->tm_year += 68; -#endif tm->tm_wday = bcd2bin(val & 0x07); tm->tm_hour = bcd2bin(M48T59_READ(M48T59_HOUR) & 0x3F); @@ -106,12 +102,7 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) struct m48t59_private *m48t59 = dev_get_drvdata(dev); unsigned long flags; u8 val = 0; - int year = tm->tm_year; - -#ifdef CONFIG_SPARC - /* Sun SPARC machines count years since 1968 */ - year -= 68; -#endif + int year = tm->tm_year - pdata->yy_offset; dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d/%02d/%02d\n", year + 1900, tm->tm_mon, tm->tm_mday, @@ -132,7 +123,7 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) M48T59_WRITE((bin2bcd(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); M48T59_WRITE(bin2bcd(year % 100), M48T59_YEAR); - if (pdata->type == M48T59RTC_TYPE_M48T59 && (year / 100)) + if (pdata->type == M48T59RTC_TYPE_M48T59 && (year >= 100)) val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); val |= (bin2bcd(tm->tm_wday) & 0x07); M48T59_WRITE(val, M48T59_WDAY); @@ -162,11 +153,7 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) /* Issue the READ command */ M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL); - tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR)); -#ifdef CONFIG_SPARC - /* Sun SPARC machines count years since 1968 */ - tm->tm_year += 68; -#endif + tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR)) + pdata->yy_offset; /* tm_mon is 0-11 */ tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1; @@ -197,12 +184,7 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) struct rtc_time *tm = &alrm->time; u8 mday, hour, min, sec; unsigned long flags; - int year = tm->tm_year; - -#ifdef CONFIG_SPARC - /* Sun SPARC machines count years since 1968 */ - year -= 68; -#endif + int year = tm->tm_year - pdata->yy_offset; /* If no irq, we don't support ALARM */ if (m48t59->irq == NO_IRQ) @@ -458,6 +440,8 @@ static int m48t59_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, m48t59); m48t59->rtc->ops = &m48t59_rtc_ops; + m48t59->rtc->range_min = RTC_TIMESTAMP_BEGIN_1900; + m48t59->rtc->range_max = RTC_TIMESTAMP_END_2099; nvmem_cfg.size = pdata->offset; ret = devm_rtc_nvmem_register(m48t59->rtc, &nvmem_cfg); diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index dd4a62e2d39c..10cd054fe86f 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c @@ -41,7 +41,6 @@ struct m48t86_rtc_info { void __iomem *index_reg; void __iomem *data_reg; - struct rtc_device *rtc; }; static unsigned char m48t86_readb(struct device *dev, unsigned long addr) @@ -219,6 +218,7 @@ static bool m48t86_verify_chip(struct platform_device *pdev) static int m48t86_rtc_probe(struct platform_device *pdev) { struct m48t86_rtc_info *info; + struct rtc_device *rtc; unsigned char reg; int err; struct nvmem_config m48t86_nvmem_cfg = { @@ -250,17 +250,17 @@ static int m48t86_rtc_probe(struct platform_device *pdev) return -ENODEV; } - info->rtc = devm_rtc_allocate_device(&pdev->dev); - if (IS_ERR(info->rtc)) - return PTR_ERR(info->rtc); + rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); - info->rtc->ops = &m48t86_rtc_ops; + rtc->ops = &m48t86_rtc_ops; - err = devm_rtc_register_device(info->rtc); + err = devm_rtc_register_device(rtc); if (err) return err; - devm_rtc_nvmem_register(info->rtc, &m48t86_nvmem_cfg); + devm_rtc_nvmem_register(rtc, &m48t86_nvmem_cfg); /* read battery status */ reg = m48t86_readb(&pdev->dev, M48T86_D); diff --git a/drivers/rtc/rtc-max31335.c b/drivers/rtc/rtc-max31335.c index a2441e5c2c74..a7bb37aaab9e 100644 --- a/drivers/rtc/rtc-max31335.c +++ b/drivers/rtc/rtc-max31335.c @@ -8,7 +8,7 @@ * */ -#include <asm-generic/unaligned.h> +#include <linux/unaligned.h> #include <linux/bcd.h> #include <linux/bitfield.h> #include <linux/bitops.h> @@ -184,31 +184,91 @@ #define MAX31335_RAM_SIZE 32 #define MAX31335_TIME_SIZE 0x07 +/* MAX31331 Register Map */ +#define MAX31331_RTC_CONFIG2 0x04 + #define clk_hw_to_max31335(_hw) container_of(_hw, struct max31335_data, clkout) +/* Supported Maxim RTC */ +enum max_rtc_ids { + ID_MAX31331, + ID_MAX31335, + MAX_RTC_ID_NR +}; + +struct chip_desc { + u8 sec_reg; + u8 alarm1_sec_reg; + + u8 int_en_reg; + u8 int_status_reg; + + u8 ram_reg; + u8 ram_size; + + u8 temp_reg; + + u8 trickle_reg; + + u8 clkout_reg; + + enum max_rtc_ids id; +}; + struct max31335_data { struct regmap *regmap; struct rtc_device *rtc; struct clk_hw clkout; + struct clk *clkin; + const struct chip_desc *chip; + int irq; }; static const int max31335_clkout_freq[] = { 1, 64, 1024, 32768 }; +static const struct chip_desc chip[MAX_RTC_ID_NR] = { + [ID_MAX31331] = { + .id = ID_MAX31331, + .int_en_reg = 0x01, + .int_status_reg = 0x00, + .sec_reg = 0x08, + .alarm1_sec_reg = 0x0F, + .ram_reg = 0x20, + .ram_size = 32, + .trickle_reg = 0x1B, + .clkout_reg = 0x04, + }, + [ID_MAX31335] = { + .id = ID_MAX31335, + .int_en_reg = 0x01, + .int_status_reg = 0x00, + .sec_reg = 0x0A, + .alarm1_sec_reg = 0x11, + .ram_reg = 0x40, + .ram_size = 32, + .temp_reg = 0x35, + .trickle_reg = 0x1D, + .clkout_reg = 0x06, + }, +}; + static const u16 max31335_trickle_resistors[] = {3000, 6000, 11000}; static bool max31335_volatile_reg(struct device *dev, unsigned int reg) { + struct max31335_data *max31335 = dev_get_drvdata(dev); + const struct chip_desc *chip = max31335->chip; + /* time keeping registers */ - if (reg >= MAX31335_SECONDS && - reg < MAX31335_SECONDS + MAX31335_TIME_SIZE) + if (reg >= chip->sec_reg && reg < chip->sec_reg + MAX31335_TIME_SIZE) return true; /* interrupt status register */ - if (reg == MAX31335_STATUS1) + if (reg == chip->int_status_reg) return true; - /* temperature registers */ - if (reg == MAX31335_TEMP_DATA_MSB || reg == MAX31335_TEMP_DATA_LSB) + /* temperature registers if valid */ + if (chip->temp_reg && (reg == chip->temp_reg || reg == chip->temp_reg + 1)) return true; return false; @@ -227,7 +287,7 @@ static int max31335_read_time(struct device *dev, struct rtc_time *tm) u8 date[7]; int ret; - ret = regmap_bulk_read(max31335->regmap, MAX31335_SECONDS, date, + ret = regmap_bulk_read(max31335->regmap, max31335->chip->sec_reg, date, sizeof(date)); if (ret) return ret; @@ -262,7 +322,7 @@ static int max31335_set_time(struct device *dev, struct rtc_time *tm) if (tm->tm_year >= 200) date[5] |= FIELD_PREP(MAX31335_MONTH_CENTURY, 1); - return regmap_bulk_write(max31335->regmap, MAX31335_SECONDS, date, + return regmap_bulk_write(max31335->regmap, max31335->chip->sec_reg, date, sizeof(date)); } @@ -273,7 +333,7 @@ static int max31335_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) struct rtc_time time; u8 regs[6]; - ret = regmap_bulk_read(max31335->regmap, MAX31335_ALM1_SEC, regs, + ret = regmap_bulk_read(max31335->regmap, max31335->chip->alarm1_sec_reg, regs, sizeof(regs)); if (ret) return ret; @@ -292,11 +352,11 @@ static int max31335_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) if (time.tm_year >= 200) alrm->time.tm_year += 100; - ret = regmap_read(max31335->regmap, MAX31335_INT_EN1, &ctrl); + ret = regmap_read(max31335->regmap, max31335->chip->int_en_reg, &ctrl); if (ret) return ret; - ret = regmap_read(max31335->regmap, MAX31335_STATUS1, &status); + ret = regmap_read(max31335->regmap, max31335->chip->int_status_reg, &status); if (ret) return ret; @@ -320,18 +380,18 @@ static int max31335_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) regs[4] = bin2bcd(alrm->time.tm_mon + 1); regs[5] = bin2bcd(alrm->time.tm_year % 100); - ret = regmap_bulk_write(max31335->regmap, MAX31335_ALM1_SEC, + ret = regmap_bulk_write(max31335->regmap, max31335->chip->alarm1_sec_reg, regs, sizeof(regs)); if (ret) return ret; reg = FIELD_PREP(MAX31335_INT_EN1_A1IE, alrm->enabled); - ret = regmap_update_bits(max31335->regmap, MAX31335_INT_EN1, + ret = regmap_update_bits(max31335->regmap, max31335->chip->int_en_reg, MAX31335_INT_EN1_A1IE, reg); if (ret) return ret; - ret = regmap_update_bits(max31335->regmap, MAX31335_STATUS1, + ret = regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg, MAX31335_STATUS1_A1F, 0); return 0; @@ -341,23 +401,33 @@ static int max31335_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct max31335_data *max31335 = dev_get_drvdata(dev); - return regmap_update_bits(max31335->regmap, MAX31335_INT_EN1, + return regmap_update_bits(max31335->regmap, max31335->chip->int_en_reg, MAX31335_INT_EN1_A1IE, enabled); } static irqreturn_t max31335_handle_irq(int irq, void *dev_id) { struct max31335_data *max31335 = dev_id; - bool status; - int ret; + struct mutex *lock = &max31335->rtc->ops_lock; + int ret, status; - ret = regmap_update_bits_check(max31335->regmap, MAX31335_STATUS1, - MAX31335_STATUS1_A1F, 0, &status); + mutex_lock(lock); + + ret = regmap_read(max31335->regmap, max31335->chip->int_status_reg, &status); if (ret) - return IRQ_HANDLED; + goto exit; + + if (FIELD_GET(MAX31335_STATUS1_A1F, status)) { + ret = regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg, + MAX31335_STATUS1_A1F, 0); + if (ret) + goto exit; - if (status) rtc_update_irq(max31335->rtc, 1, RTC_AF | RTC_IRQF); + } + +exit: + mutex_unlock(lock); return IRQ_HANDLED; } @@ -404,7 +474,7 @@ static int max31335_trickle_charger_setup(struct device *dev, i = i + trickle_cfg; - return regmap_write(max31335->regmap, MAX31335_TRICKLE_REG, + return regmap_write(max31335->regmap, max31335->chip->trickle_reg, FIELD_PREP(MAX31335_TRICKLE_REG_TRICKLE, i) | FIELD_PREP(MAX31335_TRICKLE_REG_EN_TRICKLE, chargeable)); @@ -418,7 +488,7 @@ static unsigned long max31335_clkout_recalc_rate(struct clk_hw *hw, unsigned int reg; int ret; - ret = regmap_read(max31335->regmap, MAX31335_RTC_CONFIG2, ®); + ret = regmap_read(max31335->regmap, max31335->chip->clkout_reg, ®); if (ret) return 0; @@ -449,23 +519,23 @@ static int max31335_clkout_set_rate(struct clk_hw *hw, unsigned long rate, ARRAY_SIZE(max31335_clkout_freq)); freq_mask = __roundup_pow_of_two(ARRAY_SIZE(max31335_clkout_freq)) - 1; - return regmap_update_bits(max31335->regmap, MAX31335_RTC_CONFIG2, - freq_mask, index); + return regmap_update_bits(max31335->regmap, max31335->chip->clkout_reg, + freq_mask, index); } static int max31335_clkout_enable(struct clk_hw *hw) { struct max31335_data *max31335 = clk_hw_to_max31335(hw); - return regmap_set_bits(max31335->regmap, MAX31335_RTC_CONFIG2, - MAX31335_RTC_CONFIG2_ENCLKO); + return regmap_set_bits(max31335->regmap, max31335->chip->clkout_reg, + MAX31335_RTC_CONFIG2_ENCLKO); } static void max31335_clkout_disable(struct clk_hw *hw) { struct max31335_data *max31335 = clk_hw_to_max31335(hw); - regmap_clear_bits(max31335->regmap, MAX31335_RTC_CONFIG2, + regmap_clear_bits(max31335->regmap, max31335->chip->clkout_reg, MAX31335_RTC_CONFIG2_ENCLKO); } @@ -475,7 +545,7 @@ static int max31335_clkout_is_enabled(struct clk_hw *hw) unsigned int reg; int ret; - ret = regmap_read(max31335->regmap, MAX31335_RTC_CONFIG2, ®); + ret = regmap_read(max31335->regmap, max31335->chip->clkout_reg, ®); if (ret) return ret; @@ -500,7 +570,7 @@ static int max31335_nvmem_reg_read(void *priv, unsigned int offset, void *val, size_t bytes) { struct max31335_data *max31335 = priv; - unsigned int reg = MAX31335_TS0_SEC_1_128 + offset; + unsigned int reg = max31335->chip->ram_reg + offset; return regmap_bulk_read(max31335->regmap, reg, val, bytes); } @@ -509,7 +579,7 @@ static int max31335_nvmem_reg_write(void *priv, unsigned int offset, void *val, size_t bytes) { struct max31335_data *max31335 = priv; - unsigned int reg = MAX31335_TS0_SEC_1_128 + offset; + unsigned int reg = max31335->chip->ram_reg + offset; return regmap_bulk_write(max31335->regmap, reg, val, bytes); } @@ -533,7 +603,7 @@ static int max31335_read_temp(struct device *dev, enum hwmon_sensor_types type, if (type != hwmon_temp || attr != hwmon_temp_input) return -EOPNOTSUPP; - ret = regmap_bulk_read(max31335->regmap, MAX31335_TEMP_DATA_MSB, + ret = regmap_bulk_read(max31335->regmap, max31335->chip->temp_reg, reg, 2); if (ret) return ret; @@ -577,8 +647,8 @@ static int max31335_clkout_register(struct device *dev) int ret; if (!device_property_present(dev, "#clock-cells")) - return regmap_clear_bits(max31335->regmap, MAX31335_RTC_CONFIG2, - MAX31335_RTC_CONFIG2_ENCLKO); + return regmap_clear_bits(max31335->regmap, max31335->chip->clkout_reg, + MAX31335_RTC_CONFIG2_ENCLKO); max31335->clkout.init = &max31335_clk_init; @@ -605,6 +675,7 @@ static int max31335_probe(struct i2c_client *client) #if IS_REACHABLE(HWMON) struct device *hwmon; #endif + const struct chip_desc *match; int ret; max31335 = devm_kzalloc(&client->dev, sizeof(*max31335), GFP_KERNEL); @@ -616,7 +687,10 @@ static int max31335_probe(struct i2c_client *client) return PTR_ERR(max31335->regmap); i2c_set_clientdata(client, max31335); - + match = i2c_get_match_data(client); + if (!match) + return -ENODEV; + max31335->chip = match; max31335->rtc = devm_rtc_allocate_device(&client->dev); if (IS_ERR(max31335->rtc)) return PTR_ERR(max31335->rtc); @@ -639,6 +713,8 @@ static int max31335_probe(struct i2c_client *client) dev_warn(&client->dev, "unable to request IRQ, alarm max31335 disabled\n"); client->irq = 0; + } else { + max31335->irq = client->irq; } } @@ -652,13 +728,13 @@ static int max31335_probe(struct i2c_client *client) "cannot register rtc nvmem\n"); #if IS_REACHABLE(HWMON) - hwmon = devm_hwmon_device_register_with_info(&client->dev, client->name, - max31335, - &max31335_chip_info, - NULL); - if (IS_ERR(hwmon)) - return dev_err_probe(&client->dev, PTR_ERR(hwmon), - "cannot register hwmon device\n"); + if (max31335->chip->temp_reg) { + hwmon = devm_hwmon_device_register_with_info(&client->dev, client->name, max31335, + &max31335_chip_info, NULL); + if (IS_ERR(hwmon)) + return dev_err_probe(&client->dev, PTR_ERR(hwmon), + "cannot register hwmon device\n"); + } #endif ret = max31335_trickle_charger_setup(&client->dev, max31335); @@ -669,14 +745,16 @@ static int max31335_probe(struct i2c_client *client) } static const struct i2c_device_id max31335_id[] = { - { "max31335", 0 }, + { "max31331", (kernel_ulong_t)&chip[ID_MAX31331] }, + { "max31335", (kernel_ulong_t)&chip[ID_MAX31335] }, { } }; MODULE_DEVICE_TABLE(i2c, max31335_id); static const struct of_device_id max31335_of_match[] = { - { .compatible = "adi,max31335" }, + { .compatible = "adi,max31331", .data = &chip[ID_MAX31331] }, + { .compatible = "adi,max31335", .data = &chip[ID_MAX31335] }, { } }; @@ -693,5 +771,6 @@ static struct i2c_driver max31335_driver = { module_i2c_driver(max31335_driver); MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com>"); +MODULE_AUTHOR("Saket Kumar Purwar <Saket.Kumarpurwar@analog.com>"); MODULE_DESCRIPTION("MAX31335 RTC driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index 31b910e4d91a..7be31fce5bc7 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c @@ -215,7 +215,7 @@ static int max6900_probe(struct i2c_client *client) } static const struct i2c_device_id max6900_id[] = { - { "max6900", 0 }, + { "max6900" }, { } }; MODULE_DEVICE_TABLE(i2c, max6900_id); diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 35a6021d9ba4..69ea3ce75b5a 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -85,7 +85,6 @@ struct max77686_rtc_driver_data { struct max77686_rtc_info { struct device *dev; - struct i2c_client *rtc; struct rtc_device *rtc_dev; struct mutex lock; @@ -691,6 +690,7 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info) { struct device *parent = info->dev->parent; struct i2c_client *parent_i2c = to_i2c_client(parent); + struct i2c_client *client; int ret; if (info->drv_data->rtc_irq_from_platform) { @@ -704,40 +704,35 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info) } info->regmap = dev_get_regmap(parent, NULL); - if (!info->regmap) { - dev_err(info->dev, "Failed to get rtc regmap\n"); - return -ENODEV; - } + if (!info->regmap) + return dev_err_probe(info->dev, -ENODEV, + "Failed to get rtc regmap\n"); if (info->drv_data->rtc_i2c_addr == MAX77686_INVALID_I2C_ADDR) { info->rtc_regmap = info->regmap; goto add_rtc_irq; } - info->rtc = devm_i2c_new_dummy_device(info->dev, parent_i2c->adapter, - info->drv_data->rtc_i2c_addr); - if (IS_ERR(info->rtc)) { - dev_err(info->dev, "Failed to allocate I2C device for RTC\n"); - return PTR_ERR(info->rtc); - } + client = devm_i2c_new_dummy_device(info->dev, parent_i2c->adapter, + 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"); - info->rtc_regmap = devm_regmap_init_i2c(info->rtc, + info->rtc_regmap = devm_regmap_init_i2c(client, info->drv_data->regmap_config); - if (IS_ERR(info->rtc_regmap)) { - ret = PTR_ERR(info->rtc_regmap); - dev_err(info->dev, "Failed to allocate RTC regmap: %d\n", ret); - return ret; - } + if (IS_ERR(info->rtc_regmap)) + return dev_err_probe(info->dev, PTR_ERR(info->rtc_regmap), + "Failed to allocate RTC regmap\n"); add_rtc_irq: ret = regmap_add_irq_chip(info->rtc_regmap, info->rtc_irq, IRQF_ONESHOT | IRQF_SHARED, 0, info->drv_data->rtc_irq_chip, &info->rtc_irq_data); - if (ret < 0) { - dev_err(info->dev, "Failed to add RTC irq chip: %d\n", ret); - return ret; - } + if (ret < 0) + return dev_err_probe(info->dev, ret, + "Failed to add RTC irq chip\n"); return 0; } @@ -770,7 +765,7 @@ static int max77686_rtc_probe(struct platform_device *pdev) goto err_rtc; } - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); info->rtc_dev = devm_rtc_device_register(&pdev->dev, id->name, &max77686_rtc_ops, THIS_MODULE); @@ -875,7 +870,7 @@ static struct platform_driver max77686_rtc_driver = { .pm = &max77686_rtc_pm_ops, }, .probe = max77686_rtc_probe, - .remove_new = max77686_rtc_remove, + .remove = max77686_rtc_remove, .id_table = rtc_id, }; diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c index 64bb8ac6ef62..6ce8afbeac68 100644 --- a/drivers/rtc/rtc-max8925.c +++ b/drivers/rtc/rtc-max8925.c @@ -270,7 +270,7 @@ static int max8925_rtc_probe(struct platform_device *pdev) /* XXX - isn't this redundant? */ platform_set_drvdata(pdev, info); - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max8925-rtc", &max8925_rtc_ops, THIS_MODULE); diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c index 20e50d9fdf88..e7618d715bd8 100644 --- a/drivers/rtc/rtc-max8997.c +++ b/drivers/rtc/rtc-max8997.c @@ -473,7 +473,7 @@ static int max8997_rtc_probe(struct platform_device *pdev) max8997_rtc_enable_wtsr(info, true); max8997_rtc_enable_smpl(info, true); - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max8997-rtc", &max8997_rtc_ops, THIS_MODULE); diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c index 763a42f422eb..e7b87130e624 100644 --- a/drivers/rtc/rtc-mc13xxx.c +++ b/drivers/rtc/rtc-mc13xxx.c @@ -350,7 +350,7 @@ MODULE_DEVICE_TABLE(platform, mc13xxx_rtc_idtable); static struct platform_driver mc13xxx_rtc_driver = { .id_table = mc13xxx_rtc_idtable, - .remove_new = mc13xxx_rtc_remove, + .remove = mc13xxx_rtc_remove, .driver = { .name = DRIVER_NAME, }, diff --git a/drivers/rtc/rtc-mc146818-lib.c b/drivers/rtc/rtc-mc146818-lib.c index 651bf3c279c7..dbd2d5835f00 100644 --- a/drivers/rtc/rtc-mc146818-lib.c +++ b/drivers/rtc/rtc-mc146818-lib.c @@ -216,7 +216,7 @@ int mc146818_set_time(struct rtc_time *time) unsigned char save_control, save_freq_select; unsigned int yrs; #ifdef CONFIG_MACH_DECSTATION - unsigned int real_yrs, leap_yr; + unsigned int real_yrs; #endif unsigned char century = 0; @@ -232,8 +232,6 @@ int mc146818_set_time(struct rtc_time *time) #ifdef CONFIG_MACH_DECSTATION real_yrs = yrs; - leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) || - !((yrs + 1900) % 400)); yrs = 72; /* @@ -241,7 +239,7 @@ int mc146818_set_time(struct rtc_time *time) * for non-leap years, so that Feb, 29th is handled * correctly. */ - if (!leap_yr && mon < 3) { + if (!is_leap_year(real_yrs + 1900) && mon < 3) { real_yrs--; yrs = 73; } diff --git a/drivers/rtc/rtc-mcp795.c b/drivers/rtc/rtc-mcp795.c index 0d515b3df571..e12f0f806ec4 100644 --- a/drivers/rtc/rtc-mcp795.c +++ b/drivers/rtc/rtc-mcp795.c @@ -450,4 +450,3 @@ module_spi_driver(mcp795_driver); MODULE_DESCRIPTION("MCP795 RTC SPI Driver"); MODULE_AUTHOR("Josef Gajdusek <atx@atx.name>"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:mcp795"); diff --git a/drivers/rtc/rtc-meson-vrtc.c b/drivers/rtc/rtc-meson-vrtc.c index 648fa362ec44..7d38258cbe37 100644 --- a/drivers/rtc/rtc-meson-vrtc.c +++ b/drivers/rtc/rtc-meson-vrtc.c @@ -13,7 +13,6 @@ struct meson_vrtc_data { void __iomem *io_alarm; - struct rtc_device *rtc; unsigned long alarm_time; bool enabled; }; @@ -65,6 +64,7 @@ static const struct rtc_class_ops meson_vrtc_ops = { static int meson_vrtc_probe(struct platform_device *pdev) { struct meson_vrtc_data *vrtc; + struct rtc_device *rtc; vrtc = devm_kzalloc(&pdev->dev, sizeof(*vrtc), GFP_KERNEL); if (!vrtc) @@ -74,16 +74,16 @@ static int meson_vrtc_probe(struct platform_device *pdev) if (IS_ERR(vrtc->io_alarm)) return PTR_ERR(vrtc->io_alarm); - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); platform_set_drvdata(pdev, vrtc); - vrtc->rtc = devm_rtc_allocate_device(&pdev->dev); - if (IS_ERR(vrtc->rtc)) - return PTR_ERR(vrtc->rtc); + rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); - vrtc->rtc->ops = &meson_vrtc_ops; - return devm_rtc_register_device(vrtc->rtc); + rtc->ops = &meson_vrtc_ops; + return devm_rtc_register_device(rtc); } static int __maybe_unused meson_vrtc_suspend(struct device *dev) diff --git a/drivers/rtc/rtc-meson.c b/drivers/rtc/rtc-meson.c index db1d626edca5..47e9ebf58ffc 100644 --- a/drivers/rtc/rtc-meson.c +++ b/drivers/rtc/rtc-meson.c @@ -59,7 +59,6 @@ #define MESON_STATIC_DEFAULT (MESON_STATIC_BIAS_CUR | MESON_STATIC_VOLTAGE) struct meson_rtc { - struct rtc_device *rtc; /* rtc device we created */ struct device *dev; /* device we bound from */ struct reset_control *reset; /* reset source */ struct regulator *vdd; /* voltage input */ @@ -292,6 +291,7 @@ static int meson_rtc_probe(struct platform_device *pdev) }; struct device *dev = &pdev->dev; struct meson_rtc *rtc; + struct rtc_device *rtc_dev; void __iomem *base; int ret; u32 tm; @@ -300,16 +300,16 @@ static int meson_rtc_probe(struct platform_device *pdev) if (!rtc) return -ENOMEM; - rtc->rtc = devm_rtc_allocate_device(dev); - if (IS_ERR(rtc->rtc)) - return PTR_ERR(rtc->rtc); + rtc_dev = devm_rtc_allocate_device(dev); + if (IS_ERR(rtc_dev)) + return PTR_ERR(rtc_dev); platform_set_drvdata(pdev, rtc); rtc->dev = dev; - rtc->rtc->ops = &meson_rtc_ops; - rtc->rtc->range_max = U32_MAX; + rtc_dev->ops = &meson_rtc_ops; + rtc_dev->range_max = U32_MAX; base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) @@ -365,11 +365,11 @@ static int meson_rtc_probe(struct platform_device *pdev) } meson_rtc_nvmem_config.priv = rtc; - ret = devm_rtc_nvmem_register(rtc->rtc, &meson_rtc_nvmem_config); + ret = devm_rtc_nvmem_register(rtc_dev, &meson_rtc_nvmem_config); if (ret) goto out_disable_vdd; - ret = devm_rtc_register_device(rtc->rtc); + ret = devm_rtc_register_device(rtc_dev); if (ret) goto out_disable_vdd; diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index 28858fcaea8f..b90f8337a7e6 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -303,7 +303,7 @@ static int mpc5121_rtc_probe(struct platform_device *op) return PTR_ERR(rtc->regs); } - device_init_wakeup(&op->dev, 1); + device_init_wakeup(&op->dev, true); platform_set_drvdata(op, rtc); @@ -398,10 +398,11 @@ static struct platform_driver mpc5121_rtc_driver = { .of_match_table = of_match_ptr(mpc5121_rtc_match), }, .probe = mpc5121_rtc_probe, - .remove_new = mpc5121_rtc_remove, + .remove = mpc5121_rtc_remove, }; module_platform_driver(mpc5121_rtc_driver); +MODULE_DESCRIPTION("Freescale MPC5121 built-in RTC driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("John Rigby <jcrigby@gmail.com>"); diff --git a/drivers/rtc/rtc-mpfs.c b/drivers/rtc/rtc-mpfs.c index 5b96a6d39210..6aa3eae575d2 100644 --- a/drivers/rtc/rtc-mpfs.c +++ b/drivers/rtc/rtc-mpfs.c @@ -266,19 +266,14 @@ static int mpfs_rtc_probe(struct platform_device *pdev) writel(prescaler, rtcdev->base + PRESCALER_REG); dev_info(&pdev->dev, "prescaler set to: %lu\n", prescaler); - device_init_wakeup(&pdev->dev, true); - ret = dev_pm_set_wake_irq(&pdev->dev, wakeup_irq); + devm_device_init_wakeup(&pdev->dev); + ret = devm_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 void mpfs_rtc_remove(struct platform_device *pdev) -{ - dev_pm_clear_wake_irq(&pdev->dev); -} - static const struct of_device_id mpfs_rtc_of_match[] = { { .compatible = "microchip,mpfs-rtc" }, { } @@ -288,7 +283,6 @@ MODULE_DEVICE_TABLE(of, mpfs_rtc_of_match); static struct platform_driver mpfs_rtc_driver = { .probe = mpfs_rtc_probe, - .remove_new = mpfs_rtc_remove, .driver = { .name = "mpfs_rtc", .of_match_table = mpfs_rtc_of_match, diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c index 1617063669cc..6979d225a78e 100644 --- a/drivers/rtc/rtc-mt6397.c +++ b/drivers/rtc/rtc-mt6397.c @@ -75,6 +75,7 @@ static int __mtk_rtc_read_time(struct mt6397_rtc *rtc, tm->tm_min = data[RTC_OFFSET_MIN]; tm->tm_hour = data[RTC_OFFSET_HOUR]; tm->tm_mday = data[RTC_OFFSET_DOM]; + tm->tm_wday = data[RTC_OFFSET_DOW]; tm->tm_mon = data[RTC_OFFSET_MTH] & RTC_TC_MTH_MASK; tm->tm_year = data[RTC_OFFSET_YEAR]; @@ -86,9 +87,8 @@ exit: static int mtk_rtc_read_time(struct device *dev, struct rtc_time *tm) { - time64_t time; struct mt6397_rtc *rtc = dev_get_drvdata(dev); - int days, sec, ret; + int sec, ret; do { ret = __mtk_rtc_read_time(rtc, tm, &sec); @@ -96,21 +96,9 @@ static int mtk_rtc_read_time(struct device *dev, struct rtc_time *tm) goto exit; } while (sec < tm->tm_sec); - /* HW register use 7 bits to store year data, minus - * RTC_MIN_YEAR_OFFSET before write year data to register, and plus - * RTC_MIN_YEAR_OFFSET back after read year from register - */ - tm->tm_year += RTC_MIN_YEAR_OFFSET; - - /* HW register start mon from one, but tm_mon start from zero. */ + /* HW register start mon/wday from one, but tm_mon/tm_wday start from zero. */ tm->tm_mon--; - time = rtc_tm_to_time64(tm); - - /* rtc_tm_to_time64 covert Gregorian date to seconds since - * 01-01-1970 00:00:00, and this date is Thursday. - */ - days = div_s64(time, 86400); - tm->tm_wday = (days + 4) % 7; + tm->tm_wday--; exit: return ret; @@ -122,13 +110,14 @@ static int mtk_rtc_set_time(struct device *dev, struct rtc_time *tm) int ret; u16 data[RTC_OFFSET_COUNT]; - tm->tm_year -= RTC_MIN_YEAR_OFFSET; tm->tm_mon++; + tm->tm_wday++; data[RTC_OFFSET_SEC] = tm->tm_sec; data[RTC_OFFSET_MIN] = tm->tm_min; data[RTC_OFFSET_HOUR] = tm->tm_hour; data[RTC_OFFSET_DOM] = tm->tm_mday; + data[RTC_OFFSET_DOW] = tm->tm_wday; data[RTC_OFFSET_MTH] = tm->tm_mon; data[RTC_OFFSET_YEAR] = tm->tm_year; @@ -178,7 +167,6 @@ static int mtk_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) tm->tm_mon = data[RTC_OFFSET_MTH] & RTC_AL_MTH_MASK; tm->tm_year = data[RTC_OFFSET_YEAR] & RTC_AL_YEA_MASK; - tm->tm_year += RTC_MIN_YEAR_OFFSET; tm->tm_mon--; return 0; @@ -194,7 +182,6 @@ static int mtk_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) int ret; u16 data[RTC_OFFSET_COUNT]; - tm->tm_year -= RTC_MIN_YEAR_OFFSET; tm->tm_mon++; mutex_lock(&rtc->lock); @@ -299,9 +286,13 @@ static int mtk_rtc_probe(struct platform_device *pdev) return ret; } - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); rtc->rtc_dev->ops = &mtk_rtc_ops; + rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900; + rtc->rtc_dev->range_max = mktime64(2027, 12, 31, 23, 59, 59); + rtc->rtc_dev->start_secs = mktime64(1968, 1, 2, 0, 0, 0); + rtc->rtc_dev->set_start_time = true; return devm_rtc_register_device(rtc->rtc_dev); } diff --git a/drivers/rtc/rtc-mt7622.c b/drivers/rtc/rtc-mt7622.c index 094c649fc137..4cf0cbb31a31 100644 --- a/drivers/rtc/rtc-mt7622.c +++ b/drivers/rtc/rtc-mt7622.c @@ -394,7 +394,7 @@ static SIMPLE_DEV_PM_OPS(mtk_rtc_pm_ops, mtk_rtc_suspend, mtk_rtc_resume); static struct platform_driver mtk_rtc_driver = { .probe = mtk_rtc_probe, - .remove_new = mtk_rtc_remove, + .remove = mtk_rtc_remove, .driver = { .name = MTK_RTC_DEV, .of_match_table = mtk_rtc_match, diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index db31da56bfa7..c27ad626d09f 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c @@ -264,7 +264,7 @@ static int __init mv_rtc_probe(struct platform_device *pdev) } if (pdata->irq >= 0) - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); else clear_bit(RTC_FEATURE_ALARM, pdata->rtc->features); @@ -287,7 +287,7 @@ static void __exit mv_rtc_remove(struct platform_device *pdev) struct rtc_plat_data *pdata = platform_get_drvdata(pdev); if (pdata->irq >= 0) - device_init_wakeup(&pdev->dev, 0); + device_init_wakeup(&pdev->dev, false); if (!IS_ERR(pdata->clk)) clk_disable_unprepare(pdata->clk); @@ -308,7 +308,7 @@ MODULE_DEVICE_TABLE(of, rtc_mv_of_match_table); * triggering a section mismatch warning. */ static struct platform_driver mv_rtc_driver __refdata = { - .remove_new = __exit_p(mv_rtc_remove), + .remove = __exit_p(mv_rtc_remove), .driver = { .name = "rtc-mv", .of_match_table = of_match_ptr(rtc_mv_of_match_table), diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index dbb935dbbd8a..608db97d450c 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c @@ -377,7 +377,7 @@ static int mxc_rtc_probe(struct platform_device *pdev) } if (pdata->irq >= 0) { - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); ret = dev_pm_set_wake_irq(&pdev->dev, pdata->irq); if (ret) dev_err(&pdev->dev, "failed to enable irq wake\n"); diff --git a/drivers/rtc/rtc-mxc_v2.c b/drivers/rtc/rtc-mxc_v2.c index 6934bce4b29f..570f27af4732 100644 --- a/drivers/rtc/rtc-mxc_v2.c +++ b/drivers/rtc/rtc-mxc_v2.c @@ -302,7 +302,7 @@ static int mxc_rtc_probe(struct platform_device *pdev) if (pdata->irq < 0) return pdata->irq; - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); ret = dev_pm_set_wake_irq(&pdev->dev, pdata->irq); if (ret) dev_err(&pdev->dev, "failed to enable irq wake\n"); @@ -381,7 +381,7 @@ static struct platform_driver mxc_rtc_driver = { .of_match_table = mxc_ids, }, .probe = mxc_rtc_probe, - .remove_new = mxc_rtc_remove, + .remove = mxc_rtc_remove, }; module_platform_driver(mxc_rtc_driver); diff --git a/drivers/rtc/rtc-nct3018y.c b/drivers/rtc/rtc-nct3018y.c index 076d8b99f913..76c5f464b2da 100644 --- a/drivers/rtc/rtc-nct3018y.c +++ b/drivers/rtc/rtc-nct3018y.c @@ -517,12 +517,15 @@ static int nct3018y_probe(struct i2c_client *client) if (nct3018y->part_num < 0) { dev_dbg(&client->dev, "Failed to read NCT3018Y_REG_PART.\n"); return nct3018y->part_num; - } else if (nct3018y->part_num == NCT3018Y_REG_PART_NCT3018Y) { - flags = NCT3018Y_BIT_HF; - err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_CTRL, flags); - if (err < 0) { - dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_CTRL.\n"); - return err; + } else { + nct3018y->part_num &= 0x03; /* Part number is corresponding to bit 0 and 1 */ + if (nct3018y->part_num == NCT3018Y_REG_PART_NCT3018Y) { + flags = NCT3018Y_BIT_HF; + err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_CTRL, flags); + if (err < 0) { + dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_CTRL.\n"); + return err; + } } } @@ -564,7 +567,7 @@ static int nct3018y_probe(struct i2c_client *client) } static const struct i2c_device_id nct3018y_id[] = { - { "nct3018y", 0 }, + { "nct3018y" }, { } }; MODULE_DEVICE_TABLE(i2c, nct3018y_id); diff --git a/drivers/rtc/rtc-nxp-bbnsm.c b/drivers/rtc/rtc-nxp-bbnsm.c index acbfbeb8b070..d4fc9dc583d3 100644 --- a/drivers/rtc/rtc-nxp-bbnsm.c +++ b/drivers/rtc/rtc-nxp-bbnsm.c @@ -189,8 +189,13 @@ static int bbnsm_rtc_probe(struct platform_device *pdev) /* clear all the pending events */ regmap_write(bbnsm->regmap, BBNSM_EVENTS, 0x7A); - device_init_wakeup(&pdev->dev, true); - dev_pm_set_wake_irq(&pdev->dev, bbnsm->irq); + ret = devm_device_init_wakeup(&pdev->dev); + if (ret) + dev_err(&pdev->dev, "failed to init wakeup, %d\n", ret); + + ret = devm_pm_set_wake_irq(&pdev->dev, bbnsm->irq); + if (ret) + dev_err(&pdev->dev, "failed to set wake irq, %d\n", ret); ret = devm_request_irq(&pdev->dev, bbnsm->irq, bbnsm_rtc_irq_handler, IRQF_SHARED, "rtc alarm", &pdev->dev); diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index c6155c48a4ac..0f90065e352c 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -920,7 +920,7 @@ static void omap_rtc_remove(struct platform_device *pdev) omap_rtc_power_off_rtc = NULL; } - device_init_wakeup(&pdev->dev, 0); + device_init_wakeup(&pdev->dev, false); if (!IS_ERR(rtc->clk)) clk_disable_unprepare(rtc->clk); @@ -1014,7 +1014,7 @@ static void omap_rtc_shutdown(struct platform_device *pdev) static struct platform_driver omap_rtc_driver = { .probe = omap_rtc_probe, - .remove_new = omap_rtc_remove, + .remove = omap_rtc_remove, .shutdown = omap_rtc_shutdown, .driver = { .name = "omap_rtc", @@ -1027,4 +1027,5 @@ static struct platform_driver omap_rtc_driver = { module_platform_driver(omap_rtc_driver); MODULE_AUTHOR("George G. Davis (and others)"); +MODULE_DESCRIPTION("TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx RTC driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c index 6971e47c6021..aecada6bcf8b 100644 --- a/drivers/rtc/rtc-palmas.c +++ b/drivers/rtc/rtc-palmas.c @@ -287,7 +287,7 @@ static int palmas_rtc_probe(struct platform_device *pdev) palmas_rtc->irq = platform_get_irq(pdev, 0); - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); palmas_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &palmas_rtc_ops, THIS_MODULE); if (IS_ERR(palmas_rtc->rtc)) { @@ -346,7 +346,7 @@ MODULE_DEVICE_TABLE(of, of_palmas_rtc_match); static struct platform_driver palmas_rtc_driver = { .probe = palmas_rtc_probe, - .remove_new = palmas_rtc_remove, + .remove = palmas_rtc_remove, .driver = { .name = "palmas-rtc", .pm = &palmas_rtc_pm_ops, diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index 9c04c4e1a49c..31c7dca8f469 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -20,6 +20,7 @@ #include <linux/i2c.h> #include <linux/spi/spi.h> #include <linux/bcd.h> +#include <linux/bitfield.h> #include <linux/rtc.h> #include <linux/slab.h> #include <linux/module.h> @@ -48,6 +49,7 @@ #define PCF2127_BIT_CTRL3_BLF BIT(2) #define PCF2127_BIT_CTRL3_BF BIT(3) #define PCF2127_BIT_CTRL3_BTSE BIT(4) +#define PCF2127_CTRL3_PM GENMASK(7, 5) /* Time and date registers */ #define PCF2127_REG_TIME_BASE 0x03 #define PCF2127_BIT_SC_OSF BIT(7) @@ -331,6 +333,84 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) return 0; } +static int pcf2127_param_get(struct device *dev, struct rtc_param *param) +{ + struct pcf2127 *pcf2127 = dev_get_drvdata(dev); + u32 value; + int ret; + + switch (param->param) { + case RTC_PARAM_BACKUP_SWITCH_MODE: + ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &value); + if (ret < 0) + return ret; + + value = FIELD_GET(PCF2127_CTRL3_PM, value); + + if (value < 0x3) + param->uvalue = RTC_BSM_LEVEL; + else if (value < 0x6) + param->uvalue = RTC_BSM_DIRECT; + else + param->uvalue = RTC_BSM_DISABLED; + + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int pcf2127_param_set(struct device *dev, struct rtc_param *param) +{ + struct pcf2127 *pcf2127 = dev_get_drvdata(dev); + u8 mode = 0; + u32 value; + int ret; + + switch (param->param) { + case RTC_PARAM_BACKUP_SWITCH_MODE: + ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &value); + if (ret < 0) + return ret; + + value = FIELD_GET(PCF2127_CTRL3_PM, value); + + if (value > 5) + value -= 5; + else if (value > 2) + value -= 3; + + switch (param->uvalue) { + case RTC_BSM_LEVEL: + break; + case RTC_BSM_DIRECT: + mode = 3; + break; + case RTC_BSM_DISABLED: + if (value == 0) + value = 1; + mode = 5; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3, + PCF2127_CTRL3_PM, + FIELD_PREP(PCF2127_CTRL3_PM, mode + value)); + + break; + + default: + return -EINVAL; + } + + return 0; +} + static int pcf2127_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { @@ -741,6 +821,8 @@ static const struct rtc_class_ops pcf2127_rtc_ops = { .read_alarm = pcf2127_rtc_read_alarm, .set_alarm = pcf2127_rtc_set_alarm, .alarm_irq_enable = pcf2127_rtc_alarm_irq_enable, + .param_get = pcf2127_param_get, + .param_set = pcf2127_param_set, }; /* sysfs interface */ diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c deleted file mode 100644 index 23edd11aa40c..000000000000 --- a/drivers/rtc/rtc-pcf50633.c +++ /dev/null @@ -1,284 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* NXP PCF50633 RTC Driver - * - * (C) 2006-2008 by Openmoko, Inc. - * Author: Balaji Rao <balajirrao@openmoko.org> - * All rights reserved. - * - * Broken down from monstrous PCF50633 driver mainly by - * Harald Welte, Andy Green and Werner Almesberger - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/rtc.h> -#include <linux/bcd.h> -#include <linux/err.h> - -#include <linux/mfd/pcf50633/core.h> - -#define PCF50633_REG_RTCSC 0x59 /* Second */ -#define PCF50633_REG_RTCMN 0x5a /* Minute */ -#define PCF50633_REG_RTCHR 0x5b /* Hour */ -#define PCF50633_REG_RTCWD 0x5c /* Weekday */ -#define PCF50633_REG_RTCDT 0x5d /* Day */ -#define PCF50633_REG_RTCMT 0x5e /* Month */ -#define PCF50633_REG_RTCYR 0x5f /* Year */ -#define PCF50633_REG_RTCSCA 0x60 /* Alarm Second */ -#define PCF50633_REG_RTCMNA 0x61 /* Alarm Minute */ -#define PCF50633_REG_RTCHRA 0x62 /* Alarm Hour */ -#define PCF50633_REG_RTCWDA 0x63 /* Alarm Weekday */ -#define PCF50633_REG_RTCDTA 0x64 /* Alarm Day */ -#define PCF50633_REG_RTCMTA 0x65 /* Alarm Month */ -#define PCF50633_REG_RTCYRA 0x66 /* Alarm Year */ - -enum pcf50633_time_indexes { - PCF50633_TI_SEC, - PCF50633_TI_MIN, - PCF50633_TI_HOUR, - PCF50633_TI_WKDAY, - PCF50633_TI_DAY, - PCF50633_TI_MONTH, - PCF50633_TI_YEAR, - PCF50633_TI_EXTENT /* always last */ -}; - -struct pcf50633_time { - u_int8_t time[PCF50633_TI_EXTENT]; -}; - -struct pcf50633_rtc { - int alarm_enabled; - int alarm_pending; - - struct pcf50633 *pcf; - struct rtc_device *rtc_dev; -}; - -static void pcf2rtc_time(struct rtc_time *rtc, struct pcf50633_time *pcf) -{ - rtc->tm_sec = bcd2bin(pcf->time[PCF50633_TI_SEC]); - rtc->tm_min = bcd2bin(pcf->time[PCF50633_TI_MIN]); - rtc->tm_hour = bcd2bin(pcf->time[PCF50633_TI_HOUR]); - rtc->tm_wday = bcd2bin(pcf->time[PCF50633_TI_WKDAY]); - rtc->tm_mday = bcd2bin(pcf->time[PCF50633_TI_DAY]); - rtc->tm_mon = bcd2bin(pcf->time[PCF50633_TI_MONTH]) - 1; - rtc->tm_year = bcd2bin(pcf->time[PCF50633_TI_YEAR]) + 100; -} - -static void rtc2pcf_time(struct pcf50633_time *pcf, struct rtc_time *rtc) -{ - pcf->time[PCF50633_TI_SEC] = bin2bcd(rtc->tm_sec); - pcf->time[PCF50633_TI_MIN] = bin2bcd(rtc->tm_min); - pcf->time[PCF50633_TI_HOUR] = bin2bcd(rtc->tm_hour); - pcf->time[PCF50633_TI_WKDAY] = bin2bcd(rtc->tm_wday); - pcf->time[PCF50633_TI_DAY] = bin2bcd(rtc->tm_mday); - pcf->time[PCF50633_TI_MONTH] = bin2bcd(rtc->tm_mon + 1); - pcf->time[PCF50633_TI_YEAR] = bin2bcd(rtc->tm_year % 100); -} - -static int -pcf50633_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - struct pcf50633_rtc *rtc = dev_get_drvdata(dev); - int err; - - if (enabled) - err = pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); - else - err = pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM); - - if (err < 0) - return err; - - rtc->alarm_enabled = enabled; - - return 0; -} - -static int pcf50633_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - struct pcf50633_rtc *rtc; - struct pcf50633_time pcf_tm; - int ret; - - rtc = dev_get_drvdata(dev); - - ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSC, - PCF50633_TI_EXTENT, - &pcf_tm.time[0]); - if (ret != PCF50633_TI_EXTENT) { - dev_err(dev, "Failed to read time\n"); - return -EIO; - } - - dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n", - pcf_tm.time[PCF50633_TI_DAY], - pcf_tm.time[PCF50633_TI_MONTH], - pcf_tm.time[PCF50633_TI_YEAR], - pcf_tm.time[PCF50633_TI_HOUR], - pcf_tm.time[PCF50633_TI_MIN], - pcf_tm.time[PCF50633_TI_SEC]); - - pcf2rtc_time(tm, &pcf_tm); - - dev_dbg(dev, "RTC_TIME: %ptRr\n", tm); - - return 0; -} - -static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - struct pcf50633_rtc *rtc; - struct pcf50633_time pcf_tm; - int alarm_masked, ret = 0; - - rtc = dev_get_drvdata(dev); - - dev_dbg(dev, "RTC_TIME: %ptRr\n", tm); - - rtc2pcf_time(&pcf_tm, tm); - - dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n", - pcf_tm.time[PCF50633_TI_DAY], - pcf_tm.time[PCF50633_TI_MONTH], - pcf_tm.time[PCF50633_TI_YEAR], - pcf_tm.time[PCF50633_TI_HOUR], - pcf_tm.time[PCF50633_TI_MIN], - pcf_tm.time[PCF50633_TI_SEC]); - - - alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM); - - if (!alarm_masked) - pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM); - - /* Returns 0 on success */ - ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSC, - PCF50633_TI_EXTENT, - &pcf_tm.time[0]); - - if (!alarm_masked) - pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); - - return ret; -} - -static int pcf50633_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct pcf50633_rtc *rtc; - struct pcf50633_time pcf_tm; - int ret = 0; - - rtc = dev_get_drvdata(dev); - - alrm->enabled = rtc->alarm_enabled; - alrm->pending = rtc->alarm_pending; - - ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA, - PCF50633_TI_EXTENT, &pcf_tm.time[0]); - if (ret != PCF50633_TI_EXTENT) { - dev_err(dev, "Failed to read time\n"); - return -EIO; - } - - pcf2rtc_time(&alrm->time, &pcf_tm); - - return rtc_valid_tm(&alrm->time); -} - -static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct pcf50633_rtc *rtc; - struct pcf50633_time pcf_tm; - int alarm_masked, ret = 0; - - rtc = dev_get_drvdata(dev); - - rtc2pcf_time(&pcf_tm, &alrm->time); - - /* do like mktime does and ignore tm_wday */ - pcf_tm.time[PCF50633_TI_WKDAY] = 7; - - alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM); - - /* disable alarm interrupt */ - if (!alarm_masked) - pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM); - - /* Returns 0 on success */ - ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA, - PCF50633_TI_EXTENT, &pcf_tm.time[0]); - if (!alrm->enabled) - rtc->alarm_pending = 0; - - if (!alarm_masked || alrm->enabled) - pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); - rtc->alarm_enabled = alrm->enabled; - - return ret; -} - -static const struct rtc_class_ops pcf50633_rtc_ops = { - .read_time = pcf50633_rtc_read_time, - .set_time = pcf50633_rtc_set_time, - .read_alarm = pcf50633_rtc_read_alarm, - .set_alarm = pcf50633_rtc_set_alarm, - .alarm_irq_enable = pcf50633_rtc_alarm_irq_enable, -}; - -static void pcf50633_rtc_irq(int irq, void *data) -{ - struct pcf50633_rtc *rtc = data; - - rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); - rtc->alarm_pending = 1; -} - -static int pcf50633_rtc_probe(struct platform_device *pdev) -{ - struct pcf50633_rtc *rtc; - - rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); - if (!rtc) - return -ENOMEM; - - rtc->pcf = dev_to_pcf50633(pdev->dev.parent); - platform_set_drvdata(pdev, rtc); - rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, "pcf50633-rtc", - &pcf50633_rtc_ops, THIS_MODULE); - - if (IS_ERR(rtc->rtc_dev)) - return PTR_ERR(rtc->rtc_dev); - - pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM, - pcf50633_rtc_irq, rtc); - return 0; -} - -static void pcf50633_rtc_remove(struct platform_device *pdev) -{ - struct pcf50633_rtc *rtc; - - rtc = platform_get_drvdata(pdev); - pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_ALARM); -} - -static struct platform_driver pcf50633_rtc_driver = { - .driver = { - .name = "pcf50633-rtc", - }, - .probe = pcf50633_rtc_probe, - .remove_new = pcf50633_rtc_remove, -}; - -module_platform_driver(pcf50633_rtc_driver); - -MODULE_DESCRIPTION("PCF50633 RTC driver"); -MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>"); -MODULE_LICENSE("GPL"); - diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index fdbc07f14036..4fa5c4ecdd5a 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -35,6 +35,7 @@ #define PCF85063_REG_CTRL1_CAP_SEL BIT(0) #define PCF85063_REG_CTRL1_STOP BIT(5) #define PCF85063_REG_CTRL1_EXT_TEST BIT(7) +#define PCF85063_REG_CTRL1_SWR 0x58 #define PCF85063_REG_CTRL2 0x01 #define PCF85063_CTRL2_AF BIT(6) @@ -322,7 +323,16 @@ static const struct rtc_class_ops pcf85063_rtc_ops = { static int pcf85063_nvmem_read(void *priv, unsigned int offset, void *val, size_t bytes) { - return regmap_read(priv, PCF85063_REG_RAM, val); + unsigned int tmp; + int ret; + + ret = regmap_read(priv, PCF85063_REG_RAM, &tmp); + if (ret < 0) + return ret; + + *(u8 *)val = tmp; + + return 0; } static int pcf85063_nvmem_write(void *priv, unsigned int offset, @@ -580,16 +590,30 @@ static int pcf85063_probe(struct i2c_client *client) i2c_set_clientdata(client, pcf85063); - err = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL1, &tmp); - if (err) { - dev_err(&client->dev, "RTC chip is not present\n"); - return err; - } + err = regmap_read(pcf85063->regmap, PCF85063_REG_SC, &tmp); + if (err) + return dev_err_probe(&client->dev, err, "RTC chip is not present\n"); pcf85063->rtc = devm_rtc_allocate_device(&client->dev); if (IS_ERR(pcf85063->rtc)) return PTR_ERR(pcf85063->rtc); + /* + * If a Power loss is detected, SW reset the device. + * From PCF85063A datasheet: + * There is a low probability that some devices will have corruption + * of the registers after the automatic power-on reset... + */ + if (tmp & PCF85063_REG_SC_OS) { + dev_warn(&client->dev, + "POR issue detected, sending a SW reset\n"); + err = regmap_write(pcf85063->regmap, PCF85063_REG_CTRL1, + PCF85063_REG_CTRL1_SWR); + if (err < 0) + dev_warn(&client->dev, + "SW reset failed, trying to continue\n"); + } + err = pcf85063_load_capacitance(pcf85063, client->dev.of_node, config->force_cap_7000 ? 7000 : 0); if (err < 0) diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index 98b77f790b0c..2c63c0ffd05a 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c @@ -495,7 +495,7 @@ static int pcf8523_probe(struct i2c_client *client) } static const struct i2c_device_id pcf8523_id[] = { - { "pcf8523", 0 }, + { "pcf8523" }, { } }; MODULE_DEVICE_TABLE(i2c, pcf8523_id); diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index ea82b89d8929..5a084d426e58 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -11,14 +11,15 @@ * https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf */ +#include <linux/bcd.h> #include <linux/clk-provider.h> +#include <linux/err.h> #include <linux/i2c.h> -#include <linux/bcd.h> -#include <linux/rtc.h> -#include <linux/slab.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/err.h> +#include <linux/regmap.h> +#include <linux/rtc.h> +#include <linux/slab.h> #define PCF8563_REG_ST1 0x00 /* status */ #define PCF8563_REG_ST2 0x01 @@ -77,64 +78,18 @@ struct pcf8563 { */ int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */ - struct i2c_client *client; + struct regmap *regmap; #ifdef CONFIG_COMMON_CLK struct clk_hw clkout_hw; #endif }; -static int pcf8563_read_block_data(struct i2c_client *client, unsigned char reg, - unsigned char length, unsigned char *buf) +static int pcf8563_set_alarm_mode(struct pcf8563 *pcf8563, bool on) { - struct i2c_msg msgs[] = { - {/* setup read ptr */ - .addr = client->addr, - .len = 1, - .buf = ®, - }, - { - .addr = client->addr, - .flags = I2C_M_RD, - .len = length, - .buf = buf - }, - }; - - if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { - dev_err(&client->dev, "%s: read error\n", __func__); - return -EIO; - } - - return 0; -} - -static int pcf8563_write_block_data(struct i2c_client *client, - unsigned char reg, unsigned char length, - unsigned char *buf) -{ - int i, err; - - for (i = 0; i < length; i++) { - unsigned char data[2] = { reg + i, buf[i] }; - - err = i2c_master_send(client, data, sizeof(data)); - if (err != sizeof(data)) { - dev_err(&client->dev, - "%s: err=%d addr=%02x, data=%02x\n", - __func__, err, data[0], data[1]); - return -EIO; - } - } - - return 0; -} - -static int pcf8563_set_alarm_mode(struct i2c_client *client, bool on) -{ - unsigned char buf; + u32 buf; int err; - err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, &buf); + err = regmap_read(pcf8563->regmap, PCF8563_REG_ST2, &buf); if (err < 0) return err; @@ -145,23 +100,17 @@ static int pcf8563_set_alarm_mode(struct i2c_client *client, bool on) buf &= ~(PCF8563_BIT_AF | PCF8563_BITS_ST2_N); - err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, &buf); - if (err < 0) { - dev_err(&client->dev, "%s: write error\n", __func__); - return -EIO; - } - - return 0; + return regmap_write(pcf8563->regmap, PCF8563_REG_ST2, buf); } -static int pcf8563_get_alarm_mode(struct i2c_client *client, unsigned char *en, +static int pcf8563_get_alarm_mode(struct pcf8563 *pcf8563, unsigned char *en, unsigned char *pen) { - unsigned char buf; + u32 buf; int err; - err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, &buf); - if (err) + err = regmap_read(pcf8563->regmap, PCF8563_REG_ST2, &buf); + if (err < 0) return err; if (en) @@ -174,17 +123,17 @@ static int pcf8563_get_alarm_mode(struct i2c_client *client, unsigned char *en, static irqreturn_t pcf8563_irq(int irq, void *dev_id) { - struct pcf8563 *pcf8563 = i2c_get_clientdata(dev_id); - int err; + struct pcf8563 *pcf8563 = dev_id; char pending; + int err; - err = pcf8563_get_alarm_mode(pcf8563->client, NULL, &pending); + err = pcf8563_get_alarm_mode(pcf8563, NULL, &pending); if (err) return IRQ_NONE; if (pending) { rtc_update_irq(pcf8563->rtc, 1, RTC_IRQF | RTC_AF); - pcf8563_set_alarm_mode(pcf8563->client, 1); + pcf8563_set_alarm_mode(pcf8563, 1); return IRQ_HANDLED; } @@ -197,22 +146,22 @@ static irqreturn_t pcf8563_irq(int irq, void *dev_id) */ static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) { - struct i2c_client *client = to_i2c_client(dev); - struct pcf8563 *pcf8563 = i2c_get_clientdata(client); + struct pcf8563 *pcf8563 = dev_get_drvdata(dev); unsigned char buf[9]; int err; - err = pcf8563_read_block_data(client, PCF8563_REG_ST1, 9, buf); - if (err) + err = regmap_bulk_read(pcf8563->regmap, PCF8563_REG_ST1, buf, + sizeof(buf)); + if (err < 0) return err; if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) { - dev_err(&client->dev, + dev_err(dev, "low voltage detected, date/time is not reliable.\n"); return -EINVAL; } - dev_dbg(&client->dev, + dev_dbg(dev, "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, " "mday=%02x, wday=%02x, mon=%02x, year=%02x\n", __func__, @@ -220,7 +169,6 @@ static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) buf[4], buf[5], buf[6], buf[7], buf[8]); - tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F); tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F); tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */ @@ -232,7 +180,7 @@ static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ? (tm->tm_year >= 100) : (tm->tm_year < 100); - dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " + dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, tm->tm_min, tm->tm_hour, @@ -243,11 +191,10 @@ static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm) { - struct i2c_client *client = to_i2c_client(dev); - struct pcf8563 *pcf8563 = i2c_get_clientdata(client); + struct pcf8563 *pcf8563 = dev_get_drvdata(dev); unsigned char buf[9]; - dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " + dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, tm->tm_min, tm->tm_hour, @@ -270,22 +217,24 @@ static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm) buf[PCF8563_REG_DW] = tm->tm_wday & 0x07; - return pcf8563_write_block_data(client, PCF8563_REG_SC, - 9 - PCF8563_REG_SC, buf + PCF8563_REG_SC); + return regmap_bulk_write(pcf8563->regmap, PCF8563_REG_SC, + buf + PCF8563_REG_SC, + sizeof(buf) - PCF8563_REG_SC); } static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { - struct i2c_client *client = to_i2c_client(dev); + struct pcf8563 *pcf8563 = dev_get_drvdata(dev); int ret; switch (cmd) { case RTC_VL_READ: - ret = i2c_smbus_read_byte_data(client, PCF8563_REG_SC); + ret = regmap_test_bits(pcf8563->regmap, PCF8563_REG_SC, + PCF8563_SC_LV); if (ret < 0) return ret; - return put_user(ret & PCF8563_SC_LV ? RTC_VL_DATA_INVALID : 0, + return put_user(ret ? RTC_VL_DATA_INVALID : 0, (unsigned int __user *)arg); default: return -ENOIOCTLCMD; @@ -294,15 +243,16 @@ static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm) { - struct i2c_client *client = to_i2c_client(dev); + struct pcf8563 *pcf8563 = dev_get_drvdata(dev); unsigned char buf[4]; int err; - err = pcf8563_read_block_data(client, PCF8563_REG_AMN, 4, buf); - if (err) + err = regmap_bulk_read(pcf8563->regmap, PCF8563_REG_AMN, buf, + sizeof(buf)); + if (err < 0) return err; - dev_dbg(&client->dev, + dev_dbg(dev, "%s: raw data is min=%02x, hr=%02x, mday=%02x, wday=%02x\n", __func__, buf[0], buf[1], buf[2], buf[3]); @@ -312,11 +262,11 @@ static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm) tm->time.tm_mday = bcd2bin(buf[2] & 0x3F); tm->time.tm_wday = bcd2bin(buf[3] & 0x7); - err = pcf8563_get_alarm_mode(client, &tm->enabled, &tm->pending); + err = pcf8563_get_alarm_mode(pcf8563, &tm->enabled, &tm->pending); if (err < 0) return err; - dev_dbg(&client->dev, "%s: tm is mins=%d, hours=%d, mday=%d, wday=%d," + dev_dbg(dev, "%s: tm is mins=%d, hours=%d, mday=%d, wday=%d," " enabled=%d, pending=%d\n", __func__, tm->time.tm_min, tm->time.tm_hour, tm->time.tm_mday, tm->time.tm_wday, tm->enabled, tm->pending); @@ -326,7 +276,7 @@ static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm) static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm) { - struct i2c_client *client = to_i2c_client(dev); + struct pcf8563 *pcf8563 = dev_get_drvdata(dev); unsigned char buf[4]; int err; @@ -335,17 +285,20 @@ static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm) buf[2] = bin2bcd(tm->time.tm_mday); buf[3] = tm->time.tm_wday & 0x07; - err = pcf8563_write_block_data(client, PCF8563_REG_AMN, 4, buf); + err = regmap_bulk_write(pcf8563->regmap, PCF8563_REG_SC, buf, + sizeof(buf)); if (err) return err; - return pcf8563_set_alarm_mode(client, !!tm->enabled); + return pcf8563_set_alarm_mode(pcf8563, !!tm->enabled); } static int pcf8563_irq_enable(struct device *dev, unsigned int enabled) { + struct pcf8563 *pcf8563 = dev_get_drvdata(dev); + dev_dbg(dev, "%s: en=%d\n", __func__, enabled); - return pcf8563_set_alarm_mode(to_i2c_client(dev), !!enabled); + return pcf8563_set_alarm_mode(pcf8563, !!enabled); } #ifdef CONFIG_COMMON_CLK @@ -366,10 +319,10 @@ static unsigned long pcf8563_clkout_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw); - struct i2c_client *client = pcf8563->client; - unsigned char buf; - int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf); + u32 buf; + int ret; + ret = regmap_read(pcf8563->regmap, PCF8563_REG_CLKO, &buf); if (ret < 0) return 0; @@ -393,11 +346,10 @@ static int pcf8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw); - struct i2c_client *client = pcf8563->client; - unsigned char buf; - int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf); - int i; + int i, ret; + u32 buf; + ret = regmap_read(pcf8563->regmap, PCF8563_REG_CLKO, &buf); if (ret < 0) return ret; @@ -405,10 +357,10 @@ static int pcf8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate, if (clkout_rates[i] == rate) { buf &= ~PCF8563_REG_CLKO_F_MASK; buf |= i; - ret = pcf8563_write_block_data(client, - PCF8563_REG_CLKO, 1, - &buf); - return ret; + return regmap_update_bits(pcf8563->regmap, + PCF8563_REG_CLKO, + PCF8563_REG_CLKO_F_MASK, + buf); } return -EINVAL; @@ -417,10 +369,10 @@ static int pcf8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate, static int pcf8563_clkout_control(struct clk_hw *hw, bool enable) { struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw); - struct i2c_client *client = pcf8563->client; - unsigned char buf; - int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf); + u32 buf; + int ret; + ret = regmap_read(pcf8563->regmap, PCF8563_REG_CLKO, &buf); if (ret < 0) return ret; @@ -429,8 +381,8 @@ static int pcf8563_clkout_control(struct clk_hw *hw, bool enable) else buf &= ~PCF8563_REG_CLKO_FE; - ret = pcf8563_write_block_data(client, PCF8563_REG_CLKO, 1, &buf); - return ret; + return regmap_update_bits(pcf8563->regmap, PCF8563_REG_CLKO, + PCF8563_REG_CLKO_FE, buf); } static int pcf8563_clkout_prepare(struct clk_hw *hw) @@ -446,10 +398,10 @@ static void pcf8563_clkout_unprepare(struct clk_hw *hw) static int pcf8563_clkout_is_prepared(struct clk_hw *hw) { struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw); - struct i2c_client *client = pcf8563->client; - unsigned char buf; - int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf); + u32 buf; + int ret; + ret = regmap_read(pcf8563->regmap, PCF8563_REG_CLKO, &buf); if (ret < 0) return ret; @@ -467,16 +419,14 @@ static const struct clk_ops pcf8563_clkout_ops = { static struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563) { - struct i2c_client *client = pcf8563->client; - struct device_node *node = client->dev.of_node; - struct clk *clk; + struct device_node *node = pcf8563->rtc->dev.of_node; struct clk_init_data init; + struct clk *clk; int ret; - unsigned char buf; /* disable the clkout output */ - buf = 0; - ret = pcf8563_write_block_data(client, PCF8563_REG_CLKO, 1, &buf); + ret = regmap_clear_bits(pcf8563->regmap, PCF8563_REG_CLKO, + PCF8563_REG_CLKO_FE); if (ret < 0) return ERR_PTR(ret); @@ -491,7 +441,7 @@ static struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563) of_property_read_string(node, "clock-output-names", &init.name); /* register the clock */ - clk = devm_clk_register(&client->dev, &pcf8563->clkout_hw); + clk = devm_clk_register(&pcf8563->rtc->dev, &pcf8563->clkout_hw); if (!IS_ERR(clk)) of_clk_add_provider(node, of_clk_src_simple_get, clk); @@ -509,11 +459,16 @@ static const struct rtc_class_ops pcf8563_rtc_ops = { .alarm_irq_enable = pcf8563_irq_enable, }; +static const struct regmap_config regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xF, +}; + static int pcf8563_probe(struct i2c_client *client) { struct pcf8563 *pcf8563; int err; - unsigned char buf; dev_dbg(&client->dev, "%s\n", __func__); @@ -525,21 +480,23 @@ static int pcf8563_probe(struct i2c_client *client) if (!pcf8563) return -ENOMEM; + pcf8563->regmap = devm_regmap_init_i2c(client, ®map_config); + if (IS_ERR(pcf8563->regmap)) + return PTR_ERR(pcf8563->regmap); + i2c_set_clientdata(client, pcf8563); - pcf8563->client = client; device_set_wakeup_capable(&client->dev, 1); /* Set timer to lowest frequency to save power (ref Haoyu datasheet) */ - buf = PCF8563_TMRC_1_60; - err = pcf8563_write_block_data(client, PCF8563_REG_TMRC, 1, &buf); + err = regmap_set_bits(pcf8563->regmap, PCF8563_REG_TMRC, + PCF8563_TMRC_1_60); if (err < 0) { dev_err(&client->dev, "%s: write error\n", __func__); return err; } /* Clear flags and disable interrupts */ - buf = 0; - err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, &buf); + err = regmap_write(pcf8563->regmap, PCF8563_REG_ST2, 0); if (err < 0) { dev_err(&client->dev, "%s: write error\n", __func__); return err; @@ -553,6 +510,7 @@ static int pcf8563_probe(struct i2c_client *client) /* the pcf8563 alarm only supports a minute accuracy */ set_bit(RTC_FEATURE_ALARM_RES_MINUTE, pcf8563->rtc->features); clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, pcf8563->rtc->features); + clear_bit(RTC_FEATURE_ALARM, pcf8563->rtc->features); pcf8563->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; pcf8563->rtc->range_max = RTC_TIMESTAMP_END_2099; pcf8563->rtc->set_start_time = true; @@ -573,7 +531,12 @@ static int pcf8563_probe(struct i2c_client *client) return err; } } else { - clear_bit(RTC_FEATURE_ALARM, pcf8563->rtc->features); + client->irq = 0; + } + + if (client->irq > 0 || device_property_read_bool(&client->dev, "wakeup-source")) { + device_init_wakeup(&client->dev, true); + set_bit(RTC_FEATURE_ALARM, pcf8563->rtc->features); } err = devm_rtc_register_device(pcf8563->rtc); @@ -589,9 +552,9 @@ static int pcf8563_probe(struct i2c_client *client) } static const struct i2c_device_id pcf8563_id[] = { - { "pcf8563", 0 }, - { "rtc8564", 0 }, - { "pca8565", 0 }, + { "pcf8563" }, + { "rtc8564" }, + { "pca8565" }, { } }; MODULE_DEVICE_TABLE(i2c, pcf8563_id); diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index a7e0fc360b6a..652b9dfa7566 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c @@ -297,7 +297,7 @@ static int pcf8583_probe(struct i2c_client *client) } static const struct i2c_device_id pcf8583_id[] = { - { "pcf8583", 0 }, + { "pcf8583" }, { } }; MODULE_DEVICE_TABLE(i2c, pcf8583_id); diff --git a/drivers/rtc/rtc-pic32.c b/drivers/rtc/rtc-pic32.c index 4f85e0c3d757..2812da2c50c5 100644 --- a/drivers/rtc/rtc-pic32.c +++ b/drivers/rtc/rtc-pic32.c @@ -330,7 +330,7 @@ static int pic32_rtc_probe(struct platform_device *pdev) pic32_rtc_enable(pdata, 1); - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); pdata->rtc->ops = &pic32_rtcops; pdata->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; @@ -371,7 +371,7 @@ MODULE_DEVICE_TABLE(of, pic32_rtc_dt_ids); static struct platform_driver pic32_rtc_driver = { .probe = pic32_rtc_probe, - .remove_new = pic32_rtc_remove, + .remove = pic32_rtc_remove, .driver = { .name = "pic32-rtc", .of_match_table = of_match_ptr(pic32_rtc_dt_ids), diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index 39038c0754ee..5caaa714f448 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c @@ -21,7 +21,6 @@ #define RTC_CR_MIE (1 << 0) struct pl030_rtc { - struct rtc_device *rtc; void __iomem *base; }; @@ -86,6 +85,7 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id) { struct pl030_rtc *rtc; int ret; + struct rtc_device *rtc_dev; ret = amba_request_regions(dev, NULL); if (ret) @@ -97,14 +97,14 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id) goto err_rtc; } - rtc->rtc = devm_rtc_allocate_device(&dev->dev); - if (IS_ERR(rtc->rtc)) { - ret = PTR_ERR(rtc->rtc); + rtc_dev = devm_rtc_allocate_device(&dev->dev); + if (IS_ERR(rtc_dev)) { + ret = PTR_ERR(rtc_dev); goto err_rtc; } - rtc->rtc->ops = &pl030_ops; - rtc->rtc->range_max = U32_MAX; + rtc_dev->ops = &pl030_ops; + rtc_dev->range_max = U32_MAX; rtc->base = ioremap(dev->res.start, resource_size(&dev->res)); if (!rtc->base) { ret = -ENOMEM; @@ -121,7 +121,7 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id) if (ret) goto err_irq; - ret = devm_rtc_register_device(rtc->rtc); + ret = devm_rtc_register_device(rtc_dev); if (ret) goto err_reg; @@ -148,7 +148,7 @@ static void pl030_remove(struct amba_device *dev) amba_release_regions(dev); } -static struct amba_id pl030_ids[] = { +static const struct amba_id pl030_ids[] = { { .id = 0x00041030, .mask = 0x000fffff, diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index bad6a5d9c683..eab39dfa4e5f 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -74,6 +74,8 @@ * @st_weekday: if this is an ST Microelectronics silicon version that need * the weekday fix * @irqflags: special IRQ flags per variant + * @range_min: minimum date/time supported by the RTC + * @range_max: maximum date/time supported by the RTC */ struct pl031_vendor_data { struct rtc_class_ops ops; @@ -284,8 +286,6 @@ static void pl031_remove(struct amba_device *adev) { struct pl031_local *ldata = dev_get_drvdata(&adev->dev); - dev_pm_clear_wake_irq(&adev->dev); - device_init_wakeup(&adev->dev, false); if (adev->irq[0]) free_irq(adev->irq[0], ldata); amba_release_regions(adev); @@ -350,7 +350,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) } } - device_init_wakeup(&adev->dev, true); + devm_device_init_wakeup(&adev->dev); ldata->rtc = devm_rtc_allocate_device(&adev->dev); if (IS_ERR(ldata->rtc)) { ret = PTR_ERR(ldata->rtc); @@ -373,7 +373,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) vendor->irqflags, "rtc-pl031", ldata); if (ret) goto out; - dev_pm_set_wake_irq(&adev->dev, adev->irq[0]); + devm_pm_set_wake_irq(&adev->dev, adev->irq[0]); } return 0; diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index f6b779c12ca7..3c1dddcc81df 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -5,6 +5,7 @@ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. * Copyright (c) 2023, Linaro Limited */ +#include <linux/efi.h> #include <linux/of.h> #include <linux/module.h> #include <linux/nvmem-consumer.h> @@ -16,8 +17,9 @@ #include <linux/regmap.h> #include <linux/slab.h> #include <linux/spinlock.h> +#include <linux/unaligned.h> -#include <asm/unaligned.h> +#include <asm/byteorder.h> /* RTC_CTRL register bit fields */ #define PM8xxx_RTC_ENABLE BIT(7) @@ -46,28 +48,125 @@ struct pm8xxx_rtc_regs { unsigned int alarm_en; }; +struct qcom_uefi_rtc_info { + __le32 offset_gps; + u8 reserved[8]; +} __packed; + /** * struct pm8xxx_rtc - RTC driver internal structure * @rtc: RTC device * @regmap: regmap used to access registers * @allow_set_time: whether the time can be set + * @use_uefi: use UEFI variable as fallback for offset * @alarm_irq: alarm irq number * @regs: register description * @dev: device structure + * @rtc_info: qcom uefi rtc-info structure * @nvmem_cell: nvmem cell for offset * @offset: offset from epoch in seconds + * @offset_dirty: offset needs to be stored on shutdown */ struct pm8xxx_rtc { struct rtc_device *rtc; struct regmap *regmap; bool allow_set_time; + bool use_uefi; int alarm_irq; const struct pm8xxx_rtc_regs *regs; struct device *dev; + struct qcom_uefi_rtc_info rtc_info; struct nvmem_cell *nvmem_cell; u32 offset; + bool offset_dirty; }; +#ifdef CONFIG_EFI + +MODULE_IMPORT_NS("EFIVAR"); + +#define QCOM_UEFI_NAME L"RTCInfo" +#define QCOM_UEFI_GUID EFI_GUID(0x882f8c2b, 0x9646, 0x435f, \ + 0x8d, 0xe5, 0xf2, 0x08, 0xff, 0x80, 0xc1, 0xbd) +#define QCOM_UEFI_ATTRS (EFI_VARIABLE_NON_VOLATILE | \ + EFI_VARIABLE_BOOTSERVICE_ACCESS | \ + EFI_VARIABLE_RUNTIME_ACCESS) + +static int pm8xxx_rtc_read_uefi_offset(struct pm8xxx_rtc *rtc_dd) +{ + struct qcom_uefi_rtc_info *rtc_info = &rtc_dd->rtc_info; + unsigned long size = sizeof(*rtc_info); + struct device *dev = rtc_dd->dev; + efi_status_t status; + u32 offset_gps; + int rc; + + rc = efivar_lock(); + if (rc) + return rc; + + status = efivar_get_variable(QCOM_UEFI_NAME, &QCOM_UEFI_GUID, NULL, + &size, rtc_info); + efivar_unlock(); + + if (status != EFI_SUCCESS) { + dev_dbg(dev, "failed to read UEFI offset: %lu\n", status); + return efi_status_to_err(status); + } + + if (size != sizeof(*rtc_info)) { + dev_dbg(dev, "unexpected UEFI structure size %lu\n", size); + return -EINVAL; + } + + dev_dbg(dev, "uefi_rtc_info = %*ph\n", (int)size, rtc_info); + + /* Convert from GPS to Unix time offset */ + offset_gps = le32_to_cpu(rtc_info->offset_gps); + rtc_dd->offset = offset_gps + (u32)RTC_TIMESTAMP_EPOCH_GPS; + + return 0; +} + +static int pm8xxx_rtc_write_uefi_offset(struct pm8xxx_rtc *rtc_dd, u32 offset) +{ + struct qcom_uefi_rtc_info *rtc_info = &rtc_dd->rtc_info; + unsigned long size = sizeof(*rtc_info); + struct device *dev = rtc_dd->dev; + efi_status_t status; + u32 offset_gps; + + /* Convert from Unix to GPS time offset */ + offset_gps = offset - (u32)RTC_TIMESTAMP_EPOCH_GPS; + + rtc_info->offset_gps = cpu_to_le32(offset_gps); + + dev_dbg(dev, "efi_rtc_info = %*ph\n", (int)size, rtc_info); + + status = efivar_set_variable(QCOM_UEFI_NAME, &QCOM_UEFI_GUID, + QCOM_UEFI_ATTRS, size, rtc_info); + if (status != EFI_SUCCESS) { + dev_dbg(dev, "failed to write UEFI offset: %lx\n", status); + return efi_status_to_err(status); + } + + return 0; +} + +#else /* CONFIG_EFI */ + +static int pm8xxx_rtc_read_uefi_offset(struct pm8xxx_rtc *rtc_dd) +{ + return -ENODEV; +} + +static int pm8xxx_rtc_write_uefi_offset(struct pm8xxx_rtc *rtc_dd, u32 offset) +{ + return -ENODEV; +} + +#endif /* CONFIG_EFI */ + static int pm8xxx_rtc_read_nvmem_offset(struct pm8xxx_rtc *rtc_dd) { size_t len; @@ -110,14 +209,6 @@ static int pm8xxx_rtc_write_nvmem_offset(struct pm8xxx_rtc *rtc_dd, u32 offset) return 0; } -static int pm8xxx_rtc_read_offset(struct pm8xxx_rtc *rtc_dd) -{ - if (!rtc_dd->nvmem_cell) - return 0; - - return pm8xxx_rtc_read_nvmem_offset(rtc_dd); -} - static int pm8xxx_rtc_read_raw(struct pm8xxx_rtc *rtc_dd, u32 *secs) { const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; @@ -155,7 +246,7 @@ static int pm8xxx_rtc_update_offset(struct pm8xxx_rtc *rtc_dd, u32 secs) u32 offset; int rc; - if (!rtc_dd->nvmem_cell) + if (!rtc_dd->nvmem_cell && !rtc_dd->use_uefi) return -ENODEV; rc = pm8xxx_rtc_read_raw(rtc_dd, &raw_secs); @@ -167,10 +258,25 @@ static int pm8xxx_rtc_update_offset(struct pm8xxx_rtc *rtc_dd, u32 secs) if (offset == rtc_dd->offset) return 0; - rc = pm8xxx_rtc_write_nvmem_offset(rtc_dd, offset); + /* + * Reduce flash wear by deferring updates due to clock drift until + * shutdown. + */ + if (abs_diff(offset, rtc_dd->offset) < 30) { + rtc_dd->offset_dirty = true; + goto out; + } + + if (rtc_dd->nvmem_cell) + rc = pm8xxx_rtc_write_nvmem_offset(rtc_dd, offset); + else + rc = pm8xxx_rtc_write_uefi_offset(rtc_dd, offset); + if (rc) return rc; + rtc_dd->offset_dirty = false; +out: rtc_dd->offset = offset; return 0; @@ -455,6 +561,30 @@ static const struct of_device_id pm8xxx_id_table[] = { }; MODULE_DEVICE_TABLE(of, pm8xxx_id_table); +static int pm8xxx_rtc_probe_offset(struct pm8xxx_rtc *rtc_dd) +{ + int rc; + + rtc_dd->nvmem_cell = devm_nvmem_cell_get(rtc_dd->dev, "offset"); + if (IS_ERR(rtc_dd->nvmem_cell)) { + rc = PTR_ERR(rtc_dd->nvmem_cell); + if (rc != -ENOENT) + return rc; + rtc_dd->nvmem_cell = NULL; + } else { + return pm8xxx_rtc_read_nvmem_offset(rtc_dd); + } + + /* Use UEFI storage as fallback if available */ + if (efivar_is_available()) { + rc = pm8xxx_rtc_read_uefi_offset(rtc_dd); + if (rc == 0) + rtc_dd->use_uefi = true; + } + + return 0; +} + static int pm8xxx_rtc_probe(struct platform_device *pdev) { const struct of_device_id *match; @@ -469,30 +599,23 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev) if (rtc_dd == NULL) return -ENOMEM; + rtc_dd->regs = match->data; + rtc_dd->dev = &pdev->dev; + rtc_dd->regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!rtc_dd->regmap) return -ENXIO; - rtc_dd->alarm_irq = platform_get_irq(pdev, 0); - if (rtc_dd->alarm_irq < 0) - return -ENXIO; + if (!of_property_read_bool(pdev->dev.of_node, "qcom,no-alarm")) { + rtc_dd->alarm_irq = platform_get_irq(pdev, 0); + if (rtc_dd->alarm_irq < 0) + return -ENXIO; + } rtc_dd->allow_set_time = of_property_read_bool(pdev->dev.of_node, "allow-set-time"); - - rtc_dd->nvmem_cell = devm_nvmem_cell_get(&pdev->dev, "offset"); - if (IS_ERR(rtc_dd->nvmem_cell)) { - rc = PTR_ERR(rtc_dd->nvmem_cell); - if (rc != -ENOENT) - return rc; - rtc_dd->nvmem_cell = NULL; - } - - rtc_dd->regs = match->data; - rtc_dd->dev = &pdev->dev; - if (!rtc_dd->allow_set_time) { - rc = pm8xxx_rtc_read_offset(rtc_dd); + rc = pm8xxx_rtc_probe_offset(rtc_dd); if (rc) return rc; } @@ -503,8 +626,6 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc_dd); - device_init_wakeup(&pdev->dev, 1); - rtc_dd->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc_dd->rtc)) return PTR_ERR(rtc_dd->rtc); @@ -512,32 +633,41 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev) rtc_dd->rtc->ops = &pm8xxx_rtc_ops; rtc_dd->rtc->range_max = U32_MAX; - rc = devm_request_any_context_irq(&pdev->dev, rtc_dd->alarm_irq, - pm8xxx_alarm_trigger, - IRQF_TRIGGER_RISING, - "pm8xxx_rtc_alarm", rtc_dd); - if (rc < 0) - return rc; + if (rtc_dd->alarm_irq) { + rc = devm_request_any_context_irq(&pdev->dev, rtc_dd->alarm_irq, + pm8xxx_alarm_trigger, + IRQF_TRIGGER_RISING, + "pm8xxx_rtc_alarm", rtc_dd); + if (rc < 0) + return rc; - rc = devm_rtc_register_device(rtc_dd->rtc); - if (rc) - return rc; + rc = devm_pm_set_wake_irq(&pdev->dev, rtc_dd->alarm_irq); + if (rc) + return rc; - rc = dev_pm_set_wake_irq(&pdev->dev, rtc_dd->alarm_irq); - if (rc) - return rc; + devm_device_init_wakeup(&pdev->dev); + } else { + clear_bit(RTC_FEATURE_ALARM, rtc_dd->rtc->features); + } - return 0; + return devm_rtc_register_device(rtc_dd->rtc); } -static void pm8xxx_remove(struct platform_device *pdev) +static void pm8xxx_shutdown(struct platform_device *pdev) { - dev_pm_clear_wake_irq(&pdev->dev); + struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev); + + if (rtc_dd->offset_dirty) { + if (rtc_dd->nvmem_cell) + pm8xxx_rtc_write_nvmem_offset(rtc_dd, rtc_dd->offset); + else + pm8xxx_rtc_write_uefi_offset(rtc_dd, rtc_dd->offset); + } } static struct platform_driver pm8xxx_rtc_driver = { .probe = pm8xxx_rtc_probe, - .remove_new = pm8xxx_remove, + .shutdown = pm8xxx_shutdown, .driver = { .name = "rtc-pm8xxx", .of_match_table = pm8xxx_id_table, diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index cdb39fc4cab5..62ee6b8f9bcd 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c @@ -360,7 +360,7 @@ static int __init pxa_rtc_probe(struct platform_device *pdev) return ret; } - device_init_wakeup(dev, 1); + device_init_wakeup(dev, true); return 0; } @@ -409,7 +409,7 @@ static SIMPLE_DEV_PM_OPS(pxa_rtc_pm_ops, pxa_rtc_suspend, pxa_rtc_resume); * triggering a section mismatch warning. */ static struct platform_driver pxa_rtc_driver __refdata = { - .remove_new = __exit_p(pxa_rtc_remove), + .remove = __exit_p(pxa_rtc_remove), .driver = { .name = "pxa-rtc", .of_match_table = of_match_ptr(pxa_rtc_dt_ids), diff --git a/drivers/rtc/rtc-rc5t583.c b/drivers/rtc/rtc-rc5t583.c index 6f4bf919827a..8ba9cda74acf 100644 --- a/drivers/rtc/rtc-rc5t583.c +++ b/drivers/rtc/rtc-rc5t583.c @@ -245,7 +245,7 @@ static int rc5t583_rtc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "IRQ is not free.\n"); return ret; } - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); ricoh_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &rc5t583_rtc_ops, THIS_MODULE); @@ -298,7 +298,7 @@ static SIMPLE_DEV_PM_OPS(rc5t583_rtc_pm_ops, rc5t583_rtc_suspend, static struct platform_driver rc5t583_rtc_driver = { .probe = rc5t583_rtc_probe, - .remove_new = rc5t583_rtc_remove, + .remove = rc5t583_rtc_remove, .driver = { .name = "rtc-rc5t583", .pm = &rc5t583_rtc_pm_ops, @@ -308,4 +308,5 @@ static struct platform_driver rc5t583_rtc_driver = { module_platform_driver(rc5t583_rtc_driver); MODULE_ALIAS("platform:rtc-rc5t583"); MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>"); +MODULE_DESCRIPTION("RICOH 5T583 RTC driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/rtc-rc5t619.c b/drivers/rtc/rtc-rc5t619.c index e73102a39f1b..74d169102074 100644 --- a/drivers/rtc/rtc-rc5t619.c +++ b/drivers/rtc/rtc-rc5t619.c @@ -414,7 +414,7 @@ static int rc5t619_rtc_probe(struct platform_device *pdev) } else { /* enable wake */ - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); enable_irq_wake(rtc->irq); } } else { @@ -429,14 +429,23 @@ static int rc5t619_rtc_probe(struct platform_device *pdev) return devm_rtc_register_device(rtc->rtc); } +static const struct platform_device_id rc5t619_rtc_id[] = { + { + .name = "rc5t619-rtc", + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(platform, rc5t619_rtc_id); + static struct platform_driver rc5t619_rtc_driver = { .driver = { .name = "rc5t619-rtc", }, .probe = rc5t619_rtc_probe, + .id_table = rc5t619_rtc_id, }; - module_platform_driver(rc5t619_rtc_driver); -MODULE_ALIAS("platform:rc5t619-rtc"); + MODULE_DESCRIPTION("RICOH RC5T619 RTC driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-renesas-rtca3.c b/drivers/rtc/rtc-renesas-rtca3.c new file mode 100644 index 000000000000..ab816bdf0d77 --- /dev/null +++ b/drivers/rtc/rtc-renesas-rtca3.c @@ -0,0 +1,897 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * On-Chip RTC Support available on RZ/G3S SoC + * + * Copyright (C) 2024 Renesas Electronics Corp. + */ +#include <linux/bcd.h> +#include <linux/bitfield.h> +#include <linux/cleanup.h> +#include <linux/clk.h> +#include <linux/completion.h> +#include <linux/delay.h> +#include <linux/iopoll.h> +#include <linux/interrupt.h> +#include <linux/jiffies.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/reset.h> +#include <linux/rtc.h> + +/* Counter registers. */ +#define RTCA3_RSECCNT 0x2 +#define RTCA3_RSECCNT_SEC GENMASK(6, 0) +#define RTCA3_RMINCNT 0x4 +#define RTCA3_RMINCNT_MIN GENMASK(6, 0) +#define RTCA3_RHRCNT 0x6 +#define RTCA3_RHRCNT_HR GENMASK(5, 0) +#define RTCA3_RHRCNT_PM BIT(6) +#define RTCA3_RWKCNT 0x8 +#define RTCA3_RWKCNT_WK GENMASK(2, 0) +#define RTCA3_RDAYCNT 0xa +#define RTCA3_RDAYCNT_DAY GENMASK(5, 0) +#define RTCA3_RMONCNT 0xc +#define RTCA3_RMONCNT_MONTH GENMASK(4, 0) +#define RTCA3_RYRCNT 0xe +#define RTCA3_RYRCNT_YEAR GENMASK(7, 0) + +/* Alarm registers. */ +#define RTCA3_RSECAR 0x10 +#define RTCA3_RSECAR_SEC GENMASK(6, 0) +#define RTCA3_RMINAR 0x12 +#define RTCA3_RMINAR_MIN GENMASK(6, 0) +#define RTCA3_RHRAR 0x14 +#define RTCA3_RHRAR_HR GENMASK(5, 0) +#define RTCA3_RHRAR_PM BIT(6) +#define RTCA3_RWKAR 0x16 +#define RTCA3_RWKAR_DAYW GENMASK(2, 0) +#define RTCA3_RDAYAR 0x18 +#define RTCA3_RDAYAR_DATE GENMASK(5, 0) +#define RTCA3_RMONAR 0x1a +#define RTCA3_RMONAR_MON GENMASK(4, 0) +#define RTCA3_RYRAR 0x1c +#define RTCA3_RYRAR_YR GENMASK(7, 0) +#define RTCA3_RYRAREN 0x1e + +/* Alarm enable bit (for all alarm registers). */ +#define RTCA3_AR_ENB BIT(7) + +/* Control registers. */ +#define RTCA3_RCR1 0x22 +#define RTCA3_RCR1_AIE BIT(0) +#define RTCA3_RCR1_CIE BIT(1) +#define RTCA3_RCR1_PIE BIT(2) +#define RTCA3_RCR1_PES GENMASK(7, 4) +#define RTCA3_RCR1_PES_1_64_SEC 0x8 +#define RTCA3_RCR2 0x24 +#define RTCA3_RCR2_START BIT(0) +#define RTCA3_RCR2_RESET BIT(1) +#define RTCA3_RCR2_AADJE BIT(4) +#define RTCA3_RCR2_ADJP BIT(5) +#define RTCA3_RCR2_HR24 BIT(6) +#define RTCA3_RCR2_CNTMD BIT(7) +#define RTCA3_RSR 0x20 +#define RTCA3_RSR_AF BIT(0) +#define RTCA3_RSR_CF BIT(1) +#define RTCA3_RSR_PF BIT(2) +#define RTCA3_RADJ 0x2e +#define RTCA3_RADJ_ADJ GENMASK(5, 0) +#define RTCA3_RADJ_ADJ_MAX 0x3f +#define RTCA3_RADJ_PMADJ GENMASK(7, 6) +#define RTCA3_RADJ_PMADJ_NONE 0 +#define RTCA3_RADJ_PMADJ_ADD 1 +#define RTCA3_RADJ_PMADJ_SUB 2 + +/* Polling operation timeouts. */ +#define RTCA3_DEFAULT_TIMEOUT_US 150 +#define RTCA3_IRQSET_TIMEOUT_US 5000 +#define RTCA3_START_TIMEOUT_US 150000 +#define RTCA3_RESET_TIMEOUT_US 200000 + +/** + * enum rtca3_alrm_set_step - RTCA3 alarm set steps + * @RTCA3_ALRM_SSTEP_DONE: alarm setup done step + * @RTCA3_ALRM_SSTEP_IRQ: two 1/64 periodic IRQs were generated step + * @RTCA3_ALRM_SSTEP_INIT: alarm setup initialization step + */ +enum rtca3_alrm_set_step { + RTCA3_ALRM_SSTEP_DONE = 0, + RTCA3_ALRM_SSTEP_IRQ = 1, + RTCA3_ALRM_SSTEP_INIT = 3, +}; + +/** + * struct rtca3_ppb_per_cycle - PPB per cycle + * @ten_sec: PPB per cycle in 10 seconds adjutment mode + * @sixty_sec: PPB per cycle in 60 seconds adjustment mode + */ +struct rtca3_ppb_per_cycle { + int ten_sec; + int sixty_sec; +}; + +/** + * struct rtca3_priv - RTCA3 private data structure + * @base: base address + * @rtc_dev: RTC device + * @rstc: reset control + * @set_alarm_completion: alarm setup completion + * @alrm_sstep: alarm setup step (see enum rtca3_alrm_set_step) + * @lock: device lock + * @ppb: ppb per cycle for each the available adjustment modes + * @wakeup_irq: wakeup IRQ + */ +struct rtca3_priv { + void __iomem *base; + struct rtc_device *rtc_dev; + struct reset_control *rstc; + struct completion set_alarm_completion; + atomic_t alrm_sstep; + spinlock_t lock; + struct rtca3_ppb_per_cycle ppb; + int wakeup_irq; +}; + +static void rtca3_byte_update_bits(struct rtca3_priv *priv, u8 off, u8 mask, u8 val) +{ + u8 tmp; + + tmp = readb(priv->base + off); + tmp &= ~mask; + tmp |= (val & mask); + writeb(tmp, priv->base + off); +} + +static u8 rtca3_alarm_handler_helper(struct rtca3_priv *priv) +{ + u8 val, pending; + + val = readb(priv->base + RTCA3_RSR); + pending = val & RTCA3_RSR_AF; + writeb(val & ~pending, priv->base + RTCA3_RSR); + + if (pending) + rtc_update_irq(priv->rtc_dev, 1, RTC_AF | RTC_IRQF); + + return pending; +} + +static irqreturn_t rtca3_alarm_handler(int irq, void *dev_id) +{ + struct rtca3_priv *priv = dev_id; + u8 pending; + + guard(spinlock)(&priv->lock); + + pending = rtca3_alarm_handler_helper(priv); + + return IRQ_RETVAL(pending); +} + +static irqreturn_t rtca3_periodic_handler(int irq, void *dev_id) +{ + struct rtca3_priv *priv = dev_id; + u8 val, pending; + + guard(spinlock)(&priv->lock); + + val = readb(priv->base + RTCA3_RSR); + pending = val & RTCA3_RSR_PF; + + if (pending) { + writeb(val & ~pending, priv->base + RTCA3_RSR); + + if (atomic_read(&priv->alrm_sstep) > RTCA3_ALRM_SSTEP_IRQ) { + /* Alarm setup in progress. */ + atomic_dec(&priv->alrm_sstep); + + if (atomic_read(&priv->alrm_sstep) == RTCA3_ALRM_SSTEP_IRQ) { + /* + * We got 2 * 1/64 periodic interrupts. Disable + * interrupt and let alarm setup continue. + */ + rtca3_byte_update_bits(priv, RTCA3_RCR1, + RTCA3_RCR1_PIE, 0); + readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, val, + !(val & RTCA3_RCR1_PIE), + 10, RTCA3_DEFAULT_TIMEOUT_US); + complete(&priv->set_alarm_completion); + } + } + } + + return IRQ_RETVAL(pending); +} + +static void rtca3_prepare_cntalrm_regs_for_read(struct rtca3_priv *priv, bool cnt) +{ + /* Offset b/w time and alarm registers. */ + u8 offset = cnt ? 0 : 0xe; + + /* + * According to HW manual (section 22.6.4. Notes on writing to and + * reading from registers) after writing to count registers, alarm + * registers, year alarm enable register, bits RCR2.AADJE, AADJP, + * and HR24 register, we need to do 3 empty reads before being + * able to fetch the registers content. + */ + for (u8 i = 0; i < 3; i++) { + readb(priv->base + RTCA3_RSECCNT + offset); + readb(priv->base + RTCA3_RMINCNT + offset); + readb(priv->base + RTCA3_RHRCNT + offset); + readb(priv->base + RTCA3_RWKCNT + offset); + readb(priv->base + RTCA3_RDAYCNT + offset); + readw(priv->base + RTCA3_RYRCNT + offset); + if (!cnt) + readb(priv->base + RTCA3_RYRAREN); + } +} + +static int rtca3_read_time(struct device *dev, struct rtc_time *tm) +{ + struct rtca3_priv *priv = dev_get_drvdata(dev); + u8 sec, min, hour, wday, mday, month, tmp; + u8 trials = 0; + u32 year100; + u16 year; + + guard(spinlock_irqsave)(&priv->lock); + + tmp = readb(priv->base + RTCA3_RCR2); + if (!(tmp & RTCA3_RCR2_START)) + return -EINVAL; + + do { + /* Clear carry interrupt. */ + rtca3_byte_update_bits(priv, RTCA3_RSR, RTCA3_RSR_CF, 0); + + /* Read counters. */ + sec = readb(priv->base + RTCA3_RSECCNT); + min = readb(priv->base + RTCA3_RMINCNT); + hour = readb(priv->base + RTCA3_RHRCNT); + wday = readb(priv->base + RTCA3_RWKCNT); + mday = readb(priv->base + RTCA3_RDAYCNT); + month = readb(priv->base + RTCA3_RMONCNT); + year = readw(priv->base + RTCA3_RYRCNT); + + tmp = readb(priv->base + RTCA3_RSR); + + /* + * We cannot generate carries due to reading 64Hz counter as + * the driver doesn't implement carry, thus, carries will be + * generated once per seconds. Add a timeout of 5 trials here + * to avoid infinite loop, if any. + */ + } while ((tmp & RTCA3_RSR_CF) && ++trials < 5); + + if (trials >= 5) + return -ETIMEDOUT; + + tm->tm_sec = bcd2bin(FIELD_GET(RTCA3_RSECCNT_SEC, sec)); + tm->tm_min = bcd2bin(FIELD_GET(RTCA3_RMINCNT_MIN, min)); + tm->tm_hour = bcd2bin(FIELD_GET(RTCA3_RHRCNT_HR, hour)); + tm->tm_wday = bcd2bin(FIELD_GET(RTCA3_RWKCNT_WK, wday)); + tm->tm_mday = bcd2bin(FIELD_GET(RTCA3_RDAYCNT_DAY, mday)); + tm->tm_mon = bcd2bin(FIELD_GET(RTCA3_RMONCNT_MONTH, month)) - 1; + year = FIELD_GET(RTCA3_RYRCNT_YEAR, year); + year100 = bcd2bin((year == 0x99) ? 0x19 : 0x20); + tm->tm_year = (year100 * 100 + bcd2bin(year)) - 1900; + + return 0; +} + +static int rtca3_set_time(struct device *dev, struct rtc_time *tm) +{ + struct rtca3_priv *priv = dev_get_drvdata(dev); + u8 rcr2, tmp; + int ret; + + guard(spinlock_irqsave)(&priv->lock); + + /* Stop the RTC. */ + rcr2 = readb(priv->base + RTCA3_RCR2); + writeb(rcr2 & ~RTCA3_RCR2_START, priv->base + RTCA3_RCR2); + ret = readb_poll_timeout_atomic(priv->base + RTCA3_RCR2, tmp, + !(tmp & RTCA3_RCR2_START), + 10, RTCA3_DEFAULT_TIMEOUT_US); + if (ret) + return ret; + + /* Update time. */ + writeb(bin2bcd(tm->tm_sec), priv->base + RTCA3_RSECCNT); + writeb(bin2bcd(tm->tm_min), priv->base + RTCA3_RMINCNT); + writeb(bin2bcd(tm->tm_hour), priv->base + RTCA3_RHRCNT); + writeb(bin2bcd(tm->tm_wday), priv->base + RTCA3_RWKCNT); + writeb(bin2bcd(tm->tm_mday), priv->base + RTCA3_RDAYCNT); + writeb(bin2bcd(tm->tm_mon + 1), priv->base + RTCA3_RMONCNT); + writew(bin2bcd(tm->tm_year % 100), priv->base + RTCA3_RYRCNT); + + /* Make sure we can read back the counters. */ + rtca3_prepare_cntalrm_regs_for_read(priv, true); + + /* Start RTC. */ + writeb(rcr2 | RTCA3_RCR2_START, priv->base + RTCA3_RCR2); + return readb_poll_timeout_atomic(priv->base + RTCA3_RCR2, tmp, + (tmp & RTCA3_RCR2_START), + 10, RTCA3_DEFAULT_TIMEOUT_US); +} + +static int rtca3_alarm_irq_set_helper(struct rtca3_priv *priv, + u8 interrupts, + unsigned int enabled) +{ + u8 tmp, val; + + if (enabled) { + /* + * AIE, CIE, PIE bit indexes in RSR corresponds with + * those on RCR1. Same interrupts mask can be used. + */ + rtca3_byte_update_bits(priv, RTCA3_RSR, interrupts, 0); + val = interrupts; + } else { + val = 0; + } + + rtca3_byte_update_bits(priv, RTCA3_RCR1, interrupts, val); + return readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp, + ((tmp & interrupts) == val), + 10, RTCA3_IRQSET_TIMEOUT_US); +} + +static int rtca3_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct rtca3_priv *priv = dev_get_drvdata(dev); + + guard(spinlock_irqsave)(&priv->lock); + + return rtca3_alarm_irq_set_helper(priv, RTCA3_RCR1_AIE, enabled); +} + +static int rtca3_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) +{ + struct rtca3_priv *priv = dev_get_drvdata(dev); + u8 sec, min, hour, wday, mday, month; + struct rtc_time *tm = &wkalrm->time; + u32 year100; + u16 year; + + guard(spinlock_irqsave)(&priv->lock); + + sec = readb(priv->base + RTCA3_RSECAR); + min = readb(priv->base + RTCA3_RMINAR); + hour = readb(priv->base + RTCA3_RHRAR); + wday = readb(priv->base + RTCA3_RWKAR); + mday = readb(priv->base + RTCA3_RDAYAR); + month = readb(priv->base + RTCA3_RMONAR); + year = readw(priv->base + RTCA3_RYRAR); + + tm->tm_sec = bcd2bin(FIELD_GET(RTCA3_RSECAR_SEC, sec)); + tm->tm_min = bcd2bin(FIELD_GET(RTCA3_RMINAR_MIN, min)); + tm->tm_hour = bcd2bin(FIELD_GET(RTCA3_RHRAR_HR, hour)); + tm->tm_wday = bcd2bin(FIELD_GET(RTCA3_RWKAR_DAYW, wday)); + tm->tm_mday = bcd2bin(FIELD_GET(RTCA3_RDAYAR_DATE, mday)); + tm->tm_mon = bcd2bin(FIELD_GET(RTCA3_RMONAR_MON, month)) - 1; + year = FIELD_GET(RTCA3_RYRAR_YR, year); + year100 = bcd2bin((year == 0x99) ? 0x19 : 0x20); + tm->tm_year = (year100 * 100 + bcd2bin(year)) - 1900; + + wkalrm->enabled = !!(readb(priv->base + RTCA3_RCR1) & RTCA3_RCR1_AIE); + + return 0; +} + +static int rtca3_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) +{ + struct rtca3_priv *priv = dev_get_drvdata(dev); + struct rtc_time *tm = &wkalrm->time; + u8 rcr1, tmp; + int ret; + + scoped_guard(spinlock_irqsave, &priv->lock) { + tmp = readb(priv->base + RTCA3_RCR2); + if (!(tmp & RTCA3_RCR2_START)) + return -EPERM; + + /* Disable AIE to prevent false interrupts. */ + rcr1 = readb(priv->base + RTCA3_RCR1); + rcr1 &= ~RTCA3_RCR1_AIE; + writeb(rcr1, priv->base + RTCA3_RCR1); + ret = readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp, + !(tmp & RTCA3_RCR1_AIE), + 10, RTCA3_DEFAULT_TIMEOUT_US); + if (ret) + return ret; + + /* Set the time and enable the alarm. */ + writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_sec), priv->base + RTCA3_RSECAR); + writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_min), priv->base + RTCA3_RMINAR); + writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_hour), priv->base + RTCA3_RHRAR); + writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_wday), priv->base + RTCA3_RWKAR); + writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_mday), priv->base + RTCA3_RDAYAR); + writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_mon + 1), priv->base + RTCA3_RMONAR); + + writew(bin2bcd(tm->tm_year % 100), priv->base + RTCA3_RYRAR); + writeb(RTCA3_AR_ENB, priv->base + RTCA3_RYRAREN); + + /* Make sure we can read back the counters. */ + rtca3_prepare_cntalrm_regs_for_read(priv, false); + + /* Need to wait for 2 * 1/64 periodic interrupts to be generated. */ + atomic_set(&priv->alrm_sstep, RTCA3_ALRM_SSTEP_INIT); + reinit_completion(&priv->set_alarm_completion); + + /* Enable periodic interrupt. */ + rcr1 |= RTCA3_RCR1_PIE; + writeb(rcr1, priv->base + RTCA3_RCR1); + ret = readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp, + (tmp & RTCA3_RCR1_PIE), + 10, RTCA3_IRQSET_TIMEOUT_US); + } + + if (ret) + goto setup_failed; + + /* Wait for the 2 * 1/64 periodic interrupts. */ + ret = wait_for_completion_interruptible_timeout(&priv->set_alarm_completion, + msecs_to_jiffies(500)); + if (ret <= 0) { + ret = -ETIMEDOUT; + goto setup_failed; + } + + scoped_guard(spinlock_irqsave, &priv->lock) { + ret = rtca3_alarm_irq_set_helper(priv, RTCA3_RCR1_AIE, wkalrm->enabled); + atomic_set(&priv->alrm_sstep, RTCA3_ALRM_SSTEP_DONE); + } + + return ret; + +setup_failed: + scoped_guard(spinlock_irqsave, &priv->lock) { + /* + * Disable PIE to avoid interrupt storm in case HW needed more than + * specified timeout for setup. + */ + writeb(rcr1 & ~RTCA3_RCR1_PIE, priv->base + RTCA3_RCR1); + readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp, !(tmp & ~RTCA3_RCR1_PIE), + 10, RTCA3_DEFAULT_TIMEOUT_US); + atomic_set(&priv->alrm_sstep, RTCA3_ALRM_SSTEP_DONE); + } + + return ret; +} + +static int rtca3_read_offset(struct device *dev, long *offset) +{ + struct rtca3_priv *priv = dev_get_drvdata(dev); + u8 val, radj, cycles; + u32 ppb_per_cycle; + + scoped_guard(spinlock_irqsave, &priv->lock) { + radj = readb(priv->base + RTCA3_RADJ); + val = readb(priv->base + RTCA3_RCR2); + } + + cycles = FIELD_GET(RTCA3_RADJ_ADJ, radj); + + if (!cycles) { + *offset = 0; + return 0; + } + + if (val & RTCA3_RCR2_ADJP) + ppb_per_cycle = priv->ppb.ten_sec; + else + ppb_per_cycle = priv->ppb.sixty_sec; + + *offset = cycles * ppb_per_cycle; + val = FIELD_GET(RTCA3_RADJ_PMADJ, radj); + if (val == RTCA3_RADJ_PMADJ_SUB) + *offset = -(*offset); + + return 0; +} + +static int rtca3_set_offset(struct device *dev, long offset) +{ + struct rtca3_priv *priv = dev_get_drvdata(dev); + int cycles, cycles10, cycles60; + u8 radj, adjp, tmp; + int ret; + + /* + * Automatic time error adjustment could be set at intervals of 10 + * or 60 seconds. + */ + cycles10 = DIV_ROUND_CLOSEST(offset, priv->ppb.ten_sec); + cycles60 = DIV_ROUND_CLOSEST(offset, priv->ppb.sixty_sec); + + /* We can set b/w 1 and 63 clock cycles. */ + if (cycles60 >= -RTCA3_RADJ_ADJ_MAX && + cycles60 <= RTCA3_RADJ_ADJ_MAX) { + cycles = cycles60; + adjp = 0; + } else if (cycles10 >= -RTCA3_RADJ_ADJ_MAX && + cycles10 <= RTCA3_RADJ_ADJ_MAX) { + cycles = cycles10; + adjp = RTCA3_RCR2_ADJP; + } else { + return -ERANGE; + } + + radj = FIELD_PREP(RTCA3_RADJ_ADJ, abs(cycles)); + if (!cycles) + radj |= FIELD_PREP(RTCA3_RADJ_PMADJ, RTCA3_RADJ_PMADJ_NONE); + else if (cycles > 0) + radj |= FIELD_PREP(RTCA3_RADJ_PMADJ, RTCA3_RADJ_PMADJ_ADD); + else + radj |= FIELD_PREP(RTCA3_RADJ_PMADJ, RTCA3_RADJ_PMADJ_SUB); + + guard(spinlock_irqsave)(&priv->lock); + + tmp = readb(priv->base + RTCA3_RCR2); + + if ((tmp & RTCA3_RCR2_ADJP) != adjp) { + /* RADJ.PMADJ need to be set to zero before setting RCR2.ADJP. */ + writeb(0, priv->base + RTCA3_RADJ); + ret = readb_poll_timeout_atomic(priv->base + RTCA3_RADJ, tmp, !tmp, + 10, RTCA3_DEFAULT_TIMEOUT_US); + if (ret) + return ret; + + rtca3_byte_update_bits(priv, RTCA3_RCR2, RTCA3_RCR2_ADJP, adjp); + ret = readb_poll_timeout_atomic(priv->base + RTCA3_RCR2, tmp, + ((tmp & RTCA3_RCR2_ADJP) == adjp), + 10, RTCA3_DEFAULT_TIMEOUT_US); + if (ret) + return ret; + } + + writeb(radj, priv->base + RTCA3_RADJ); + return readb_poll_timeout_atomic(priv->base + RTCA3_RADJ, tmp, (tmp == radj), + 10, RTCA3_DEFAULT_TIMEOUT_US); +} + +static const struct rtc_class_ops rtca3_ops = { + .read_time = rtca3_read_time, + .set_time = rtca3_set_time, + .read_alarm = rtca3_read_alarm, + .set_alarm = rtca3_set_alarm, + .alarm_irq_enable = rtca3_alarm_irq_enable, + .set_offset = rtca3_set_offset, + .read_offset = rtca3_read_offset, +}; + +static int rtca3_initial_setup(struct clk *clk, struct rtca3_priv *priv) +{ + unsigned long osc32k_rate; + u8 val, tmp, mask; + u32 sleep_us; + int ret; + + osc32k_rate = clk_get_rate(clk); + if (!osc32k_rate) + return -EINVAL; + + sleep_us = DIV_ROUND_UP_ULL(1000000ULL, osc32k_rate) * 6; + + priv->ppb.ten_sec = DIV_ROUND_CLOSEST_ULL(1000000000ULL, (osc32k_rate * 10)); + priv->ppb.sixty_sec = DIV_ROUND_CLOSEST_ULL(1000000000ULL, (osc32k_rate * 60)); + + /* + * According to HW manual (section 22.4.2. Clock and count mode setting procedure) + * we need to wait at least 6 cycles of the 32KHz clock after clock was enabled. + */ + usleep_range(sleep_us, sleep_us + 10); + + mask = RTCA3_RCR2_START | RTCA3_RCR2_HR24; + val = readb(priv->base + RTCA3_RCR2); + /* Only disable the interrupts if already started in 24 hours and calendar count mode. */ + if ((val & mask) == mask) { + /* Disable all interrupts. */ + mask = RTCA3_RCR1_AIE | RTCA3_RCR1_CIE | RTCA3_RCR1_PIE; + return rtca3_alarm_irq_set_helper(priv, mask, 0); + } + + /* Reconfigure the RTC in 24 hours and calendar count mode. */ + mask = RTCA3_RCR2_START | RTCA3_RCR2_CNTMD; + writeb(0, priv->base + RTCA3_RCR2); + ret = readb_poll_timeout(priv->base + RTCA3_RCR2, tmp, !(tmp & mask), + 10, RTCA3_DEFAULT_TIMEOUT_US); + if (ret) + return ret; + + /* + * Set 24 hours mode. According to HW manual (section 22.3.19. RTC Control + * Register 2) this needs to be done separate from stop operation. + */ + mask = RTCA3_RCR2_HR24; + val = RTCA3_RCR2_HR24; + writeb(val, priv->base + RTCA3_RCR2); + ret = readb_poll_timeout(priv->base + RTCA3_RCR2, tmp, (tmp & mask), + 10, RTCA3_DEFAULT_TIMEOUT_US); + if (ret) + return ret; + + /* Execute reset. */ + mask = RTCA3_RCR2_RESET; + writeb(val | RTCA3_RCR2_RESET, priv->base + RTCA3_RCR2); + ret = readb_poll_timeout(priv->base + RTCA3_RCR2, tmp, !(tmp & mask), + 10, RTCA3_RESET_TIMEOUT_US); + if (ret) + return ret; + + /* + * According to HW manual (section 22.6.3. Notes on writing to and reading + * from registers) after reset we need to wait 6 clock cycles before + * writing to RTC registers. + */ + usleep_range(sleep_us, sleep_us + 10); + + /* Set no adjustment. */ + writeb(0, priv->base + RTCA3_RADJ); + ret = readb_poll_timeout(priv->base + RTCA3_RADJ, tmp, !tmp, 10, + RTCA3_DEFAULT_TIMEOUT_US); + + /* Start the RTC and enable automatic time error adjustment. */ + mask = RTCA3_RCR2_START | RTCA3_RCR2_AADJE; + val |= RTCA3_RCR2_START | RTCA3_RCR2_AADJE; + writeb(val, priv->base + RTCA3_RCR2); + ret = readb_poll_timeout(priv->base + RTCA3_RCR2, tmp, ((tmp & mask) == mask), + 10, RTCA3_START_TIMEOUT_US); + if (ret) + return ret; + + /* + * According to HW manual (section 22.6.4. Notes on writing to and reading + * from registers) we need to wait 1/128 seconds while the clock is operating + * (RCR2.START bit = 1) to be able to read the counters after a return from + * reset. + */ + usleep_range(8000, 9000); + + /* Set period interrupt to 1/64 seconds. It is necessary for alarm setup. */ + val = FIELD_PREP(RTCA3_RCR1_PES, RTCA3_RCR1_PES_1_64_SEC); + rtca3_byte_update_bits(priv, RTCA3_RCR1, RTCA3_RCR1_PES, val); + return readb_poll_timeout(priv->base + RTCA3_RCR1, tmp, ((tmp & RTCA3_RCR1_PES) == val), + 10, RTCA3_DEFAULT_TIMEOUT_US); +} + +static int rtca3_request_irqs(struct platform_device *pdev, struct rtca3_priv *priv) +{ + struct device *dev = &pdev->dev; + int ret, irq; + + irq = platform_get_irq_byname(pdev, "alarm"); + if (irq < 0) + return dev_err_probe(dev, irq, "Failed to get alarm IRQ!\n"); + + ret = devm_request_irq(dev, irq, rtca3_alarm_handler, 0, "rtca3-alarm", priv); + if (ret) + return dev_err_probe(dev, ret, "Failed to request alarm IRQ!\n"); + priv->wakeup_irq = irq; + + irq = platform_get_irq_byname(pdev, "period"); + if (irq < 0) + return dev_err_probe(dev, irq, "Failed to get period IRQ!\n"); + + ret = devm_request_irq(dev, irq, rtca3_periodic_handler, 0, "rtca3-period", priv); + if (ret) + return dev_err_probe(dev, ret, "Failed to request period IRQ!\n"); + + /* + * Driver doesn't implement carry handler. Just get the IRQ here + * for backward compatibility, in case carry support will be added later. + */ + irq = platform_get_irq_byname(pdev, "carry"); + if (irq < 0) + return dev_err_probe(dev, irq, "Failed to get carry IRQ!\n"); + + return 0; +} + +static void rtca3_action(void *data) +{ + struct device *dev = data; + struct rtca3_priv *priv = dev_get_drvdata(dev); + int ret; + + ret = reset_control_assert(priv->rstc); + if (ret) + dev_err(dev, "Failed to de-assert reset!"); + + ret = pm_runtime_put_sync(dev); + if (ret < 0) + dev_err(dev, "Failed to runtime suspend!"); +} + +static int rtca3_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct rtca3_priv *priv; + struct clk *clk; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; + + priv->rstc = devm_reset_control_get_shared(dev, NULL); + if (IS_ERR(priv->rstc)) + return PTR_ERR(priv->rstc); + + ret = pm_runtime_resume_and_get(dev); + if (ret) + return ret; + + ret = reset_control_deassert(priv->rstc); + if (ret) { + pm_runtime_put_sync(dev); + return ret; + } + + dev_set_drvdata(dev, priv); + ret = devm_add_action_or_reset(dev, rtca3_action, dev); + if (ret) + return ret; + + /* + * This must be an always-on clock to keep the RTC running even after + * driver is unbinded. + */ + clk = devm_clk_get_enabled(dev, "counter"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + spin_lock_init(&priv->lock); + atomic_set(&priv->alrm_sstep, RTCA3_ALRM_SSTEP_DONE); + init_completion(&priv->set_alarm_completion); + + ret = rtca3_initial_setup(clk, priv); + if (ret) + return dev_err_probe(dev, ret, "Failed to setup the RTC!\n"); + + ret = rtca3_request_irqs(pdev, priv); + if (ret) + return ret; + + device_init_wakeup(&pdev->dev, true); + + priv->rtc_dev = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(priv->rtc_dev)) + return PTR_ERR(priv->rtc_dev); + + priv->rtc_dev->ops = &rtca3_ops; + priv->rtc_dev->max_user_freq = 256; + priv->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000; + priv->rtc_dev->range_max = RTC_TIMESTAMP_END_2099; + + return devm_rtc_register_device(priv->rtc_dev); +} + +static void rtca3_remove(struct platform_device *pdev) +{ + struct rtca3_priv *priv = platform_get_drvdata(pdev); + + guard(spinlock_irqsave)(&priv->lock); + + /* + * Disable alarm, periodic interrupts. The RTC device cannot + * power up the system. + */ + rtca3_alarm_irq_set_helper(priv, RTCA3_RCR1_AIE | RTCA3_RCR1_PIE, 0); +} + +static int rtca3_suspend(struct device *dev) +{ + struct rtca3_priv *priv = dev_get_drvdata(dev); + + if (!device_may_wakeup(dev)) + return 0; + + /* Alarm setup in progress. */ + if (atomic_read(&priv->alrm_sstep) != RTCA3_ALRM_SSTEP_DONE) + return -EBUSY; + + enable_irq_wake(priv->wakeup_irq); + + return 0; +} + +static int rtca3_clean_alarm(struct rtca3_priv *priv) +{ + struct rtc_device *rtc_dev = priv->rtc_dev; + time64_t alarm_time, now; + struct rtc_wkalrm alarm; + struct rtc_time tm; + u8 pending; + int ret; + + ret = rtc_read_alarm(rtc_dev, &alarm); + if (ret) + return ret; + + if (!alarm.enabled) + return 0; + + ret = rtc_read_time(rtc_dev, &tm); + if (ret) + return ret; + + alarm_time = rtc_tm_to_time64(&alarm.time); + now = rtc_tm_to_time64(&tm); + if (alarm_time >= now) + return 0; + + /* + * Heuristically, it has been determined that when returning from deep + * sleep state the RTCA3_RSR.AF is zero even though the alarm expired. + * Call again the rtc_update_irq() if alarm helper detects this. + */ + + guard(spinlock_irqsave)(&priv->lock); + + pending = rtca3_alarm_handler_helper(priv); + if (!pending) + rtc_update_irq(priv->rtc_dev, 1, RTC_AF | RTC_IRQF); + + return 0; +} + +static int rtca3_resume(struct device *dev) +{ + struct rtca3_priv *priv = dev_get_drvdata(dev); + + if (!device_may_wakeup(dev)) + return 0; + + disable_irq_wake(priv->wakeup_irq); + + /* + * According to the HW manual (section 22.6.4 Notes on writing to + * and reading from registers) we need to wait 1/128 seconds while + * RCR2.START = 1 to be able to read the counters after a return from low + * power consumption state. + */ + mdelay(8); + + /* + * The alarm cannot wake the system from deep sleep states. In case + * we return from deep sleep states and the alarm expired we need + * to disable it to avoid failures when setting another alarm. + */ + return rtca3_clean_alarm(priv); +} + +static DEFINE_SIMPLE_DEV_PM_OPS(rtca3_pm_ops, rtca3_suspend, rtca3_resume); + +static const struct of_device_id rtca3_of_match[] = { + { .compatible = "renesas,rz-rtca3", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, rtca3_of_match); + +static struct platform_driver rtca3_platform_driver = { + .driver = { + .name = "rtc-rtca3", + .pm = pm_ptr(&rtca3_pm_ops), + .of_match_table = rtca3_of_match, + }, + .probe = rtca3_probe, + .remove = rtca3_remove, +}; +module_platform_driver(rtca3_platform_driver); + +MODULE_DESCRIPTION("Renesas RTCA-3 RTC driver"); +MODULE_AUTHOR("Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c index 2d9bcb3ce1e3..59b8e9a30fe6 100644 --- a/drivers/rtc/rtc-rk808.c +++ b/drivers/rtc/rtc-rk808.c @@ -418,7 +418,7 @@ static int rk808_rtc_probe(struct platform_device *pdev) return ret; } - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); rk808_rtc->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rk808_rtc->rtc)) diff --git a/drivers/rtc/rtc-rtd119x.c b/drivers/rtc/rtc-rtd119x.c index 29662dfd56fe..85a138db81d7 100644 --- a/drivers/rtc/rtc-rtd119x.c +++ b/drivers/rtc/rtc-rtd119x.c @@ -228,7 +228,7 @@ static void rtd119x_rtc_remove(struct platform_device *pdev) static struct platform_driver rtd119x_rtc_driver = { .probe = rtd119x_rtc_probe, - .remove_new = rtd119x_rtc_remove, + .remove = rtd119x_rtc_remove, .driver = { .name = "rtd1295-rtc", .of_match_table = rtd119x_rtc_dt_ids, diff --git a/drivers/rtc/rtc-rv3028.c b/drivers/rtc/rtc-rv3028.c index 2f001c59c61d..868d1b1eb0f4 100644 --- a/drivers/rtc/rtc-rv3028.c +++ b/drivers/rtc/rtc-rv3028.c @@ -120,8 +120,9 @@ static ssize_t timestamp0_show(struct device *dev, { struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent); struct rtc_time tm; - int ret, count; + unsigned int count; u8 date[6]; + int ret; ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count); if (ret) @@ -156,7 +157,8 @@ static ssize_t timestamp0_count_show(struct device *dev, struct device_attribute *attr, char *buf) { struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent); - int ret, count; + unsigned int count; + int ret; ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count); if (ret) diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index 4a81feeb00ff..83331d1fcab0 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c @@ -807,8 +807,8 @@ static int rv3029_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id rv3029_id[] = { - { "rv3029", 0 }, - { "rv3029c2", 0 }, + { "rv3029" }, + { "rv3029c2" }, { } }; MODULE_DEVICE_TABLE(i2c, rv3029_id); diff --git a/drivers/rtc/rtc-rv3032.c b/drivers/rtc/rtc-rv3032.c index 35b2e36b426a..2c6a8918acba 100644 --- a/drivers/rtc/rtc-rv3032.c +++ b/drivers/rtc/rtc-rv3032.c @@ -69,8 +69,7 @@ #define RV3032_CLKOUT2_FD_MSK GENMASK(6, 5) #define RV3032_CLKOUT2_OS BIT(7) -#define RV3032_CTRL1_EERD BIT(3) -#define RV3032_CTRL1_WADA BIT(5) +#define RV3032_CTRL1_EERD BIT(2) #define RV3032_CTRL2_STOP BIT(0) #define RV3032_CTRL2_EIE BIT(2) @@ -947,11 +946,6 @@ static int rv3032_probe(struct i2c_client *client) if (!client->irq) clear_bit(RTC_FEATURE_ALARM, rv3032->rtc->features); - ret = regmap_update_bits(rv3032->regmap, RV3032_CTRL1, - RV3032_CTRL1_WADA, RV3032_CTRL1_WADA); - if (ret) - return ret; - rv3032_trickle_charger_setup(&client->dev, rv3032); set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, rv3032->rtc->features); diff --git a/drivers/rtc/rtc-rx6110.c b/drivers/rtc/rtc-rx6110.c index 834274db8c3f..7c423d672adb 100644 --- a/drivers/rtc/rtc-rx6110.c +++ b/drivers/rtc/rtc-rx6110.c @@ -330,7 +330,7 @@ static int rx6110_probe(struct rx6110_data *rx6110, struct device *dev) } #if IS_ENABLED(CONFIG_SPI_MASTER) -static struct regmap_config regmap_spi_config = { +static const struct regmap_config regmap_spi_config = { .reg_bits = 8, .val_bits = 8, .max_register = RX6110_REG_IRQ, @@ -410,7 +410,7 @@ static void rx6110_spi_unregister(void) #endif /* CONFIG_SPI_MASTER */ #if IS_ENABLED(CONFIG_I2C) -static struct regmap_config regmap_i2c_config = { +static const struct regmap_config regmap_i2c_config = { .reg_bits = 8, .val_bits = 8, .max_register = RX6110_REG_IRQ, @@ -451,7 +451,7 @@ static const struct acpi_device_id rx6110_i2c_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, rx6110_i2c_acpi_match); static const struct i2c_device_id rx6110_i2c_id[] = { - { "rx6110", 0 }, + { "rx6110" }, { } }; MODULE_DEVICE_TABLE(i2c, rx6110_i2c_id); diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c index f44e212c07de..2b6198d1cf81 100644 --- a/drivers/rtc/rtc-rx8010.c +++ b/drivers/rtc/rtc-rx8010.c @@ -50,7 +50,7 @@ #define RX8010_ALARM_AE BIT(7) static const struct i2c_device_id rx8010_id[] = { - { "rx8010", 0 }, + { "rx8010" }, { } }; MODULE_DEVICE_TABLE(i2c, rx8010_id); diff --git a/drivers/rtc/rtc-rx8111.c b/drivers/rtc/rtc-rx8111.c new file mode 100644 index 000000000000..8450d9f0b566 --- /dev/null +++ b/drivers/rtc/rtc-rx8111.c @@ -0,0 +1,368 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Driver for Epson RX8111 RTC. + * + * Copyright (C) 2023 Axis Communications AB + */ + +#include <linux/bcd.h> +#include <linux/bitfield.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/regmap.h> + +#include <linux/rtc.h> + +#define RX8111_REG_SEC 0x10 /* Second counter. */ +#define RX8111_REG_MIN 0x11 /* Minute counter */ +#define RX8111_REG_HOUR 0x12 /* Hour counter. */ +#define RX8111_REG_WEEK 0x13 /* Week day counter. */ +#define RX8111_REG_DAY 0x14 /* Month day counter. */ +#define RX8111_REG_MONTH 0x15 /* Month counter. */ +#define RX8111_REG_YEAR 0x16 /* Year counter. */ + +#define RX8111_REG_ALARM_MIN 0x17 /* Alarm minute. */ +#define RX8111_REG_ALARM_HOUR 0x18 /* Alarm hour. */ +#define RX8111_REG_ALARM_WEEK_DAY 0x19 /* Alarm week or month day. */ + +#define RX8111_REG_TIMER_COUNTER0 0x1a /* Timer counter LSB. */ +#define RX8111_REG_TIMER_COUNTER1 0x1b /* Timer counter. */ +#define RX8111_REG_TIMER_COUNTER2 0x1c /* Timer counter MSB. */ + +#define RX8111_REG_EXT 0x1d /* Extension register. */ +#define RX8111_REG_FLAG 0x1e /* Flag register. */ +#define RX8111_REG_CTRL 0x1f /* Control register. */ + +#define RX8111_REG_TS_1_1000_SEC 0x20 /* Timestamp 256 or 512 Hz . */ +#define RX8111_REG_TS_1_100_SEC 0x21 /* Timestamp 1 - 128 Hz. */ +#define RX8111_REG_TS_SEC 0x22 /* Timestamp second. */ +#define RX8111_REG_TS_MIN 0x23 /* Timestamp minute. */ +#define RX8111_REG_TS_HOUR 0x24 /* Timestamp hour. */ +#define RX8111_REG_TS_WEEK 0x25 /* Timestamp week day. */ +#define RX8111_REG_TS_DAY 0x26 /* Timestamp month day. */ +#define RX8111_REG_TS_MONTH 0x27 /* Timestamp month. */ +#define RX8111_REG_TS_YEAR 0x28 /* Timestamp year. */ +#define RX8111_REG_TS_STATUS 0x29 /* Timestamp status. */ + +#define RX8111_REG_EVIN_SETTING 0x2b /* Timestamp trigger setting. */ +#define RX8111_REG_ALARM_SEC 0x2c /* Alarm second. */ +#define RX8111_REG_TIMER_CTRL 0x2d /* Timer control. */ +#define RX8111_REG_TS_CTRL0 0x2e /* Timestamp control 0. */ +#define RX8111_REG_CMD_TRIGGER 0x2f /* Timestamp trigger. */ +#define RX8111_REG_PWR_SWITCH_CTRL 0x32 /* Power switch control. */ +#define RX8111_REG_STATUS_MON 0x33 /* Status monitor. */ +#define RX8111_REG_TS_CTRL1 0x34 /* Timestamp control 1. */ +#define RX8111_REG_TS_CTRL2 0x35 /* Timestamp control 2. */ +#define RX8111_REG_TS_CTRL3 0x36 /* Timestamp control 3. */ + +#define RX8111_FLAG_XST_BIT BIT(0) +#define RX8111_FLAG_VLF_BIT BIT(1) + +#define RX8111_TIME_BUF_SZ (RX8111_REG_YEAR - RX8111_REG_SEC + 1) + +enum rx8111_regfield { + /* RX8111_REG_EXT. */ + RX8111_REGF_TSEL0, + RX8111_REGF_TSEL1, + RX8111_REGF_ETS, + RX8111_REGF_WADA, + RX8111_REGF_TE, + RX8111_REGF_USEL, + RX8111_REGF_FSEL0, + RX8111_REGF_FSEL1, + + /* RX8111_REG_FLAG. */ + RX8111_REGF_XST, + RX8111_REGF_VLF, + RX8111_REGF_EVF, + RX8111_REGF_AF, + RX8111_REGF_TF, + RX8111_REGF_UF, + RX8111_REGF_POR, + + /* RX8111_REG_CTRL. */ + RX8111_REGF_STOP, + RX8111_REGF_EIE, + RX8111_REGF_AIE, + RX8111_REGF_TIE, + RX8111_REGF_UIE, + + /* RX8111_REG_PWR_SWITCH_CTRL. */ + RX8111_REGF_SMPT0, + RX8111_REGF_SMPT1, + RX8111_REGF_SWSEL0, + RX8111_REGF_SWSEL1, + RX8111_REGF_INIEN, + RX8111_REGF_CHGEN, + + /* RX8111_REG_STATUS_MON. */ + RX8111_REGF_VLOW, + + /* Sentinel value. */ + RX8111_REGF_MAX +}; + +static const struct reg_field rx8111_regfields[] = { + [RX8111_REGF_TSEL0] = REG_FIELD(RX8111_REG_EXT, 0, 0), + [RX8111_REGF_TSEL1] = REG_FIELD(RX8111_REG_EXT, 1, 1), + [RX8111_REGF_ETS] = REG_FIELD(RX8111_REG_EXT, 2, 2), + [RX8111_REGF_WADA] = REG_FIELD(RX8111_REG_EXT, 3, 3), + [RX8111_REGF_TE] = REG_FIELD(RX8111_REG_EXT, 4, 4), + [RX8111_REGF_USEL] = REG_FIELD(RX8111_REG_EXT, 5, 5), + [RX8111_REGF_FSEL0] = REG_FIELD(RX8111_REG_EXT, 6, 6), + [RX8111_REGF_FSEL1] = REG_FIELD(RX8111_REG_EXT, 7, 7), + + [RX8111_REGF_XST] = REG_FIELD(RX8111_REG_FLAG, 0, 0), + [RX8111_REGF_VLF] = REG_FIELD(RX8111_REG_FLAG, 1, 1), + [RX8111_REGF_EVF] = REG_FIELD(RX8111_REG_FLAG, 2, 2), + [RX8111_REGF_AF] = REG_FIELD(RX8111_REG_FLAG, 3, 3), + [RX8111_REGF_TF] = REG_FIELD(RX8111_REG_FLAG, 4, 4), + [RX8111_REGF_UF] = REG_FIELD(RX8111_REG_FLAG, 5, 5), + [RX8111_REGF_POR] = REG_FIELD(RX8111_REG_FLAG, 7, 7), + + [RX8111_REGF_STOP] = REG_FIELD(RX8111_REG_CTRL, 0, 0), + [RX8111_REGF_EIE] = REG_FIELD(RX8111_REG_CTRL, 2, 2), + [RX8111_REGF_AIE] = REG_FIELD(RX8111_REG_CTRL, 3, 3), + [RX8111_REGF_TIE] = REG_FIELD(RX8111_REG_CTRL, 4, 4), + [RX8111_REGF_UIE] = REG_FIELD(RX8111_REG_CTRL, 5, 5), + + [RX8111_REGF_SMPT0] = REG_FIELD(RX8111_REG_PWR_SWITCH_CTRL, 0, 0), + [RX8111_REGF_SMPT1] = REG_FIELD(RX8111_REG_PWR_SWITCH_CTRL, 1, 1), + [RX8111_REGF_SWSEL0] = REG_FIELD(RX8111_REG_PWR_SWITCH_CTRL, 2, 2), + [RX8111_REGF_SWSEL1] = REG_FIELD(RX8111_REG_PWR_SWITCH_CTRL, 3, 3), + [RX8111_REGF_INIEN] = REG_FIELD(RX8111_REG_PWR_SWITCH_CTRL, 6, 6), + [RX8111_REGF_CHGEN] = REG_FIELD(RX8111_REG_PWR_SWITCH_CTRL, 7, 7), + + [RX8111_REGF_VLOW] = REG_FIELD(RX8111_REG_STATUS_MON, 1, 1), +}; + +static const struct regmap_config rx8111_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RX8111_REG_TS_CTRL3, +}; + +struct rx8111_data { + struct regmap *regmap; + struct regmap_field *regfields[RX8111_REGF_MAX]; + struct device *dev; + struct rtc_device *rtc; +}; + +static int rx8111_read_vl_flag(struct rx8111_data *data, unsigned int *vlval) +{ + int ret; + + ret = regmap_field_read(data->regfields[RX8111_REGF_VLF], vlval); + if (ret) + dev_dbg(data->dev, "Could not read VL flag (%d)", ret); + + return ret; +} + +static int rx8111_read_time(struct device *dev, struct rtc_time *tm) +{ + struct rx8111_data *data = dev_get_drvdata(dev); + u8 buf[RX8111_TIME_BUF_SZ]; + unsigned int regval; + int ret; + + /* Check status. */ + ret = regmap_read(data->regmap, RX8111_REG_FLAG, ®val); + if (ret) { + dev_dbg(data->dev, "Could not read flag register (%d)\n", ret); + return ret; + } + + if (FIELD_GET(RX8111_FLAG_XST_BIT, regval)) { + dev_dbg(data->dev, + "Crystal oscillation stopped, time is not reliable\n"); + return -EINVAL; + } + + if (FIELD_GET(RX8111_FLAG_VLF_BIT, regval)) { + dev_dbg(data->dev, + "Low voltage detected, time is not reliable\n"); + return -EINVAL; + } + + ret = regmap_field_read(data->regfields[RX8111_REGF_STOP], ®val); + if (ret) { + dev_dbg(data->dev, "Could not read clock status (%d)\n", ret); + return ret; + } + + if (regval) { + dev_dbg(data->dev, "Clock stopped, time is not reliable\n"); + return -EINVAL; + } + + /* Read time. */ + ret = regmap_bulk_read(data->regmap, RX8111_REG_SEC, buf, + ARRAY_SIZE(buf)); + if (ret) { + dev_dbg(data->dev, "Could not bulk read time (%d)\n", ret); + return ret; + } + + tm->tm_sec = bcd2bin(buf[0]); + tm->tm_min = bcd2bin(buf[1]); + tm->tm_hour = bcd2bin(buf[2]); + tm->tm_wday = ffs(buf[3]) - 1; + tm->tm_mday = bcd2bin(buf[4]); + tm->tm_mon = bcd2bin(buf[5]) - 1; + tm->tm_year = bcd2bin(buf[6]) + 100; + + return 0; +} + +static int rx8111_set_time(struct device *dev, struct rtc_time *tm) +{ + struct rx8111_data *data = dev_get_drvdata(dev); + u8 buf[RX8111_TIME_BUF_SZ]; + int ret; + + buf[0] = bin2bcd(tm->tm_sec); + buf[1] = bin2bcd(tm->tm_min); + buf[2] = bin2bcd(tm->tm_hour); + buf[3] = BIT(tm->tm_wday); + buf[4] = bin2bcd(tm->tm_mday); + buf[5] = bin2bcd(tm->tm_mon + 1); + buf[6] = bin2bcd(tm->tm_year - 100); + + ret = regmap_clear_bits(data->regmap, RX8111_REG_FLAG, + RX8111_FLAG_XST_BIT | RX8111_FLAG_VLF_BIT); + if (ret) + return ret; + + /* Stop the clock. */ + ret = regmap_field_write(data->regfields[RX8111_REGF_STOP], 1); + if (ret) { + dev_dbg(data->dev, "Could not stop the clock (%d)\n", ret); + return ret; + } + + /* Set the time. */ + ret = regmap_bulk_write(data->regmap, RX8111_REG_SEC, buf, + ARRAY_SIZE(buf)); + if (ret) { + dev_dbg(data->dev, "Could not bulk write time (%d)\n", ret); + + /* + * We don't bother with trying to start the clock again. We + * check for this in rx8111_read_time() (and thus force user to + * call rx8111_set_time() to try again). + */ + return ret; + } + + /* Start the clock. */ + ret = regmap_field_write(data->regfields[RX8111_REGF_STOP], 0); + if (ret) { + dev_dbg(data->dev, "Could not start the clock (%d)\n", ret); + return ret; + } + + return 0; +} + +static int rx8111_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) +{ + struct rx8111_data *data = dev_get_drvdata(dev); + unsigned int regval; + unsigned int vlval; + int ret; + + switch (cmd) { + case RTC_VL_READ: + ret = rx8111_read_vl_flag(data, ®val); + if (ret) + return ret; + + vlval = regval ? RTC_VL_DATA_INVALID : 0; + + ret = regmap_field_read(data->regfields[RX8111_REGF_VLOW], + ®val); + if (ret) + return ret; + + vlval |= regval ? RTC_VL_BACKUP_LOW : 0; + + return put_user(vlval, (typeof(vlval) __user *)arg); + default: + return -ENOIOCTLCMD; + } +} + +static const struct rtc_class_ops rx8111_rtc_ops = { + .read_time = rx8111_read_time, + .set_time = rx8111_set_time, + .ioctl = rx8111_ioctl, +}; + +static int rx8111_probe(struct i2c_client *client) +{ + struct rx8111_data *data; + struct rtc_device *rtc; + size_t i; + + data = devm_kmalloc(&client->dev, sizeof(*data), GFP_KERNEL); + if (!data) { + dev_dbg(&client->dev, "Could not allocate device data\n"); + return -ENOMEM; + } + + data->dev = &client->dev; + dev_set_drvdata(data->dev, data); + + data->regmap = devm_regmap_init_i2c(client, &rx8111_regmap_config); + if (IS_ERR(data->regmap)) { + dev_dbg(data->dev, "Could not initialize regmap\n"); + return PTR_ERR(data->regmap); + } + + for (i = 0; i < RX8111_REGF_MAX; ++i) { + data->regfields[i] = devm_regmap_field_alloc( + data->dev, data->regmap, rx8111_regfields[i]); + if (IS_ERR(data->regfields[i])) { + dev_dbg(data->dev, + "Could not allocate register field %zu\n", i); + return PTR_ERR(data->regfields[i]); + } + } + + rtc = devm_rtc_allocate_device(data->dev); + if (IS_ERR(rtc)) { + dev_dbg(data->dev, "Could not allocate rtc device\n"); + return PTR_ERR(rtc); + } + + rtc->ops = &rx8111_rtc_ops; + rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + rtc->range_max = RTC_TIMESTAMP_END_2099; + + clear_bit(RTC_FEATURE_ALARM, rtc->features); + + return devm_rtc_register_device(rtc); +} + +static const struct of_device_id rx8111_of_match[] = { + { + .compatible = "epson,rx8111", + }, + {} +}; +MODULE_DEVICE_TABLE(of, rx8111_of_match); + +static struct i2c_driver rx8111_driver = { + .driver = { + .name = "rtc-rx8111", + .of_match_table = rx8111_of_match, + }, + .probe = rx8111_probe, +}; +module_i2c_driver(rx8111_driver); + +MODULE_AUTHOR("Waqar Hameed <waqar.hameed@axis.com>"); +MODULE_DESCRIPTION("Epson RX8111 RTC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index 48efd61a114d..20c2dff01bae 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -52,11 +52,6 @@ #define RX8571_USER_RAM 0x10 #define RX8571_NVRAM_SIZE 0x10 -struct rx8581 { - struct regmap *regmap; - struct rtc_device *rtc; -}; - struct rx85x1_config { struct regmap_config regmap; unsigned int num_nvram; @@ -72,14 +67,14 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) unsigned char date[7]; unsigned int data; int err; - struct rx8581 *rx8581 = i2c_get_clientdata(client); + struct regmap *regmap = i2c_get_clientdata(client); /* First we ensure that the "update flag" is not set, we read the * time and date then re-read the "update flag". If the update flag * has been set, we know that the time has changed during the read so * we repeat the whole process again. */ - err = regmap_read(rx8581->regmap, RX8581_REG_FLAG, &data); + err = regmap_read(regmap, RX8581_REG_FLAG, &data); if (err < 0) return err; @@ -92,20 +87,20 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) do { /* If update flag set, clear it */ if (data & RX8581_FLAG_UF) { - err = regmap_write(rx8581->regmap, RX8581_REG_FLAG, - data & ~RX8581_FLAG_UF); + err = regmap_write(regmap, RX8581_REG_FLAG, + data & ~RX8581_FLAG_UF); if (err < 0) return err; } /* Now read time and date */ - err = regmap_bulk_read(rx8581->regmap, RX8581_REG_SC, date, + err = regmap_bulk_read(regmap, RX8581_REG_SC, date, sizeof(date)); if (err < 0) return err; /* Check flag register */ - err = regmap_read(rx8581->regmap, RX8581_REG_FLAG, &data); + err = regmap_read(regmap, RX8581_REG_FLAG, &data); if (err < 0) return err; } while (data & RX8581_FLAG_UF); @@ -137,7 +132,7 @@ static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm) struct i2c_client *client = to_i2c_client(dev); int err; unsigned char buf[7]; - struct rx8581 *rx8581 = i2c_get_clientdata(client); + struct regmap *regmap = i2c_get_clientdata(client); dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", @@ -160,25 +155,23 @@ static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm) buf[RX8581_REG_DW] = (0x1 << tm->tm_wday); /* Stop the clock */ - err = regmap_update_bits(rx8581->regmap, RX8581_REG_CTRL, + err = regmap_update_bits(regmap, RX8581_REG_CTRL, RX8581_CTRL_STOP, RX8581_CTRL_STOP); if (err < 0) return err; /* write register's data */ - err = regmap_bulk_write(rx8581->regmap, RX8581_REG_SC, - buf, sizeof(buf)); + err = regmap_bulk_write(regmap, RX8581_REG_SC, buf, sizeof(buf)); if (err < 0) return err; /* get VLF and clear it */ - err = regmap_update_bits(rx8581->regmap, RX8581_REG_FLAG, - RX8581_FLAG_VLF, 0); + err = regmap_update_bits(regmap, RX8581_REG_FLAG, RX8581_FLAG_VLF, 0); if (err < 0) return err; /* Restart the clock */ - return regmap_update_bits(rx8581->regmap, RX8581_REG_CTRL, + return regmap_update_bits(regmap, RX8581_REG_CTRL, RX8581_CTRL_STOP, 0); } @@ -190,29 +183,27 @@ static const struct rtc_class_ops rx8581_rtc_ops = { static int rx8571_nvram_read(void *priv, unsigned int offset, void *val, size_t bytes) { - struct rx8581 *rx8581 = priv; + struct regmap *regmap = priv; - return regmap_bulk_read(rx8581->regmap, RX8571_USER_RAM + offset, - val, bytes); + return regmap_bulk_read(regmap, RX8571_USER_RAM + offset, val, bytes); } static int rx8571_nvram_write(void *priv, unsigned int offset, void *val, size_t bytes) { - struct rx8581 *rx8581 = priv; + struct regmap *regmap = priv; - return regmap_bulk_write(rx8581->regmap, RX8571_USER_RAM + offset, - val, bytes); + return regmap_bulk_write(regmap, RX8571_USER_RAM + offset, val, bytes); } static int rx85x1_nvram_read(void *priv, unsigned int offset, void *val, size_t bytes) { - struct rx8581 *rx8581 = priv; + struct regmap *regmap = priv; unsigned int tmp_val; int ret; - ret = regmap_read(rx8581->regmap, RX8581_REG_RAM, &tmp_val); + ret = regmap_read(regmap, RX8581_REG_RAM, &tmp_val); (*(unsigned char *)val) = (unsigned char) tmp_val; return ret; @@ -221,12 +212,11 @@ static int rx85x1_nvram_read(void *priv, unsigned int offset, void *val, static int rx85x1_nvram_write(void *priv, unsigned int offset, void *val, size_t bytes) { - struct rx8581 *rx8581 = priv; + struct regmap *regmap = priv; unsigned char tmp_val; tmp_val = *((unsigned char *)val); - return regmap_write(rx8581->regmap, RX8581_REG_RAM, - (unsigned int)tmp_val); + return regmap_write(regmap, RX8581_REG_RAM, (unsigned int)tmp_val); } static const struct rx85x1_config rx8581_config = { @@ -249,9 +239,10 @@ static const struct rx85x1_config rx8571_config = { static int rx8581_probe(struct i2c_client *client) { - struct rx8581 *rx8581; + struct regmap *regmap; const struct rx85x1_config *config = &rx8581_config; const void *data = of_device_get_match_data(&client->dev); + struct rtc_device *rtc; static struct nvmem_config nvmem_cfg[] = { { .name = "rx85x1-", @@ -276,38 +267,34 @@ static int rx8581_probe(struct i2c_client *client) if (data) config = data; - rx8581 = devm_kzalloc(&client->dev, sizeof(struct rx8581), GFP_KERNEL); - if (!rx8581) - return -ENOMEM; - - i2c_set_clientdata(client, rx8581); + regmap = devm_regmap_init_i2c(client, &config->regmap); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); - rx8581->regmap = devm_regmap_init_i2c(client, &config->regmap); - if (IS_ERR(rx8581->regmap)) - return PTR_ERR(rx8581->regmap); + i2c_set_clientdata(client, regmap); - rx8581->rtc = devm_rtc_allocate_device(&client->dev); - if (IS_ERR(rx8581->rtc)) - return PTR_ERR(rx8581->rtc); + rtc = devm_rtc_allocate_device(&client->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); - rx8581->rtc->ops = &rx8581_rtc_ops; - rx8581->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; - rx8581->rtc->range_max = RTC_TIMESTAMP_END_2099; - rx8581->rtc->start_secs = 0; - rx8581->rtc->set_start_time = true; + rtc->ops = &rx8581_rtc_ops; + rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + rtc->range_max = RTC_TIMESTAMP_END_2099; + rtc->start_secs = 0; + rtc->set_start_time = true; - ret = devm_rtc_register_device(rx8581->rtc); + ret = devm_rtc_register_device(rtc); for (i = 0; i < config->num_nvram; i++) { - nvmem_cfg[i].priv = rx8581; - devm_rtc_nvmem_register(rx8581->rtc, &nvmem_cfg[i]); + nvmem_cfg[i].priv = regmap; + devm_rtc_nvmem_register(rtc, &nvmem_cfg[i]); } return ret; } static const struct i2c_device_id rx8581_id[] = { - { "rx8581", 0 }, + { "rx8581" }, { } }; MODULE_DEVICE_TABLE(i2c, rx8581_id); diff --git a/drivers/rtc/rtc-rzn1.c b/drivers/rtc/rtc-rzn1.c index 56ebbd4d0481..eeb9612a666f 100644 --- a/drivers/rtc/rtc-rzn1.c +++ b/drivers/rtc/rtc-rzn1.c @@ -7,7 +7,7 @@ * - 2022 Schneider Electric * * Authors: - * - Michel Pollet <michel.pollet@bp.renesas.com>, <buserror@gmail.com> + * - Michel Pollet <buserror@gmail.com> * - Miquel Raynal <miquel.raynal@bootlin.com> */ @@ -19,6 +19,7 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/rtc.h> +#include <linux/spinlock.h> #define RZN1_RTC_CTL0 0x00 #define RZN1_RTC_CTL0_SLSB_SUBU 0 @@ -27,6 +28,7 @@ #define RZN1_RTC_CTL0_CE BIT(7) #define RZN1_RTC_CTL1 0x04 +#define RZN1_RTC_CTL1_1SE BIT(3) #define RZN1_RTC_CTL1_ALME BIT(4) #define RZN1_RTC_CTL2 0x08 @@ -35,13 +37,13 @@ #define RZN1_RTC_CTL2_WUST BIT(5) #define RZN1_RTC_CTL2_STOPPED (RZN1_RTC_CTL2_WAIT | RZN1_RTC_CTL2_WST) -#define RZN1_RTC_SEC 0x14 -#define RZN1_RTC_MIN 0x18 -#define RZN1_RTC_HOUR 0x1c -#define RZN1_RTC_WEEK 0x20 -#define RZN1_RTC_DAY 0x24 -#define RZN1_RTC_MONTH 0x28 -#define RZN1_RTC_YEAR 0x2c +#define RZN1_RTC_TIME 0x30 +#define RZN1_RTC_TIME_MIN_SHIFT 8 +#define RZN1_RTC_TIME_HOUR_SHIFT 16 +#define RZN1_RTC_CAL 0x34 +#define RZN1_RTC_CAL_DAY_SHIFT 8 +#define RZN1_RTC_CAL_MON_SHIFT 16 +#define RZN1_RTC_CAL_YEAR_SHIFT 24 #define RZN1_RTC_SUBU 0x38 #define RZN1_RTC_SUBU_DEV BIT(7) @@ -52,40 +54,35 @@ #define RZN1_RTC_ALW 0x48 #define RZN1_RTC_SECC 0x4c -#define RZN1_RTC_MINC 0x50 -#define RZN1_RTC_HOURC 0x54 -#define RZN1_RTC_WEEKC 0x58 -#define RZN1_RTC_DAYC 0x5c -#define RZN1_RTC_MONTHC 0x60 -#define RZN1_RTC_YEARC 0x64 +#define RZN1_RTC_TIMEC 0x68 +#define RZN1_RTC_CALC 0x6c struct rzn1_rtc { struct rtc_device *rtcdev; void __iomem *base; + /* + * Protects access to RZN1_RTC_CTL1 reg. rtc_lock with threaded_irqs + * would introduce race conditions when switching interrupts because + * of potential sleeps + */ + spinlock_t ctl1_access_lock; + struct rtc_time tm_alarm; }; static void rzn1_rtc_get_time_snapshot(struct rzn1_rtc *rtc, struct rtc_time *tm) { - tm->tm_sec = readl(rtc->base + RZN1_RTC_SECC); - tm->tm_min = readl(rtc->base + RZN1_RTC_MINC); - tm->tm_hour = readl(rtc->base + RZN1_RTC_HOURC); - tm->tm_wday = readl(rtc->base + RZN1_RTC_WEEKC); - tm->tm_mday = readl(rtc->base + RZN1_RTC_DAYC); - tm->tm_mon = readl(rtc->base + RZN1_RTC_MONTHC); - tm->tm_year = readl(rtc->base + RZN1_RTC_YEARC); -} - -static unsigned int rzn1_rtc_tm_to_wday(struct rtc_time *tm) -{ - time64_t time; - unsigned int days; - u32 secs; + u32 val; - time = rtc_tm_to_time64(tm); - days = div_s64_rem(time, 86400, &secs); + val = readl(rtc->base + RZN1_RTC_TIMEC); + tm->tm_sec = bcd2bin(val); + tm->tm_min = bcd2bin(val >> RZN1_RTC_TIME_MIN_SHIFT); + tm->tm_hour = bcd2bin(val >> RZN1_RTC_TIME_HOUR_SHIFT); - /* day of the week, 1970-01-01 was a Thursday */ - return (days + 4) % 7; + val = readl(rtc->base + RZN1_RTC_CALC); + tm->tm_wday = val & 0x0f; + tm->tm_mday = bcd2bin(val >> RZN1_RTC_CAL_DAY_SHIFT); + tm->tm_mon = bcd2bin(val >> RZN1_RTC_CAL_MON_SHIFT) - 1; + tm->tm_year = bcd2bin(val >> RZN1_RTC_CAL_YEAR_SHIFT) + 100; } static int rzn1_rtc_read_time(struct device *dev, struct rtc_time *tm) @@ -103,17 +100,9 @@ static int rzn1_rtc_read_time(struct device *dev, struct rtc_time *tm) rzn1_rtc_get_time_snapshot(rtc, tm); secs = readl(rtc->base + RZN1_RTC_SECC); - if (tm->tm_sec != secs) + if (tm->tm_sec != bcd2bin(secs)) rzn1_rtc_get_time_snapshot(rtc, tm); - tm->tm_sec = bcd2bin(tm->tm_sec); - tm->tm_min = bcd2bin(tm->tm_min); - tm->tm_hour = bcd2bin(tm->tm_hour); - tm->tm_wday = bcd2bin(tm->tm_wday); - tm->tm_mday = bcd2bin(tm->tm_mday); - tm->tm_mon = bcd2bin(tm->tm_mon); - tm->tm_year = bcd2bin(tm->tm_year); - return 0; } @@ -123,14 +112,6 @@ static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm) u32 val; int ret; - tm->tm_sec = bin2bcd(tm->tm_sec); - tm->tm_min = bin2bcd(tm->tm_min); - tm->tm_hour = bin2bcd(tm->tm_hour); - tm->tm_wday = bin2bcd(rzn1_rtc_tm_to_wday(tm)); - tm->tm_mday = bin2bcd(tm->tm_mday); - tm->tm_mon = bin2bcd(tm->tm_mon); - tm->tm_year = bin2bcd(tm->tm_year); - val = readl(rtc->base + RZN1_RTC_CTL2); if (!(val & RZN1_RTC_CTL2_STOPPED)) { /* Hold the counter if it was counting up */ @@ -144,13 +125,17 @@ static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm) return ret; } - writel(tm->tm_sec, rtc->base + RZN1_RTC_SEC); - writel(tm->tm_min, rtc->base + RZN1_RTC_MIN); - writel(tm->tm_hour, rtc->base + RZN1_RTC_HOUR); - writel(tm->tm_wday, rtc->base + RZN1_RTC_WEEK); - writel(tm->tm_mday, rtc->base + RZN1_RTC_DAY); - writel(tm->tm_mon, rtc->base + RZN1_RTC_MONTH); - writel(tm->tm_year, rtc->base + RZN1_RTC_YEAR); + val = bin2bcd(tm->tm_sec); + val |= bin2bcd(tm->tm_min) << RZN1_RTC_TIME_MIN_SHIFT; + val |= bin2bcd(tm->tm_hour) << RZN1_RTC_TIME_HOUR_SHIFT; + writel(val, rtc->base + RZN1_RTC_TIME); + + val = tm->tm_wday; + val |= bin2bcd(tm->tm_mday) << RZN1_RTC_CAL_DAY_SHIFT; + val |= bin2bcd(tm->tm_mon + 1) << RZN1_RTC_CAL_MON_SHIFT; + val |= bin2bcd(tm->tm_year - 100) << RZN1_RTC_CAL_YEAR_SHIFT; + writel(val, rtc->base + RZN1_RTC_CAL); + writel(0, rtc->base + RZN1_RTC_CTL2); return 0; @@ -159,8 +144,38 @@ static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm) static irqreturn_t rzn1_rtc_alarm_irq(int irq, void *dev_id) { struct rzn1_rtc *rtc = dev_id; + u32 ctl1, set_irq_bits = 0; - rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF); + if (rtc->tm_alarm.tm_sec == 0) + rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF); + else + /* Switch to 1s interrupts */ + set_irq_bits = RZN1_RTC_CTL1_1SE; + + guard(spinlock)(&rtc->ctl1_access_lock); + + ctl1 = readl(rtc->base + RZN1_RTC_CTL1); + ctl1 &= ~RZN1_RTC_CTL1_ALME; + ctl1 |= set_irq_bits; + writel(ctl1, rtc->base + RZN1_RTC_CTL1); + + return IRQ_HANDLED; +} + +static irqreturn_t rzn1_rtc_1s_irq(int irq, void *dev_id) +{ + struct rzn1_rtc *rtc = dev_id; + u32 ctl1; + + if (readl(rtc->base + RZN1_RTC_SECC) == bin2bcd(rtc->tm_alarm.tm_sec)) { + guard(spinlock)(&rtc->ctl1_access_lock); + + ctl1 = readl(rtc->base + RZN1_RTC_CTL1); + ctl1 &= ~RZN1_RTC_CTL1_1SE; + writel(ctl1, rtc->base + RZN1_RTC_CTL1); + + rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF); + } return IRQ_HANDLED; } @@ -168,14 +183,38 @@ static irqreturn_t rzn1_rtc_alarm_irq(int irq, void *dev_id) static int rzn1_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) { struct rzn1_rtc *rtc = dev_get_drvdata(dev); - u32 ctl1 = readl(rtc->base + RZN1_RTC_CTL1); + struct rtc_time *tm = &rtc->tm_alarm, tm_now; + u32 ctl1; + int ret; - if (enable) - ctl1 |= RZN1_RTC_CTL1_ALME; - else - ctl1 &= ~RZN1_RTC_CTL1_ALME; + guard(spinlock_irqsave)(&rtc->ctl1_access_lock); - writel(ctl1, rtc->base + RZN1_RTC_CTL1); + ctl1 = readl(rtc->base + RZN1_RTC_CTL1); + + if (enable) { + /* + * Use alarm interrupt if alarm time is at least a minute away + * or less than a minute but in the next minute. Otherwise use + * 1 second interrupt to wait for the proper second + */ + do { + ctl1 &= ~(RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE); + + ret = rzn1_rtc_read_time(dev, &tm_now); + if (ret) + return ret; + + if (rtc_tm_sub(tm, &tm_now) > 59 || tm->tm_min != tm_now.tm_min) + ctl1 |= RZN1_RTC_CTL1_ALME; + else + ctl1 |= RZN1_RTC_CTL1_1SE; + + writel(ctl1, rtc->base + RZN1_RTC_CTL1); + } while (readl(rtc->base + RZN1_RTC_SECC) != bin2bcd(tm_now.tm_sec)); + } else { + ctl1 &= ~(RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE); + writel(ctl1, rtc->base + RZN1_RTC_CTL1); + } return 0; } @@ -209,7 +248,7 @@ static int rzn1_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) } ctl1 = readl(rtc->base + RZN1_RTC_CTL1); - alrm->enabled = !!(ctl1 & RZN1_RTC_CTL1_ALME); + alrm->enabled = !!(ctl1 & (RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE)); return 0; } @@ -240,6 +279,8 @@ static int rzn1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) writel(bin2bcd(tm->tm_hour), rtc->base + RZN1_RTC_ALH); writel(BIT(wday), rtc->base + RZN1_RTC_ALW); + rtc->tm_alarm = alrm->time; + rzn1_rtc_alarm_irq_enable(dev, alrm->enabled); return 0; @@ -328,7 +369,7 @@ static const struct rtc_class_ops rzn1_rtc_ops = { static int rzn1_rtc_probe(struct platform_device *pdev) { struct rzn1_rtc *rtc; - int alarm_irq; + int irq; int ret; rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); @@ -341,9 +382,9 @@ static int rzn1_rtc_probe(struct platform_device *pdev) if (IS_ERR(rtc->base)) return dev_err_probe(&pdev->dev, PTR_ERR(rtc->base), "Missing reg\n"); - alarm_irq = platform_get_irq(pdev, 0); - if (alarm_irq < 0) - return alarm_irq; + irq = platform_get_irq_byname(pdev, "alarm"); + if (irq < 0) + return irq; rtc->rtcdev = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc->rtcdev)) @@ -353,8 +394,6 @@ static int rzn1_rtc_probe(struct platform_device *pdev) rtc->rtcdev->range_max = RTC_TIMESTAMP_END_2099; rtc->rtcdev->alarm_offset_max = 7 * 86400; rtc->rtcdev->ops = &rzn1_rtc_ops; - set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->rtcdev->features); - clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtcdev->features); ret = devm_pm_runtime_enable(&pdev->dev); if (ret < 0) @@ -373,13 +412,24 @@ static int rzn1_rtc_probe(struct platform_device *pdev) /* Disable all interrupts */ writel(0, rtc->base + RZN1_RTC_CTL1); - ret = devm_request_irq(&pdev->dev, alarm_irq, rzn1_rtc_alarm_irq, 0, - dev_name(&pdev->dev), rtc); + spin_lock_init(&rtc->ctl1_access_lock); + + ret = devm_request_irq(&pdev->dev, irq, rzn1_rtc_alarm_irq, 0, "RZN1 RTC Alarm", rtc); if (ret) { - dev_err(&pdev->dev, "RTC timer interrupt not available\n"); + dev_err(&pdev->dev, "RTC alarm interrupt not available\n"); goto dis_runtime_pm; } + irq = platform_get_irq_byname_optional(pdev, "pps"); + if (irq >= 0) + ret = devm_request_irq(&pdev->dev, irq, rzn1_rtc_1s_irq, 0, "RZN1 RTC 1s", rtc); + + if (irq < 0 || ret) { + set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->rtcdev->features); + clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtcdev->features); + dev_warn(&pdev->dev, "RTC pps interrupt not available. Alarm has only minute accuracy\n"); + } + ret = devm_rtc_register_device(rtc->rtcdev); if (ret) goto dis_runtime_pm; @@ -405,7 +455,7 @@ MODULE_DEVICE_TABLE(of, rzn1_rtc_of_match); static struct platform_driver rzn1_rtc_driver = { .probe = rzn1_rtc_probe, - .remove_new = rzn1_rtc_remove, + .remove = rzn1_rtc_remove, .driver = { .name = "rzn1-rtc", .of_match_table = rzn1_rtc_of_match, @@ -413,7 +463,7 @@ static struct platform_driver rzn1_rtc_driver = { }; module_platform_driver(rzn1_rtc_driver); -MODULE_AUTHOR("Michel Pollet <Michel.Pollet@bp.renesas.com"); +MODULE_AUTHOR("Michel Pollet <buserror@gmail.com>"); MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com"); MODULE_DESCRIPTION("RZ/N1 RTC driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 90a3028ac574..3408d2ab2741 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -50,13 +50,12 @@ #define S35390A_INT2_MODE_PMIN (BIT(3) | BIT(2)) /* INT2FE | INT2ME */ static const struct i2c_device_id s35390a_id[] = { - { "s35390a", 0 }, + { "s35390a" }, { } }; MODULE_DEVICE_TABLE(i2c, s35390a_id); static const __maybe_unused struct of_device_id s35390a_of_match[] = { - { .compatible = "s35390a" }, { .compatible = "sii,s35390a" }, { } }; @@ -64,7 +63,6 @@ MODULE_DEVICE_TABLE(of, s35390a_of_match); struct s35390a { struct i2c_client *client[8]; - struct rtc_device *rtc; int twentyfourhour; }; @@ -423,6 +421,7 @@ static int s35390a_probe(struct i2c_client *client) int err, err_read; unsigned int i; struct s35390a *s35390a; + struct rtc_device *rtc; char buf, status1; struct device *dev = &client->dev; @@ -448,9 +447,9 @@ static int s35390a_probe(struct i2c_client *client) } } - s35390a->rtc = devm_rtc_allocate_device(dev); - if (IS_ERR(s35390a->rtc)) - return PTR_ERR(s35390a->rtc); + rtc = devm_rtc_allocate_device(dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); err_read = s35390a_read_status(s35390a, &status1); if (err_read < 0) { @@ -481,17 +480,17 @@ static int s35390a_probe(struct i2c_client *client) device_set_wakeup_capable(dev, 1); - s35390a->rtc->ops = &s35390a_rtc_ops; - s35390a->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; - s35390a->rtc->range_max = RTC_TIMESTAMP_END_2099; + rtc->ops = &s35390a_rtc_ops; + rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + rtc->range_max = RTC_TIMESTAMP_END_2099; - set_bit(RTC_FEATURE_ALARM_RES_MINUTE, s35390a->rtc->features); - clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, s35390a->rtc->features ); + set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features); + clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features); if (status1 & S35390A_FLAG_INT2) - rtc_update_irq(s35390a->rtc, 1, RTC_AF); + rtc_update_irq(rtc, 1, RTC_AF); - return devm_rtc_register_device(s35390a->rtc); + return devm_rtc_register_device(rtc); } static struct i2c_driver s35390a_driver = { diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 282238818f63..58c957eb753d 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -456,7 +456,7 @@ static int s3c_rtc_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "s3c2410_rtc: RTCCON=%02x\n", readw(info->base + S3C2410_RTCCON)); - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); info->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(info->rtc)) { @@ -597,7 +597,7 @@ MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match); static struct platform_driver s3c_rtc_driver = { .probe = s3c_rtc_probe, - .remove_new = s3c_rtc_remove, + .remove = s3c_rtc_remove, .driver = { .name = "s3c-rtc", .pm = &s3c_rtc_pm_ops, diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index dad294a0ce2a..db5c9b641277 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -146,7 +146,6 @@ static const struct s5m_rtc_reg_config s2mps15_rtc_regs = { struct s5m_rtc_info { struct device *dev; - struct i2c_client *i2c; struct sec_pmic_dev *s5m87xx; struct regmap *regmap; struct rtc_device *rtc_dev; @@ -627,11 +626,10 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info) } info->rtc_24hr_mode = 1; - if (ret < 0) { - dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", - __func__, ret); - return ret; - } + if (ret < 0) + return dev_err_probe(info->dev, ret, + "%s: fail to write controlm reg\n", + __func__); return ret; } @@ -640,6 +638,7 @@ static int s5m_rtc_probe(struct platform_device *pdev) { struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent); struct s5m_rtc_info *info; + struct i2c_client *i2c; const struct regmap_config *regmap_cfg; int ret, alarm_irq; @@ -669,26 +668,21 @@ static int s5m_rtc_probe(struct platform_device *pdev) alarm_irq = S5M8767_IRQ_RTCA1; break; default: - dev_err(&pdev->dev, - "Device type %lu is not supported by RTC driver\n", - platform_get_device_id(pdev)->driver_data); - return -ENODEV; + return dev_err_probe(&pdev->dev, -ENODEV, + "Device type %lu is not supported by RTC driver\n", + platform_get_device_id(pdev)->driver_data); } - info->i2c = devm_i2c_new_dummy_device(&pdev->dev, s5m87xx->i2c->adapter, - RTC_I2C_ADDR); - if (IS_ERR(info->i2c)) { - dev_err(&pdev->dev, "Failed to allocate I2C for RTC\n"); - return PTR_ERR(info->i2c); - } + i2c = devm_i2c_new_dummy_device(&pdev->dev, s5m87xx->i2c->adapter, + RTC_I2C_ADDR); + if (IS_ERR(i2c)) + return dev_err_probe(&pdev->dev, PTR_ERR(i2c), + "Failed to allocate I2C for RTC\n"); - info->regmap = devm_regmap_init_i2c(info->i2c, regmap_cfg); - if (IS_ERR(info->regmap)) { - ret = PTR_ERR(info->regmap); - dev_err(&pdev->dev, "Failed to allocate RTC register map: %d\n", - ret); - return ret; - } + info->regmap = devm_regmap_init_i2c(i2c, regmap_cfg); + if (IS_ERR(info->regmap)) + return dev_err_probe(&pdev->dev, PTR_ERR(info->regmap), + "Failed to allocate RTC register map\n"); info->dev = &pdev->dev; info->s5m87xx = s5m87xx; @@ -696,11 +690,10 @@ static int s5m_rtc_probe(struct platform_device *pdev) if (s5m87xx->irq_data) { info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq); - if (info->irq <= 0) { - dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n", - alarm_irq); - return -EINVAL; - } + if (info->irq <= 0) + return dev_err_probe(&pdev->dev, -EINVAL, + "Failed to get virtual IRQ %d\n", + alarm_irq); } platform_set_drvdata(pdev, info); @@ -724,12 +717,11 @@ static int s5m_rtc_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, s5m_rtc_alarm_irq, 0, "rtc-alarm0", info); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", - info->irq, ret); - return ret; - } - device_init_wakeup(&pdev->dev, 1); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "Failed to request alarm IRQ %d\n", + info->irq); + device_init_wakeup(&pdev->dev, true); } return devm_rtc_register_device(info->rtc_dev); diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 0b2cfa8ca05b..1ad93648d69c 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -292,7 +292,7 @@ static int sa1100_rtc_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, info); - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); return sa1100_rtc_init(pdev, info); } @@ -341,7 +341,7 @@ MODULE_DEVICE_TABLE(of, sa1100_rtc_dt_ids); static struct platform_driver sa1100_rtc_driver = { .probe = sa1100_rtc_probe, - .remove_new = sa1100_rtc_remove, + .remove = sa1100_rtc_remove, .driver = { .name = "sa1100-rtc", .pm = &sa1100_rtc_pm_ops, diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index ce7a2ddbbc16..2b83561d4d28 100644 --- a/drivers/rtc/rtc-sc27xx.c +++ b/drivers/rtc/rtc-sc27xx.c @@ -613,14 +613,14 @@ static int sprd_rtc_probe(struct platform_device *pdev) return ret; } - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); rtc->rtc->ops = &sprd_rtc_ops; rtc->rtc->range_min = 0; rtc->rtc->range_max = 5662310399LL; ret = devm_rtc_register_device(rtc->rtc); if (ret) { - device_init_wakeup(&pdev->dev, 0); + device_init_wakeup(&pdev->dev, false); return ret; } diff --git a/drivers/rtc/rtc-sd2405al.c b/drivers/rtc/rtc-sd2405al.c new file mode 100644 index 000000000000..00c3033e8079 --- /dev/null +++ b/drivers/rtc/rtc-sd2405al.c @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * RTC driver for the SD2405AL Real-Time Clock + * + * Datasheet: + * https://image.dfrobot.com/image/data/TOY0021/SD2405AL%20datasheet%20(Angelo%20v0.1).pdf + * + * Copyright (C) 2024 Tóth János <gomba007@gmail.com> + */ + +#include <linux/bcd.h> +#include <linux/i2c.h> +#include <linux/regmap.h> +#include <linux/rtc.h> + +/* Real time clock registers */ +#define SD2405AL_REG_T_SEC 0x00 +#define SD2405AL_REG_T_MIN 0x01 +#define SD2405AL_REG_T_HOUR 0x02 +# define SD2405AL_BIT_12H_PM BIT(5) +# define SD2405AL_BIT_24H BIT(7) +#define SD2405AL_REG_T_WEEK 0x03 +#define SD2405AL_REG_T_DAY 0x04 +#define SD2405AL_REG_T_MON 0x05 +#define SD2405AL_REG_T_YEAR 0x06 + +#define SD2405AL_NUM_T_REGS (SD2405AL_REG_T_YEAR - SD2405AL_REG_T_SEC + 1) + +/* Control registers */ +#define SD2405AL_REG_CTR1 0x0F +# define SD2405AL_BIT_WRTC2 BIT(2) +# define SD2405AL_BIT_WRTC3 BIT(7) +#define SD2405AL_REG_CTR2 0x10 +# define SD2405AL_BIT_WRTC1 BIT(7) +#define SD2405AL_REG_CTR3 0x11 +#define SD2405AL_REG_TTF 0x12 +#define SD2405AL_REG_CNTDWN 0x13 + +/* General RAM */ +#define SD2405AL_REG_M_START 0x14 +#define SD2405AL_REG_M_END 0x1F + +struct sd2405al { + struct device *dev; + struct regmap *regmap; +}; + +static int sd2405al_enable_reg_write(struct sd2405al *sd2405al) +{ + int ret; + + /* order of writes is important */ + ret = regmap_update_bits(sd2405al->regmap, SD2405AL_REG_CTR2, + SD2405AL_BIT_WRTC1, SD2405AL_BIT_WRTC1); + if (ret < 0) + return ret; + + ret = regmap_update_bits(sd2405al->regmap, SD2405AL_REG_CTR1, + SD2405AL_BIT_WRTC2 | SD2405AL_BIT_WRTC3, + SD2405AL_BIT_WRTC2 | SD2405AL_BIT_WRTC3); + if (ret < 0) + return ret; + + return 0; +} + +static int sd2405al_disable_reg_write(struct sd2405al *sd2405al) +{ + int ret; + + /* order of writes is important */ + ret = regmap_update_bits(sd2405al->regmap, SD2405AL_REG_CTR1, + SD2405AL_BIT_WRTC2 | SD2405AL_BIT_WRTC3, 0x00); + if (ret < 0) + return ret; + + ret = regmap_update_bits(sd2405al->regmap, SD2405AL_REG_CTR2, + SD2405AL_BIT_WRTC1, 0x00); + if (ret < 0) + return ret; + + return 0; +} + +static int sd2405al_read_time(struct device *dev, struct rtc_time *time) +{ + u8 data[SD2405AL_NUM_T_REGS] = { 0 }; + struct sd2405al *sd2405al = dev_get_drvdata(dev); + int ret; + + ret = regmap_bulk_read(sd2405al->regmap, SD2405AL_REG_T_SEC, data, + SD2405AL_NUM_T_REGS); + if (ret < 0) + return ret; + + time->tm_sec = bcd2bin(data[SD2405AL_REG_T_SEC] & 0x7F); + time->tm_min = bcd2bin(data[SD2405AL_REG_T_MIN] & 0x7F); + + if (data[SD2405AL_REG_T_HOUR] & SD2405AL_BIT_24H) + time->tm_hour = bcd2bin(data[SD2405AL_REG_T_HOUR] & 0x3F); + else + if (data[SD2405AL_REG_T_HOUR] & SD2405AL_BIT_12H_PM) + time->tm_hour = bcd2bin(data[SD2405AL_REG_T_HOUR] + & 0x1F) + 12; + else /* 12 hour mode, AM */ + time->tm_hour = bcd2bin(data[SD2405AL_REG_T_HOUR] + & 0x1F); + + time->tm_wday = bcd2bin(data[SD2405AL_REG_T_WEEK] & 0x07); + time->tm_mday = bcd2bin(data[SD2405AL_REG_T_DAY] & 0x3F); + time->tm_mon = bcd2bin(data[SD2405AL_REG_T_MON] & 0x1F) - 1; + time->tm_year = bcd2bin(data[SD2405AL_REG_T_YEAR]) + 100; + + dev_dbg(sd2405al->dev, "read time: %ptR (%d)\n", time, time->tm_wday); + + return 0; +} + +static int sd2405al_set_time(struct device *dev, struct rtc_time *time) +{ + u8 data[SD2405AL_NUM_T_REGS]; + struct sd2405al *sd2405al = dev_get_drvdata(dev); + int ret; + + data[SD2405AL_REG_T_SEC] = bin2bcd(time->tm_sec); + data[SD2405AL_REG_T_MIN] = bin2bcd(time->tm_min); + data[SD2405AL_REG_T_HOUR] = bin2bcd(time->tm_hour) | SD2405AL_BIT_24H; + data[SD2405AL_REG_T_DAY] = bin2bcd(time->tm_mday); + data[SD2405AL_REG_T_WEEK] = bin2bcd(time->tm_wday); + data[SD2405AL_REG_T_MON] = bin2bcd(time->tm_mon) + 1; + data[SD2405AL_REG_T_YEAR] = bin2bcd(time->tm_year - 100); + + ret = sd2405al_enable_reg_write(sd2405al); + if (ret < 0) + return ret; + + ret = regmap_bulk_write(sd2405al->regmap, SD2405AL_REG_T_SEC, data, + SD2405AL_NUM_T_REGS); + if (ret < 0) + return ret; + + ret = regmap_write(sd2405al->regmap, SD2405AL_REG_TTF, 0x00); + if (ret < 0) + return ret; + + ret = sd2405al_disable_reg_write(sd2405al); + if (ret < 0) + return ret; + + dev_dbg(sd2405al->dev, "set time: %ptR (%d)\n", time, time->tm_wday); + + return 0; +} + +static const struct rtc_class_ops sd2405al_rtc_ops = { + .read_time = sd2405al_read_time, + .set_time = sd2405al_set_time, +}; + +static const struct regmap_config sd2405al_regmap_conf = { + .reg_bits = 8, + .val_bits = 8, + .max_register = SD2405AL_REG_M_END, +}; + +static int sd2405al_probe(struct i2c_client *client) +{ + struct sd2405al *sd2405al; + struct rtc_device *rtc; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; + + sd2405al = devm_kzalloc(&client->dev, sizeof(*sd2405al), GFP_KERNEL); + if (!sd2405al) + return -ENOMEM; + + sd2405al->dev = &client->dev; + + sd2405al->regmap = devm_regmap_init_i2c(client, &sd2405al_regmap_conf); + if (IS_ERR(sd2405al->regmap)) + return PTR_ERR(sd2405al->regmap); + + rtc = devm_rtc_allocate_device(&client->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + rtc->ops = &sd2405al_rtc_ops; + rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + rtc->range_max = RTC_TIMESTAMP_END_2099; + + dev_set_drvdata(&client->dev, sd2405al); + + ret = devm_rtc_register_device(rtc); + if (ret < 0) + return ret; + + return 0; +} + +static const struct i2c_device_id sd2405al_id[] = { + { "sd2405al" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, sd2405al_id); + +static const __maybe_unused struct of_device_id sd2405al_of_match[] = { + { .compatible = "dfrobot,sd2405al" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, sd2405al_of_match); + +static struct i2c_driver sd2405al_driver = { + .driver = { + .name = "sd2405al", + .of_match_table = of_match_ptr(sd2405al_of_match), + }, + .probe = sd2405al_probe, + .id_table = sd2405al_id, +}; + +module_i2c_driver(sd2405al_driver); + +MODULE_AUTHOR("Tóth János <gomba007@gmail.com>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SD2405AL RTC driver"); diff --git a/drivers/rtc/rtc-sd3078.c b/drivers/rtc/rtc-sd3078.c index 7760394ccd2d..10cc1dcfc774 100644 --- a/drivers/rtc/rtc-sd3078.c +++ b/drivers/rtc/rtc-sd3078.c @@ -36,11 +36,6 @@ */ #define WRITE_PROTECT_EN 0 -struct sd3078 { - struct rtc_device *rtc; - struct regmap *regmap; -}; - /* * In order to prevent arbitrary modification of the time register, * when modification of the register, @@ -49,14 +44,11 @@ struct sd3078 { * 2. set WRITE2 bit * 3. set WRITE3 bit */ -static void sd3078_enable_reg_write(struct sd3078 *sd3078) +static void sd3078_enable_reg_write(struct regmap *regmap) { - regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL2, - KEY_WRITE1, KEY_WRITE1); - regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1, - KEY_WRITE2, KEY_WRITE2); - regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1, - KEY_WRITE3, KEY_WRITE3); + regmap_update_bits(regmap, SD3078_REG_CTRL2, KEY_WRITE1, KEY_WRITE1); + regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE2, KEY_WRITE2); + regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE3, KEY_WRITE3); } #if WRITE_PROTECT_EN @@ -69,14 +61,11 @@ static void sd3078_enable_reg_write(struct sd3078 *sd3078) * 2. clear WRITE3 bit * 3. clear WRITE1 bit */ -static void sd3078_disable_reg_write(struct sd3078 *sd3078) +static void sd3078_disable_reg_write(struct regmap *regmap) { - regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1, - KEY_WRITE2, 0); - regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1, - KEY_WRITE3, 0); - regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL2, - KEY_WRITE1, 0); + regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE2, 0); + regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE3, 0); + regmap_update_bits(regmap, SD3078_REG_CTRL2, KEY_WRITE1, 0); } #endif @@ -85,11 +74,10 @@ static int sd3078_rtc_read_time(struct device *dev, struct rtc_time *tm) unsigned char hour; unsigned char rtc_data[NUM_TIME_REGS] = {0}; struct i2c_client *client = to_i2c_client(dev); - struct sd3078 *sd3078 = i2c_get_clientdata(client); + struct regmap *regmap = i2c_get_clientdata(client); int ret; - ret = regmap_bulk_read(sd3078->regmap, SD3078_REG_SC, rtc_data, - NUM_TIME_REGS); + ret = regmap_bulk_read(regmap, SD3078_REG_SC, rtc_data, NUM_TIME_REGS); if (ret < 0) { dev_err(dev, "reading from RTC failed with err:%d\n", ret); return ret; @@ -123,7 +111,7 @@ static int sd3078_rtc_set_time(struct device *dev, struct rtc_time *tm) { unsigned char rtc_data[NUM_TIME_REGS]; struct i2c_client *client = to_i2c_client(dev); - struct sd3078 *sd3078 = i2c_get_clientdata(client); + struct regmap *regmap = i2c_get_clientdata(client); int ret; rtc_data[SD3078_REG_SC] = bin2bcd(tm->tm_sec); @@ -135,10 +123,10 @@ static int sd3078_rtc_set_time(struct device *dev, struct rtc_time *tm) rtc_data[SD3078_REG_YR] = bin2bcd(tm->tm_year - 100); #if WRITE_PROTECT_EN - sd3078_enable_reg_write(sd3078); + sd3078_enable_reg_write(regmap); #endif - ret = regmap_bulk_write(sd3078->regmap, SD3078_REG_SC, rtc_data, + ret = regmap_bulk_write(regmap, SD3078_REG_SC, rtc_data, NUM_TIME_REGS); if (ret < 0) { dev_err(dev, "writing to RTC failed with err:%d\n", ret); @@ -146,7 +134,7 @@ static int sd3078_rtc_set_time(struct device *dev, struct rtc_time *tm) } #if WRITE_PROTECT_EN - sd3078_disable_reg_write(sd3078); + sd3078_disable_reg_write(regmap); #endif return 0; @@ -166,42 +154,39 @@ static const struct regmap_config regmap_config = { static int sd3078_probe(struct i2c_client *client) { int ret; - struct sd3078 *sd3078; + struct regmap *regmap; + struct rtc_device *rtc; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; - sd3078 = devm_kzalloc(&client->dev, sizeof(*sd3078), GFP_KERNEL); - if (!sd3078) - return -ENOMEM; - - sd3078->regmap = devm_regmap_init_i2c(client, ®map_config); - if (IS_ERR(sd3078->regmap)) { + regmap = devm_regmap_init_i2c(client, ®map_config); + if (IS_ERR(regmap)) { dev_err(&client->dev, "regmap allocation failed\n"); - return PTR_ERR(sd3078->regmap); + return PTR_ERR(regmap); } - i2c_set_clientdata(client, sd3078); + i2c_set_clientdata(client, regmap); - sd3078->rtc = devm_rtc_allocate_device(&client->dev); - if (IS_ERR(sd3078->rtc)) - return PTR_ERR(sd3078->rtc); + rtc = devm_rtc_allocate_device(&client->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); - sd3078->rtc->ops = &sd3078_rtc_ops; - sd3078->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; - sd3078->rtc->range_max = RTC_TIMESTAMP_END_2099; + rtc->ops = &sd3078_rtc_ops; + rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + rtc->range_max = RTC_TIMESTAMP_END_2099; - ret = devm_rtc_register_device(sd3078->rtc); + ret = devm_rtc_register_device(rtc); if (ret) return ret; - sd3078_enable_reg_write(sd3078); + sd3078_enable_reg_write(regmap); return 0; } static const struct i2c_device_id sd3078_id[] = { - {"sd3078", 0}, + { "sd3078" }, { } }; MODULE_DEVICE_TABLE(i2c, sd3078_id); diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 27a191fa3704..9ea40f40188f 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -611,7 +611,7 @@ static int __init sh_rtc_probe(struct platform_device *pdev) if (ret) goto err_unmap; - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); return 0; err_unmap: @@ -678,7 +678,7 @@ static struct platform_driver sh_rtc_platform_driver __refdata = { .pm = &sh_rtc_pm_ops, .of_match_table = sh_rtc_of_match, }, - .remove_new = __exit_p(sh_rtc_remove), + .remove = __exit_p(sh_rtc_remove), }; module_platform_driver_probe(sh_rtc_platform_driver, sh_rtc_probe); diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index 1df5c7e94198..959acff8faff 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c @@ -395,7 +395,7 @@ static int spear_rtc_probe(struct platform_device *pdev) goto err_disable_clock; if (!device_can_wakeup(&pdev->dev)) - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); return 0; @@ -411,7 +411,7 @@ static void spear_rtc_remove(struct platform_device *pdev) spear_rtc_disable_interrupt(config); clk_disable_unprepare(config->clk); - device_init_wakeup(&pdev->dev, 0); + device_init_wakeup(&pdev->dev, false); } #ifdef CONFIG_PM_SLEEP @@ -475,7 +475,7 @@ MODULE_DEVICE_TABLE(of, spear_rtc_id_table); static struct platform_driver spear_rtc_driver = { .probe = spear_rtc_probe, - .remove_new = spear_rtc_remove, + .remove = spear_rtc_remove, .shutdown = spear_rtc_shutdown, .driver = { .name = "rtc-spear", diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c index d492a2d26600..c6d4522411b3 100644 --- a/drivers/rtc/rtc-st-lpc.c +++ b/drivers/rtc/rtc-st-lpc.c @@ -218,15 +218,14 @@ static int st_rtc_probe(struct platform_device *pdev) return -EINVAL; } - ret = devm_request_irq(&pdev->dev, rtc->irq, st_rtc_handler, 0, - pdev->name, rtc); + ret = devm_request_irq(&pdev->dev, rtc->irq, st_rtc_handler, + IRQF_NO_AUTOEN, pdev->name, rtc); if (ret) { dev_err(&pdev->dev, "Failed to request irq %i\n", rtc->irq); return ret; } enable_irq_wake(rtc->irq); - disable_irq(rtc->irq); rtc->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(rtc->clk)) diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index 76753c71d92e..1b715db47160 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -5,13 +5,18 @@ */ #include <linux/bcd.h> +#include <linux/bitfield.h> #include <linux/clk.h> +#include <linux/clk-provider.h> #include <linux/errno.h> #include <linux/iopoll.h> #include <linux/ioport.h> #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/pinctrl/pinconf-generic.h> +#include <linux/pinctrl/pinmux.h> #include <linux/platform_device.h> #include <linux/pm_wakeirq.h> #include <linux/regmap.h> @@ -41,6 +46,12 @@ #define STM32_RTC_CR_FMT BIT(6) #define STM32_RTC_CR_ALRAE BIT(8) #define STM32_RTC_CR_ALRAIE BIT(12) +#define STM32_RTC_CR_OSEL GENMASK(22, 21) +#define STM32_RTC_CR_OSEL_ALARM_A FIELD_PREP(STM32_RTC_CR_OSEL, 0x01) +#define STM32_RTC_CR_COE BIT(23) +#define STM32_RTC_CR_TAMPOE BIT(26) +#define STM32_RTC_CR_TAMPALRM_TYPE BIT(30) +#define STM32_RTC_CR_OUT2EN BIT(31) /* STM32_RTC_ISR/STM32_RTC_ICSR bit fields */ #define STM32_RTC_ISR_ALRAWF BIT(0) @@ -77,12 +88,30 @@ /* STM32_RTC_SR/_SCR bit fields */ #define STM32_RTC_SR_ALRA BIT(0) +/* STM32_RTC_CFGR bit fields */ +#define STM32_RTC_CFGR_OUT2_RMP BIT(0) +#define STM32_RTC_CFGR_LSCOEN GENMASK(2, 1) +#define STM32_RTC_CFGR_LSCOEN_OUT1 1 +#define STM32_RTC_CFGR_LSCOEN_OUT2_RMP 2 + /* STM32_RTC_VERR bit fields */ #define STM32_RTC_VERR_MINREV_SHIFT 0 #define STM32_RTC_VERR_MINREV GENMASK(3, 0) #define STM32_RTC_VERR_MAJREV_SHIFT 4 #define STM32_RTC_VERR_MAJREV GENMASK(7, 4) +/* STM32_RTC_SECCFGR bit fields */ +#define STM32_RTC_SECCFGR 0x20 +#define STM32_RTC_SECCFGR_ALRA_SEC BIT(0) +#define STM32_RTC_SECCFGR_INIT_SEC BIT(14) +#define STM32_RTC_SECCFGR_SEC BIT(15) + +/* STM32_RTC_RXCIDCFGR bit fields */ +#define STM32_RTC_RXCIDCFGR(x) (0x80 + 0x4 * (x)) +#define STM32_RTC_RXCIDCFGR_CFEN BIT(0) +#define STM32_RTC_RXCIDCFGR_CID GENMASK(6, 4) +#define STM32_RTC_RXCIDCFGR_CID1 1 + /* STM32_RTC_WPR key constants */ #define RTC_WPR_1ST_KEY 0xCA #define RTC_WPR_2ND_KEY 0x53 @@ -94,6 +123,14 @@ /* STM32 RTC driver time helpers */ #define SEC_PER_DAY (24 * 60 * 60) +/* STM32 RTC pinctrl helpers */ +#define STM32_RTC_PINMUX(_name, _action, ...) { \ + .name = (_name), \ + .action = (_action), \ + .groups = ((const char *[]){ __VA_ARGS__ }), \ + .num_groups = ARRAY_SIZE(((const char *[]){ __VA_ARGS__ })), \ +} + struct stm32_rtc; struct stm32_rtc_registers { @@ -106,6 +143,7 @@ struct stm32_rtc_registers { u16 wpr; u16 sr; u16 scr; + u16 cfgr; u16 verr; }; @@ -120,6 +158,9 @@ struct stm32_rtc_data { bool has_pclk; bool need_dbp; bool need_accuracy; + bool rif_protected; + bool has_lsco; + bool has_alarm_out; }; struct stm32_rtc { @@ -132,8 +173,17 @@ struct stm32_rtc { struct clk *rtc_ck; const struct stm32_rtc_data *data; int irq_alarm; + struct clk *clk_lsco; }; +struct stm32_rtc_rif_resource { + unsigned int num; + u32 bit; +}; + +static const struct stm32_rtc_rif_resource STM32_RTC_RES_ALRA = {0, STM32_RTC_SECCFGR_ALRA_SEC}; +static const struct stm32_rtc_rif_resource STM32_RTC_RES_INIT = {5, STM32_RTC_SECCFGR_INIT_SEC}; + static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc) { const struct stm32_rtc_registers *regs = &rtc->data->regs; @@ -149,6 +199,209 @@ static void stm32_rtc_wpr_lock(struct stm32_rtc *rtc) writel_relaxed(RTC_WPR_WRONG_KEY, rtc->base + regs->wpr); } +enum stm32_rtc_pin_name { + NONE, + OUT1, + OUT2, + OUT2_RMP +}; + +static const struct pinctrl_pin_desc stm32_rtc_pinctrl_pins[] = { + PINCTRL_PIN(OUT1, "out1"), + PINCTRL_PIN(OUT2, "out2"), + PINCTRL_PIN(OUT2_RMP, "out2_rmp"), +}; + +static int stm32_rtc_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(stm32_rtc_pinctrl_pins); +} + +static const char *stm32_rtc_pinctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + return stm32_rtc_pinctrl_pins[selector].name; +} + +static int stm32_rtc_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int selector, + const unsigned int **pins, + unsigned int *num_pins) +{ + *pins = &stm32_rtc_pinctrl_pins[selector].number; + *num_pins = 1; + return 0; +} + +static const struct pinctrl_ops stm32_rtc_pinctrl_ops = { + .dt_node_to_map = pinconf_generic_dt_node_to_map_all, + .dt_free_map = pinconf_generic_dt_free_map, + .get_groups_count = stm32_rtc_pinctrl_get_groups_count, + .get_group_name = stm32_rtc_pinctrl_get_group_name, + .get_group_pins = stm32_rtc_pinctrl_get_group_pins, +}; + +struct stm32_rtc_pinmux_func { + const char *name; + const char * const *groups; + const unsigned int num_groups; + int (*action)(struct pinctrl_dev *pctl_dev, unsigned int pin); +}; + +static int stm32_rtc_pinmux_action_alarm(struct pinctrl_dev *pctldev, unsigned int pin) +{ + struct stm32_rtc *rtc = pinctrl_dev_get_drvdata(pctldev); + struct stm32_rtc_registers regs = rtc->data->regs; + unsigned int cr = readl_relaxed(rtc->base + regs.cr); + unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr); + + if (!rtc->data->has_alarm_out) + return -EPERM; + + cr &= ~STM32_RTC_CR_OSEL; + cr |= STM32_RTC_CR_OSEL_ALARM_A; + cr &= ~STM32_RTC_CR_TAMPOE; + cr &= ~STM32_RTC_CR_COE; + cr &= ~STM32_RTC_CR_TAMPALRM_TYPE; + + switch (pin) { + case OUT1: + cr &= ~STM32_RTC_CR_OUT2EN; + cfgr &= ~STM32_RTC_CFGR_OUT2_RMP; + break; + case OUT2: + cr |= STM32_RTC_CR_OUT2EN; + cfgr &= ~STM32_RTC_CFGR_OUT2_RMP; + break; + case OUT2_RMP: + cr |= STM32_RTC_CR_OUT2EN; + cfgr |= STM32_RTC_CFGR_OUT2_RMP; + break; + default: + return -EINVAL; + } + + stm32_rtc_wpr_unlock(rtc); + writel_relaxed(cr, rtc->base + regs.cr); + writel_relaxed(cfgr, rtc->base + regs.cfgr); + stm32_rtc_wpr_lock(rtc); + + return 0; +} + +static int stm32_rtc_pinmux_lsco_available(struct pinctrl_dev *pctldev, unsigned int pin) +{ + struct stm32_rtc *rtc = pinctrl_dev_get_drvdata(pctldev); + struct stm32_rtc_registers regs = rtc->data->regs; + unsigned int cr = readl_relaxed(rtc->base + regs.cr); + unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr); + unsigned int calib = STM32_RTC_CR_COE; + unsigned int tampalrm = STM32_RTC_CR_TAMPOE | STM32_RTC_CR_OSEL; + + switch (pin) { + case OUT1: + if ((!(cr & STM32_RTC_CR_OUT2EN) && + ((cr & calib) || cr & tampalrm)) || + ((cr & calib) && (cr & tampalrm))) + return -EBUSY; + break; + case OUT2_RMP: + if ((cr & STM32_RTC_CR_OUT2EN) && + (cfgr & STM32_RTC_CFGR_OUT2_RMP) && + ((cr & calib) || (cr & tampalrm))) + return -EBUSY; + break; + default: + return -EINVAL; + } + + if (clk_get_rate(rtc->rtc_ck) != 32768) + return -ERANGE; + + return 0; +} + +static int stm32_rtc_pinmux_action_lsco(struct pinctrl_dev *pctldev, unsigned int pin) +{ + struct stm32_rtc *rtc = pinctrl_dev_get_drvdata(pctldev); + struct stm32_rtc_registers regs = rtc->data->regs; + struct device *dev = rtc->rtc_dev->dev.parent; + u8 lscoen; + int ret; + + if (!rtc->data->has_lsco) + return -EPERM; + + ret = stm32_rtc_pinmux_lsco_available(pctldev, pin); + if (ret) + return ret; + + lscoen = (pin == OUT1) ? STM32_RTC_CFGR_LSCOEN_OUT1 : STM32_RTC_CFGR_LSCOEN_OUT2_RMP; + + rtc->clk_lsco = clk_register_gate(dev, "rtc_lsco", __clk_get_name(rtc->rtc_ck), + CLK_IGNORE_UNUSED | CLK_IS_CRITICAL, + rtc->base + regs.cfgr, lscoen, 0, NULL); + if (IS_ERR(rtc->clk_lsco)) + return PTR_ERR(rtc->clk_lsco); + + of_clk_add_provider(dev->of_node, of_clk_src_simple_get, rtc->clk_lsco); + + return 0; +} + +static const struct stm32_rtc_pinmux_func stm32_rtc_pinmux_functions[] = { + STM32_RTC_PINMUX("lsco", &stm32_rtc_pinmux_action_lsco, "out1", "out2_rmp"), + STM32_RTC_PINMUX("alarm-a", &stm32_rtc_pinmux_action_alarm, "out1", "out2", "out2_rmp"), +}; + +static int stm32_rtc_pinmux_get_functions_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(stm32_rtc_pinmux_functions); +} + +static const char *stm32_rtc_pinmux_get_fname(struct pinctrl_dev *pctldev, unsigned int selector) +{ + return stm32_rtc_pinmux_functions[selector].name; +} + +static int stm32_rtc_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned int selector, + const char * const **groups, unsigned int * const num_groups) +{ + *groups = stm32_rtc_pinmux_functions[selector].groups; + *num_groups = stm32_rtc_pinmux_functions[selector].num_groups; + return 0; +} + +static int stm32_rtc_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int selector, + unsigned int group) +{ + struct stm32_rtc_pinmux_func selected_func = stm32_rtc_pinmux_functions[selector]; + struct pinctrl_pin_desc pin = stm32_rtc_pinctrl_pins[group]; + + /* Call action */ + if (selected_func.action) + return selected_func.action(pctldev, pin.number); + + return -EINVAL; +} + +static const struct pinmux_ops stm32_rtc_pinmux_ops = { + .get_functions_count = stm32_rtc_pinmux_get_functions_count, + .get_function_name = stm32_rtc_pinmux_get_fname, + .get_function_groups = stm32_rtc_pinmux_get_groups, + .set_mux = stm32_rtc_pinmux_set_mux, + .strict = true, +}; + +static struct pinctrl_desc stm32_rtc_pdesc = { + .name = DRIVER_NAME, + .pins = stm32_rtc_pinctrl_pins, + .npins = ARRAY_SIZE(stm32_rtc_pinctrl_pins), + .owner = THIS_MODULE, + .pctlops = &stm32_rtc_pinctrl_ops, + .pmxops = &stm32_rtc_pinmux_ops, +}; + static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc) { const struct stm32_rtc_registers *regs = &rtc->data->regs; @@ -553,6 +806,9 @@ static const struct stm32_rtc_data stm32_rtc_data = { .has_pclk = false, .need_dbp = true, .need_accuracy = false, + .rif_protected = false, + .has_lsco = false, + .has_alarm_out = false, .regs = { .tr = 0x00, .dr = 0x04, @@ -563,6 +819,7 @@ static const struct stm32_rtc_data stm32_rtc_data = { .wpr = 0x24, .sr = 0x0C, /* set to ISR offset to ease alarm management */ .scr = UNDEF_REG, + .cfgr = UNDEF_REG, .verr = UNDEF_REG, }, .events = { @@ -575,6 +832,9 @@ static const struct stm32_rtc_data stm32h7_rtc_data = { .has_pclk = true, .need_dbp = true, .need_accuracy = false, + .rif_protected = false, + .has_lsco = false, + .has_alarm_out = false, .regs = { .tr = 0x00, .dr = 0x04, @@ -585,6 +845,7 @@ static const struct stm32_rtc_data stm32h7_rtc_data = { .wpr = 0x24, .sr = 0x0C, /* set to ISR offset to ease alarm management */ .scr = UNDEF_REG, + .cfgr = UNDEF_REG, .verr = UNDEF_REG, }, .events = { @@ -606,6 +867,9 @@ static const struct stm32_rtc_data stm32mp1_data = { .has_pclk = true, .need_dbp = false, .need_accuracy = true, + .rif_protected = false, + .has_lsco = true, + .has_alarm_out = true, .regs = { .tr = 0x00, .dr = 0x04, @@ -616,6 +880,33 @@ static const struct stm32_rtc_data stm32mp1_data = { .wpr = 0x24, .sr = 0x50, .scr = 0x5C, + .cfgr = 0x60, + .verr = 0x3F4, + }, + .events = { + .alra = STM32_RTC_SR_ALRA, + }, + .clear_events = stm32mp1_rtc_clear_events, +}; + +static const struct stm32_rtc_data stm32mp25_data = { + .has_pclk = true, + .need_dbp = false, + .need_accuracy = true, + .rif_protected = true, + .has_lsco = true, + .has_alarm_out = true, + .regs = { + .tr = 0x00, + .dr = 0x04, + .cr = 0x18, + .isr = 0x0C, /* named RTC_ICSR on stm32mp25 */ + .prer = 0x10, + .alrmar = 0x40, + .wpr = 0x24, + .sr = 0x50, + .scr = 0x5C, + .cfgr = 0x60, .verr = 0x3F4, }, .events = { @@ -628,10 +919,54 @@ static const struct of_device_id stm32_rtc_of_match[] = { { .compatible = "st,stm32-rtc", .data = &stm32_rtc_data }, { .compatible = "st,stm32h7-rtc", .data = &stm32h7_rtc_data }, { .compatible = "st,stm32mp1-rtc", .data = &stm32mp1_data }, + { .compatible = "st,stm32mp25-rtc", .data = &stm32mp25_data }, {} }; MODULE_DEVICE_TABLE(of, stm32_rtc_of_match); +static void stm32_rtc_clean_outs(struct stm32_rtc *rtc) +{ + struct stm32_rtc_registers regs = rtc->data->regs; + unsigned int cr = readl_relaxed(rtc->base + regs.cr); + + cr &= ~STM32_RTC_CR_OSEL; + cr &= ~STM32_RTC_CR_TAMPOE; + cr &= ~STM32_RTC_CR_COE; + cr &= ~STM32_RTC_CR_TAMPALRM_TYPE; + cr &= ~STM32_RTC_CR_OUT2EN; + + stm32_rtc_wpr_unlock(rtc); + writel_relaxed(cr, rtc->base + regs.cr); + stm32_rtc_wpr_lock(rtc); + + if (regs.cfgr != UNDEF_REG) { + unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr); + + cfgr &= ~STM32_RTC_CFGR_LSCOEN; + cfgr &= ~STM32_RTC_CFGR_OUT2_RMP; + writel_relaxed(cfgr, rtc->base + regs.cfgr); + } +} + +static int stm32_rtc_check_rif(struct stm32_rtc *stm32_rtc, + struct stm32_rtc_rif_resource res) +{ + u32 rxcidcfgr = readl_relaxed(stm32_rtc->base + STM32_RTC_RXCIDCFGR(res.num)); + u32 seccfgr; + + /* Check if RTC available for our CID */ + if ((rxcidcfgr & STM32_RTC_RXCIDCFGR_CFEN) && + (FIELD_GET(STM32_RTC_RXCIDCFGR_CID, rxcidcfgr) != STM32_RTC_RXCIDCFGR_CID1)) + return -EACCES; + + /* Check if RTC available for non secure world */ + seccfgr = readl_relaxed(stm32_rtc->base + STM32_RTC_SECCFGR); + if ((seccfgr & STM32_RTC_SECCFGR_SEC) | (seccfgr & res.bit)) + return -EACCES; + + return 0; +} + static int stm32_rtc_init(struct platform_device *pdev, struct stm32_rtc *rtc) { @@ -723,6 +1058,7 @@ static int stm32_rtc_probe(struct platform_device *pdev) { struct stm32_rtc *rtc; const struct stm32_rtc_registers *regs; + struct pinctrl_dev *pctl; int ret; rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); @@ -738,26 +1074,18 @@ static int stm32_rtc_probe(struct platform_device *pdev) regs = &rtc->data->regs; if (rtc->data->need_dbp) { - rtc->dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, - "st,syscfg"); + unsigned int args[2]; + + rtc->dbp = syscon_regmap_lookup_by_phandle_args(pdev->dev.of_node, + "st,syscfg", + 2, args); if (IS_ERR(rtc->dbp)) { dev_err(&pdev->dev, "no st,syscfg\n"); return PTR_ERR(rtc->dbp); } - ret = of_property_read_u32_index(pdev->dev.of_node, "st,syscfg", - 1, &rtc->dbp_reg); - if (ret) { - dev_err(&pdev->dev, "can't read DBP register offset\n"); - return ret; - } - - ret = of_property_read_u32_index(pdev->dev.of_node, "st,syscfg", - 2, &rtc->dbp_mask); - if (ret) { - dev_err(&pdev->dev, "can't read DBP register mask\n"); - return ret; - } + rtc->dbp_reg = args[0]; + rtc->dbp_mask = args[1]; } if (!rtc->data->has_pclk) { @@ -787,6 +1115,16 @@ static int stm32_rtc_probe(struct platform_device *pdev) regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, rtc->dbp_mask); + if (rtc->data->rif_protected) { + ret = stm32_rtc_check_rif(rtc, STM32_RTC_RES_INIT); + if (!ret) + ret = stm32_rtc_check_rif(rtc, STM32_RTC_RES_ALRA); + if (ret) { + dev_err(&pdev->dev, "Failed to probe RTC due to RIF configuration\n"); + goto err; + } + } + /* * After a system reset, RTC_ISR.INITS flag can be read to check if * the calendar has been initialized or not. INITS flag is reset by a @@ -805,11 +1143,11 @@ static int stm32_rtc_probe(struct platform_device *pdev) goto err; } - ret = device_init_wakeup(&pdev->dev, true); + ret = devm_device_init_wakeup(&pdev->dev); if (ret) goto err; - ret = dev_pm_set_wake_irq(&pdev->dev, rtc->irq_alarm); + ret = devm_pm_set_wake_irq(&pdev->dev, rtc->irq_alarm); if (ret) goto err; @@ -834,6 +1172,16 @@ static int stm32_rtc_probe(struct platform_device *pdev) goto err; } + stm32_rtc_clean_outs(rtc); + + ret = devm_pinctrl_register_and_init(&pdev->dev, &stm32_rtc_pdesc, rtc, &pctl); + if (ret) + return dev_err_probe(&pdev->dev, ret, "pinctrl register failed"); + + ret = pinctrl_enable(pctl); + if (ret) + return dev_err_probe(&pdev->dev, ret, "pinctrl enable failed"); + /* * If INITS flag is reset (calendar year field set to 0x00), calendar * must be initialized @@ -860,9 +1208,6 @@ err_no_rtc_ck: if (rtc->data->need_dbp) regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0); - dev_pm_clear_wake_irq(&pdev->dev); - device_init_wakeup(&pdev->dev, false); - return ret; } @@ -872,6 +1217,9 @@ static void stm32_rtc_remove(struct platform_device *pdev) const struct stm32_rtc_registers *regs = &rtc->data->regs; unsigned int cr; + if (!IS_ERR_OR_NULL(rtc->clk_lsco)) + clk_unregister_gate(rtc->clk_lsco); + /* Disable interrupts */ stm32_rtc_wpr_unlock(rtc); cr = readl_relaxed(rtc->base + regs->cr); @@ -886,9 +1234,6 @@ static void stm32_rtc_remove(struct platform_device *pdev) /* Enable backup domain write protection if needed */ if (rtc->data->need_dbp) regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0); - - dev_pm_clear_wake_irq(&pdev->dev); - device_init_wakeup(&pdev->dev, false); } static int stm32_rtc_suspend(struct device *dev) @@ -928,7 +1273,7 @@ static const struct dev_pm_ops stm32_rtc_pm_ops = { static struct platform_driver stm32_rtc_driver = { .probe = stm32_rtc_probe, - .remove_new = stm32_rtc_remove, + .remove = stm32_rtc_remove, .driver = { .name = DRIVER_NAME, .pm = &stm32_rtc_pm_ops, diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index 7566d0a44af8..7afcd14aeee5 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c @@ -403,7 +403,7 @@ MODULE_DEVICE_TABLE(of, rtc_dt_ids); static struct platform_driver stmp3xxx_rtcdrv = { .probe = stmp3xxx_rtc_probe, - .remove_new = stmp3xxx_rtc_remove, + .remove = stmp3xxx_rtc_remove, .driver = { .name = "stmp3xxx-rtc", .pm = &stmp3xxx_rtc_pm_ops, diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index 8e0c66906103..e5e6013d080e 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -402,6 +402,7 @@ CLK_OF_DECLARE_DRIVER(sun8i_r40_rtc_clk, "allwinner,sun8i-r40-rtc", static const struct sun6i_rtc_clk_data sun8i_v3_rtc_data = { .rc_osc_rate = 32000, .has_out_clk = 1, + .has_auto_swt = 1, }; static void __init sun8i_v3_rtc_clk_init(struct device_node *node) @@ -825,7 +826,7 @@ static int sun6i_rtc_probe(struct platform_device *pdev) clk_prepare_enable(chip->losc); - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); chip->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(chip->rtc)) diff --git a/drivers/rtc/rtc-sunplus.c b/drivers/rtc/rtc-sunplus.c index 20c7e97c2fc8..519a06e728d6 100644 --- a/drivers/rtc/rtc-sunplus.c +++ b/drivers/rtc/rtc-sunplus.c @@ -269,7 +269,7 @@ static int sp_rtc_probe(struct platform_device *plat_dev) if (ret) goto free_reset_assert; - device_init_wakeup(&plat_dev->dev, 1); + device_init_wakeup(&plat_dev->dev, true); dev_set_drvdata(&plat_dev->dev, sp_rtc); sp_rtc->rtc = devm_rtc_allocate_device(&plat_dev->dev); @@ -307,7 +307,7 @@ static void sp_rtc_remove(struct platform_device *plat_dev) { struct sunplus_rtc *sp_rtc = dev_get_drvdata(&plat_dev->dev); - device_init_wakeup(&plat_dev->dev, 0); + device_init_wakeup(&plat_dev->dev, false); reset_control_assert(sp_rtc->rstc); clk_disable_unprepare(sp_rtc->rtcclk); } @@ -344,7 +344,7 @@ static SIMPLE_DEV_PM_OPS(sp_rtc_pm_ops, sp_rtc_suspend, sp_rtc_resume); static struct platform_driver sp_rtc_driver = { .probe = sp_rtc_probe, - .remove_new = sp_rtc_remove, + .remove = sp_rtc_remove, .driver = { .name = "sp7021-rtc", .of_match_table = sp_rtc_of_match, diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index 441e0a66b215..46788db89953 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -319,7 +319,7 @@ static int tegra_rtc_probe(struct platform_device *pdev) writel(0xffffffff, info->base + TEGRA_RTC_REG_INTR_STATUS); writel(0, info->base + TEGRA_RTC_REG_INTR_MASK); - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); ret = devm_request_irq(&pdev->dev, info->irq, tegra_rtc_irq_handler, IRQF_TRIGGER_HIGH, dev_name(&pdev->dev), @@ -399,7 +399,7 @@ static void tegra_rtc_shutdown(struct platform_device *pdev) static struct platform_driver tegra_rtc_driver = { .probe = tegra_rtc_probe, - .remove_new = tegra_rtc_remove, + .remove = tegra_rtc_remove, .shutdown = tegra_rtc_shutdown, .driver = { .name = "tegra_rtc", diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index 7e0d8fb26465..a9f5b9466fb5 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -44,7 +44,7 @@ static int test_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) timeout = rtc_tm_to_time64(&alrm->time) - ktime_get_real_seconds(); timeout -= rtd->offset; - del_timer(&rtd->alarm); + timer_delete(&rtd->alarm); expires = jiffies + timeout * HZ; if (expires > U32_MAX) @@ -86,7 +86,7 @@ static int test_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) if (enable) add_timer(&rtd->alarm); else - del_timer(&rtd->alarm); + timer_delete(&rtd->alarm); return 0; } @@ -132,7 +132,7 @@ static int test_probe(struct platform_device *plat_dev) break; default: rtd->rtc->ops = &test_rtc_ops; - device_init_wakeup(&plat_dev->dev, 1); + device_init_wakeup(&plat_dev->dev, true); } timer_setup(&rtd->alarm, test_rtc_alarm_handler, 0); diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c index 20faf08c254c..54c8429b16bf 100644 --- a/drivers/rtc/rtc-tps6586x.c +++ b/drivers/rtc/rtc-tps6586x.c @@ -241,7 +241,7 @@ static int tps6586x_rtc_probe(struct platform_device *pdev) return ret; } - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); platform_set_drvdata(pdev, rtc); rtc->rtc = devm_rtc_allocate_device(&pdev->dev); @@ -317,7 +317,7 @@ static struct platform_driver tps6586x_rtc_driver = { .pm = &tps6586x_pm_ops, }, .probe = tps6586x_rtc_probe, - .remove_new = tps6586x_rtc_remove, + .remove = tps6586x_rtc_remove, }; module_platform_driver(tps6586x_rtc_driver); diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 411ff66c0468..284aa2f0392b 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -418,7 +418,7 @@ static int tps65910_rtc_probe(struct platform_device *pdev) tps_rtc->irq = irq; if (irq != -1) { if (device_property_present(tps65910->dev, "wakeup-source")) - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); else device_set_wakeup_capable(&pdev->dev, 1); } else { @@ -466,4 +466,5 @@ static struct platform_driver tps65910_rtc_driver = { module_platform_driver(tps65910_rtc_driver); MODULE_ALIAS("platform:tps65910-rtc"); MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>"); +MODULE_DESCRIPTION("TI TPS65910 RTC driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-tps6594.c b/drivers/rtc/rtc-tps6594.c index 838ae8562a35..7c6246e3f029 100644 --- a/drivers/rtc/rtc-tps6594.c +++ b/drivers/rtc/rtc-tps6594.c @@ -37,11 +37,16 @@ #define MAX_OFFSET (277774) // Number of ticks per hour -#define TICKS_PER_HOUR (32768 * 3600) +#define TICKS_PER_HOUR (32768 * 3600LL) // Multiplier for ppb conversions #define PPB_MULT NANO +struct tps6594_rtc { + struct rtc_device *rtc_dev; + int irq; +}; + static int tps6594_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { @@ -325,11 +330,11 @@ static int tps6594_rtc_set_offset(struct device *dev, long offset) return tps6594_rtc_set_calibration(dev, calibration); } -static irqreturn_t tps6594_rtc_interrupt(int irq, void *rtc) +static irqreturn_t tps6594_rtc_interrupt(int irq, void *data) { - struct device *dev = rtc; + struct device *dev = data; struct tps6594 *tps = dev_get_drvdata(dev->parent); - struct rtc_device *rtc_dev = dev_get_drvdata(dev); + struct tps6594_rtc *rtc = dev_get_drvdata(dev); int ret; u32 rtc_reg; @@ -337,7 +342,7 @@ static irqreturn_t tps6594_rtc_interrupt(int irq, void *rtc) if (ret) return IRQ_NONE; - rtc_update_irq(rtc_dev, 1, RTC_IRQF | RTC_AF); + rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF); return IRQ_HANDLED; } @@ -356,7 +361,7 @@ static int tps6594_rtc_probe(struct platform_device *pdev) { struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent); struct device *dev = &pdev->dev; - struct rtc_device *rtc; + struct tps6594_rtc *rtc; int irq; int ret; @@ -364,9 +369,9 @@ static int tps6594_rtc_probe(struct platform_device *pdev) if (!rtc) return -ENOMEM; - rtc = devm_rtc_allocate_device(dev); - if (IS_ERR(rtc)) - return PTR_ERR(rtc); + rtc->rtc_dev = devm_rtc_allocate_device(dev); + if (IS_ERR(rtc->rtc_dev)) + return PTR_ERR(rtc->rtc_dev); // Enable crystal oscillator. ret = regmap_set_bits(tps->regmap, TPS6594_REG_RTC_CTRL_2, @@ -415,6 +420,8 @@ static int tps6594_rtc_probe(struct platform_device *pdev) if (irq < 0) return dev_err_probe(dev, irq, "Failed to get irq\n"); + rtc->irq = irq; + ret = devm_request_threaded_irq(dev, irq, NULL, tps6594_rtc_interrupt, IRQF_ONESHOT, TPS6594_IRQ_NAME_ALARM, dev); @@ -427,13 +434,56 @@ static int tps6594_rtc_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "Failed to init rtc as wakeup source\n"); - rtc->ops = &tps6594_rtc_ops; - rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; - rtc->range_max = RTC_TIMESTAMP_END_2099; + rtc->rtc_dev->ops = &tps6594_rtc_ops; + rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000; + rtc->rtc_dev->range_max = RTC_TIMESTAMP_END_2099; + + return devm_rtc_register_device(rtc->rtc_dev); +} + +static int tps6594_rtc_resume(struct device *dev) +{ + struct tps6594 *tps = dev_get_drvdata(dev->parent); + struct tps6594_rtc *rtc = dev_get_drvdata(dev); + int ret; + + ret = regmap_test_bits(tps->regmap, TPS6594_REG_INT_STARTUP, + TPS6594_BIT_RTC_INT); + if (ret < 0) { + dev_err(dev, "failed to read REG_INT_STARTUP: %d\n", ret); + goto out; + } + + if (ret > 0) { + /* + * If the alarm bit is set, it means that the IRQ has been + * fired. But, the kernel may not have woke up yet when it + * happened. So, we have to clear it. + */ + ret = regmap_write(tps->regmap, TPS6594_REG_RTC_STATUS, + TPS6594_BIT_ALARM); + if (ret < 0) + dev_err(dev, "error clearing alarm bit: %d", ret); - return devm_rtc_register_device(rtc); + rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF); + } +out: + disable_irq_wake(rtc->irq); + + return 0; } +static int tps6594_rtc_suspend(struct device *dev) +{ + struct tps6594_rtc *rtc = dev_get_drvdata(dev); + + enable_irq_wake(rtc->irq); + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(tps6594_rtc_pm_ops, tps6594_rtc_suspend, tps6594_rtc_resume); + static const struct platform_device_id tps6594_rtc_id_table[] = { { "tps6594-rtc", }, {} @@ -444,6 +494,7 @@ static struct platform_driver tps6594_rtc_driver = { .probe = tps6594_rtc_probe, .driver = { .name = "tps6594-rtc", + .pm = pm_sleep_ptr(&tps6594_rtc_pm_ops), }, .id_table = tps6594_rtc_id_table, }; diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 13f8ce08243c..e6106e67e1f4 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -572,7 +572,7 @@ static int twl_rtc_probe(struct platform_device *pdev) return ret; platform_set_drvdata(pdev, twl_rtc); - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); twl_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &twl_rtc_ops, THIS_MODULE); @@ -591,8 +591,8 @@ static int twl_rtc_probe(struct platform_device *pdev) memset(&nvmem_cfg, 0, sizeof(nvmem_cfg)); nvmem_cfg.name = "twl-secured-"; nvmem_cfg.type = NVMEM_TYPE_BATTERY_BACKED; - nvmem_cfg.reg_read = twl_nvram_read, - nvmem_cfg.reg_write = twl_nvram_write, + nvmem_cfg.reg_read = twl_nvram_read; + nvmem_cfg.reg_write = twl_nvram_write; nvmem_cfg.word_size = 1; nvmem_cfg.stride = 1; if (twl_class_is_4030()) { @@ -673,7 +673,7 @@ MODULE_DEVICE_TABLE(of, twl_rtc_of_match); static struct platform_driver twl4030rtc_driver = { .probe = twl_rtc_probe, - .remove_new = twl_rtc_remove, + .remove = twl_rtc_remove, .shutdown = twl_rtc_shutdown, .driver = { .name = "twl_rtc", @@ -685,4 +685,5 @@ static struct platform_driver twl4030rtc_driver = { module_platform_driver(twl4030rtc_driver); MODULE_AUTHOR("Texas Instruments, MontaVista Software"); +MODULE_DESCRIPTION("TI TWL4030/TWL5030/TWL6030/TPS659x0 RTC driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index ccfa76513a2c..c8b568498016 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c @@ -251,7 +251,7 @@ MODULE_DEVICE_TABLE(of, wmt_dt_ids); static struct platform_driver vt8500_rtc_driver = { .probe = vt8500_rtc_probe, - .remove_new = vt8500_rtc_remove, + .remove = vt8500_rtc_remove, .driver = { .name = "vt8500-rtc", .of_match_table = wmt_dt_ids, diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index 640833e21057..218316be942a 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c @@ -420,7 +420,7 @@ static int wm831x_rtc_probe(struct platform_device *pdev) if (ret & WM831X_RTC_ALM_ENA) wm831x_rtc->alarm_enabled = 1; - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); wm831x_rtc->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(wm831x_rtc->rtc)) diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index 3c773cff2b39..3bd60d067a5e 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c @@ -420,7 +420,7 @@ static int wm8350_rtc_probe(struct platform_device *pdev) } } - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); wm_rtc->rtc = devm_rtc_device_register(&pdev->dev, "wm8350", &wm8350_rtc_ops, THIS_MODULE); @@ -459,7 +459,7 @@ static SIMPLE_DEV_PM_OPS(wm8350_rtc_pm_ops, wm8350_rtc_suspend, static struct platform_driver wm8350_rtc_driver = { .probe = wm8350_rtc_probe, - .remove_new = wm8350_rtc_remove, + .remove = wm8350_rtc_remove, .driver = { .name = "wm8350-rtc", .pm = &wm8350_rtc_pm_ops, diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index 807f953ae0ae..4bcd7ca32f27 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c @@ -663,7 +663,7 @@ static void x1205_remove(struct i2c_client *client) } static const struct i2c_device_id x1205_id[] = { - { "x1205", 0 }, + { "x1205" }, { } }; MODULE_DEVICE_TABLE(i2c, x1205_id); diff --git a/drivers/rtc/rtc-xgene.c b/drivers/rtc/rtc-xgene.c index f78efc9760c0..6660b664e8dd 100644 --- a/drivers/rtc/rtc-xgene.c +++ b/drivers/rtc/rtc-xgene.c @@ -174,7 +174,7 @@ static int xgene_rtc_probe(struct platform_device *pdev) /* Turn on the clock and the crystal */ writel(RTC_CCR_EN, pdata->csr_base + RTC_CCR); - ret = device_init_wakeup(&pdev->dev, 1); + ret = device_init_wakeup(&pdev->dev, true); if (ret) { clk_disable_unprepare(pdata->clk); return ret; @@ -197,7 +197,7 @@ static void xgene_rtc_remove(struct platform_device *pdev) struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev); xgene_rtc_alarm_irq_enable(&pdev->dev, 0); - device_init_wakeup(&pdev->dev, 0); + device_init_wakeup(&pdev->dev, false); clk_disable_unprepare(pdata->clk); } @@ -263,7 +263,7 @@ MODULE_DEVICE_TABLE(of, xgene_rtc_of_match); static struct platform_driver xgene_rtc_driver = { .probe = xgene_rtc_probe, - .remove_new = xgene_rtc_remove, + .remove = xgene_rtc_remove, .driver = { .name = "xgene-rtc", .pm = &xgene_rtc_pm_ops, diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c index 08ed171bdab4..f39102b66eac 100644 --- a/drivers/rtc/rtc-zynqmp.c +++ b/drivers/rtc/rtc-zynqmp.c @@ -318,8 +318,8 @@ static int xlnx_rtc_probe(struct platform_device *pdev) return ret; } - /* Getting the rtc_clk info */ - xrtcdev->rtc_clk = devm_clk_get_optional(&pdev->dev, "rtc_clk"); + /* Getting the rtc info */ + xrtcdev->rtc_clk = devm_clk_get_optional(&pdev->dev, "rtc"); if (IS_ERR(xrtcdev->rtc_clk)) { if (PTR_ERR(xrtcdev->rtc_clk) != -EPROBE_DEFER) dev_warn(&pdev->dev, "Device clock not found.\n"); @@ -337,7 +337,7 @@ static int xlnx_rtc_probe(struct platform_device *pdev) xlnx_init_rtc(xrtcdev); - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, true); return devm_rtc_register_device(xrtcdev->rtc); } @@ -345,7 +345,7 @@ static int xlnx_rtc_probe(struct platform_device *pdev) static void xlnx_rtc_remove(struct platform_device *pdev) { xlnx_rtc_alarm_irq_enable(&pdev->dev, 0); - device_init_wakeup(&pdev->dev, 0); + device_init_wakeup(&pdev->dev, false); } static int __maybe_unused xlnx_rtc_suspend(struct device *dev) @@ -382,7 +382,7 @@ MODULE_DEVICE_TABLE(of, xlnx_rtc_of_match); static struct platform_driver xlnx_rtc_driver = { .probe = xlnx_rtc_probe, - .remove_new = xlnx_rtc_remove, + .remove = xlnx_rtc_remove, .driver = { .name = KBUILD_MODNAME, .pm = &xlnx_rtc_pm_ops, |