* [PATCH 1/2] dt-bindings: counter: Add binding for NXP PCF85263/PCF85363 stopwatch
@ 2025-09-15 7:14 Lakshay Piplani
2025-09-15 7:14 ` [PATCH 2/2] counter: nxp-pcf85363-stopwatch: Add driver " Lakshay Piplani
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Lakshay Piplani @ 2025-09-15 7:14 UTC (permalink / raw)
To: wbg, linux-iio, linux-kernel, robh, krzk+dt, conor+dt, devicetree
Cc: vikash.bansal, priyanka.jain, shashank.rebbapragada,
Lakshay Piplani
Add a devicetree binding schema for the NXP PCF8263/PCF85363 devices when used in
stopwatch (counter) mode.
In this configuration, the device operates as a high resolution stopwatch over I2C,
counting in centiseconds (1/100th of a second) up to 999,999 hours.
Signed-off-by: Lakshay Piplani <lakshay.piplani@nxp.com>
---
.../counter/nxp,pcf85363-stopwatch.yaml | 49 +++++++++++++++++++
1 file changed, 49 insertions(+)
create mode 100644 Documentation/devicetree/bindings/counter/nxp,pcf85363-stopwatch.yaml
diff --git a/Documentation/devicetree/bindings/counter/nxp,pcf85363-stopwatch.yaml b/Documentation/devicetree/bindings/counter/nxp,pcf85363-stopwatch.yaml
new file mode 100644
index 000000000000..5fbb3f22ace4
--- /dev/null
+++ b/Documentation/devicetree/bindings/counter/nxp,pcf85363-stopwatch.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/counter/nxp,pcf85363-stopwatch.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP PCF85263ATL/PCF85363ATL Stopwatch (counter) mode
+
+maintainers:
+ - Lakshay Piplani <lakshay.piplani@nxp.com>
+
+description: |
+ Binding for NXP PCF82563ATL/PCF85363ATL devices when used in the
+ stopwatch mode. In this mode, the device provides a centi-seconds
+ (1/100th of a second) resolution operating over i2c.
+
+properties:
+ compatible:
+ enum:
+ - nxp,pcf85263atl
+ - nxp,pcf85363atl
+
+ reg:
+ maxItems: 1
+
+ quartz-load-femtofarads:
+ description:
+ The capacitive load of the quartz(x-tal).
+ enum: [6000, 7000, 12500]
+ default: 7000
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ counter@51 {
+ compatible = "nxp,pcf85363atl";
+ reg = <0x51>;
+ quartz-load-femtofarads = <7000>;
+ };
+ };
--
2.25.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 2/2] counter: nxp-pcf85363-stopwatch: Add driver for NXP PCF85263/PCF85363 stopwatch 2025-09-15 7:14 [PATCH 1/2] dt-bindings: counter: Add binding for NXP PCF85263/PCF85363 stopwatch Lakshay Piplani @ 2025-09-15 7:14 ` Lakshay Piplani 2025-09-15 7:21 ` Krzysztof Kozlowski ` (2 more replies) 2025-09-15 7:23 ` [PATCH 1/2] dt-bindings: counter: Add binding " Krzysztof Kozlowski 2025-10-05 6:45 ` William Breathitt Gray 2 siblings, 3 replies; 7+ messages in thread From: Lakshay Piplani @ 2025-09-15 7:14 UTC (permalink / raw) To: wbg, linux-iio, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: vikash.bansal, priyanka.jain, shashank.rebbapragada, Lakshay Piplani Add driver for the NXP PCF85263/PCF85363 devices when configured in stopwatch mode. In this mode, the device provides a dedicated stopwatch function that counts in centiseconds (1/100th of a second) and supports a range up to 999,999 hours. Signed-off-by: Lakshay Piplani <lakshay.piplani@nxp.com> --- drivers/counter/Kconfig | 12 + drivers/counter/Makefile | 1 + drivers/counter/nxp-pcf85363-stopwatch.c | 395 +++++++++++++++++++++++ 3 files changed, 408 insertions(+) create mode 100644 drivers/counter/nxp-pcf85363-stopwatch.c diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index d30d22dfe577..1d62893ffd5c 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -147,4 +147,16 @@ config TI_EQEP To compile this driver as a module, choose M here: the module will be called ti-eqep. +config NXP_PCF85363_STOPWATCH + tristate "NXP PCF85263/PCF85363 stopwatch" + depends on I2C + select REGMAP_I2C + help + Say Y to enable support for the NXP PCF85263ATL/PCF85363ATL when operated + in stopwatch (counter) mode. This device exposes a counter over I2C with + centisecond (1/100th of a second) granularity, counting up to 999,999 hours. + + To compile this driver as a module, choose M here: the + module will be called nxp-pcf85363-stopwatch. + endif # COUNTER diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile index fa3c1d08f706..298e14f113f2 100644 --- a/drivers/counter/Makefile +++ b/drivers/counter/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_FTM_QUADDEC) += ftm-quaddec.o obj-$(CONFIG_MICROCHIP_TCB_CAPTURE) += microchip-tcb-capture.o obj-$(CONFIG_INTEL_QEP) += intel-qep.o obj-$(CONFIG_TI_ECAP_CAPTURE) += ti-ecap-capture.o +obj-$(CONFIG_NXP_PCF85363_STOPWATCH) += nxp-pcf85363-stopwatch.o diff --git a/drivers/counter/nxp-pcf85363-stopwatch.c b/drivers/counter/nxp-pcf85363-stopwatch.c new file mode 100644 index 000000000000..ee920634282c --- /dev/null +++ b/drivers/counter/nxp-pcf85363-stopwatch.c @@ -0,0 +1,395 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for NXP PCF85263/PCF85363 Stopwatch + * + * Copyright (C) 2025 NXP + */ +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/bcd.h> +#include <linux/of_device.h> +#include <linux/regmap.h> +#include <linux/counter.h> +#include <linux/cleanup.h> +#include <linux/bitfield.h> +#include <linux/nvmem-provider.h> + +#define SW_100THS 0x00 +#define SW_SECS 0x01 +#define SW_MINUTES 0x02 +#define SW_HOURS_XX_XX_00 0x03 +#define SW_HOURS_XX_00_XX 0x04 +#define SW_HOURS_00_XX_XX 0x05 + +#define CTRL_OFFSET 0x24 +#define CTRL_OSCILLATOR 0x25 +#define CTRL_BATTERY 0x26 +#define CTRL_PIN_IO 0x27 +#define CTRL_FUNCTION 0x28 +#define CTRL_INTA_EN 0x29 +#define CTRL_INTB_EN 0x2a +#define CTRL_FLAGS 0x2b +#define CTRL_RAMBYTE 0x2c +#define CTRL_WDOG 0x2d +#define CTRL_STOP_EN 0x2e +#define CTRL_RESETS 0x2f +#define CTRL_RAM 0x40 + +#define OSC_CAP_SEL GENMASK(1, 0) +#define OSC_CAP_6000 0x01 +#define OSC_CAP_12500 0x02 + +#define STOP_EN_STOP BIT(0) +#define RTCM_BIT BIT(4) +#define MODE_100TH_S BIT(7) +#define SW_BCD7_MASK GENMASK(6, 0) + +#define RESET_CPR 0xa4 + +#define NVRAM_SIZE 0x40 + +#define SW_MAX_100THS 359999999999ULL /* Maximum representable value in centiseconds (10ms)*/ + +#define SW_TIME_REGS 6 + +struct pcf85363 { + struct regmap *regmap; + struct counter_device *counter; + struct mutex lock; /* Protects access to stopwatch registers */ +}; + +struct pcf85x63_config { + const struct regmap_config regmap; + unsigned int num_nvram; +}; + +static int pcf85363_load_capacitance(struct pcf85363 *pcf85363) +{ + struct device *dev = pcf85363->counter->parent; + u32 load = 7000; + u8 value = 0; + + device_property_read_u32(dev, "quartz-load-femtofarads", &load); + + switch (load) { + default: + dev_warn(pcf85363->counter->parent, "Unknown quartz-load-femtofarads value: %d. Assuming 7000", + load); + fallthrough; + case 7000: + break; + case 6000: + value = OSC_CAP_6000; + break; + case 12500: + value = OSC_CAP_12500; + break; + } + + return regmap_update_bits(pcf85363->regmap, CTRL_OSCILLATOR, + OSC_CAP_SEL, value); +} + +/* Reads stopwatch value in 1/100 seconds (centiseconds), the device stores + * six BCD fields: CC(0..99), SS(0..59), MM(0..59), HH0/HH1/HH2 (each 0..99) + * Seconds and minutes contain OS/EMON flag bits; mask them as per datasheet + * before bcd2bin(). + */ +static int pcf85363_counter_read(struct counter_device *counter, + struct counter_count *count, u64 *val) +{ + struct pcf85363 *pcf85363 = counter_priv(counter); + u8 raw[SW_TIME_REGS]; + u64 hours; + int ret; + + guard(mutex)(&pcf85363->lock); + ret = regmap_bulk_read(pcf85363->regmap, SW_100THS, raw, ARRAY_SIZE(raw)); + if (ret) + return ret; + + /* Mask OS/EMON flag bits in seconds/minutes */ + raw[1] = FIELD_GET(SW_BCD7_MASK, raw[1]); + raw[2] = FIELD_GET(SW_BCD7_MASK, raw[2]); + + hours = (u64)bcd2bin(raw[3]); + hours += (u64)bcd2bin(raw[4]) * 100ULL; + hours += (u64)bcd2bin(raw[5]) * 10000ULL; + + *val = (u64)bcd2bin(raw[0]); + *val += (u64)bcd2bin(raw[1]) * 100ULL; + *val += (u64)bcd2bin(raw[2]) * 60ULL * 100ULL; + *val += hours * 60ULL * 60ULL * 100ULL; + + /* Defensive clamp in case of transient read while rolling over */ + if (*val > SW_MAX_100THS) { + dev_warn(counter->parent, "stopwatch value exceeds max, clamping\n"); + *val = SW_MAX_100THS; + } + + return 0; +} + +/* Set stopwatch value in centiseconds. It requires a stop-load-start sequence. + * set STOP_EN, write all six BCD fields then clear STOP_EN. + */ +static int pcf85363_counter_write(struct counter_device *counter, + struct counter_count *count, const u64 val) +{ + struct pcf85363 *pcf85363 = counter_priv(counter); + u64 rem = val; + u8 buf[SW_TIME_REGS]; + int ret; + + if (val > SW_MAX_100THS) + return -ERANGE; + + buf[0] = bin2bcd(rem % 100); rem /= 100; + buf[1] = bin2bcd(rem % 60); rem /= 60; + buf[2] = bin2bcd(rem % 60); rem /= 60; + buf[3] = bin2bcd(rem % 100); rem /= 100; + buf[4] = bin2bcd(rem % 100); rem /= 100; + buf[5] = bin2bcd(rem % 100); + + guard(mutex)(&pcf85363->lock); + ret = regmap_update_bits(pcf85363->regmap, CTRL_STOP_EN, STOP_EN_STOP, + FIELD_PREP(STOP_EN_STOP, 1)); + if (ret) + return ret; + + ret = regmap_bulk_write(pcf85363->regmap, SW_100THS, buf, ARRAY_SIZE(buf)); + if (ret) + return ret; + + ret = regmap_update_bits(pcf85363->regmap, CTRL_STOP_EN, STOP_EN_STOP, + FIELD_PREP(STOP_EN_STOP, 0)); + + return ret; +} + +static int pcf85363_counter_is_enabled(struct counter_device *counter, + struct counter_count *count, u8 *enable) +{ + struct pcf85363 *pcf85363 = counter_priv(counter); + unsigned int val; + int ret; + + guard(mutex)(&pcf85363->lock); + ret = regmap_read(pcf85363->regmap, CTRL_STOP_EN, &val); + if (ret) + return ret; + + *enable = !FIELD_GET(STOP_EN_STOP, val); + + return 0; +} + +static int pcf85363_counter_set_enable(struct counter_device *counter, + struct counter_count *count, u8 enable) +{ + struct pcf85363 *pcf85363 = counter_priv(counter); + + guard(mutex)(&pcf85363->lock); + + return regmap_update_bits(pcf85363->regmap, CTRL_STOP_EN, + STOP_EN_STOP, FIELD_PREP(STOP_EN_STOP, enable ? 0 : 1)); +} + +static const struct counter_ops pcf85363_counter_ops = { + .count_read = pcf85363_counter_read, + .count_write = pcf85363_counter_write, +}; + +static struct counter_comp pcf85363_counter_ext[] = { + COUNTER_COMP_ENABLE(pcf85363_counter_is_enabled, + pcf85363_counter_set_enable), +}; + +static struct counter_count pcf85363_counts[] = { + { + .id = 0, + .name = "pcf85363-stopwatch", + .functions_list = (const enum counter_function[]){ + COUNTER_FUNCTION_INCREASE }, + .num_functions = 1, + .ext = pcf85363_counter_ext, + .num_ext = ARRAY_SIZE(pcf85363_counter_ext), + } +}; + +static int pcf85363_nvram_read(void *priv, unsigned int offset, void *val, + size_t bytes) +{ + struct pcf85363 *pcf85363 = priv; + + guard(mutex)(&pcf85363->lock); + + return regmap_bulk_read(pcf85363->regmap, CTRL_RAM + offset, + val, bytes); +} + +static int pcf85363_nvram_write(void *priv, unsigned int offset, void *val, + size_t bytes) +{ + struct pcf85363 *pcf85363 = priv; + + guard(mutex)(&pcf85363->lock); + + return regmap_bulk_write(pcf85363->regmap, CTRL_RAM + offset, + val, bytes); +} + +static int pcf85x63_nvram_read(void *priv, unsigned int offset, void *val, + size_t bytes) +{ + struct pcf85363 *pcf85363 = priv; + unsigned int tmp_val; + int ret; + + guard(mutex)(&pcf85363->lock); + + ret = regmap_read(pcf85363->regmap, CTRL_RAMBYTE, &tmp_val); + (*(unsigned char *)val) = (unsigned char)tmp_val; + + return ret; +} + +static int pcf85x63_nvram_write(void *priv, unsigned int offset, void *val, + size_t bytes) +{ + struct pcf85363 *pcf85363 = priv; + unsigned char tmp_val; + + guard(mutex)(&pcf85363->lock); + + tmp_val = *((unsigned char *)val); + return regmap_write(pcf85363->regmap, CTRL_RAMBYTE, + (unsigned int)tmp_val); +} + +static const struct pcf85x63_config pcf_85263_config = { + .regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x2f, + }, + .num_nvram = 1 +}; + +static const struct pcf85x63_config pcf_85363_config = { + .regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x7f, + }, + .num_nvram = 2 +}; + +static const struct nvmem_config nvmem_cfgs[] = { + { + .name = "pcf85x63-", + .word_size = 1, + .stride = 1, + .size = 1, + .reg_read = pcf85x63_nvram_read, + .reg_write = pcf85x63_nvram_write, + }, { + .name = "pcf85363-", + .word_size = 1, + .stride = 1, + .size = NVRAM_SIZE, + .reg_read = pcf85363_nvram_read, + .reg_write = pcf85363_nvram_write, + }, +}; + +static int pcf85363_stopwatch_probe(struct i2c_client *client) +{ + struct pcf85363 *pcf85363; + const struct pcf85x63_config *config = &pcf_85363_config; + const void *data = of_device_get_match_data(&client->dev); + struct device *dev = &client->dev; + struct nvmem_device *nvmem; + int ret, i, err; + + if (data) + config = data; + + struct counter_device *counter = devm_counter_alloc(dev, sizeof(struct pcf85363)); + + if (!counter) + return -ENOMEM; + + pcf85363 = counter_priv(counter); + + mutex_init(&pcf85363->lock); + + pcf85363->regmap = devm_regmap_init_i2c(client, &config->regmap); + if (IS_ERR(pcf85363->regmap)) + return dev_err_probe(dev, PTR_ERR(pcf85363->regmap), "regmap init failed\n"); + + /* Stopwatch Mode set and centiseconds granularity enabled */ + ret = regmap_update_bits(pcf85363->regmap, CTRL_FUNCTION, + RTCM_BIT | MODE_100TH_S, RTCM_BIT | MODE_100TH_S); + if (ret) + return dev_err_probe(dev, ret, "Failed to set RTCM bit\n"); + + ret = regmap_write(pcf85363->regmap, CTRL_FLAGS, 0); + if (ret) + return dev_err_probe(dev, ret, "Failed to clear flags\n"); + + counter->name = "pcf85363-stopwatch"; + counter->parent = dev; + counter->ops = &pcf85363_counter_ops; + counter->counts = pcf85363_counts; + counter->num_counts = ARRAY_SIZE(pcf85363_counts); + pcf85363->counter = counter; + + ret = devm_counter_add(dev, counter); + if (ret) + return dev_err_probe(dev, ret, "Counter registration failed\n"); + + dev_dbg(dev, "pcf85363 registered in stopwatch mode\n"); + + err = pcf85363_load_capacitance(pcf85363); + if (err < 0) + dev_warn(&client->dev, "failed to set xtal load capacitance: %d", err); + + for (i = 0; i < config->num_nvram; i++) { + struct nvmem_config cfg = nvmem_cfgs[i]; + + cfg.priv = pcf85363; + cfg.dev = dev; + cfg.id = i; + nvmem = devm_nvmem_register(dev, &cfg); + if (IS_ERR(nvmem)) + return dev_err_probe(dev, PTR_ERR(nvmem), "nvmem reg %d failed\n", i); + } + + return 0; +} + +static const struct of_device_id dev_ids[] = { + { .compatible = "nxp,pcf85263atl", .data = &pcf_85263_config }, + { .compatible = "nxp,pcf85363atl", .data = &pcf_85363_config }, + { } +}; +MODULE_DEVICE_TABLE(of, dev_ids); + +static struct i2c_driver pcf85363_sw_driver = { + .driver = { + .name = "pcf85363-stopwatch", + .of_match_table = of_match_ptr(dev_ids), + }, + .probe = pcf85363_stopwatch_probe, +}; + +module_i2c_driver(pcf85363_sw_driver); + +MODULE_AUTHOR("Lakshay Piplani"); +MODULE_DESCRIPTION("pcf85263/pcf85363 stopwatch driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("COUNTER"); -- 2.25.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] counter: nxp-pcf85363-stopwatch: Add driver for NXP PCF85263/PCF85363 stopwatch 2025-09-15 7:14 ` [PATCH 2/2] counter: nxp-pcf85363-stopwatch: Add driver " Lakshay Piplani @ 2025-09-15 7:21 ` Krzysztof Kozlowski 2025-09-15 19:36 ` kernel test robot 2025-09-16 9:21 ` kernel test robot 2 siblings, 0 replies; 7+ messages in thread From: Krzysztof Kozlowski @ 2025-09-15 7:21 UTC (permalink / raw) To: Lakshay Piplani, wbg, linux-iio, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: vikash.bansal, priyanka.jain, shashank.rebbapragada On 15/09/2025 09:14, Lakshay Piplani wrote: > +#include <linux/regmap.h> > +#include <linux/counter.h> > +#include <linux/cleanup.h> > +#include <linux/bitfield.h> > +#include <linux/nvmem-provider.h> > + > +#define SW_100THS 0x00 > +#define SW_SECS 0x01 > +#define SW_MINUTES 0x02 > +#define SW_HOURS_XX_XX_00 0x03 > +#define SW_HOURS_XX_00_XX 0x04 > +#define SW_HOURS_00_XX_XX 0x05 > + > +#define CTRL_OFFSET 0x24 > +#define CTRL_OSCILLATOR 0x25 > +#define CTRL_BATTERY 0x26 > +#define CTRL_PIN_IO 0x27 > +#define CTRL_FUNCTION 0x28 > +#define CTRL_INTA_EN 0x29 > +#define CTRL_INTB_EN 0x2a > +#define CTRL_FLAGS 0x2b > +#define CTRL_RAMBYTE 0x2c > +#define CTRL_WDOG 0x2d > +#define CTRL_STOP_EN 0x2e > +#define CTRL_RESETS 0x2f > +#define CTRL_RAM 0x40 > + > +#define OSC_CAP_SEL GENMASK(1, 0) > +#define OSC_CAP_6000 0x01 > +#define OSC_CAP_12500 0x02 > + > +#define STOP_EN_STOP BIT(0) > +#define RTCM_BIT BIT(4) > +#define MODE_100TH_S BIT(7) > +#define SW_BCD7_MASK GENMASK(6, 0) > + > +#define RESET_CPR 0xa4 > + > +#define NVRAM_SIZE 0x40 > + > +#define SW_MAX_100THS 359999999999ULL /* Maximum representable value in centiseconds (10ms)*/ > + > +#define SW_TIME_REGS 6 > + > +struct pcf85363 { > + struct regmap *regmap; > + struct counter_device *counter; > + struct mutex lock; /* Protects access to stopwatch registers */ regmap protects it already (see also further) > +}; > + > +struct pcf85x63_config { > + const struct regmap_config regmap; > + unsigned int num_nvram; > +}; > + > +static int pcf85363_load_capacitance(struct pcf85363 *pcf85363) > +{ > + struct device *dev = pcf85363->counter->parent; > + u32 load = 7000; > + u8 value = 0; > + > + device_property_read_u32(dev, "quartz-load-femtofarads", &load); > + > + switch (load) { > + default: > + dev_warn(pcf85363->counter->parent, "Unknown quartz-load-femtofarads value: %d. Assuming 7000", Missing wrapping. Please wrap around 80, so after parent, see Linux coding style for proper explanation. > + load); > + fallthrough; > + case 7000: > + break; > + case 6000: > + value = OSC_CAP_6000; > + break; > + case 12500: > + value = OSC_CAP_12500; > + break; > + } > + > + return regmap_update_bits(pcf85363->regmap, CTRL_OSCILLATOR, > + OSC_CAP_SEL, value); > +} > + > +/* Reads stopwatch value in 1/100 seconds (centiseconds), the device stores That's not netdev, so use standard Linux coding style comments. > + * six BCD fields: CC(0..99), SS(0..59), MM(0..59), HH0/HH1/HH2 (each 0..99) > + * Seconds and minutes contain OS/EMON flag bits; mask them as per datasheet > + * before bcd2bin(). > + */ > +static int pcf85363_counter_read(struct counter_device *counter, > + struct counter_count *count, u64 *val) > +{ > + struct pcf85363 *pcf85363 = counter_priv(counter); > + u8 raw[SW_TIME_REGS]; > + u64 hours; > + int ret; > + > + guard(mutex)(&pcf85363->lock); > + ret = regmap_bulk_read(pcf85363->regmap, SW_100THS, raw, ARRAY_SIZE(raw)); > + if (ret) > + return ret; > + So the lock would end here if you were protecting registers. Your comment about locking is misleading or incomplete or incorrect. > + /* Mask OS/EMON flag bits in seconds/minutes */ > + raw[1] = FIELD_GET(SW_BCD7_MASK, raw[1]); > + raw[2] = FIELD_GET(SW_BCD7_MASK, raw[2]); > + > + hours = (u64)bcd2bin(raw[3]); > + hours += (u64)bcd2bin(raw[4]) * 100ULL; > + hours += (u64)bcd2bin(raw[5]) * 10000ULL; > + > + *val = (u64)bcd2bin(raw[0]); > + *val += (u64)bcd2bin(raw[1]) * 100ULL; > + *val += (u64)bcd2bin(raw[2]) * 60ULL * 100ULL; > + *val += hours * 60ULL * 60ULL * 100ULL; > + > + /* Defensive clamp in case of transient read while rolling over */ > + if (*val > SW_MAX_100THS) { > + dev_warn(counter->parent, "stopwatch value exceeds max, clamping\n"); > + *val = SW_MAX_100THS; > + } > + > + return 0; > +} > + > +/* Set stopwatch value in centiseconds. It requires a stop-load-start sequence. > + * set STOP_EN, write all six BCD fields then clear STOP_EN. > + */ > +static int pcf85363_counter_write(struct counter_device *counter, > + struct counter_count *count, const u64 val) > +{ > + struct pcf85363 *pcf85363 = counter_priv(counter); > + u64 rem = val; > + u8 buf[SW_TIME_REGS]; > + int ret; > + > + if (val > SW_MAX_100THS) > + return -ERANGE; > + > + buf[0] = bin2bcd(rem % 100); rem /= 100; > + buf[1] = bin2bcd(rem % 60); rem /= 60; > + buf[2] = bin2bcd(rem % 60); rem /= 60; > + buf[3] = bin2bcd(rem % 100); rem /= 100; > + buf[4] = bin2bcd(rem % 100); rem /= 100; > + buf[5] = bin2bcd(rem % 100); > + > + guard(mutex)(&pcf85363->lock); > + ret = regmap_update_bits(pcf85363->regmap, CTRL_STOP_EN, STOP_EN_STOP, > + FIELD_PREP(STOP_EN_STOP, 1)); > + if (ret) > + return ret; > + > + ret = regmap_bulk_write(pcf85363->regmap, SW_100THS, buf, ARRAY_SIZE(buf)); > + if (ret) > + return ret; > + > + ret = regmap_update_bits(pcf85363->regmap, CTRL_STOP_EN, STOP_EN_STOP, > + FIELD_PREP(STOP_EN_STOP, 0)); > + > + return ret; > +} > + > +static int pcf85363_counter_is_enabled(struct counter_device *counter, > + struct counter_count *count, u8 *enable) > +{ > + struct pcf85363 *pcf85363 = counter_priv(counter); > + unsigned int val; > + int ret; > + > + guard(mutex)(&pcf85363->lock); > + ret = regmap_read(pcf85363->regmap, CTRL_STOP_EN, &val); > + if (ret) > + return ret; > + > + *enable = !FIELD_GET(STOP_EN_STOP, val); > + > + return 0; > +} > + > +static int pcf85363_counter_set_enable(struct counter_device *counter, > + struct counter_count *count, u8 enable) > +{ > + struct pcf85363 *pcf85363 = counter_priv(counter); > + > + guard(mutex)(&pcf85363->lock); > + > + return regmap_update_bits(pcf85363->regmap, CTRL_STOP_EN, > + STOP_EN_STOP, FIELD_PREP(STOP_EN_STOP, enable ? 0 : 1)); > +} > + > +static const struct counter_ops pcf85363_counter_ops = { > + .count_read = pcf85363_counter_read, > + .count_write = pcf85363_counter_write, > +}; > + > +static struct counter_comp pcf85363_counter_ext[] = { > + COUNTER_COMP_ENABLE(pcf85363_counter_is_enabled, > + pcf85363_counter_set_enable), > +}; > + > +static struct counter_count pcf85363_counts[] = { > + { > + .id = 0, > + .name = "pcf85363-stopwatch", > + .functions_list = (const enum counter_function[]){ > + COUNTER_FUNCTION_INCREASE }, > + .num_functions = 1, > + .ext = pcf85363_counter_ext, > + .num_ext = ARRAY_SIZE(pcf85363_counter_ext), > + } > +}; > + > +static int pcf85363_nvram_read(void *priv, unsigned int offset, void *val, > + size_t bytes) > +{ > + struct pcf85363 *pcf85363 = priv; > + > + guard(mutex)(&pcf85363->lock); > + > + return regmap_bulk_read(pcf85363->regmap, CTRL_RAM + offset, > + val, bytes); > +} > + > +static int pcf85363_nvram_write(void *priv, unsigned int offset, void *val, > + size_t bytes) > +{ > + struct pcf85363 *pcf85363 = priv; > + > + guard(mutex)(&pcf85363->lock); > + > + return regmap_bulk_write(pcf85363->regmap, CTRL_RAM + offset, > + val, bytes); > +} > + > +static int pcf85x63_nvram_read(void *priv, unsigned int offset, void *val, > + size_t bytes) > +{ > + struct pcf85363 *pcf85363 = priv; > + unsigned int tmp_val; > + int ret; > + > + guard(mutex)(&pcf85363->lock); > + > + ret = regmap_read(pcf85363->regmap, CTRL_RAMBYTE, &tmp_val); > + (*(unsigned char *)val) = (unsigned char)tmp_val; > + > + return ret; > +} > + > +static int pcf85x63_nvram_write(void *priv, unsigned int offset, void *val, > + size_t bytes) > +{ > + struct pcf85363 *pcf85363 = priv; > + unsigned char tmp_val; > + > + guard(mutex)(&pcf85363->lock); > + > + tmp_val = *((unsigned char *)val); > + return regmap_write(pcf85363->regmap, CTRL_RAMBYTE, > + (unsigned int)tmp_val); > +} > + > +static const struct pcf85x63_config pcf_85263_config = { > + .regmap = { > + .reg_bits = 8, > + .val_bits = 8, > + .max_register = 0x2f, > + }, > + .num_nvram = 1 > +}; > + > +static const struct pcf85x63_config pcf_85363_config = { > + .regmap = { > + .reg_bits = 8, > + .val_bits = 8, > + .max_register = 0x7f, > + }, > + .num_nvram = 2 > +}; > + > +static const struct nvmem_config nvmem_cfgs[] = { > + { > + .name = "pcf85x63-", > + .word_size = 1, > + .stride = 1, > + .size = 1, > + .reg_read = pcf85x63_nvram_read, > + .reg_write = pcf85x63_nvram_write, > + }, { > + .name = "pcf85363-", > + .word_size = 1, > + .stride = 1, > + .size = NVRAM_SIZE, > + .reg_read = pcf85363_nvram_read, > + .reg_write = pcf85363_nvram_write, > + }, > +}; > + > +static int pcf85363_stopwatch_probe(struct i2c_client *client) > +{ > + struct pcf85363 *pcf85363; > + const struct pcf85x63_config *config = &pcf_85363_config; Drop this assignment, not correct. > + const void *data = of_device_get_match_data(&client->dev); Drop, pointless. > + struct device *dev = &client->dev; > + struct nvmem_device *nvmem; > + int ret, i, err; > + > + if (data) > + config = data; You only need the assignment here data = get_match_data. > + > + struct counter_device *counter = devm_counter_alloc(dev, sizeof(struct pcf85363)); > + > + if (!counter) > + return -ENOMEM; > + > + pcf85363 = counter_priv(counter); > + > + mutex_init(&pcf85363->lock); > + > + pcf85363->regmap = devm_regmap_init_i2c(client, &config->regmap); > + if (IS_ERR(pcf85363->regmap)) > + return dev_err_probe(dev, PTR_ERR(pcf85363->regmap), "regmap init failed\n"); > + > + /* Stopwatch Mode set and centiseconds granularity enabled */ > + ret = regmap_update_bits(pcf85363->regmap, CTRL_FUNCTION, > + RTCM_BIT | MODE_100TH_S, RTCM_BIT | MODE_100TH_S); > + if (ret) > + return dev_err_probe(dev, ret, "Failed to set RTCM bit\n"); > + > + ret = regmap_write(pcf85363->regmap, CTRL_FLAGS, 0); > + if (ret) > + return dev_err_probe(dev, ret, "Failed to clear flags\n"); > + > + counter->name = "pcf85363-stopwatch"; > + counter->parent = dev; > + counter->ops = &pcf85363_counter_ops; > + counter->counts = pcf85363_counts; > + counter->num_counts = ARRAY_SIZE(pcf85363_counts); > + pcf85363->counter = counter; > + > + ret = devm_counter_add(dev, counter); > + if (ret) > + return dev_err_probe(dev, ret, "Counter registration failed\n"); > + > + dev_dbg(dev, "pcf85363 registered in stopwatch mode\n"); > + > + err = pcf85363_load_capacitance(pcf85363); > + if (err < 0) > + dev_warn(&client->dev, "failed to set xtal load capacitance: %d", err); > + > + for (i = 0; i < config->num_nvram; i++) { > + struct nvmem_config cfg = nvmem_cfgs[i]; > + > + cfg.priv = pcf85363; > + cfg.dev = dev; > + cfg.id = i; > + nvmem = devm_nvmem_register(dev, &cfg); > + if (IS_ERR(nvmem)) > + return dev_err_probe(dev, PTR_ERR(nvmem), "nvmem reg %d failed\n", i); > + } > + > + return 0; > +} > + > +static const struct of_device_id dev_ids[] = { > + { .compatible = "nxp,pcf85263atl", .data = &pcf_85263_config }, > + { .compatible = "nxp,pcf85363atl", .data = &pcf_85363_config }, > + { } > +}; > +MODULE_DEVICE_TABLE(of, dev_ids); > + > +static struct i2c_driver pcf85363_sw_driver = { > + .driver = { > + .name = "pcf85363-stopwatch", > + .of_match_table = of_match_ptr(dev_ids), You have warnings here, drop of_match_ptr. There is no such combination in mainline anymore, we fixed it some time ago. > + }, > + .probe = pcf85363_stopwatch_probe, > +}; > + > +module_i2c_driver(pcf85363_sw_driver); > + > +MODULE_AUTHOR("Lakshay Piplani"); > +MODULE_DESCRIPTION("pcf85263/pcf85363 stopwatch driver"); > +MODULE_LICENSE("GPL"); > +MODULE_IMPORT_NS("COUNTER"); Best regards, Krzysztof ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] counter: nxp-pcf85363-stopwatch: Add driver for NXP PCF85263/PCF85363 stopwatch 2025-09-15 7:14 ` [PATCH 2/2] counter: nxp-pcf85363-stopwatch: Add driver " Lakshay Piplani 2025-09-15 7:21 ` Krzysztof Kozlowski @ 2025-09-15 19:36 ` kernel test robot 2025-09-16 9:21 ` kernel test robot 2 siblings, 0 replies; 7+ messages in thread From: kernel test robot @ 2025-09-15 19:36 UTC (permalink / raw) To: Lakshay Piplani, wbg, linux-iio, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: oe-kbuild-all, vikash.bansal, priyanka.jain, shashank.rebbapragada, Lakshay Piplani Hi Lakshay, kernel test robot noticed the following build warnings: [auto build test WARNING on robh/for-next] [also build test WARNING on linus/master v6.17-rc6 next-20250912] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Lakshay-Piplani/counter-nxp-pcf85363-stopwatch-Add-driver-for-NXP-PCF85263-PCF85363-stopwatch/20250915-152227 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next patch link: https://lore.kernel.org/r/20250915071415.1956219-2-lakshay.piplani%40nxp.com patch subject: [PATCH 2/2] counter: nxp-pcf85363-stopwatch: Add driver for NXP PCF85263/PCF85363 stopwatch config: i386-randconfig-141-20250916 (https://download.01.org/0day-ci/archive/20250916/202509160317.ig0aBXeu-lkp@intel.com/config) compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250916/202509160317.ig0aBXeu-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202509160317.ig0aBXeu-lkp@intel.com/ All warnings (new ones prefixed by >>): >> drivers/counter/nxp-pcf85363-stopwatch.c:375:34: warning: unused variable 'dev_ids' [-Wunused-const-variable] 375 | static const struct of_device_id dev_ids[] = { | ^~~~~~~ 1 warning generated. vim +/dev_ids +375 drivers/counter/nxp-pcf85363-stopwatch.c 374 > 375 static const struct of_device_id dev_ids[] = { 376 { .compatible = "nxp,pcf85263atl", .data = &pcf_85263_config }, 377 { .compatible = "nxp,pcf85363atl", .data = &pcf_85363_config }, 378 { } 379 }; 380 MODULE_DEVICE_TABLE(of, dev_ids); 381 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] counter: nxp-pcf85363-stopwatch: Add driver for NXP PCF85263/PCF85363 stopwatch 2025-09-15 7:14 ` [PATCH 2/2] counter: nxp-pcf85363-stopwatch: Add driver " Lakshay Piplani 2025-09-15 7:21 ` Krzysztof Kozlowski 2025-09-15 19:36 ` kernel test robot @ 2025-09-16 9:21 ` kernel test robot 2 siblings, 0 replies; 7+ messages in thread From: kernel test robot @ 2025-09-16 9:21 UTC (permalink / raw) To: Lakshay Piplani, wbg, linux-iio, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: oe-kbuild-all, vikash.bansal, priyanka.jain, shashank.rebbapragada, Lakshay Piplani Hi Lakshay, kernel test robot noticed the following build errors: [auto build test ERROR on robh/for-next] [also build test ERROR on linus/master v6.17-rc6] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Lakshay-Piplani/counter-nxp-pcf85363-stopwatch-Add-driver-for-NXP-PCF85263-PCF85363-stopwatch/20250915-152227 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next patch link: https://lore.kernel.org/r/20250915071415.1956219-2-lakshay.piplani%40nxp.com patch subject: [PATCH 2/2] counter: nxp-pcf85363-stopwatch: Add driver for NXP PCF85263/PCF85363 stopwatch config: sparc-randconfig-r121-20250916 (https://download.01.org/0day-ci/archive/20250916/202509161703.0ADG0iw4-lkp@intel.com/config) compiler: sparc-linux-gcc (GCC) 8.5.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250916/202509161703.0ADG0iw4-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202509161703.0ADG0iw4-lkp@intel.com/ All errors (new ones prefixed by >>): sparc-linux-ld: drivers/counter/nxp-pcf85363-stopwatch.o: in function `pcf85363_counter_write': >> nxp-pcf85363-stopwatch.c:(.text+0x418): undefined reference to `__umoddi3' >> sparc-linux-ld: nxp-pcf85363-stopwatch.c:(.text+0x444): undefined reference to `__umoddi3' sparc-linux-ld: nxp-pcf85363-stopwatch.c:(.text+0x474): undefined reference to `__umoddi3' sparc-linux-ld: nxp-pcf85363-stopwatch.c:(.text+0x4a4): undefined reference to `__umoddi3' sparc-linux-ld: nxp-pcf85363-stopwatch.c:(.text+0x4d4): undefined reference to `__umoddi3' -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] dt-bindings: counter: Add binding for NXP PCF85263/PCF85363 stopwatch 2025-09-15 7:14 [PATCH 1/2] dt-bindings: counter: Add binding for NXP PCF85263/PCF85363 stopwatch Lakshay Piplani 2025-09-15 7:14 ` [PATCH 2/2] counter: nxp-pcf85363-stopwatch: Add driver " Lakshay Piplani @ 2025-09-15 7:23 ` Krzysztof Kozlowski 2025-10-05 6:45 ` William Breathitt Gray 2 siblings, 0 replies; 7+ messages in thread From: Krzysztof Kozlowski @ 2025-09-15 7:23 UTC (permalink / raw) To: Lakshay Piplani, wbg, linux-iio, linux-kernel, robh, krzk+dt, conor+dt, devicetree Cc: vikash.bansal, priyanka.jain, shashank.rebbapragada On 15/09/2025 09:14, Lakshay Piplani wrote: > Add a devicetree binding schema for the NXP PCF8263/PCF85363 devices when used in > stopwatch (counter) mode. > > In this configuration, the device operates as a high resolution stopwatch over I2C, > counting in centiseconds (1/100th of a second) up to 999,999 hours. A nit, subject: drop second/last, redundant "binding for". The "dt-bindings" prefix is already stating that these are bindings. See also: https://elixir.bootlin.com/linux/v6.17-rc3/source/Documentation/devicetree/bindings/submitting-patches.rst#L18 > > Signed-off-by: Lakshay Piplani <lakshay.piplani@nxp.com> > --- > .../counter/nxp,pcf85363-stopwatch.yaml | 49 +++++++++++++++++++ > 1 file changed, 49 insertions(+) > create mode 100644 Documentation/devicetree/bindings/counter/nxp,pcf85363-stopwatch.yaml > > diff --git a/Documentation/devicetree/bindings/counter/nxp,pcf85363-stopwatch.yaml b/Documentation/devicetree/bindings/counter/nxp,pcf85363-stopwatch.yaml > new file mode 100644 > index 000000000000..5fbb3f22ace4 > --- /dev/null > +++ b/Documentation/devicetree/bindings/counter/nxp,pcf85363-stopwatch.yaml > @@ -0,0 +1,49 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/counter/nxp,pcf85363-stopwatch.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: NXP PCF85263ATL/PCF85363ATL Stopwatch (counter) mode > + > +maintainers: > + - Lakshay Piplani <lakshay.piplani@nxp.com> > + > +description: | Drop | > + Binding for NXP PCF82563ATL/PCF85363ATL devices when used in the Drop "Binding for", but describe here hardware. With these three fixes: Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> <form letter> This is an automated instruction, just in case, because many review tags are being ignored. If you know the process, just skip it entirely (please do not feel offended by me posting it here - no bad intentions intended, no patronizing, I just want to avoid wasted efforts). If you do not know the process, here is a short explanation: Please add Acked-by/Reviewed-by/Tested-by tags when posting new versions of patchset, under or above your Signed-off-by tag, unless patch changed significantly (e.g. new properties added to the DT bindings). Tag is "received", when provided in a message replied to you on the mailing list. Tools like b4 can help here ('b4 trailers -u ...'). However, there's no need to repost patches *only* to add the tags. The upstream maintainer will do that for tags received on the version they apply. Full context and explanation: https://elixir.bootlin.com/linux/v6.15/source/Documentation/process/submitting-patches.rst#L591 </form letter> Best regards, Krzysztof ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] dt-bindings: counter: Add binding for NXP PCF85263/PCF85363 stopwatch 2025-09-15 7:14 [PATCH 1/2] dt-bindings: counter: Add binding for NXP PCF85263/PCF85363 stopwatch Lakshay Piplani 2025-09-15 7:14 ` [PATCH 2/2] counter: nxp-pcf85363-stopwatch: Add driver " Lakshay Piplani 2025-09-15 7:23 ` [PATCH 1/2] dt-bindings: counter: Add binding " Krzysztof Kozlowski @ 2025-10-05 6:45 ` William Breathitt Gray 2 siblings, 0 replies; 7+ messages in thread From: William Breathitt Gray @ 2025-10-05 6:45 UTC (permalink / raw) To: Lakshay Piplani Cc: William Breathitt Gray, linux-iio, linux-kernel, robh, krzk+dt, conor+dt, devicetree, vikash.bansal, priyanka.jain, shashank.rebbapragada On Mon, Sep 15, 2025 at 12:44:14PM +0530, Lakshay Piplani wrote: > Add a devicetree binding schema for the NXP PCF8263/PCF85363 devices when used in > stopwatch (counter) mode. > > In this configuration, the device operates as a high resolution stopwatch over I2C, > counting in centiseconds (1/100th of a second) up to 999,999 hours. > > Signed-off-by: Lakshay Piplani <lakshay.piplani@nxp.com> > --- > .../counter/nxp,pcf85363-stopwatch.yaml | 49 +++++++++++++++++++ > 1 file changed, 49 insertions(+) > create mode 100644 Documentation/devicetree/bindings/counter/nxp,pcf85363-stopwatch.yaml > > diff --git a/Documentation/devicetree/bindings/counter/nxp,pcf85363-stopwatch.yaml b/Documentation/devicetree/bindings/counter/nxp,pcf85363-stopwatch.yaml > new file mode 100644 > index 000000000000..5fbb3f22ace4 > --- /dev/null > +++ b/Documentation/devicetree/bindings/counter/nxp,pcf85363-stopwatch.yaml > @@ -0,0 +1,49 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/counter/nxp,pcf85363-stopwatch.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: NXP PCF85263ATL/PCF85363ATL Stopwatch (counter) mode > + > +maintainers: > + - Lakshay Piplani <lakshay.piplani@nxp.com> > + > +description: | > + Binding for NXP PCF82563ATL/PCF85363ATL devices when used in the > + stopwatch mode. In this mode, the device provides a centi-seconds > + (1/100th of a second) resolution operating over i2c. > + > +properties: > + compatible: > + enum: > + - nxp,pcf85263atl > + - nxp,pcf85363atl > + > + reg: > + maxItems: 1 > + > + quartz-load-femtofarads: > + description: > + The capacitive load of the quartz(x-tal). > + enum: [6000, 7000, 12500] > + default: 7000 > + > +required: > + - compatible > + - reg > + > +additionalProperties: false > + > +examples: > + - | > + i2c { > + #address-cells = <1>; > + #size-cells = <0>; > + > + counter@51 { > + compatible = "nxp,pcf85363atl"; > + reg = <0x51>; > + quartz-load-femtofarads = <7000>; > + }; > + }; Hi Lakshay, It sounds like you're trying to implement a clock. Is there any particular reason you are trying to do this as a counter driver instead of using the common clk[^1] framework? The Linux counter interface isn't specifically designed for clock operations so I suspect a stopwatch module would fit better in the clk subsystem instead. Wiliam Breathitt Gray [^1] https://docs.kernel.org/driver-api/clk.html ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-10-05 6:45 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-09-15 7:14 [PATCH 1/2] dt-bindings: counter: Add binding for NXP PCF85263/PCF85363 stopwatch Lakshay Piplani 2025-09-15 7:14 ` [PATCH 2/2] counter: nxp-pcf85363-stopwatch: Add driver " Lakshay Piplani 2025-09-15 7:21 ` Krzysztof Kozlowski 2025-09-15 19:36 ` kernel test robot 2025-09-16 9:21 ` kernel test robot 2025-09-15 7:23 ` [PATCH 1/2] dt-bindings: counter: Add binding " Krzysztof Kozlowski 2025-10-05 6:45 ` William Breathitt Gray
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).