summaryrefslogtreecommitdiff
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig79
-rw-r--r--drivers/rtc/Makefile9
-rw-r--r--drivers/rtc/class.c3
-rw-r--r--drivers/rtc/dev.c3
-rw-r--r--drivers/rtc/interface.c16
-rw-r--r--drivers/rtc/lib_test.c34
-rw-r--r--drivers/rtc/rtc-88pm80x.c4
-rw-r--r--drivers/rtc/rtc-88pm860x.c4
-rw-r--r--drivers/rtc/rtc-88pm886.c97
-rw-r--r--drivers/rtc/rtc-ab-b5ze-s3.c2
-rw-r--r--drivers/rtc/rtc-ab-eoz9.c37
-rw-r--r--drivers/rtc/rtc-ab8500.c11
-rw-r--r--drivers/rtc/rtc-abx80x.c14
-rw-r--r--drivers/rtc/rtc-ac100.c2
-rw-r--r--drivers/rtc/rtc-amlogic-a4.c465
-rw-r--r--drivers/rtc/rtc-armada38x.c2
-rw-r--r--drivers/rtc/rtc-as3722.c2
-rw-r--r--drivers/rtc/rtc-asm9260.c2
-rw-r--r--drivers/rtc/rtc-aspeed.c16
-rw-r--r--drivers/rtc/rtc-at91rm9200.c4
-rw-r--r--drivers/rtc/rtc-at91sam9.c5
-rw-r--r--drivers/rtc/rtc-bd70528.c5
-rw-r--r--drivers/rtc/rtc-bq32k.c2
-rw-r--r--drivers/rtc/rtc-brcmstb-waketimer.c3
-rw-r--r--drivers/rtc/rtc-cadence.c4
-rw-r--r--drivers/rtc/rtc-cmos.c42
-rw-r--r--drivers/rtc/rtc-cpcap.c2
-rw-r--r--drivers/rtc/rtc-cros-ec.c43
-rw-r--r--drivers/rtc/rtc-da9055.c2
-rw-r--r--drivers/rtc/rtc-ds1307.c11
-rw-r--r--drivers/rtc/rtc-ds1343.c8
-rw-r--r--drivers/rtc/rtc-ds1374.c2
-rw-r--r--drivers/rtc/rtc-ds1672.c2
-rw-r--r--drivers/rtc/rtc-ds1685.c2
-rw-r--r--drivers/rtc/rtc-ds2404.c14
-rw-r--r--drivers/rtc/rtc-ds3232.c28
-rw-r--r--drivers/rtc/rtc-em3027.c2
-rw-r--r--drivers/rtc/rtc-ep93xx.c16
-rw-r--r--drivers/rtc/rtc-fm3130.c2
-rw-r--r--drivers/rtc/rtc-fsl-ftm-alarm.c2
-rw-r--r--drivers/rtc/rtc-ftrtc010.c19
-rw-r--r--drivers/rtc/rtc-goldfish.c1
-rw-r--r--drivers/rtc/rtc-hid-sensor-time.c4
-rw-r--r--drivers/rtc/rtc-hym8563.c4
-rw-r--r--drivers/rtc/rtc-imx-sm-bbm.c162
-rw-r--r--drivers/rtc/rtc-imxdi.c2
-rw-r--r--drivers/rtc/rtc-isl12022.c271
-rw-r--r--drivers/rtc/rtc-isl1208.c38
-rw-r--r--drivers/rtc/rtc-jz4740.c2
-rw-r--r--drivers/rtc/rtc-loongson.c19
-rw-r--r--drivers/rtc/rtc-lp8788.c2
-rw-r--r--drivers/rtc/rtc-lpc24xx.c2
-rw-r--r--drivers/rtc/rtc-lpc32xx.c2
-rw-r--r--drivers/rtc/rtc-m41t80.c1
-rw-r--r--drivers/rtc/rtc-m48t59.c30
-rw-r--r--drivers/rtc/rtc-m48t86.c14
-rw-r--r--drivers/rtc/rtc-max31335.c167
-rw-r--r--drivers/rtc/rtc-max6900.c2
-rw-r--r--drivers/rtc/rtc-max77686.c41
-rw-r--r--drivers/rtc/rtc-max8925.c2
-rw-r--r--drivers/rtc/rtc-max8997.c2
-rw-r--r--drivers/rtc/rtc-mc13xxx.c2
-rw-r--r--drivers/rtc/rtc-mc146818-lib.c6
-rw-r--r--drivers/rtc/rtc-mcp795.c1
-rw-r--r--drivers/rtc/rtc-meson-vrtc.c14
-rw-r--r--drivers/rtc/rtc-meson.c16
-rw-r--r--drivers/rtc/rtc-mpc5121.c5
-rw-r--r--drivers/rtc/rtc-mpfs.c10
-rw-r--r--drivers/rtc/rtc-mt6397.c31
-rw-r--r--drivers/rtc/rtc-mt7622.c2
-rw-r--r--drivers/rtc/rtc-mv.c6
-rw-r--r--drivers/rtc/rtc-mxc.c2
-rw-r--r--drivers/rtc/rtc-mxc_v2.c4
-rw-r--r--drivers/rtc/rtc-nct3018y.c17
-rw-r--r--drivers/rtc/rtc-nxp-bbnsm.c9
-rw-r--r--drivers/rtc/rtc-omap.c5
-rw-r--r--drivers/rtc/rtc-palmas.c4
-rw-r--r--drivers/rtc/rtc-pcf2127.c82
-rw-r--r--drivers/rtc/rtc-pcf50633.c284
-rw-r--r--drivers/rtc/rtc-pcf85063.c36
-rw-r--r--drivers/rtc/rtc-pcf8523.c2
-rw-r--r--drivers/rtc/rtc-pcf8563.c225
-rw-r--r--drivers/rtc/rtc-pcf8583.c2
-rw-r--r--drivers/rtc/rtc-pic32.c4
-rw-r--r--drivers/rtc/rtc-pl030.c16
-rw-r--r--drivers/rtc/rtc-pl031.c8
-rw-r--r--drivers/rtc/rtc-pm8xxx.c220
-rw-r--r--drivers/rtc/rtc-pxa.c4
-rw-r--r--drivers/rtc/rtc-rc5t583.c5
-rw-r--r--drivers/rtc/rtc-rc5t619.c15
-rw-r--r--drivers/rtc/rtc-renesas-rtca3.c897
-rw-r--r--drivers/rtc/rtc-rk808.c2
-rw-r--r--drivers/rtc/rtc-rtd119x.c2
-rw-r--r--drivers/rtc/rtc-rv3028.c6
-rw-r--r--drivers/rtc/rtc-rv3029c2.c4
-rw-r--r--drivers/rtc/rtc-rv3032.c8
-rw-r--r--drivers/rtc/rtc-rx6110.c6
-rw-r--r--drivers/rtc/rtc-rx8010.c2
-rw-r--r--drivers/rtc/rtc-rx8111.c368
-rw-r--r--drivers/rtc/rtc-rx8581.c87
-rw-r--r--drivers/rtc/rtc-rzn1.c200
-rw-r--r--drivers/rtc/rtc-s35390a.c25
-rw-r--r--drivers/rtc/rtc-s3c.c4
-rw-r--r--drivers/rtc/rtc-s5m.c60
-rw-r--r--drivers/rtc/rtc-sa1100.c4
-rw-r--r--drivers/rtc/rtc-sc27xx.c4
-rw-r--r--drivers/rtc/rtc-sd2405al.c227
-rw-r--r--drivers/rtc/rtc-sd3078.c73
-rw-r--r--drivers/rtc/rtc-sh.c4
-rw-r--r--drivers/rtc/rtc-spear.c6
-rw-r--r--drivers/rtc/rtc-st-lpc.c5
-rw-r--r--drivers/rtc/rtc-stm32.c393
-rw-r--r--drivers/rtc/rtc-stmp3xxx.c2
-rw-r--r--drivers/rtc/rtc-sun6i.c3
-rw-r--r--drivers/rtc/rtc-sunplus.c6
-rw-r--r--drivers/rtc/rtc-tegra.c4
-rw-r--r--drivers/rtc/rtc-test.c6
-rw-r--r--drivers/rtc/rtc-tps6586x.c4
-rw-r--r--drivers/rtc/rtc-tps65910.c3
-rw-r--r--drivers/rtc/rtc-tps6594.c77
-rw-r--r--drivers/rtc/rtc-twl.c9
-rw-r--r--drivers/rtc/rtc-vt8500.c2
-rw-r--r--drivers/rtc/rtc-wm831x.c2
-rw-r--r--drivers/rtc/rtc-wm8350.c4
-rw-r--r--drivers/rtc/rtc-x1205.c2
-rw-r--r--drivers/rtc/rtc-xgene.c6
-rw-r--r--drivers/rtc/rtc-zynqmp.c10
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, &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, &regs, 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, &regmap_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, &reg);
+ ret = regmap_read(max31335->regmap, max31335->chip->clkout_reg, &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, &reg);
+ ret = regmap_read(max31335->regmap, max31335->chip->clkout_reg, &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 = &reg,
- },
- {
- .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, &regmap_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, &regval);
+ 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], &regval);
+ 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, &regval);
+ if (ret)
+ return ret;
+
+ vlval = regval ? RTC_VL_DATA_INVALID : 0;
+
+ ret = regmap_field_read(data->regfields[RX8111_REGF_VLOW],
+ &regval);
+ 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, &regmap_config);
- if (IS_ERR(sd3078->regmap)) {
+ regmap = devm_regmap_init_i2c(client, &regmap_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,