RTC for 6.11

Subsystem:
  - add missing MODULE_DESCRIPTION() macro
  - fix offset addition for alarms
 
 Drivers:
  - isl1208: alarm clearing fixes
  - mcp794xx: oscillator failure detection
  - stm32: stm32mp25 support
  - tps6594: power management support
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEBqsFVZXh8s/0O5JiY6TcMGxwOjIFAmadgncACgkQY6TcMGxw
 OjKWNg//SYop0kLi352RF/hzcb2wBCcpbTdx4d6vq22Wt4HL8LH+IUBvB/A1pma0
 Mk6EQrtlroSE1l+qtu9GgWsi9G8XIjxqu9KiGMm2Qkn4EyDVpuktNsOaZPDbx5s8
 iPVVzO2jTx6Fk1hJcP8c9H50WxhYuDf4IU3bu1Z3ALfifowwW5W9HYNfdQN05/vd
 mIt9ssmtzlt1kQYVgVc0LYch3NPMsp4mIP0Z0GDHzU/4MtZJyzG/P36/uVXwvbXv
 hCeENXQFU6eqQfGxSJHlTmfjrE03nxx7WSXCsPItxA0EjgkIspMNJ9XC2w5u/1aC
 GfRhZ4YgTnuJJhgRmnmVkmiW9Hr9aHsTDqYAy5mwv4X+ZPo0d5G3esPv+lWNVO5i
 220uDCzmeqE7Ecu8goBE2AlNtoY3+ooUnd7oNmcQdCISNPMauMhfZbklb+0s9Z5y
 8aalXyvyX9wE78uZnWHPG63G0MA3A7RF3G9jJIZ6jy2UZzQW8m9f8HzEECGVl1MB
 ehEp8ghGBP/LpRNzO3FLKdaFQqQ8t7f67Cw2Pp5qWpoVvaoHIXkfoXB+Zj8TSLuz
 IQMdQgm1R9/Ogc2Inu6RlTbMJ/Y9ac1Qx9sRmhVOz56uFXXozHVW0fGtFxdbU6XJ
 vGMallLK5zp0QxGES5oXVYx/2Hn7hAbMwd2nboCnvXk3KZfJYzU=
 =372M
 -----END PGP SIGNATURE-----

Merge tag 'rtc-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux

Pull RTC updates from Alexandre Belloni:
 "Subsystem:
   - add missing MODULE_DESCRIPTION() macro
   - fix offset addition for alarms

  Drivers:
   - isl1208: alarm clearing fixes
   - mcp794xx: oscillator failure detection
   - stm32: stm32mp25 support
   - tps6594: power management support"

* tag 'rtc-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux:
  rtc: stm32: add new st,stm32mp25-rtc compatible and check RIF configuration
  dt-bindings: rtc: stm32: introduce new st,stm32mp25-rtc compatible
  rtc: Drop explicit initialization of struct i2c_device_id::driver_data to 0
  rtc: interface: Add RTC offset to alarm after fix-up
  rtc: ds1307: Clamp year to valid BCD (0-99) in `set_time()`
  rtc: ds1307: Detect oscillator fail on mcp794xx
  rtc: isl1208: Update correct procedure for clearing alarm
  rtc: isl1208: Add a delay for clearing alarm
  dt-bindings: rtc: Convert rtc-fsl-ftm-alarm.txt to yaml format
  rtc: add missing MODULE_DESCRIPTION() macro
  rtc: abx80x: Fix return value of nvmem callback on read
  rtc: cmos: Fix return value of nvmem callbacks
  rtc: isl1208: Fix return value of nvmem callbacks
  rtc: tps6594: Add power management support
  rtc: tps6594: introduce private structure as drvdata
  rtc: tps6594: Fix memleak in probe
This commit is contained in:
Linus Torvalds 2024-07-21 15:34:10 -07:00
commit 7846b618e0
40 changed files with 299 additions and 103 deletions

View File

@ -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 <Frank.Li@nxp.com>
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 <dt-bindings/interrupt-controller/arm-gic.h>
rtc@2800000 {
compatible = "fsl,ls1088a-ftm-alarm";
reg = <0x2800000 0x10000>;
fsl,rcpm-wakeup = <&rcpm 0x0 0x0 0x0 0x0 0x4000 0x0>;
interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
};

View File

@ -1,36 +0,0 @@
Freescale FlexTimer Module (FTM) Alarm
Required properties:
- compatible : Should be "fsl,<chip>-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>;
};

View File

@ -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:

View File

@ -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;
}

View File

@ -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");

View File

@ -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);

View File

@ -575,7 +575,7 @@ MODULE_DEVICE_TABLE(of, abeoz9_dt_match);
#endif
static const struct i2c_device_id abeoz9_id[] = {
{ "abeoz9", 0 },
{ "abeoz9" },
{ }
};

View File

@ -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;

View File

@ -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);

View File

@ -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;
}
/*----------------------------------------------------------------*/

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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");

View File

@ -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);

View File

@ -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);

View File

@ -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 = {

View File

@ -669,7 +669,7 @@ static int max31335_probe(struct i2c_client *client)
}
static const struct i2c_device_id max31335_id[] = {
{ "max31335", 0 },
{ "max31335" },
{ }
};

View File

@ -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);

View File

@ -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 <jcrigby@gmail.com>");

View File

@ -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);

View File

@ -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");

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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");

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -5,6 +5,7 @@
*/
#include <linux/bcd.h>
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/errno.h>
#include <linux/iopoll.h>
@ -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

View File

@ -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");

View File

@ -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,
};

View File

@ -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");

View File

@ -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);