diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-05-11 10:50:04 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-05-11 10:50:04 +0300 |
commit | 6a8b25abf1b79db6877645335c73ad6a5061d9b0 (patch) | |
tree | 5c18fa75ece496f0b4b77483ad2645e1fbdde29d /drivers/staging/iio | |
parent | 26a5e9b834a647b9d4dfbeef8b42f201cb3293ae (diff) | |
parent | d58c67d1d851d40b0094b6dd8b1a27ac9076ffa2 (diff) | |
download | linux-6a8b25abf1b79db6877645335c73ad6a5061d9b0.tar.xz |
Merge tag 'iio-for-4.18a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes:
1st round of IIO new device support, features and cleanup for the 4.18 cycle
A nice mix this time of excellent cleanups (many to send drivers
speeding toward staging graduations) and new drivers / device support.
A good part of this is Brian Masney's never ending task on the tsl2x7x
driver. The end is in sight so hopefully we'll get that one out of
staging very soon!
New device support
* AD5686
- Support AD5685R (was wrongly present as AD5685)
- Support AD5672R, AD5676, AD5676, AD5684R and AD5686R 4 and 8 channel
SPI DACs with various precisions.
- Support AD5671R, AD5675R, AD5694, AD5694R, AD5695R, AD5696 and AD5696R
I2C DACs with various percisions and numbers of channels.
* Analog front end rescale driver - New driver.
- Support current sensing usings a shunt resistor.
- Support simple voltage dividers.
- support simple current sense amplifiers.
* TI dac5571
- New driver and device bindings supporting:
dac5571, dac6571, dac7571, dac5574, dac6574, dac7574,
dac5573, dac6573 and dac7573
* Meson-adc
- Support for Meson AXG with DT bindings.
* mpu6050
- Support the mpu9255 which only requires additional WHOAMI entry and
compatible string.
* st_lsm6dsx
- Support for lsm330dlc combinded accelerometer and gyro sensors with
DT bindings.
* stm32_adc
- Add support for STM32MP1 with bindings.
Staging graduations
* adis16201 after some excelent cleanup by Himanshu Jha.
* adis16029 after some excelent cleanup by Shreeya Patel.
New features:
* ABI docs
- Add core ABI docs for angle channels.
* inv_mpu6050
- Provide support for the full range of interrupts the device
supports.
* st_accel
- Add SMO8840 ACPI ID seen in the wild on some Lenovo machines.
* stx104
- Provide a multiple gpio get function.
Cleanups / Minor fixes
* core
- Use new nested structure support to improve kernel-doc.
* ad2s1200
- Use be16_to_cpup instead of opencoding.
* ad5686
- Indentation tidy up.
- Switch to SPDX
- Refactor to allow various numbers of channels.
- Refactor to separate core and SPI specific support, prior to
addition of i2c equivalent devices.
* ad7606
- Use drvdata directly from device rather than boucing via the
platform_device structure.
* ad7746
- Replace opencoded byte swapped i2c calls with _swapped variants.
- White space and line break readability improvements.
- Reorder includes and variable declarations where appropriate.
* ad7791
- Changes to the AD ADC library used by this driver took in the
sampling frequency. This lead to be the wrong path being the one
tied to the resulting attribute, so it didn't work, and a warning
to be printed.
* ad7780
- Remove apparent support for sampling frequency control on devices
that don't support changing the sampling attributes.
* ade7854
- Fix a read of the wrong number of bits.
- Improve error handling on i2c read/write errors.
- Rework i2c and spi code to reduce duplication.
* adis16201 (staging)
- Improve meaning inherent in some macro names by adding units etc
where relevant.
- Adjust comments to improve detail and drop the irrelevant.
- Rename register address definitions definitions to add a _REG
postfix, clearly separating them from field definitions. Reorganize
the definitions to group register address and fields.
- Use sign_extend32 rather than open coding.
- Reverse Xmas tree ordering where appropriate and align function args.
- Remove unused headers.
- Use GENMASK where appropriate instead of open coding.
* adis16209 (staging)
- Indent field definitions to visually separate them from
register address definitions.
- Use reverse xmas tree ordering where appropriate.
- Add some whitespace where it will help readability.
- Drop some unused headers.
- Use GENMASK where appropriate.
* ad2s1200
- Drop unnecessary includes and reorder alphabetically.
- Reverse xmas tree and blank line cleanups.
* atlas-ph-sensor
- Use msleep instead of usleep_range where the precise value doesn't
matter and the delays are long.
* bcm150
- Drop transaction splitting as core now handles it.
* cros_ec
- Move the shared header to the include/iio/common directory.
This brings it inline with the other multiple type devices.
- Use drvdata directly from device rather than boucing via the
platform_device structure.
* hid-sensors
- Use drvdata directly from device rather than boucing via the
platform_device structure.
* inv_mpu6050
- Clear out a second function definition for the same function.
- Don't flush fifo when the iio buffer is full but just drop excess
data.
- Tidy up set_power_itg and ensure it is used in the right places.
- Use set_power_itg rather than opencoding it again in the i2c mux
control.
- Make sure error paths disable the power if undoing power on.
- Used managed devm_ functions during probe. Delete remove function.
- Refactor to pull raw data read out of read_raw function.
- Simplify data reading error paths.
- Only enable the i2c mux for chips with the i2c aux bus (not icm20608)
- Fix a potential deadlock due to varying lock ordering.
- Fix an issue where first sample from gyro after enabling is unstable
by dropping the first sample.
- Fix an issue where the user_ctrl register is incorrectly overwritten.
- Tidy up some grammar and spelling minor issus.
* mcp320x
- Use vendor compatible strings.
* mcp4018
- Switch to using i2c .probe_new.
* mcp4351
- switch to using i2c .probe_new.
* meson-adc
- rework handing on common ADC platform data so it can be shared
across multiple families of SoCs.
* sca3000
- Fix an error handling path if the ring configure fails.
* st_lsm6dsx
- Fix a wrong fifo threshold mask (no actual effect)
* stm32-dfsdm
- Style fixes and cleanups.
- Check filter ID is in range and check spi-max-frequency.
* tsl2x7x (staging)
- Drop some unnecessary function calls, unused variables and
unnecessary local variables.
- Fix wrong interrupt type.
- Avoid unnecessary double clear of interrupt.
- Simplify proximity calibration call which did various things
unrelated to actually calibrating.
- Separate control of the proximity and ALS interrupts.
- Improve consistency of logging.
- Separate ALS and proximity persistence settings as they have
separate hardware controls.
- Tidy up variable ordering.
- Add Brian to copyright notice given consider work on this driver.
- Take advantage of hardware support for I2C address auto increment.
- Combine individuaal enable and period attributes for the two
directions on the threshold events into a single value as the
hardware doesn't separate them.
- Move integration_time* attributes from light channel to
intensity value as they effect the intensity readings directly
and the light reading only indirectly. Hence this better
reflects reality. Also move the calibscale_available.
- Avoid returning an error in the IRQ handler.
- Hard code the reg value in _clear_interrupts as it only takes
one value in the code. Result is the function has little
purpose so opencode the two remaining i2c_smbus_write_byte
calls.
- Drop some unnecessary checking of the chip status register.
- Tidy up return path in _write_interrupt_config.
- Tidy up the ID verification code.
- Move the power and diode settings defines into the header as these
are needed for platform data configuration.
- Various renames and comment cleanups for consistency and clarity.
- Use actual device defaults for default startup settings.
- SPDX
- Add some range sanity checking to sysfs attribute writes.
- Don't provide event interfaces if the interrupt line isn't available.
- Use IIO_CONST_ATTR macro for calibscale_available as it's a constant
string.
- Fix the integration time and lux equations.
- Make device IDs explicit index values in the device_channel_config array.
Diffstat (limited to 'drivers/staging/iio')
-rw-r--r-- | drivers/staging/iio/accel/Kconfig | 24 | ||||
-rw-r--r-- | drivers/staging/iio/accel/Makefile | 2 | ||||
-rw-r--r-- | drivers/staging/iio/accel/adis16201.c | 385 | ||||
-rw-r--r-- | drivers/staging/iio/accel/adis16209.c | 334 | ||||
-rw-r--r-- | drivers/staging/iio/adc/ad7606_par.c | 6 | ||||
-rw-r--r-- | drivers/staging/iio/adc/ad7780.c | 2 | ||||
-rw-r--r-- | drivers/staging/iio/cdc/ad7746.c | 44 | ||||
-rw-r--r-- | drivers/staging/iio/light/tsl2x7x.c | 935 | ||||
-rw-r--r-- | drivers/staging/iio/light/tsl2x7x.h | 91 | ||||
-rw-r--r-- | drivers/staging/iio/meter/ade7854-i2c.c | 238 | ||||
-rw-r--r-- | drivers/staging/iio/meter/ade7854-spi.c | 268 | ||||
-rw-r--r-- | drivers/staging/iio/meter/ade7854.c | 40 | ||||
-rw-r--r-- | drivers/staging/iio/meter/ade7854.h | 16 | ||||
-rw-r--r-- | drivers/staging/iio/resolver/ad2s1200.c | 35 |
14 files changed, 649 insertions, 1771 deletions
diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig index c6b0f5eae7ab..befbbfe911c2 100644 --- a/drivers/staging/iio/accel/Kconfig +++ b/drivers/staging/iio/accel/Kconfig @@ -3,18 +3,6 @@ # menu "Accelerometers" -config ADIS16201 - tristate "Analog Devices ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer" - depends on SPI - select IIO_ADIS_LIB - select IIO_ADIS_LIB_BUFFER if IIO_BUFFER - help - Say Y here to build support for Analog Devices adis16201 dual-axis - digital inclinometer and accelerometer. - - To compile this driver as a module, say M here: the module will - be called adis16201. - config ADIS16203 tristate "Analog Devices ADIS16203 Programmable 360 Degrees Inclinometer" depends on SPI @@ -27,18 +15,6 @@ config ADIS16203 To compile this driver as a module, say M here: the module will be called adis16203. -config ADIS16209 - tristate "Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer" - depends on SPI - select IIO_ADIS_LIB - select IIO_ADIS_LIB_BUFFER if IIO_BUFFER - help - Say Y here to build support for Analog Devices adis16209 dual-axis digital inclinometer - and accelerometer. - - To compile this driver as a module, say M here: the module will be - called adis16209. - config ADIS16240 tristate "Analog Devices ADIS16240 Programmable Impact Sensor and Recorder" depends on SPI diff --git a/drivers/staging/iio/accel/Makefile b/drivers/staging/iio/accel/Makefile index 5d8ad21a0dae..773212e0c859 100644 --- a/drivers/staging/iio/accel/Makefile +++ b/drivers/staging/iio/accel/Makefile @@ -2,7 +2,5 @@ # Makefile for industrial I/O accelerometer drivers # -obj-$(CONFIG_ADIS16201) += adis16201.o obj-$(CONFIG_ADIS16203) += adis16203.o -obj-$(CONFIG_ADIS16209) += adis16209.o obj-$(CONFIG_ADIS16240) += adis16240.o diff --git a/drivers/staging/iio/accel/adis16201.c b/drivers/staging/iio/accel/adis16201.c deleted file mode 100644 index 0fae8aaf1cf4..000000000000 --- a/drivers/staging/iio/accel/adis16201.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/slab.h> -#include <linux/spi/spi.h> -#include <linux/sysfs.h> - -#include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> -#include <linux/iio/buffer.h> -#include <linux/iio/imu/adis.h> - -#define ADIS16201_STARTUP_DELAY 220 /* ms */ - -/* Flash memory write count */ -#define ADIS16201_FLASH_CNT 0x00 - -/* Output, power supply */ -#define ADIS16201_SUPPLY_OUT 0x02 - -/* Output, x-axis accelerometer */ -#define ADIS16201_XACCL_OUT 0x04 - -/* Output, y-axis accelerometer */ -#define ADIS16201_YACCL_OUT 0x06 - -/* Output, auxiliary ADC input */ -#define ADIS16201_AUX_ADC 0x08 - -/* Output, temperature */ -#define ADIS16201_TEMP_OUT 0x0A - -/* Output, x-axis inclination */ -#define ADIS16201_XINCL_OUT 0x0C - -/* Output, y-axis inclination */ -#define ADIS16201_YINCL_OUT 0x0E - -/* Calibration, x-axis acceleration offset */ -#define ADIS16201_XACCL_OFFS 0x10 - -/* Calibration, y-axis acceleration offset */ -#define ADIS16201_YACCL_OFFS 0x12 - -/* x-axis acceleration scale factor */ -#define ADIS16201_XACCL_SCALE 0x14 - -/* y-axis acceleration scale factor */ -#define ADIS16201_YACCL_SCALE 0x16 - -/* Calibration, x-axis inclination offset */ -#define ADIS16201_XINCL_OFFS 0x18 - -/* Calibration, y-axis inclination offset */ -#define ADIS16201_YINCL_OFFS 0x1A - -/* x-axis inclination scale factor */ -#define ADIS16201_XINCL_SCALE 0x1C - -/* y-axis inclination scale factor */ -#define ADIS16201_YINCL_SCALE 0x1E - -/* Alarm 1 amplitude threshold */ -#define ADIS16201_ALM_MAG1 0x20 - -/* Alarm 2 amplitude threshold */ -#define ADIS16201_ALM_MAG2 0x22 - -/* Alarm 1, sample period */ -#define ADIS16201_ALM_SMPL1 0x24 - -/* Alarm 2, sample period */ -#define ADIS16201_ALM_SMPL2 0x26 - -/* Alarm control */ -#define ADIS16201_ALM_CTRL 0x28 - -/* Auxiliary DAC data */ -#define ADIS16201_AUX_DAC 0x30 - -/* General-purpose digital input/output control */ -#define ADIS16201_GPIO_CTRL 0x32 - -/* Miscellaneous control */ -#define ADIS16201_MSC_CTRL 0x34 - -/* Internal sample period (rate) control */ -#define ADIS16201_SMPL_PRD 0x36 - -/* Operation, filter configuration */ -#define ADIS16201_AVG_CNT 0x38 - -/* Operation, sleep mode control */ -#define ADIS16201_SLP_CNT 0x3A - -/* Diagnostics, system status register */ -#define ADIS16201_DIAG_STAT 0x3C - -/* Operation, system command register */ -#define ADIS16201_GLOB_CMD 0x3E - -/* MSC_CTRL */ - -/* Self-test enable */ -#define ADIS16201_MSC_CTRL_SELF_TEST_EN BIT(8) - -/* Data-ready enable: 1 = enabled, 0 = disabled */ -#define ADIS16201_MSC_CTRL_DATA_RDY_EN BIT(2) - -/* Data-ready polarity: 1 = active high, 0 = active low */ -#define ADIS16201_MSC_CTRL_ACTIVE_HIGH BIT(1) - -/* Data-ready line selection: 1 = DIO1, 0 = DIO0 */ -#define ADIS16201_MSC_CTRL_DATA_RDY_DIO1 BIT(0) - -/* DIAG_STAT */ - -/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ -#define ADIS16201_DIAG_STAT_ALARM2 BIT(9) - -/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ -#define ADIS16201_DIAG_STAT_ALARM1 BIT(8) - -/* SPI communications failure */ -#define ADIS16201_DIAG_STAT_SPI_FAIL_BIT 3 - -/* Flash update failure */ -#define ADIS16201_DIAG_STAT_FLASH_UPT_BIT 2 - -/* Power supply above 3.625 V */ -#define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1 - -/* Power supply below 3.15 V */ -#define ADIS16201_DIAG_STAT_POWER_LOW_BIT 0 - -/* GLOB_CMD */ - -#define ADIS16201_GLOB_CMD_SW_RESET BIT(7) -#define ADIS16201_GLOB_CMD_FACTORY_CAL BIT(1) - -#define ADIS16201_ERROR_ACTIVE BIT(14) - -enum adis16201_scan { - ADIS16201_SCAN_ACC_X, - ADIS16201_SCAN_ACC_Y, - ADIS16201_SCAN_INCLI_X, - ADIS16201_SCAN_INCLI_Y, - ADIS16201_SCAN_SUPPLY, - ADIS16201_SCAN_AUX_ADC, - ADIS16201_SCAN_TEMP, -}; - -static const u8 adis16201_addresses[] = { - [ADIS16201_SCAN_ACC_X] = ADIS16201_XACCL_OFFS, - [ADIS16201_SCAN_ACC_Y] = ADIS16201_YACCL_OFFS, - [ADIS16201_SCAN_INCLI_X] = ADIS16201_XINCL_OFFS, - [ADIS16201_SCAN_INCLI_Y] = ADIS16201_YINCL_OFFS, -}; - -static int adis16201_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - struct adis *st = iio_priv(indio_dev); - int ret; - int bits; - u8 addr; - s16 val16; - - switch (mask) { - case IIO_CHAN_INFO_RAW: - return adis_single_conversion(indio_dev, chan, - ADIS16201_ERROR_ACTIVE, val); - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_VOLTAGE: - if (chan->channel == 0) { - *val = 1; - *val2 = 220000; /* 1.22 mV */ - } else { - *val = 0; - *val2 = 610000; /* 0.610 mV */ - } - return IIO_VAL_INT_PLUS_MICRO; - case IIO_TEMP: - *val = -470; /* 0.47 C */ - *val2 = 0; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_ACCEL: - *val = 0; - *val2 = IIO_G_TO_M_S_2(462400); /* 0.4624 mg */ - return IIO_VAL_INT_PLUS_NANO; - case IIO_INCLI: - *val = 0; - *val2 = 100000; /* 0.1 degree */ - return IIO_VAL_INT_PLUS_MICRO; - default: - return -EINVAL; - } - break; - case IIO_CHAN_INFO_OFFSET: - *val = 25000 / -470 - 1278; /* 25 C = 1278 */ - return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBBIAS: - switch (chan->type) { - case IIO_ACCEL: - bits = 12; - break; - case IIO_INCLI: - bits = 9; - break; - default: - return -EINVAL; - } - addr = adis16201_addresses[chan->scan_index]; - ret = adis_read_reg_16(st, addr, &val16); - if (ret) - return ret; - val16 &= (1 << bits) - 1; - val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); - *val = val16; - return IIO_VAL_INT; - } - - return -EINVAL; -} - -static int adis16201_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct adis *st = iio_priv(indio_dev); - int bits; - s16 val16; - u8 addr; - - switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS: - switch (chan->type) { - case IIO_ACCEL: - bits = 12; - break; - case IIO_INCLI: - bits = 9; - break; - default: - return -EINVAL; - } - val16 = val & ((1 << bits) - 1); - addr = adis16201_addresses[chan->scan_index]; - return adis_write_reg_16(st, addr, val16); - } - - return -EINVAL; -} - -static const struct iio_chan_spec adis16201_channels[] = { - ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 0, 12), - ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 0, 12), - ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT, ADIS16201_SCAN_ACC_X, - BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), - ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT, ADIS16201_SCAN_ACC_Y, - BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), - ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 0, 12), - ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT, ADIS16201_SCAN_INCLI_X, - BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), - ADIS_INCLI_CHAN(X, ADIS16201_YINCL_OUT, ADIS16201_SCAN_INCLI_Y, - BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), - IIO_CHAN_SOFT_TIMESTAMP(7) -}; - -static const struct iio_info adis16201_info = { - .read_raw = adis16201_read_raw, - .write_raw = adis16201_write_raw, - .update_scan_mode = adis_update_scan_mode, -}; - -static const char * const adis16201_status_error_msgs[] = { - [ADIS16201_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure", - [ADIS16201_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed", - [ADIS16201_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V", - [ADIS16201_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V", -}; - -static const struct adis_data adis16201_data = { - .read_delay = 20, - .msc_ctrl_reg = ADIS16201_MSC_CTRL, - .glob_cmd_reg = ADIS16201_GLOB_CMD, - .diag_stat_reg = ADIS16201_DIAG_STAT, - - .self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN, - .self_test_no_autoclear = true, - .startup_delay = ADIS16201_STARTUP_DELAY, - - .status_error_msgs = adis16201_status_error_msgs, - .status_error_mask = BIT(ADIS16201_DIAG_STAT_SPI_FAIL_BIT) | - BIT(ADIS16201_DIAG_STAT_FLASH_UPT_BIT) | - BIT(ADIS16201_DIAG_STAT_POWER_HIGH_BIT) | - BIT(ADIS16201_DIAG_STAT_POWER_LOW_BIT), -}; - -static int adis16201_probe(struct spi_device *spi) -{ - int ret; - struct adis *st; - struct iio_dev *indio_dev; - - /* setup the industrialio driver allocated elements */ - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); - if (!indio_dev) - return -ENOMEM; - - st = iio_priv(indio_dev); - /* this is only used for removal purposes */ - spi_set_drvdata(spi, indio_dev); - - indio_dev->name = spi->dev.driver->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &adis16201_info; - - indio_dev->channels = adis16201_channels; - indio_dev->num_channels = ARRAY_SIZE(adis16201_channels); - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = adis_init(st, indio_dev, spi, &adis16201_data); - if (ret) - return ret; - - ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL); - if (ret) - return ret; - - /* Get the device into a sane initial state */ - ret = adis_initial_startup(st); - if (ret) - goto error_cleanup_buffer_trigger; - - ret = iio_device_register(indio_dev); - if (ret < 0) - goto error_cleanup_buffer_trigger; - - return 0; - -error_cleanup_buffer_trigger: - adis_cleanup_buffer_and_trigger(st, indio_dev); - return ret; -} - -static int adis16201_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct adis *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - adis_cleanup_buffer_and_trigger(st, indio_dev); - - return 0; -} - -static struct spi_driver adis16201_driver = { - .driver = { - .name = "adis16201", - }, - .probe = adis16201_probe, - .remove = adis16201_remove, -}; -module_spi_driver(adis16201_driver); - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:adis16201"); diff --git a/drivers/staging/iio/accel/adis16209.c b/drivers/staging/iio/accel/adis16209.c deleted file mode 100644 index 72a18cfe81ee..000000000000 --- a/drivers/staging/iio/accel/adis16209.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> - -#include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> -#include <linux/iio/buffer.h> -#include <linux/iio/imu/adis.h> - -#define ADIS16209_STARTUP_DELAY_MS 220 -#define ADIS16209_FLASH_CNT_REG 0x00 - -/* Data Output Register Definitions */ -#define ADIS16209_SUPPLY_OUT_REG 0x02 -#define ADIS16209_XACCL_OUT_REG 0x04 -#define ADIS16209_YACCL_OUT_REG 0x06 -/* Output, auxiliary ADC input */ -#define ADIS16209_AUX_ADC_REG 0x08 -/* Output, temperature */ -#define ADIS16209_TEMP_OUT_REG 0x0A -/* Output, +/- 90 degrees X-axis inclination */ -#define ADIS16209_XINCL_OUT_REG 0x0C -#define ADIS16209_YINCL_OUT_REG 0x0E -/* Output, +/-180 vertical rotational position */ -#define ADIS16209_ROT_OUT_REG 0x10 - -/* - * Calibration Register Definitions. - * Acceleration, inclination or rotation offset null. - */ -#define ADIS16209_XACCL_NULL_REG 0x12 -#define ADIS16209_YACCL_NULL_REG 0x14 -#define ADIS16209_XINCL_NULL_REG 0x16 -#define ADIS16209_YINCL_NULL_REG 0x18 -#define ADIS16209_ROT_NULL_REG 0x1A - -/* Alarm Register Definitions */ -#define ADIS16209_ALM_MAG1_REG 0x20 -#define ADIS16209_ALM_MAG2_REG 0x22 -#define ADIS16209_ALM_SMPL1_REG 0x24 -#define ADIS16209_ALM_SMPL2_REG 0x26 -#define ADIS16209_ALM_CTRL_REG 0x28 - -#define ADIS16209_AUX_DAC_REG 0x30 -#define ADIS16209_GPIO_CTRL_REG 0x32 -#define ADIS16209_SMPL_PRD_REG 0x36 -#define ADIS16209_AVG_CNT_REG 0x38 -#define ADIS16209_SLP_CNT_REG 0x3A - -#define ADIS16209_MSC_CTRL_REG 0x34 -#define ADIS16209_MSC_CTRL_PWRUP_SELF_TEST BIT(10) -#define ADIS16209_MSC_CTRL_SELF_TEST_EN BIT(8) -#define ADIS16209_MSC_CTRL_DATA_RDY_EN BIT(2) -/* Data-ready polarity: 1 = active high, 0 = active low */ -#define ADIS16209_MSC_CTRL_ACTIVE_HIGH BIT(1) -#define ADIS16209_MSC_CTRL_DATA_RDY_DIO2 BIT(0) - -#define ADIS16209_STAT_REG 0x3C -#define ADIS16209_STAT_ALARM2 BIT(9) -#define ADIS16209_STAT_ALARM1 BIT(8) -#define ADIS16209_STAT_SELFTEST_FAIL_BIT 5 -#define ADIS16209_STAT_SPI_FAIL_BIT 3 -#define ADIS16209_STAT_FLASH_UPT_FAIL_BIT 2 -/* Power supply above 3.625 V */ -#define ADIS16209_STAT_POWER_HIGH_BIT 1 -/* Power supply below 3.15 V */ -#define ADIS16209_STAT_POWER_LOW_BIT 0 - -#define ADIS16209_CMD_REG 0x3E -#define ADIS16209_CMD_SW_RESET BIT(7) -#define ADIS16209_CMD_CLEAR_STAT BIT(4) -#define ADIS16209_CMD_FACTORY_CAL BIT(1) - -#define ADIS16209_ERROR_ACTIVE BIT(14) - -enum adis16209_scan { - ADIS16209_SCAN_SUPPLY, - ADIS16209_SCAN_ACC_X, - ADIS16209_SCAN_ACC_Y, - ADIS16209_SCAN_AUX_ADC, - ADIS16209_SCAN_TEMP, - ADIS16209_SCAN_INCLI_X, - ADIS16209_SCAN_INCLI_Y, - ADIS16209_SCAN_ROT, -}; - -static const u8 adis16209_addresses[8][1] = { - [ADIS16209_SCAN_SUPPLY] = { }, - [ADIS16209_SCAN_AUX_ADC] = { }, - [ADIS16209_SCAN_ACC_X] = { ADIS16209_XACCL_NULL_REG }, - [ADIS16209_SCAN_ACC_Y] = { ADIS16209_YACCL_NULL_REG }, - [ADIS16209_SCAN_INCLI_X] = { ADIS16209_XINCL_NULL_REG }, - [ADIS16209_SCAN_INCLI_Y] = { ADIS16209_YINCL_NULL_REG }, - [ADIS16209_SCAN_ROT] = { }, - [ADIS16209_SCAN_TEMP] = { }, -}; - -static int adis16209_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct adis *st = iio_priv(indio_dev); - int bits; - s16 val16; - u8 addr; - - switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS: - switch (chan->type) { - case IIO_ACCEL: - case IIO_INCLI: - bits = 14; - break; - default: - return -EINVAL; - } - val16 = val & ((1 << bits) - 1); - addr = adis16209_addresses[chan->scan_index][0]; - return adis_write_reg_16(st, addr, val16); - } - return -EINVAL; -} - -static int adis16209_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - struct adis *st = iio_priv(indio_dev); - int ret; - int bits; - u8 addr; - s16 val16; - - switch (mask) { - case IIO_CHAN_INFO_RAW: - return adis_single_conversion(indio_dev, chan, - ADIS16209_ERROR_ACTIVE, val); - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_VOLTAGE: - *val = 0; - switch (chan->channel) { - case 0: - *val2 = 305180; /* 0.30518 mV */ - break; - case 1: - *val2 = 610500; /* 0.6105 mV */ - break; - default: - return -EINVAL; - } - return IIO_VAL_INT_PLUS_MICRO; - case IIO_TEMP: - *val = -470; - *val2 = 0; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_ACCEL: - /* - * IIO base unit for sensitivity of accelerometer - * is milli g. - * 1 LSB represents 0.244 mg. - */ - *val = 0; - *val2 = IIO_G_TO_M_S_2(244140); - return IIO_VAL_INT_PLUS_NANO; - case IIO_INCLI: - case IIO_ROT: - /* - * IIO base units for rotation are degrees. - * 1 LSB represents 0.025 milli degrees. - */ - *val = 0; - *val2 = 25000; - return IIO_VAL_INT_PLUS_MICRO; - default: - return -EINVAL; - } - break; - case IIO_CHAN_INFO_OFFSET: - /* - * The raw ADC value is 0x4FE when the temperature - * is 25 degrees and the scale factor per milli - * degree celcius is -470. - */ - *val = 25000 / -470 - 0x4FE; - return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBBIAS: - switch (chan->type) { - case IIO_ACCEL: - bits = 14; - break; - default: - return -EINVAL; - } - addr = adis16209_addresses[chan->scan_index][0]; - ret = adis_read_reg_16(st, addr, &val16); - if (ret) - return ret; - - *val = sign_extend32(val16, bits - 1); - return IIO_VAL_INT; - } - return -EINVAL; -} - -static const struct iio_chan_spec adis16209_channels[] = { - ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT_REG, ADIS16209_SCAN_SUPPLY, - 0, 14), - ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT_REG, ADIS16209_SCAN_TEMP, 0, 12), - ADIS_ACCEL_CHAN(X, ADIS16209_XACCL_OUT_REG, ADIS16209_SCAN_ACC_X, - BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), - ADIS_ACCEL_CHAN(Y, ADIS16209_YACCL_OUT_REG, ADIS16209_SCAN_ACC_Y, - BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), - ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC_REG, ADIS16209_SCAN_AUX_ADC, 0, 12), - ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT_REG, ADIS16209_SCAN_INCLI_X, - 0, 0, 14), - ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT_REG, ADIS16209_SCAN_INCLI_Y, - 0, 0, 14), - ADIS_ROT_CHAN(X, ADIS16209_ROT_OUT_REG, ADIS16209_SCAN_ROT, 0, 0, 14), - IIO_CHAN_SOFT_TIMESTAMP(8) -}; - -static const struct iio_info adis16209_info = { - .read_raw = adis16209_read_raw, - .write_raw = adis16209_write_raw, - .update_scan_mode = adis_update_scan_mode, -}; - -static const char * const adis16209_status_error_msgs[] = { - [ADIS16209_STAT_SELFTEST_FAIL_BIT] = "Self test failure", - [ADIS16209_STAT_SPI_FAIL_BIT] = "SPI failure", - [ADIS16209_STAT_FLASH_UPT_FAIL_BIT] = "Flash update failed", - [ADIS16209_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V", - [ADIS16209_STAT_POWER_LOW_BIT] = "Power supply below 3.15V", -}; - -static const struct adis_data adis16209_data = { - .read_delay = 30, - .msc_ctrl_reg = ADIS16209_MSC_CTRL_REG, - .glob_cmd_reg = ADIS16209_CMD_REG, - .diag_stat_reg = ADIS16209_STAT_REG, - - .self_test_mask = ADIS16209_MSC_CTRL_SELF_TEST_EN, - .self_test_no_autoclear = true, - .startup_delay = ADIS16209_STARTUP_DELAY_MS, - - .status_error_msgs = adis16209_status_error_msgs, - .status_error_mask = BIT(ADIS16209_STAT_SELFTEST_FAIL_BIT) | - BIT(ADIS16209_STAT_SPI_FAIL_BIT) | - BIT(ADIS16209_STAT_FLASH_UPT_FAIL_BIT) | - BIT(ADIS16209_STAT_POWER_HIGH_BIT) | - BIT(ADIS16209_STAT_POWER_LOW_BIT), -}; - -static int adis16209_probe(struct spi_device *spi) -{ - int ret; - struct adis *st; - struct iio_dev *indio_dev; - - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); - if (!indio_dev) - return -ENOMEM; - st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); - - indio_dev->name = spi->dev.driver->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &adis16209_info; - indio_dev->channels = adis16209_channels; - indio_dev->num_channels = ARRAY_SIZE(adis16209_channels); - indio_dev->modes = INDIO_DIRECT_MODE; - - ret = adis_init(st, indio_dev, spi, &adis16209_data); - if (ret) - return ret; - ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL); - if (ret) - return ret; - - ret = adis_initial_startup(st); - if (ret) - goto error_cleanup_buffer_trigger; - ret = iio_device_register(indio_dev); - if (ret) - goto error_cleanup_buffer_trigger; - - return 0; - -error_cleanup_buffer_trigger: - adis_cleanup_buffer_and_trigger(st, indio_dev); - return ret; -} - -static int adis16209_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct adis *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - adis_cleanup_buffer_and_trigger(st, indio_dev); - - return 0; -} - -static struct spi_driver adis16209_driver = { - .driver = { - .name = "adis16209", - }, - .probe = adis16209_probe, - .remove = adis16209_remove, -}; -module_spi_driver(adis16209_driver); - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:adis16209"); diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index 3eb6f8f312dd..a34c2a1d5373 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -18,8 +18,7 @@ static int ad7606_par16_read_block(struct device *dev, int count, void *buf) { - struct platform_device *pdev = to_platform_device(dev); - struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad7606_state *st = iio_priv(indio_dev); insw((unsigned long)st->base_address, buf, count); @@ -34,8 +33,7 @@ static const struct ad7606_bus_ops ad7606_par16_bops = { static int ad7606_par8_read_block(struct device *dev, int count, void *buf) { - struct platform_device *pdev = to_platform_device(dev); - struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad7606_state *st = iio_priv(indio_dev); insb((unsigned long)st->base_address, buf, count * 2); diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c index a7797af579b9..16d72072c076 100644 --- a/drivers/staging/iio/adc/ad7780.c +++ b/drivers/staging/iio/adc/ad7780.c @@ -128,7 +128,7 @@ static const struct ad_sigma_delta_info ad7780_sigma_delta_info = { }; #define AD7780_CHANNEL(bits, wordsize) \ - AD_SD_CHANNEL(1, 0, 0, bits, 32, wordsize - bits) + AD_SD_CHANNEL_NO_SAMP_FREQ(1, 0, 0, bits, 32, wordsize - bits) static const struct ad7780_chip_info ad7780_chip_info_tbl[] = { [ID_AD7170] = { diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 4882dbc81c53..f53612a6461d 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -6,15 +6,15 @@ * Licensed under the GPL-2. */ -#include <linux/interrupt.h> +#include <linux/delay.h> #include <linux/device.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/sysfs.h> #include <linux/i2c.h> -#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> #include <linux/module.h> +#include <linux/slab.h> #include <linux/stat.h> +#include <linux/sysfs.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> @@ -220,8 +220,8 @@ static int ad7746_select_channel(struct iio_dev *indio_dev, struct iio_chan_spec const *chan) { struct ad7746_chip_info *chip = iio_priv(indio_dev); - int ret, delay, idx; u8 vt_setup, cap_setup; + int ret, delay, idx; switch (chan->type) { case IIO_CAPACITANCE: @@ -289,8 +289,8 @@ static inline ssize_t ad7746_start_calib(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7746_chip_info *chip = iio_priv(indio_dev); - bool doit; int ret, timeout = 10; + bool doit; ret = strtobool(buf, &doit); if (ret < 0) @@ -410,8 +410,7 @@ static struct attribute *ad7746_attributes[] = { &iio_dev_attr_in_capacitance1_calibbias_calibration.dev_attr.attr, &iio_dev_attr_in_voltage0_calibscale_calibration.dev_attr.attr, &iio_const_attr_in_voltage_sampling_frequency_available.dev_attr.attr, - &iio_const_attr_in_capacitance_sampling_frequency_available. - dev_attr.attr, + &iio_const_attr_in_capacitance_sampling_frequency_available.dev_attr.attr, NULL, }; @@ -451,26 +450,26 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, goto out; } - ret = i2c_smbus_write_word_data(chip->client, reg, swab16(val)); + ret = i2c_smbus_write_word_swapped(chip->client, reg, val); if (ret < 0) goto out; ret = 0; break; case IIO_CHAN_INFO_CALIBBIAS: - if ((val < 0) | (val > 0xFFFF)) { + if (val < 0 || val > 0xFFFF) { ret = -EINVAL; goto out; } - ret = i2c_smbus_write_word_data(chip->client, - AD7746_REG_CAP_OFFH, swab16(val)); + ret = i2c_smbus_write_word_swapped(chip->client, + AD7746_REG_CAP_OFFH, val); if (ret < 0) goto out; ret = 0; break; case IIO_CHAN_INFO_OFFSET: - if ((val < 0) | (val > 43008000)) { /* 21pF */ + if (val < 0 || val > 43008000) { /* 21pF */ ret = -EINVAL; goto out; } @@ -556,7 +555,8 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, /* Now read the actual register */ ret = i2c_smbus_read_i2c_block_data(chip->client, - chan->address >> 8, 3, &chip->data.d8[1]); + chan->address >> 8, 3, + &chip->data.d8[1]); if (ret < 0) goto out; @@ -594,27 +594,27 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, goto out; } - ret = i2c_smbus_read_word_data(chip->client, reg); + ret = i2c_smbus_read_word_swapped(chip->client, reg); if (ret < 0) goto out; /* 1 + gain_val / 2^16 */ *val = 1; - *val2 = (15625 * swab16(ret)) / 1024; + *val2 = (15625 * ret) / 1024; ret = IIO_VAL_INT_PLUS_MICRO; break; case IIO_CHAN_INFO_CALIBBIAS: - ret = i2c_smbus_read_word_data(chip->client, - AD7746_REG_CAP_OFFH); + ret = i2c_smbus_read_word_swapped(chip->client, + AD7746_REG_CAP_OFFH); if (ret < 0) goto out; - *val = swab16(ret); + *val = ret; ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_OFFSET: *val = AD7746_CAPDAC_DACP(chip->capdac[chan->channel] - [chan->differential]) * 338646; + [chan->differential]) * 338646; ret = IIO_VAL_INT; break; @@ -680,8 +680,8 @@ static int ad7746_probe(struct i2c_client *client, struct ad7746_platform_data *pdata = client->dev.platform_data; struct ad7746_chip_info *chip; struct iio_dev *indio_dev; - int ret = 0; unsigned char regval = 0; + int ret = 0; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); if (!indio_dev) diff --git a/drivers/staging/iio/light/tsl2x7x.c b/drivers/staging/iio/light/tsl2x7x.c index 82681300e106..cc863e8927f5 100644 --- a/drivers/staging/iio/light/tsl2x7x.c +++ b/drivers/staging/iio/light/tsl2x7x.c @@ -1,18 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * Device driver for monitoring ambient light intensity in (lux) - * and proximity detection (prox) within the TAOS TSL2X7X family of devices. + * Device driver for monitoring ambient light intensity in (lux) and proximity + * detection (prox) within the TAOS TSL2X7X family of devices. * * Copyright (c) 2012, TAOS Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. + * Copyright (c) 2017-2018 Brian Masney <masneyb@onstation.org> */ #include <linux/delay.h> @@ -28,7 +20,7 @@ #include <linux/iio/sysfs.h> #include "tsl2x7x.h" -/* Cal defs*/ +/* Cal defs */ #define PROX_STAT_CAL 0 #define PROX_STAT_SAMP 1 #define MAX_SAMPLES_CAL 200 @@ -41,10 +33,11 @@ /* Lux calculation constants */ #define TSL2X7X_LUX_CALC_OVER_FLOW 65535 -/* TAOS Register definitions - note: - * depending on device, some of these register are not used and the - * register address is benign. +/* + * TAOS Register definitions - Note: depending on device, some of these register + * are not used and the register address is benign. */ + /* 2X7X register offsets */ #define TSL2X7X_MAX_CONFIG_REG 16 @@ -62,7 +55,7 @@ #define TSL2X7X_PRX_MAXTHRESHLO 0X0A #define TSL2X7X_PRX_MAXTHRESHHI 0X0B #define TSL2X7X_PERSISTENCE 0x0C -#define TSL2X7X_PRX_CONFIG 0x0D +#define TSL2X7X_ALS_PRX_CONFIG 0x0D #define TSL2X7X_PRX_COUNT 0x0E #define TSL2X7X_GAIN 0x0F #define TSL2X7X_NOTUSED 0x10 @@ -79,6 +72,8 @@ /* tsl2X7X cmd reg masks */ #define TSL2X7X_CMD_REG 0x80 #define TSL2X7X_CMD_SPL_FN 0x60 +#define TSL2X7X_CMD_REPEAT_PROTO 0x00 +#define TSL2X7X_CMD_AUTOINC_PROTO 0x20 #define TSL2X7X_CMD_PROX_INT_CLR 0X05 #define TSL2X7X_CMD_ALS_INT_CLR 0x06 @@ -108,18 +103,6 @@ #define TSL2X7X_CNTL_PROXPON_ENBL 0x0F #define TSL2X7X_CNTL_INTPROXPON_ENBL 0x2F -/*Prox diode to use */ -#define TSL2X7X_DIODE0 0x01 -#define TSL2X7X_DIODE1 0x02 -#define TSL2X7X_DIODE_BOTH 0x03 - -/* LED Power */ -#define TSL2X7X_100_mA 0x00 -#define TSL2X7X_50_mA 0x01 -#define TSL2X7X_25_mA 0x02 -#define TSL2X7X_13_mA 0x03 -#define TSL2X7X_MAX_TIMER_CNT 0xFF - #define TSL2X7X_MIN_ITIME 3 /* TAOS txx2x7x Device family members */ @@ -149,17 +132,11 @@ struct tsl2x7x_als_info { u16 lux; }; -struct tsl2x7x_prox_stat { - int min; - int max; - int mean; - unsigned long stddev; -}; - struct tsl2x7x_chip_info { int chan_table_elements; - struct iio_chan_spec channel[4]; - const struct iio_info *info; + struct iio_chan_spec channel_with_events[4]; + struct iio_chan_spec channel_without_events[4]; + const struct iio_info *info; }; struct tsl2X7X_chip { @@ -171,7 +148,7 @@ struct tsl2X7X_chip { struct tsl2x7x_als_info als_cur_info; struct tsl2x7x_settings settings; struct tsl2X7X_platform_data *pdata; - int als_time_scale; + int als_gain_time_scale; int als_saturation; int tsl2x7x_chip_status; u8 tsl2x7x_config[TSL2X7X_MAX_CONFIG_REG]; @@ -186,29 +163,36 @@ struct tsl2X7X_chip { struct tsl2x7x_lux tsl2x7x_device_lux[TSL2X7X_MAX_LUX_TABLE_SIZE]; }; -/* Different devices require different coefficents */ +/* + * Different devices require different coefficents, and these numbers were + * derived from the 'Lux Equation' section of the various device datasheets. + * All of these coefficients assume a Glass Attenuation (GA) factor of 1. + * The coefficients are multiplied by 1000 to avoid floating point operations. + * The two rows in each table correspond to the Lux1 and Lux2 equations from + * the datasheets. + */ static const struct tsl2x7x_lux tsl2x71_lux_table[TSL2X7X_DEF_LUX_TABLE_SZ] = { - { 14461, 611, 1211 }, - { 18540, 352, 623 }, - { 0, 0, 0 }, + { 53000, 106000 }, + { 31800, 53000 }, + { 0, 0 }, }; static const struct tsl2x7x_lux tmd2x71_lux_table[TSL2X7X_DEF_LUX_TABLE_SZ] = { - { 11635, 115, 256 }, - { 15536, 87, 179 }, - { 0, 0, 0 }, + { 24000, 48000 }, + { 14400, 24000 }, + { 0, 0 }, }; static const struct tsl2x7x_lux tsl2x72_lux_table[TSL2X7X_DEF_LUX_TABLE_SZ] = { - { 14013, 466, 917 }, - { 18222, 310, 552 }, - { 0, 0, 0 }, + { 60000, 112200 }, + { 37800, 60000 }, + { 0, 0 }, }; static const struct tsl2x7x_lux tmd2x72_lux_table[TSL2X7X_DEF_LUX_TABLE_SZ] = { - { 13218, 130, 262 }, - { 17592, 92, 169 }, - { 0, 0, 0 }, + { 20000, 35000 }, + { 12600, 20000 }, + { 0, 0 }, }; static const struct tsl2x7x_lux *tsl2x7x_default_lux_table_group[] = { @@ -225,18 +209,20 @@ static const struct tsl2x7x_lux *tsl2x7x_default_lux_table_group[] = { }; static const struct tsl2x7x_settings tsl2x7x_default_settings = { - .als_time = 219, /* 101 ms */ + .als_time = 255, /* 2.73 ms */ .als_gain = 0, - .prx_time = 254, /* 5.4 ms */ + .prox_time = 255, /* 2.73 ms */ .prox_gain = 0, - .wait_time = 245, - .prox_config = 0, + .wait_time = 255, + .als_prox_config = 0, .als_gain_trim = 1000, .als_cal_target = 150, + .als_persistence = 1, + .als_interrupt_en = false, .als_thresh_low = 200, .als_thresh_high = 256, - .persistence = 255, - .interrupts_en = 0, + .prox_persistence = 1, + .prox_interrupt_en = false, .prox_thres_low = 0, .prox_thres_high = 512, .prox_max_samples_cal = 30, @@ -252,7 +238,7 @@ static const s16 tsl2x7x_als_gain[] = { 120 }; -static const s16 tsl2x7x_prx_gain[] = { +static const s16 tsl2x7x_prox_gain[] = { 1, 2, 4, @@ -269,32 +255,18 @@ enum { }; static const u8 device_channel_config[] = { - ALS, - PRX, - PRX, - ALSPRX, - ALSPRX, - ALS, - PRX2, - PRX2, - ALSPRX2, - ALSPRX2 + [tsl2571] = ALS, + [tsl2671] = PRX, + [tmd2671] = PRX, + [tsl2771] = ALSPRX, + [tmd2771] = ALSPRX, + [tsl2572] = ALS, + [tsl2672] = PRX2, + [tmd2672] = PRX2, + [tsl2772] = ALSPRX2, + [tmd2772] = ALSPRX2 }; -static int tsl2x7x_clear_interrupts(struct tsl2X7X_chip *chip, int reg) -{ - int ret; - - ret = i2c_smbus_write_byte(chip->client, - TSL2X7X_CMD_REG | TSL2X7X_CMD_SPL_FN | reg); - if (ret < 0) - dev_err(&chip->client->dev, - "%s: failed to clear interrupt status %x: %d\n", - __func__, reg, ret); - - return ret; -} - static int tsl2x7x_read_status(struct tsl2X7X_chip *chip) { int ret; @@ -324,38 +296,76 @@ static int tsl2x7x_write_control_reg(struct tsl2X7X_chip *chip, u8 data) return ret; } +static int tsl2x7x_read_autoinc_regs(struct tsl2X7X_chip *chip, int lower_reg, + int upper_reg) +{ + u8 buf[2]; + int ret; + + ret = i2c_smbus_write_byte(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_CMD_AUTOINC_PROTO | + lower_reg); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: failed to enable auto increment protocol: %d\n", + __func__, ret); + return ret; + } + + ret = i2c_smbus_read_byte_data(chip->client, + TSL2X7X_CMD_REG | lower_reg); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: failed to read from register %x: %d\n", __func__, + lower_reg, ret); + return ret; + } + buf[0] = ret; + + ret = i2c_smbus_read_byte_data(chip->client, + TSL2X7X_CMD_REG | upper_reg); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: failed to read from register %x: %d\n", __func__, + upper_reg, ret); + return ret; + } + buf[1] = ret; + + ret = i2c_smbus_write_byte(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_CMD_REPEAT_PROTO | + lower_reg); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: failed to enable repeated byte protocol: %d\n", + __func__, ret); + return ret; + } + + return le16_to_cpup((const __le16 *)&buf[0]); +} + /** * tsl2x7x_get_lux() - Reads and calculates current lux value. * @indio_dev: pointer to IIO device * * The raw ch0 and ch1 values of the ambient light sensed in the last - * integration cycle are read from the device. - * Time scale factor array values are adjusted based on the integration time. - * The raw values are multiplied by a scale factor, and device gain is obtained - * using gain index. Limit checks are done next, then the ratio of a multiple - * of ch1 value, to the ch0 value, is calculated. Array tsl2x7x_device_lux[] - * is then scanned to find the first ratio value that is just above the ratio - * we just calculated. The ch0 and ch1 multiplier constants in the array are - * then used along with the time scale factor array values, to calculate the - * lux. + * integration cycle are read from the device. The raw values are multiplied + * by a device-specific scale factor, and divided by the integration time and + * device gain. The code supports multiple lux equations through the lux table + * coefficients. A lux gain trim is applied to each lux equation, and then the + * maximum lux within the interval 0..65535 is selected. */ static int tsl2x7x_get_lux(struct iio_dev *indio_dev) { - u16 ch0, ch1; /* separated ch0/ch1 data from device */ - u32 lux; /* raw lux calculated from device data */ - u64 lux64; - u32 ratio; - u8 buf[4]; - struct tsl2x7x_lux *p; struct tsl2X7X_chip *chip = iio_priv(indio_dev); - int i, ret; - u32 ch0lux = 0; - u32 ch1lux = 0; + struct tsl2x7x_lux *p; + int max_lux, ret; + bool overflow; mutex_lock(&chip->als_mutex); if (chip->tsl2x7x_chip_status != TSL2X7X_CHIP_WORKING) { - /* device is not enabled */ dev_err(&chip->client->dev, "%s: device is not enabled\n", __func__); ret = -EBUSY; @@ -366,7 +376,6 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev) if (ret < 0) goto out_unlock; - /* is data new & valid */ if (!(ret & TSL2X7X_STA_ADC_VALID)) { dev_err(&chip->client->dev, "%s: data not valid yet\n", __func__); @@ -374,91 +383,61 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev) goto out_unlock; } - for (i = 0; i < 4; i++) { - int reg = TSL2X7X_CMD_REG | (TSL2X7X_ALS_CHAN0LO + i); - - ret = i2c_smbus_read_byte_data(chip->client, reg); - if (ret < 0) { - dev_err(&chip->client->dev, - "failed to read. err=%x\n", ret); - goto out_unlock; - } - - buf[i] = ret; - } - - ret = tsl2x7x_clear_interrupts(chip, TSL2X7X_CMD_ALS_INT_CLR); + ret = tsl2x7x_read_autoinc_regs(chip, TSL2X7X_ALS_CHAN0LO, + TSL2X7X_ALS_CHAN0HI); if (ret < 0) goto out_unlock; + chip->als_cur_info.als_ch0 = ret; - /* extract ALS/lux data */ - ch0 = le16_to_cpup((const __le16 *)&buf[0]); - ch1 = le16_to_cpup((const __le16 *)&buf[2]); - - chip->als_cur_info.als_ch0 = ch0; - chip->als_cur_info.als_ch1 = ch1; + ret = tsl2x7x_read_autoinc_regs(chip, TSL2X7X_ALS_CHAN1LO, + TSL2X7X_ALS_CHAN1HI); + if (ret < 0) + goto out_unlock; + chip->als_cur_info.als_ch1 = ret; - if (ch0 >= chip->als_saturation || ch1 >= chip->als_saturation) { - lux = TSL2X7X_LUX_CALC_OVER_FLOW; - goto return_max; + if (chip->als_cur_info.als_ch0 >= chip->als_saturation) { + max_lux = TSL2X7X_LUX_CALC_OVER_FLOW; + goto update_struct_with_max_lux; } - if (!ch0) { + if (!chip->als_cur_info.als_ch0) { /* have no data, so return LAST VALUE */ ret = chip->als_cur_info.lux; goto out_unlock; } - /* calculate ratio */ - ratio = (ch1 << 15) / ch0; - /* convert to unscaled lux using the pointer to the table */ - p = (struct tsl2x7x_lux *)chip->tsl2x7x_device_lux; - while (p->ratio != 0 && p->ratio < ratio) - p++; - - if (p->ratio == 0) { - lux = 0; - } else { - lux = DIV_ROUND_UP(ch0 * p->ch0, - tsl2x7x_als_gain[chip->settings.als_gain]) - - DIV_ROUND_UP(ch1 * p->ch1, - tsl2x7x_als_gain[chip->settings.als_gain]); - } - - /* note: lux is 31 bit max at this point */ - if (ch1lux > ch0lux) { - dev_dbg(&chip->client->dev, "ch1lux > ch0lux-return last value\n"); - ret = chip->als_cur_info.lux; - goto out_unlock; - } - /* adjust for active time scale */ - if (chip->als_time_scale == 0) - lux = 0; - else - lux = (lux + (chip->als_time_scale >> 1)) / - chip->als_time_scale; - - /* adjust for active gain scale - * The tsl2x7x_device_lux tables have a factor of 256 built-in. - * User-specified gain provides a multiplier. - * Apply user-specified gain before shifting right to retain precision. - * Use 64 bits to avoid overflow on multiplication. - * Then go back to 32 bits before division to avoid using div_u64(). - */ + max_lux = 0; + overflow = false; + for (p = (struct tsl2x7x_lux *)chip->tsl2x7x_device_lux; p->ch0 != 0; + p++) { + int lux; + + lux = ((chip->als_cur_info.als_ch0 * p->ch0) - + (chip->als_cur_info.als_ch1 * p->ch1)) / + chip->als_gain_time_scale; + + /* + * The als_gain_trim can have a value within the range 250..4000 + * and is a multiplier for the lux. A trim of 1000 makes no + * changes to the lux, less than 1000 scales it down, and + * greater than 1000 scales it up. + */ + lux = (lux * chip->settings.als_gain_trim) / 1000; + + if (lux > TSL2X7X_LUX_CALC_OVER_FLOW) { + overflow = true; + continue; + } - lux64 = lux; - lux64 = lux64 * chip->settings.als_gain_trim; - lux64 >>= 8; - lux = lux64; - lux = (lux + 500) / 1000; + max_lux = max(max_lux, lux); + } - if (lux > TSL2X7X_LUX_CALC_OVER_FLOW) /* check for overflow */ - lux = TSL2X7X_LUX_CALC_OVER_FLOW; + if (overflow && max_lux == 0) + max_lux = TSL2X7X_LUX_CALC_OVER_FLOW; - /* Update the structure with the latest lux. */ -return_max: - chip->als_cur_info.lux = lux; - ret = lux; +update_struct_with_max_lux: + chip->als_cur_info.lux = max_lux; + ret = max_lux; out_unlock: mutex_unlock(&chip->als_mutex); @@ -474,10 +453,8 @@ out_unlock: */ static int tsl2x7x_get_prox(struct iio_dev *indio_dev) { - int i; - int ret; - u8 chdata[2]; struct tsl2X7X_chip *chip = iio_priv(indio_dev); + int ret; mutex_lock(&chip->prox_mutex); @@ -508,18 +485,10 @@ static int tsl2x7x_get_prox(struct iio_dev *indio_dev) break; } - for (i = 0; i < 2; i++) { - int reg = TSL2X7X_CMD_REG | (TSL2X7X_PRX_LO + i); - - ret = i2c_smbus_read_byte_data(chip->client, reg); - if (ret < 0) - goto prox_poll_err; - - chdata[i] = ret; - } - - chip->prox_data = le16_to_cpup((const __le16 *)&chdata[0]); - ret = chip->prox_data; + ret = tsl2x7x_read_autoinc_regs(chip, TSL2X7X_PRX_LO, TSL2X7X_PRX_HI); + if (ret < 0) + goto prox_poll_err; + chip->prox_data = ret; prox_poll_err: mutex_unlock(&chip->prox_mutex); @@ -545,7 +514,7 @@ static void tsl2x7x_defaults(struct tsl2X7X_chip *chip) sizeof(tsl2x7x_default_settings)); /* Load up the proper lux table. */ - if (chip->pdata && chip->pdata->platform_lux_table[0].ratio != 0) + if (chip->pdata && chip->pdata->platform_lux_table[0].ch0 != 0) memcpy(chip->tsl2x7x_device_lux, chip->pdata->platform_lux_table, sizeof(chip->pdata->platform_lux_table)); @@ -601,26 +570,22 @@ static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev) return -ERANGE; chip->settings.als_gain_trim = ret; - dev_info(&chip->client->dev, - "%s als_calibrate completed\n", chip->client->name); return ret; } static int tsl2x7x_chip_on(struct iio_dev *indio_dev) { - int i; - int ret = 0; - u8 *dev_reg; - int als_count; - int als_time; struct tsl2X7X_chip *chip = iio_priv(indio_dev); - u8 reg_val = 0; + int ret, i, als_count, als_time_us; + u8 *dev_reg, reg_val; /* Non calculated parameters */ - chip->tsl2x7x_config[TSL2X7X_PRX_TIME] = chip->settings.prx_time; + chip->tsl2x7x_config[TSL2X7X_ALS_TIME] = chip->settings.als_time; + chip->tsl2x7x_config[TSL2X7X_PRX_TIME] = chip->settings.prox_time; chip->tsl2x7x_config[TSL2X7X_WAIT_TIME] = chip->settings.wait_time; - chip->tsl2x7x_config[TSL2X7X_PRX_CONFIG] = chip->settings.prox_config; + chip->tsl2x7x_config[TSL2X7X_ALS_PRX_CONFIG] = + chip->settings.als_prox_config; chip->tsl2x7x_config[TSL2X7X_ALS_MINTHRESHLO] = (chip->settings.als_thresh_low) & 0xFF; @@ -630,7 +595,9 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) (chip->settings.als_thresh_high) & 0xFF; chip->tsl2x7x_config[TSL2X7X_ALS_MAXTHRESHHI] = (chip->settings.als_thresh_high >> 8) & 0xFF; - chip->tsl2x7x_config[TSL2X7X_PERSISTENCE] = chip->settings.persistence; + chip->tsl2x7x_config[TSL2X7X_PERSISTENCE] = + (chip->settings.prox_persistence & 0xFF) << 4 | + (chip->settings.als_persistence & 0xFF); chip->tsl2x7x_config[TSL2X7X_PRX_COUNT] = chip->settings.prox_pulse_count; @@ -650,15 +617,6 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) return -EINVAL; } - /* determine als integration register */ - als_count = (chip->settings.als_time * 100 + 135) / 270; - if (!als_count) - als_count = 1; /* ensure at least one cycle */ - - /* convert back to time (encompasses overrides) */ - als_time = (als_count * 27 + 5) / 10; - chip->tsl2x7x_config[TSL2X7X_ALS_TIME] = 256 - als_count; - /* Set the gain based on tsl2x7x_settings struct */ chip->tsl2x7x_config[TSL2X7X_GAIN] = (chip->settings.als_gain & 0xFF) | @@ -666,9 +624,12 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) (chip->settings.prox_diode << 4) | (chip->settings.prox_power << 6); - /* set chip struct re scaling and saturation */ - chip->als_saturation = als_count * 922; /* 90% of full scale */ - chip->als_time_scale = (als_time + 25) / 50; + /* set chip time scaling and saturation */ + als_count = 256 - chip->settings.als_time; + als_time_us = als_count * 2720; + chip->als_saturation = als_count * 768; /* 75% of full scale */ + chip->als_gain_time_scale = als_time_us * + tsl2x7x_als_gain[chip->settings.als_gain]; /* * TSL2X7X Specific power-on / adc enable sequence @@ -684,12 +645,14 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) */ for (i = 0, dev_reg = chip->tsl2x7x_config; i < TSL2X7X_MAX_CONFIG_REG; i++) { - ret = i2c_smbus_write_byte_data(chip->client, - TSL2X7X_CMD_REG + i, + int reg = TSL2X7X_CMD_REG + i; + + ret = i2c_smbus_write_byte_data(chip->client, reg, *dev_reg++); if (ret < 0) { dev_err(&chip->client->dev, - "failed on write to reg %d.\n", i); + "%s: failed to write to register %x: %d\n", + __func__, reg, ret); return ret; } } @@ -697,38 +660,29 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev) /* Power-on settling time */ usleep_range(3000, 3500); - /* - * NOW enable the ADC - * initialize the desired mode of operation - */ - ret = tsl2x7x_write_control_reg(chip, - TSL2X7X_CNTL_PWR_ON | - TSL2X7X_CNTL_ADC_ENBL | - TSL2X7X_CNTL_PROX_DET_ENBL); + reg_val = TSL2X7X_CNTL_PWR_ON | TSL2X7X_CNTL_ADC_ENBL | + TSL2X7X_CNTL_PROX_DET_ENBL; + if (chip->settings.als_interrupt_en) + reg_val |= TSL2X7X_CNTL_ALS_INT_ENBL; + if (chip->settings.prox_interrupt_en) + reg_val |= TSL2X7X_CNTL_PROX_INT_ENBL; + + ret = tsl2x7x_write_control_reg(chip, reg_val); if (ret < 0) return ret; - chip->tsl2x7x_chip_status = TSL2X7X_CHIP_WORKING; - - if (chip->settings.interrupts_en != 0) { - dev_info(&chip->client->dev, "Setting Up Interrupt(s)\n"); - - reg_val = TSL2X7X_CNTL_PWR_ON | TSL2X7X_CNTL_ADC_ENBL; - if (chip->settings.interrupts_en == 0x20 || - chip->settings.interrupts_en == 0x30) - reg_val |= TSL2X7X_CNTL_PROX_DET_ENBL; - - reg_val |= chip->settings.interrupts_en; - ret = tsl2x7x_write_control_reg(chip, reg_val); - if (ret < 0) - return ret; - - ret = tsl2x7x_clear_interrupts(chip, - TSL2X7X_CMD_PROXALS_INT_CLR); - if (ret < 0) - return ret; + ret = i2c_smbus_write_byte(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_CMD_SPL_FN | + TSL2X7X_CMD_PROXALS_INT_CLR); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: failed to clear interrupt status: %d\n", + __func__, ret); + return ret; } + chip->tsl2x7x_chip_status = TSL2X7X_CHIP_WORKING; + return ret; } @@ -742,14 +696,13 @@ static int tsl2x7x_chip_off(struct iio_dev *indio_dev) } /** - * tsl2x7x_invoke_change + * tsl2x7x_invoke_change - power cycle the device to implement the user + * parameters * @indio_dev: pointer to IIO device * - * Obtain and lock both ALS and PROX resources, - * determine and save device state (On/Off), - * cycle device to implement updated parameter, - * put device back into proper state, and unlock - * resource. + * Obtain and lock both ALS and PROX resources, determine and save device state + * (On/Off), cycle device to implement updated parameter, put device back into + * proper state, and unlock resource. */ static int tsl2x7x_invoke_change(struct iio_dev *indio_dev) { @@ -775,130 +728,43 @@ unlock: return ret; } -static void tsl2x7x_prox_calculate(int *data, int length, - struct tsl2x7x_prox_stat *stat) -{ - int i; - int sample_sum; - int tmp; - - if (!length) - length = 1; - - sample_sum = 0; - stat->min = INT_MAX; - stat->max = INT_MIN; - for (i = 0; i < length; i++) { - sample_sum += data[i]; - stat->min = min(stat->min, data[i]); - stat->max = max(stat->max, data[i]); - } - - stat->mean = sample_sum / length; - sample_sum = 0; - for (i = 0; i < length; i++) { - tmp = data[i] - stat->mean; - sample_sum += tmp * tmp; - } - stat->stddev = int_sqrt((long)sample_sum / length); -} - -/** - * tsl2x7x_prox_cal() - Calculates std. and sets thresholds. - * @indio_dev: pointer to IIO device - * - * Calculates a standard deviation based on the samples, - * and sets the threshold accordingly. - */ static int tsl2x7x_prox_cal(struct iio_dev *indio_dev) { - int prox_history[MAX_SAMPLES_CAL + 1]; - int i, ret; - struct tsl2x7x_prox_stat prox_stat_data[2]; - struct tsl2x7x_prox_stat *cal; struct tsl2X7X_chip *chip = iio_priv(indio_dev); - u8 tmp_irq_settings; - u8 current_state = chip->tsl2x7x_chip_status; - - if (chip->settings.prox_max_samples_cal > MAX_SAMPLES_CAL) { - dev_err(&chip->client->dev, - "max prox samples cal is too big: %d\n", - chip->settings.prox_max_samples_cal); - chip->settings.prox_max_samples_cal = MAX_SAMPLES_CAL; - } - - /* have to stop to change settings */ - ret = tsl2x7x_chip_off(indio_dev); - if (ret < 0) - return ret; - - /* Enable proximity detection save just in case prox not wanted yet*/ - tmp_irq_settings = chip->settings.interrupts_en; - chip->settings.interrupts_en |= TSL2X7X_CNTL_PROX_INT_ENBL; + int prox_history[MAX_SAMPLES_CAL + 1]; + int i, ret, mean, max, sample_sum; - /*turn on device if not already on*/ - ret = tsl2x7x_chip_on(indio_dev); - if (ret < 0) - return ret; + if (chip->settings.prox_max_samples_cal < 1 || + chip->settings.prox_max_samples_cal > MAX_SAMPLES_CAL) + return -EINVAL; - /*gather the samples*/ for (i = 0; i < chip->settings.prox_max_samples_cal; i++) { usleep_range(15000, 17500); ret = tsl2x7x_get_prox(indio_dev); if (ret < 0) return ret; + prox_history[i] = chip->prox_data; - dev_info(&chip->client->dev, "2 i=%d prox data= %d\n", - i, chip->prox_data); } - ret = tsl2x7x_chip_off(indio_dev); - if (ret < 0) - return ret; - cal = &prox_stat_data[PROX_STAT_CAL]; - tsl2x7x_prox_calculate(prox_history, - chip->settings.prox_max_samples_cal, cal); - chip->settings.prox_thres_high = (cal->max << 1) - cal->mean; - - dev_info(&chip->client->dev, " cal min=%d mean=%d max=%d\n", - cal->min, cal->mean, cal->max); - dev_info(&chip->client->dev, - "%s proximity threshold set to %d\n", - chip->client->name, chip->settings.prox_thres_high); - - /* back to the way they were */ - chip->settings.interrupts_en = tmp_irq_settings; - if (current_state == TSL2X7X_CHIP_WORKING) { - ret = tsl2x7x_chip_on(indio_dev); - if (ret < 0) - return ret; + sample_sum = 0; + max = INT_MIN; + for (i = 0; i < chip->settings.prox_max_samples_cal; i++) { + sample_sum += prox_history[i]; + max = max(max, prox_history[i]); } + mean = sample_sum / chip->settings.prox_max_samples_cal; - return 0; -} - -static ssize_t -in_illuminance0_calibscale_available_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct tsl2X7X_chip *chip = iio_priv(dev_to_iio_dev(dev)); - - switch (chip->id) { - case tsl2571: - case tsl2671: - case tmd2671: - case tsl2771: - case tmd2771: - return snprintf(buf, PAGE_SIZE, "%s\n", "1 8 16 128"); - } + chip->settings.prox_thres_high = (max << 1) - mean; - return snprintf(buf, PAGE_SIZE, "%s\n", "1 8 16 120"); + return tsl2x7x_invoke_change(indio_dev); } +static IIO_CONST_ATTR(in_intensity0_calibscale_available, "1 8 16 120"); + static IIO_CONST_ATTR(in_proximity0_calibscale_available, "1 2 4 8"); -static IIO_CONST_ATTR(in_illuminance0_integration_time_available, +static IIO_CONST_ATTR(in_intensity0_integration_time_available, ".00272 - .696"); static ssize_t in_illuminance0_target_input_show(struct device *dev, @@ -916,15 +782,13 @@ static ssize_t in_illuminance0_target_input_store(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2X7X_chip *chip = iio_priv(indio_dev); - unsigned long value; + u16 value; int ret; - if (kstrtoul(buf, 0, &value)) + if (kstrtou16(buf, 0, &value)) return -EINVAL; - if (value) - chip->settings.als_cal_target = value; - + chip->settings.als_cal_target = value; ret = tsl2x7x_invoke_change(indio_dev); if (ret < 0) return ret; @@ -940,14 +804,12 @@ static ssize_t in_illuminance0_calibrate_store(struct device *dev, bool value; int ret; - if (strtobool(buf, &value)) + if (kstrtobool(buf, &value) || !value) return -EINVAL; - if (value) { - ret = tsl2x7x_als_calibrate(indio_dev); - if (ret < 0) - return ret; - } + ret = tsl2x7x_als_calibrate(indio_dev); + if (ret < 0) + return ret; ret = tsl2x7x_invoke_change(indio_dev); if (ret < 0) @@ -965,11 +827,10 @@ static ssize_t in_illuminance0_lux_table_show(struct device *dev, int offset = 0; while (i < TSL2X7X_MAX_LUX_TABLE_SIZE) { - offset += snprintf(buf + offset, PAGE_SIZE, "%u,%u,%u,", - chip->tsl2x7x_device_lux[i].ratio, + offset += snprintf(buf + offset, PAGE_SIZE, "%u,%u,", chip->tsl2x7x_device_lux[i].ch0, chip->tsl2x7x_device_lux[i].ch1); - if (chip->tsl2x7x_device_lux[i].ratio == 0) { + if (chip->tsl2x7x_device_lux[i].ch0 == 0) { /* * We just printed the first "0" entry. * Now get rid of the extra "," and break. @@ -990,27 +851,24 @@ static ssize_t in_illuminance0_lux_table_store(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct tsl2X7X_chip *chip = iio_priv(indio_dev); - int value[ARRAY_SIZE(chip->tsl2x7x_device_lux) * 3 + 1]; + int value[ARRAY_SIZE(chip->tsl2x7x_device_lux) * 2 + 1]; int n, ret; get_options(buf, ARRAY_SIZE(value), value); - /* We now have an array of ints starting at value[1], and + /* + * We now have an array of ints starting at value[1], and * enumerated by value[0]. - * We expect each group of three ints is one table entry, + * We expect each group of two ints to be one table entry, * and the last table entry is all 0. */ n = value[0]; - if ((n % 3) || n < 6 || - n > ((ARRAY_SIZE(chip->tsl2x7x_device_lux) - 1) * 3)) { - dev_info(dev, "LUX TABLE INPUT ERROR 1 Value[0]=%d\n", n); + if ((n % 2) || n < 4 || + n > ((ARRAY_SIZE(chip->tsl2x7x_device_lux) - 1) * 2)) return -EINVAL; - } - if ((value[(n - 2)] | value[(n - 1)] | value[n]) != 0) { - dev_info(dev, "LUX TABLE INPUT ERROR 2 Value[0]=%d\n", n); + if ((value[(n - 1)] | value[n]) != 0) return -EINVAL; - } if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_WORKING) { ret = tsl2x7x_chip_off(indio_dev); @@ -1037,14 +895,12 @@ static ssize_t in_proximity0_calibrate_store(struct device *dev, bool value; int ret; - if (strtobool(buf, &value)) + if (kstrtobool(buf, &value) || !value) return -EINVAL; - if (value) { - ret = tsl2x7x_prox_cal(indio_dev); - if (ret < 0) - return ret; - } + ret = tsl2x7x_prox_cal(indio_dev); + if (ret < 0) + return ret; ret = tsl2x7x_invoke_change(indio_dev); if (ret < 0) @@ -1059,14 +915,11 @@ static int tsl2x7x_read_interrupt_config(struct iio_dev *indio_dev, enum iio_event_direction dir) { struct tsl2X7X_chip *chip = iio_priv(indio_dev); - int ret; if (chan->type == IIO_INTENSITY) - ret = !!(chip->settings.interrupts_en & 0x10); + return chip->settings.als_interrupt_en; else - ret = !!(chip->settings.interrupts_en & 0x20); - - return ret; + return chip->settings.prox_interrupt_en; } static int tsl2x7x_write_interrupt_config(struct iio_dev *indio_dev, @@ -1076,25 +929,13 @@ static int tsl2x7x_write_interrupt_config(struct iio_dev *indio_dev, int val) { struct tsl2X7X_chip *chip = iio_priv(indio_dev); - int ret; - if (chan->type == IIO_INTENSITY) { - if (val) - chip->settings.interrupts_en |= 0x10; - else - chip->settings.interrupts_en &= 0x20; - } else { - if (val) - chip->settings.interrupts_en |= 0x20; - else - chip->settings.interrupts_en &= 0x10; - } - - ret = tsl2x7x_invoke_change(indio_dev); - if (ret < 0) - return ret; + if (chan->type == IIO_INTENSITY) + chip->settings.als_interrupt_en = val ? true : false; + else + chip->settings.prox_interrupt_en = val ? true : false; - return 0; + return tsl2x7x_invoke_change(indio_dev); } static int tsl2x7x_write_event_value(struct iio_dev *indio_dev, @@ -1142,27 +983,17 @@ static int tsl2x7x_write_event_value(struct iio_dev *indio_dev, if (chan->type == IIO_INTENSITY) time = chip->settings.als_time; else - time = chip->settings.prx_time; + time = chip->settings.prox_time; y = (TSL2X7X_MAX_TIMER_CNT - time) + 1; z = y * TSL2X7X_MIN_ITIME; filter_delay = DIV_ROUND_UP((val * 1000) + val2, z); - if (chan->type == IIO_INTENSITY) { - chip->settings.persistence &= 0xF0; - chip->settings.persistence |= - (filter_delay & 0x0F); - dev_info(&chip->client->dev, "%s: ALS persistence = %d", - __func__, filter_delay); - } else { - chip->settings.persistence &= 0x0F; - chip->settings.persistence |= - ((filter_delay << 4) & 0xF0); - dev_info(&chip->client->dev, - "%s: Proximity persistence = %d", - __func__, filter_delay); - } + if (chan->type == IIO_INTENSITY) + chip->settings.als_persistence = filter_delay; + else + chip->settings.prox_persistence = filter_delay; ret = 0; break; default: @@ -1219,10 +1050,10 @@ static int tsl2x7x_read_event_value(struct iio_dev *indio_dev, case IIO_EV_INFO_PERIOD: if (chan->type == IIO_INTENSITY) { time = chip->settings.als_time; - mult = chip->settings.persistence & 0x0F; + mult = chip->settings.als_persistence; } else { - time = chip->settings.prx_time; - mult = (chip->settings.persistence & 0xF0) >> 4; + time = chip->settings.prox_time; + mult = chip->settings.prox_persistence; } /* Determine integration time */ @@ -1246,8 +1077,8 @@ static int tsl2x7x_read_raw(struct iio_dev *indio_dev, int *val2, long mask) { - int ret = -EINVAL; struct tsl2X7X_chip *chip = iio_priv(indio_dev); + int ret = -EINVAL; switch (mask) { case IIO_CHAN_INFO_PROCESSED: @@ -1284,7 +1115,7 @@ static int tsl2x7x_read_raw(struct iio_dev *indio_dev, if (chan->type == IIO_LIGHT) *val = tsl2x7x_als_gain[chip->settings.als_gain]; else - *val = tsl2x7x_prx_gain[chip->settings.prox_gain]; + *val = tsl2x7x_prox_gain[chip->settings.prox_gain]; ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_CALIBBIAS: @@ -1292,8 +1123,8 @@ static int tsl2x7x_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_INT_TIME: - *val = (TSL2X7X_MAX_TIMER_CNT - chip->settings.als_time) + 1; - *val2 = ((*val * TSL2X7X_MIN_ITIME) % 1000) / 1000; + *val = 0; + *val2 = (256 - chip->settings.als_time) * 2720; ret = IIO_VAL_INT_PLUS_MICRO; break; default: @@ -1325,25 +1156,6 @@ static int tsl2x7x_write_raw(struct iio_dev *indio_dev, chip->settings.als_gain = 2; break; case 120: - switch (chip->id) { - case tsl2572: - case tsl2672: - case tmd2672: - case tsl2772: - case tmd2772: - return -EINVAL; - } - chip->settings.als_gain = 3; - break; - case 128: - switch (chip->id) { - case tsl2571: - case tsl2671: - case tmd2671: - case tsl2771: - case tmd2771: - return -EINVAL; - } chip->settings.als_gain = 3; break; default: @@ -1372,11 +1184,7 @@ static int tsl2x7x_write_raw(struct iio_dev *indio_dev, chip->settings.als_gain_trim = val; break; case IIO_CHAN_INFO_INT_TIME: - chip->settings.als_time = - TSL2X7X_MAX_TIMER_CNT - (val2 / TSL2X7X_MIN_ITIME); - - dev_info(&chip->client->dev, "%s: als time = %d", - __func__, chip->settings.als_time); + chip->settings.als_time = 256 - (val2 / 2720); break; default: return -EINVAL; @@ -1385,8 +1193,6 @@ static int tsl2x7x_write_raw(struct iio_dev *indio_dev, return tsl2x7x_invoke_change(indio_dev); } -static DEVICE_ATTR_RO(in_illuminance0_calibscale_available); - static DEVICE_ATTR_RW(in_illuminance0_target_input); static DEVICE_ATTR_WO(in_illuminance0_calibrate); @@ -1396,22 +1202,22 @@ static DEVICE_ATTR_WO(in_proximity0_calibrate); static DEVICE_ATTR_RW(in_illuminance0_lux_table); /* Use the default register values to identify the Taos device */ -static int tsl2x7x_device_id(int *id, int target) +static int tsl2x7x_device_id_verif(int id, int target) { switch (target) { case tsl2571: case tsl2671: case tsl2771: - return (*id & 0xf0) == TRITON_ID; + return (id & 0xf0) == TRITON_ID; case tmd2671: case tmd2771: - return (*id & 0xf0) == HALIBUT_ID; + return (id & 0xf0) == HALIBUT_ID; case tsl2572: case tsl2672: case tmd2672: case tsl2772: case tmd2772: - return (*id & 0xf0) == SWORDFISH_ID; + return (id & 0xf0) == SWORDFISH_ID; } return -EINVAL; @@ -1426,11 +1232,10 @@ static irqreturn_t tsl2x7x_event_handler(int irq, void *private) ret = tsl2x7x_read_status(chip); if (ret < 0) - return ret; + return IRQ_HANDLED; /* What type of interrupt do we need to process */ if (ret & TSL2X7X_STA_PRX_INTR) { - tsl2x7x_get_prox(indio_dev); /* freshen data for ABI */ iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0, @@ -1440,7 +1245,6 @@ static irqreturn_t tsl2x7x_event_handler(int irq, void *private) } if (ret & TSL2X7X_STA_ALS_INTR) { - tsl2x7x_get_lux(indio_dev); /* freshen data for ABI */ iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0, @@ -1449,17 +1253,20 @@ static irqreturn_t tsl2x7x_event_handler(int irq, void *private) timestamp); } - ret = tsl2x7x_clear_interrupts(chip, TSL2X7X_CMD_PROXALS_INT_CLR); + ret = i2c_smbus_write_byte(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_CMD_SPL_FN | + TSL2X7X_CMD_PROXALS_INT_CLR); if (ret < 0) - return ret; + dev_err(&chip->client->dev, + "%s: failed to clear interrupt status: %d\n", + __func__, ret); return IRQ_HANDLED; } static struct attribute *tsl2x7x_ALS_device_attrs[] = { - &dev_attr_in_illuminance0_calibscale_available.attr, - &iio_const_attr_in_illuminance0_integration_time_available - .dev_attr.attr, + &iio_const_attr_in_intensity0_calibscale_available.dev_attr.attr, + &iio_const_attr_in_intensity0_integration_time_available.dev_attr.attr, &dev_attr_in_illuminance0_target_input.attr, &dev_attr_in_illuminance0_calibrate.attr, &dev_attr_in_illuminance0_lux_table.attr, @@ -1472,9 +1279,8 @@ static struct attribute *tsl2x7x_PRX_device_attrs[] = { }; static struct attribute *tsl2x7x_ALSPRX_device_attrs[] = { - &dev_attr_in_illuminance0_calibscale_available.attr, - &iio_const_attr_in_illuminance0_integration_time_available - .dev_attr.attr, + &iio_const_attr_in_intensity0_calibscale_available.dev_attr.attr, + &iio_const_attr_in_intensity0_integration_time_available.dev_attr.attr, &dev_attr_in_illuminance0_target_input.attr, &dev_attr_in_illuminance0_calibrate.attr, &dev_attr_in_illuminance0_lux_table.attr, @@ -1488,9 +1294,8 @@ static struct attribute *tsl2x7x_PRX2_device_attrs[] = { }; static struct attribute *tsl2x7x_ALSPRX2_device_attrs[] = { - &dev_attr_in_illuminance0_calibscale_available.attr, - &iio_const_attr_in_illuminance0_integration_time_available - .dev_attr.attr, + &iio_const_attr_in_intensity0_calibscale_available.dev_attr.attr, + &iio_const_attr_in_intensity0_integration_time_available.dev_attr.attr, &dev_attr_in_illuminance0_target_input.attr, &dev_attr_in_illuminance0_calibrate.attr, &dev_attr_in_illuminance0_lux_table.attr, @@ -1569,34 +1374,33 @@ static const struct iio_event_spec tsl2x7x_events[] = { { .type = IIO_EV_TYPE_THRESH, .dir = IIO_EV_DIR_RISING, - .mask_separate = BIT(IIO_EV_INFO_VALUE) | - BIT(IIO_EV_INFO_ENABLE), + .mask_separate = BIT(IIO_EV_INFO_VALUE), }, { .type = IIO_EV_TYPE_THRESH, .dir = IIO_EV_DIR_FALLING, - .mask_separate = BIT(IIO_EV_INFO_VALUE) | - BIT(IIO_EV_INFO_ENABLE), + .mask_separate = BIT(IIO_EV_INFO_VALUE), }, { .type = IIO_EV_TYPE_THRESH, .dir = IIO_EV_DIR_EITHER, - .mask_separate = BIT(IIO_EV_INFO_PERIOD), + .mask_separate = BIT(IIO_EV_INFO_PERIOD) | + BIT(IIO_EV_INFO_ENABLE), }, }; static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { [ALS] = { - .channel = { + .channel_with_events = { { .type = IIO_LIGHT, .indexed = 1, .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | - BIT(IIO_CHAN_INFO_INT_TIME), + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), }, { .type = IIO_INTENSITY, .indexed = 1, .channel = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_CALIBBIAS), .event_spec = tsl2x7x_events, @@ -1607,11 +1411,31 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { .channel = 1, }, }, - .chan_table_elements = 3, - .info = &tsl2X7X_device_info[ALS], + .channel_without_events = { + { + .type = IIO_LIGHT, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + }, { + .type = IIO_INTENSITY, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | + BIT(IIO_CHAN_INFO_CALIBBIAS), + }, { + .type = IIO_INTENSITY, + .indexed = 1, + .channel = 1, + }, + }, + .chan_table_elements = 3, + .info = &tsl2X7X_device_info[ALS], }, [PRX] = { - .channel = { + .channel_with_events = { { .type = IIO_PROXIMITY, .indexed = 1, @@ -1621,22 +1445,30 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { .num_event_specs = ARRAY_SIZE(tsl2x7x_events), }, }, - .chan_table_elements = 1, - .info = &tsl2X7X_device_info[PRX], + .channel_without_events = { + { + .type = IIO_PROXIMITY, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + }, + }, + .chan_table_elements = 1, + .info = &tsl2X7X_device_info[PRX], }, [ALSPRX] = { - .channel = { + .channel_with_events = { { .type = IIO_LIGHT, .indexed = 1, .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | - BIT(IIO_CHAN_INFO_INT_TIME), + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), }, { .type = IIO_INTENSITY, .indexed = 1, .channel = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_CALIBBIAS), .event_spec = tsl2x7x_events, @@ -1655,11 +1487,37 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { .num_event_specs = ARRAY_SIZE(tsl2x7x_events), }, }, - .chan_table_elements = 4, - .info = &tsl2X7X_device_info[ALSPRX], + .channel_without_events = { + { + .type = IIO_LIGHT, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + }, { + .type = IIO_INTENSITY, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | + BIT(IIO_CHAN_INFO_CALIBBIAS), + }, { + .type = IIO_INTENSITY, + .indexed = 1, + .channel = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + }, { + .type = IIO_PROXIMITY, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + }, + }, + .chan_table_elements = 4, + .info = &tsl2X7X_device_info[ALSPRX], }, [PRX2] = { - .channel = { + .channel_with_events = { { .type = IIO_PROXIMITY, .indexed = 1, @@ -1670,22 +1528,31 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { .num_event_specs = ARRAY_SIZE(tsl2x7x_events), }, }, - .chan_table_elements = 1, - .info = &tsl2X7X_device_info[PRX2], + .channel_without_events = { + { + .type = IIO_PROXIMITY, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE), + }, + }, + .chan_table_elements = 1, + .info = &tsl2X7X_device_info[PRX2], }, [ALSPRX2] = { - .channel = { + .channel_with_events = { { .type = IIO_LIGHT, .indexed = 1, .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | - BIT(IIO_CHAN_INFO_INT_TIME), + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), }, { .type = IIO_INTENSITY, .indexed = 1, .channel = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_CALIBBIAS), .event_spec = tsl2x7x_events, @@ -1705,17 +1572,44 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = { .num_event_specs = ARRAY_SIZE(tsl2x7x_events), }, }, - .chan_table_elements = 4, - .info = &tsl2X7X_device_info[ALSPRX2], + .channel_without_events = { + { + .type = IIO_LIGHT, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + }, { + .type = IIO_INTENSITY, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | + BIT(IIO_CHAN_INFO_CALIBBIAS), + }, { + .type = IIO_INTENSITY, + .indexed = 1, + .channel = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + }, { + .type = IIO_PROXIMITY, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE), + }, + }, + .chan_table_elements = 4, + .info = &tsl2X7X_device_info[ALSPRX2], }, }; static int tsl2x7x_probe(struct i2c_client *clientp, const struct i2c_device_id *id) { - int ret; struct iio_dev *indio_dev; struct tsl2X7X_chip *chip; + int ret; indio_dev = devm_iio_device_alloc(&clientp->dev, sizeof(*chip)); if (!indio_dev) @@ -1730,8 +1624,7 @@ static int tsl2x7x_probe(struct i2c_client *clientp, if (ret < 0) return ret; - if ((!tsl2x7x_device_id(&ret, id->driver_data)) || - (tsl2x7x_device_id(&ret, id->driver_data) == -EINVAL)) { + if (tsl2x7x_device_id_verif(ret, id->driver_data) <= 0) { dev_info(&chip->client->dev, "%s: i2c device found does not match expected id\n", __func__); @@ -1740,15 +1633,12 @@ static int tsl2x7x_probe(struct i2c_client *clientp, ret = i2c_smbus_write_byte(clientp, TSL2X7X_CMD_REG | TSL2X7X_CNTRL); if (ret < 0) { - dev_err(&clientp->dev, "write to cmd reg failed. err = %d\n", - ret); + dev_err(&clientp->dev, + "%s: Failed to write to CMD register: %d\n", + __func__, ret); return ret; } - /* - * ALS and PROX functions can be invoked via user space poll - * or H/W interrupt. If busy return last sample. - */ mutex_init(&chip->als_mutex); mutex_init(&chip->prox_mutex); @@ -1762,27 +1652,28 @@ static int tsl2x7x_probe(struct i2c_client *clientp, indio_dev->dev.parent = &clientp->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->name = chip->client->name; - indio_dev->channels = chip->chip_info->channel; indio_dev->num_channels = chip->chip_info->chan_table_elements; if (clientp->irq) { + indio_dev->channels = chip->chip_info->channel_with_events; + ret = devm_request_threaded_irq(&clientp->dev, clientp->irq, NULL, &tsl2x7x_event_handler, - IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "TSL2X7X_event", indio_dev); if (ret) { dev_err(&clientp->dev, - "%s: irq request failed", __func__); + "%s: irq request failed\n", __func__); return ret; } + } else { + indio_dev->channels = chip->chip_info->channel_without_events; } - /* Load up the defaults */ tsl2x7x_defaults(chip); - /* Make sure the chip is on */ tsl2x7x_chip_on(indio_dev); ret = iio_device_register(indio_dev); @@ -1792,35 +1683,21 @@ static int tsl2x7x_probe(struct i2c_client *clientp, return ret; } - dev_info(&clientp->dev, "%s Light sensor found.\n", id->name); - return 0; } static int tsl2x7x_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2X7X_chip *chip = iio_priv(indio_dev); - int ret = 0; - - if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_WORKING) { - ret = tsl2x7x_chip_off(indio_dev); - chip->tsl2x7x_chip_status = TSL2X7X_CHIP_SUSPENDED; - } - return ret; + return tsl2x7x_chip_off(indio_dev); } static int tsl2x7x_resume(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct tsl2X7X_chip *chip = iio_priv(indio_dev); - int ret = 0; - if (chip->tsl2x7x_chip_status == TSL2X7X_CHIP_SUSPENDED) - ret = tsl2x7x_chip_on(indio_dev); - - return ret; + return tsl2x7x_chip_on(indio_dev); } static int tsl2x7x_remove(struct i2c_client *client) @@ -1870,7 +1747,6 @@ static const struct dev_pm_ops tsl2x7x_pm_ops = { .resume = tsl2x7x_resume, }; -/* Driver definition */ static struct i2c_driver tsl2x7x_driver = { .driver = { .name = "tsl2x7x", @@ -1884,6 +1760,7 @@ static struct i2c_driver tsl2x7x_driver = { module_i2c_driver(tsl2x7x_driver); -MODULE_AUTHOR("J. August Brenner<jbrenner@taosinc.com>"); +MODULE_AUTHOR("J. August Brenner <Jon.Brenner@ams.com>"); +MODULE_AUTHOR("Brian Masney <masneyb@onstation.org>"); MODULE_DESCRIPTION("TAOS tsl2x7x ambient and proximity light sensor driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/light/tsl2x7x.h b/drivers/staging/iio/light/tsl2x7x.h index 28b0e7fdc9b8..1097ee890ce2 100644 --- a/drivers/staging/iio/light/tsl2x7x.h +++ b/drivers/staging/iio/light/tsl2x7x.h @@ -1,79 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Device driver for monitoring ambient light intensity (lux) * and proximity (prox) within the TAOS TSL2X7X family of devices. * * Copyright (c) 2012, TAOS Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __TSL2X7X_H #define __TSL2X7X_H struct tsl2x7x_lux { - unsigned int ratio; unsigned int ch0; unsigned int ch1; }; /* Max number of segments allowable in LUX table */ -#define TSL2X7X_MAX_LUX_TABLE_SIZE 9 +#define TSL2X7X_MAX_LUX_TABLE_SIZE 6 /* The default LUX tables all have 3 elements. */ #define TSL2X7X_DEF_LUX_TABLE_SZ 3 #define TSL2X7X_DEFAULT_TABLE_BYTES (sizeof(struct tsl2x7x_lux) * \ TSL2X7X_DEF_LUX_TABLE_SZ) +/* Proximity diode to use */ +#define TSL2X7X_DIODE0 0x01 +#define TSL2X7X_DIODE1 0x02 +#define TSL2X7X_DIODE_BOTH 0x03 + +/* LED Power */ +#define TSL2X7X_100_mA 0x00 +#define TSL2X7X_50_mA 0x01 +#define TSL2X7X_25_mA 0x02 +#define TSL2X7X_13_mA 0x03 +#define TSL2X7X_MAX_TIMER_CNT 0xFF + /** - * struct tsl2x7x_default_settings - power on defaults unless - * overridden by platform data. - * @als_time: ALS Integration time - multiple of 50mS - * @als_gain: Index into the ALS gain table. - * @als_gain_trim: default gain trim to account for - * aperture effects. - * @wait_time: Time between PRX and ALS cycles - * in 2.7 periods - * @prx_time: 5.2ms prox integration time - - * decrease in 2.7ms periods - * @prx_gain: Proximity gain index - * @prox_config: Prox configuration filters. - * @als_cal_target: Known external ALS reading for - * calibration. - * @interrupts_en: Enable/Disable - 0x00 = none, 0x10 = als, - * 0x20 = prx, 0x30 = bth - * @persistence: H/W Filters, Number of 'out of limits' - * ADC readings PRX/ALS. + * struct tsl2x7x_settings - Settings for the tsl2x7x driver + * @als_time: Integration time of the ALS channel ADCs in 2.73 ms + * increments. Total integration time is + * (256 - als_time) * 2.73. + * @als_gain: Index into the tsl2x7x_als_gain array. + * @als_gain_trim: Default gain trim to account for aperture effects. + * @wait_time: Time between proximity and ALS cycles in 2.73 + * periods. + * @prox_time: Integration time of the proximity ADC in 2.73 ms + * increments. Total integration time is + * (256 - prx_time) * 2.73. + * @prox_gain: Index into the tsl2x7x_prx_gain array. + * @als_prox_config: The value of the ALS / Proximity configuration + * register. + * @als_cal_target: Known external ALS reading for calibration. + * @als_persistence: H/W Filters, Number of 'out of limits' ALS readings. + * @als_interrupt_en: Enable/Disable ALS interrupts * @als_thresh_low: CH0 'low' count to trigger interrupt. * @als_thresh_high: CH0 'high' count to trigger interrupt. + * @prox_persistence: H/W Filters, Number of 'out of limits' proximity + * readings. + * @prox_interrupt_en: Enable/Disable proximity interrupts. * @prox_thres_low: Low threshold proximity detection. - * @prox_thres_high: High threshold proximity detection - * @prox_pulse_count: Number if proximity emitter pulses - * @prox_max_samples_cal: Used for prox cal. + * @prox_thres_high: High threshold proximity detection. + * @prox_pulse_count: Number if proximity emitter pulses. + * @prox_max_samples_cal: The number of samples that are taken when performing + * a proximity calibration. + * @prox_diode Which diode(s) to use for driving the external + * LED(s) for proximity sensing. + * @prox_power The amount of power to use for the external LED(s). */ struct tsl2x7x_settings { int als_time; int als_gain; int als_gain_trim; int wait_time; - int prx_time; + int prox_time; int prox_gain; - int prox_config; + int als_prox_config; int als_cal_target; - u8 interrupts_en; - u8 persistence; + u8 als_persistence; + bool als_interrupt_en; int als_thresh_low; int als_thresh_high; + u8 prox_persistence; + bool prox_interrupt_en; int prox_thres_low; int prox_thres_high; int prox_pulse_count; @@ -84,9 +90,6 @@ struct tsl2x7x_settings { /** * struct tsl2X7X_platform_data - Platform callback, glass and defaults - * @platform_power: Suspend/resume platform callback - * @power_on: Power on callback - * @power_off: Power off callback * @platform_lux_table: Device specific glass coefficents * @platform_default_settings: Device specific power on defaults * diff --git a/drivers/staging/iio/meter/ade7854-i2c.c b/drivers/staging/iio/meter/ade7854-i2c.c index 317e4f0d8176..c3aa6ea9d036 100644 --- a/drivers/staging/iio/meter/ade7854-i2c.c +++ b/drivers/staging/iio/meter/ade7854-i2c.c @@ -15,91 +15,60 @@ #include <linux/iio/iio.h> #include "ade7854.h" -static int ade7854_i2c_write_reg_8(struct device *dev, - u16 reg_address, - u8 val) +static int ade7854_i2c_write_reg(struct device *dev, + u16 reg_address, + u32 val, + int bits) { int ret; + int count; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); st->tx[0] = (reg_address >> 8) & 0xFF; st->tx[1] = reg_address & 0xFF; - st->tx[2] = val; - ret = i2c_master_send(st->i2c, st->tx, 3); + switch (bits) { + case 8: + st->tx[2] = val & 0xFF; + count = 3; + break; + case 16: + st->tx[2] = (val >> 8) & 0xFF; + st->tx[3] = val & 0xFF; + count = 4; + break; + case 24: + st->tx[2] = (val >> 16) & 0xFF; + st->tx[3] = (val >> 8) & 0xFF; + st->tx[4] = val & 0xFF; + count = 5; + break; + case 32: + st->tx[2] = (val >> 24) & 0xFF; + st->tx[3] = (val >> 16) & 0xFF; + st->tx[4] = (val >> 8) & 0xFF; + st->tx[5] = val & 0xFF; + count = 6; + break; + default: + ret = -EINVAL; + goto unlock; + } + + ret = i2c_master_send(st->i2c, st->tx, count); + +unlock: mutex_unlock(&st->buf_lock); - return ret; + return ret < 0 ? ret : 0; } -static int ade7854_i2c_write_reg_16(struct device *dev, - u16 reg_address, - u16 val) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7854_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->tx[0] = (reg_address >> 8) & 0xFF; - st->tx[1] = reg_address & 0xFF; - st->tx[2] = (val >> 8) & 0xFF; - st->tx[3] = val & 0xFF; - - ret = i2c_master_send(st->i2c, st->tx, 4); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int ade7854_i2c_write_reg_24(struct device *dev, - u16 reg_address, - u32 val) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7854_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->tx[0] = (reg_address >> 8) & 0xFF; - st->tx[1] = reg_address & 0xFF; - st->tx[2] = (val >> 16) & 0xFF; - st->tx[3] = (val >> 8) & 0xFF; - st->tx[4] = val & 0xFF; - - ret = i2c_master_send(st->i2c, st->tx, 5); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int ade7854_i2c_write_reg_32(struct device *dev, - u16 reg_address, - u32 val) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7854_state *st = iio_priv(indio_dev); - - mutex_lock(&st->buf_lock); - st->tx[0] = (reg_address >> 8) & 0xFF; - st->tx[1] = reg_address & 0xFF; - st->tx[2] = (val >> 24) & 0xFF; - st->tx[3] = (val >> 16) & 0xFF; - st->tx[4] = (val >> 8) & 0xFF; - st->tx[5] = val & 0xFF; - - ret = i2c_master_send(st->i2c, st->tx, 6); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int ade7854_i2c_read_reg_8(struct device *dev, - u16 reg_address, - u8 *val) +static int ade7854_i2c_read_reg(struct device *dev, + u16 reg_address, + u32 *val, + int bits) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); @@ -110,94 +79,33 @@ static int ade7854_i2c_read_reg_8(struct device *dev, st->tx[1] = reg_address & 0xFF; ret = i2c_master_send(st->i2c, st->tx, 2); - if (ret) - goto out; - - ret = i2c_master_recv(st->i2c, st->rx, 1); - if (ret) - goto out; - - *val = st->rx[0]; -out: - mutex_unlock(&st->buf_lock); - return ret; -} - -static int ade7854_i2c_read_reg_16(struct device *dev, - u16 reg_address, - u16 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7854_state *st = iio_priv(indio_dev); - int ret; - - mutex_lock(&st->buf_lock); - st->tx[0] = (reg_address >> 8) & 0xFF; - st->tx[1] = reg_address & 0xFF; - - ret = i2c_master_send(st->i2c, st->tx, 2); - if (ret) - goto out; - - ret = i2c_master_recv(st->i2c, st->rx, 2); - if (ret) - goto out; - - *val = (st->rx[0] << 8) | st->rx[1]; -out: - mutex_unlock(&st->buf_lock); - return ret; -} - -static int ade7854_i2c_read_reg_24(struct device *dev, - u16 reg_address, - u32 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7854_state *st = iio_priv(indio_dev); - int ret; - - mutex_lock(&st->buf_lock); - st->tx[0] = (reg_address >> 8) & 0xFF; - st->tx[1] = reg_address & 0xFF; - - ret = i2c_master_send(st->i2c, st->tx, 2); - if (ret) - goto out; - - ret = i2c_master_recv(st->i2c, st->rx, 3); - if (ret) - goto out; - - *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2]; -out: - mutex_unlock(&st->buf_lock); - return ret; -} - -static int ade7854_i2c_read_reg_32(struct device *dev, - u16 reg_address, - u32 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7854_state *st = iio_priv(indio_dev); - int ret; - - mutex_lock(&st->buf_lock); - st->tx[0] = (reg_address >> 8) & 0xFF; - st->tx[1] = reg_address & 0xFF; - - ret = i2c_master_send(st->i2c, st->tx, 2); - if (ret) - goto out; - - ret = i2c_master_recv(st->i2c, st->rx, 3); - if (ret) - goto out; - - *val = (st->rx[0] << 24) | (st->rx[1] << 16) | - (st->rx[2] << 8) | st->rx[3]; -out: + if (ret < 0) + goto unlock; + + ret = i2c_master_recv(st->i2c, st->rx, bits); + if (ret < 0) + goto unlock; + + switch (bits) { + case 8: + *val = st->rx[0]; + break; + case 16: + *val = (st->rx[0] << 8) | st->rx[1]; + break; + case 24: + *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2]; + break; + case 32: + *val = (st->rx[0] << 24) | (st->rx[1] << 16) | + (st->rx[2] << 8) | st->rx[3]; + break; + default: + ret = -EINVAL; + goto unlock; + } + +unlock: mutex_unlock(&st->buf_lock); return ret; } @@ -213,14 +121,8 @@ static int ade7854_i2c_probe(struct i2c_client *client, return -ENOMEM; st = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); - st->read_reg_8 = ade7854_i2c_read_reg_8; - st->read_reg_16 = ade7854_i2c_read_reg_16; - st->read_reg_24 = ade7854_i2c_read_reg_24; - st->read_reg_32 = ade7854_i2c_read_reg_32; - st->write_reg_8 = ade7854_i2c_write_reg_8; - st->write_reg_16 = ade7854_i2c_write_reg_16; - st->write_reg_24 = ade7854_i2c_write_reg_24; - st->write_reg_32 = ade7854_i2c_write_reg_32; + st->read_reg = ade7854_i2c_read_reg; + st->write_reg = ade7854_i2c_write_reg; st->i2c = client; st->irq = client->irq; diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c index 4419b8f06197..fc9146757283 100644 --- a/drivers/staging/iio/meter/ade7854-spi.c +++ b/drivers/staging/iio/meter/ade7854-spi.c @@ -15,9 +15,10 @@ #include <linux/iio/iio.h> #include "ade7854.h" -static int ade7854_spi_write_reg_8(struct device *dev, - u16 reg_address, - u8 val) +static int ade7854_spi_write_reg(struct device *dev, + u16 reg_address, + u32 val, + int bits) { int ret; struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -32,173 +33,44 @@ static int ade7854_spi_write_reg_8(struct device *dev, st->tx[0] = ADE7854_WRITE_REG; st->tx[1] = (reg_address >> 8) & 0xFF; st->tx[2] = reg_address & 0xFF; - st->tx[3] = val & 0xFF; - - ret = spi_sync_transfer(st->spi, &xfer, 1); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int ade7854_spi_write_reg_16(struct device *dev, - u16 reg_address, - u16 val) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7854_state *st = iio_priv(indio_dev); - struct spi_transfer xfer = { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 5, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADE7854_WRITE_REG; - st->tx[1] = (reg_address >> 8) & 0xFF; - st->tx[2] = reg_address & 0xFF; - st->tx[3] = (val >> 8) & 0xFF; - st->tx[4] = val & 0xFF; - - ret = spi_sync_transfer(st->spi, &xfer, 1); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int ade7854_spi_write_reg_24(struct device *dev, - u16 reg_address, - u32 val) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7854_state *st = iio_priv(indio_dev); - struct spi_transfer xfer = { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 6, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADE7854_WRITE_REG; - st->tx[1] = (reg_address >> 8) & 0xFF; - st->tx[2] = reg_address & 0xFF; - st->tx[3] = (val >> 16) & 0xFF; - st->tx[4] = (val >> 8) & 0xFF; - st->tx[5] = val & 0xFF; - - ret = spi_sync_transfer(st->spi, &xfer, 1); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int ade7854_spi_write_reg_32(struct device *dev, - u16 reg_address, - u32 val) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7854_state *st = iio_priv(indio_dev); - struct spi_transfer xfer = { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 7, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADE7854_WRITE_REG; - st->tx[1] = (reg_address >> 8) & 0xFF; - st->tx[2] = reg_address & 0xFF; - st->tx[3] = (val >> 24) & 0xFF; - st->tx[4] = (val >> 16) & 0xFF; - st->tx[5] = (val >> 8) & 0xFF; - st->tx[6] = val & 0xFF; - - ret = spi_sync_transfer(st->spi, &xfer, 1); - mutex_unlock(&st->buf_lock); - - return ret; -} - -static int ade7854_spi_read_reg_8(struct device *dev, - u16 reg_address, - u8 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7854_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 3, - }, { - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 1, - } - }; - - mutex_lock(&st->buf_lock); - - st->tx[0] = ADE7854_READ_REG; - st->tx[1] = (reg_address >> 8) & 0xFF; - st->tx[2] = reg_address & 0xFF; - - ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); - if (ret) { - dev_err(&st->spi->dev, "problem when reading 8 bit register 0x%02X", - reg_address); - goto error_ret; + switch (bits) { + case 8: + st->tx[3] = val & 0xFF; + break; + case 16: + xfer.len = 5; + st->tx[3] = (val >> 8) & 0xFF; + st->tx[4] = val & 0xFF; + break; + case 24: + xfer.len = 6; + st->tx[3] = (val >> 16) & 0xFF; + st->tx[4] = (val >> 8) & 0xFF; + st->tx[5] = val & 0xFF; + break; + case 32: + xfer.len = 7; + st->tx[3] = (val >> 24) & 0xFF; + st->tx[4] = (val >> 16) & 0xFF; + st->tx[5] = (val >> 8) & 0xFF; + st->tx[6] = val & 0xFF; + break; + default: + ret = -EINVAL; + goto unlock; } - *val = st->rx[0]; -error_ret: + ret = spi_sync_transfer(st->spi, &xfer, 1); +unlock: mutex_unlock(&st->buf_lock); - return ret; -} - -static int ade7854_spi_read_reg_16(struct device *dev, - u16 reg_address, - u16 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7854_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 3, - }, { - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 2, - } - }; - mutex_lock(&st->buf_lock); - st->tx[0] = ADE7854_READ_REG; - st->tx[1] = (reg_address >> 8) & 0xFF; - st->tx[2] = reg_address & 0xFF; - - ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); - if (ret) { - dev_err(&st->spi->dev, "problem when reading 16 bit register 0x%02X", - reg_address); - goto error_ret; - } - *val = be16_to_cpup((const __be16 *)st->rx); - -error_ret: - mutex_unlock(&st->buf_lock); return ret; } -static int ade7854_spi_read_reg_24(struct device *dev, - u16 reg_address, - u32 *val) +static int ade7854_spi_read_reg(struct device *dev, + u16 reg_address, + u32 *val, + int bits) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); @@ -211,7 +83,7 @@ static int ade7854_spi_read_reg_24(struct device *dev, }, { .rx_buf = st->rx, .bits_per_word = 8, - .len = 3, + .len = bits, } }; @@ -222,52 +94,28 @@ static int ade7854_spi_read_reg_24(struct device *dev, st->tx[2] = reg_address & 0xFF; ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); - if (ret) { - dev_err(&st->spi->dev, "problem when reading 24 bit register 0x%02X", + if (ret < 0) { + dev_err(&st->spi->dev, "problem when reading register 0x%02X", reg_address); - goto error_ret; + goto unlock; } - *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2]; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -static int ade7854_spi_read_reg_32(struct device *dev, - u16 reg_address, - u32 *val) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ade7854_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 3, - }, { - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 4, - } - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADE7854_READ_REG; - st->tx[1] = (reg_address >> 8) & 0xFF; - st->tx[2] = reg_address & 0xFF; - - ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); - if (ret) { - dev_err(&st->spi->dev, "problem when reading 32 bit register 0x%02X", - reg_address); - goto error_ret; + switch (bits) { + case 8: + *val = st->rx[0]; + break; + case 16: + *val = be16_to_cpup((const __be16 *)st->rx); + break; + case 24: + *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2]; + break; + case 32: + *val = be32_to_cpup((const __be32 *)st->rx); + break; } - *val = be32_to_cpup((const __be32 *)st->rx); -error_ret: +unlock: mutex_unlock(&st->buf_lock); return ret; } @@ -282,14 +130,8 @@ static int ade7854_spi_probe(struct spi_device *spi) return -ENOMEM; st = iio_priv(indio_dev); spi_set_drvdata(spi, indio_dev); - st->read_reg_8 = ade7854_spi_read_reg_8; - st->read_reg_16 = ade7854_spi_read_reg_16; - st->read_reg_24 = ade7854_spi_read_reg_24; - st->read_reg_32 = ade7854_spi_read_reg_32; - st->write_reg_8 = ade7854_spi_write_reg_8; - st->write_reg_16 = ade7854_spi_write_reg_16; - st->write_reg_24 = ade7854_spi_write_reg_24; - st->write_reg_32 = ade7854_spi_write_reg_32; + st->read_reg = ade7854_spi_read_reg; + st->write_reg = ade7854_spi_write_reg; st->irq = spi->irq; st->spi = spi; diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c index 90d07cdca4b8..029c3bf42d4d 100644 --- a/drivers/staging/iio/meter/ade7854.c +++ b/drivers/staging/iio/meter/ade7854.c @@ -27,13 +27,13 @@ static ssize_t ade7854_read_8bit(struct device *dev, char *buf) { int ret; - u8 val = 0; + u32 val = 0; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - ret = st->read_reg_8(dev, this_attr->address, &val); - if (ret) + ret = st->read_reg(dev, this_attr->address, &val, 8); + if (ret < 0) return ret; return sprintf(buf, "%u\n", val); @@ -44,13 +44,13 @@ static ssize_t ade7854_read_16bit(struct device *dev, char *buf) { int ret; - u16 val = 0; + u32 val = 0; struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - ret = st->read_reg_16(dev, this_attr->address, &val); - if (ret) + ret = st->read_reg(dev, this_attr->address, &val, 16); + if (ret < 0) return ret; return sprintf(buf, "%u\n", val); @@ -66,8 +66,8 @@ static ssize_t ade7854_read_24bit(struct device *dev, struct ade7854_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - ret = st->read_reg_24(dev, this_attr->address, &val); - if (ret) + ret = st->read_reg(dev, this_attr->address, &val, 24); + if (ret < 0) return ret; return sprintf(buf, "%u\n", val); @@ -83,8 +83,8 @@ static ssize_t ade7854_read_32bit(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); - ret = st->read_reg_32(dev, this_attr->address, &val); - if (ret) + ret = st->read_reg(dev, this_attr->address, &val, 32); + if (ret < 0) return ret; return sprintf(buf, "%u\n", val); @@ -105,7 +105,7 @@ static ssize_t ade7854_write_8bit(struct device *dev, ret = kstrtou8(buf, 10, &val); if (ret) goto error_ret; - ret = st->write_reg_8(dev, this_attr->address, val); + ret = st->write_reg(dev, this_attr->address, val, 8); error_ret: return ret ? ret : len; @@ -126,7 +126,7 @@ static ssize_t ade7854_write_16bit(struct device *dev, ret = kstrtou16(buf, 10, &val); if (ret) goto error_ret; - ret = st->write_reg_16(dev, this_attr->address, val); + ret = st->write_reg(dev, this_attr->address, val, 16); error_ret: return ret ? ret : len; @@ -147,7 +147,7 @@ static ssize_t ade7854_write_24bit(struct device *dev, ret = kstrtou32(buf, 10, &val); if (ret) goto error_ret; - ret = st->write_reg_24(dev, this_attr->address, val); + ret = st->write_reg(dev, this_attr->address, val, 24); error_ret: return ret ? ret : len; @@ -168,7 +168,7 @@ static ssize_t ade7854_write_32bit(struct device *dev, ret = kstrtou32(buf, 10, &val); if (ret) goto error_ret; - ret = st->write_reg_32(dev, this_attr->address, val); + ret = st->write_reg(dev, this_attr->address, val, 32); error_ret: return ret ? ret : len; @@ -178,12 +178,12 @@ static int ade7854_reset(struct device *dev) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7854_state *st = iio_priv(indio_dev); - u16 val; + u32 val; - st->read_reg_16(dev, ADE7854_CONFIG, &val); + st->read_reg(dev, ADE7854_CONFIG, &val, 16); val |= BIT(7); /* Software Chip Reset */ - return st->write_reg_16(dev, ADE7854_CONFIG, val); + return st->write_reg(dev, ADE7854_CONFIG, val, 16); } static IIO_DEV_ATTR_AIGAIN(0644, @@ -415,8 +415,8 @@ static int ade7854_set_irq(struct device *dev, bool enable) int ret; u32 irqen; - ret = st->read_reg_32(dev, ADE7854_MASK0, &irqen); - if (ret) + ret = st->read_reg(dev, ADE7854_MASK0, &irqen, 32); + if (ret < 0) return ret; if (enable) @@ -426,7 +426,7 @@ static int ade7854_set_irq(struct device *dev, bool enable) else irqen &= ~BIT(17); - return st->write_reg_32(dev, ADE7854_MASK0, irqen); + return st->write_reg(dev, ADE7854_MASK0, irqen, 32); } static int ade7854_initial_setup(struct iio_dev *indio_dev) diff --git a/drivers/staging/iio/meter/ade7854.h b/drivers/staging/iio/meter/ade7854.h index a82d38224cbd..a51e6e3183d3 100644 --- a/drivers/staging/iio/meter/ade7854.h +++ b/drivers/staging/iio/meter/ade7854.h @@ -145,7 +145,9 @@ /** * struct ade7854_state - device instance specific data - * @spi: actual spi_device + * @spi: actual spi_device + * @read_reg Wrapper function for I2C and SPI read + * @write_reg Wrapper function for I2C and SPI write * @indio_dev: industrial I/O device structure * @buf_lock: mutex to protect tx and rx * @tx: transmit buffer @@ -154,14 +156,10 @@ struct ade7854_state { struct spi_device *spi; struct i2c_client *i2c; - int (*read_reg_8)(struct device *dev, u16 reg_address, u8 *val); - int (*read_reg_16)(struct device *dev, u16 reg_address, u16 *val); - int (*read_reg_24)(struct device *dev, u16 reg_address, u32 *val); - int (*read_reg_32)(struct device *dev, u16 reg_address, u32 *val); - int (*write_reg_8)(struct device *dev, u16 reg_address, u8 val); - int (*write_reg_16)(struct device *dev, u16 reg_address, u16 val); - int (*write_reg_24)(struct device *dev, u16 reg_address, u32 val); - int (*write_reg_32)(struct device *dev, u16 reg_address, u32 val); + int (*read_reg)(struct device *dev, u16 reg_address, u32 *val, + int bits); + int (*write_reg)(struct device *dev, u16 reg_address, u32 val, + int bits); int irq; struct mutex buf_lock; u8 tx[ADE7854_MAX_TX] ____cacheline_aligned; diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c index aa62c64e9bc4..ea7336645116 100644 --- a/drivers/staging/iio/resolver/ad2s1200.c +++ b/drivers/staging/iio/resolver/ad2s1200.c @@ -9,16 +9,16 @@ * published by the Free Software Foundation. * */ -#include <linux/types.h> -#include <linux/mutex.h> -#include <linux/device.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> + +#include <linux/bitops.h> #include <linux/delay.h> +#include <linux/device.h> #include <linux/gpio.h> #include <linux/module.h> -#include <linux/bitops.h> +#include <linux/mutex.h> +#include <linux/spi/spi.h> +#include <linux/sysfs.h> +#include <linux/types.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> @@ -38,7 +38,7 @@ struct ad2s1200_state { struct spi_device *sdev; int sample; int rdvel; - u8 rx[2] ____cacheline_aligned; + __be16 rx ____cacheline_aligned; }; static int ad2s1200_read_raw(struct iio_dev *indio_dev, @@ -47,17 +47,18 @@ static int ad2s1200_read_raw(struct iio_dev *indio_dev, int *val2, long m) { - int ret = 0; - s16 vel; struct ad2s1200_state *st = iio_priv(indio_dev); + int ret = 0; mutex_lock(&st->lock); gpio_set_value(st->sample, 0); + /* delay (6 * AD2S1200_TSCLK + 20) nano seconds */ udelay(1); gpio_set_value(st->sample, 1); gpio_set_value(st->rdvel, !!(chan->type == IIO_ANGL)); - ret = spi_read(st->sdev, st->rx, 2); + + ret = spi_read(st->sdev, &st->rx, 2); if (ret < 0) { mutex_unlock(&st->lock); return ret; @@ -65,20 +66,20 @@ static int ad2s1200_read_raw(struct iio_dev *indio_dev, switch (chan->type) { case IIO_ANGL: - *val = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); + *val = be16_to_cpup(&st->rx) >> 4; break; case IIO_ANGL_VEL: - vel = (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); - vel = sign_extend32(vel, 11); - *val = vel; + *val = sign_extend32(be16_to_cpup(&st->rx) >> 4, 11); break; default: mutex_unlock(&st->lock); return -EINVAL; } + /* delay (2 * AD2S1200_TSCLK + 20) ns for sample pulse */ udelay(1); mutex_unlock(&st->lock); + return IIO_VAL_INT; } @@ -102,10 +103,10 @@ static const struct iio_info ad2s1200_info = { static int ad2s1200_probe(struct spi_device *spi) { + unsigned short *pins = spi->dev.platform_data; struct ad2s1200_state *st; struct iio_dev *indio_dev; int pn, ret = 0; - unsigned short *pins = spi->dev.platform_data; for (pn = 0; pn < AD2S1200_PN; pn++) { ret = devm_gpio_request_one(&spi->dev, pins[pn], GPIOF_DIR_OUT, @@ -116,9 +117,11 @@ static int ad2s1200_probe(struct spi_device *spi) return ret; } } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; + spi_set_drvdata(spi, indio_dev); st = iio_priv(indio_dev); mutex_init(&st->lock); |