@@ -20,6 +20,8 @@
#define IRQ_RESOURCE_GPIO 1
#define IRQ_RESOURCE_APIC 2
+#define PASS_FWNODE BIT(2)
+
struct i2c_inst_data {
const char *type;
unsigned int flags;
@@ -93,6 +95,10 @@ static int i2c_multi_inst_probe(struct platform_device *pdev)
snprintf(name, sizeof(name), "%s-%s.%d", dev_name(dev),
inst_data[i].type, i);
board_info.dev_name = name;
+
+ if (inst_data[i].flags & PASS_FWNODE)
+ board_info.fwnode = dev->fwnode;
+
switch (inst_data[i].flags & IRQ_RESOURCE_TYPE) {
case IRQ_RESOURCE_GPIO:
ret = acpi_dev_gpio_irq_get(adev, inst_data[i].irq_idx);
In some cases the driver for the i2c_client-s which i2c-multi-instantiate instantiates may need access some fields / methods from to the ACPI fwnode for which i2c_clients are being instantiated. An example of this are CPLM3218 ACPI device-s. These contain CPM0 and CPM1 packages with various information (e.g. register init values) which the driver needs. Passing the fwnode through the i2c_board_info struct also gives the i2c-core access to it, and if we do not pass an IRQ then the i2c-core will use the fwnode to get an IRQ, see i2c_acpi_get_irq(). This is a problem when there is only an IRQ for 1 of the clients described in the ACPI device we are instantiating clients for. If we unconditionally pass the fwnode, then i2c_acpi_get_irq() will assign the same IRQ to all clients instantiated, leading to kernel-oopses like this (BSG1160 device): [ 27.340557] genirq: Flags mismatch irq 76. 00002001 (bmc150_magn_event) vs. 00000001 (bmc150_accel_event) [ 27.340567] Call Trace: ... So we cannot simply always pass the fwnode. This commit adds a PASS_FWNODE flag, which can be used to pass the fwnode in cases where we do not have the IRQ problem and the driver for the instantiated client(s) needs access to the fwnode. Signed-off-by: Hans de Goede <hdegoede@redhat.com> --- drivers/platform/x86/i2c-multi-instantiate.c | 6 ++++++ 1 file changed, 6 insertions(+)