X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=drivers%2Fiio%2Fpressure%2Fst_pressure_core.c;h=58083f9d51c56691281891e4afbbe368d92697ab;hb=0a759b2466d19c619257fec36f988f93424cf3ae;hp=ceebd3c27892b183f6f276b1dbdb4d7a6a5a9a74;hpb=1329dfc8bb8932976844438cd5e757c720d6f1ff;p=~andy%2Flinux diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index ceebd3c2789..58083f9d51c 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -36,94 +37,200 @@ ST_PRESS_LSB_PER_CELSIUS) #define ST_PRESS_NUMBER_DATA_CHANNELS 1 -/* DEFAULT VALUE FOR SENSORS */ -#define ST_PRESS_DEFAULT_OUT_XL_ADDR 0x28 -#define ST_TEMP_DEFAULT_OUT_L_ADDR 0x2b - /* FULLSCALE */ #define ST_PRESS_FS_AVL_1260MB 1260 -/* CUSTOM VALUES FOR SENSOR 1 */ -#define ST_PRESS_1_WAI_EXP 0xbb -#define ST_PRESS_1_ODR_ADDR 0x20 -#define ST_PRESS_1_ODR_MASK 0x70 -#define ST_PRESS_1_ODR_AVL_1HZ_VAL 0x01 -#define ST_PRESS_1_ODR_AVL_7HZ_VAL 0x05 -#define ST_PRESS_1_ODR_AVL_13HZ_VAL 0x06 -#define ST_PRESS_1_ODR_AVL_25HZ_VAL 0x07 -#define ST_PRESS_1_PW_ADDR 0x20 -#define ST_PRESS_1_PW_MASK 0x80 -#define ST_PRESS_1_FS_ADDR 0x23 -#define ST_PRESS_1_FS_MASK 0x30 -#define ST_PRESS_1_FS_AVL_1260_VAL 0x00 -#define ST_PRESS_1_FS_AVL_1260_GAIN ST_PRESS_KPASCAL_NANO_SCALE -#define ST_PRESS_1_FS_AVL_TEMP_GAIN ST_PRESS_CELSIUS_NANO_SCALE -#define ST_PRESS_1_BDU_ADDR 0x20 -#define ST_PRESS_1_BDU_MASK 0x04 -#define ST_PRESS_1_DRDY_IRQ_ADDR 0x22 -#define ST_PRESS_1_DRDY_IRQ_INT1_MASK 0x04 -#define ST_PRESS_1_DRDY_IRQ_INT2_MASK 0x20 -#define ST_PRESS_1_MULTIREAD_BIT true -#define ST_PRESS_1_TEMP_OFFSET 42500 - -static const struct iio_chan_spec st_press_channels[] = { - ST_SENSORS_LSM_CHANNELS(IIO_PRESSURE, +/* CUSTOM VALUES FOR LPS331AP SENSOR */ +#define ST_PRESS_LPS331AP_WAI_EXP 0xbb +#define ST_PRESS_LPS331AP_ODR_ADDR 0x20 +#define ST_PRESS_LPS331AP_ODR_MASK 0x70 +#define ST_PRESS_LPS331AP_ODR_AVL_1HZ_VAL 0x01 +#define ST_PRESS_LPS331AP_ODR_AVL_7HZ_VAL 0x05 +#define ST_PRESS_LPS331AP_ODR_AVL_13HZ_VAL 0x06 +#define ST_PRESS_LPS331AP_ODR_AVL_25HZ_VAL 0x07 +#define ST_PRESS_LPS331AP_PW_ADDR 0x20 +#define ST_PRESS_LPS331AP_PW_MASK 0x80 +#define ST_PRESS_LPS331AP_FS_ADDR 0x23 +#define ST_PRESS_LPS331AP_FS_MASK 0x30 +#define ST_PRESS_LPS331AP_FS_AVL_1260_VAL 0x00 +#define ST_PRESS_LPS331AP_FS_AVL_1260_GAIN ST_PRESS_KPASCAL_NANO_SCALE +#define ST_PRESS_LPS331AP_FS_AVL_TEMP_GAIN ST_PRESS_CELSIUS_NANO_SCALE +#define ST_PRESS_LPS331AP_BDU_ADDR 0x20 +#define ST_PRESS_LPS331AP_BDU_MASK 0x04 +#define ST_PRESS_LPS331AP_DRDY_IRQ_ADDR 0x22 +#define ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK 0x04 +#define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK 0x20 +#define ST_PRESS_LPS331AP_MULTIREAD_BIT true +#define ST_PRESS_LPS331AP_TEMP_OFFSET 42500 +#define ST_PRESS_LPS331AP_OUT_XL_ADDR 0x28 +#define ST_TEMP_LPS331AP_OUT_L_ADDR 0x2b + +/* CUSTOM VALUES FOR LPS001WP SENSOR */ +#define ST_PRESS_LPS001WP_WAI_EXP 0xba +#define ST_PRESS_LPS001WP_ODR_ADDR 0x20 +#define ST_PRESS_LPS001WP_ODR_MASK 0x30 +#define ST_PRESS_LPS001WP_ODR_AVL_1HZ_VAL 0x01 +#define ST_PRESS_LPS001WP_ODR_AVL_7HZ_VAL 0x02 +#define ST_PRESS_LPS001WP_ODR_AVL_13HZ_VAL 0x03 +#define ST_PRESS_LPS001WP_PW_ADDR 0x20 +#define ST_PRESS_LPS001WP_PW_MASK 0x40 +#define ST_PRESS_LPS001WP_BDU_ADDR 0x20 +#define ST_PRESS_LPS001WP_BDU_MASK 0x04 +#define ST_PRESS_LPS001WP_MULTIREAD_BIT true +#define ST_PRESS_LPS001WP_OUT_L_ADDR 0x28 +#define ST_TEMP_LPS001WP_OUT_L_ADDR 0x2a + +static const struct iio_chan_spec st_press_lps331ap_channels[] = { + { + .type = IIO_PRESSURE, + .channel2 = IIO_NO_MOD, + .address = ST_PRESS_LPS331AP_OUT_XL_ADDR, + .scan_index = ST_SENSORS_SCAN_X, + .scan_type = { + .sign = 'u', + .realbits = 24, + .storagebits = 24, + .endianness = IIO_LE, + }, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), - ST_SENSORS_SCAN_X, 0, IIO_NO_MOD, 'u', IIO_LE, 24, 24, - ST_PRESS_DEFAULT_OUT_XL_ADDR), - ST_SENSORS_LSM_CHANNELS(IIO_TEMP, - BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) | - BIT(IIO_CHAN_INFO_OFFSET), - -1, 0, IIO_NO_MOD, 's', IIO_LE, 16, 16, - ST_TEMP_DEFAULT_OUT_L_ADDR), + .modified = 0, + }, + { + .type = IIO_TEMP, + .channel2 = IIO_NO_MOD, + .address = ST_TEMP_LPS331AP_OUT_L_ADDR, + .scan_index = -1, + .scan_type = { + .sign = 'u', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + .modified = 0, + }, + IIO_CHAN_SOFT_TIMESTAMP(1) +}; + +static const struct iio_chan_spec st_press_lps001wp_channels[] = { + { + .type = IIO_PRESSURE, + .channel2 = IIO_NO_MOD, + .address = ST_PRESS_LPS001WP_OUT_L_ADDR, + .scan_index = ST_SENSORS_SCAN_X, + .scan_type = { + .sign = 'u', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .modified = 0, + }, + { + .type = IIO_TEMP, + .channel2 = IIO_NO_MOD, + .address = ST_TEMP_LPS001WP_OUT_L_ADDR, + .scan_index = -1, + .scan_type = { + .sign = 'u', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_OFFSET), + .modified = 0, + }, IIO_CHAN_SOFT_TIMESTAMP(1) }; static const struct st_sensors st_press_sensors[] = { { - .wai = ST_PRESS_1_WAI_EXP, + .wai = ST_PRESS_LPS331AP_WAI_EXP, .sensors_supported = { [0] = LPS331AP_PRESS_DEV_NAME, }, - .ch = (struct iio_chan_spec *)st_press_channels, + .ch = (struct iio_chan_spec *)st_press_lps331ap_channels, + .num_ch = ARRAY_SIZE(st_press_lps331ap_channels), .odr = { - .addr = ST_PRESS_1_ODR_ADDR, - .mask = ST_PRESS_1_ODR_MASK, + .addr = ST_PRESS_LPS331AP_ODR_ADDR, + .mask = ST_PRESS_LPS331AP_ODR_MASK, .odr_avl = { - { 1, ST_PRESS_1_ODR_AVL_1HZ_VAL, }, - { 7, ST_PRESS_1_ODR_AVL_7HZ_VAL, }, - { 13, ST_PRESS_1_ODR_AVL_13HZ_VAL, }, - { 25, ST_PRESS_1_ODR_AVL_25HZ_VAL, }, + { 1, ST_PRESS_LPS331AP_ODR_AVL_1HZ_VAL, }, + { 7, ST_PRESS_LPS331AP_ODR_AVL_7HZ_VAL, }, + { 13, ST_PRESS_LPS331AP_ODR_AVL_13HZ_VAL, }, + { 25, ST_PRESS_LPS331AP_ODR_AVL_25HZ_VAL, }, }, }, .pw = { - .addr = ST_PRESS_1_PW_ADDR, - .mask = ST_PRESS_1_PW_MASK, + .addr = ST_PRESS_LPS331AP_PW_ADDR, + .mask = ST_PRESS_LPS331AP_PW_MASK, .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, }, .fs = { - .addr = ST_PRESS_1_FS_ADDR, - .mask = ST_PRESS_1_FS_MASK, + .addr = ST_PRESS_LPS331AP_FS_ADDR, + .mask = ST_PRESS_LPS331AP_FS_MASK, .fs_avl = { [0] = { .num = ST_PRESS_FS_AVL_1260MB, - .value = ST_PRESS_1_FS_AVL_1260_VAL, - .gain = ST_PRESS_1_FS_AVL_1260_GAIN, - .gain2 = ST_PRESS_1_FS_AVL_TEMP_GAIN, + .value = ST_PRESS_LPS331AP_FS_AVL_1260_VAL, + .gain = ST_PRESS_LPS331AP_FS_AVL_1260_GAIN, + .gain2 = ST_PRESS_LPS331AP_FS_AVL_TEMP_GAIN, }, }, }, .bdu = { - .addr = ST_PRESS_1_BDU_ADDR, - .mask = ST_PRESS_1_BDU_MASK, + .addr = ST_PRESS_LPS331AP_BDU_ADDR, + .mask = ST_PRESS_LPS331AP_BDU_MASK, }, .drdy_irq = { - .addr = ST_PRESS_1_DRDY_IRQ_ADDR, - .mask_int1 = ST_PRESS_1_DRDY_IRQ_INT1_MASK, - .mask_int2 = ST_PRESS_1_DRDY_IRQ_INT2_MASK, + .addr = ST_PRESS_LPS331AP_DRDY_IRQ_ADDR, + .mask_int1 = ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK, + .mask_int2 = ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK, }, - .multi_read_bit = ST_PRESS_1_MULTIREAD_BIT, + .multi_read_bit = ST_PRESS_LPS331AP_MULTIREAD_BIT, + .bootime = 2, + }, + { + .wai = ST_PRESS_LPS001WP_WAI_EXP, + .sensors_supported = { + [0] = LPS001WP_PRESS_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_press_lps001wp_channels, + .num_ch = ARRAY_SIZE(st_press_lps001wp_channels), + .odr = { + .addr = ST_PRESS_LPS001WP_ODR_ADDR, + .mask = ST_PRESS_LPS001WP_ODR_MASK, + .odr_avl = { + { 1, ST_PRESS_LPS001WP_ODR_AVL_1HZ_VAL, }, + { 7, ST_PRESS_LPS001WP_ODR_AVL_7HZ_VAL, }, + { 13, ST_PRESS_LPS001WP_ODR_AVL_13HZ_VAL, }, + }, + }, + .pw = { + .addr = ST_PRESS_LPS001WP_PW_ADDR, + .mask = ST_PRESS_LPS001WP_PW_MASK, + .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .fs = { + .addr = 0, + }, + .bdu = { + .addr = ST_PRESS_LPS001WP_BDU_ADDR, + .mask = ST_PRESS_LPS001WP_BDU_MASK, + }, + .drdy_irq = { + .addr = 0, + }, + .multi_read_bit = ST_PRESS_LPS001WP_MULTIREAD_BIT, .bootime = 2, }, }; @@ -207,44 +314,85 @@ static const struct iio_trigger_ops st_press_trigger_ops = { #define ST_PRESS_TRIGGER_OPS NULL #endif +static void st_press_power_enable(struct iio_dev *indio_dev) +{ + struct st_sensor_data *pdata = iio_priv(indio_dev); + int err; + + /* Regulators not mandatory, but if requested we should enable them. */ + pdata->vdd = devm_regulator_get_optional(&indio_dev->dev, "vdd"); + if (!IS_ERR(pdata->vdd)) { + err = regulator_enable(pdata->vdd); + if (err != 0) + dev_warn(&indio_dev->dev, + "Failed to enable specified Vdd supply\n"); + } + + pdata->vdd_io = devm_regulator_get_optional(&indio_dev->dev, "vddio"); + if (!IS_ERR(pdata->vdd_io)) { + err = regulator_enable(pdata->vdd_io); + if (err != 0) + dev_warn(&indio_dev->dev, + "Failed to enable specified Vdd_IO supply\n"); + } +} + +static void st_press_power_disable(struct iio_dev *indio_dev) +{ + struct st_sensor_data *pdata = iio_priv(indio_dev); + + if (!IS_ERR(pdata->vdd)) + regulator_disable(pdata->vdd); + + if (!IS_ERR(pdata->vdd_io)) + regulator_disable(pdata->vdd_io); +} + int st_press_common_probe(struct iio_dev *indio_dev, struct st_sensors_platform_data *plat_data) { - int err; struct st_sensor_data *pdata = iio_priv(indio_dev); + int irq = pdata->get_irq_data_ready(indio_dev); + int err; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &press_info; + st_press_power_enable(indio_dev); + err = st_sensors_check_device_support(indio_dev, - ARRAY_SIZE(st_press_sensors), st_press_sensors); + ARRAY_SIZE(st_press_sensors), + st_press_sensors); if (err < 0) - goto st_press_common_probe_error; + return err; pdata->num_data_channels = ST_PRESS_NUMBER_DATA_CHANNELS; - pdata->multiread_bit = pdata->sensor->multi_read_bit; - indio_dev->channels = pdata->sensor->ch; - indio_dev->num_channels = ARRAY_SIZE(st_press_channels); + pdata->multiread_bit = pdata->sensor->multi_read_bit; + indio_dev->channels = pdata->sensor->ch; + indio_dev->num_channels = pdata->sensor->num_ch; + + if (pdata->sensor->fs.addr != 0) + pdata->current_fullscale = (struct st_sensor_fullscale_avl *) + &pdata->sensor->fs.fs_avl[0]; - pdata->current_fullscale = (struct st_sensor_fullscale_avl *) - &pdata->sensor->fs.fs_avl[0]; pdata->odr = pdata->sensor->odr.odr_avl[0].hz; - if (!plat_data) + /* Some devices don't support a data ready pin. */ + if (!plat_data && pdata->sensor->drdy_irq.addr) plat_data = (struct st_sensors_platform_data *)&default_press_pdata; err = st_sensors_init_sensor(indio_dev, plat_data); if (err < 0) - goto st_press_common_probe_error; + return err; - if (pdata->get_irq_data_ready(indio_dev) > 0) { - err = st_press_allocate_ring(indio_dev); - if (err < 0) - goto st_press_common_probe_error; + err = st_press_allocate_ring(indio_dev); + if (err < 0) + return err; + if (irq > 0) { err = st_sensors_allocate_trigger(indio_dev, - ST_PRESS_TRIGGER_OPS); + ST_PRESS_TRIGGER_OPS); if (err < 0) goto st_press_probe_trigger_error; } @@ -256,12 +404,11 @@ int st_press_common_probe(struct iio_dev *indio_dev, return err; st_press_device_register_error: - if (pdata->get_irq_data_ready(indio_dev) > 0) + if (irq > 0) st_sensors_deallocate_trigger(indio_dev); st_press_probe_trigger_error: - if (pdata->get_irq_data_ready(indio_dev) > 0) - st_press_deallocate_ring(indio_dev); -st_press_common_probe_error: + st_press_deallocate_ring(indio_dev); + return err; } EXPORT_SYMBOL(st_press_common_probe); @@ -270,11 +417,13 @@ void st_press_common_remove(struct iio_dev *indio_dev) { struct st_sensor_data *pdata = iio_priv(indio_dev); + st_press_power_disable(indio_dev); + iio_device_unregister(indio_dev); - if (pdata->get_irq_data_ready(indio_dev) > 0) { + if (pdata->get_irq_data_ready(indio_dev) > 0) st_sensors_deallocate_trigger(indio_dev); - st_press_deallocate_ring(indio_dev); - } + + st_press_deallocate_ring(indio_dev); } EXPORT_SYMBOL(st_press_common_remove);