diff --git a/Documentation/devicetree/bindings/rtc/fsl,ls-ftm-alarm.yaml b/Documentation/devicetree/bindings/rtc/fsl,ls-ftm-alarm.yaml new file mode 100644 index 000000000000..388102ae30cd --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/fsl,ls-ftm-alarm.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/rtc/fsl,ls-ftm-alarm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale FlexTimer Module (FTM) Alarm + +maintainers: + - Frank Li + +properties: + compatible: + enum: + - fsl,ls1012a-ftm-alarm + - fsl,ls1021a-ftm-alarm + - fsl,ls1028a-ftm-alarm + - fsl,ls1043a-ftm-alarm + - fsl,ls1046a-ftm-alarm + - fsl,ls1088a-ftm-alarm + - fsl,ls208xa-ftm-alarm + - fsl,lx2160a-ftm-alarm + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + fsl,rcpm-wakeup: + $ref: /schemas/types.yaml#/definitions/phandle-array + items: + - items: + - description: phandle to rcpm node + - description: bit mask of IPPDEXPCR0 + - description: bit mask of IPPDEXPCR1 + - description: bit mask of IPPDEXPCR2 + - description: bit mask of IPPDEXPCR3 + - description: bit mask of IPPDEXPCR4 + - description: bit mask of IPPDEXPCR5 + - description: bit mask of IPPDEXPCR6 + minItems: 1 + description: + phandle to rcpm node, Please refer + Documentation/devicetree/bindings/soc/fsl/rcpm.txt + + big-endian: + $ref: /schemas/types.yaml#/definitions/flag + description: + If the host controller is big-endian mode, specify this property. + The default endian mode is little-endian. + +required: + - compatible + - reg + - interrupts + - fsl,rcpm-wakeup + +allOf: + - $ref: rtc.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + + rtc@2800000 { + compatible = "fsl,ls1088a-ftm-alarm"; + reg = <0x2800000 0x10000>; + fsl,rcpm-wakeup = <&rcpm 0x0 0x0 0x0 0x0 0x4000 0x0>; + interrupts = ; + }; diff --git a/Documentation/devicetree/bindings/rtc/rtc-fsl-ftm-alarm.txt b/Documentation/devicetree/bindings/rtc/rtc-fsl-ftm-alarm.txt deleted file mode 100644 index fffac74999da..000000000000 --- a/Documentation/devicetree/bindings/rtc/rtc-fsl-ftm-alarm.txt +++ /dev/null @@ -1,36 +0,0 @@ -Freescale FlexTimer Module (FTM) Alarm - -Required properties: -- compatible : Should be "fsl,-ftm-alarm", the - supported chips include - "fsl,ls1012a-ftm-alarm" - "fsl,ls1021a-ftm-alarm" - "fsl,ls1028a-ftm-alarm" - "fsl,ls1043a-ftm-alarm" - "fsl,ls1046a-ftm-alarm" - "fsl,ls1088a-ftm-alarm" - "fsl,ls208xa-ftm-alarm" - "fsl,lx2160a-ftm-alarm" -- reg : Specifies base physical address and size of the register sets for the - FlexTimer Module. -- interrupts : Should be the FlexTimer Module interrupt. -- fsl,rcpm-wakeup property and rcpm node : Please refer - Documentation/devicetree/bindings/soc/fsl/rcpm.txt - -Optional properties: -- big-endian: If the host controller is big-endian mode, specify this property. - The default endian mode is little-endian. - -Example: -rcpm: rcpm@1e34040 { - compatible = "fsl,ls1088a-rcpm", "fsl,qoriq-rcpm-2.1+"; - reg = <0x0 0x1e34040 0x0 0x18>; - #fsl,rcpm-wakeup-cells = <6>; -}; - -ftm_alarm0: timer@2800000 { - compatible = "fsl,ls1088a-ftm-alarm"; - reg = <0x0 0x2800000 0x0 0x10000>; - fsl,rcpm-wakeup = <&rcpm 0x0 0x0 0x0 0x0 0x4000 0x0>; - interrupts = <0 44 4>; -}; diff --git a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml index 4703083d1f11..7a0fab721cf1 100644 --- a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml +++ b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml @@ -15,6 +15,7 @@ properties: - st,stm32-rtc - st,stm32h7-rtc - st,stm32mp1-rtc + - st,stm32mp25-rtc reg: maxItems: 1 @@ -90,7 +91,9 @@ allOf: properties: compatible: contains: - const: st,stm32mp1-rtc + enum: + - st,stm32mp1-rtc + - st,stm32mp25-rtc then: properties: diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 5faafb4aa55c..cca650b2e0b9 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; } diff --git a/drivers/rtc/lib_test.c b/drivers/rtc/lib_test.c index 3893a202e9ea..c30c759662e3 100644 --- a/drivers/rtc/lib_test.c +++ b/drivers/rtc/lib_test.c @@ -97,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-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..02f7d0711287 100644 --- a/drivers/rtc/rtc-ab-eoz9.c +++ b/drivers/rtc/rtc-ab-eoz9.c @@ -575,7 +575,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-abx80x.c b/drivers/rtc/rtc-abx80x.c index fde2b8054c2e..1298962402ff 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -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-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-cmos.c b/drivers/rtc/rtc-cmos.c index 7d99cd2c37a0..35dca2accbb8 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -643,11 +643,10 @@ 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++) { if (off < 128) *buf++ = CMOS_READ(off); else if (can_bank2) @@ -657,7 +656,7 @@ static int cmos_nvram_read(void *priv, unsigned int off, void *val, } spin_unlock_irq(&rtc_lock); - return retval; + return count ? -EIO : 0; } static int cmos_nvram_write(void *priv, unsigned int off, void *val, @@ -665,7 +664,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 @@ -674,7 +672,7 @@ static int cmos_nvram_write(void *priv, unsigned int off, void *val, */ off += NVRAM_OFFSET; spin_lock_irq(&rtc_lock); - for (retval = 0; count; count--, off++, retval++) { + for (; count; count--, off++) { /* don't trash RTC registers */ if (off == cmos->day_alrm || off == cmos->mon_alrm @@ -689,7 +687,7 @@ static int cmos_nvram_write(void *priv, unsigned int off, void *val, } spin_unlock_irq(&rtc_lock); - return retval; + return count ? -EIO : 0; } /*----------------------------------------------------------------*/ diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 506b7d1c2397..872e0b679be4 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) 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-ds3232.c b/drivers/rtc/rtc-ds3232.c index 1485a6ae51e6..dd37b055693c 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -586,7 +586,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-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-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-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-isl12022.c b/drivers/rtc/rtc-isl12022.c index 4eef7afcc8bc..6fa9a68af9d9 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c @@ -366,7 +366,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..7b82e4a14b7a 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -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 = { diff --git a/drivers/rtc/rtc-max31335.c b/drivers/rtc/rtc-max31335.c index a2441e5c2c74..9a456f537d3b 100644 --- a/drivers/rtc/rtc-max31335.c +++ b/drivers/rtc/rtc-max31335.c @@ -669,7 +669,7 @@ static int max31335_probe(struct i2c_client *client) } static const struct i2c_device_id max31335_id[] = { - { "max31335", 0 }, + { "max31335" }, { } }; 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-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index 28858fcaea8f..71eafe4fbc72 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -403,5 +403,6 @@ static struct platform_driver mpc5121_rtc_driver = { module_platform_driver(mpc5121_rtc_driver); +MODULE_DESCRIPTION("Freescale MPC5121 built-in RTC driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("John Rigby "); diff --git a/drivers/rtc/rtc-nct3018y.c b/drivers/rtc/rtc-nct3018y.c index 7a8b4de893b8..76c5f464b2da 100644 --- a/drivers/rtc/rtc-nct3018y.c +++ b/drivers/rtc/rtc-nct3018y.c @@ -567,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-omap.c b/drivers/rtc/rtc-omap.c index c6155c48a4ac..e6b2a9c15b54 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -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-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 1949d7473310..647d52f1f5c5 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -594,9 +594,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-rc5t583.c b/drivers/rtc/rtc-rc5t583.c index 6f4bf919827a..115c46f862f9 100644 --- a/drivers/rtc/rtc-rc5t583.c +++ b/drivers/rtc/rtc-rc5t583.c @@ -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 "); +MODULE_DESCRIPTION("RICOH 5T583 RTC driver"); MODULE_LICENSE("GPL v2"); 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-rx6110.c b/drivers/rtc/rtc-rx6110.c index af6dd6ccbe3b..7c423d672adb 100644 --- a/drivers/rtc/rtc-rx6110.c +++ b/drivers/rtc/rtc-rx6110.c @@ -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-rx8581.c b/drivers/rtc/rtc-rx8581.c index 48efd61a114d..b18c12887bdc 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -307,7 +307,7 @@ static int rx8581_probe(struct i2c_client *client) } static const struct i2c_device_id rx8581_id[] = { - { "rx8581", 0 }, + { "rx8581" }, { } }; MODULE_DEVICE_TABLE(i2c, rx8581_id); diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 90a3028ac574..2d6b655a4b25 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -50,7 +50,7 @@ #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); diff --git a/drivers/rtc/rtc-sd3078.c b/drivers/rtc/rtc-sd3078.c index 7760394ccd2d..fe27b54beaad 100644 --- a/drivers/rtc/rtc-sd3078.c +++ b/drivers/rtc/rtc-sd3078.c @@ -201,7 +201,7 @@ static int sd3078_probe(struct i2c_client *client) } static const struct i2c_device_id sd3078_id[] = { - {"sd3078", 0}, + { "sd3078" }, { } }; MODULE_DEVICE_TABLE(i2c, sd3078_id); diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index 76753c71d92e..98b07969609d 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -83,6 +84,18 @@ #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 @@ -120,6 +133,7 @@ struct stm32_rtc_data { bool has_pclk; bool need_dbp; bool need_accuracy; + bool rif_protected; }; struct stm32_rtc { @@ -134,6 +148,14 @@ struct stm32_rtc { int irq_alarm; }; +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; @@ -553,6 +575,7 @@ static const struct stm32_rtc_data stm32_rtc_data = { .has_pclk = false, .need_dbp = true, .need_accuracy = false, + .rif_protected = false, .regs = { .tr = 0x00, .dr = 0x04, @@ -575,6 +598,7 @@ static const struct stm32_rtc_data stm32h7_rtc_data = { .has_pclk = true, .need_dbp = true, .need_accuracy = false, + .rif_protected = false, .regs = { .tr = 0x00, .dr = 0x04, @@ -606,6 +630,7 @@ static const struct stm32_rtc_data stm32mp1_data = { .has_pclk = true, .need_dbp = false, .need_accuracy = true, + .rif_protected = false, .regs = { .tr = 0x00, .dr = 0x04, @@ -624,14 +649,57 @@ static const struct stm32_rtc_data stm32mp1_data = { .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, + .regs = { + .tr = 0x00, + .dr = 0x04, + .cr = 0x18, + .isr = 0x0C, /* named RTC_ICSR on stm32mp25 */ + .prer = 0x10, + .alrmar = 0x40, + .wpr = 0x24, + .sr = 0x50, + .scr = 0x5C, + .verr = 0x3F4, + }, + .events = { + .alra = STM32_RTC_SR_ALRA, + }, + .clear_events = stm32mp1_rtc_clear_events, +}; + 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 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) { @@ -787,6 +855,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 diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 411ff66c0468..2ea1bbfbbc2a 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -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 "); +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..e69667634137 100644 --- a/drivers/rtc/rtc-tps6594.c +++ b/drivers/rtc/rtc-tps6594.c @@ -42,6 +42,11 @@ // 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); + 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); + + 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..2cfacdd37e09 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -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-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);