[PATCH v3 2/5] hwmon: (pmbus/adm1266) add clear_blackbox debugfs entry

From: Abdurrahman Hussain

Date: Tue May 12 2026 - 14:58:47 EST


The ADM1266 blackbox can be configured in two recording modes via
BLACKBOX_CONFIG[0]: cyclic, where the device overwrites the oldest
record once the 32-record buffer fills, and single, where it stops
recording until the buffer is cleared. Deployments that need to
preserve the full record history across multiple fault episodes
typically run in single mode and need a way to clear the buffer
after the records have been collected.

Expose a write-only debugfs file alongside sequencer_state. Writing
any data to it issues the documented clear-blackbox sub-command:
a 2-byte block-write to READ_BLACKBOX (0xDE) with payload
{0xFE, 0x00} (datasheet Rev. D).

Signed-off-by: Abdurrahman Hussain <abdurrahman@xxxxxxxxxx>
---
drivers/hwmon/pmbus/adm1266.c | 48 +++++++++++++++++++++++++++++++++++++------
1 file changed, 42 insertions(+), 6 deletions(-)

diff --git a/drivers/hwmon/pmbus/adm1266.c b/drivers/hwmon/pmbus/adm1266.c
index 7b8433226176..bd3784d59a7c 100644
--- a/drivers/hwmon/pmbus/adm1266.c
+++ b/drivers/hwmon/pmbus/adm1266.c
@@ -356,6 +356,40 @@ static int adm1266_firmware_revision_read(struct seq_file *s, void *pdata)
return 0;
}

+/*
+ * Clearing the blackbox is required when the device is configured in
+ * single-recording mode (BLACKBOX_CONFIG[0] = 0): once the 32-record
+ * buffer is full the device stops recording until cleared.
+ *
+ * The clear is issued as a 2-byte block-write to READ_BLACKBOX with
+ * payload {0xFE, 0x00} per the datasheet. READ_BLACKBOX is also used
+ * by adm1266_nvmem_read_blackbox() to walk records one at a time, so
+ * both paths take pmbus_lock to keep the clear from interleaving
+ * mid-iteration and corrupting the read sequence.
+ */
+static ssize_t adm1266_clear_blackbox_write(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct i2c_client *client = file->private_data;
+ u8 payload[2] = { 0xFE, 0x00 };
+ int ret;
+
+ guard(pmbus_lock)(client);
+ ret = i2c_smbus_write_block_data(client, ADM1266_READ_BLACKBOX,
+ sizeof(payload), payload);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static const struct file_operations adm1266_clear_blackbox_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .write = adm1266_clear_blackbox_write,
+ .llseek = noop_llseek,
+};
+
static void adm1266_init_debugfs(struct adm1266_data *data)
{
struct dentry *root;
@@ -370,6 +404,8 @@ static void adm1266_init_debugfs(struct adm1266_data *data)
adm1266_state_read);
debugfs_create_devm_seqfile(&data->client->dev, "firmware_revision", data->debugfs_dir,
adm1266_firmware_revision_read);
+ debugfs_create_file("clear_blackbox", 0200, data->debugfs_dir, data->client,
+ &adm1266_clear_blackbox_fops);
}

static int adm1266_nvmem_read_blackbox(struct adm1266_data *data, u8 *read_buff)
@@ -379,10 +415,11 @@ static int adm1266_nvmem_read_blackbox(struct adm1266_data *data, u8 *read_buff)
u8 buf[5];
int ret;

+ guard(pmbus_lock)(data->client);
+
ret = i2c_smbus_read_block_data(data->client, ADM1266_BLACKBOX_INFO, buf);
if (ret < 0)
return ret;
-
if (ret != 4)
return -EIO;

@@ -392,7 +429,6 @@ static int adm1266_nvmem_read_blackbox(struct adm1266_data *data, u8 *read_buff)
ret = adm1266_pmbus_block_xfer(data, ADM1266_READ_BLACKBOX, 1, &index, read_buff);
if (ret < 0)
return ret;
-
if (ret != ADM1266_BLACKBOX_SIZE)
return -EIO;

@@ -497,14 +533,14 @@ static int adm1266_probe(struct i2c_client *client)
if (ret < 0)
return ret;

- ret = adm1266_config_nvmem(data);
- if (ret < 0)
- return ret;
-
ret = pmbus_do_probe(client, &data->info);
if (ret)
return ret;

+ ret = adm1266_config_nvmem(data);
+ if (ret < 0)
+ return ret;
+
adm1266_init_debugfs(data);

return 0;

--
2.53.0