Skip to content
Snippets Groups Projects
Commit 52ae7c70 authored by Stephan Gerhold's avatar Stephan Gerhold Committed by Jonathan Cameron
Browse files

iio: accel: bmc150: Add support for BMC156


BMC156 is another accelerometer that works just fine with the bmc150-accel
driver. It's very similar to BMC150 (also a accelerometer + magnetometer
combo) but with only one accelerometer interrupt pin. It would make sense
if only INT1 was exposed but someone at Bosch decided to only have an
INT2 pin.

Try to deal with this by making use of the INT2 support introduced
in the previous commit and force using INT2 for BMC156. To detect
that we need to bring up a simplified version of the previous type IDs.

Note that unlike the type IDs removed in commit c06a6aba
("iio: accel: bmc150: Drop misleading/duplicate chip identifiers")
here I only add one for the special case of BMC156. Everything else
still happens by reading the CHIP_ID register since the chip type
information often is not accurate in ACPI tables.

Tested-by: Nikita Travkin <nikita@trvn.ru> # BMC156
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarStephan Gerhold <stephan@gerhold.net>
Link: https://lore.kernel.org/r/20210802155657.102766-5-stephan@gerhold.net


Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent 73d672e6
No related branches found
No related tags found
No related merge requests found
...@@ -143,10 +143,11 @@ config BMC150_ACCEL ...@@ -143,10 +143,11 @@ config BMC150_ACCEL
select BMC150_ACCEL_SPI if SPI select BMC150_ACCEL_SPI if SPI
help help
Say yes here to build support for the following Bosch accelerometers: Say yes here to build support for the following Bosch accelerometers:
BMA222, BMA222E, BMA250E, BMA253, BMA254, BMA255, BMA280, BMC150, BMI055. BMA222, BMA222E, BMA250E, BMA253, BMA254, BMA255, BMA280, BMC150, BMC156
BMI055.
Note that some of these are combo modules: Note that some of these are combo modules:
- BMC150: accelerometer and magnetometer - BMC150/BMC156: accelerometer and magnetometer
- BMI055: accelerometer and gyroscope - BMI055: accelerometer and gyroscope
This driver is only implementing accelerometer part, which has This driver is only implementing accelerometer part, which has
......
...@@ -553,7 +553,8 @@ static void bmc150_accel_interrupts_setup(struct iio_dev *indio_dev, ...@@ -553,7 +553,8 @@ static void bmc150_accel_interrupts_setup(struct iio_dev *indio_dev,
* Without interrupt-names, we assume the irq belongs to INT1. * Without interrupt-names, we assume the irq belongs to INT1.
*/ */
irq_info = bmc150_accel_interrupts_int1; irq_info = bmc150_accel_interrupts_int1;
if (irq == of_irq_get_byname(dev->of_node, "INT2")) if (data->type == BOSCH_BMC156 ||
irq == of_irq_get_byname(dev->of_node, "INT2"))
irq_info = bmc150_accel_interrupts_int2; irq_info = bmc150_accel_interrupts_int2;
for (i = 0; i < BMC150_ACCEL_INTERRUPTS; i++) for (i = 0; i < BMC150_ACCEL_INTERRUPTS; i++)
...@@ -1174,7 +1175,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = { ...@@ -1174,7 +1175,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
{306458, BMC150_ACCEL_DEF_RANGE_16G} }, {306458, BMC150_ACCEL_DEF_RANGE_16G} },
}, },
{ {
.name = "BMA253/BMA254/BMA255/BMC150/BMI055", .name = "BMA253/BMA254/BMA255/BMC150/BMC156/BMI055",
.chip_id = 0xFA, .chip_id = 0xFA,
.channels = bmc150_accel_channels, .channels = bmc150_accel_channels,
.num_channels = ARRAY_SIZE(bmc150_accel_channels), .num_channels = ARRAY_SIZE(bmc150_accel_channels),
...@@ -1661,7 +1662,8 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data) ...@@ -1661,7 +1662,8 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
} }
int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
const char *name, bool block_supported) enum bmc150_type type, const char *name,
bool block_supported)
{ {
const struct attribute **fifo_attrs; const struct attribute **fifo_attrs;
struct bmc150_accel_data *data; struct bmc150_accel_data *data;
...@@ -1676,6 +1678,7 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, ...@@ -1676,6 +1678,7 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
dev_set_drvdata(dev, indio_dev); dev_set_drvdata(dev, indio_dev);
data->regmap = regmap; data->regmap = regmap;
data->type = type;
if (!bmc150_apply_acpi_orientation(dev, &data->orientation)) { if (!bmc150_apply_acpi_orientation(dev, &data->orientation)) {
ret = iio_read_mount_matrix(dev, &data->orientation); ret = iio_read_mount_matrix(dev, &data->orientation);
......
...@@ -176,6 +176,7 @@ static int bmc150_accel_probe(struct i2c_client *client, ...@@ -176,6 +176,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
{ {
struct regmap *regmap; struct regmap *regmap;
const char *name = NULL; const char *name = NULL;
enum bmc150_type type = BOSCH_UNKNOWN;
bool block_supported = bool block_supported =
i2c_check_functionality(client->adapter, I2C_FUNC_I2C) || i2c_check_functionality(client->adapter, I2C_FUNC_I2C) ||
i2c_check_functionality(client->adapter, i2c_check_functionality(client->adapter,
...@@ -188,10 +189,13 @@ static int bmc150_accel_probe(struct i2c_client *client, ...@@ -188,10 +189,13 @@ static int bmc150_accel_probe(struct i2c_client *client,
return PTR_ERR(regmap); return PTR_ERR(regmap);
} }
if (id) if (id) {
name = id->name; name = id->name;
type = id->driver_data;
}
ret = bmc150_accel_core_probe(&client->dev, regmap, client->irq, name, block_supported); ret = bmc150_accel_core_probe(&client->dev, regmap, client->irq,
type, name, block_supported);
if (ret) if (ret)
return ret; return ret;
...@@ -236,6 +240,7 @@ static const struct i2c_device_id bmc150_accel_id[] = { ...@@ -236,6 +240,7 @@ static const struct i2c_device_id bmc150_accel_id[] = {
{"bma255"}, {"bma255"},
{"bma280"}, {"bma280"},
{"bmc150_accel"}, {"bmc150_accel"},
{"bmc156_accel", BOSCH_BMC156},
{"bmi055_accel"}, {"bmi055_accel"},
{} {}
}; };
...@@ -251,6 +256,7 @@ static const struct of_device_id bmc150_accel_of_match[] = { ...@@ -251,6 +256,7 @@ static const struct of_device_id bmc150_accel_of_match[] = {
{ .compatible = "bosch,bma255" }, { .compatible = "bosch,bma255" },
{ .compatible = "bosch,bma280" }, { .compatible = "bosch,bma280" },
{ .compatible = "bosch,bmc150_accel" }, { .compatible = "bosch,bmc150_accel" },
{ .compatible = "bosch,bmc156_accel" },
{ .compatible = "bosch,bmi055_accel" }, { .compatible = "bosch,bmi055_accel" },
{ }, { },
}; };
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
static int bmc150_accel_probe(struct spi_device *spi) static int bmc150_accel_probe(struct spi_device *spi)
{ {
struct regmap *regmap; struct regmap *regmap;
const char *name = NULL;
enum bmc150_type type = BOSCH_UNKNOWN;
const struct spi_device_id *id = spi_get_device_id(spi); const struct spi_device_id *id = spi_get_device_id(spi);
regmap = devm_regmap_init_spi(spi, &bmc150_regmap_conf); regmap = devm_regmap_init_spi(spi, &bmc150_regmap_conf);
...@@ -24,7 +26,12 @@ static int bmc150_accel_probe(struct spi_device *spi) ...@@ -24,7 +26,12 @@ static int bmc150_accel_probe(struct spi_device *spi)
return PTR_ERR(regmap); return PTR_ERR(regmap);
} }
return bmc150_accel_core_probe(&spi->dev, regmap, spi->irq, id->name, if (id) {
name = id->name;
type = id->driver_data;
}
return bmc150_accel_core_probe(&spi->dev, regmap, spi->irq, type, name,
true); true);
} }
...@@ -54,6 +61,7 @@ static const struct spi_device_id bmc150_accel_id[] = { ...@@ -54,6 +61,7 @@ static const struct spi_device_id bmc150_accel_id[] = {
{"bma255"}, {"bma255"},
{"bma280"}, {"bma280"},
{"bmc150_accel"}, {"bmc150_accel"},
{"bmc156_accel", BOSCH_BMC156},
{"bmi055_accel"}, {"bmi055_accel"},
{} {}
}; };
......
...@@ -13,6 +13,22 @@ struct i2c_client; ...@@ -13,6 +13,22 @@ struct i2c_client;
struct bmc150_accel_chip_info; struct bmc150_accel_chip_info;
struct bmc150_accel_interrupt_info; struct bmc150_accel_interrupt_info;
/*
* We can often guess better than "UNKNOWN" based on the device IDs
* but unfortunately this information is not always accurate. There are some
* devices where ACPI firmware specifies an ID like "BMA250E" when the device
* actually has a BMA222E. The driver attempts to detect those by reading the
* chip ID from the registers but this information is not always enough either.
*
* Therefore, this enum should be only used when the chip ID detection is not
* enough and we can be reasonably sure that the device IDs are reliable
* in practice (e.g. for device tree platforms).
*/
enum bmc150_type {
BOSCH_UNKNOWN,
BOSCH_BMC156,
};
struct bmc150_accel_interrupt { struct bmc150_accel_interrupt {
const struct bmc150_accel_interrupt_info *info; const struct bmc150_accel_interrupt_info *info;
atomic_t users; atomic_t users;
...@@ -62,6 +78,7 @@ struct bmc150_accel_data { ...@@ -62,6 +78,7 @@ struct bmc150_accel_data {
int ev_enable_state; int ev_enable_state;
int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */ int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */
const struct bmc150_accel_chip_info *chip_info; const struct bmc150_accel_chip_info *chip_info;
enum bmc150_type type;
struct i2c_client *second_device; struct i2c_client *second_device;
void (*resume_callback)(struct device *dev); void (*resume_callback)(struct device *dev);
struct delayed_work resume_work; struct delayed_work resume_work;
...@@ -69,7 +86,8 @@ struct bmc150_accel_data { ...@@ -69,7 +86,8 @@ struct bmc150_accel_data {
}; };
int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
const char *name, bool block_supported); enum bmc150_type type, const char *name,
bool block_supported);
int bmc150_accel_core_remove(struct device *dev); int bmc150_accel_core_remove(struct device *dev);
extern const struct dev_pm_ops bmc150_accel_pm_ops; extern const struct dev_pm_ops bmc150_accel_pm_ops;
extern const struct regmap_config bmc150_regmap_conf; extern const struct regmap_config bmc150_regmap_conf;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment