diff options
Diffstat (limited to 'drivers/iio/common')
-rw-r--r-- | drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c | 54 | ||||
-rw-r--r-- | drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c | 153 | ||||
-rw-r--r-- | drivers/iio/common/hid-sensors/hid-sensor-attributes.c | 69 | ||||
-rw-r--r-- | drivers/iio/common/st_sensors/Kconfig | 2 | ||||
-rw-r--r-- | drivers/iio/common/st_sensors/st_sensors_buffer.c | 10 | ||||
-rw-r--r-- | drivers/iio/common/st_sensors/st_sensors_core.c | 118 | ||||
-rw-r--r-- | drivers/iio/common/st_sensors/st_sensors_i2c.c | 82 | ||||
-rw-r--r-- | drivers/iio/common/st_sensors/st_sensors_spi.c | 148 | ||||
-rw-r--r-- | drivers/iio/common/st_sensors/st_sensors_trigger.c | 31 |
9 files changed, 393 insertions, 274 deletions
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c index 17af4e0fd5f8..6a4919cd83c3 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -63,10 +63,35 @@ static int cros_ec_sensors_read(struct iio_dev *indio_dev, /* Save values */ for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) - st->core.calib[i] = + st->core.calib[i].offset = st->core.resp->sensor_offset.offset[i]; ret = IIO_VAL_INT; - *val = st->core.calib[idx]; + *val = st->core.calib[idx].offset; + break; + case IIO_CHAN_INFO_CALIBSCALE: + st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE; + st->core.param.sensor_offset.flags = 0; + + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + if (ret == -EPROTO) { + /* Reading calibscale is not supported on older EC. */ + *val = 1; + *val2 = 0; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + } else if (ret) { + break; + } + + /* Save values */ + for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) + st->core.calib[i].scale = + st->core.resp->sensor_scale.scale[i]; + + *val = st->core.calib[idx].scale >> 15; + *val2 = ((st->core.calib[idx].scale & 0x7FFF) * 1000000LL) / + MOTION_SENSE_DEFAULT_SCALE; + ret = IIO_VAL_INT_PLUS_MICRO; break; case IIO_CHAN_INFO_SCALE: st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; @@ -134,7 +159,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: - st->core.calib[idx] = val; + st->core.calib[idx].offset = val; /* Send to EC for each axis, even if not complete */ st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; @@ -142,12 +167,27 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev, MOTION_SENSE_SET_OFFSET; for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) st->core.param.sensor_offset.offset[i] = - st->core.calib[i]; + st->core.calib[i].offset; st->core.param.sensor_offset.temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; ret = cros_ec_motion_send_host_cmd(&st->core, 0); break; + case IIO_CHAN_INFO_CALIBSCALE: + st->core.calib[idx].scale = val; + /* Send to EC for each axis, even if not complete */ + + st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE; + st->core.param.sensor_offset.flags = + MOTION_SENSE_SET_OFFSET; + for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) + st->core.param.sensor_scale.scale[i] = + st->core.calib[i].scale; + st->core.param.sensor_scale.temp = + EC_MOTION_SENSE_INVALID_CALIB_TEMP; + + ret = cros_ec_motion_send_host_cmd(&st->core, 0); + break; case IIO_CHAN_INFO_SCALE: if (st->core.type == MOTIONSENSE_TYPE_MAG) { ret = -EINVAL; @@ -175,6 +215,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev, static const struct iio_info ec_sensors_info = { .read_raw = &cros_ec_sensors_read, .write_raw = &cros_ec_sensors_write, + .read_avail = &cros_ec_sensors_core_read_avail, }; static int cros_ec_sensors_probe(struct platform_device *pdev) @@ -206,11 +247,14 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) /* Common part */ channel->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_CALIBBIAS); + BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_CALIBSCALE); channel->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_FREQUENCY) | BIT(IIO_CHAN_INFO_SAMP_FREQ); + channel->info_mask_shared_by_all_available = + BIT(IIO_CHAN_INFO_SAMP_FREQ); channel->scan_type.realbits = CROS_EC_SENSOR_BITS; channel->scan_type.storagebits = CROS_EC_SENSOR_BITS; channel->scan_index = i; diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index 130362ca421b..d44ae126f457 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -25,6 +25,62 @@ static char *cros_ec_loc[] = { [MOTIONSENSE_LOC_MAX] = "unknown", }; +static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev, + u16 cmd_offset, u16 cmd, u32 *mask) +{ + int ret; + struct { + struct cros_ec_command msg; + union { + struct ec_params_get_cmd_versions params; + struct ec_response_get_cmd_versions resp; + }; + } __packed buf = { + .msg = { + .command = EC_CMD_GET_CMD_VERSIONS + cmd_offset, + .insize = sizeof(struct ec_response_get_cmd_versions), + .outsize = sizeof(struct ec_params_get_cmd_versions) + }, + .params = {.cmd = cmd} + }; + + ret = cros_ec_cmd_xfer_status(ec_dev, &buf.msg); + if (ret >= 0) + *mask = buf.resp.version_mask; + return ret; +} + +static void get_default_min_max_freq(enum motionsensor_type type, + u32 *min_freq, + u32 *max_freq) +{ + switch (type) { + case MOTIONSENSE_TYPE_ACCEL: + case MOTIONSENSE_TYPE_GYRO: + *min_freq = 12500; + *max_freq = 100000; + break; + case MOTIONSENSE_TYPE_MAG: + *min_freq = 5000; + *max_freq = 25000; + break; + case MOTIONSENSE_TYPE_PROX: + case MOTIONSENSE_TYPE_LIGHT: + *min_freq = 100; + *max_freq = 50000; + break; + case MOTIONSENSE_TYPE_BARO: + *min_freq = 250; + *max_freq = 20000; + break; + case MOTIONSENSE_TYPE_ACTIVITY: + default: + *min_freq = 0; + *max_freq = 0; + break; + } +} + int cros_ec_sensors_core_init(struct platform_device *pdev, struct iio_dev *indio_dev, bool physical_device) @@ -33,6 +89,8 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent); struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); + u32 ver_mask; + int ret, i; platform_set_drvdata(pdev, indio_dev); @@ -47,8 +105,15 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, mutex_init(&state->cmd_lock); + ret = cros_ec_get_host_cmd_version_mask(state->ec, + ec->cmd_offset, + EC_CMD_MOTION_SENSE_CMD, + &ver_mask); + if (ret < 0) + return ret; + /* Set up the host command structure. */ - state->msg->version = 2; + state->msg->version = fls(ver_mask) - 1; state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; state->msg->outsize = sizeof(struct ec_params_motion_sense); @@ -60,12 +125,32 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, state->param.cmd = MOTIONSENSE_CMD_INFO; state->param.info.sensor_num = sensor_platform->sensor_num; - if (cros_ec_motion_send_host_cmd(state, 0)) { + ret = cros_ec_motion_send_host_cmd(state, 0); + if (ret) { dev_warn(dev, "Can not access sensor info\n"); - return -EIO; + return ret; } state->type = state->resp->info.type; state->loc = state->resp->info.location; + + /* Set sign vector, only used for backward compatibility. */ + memset(state->sign, 1, CROS_EC_SENSOR_MAX_AXIS); + + for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) + state->calib[i].scale = MOTION_SENSE_DEFAULT_SCALE; + + /* 0 is a correct value used to stop the device */ + state->frequencies[0] = 0; + if (state->msg->version < 3) { + get_default_min_max_freq(state->resp->info.type, + &state->frequencies[1], + &state->frequencies[2]); + } else { + state->frequencies[1] = + state->resp->info_3.min_frequency; + state->frequencies[2] = + state->resp->info_3.max_frequency; + } } return 0; @@ -86,7 +171,7 @@ int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state, ret = cros_ec_cmd_xfer_status(state->ec, state->msg); if (ret < 0) - return -EIO; + return ret; if (ret && state->resp != (struct ec_response_motion_sense *)state->msg->data) @@ -118,7 +203,7 @@ static ssize_t cros_ec_sensors_calibrate(struct iio_dev *indio_dev, } else { /* Save values */ for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) - st->calib[i] = st->resp->perform_calib.offset[i]; + st->calib[i].offset = st->resp->perform_calib.offset[i]; } mutex_unlock(&st->cmd_lock); @@ -268,6 +353,7 @@ static int cros_ec_sensors_read_data_unsafe(struct iio_dev *indio_dev, if (ret < 0) return ret; + *data *= st->sign[i]; data++; } @@ -396,7 +482,7 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { - int ret = IIO_VAL_INT; + int ret; switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: @@ -404,22 +490,27 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, st->param.ec_rate.data = EC_MOTION_SENSE_NO_VALUE; - if (cros_ec_motion_send_host_cmd(st, 0)) - ret = -EIO; - else - *val = st->resp->ec_rate.ret; + ret = cros_ec_motion_send_host_cmd(st, 0); + if (ret) + break; + + *val = st->resp->ec_rate.ret; + ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_FREQUENCY: st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR; st->param.sensor_odr.data = EC_MOTION_SENSE_NO_VALUE; - if (cros_ec_motion_send_host_cmd(st, 0)) - ret = -EIO; - else - *val = st->resp->sensor_odr.ret; + ret = cros_ec_motion_send_host_cmd(st, 0); + if (ret) + break; + + *val = st->resp->sensor_odr.ret; + ret = IIO_VAL_INT; break; default: + ret = -EINVAL; break; } @@ -427,11 +518,32 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, } EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read); +int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, + int *type, + int *length, + long mask) +{ + struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *length = ARRAY_SIZE(state->frequencies); + *vals = (const int *)&state->frequencies; + *type = IIO_VAL_INT; + return IIO_AVAIL_LIST; + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read_avail); + int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, struct iio_chan_spec const *chan, int val, int val2, long mask) { - int ret = 0; + int ret; switch (mask) { case IIO_CHAN_INFO_FREQUENCY: @@ -441,17 +553,16 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, /* Always roundup, so caller gets at least what it asks for. */ st->param.sensor_odr.roundup = 1; - if (cros_ec_motion_send_host_cmd(st, 0)) - ret = -EIO; + ret = cros_ec_motion_send_host_cmd(st, 0); break; case IIO_CHAN_INFO_SAMP_FREQ: st->param.cmd = MOTIONSENSE_CMD_EC_RATE; st->param.ec_rate.data = val; - if (cros_ec_motion_send_host_cmd(st, 0)) - ret = -EIO; - else - st->curr_sampl_freq = val; + ret = cros_ec_motion_send_host_cmd(st, 0); + if (ret) + break; + st->curr_sampl_freq = val; break; default: ret = -EINVAL; diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c index a8a3fe428d8d..442ff787f7af 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c @@ -8,11 +8,16 @@ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/kernel.h> #include <linux/slab.h> +#include <linux/time.h> + #include <linux/hid-sensor-hub.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> +#define HZ_PER_MHZ 1000000L + static struct { u32 usage_id; int unit; /* 0 for default others from HID sensor spec */ @@ -68,16 +73,6 @@ static struct { {HID_USAGE_SENSOR_HUMIDITY, 0, 1000, 0}, }; -static int pow_10(unsigned power) -{ - int i; - int ret = 1; - for (i = 0; i < power; ++i) - ret = ret * 10; - - return ret; -} - static void simple_div(int dividend, int divisor, int *whole, int *micro_frac) { @@ -96,14 +91,16 @@ static void simple_div(int dividend, int divisor, int *whole, rem *= 10; exp++; } - *micro_frac = (rem / divisor) * pow_10(6-exp); + *micro_frac = (rem / divisor) * int_pow(10, 6 - exp); } } static void split_micro_fraction(unsigned int no, int exp, int *val1, int *val2) { - *val1 = no/pow_10(exp); - *val2 = no%pow_10(exp) * pow_10(6-exp); + int divisor = int_pow(10, exp); + + *val1 = no / divisor; + *val2 = no % divisor * int_pow(10, 6 - exp); } /* @@ -125,7 +122,7 @@ static void convert_from_vtf_format(u32 value, int size, int exp, } exp = hid_sensor_convert_exponent(exp); if (exp >= 0) { - *val1 = sign * value * pow_10(exp); + *val1 = sign * value * int_pow(10, exp); *val2 = 0; } else { split_micro_fraction(value, -exp, val1, val2); @@ -138,6 +135,7 @@ static void convert_from_vtf_format(u32 value, int size, int exp, static u32 convert_to_vtf_format(int size, int exp, int val1, int val2) { + int divisor; u32 value; int sign = 1; @@ -145,10 +143,13 @@ static u32 convert_to_vtf_format(int size, int exp, int val1, int val2) sign = -1; exp = hid_sensor_convert_exponent(exp); if (exp < 0) { - value = abs(val1) * pow_10(-exp); - value += abs(val2) / pow_10(6+exp); - } else - value = abs(val1) / pow_10(exp); + divisor = int_pow(10, 6 + exp); + value = abs(val1) * int_pow(10, -exp); + value += abs(val2) / divisor; + } else { + divisor = int_pow(10, exp); + value = abs(val1) / divisor; + } if (sign < 0) value = ((1LL << (size * 8)) - value); @@ -211,12 +212,12 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st, if (val1 < 0 || val2 < 0) return -EINVAL; - value = val1 * pow_10(6) + val2; + value = val1 * HZ_PER_MHZ + val2; if (value) { if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND) - value = pow_10(9)/value; + value = NSEC_PER_SEC / value; else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND) - value = pow_10(6)/value; + value = USEC_PER_SEC / value; else value = 0; } @@ -305,40 +306,44 @@ EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); static void adjust_exponent_nano(int *val0, int *val1, int scale0, int scale1, int exp) { + int divisor; int i; int x; int res; int rem; if (exp > 0) { - *val0 = scale0 * pow_10(exp); + *val0 = scale0 * int_pow(10, exp); res = 0; if (exp > 9) { *val1 = 0; return; } for (i = 0; i < exp; ++i) { - x = scale1 / pow_10(8 - i); - res += (pow_10(exp - 1 - i) * x); - scale1 = scale1 % pow_10(8 - i); + divisor = int_pow(10, 8 - i); + x = scale1 / divisor; + res += int_pow(10, exp - 1 - i) * x; + scale1 = scale1 % divisor; } *val0 += res; - *val1 = scale1 * pow_10(exp); + *val1 = scale1 * int_pow(10, exp); } else if (exp < 0) { exp = abs(exp); if (exp > 9) { *val0 = *val1 = 0; return; } - *val0 = scale0 / pow_10(exp); - rem = scale0 % pow_10(exp); + divisor = int_pow(10, exp); + *val0 = scale0 / divisor; + rem = scale0 % divisor; res = 0; for (i = 0; i < (9 - exp); ++i) { - x = scale1 / pow_10(8 - i); - res += (pow_10(8 - exp - i) * x); - scale1 = scale1 % pow_10(8 - i); + divisor = int_pow(10, 8 - i); + x = scale1 / divisor; + res += int_pow(10, 8 - exp - i) * x; + scale1 = scale1 % divisor; } - *val1 = rem * pow_10(9 - exp) + res; + *val1 = rem * int_pow(10, 9 - exp) + res; } else { *val0 = scale0; *val1 = scale1; diff --git a/drivers/iio/common/st_sensors/Kconfig b/drivers/iio/common/st_sensors/Kconfig index 91b98e152d75..9364ec7a811f 100644 --- a/drivers/iio/common/st_sensors/Kconfig +++ b/drivers/iio/common/st_sensors/Kconfig @@ -5,9 +5,11 @@ config IIO_ST_SENSORS_I2C tristate + select REGMAP_I2C config IIO_ST_SENSORS_SPI tristate + select REGMAP_SPI config IIO_ST_SENSORS_CORE tristate diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c index 4a68669dc555..eee30130ae23 100644 --- a/drivers/iio/common/st_sensors/st_sensors_buffer.c +++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c @@ -17,15 +17,16 @@ #include <linux/iio/trigger_consumer.h> #include <linux/iio/triggered_buffer.h> #include <linux/irqreturn.h> +#include <linux/regmap.h> #include <linux/iio/common/st_sensors.h> static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) { - int i; struct st_sensor_data *sdata = iio_priv(indio_dev); unsigned int num_data_channels = sdata->num_data_channels; + int i; for_each_set_bit(i, indio_dev->active_scan_mask, num_data_channels) { const struct iio_chan_spec *channel = &indio_dev->channels[i]; @@ -36,11 +37,8 @@ static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) channel->scan_type.storagebits >> 3; buf = PTR_ALIGN(buf, storage_bytes); - if (sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, - channel->address, - bytes_to_read, buf, - sdata->multiread_bit) < - bytes_to_read) + if (regmap_bulk_read(sdata->regmap, channel->address, + buf, bytes_to_read) < 0) return -EIO; /* Advance the buffer pointer */ diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 8b22dc241482..4a3064fb6cd9 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -15,6 +15,7 @@ #include <linux/regulator/consumer.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/regmap.h> #include <asm/unaligned.h> #include <linux/iio/common/st_sensors.h> @@ -28,19 +29,10 @@ static inline u32 st_sensors_get_unaligned_le24(const u8 *p) int st_sensors_write_data_with_mask(struct iio_dev *indio_dev, u8 reg_addr, u8 mask, u8 data) { - int err; - u8 new_data; struct st_sensor_data *sdata = iio_priv(indio_dev); - err = sdata->tf->read_byte(&sdata->tb, sdata->dev, reg_addr, &new_data); - if (err < 0) - goto st_sensors_write_data_with_mask_error; - - new_data = ((new_data & (~mask)) | ((data << __ffs(mask)) & mask)); - err = sdata->tf->write_byte(&sdata->tb, sdata->dev, reg_addr, new_data); - -st_sensors_write_data_with_mask_error: - return err; + return regmap_update_bits(sdata->regmap, + reg_addr, mask, data << __ffs(mask)); } int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev, @@ -48,19 +40,15 @@ int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev, unsigned *readval) { struct st_sensor_data *sdata = iio_priv(indio_dev); - u8 readdata; int err; if (!readval) - return sdata->tf->write_byte(&sdata->tb, sdata->dev, - (u8)reg, (u8)writeval); + return regmap_write(sdata->regmap, reg, writeval); - err = sdata->tf->read_byte(&sdata->tb, sdata->dev, (u8)reg, &readdata); + err = regmap_read(sdata->regmap, reg, readval); if (err < 0) return err; - *readval = (unsigned)readdata; - return 0; } EXPORT_SYMBOL(st_sensors_debugfs_reg_access); @@ -545,7 +533,7 @@ st_sensors_match_scale_error: EXPORT_SYMBOL(st_sensors_set_fullscale_by_gain); static int st_sensors_read_axis_data(struct iio_dev *indio_dev, - struct iio_chan_spec const *ch, int *data) + struct iio_chan_spec const *ch, int *data) { int err; u8 *outdata; @@ -554,13 +542,12 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev, byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits + ch->scan_type.shift, 8); - outdata = kmalloc(byte_for_channel, GFP_KERNEL); + outdata = kmalloc(byte_for_channel, GFP_DMA | GFP_KERNEL); if (!outdata) return -ENOMEM; - err = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, - ch->address, byte_for_channel, - outdata, sdata->multiread_bit); + err = regmap_bulk_read(sdata->regmap, ch->address, + outdata, byte_for_channel); if (err < 0) goto st_sensors_free_memory; @@ -608,69 +595,55 @@ out: } EXPORT_SYMBOL(st_sensors_read_info_raw); -static int st_sensors_init_interface_mode(struct iio_dev *indio_dev, - const struct st_sensor_settings *sensor_settings) +/* + * st_sensors_get_settings_index() - get index of the sensor settings for a + * specific device from list of settings + * @name: device name buffer reference. + * @list: sensor settings list. + * @list_length: length of sensor settings list. + * + * Return: non negative number on success (valid index), + * negative error code otherwise. + */ +int st_sensors_get_settings_index(const char *name, + const struct st_sensor_settings *list, + const int list_length) { - struct st_sensor_data *sdata = iio_priv(indio_dev); - struct device_node *np = sdata->dev->of_node; - struct st_sensors_platform_data *pdata; + int i, n; - pdata = (struct st_sensors_platform_data *)sdata->dev->platform_data; - if (((np && of_property_read_bool(np, "spi-3wire")) || - (pdata && pdata->spi_3wire)) && sensor_settings->sim.addr) { - int err; - - err = sdata->tf->write_byte(&sdata->tb, sdata->dev, - sensor_settings->sim.addr, - sensor_settings->sim.value); - if (err < 0) { - dev_err(&indio_dev->dev, - "failed to init interface mode\n"); - return err; + for (i = 0; i < list_length; i++) { + for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) { + if (strcmp(name, list[i].sensors_supported[n]) == 0) + return i; } } - return 0; + return -ENODEV; } +EXPORT_SYMBOL(st_sensors_get_settings_index); -int st_sensors_check_device_support(struct iio_dev *indio_dev, - int num_sensors_list, - const struct st_sensor_settings *sensor_settings) +/* + * st_sensors_verify_id() - verify sensor ID (WhoAmI) is matching with the + * expected value + * @indio_dev: IIO device reference. + * + * Return: 0 on success (valid sensor ID), else a negative error code. + */ +int st_sensors_verify_id(struct iio_dev *indio_dev) { - int i, n, err = 0; - u8 wai; struct st_sensor_data *sdata = iio_priv(indio_dev); + int wai, err; - for (i = 0; i < num_sensors_list; i++) { - for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) { - if (strcmp(indio_dev->name, - sensor_settings[i].sensors_supported[n]) == 0) { - break; - } - } - if (n < ST_SENSORS_MAX_4WAI) - break; - } - if (i == num_sensors_list) { - dev_err(&indio_dev->dev, "device name %s not recognized.\n", - indio_dev->name); - return -ENODEV; - } - - err = st_sensors_init_interface_mode(indio_dev, &sensor_settings[i]); - if (err < 0) - return err; - - if (sensor_settings[i].wai_addr) { - err = sdata->tf->read_byte(&sdata->tb, sdata->dev, - sensor_settings[i].wai_addr, &wai); + if (sdata->sensor_settings->wai_addr) { + err = regmap_read(sdata->regmap, + sdata->sensor_settings->wai_addr, &wai); if (err < 0) { dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n"); return err; } - if (sensor_settings[i].wai != wai) { + if (sdata->sensor_settings->wai != wai) { dev_err(&indio_dev->dev, "%s: WhoAmI mismatch (0x%x).\n", indio_dev->name, wai); @@ -678,12 +651,9 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev, } } - sdata->sensor_settings = - (struct st_sensor_settings *)&sensor_settings[i]; - - return i; + return 0; } -EXPORT_SYMBOL(st_sensors_check_device_support); +EXPORT_SYMBOL(st_sensors_verify_id); ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c index b1c9812407e7..aa89d54a7c59 100644 --- a/drivers/iio/common/st_sensors/st_sensors_i2c.c +++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c @@ -13,68 +13,58 @@ #include <linux/iio/iio.h> #include <linux/of_device.h> #include <linux/acpi.h> +#include <linux/regmap.h> #include <linux/iio/common/st_sensors_i2c.h> #define ST_SENSORS_I2C_MULTIREAD 0x80 -static unsigned int st_sensors_i2c_get_irq(struct iio_dev *indio_dev) -{ - struct st_sensor_data *sdata = iio_priv(indio_dev); - - return to_i2c_client(sdata->dev)->irq; -} - -static int st_sensors_i2c_read_byte(struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 *res_byte) -{ - int err; - - err = i2c_smbus_read_byte_data(to_i2c_client(dev), reg_addr); - if (err < 0) - goto st_accel_i2c_read_byte_error; - - *res_byte = err & 0xff; - -st_accel_i2c_read_byte_error: - return err < 0 ? err : 0; -} - -static int st_sensors_i2c_read_multiple_byte( - struct st_sensor_transfer_buffer *tb, struct device *dev, - u8 reg_addr, int len, u8 *data, bool multiread_bit) -{ - if (multiread_bit) - reg_addr |= ST_SENSORS_I2C_MULTIREAD; - - return i2c_smbus_read_i2c_block_data_or_emulated(to_i2c_client(dev), - reg_addr, len, data); -} - -static int st_sensors_i2c_write_byte(struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 data) -{ - return i2c_smbus_write_byte_data(to_i2c_client(dev), reg_addr, data); -} +static const struct regmap_config st_sensors_i2c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; -static const struct st_sensor_transfer_function st_sensors_tf_i2c = { - .read_byte = st_sensors_i2c_read_byte, - .write_byte = st_sensors_i2c_write_byte, - .read_multiple_byte = st_sensors_i2c_read_multiple_byte, +static const struct regmap_config st_sensors_i2c_regmap_multiread_bit_config = { + .reg_bits = 8, + .val_bits = 8, + .read_flag_mask = ST_SENSORS_I2C_MULTIREAD, }; -void st_sensors_i2c_configure(struct iio_dev *indio_dev, - struct i2c_client *client, struct st_sensor_data *sdata) +/* + * st_sensors_i2c_configure() - configure I2C interface + * @indio_dev: IIO device reference. + * @client: i2c client reference. + * + * Return: 0 on success, else a negative error code. + */ +int st_sensors_i2c_configure(struct iio_dev *indio_dev, + struct i2c_client *client) { + struct st_sensor_data *sdata = iio_priv(indio_dev); + const struct regmap_config *config; + + if (sdata->sensor_settings->multi_read_bit) + config = &st_sensors_i2c_regmap_multiread_bit_config; + else + config = &st_sensors_i2c_regmap_config; + + sdata->regmap = devm_regmap_init_i2c(client, config); + if (IS_ERR(sdata->regmap)) { + dev_err(&client->dev, "Failed to register i2c regmap (%d)\n", + (int)PTR_ERR(sdata->regmap)); + return PTR_ERR(sdata->regmap); + } + i2c_set_clientdata(client, indio_dev); indio_dev->dev.parent = &client->dev; indio_dev->name = client->name; sdata->dev = &client->dev; - sdata->tf = &st_sensors_tf_i2c; - sdata->get_irq_data_ready = st_sensors_i2c_get_irq; + sdata->irq = client->irq; + + return 0; } EXPORT_SYMBOL(st_sensors_i2c_configure); diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c index 2213843f02cb..2262f81b07c2 100644 --- a/drivers/iio/common/st_sensors/st_sensors_spi.c +++ b/drivers/iio/common/st_sensors/st_sensors_spi.c @@ -11,108 +11,108 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/iio/iio.h> +#include <linux/regmap.h> #include <linux/iio/common/st_sensors_spi.h> - +#include "st_sensors_core.h" #define ST_SENSORS_SPI_MULTIREAD 0xc0 -#define ST_SENSORS_SPI_READ 0x80 -static unsigned int st_sensors_spi_get_irq(struct iio_dev *indio_dev) -{ - struct st_sensor_data *sdata = iio_priv(indio_dev); +static const struct regmap_config st_sensors_spi_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; - return to_spi_device(sdata->dev)->irq; -} +static const struct regmap_config st_sensors_spi_regmap_multiread_bit_config = { + .reg_bits = 8, + .val_bits = 8, + .read_flag_mask = ST_SENSORS_SPI_MULTIREAD, +}; -static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, int len, u8 *data, bool multiread_bit) +/* + * st_sensors_is_spi_3_wire() - check if SPI 3-wire mode has been selected + * @spi: spi device reference. + * + * Return: true if SPI 3-wire mode is selected, false otherwise. + */ +static bool st_sensors_is_spi_3_wire(struct spi_device *spi) { - int err; - - struct spi_transfer xfers[] = { - { - .tx_buf = tb->tx_buf, - .bits_per_word = 8, - .len = 1, - }, - { - .rx_buf = tb->rx_buf, - .bits_per_word = 8, - .len = len, - } - }; - - mutex_lock(&tb->buf_lock); - if ((multiread_bit) && (len > 1)) - tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_MULTIREAD; - else - tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_READ; + struct device_node *np = spi->dev.of_node; + struct st_sensors_platform_data *pdata; - err = spi_sync_transfer(to_spi_device(dev), xfers, ARRAY_SIZE(xfers)); - if (err) - goto acc_spi_read_error; + pdata = (struct st_sensors_platform_data *)spi->dev.platform_data; + if ((np && of_property_read_bool(np, "spi-3wire")) || + (pdata && pdata->spi_3wire)) { + return true; + } - memcpy(data, tb->rx_buf, len); - mutex_unlock(&tb->buf_lock); - return len; - -acc_spi_read_error: - mutex_unlock(&tb->buf_lock); - return err; + return false; } -static int st_sensors_spi_read_byte(struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 *res_byte) +/* + * st_sensors_configure_spi_3_wire() - configure SPI 3-wire if needed + * @spi: spi device reference. + * @settings: sensor specific settings reference. + * + * Return: 0 on success, else a negative error code. + */ +static int st_sensors_configure_spi_3_wire(struct spi_device *spi, + struct st_sensor_settings *settings) { - return st_sensors_spi_read(tb, dev, reg_addr, 1, res_byte, false); -} + if (settings->sim.addr) { + u8 buffer[] = { + settings->sim.addr, + settings->sim.value + }; -static int st_sensors_spi_read_multiple_byte( - struct st_sensor_transfer_buffer *tb, struct device *dev, - u8 reg_addr, int len, u8 *data, bool multiread_bit) -{ - return st_sensors_spi_read(tb, dev, reg_addr, len, data, multiread_bit); + return spi_write(spi, buffer, 2); + } + + return 0; } -static int st_sensors_spi_write_byte(struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 data) +/* + * st_sensors_spi_configure() - configure SPI interface + * @indio_dev: IIO device reference. + * @spi: spi device reference. + * + * Return: 0 on success, else a negative error code. + */ +int st_sensors_spi_configure(struct iio_dev *indio_dev, + struct spi_device *spi) { + struct st_sensor_data *sdata = iio_priv(indio_dev); + const struct regmap_config *config; int err; - struct spi_transfer xfers = { - .tx_buf = tb->tx_buf, - .bits_per_word = 8, - .len = 2, - }; + if (st_sensors_is_spi_3_wire(spi)) { + err = st_sensors_configure_spi_3_wire(spi, + sdata->sensor_settings); + if (err < 0) + return err; + } - mutex_lock(&tb->buf_lock); - tb->tx_buf[0] = reg_addr; - tb->tx_buf[1] = data; - - err = spi_sync_transfer(to_spi_device(dev), &xfers, 1); - mutex_unlock(&tb->buf_lock); + if (sdata->sensor_settings->multi_read_bit) + config = &st_sensors_spi_regmap_multiread_bit_config; + else + config = &st_sensors_spi_regmap_config; - return err; -} + sdata->regmap = devm_regmap_init_spi(spi, config); + if (IS_ERR(sdata->regmap)) { + dev_err(&spi->dev, "Failed to register spi regmap (%d)\n", + (int)PTR_ERR(sdata->regmap)); + return PTR_ERR(sdata->regmap); + } -static const struct st_sensor_transfer_function st_sensors_tf_spi = { - .read_byte = st_sensors_spi_read_byte, - .write_byte = st_sensors_spi_write_byte, - .read_multiple_byte = st_sensors_spi_read_multiple_byte, -}; - -void st_sensors_spi_configure(struct iio_dev *indio_dev, - struct spi_device *spi, struct st_sensor_data *sdata) -{ spi_set_drvdata(spi, indio_dev); indio_dev->dev.parent = &spi->dev; indio_dev->name = spi->modalias; sdata->dev = &spi->dev; - sdata->tf = &st_sensors_tf_spi; - sdata->get_irq_data_ready = st_sensors_spi_get_irq; + sdata->irq = spi->irq; + + return 0; } EXPORT_SYMBOL(st_sensors_spi_configure); diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c index 630c8cb35e8b..4a2efa00f7f2 100644 --- a/drivers/iio/common/st_sensors/st_sensors_trigger.c +++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c @@ -13,6 +13,7 @@ #include <linux/iio/iio.h> #include <linux/iio/trigger.h> #include <linux/interrupt.h> +#include <linux/regmap.h> #include <linux/iio/common/st_sensors.h> #include "st_sensors_core.h" @@ -26,8 +27,7 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev, struct st_sensor_data *sdata) { - u8 status; - int ret; + int ret, status; /* How would I know if I can't check it? */ if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr) @@ -37,9 +37,9 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev, if (!indio_dev->active_scan_mask) return 0; - ret = sdata->tf->read_byte(&sdata->tb, sdata->dev, - sdata->sensor_settings->drdy_irq.stat_drdy.addr, - &status); + ret = regmap_read(sdata->regmap, + sdata->sensor_settings->drdy_irq.stat_drdy.addr, + &status); if (ret < 0) { dev_err(sdata->dev, "error checking samples available\n"); @@ -121,9 +121,9 @@ static irqreturn_t st_sensors_irq_thread(int irq, void *p) int st_sensors_allocate_trigger(struct iio_dev *indio_dev, const struct iio_trigger_ops *trigger_ops) { - int err, irq; struct st_sensor_data *sdata = iio_priv(indio_dev); unsigned long irq_trig; + int err; sdata->trig = iio_trigger_alloc("%s-trigger", indio_dev->name); if (sdata->trig == NULL) { @@ -135,8 +135,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, sdata->trig->ops = trigger_ops; sdata->trig->dev.parent = sdata->dev; - irq = sdata->get_irq_data_ready(indio_dev); - irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq)); + irq_trig = irqd_get_trigger_type(irq_get_irq_data(sdata->irq)); /* * If the IRQ is triggered on falling edge, we need to mark the * interrupt as active low, if the hardware supports this. @@ -206,12 +205,12 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, sdata->sensor_settings->drdy_irq.stat_drdy.addr) irq_trig |= IRQF_SHARED; - err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev), - st_sensors_irq_handler, - st_sensors_irq_thread, - irq_trig, - sdata->trig->name, - sdata->trig); + err = request_threaded_irq(sdata->irq, + st_sensors_irq_handler, + st_sensors_irq_thread, + irq_trig, + sdata->trig->name, + sdata->trig); if (err) { dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n"); goto iio_trigger_free; @@ -227,7 +226,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, return 0; iio_trigger_register_error: - free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig); + free_irq(sdata->irq, sdata->trig); iio_trigger_free: iio_trigger_free(sdata->trig); return err; @@ -239,7 +238,7 @@ void st_sensors_deallocate_trigger(struct iio_dev *indio_dev) struct st_sensor_data *sdata = iio_priv(indio_dev); iio_trigger_unregister(sdata->trig); - free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig); + free_irq(sdata->irq, sdata->trig); iio_trigger_free(sdata->trig); } EXPORT_SYMBOL(st_sensors_deallocate_trigger); |