On 10/09/14 20:43, Srinivas Pandruvada wrote: > On Wed, 2014-09-10 at 20:35 +0100, Jonathan Cameron wrote: >> On 02/09/14 10:30, Laurentiu Palcu wrote: >>> The following chips are either similar or have only the resolution >>> different. Hence, change this driver to support these chips too: >>> >>> BMI055 - combo chip (accelerometer part is identical to BMC150's) >>> BMA255 - identical to BMC150's accelerometer >>> BMA222E - 8 bit resolution >>> BMA250E - 10 bit resolution >>> BMA280 - 14 bit resolution >>> >>> Additionally: >>> * add bmc150_accel_match_acpi_device() function to check that the device >>> has been enumerated through ACPI; >>> * rename bmc150_accel_acpi_gpio_probe() to bmc150_accel_gpio_probe() >>> since the ACPI matching has been moved to the new function. Also, this >>> will allow for the GPIO matching to be done against a device tree too, not only >>> ACPI tree; >>> * rename bmc150_scale_info struct member 'range' to 'reg_range' to be >>> consistent with the naming convention used elsewhere in the driver >>> and declare it u8, instead of int; >>> * change CONFIG description to list all supported chips; >>> >>> Signed-off-by: Laurentiu Palcu <laurentiu.palcu@xxxxxxxxx> >> Looks fine to me, though I'm not really in a fit state to review right now. >> Srinivas, do you want to give an Ack? > Sure > > Acked-by: Srinivas Pandruvada <srinivas.pandruvada@xxxxxxxxxxxxxxx> Applied to the togreg branch of iio.git - initially pushed out as testing for the autobuilders to play. Thanks, Jonathan > >>> --- >>> >>> Changes in v5: >>> * addressed Joe's suggestion to rewrite a small portion of the code to make it >>> more readable; >>> * changed the CONFIG description according to Srinivas's advise; >>> >>> Changes in v4: >>> * address Peter's comments: see 3rd bullet in the commit's message. As a result, do >>> some re-indentation to make lines fit 80 chars; >>> >>> Changes in v3: >>> * remove the chip id macros since they were not used anywhere else and put the id >>> values directly in the chip info table; >>> * fix the unnecessary casting from const char * to char * and back; >>> >>> laurentiu >>> >>> drivers/iio/accel/Kconfig | 4 +- >>> drivers/iio/accel/bmc150-accel.c | 234 +++++++++++++++++++++++++++++---------- >>> 2 files changed, 178 insertions(+), 60 deletions(-) >>> >>> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig >>> index 01b857e..01a2151 100644 >>> --- a/drivers/iio/accel/Kconfig >>> +++ b/drivers/iio/accel/Kconfig >>> @@ -23,7 +23,9 @@ config BMC150_ACCEL >>> select IIO_BUFFER >>> select IIO_TRIGGERED_BUFFER >>> help >>> - Say yes here to build support for the Bosch BMC150 accelerometer. >>> + Say yes here to build support for the following Bosch accelerometers: >>> + BMC150, BMI055, BMA250E, BMA222E, BMA255, BMA280. >>> + >>> Currently this only supports the device via an i2c interface. >>> >>> This is a combo module with both accelerometer and magnetometer. >>> diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c >>> index 0e6566a..22c096c 100644 >>> --- a/drivers/iio/accel/bmc150-accel.c >>> +++ b/drivers/iio/accel/bmc150-accel.c >>> @@ -1,5 +1,12 @@ >>> /* >>> - * BMC150 3-axis accelerometer driver >>> + * 3-axis accelerometer driver supporting following Bosch-Sensortec chips: >>> + * - BMC150 >>> + * - BMI055 >>> + * - BMA255 >>> + * - BMA250E >>> + * - BMA222E >>> + * - BMA280 >>> + * >>> * Copyright (c) 2014, Intel Corporation. >>> * >>> * This program is free software; you can redistribute it and/or modify it >>> @@ -34,7 +41,6 @@ >>> #define BMC150_ACCEL_GPIO_NAME "bmc150_accel_int" >>> >>> #define BMC150_ACCEL_REG_CHIP_ID 0x00 >>> -#define BMC150_ACCEL_CHIP_ID_VAL 0xFA >>> >>> #define BMC150_ACCEL_REG_INT_STATUS_2 0x0B >>> #define BMC150_ACCEL_ANY_MOTION_MASK 0x07 >>> @@ -126,6 +132,18 @@ enum bmc150_power_modes { >>> BMC150_ACCEL_SLEEP_MODE_SUSPEND = 0x04, >>> }; >>> >>> +struct bmc150_scale_info { >>> + int scale; >>> + u8 reg_range; >>> +}; >>> + >>> +struct bmc150_accel_chip_info { >>> + u8 chip_id; >>> + const struct iio_chan_spec *channels; >>> + int num_channels; >>> + const struct bmc150_scale_info scale_table[4]; >>> +}; >>> + >>> struct bmc150_accel_data { >>> struct i2c_client *client; >>> struct iio_trigger *dready_trig; >>> @@ -140,6 +158,7 @@ struct bmc150_accel_data { >>> bool dready_trigger_on; >>> bool motion_trigger_on; >>> int64_t timestamp; >>> + const struct bmc150_accel_chip_info *chip_info; >>> }; >>> >>> static const struct { >>> @@ -168,16 +187,8 @@ static const struct { >>> {0x0F, 1} }; >>> >>> static const struct { >>> - int scale; >>> - int range; >>> -} bmc150_accel_scale_table[] = { {9610, BMC150_ACCEL_DEF_RANGE_2G}, >>> - {19122, BMC150_ACCEL_DEF_RANGE_4G}, >>> - {38344, BMC150_ACCEL_DEF_RANGE_8G}, >>> - {76590, BMC150_ACCEL_DEF_RANGE_16G} }; >>> - >>> -static const struct { >>> int sleep_dur; >>> - int reg_value; >>> + u8 reg_value; >>> } bmc150_accel_sleep_value_table[] = { {0, 0}, >>> {500, BMC150_ACCEL_SLEEP_500_MICRO}, >>> {1000, BMC150_ACCEL_SLEEP_1_MS}, >>> @@ -267,7 +278,7 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data) >>> } >>> >>> dev_dbg(&data->client->dev, "Chip Id %x\n", ret); >>> - if (ret != BMC150_ACCEL_CHIP_ID_VAL) { >>> + if (ret != data->chip_info->chip_id) { >>> dev_err(&data->client->dev, "Invalid chip %x\n", ret); >>> return -ENODEV; >>> } >>> @@ -541,19 +552,19 @@ static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val) >>> { >>> int ret, i; >>> >>> - for (i = 0; i < ARRAY_SIZE(bmc150_accel_scale_table); ++i) { >>> - if (bmc150_accel_scale_table[i].scale == val) { >>> + for (i = 0; i < ARRAY_SIZE(data->chip_info->scale_table); ++i) { >>> + if (data->chip_info->scale_table[i].scale == val) { >>> ret = i2c_smbus_write_byte_data( >>> - data->client, >>> - BMC150_ACCEL_REG_PMU_RANGE, >>> - bmc150_accel_scale_table[i].range); >>> + data->client, >>> + BMC150_ACCEL_REG_PMU_RANGE, >>> + data->chip_info->scale_table[i].reg_range); >>> if (ret < 0) { >>> dev_err(&data->client->dev, >>> "Error writing pmu_range\n"); >>> return ret; >>> } >>> >>> - data->range = bmc150_accel_scale_table[i].range; >>> + data->range = data->chip_info->scale_table[i].reg_range; >>> return 0; >>> } >>> } >>> @@ -580,10 +591,12 @@ static int bmc150_accel_get_temp(struct bmc150_accel_data *data, int *val) >>> return IIO_VAL_INT; >>> } >>> >>> -static int bmc150_accel_get_axis(struct bmc150_accel_data *data, int axis, >>> +static int bmc150_accel_get_axis(struct bmc150_accel_data *data, >>> + struct iio_chan_spec const *chan, >>> int *val) >>> { >>> int ret; >>> + int axis = chan->scan_index; >>> >>> mutex_lock(&data->mutex); >>> ret = bmc150_accel_set_power_state(data, true); >>> @@ -600,7 +613,8 @@ static int bmc150_accel_get_axis(struct bmc150_accel_data *data, int axis, >>> mutex_unlock(&data->mutex); >>> return ret; >>> } >>> - *val = sign_extend32(ret >> 4, 11); >>> + *val = sign_extend32(ret >> chan->scan_type.shift, >>> + chan->scan_type.realbits - 1); >>> ret = bmc150_accel_set_power_state(data, false); >>> mutex_unlock(&data->mutex); >>> if (ret < 0) >>> @@ -625,9 +639,7 @@ static int bmc150_accel_read_raw(struct iio_dev *indio_dev, >>> if (iio_buffer_enabled(indio_dev)) >>> return -EBUSY; >>> else >>> - return bmc150_accel_get_axis(data, >>> - chan->scan_index, >>> - val); >>> + return bmc150_accel_get_axis(data, chan, val); >>> default: >>> return -EINVAL; >>> } >>> @@ -646,13 +658,13 @@ static int bmc150_accel_read_raw(struct iio_dev *indio_dev, >>> case IIO_ACCEL: >>> { >>> int i; >>> + const struct bmc150_scale_info *si; >>> + int st_size = ARRAY_SIZE(data->chip_info->scale_table); >>> >>> - for (i = 0; i < ARRAY_SIZE(bmc150_accel_scale_table); >>> - ++i) { >>> - if (bmc150_accel_scale_table[i].range == >>> - data->range) { >>> - *val2 = >>> - bmc150_accel_scale_table[i].scale; >>> + for (i = 0; i < st_size; ++i) { >>> + si = &data->chip_info->scale_table[i]; >>> + if (si->reg_range == data->range) { >>> + *val2 = si->scale; >>> return IIO_VAL_INT_PLUS_MICRO; >>> } >>> } >>> @@ -840,7 +852,7 @@ static const struct iio_event_spec bmc150_accel_event = { >>> BIT(IIO_EV_INFO_PERIOD) >>> }; >>> >>> -#define BMC150_ACCEL_CHANNEL(_axis) { \ >>> +#define BMC150_ACCEL_CHANNEL(_axis, bits) { \ >>> .type = IIO_ACCEL, \ >>> .modified = 1, \ >>> .channel2 = IIO_MOD_##_axis, \ >>> @@ -850,26 +862,101 @@ static const struct iio_event_spec bmc150_accel_event = { >>> .scan_index = AXIS_##_axis, \ >>> .scan_type = { \ >>> .sign = 's', \ >>> - .realbits = 12, \ >>> + .realbits = (bits), \ >>> .storagebits = 16, \ >>> - .shift = 4, \ >>> + .shift = 16 - (bits), \ >>> }, \ >>> .event_spec = &bmc150_accel_event, \ >>> .num_event_specs = 1 \ >>> } >>> >>> -static const struct iio_chan_spec bmc150_accel_channels[] = { >>> - { >>> - .type = IIO_TEMP, >>> - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | >>> - BIT(IIO_CHAN_INFO_SCALE) | >>> - BIT(IIO_CHAN_INFO_OFFSET), >>> - .scan_index = -1, >>> +#define BMC150_ACCEL_CHANNELS(bits) { \ >>> + { \ >>> + .type = IIO_TEMP, \ >>> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ >>> + BIT(IIO_CHAN_INFO_SCALE) | \ >>> + BIT(IIO_CHAN_INFO_OFFSET), \ >>> + .scan_index = -1, \ >>> + }, \ >>> + BMC150_ACCEL_CHANNEL(X, bits), \ >>> + BMC150_ACCEL_CHANNEL(Y, bits), \ >>> + BMC150_ACCEL_CHANNEL(Z, bits), \ >>> + IIO_CHAN_SOFT_TIMESTAMP(3), \ >>> +} >>> + >>> +static const struct iio_chan_spec bma222e_accel_channels[] = >>> + BMC150_ACCEL_CHANNELS(8); >>> +static const struct iio_chan_spec bma250e_accel_channels[] = >>> + BMC150_ACCEL_CHANNELS(10); >>> +static const struct iio_chan_spec bmc150_accel_channels[] = >>> + BMC150_ACCEL_CHANNELS(12); >>> +static const struct iio_chan_spec bma280_accel_channels[] = >>> + BMC150_ACCEL_CHANNELS(14); >>> + >>> +enum { >>> + bmc150, >>> + bmi055, >>> + bma255, >>> + bma250e, >>> + bma222e, >>> + bma280, >>> +}; >>> + >>> +static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = { >>> + [bmc150] = { >>> + .chip_id = 0xFA, >>> + .channels = bmc150_accel_channels, >>> + .num_channels = ARRAY_SIZE(bmc150_accel_channels), >>> + .scale_table = { {9610, BMC150_ACCEL_DEF_RANGE_2G}, >>> + {19122, BMC150_ACCEL_DEF_RANGE_4G}, >>> + {38344, BMC150_ACCEL_DEF_RANGE_8G}, >>> + {76590, BMC150_ACCEL_DEF_RANGE_16G} }, >>> + }, >>> + [bmi055] = { >>> + .chip_id = 0xFA, >>> + .channels = bmc150_accel_channels, >>> + .num_channels = ARRAY_SIZE(bmc150_accel_channels), >>> + .scale_table = { {9610, BMC150_ACCEL_DEF_RANGE_2G}, >>> + {19122, BMC150_ACCEL_DEF_RANGE_4G}, >>> + {38344, BMC150_ACCEL_DEF_RANGE_8G}, >>> + {76590, BMC150_ACCEL_DEF_RANGE_16G} }, >>> + }, >>> + [bma255] = { >>> + .chip_id = 0xFA, >>> + .channels = bmc150_accel_channels, >>> + .num_channels = ARRAY_SIZE(bmc150_accel_channels), >>> + .scale_table = { {9610, BMC150_ACCEL_DEF_RANGE_2G}, >>> + {19122, BMC150_ACCEL_DEF_RANGE_4G}, >>> + {38344, BMC150_ACCEL_DEF_RANGE_8G}, >>> + {76590, BMC150_ACCEL_DEF_RANGE_16G} }, >>> + }, >>> + [bma250e] = { >>> + .chip_id = 0xF9, >>> + .channels = bma250e_accel_channels, >>> + .num_channels = ARRAY_SIZE(bma250e_accel_channels), >>> + .scale_table = { {38344, BMC150_ACCEL_DEF_RANGE_2G}, >>> + {76590, BMC150_ACCEL_DEF_RANGE_4G}, >>> + {153277, BMC150_ACCEL_DEF_RANGE_8G}, >>> + {306457, BMC150_ACCEL_DEF_RANGE_16G} }, >>> + }, >>> + [bma222e] = { >>> + .chip_id = 0xF8, >>> + .channels = bma222e_accel_channels, >>> + .num_channels = ARRAY_SIZE(bma222e_accel_channels), >>> + .scale_table = { {153277, BMC150_ACCEL_DEF_RANGE_2G}, >>> + {306457, BMC150_ACCEL_DEF_RANGE_4G}, >>> + {612915, BMC150_ACCEL_DEF_RANGE_8G}, >>> + {1225831, BMC150_ACCEL_DEF_RANGE_16G} }, >>> + }, >>> + [bma280] = { >>> + .chip_id = 0xFB, >>> + .channels = bma280_accel_channels, >>> + .num_channels = ARRAY_SIZE(bma280_accel_channels), >>> + .scale_table = { {2392, BMC150_ACCEL_DEF_RANGE_2G}, >>> + {4785, BMC150_ACCEL_DEF_RANGE_4G}, >>> + {9581, BMC150_ACCEL_DEF_RANGE_8G}, >>> + {19152, BMC150_ACCEL_DEF_RANGE_16G} }, >>> }, >>> - BMC150_ACCEL_CHANNEL(X), >>> - BMC150_ACCEL_CHANNEL(Y), >>> - BMC150_ACCEL_CHANNEL(Z), >>> - IIO_CHAN_SOFT_TIMESTAMP(3), >>> }; >>> >>> static const struct iio_info bmc150_accel_info = { >>> @@ -1040,10 +1127,23 @@ static irqreturn_t bmc150_accel_data_rdy_trig_poll(int irq, void *private) >>> return IRQ_HANDLED; >>> } >>> >>> -static int bmc150_accel_acpi_gpio_probe(struct i2c_client *client, >>> - struct bmc150_accel_data *data) >>> +static const char *bmc150_accel_match_acpi_device(struct device *dev, int *data) >>> { >>> const struct acpi_device_id *id; >>> + >>> + id = acpi_match_device(dev->driver->acpi_match_table, dev); >>> + >>> + if (!id) >>> + return NULL; >>> + >>> + *data = (int) id->driver_data; >>> + >>> + return dev_name(dev); >>> +} >>> + >>> +static int bmc150_accel_gpio_probe(struct i2c_client *client, >>> + struct bmc150_accel_data *data) >>> +{ >>> struct device *dev; >>> struct gpio_desc *gpio; >>> int ret; >>> @@ -1052,17 +1152,11 @@ static int bmc150_accel_acpi_gpio_probe(struct i2c_client *client, >>> return -EINVAL; >>> >>> dev = &client->dev; >>> - if (!ACPI_HANDLE(dev)) >>> - return -ENODEV; >>> - >>> - id = acpi_match_device(dev->driver->acpi_match_table, dev); >>> - if (!id) >>> - return -ENODEV; >>> >>> /* data ready gpio interrupt pin */ >>> gpio = devm_gpiod_get_index(dev, BMC150_ACCEL_GPIO_NAME, 0); >>> if (IS_ERR(gpio)) { >>> - dev_err(dev, "Failed: acpi gpio get index\n"); >>> + dev_err(dev, "Failed: gpio get index\n"); >>> return PTR_ERR(gpio); >>> } >>> >>> @@ -1083,6 +1177,8 @@ static int bmc150_accel_probe(struct i2c_client *client, >>> struct bmc150_accel_data *data; >>> struct iio_dev *indio_dev; >>> int ret; >>> + const char *name = NULL; >>> + int chip_id = 0; >>> >>> indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); >>> if (!indio_dev) >>> @@ -1092,6 +1188,16 @@ static int bmc150_accel_probe(struct i2c_client *client, >>> i2c_set_clientdata(client, indio_dev); >>> data->client = client; >>> >>> + if (id) { >>> + name = id->name; >>> + chip_id = id->driver_data; >>> + } >>> + >>> + if (ACPI_HANDLE(&client->dev)) >>> + name = bmc150_accel_match_acpi_device(&client->dev, &chip_id); >>> + >>> + data->chip_info = &bmc150_accel_chip_info_tbl[chip_id]; >>> + >>> ret = bmc150_accel_chip_init(data); >>> if (ret < 0) >>> return ret; >>> @@ -1099,14 +1205,14 @@ static int bmc150_accel_probe(struct i2c_client *client, >>> mutex_init(&data->mutex); >>> >>> indio_dev->dev.parent = &client->dev; >>> - indio_dev->channels = bmc150_accel_channels; >>> - indio_dev->num_channels = ARRAY_SIZE(bmc150_accel_channels); >>> - indio_dev->name = BMC150_ACCEL_DRV_NAME; >>> + indio_dev->channels = data->chip_info->channels; >>> + indio_dev->num_channels = data->chip_info->num_channels; >>> + indio_dev->name = name; >>> indio_dev->modes = INDIO_DIRECT_MODE; >>> indio_dev->info = &bmc150_accel_info; >>> >>> if (client->irq < 0) >>> - client->irq = bmc150_accel_acpi_gpio_probe(client, data); >>> + client->irq = bmc150_accel_gpio_probe(client, data); >>> >>> if (client->irq >= 0) { >>> ret = devm_request_threaded_irq( >>> @@ -1284,14 +1390,24 @@ static const struct dev_pm_ops bmc150_accel_pm_ops = { >>> }; >>> >>> static const struct acpi_device_id bmc150_accel_acpi_match[] = { >>> - {"BSBA0150", 0}, >>> - {"BMC150A", 0}, >>> + {"BSBA0150", bmc150}, >>> + {"BMC150A", bmc150}, >>> + {"BMI055A", bmi055}, >>> + {"BMA0255", bma255}, >>> + {"BMA250E", bma250e}, >>> + {"BMA222E", bma222e}, >>> + {"BMA0280", bma280}, >>> { }, >>> }; >>> MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match); >>> >>> static const struct i2c_device_id bmc150_accel_id[] = { >>> - {"bmc150_accel", 0}, >>> + {"bmc150_accel", bmc150}, >>> + {"bmi055_accel", bmi055}, >>> + {"bma255", bma255}, >>> + {"bma250e", bma250e}, >>> + {"bma222e", bma222e}, >>> + {"bma280", bma280}, >>> {} >>> }; >>> >>> > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-iio" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html