diff options
Diffstat (limited to 'drivers/iio/accel/fxls8962af-core.c')
| -rw-r--r-- | drivers/iio/accel/fxls8962af-core.c | 166 |
1 files changed, 89 insertions, 77 deletions
diff --git a/drivers/iio/accel/fxls8962af-core.c b/drivers/iio/accel/fxls8962af-core.c index 32989d91b982..8763e91c63d2 100644 --- a/drivers/iio/accel/fxls8962af-core.c +++ b/drivers/iio/accel/fxls8962af-core.c @@ -15,11 +15,15 @@ #include <linux/bits.h> #include <linux/bitfield.h> #include <linux/i2c.h> +#include <linux/irq.h> #include <linux/module.h> -#include <linux/of_irq.h> +#include <linux/mod_devicetable.h> #include <linux/pm_runtime.h> +#include <linux/property.h> #include <linux/regulator/consumer.h> #include <linux/regmap.h> +#include <linux/types.h> +#include <linux/units.h> #include <linux/iio/buffer.h> #include <linux/iio/events.h> @@ -126,6 +130,8 @@ #define FXLS8962AF_DEVICE_ID 0x62 #define FXLS8964AF_DEVICE_ID 0x84 +#define FXLS8974CF_DEVICE_ID 0x86 +#define FXLS8967AF_DEVICE_ID 0x87 /* Raw temp channel offset */ #define FXLS8962AF_TEMP_CENTER_VAL 25 @@ -159,10 +165,9 @@ struct fxls8962af_chip_info { struct fxls8962af_data { struct regmap *regmap; const struct fxls8962af_chip_info *chip_info; - struct regulator *vdd_reg; struct { __le16 channels[3]; - s64 ts __aligned(8); + aligned_s64 ts; } scan; int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */ struct iio_mount_matrix orientation; @@ -173,12 +178,20 @@ struct fxls8962af_data { u16 upper_thres; }; -const struct regmap_config fxls8962af_regmap_conf = { +const struct regmap_config fxls8962af_i2c_regmap_conf = { .reg_bits = 8, .val_bits = 8, .max_register = FXLS8962AF_MAX_REG, }; -EXPORT_SYMBOL_GPL(fxls8962af_regmap_conf); +EXPORT_SYMBOL_NS_GPL(fxls8962af_i2c_regmap_conf, "IIO_FXLS8962AF"); + +const struct regmap_config fxls8962af_spi_regmap_conf = { + .reg_bits = 8, + .pad_bits = 8, + .val_bits = 8, + .max_register = FXLS8962AF_MAX_REG, +}; +EXPORT_SYMBOL_NS_GPL(fxls8962af_spi_regmap_conf, "IIO_FXLS8962AF"); enum { fxls8962af_idx_x, @@ -209,7 +222,6 @@ static int fxls8962af_power_off(struct fxls8962af_data *data) struct device *dev = regmap_get_device(data->regmap); int ret; - pm_runtime_mark_last_busy(dev); ret = pm_runtime_put_autosuspend(dev); if (ret) dev_err(dev, "failed to power off\n"); @@ -219,8 +231,8 @@ static int fxls8962af_power_off(struct fxls8962af_data *data) static int fxls8962af_standby(struct fxls8962af_data *data) { - return regmap_update_bits(data->regmap, FXLS8962AF_SENS_CONFIG1, - FXLS8962AF_SENS_CONFIG1_ACTIVE, 0); + return regmap_clear_bits(data->regmap, FXLS8962AF_SENS_CONFIG1, + FXLS8962AF_SENS_CONFIG1_ACTIVE); } static int fxls8962af_active(struct fxls8962af_data *data) @@ -427,8 +439,16 @@ static int fxls8962af_read_raw(struct iio_dev *indio_dev, *val = FXLS8962AF_TEMP_CENTER_VAL; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - *val = 0; - return fxls8962af_read_full_scale(data, val2); + switch (chan->type) { + case IIO_TEMP: + *val = MILLIDEGREE_PER_DEGREE; + return IIO_VAL_INT; + case IIO_ACCEL: + *val = 0; + return fxls8962af_read_full_scale(data, val2); + default: + return -EINVAL; + } case IIO_CHAN_INFO_SAMP_FREQ: return fxls8962af_read_samp_freq(data, val, val2); default: @@ -448,22 +468,20 @@ static int fxls8962af_write_raw(struct iio_dev *indio_dev, if (val != 0) return -EINVAL; - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = fxls8962af_set_full_scale(data, val2); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; case IIO_CHAN_INFO_SAMP_FREQ: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = fxls8962af_set_samp_freq(data, val, val2); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; default: return -EINVAL; @@ -607,7 +625,7 @@ static int fxls8962af_write_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, - enum iio_event_direction dir, int state) + enum iio_event_direction dir, bool state) { struct fxls8962af_data *data = iio_priv(indio_dev); u8 enable_event, enable_bits; @@ -671,14 +689,13 @@ fxls8962af_write_event_config(struct iio_dev *indio_dev, fxls8962af_active(data); ret = fxls8962af_power_on(data); } else { - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; /* Not in buffered mode so disable power */ ret = fxls8962af_power_off(data); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); } return ret; @@ -717,8 +734,7 @@ static const struct iio_event_spec fxls8962af_event[] = { .sign = 's', \ .realbits = 12, \ .storagebits = 16, \ - .shift = 4, \ - .endianness = IIO_BE, \ + .endianness = IIO_LE, \ }, \ .event_spec = fxls8962af_event, \ .num_event_specs = ARRAY_SIZE(fxls8962af_event), \ @@ -728,9 +744,11 @@ static const struct iio_event_spec fxls8962af_event[] = { .type = IIO_TEMP, \ .address = FXLS8962AF_TEMP_OUT, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_OFFSET),\ .scan_index = -1, \ .scan_type = { \ + .sign = 's', \ .realbits = 8, \ .storagebits = 8, \ }, \ @@ -757,6 +775,18 @@ static const struct fxls8962af_chip_info fxls_chip_info_table[] = { .channels = fxls8962af_channels, .num_channels = ARRAY_SIZE(fxls8962af_channels), }, + [fxls8967af] = { + .chip_id = FXLS8967AF_DEVICE_ID, + .name = "fxls8967af", + .channels = fxls8962af_channels, + .num_channels = ARRAY_SIZE(fxls8962af_channels), + }, + [fxls8974cf] = { + .chip_id = FXLS8974CF_DEVICE_ID, + .name = "fxls8974cf", + .channels = fxls8962af_channels, + .num_channels = ARRAY_SIZE(fxls8962af_channels), + }, }; static const struct iio_info fxls8962af_info = { @@ -777,9 +807,8 @@ static int fxls8962af_reset(struct fxls8962af_data *data) unsigned int reg; int ret; - ret = regmap_update_bits(data->regmap, FXLS8962AF_SENS_CONFIG1, - FXLS8962AF_SENS_CONFIG1_RST, - FXLS8962AF_SENS_CONFIG1_RST); + ret = regmap_set_bits(data->regmap, FXLS8962AF_SENS_CONFIG1, + FXLS8962AF_SENS_CONFIG1_RST); if (ret) return ret; @@ -822,9 +851,8 @@ static int fxls8962af_buffer_postenable(struct iio_dev *indio_dev) fxls8962af_standby(data); /* Enable buffer interrupt */ - ret = regmap_update_bits(data->regmap, FXLS8962AF_INT_EN, - FXLS8962AF_INT_EN_BUF_EN, - FXLS8962AF_INT_EN_BUF_EN); + ret = regmap_set_bits(data->regmap, FXLS8962AF_INT_EN, + FXLS8962AF_INT_EN_BUF_EN); if (ret) return ret; @@ -843,11 +871,13 @@ static int fxls8962af_buffer_predisable(struct iio_dev *indio_dev) fxls8962af_standby(data); /* Disable buffer interrupt */ - ret = regmap_update_bits(data->regmap, FXLS8962AF_INT_EN, - FXLS8962AF_INT_EN_BUF_EN, 0); + ret = regmap_clear_bits(data->regmap, FXLS8962AF_INT_EN, + FXLS8962AF_INT_EN_BUF_EN); if (ret) return ret; + synchronize_irq(data->irq); + ret = __fxls8962af_fifo_set_mode(data, false); if (data->enable_event) @@ -897,9 +927,10 @@ static int fxls8962af_fifo_transfer(struct fxls8962af_data *data, int total_length = samples * sample_length; int ret; - if (i2c_verify_client(dev)) + if (i2c_verify_client(dev) && + data->chip_info->chip_id == FXLS8962AF_DEVICE_ID) /* - * Due to errata bug: + * Due to errata bug (only applicable on fxls8962af): * E3: FIFO burst read operation error using I2C interface * We have to avoid burst reads on I2C.. */ @@ -959,14 +990,13 @@ static int fxls8962af_fifo_flush(struct iio_dev *indio_dev) int j, bit; j = 0; - for_each_set_bit(bit, indio_dev->active_scan_mask, - indio_dev->masklength) { + iio_for_each_active_channel(indio_dev, bit) { memcpy(&data->scan.channels[j++], &buffer[i * 3 + bit], sizeof(data->scan.channels[0])); } - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - tstamp); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, + sizeof(data->scan), tstamp); tstamp += sample_period; } @@ -1043,13 +1073,6 @@ static irqreturn_t fxls8962af_interrupt(int irq, void *p) return IRQ_NONE; } -static void fxls8962af_regulator_disable(void *data_ptr) -{ - struct fxls8962af_data *data = data_ptr; - - regulator_disable(data->vdd_reg); -} - static void fxls8962af_pm_disable(void *dev_ptr) { struct device *dev = dev_ptr; @@ -1062,12 +1085,12 @@ static void fxls8962af_pm_disable(void *dev_ptr) fxls8962af_standby(iio_priv(indio_dev)); } -static void fxls8962af_get_irq(struct device_node *of_node, +static void fxls8962af_get_irq(struct device *dev, enum fxls8962af_int_pin *pin) { int irq; - irq = of_irq_get_byname(of_node, "INT2"); + irq = fwnode_irq_get_byname(dev_fwnode(dev), "INT2"); if (irq > 0) { *pin = FXLS8962AF_PIN_INT2; return; @@ -1086,7 +1109,7 @@ static int fxls8962af_irq_setup(struct iio_dev *indio_dev, int irq) u8 int_pin_sel; int ret; - fxls8962af_get_irq(dev->of_node, &int_pin); + fxls8962af_get_irq(dev, &int_pin); switch (int_pin) { case FXLS8962AF_PIN_INT1: int_pin_sel = FXLS8962AF_INT_PIN_SEL_INT1; @@ -1104,8 +1127,7 @@ static int fxls8962af_irq_setup(struct iio_dev *indio_dev, int irq) if (ret) return ret; - irq_type = irqd_get_trigger_type(irq_get_irq_data(irq)); - + irq_type = irq_get_trigger_type(irq); switch (irq_type) { case IRQF_TRIGGER_HIGH: case IRQF_TRIGGER_RISING: @@ -1163,20 +1185,10 @@ int fxls8962af_core_probe(struct device *dev, struct regmap *regmap, int irq) if (ret) return ret; - data->vdd_reg = devm_regulator_get(dev, "vdd"); - if (IS_ERR(data->vdd_reg)) - return dev_err_probe(dev, PTR_ERR(data->vdd_reg), - "Failed to get vdd regulator\n"); - - ret = regulator_enable(data->vdd_reg); - if (ret) { - dev_err(dev, "Failed to enable vdd regulator: %d\n", ret); - return ret; - } - - ret = devm_add_action_or_reset(dev, fxls8962af_regulator_disable, data); + ret = devm_regulator_get_enable(dev, "vdd"); if (ret) - return ret; + return dev_err_probe(dev, ret, + "Failed to get vdd regulator\n"); ret = regmap_read(data->regmap, FXLS8962AF_WHO_AM_I, ®); if (ret) @@ -1209,7 +1221,6 @@ int fxls8962af_core_probe(struct device *dev, struct regmap *regmap, int irq) return ret; ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, - INDIO_BUFFER_SOFTWARE, &fxls8962af_buffer_ops); if (ret) return ret; @@ -1227,14 +1238,17 @@ int fxls8962af_core_probe(struct device *dev, struct regmap *regmap, int irq) if (ret) return ret; - if (device_property_read_bool(dev, "wakeup-source")) - device_init_wakeup(dev, true); + if (device_property_read_bool(dev, "wakeup-source")) { + ret = devm_device_init_wakeup(dev); + if (ret) + return dev_err_probe(dev, ret, "Failed to init wakeup\n"); + } return devm_iio_device_register(dev, indio_dev); } -EXPORT_SYMBOL_GPL(fxls8962af_core_probe); +EXPORT_SYMBOL_NS_GPL(fxls8962af_core_probe, "IIO_FXLS8962AF"); -static int __maybe_unused fxls8962af_runtime_suspend(struct device *dev) +static int fxls8962af_runtime_suspend(struct device *dev) { struct fxls8962af_data *data = iio_priv(dev_get_drvdata(dev)); int ret; @@ -1248,14 +1262,14 @@ static int __maybe_unused fxls8962af_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused fxls8962af_runtime_resume(struct device *dev) +static int fxls8962af_runtime_resume(struct device *dev) { struct fxls8962af_data *data = iio_priv(dev_get_drvdata(dev)); return fxls8962af_active(data); } -static int __maybe_unused fxls8962af_suspend(struct device *dev) +static int fxls8962af_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct fxls8962af_data *data = iio_priv(indio_dev); @@ -1276,7 +1290,7 @@ static int __maybe_unused fxls8962af_suspend(struct device *dev) return 0; } -static int __maybe_unused fxls8962af_resume(struct device *dev) +static int fxls8962af_resume(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct fxls8962af_data *data = iio_priv(indio_dev); @@ -1293,12 +1307,10 @@ static int __maybe_unused fxls8962af_resume(struct device *dev) return 0; } -const struct dev_pm_ops fxls8962af_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(fxls8962af_suspend, fxls8962af_resume) - SET_RUNTIME_PM_OPS(fxls8962af_runtime_suspend, - fxls8962af_runtime_resume, NULL) +EXPORT_NS_GPL_DEV_PM_OPS(fxls8962af_pm_ops, IIO_FXLS8962AF) = { + SYSTEM_SLEEP_PM_OPS(fxls8962af_suspend, fxls8962af_resume) + RUNTIME_PM_OPS(fxls8962af_runtime_suspend, fxls8962af_runtime_resume, NULL) }; -EXPORT_SYMBOL_GPL(fxls8962af_pm_ops); MODULE_AUTHOR("Sean Nyekjaer <sean@geanix.com>"); MODULE_DESCRIPTION("NXP FXLS8962AF/FXLS8964AF accelerometer driver"); |
