diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index 8561d5a040cb..425b98e6efaa 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -3076,6 +3077,13 @@ static int i3c_master_add_of_dev(struct i3c_master_controller *master, return ret; } +#define I3C_ACPI_ADR_PID GENMASK_U64(47, 0) +/* + * Zero-based instance number of the Bus Controller to which the Target is + * connected. + */ +#define I3C_ACPI_ADR_INSTANCE GENMASK_U64(51, 48) + #ifdef CONFIG_ACPI static int i3c_master_add_acpi_dev(struct i3c_master_controller *master, struct fwnode_handle *fwnode) @@ -3083,6 +3091,7 @@ static int i3c_master_add_acpi_dev(struct i3c_master_controller *master, struct acpi_device *adev = to_acpi_device_node(fwnode); acpi_bus_address adr; u32 reg[3] = { 0 }; + u64 pid; int ret; /* @@ -3100,9 +3109,15 @@ static int i3c_master_add_acpi_dev(struct i3c_master_controller *master, adr = acpi_device_adr(adev); + /* Match the multi-bus instance number */ + if (FIELD_GET(I3C_ACPI_ADR_INSTANCE, adr) != master->instance) + return 0; + /* For I3C devices, _ADR will have the 48 bit PID of the device */ - reg[1] = upper_32_bits(adr); - reg[2] = lower_32_bits(adr); + pid = FIELD_GET(I3C_ACPI_ADR_PID, adr); + + reg[1] = upper_32_bits(pid); + reg[2] = lower_32_bits(pid); fwnode_property_read_u32(fwnode, "mipi-i3c-static-address", ®[0]); diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c index dadf049bd4b5..8b3a87d8a8bb 100644 --- a/drivers/i3c/master/mipi-i3c-hci/core.c +++ b/drivers/i3c/master/mipi-i3c-hci/core.c @@ -1142,8 +1142,10 @@ static int i3c_hci_probe(struct platform_device *pdev) * necessarily in separate contiguous sub-ranges. To avoid overlapping * mappings, provide base_regs from the parent mapping. */ - if (pdata) + if (pdata) { hci->base_regs = pdata->base_regs; + hci->master.instance = pdata->instance; + } if (!hci->base_regs) { hci->base_regs = devm_platform_ioremap_resource(pdev, 0); diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c index af9595009b03..5b8e10d05cee 100644 --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c @@ -390,6 +390,7 @@ static void mipi_i3c_hci_pci_setup_cell(struct mipi_i3c_hci_pci *hci, int idx, struct mfd_cell *cell) { data->pdata.base_regs = hci->base + hci->info->instance_offset[idx]; + data->pdata.instance = idx; data->res = DEFINE_RES_IRQ(0); diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h index f7ceec2b4477..72065715feee 100644 --- a/include/linux/i3c/master.h +++ b/include/linux/i3c/master.h @@ -536,6 +536,8 @@ struct i3c_master_controller_ops { * Bit 0: SETDASA * Bit 1: SETAASA * All other bits are reserved. + * @instance: Zero-based instance number of the Bus Controller as defined by the + * DisCo specification I3C Target Address (_ADR) Encoding * @wq: freezable workqueue which can be used by master * drivers if they need to postpone operations that need to take place * in a thread context. Typical examples are Hot Join processing which @@ -573,6 +575,7 @@ struct i3c_master_controller { } boardinfo; struct i3c_bus bus; u8 addr_method; + u8 instance; struct workqueue_struct *wq; struct work_struct hj_work; struct work_struct reg_work; diff --git a/include/linux/platform_data/mipi-i3c-hci.h b/include/linux/platform_data/mipi-i3c-hci.h index ab7395f455f9..6f61d8a02378 100644 --- a/include/linux/platform_data/mipi-i3c-hci.h +++ b/include/linux/platform_data/mipi-i3c-hci.h @@ -3,13 +3,17 @@ #define INCLUDE_PLATFORM_DATA_MIPI_I3C_HCI_H #include +#include /** * struct mipi_i3c_hci_platform_data - Platform-dependent data for mipi_i3c_hci * @base_regs: Register set base address (to support multi-bus instances) + * @instance: Zero-based instance number of the Bus Controller as defined by the + * DisCo specification I3C Target Address (_ADR) Encoding */ struct mipi_i3c_hci_platform_data { void __iomem *base_regs; + u8 instance; }; #endif