2024-03-05 20:29:51

by Heiner Kallweit

[permalink] [raw]
Subject: [PATCH RFT] i2c: i801: Call i2c_register_spd for muxed child segments

So far i2c_register_spd() is supported only on systems with up to
8 memory slots. Reason is that on a single SMBus only 8 SPD EEPROMS
can be addressed. The following patch adds support for calling
i2c_register_spd() on multiplexed SMBUS segments.

Out-of-the-box only certain ASUS Z8 systems are supported.
See mux_dmi_table[] in the i801 driver.
These systems seem to be quite rare nowadays, so I'd appreciate
if the owner of such a system could test the patch.

For each DIMM module a message like the following should appear in dmesg.
i2c i2c-11: Successfully instantiated SPD at 0x50
A response including the full dmesg log would be perfect.

For other systems with >8 memory slots, where the SMBUS is GPIO-muxed,
it should be possible to add an appropriate entry to mux_dmi_table[].
Then the patch should work as expected on such a system too.

Note: This patch is applicable only after 8821c8376993 ("i2c: smbus:
Prepare i2c_register_spd for usage on muxed segments").
This patch showed up in linux-next from March 5th 2024.

Signed-off-by: Heiner Kallweit <[email protected]>
---
drivers/i2c/busses/i2c-i801.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 8f225cd7b..4b9d04f20 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -105,6 +105,7 @@
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/i2c.h>
+#include <linux/i2c-mux.h>
#include <linux/i2c-smbus.h>
#include <linux/acpi.h>
#include <linux/io.h>
@@ -291,6 +292,7 @@ struct i801_priv {
#if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI
struct platform_device *mux_pdev;
struct gpiod_lookup_table *lookup;
+ struct notifier_block mux_notifier_block;
#endif
struct platform_device *tco_pdev;

@@ -1388,6 +1390,23 @@ static const struct dmi_system_id mux_dmi_table[] = {
{ }
};

+static int i801_notifier_call(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct i801_priv *priv = container_of(nb, struct i801_priv, mux_notifier_block);
+ struct device *dev = data;
+
+ if (action != BUS_NOTIFY_ADD_DEVICE ||
+ dev->type != &i2c_adapter_type ||
+ i2c_root_adapter(dev) != &priv->adapter)
+ return NOTIFY_DONE;
+
+ /* Call i2c_register_spd for muxed child segments */
+ i2c_register_spd(to_i2c_adapter(dev));
+
+ return NOTIFY_OK;
+}
+
/* Setup multiplexing if needed */
static void i801_add_mux(struct i801_priv *priv)
{
@@ -1425,6 +1444,9 @@ static void i801_add_mux(struct i801_priv *priv)
gpiod_add_lookup_table(lookup);
priv->lookup = lookup;

+ priv->mux_notifier_block.notifier_call = i801_notifier_call;
+ if (bus_register_notifier(&i2c_bus_type, &priv->mux_notifier_block))
+ return;
/*
* Register the mux device, we use PLATFORM_DEVID_NONE here
* because since we are referring to the GPIO chip by name we are
@@ -1443,6 +1465,7 @@ static void i801_add_mux(struct i801_priv *priv)

static void i801_del_mux(struct i801_priv *priv)
{
+ bus_unregister_notifier(&i2c_bus_type, &priv->mux_notifier_block);
platform_device_unregister(priv->mux_pdev);
gpiod_remove_lookup_table(priv->lookup);
}
--
2.44.0