diff options
Diffstat (limited to 'drivers/iio/accel/bmc150-accel-i2c.c')
-rw-r--r-- | drivers/iio/accel/bmc150-accel-i2c.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c index 06021c8685a7..69f709319484 100644 --- a/drivers/iio/accel/bmc150-accel-i2c.c +++ b/drivers/iio/accel/bmc150-accel-i2c.c @@ -5,6 +5,7 @@ * - BMI055 * - BMA255 * - BMA250E + * - BMA222 * - BMA222E * - BMA280 * @@ -29,6 +30,8 @@ static int bmc150_accel_probe(struct i2c_client *client, i2c_check_functionality(client->adapter, I2C_FUNC_I2C) || i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK); + struct acpi_device __maybe_unused *adev; + int ret; regmap = devm_regmap_init_i2c(client, &bmc150_regmap_conf); if (IS_ERR(regmap)) { @@ -39,12 +42,47 @@ static int bmc150_accel_probe(struct i2c_client *client, if (id) name = id->name; - return bmc150_accel_core_probe(&client->dev, regmap, client->irq, name, - block_supported); + ret = bmc150_accel_core_probe(&client->dev, regmap, client->irq, name, block_supported); + if (ret) + return ret; + + /* + * Some BOSC0200 acpi_devices describe 2 accelerometers in a single ACPI + * device, try instantiating a second i2c_client for an I2cSerialBusV2 + * ACPI resource with index 1. The !id check avoids recursion when + * bmc150_accel_probe() gets called for the second client. + */ +#ifdef CONFIG_ACPI + adev = ACPI_COMPANION(&client->dev); + if (!id && adev && strcmp(acpi_device_hid(adev), "BOSC0200") == 0) { + struct i2c_board_info board_info = { + .type = "bmc150_accel", + /* + * The 2nd accel sits in the base of 2-in-1s. Note this + * name is static, as there should never be more then 1 + * BOSC0200 ACPI node with 2 accelerometers in it. + */ + .dev_name = "BOSC0200:base", + .fwnode = client->dev.fwnode, + .irq = -ENOENT, + }; + struct i2c_client *second_dev; + + second_dev = i2c_acpi_new_device(&client->dev, 1, &board_info); + if (!IS_ERR(second_dev)) + bmc150_set_second_device(second_dev); + } +#endif + + return 0; } static int bmc150_accel_remove(struct i2c_client *client) { + struct i2c_client *second_dev = bmc150_get_second_device(client); + + i2c_unregister_device(second_dev); + return bmc150_accel_core_remove(&client->dev); } @@ -54,6 +92,7 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = { {"BMI055A", bmi055}, {"BMA0255", bma255}, {"BMA250E", bma250e}, + {"BMA222", bma222}, {"BMA222E", bma222e}, {"BMA0280", bma280}, {"BOSC0200"}, @@ -66,6 +105,7 @@ static const struct i2c_device_id bmc150_accel_id[] = { {"bmi055_accel", bmi055}, {"bma255", bma255}, {"bma250e", bma250e}, + {"bma222", bma222}, {"bma222e", bma222e}, {"bma280", bma280}, {} @@ -78,6 +118,7 @@ static const struct of_device_id bmc150_accel_of_match[] = { { .compatible = "bosch,bmi055_accel" }, { .compatible = "bosch,bma255" }, { .compatible = "bosch,bma250e" }, + { .compatible = "bosch,bma222" }, { .compatible = "bosch,bma222e" }, { .compatible = "bosch,bma280" }, { }, |