aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio/accel/bmc150-accel-i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/accel/bmc150-accel-i2c.c')
-rw-r--r--drivers/iio/accel/bmc150-accel-i2c.c45
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" },
{ },