[PATCH v3 8/9] mfd: cgbc: Add virtual storage devices on the virtual I2C bus

From: Thomas Richard (congatec GmbH)

Date: Fri Sep 11 2026 - 14:58:24 EST


Add support for virtual storage devices exposed by the Board Controller
on its virtual I2C bus. There are two device types: EEPROM for persistent
storage and RAM for non-persistent storage:
- Secure Data EEPROM (64 bytes, RO): static and dynamic board info
- BIOS EEPROM (32 bytes, RW): reserved for BIOS applications
- BC EEPROM (32 bytes, RO): Board Controller operational params
- User EEPROM (32 bytes, RW): user applications
- BIOS RAM (32 bytes, RW): reserved for BIOS applications
- BC RAM (8 bytes, RO): Board Controller operational params
- User RAM (16 bytes, RW): user applications

Use the at24 driver with the 24c01 entry (the most generic one) for all
virtual storage devices, customizing parameters via software_node
properties (size, pagesize, read-only flag, label).

Signed-off-by: Thomas Richard (congatec GmbH) <thomas.richard@xxxxxxxxxxx>
---
drivers/mfd/cgbc-core.c | 129 +++++++++++++++++++++++++++++++++
include/linux/platform_data/i2c-cgbc.h | 4 +
2 files changed, 133 insertions(+)

diff --git a/drivers/mfd/cgbc-core.c b/drivers/mfd/cgbc-core.c
index 90fa0e657385..097b7309a400 100644
--- a/drivers/mfd/cgbc-core.c
+++ b/drivers/mfd/cgbc-core.c
@@ -13,11 +13,13 @@

#include <linux/dmi.h>
#include <linux/iopoll.h>
+#include <linux/i2c.h>
#include <linux/mfd/cgbc.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/platform_data/i2c-cgbc.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/sysfs.h>

#define CGBC_IO_SESSION_BASE 0x0E20
@@ -56,6 +58,131 @@

static struct platform_device *cgbc_pdev;

+static const struct property_entry cgbc_secure_data_eeprom_props[] = {
+ PROPERTY_ENTRY_U32("size", 64),
+ PROPERTY_ENTRY_U32("pagesize", 1),
+ PROPERTY_ENTRY_BOOL("read-only"),
+ PROPERTY_ENTRY_STRING("label", "cgbc-secure-data-eeprom"),
+ { }
+};
+
+static const struct software_node cgbc_secure_data_eeprom_node = {
+ .properties = cgbc_secure_data_eeprom_props,
+};
+
+static const struct property_entry cgbc_bc_eeprom_props[] = {
+ PROPERTY_ENTRY_U32("size", 32),
+ PROPERTY_ENTRY_U32("pagesize", 1),
+ PROPERTY_ENTRY_BOOL("read-only"),
+ PROPERTY_ENTRY_STRING("label", "cgbc-bc-eeprom"),
+ { }
+};
+
+static const struct software_node cgbc_bc_eeprom_node = {
+ .properties = cgbc_bc_eeprom_props,
+};
+
+static const struct property_entry cgbc_user_eeprom_props[] = {
+ PROPERTY_ENTRY_U32("size", 32),
+ PROPERTY_ENTRY_U32("pagesize", 1),
+ PROPERTY_ENTRY_STRING("label", "cgbc-user-eeprom"),
+ { }
+};
+
+static const struct software_node cgbc_user_eeprom_node = {
+ .properties = cgbc_user_eeprom_props,
+};
+
+static const struct property_entry cgbc_bios_eeprom_props[] = {
+ PROPERTY_ENTRY_U32("size", 32),
+ PROPERTY_ENTRY_U32("pagesize", 1),
+ PROPERTY_ENTRY_STRING("label", "cgbc-bios-eeprom"),
+ { }
+};
+
+static const struct software_node cgbc_bios_eeprom_node = {
+ .properties = cgbc_bios_eeprom_props,
+};
+
+static const struct property_entry cgbc_bc_ram_props[] = {
+ PROPERTY_ENTRY_U32("size", 8),
+ PROPERTY_ENTRY_U32("pagesize", 1),
+ PROPERTY_ENTRY_BOOL("read-only"),
+ PROPERTY_ENTRY_STRING("label", "cgbc-bc-ram"),
+ { }
+};
+
+static const struct software_node cgbc_bc_ram_node = {
+ .properties = cgbc_bc_ram_props,
+};
+
+static const struct property_entry cgbc_user_ram_props[] = {
+ PROPERTY_ENTRY_U32("size", 16),
+ PROPERTY_ENTRY_U32("pagesize", 1),
+ PROPERTY_ENTRY_STRING("label", "cgbc-user-ram"),
+ { }
+};
+
+static const struct software_node cgbc_user_ram_node = {
+ .properties = cgbc_user_ram_props,
+};
+
+static const struct property_entry cgbc_bios_ram_props[] = {
+ PROPERTY_ENTRY_U32("size", 32),
+ PROPERTY_ENTRY_U32("pagesize", 1),
+ PROPERTY_ENTRY_STRING("label", "cgbc-bios-ram"),
+ { }
+};
+
+static const struct software_node cgbc_bios_ram_node = {
+ .properties = cgbc_bios_ram_props,
+};
+
+static const struct i2c_board_info cgbc_i2c_i2cv_board_info[] = {
+ {
+ .type = "24c01",
+ .addr = 0x40,
+ .dev_name = "cgbc-secure-data-eeprom",
+ .swnode = &cgbc_secure_data_eeprom_node,
+ },
+ {
+ .type = "24c01",
+ .addr = 0x48,
+ .dev_name = "cgbc-bc-eeprom",
+ .swnode = &cgbc_bc_eeprom_node,
+ },
+ {
+ .type = "24c01",
+ .addr = 0x50,
+ .dev_name = "cgbc-user-eeprom",
+ .swnode = &cgbc_user_eeprom_node,
+ },
+ {
+ .type = "24c01",
+ .addr = 0x58,
+ .dev_name = "cgbc-bios-eeprom",
+ .swnode = &cgbc_bios_eeprom_node,
+ },
+ {
+ .type = "24c01",
+ .addr = 0x60,
+ .dev_name = "cgbc-bc-ram",
+ .swnode = &cgbc_bc_ram_node,
+ },
+ {
+ .type = "24c01",
+ .addr = 0x68,
+ .dev_name = "cgbc-user-ram",
+ .swnode = &cgbc_user_ram_node,
+ },
+ {
+ .type = "24c01",
+ .addr = 0x70,
+ .dev_name = "cgbc-bios-ram",
+ .swnode = &cgbc_bios_ram_node,
+ }
+};
+
static const struct cgbc_i2c_platform_data cgbc_i2c_i2c0_pdata = {
.name = "cgbc-i2c0",
.cgbc_bus_id = 0,
@@ -70,6 +197,8 @@ static const struct cgbc_i2c_platform_data cgbc_i2c_i2cv_pdata = {
.name = "cgbc-i2cv",
.cgbc_bus_id = 3,
.fixed_freq = true,
+ .devices = cgbc_i2c_i2cv_board_info,
+ .nb_devices = ARRAY_SIZE(cgbc_i2c_i2cv_board_info),
};

static const struct mfd_cell cgbc_devs[] = {
diff --git a/include/linux/platform_data/i2c-cgbc.h b/include/linux/platform_data/i2c-cgbc.h
index 224926c12070..5f20503ce858 100644
--- a/include/linux/platform_data/i2c-cgbc.h
+++ b/include/linux/platform_data/i2c-cgbc.h
@@ -14,11 +14,15 @@
* @name: I2C adapter name
* @cgbc_bus_id: I2C bus ID (from Board Controller point of view)
* @fixed_freq: I2C bus has a fixed frequency
+ * @nb_devices: number of devices to add when the driver is probed
+ * @devices: devices to add
*/
struct cgbc_i2c_platform_data {
const char *name;
int cgbc_bus_id;
bool fixed_freq;
+ int nb_devices;
+ struct i2c_board_info const *devices;
};

#endif /* _LINUX_I2C_CGBC_H */

--
2.53.0