Hi Peter,

On Thu, Aug 28, 2014 at 11:26:19AM +0200, Peter Meerwald 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
> > BMA222 - 8 bit resolution
> > BMA250 - 10 bit resolution
> > BMA280 - 14 bit resolution
> 
> I recently proposed to add BMA250 support to the BMA180 IIO driver; 
> according to the datasheet, the chip ID value for the BMA180 and (!) 
> BMA250 is 0x03, while your patch claims that it is 0xf9
Actually, this driver is for BMA250E and BMA222E. I didn't even notice
there are other versions of these chips... :/ That's why I ignored the
'E' in the IDs. I will fix the comments and the other IDs in the next
patchset version.

I looked closer now, on the Bosch-Sensortec web page and, apparently,
BMA222 and BMA250 are older versions, 'not recommended for new designs'.
> 
> see 
> http://ae-bst.resource.bosch.com/media/products/dokumente/bma250/bst-bma250-ds002-05.pdf,
>  
> page 37 (and it really is on my chip :)
> 
> the question is whether to add further Bosch accelerometer chips to the 
> BMA180 driver or the BMC150 driver and what explains the different chip IDs
Clearly, in terms of register compatibility, the chips I mentioned are
completely compatible with BMC150 accelerometer, AFAICS, except for the
data registers which have different resolutions. However, the 'non-E'
versions are a little different and they seem to match BMA180.

laurentiu
> 
> need to check if these are really so similar and what driver provides /
> exposes more features
> 
> p.
>  
> > 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;
> > 
> > Signed-off-by: Laurentiu Palcu <[email protected]>
> > ---
> >  drivers/iio/accel/bmc150-accel.c | 231 
> > ++++++++++++++++++++++++++++++---------
> >  1 file changed, 177 insertions(+), 54 deletions(-)
> > 
> > diff --git a/drivers/iio/accel/bmc150-accel.c 
> > b/drivers/iio/accel/bmc150-accel.c
> > index 0e6566a..07e10fc 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
> > + *  - BMA250
> > + *  - BMA222
> > + *  - BMA280
> > + *
> >   * Copyright (c) 2014, Intel Corporation.
> >   *
> >   * This program is free software; you can redistribute it and/or modify it
> > @@ -35,6 +42,11 @@
> >  
> >  #define BMC150_ACCEL_REG_CHIP_ID           0x00
> >  #define BMC150_ACCEL_CHIP_ID_VAL           0xFA
> > +#define BMA255_ACCEL_CHIP_ID_VAL           0xFA
> > +#define BMI055_ACCEL_CHIP_ID_VAL           0xFA
> > +#define BMA222_ACCEL_CHIP_ID_VAL           0xF8
> > +#define BMA250_ACCEL_CHIP_ID_VAL           0xF9
> > +#define BMA280_ACCEL_CHIP_ID_VAL           0xFB
> >  
> >  #define BMC150_ACCEL_REG_INT_STATUS_2              0x0B
> >  #define BMC150_ACCEL_ANY_MOTION_MASK               0x07
> > @@ -126,6 +138,18 @@ enum bmc150_power_modes {
> >     BMC150_ACCEL_SLEEP_MODE_SUSPEND = 0x04,
> >  };
> >  
> > +struct bmc150_scale_info {
> > +   int scale;
> > +   int 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 +164,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,14 +193,6 @@ 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;
> >  } bmc150_accel_sleep_value_table[] = { {0, 0},
> > @@ -267,7 +284,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 +558,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->chip_info->scale_table[i].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].range;
> >                     return 0;
> >             }
> >     }
> > @@ -580,10 +597,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 +619,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 +645,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;
> >             }
> > @@ -647,12 +665,13 @@ static int bmc150_accel_read_raw(struct iio_dev 
> > *indio_dev,
> >             {
> >                     int i;
> >  
> > -                   for (i = 0; i < ARRAY_SIZE(bmc150_accel_scale_table);
> > -                                                                    ++i) {
> > -                           if (bmc150_accel_scale_table[i].range ==
> > +                   for (i = 0;
> > +                        i < ARRAY_SIZE(data->chip_info->scale_table);
> > +                        ++i) {
> > +                           if (data->chip_info->scale_table[i].range ==
> >                                                             data->range) {
> >                                     *val2 =
> > -                                   bmc150_accel_scale_table[i].scale;
> > +                                   data->chip_info->scale_table[i].scale;
> >                                     return IIO_VAL_INT_PLUS_MICRO;
> >                             }
> >                     }
> > @@ -840,7 +859,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,28 +869,103 @@ 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,
> > -   },
> > -   BMC150_ACCEL_CHANNEL(X),
> > -   BMC150_ACCEL_CHANNEL(Y),
> > -   BMC150_ACCEL_CHANNEL(Z),
> > -   IIO_CHAN_SOFT_TIMESTAMP(3),
> > +#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 bma222_accel_channels[] =
> > +   BMC150_ACCEL_CHANNELS(8);
> > +static const struct iio_chan_spec bma250_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,
> > +   bma250,
> > +   bma222,
> > +   bma280,
> >  };
> >  
> > +static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
> > +   [bmc150] = {
> > +           .chip_id = BMC150_ACCEL_CHIP_ID_VAL,
> > +           .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},
> > +                            {75590, BMC150_ACCEL_DEF_RANGE_16G} },
> > +   },
> > +   [bmi055] = {
> > +           .chip_id = BMI055_ACCEL_CHIP_ID_VAL,
> > +           .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},
> > +                            {75590, BMC150_ACCEL_DEF_RANGE_16G} },
> > +   },
> > +   [bma255] = {
> > +           .chip_id = BMA255_ACCEL_CHIP_ID_VAL,
> > +           .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},
> > +                            {75590, BMC150_ACCEL_DEF_RANGE_16G} },
> > +   },
> > +   [bma250] = {
> > +           .chip_id = BMA250_ACCEL_CHIP_ID_VAL,
> > +           .channels = bma250_accel_channels,
> > +           .num_channels = ARRAY_SIZE(bma250_accel_channels),
> > +           .scale_table = { {38344, BMC150_ACCEL_DEF_RANGE_2G},
> > +                            {75590, BMC150_ACCEL_DEF_RANGE_4G},
> > +                            {153277, BMC150_ACCEL_DEF_RANGE_8G},
> > +                            {306457, BMC150_ACCEL_DEF_RANGE_16G} },
> > +   },
> > +   [bma222] = {
> > +           .chip_id = BMA222_ACCEL_CHIP_ID_VAL,
> > +           .channels = bma222_accel_channels,
> > +           .num_channels = ARRAY_SIZE(bma222_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 = BMA280_ACCEL_CHIP_ID_VAL,
> > +           .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} },
> > +   },
> > +};
> > +
> >  static const struct iio_info bmc150_accel_info = {
> >     .attrs                  = &bmc150_accel_attrs_group,
> >     .read_raw               = bmc150_accel_read_raw,
> > @@ -1040,10 +1134,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 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 (char *) 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 +1159,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 +1184,8 @@ static int bmc150_accel_probe(struct i2c_client 
> > *client,
> >     struct bmc150_accel_data *data;
> >     struct iio_dev *indio_dev;
> >     int ret;
> > +   char *name = NULL;
> > +   int chip_id = 0;
> >  
> >     indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> >     if (!indio_dev)
> > @@ -1092,6 +1195,16 @@ static int bmc150_accel_probe(struct i2c_client 
> > *client,
> >     i2c_set_clientdata(client, indio_dev);
> >     data->client = client;
> >  
> > +   if (id) {
> > +           name = (char *) 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 +1212,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 +1397,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},
> > +   {"BMA0250",     bma250},
> > +   {"BMA0222",     bma222},
> > +   {"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},
> > +   {"bma250",              bma250},
> > +   {"bma222",              bma222},
> > +   {"bma280",              bma280},
> >     {}
> >  };
> >  
> > 
> 
> -- 
> 
> Peter Meerwald
> +43-664-2444418 (mobile)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to