mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 06:01:57 +00:00
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:
commit
7846b618e0
73
Documentation/devicetree/bindings/rtc/fsl,ls-ftm-alarm.yaml
Normal file
73
Documentation/devicetree/bindings/rtc/fsl,ls-ftm-alarm.yaml
Normal 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>;
|
||||
};
|
@ -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>;
|
||||
};
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -575,7 +575,7 @@ MODULE_DEVICE_TABLE(of, abeoz9_dt_match);
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id abeoz9_id[] = {
|
||||
{ "abeoz9", 0 },
|
||||
{ "abeoz9" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 = {
|
||||
|
@ -669,7 +669,7 @@ static int max31335_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id max31335_id[] = {
|
||||
{ "max31335", 0 },
|
||||
{ "max31335" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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>");
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user