* [PATCH v2 0/5] rtc-rv8803: Implement timestamp trigger over event pins
@ 2025-01-16 13:15 Markus Burri
2025-01-16 13:15 ` [PATCH v2 1/5] dt-bindings: rtc: add new type for epson,rx8901 Markus Burri
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Markus Burri @ 2025-01-16 13:15 UTC (permalink / raw)
To: linux-kernel
Cc: Markus Burri, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Marek Vasut, linux-rtc, devicetree, Manuel Traut
The RV8901 RTC chip provides a function to store timestamp events.
There are three input pins (EVIN1-3) available for triggering.
The timestamp can be read to detect tamper alerts, for example.
This patch series extends the sysfs interface to enable and read the
timestamp events.
The data-sheet can be found here:
https://download.epsondevice.com/td/pdf/brief/RX8901CE_en.pdf
This series applies on 'linux-6.13~rc7'
Changes in V2:
* remove separate patch for register definitions
* remove pin configuration over sysfs (use default settings)
* add sysfs documentation
* rework enable to simplify and remove big mutext scope
---
[V1] https://lore.kernel.org/lkml/20250110061401.358371-1-markus.burri@mt.com/
Markus Burri (5):
dt-bindings: rtc: add new type for epson,rx8901
rtc-rv8803: add new type for rv8901
rtc-rv8803: add tamper function to sysfs for rv8901
rtc-rv8803: extend sysfs to trigger internal ts-event
rtc-rv8803: extend sysfs to read status
.../ABI/testing/sysfs-class-rtc-tamper | 36 ++
.../devicetree/bindings/rtc/epson,rx8900.yaml | 2 +
drivers/rtc/rtc-rv8803.c | 516 +++++++++++++++++-
3 files changed, 552 insertions(+), 2 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-class-rtc-tamper
base-commit: 5bc55a333a2f7316b58edc7573e8e893f7acb532
--
2.39.5
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 1/5] dt-bindings: rtc: add new type for epson,rx8901
2025-01-16 13:15 [PATCH v2 0/5] rtc-rv8803: Implement timestamp trigger over event pins Markus Burri
@ 2025-01-16 13:15 ` Markus Burri
2025-02-19 15:32 ` Manuel Traut
2025-01-16 13:15 ` [PATCH v2 2/5] rtc-rv8803: add new type for rv8901 Markus Burri
` (3 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Markus Burri @ 2025-01-16 13:15 UTC (permalink / raw)
To: linux-kernel
Cc: Markus Burri, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Marek Vasut, linux-rtc, devicetree, Manuel Traut,
Krzysztof Kozlowski
Document compatibles for:
- RX8803: already used by the driver
- RX8901: new device supporting also tamper detection and pinctrl
Signed-off-by: Markus Burri <markus.burri@mt.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
Documentation/devicetree/bindings/rtc/epson,rx8900.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/rtc/epson,rx8900.yaml b/Documentation/devicetree/bindings/rtc/epson,rx8900.yaml
index b770149c5..03af81754 100644
--- a/Documentation/devicetree/bindings/rtc/epson,rx8900.yaml
+++ b/Documentation/devicetree/bindings/rtc/epson,rx8900.yaml
@@ -15,8 +15,10 @@ allOf:
properties:
compatible:
enum:
+ - epson,rx8803
- epson,rx8804
- epson,rx8900
+ - epson,rx8901
- microcrystal,rv8803
reg:
--
2.39.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 2/5] rtc-rv8803: add new type for rv8901
2025-01-16 13:15 [PATCH v2 0/5] rtc-rv8803: Implement timestamp trigger over event pins Markus Burri
2025-01-16 13:15 ` [PATCH v2 1/5] dt-bindings: rtc: add new type for epson,rx8901 Markus Burri
@ 2025-01-16 13:15 ` Markus Burri
2025-02-19 15:33 ` Manuel Traut
2025-01-16 13:15 ` [PATCH v2 3/5] rtc-rv8803: add tamper function to sysfs " Markus Burri
` (2 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Markus Burri @ 2025-01-16 13:15 UTC (permalink / raw)
To: linux-kernel
Cc: Markus Burri, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Marek Vasut, linux-rtc, devicetree, Manuel Traut
The rtc-rv8901 has additional functionality (tamper detection).
To support this additional functionality the type must be extended.
Signed-off-by: Markus Burri <markus.burri@mt.com>
---
drivers/rtc/rtc-rv8803.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index 1327251e5..50fbae931 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -62,7 +62,8 @@ enum rv8803_type {
rv_8803,
rx_8803,
rx_8804,
- rx_8900
+ rx_8900,
+ rx_8901,
};
struct rv8803_data {
@@ -173,7 +174,8 @@ static int rv8803_regs_reset(struct rv8803_data *rv8803, bool full)
* The RV-8803 resets all registers to POR defaults after voltage-loss,
* the Epson RTCs don't, so we manually reset the remainder here.
*/
- if (full || rv8803->type == rx_8803 || rv8803->type == rx_8900) {
+ if (full || rv8803->type == rx_8803 || rv8803->type == rx_8900 ||
+ rv8803->type == rx_8901) {
int ret = rv8803_regs_init(rv8803);
if (ret)
return ret;
@@ -635,6 +637,7 @@ static const struct i2c_device_id rv8803_id[] = {
{ "rv8804", rx_8804 },
{ "rx8803", rx_8803 },
{ "rx8900", rx_8900 },
+ { "rx8901", rx_8901 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rv8803_id);
@@ -760,6 +763,10 @@ static const __maybe_unused struct of_device_id rv8803_of_match[] = {
.compatible = "epson,rx8900",
.data = (void *)rx_8900
},
+ {
+ .compatible = "epson,rx8901",
+ .data = (void *)rx_8901
+ },
{ }
};
MODULE_DEVICE_TABLE(of, rv8803_of_match);
--
2.39.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 3/5] rtc-rv8803: add tamper function to sysfs for rv8901
2025-01-16 13:15 [PATCH v2 0/5] rtc-rv8803: Implement timestamp trigger over event pins Markus Burri
2025-01-16 13:15 ` [PATCH v2 1/5] dt-bindings: rtc: add new type for epson,rx8901 Markus Burri
2025-01-16 13:15 ` [PATCH v2 2/5] rtc-rv8803: add new type for rv8901 Markus Burri
@ 2025-01-16 13:15 ` Markus Burri
2025-02-19 16:20 ` Manuel Traut
2025-01-16 13:15 ` [PATCH v2 4/5] rtc-rv8803: extend sysfs to trigger internal ts-event Markus Burri
2025-01-16 13:15 ` [PATCH v2 5/5] rtc-rv8803: extend sysfs to read status Markus Burri
4 siblings, 1 reply; 11+ messages in thread
From: Markus Burri @ 2025-01-16 13:15 UTC (permalink / raw)
To: linux-kernel
Cc: Markus Burri, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Marek Vasut, linux-rtc, devicetree, Manuel Traut
Add sysfs interface to enable the EVINx pins and read the time-stamp
events from EVINX.
Signed-off-by: Markus Burri <markus.burri@mt.com>
---
.../ABI/testing/sysfs-class-rtc-tamper | 21 +
drivers/rtc/rtc-rv8803.c | 366 ++++++++++++++++++
2 files changed, 387 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-class-rtc-tamper
diff --git a/Documentation/ABI/testing/sysfs-class-rtc-tamper b/Documentation/ABI/testing/sysfs-class-rtc-tamper
new file mode 100644
index 000000000..f035d0fa5
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-rtc-tamper
@@ -0,0 +1,21 @@
+What: /sys/class/rtc/rtcX/tamper/enable
+Date: January 2025
+KernelVersion: 6.13
+Contact: Markus Burri <markus.burri@mt.com>
+Description: (WO) Attribute to enable and disable the rtc tamper function.
+ Write a '1' to enable tamper detection or a '0' to disable.
+
+What: /sys/class/rtc/rtcX/tamper/read
+Date: January 2025
+KernelVersion: 6.13
+Contact: Markus Burri <markus.burri@mt.com>
+Description: (RO) Attribute to read the stored timestamps form buffer FIFO.
+ The timestamps are returned one by one
+ Format is 'seconds.milliseconds' since the epoch followed by the trigger events.
+ The value of the event is the current pin value.
+
+ Example values:
+ - "1234.567 EVIN1=1" for a trigger from EVIN1 changed from low to high
+ - "1234.567 EVIN1=0 EVIN2=1 for a simultaneous trigger of EVIN1 changed to low and
+ EVIN2 changed to high.
+
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index 50fbae931..764e654c2 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -10,6 +10,7 @@
#include <linux/bcd.h>
#include <linux/bitops.h>
#include <linux/bitfield.h>
+#include <linux/delay.h>
#include <linux/log2.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
@@ -58,6 +59,35 @@
#define RX8900_FLAG_SWOFF BIT(2)
#define RX8900_FLAG_VDETOFF BIT(3)
+#define RX8901_EVIN_EN 0x20
+#define RX8901_EVIN1_CFG 0x21
+#define RX8901_EVIN2_CFG 0x23
+#define RX8901_EVIN3_CFG 0x25
+#define RX8901_EVENTx_CFG_POL GENMASK(1, 0)
+#define RX8901_EVENTx_CFG_PUPD GENMASK(4, 2)
+
+#define RX8901_EVIN1_FLT 0x22
+#define RX8901_EVIN2_FLT 0x24
+#define RX8901_EVIN3_FLT 0x26
+
+#define RX8901_BUF1_CFG1 0x27
+
+#define RX8901_BUF1_STAT 0x28
+#define RX8901_BUFx_STAT_PTR GENMASK(5, 0)
+#define RX8901_WRCMD_CFG 0x41
+#define RX8901_WRCMD_TRG 0x42
+
+#define RX8901_EVNT_INTE 0x43
+
+#define RX8901_BUF_INTF 0x46
+#define RX8901_BUF_INTF_BUF1F BIT(5)
+
+#define RX8901_EVNT_INTF 0x47
+
+#define NO_OF_EVIN 3
+
+#define EVIN_FILTER_MAX 40
+
enum rv8803_type {
rv_8803,
rx_8803,
@@ -66,6 +96,50 @@ enum rv8803_type {
rx_8901,
};
+enum evin_pull_resistor {
+ no = 0b000,
+ pull_up_500k = 0b001,
+ pull_up_1M = 0b010,
+ pull_up_10M = 0b011,
+ pull_down_500k = 0b100,
+};
+
+enum evin_trigger {
+ falling_edge = 0b00,
+ rising_edge = 0b01,
+ both_edges = 0b10,
+};
+
+struct cfg_val_txt {
+ char *txt;
+ u8 val;
+ bool hide;
+};
+
+static const struct cfg_val_txt trg_status_txt[] = {
+ { "EVIN1", BIT(5) },
+ { "EVIN2", BIT(6) },
+ { "EVIN3", BIT(7) },
+ { "CMD", BIT(4) },
+ { "VBATL", BIT(3) },
+ { "VTMPL", BIT(2) },
+ { "VDDL", BIT(1) },
+ { "OSCSTP", BIT(0) },
+ { NULL }
+};
+
+static const u8 evin_cfg_regs[] = {
+ RX8901_EVIN1_CFG,
+ RX8901_EVIN2_CFG,
+ RX8901_EVIN3_CFG
+};
+
+static const u8 evin_flt_regs[] = {
+ RX8901_EVIN1_FLT,
+ RX8901_EVIN2_FLT,
+ RX8901_EVIN3_FLT
+};
+
struct rv8803_data {
struct i2c_client *client;
struct rtc_device *rtc;
@@ -558,6 +632,292 @@ static int rv8803_nvram_read(void *priv, unsigned int offset,
return 0;
}
+static int rv8803_ts_event_write_evin(int evin, struct rv8803_data *rv8803,
+ enum evin_pull_resistor pullup_down,
+ enum evin_trigger trigger, int filter)
+{
+ int ret;
+ u8 reg_mask;
+ struct i2c_client *client = rv8803->client;
+
+ /* according to data-sheet, "1" is not valid for filter */
+ if (evin >= NO_OF_EVIN || filter == 1 || filter > EVIN_FILTER_MAX)
+ return -EINVAL;
+
+ guard(mutex)(&rv8803->flags_lock);
+
+ /* set EVENTx pull-up edge trigger */
+ ret = rv8803_read_reg(client, evin_cfg_regs[evin]);
+ if (ret < 0)
+ return ret;
+ reg_mask = ret;
+ reg_mask &= ~(RX8901_EVENTx_CFG_PUPD | RX8901_EVENTx_CFG_POL);
+ reg_mask |= FIELD_PREP(RX8901_EVENTx_CFG_PUPD, pullup_down);
+ reg_mask |= FIELD_PREP(RX8901_EVENTx_CFG_POL, trigger);
+ ret = rv8803_write_reg(client, evin_cfg_regs[evin], reg_mask);
+ if (ret < 0)
+ return ret;
+
+ /* set EVENTx noise filter */
+ if (filter != -1) {
+ ret = rv8803_write_reg(client, evin_flt_regs[evin], filter);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rv8803_ts_enable_events(struct rv8803_data *rv8803, u8 enable_mask)
+{
+ int ret;
+ u8 reg_mask;
+ struct i2c_client *client = rv8803->client;
+
+ guard(mutex)(&rv8803->flags_lock);
+
+ /* event detection interrupt */
+ ret = rv8803_read_reg(client, RV8803_CTRL);
+ if (ret < 0)
+ return ret;
+
+ reg_mask = ret & ~RV8803_CTRL_EIE;
+ if (enable_mask)
+ reg_mask |= RV8803_CTRL_EIE;
+
+ ret = rv8803_write_reg(client, RV8803_CTRL, reg_mask);
+ if (ret)
+ return ret;
+
+ /* events for configuration */
+ ret = rv8803_write_reg(client, RX8901_EVIN_EN, enable_mask);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static ssize_t enable_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ int ret;
+ int i;
+ unsigned long tmo;
+ u8 reg;
+ u8 reg_mask;
+ struct rv8803_data *rv8803 = dev_get_drvdata(dev->parent);
+ struct i2c_client *client = rv8803->client;
+
+ /* EVINxCPEN | EVINxEN */;
+ const u8 reg_mask_evin_en = GENMASK(5, 3) | GENMASK(2, 0);
+
+ bool enable = (strstr(buf, "1") == buf) ? true : false;
+
+ /* check if event detection status match requested mode */
+ ret = rv8803_read_reg(client, RX8901_EVIN_EN);
+ if (ret < 0)
+ return ret;
+
+ /* requested mode match current state -> nothing to do */
+ if (ret == (enable ? reg_mask_evin_en : 0))
+ return count;
+
+ dev_info(&client->dev, "%s time-stamp event detection\n",
+ (enable) ? "configure" : "disable");
+
+ /*
+ * 1. disable event detection interrupt
+ * 2. disable events for configuration
+ */
+ ret = rv8803_ts_enable_events(rv8803, 0);
+ if (ret < 0)
+ return ret;
+
+ /* for disable no configuration is needed */
+ if (!enable)
+ return count;
+
+ /* 3. set EVENTx pull-up edge trigger and noise filter */
+ for (i = 0; i < NO_OF_EVIN; ++i) {
+ ret = rv8803_ts_event_write_evin(i, rv8803, pull_up_1M, falling_edge, 0);
+ if (ret < 0)
+ return ret;
+ }
+
+ scoped_guard(mutex, &rv8803->flags_lock) {
+ /* 4. enable EVENTx interrupt */
+ ret = rv8803_read_reg(client, RX8901_EVNT_INTE);
+ if (ret < 0)
+ return ret;
+ reg_mask = BIT(5) | BIT(6) | BIT(7); /* EVINxIEN 1-3 */
+ reg = (ret & ~reg_mask) | reg_mask;
+ ret = rv8803_write_reg(client, RX8901_EVNT_INTE, reg);
+ if (ret < 0)
+ return ret;
+ }
+
+ /*
+ * 5. set BUF1 inhibit and interrupt every 1 event
+ * NOTE: BUF2-3 are not used in FIFO-mode
+ */
+ ret = rv8803_write_reg(client, RX8901_BUF1_CFG1, 0x01);
+ if (ret < 0)
+ return ret;
+
+ /* 6. clean and init for BUFx and event counter 1-3 and trigger cmd */
+ reg = BIT(7) | GENMASK(6, 4);
+ reg |= BIT(0); /* CMDTRGEN */
+ ret = rv8803_write_reg(client, RX8901_WRCMD_CFG, reg);
+ if (ret < 0)
+ return ret;
+ ret = rv8803_write_reg(client, RX8901_WRCMD_TRG, 0xFF);
+ if (ret < 0)
+ return ret;
+ tmo = jiffies + msecs_to_jiffies(100); /* timeout 100ms */
+ do {
+ usleep_range(10, 2000);
+ ret = rv8803_read_reg(client, RX8901_WRCMD_TRG);
+ if (ret < 0)
+ return ret;
+ if (time_after(jiffies, tmo))
+ return -EBUSY;
+ } while (ret);
+
+ /*
+ * 7. enable event detection interrupt
+ * 8. / 10. enable events for configuration in FIFO mode
+ */
+ ret = rv8803_ts_enable_events(rv8803, reg_mask_evin_en);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static ssize_t read_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret;
+ int ev_idx;
+ int num_events;
+ unsigned long long time_s;
+ int time_ms;
+ int offset = 0;
+ u8 reg_mask;
+ u8 data[10];
+ struct rtc_time tm;
+
+ struct i2c_client *client = to_i2c_client(dev->parent);
+ struct rv8803_data *rv8803 = dev_get_drvdata(dev->parent);
+
+ guard(mutex)(&rv8803->flags_lock);
+
+ /*
+ * For detailed description see datasheet:
+ * - Reading Time Stamp Data (FIFO mode)
+ */
+
+ /* check interrupt source is from event 1-3 */
+ ret = rv8803_read_reg(client, RX8901_EVNT_INTF);
+ if (ret < 0)
+ return ret;
+
+ /* CHECK for EVF bit */
+ if (ret & BIT(2)) {
+ /* clear EVINxF 1-3 */
+ reg_mask = BIT(5) | BIT(6) | BIT(7);
+ ret = rv8803_write_reg(client, RX8901_EVNT_INTF, ret & ~reg_mask);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* check interrupt source is from event 1-3 */
+ ret = rv8803_read_reg(client, RX8901_BUF_INTF);
+ if (ret < 0)
+ return ret;
+ if (ret & RX8901_BUF_INTF_BUF1F) {
+ /* disable interrupts */
+ ret = rv8803_read_reg(client, RV8803_CTRL);
+ if (ret < 0)
+ return ret;
+ ret = rv8803_write_reg(client, RV8803_CTRL, ret & ~RV8803_CTRL_EIE);
+ if (ret < 0)
+ return ret;
+
+ /* clear interrupt flag */
+ ret = rv8803_read_reg(client, RX8901_BUF_INTF);
+ if (ret < 0)
+ return ret;
+ ret = rv8803_write_reg(client, RX8901_BUF_INTF, ret & ~RX8901_BUF_INTF_BUF1F);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* test if there are events available */
+ ret = rv8803_read_reg(client, RX8901_BUF1_STAT);
+ if (ret < 0)
+ return ret;
+ num_events = ret & RX8901_BUFx_STAT_PTR;
+
+ if (num_events) {
+ ret = rv8803_read_regs(client, 0x60, ARRAY_SIZE(data), data);
+ if (ret < 0)
+ return ret;
+
+ tm.tm_sec = bcd2bin(data[2]);
+ tm.tm_min = bcd2bin(data[3]);
+ tm.tm_hour = bcd2bin(data[4]);
+ tm.tm_mday = bcd2bin(data[5]);
+ tm.tm_mon = bcd2bin(data[6]) - 1;
+ tm.tm_year = bcd2bin(data[7]) + 100;
+ tm.tm_wday = -1;
+ tm.tm_yday = -1;
+ tm.tm_isdst = -1;
+
+ ret = rtc_valid_tm(&tm);
+ if (ret)
+ return ret;
+
+ /* calculate 1/1024 -> ms */
+ time_ms = (1000 * ((data[1] << 2) | (data[0] >> 6))) / 1024;
+ time_s = rtc_tm_to_time64(&tm);
+
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, "%llu.%03d", time_s, time_ms);
+ for (ev_idx = 0; trg_status_txt[ev_idx].txt; ++ev_idx)
+ if (data[9] & trg_status_txt[ev_idx].val)
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, " %s=%d",
+ trg_status_txt[ev_idx].txt,
+ !!(trg_status_txt[ev_idx].val & data[8]));
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n");
+
+ /* according to the datasheet we have to wait for 1ms */
+ usleep_range(1000, 2000);
+ }
+
+ /* re-enable interrupts */
+ ret = rv8803_read_reg(client, RV8803_CTRL);
+ if (ret < 0)
+ return ret;
+ ret = rv8803_write_reg(client, RV8803_CTRL, ret | RV8803_CTRL_EIE);
+ if (ret < 0)
+ return ret;
+
+ return offset;
+}
+
+static DEVICE_ATTR_WO(enable);
+static DEVICE_ATTR_RO(read);
+
+static struct attribute *rv8803_rtc_event_attrs[] = {
+ &dev_attr_enable.attr,
+ &dev_attr_read.attr,
+ NULL
+};
+
+static const struct attribute_group rv8803_rtc_sysfs_event_files = {
+ .name = "tamper",
+ .attrs = rv8803_rtc_event_attrs,
+};
+
static const struct rtc_class_ops rv8803_rtc_ops = {
.read_time = rv8803_get_time,
.set_time = rv8803_set_time,
@@ -732,6 +1092,12 @@ static int rv8803_probe(struct i2c_client *client)
if (err)
return err;
+ if (rv8803->type == rx_8901) {
+ err = rtc_add_group(rv8803->rtc, &rv8803_rtc_sysfs_event_files);
+ if (err)
+ return err;
+ }
+
rv8803->rtc->ops = &rv8803_rtc_ops;
rv8803->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rv8803->rtc->range_max = RTC_TIMESTAMP_END_2099;
--
2.39.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 4/5] rtc-rv8803: extend sysfs to trigger internal ts-event
2025-01-16 13:15 [PATCH v2 0/5] rtc-rv8803: Implement timestamp trigger over event pins Markus Burri
` (2 preceding siblings ...)
2025-01-16 13:15 ` [PATCH v2 3/5] rtc-rv8803: add tamper function to sysfs " Markus Burri
@ 2025-01-16 13:15 ` Markus Burri
2025-02-19 16:23 ` Manuel Traut
2025-01-16 13:15 ` [PATCH v2 5/5] rtc-rv8803: extend sysfs to read status Markus Burri
4 siblings, 1 reply; 11+ messages in thread
From: Markus Burri @ 2025-01-16 13:15 UTC (permalink / raw)
To: linux-kernel
Cc: Markus Burri, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Marek Vasut, linux-rtc, devicetree, Manuel Traut
Extend sysfs to trigger an internal time-stamp event.
The trigger function can be used from an application to trigger an
internal time-stamp event.
Signed-off-by: Markus Burri <markus.burri@mt.com>
---
.../ABI/testing/sysfs-class-rtc-tamper | 7 ++++
drivers/rtc/rtc-rv8803.c | 33 +++++++++++++++++++
2 files changed, 40 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-class-rtc-tamper b/Documentation/ABI/testing/sysfs-class-rtc-tamper
index f035d0fa5..2fd6578a6 100644
--- a/Documentation/ABI/testing/sysfs-class-rtc-tamper
+++ b/Documentation/ABI/testing/sysfs-class-rtc-tamper
@@ -18,4 +18,11 @@ Description: (RO) Attribute to read the stored timestamps form buffer FIFO.
- "1234.567 EVIN1=1" for a trigger from EVIN1 changed from low to high
- "1234.567 EVIN1=0 EVIN2=1 for a simultaneous trigger of EVIN1 changed to low and
EVIN2 changed to high.
+ - "1234.567 CMD=0" for a internal trigger
+What: /sys/class/rtc/rtcX/tamper/trigger
+Date: January 2025
+KernelVersion: 6.13
+Contact: Markus Burri <markus.burri@mt.com>
+Description: (WO) Attribute to trigger an internal timestamp event
+ Write a '1' to trigger an internal event and store a timestamp.
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index 764e654c2..ca3a19162 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -904,12 +904,45 @@ static ssize_t read_show(struct device *dev, struct device_attribute *attr, char
return offset;
}
+static ssize_t trigger_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct rv8803_data *rv8803 = dev_get_drvdata(dev->parent);
+ struct i2c_client *client = rv8803->client;
+ int ret;
+ unsigned long tmo;
+
+ guard(mutex)(&rv8803->flags_lock);
+
+ /* CMDTRGEN */
+ ret = rv8803_write_reg(client, RX8901_WRCMD_CFG, BIT(0));
+ if (ret < 0)
+ return ret;
+ ret = rv8803_write_reg(client, RX8901_WRCMD_TRG, 0xFF);
+ if (ret < 0)
+ return ret;
+
+ tmo = jiffies + msecs_to_jiffies(100); /* timeout 100ms */
+ do {
+ usleep_range(10, 2000);
+ ret = rv8803_read_reg(client, RX8901_WRCMD_TRG);
+ if (ret < 0)
+ return ret;
+ if (time_after(jiffies, tmo))
+ return -EBUSY;
+ } while (ret);
+
+ return count;
+}
+
static DEVICE_ATTR_WO(enable);
static DEVICE_ATTR_RO(read);
+static DEVICE_ATTR_WO(trigger);
static struct attribute *rv8803_rtc_event_attrs[] = {
&dev_attr_enable.attr,
&dev_attr_read.attr,
+ &dev_attr_trigger.attr,
NULL
};
--
2.39.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 5/5] rtc-rv8803: extend sysfs to read status
2025-01-16 13:15 [PATCH v2 0/5] rtc-rv8803: Implement timestamp trigger over event pins Markus Burri
` (3 preceding siblings ...)
2025-01-16 13:15 ` [PATCH v2 4/5] rtc-rv8803: extend sysfs to trigger internal ts-event Markus Burri
@ 2025-01-16 13:15 ` Markus Burri
2025-02-19 16:33 ` Manuel Traut
4 siblings, 1 reply; 11+ messages in thread
From: Markus Burri @ 2025-01-16 13:15 UTC (permalink / raw)
To: linux-kernel
Cc: Markus Burri, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Marek Vasut, linux-rtc, devicetree, Manuel Traut
Add sysfs functionality to read the status and configuration.
The functions provide the number of stored timestamp events, the current
EVIN pin configuration and the enabled/disabled status.
Signed-off-by: Markus Burri <markus.burri@mt.com>
---
.../ABI/testing/sysfs-class-rtc-tamper | 8 ++
drivers/rtc/rtc-rv8803.c | 106 ++++++++++++++++++
2 files changed, 114 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-class-rtc-tamper b/Documentation/ABI/testing/sysfs-class-rtc-tamper
index 2fd6578a6..b3aa73c81 100644
--- a/Documentation/ABI/testing/sysfs-class-rtc-tamper
+++ b/Documentation/ABI/testing/sysfs-class-rtc-tamper
@@ -26,3 +26,11 @@ KernelVersion: 6.13
Contact: Markus Burri <markus.burri@mt.com>
Description: (WO) Attribute to trigger an internal timestamp event
Write a '1' to trigger an internal event and store a timestamp.
+
+What: /sys/class/rtc/rtcX/tamper/status
+Date: January 2025
+KernelVersion: 6.13
+Contact: Markus Burri <markus.burri@mt.com>
+Description: (RO) Attribute to read configuration and status for EVINx and buffer.
+ Provide the number of stored timestamp events, the current EVIN pin configuration
+ and the enabled/disabled status.
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index ca3a19162..350cd92d6 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -84,8 +84,11 @@
#define RX8901_EVNT_INTF 0x47
+#define RX8901_BUF_OVWF 0x4F
+
#define NO_OF_EVIN 3
+#define EVIN_FILTER_FACTOR 125
#define EVIN_FILTER_MAX 40
enum rv8803_type {
@@ -116,6 +119,26 @@ struct cfg_val_txt {
bool hide;
};
+static const struct cfg_val_txt pull_resistor_txt[] = {
+ { "no", no },
+ { "PU/500k", pull_up_500k },
+ { "PU/1M", pull_up_1M },
+ { "PU/10M", pull_up_10M },
+ { "PD/500k", pull_down_500k },
+ { "no", 0b101, 1 },
+ { "no", 0b110, 1 },
+ { "no", 0b111, 1 },
+ { NULL }
+};
+
+static const struct cfg_val_txt trigger_txt[] = {
+ { "falling", falling_edge },
+ { "rising", rising_edge },
+ { "both", both_edges },
+ { "both", 0b11, 1 },
+ { NULL }
+};
+
static const struct cfg_val_txt trg_status_txt[] = {
{ "EVIN1", BIT(5) },
{ "EVIN2", BIT(6) },
@@ -632,6 +655,16 @@ static int rv8803_nvram_read(void *priv, unsigned int offset,
return 0;
}
+static char *cfg2txt(const struct cfg_val_txt *cfg, u8 value)
+{
+ do {
+ if (cfg->val == value)
+ return cfg->txt;
+ } while (++cfg && cfg->txt);
+
+ return NULL;
+}
+
static int rv8803_ts_event_write_evin(int evin, struct rv8803_data *rv8803,
enum evin_pull_resistor pullup_down,
enum evin_trigger trigger, int filter)
@@ -935,14 +968,87 @@ static ssize_t trigger_store(struct device *dev, struct device_attribute *attr,
return count;
}
+static ssize_t status_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int evin_en, evin_cfg, evin_flt, buf1_cfg, buf1_stat, buf_ovwf;
+ int i;
+ int offset = 0;
+ u8 ev_pullupdown[NO_OF_EVIN];
+ u8 ev_trigger[NO_OF_EVIN];
+ int ev_filter[NO_OF_EVIN];
+
+ struct i2c_client *client = to_i2c_client(dev->parent);
+ struct rv8803_data *rv8803 = dev_get_drvdata(dev->parent);
+
+ scoped_guard(mutex, &rv8803->flags_lock) {
+ evin_en = rv8803_read_reg(client, RX8901_EVIN_EN);
+ if (evin_en < 0)
+ return evin_en;
+
+ for (i = 0; i < NO_OF_EVIN; ++i) {
+ evin_cfg = rv8803_read_reg(client, evin_cfg_regs[i]);
+ evin_flt = rv8803_read_reg(client, evin_flt_regs[i]);
+ if (evin_cfg < 0 || evin_flt < 0)
+ return -EIO;
+
+ ev_pullupdown[i] = FIELD_GET(RX8901_EVENTx_CFG_PUPD, evin_cfg);
+ ev_trigger[i] = FIELD_GET(RX8901_EVENTx_CFG_POL, evin_cfg);
+ ev_filter[i] = EVIN_FILTER_FACTOR * evin_flt;
+ }
+
+ buf1_cfg = rv8803_read_reg(client, RX8901_BUF1_CFG1);
+ buf1_stat = rv8803_read_reg(client, RX8901_BUF1_STAT);
+ buf_ovwf = rv8803_read_reg(client, RX8901_BUF_OVWF);
+ if (buf1_stat < 0 || buf1_stat < 0 || buf_ovwf < 0)
+ return -EIO;
+ }
+
+ offset += sprintf(buf + offset, "Mode: %s\n\n",
+ FIELD_GET(BIT(6), evin_en) ? "direct" : "fifo");
+ offset += sprintf(buf + offset, "Event config:\n");
+ offset += sprintf(buf + offset, " %-13s %-7s %-7s %-7s\n", "", "EVIN1", "EVIN2", "EVIN3");
+ offset += sprintf(buf + offset, " %-13s %-7ld %-7ld %-7ld\n", "Enable",
+ FIELD_GET(BIT(0), evin_en), FIELD_GET(BIT(1), evin_en),
+ FIELD_GET(BIT(2), evin_en));
+ offset += sprintf(buf + offset, " %-13s %-7ld %-7ld %-7ld\n", "Capture",
+ FIELD_GET(BIT(3), evin_en), FIELD_GET(BIT(4), evin_en),
+ FIELD_GET(BIT(5), evin_en));
+
+ offset += sprintf(buf + offset, " %-13s %-7s %-7s %-7s\n", "Pull-resistor",
+ cfg2txt(pull_resistor_txt, ev_pullupdown[0]),
+ cfg2txt(pull_resistor_txt, ev_pullupdown[1]),
+ cfg2txt(pull_resistor_txt, ev_pullupdown[2]));
+ offset += sprintf(buf + offset, " %-13s %-7s %-7s %-7s\n", "Edge",
+ cfg2txt(trigger_txt, ev_trigger[0]),
+ cfg2txt(trigger_txt, ev_trigger[1]),
+ cfg2txt(trigger_txt, ev_trigger[2]));
+ offset += sprintf(buf + offset, " %-13s %-7d %-7d %-7d\n\n", "Filter [ms]",
+ ev_filter[0], ev_filter[1], ev_filter[2]);
+
+ offset += sprintf(buf + offset, "Buffer config:\n");
+ offset += sprintf(buf + offset, " %-13s %-10s\n", "Mode",
+ (FIELD_GET(BIT(6), buf1_cfg) ? "overwrite" : "inhibit"));
+ offset += sprintf(buf + offset, " %-13s %-10s\n", "Status",
+ (FIELD_GET(BIT(7), buf1_stat) ? "full" : "free"));
+ offset += sprintf(buf + offset, " %-13s %-10ld\n", "Overrun",
+ (FIELD_GET(BIT(4), buf_ovwf)));
+ offset += sprintf(buf + offset, " %-13s %-10ld\n", "No of data",
+ (FIELD_GET(GENMASK(5, 0), buf1_stat)));
+
+ return offset;
+}
+
static DEVICE_ATTR_WO(enable);
static DEVICE_ATTR_RO(read);
static DEVICE_ATTR_WO(trigger);
+static DEVICE_ATTR_RO(status);
static struct attribute *rv8803_rtc_event_attrs[] = {
&dev_attr_enable.attr,
&dev_attr_read.attr,
&dev_attr_trigger.attr,
+ &dev_attr_status.attr,
NULL
};
--
2.39.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v2 1/5] dt-bindings: rtc: add new type for epson,rx8901
2025-01-16 13:15 ` [PATCH v2 1/5] dt-bindings: rtc: add new type for epson,rx8901 Markus Burri
@ 2025-02-19 15:32 ` Manuel Traut
0 siblings, 0 replies; 11+ messages in thread
From: Manuel Traut @ 2025-02-19 15:32 UTC (permalink / raw)
To: Markus Burri
Cc: linux-kernel, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Marek Vasut, linux-rtc, devicetree,
Krzysztof Kozlowski
On Thu, Jan 16, 2025 at 02:15:28PM +0100, Markus Burri wrote:
> Document compatibles for:
> - RX8803: already used by the driver
> - RX8901: new device supporting also tamper detection and pinctrl
>
> Signed-off-by: Markus Burri <markus.burri@mt.com>
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Reviewed-by: Manuel Traut <manuel.traut@mt.com>
> ---
> Documentation/devicetree/bindings/rtc/epson,rx8900.yaml | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/rtc/epson,rx8900.yaml b/Documentation/devicetree/bindings/rtc/epson,rx8900.yaml
> index b770149c5..03af81754 100644
> --- a/Documentation/devicetree/bindings/rtc/epson,rx8900.yaml
> +++ b/Documentation/devicetree/bindings/rtc/epson,rx8900.yaml
> @@ -15,8 +15,10 @@ allOf:
> properties:
> compatible:
> enum:
> + - epson,rx8803
> - epson,rx8804
> - epson,rx8900
> + - epson,rx8901
> - microcrystal,rv8803
>
> reg:
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 2/5] rtc-rv8803: add new type for rv8901
2025-01-16 13:15 ` [PATCH v2 2/5] rtc-rv8803: add new type for rv8901 Markus Burri
@ 2025-02-19 15:33 ` Manuel Traut
0 siblings, 0 replies; 11+ messages in thread
From: Manuel Traut @ 2025-02-19 15:33 UTC (permalink / raw)
To: Markus Burri
Cc: linux-kernel, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Marek Vasut, linux-rtc, devicetree
On Thu, Jan 16, 2025 at 02:15:29PM +0100, Markus Burri wrote:
> The rtc-rv8901 has additional functionality (tamper detection).
> To support this additional functionality the type must be extended.
>
> Signed-off-by: Markus Burri <markus.burri@mt.com>
Reviewed-by: Manuel Traut <manuel.traut@mt.com>
> ---
> drivers/rtc/rtc-rv8803.c | 11 +++++++++--
> 1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
> index 1327251e5..50fbae931 100644
> --- a/drivers/rtc/rtc-rv8803.c
> +++ b/drivers/rtc/rtc-rv8803.c
> @@ -62,7 +62,8 @@ enum rv8803_type {
> rv_8803,
> rx_8803,
> rx_8804,
> - rx_8900
> + rx_8900,
> + rx_8901,
> };
>
> struct rv8803_data {
> @@ -173,7 +174,8 @@ static int rv8803_regs_reset(struct rv8803_data *rv8803, bool full)
> * The RV-8803 resets all registers to POR defaults after voltage-loss,
> * the Epson RTCs don't, so we manually reset the remainder here.
> */
> - if (full || rv8803->type == rx_8803 || rv8803->type == rx_8900) {
> + if (full || rv8803->type == rx_8803 || rv8803->type == rx_8900 ||
> + rv8803->type == rx_8901) {
> int ret = rv8803_regs_init(rv8803);
> if (ret)
> return ret;
> @@ -635,6 +637,7 @@ static const struct i2c_device_id rv8803_id[] = {
> { "rv8804", rx_8804 },
> { "rx8803", rx_8803 },
> { "rx8900", rx_8900 },
> + { "rx8901", rx_8901 },
> { }
> };
> MODULE_DEVICE_TABLE(i2c, rv8803_id);
> @@ -760,6 +763,10 @@ static const __maybe_unused struct of_device_id rv8803_of_match[] = {
> .compatible = "epson,rx8900",
> .data = (void *)rx_8900
> },
> + {
> + .compatible = "epson,rx8901",
> + .data = (void *)rx_8901
> + },
> { }
> };
> MODULE_DEVICE_TABLE(of, rv8803_of_match);
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 3/5] rtc-rv8803: add tamper function to sysfs for rv8901
2025-01-16 13:15 ` [PATCH v2 3/5] rtc-rv8803: add tamper function to sysfs " Markus Burri
@ 2025-02-19 16:20 ` Manuel Traut
0 siblings, 0 replies; 11+ messages in thread
From: Manuel Traut @ 2025-02-19 16:20 UTC (permalink / raw)
To: Markus Burri
Cc: linux-kernel, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Marek Vasut, linux-rtc, devicetree
On Thu, Jan 16, 2025 at 02:15:30PM +0100, Markus Burri wrote:
> Add sysfs interface to enable the EVINx pins and read the time-stamp
> events from EVINX.
>
> Signed-off-by: Markus Burri <markus.burri@mt.com>
> ---
> .../ABI/testing/sysfs-class-rtc-tamper | 21 +
> drivers/rtc/rtc-rv8803.c | 366 ++++++++++++++++++
> 2 files changed, 387 insertions(+)
> create mode 100644 Documentation/ABI/testing/sysfs-class-rtc-tamper
>
> diff --git a/Documentation/ABI/testing/sysfs-class-rtc-tamper b/Documentation/ABI/testing/sysfs-class-rtc-tamper
> new file mode 100644
> index 000000000..f035d0fa5
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-class-rtc-tamper
> @@ -0,0 +1,21 @@
> +What: /sys/class/rtc/rtcX/tamper/enable
> +Date: January 2025
> +KernelVersion: 6.13
> +Contact: Markus Burri <markus.burri@mt.com>
> +Description: (WO) Attribute to enable and disable the rtc tamper function.
> + Write a '1' to enable tamper detection or a '0' to disable.
> +
> +What: /sys/class/rtc/rtcX/tamper/read
> +Date: January 2025
> +KernelVersion: 6.13
> +Contact: Markus Burri <markus.burri@mt.com>
> +Description: (RO) Attribute to read the stored timestamps form buffer FIFO.
Description: (RO) Attribute to read tamper events.
> + The timestamps are returned one by one
Each read tries to retrieve a single entry from the hardware
FIFO. Events that are not retrieved stay in the hardware FIFO.
> + Format is 'seconds.milliseconds' since the epoch followed by the trigger events.
> + The value of the event is the current pin value.
> +
> + Example values:
> + - "1234.567 EVIN1=1" for a trigger from EVIN1 changed from low to high
> + - "1234.567 EVIN1=0 EVIN2=1 for a simultaneous trigger of EVIN1 changed to low and
> + EVIN2 changed to high.
> +
> diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
> index 50fbae931..764e654c2 100644
> --- a/drivers/rtc/rtc-rv8803.c
> +++ b/drivers/rtc/rtc-rv8803.c
> @@ -10,6 +10,7 @@
> #include <linux/bcd.h>
> #include <linux/bitops.h>
> #include <linux/bitfield.h>
> +#include <linux/delay.h>
> #include <linux/log2.h>
> #include <linux/i2c.h>
> #include <linux/interrupt.h>
> @@ -58,6 +59,35 @@
> #define RX8900_FLAG_SWOFF BIT(2)
> #define RX8900_FLAG_VDETOFF BIT(3)
>
> +#define RX8901_EVIN_EN 0x20
> +#define RX8901_EVIN1_CFG 0x21
> +#define RX8901_EVIN2_CFG 0x23
> +#define RX8901_EVIN3_CFG 0x25
> +#define RX8901_EVENTx_CFG_POL GENMASK(1, 0)
> +#define RX8901_EVENTx_CFG_PUPD GENMASK(4, 2)
> +
> +#define RX8901_EVIN1_FLT 0x22
> +#define RX8901_EVIN2_FLT 0x24
> +#define RX8901_EVIN3_FLT 0x26
> +
> +#define RX8901_BUF1_CFG1 0x27
> +
> +#define RX8901_BUF1_STAT 0x28
> +#define RX8901_BUFx_STAT_PTR GENMASK(5, 0)
> +#define RX8901_WRCMD_CFG 0x41
> +#define RX8901_WRCMD_TRG 0x42
> +
> +#define RX8901_EVNT_INTE 0x43
> +
> +#define RX8901_BUF_INTF 0x46
> +#define RX8901_BUF_INTF_BUF1F BIT(5)
> +
> +#define RX8901_EVNT_INTF 0x47
> +
> +#define NO_OF_EVIN 3
> +
> +#define EVIN_FILTER_MAX 40
> +
> enum rv8803_type {
> rv_8803,
> rx_8803,
> @@ -66,6 +96,50 @@ enum rv8803_type {
> rx_8901,
> };
>
> +enum evin_pull_resistor {
> + no = 0b000,
> + pull_up_500k = 0b001,
> + pull_up_1M = 0b010,
> + pull_up_10M = 0b011,
> + pull_down_500k = 0b100,
> +};
> +
> +enum evin_trigger {
> + falling_edge = 0b00,
> + rising_edge = 0b01,
> + both_edges = 0b10,
> +};
> +
> +struct cfg_val_txt {
> + char *txt;
> + u8 val;
> + bool hide;
> +};
> +
> +static const struct cfg_val_txt trg_status_txt[] = {
> + { "EVIN1", BIT(5) },
> + { "EVIN2", BIT(6) },
> + { "EVIN3", BIT(7) },
> + { "CMD", BIT(4) },
> + { "VBATL", BIT(3) },
> + { "VTMPL", BIT(2) },
> + { "VDDL", BIT(1) },
> + { "OSCSTP", BIT(0) },
> + { NULL }
> +};
> +
> +static const u8 evin_cfg_regs[] = {
> + RX8901_EVIN1_CFG,
> + RX8901_EVIN2_CFG,
> + RX8901_EVIN3_CFG
> +};
> +
> +static const u8 evin_flt_regs[] = {
> + RX8901_EVIN1_FLT,
> + RX8901_EVIN2_FLT,
> + RX8901_EVIN3_FLT
> +};
> +
> struct rv8803_data {
> struct i2c_client *client;
> struct rtc_device *rtc;
> @@ -558,6 +632,292 @@ static int rv8803_nvram_read(void *priv, unsigned int offset,
> return 0;
> }
>
> +static int rv8803_ts_event_write_evin(int evin, struct rv8803_data *rv8803,
> + enum evin_pull_resistor pullup_down,
> + enum evin_trigger trigger, int filter)
> +{
> + int ret;
>
> + u8 reg_mask;
> + struct i2c_client *client = rv8803->client;
> +
> + /* according to data-sheet, "1" is not valid for filter */
> + if (evin >= NO_OF_EVIN || filter == 1 || filter > EVIN_FILTER_MAX)
> + return -EINVAL;
> +
> + guard(mutex)(&rv8803->flags_lock);
> +
> + /* set EVENTx pull-up edge trigger */
> + ret = rv8803_read_reg(client, evin_cfg_regs[evin]);
> + if (ret < 0)
> + return ret;
> + reg_mask = ret;
> + reg_mask &= ~(RX8901_EVENTx_CFG_PUPD | RX8901_EVENTx_CFG_POL);
> + reg_mask |= FIELD_PREP(RX8901_EVENTx_CFG_PUPD, pullup_down);
> + reg_mask |= FIELD_PREP(RX8901_EVENTx_CFG_POL, trigger);
> + ret = rv8803_write_reg(client, evin_cfg_regs[evin], reg_mask);
> + if (ret < 0)
> + return ret;
> +
> + /* set EVENTx noise filter */
> + if (filter != -1) {
> + ret = rv8803_write_reg(client, evin_flt_regs[evin], filter);
> + if (ret < 0)
> + return ret;
This check is not needed.
> + }
> +
> + return 0;
return ret;
> +}
> +
> +static int rv8803_ts_enable_events(struct rv8803_data *rv8803, u8 enable_mask)
> +{
> + int ret;
> + u8 reg_mask;
> + struct i2c_client *client = rv8803->client;
> +
> + guard(mutex)(&rv8803->flags_lock);
> +
> + /* event detection interrupt */
> + ret = rv8803_read_reg(client, RV8803_CTRL);
> + if (ret < 0)
> + return ret;
> +
> + reg_mask = ret & ~RV8803_CTRL_EIE;
> + if (enable_mask)
> + reg_mask |= RV8803_CTRL_EIE;
> +
> + ret = rv8803_write_reg(client, RV8803_CTRL, reg_mask);
> + if (ret)
> + return ret;
> +
> + /* events for configuration */
> + ret = rv8803_write_reg(client, RX8901_EVIN_EN, enable_mask);
> + if (ret < 0)
> + return ret;
Not needed
> + return 0;
return ret;
> +}
> +
> +static ssize_t enable_store(struct device *dev, struct device_attribute *attr, const char *buf,
> + size_t count)
> +{
> + int ret;
> + int i;
can be declared in the scope of the for loop
> + unsigned long tmo;
> + u8 reg;
> + u8 reg_mask;
> + struct rv8803_data *rv8803 = dev_get_drvdata(dev->parent);
> + struct i2c_client *client = rv8803->client;
> +
> + /* EVINxCPEN | EVINxEN */;
> + const u8 reg_mask_evin_en = GENMASK(5, 3) | GENMASK(2, 0);
> +
> + bool enable = (strstr(buf, "1") == buf) ? true : false;
> +
> + /* check if event detection status match requested mode */
> + ret = rv8803_read_reg(client, RX8901_EVIN_EN);
> + if (ret < 0)
> + return ret;
> +
> + /* requested mode match current state -> nothing to do */
> + if (ret == (enable ? reg_mask_evin_en : 0))
> + return count;
> +
> + dev_info(&client->dev, "%s time-stamp event detection\n",
> + (enable) ? "configure" : "disable");
dev_dbg
> + /*
> + * 1. disable event detection interrupt
> + * 2. disable events for configuration
> + */
> + ret = rv8803_ts_enable_events(rv8803, 0);
> + if (ret < 0)
> + return ret;
> +
> + /* for disable no configuration is needed */
> + if (!enable)
> + return count;
> +
> + /* 3. set EVENTx pull-up edge trigger and noise filter */
> + for (i = 0; i < NO_OF_EVIN; ++i) {
for (int i = 0; i < NO_OF_EVIN; ++i) {
> + ret = rv8803_ts_event_write_evin(i, rv8803, pull_up_1M, falling_edge, 0);
> + if (ret < 0)
> + return ret;
> + }
> +
> + scoped_guard(mutex, &rv8803->flags_lock) {
> + /* 4. enable EVENTx interrupt */
> + ret = rv8803_read_reg(client, RX8901_EVNT_INTE);
> + if (ret < 0)
> + return ret;
> + reg_mask = BIT(5) | BIT(6) | BIT(7); /* EVINxIEN 1-3 */
> + reg = (ret & ~reg_mask) | reg_mask;
> + ret = rv8803_write_reg(client, RX8901_EVNT_INTE, reg);
> + if (ret < 0)
> + return ret;
> + }
> +
> + /*
> + * 5. set BUF1 inhibit and interrupt every 1 event
> + * NOTE: BUF2-3 are not used in FIFO-mode
> + */
> + ret = rv8803_write_reg(client, RX8901_BUF1_CFG1, 0x01);
> + if (ret < 0)
> + return ret;
> +
> + /* 6. clean and init for BUFx and event counter 1-3 and trigger cmd */
> + reg = BIT(7) | GENMASK(6, 4);
> + reg |= BIT(0); /* CMDTRGEN */
> + ret = rv8803_write_reg(client, RX8901_WRCMD_CFG, reg);
> + if (ret < 0)
> + return ret;
> + ret = rv8803_write_reg(client, RX8901_WRCMD_TRG, 0xFF);
> + if (ret < 0)
> + return ret;
> + tmo = jiffies + msecs_to_jiffies(100); /* timeout 100ms */
> + do {
> + usleep_range(10, 2000);
> + ret = rv8803_read_reg(client, RX8901_WRCMD_TRG);
> + if (ret < 0)
> + return ret;
> + if (time_after(jiffies, tmo))
> + return -EBUSY;
> + } while (ret);
> +
> + /*
> + * 7. enable event detection interrupt
> + * 8. / 10. enable events for configuration in FIFO mode
> + */
> + ret = rv8803_ts_enable_events(rv8803, reg_mask_evin_en);
> + if (ret < 0)
> + return ret;
> +
> + return count;
> +}
> +
> +static ssize_t read_show(struct device *dev, struct device_attribute *attr, char *buf)
> +{
> + int ret;
> + int ev_idx;
> + int num_events;
> + unsigned long long time_s;
> + int time_ms;
> + int offset = 0;
> + u8 reg_mask;
> + u8 data[10];
> + struct rtc_time tm;
> +
> + struct i2c_client *client = to_i2c_client(dev->parent);
> + struct rv8803_data *rv8803 = dev_get_drvdata(dev->parent);
> +
> + guard(mutex)(&rv8803->flags_lock);
> +
> + /*
> + * For detailed description see datasheet:
> + * - Reading Time Stamp Data (FIFO mode)
> + */
> +
> + /* check interrupt source is from event 1-3 */
> + ret = rv8803_read_reg(client, RX8901_EVNT_INTF);
> + if (ret < 0)
> + return ret;
> +
> + /* CHECK for EVF bit */
> + if (ret & BIT(2)) {
> + /* clear EVINxF 1-3 */
> + reg_mask = BIT(5) | BIT(6) | BIT(7);
> + ret = rv8803_write_reg(client, RX8901_EVNT_INTF, ret & ~reg_mask);
> + if (ret < 0)
> + return ret;
> + }
> +
> + /* check interrupt source is from event 1-3 */
> + ret = rv8803_read_reg(client, RX8901_BUF_INTF);
> + if (ret < 0)
> + return ret;
> + if (ret & RX8901_BUF_INTF_BUF1F) {
> + /* disable interrupts */
> + ret = rv8803_read_reg(client, RV8803_CTRL);
> + if (ret < 0)
> + return ret;
> + ret = rv8803_write_reg(client, RV8803_CTRL, ret & ~RV8803_CTRL_EIE);
> + if (ret < 0)
> + return ret;
> +
> + /* clear interrupt flag */
> + ret = rv8803_read_reg(client, RX8901_BUF_INTF);
> + if (ret < 0)
> + return ret;
> + ret = rv8803_write_reg(client, RX8901_BUF_INTF, ret & ~RX8901_BUF_INTF_BUF1F);
> + if (ret < 0)
> + return ret;
> + }
> +
> + /* test if there are events available */
> + ret = rv8803_read_reg(client, RX8901_BUF1_STAT);
> + if (ret < 0)
> + return ret;
> + num_events = ret & RX8901_BUFx_STAT_PTR;
> +
> + if (num_events) {
if (!num_events)
goto exit_reenable_irq;
would be better readable.
> + ret = rv8803_read_regs(client, 0x60, ARRAY_SIZE(data), data);
> + if (ret < 0)
> + return ret;
> +
> + tm.tm_sec = bcd2bin(data[2]);
> + tm.tm_min = bcd2bin(data[3]);
> + tm.tm_hour = bcd2bin(data[4]);
> + tm.tm_mday = bcd2bin(data[5]);
> + tm.tm_mon = bcd2bin(data[6]) - 1;
> + tm.tm_year = bcd2bin(data[7]) + 100;
> + tm.tm_wday = -1;
> + tm.tm_yday = -1;
> + tm.tm_isdst = -1;
> +
> + ret = rtc_valid_tm(&tm);
> + if (ret)
> + return ret;
> +
> + /* calculate 1/1024 -> ms */
> + time_ms = (1000 * ((data[1] << 2) | (data[0] >> 6))) / 1024;
> + time_s = rtc_tm_to_time64(&tm);
> +
> + offset += snprintf(buf + offset, PAGE_SIZE - offset, "%llu.%03d", time_s, time_ms);
> + for (ev_idx = 0; trg_status_txt[ev_idx].txt; ++ev_idx)
> + if (data[9] & trg_status_txt[ev_idx].val)
> + offset += snprintf(buf + offset, PAGE_SIZE - offset, " %s=%d",
> + trg_status_txt[ev_idx].txt,
> + !!(trg_status_txt[ev_idx].val & data[8]));
> + offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n");
> +
> + /* according to the datasheet we have to wait for 1ms */
Is it fine that interrupts are disabled that long?
> + usleep_range(1000, 2000);
> + }
> +
exit_reenable_irq:
> + /* re-enable interrupts */
> + ret = rv8803_read_reg(client, RV8803_CTRL);
Is it fine, that interrupts are only enabled again, if all of the above code
doesn't return with a failure?
> + if (ret < 0)
> + return ret;
> + ret = rv8803_write_reg(client, RV8803_CTRL, ret | RV8803_CTRL_EIE);
> + if (ret < 0)
> + return ret;
> +
> + return offset;
> +}
> +
> +static DEVICE_ATTR_WO(enable);
> +static DEVICE_ATTR_RO(read);
> +
> +static struct attribute *rv8803_rtc_event_attrs[] = {
> + &dev_attr_enable.attr,
> + &dev_attr_read.attr,
> + NULL
> +};
> +
> +static const struct attribute_group rv8803_rtc_sysfs_event_files = {
> + .name = "tamper",
> + .attrs = rv8803_rtc_event_attrs,
> +};
> +
> static const struct rtc_class_ops rv8803_rtc_ops = {
> .read_time = rv8803_get_time,
> .set_time = rv8803_set_time,
> @@ -732,6 +1092,12 @@ static int rv8803_probe(struct i2c_client *client)
> if (err)
> return err;
>
> + if (rv8803->type == rx_8901) {
> + err = rtc_add_group(rv8803->rtc, &rv8803_rtc_sysfs_event_files);
> + if (err)
> + return err;
> + }
> +
> rv8803->rtc->ops = &rv8803_rtc_ops;
> rv8803->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
> rv8803->rtc->range_max = RTC_TIMESTAMP_END_2099;
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 4/5] rtc-rv8803: extend sysfs to trigger internal ts-event
2025-01-16 13:15 ` [PATCH v2 4/5] rtc-rv8803: extend sysfs to trigger internal ts-event Markus Burri
@ 2025-02-19 16:23 ` Manuel Traut
0 siblings, 0 replies; 11+ messages in thread
From: Manuel Traut @ 2025-02-19 16:23 UTC (permalink / raw)
To: Markus Burri
Cc: linux-kernel, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Marek Vasut, linux-rtc, devicetree
On Thu, Jan 16, 2025 at 02:15:31PM +0100, Markus Burri wrote:
> Extend sysfs to trigger an internal time-stamp event.
>
> The trigger function can be used from an application to trigger an
> internal time-stamp event.
>
> Signed-off-by: Markus Burri <markus.burri@mt.com>
Reviewed-by: Manuel Traut <manuel.traut@mt.com>
> ---
> .../ABI/testing/sysfs-class-rtc-tamper | 7 ++++
> drivers/rtc/rtc-rv8803.c | 33 +++++++++++++++++++
> 2 files changed, 40 insertions(+)
>
> diff --git a/Documentation/ABI/testing/sysfs-class-rtc-tamper b/Documentation/ABI/testing/sysfs-class-rtc-tamper
> index f035d0fa5..2fd6578a6 100644
> --- a/Documentation/ABI/testing/sysfs-class-rtc-tamper
> +++ b/Documentation/ABI/testing/sysfs-class-rtc-tamper
> @@ -18,4 +18,11 @@ Description: (RO) Attribute to read the stored timestamps form buffer FIFO.
> - "1234.567 EVIN1=1" for a trigger from EVIN1 changed from low to high
> - "1234.567 EVIN1=0 EVIN2=1 for a simultaneous trigger of EVIN1 changed to low and
> EVIN2 changed to high.
> + - "1234.567 CMD=0" for a internal trigger
>
> +What: /sys/class/rtc/rtcX/tamper/trigger
> +Date: January 2025
> +KernelVersion: 6.13
> +Contact: Markus Burri <markus.burri@mt.com>
> +Description: (WO) Attribute to trigger an internal timestamp event
> + Write a '1' to trigger an internal event and store a timestamp.
> diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
> index 764e654c2..ca3a19162 100644
> --- a/drivers/rtc/rtc-rv8803.c
> +++ b/drivers/rtc/rtc-rv8803.c
> @@ -904,12 +904,45 @@ static ssize_t read_show(struct device *dev, struct device_attribute *attr, char
> return offset;
> }
>
> +static ssize_t trigger_store(struct device *dev, struct device_attribute *attr, const char *buf,
> + size_t count)
> +{
> + struct rv8803_data *rv8803 = dev_get_drvdata(dev->parent);
> + struct i2c_client *client = rv8803->client;
> + int ret;
> + unsigned long tmo;
> +
> + guard(mutex)(&rv8803->flags_lock);
> +
> + /* CMDTRGEN */
> + ret = rv8803_write_reg(client, RX8901_WRCMD_CFG, BIT(0));
> + if (ret < 0)
> + return ret;
> + ret = rv8803_write_reg(client, RX8901_WRCMD_TRG, 0xFF);
> + if (ret < 0)
> + return ret;
> +
> + tmo = jiffies + msecs_to_jiffies(100); /* timeout 100ms */
> + do {
> + usleep_range(10, 2000);
> + ret = rv8803_read_reg(client, RX8901_WRCMD_TRG);
> + if (ret < 0)
> + return ret;
> + if (time_after(jiffies, tmo))
> + return -EBUSY;
> + } while (ret);
> +
> + return count;
> +}
> +
> static DEVICE_ATTR_WO(enable);
> static DEVICE_ATTR_RO(read);
> +static DEVICE_ATTR_WO(trigger);
>
> static struct attribute *rv8803_rtc_event_attrs[] = {
> &dev_attr_enable.attr,
> &dev_attr_read.attr,
> + &dev_attr_trigger.attr,
> NULL
> };
>
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 5/5] rtc-rv8803: extend sysfs to read status
2025-01-16 13:15 ` [PATCH v2 5/5] rtc-rv8803: extend sysfs to read status Markus Burri
@ 2025-02-19 16:33 ` Manuel Traut
0 siblings, 0 replies; 11+ messages in thread
From: Manuel Traut @ 2025-02-19 16:33 UTC (permalink / raw)
To: Markus Burri
Cc: linux-kernel, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Marek Vasut, linux-rtc, devicetree
On Thu, Jan 16, 2025 at 02:15:32PM +0100, Markus Burri wrote:
> Add sysfs functionality to read the status and configuration.
> The functions provide the number of stored timestamp events, the current
> EVIN pin configuration and the enabled/disabled status.
>
> Signed-off-by: Markus Burri <markus.burri@mt.com>
Reviewed-by: Manuel Traut <manuel.traut@mt.com>
> ---
> .../ABI/testing/sysfs-class-rtc-tamper | 8 ++
> drivers/rtc/rtc-rv8803.c | 106 ++++++++++++++++++
> 2 files changed, 114 insertions(+)
>
> diff --git a/Documentation/ABI/testing/sysfs-class-rtc-tamper b/Documentation/ABI/testing/sysfs-class-rtc-tamper
> index 2fd6578a6..b3aa73c81 100644
> --- a/Documentation/ABI/testing/sysfs-class-rtc-tamper
> +++ b/Documentation/ABI/testing/sysfs-class-rtc-tamper
> @@ -26,3 +26,11 @@ KernelVersion: 6.13
> Contact: Markus Burri <markus.burri@mt.com>
> Description: (WO) Attribute to trigger an internal timestamp event
> Write a '1' to trigger an internal event and store a timestamp.
> +
> +What: /sys/class/rtc/rtcX/tamper/status
> +Date: January 2025
> +KernelVersion: 6.13
> +Contact: Markus Burri <markus.burri@mt.com>
> +Description: (RO) Attribute to read configuration and status for EVINx and buffer.
> + Provide the number of stored timestamp events, the current EVIN pin configuration
> + and the enabled/disabled status.
> diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
> index ca3a19162..350cd92d6 100644
> --- a/drivers/rtc/rtc-rv8803.c
> +++ b/drivers/rtc/rtc-rv8803.c
> @@ -84,8 +84,11 @@
>
> #define RX8901_EVNT_INTF 0x47
>
> +#define RX8901_BUF_OVWF 0x4F
> +
> #define NO_OF_EVIN 3
>
> +#define EVIN_FILTER_FACTOR 125
> #define EVIN_FILTER_MAX 40
>
> enum rv8803_type {
> @@ -116,6 +119,26 @@ struct cfg_val_txt {
> bool hide;
> };
>
> +static const struct cfg_val_txt pull_resistor_txt[] = {
> + { "no", no },
> + { "PU/500k", pull_up_500k },
> + { "PU/1M", pull_up_1M },
> + { "PU/10M", pull_up_10M },
> + { "PD/500k", pull_down_500k },
> + { "no", 0b101, 1 },
> + { "no", 0b110, 1 },
> + { "no", 0b111, 1 },
> + { NULL }
> +};
> +
> +static const struct cfg_val_txt trigger_txt[] = {
> + { "falling", falling_edge },
> + { "rising", rising_edge },
> + { "both", both_edges },
> + { "both", 0b11, 1 },
> + { NULL }
> +};
> +
> static const struct cfg_val_txt trg_status_txt[] = {
> { "EVIN1", BIT(5) },
> { "EVIN2", BIT(6) },
> @@ -632,6 +655,16 @@ static int rv8803_nvram_read(void *priv, unsigned int offset,
> return 0;
> }
>
> +static char *cfg2txt(const struct cfg_val_txt *cfg, u8 value)
> +{
> + do {
> + if (cfg->val == value)
> + return cfg->txt;
> + } while (++cfg && cfg->txt);
> +
> + return NULL;
Maybe return a more human readable string here?
> +}
> +
> static int rv8803_ts_event_write_evin(int evin, struct rv8803_data *rv8803,
> enum evin_pull_resistor pullup_down,
> enum evin_trigger trigger, int filter)
> @@ -935,14 +968,87 @@ static ssize_t trigger_store(struct device *dev, struct device_attribute *attr,
> return count;
> }
>
> +static ssize_t status_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + int evin_en, evin_cfg, evin_flt, buf1_cfg, buf1_stat, buf_ovwf;
> + int i;
> + int offset = 0;
> + u8 ev_pullupdown[NO_OF_EVIN];
> + u8 ev_trigger[NO_OF_EVIN];
> + int ev_filter[NO_OF_EVIN];
> +
> + struct i2c_client *client = to_i2c_client(dev->parent);
> + struct rv8803_data *rv8803 = dev_get_drvdata(dev->parent);
> +
> + scoped_guard(mutex, &rv8803->flags_lock) {
> + evin_en = rv8803_read_reg(client, RX8901_EVIN_EN);
> + if (evin_en < 0)
> + return evin_en;
> +
> + for (i = 0; i < NO_OF_EVIN; ++i) {
> + evin_cfg = rv8803_read_reg(client, evin_cfg_regs[i]);
> + evin_flt = rv8803_read_reg(client, evin_flt_regs[i]);
> + if (evin_cfg < 0 || evin_flt < 0)
> + return -EIO;
> +
> + ev_pullupdown[i] = FIELD_GET(RX8901_EVENTx_CFG_PUPD, evin_cfg);
> + ev_trigger[i] = FIELD_GET(RX8901_EVENTx_CFG_POL, evin_cfg);
> + ev_filter[i] = EVIN_FILTER_FACTOR * evin_flt;
> + }
> +
> + buf1_cfg = rv8803_read_reg(client, RX8901_BUF1_CFG1);
> + buf1_stat = rv8803_read_reg(client, RX8901_BUF1_STAT);
> + buf_ovwf = rv8803_read_reg(client, RX8901_BUF_OVWF);
> + if (buf1_stat < 0 || buf1_stat < 0 || buf_ovwf < 0)
> + return -EIO;
> + }
> +
> + offset += sprintf(buf + offset, "Mode: %s\n\n",
> + FIELD_GET(BIT(6), evin_en) ? "direct" : "fifo");
> + offset += sprintf(buf + offset, "Event config:\n");
> + offset += sprintf(buf + offset, " %-13s %-7s %-7s %-7s\n", "", "EVIN1", "EVIN2", "EVIN3");
> + offset += sprintf(buf + offset, " %-13s %-7ld %-7ld %-7ld\n", "Enable",
> + FIELD_GET(BIT(0), evin_en), FIELD_GET(BIT(1), evin_en),
> + FIELD_GET(BIT(2), evin_en));
> + offset += sprintf(buf + offset, " %-13s %-7ld %-7ld %-7ld\n", "Capture",
> + FIELD_GET(BIT(3), evin_en), FIELD_GET(BIT(4), evin_en),
> + FIELD_GET(BIT(5), evin_en));
> +
> + offset += sprintf(buf + offset, " %-13s %-7s %-7s %-7s\n", "Pull-resistor",
> + cfg2txt(pull_resistor_txt, ev_pullupdown[0]),
> + cfg2txt(pull_resistor_txt, ev_pullupdown[1]),
> + cfg2txt(pull_resistor_txt, ev_pullupdown[2]));
> + offset += sprintf(buf + offset, " %-13s %-7s %-7s %-7s\n", "Edge",
> + cfg2txt(trigger_txt, ev_trigger[0]),
> + cfg2txt(trigger_txt, ev_trigger[1]),
> + cfg2txt(trigger_txt, ev_trigger[2]));
> + offset += sprintf(buf + offset, " %-13s %-7d %-7d %-7d\n\n", "Filter [ms]",
> + ev_filter[0], ev_filter[1], ev_filter[2]);
> +
> + offset += sprintf(buf + offset, "Buffer config:\n");
> + offset += sprintf(buf + offset, " %-13s %-10s\n", "Mode",
> + (FIELD_GET(BIT(6), buf1_cfg) ? "overwrite" : "inhibit"));
> + offset += sprintf(buf + offset, " %-13s %-10s\n", "Status",
> + (FIELD_GET(BIT(7), buf1_stat) ? "full" : "free"));
> + offset += sprintf(buf + offset, " %-13s %-10ld\n", "Overrun",
> + (FIELD_GET(BIT(4), buf_ovwf)));
> + offset += sprintf(buf + offset, " %-13s %-10ld\n", "No of data",
> + (FIELD_GET(GENMASK(5, 0), buf1_stat)));
> +
> + return offset;
> +}
> +
> static DEVICE_ATTR_WO(enable);
> static DEVICE_ATTR_RO(read);
> static DEVICE_ATTR_WO(trigger);
> +static DEVICE_ATTR_RO(status);
>
> static struct attribute *rv8803_rtc_event_attrs[] = {
> &dev_attr_enable.attr,
> &dev_attr_read.attr,
> &dev_attr_trigger.attr,
> + &dev_attr_status.attr,
> NULL
> };
>
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-02-19 16:33 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-16 13:15 [PATCH v2 0/5] rtc-rv8803: Implement timestamp trigger over event pins Markus Burri
2025-01-16 13:15 ` [PATCH v2 1/5] dt-bindings: rtc: add new type for epson,rx8901 Markus Burri
2025-02-19 15:32 ` Manuel Traut
2025-01-16 13:15 ` [PATCH v2 2/5] rtc-rv8803: add new type for rv8901 Markus Burri
2025-02-19 15:33 ` Manuel Traut
2025-01-16 13:15 ` [PATCH v2 3/5] rtc-rv8803: add tamper function to sysfs " Markus Burri
2025-02-19 16:20 ` Manuel Traut
2025-01-16 13:15 ` [PATCH v2 4/5] rtc-rv8803: extend sysfs to trigger internal ts-event Markus Burri
2025-02-19 16:23 ` Manuel Traut
2025-01-16 13:15 ` [PATCH v2 5/5] rtc-rv8803: extend sysfs to read status Markus Burri
2025-02-19 16:33 ` Manuel Traut
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).