On Fri, 2018-06-08 at 23:11 +0200, Hans de Goede wrote: > Normally i2c_new_device will check that a client at the same address > does > not already exists. > > On systems with ACPI instantiated i2c-clients, normally there is 1 > fw_node > per i2c-device and that fw-node contains 1 I2cSerialBus resource for > that 1 > i2c-device. > > But in some rare cases the manufacturer has decided to describe > multiple > i2c-devices in a single ACPI fwnode with multiple I2cSerialBus > resources. > > After an earlier attempt to fix this in the i2c-core which resulted in > a > lot of extra code to support this corner-case it was decided to go for > a > different approach. The next patch in this series introduces a new > special > i2c-multi-instantiate driver which can be build as a module and which > will > bind to the i2c-client which gets instantiated by the core for the > first > I2cSerialBus resource in the fwnode. > > This driver will instantiate a new i2c-client per I2cSerialBus > resource, > using the driver_data from the acpi_device_id it is binding to to tell > it > which chip-type (and optional irq-resource) to use when instantiating. > > Since it binds to the core instantiated i2c-client and claims the > acpi_device_id of the fwnode, it also needs to instantiate a new i2c- > client > for the first I2cSerialBus resource uses the chip-id for the real > driver, > so that that can bind to the i2c-device described by the first > I2cSerialBus > resource, this requires the new I2C_CLIENT_IGNORE_BUSY flag. > > Note this means that we will be instantiating 2 i2c_client-s for the > first > I2cSerialBus resource, this is not pretty, but since the multi- > instantiate > driver does exactly 0 i2c-transfers this is not a problem. > You forgot to Cc Heikki. > Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> > --- > drivers/i2c/i2c-core-base.c | 11 +++++++---- > include/linux/i2c.h | 3 +++ > 2 files changed, 10 insertions(+), 4 deletions(-) > > diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c > index a17f46a95f73..77d70b611bc5 100644 > --- a/drivers/i2c/i2c-core-base.c > +++ b/drivers/i2c/i2c-core-base.c > @@ -721,7 +721,7 @@ i2c_new_device(struct i2c_adapter *adap, struct > i2c_board_info const *info) > if (info->archdata) > client->dev.archdata = *info->archdata; > > - client->flags = info->flags; > + client->flags = info->flags & ~I2C_CLIENT_IGNORE_BUSY; > client->addr = info->addr; > > client->irq = info->irq; > @@ -739,9 +739,12 @@ i2c_new_device(struct i2c_adapter *adap, struct > i2c_board_info const *info) > } > > /* Check for address business */ > - status = i2c_check_addr_busy(adap, > i2c_encode_flags_to_addr(client)); > - if (status) > - goto out_err; > + if (!(info->flags & I2C_CLIENT_IGNORE_BUSY)) { > + status = i2c_check_addr_busy(adap, > + i2c_encode_flags_to_addr > (client)); > + if (status) > + goto out_err; > + } > > client->dev.parent = &client->adapter->dev; > client->dev.bus = &i2c_bus_type; > diff --git a/include/linux/i2c.h b/include/linux/i2c.h > index 44ad14e016b5..3ad73cf1b187 100644 > --- a/include/linux/i2c.h > +++ b/include/linux/i2c.h > @@ -775,6 +775,9 @@ i2c_unlock_adapter(struct i2c_adapter *adapter) > #define I2C_CLIENT_SLAVE 0x20 /* we are the slave */ > #define I2C_CLIENT_HOST_NOTIFY 0x40 /* We want to use > I2C host notify */ > #define I2C_CLIENT_WAKE 0x80 /* for board_info; > true iff can wake */ > +#define I2C_CLIENT_IGNORE_BUSY 0x100 /* For board_info; > skip busy check */ > + /* Do NOT use, reserved for > use by */ > + /* drv/i2c/i2c-multi- > instantiate.c */ > #define I2C_CLIENT_SCCB 0x9000 /* Use > Omnivision SCCB protocol */ > /* Must match > I2C_M_STOP|IGNORE_NAK */ > -- Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx> Intel Finland Oy