diff options
author | Ingo Molnar <mingo@kernel.org> | 2017-03-01 09:02:26 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2017-03-01 09:02:26 +0100 |
commit | 0871d5a66da5c41151e0896a90298b163e42f2e0 (patch) | |
tree | 1ba71fab9016cb28bb9d18ffd62b6b744f2f761c /drivers/iio/pressure | |
parent | x86/boot: Fix pr_debug() API braindamage (diff) | |
parent | Merge tag 'for-linus-4.11' of git://git.code.sf.net/p/openipmi/linux-ipmi (diff) | |
download | linux-0871d5a66da5c41151e0896a90298b163e42f2e0.tar.xz linux-0871d5a66da5c41151e0896a90298b163e42f2e0.zip |
Merge branch 'linus' into WIP.x86/boot, to fix up conflicts and to pick up updates
Conflicts:
arch/x86/xen/setup.c
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/iio/pressure')
-rw-r--r-- | drivers/iio/pressure/Kconfig | 10 | ||||
-rw-r--r-- | drivers/iio/pressure/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/pressure/bmp280-core.c | 14 | ||||
-rw-r--r-- | drivers/iio/pressure/cros_ec_baro.c | 220 | ||||
-rw-r--r-- | drivers/iio/pressure/mpl115.c | 1 | ||||
-rw-r--r-- | drivers/iio/pressure/mpl3115.c | 4 | ||||
-rw-r--r-- | drivers/iio/pressure/ms5611_core.c | 12 | ||||
-rw-r--r-- | drivers/iio/pressure/st_pressure.h | 8 | ||||
-rw-r--r-- | drivers/iio/pressure/st_pressure_core.c | 12 | ||||
-rw-r--r-- | drivers/iio/pressure/st_pressure_i2c.c | 51 |
10 files changed, 301 insertions, 32 deletions
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index bd8d96b96771..5d16b252ab6b 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -42,6 +42,16 @@ config BMP280_SPI depends on SPI_MASTER select REGMAP +config IIO_CROS_EC_BARO + tristate "ChromeOS EC Barometer Sensor" + depends on IIO_CROS_EC_SENSORS_CORE + help + Say yes here to build support for the Barometer sensor when + presented by the ChromeOS EC Sensor hub. + + To compile this driver as a module, choose M here: the module + will be called cros_ec_baro. + config HID_SENSOR_PRESS depends on HID_SENSOR_HUB select IIO_BUFFER diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index de3dbc81dc5a..838642789389 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_BMP280) += bmp280.o bmp280-objs := bmp280-core.o bmp280-regmap.o obj-$(CONFIG_BMP280_I2C) += bmp280-i2c.o obj-$(CONFIG_BMP280_SPI) += bmp280-spi.o +obj-$(CONFIG_IIO_CROS_EC_BARO) += cros_ec_baro.o obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o obj-$(CONFIG_HP03) += hp03.o obj-$(CONFIG_MPL115) += mpl115.o diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index e5a533cbd53f..4d18826ac63c 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -65,7 +65,7 @@ struct bmp280_data { struct bmp180_calib calib; struct regulator *vddd; struct regulator *vdda; - unsigned int start_up_time; /* in milliseconds */ + unsigned int start_up_time; /* in microseconds */ /* log of base 2 of oversampling rate */ u8 oversampling_press; @@ -935,14 +935,14 @@ int bmp280_common_probe(struct device *dev, data->chip_info = &bmp180_chip_info; data->oversampling_press = ilog2(8); data->oversampling_temp = ilog2(1); - data->start_up_time = 10; + data->start_up_time = 10000; break; case BMP280_CHIP_ID: indio_dev->num_channels = 2; data->chip_info = &bmp280_chip_info; data->oversampling_press = ilog2(16); data->oversampling_temp = ilog2(2); - data->start_up_time = 2; + data->start_up_time = 2000; break; case BME280_CHIP_ID: indio_dev->num_channels = 3; @@ -950,7 +950,7 @@ int bmp280_common_probe(struct device *dev, data->oversampling_press = ilog2(16); data->oversampling_humid = ilog2(16); data->oversampling_temp = ilog2(2); - data->start_up_time = 2; + data->start_up_time = 2000; break; default: return -EINVAL; @@ -979,7 +979,7 @@ int bmp280_common_probe(struct device *dev, goto out_disable_vddd; } /* Wait to make sure we started up properly */ - mdelay(data->start_up_time); + usleep_range(data->start_up_time, data->start_up_time + 100); /* Bring chip out of reset if there is an assigned GPIO line */ gpiod = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); @@ -1038,7 +1038,7 @@ int bmp280_common_probe(struct device *dev, * Set autosuspend to two orders of magnitude larger than the * start-up time. */ - pm_runtime_set_autosuspend_delay(dev, data->start_up_time *100); + pm_runtime_set_autosuspend_delay(dev, data->start_up_time / 10); pm_runtime_use_autosuspend(dev); pm_runtime_put(dev); @@ -1101,7 +1101,7 @@ static int bmp280_runtime_resume(struct device *dev) ret = regulator_enable(data->vdda); if (ret) return ret; - msleep(data->start_up_time); + usleep_range(data->start_up_time, data->start_up_time + 100); return data->chip_info->chip_config(data); } #endif /* CONFIG_PM */ diff --git a/drivers/iio/pressure/cros_ec_baro.c b/drivers/iio/pressure/cros_ec_baro.c new file mode 100644 index 000000000000..48b2a30f57ae --- /dev/null +++ b/drivers/iio/pressure/cros_ec_baro.c @@ -0,0 +1,220 @@ +/* + * cros_ec_baro - Driver for barometer sensor behind CrosEC. + * + * Copyright (C) 2017 Google, Inc + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/iio/buffer.h> +#include <linux/iio/iio.h> +#include <linux/iio/kfifo_buf.h> +#include <linux/iio/trigger.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/kernel.h> +#include <linux/mfd/cros_ec.h> +#include <linux/mfd/cros_ec_commands.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/platform_device.h> + +#include "../common/cros_ec_sensors/cros_ec_sensors_core.h" + +/* + * One channel for pressure, the other for timestamp. + */ +#define CROS_EC_BARO_MAX_CHANNELS (1 + 1) + +/* State data for ec_sensors iio driver. */ +struct cros_ec_baro_state { + /* Shared by all sensors */ + struct cros_ec_sensors_core_state core; + + struct iio_chan_spec channels[CROS_EC_BARO_MAX_CHANNELS]; +}; + +static int cros_ec_baro_read(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct cros_ec_baro_state *st = iio_priv(indio_dev); + u16 data = 0; + int ret = IIO_VAL_INT; + int idx = chan->scan_index; + + mutex_lock(&st->core.cmd_lock); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx, + (s16 *)&data) < 0) + ret = -EIO; + *val = data; + break; + case IIO_CHAN_INFO_SCALE: + st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; + st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE; + + if (cros_ec_motion_send_host_cmd(&st->core, 0)) { + ret = -EIO; + break; + } + *val = st->core.resp->sensor_range.ret; + + /* scale * in_pressure_raw --> kPa */ + *val2 = 10 << CROS_EC_SENSOR_BITS; + ret = IIO_VAL_FRACTIONAL; + break; + default: + ret = cros_ec_sensors_core_read(&st->core, chan, val, val2, + mask); + break; + } + + mutex_unlock(&st->core.cmd_lock); + + return ret; +} + +static int cros_ec_baro_write(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct cros_ec_baro_state *st = iio_priv(indio_dev); + int ret = 0; + + mutex_lock(&st->core.cmd_lock); + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; + st->core.param.sensor_range.data = val; + + /* Always roundup, so caller gets at least what it asks for. */ + st->core.param.sensor_range.roundup = 1; + + if (cros_ec_motion_send_host_cmd(&st->core, 0)) + ret = -EIO; + break; + default: + ret = cros_ec_sensors_core_write(&st->core, chan, val, val2, + mask); + break; + } + + mutex_unlock(&st->core.cmd_lock); + + return ret; +} + +static const struct iio_info cros_ec_baro_info = { + .read_raw = &cros_ec_baro_read, + .write_raw = &cros_ec_baro_write, + .driver_module = THIS_MODULE, +}; + +static int cros_ec_baro_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent); + struct cros_ec_device *ec_device; + struct iio_dev *indio_dev; + struct cros_ec_baro_state *state; + struct iio_chan_spec *channel; + int ret; + + if (!ec_dev || !ec_dev->ec_dev) { + dev_warn(dev, "No CROS EC device found.\n"); + return -EINVAL; + } + ec_device = ec_dev->ec_dev; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*state)); + if (!indio_dev) + return -ENOMEM; + + ret = cros_ec_sensors_core_init(pdev, indio_dev, true); + if (ret) + return ret; + + indio_dev->info = &cros_ec_baro_info; + state = iio_priv(indio_dev); + state->core.type = state->core.resp->info.type; + state->core.loc = state->core.resp->info.location; + channel = state->channels; + /* Common part */ + channel->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); + channel->info_mask_shared_by_all = + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_FREQUENCY); + channel->scan_type.realbits = CROS_EC_SENSOR_BITS; + channel->scan_type.storagebits = CROS_EC_SENSOR_BITS; + channel->scan_type.shift = 0; + channel->scan_index = 0; + channel->ext_info = cros_ec_sensors_ext_info; + channel->scan_type.sign = 'u'; + + state->core.calib[0] = 0; + + /* Sensor specific */ + switch (state->core.type) { + case MOTIONSENSE_TYPE_BARO: + channel->type = IIO_PRESSURE; + break; + default: + dev_warn(dev, "Unknown motion sensor\n"); + return -EINVAL; + } + + /* Timestamp */ + channel++; + channel->type = IIO_TIMESTAMP; + channel->channel = -1; + channel->scan_index = 1; + channel->scan_type.sign = 's'; + channel->scan_type.realbits = 64; + channel->scan_type.storagebits = 64; + + indio_dev->channels = state->channels; + indio_dev->num_channels = CROS_EC_BARO_MAX_CHANNELS; + + state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd; + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, + cros_ec_sensors_capture, NULL); + if (ret) + return ret; + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct platform_device_id cros_ec_baro_ids[] = { + { + .name = "cros-ec-baro", + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, cros_ec_baro_ids); + +static struct platform_driver cros_ec_baro_platform_driver = { + .driver = { + .name = "cros-ec-baro", + }, + .probe = cros_ec_baro_probe, + .id_table = cros_ec_baro_ids, +}; +module_platform_driver(cros_ec_baro_platform_driver); + +MODULE_DESCRIPTION("ChromeOS EC barometer sensor driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/pressure/mpl115.c b/drivers/iio/pressure/mpl115.c index 73f2f0c46e62..8f2bce213248 100644 --- a/drivers/iio/pressure/mpl115.c +++ b/drivers/iio/pressure/mpl115.c @@ -137,6 +137,7 @@ static const struct iio_chan_spec mpl115_channels[] = { { .type = IIO_TEMP, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), }, }; diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c index cc3f84139157..525644a7442d 100644 --- a/drivers/iio/pressure/mpl3115.c +++ b/drivers/iio/pressure/mpl3115.c @@ -190,7 +190,7 @@ static const struct iio_chan_spec mpl3115_channels[] = { { .type = IIO_PRESSURE, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), .scan_index = 0, .scan_type = { .sign = 'u', @@ -203,7 +203,7 @@ static const struct iio_chan_spec mpl3115_channels[] = { { .type = IIO_TEMP, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), .scan_index = 1, .scan_type = { .sign = 's', diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c index 6bd53e702667..2a77a2f15752 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -308,6 +308,7 @@ static int ms5611_write_raw(struct iio_dev *indio_dev, { struct ms5611_state *st = iio_priv(indio_dev); const struct ms5611_osr *osr = NULL; + int ret; if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO) return -EINVAL; @@ -321,12 +322,11 @@ static int ms5611_write_raw(struct iio_dev *indio_dev, if (!osr) return -EINVAL; - mutex_lock(&st->lock); + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; - if (iio_buffer_enabled(indio_dev)) { - mutex_unlock(&st->lock); - return -EBUSY; - } + mutex_lock(&st->lock); if (chan->type == IIO_TEMP) st->temp_osr = osr; @@ -334,6 +334,8 @@ static int ms5611_write_raw(struct iio_dev *indio_dev, st->pressure_osr = osr; mutex_unlock(&st->lock); + iio_device_release_direct_mode(indio_dev); + return 0; } diff --git a/drivers/iio/pressure/st_pressure.h b/drivers/iio/pressure/st_pressure.h index 903a21e46874..7d995937adba 100644 --- a/drivers/iio/pressure/st_pressure.h +++ b/drivers/iio/pressure/st_pressure.h @@ -14,6 +14,14 @@ #include <linux/types.h> #include <linux/iio/common/st_sensors.h> +enum st_press_type { + LPS001WP, + LPS25H, + LPS331AP, + LPS22HB, + ST_PRESS_MAX, +}; + #define LPS001WP_PRESS_DEV_NAME "lps001wp" #define LPS25H_PRESS_DEV_NAME "lps25h" #define LPS331AP_PRESS_DEV_NAME "lps331ap" diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index e19e0787864c..5f2680855552 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -136,20 +136,21 @@ static const struct iio_chan_spec st_press_1_channels[] = { .address = ST_PRESS_1_OUT_XL_ADDR, .scan_index = 0, .scan_type = { - .sign = 'u', + .sign = 's', .realbits = 24, .storagebits = 32, .endianness = IIO_LE, }, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), }, { .type = IIO_TEMP, .address = ST_TEMP_1_OUT_L_ADDR, .scan_index = 1, .scan_type = { - .sign = 'u', + .sign = 's', .realbits = 16, .storagebits = 16, .endianness = IIO_LE, @@ -158,6 +159,7 @@ static const struct iio_chan_spec st_press_1_channels[] = { BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), }, IIO_CHAN_SOFT_TIMESTAMP(2) }; @@ -168,7 +170,7 @@ static const struct iio_chan_spec st_press_lps001wp_channels[] = { .address = ST_PRESS_LPS001WP_OUT_L_ADDR, .scan_index = 0, .scan_type = { - .sign = 'u', + .sign = 's', .realbits = 16, .storagebits = 16, .endianness = IIO_LE, @@ -182,7 +184,7 @@ static const struct iio_chan_spec st_press_lps001wp_channels[] = { .address = ST_TEMP_LPS001WP_OUT_L_ADDR, .scan_index = 1, .scan_type = { - .sign = 'u', + .sign = 's', .realbits = 16, .storagebits = 16, .endianness = IIO_LE, @@ -200,7 +202,7 @@ static const struct iio_chan_spec st_press_lps22hb_channels[] = { .address = ST_PRESS_1_OUT_XL_ADDR, .scan_index = 0, .scan_type = { - .sign = 'u', + .sign = 's', .realbits = 24, .storagebits = 32, .endianness = IIO_LE, diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index ed18701c68c9..17417a4d5a5f 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -11,6 +11,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/acpi.h> #include <linux/i2c.h> #include <linux/iio/iio.h> @@ -43,25 +44,56 @@ MODULE_DEVICE_TABLE(of, st_press_of_match); #define st_press_of_match NULL #endif +#ifdef CONFIG_ACPI +static const struct acpi_device_id st_press_acpi_match[] = { + {"SNO9210", LPS22HB}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, st_press_acpi_match); +#else +#define st_press_acpi_match NULL +#endif + +static const struct i2c_device_id st_press_id_table[] = { + { LPS001WP_PRESS_DEV_NAME, LPS001WP }, + { LPS25H_PRESS_DEV_NAME, LPS25H }, + { LPS331AP_PRESS_DEV_NAME, LPS331AP }, + { LPS22HB_PRESS_DEV_NAME, LPS22HB }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, st_press_id_table); + static int st_press_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct iio_dev *indio_dev; struct st_sensor_data *press_data; - int err; + int ret; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*press_data)); if (!indio_dev) return -ENOMEM; press_data = iio_priv(indio_dev); - st_sensors_of_i2c_probe(client, st_press_of_match); + + if (client->dev.of_node) { + st_sensors_of_i2c_probe(client, st_press_of_match); + } else if (ACPI_HANDLE(&client->dev)) { + ret = st_sensors_match_acpi_device(&client->dev); + if ((ret < 0) || (ret >= ST_PRESS_MAX)) + return -ENODEV; + + strncpy(client->name, st_press_id_table[ret].name, + sizeof(client->name)); + client->name[sizeof(client->name) - 1] = '\0'; + } else if (!id) + return -ENODEV; st_sensors_i2c_configure(indio_dev, client, press_data); - err = st_press_common_probe(indio_dev); - if (err < 0) - return err; + ret = st_press_common_probe(indio_dev); + if (ret < 0) + return ret; return 0; } @@ -73,18 +105,11 @@ static int st_press_i2c_remove(struct i2c_client *client) return 0; } -static const struct i2c_device_id st_press_id_table[] = { - { LPS001WP_PRESS_DEV_NAME }, - { LPS25H_PRESS_DEV_NAME }, - { LPS331AP_PRESS_DEV_NAME }, - {}, -}; -MODULE_DEVICE_TABLE(i2c, st_press_id_table); - static struct i2c_driver st_press_driver = { .driver = { .name = "st-press-i2c", .of_match_table = of_match_ptr(st_press_of_match), + .acpi_match_table = ACPI_PTR(st_press_acpi_match), }, .probe = st_press_i2c_probe, .remove = st_press_i2c_remove, |