Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'iio-for-4.10c' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next

Jonathan writes:

Third set of IIO new device support, features and cleanup for the 4.10 cycle.

Includes Peter Rosin's interesting drivers for a comparator. First complex
use we have had with an analog front end made from discrete components.

Brian Masney's work on moving the tsl2583 driver out of staging also
feature extensively!

New Drivers
* DAC based on a digital potentiometer
- New driver for the use of a dpot as a DAC. Includes bindings and Axentia
entry in vendor prefixes.
* Envelope detector baed on DAC and a comparator including device tree
bindings.

Staging Graduation
* tsl2583.

Core new features
- Core provision for _available attributes. This one had been stalled for
a long time until Peter picked it up and ran with it!
- In kernel interface helpers to retrieve available info from channels.

Driver new features
* mcp4531
- Add range of available raw values (used for the dpot dac driver).

Driver cleanups and fixes for issues introduced
* ad7766
- Testing the wrong variable following devm_regulator_bulk_get introduced
with the driver earlier in this cycle.
* ad9832
- Fix a wrong ordering in the probe introduced in the previous set of
patches. A use before allocation bug.
* cros_ec_sensors
- Testing for an error in a u8 will never work.
* mpu3050
- Remove duplicate initializer for the module owner.
- Add missing i2c dependency.
- Inform the i2c mux core how it is used - step one in implifying device
tree bindings.
* st-sensors
- Get rid of large number of uninformative defines in favour of putting the
constants where they are relevant. It is clear what they are from where
they are used.
* tsl2583
- Fix unused function warning when CONFIG_PM disabled and remove the
ifdefs in favour of __maybe_unused.
- Refactor taos_chip_on to only read relevant registers.
- Make sure calibscale and integration time are being set.
- Verify chip is in ready to be used before calibration.
- Remove some repeated checks for chip status (it's protected by a mutex
so can't change until it's released)
- Change current state storage from a tristate enum to a boolean seeing as
only two values are actually used now.
- Drop a redundant write to the control regiser in taos_probe (it's a noop)
- Drop the FSF mailing address.
- Clean up logging to not use hard coded function names (use __func__
instead).
- Cleanup up variable and function name prefixes.
- Alignment of #define fixes.
- Fix comparison between signed and unsigned integer warnings.
- Add some newlines in favour of readability.
- Combine the two sysfs ABI docs that somehow ended up in different places.
- Fix multiline comment syntax.
- Move a code block to inside an else statement as it makes more sense there.
- Change tsl2583_als_calibrate to return 0 rather than a value nothing
reads.
- Drop some pointless brackets
- Don't assume 32bit unsigned int.
- Change to a per device instance lux table.
- Add missing tsl2583 to the list of supported devices in the intro comments.
- Improve commment on clearing of interrupts.
- Drop some uninformative comments.
- Drop a memset call that doesn't do anything useful any more.
- Don't initialize some return variables that are always set.
- Add Brian Masney as a module author after all these changes.

+1995 -981
+36
Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector
··· 1 + What: /sys/bus/iio/devices/iio:deviceX/in_altvoltageY_invert 2 + Date: October 2016 3 + KernelVersion: 4.9 4 + Contact: Peter Rosin <peda@axentia.se> 5 + Description: 6 + The DAC is used to find the peak level of an alternating 7 + voltage input signal by a binary search using the output 8 + of a comparator wired to an interrupt pin. Like so: 9 + _ 10 + | \ 11 + input +------>-------|+ \ 12 + | \ 13 + .-------. | }---. 14 + | | | / | 15 + | dac|-->--|- / | 16 + | | |_/ | 17 + | | | 18 + | | | 19 + | irq|------<-------' 20 + | | 21 + '-------' 22 + The boolean invert attribute (0/1) should be set when the 23 + input signal is centered around the maximum value of the 24 + dac instead of zero. The envelope detector will search 25 + from below in this case and will also invert the result. 26 + The edge/level of the interrupt is also switched to its 27 + opposite value. 28 + 29 + What: /sys/bus/iio/devices/iio:deviceX/in_altvoltageY_compare_interval 30 + Date: October 2016 31 + KernelVersion: 4.9 32 + Contact: Peter Rosin <peda@axentia.se> 33 + Description: 34 + Number of milliseconds to wait for the comparator in each 35 + step of the binary search for the input peak level. Needs 36 + to relate to the frequency of the input signal.
+8
Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac
··· 1 + What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_raw_available 2 + Date: October 2016 3 + KernelVersion: 4.9 4 + Contact: Peter Rosin <peda@axentia.se> 5 + Description: 6 + The range of available values represented as the minimum value, 7 + the step and the maximum value, all enclosed in square brackets. 8 + Example: [0 1 256]
+20
Documentation/ABI/testing/sysfs-bus-iio-light-tsl2583
··· 1 + What: /sys/bus/iio/devices/device[n]/in_illuminance_calibrate 2 + KernelVersion: 2.6.37 3 + Contact: linux-iio@vger.kernel.org 4 + Description: 5 + This property causes an internal calibration of the als gain trim 6 + value which is later used in calculating illuminance in lux. 7 + 8 + What: /sys/bus/iio/devices/device[n]/in_illuminance_lux_table 9 + KernelVersion: 2.6.37 10 + Contact: linux-iio@vger.kernel.org 11 + Description: 12 + This property gets/sets the table of coefficients 13 + used in calculating illuminance in lux. 14 + 15 + What: /sys/bus/iio/devices/device[n]/in_illuminance_input_target 16 + KernelVersion: 2.6.37 17 + Contact: linux-iio@vger.kernel.org 18 + Description: 19 + This property is the known externally illuminance (in lux). 20 + It is used in the process of calibrating the device accuracy.
+8
Documentation/ABI/testing/sysfs-bus-iio-potentiometer-mcp4531
··· 1 + What: /sys/bus/iio/devices/iio:deviceX/out_resistance_raw_available 2 + Date: October 2016 3 + KernelVersion: 4.9 4 + Contact: Peter Rosin <peda@axentia.se> 5 + Description: 6 + The range of available values represented as the minimum value, 7 + the step and the maximum value, all enclosed in square brackets. 8 + Example: [0 1 256]
+54
Documentation/devicetree/bindings/iio/adc/envelope-detector.txt
··· 1 + Bindings for ADC envelope detector using a DAC and a comparator 2 + 3 + The DAC is used to find the peak level of an alternating voltage input 4 + signal by a binary search using the output of a comparator wired to 5 + an interrupt pin. Like so: 6 + _ 7 + | \ 8 + input +------>-------|+ \ 9 + | \ 10 + .-------. | }---. 11 + | | | / | 12 + | dac|-->--|- / | 13 + | | |_/ | 14 + | | | 15 + | | | 16 + | irq|------<-------' 17 + | | 18 + '-------' 19 + 20 + Required properties: 21 + - compatible: Should be "axentia,tse850-envelope-detector" 22 + - io-channels: Channel node of the dac to be used for comparator input. 23 + - io-channel-names: Should be "dac". 24 + - interrupt specification for one client interrupt, 25 + see ../../interrupt-controller/interrupts.txt for details. 26 + - interrupt-names: Should be "comp". 27 + 28 + Example: 29 + 30 + &i2c { 31 + dpot: mcp4651-104@28 { 32 + compatible = "microchip,mcp4651-104"; 33 + reg = <0x28>; 34 + #io-channel-cells = <1>; 35 + }; 36 + }; 37 + 38 + dac: dac { 39 + compatible = "dpot-dac"; 40 + vref-supply = <&reg_3v3>; 41 + io-channels = <&dpot 0>; 42 + io-channel-names = "dpot"; 43 + #io-channel-cells = <1>; 44 + }; 45 + 46 + envelope-detector { 47 + compatible = "axentia,tse850-envelope-detector"; 48 + io-channels = <&dac 0>; 49 + io-channel-names = "dac"; 50 + 51 + interrupt-parent = <&gpio>; 52 + interrupts = <3 IRQ_TYPE_EDGE_FALLING>; 53 + interrupt-names = "comp"; 54 + };
+41
Documentation/devicetree/bindings/iio/dac/dpot-dac.txt
··· 1 + Bindings for DAC emulation using a digital potentiometer 2 + 3 + It is assumed that the dpot is used as a voltage divider between the 4 + current dpot wiper setting and the maximum resistance of the dpot. The 5 + divided voltage is provided by a vref regulator. 6 + 7 + .------. 8 + .-----------. | | 9 + | vref |--' .---. 10 + | regulator |--. | | 11 + '-----------' | | d | 12 + | | p | 13 + | | o | wiper 14 + | | t |<---------+ 15 + | | | 16 + | '---' dac output voltage 17 + | | 18 + '------+------------+ 19 + 20 + Required properties: 21 + - compatible: Should be "dpot-dac" 22 + - vref-supply: The regulator supplying the voltage divider. 23 + - io-channels: Channel node of the dpot to be used for the voltage division. 24 + - io-channel-names: Should be "dpot". 25 + 26 + Example: 27 + 28 + &i2c { 29 + dpot: mcp4651-503@28 { 30 + compatible = "microchip,mcp4651-503"; 31 + reg = <0x28>; 32 + #io-channel-cells = <1>; 33 + }; 34 + }; 35 + 36 + dac { 37 + compatible = "dpot-dac"; 38 + vref-supply = <&reg_3v3>; 39 + io-channels = <&dpot 0>; 40 + io-channel-names = "dpot"; 41 + };
+1
Documentation/devicetree/bindings/vendor-prefixes.txt
··· 39 39 auvidea Auvidea GmbH 40 40 avago Avago Technologies 41 41 avic Shanghai AVIC Optoelectronics Co., Ltd. 42 + axentia Axentia Technologies AB 42 43 axis Axis Communications AB 43 44 boe BOE Technology Group Co., Ltd. 44 45 bosch Bosch Sensortec GmbH
+17
MAINTAINERS
··· 6124 6124 S: Maintained 6125 6125 F: drivers/media/rc/iguanair.c 6126 6126 6127 + IIO DIGITAL POTENTIOMETER DAC 6128 + M: Peter Rosin <peda@axentia.se> 6129 + L: linux-iio@vger.kernel.org 6130 + S: Maintained 6131 + F: Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac 6132 + F: Documentation/devicetree/bindings/iio/dac/dpot-dac.txt 6133 + F: drivers/iio/dac/dpot-dac.c 6134 + 6135 + IIO ENVELOPE DETECTOR 6136 + M: Peter Rosin <peda@axentia.se> 6137 + L: linux-iio@vger.kernel.org 6138 + S: Maintained 6139 + F: Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector 6140 + F: Documentation/devicetree/bindings/iio/adc/envelope-detector.txt 6141 + F: drivers/iio/adc/envelope-detector.c 6142 + 6127 6143 IIO SUBSYSTEM AND DRIVERS 6128 6144 M: Jonathan Cameron <jic23@kernel.org> 6129 6145 R: Hartmut Knaack <knaack.h@gmx.de> ··· 7730 7714 M: Peter Rosin <peda@axentia.se> 7731 7715 L: linux-iio@vger.kernel.org 7732 7716 S: Maintained 7717 + F: Documentation/ABI/testing/sysfs-bus-iio-potentiometer-mcp4531 7733 7718 F: drivers/iio/potentiometer/mcp4531.c 7734 7719 7735 7720 MEASUREMENT COMPUTING CIO-DAC IIO DRIVER
+10
drivers/iio/adc/Kconfig
··· 207 207 To compile this driver as a module, choose M here: the module will be 208 208 called berlin2-adc. 209 209 210 + config ENVELOPE_DETECTOR 211 + tristate "Envelope detector using a DAC and a comparator" 212 + depends on OF 213 + help 214 + Say yes here to build support for an envelope detector using a DAC 215 + and a comparator. 216 + 217 + To compile this driver as a module, choose M here: the module will be 218 + called envelope-detector. 219 + 210 220 config EXYNOS_ADC 211 221 tristate "Exynos ADC driver support" 212 222 depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST)
+1
drivers/iio/adc/Makefile
··· 21 21 obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o 22 22 obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o 23 23 obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o 24 + obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o 24 25 obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o 25 26 obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o 26 27 obj-$(CONFIG_HI8435) += hi8435.o
+2 -2
drivers/iio/adc/ad7766.c
··· 239 239 240 240 ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(ad7766->reg), 241 241 ad7766->reg); 242 - if (IS_ERR(ad7766->reg)) 243 - return PTR_ERR(ad7766->reg); 242 + if (ret) 243 + return ret; 244 244 245 245 ad7766->pd_gpio = devm_gpiod_get_optional(&spi->dev, "powerdown", 246 246 GPIOD_OUT_HIGH);
+422
drivers/iio/adc/envelope-detector.c
··· 1 + /* 2 + * Driver for an envelope detector using a DAC and a comparator 3 + * 4 + * Copyright (C) 2016 Axentia Technologies AB 5 + * 6 + * Author: Peter Rosin <peda@axentia.se> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + 13 + /* 14 + * The DAC is used to find the peak level of an alternating voltage input 15 + * signal by a binary search using the output of a comparator wired to 16 + * an interrupt pin. Like so: 17 + * _ 18 + * | \ 19 + * input +------>-------|+ \ 20 + * | \ 21 + * .-------. | }---. 22 + * | | | / | 23 + * | dac|-->--|- / | 24 + * | | |_/ | 25 + * | | | 26 + * | | | 27 + * | irq|------<-------' 28 + * | | 29 + * '-------' 30 + */ 31 + 32 + #include <linux/completion.h> 33 + #include <linux/device.h> 34 + #include <linux/err.h> 35 + #include <linux/kernel.h> 36 + #include <linux/module.h> 37 + #include <linux/mutex.h> 38 + #include <linux/iio/consumer.h> 39 + #include <linux/iio/iio.h> 40 + #include <linux/iio/sysfs.h> 41 + #include <linux/interrupt.h> 42 + #include <linux/irq.h> 43 + #include <linux/of.h> 44 + #include <linux/of_device.h> 45 + #include <linux/platform_device.h> 46 + #include <linux/spinlock.h> 47 + #include <linux/workqueue.h> 48 + 49 + struct envelope { 50 + spinlock_t comp_lock; /* protects comp */ 51 + int comp; 52 + 53 + struct mutex read_lock; /* protects everything else */ 54 + 55 + int comp_irq; 56 + u32 comp_irq_trigger; 57 + u32 comp_irq_trigger_inv; 58 + 59 + struct iio_channel *dac; 60 + struct delayed_work comp_timeout; 61 + 62 + unsigned int comp_interval; 63 + bool invert; 64 + u32 dac_max; 65 + 66 + int high; 67 + int level; 68 + int low; 69 + 70 + struct completion done; 71 + }; 72 + 73 + /* 74 + * The envelope_detector_comp_latch function works together with the compare 75 + * interrupt service routine below (envelope_detector_comp_isr) as a latch 76 + * (one-bit memory) for if the interrupt has triggered since last calling 77 + * this function. 78 + * The ..._comp_isr function disables the interrupt so that the cpu does not 79 + * need to service a possible interrupt flood from the comparator when no-one 80 + * cares anyway, and this ..._comp_latch function reenables them again if 81 + * needed. 82 + */ 83 + static int envelope_detector_comp_latch(struct envelope *env) 84 + { 85 + int comp; 86 + 87 + spin_lock_irq(&env->comp_lock); 88 + comp = env->comp; 89 + env->comp = 0; 90 + spin_unlock_irq(&env->comp_lock); 91 + 92 + if (!comp) 93 + return 0; 94 + 95 + /* 96 + * The irq was disabled, and is reenabled just now. 97 + * But there might have been a pending irq that 98 + * happened while the irq was disabled that fires 99 + * just as the irq is reenabled. That is not what 100 + * is desired. 101 + */ 102 + enable_irq(env->comp_irq); 103 + 104 + /* So, synchronize this possibly pending irq... */ 105 + synchronize_irq(env->comp_irq); 106 + 107 + /* ...and redo the whole dance. */ 108 + spin_lock_irq(&env->comp_lock); 109 + comp = env->comp; 110 + env->comp = 0; 111 + spin_unlock_irq(&env->comp_lock); 112 + 113 + if (comp) 114 + enable_irq(env->comp_irq); 115 + 116 + return 1; 117 + } 118 + 119 + static irqreturn_t envelope_detector_comp_isr(int irq, void *ctx) 120 + { 121 + struct envelope *env = ctx; 122 + 123 + spin_lock(&env->comp_lock); 124 + env->comp = 1; 125 + disable_irq_nosync(env->comp_irq); 126 + spin_unlock(&env->comp_lock); 127 + 128 + return IRQ_HANDLED; 129 + } 130 + 131 + static void envelope_detector_setup_compare(struct envelope *env) 132 + { 133 + int ret; 134 + 135 + /* 136 + * Do a binary search for the peak input level, and stop 137 + * when that level is "trapped" between two adjacent DAC 138 + * values. 139 + * When invert is active, use the midpoint floor so that 140 + * env->level ends up as env->low when the termination 141 + * criteria below is fulfilled, and use the midpoint 142 + * ceiling when invert is not active so that env->level 143 + * ends up as env->high in that case. 144 + */ 145 + env->level = (env->high + env->low + !env->invert) / 2; 146 + 147 + if (env->high == env->low + 1) { 148 + complete(&env->done); 149 + return; 150 + } 151 + 152 + /* Set a "safe" DAC level (if there is such a thing)... */ 153 + ret = iio_write_channel_raw(env->dac, env->invert ? 0 : env->dac_max); 154 + if (ret < 0) 155 + goto err; 156 + 157 + /* ...clear the comparison result... */ 158 + envelope_detector_comp_latch(env); 159 + 160 + /* ...set the real DAC level... */ 161 + ret = iio_write_channel_raw(env->dac, env->level); 162 + if (ret < 0) 163 + goto err; 164 + 165 + /* ...and wait for a bit to see if the latch catches anything. */ 166 + schedule_delayed_work(&env->comp_timeout, 167 + msecs_to_jiffies(env->comp_interval)); 168 + return; 169 + 170 + err: 171 + env->level = ret; 172 + complete(&env->done); 173 + } 174 + 175 + static void envelope_detector_timeout(struct work_struct *work) 176 + { 177 + struct envelope *env = container_of(work, struct envelope, 178 + comp_timeout.work); 179 + 180 + /* Adjust low/high depending on the latch content... */ 181 + if (!envelope_detector_comp_latch(env) ^ !env->invert) 182 + env->low = env->level; 183 + else 184 + env->high = env->level; 185 + 186 + /* ...and continue the search. */ 187 + envelope_detector_setup_compare(env); 188 + } 189 + 190 + static int envelope_detector_read_raw(struct iio_dev *indio_dev, 191 + struct iio_chan_spec const *chan, 192 + int *val, int *val2, long mask) 193 + { 194 + struct envelope *env = iio_priv(indio_dev); 195 + int ret; 196 + 197 + switch (mask) { 198 + case IIO_CHAN_INFO_RAW: 199 + /* 200 + * When invert is active, start with high=max+1 and low=0 201 + * since we will end up with the low value when the 202 + * termination criteria is fulfilled (rounding down). And 203 + * start with high=max and low=-1 when invert is not active 204 + * since we will end up with the high value in that case. 205 + * This ensures that the returned value in both cases are 206 + * in the same range as the DAC and is a value that has not 207 + * triggered the comparator. 208 + */ 209 + mutex_lock(&env->read_lock); 210 + env->high = env->dac_max + env->invert; 211 + env->low = -1 + env->invert; 212 + envelope_detector_setup_compare(env); 213 + wait_for_completion(&env->done); 214 + if (env->level < 0) { 215 + ret = env->level; 216 + goto err_unlock; 217 + } 218 + *val = env->invert ? env->dac_max - env->level : env->level; 219 + mutex_unlock(&env->read_lock); 220 + 221 + return IIO_VAL_INT; 222 + 223 + case IIO_CHAN_INFO_SCALE: 224 + return iio_read_channel_scale(env->dac, val, val2); 225 + } 226 + 227 + return -EINVAL; 228 + 229 + err_unlock: 230 + mutex_unlock(&env->read_lock); 231 + return ret; 232 + } 233 + 234 + static ssize_t envelope_show_invert(struct iio_dev *indio_dev, 235 + uintptr_t private, 236 + struct iio_chan_spec const *ch, char *buf) 237 + { 238 + struct envelope *env = iio_priv(indio_dev); 239 + 240 + return sprintf(buf, "%u\n", env->invert); 241 + } 242 + 243 + static ssize_t envelope_store_invert(struct iio_dev *indio_dev, 244 + uintptr_t private, 245 + struct iio_chan_spec const *ch, 246 + const char *buf, size_t len) 247 + { 248 + struct envelope *env = iio_priv(indio_dev); 249 + unsigned long invert; 250 + int ret; 251 + u32 trigger; 252 + 253 + ret = kstrtoul(buf, 0, &invert); 254 + if (ret < 0) 255 + return ret; 256 + if (invert > 1) 257 + return -EINVAL; 258 + 259 + trigger = invert ? env->comp_irq_trigger_inv : env->comp_irq_trigger; 260 + 261 + mutex_lock(&env->read_lock); 262 + if (invert != env->invert) 263 + ret = irq_set_irq_type(env->comp_irq, trigger); 264 + if (!ret) { 265 + env->invert = invert; 266 + ret = len; 267 + } 268 + mutex_unlock(&env->read_lock); 269 + 270 + return ret; 271 + } 272 + 273 + static ssize_t envelope_show_comp_interval(struct iio_dev *indio_dev, 274 + uintptr_t private, 275 + struct iio_chan_spec const *ch, 276 + char *buf) 277 + { 278 + struct envelope *env = iio_priv(indio_dev); 279 + 280 + return sprintf(buf, "%u\n", env->comp_interval); 281 + } 282 + 283 + static ssize_t envelope_store_comp_interval(struct iio_dev *indio_dev, 284 + uintptr_t private, 285 + struct iio_chan_spec const *ch, 286 + const char *buf, size_t len) 287 + { 288 + struct envelope *env = iio_priv(indio_dev); 289 + unsigned long interval; 290 + int ret; 291 + 292 + ret = kstrtoul(buf, 0, &interval); 293 + if (ret < 0) 294 + return ret; 295 + if (interval > 1000) 296 + return -EINVAL; 297 + 298 + mutex_lock(&env->read_lock); 299 + env->comp_interval = interval; 300 + mutex_unlock(&env->read_lock); 301 + 302 + return len; 303 + } 304 + 305 + static const struct iio_chan_spec_ext_info envelope_detector_ext_info[] = { 306 + { .name = "invert", 307 + .read = envelope_show_invert, 308 + .write = envelope_store_invert, }, 309 + { .name = "compare_interval", 310 + .read = envelope_show_comp_interval, 311 + .write = envelope_store_comp_interval, }, 312 + { /* sentinel */ } 313 + }; 314 + 315 + static const struct iio_chan_spec envelope_detector_iio_channel = { 316 + .type = IIO_ALTVOLTAGE, 317 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) 318 + | BIT(IIO_CHAN_INFO_SCALE), 319 + .ext_info = envelope_detector_ext_info, 320 + .indexed = 1, 321 + }; 322 + 323 + static const struct iio_info envelope_detector_info = { 324 + .read_raw = &envelope_detector_read_raw, 325 + .driver_module = THIS_MODULE, 326 + }; 327 + 328 + static int envelope_detector_probe(struct platform_device *pdev) 329 + { 330 + struct device *dev = &pdev->dev; 331 + struct iio_dev *indio_dev; 332 + struct envelope *env; 333 + enum iio_chan_type type; 334 + int ret; 335 + 336 + indio_dev = devm_iio_device_alloc(dev, sizeof(*env)); 337 + if (!indio_dev) 338 + return -ENOMEM; 339 + 340 + platform_set_drvdata(pdev, indio_dev); 341 + env = iio_priv(indio_dev); 342 + env->comp_interval = 50; /* some sensible default? */ 343 + 344 + spin_lock_init(&env->comp_lock); 345 + mutex_init(&env->read_lock); 346 + init_completion(&env->done); 347 + INIT_DELAYED_WORK(&env->comp_timeout, envelope_detector_timeout); 348 + 349 + indio_dev->name = dev_name(dev); 350 + indio_dev->dev.parent = dev; 351 + indio_dev->dev.of_node = dev->of_node; 352 + indio_dev->info = &envelope_detector_info; 353 + indio_dev->channels = &envelope_detector_iio_channel; 354 + indio_dev->num_channels = 1; 355 + 356 + env->dac = devm_iio_channel_get(dev, "dac"); 357 + if (IS_ERR(env->dac)) { 358 + if (PTR_ERR(env->dac) != -EPROBE_DEFER) 359 + dev_err(dev, "failed to get dac input channel\n"); 360 + return PTR_ERR(env->dac); 361 + } 362 + 363 + env->comp_irq = platform_get_irq_byname(pdev, "comp"); 364 + if (env->comp_irq < 0) { 365 + if (env->comp_irq != -EPROBE_DEFER) 366 + dev_err(dev, "failed to get compare interrupt\n"); 367 + return env->comp_irq; 368 + } 369 + 370 + ret = devm_request_irq(dev, env->comp_irq, envelope_detector_comp_isr, 371 + 0, "envelope-detector", env); 372 + if (ret) { 373 + if (ret != -EPROBE_DEFER) 374 + dev_err(dev, "failed to request interrupt\n"); 375 + return ret; 376 + } 377 + env->comp_irq_trigger = irq_get_trigger_type(env->comp_irq); 378 + if (env->comp_irq_trigger & IRQF_TRIGGER_RISING) 379 + env->comp_irq_trigger_inv |= IRQF_TRIGGER_FALLING; 380 + if (env->comp_irq_trigger & IRQF_TRIGGER_FALLING) 381 + env->comp_irq_trigger_inv |= IRQF_TRIGGER_RISING; 382 + if (env->comp_irq_trigger & IRQF_TRIGGER_HIGH) 383 + env->comp_irq_trigger_inv |= IRQF_TRIGGER_LOW; 384 + if (env->comp_irq_trigger & IRQF_TRIGGER_LOW) 385 + env->comp_irq_trigger_inv |= IRQF_TRIGGER_HIGH; 386 + 387 + ret = iio_get_channel_type(env->dac, &type); 388 + if (ret < 0) 389 + return ret; 390 + 391 + if (type != IIO_VOLTAGE) { 392 + dev_err(dev, "dac is of the wrong type\n"); 393 + return -EINVAL; 394 + } 395 + 396 + ret = iio_read_max_channel_raw(env->dac, &env->dac_max); 397 + if (ret < 0) { 398 + dev_err(dev, "dac does not indicate its raw maximum value\n"); 399 + return ret; 400 + } 401 + 402 + return devm_iio_device_register(dev, indio_dev); 403 + } 404 + 405 + static const struct of_device_id envelope_detector_match[] = { 406 + { .compatible = "axentia,tse850-envelope-detector", }, 407 + { /* sentinel */ } 408 + }; 409 + MODULE_DEVICE_TABLE(of, envelope_detector_match); 410 + 411 + static struct platform_driver envelope_detector_driver = { 412 + .probe = envelope_detector_probe, 413 + .driver = { 414 + .name = "iio-envelope-detector", 415 + .of_match_table = envelope_detector_match, 416 + }, 417 + }; 418 + module_platform_driver(envelope_detector_driver); 419 + 420 + MODULE_DESCRIPTION("Envelope detector using a DAC and a comparator"); 421 + MODULE_AUTHOR("Peter Rosin <peda@axentia.se>"); 422 + MODULE_LICENSE("GPL v2");
+4 -4
drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
··· 291 291 return -EIO; 292 292 293 293 /* Read status byte until EC is not busy. */ 294 - status = cros_ec_sensors_read_until_not_busy(st); 295 - if (status < 0) 296 - return status; 294 + ret = cros_ec_sensors_read_until_not_busy(st); 295 + if (ret < 0) 296 + return ret; 297 297 298 298 /* 299 299 * Store the current sample id so that we can compare to the 300 300 * sample id after reading the data. 301 301 */ 302 - samp_id = status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK; 302 + samp_id = ret & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK; 303 303 304 304 /* Read all EC data, format it, and store it into data. */ 305 305 ret = cros_ec_sensors_read_data_unsafe(indio_dev, scan_mask,
+10
drivers/iio/dac/Kconfig
··· 200 200 To compile this driver as a module choose M here: the module will be called 201 201 ad8801. 202 202 203 + config DPOT_DAC 204 + tristate "DAC emulation using a DPOT" 205 + depends on OF 206 + help 207 + Say yes here to build support for DAC emulation using a digital 208 + potentiometer. 209 + 210 + To compile this driver as a module, choose M here: the module will be 211 + called dpot-dac. 212 + 203 213 config LPC18XX_DAC 204 214 tristate "NXP LPC18xx DAC driver" 205 215 depends on ARCH_LPC18XX || COMPILE_TEST
+1
drivers/iio/dac/Makefile
··· 22 22 obj-$(CONFIG_AD7303) += ad7303.o 23 23 obj-$(CONFIG_AD8801) += ad8801.o 24 24 obj-$(CONFIG_CIO_DAC) += cio-dac.o 25 + obj-$(CONFIG_DPOT_DAC) += dpot-dac.o 25 26 obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o 26 27 obj-$(CONFIG_M62332) += m62332.o 27 28 obj-$(CONFIG_MAX517) += max517.o
+266
drivers/iio/dac/dpot-dac.c
··· 1 + /* 2 + * IIO DAC emulation driver using a digital potentiometer 3 + * 4 + * Copyright (C) 2016 Axentia Technologies AB 5 + * 6 + * Author: Peter Rosin <peda@axentia.se> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + 13 + /* 14 + * It is assumed that the dpot is used as a voltage divider between the 15 + * current dpot wiper setting and the maximum resistance of the dpot. The 16 + * divided voltage is provided by a vref regulator. 17 + * 18 + * .------. 19 + * .-----------. | | 20 + * | vref |--' .---. 21 + * | regulator |--. | | 22 + * '-----------' | | d | 23 + * | | p | 24 + * | | o | wiper 25 + * | | t |<---------+ 26 + * | | | 27 + * | '---' dac output voltage 28 + * | | 29 + * '------+------------+ 30 + */ 31 + 32 + #include <linux/err.h> 33 + #include <linux/iio/consumer.h> 34 + #include <linux/iio/iio.h> 35 + #include <linux/module.h> 36 + #include <linux/of.h> 37 + #include <linux/platform_device.h> 38 + #include <linux/regulator/consumer.h> 39 + 40 + struct dpot_dac { 41 + struct regulator *vref; 42 + struct iio_channel *dpot; 43 + u32 max_ohms; 44 + }; 45 + 46 + static const struct iio_chan_spec dpot_dac_iio_channel = { 47 + .type = IIO_VOLTAGE, 48 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) 49 + | BIT(IIO_CHAN_INFO_SCALE), 50 + .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW), 51 + .output = 1, 52 + .indexed = 1, 53 + }; 54 + 55 + static int dpot_dac_read_raw(struct iio_dev *indio_dev, 56 + struct iio_chan_spec const *chan, 57 + int *val, int *val2, long mask) 58 + { 59 + struct dpot_dac *dac = iio_priv(indio_dev); 60 + int ret; 61 + unsigned long long tmp; 62 + 63 + switch (mask) { 64 + case IIO_CHAN_INFO_RAW: 65 + return iio_read_channel_raw(dac->dpot, val); 66 + 67 + case IIO_CHAN_INFO_SCALE: 68 + ret = iio_read_channel_scale(dac->dpot, val, val2); 69 + switch (ret) { 70 + case IIO_VAL_FRACTIONAL_LOG2: 71 + tmp = *val * 1000000000LL; 72 + do_div(tmp, dac->max_ohms); 73 + tmp *= regulator_get_voltage(dac->vref) / 1000; 74 + do_div(tmp, 1000000000LL); 75 + *val = tmp; 76 + return ret; 77 + case IIO_VAL_INT: 78 + /* 79 + * Convert integer scale to fractional scale by 80 + * setting the denominator (val2) to one... 81 + */ 82 + *val2 = 1; 83 + ret = IIO_VAL_FRACTIONAL; 84 + /* ...and fall through. */ 85 + case IIO_VAL_FRACTIONAL: 86 + *val *= regulator_get_voltage(dac->vref) / 1000; 87 + *val2 *= dac->max_ohms; 88 + break; 89 + } 90 + 91 + return ret; 92 + } 93 + 94 + return -EINVAL; 95 + } 96 + 97 + static int dpot_dac_read_avail(struct iio_dev *indio_dev, 98 + struct iio_chan_spec const *chan, 99 + const int **vals, int *type, int *length, 100 + long mask) 101 + { 102 + struct dpot_dac *dac = iio_priv(indio_dev); 103 + 104 + switch (mask) { 105 + case IIO_CHAN_INFO_RAW: 106 + *type = IIO_VAL_INT; 107 + return iio_read_avail_channel_raw(dac->dpot, vals, length); 108 + } 109 + 110 + return -EINVAL; 111 + } 112 + 113 + static int dpot_dac_write_raw(struct iio_dev *indio_dev, 114 + struct iio_chan_spec const *chan, 115 + int val, int val2, long mask) 116 + { 117 + struct dpot_dac *dac = iio_priv(indio_dev); 118 + 119 + switch (mask) { 120 + case IIO_CHAN_INFO_RAW: 121 + return iio_write_channel_raw(dac->dpot, val); 122 + } 123 + 124 + return -EINVAL; 125 + } 126 + 127 + static const struct iio_info dpot_dac_info = { 128 + .read_raw = dpot_dac_read_raw, 129 + .read_avail = dpot_dac_read_avail, 130 + .write_raw = dpot_dac_write_raw, 131 + .driver_module = THIS_MODULE, 132 + }; 133 + 134 + static int dpot_dac_channel_max_ohms(struct iio_dev *indio_dev) 135 + { 136 + struct device *dev = &indio_dev->dev; 137 + struct dpot_dac *dac = iio_priv(indio_dev); 138 + unsigned long long tmp; 139 + int ret; 140 + int val; 141 + int val2; 142 + int max; 143 + 144 + ret = iio_read_max_channel_raw(dac->dpot, &max); 145 + if (ret < 0) { 146 + dev_err(dev, "dpot does not indicate its raw maximum value\n"); 147 + return ret; 148 + } 149 + 150 + switch (iio_read_channel_scale(dac->dpot, &val, &val2)) { 151 + case IIO_VAL_INT: 152 + return max * val; 153 + case IIO_VAL_FRACTIONAL: 154 + tmp = (unsigned long long)max * val; 155 + do_div(tmp, val2); 156 + return tmp; 157 + case IIO_VAL_FRACTIONAL_LOG2: 158 + tmp = val * 1000000000LL * max >> val2; 159 + do_div(tmp, 1000000000LL); 160 + return tmp; 161 + default: 162 + dev_err(dev, "dpot has a scale that is too weird\n"); 163 + } 164 + 165 + return -EINVAL; 166 + } 167 + 168 + static int dpot_dac_probe(struct platform_device *pdev) 169 + { 170 + struct device *dev = &pdev->dev; 171 + struct iio_dev *indio_dev; 172 + struct dpot_dac *dac; 173 + enum iio_chan_type type; 174 + int ret; 175 + 176 + indio_dev = devm_iio_device_alloc(dev, sizeof(*dac)); 177 + if (!indio_dev) 178 + return -ENOMEM; 179 + 180 + platform_set_drvdata(pdev, indio_dev); 181 + dac = iio_priv(indio_dev); 182 + 183 + indio_dev->name = dev_name(dev); 184 + indio_dev->dev.parent = dev; 185 + indio_dev->info = &dpot_dac_info; 186 + indio_dev->modes = INDIO_DIRECT_MODE; 187 + indio_dev->channels = &dpot_dac_iio_channel; 188 + indio_dev->num_channels = 1; 189 + 190 + dac->vref = devm_regulator_get(dev, "vref"); 191 + if (IS_ERR(dac->vref)) { 192 + if (PTR_ERR(dac->vref) != -EPROBE_DEFER) 193 + dev_err(&pdev->dev, "failed to get vref regulator\n"); 194 + return PTR_ERR(dac->vref); 195 + } 196 + 197 + dac->dpot = devm_iio_channel_get(dev, "dpot"); 198 + if (IS_ERR(dac->dpot)) { 199 + if (PTR_ERR(dac->dpot) != -EPROBE_DEFER) 200 + dev_err(dev, "failed to get dpot input channel\n"); 201 + return PTR_ERR(dac->dpot); 202 + } 203 + 204 + ret = iio_get_channel_type(dac->dpot, &type); 205 + if (ret < 0) 206 + return ret; 207 + 208 + if (type != IIO_RESISTANCE) { 209 + dev_err(dev, "dpot is of the wrong type\n"); 210 + return -EINVAL; 211 + } 212 + 213 + ret = dpot_dac_channel_max_ohms(indio_dev); 214 + if (ret < 0) 215 + return ret; 216 + dac->max_ohms = ret; 217 + 218 + ret = regulator_enable(dac->vref); 219 + if (ret) { 220 + dev_err(dev, "failed to enable the vref regulator\n"); 221 + return ret; 222 + } 223 + 224 + ret = iio_device_register(indio_dev); 225 + if (ret) { 226 + dev_err(dev, "failed to register iio device\n"); 227 + goto disable_reg; 228 + } 229 + 230 + return 0; 231 + 232 + disable_reg: 233 + regulator_disable(dac->vref); 234 + return ret; 235 + } 236 + 237 + static int dpot_dac_remove(struct platform_device *pdev) 238 + { 239 + struct iio_dev *indio_dev = platform_get_drvdata(pdev); 240 + struct dpot_dac *dac = iio_priv(indio_dev); 241 + 242 + iio_device_unregister(indio_dev); 243 + regulator_disable(dac->vref); 244 + 245 + return 0; 246 + } 247 + 248 + static const struct of_device_id dpot_dac_match[] = { 249 + { .compatible = "dpot-dac" }, 250 + { /* sentinel */ } 251 + }; 252 + MODULE_DEVICE_TABLE(of, dpot_dac_match); 253 + 254 + static struct platform_driver dpot_dac_driver = { 255 + .probe = dpot_dac_probe, 256 + .remove = dpot_dac_remove, 257 + .driver = { 258 + .name = "iio-dpot-dac", 259 + .of_match_table = dpot_dac_match, 260 + }, 261 + }; 262 + module_platform_driver(dpot_dac_driver); 263 + 264 + MODULE_DESCRIPTION("DAC emulation driver using a digital potentiometer"); 265 + MODULE_AUTHOR("Peter Rosin <peda@axentia.se>"); 266 + MODULE_LICENSE("GPL v2");
+1
drivers/iio/gyro/Kconfig
··· 93 93 config MPU3050_I2C 94 94 tristate "Invensense MPU3050 devices on I2C" 95 95 depends on !(INPUT_MPU3050=y || INPUT_MPU3050=m) 96 + depends on I2C 96 97 select MPU3050 97 98 select REGMAP_I2C 98 99 select I2C_MUX
-1
drivers/iio/gyro/mpu3050-core.c
··· 746 746 .read_raw = mpu3050_read_raw, 747 747 .write_raw = mpu3050_write_raw, 748 748 .attrs = &mpu3050_attribute_group, 749 - .driver_module = THIS_MODULE, 750 749 }; 751 750 752 751 /**
+66 -139
drivers/iio/gyro/st_gyro_core.c
··· 39 39 #define ST_GYRO_FS_AVL_500DPS 500 40 40 #define ST_GYRO_FS_AVL_2000DPS 2000 41 41 42 - /* CUSTOM VALUES FOR SENSOR 1 */ 43 - #define ST_GYRO_1_WAI_EXP 0xd3 44 - #define ST_GYRO_1_ODR_ADDR 0x20 45 - #define ST_GYRO_1_ODR_MASK 0xc0 46 - #define ST_GYRO_1_ODR_AVL_100HZ_VAL 0x00 47 - #define ST_GYRO_1_ODR_AVL_200HZ_VAL 0x01 48 - #define ST_GYRO_1_ODR_AVL_400HZ_VAL 0x02 49 - #define ST_GYRO_1_ODR_AVL_800HZ_VAL 0x03 50 - #define ST_GYRO_1_PW_ADDR 0x20 51 - #define ST_GYRO_1_PW_MASK 0x08 52 - #define ST_GYRO_1_FS_ADDR 0x23 53 - #define ST_GYRO_1_FS_MASK 0x30 54 - #define ST_GYRO_1_FS_AVL_250_VAL 0x00 55 - #define ST_GYRO_1_FS_AVL_500_VAL 0x01 56 - #define ST_GYRO_1_FS_AVL_2000_VAL 0x02 57 - #define ST_GYRO_1_FS_AVL_250_GAIN IIO_DEGREE_TO_RAD(8750) 58 - #define ST_GYRO_1_FS_AVL_500_GAIN IIO_DEGREE_TO_RAD(17500) 59 - #define ST_GYRO_1_FS_AVL_2000_GAIN IIO_DEGREE_TO_RAD(70000) 60 - #define ST_GYRO_1_BDU_ADDR 0x23 61 - #define ST_GYRO_1_BDU_MASK 0x80 62 - #define ST_GYRO_1_DRDY_IRQ_ADDR 0x22 63 - #define ST_GYRO_1_DRDY_IRQ_INT2_MASK 0x08 64 - #define ST_GYRO_1_MULTIREAD_BIT true 65 - 66 - /* CUSTOM VALUES FOR SENSOR 2 */ 67 - #define ST_GYRO_2_WAI_EXP 0xd4 68 - #define ST_GYRO_2_ODR_ADDR 0x20 69 - #define ST_GYRO_2_ODR_MASK 0xc0 70 - #define ST_GYRO_2_ODR_AVL_95HZ_VAL 0x00 71 - #define ST_GYRO_2_ODR_AVL_190HZ_VAL 0x01 72 - #define ST_GYRO_2_ODR_AVL_380HZ_VAL 0x02 73 - #define ST_GYRO_2_ODR_AVL_760HZ_VAL 0x03 74 - #define ST_GYRO_2_PW_ADDR 0x20 75 - #define ST_GYRO_2_PW_MASK 0x08 76 - #define ST_GYRO_2_FS_ADDR 0x23 77 - #define ST_GYRO_2_FS_MASK 0x30 78 - #define ST_GYRO_2_FS_AVL_250_VAL 0x00 79 - #define ST_GYRO_2_FS_AVL_500_VAL 0x01 80 - #define ST_GYRO_2_FS_AVL_2000_VAL 0x02 81 - #define ST_GYRO_2_FS_AVL_250_GAIN IIO_DEGREE_TO_RAD(8750) 82 - #define ST_GYRO_2_FS_AVL_500_GAIN IIO_DEGREE_TO_RAD(17500) 83 - #define ST_GYRO_2_FS_AVL_2000_GAIN IIO_DEGREE_TO_RAD(70000) 84 - #define ST_GYRO_2_BDU_ADDR 0x23 85 - #define ST_GYRO_2_BDU_MASK 0x80 86 - #define ST_GYRO_2_DRDY_IRQ_ADDR 0x22 87 - #define ST_GYRO_2_DRDY_IRQ_INT2_MASK 0x08 88 - #define ST_GYRO_2_MULTIREAD_BIT true 89 - 90 - /* CUSTOM VALUES FOR SENSOR 3 */ 91 - #define ST_GYRO_3_WAI_EXP 0xd7 92 - #define ST_GYRO_3_ODR_ADDR 0x20 93 - #define ST_GYRO_3_ODR_MASK 0xc0 94 - #define ST_GYRO_3_ODR_AVL_95HZ_VAL 0x00 95 - #define ST_GYRO_3_ODR_AVL_190HZ_VAL 0x01 96 - #define ST_GYRO_3_ODR_AVL_380HZ_VAL 0x02 97 - #define ST_GYRO_3_ODR_AVL_760HZ_VAL 0x03 98 - #define ST_GYRO_3_PW_ADDR 0x20 99 - #define ST_GYRO_3_PW_MASK 0x08 100 - #define ST_GYRO_3_FS_ADDR 0x23 101 - #define ST_GYRO_3_FS_MASK 0x30 102 - #define ST_GYRO_3_FS_AVL_250_VAL 0x00 103 - #define ST_GYRO_3_FS_AVL_500_VAL 0x01 104 - #define ST_GYRO_3_FS_AVL_2000_VAL 0x02 105 - #define ST_GYRO_3_FS_AVL_250_GAIN IIO_DEGREE_TO_RAD(8750) 106 - #define ST_GYRO_3_FS_AVL_500_GAIN IIO_DEGREE_TO_RAD(17500) 107 - #define ST_GYRO_3_FS_AVL_2000_GAIN IIO_DEGREE_TO_RAD(70000) 108 - #define ST_GYRO_3_BDU_ADDR 0x23 109 - #define ST_GYRO_3_BDU_MASK 0x80 110 - #define ST_GYRO_3_DRDY_IRQ_ADDR 0x22 111 - #define ST_GYRO_3_DRDY_IRQ_INT2_MASK 0x08 112 - #define ST_GYRO_3_MULTIREAD_BIT true 113 - 114 - 115 42 static const struct iio_chan_spec st_gyro_16bit_channels[] = { 116 43 ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, 117 44 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ··· 57 130 58 131 static const struct st_sensor_settings st_gyro_sensors_settings[] = { 59 132 { 60 - .wai = ST_GYRO_1_WAI_EXP, 133 + .wai = 0xd3, 61 134 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, 62 135 .sensors_supported = { 63 136 [0] = L3G4200D_GYRO_DEV_NAME, ··· 65 138 }, 66 139 .ch = (struct iio_chan_spec *)st_gyro_16bit_channels, 67 140 .odr = { 68 - .addr = ST_GYRO_1_ODR_ADDR, 69 - .mask = ST_GYRO_1_ODR_MASK, 141 + .addr = 0x20, 142 + .mask = 0xc0, 70 143 .odr_avl = { 71 - { 100, ST_GYRO_1_ODR_AVL_100HZ_VAL, }, 72 - { 200, ST_GYRO_1_ODR_AVL_200HZ_VAL, }, 73 - { 400, ST_GYRO_1_ODR_AVL_400HZ_VAL, }, 74 - { 800, ST_GYRO_1_ODR_AVL_800HZ_VAL, }, 144 + { .hz = 100, .value = 0x00, }, 145 + { .hz = 200, .value = 0x01, }, 146 + { .hz = 400, .value = 0x02, }, 147 + { .hz = 800, .value = 0x03, }, 75 148 }, 76 149 }, 77 150 .pw = { 78 - .addr = ST_GYRO_1_PW_ADDR, 79 - .mask = ST_GYRO_1_PW_MASK, 151 + .addr = 0x20, 152 + .mask = 0x08, 80 153 .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, 81 154 .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, 82 155 }, ··· 85 158 .mask = ST_SENSORS_DEFAULT_AXIS_MASK, 86 159 }, 87 160 .fs = { 88 - .addr = ST_GYRO_1_FS_ADDR, 89 - .mask = ST_GYRO_1_FS_MASK, 161 + .addr = 0x23, 162 + .mask = 0x30, 90 163 .fs_avl = { 91 164 [0] = { 92 165 .num = ST_GYRO_FS_AVL_250DPS, 93 - .value = ST_GYRO_1_FS_AVL_250_VAL, 94 - .gain = ST_GYRO_1_FS_AVL_250_GAIN, 166 + .value = 0x00, 167 + .gain = IIO_DEGREE_TO_RAD(8750), 95 168 }, 96 169 [1] = { 97 170 .num = ST_GYRO_FS_AVL_500DPS, 98 - .value = ST_GYRO_1_FS_AVL_500_VAL, 99 - .gain = ST_GYRO_1_FS_AVL_500_GAIN, 171 + .value = 0x01, 172 + .gain = IIO_DEGREE_TO_RAD(17500), 100 173 }, 101 174 [2] = { 102 175 .num = ST_GYRO_FS_AVL_2000DPS, 103 - .value = ST_GYRO_1_FS_AVL_2000_VAL, 104 - .gain = ST_GYRO_1_FS_AVL_2000_GAIN, 176 + .value = 0x02, 177 + .gain = IIO_DEGREE_TO_RAD(70000), 105 178 }, 106 179 }, 107 180 }, 108 181 .bdu = { 109 - .addr = ST_GYRO_1_BDU_ADDR, 110 - .mask = ST_GYRO_1_BDU_MASK, 182 + .addr = 0x23, 183 + .mask = 0x80, 111 184 }, 112 185 .drdy_irq = { 113 - .addr = ST_GYRO_1_DRDY_IRQ_ADDR, 114 - .mask_int2 = ST_GYRO_1_DRDY_IRQ_INT2_MASK, 186 + .addr = 0x22, 187 + .mask_int2 = 0x08, 115 188 /* 116 189 * The sensor has IHL (active low) and open 117 190 * drain settings, but only for INT1 and not ··· 119 192 */ 120 193 .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, 121 194 }, 122 - .multi_read_bit = ST_GYRO_1_MULTIREAD_BIT, 195 + .multi_read_bit = true, 123 196 .bootime = 2, 124 197 }, 125 198 { 126 - .wai = ST_GYRO_2_WAI_EXP, 199 + .wai = 0xd4, 127 200 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, 128 201 .sensors_supported = { 129 202 [0] = L3GD20_GYRO_DEV_NAME, ··· 135 208 }, 136 209 .ch = (struct iio_chan_spec *)st_gyro_16bit_channels, 137 210 .odr = { 138 - .addr = ST_GYRO_2_ODR_ADDR, 139 - .mask = ST_GYRO_2_ODR_MASK, 211 + .addr = 0x20, 212 + .mask = 0xc0, 140 213 .odr_avl = { 141 - { 95, ST_GYRO_2_ODR_AVL_95HZ_VAL, }, 142 - { 190, ST_GYRO_2_ODR_AVL_190HZ_VAL, }, 143 - { 380, ST_GYRO_2_ODR_AVL_380HZ_VAL, }, 144 - { 760, ST_GYRO_2_ODR_AVL_760HZ_VAL, }, 214 + { .hz = 95, .value = 0x00, }, 215 + { .hz = 190, .value = 0x01, }, 216 + { .hz = 380, .value = 0x02, }, 217 + { .hz = 760, .value = 0x03, }, 145 218 }, 146 219 }, 147 220 .pw = { 148 - .addr = ST_GYRO_2_PW_ADDR, 149 - .mask = ST_GYRO_2_PW_MASK, 221 + .addr = 0x20, 222 + .mask = 0x08, 150 223 .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, 151 224 .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, 152 225 }, ··· 155 228 .mask = ST_SENSORS_DEFAULT_AXIS_MASK, 156 229 }, 157 230 .fs = { 158 - .addr = ST_GYRO_2_FS_ADDR, 159 - .mask = ST_GYRO_2_FS_MASK, 231 + .addr = 0x23, 232 + .mask = 0x30, 160 233 .fs_avl = { 161 234 [0] = { 162 235 .num = ST_GYRO_FS_AVL_250DPS, 163 - .value = ST_GYRO_2_FS_AVL_250_VAL, 164 - .gain = ST_GYRO_2_FS_AVL_250_GAIN, 236 + .value = 0x00, 237 + .gain = IIO_DEGREE_TO_RAD(8750), 165 238 }, 166 239 [1] = { 167 240 .num = ST_GYRO_FS_AVL_500DPS, 168 - .value = ST_GYRO_2_FS_AVL_500_VAL, 169 - .gain = ST_GYRO_2_FS_AVL_500_GAIN, 241 + .value = 0x01, 242 + .gain = IIO_DEGREE_TO_RAD(17500), 170 243 }, 171 244 [2] = { 172 245 .num = ST_GYRO_FS_AVL_2000DPS, 173 - .value = ST_GYRO_2_FS_AVL_2000_VAL, 174 - .gain = ST_GYRO_2_FS_AVL_2000_GAIN, 246 + .value = 0x02, 247 + .gain = IIO_DEGREE_TO_RAD(70000), 175 248 }, 176 249 }, 177 250 }, 178 251 .bdu = { 179 - .addr = ST_GYRO_2_BDU_ADDR, 180 - .mask = ST_GYRO_2_BDU_MASK, 252 + .addr = 0x23, 253 + .mask = 0x80, 181 254 }, 182 255 .drdy_irq = { 183 - .addr = ST_GYRO_2_DRDY_IRQ_ADDR, 184 - .mask_int2 = ST_GYRO_2_DRDY_IRQ_INT2_MASK, 256 + .addr = 0x22, 257 + .mask_int2 = 0x08, 185 258 /* 186 259 * The sensor has IHL (active low) and open 187 260 * drain settings, but only for INT1 and not ··· 189 262 */ 190 263 .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, 191 264 }, 192 - .multi_read_bit = ST_GYRO_2_MULTIREAD_BIT, 265 + .multi_read_bit = true, 193 266 .bootime = 2, 194 267 }, 195 268 { 196 - .wai = ST_GYRO_3_WAI_EXP, 269 + .wai = 0xd7, 197 270 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, 198 271 .sensors_supported = { 199 272 [0] = L3GD20_GYRO_DEV_NAME, 200 273 }, 201 274 .ch = (struct iio_chan_spec *)st_gyro_16bit_channels, 202 275 .odr = { 203 - .addr = ST_GYRO_3_ODR_ADDR, 204 - .mask = ST_GYRO_3_ODR_MASK, 276 + .addr = 0x20, 277 + .mask = 0xc0, 205 278 .odr_avl = { 206 - { 95, ST_GYRO_3_ODR_AVL_95HZ_VAL, }, 207 - { 190, ST_GYRO_3_ODR_AVL_190HZ_VAL, }, 208 - { 380, ST_GYRO_3_ODR_AVL_380HZ_VAL, }, 209 - { 760, ST_GYRO_3_ODR_AVL_760HZ_VAL, }, 279 + { .hz = 95, .value = 0x00, }, 280 + { .hz = 190, .value = 0x01, }, 281 + { .hz = 380, .value = 0x02, }, 282 + { .hz = 760, .value = 0x03, }, 210 283 }, 211 284 }, 212 285 .pw = { 213 - .addr = ST_GYRO_3_PW_ADDR, 214 - .mask = ST_GYRO_3_PW_MASK, 286 + .addr = 0x20, 287 + .mask = 0x08, 215 288 .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, 216 289 .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, 217 290 }, ··· 220 293 .mask = ST_SENSORS_DEFAULT_AXIS_MASK, 221 294 }, 222 295 .fs = { 223 - .addr = ST_GYRO_3_FS_ADDR, 224 - .mask = ST_GYRO_3_FS_MASK, 296 + .addr = 0x23, 297 + .mask = 0x30, 225 298 .fs_avl = { 226 299 [0] = { 227 300 .num = ST_GYRO_FS_AVL_250DPS, 228 - .value = ST_GYRO_3_FS_AVL_250_VAL, 229 - .gain = ST_GYRO_3_FS_AVL_250_GAIN, 301 + .value = 0x00, 302 + .gain = IIO_DEGREE_TO_RAD(8750), 230 303 }, 231 304 [1] = { 232 305 .num = ST_GYRO_FS_AVL_500DPS, 233 - .value = ST_GYRO_3_FS_AVL_500_VAL, 234 - .gain = ST_GYRO_3_FS_AVL_500_GAIN, 306 + .value = 0x01, 307 + .gain = IIO_DEGREE_TO_RAD(17500), 235 308 }, 236 309 [2] = { 237 310 .num = ST_GYRO_FS_AVL_2000DPS, 238 - .value = ST_GYRO_3_FS_AVL_2000_VAL, 239 - .gain = ST_GYRO_3_FS_AVL_2000_GAIN, 311 + .value = 0x02, 312 + .gain = IIO_DEGREE_TO_RAD(70000), 240 313 }, 241 314 }, 242 315 }, 243 316 .bdu = { 244 - .addr = ST_GYRO_3_BDU_ADDR, 245 - .mask = ST_GYRO_3_BDU_MASK, 317 + .addr = 0x23, 318 + .mask = 0x80, 246 319 }, 247 320 .drdy_irq = { 248 - .addr = ST_GYRO_3_DRDY_IRQ_ADDR, 249 - .mask_int2 = ST_GYRO_3_DRDY_IRQ_INT2_MASK, 321 + .addr = 0x22, 322 + .mask_int2 = 0x08, 250 323 /* 251 324 * The sensor has IHL (active low) and open 252 325 * drain settings, but only for INT1 and not ··· 254 327 */ 255 328 .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, 256 329 }, 257 - .multi_read_bit = ST_GYRO_3_MULTIREAD_BIT, 330 + .multi_read_bit = true, 258 331 .bootime = 2, 259 332 }, 260 333 };
+1 -1
drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
··· 126 126 127 127 st = iio_priv(dev_get_drvdata(&client->dev)); 128 128 st->muxc = i2c_mux_alloc(client->adapter, &client->dev, 129 - 1, 0, I2C_MUX_LOCKED, 129 + 1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE, 130 130 inv_mpu6050_select_bypass, 131 131 inv_mpu6050_deselect_bypass); 132 132 if (!st->muxc) {
+235 -42
drivers/iio/industrialio-core.c
··· 577 577 #endif 578 578 EXPORT_SYMBOL(of_iio_read_mount_matrix); 579 579 580 + static ssize_t __iio_format_value(char *buf, size_t len, unsigned int type, 581 + int size, const int *vals) 582 + { 583 + unsigned long long tmp; 584 + int tmp0, tmp1; 585 + bool scale_db = false; 586 + 587 + switch (type) { 588 + case IIO_VAL_INT: 589 + return snprintf(buf, len, "%d", vals[0]); 590 + case IIO_VAL_INT_PLUS_MICRO_DB: 591 + scale_db = true; 592 + case IIO_VAL_INT_PLUS_MICRO: 593 + if (vals[1] < 0) 594 + return snprintf(buf, len, "-%d.%06u%s", abs(vals[0]), 595 + -vals[1], scale_db ? " dB" : ""); 596 + else 597 + return snprintf(buf, len, "%d.%06u%s", vals[0], vals[1], 598 + scale_db ? " dB" : ""); 599 + case IIO_VAL_INT_PLUS_NANO: 600 + if (vals[1] < 0) 601 + return snprintf(buf, len, "-%d.%09u", abs(vals[0]), 602 + -vals[1]); 603 + else 604 + return snprintf(buf, len, "%d.%09u", vals[0], vals[1]); 605 + case IIO_VAL_FRACTIONAL: 606 + tmp = div_s64((s64)vals[0] * 1000000000LL, vals[1]); 607 + tmp1 = vals[1]; 608 + tmp0 = (int)div_s64_rem(tmp, 1000000000, &tmp1); 609 + return snprintf(buf, len, "%d.%09u", tmp0, abs(tmp1)); 610 + case IIO_VAL_FRACTIONAL_LOG2: 611 + tmp = (s64)vals[0] * 1000000000LL >> vals[1]; 612 + tmp1 = do_div(tmp, 1000000000LL); 613 + tmp0 = tmp; 614 + return snprintf(buf, len, "%d.%09u", tmp0, tmp1); 615 + case IIO_VAL_INT_MULTIPLE: 616 + { 617 + int i; 618 + int l = 0; 619 + 620 + for (i = 0; i < size; ++i) { 621 + l += snprintf(&buf[l], len - l, "%d ", vals[i]); 622 + if (l >= len) 623 + break; 624 + } 625 + return l; 626 + } 627 + default: 628 + return 0; 629 + } 630 + } 631 + 580 632 /** 581 633 * iio_format_value() - Formats a IIO value into its string representation 582 634 * @buf: The buffer to which the formatted value gets written 635 + * which is assumed to be big enough (i.e. PAGE_SIZE). 583 636 * @type: One of the IIO_VAL_... constants. This decides how the val 584 637 * and val2 parameters are formatted. 585 638 * @size: Number of IIO value entries contained in vals ··· 645 592 */ 646 593 ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals) 647 594 { 648 - unsigned long long tmp; 649 - bool scale_db = false; 595 + ssize_t len; 650 596 651 - switch (type) { 652 - case IIO_VAL_INT: 653 - return sprintf(buf, "%d\n", vals[0]); 654 - case IIO_VAL_INT_PLUS_MICRO_DB: 655 - scale_db = true; 656 - case IIO_VAL_INT_PLUS_MICRO: 657 - if (vals[1] < 0) 658 - return sprintf(buf, "-%d.%06u%s\n", abs(vals[0]), 659 - -vals[1], scale_db ? " dB" : ""); 660 - else 661 - return sprintf(buf, "%d.%06u%s\n", vals[0], vals[1], 662 - scale_db ? " dB" : ""); 663 - case IIO_VAL_INT_PLUS_NANO: 664 - if (vals[1] < 0) 665 - return sprintf(buf, "-%d.%09u\n", abs(vals[0]), 666 - -vals[1]); 667 - else 668 - return sprintf(buf, "%d.%09u\n", vals[0], vals[1]); 669 - case IIO_VAL_FRACTIONAL: 670 - tmp = div_s64((s64)vals[0] * 1000000000LL, vals[1]); 671 - vals[0] = (int)div_s64_rem(tmp, 1000000000, &vals[1]); 672 - return sprintf(buf, "%d.%09u\n", vals[0], abs(vals[1])); 673 - case IIO_VAL_FRACTIONAL_LOG2: 674 - tmp = (s64)vals[0] * 1000000000LL >> vals[1]; 675 - vals[1] = do_div(tmp, 1000000000LL); 676 - vals[0] = tmp; 677 - return sprintf(buf, "%d.%09u\n", vals[0], vals[1]); 678 - case IIO_VAL_INT_MULTIPLE: 679 - { 680 - int i; 681 - int len = 0; 597 + len = __iio_format_value(buf, PAGE_SIZE, type, size, vals); 598 + if (len >= PAGE_SIZE - 1) 599 + return -EFBIG; 682 600 683 - for (i = 0; i < size; ++i) 684 - len += snprintf(&buf[len], PAGE_SIZE - len, "%d ", 685 - vals[i]); 686 - len += snprintf(&buf[len], PAGE_SIZE - len, "\n"); 687 - return len; 688 - } 689 - default: 690 - return 0; 691 - } 601 + return len + sprintf(buf + len, "\n"); 692 602 } 693 603 EXPORT_SYMBOL_GPL(iio_format_value); 694 604 ··· 678 662 return ret; 679 663 680 664 return iio_format_value(buf, ret, val_len, vals); 665 + } 666 + 667 + static ssize_t iio_format_avail_list(char *buf, const int *vals, 668 + int type, int length) 669 + { 670 + int i; 671 + ssize_t len = 0; 672 + 673 + switch (type) { 674 + case IIO_VAL_INT: 675 + for (i = 0; i < length; i++) { 676 + len += __iio_format_value(buf + len, PAGE_SIZE - len, 677 + type, 1, &vals[i]); 678 + if (len >= PAGE_SIZE) 679 + return -EFBIG; 680 + if (i < length - 1) 681 + len += snprintf(buf + len, PAGE_SIZE - len, 682 + " "); 683 + else 684 + len += snprintf(buf + len, PAGE_SIZE - len, 685 + "\n"); 686 + if (len >= PAGE_SIZE) 687 + return -EFBIG; 688 + } 689 + break; 690 + default: 691 + for (i = 0; i < length / 2; i++) { 692 + len += __iio_format_value(buf + len, PAGE_SIZE - len, 693 + type, 2, &vals[i * 2]); 694 + if (len >= PAGE_SIZE) 695 + return -EFBIG; 696 + if (i < length / 2 - 1) 697 + len += snprintf(buf + len, PAGE_SIZE - len, 698 + " "); 699 + else 700 + len += snprintf(buf + len, PAGE_SIZE - len, 701 + "\n"); 702 + if (len >= PAGE_SIZE) 703 + return -EFBIG; 704 + } 705 + } 706 + 707 + return len; 708 + } 709 + 710 + static ssize_t iio_format_avail_range(char *buf, const int *vals, int type) 711 + { 712 + int i; 713 + ssize_t len; 714 + 715 + len = snprintf(buf, PAGE_SIZE, "["); 716 + switch (type) { 717 + case IIO_VAL_INT: 718 + for (i = 0; i < 3; i++) { 719 + len += __iio_format_value(buf + len, PAGE_SIZE - len, 720 + type, 1, &vals[i]); 721 + if (len >= PAGE_SIZE) 722 + return -EFBIG; 723 + if (i < 2) 724 + len += snprintf(buf + len, PAGE_SIZE - len, 725 + " "); 726 + else 727 + len += snprintf(buf + len, PAGE_SIZE - len, 728 + "]\n"); 729 + if (len >= PAGE_SIZE) 730 + return -EFBIG; 731 + } 732 + break; 733 + default: 734 + for (i = 0; i < 3; i++) { 735 + len += __iio_format_value(buf + len, PAGE_SIZE - len, 736 + type, 2, &vals[i * 2]); 737 + if (len >= PAGE_SIZE) 738 + return -EFBIG; 739 + if (i < 2) 740 + len += snprintf(buf + len, PAGE_SIZE - len, 741 + " "); 742 + else 743 + len += snprintf(buf + len, PAGE_SIZE - len, 744 + "]\n"); 745 + if (len >= PAGE_SIZE) 746 + return -EFBIG; 747 + } 748 + } 749 + 750 + return len; 751 + } 752 + 753 + static ssize_t iio_read_channel_info_avail(struct device *dev, 754 + struct device_attribute *attr, 755 + char *buf) 756 + { 757 + struct iio_dev *indio_dev = dev_to_iio_dev(dev); 758 + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 759 + const int *vals; 760 + int ret; 761 + int length; 762 + int type; 763 + 764 + ret = indio_dev->info->read_avail(indio_dev, this_attr->c, 765 + &vals, &type, &length, 766 + this_attr->address); 767 + 768 + if (ret < 0) 769 + return ret; 770 + switch (ret) { 771 + case IIO_AVAIL_LIST: 772 + return iio_format_avail_list(buf, vals, type, length); 773 + case IIO_AVAIL_RANGE: 774 + return iio_format_avail_range(buf, vals, type); 775 + default: 776 + return -EINVAL; 777 + } 681 778 } 682 779 683 780 /** ··· 1109 980 return attrcount; 1110 981 } 1111 982 983 + static int iio_device_add_info_mask_type_avail(struct iio_dev *indio_dev, 984 + struct iio_chan_spec const *chan, 985 + enum iio_shared_by shared_by, 986 + const long *infomask) 987 + { 988 + int i, ret, attrcount = 0; 989 + char *avail_postfix; 990 + 991 + for_each_set_bit(i, infomask, sizeof(infomask) * 8) { 992 + avail_postfix = kasprintf(GFP_KERNEL, 993 + "%s_available", 994 + iio_chan_info_postfix[i]); 995 + if (!avail_postfix) 996 + return -ENOMEM; 997 + 998 + ret = __iio_add_chan_devattr(avail_postfix, 999 + chan, 1000 + &iio_read_channel_info_avail, 1001 + NULL, 1002 + i, 1003 + shared_by, 1004 + &indio_dev->dev, 1005 + &indio_dev->channel_attr_list); 1006 + kfree(avail_postfix); 1007 + if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE)) 1008 + continue; 1009 + else if (ret < 0) 1010 + return ret; 1011 + attrcount++; 1012 + } 1013 + 1014 + return attrcount; 1015 + } 1016 + 1112 1017 static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, 1113 1018 struct iio_chan_spec const *chan) 1114 1019 { ··· 1158 995 return ret; 1159 996 attrcount += ret; 1160 997 998 + ret = iio_device_add_info_mask_type_avail(indio_dev, chan, 999 + IIO_SEPARATE, 1000 + &chan-> 1001 + info_mask_separate_available); 1002 + if (ret < 0) 1003 + return ret; 1004 + attrcount += ret; 1005 + 1161 1006 ret = iio_device_add_info_mask_type(indio_dev, chan, 1162 1007 IIO_SHARED_BY_TYPE, 1163 1008 &chan->info_mask_shared_by_type); 1009 + if (ret < 0) 1010 + return ret; 1011 + attrcount += ret; 1012 + 1013 + ret = iio_device_add_info_mask_type_avail(indio_dev, chan, 1014 + IIO_SHARED_BY_TYPE, 1015 + &chan-> 1016 + info_mask_shared_by_type_available); 1164 1017 if (ret < 0) 1165 1018 return ret; 1166 1019 attrcount += ret; ··· 1188 1009 return ret; 1189 1010 attrcount += ret; 1190 1011 1012 + ret = iio_device_add_info_mask_type_avail(indio_dev, chan, 1013 + IIO_SHARED_BY_DIR, 1014 + &chan->info_mask_shared_by_dir_available); 1015 + if (ret < 0) 1016 + return ret; 1017 + attrcount += ret; 1018 + 1191 1019 ret = iio_device_add_info_mask_type(indio_dev, chan, 1192 1020 IIO_SHARED_BY_ALL, 1193 1021 &chan->info_mask_shared_by_all); 1022 + if (ret < 0) 1023 + return ret; 1024 + attrcount += ret; 1025 + 1026 + ret = iio_device_add_info_mask_type_avail(indio_dev, chan, 1027 + IIO_SHARED_BY_ALL, 1028 + &chan->info_mask_shared_by_all_available); 1194 1029 if (ret < 0) 1195 1030 return ret; 1196 1031 attrcount += ret;
+104
drivers/iio/inkern.c
··· 716 716 } 717 717 EXPORT_SYMBOL_GPL(iio_read_channel_scale); 718 718 719 + static int iio_channel_read_avail(struct iio_channel *chan, 720 + const int **vals, int *type, int *length, 721 + enum iio_chan_info_enum info) 722 + { 723 + if (!iio_channel_has_available(chan->channel, info)) 724 + return -EINVAL; 725 + 726 + return chan->indio_dev->info->read_avail(chan->indio_dev, chan->channel, 727 + vals, type, length, info); 728 + } 729 + 730 + int iio_read_avail_channel_raw(struct iio_channel *chan, 731 + const int **vals, int *length) 732 + { 733 + int ret; 734 + int type; 735 + 736 + mutex_lock(&chan->indio_dev->info_exist_lock); 737 + if (!chan->indio_dev->info) { 738 + ret = -ENODEV; 739 + goto err_unlock; 740 + } 741 + 742 + ret = iio_channel_read_avail(chan, 743 + vals, &type, length, IIO_CHAN_INFO_RAW); 744 + err_unlock: 745 + mutex_unlock(&chan->indio_dev->info_exist_lock); 746 + 747 + if (ret >= 0 && type != IIO_VAL_INT) { 748 + /* raw values are assumed to be IIO_VAL_INT */ 749 + ret = -EINVAL; 750 + goto err_unlock; 751 + } 752 + 753 + return ret; 754 + } 755 + EXPORT_SYMBOL_GPL(iio_read_avail_channel_raw); 756 + 757 + static int iio_channel_read_max(struct iio_channel *chan, 758 + int *val, int *val2, int *type, 759 + enum iio_chan_info_enum info) 760 + { 761 + int unused; 762 + const int *vals; 763 + int length; 764 + int ret; 765 + 766 + if (!val2) 767 + val2 = &unused; 768 + 769 + ret = iio_channel_read_avail(chan, &vals, type, &length, info); 770 + switch (ret) { 771 + case IIO_AVAIL_RANGE: 772 + switch (*type) { 773 + case IIO_VAL_INT: 774 + *val = vals[2]; 775 + break; 776 + default: 777 + *val = vals[4]; 778 + *val2 = vals[5]; 779 + } 780 + return 0; 781 + 782 + case IIO_AVAIL_LIST: 783 + if (length <= 0) 784 + return -EINVAL; 785 + switch (*type) { 786 + case IIO_VAL_INT: 787 + *val = vals[--length]; 788 + while (length) { 789 + if (vals[--length] > *val) 790 + *val = vals[length]; 791 + } 792 + break; 793 + default: 794 + /* FIXME: learn about max for other iio values */ 795 + return -EINVAL; 796 + } 797 + return 0; 798 + 799 + default: 800 + return ret; 801 + } 802 + } 803 + 804 + int iio_read_max_channel_raw(struct iio_channel *chan, int *val) 805 + { 806 + int ret; 807 + int type; 808 + 809 + mutex_lock(&chan->indio_dev->info_exist_lock); 810 + if (!chan->indio_dev->info) { 811 + ret = -ENODEV; 812 + goto err_unlock; 813 + } 814 + 815 + ret = iio_channel_read_max(chan, val, NULL, &type, IIO_CHAN_INFO_RAW); 816 + err_unlock: 817 + mutex_unlock(&chan->indio_dev->info_exist_lock); 818 + 819 + return ret; 820 + } 821 + EXPORT_SYMBOL_GPL(iio_read_max_channel_raw); 822 + 719 823 int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type) 720 824 { 721 825 int ret = 0;
+7
drivers/iio/light/Kconfig
··· 338 338 This driver can also be built as a module. If so, the module 339 339 will be called tsl2563. 340 340 341 + config TSL2583 342 + tristate "TAOS TSL2580, TSL2581 and TSL2583 light-to-digital converters" 343 + depends on I2C 344 + help 345 + Provides support for the TAOS tsl2580, tsl2581 and tsl2583 devices. 346 + Access ALS data via iio, sysfs. 347 + 341 348 config TSL4531 342 349 tristate "TAOS TSL4531 ambient light sensors" 343 350 depends on I2C
+1
drivers/iio/light/Makefile
··· 31 31 obj-$(CONFIG_STK3310) += stk3310.o 32 32 obj-$(CONFIG_TCS3414) += tcs3414.o 33 33 obj-$(CONFIG_TCS3472) += tcs3472.o 34 + obj-$(CONFIG_TSL2583) += tsl2583.o 34 35 obj-$(CONFIG_TSL4531) += tsl4531.o 35 36 obj-$(CONFIG_US5182D) += us5182d.o 36 37 obj-$(CONFIG_VCNL4000) += vcnl4000.o
+125 -251
drivers/iio/magnetometer/st_magn_core.c
··· 46 46 #define ST_MAGN_FS_AVL_15000MG 15000 47 47 #define ST_MAGN_FS_AVL_16000MG 16000 48 48 49 - /* CUSTOM VALUES FOR SENSOR 0 */ 50 - #define ST_MAGN_0_ODR_ADDR 0x00 51 - #define ST_MAGN_0_ODR_MASK 0x1c 52 - #define ST_MAGN_0_ODR_AVL_1HZ_VAL 0x00 53 - #define ST_MAGN_0_ODR_AVL_2HZ_VAL 0x01 54 - #define ST_MAGN_0_ODR_AVL_3HZ_VAL 0x02 55 - #define ST_MAGN_0_ODR_AVL_8HZ_VAL 0x03 56 - #define ST_MAGN_0_ODR_AVL_15HZ_VAL 0x04 57 - #define ST_MAGN_0_ODR_AVL_30HZ_VAL 0x05 58 - #define ST_MAGN_0_ODR_AVL_75HZ_VAL 0x06 59 - #define ST_MAGN_0_ODR_AVL_220HZ_VAL 0x07 60 - #define ST_MAGN_0_PW_ADDR 0x02 61 - #define ST_MAGN_0_PW_MASK 0x03 62 - #define ST_MAGN_0_PW_ON 0x00 63 - #define ST_MAGN_0_PW_OFF 0x03 64 - #define ST_MAGN_0_FS_ADDR 0x01 65 - #define ST_MAGN_0_FS_MASK 0xe0 66 - #define ST_MAGN_0_FS_AVL_1300_VAL 0x01 67 - #define ST_MAGN_0_FS_AVL_1900_VAL 0x02 68 - #define ST_MAGN_0_FS_AVL_2500_VAL 0x03 69 - #define ST_MAGN_0_FS_AVL_4000_VAL 0x04 70 - #define ST_MAGN_0_FS_AVL_4700_VAL 0x05 71 - #define ST_MAGN_0_FS_AVL_5600_VAL 0x06 72 - #define ST_MAGN_0_FS_AVL_8100_VAL 0x07 73 - #define ST_MAGN_0_FS_AVL_1300_GAIN_XY 1100 74 - #define ST_MAGN_0_FS_AVL_1900_GAIN_XY 855 75 - #define ST_MAGN_0_FS_AVL_2500_GAIN_XY 670 76 - #define ST_MAGN_0_FS_AVL_4000_GAIN_XY 450 77 - #define ST_MAGN_0_FS_AVL_4700_GAIN_XY 400 78 - #define ST_MAGN_0_FS_AVL_5600_GAIN_XY 330 79 - #define ST_MAGN_0_FS_AVL_8100_GAIN_XY 230 80 - #define ST_MAGN_0_FS_AVL_1300_GAIN_Z 980 81 - #define ST_MAGN_0_FS_AVL_1900_GAIN_Z 760 82 - #define ST_MAGN_0_FS_AVL_2500_GAIN_Z 600 83 - #define ST_MAGN_0_FS_AVL_4000_GAIN_Z 400 84 - #define ST_MAGN_0_FS_AVL_4700_GAIN_Z 355 85 - #define ST_MAGN_0_FS_AVL_5600_GAIN_Z 295 86 - #define ST_MAGN_0_FS_AVL_8100_GAIN_Z 205 87 - #define ST_MAGN_0_MULTIREAD_BIT false 88 - 89 - /* CUSTOM VALUES FOR SENSOR 1 */ 90 - #define ST_MAGN_1_WAI_EXP 0x3c 91 - #define ST_MAGN_1_ODR_ADDR 0x00 92 - #define ST_MAGN_1_ODR_MASK 0x1c 93 - #define ST_MAGN_1_ODR_AVL_1HZ_VAL 0x00 94 - #define ST_MAGN_1_ODR_AVL_2HZ_VAL 0x01 95 - #define ST_MAGN_1_ODR_AVL_3HZ_VAL 0x02 96 - #define ST_MAGN_1_ODR_AVL_8HZ_VAL 0x03 97 - #define ST_MAGN_1_ODR_AVL_15HZ_VAL 0x04 98 - #define ST_MAGN_1_ODR_AVL_30HZ_VAL 0x05 99 - #define ST_MAGN_1_ODR_AVL_75HZ_VAL 0x06 100 - #define ST_MAGN_1_ODR_AVL_220HZ_VAL 0x07 101 - #define ST_MAGN_1_PW_ADDR 0x02 102 - #define ST_MAGN_1_PW_MASK 0x03 103 - #define ST_MAGN_1_PW_ON 0x00 104 - #define ST_MAGN_1_PW_OFF 0x03 105 - #define ST_MAGN_1_FS_ADDR 0x01 106 - #define ST_MAGN_1_FS_MASK 0xe0 107 - #define ST_MAGN_1_FS_AVL_1300_VAL 0x01 108 - #define ST_MAGN_1_FS_AVL_1900_VAL 0x02 109 - #define ST_MAGN_1_FS_AVL_2500_VAL 0x03 110 - #define ST_MAGN_1_FS_AVL_4000_VAL 0x04 111 - #define ST_MAGN_1_FS_AVL_4700_VAL 0x05 112 - #define ST_MAGN_1_FS_AVL_5600_VAL 0x06 113 - #define ST_MAGN_1_FS_AVL_8100_VAL 0x07 114 - #define ST_MAGN_1_FS_AVL_1300_GAIN_XY 909 115 - #define ST_MAGN_1_FS_AVL_1900_GAIN_XY 1169 116 - #define ST_MAGN_1_FS_AVL_2500_GAIN_XY 1492 117 - #define ST_MAGN_1_FS_AVL_4000_GAIN_XY 2222 118 - #define ST_MAGN_1_FS_AVL_4700_GAIN_XY 2500 119 - #define ST_MAGN_1_FS_AVL_5600_GAIN_XY 3030 120 - #define ST_MAGN_1_FS_AVL_8100_GAIN_XY 4347 121 - #define ST_MAGN_1_FS_AVL_1300_GAIN_Z 1020 122 - #define ST_MAGN_1_FS_AVL_1900_GAIN_Z 1315 123 - #define ST_MAGN_1_FS_AVL_2500_GAIN_Z 1666 124 - #define ST_MAGN_1_FS_AVL_4000_GAIN_Z 2500 125 - #define ST_MAGN_1_FS_AVL_4700_GAIN_Z 2816 126 - #define ST_MAGN_1_FS_AVL_5600_GAIN_Z 3389 127 - #define ST_MAGN_1_FS_AVL_8100_GAIN_Z 4878 128 - #define ST_MAGN_1_MULTIREAD_BIT false 129 - 130 - /* CUSTOM VALUES FOR SENSOR 2 */ 131 - #define ST_MAGN_2_WAI_EXP 0x3d 132 - #define ST_MAGN_2_ODR_ADDR 0x20 133 - #define ST_MAGN_2_ODR_MASK 0x1c 134 - #define ST_MAGN_2_ODR_AVL_1HZ_VAL 0x00 135 - #define ST_MAGN_2_ODR_AVL_2HZ_VAL 0x01 136 - #define ST_MAGN_2_ODR_AVL_3HZ_VAL 0x02 137 - #define ST_MAGN_2_ODR_AVL_5HZ_VAL 0x03 138 - #define ST_MAGN_2_ODR_AVL_10HZ_VAL 0x04 139 - #define ST_MAGN_2_ODR_AVL_20HZ_VAL 0x05 140 - #define ST_MAGN_2_ODR_AVL_40HZ_VAL 0x06 141 - #define ST_MAGN_2_ODR_AVL_80HZ_VAL 0x07 142 - #define ST_MAGN_2_PW_ADDR 0x22 143 - #define ST_MAGN_2_PW_MASK 0x03 144 - #define ST_MAGN_2_PW_ON 0x00 145 - #define ST_MAGN_2_PW_OFF 0x03 146 - #define ST_MAGN_2_FS_ADDR 0x21 147 - #define ST_MAGN_2_FS_MASK 0x60 148 - #define ST_MAGN_2_FS_AVL_4000_VAL 0x00 149 - #define ST_MAGN_2_FS_AVL_8000_VAL 0x01 150 - #define ST_MAGN_2_FS_AVL_12000_VAL 0x02 151 - #define ST_MAGN_2_FS_AVL_16000_VAL 0x03 152 - #define ST_MAGN_2_FS_AVL_4000_GAIN 146 153 - #define ST_MAGN_2_FS_AVL_8000_GAIN 292 154 - #define ST_MAGN_2_FS_AVL_12000_GAIN 438 155 - #define ST_MAGN_2_FS_AVL_16000_GAIN 584 156 - #define ST_MAGN_2_MULTIREAD_BIT false 49 + /* Special L addresses for Sensor 2 */ 157 50 #define ST_MAGN_2_OUT_X_L_ADDR 0x28 158 51 #define ST_MAGN_2_OUT_Y_L_ADDR 0x2a 159 52 #define ST_MAGN_2_OUT_Z_L_ADDR 0x2c 160 53 161 - /* CUSTOM VALUES FOR SENSOR 3 */ 162 - #define ST_MAGN_3_WAI_ADDR 0x4f 163 - #define ST_MAGN_3_WAI_EXP 0x40 164 - #define ST_MAGN_3_ODR_ADDR 0x60 165 - #define ST_MAGN_3_ODR_MASK 0x0c 166 - #define ST_MAGN_3_ODR_AVL_10HZ_VAL 0x00 167 - #define ST_MAGN_3_ODR_AVL_20HZ_VAL 0x01 168 - #define ST_MAGN_3_ODR_AVL_50HZ_VAL 0x02 169 - #define ST_MAGN_3_ODR_AVL_100HZ_VAL 0x03 170 - #define ST_MAGN_3_PW_ADDR 0x60 171 - #define ST_MAGN_3_PW_MASK 0x03 172 - #define ST_MAGN_3_PW_ON 0x00 173 - #define ST_MAGN_3_PW_OFF 0x03 174 - #define ST_MAGN_3_BDU_ADDR 0x62 175 - #define ST_MAGN_3_BDU_MASK 0x10 176 - #define ST_MAGN_3_DRDY_IRQ_ADDR 0x62 177 - #define ST_MAGN_3_DRDY_INT_MASK 0x01 178 - #define ST_MAGN_3_IHL_IRQ_ADDR 0x63 179 - #define ST_MAGN_3_IHL_IRQ_MASK 0x04 180 - #define ST_MAGN_3_FS_AVL_15000_GAIN 1500 181 - #define ST_MAGN_3_MULTIREAD_BIT false 54 + /* Special L addresses for sensor 3 */ 182 55 #define ST_MAGN_3_OUT_X_L_ADDR 0x68 183 56 #define ST_MAGN_3_OUT_Y_L_ADDR 0x6a 184 57 #define ST_MAGN_3_OUT_Z_L_ADDR 0x6c ··· 113 240 }, 114 241 .ch = (struct iio_chan_spec *)st_magn_16bit_channels, 115 242 .odr = { 116 - .addr = ST_MAGN_0_ODR_ADDR, 117 - .mask = ST_MAGN_0_ODR_MASK, 243 + .addr = 0x00, 244 + .mask = 0x1c, 118 245 .odr_avl = { 119 - { 1, ST_MAGN_0_ODR_AVL_1HZ_VAL, }, 120 - { 2, ST_MAGN_0_ODR_AVL_2HZ_VAL, }, 121 - { 3, ST_MAGN_0_ODR_AVL_3HZ_VAL, }, 122 - { 8, ST_MAGN_0_ODR_AVL_8HZ_VAL, }, 123 - { 15, ST_MAGN_0_ODR_AVL_15HZ_VAL, }, 124 - { 30, ST_MAGN_0_ODR_AVL_30HZ_VAL, }, 125 - { 75, ST_MAGN_0_ODR_AVL_75HZ_VAL, }, 246 + { .hz = 1, .value = 0x00 }, 247 + { .hz = 2, .value = 0x01 }, 248 + { .hz = 3, .value = 0x02 }, 249 + { .hz = 8, .value = 0x03 }, 250 + { .hz = 15, .value = 0x04 }, 251 + { .hz = 30, .value = 0x05 }, 252 + { .hz = 75, .value = 0x06 }, 253 + /* 220 Hz, 0x07 reportedly exist */ 126 254 }, 127 255 }, 128 256 .pw = { 129 - .addr = ST_MAGN_0_PW_ADDR, 130 - .mask = ST_MAGN_0_PW_MASK, 131 - .value_on = ST_MAGN_0_PW_ON, 132 - .value_off = ST_MAGN_0_PW_OFF, 257 + .addr = 0x02, 258 + .mask = 0x03, 259 + .value_on = 0x00, 260 + .value_off = 0x03, 133 261 }, 134 262 .fs = { 135 - .addr = ST_MAGN_0_FS_ADDR, 136 - .mask = ST_MAGN_0_FS_MASK, 263 + .addr = 0x01, 264 + .mask = 0xe0, 137 265 .fs_avl = { 138 266 [0] = { 139 267 .num = ST_MAGN_FS_AVL_1300MG, 140 - .value = ST_MAGN_0_FS_AVL_1300_VAL, 141 - .gain = ST_MAGN_0_FS_AVL_1300_GAIN_XY, 142 - .gain2 = ST_MAGN_0_FS_AVL_1300_GAIN_Z, 268 + .value = 0x01, 269 + .gain = 1100, 270 + .gain2 = 980, 143 271 }, 144 272 [1] = { 145 273 .num = ST_MAGN_FS_AVL_1900MG, 146 - .value = ST_MAGN_0_FS_AVL_1900_VAL, 147 - .gain = ST_MAGN_0_FS_AVL_1900_GAIN_XY, 148 - .gain2 = ST_MAGN_0_FS_AVL_1900_GAIN_Z, 274 + .value = 0x02, 275 + .gain = 855, 276 + .gain2 = 760, 149 277 }, 150 278 [2] = { 151 279 .num = ST_MAGN_FS_AVL_2500MG, 152 - .value = ST_MAGN_0_FS_AVL_2500_VAL, 153 - .gain = ST_MAGN_0_FS_AVL_2500_GAIN_XY, 154 - .gain2 = ST_MAGN_0_FS_AVL_2500_GAIN_Z, 280 + .value = 0x03, 281 + .gain = 670, 282 + .gain2 = 600, 155 283 }, 156 284 [3] = { 157 285 .num = ST_MAGN_FS_AVL_4000MG, 158 - .value = ST_MAGN_0_FS_AVL_4000_VAL, 159 - .gain = ST_MAGN_0_FS_AVL_4000_GAIN_XY, 160 - .gain2 = ST_MAGN_0_FS_AVL_4000_GAIN_Z, 286 + .value = 0x04, 287 + .gain = 450, 288 + .gain2 = 400, 161 289 }, 162 290 [4] = { 163 291 .num = ST_MAGN_FS_AVL_4700MG, 164 - .value = ST_MAGN_0_FS_AVL_4700_VAL, 165 - .gain = ST_MAGN_0_FS_AVL_4700_GAIN_XY, 166 - .gain2 = ST_MAGN_0_FS_AVL_4700_GAIN_Z, 292 + .value = 0x05, 293 + .gain = 400, 294 + .gain2 = 355, 167 295 }, 168 296 [5] = { 169 297 .num = ST_MAGN_FS_AVL_5600MG, 170 - .value = ST_MAGN_0_FS_AVL_5600_VAL, 171 - .gain = ST_MAGN_0_FS_AVL_5600_GAIN_XY, 172 - .gain2 = ST_MAGN_0_FS_AVL_5600_GAIN_Z, 298 + .value = 0x06, 299 + .gain = 330, 300 + .gain2 = 295, 173 301 }, 174 302 [6] = { 175 303 .num = ST_MAGN_FS_AVL_8100MG, 176 - .value = ST_MAGN_0_FS_AVL_8100_VAL, 177 - .gain = ST_MAGN_0_FS_AVL_8100_GAIN_XY, 178 - .gain2 = ST_MAGN_0_FS_AVL_8100_GAIN_Z, 304 + .value = 0x07, 305 + .gain = 230, 306 + .gain2 = 205, 179 307 }, 180 308 }, 181 309 }, 182 - .multi_read_bit = ST_MAGN_0_MULTIREAD_BIT, 310 + .multi_read_bit = false, 183 311 .bootime = 2, 184 312 }, 185 313 { 186 - .wai = ST_MAGN_1_WAI_EXP, 314 + .wai = 0x3c, 187 315 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, 188 316 .sensors_supported = { 189 317 [0] = LSM303DLHC_MAGN_DEV_NAME, ··· 192 318 }, 193 319 .ch = (struct iio_chan_spec *)st_magn_16bit_channels, 194 320 .odr = { 195 - .addr = ST_MAGN_1_ODR_ADDR, 196 - .mask = ST_MAGN_1_ODR_MASK, 321 + .addr = 0x00, 322 + .mask = 0x1c, 197 323 .odr_avl = { 198 - { 1, ST_MAGN_1_ODR_AVL_1HZ_VAL, }, 199 - { 2, ST_MAGN_1_ODR_AVL_2HZ_VAL, }, 200 - { 3, ST_MAGN_1_ODR_AVL_3HZ_VAL, }, 201 - { 8, ST_MAGN_1_ODR_AVL_8HZ_VAL, }, 202 - { 15, ST_MAGN_1_ODR_AVL_15HZ_VAL, }, 203 - { 30, ST_MAGN_1_ODR_AVL_30HZ_VAL, }, 204 - { 75, ST_MAGN_1_ODR_AVL_75HZ_VAL, }, 205 - { 220, ST_MAGN_1_ODR_AVL_220HZ_VAL, }, 324 + { .hz = 1, .value = 0x00 }, 325 + { .hz = 2, .value = 0x01 }, 326 + { .hz = 3, .value = 0x02 }, 327 + { .hz = 8, .value = 0x03 }, 328 + { .hz = 15, .value = 0x04 }, 329 + { .hz = 30, .value = 0x05 }, 330 + { .hz = 75, .value = 0x06 }, 331 + { .hz = 220, .value = 0x07 }, 206 332 }, 207 333 }, 208 334 .pw = { 209 - .addr = ST_MAGN_1_PW_ADDR, 210 - .mask = ST_MAGN_1_PW_MASK, 211 - .value_on = ST_MAGN_1_PW_ON, 212 - .value_off = ST_MAGN_1_PW_OFF, 335 + .addr = 0x02, 336 + .mask = 0x03, 337 + .value_on = 0x00, 338 + .value_off = 0x03, 213 339 }, 214 340 .fs = { 215 - .addr = ST_MAGN_1_FS_ADDR, 216 - .mask = ST_MAGN_1_FS_MASK, 341 + .addr = 0x01, 342 + .mask = 0xe0, 217 343 .fs_avl = { 218 344 [0] = { 219 345 .num = ST_MAGN_FS_AVL_1300MG, 220 - .value = ST_MAGN_1_FS_AVL_1300_VAL, 221 - .gain = ST_MAGN_1_FS_AVL_1300_GAIN_XY, 222 - .gain2 = ST_MAGN_1_FS_AVL_1300_GAIN_Z, 346 + .value = 0x01, 347 + .gain = 909, 348 + .gain2 = 1020, 223 349 }, 224 350 [1] = { 225 351 .num = ST_MAGN_FS_AVL_1900MG, 226 - .value = ST_MAGN_1_FS_AVL_1900_VAL, 227 - .gain = ST_MAGN_1_FS_AVL_1900_GAIN_XY, 228 - .gain2 = ST_MAGN_1_FS_AVL_1900_GAIN_Z, 352 + .value = 0x02, 353 + .gain = 1169, 354 + .gain2 = 1315, 229 355 }, 230 356 [2] = { 231 357 .num = ST_MAGN_FS_AVL_2500MG, 232 - .value = ST_MAGN_1_FS_AVL_2500_VAL, 233 - .gain = ST_MAGN_1_FS_AVL_2500_GAIN_XY, 234 - .gain2 = ST_MAGN_1_FS_AVL_2500_GAIN_Z, 358 + .value = 0x03, 359 + .gain = 1492, 360 + .gain2 = 1666, 235 361 }, 236 362 [3] = { 237 363 .num = ST_MAGN_FS_AVL_4000MG, 238 - .value = ST_MAGN_1_FS_AVL_4000_VAL, 239 - .gain = ST_MAGN_1_FS_AVL_4000_GAIN_XY, 240 - .gain2 = ST_MAGN_1_FS_AVL_4000_GAIN_Z, 364 + .value = 0x04, 365 + .gain = 2222, 366 + .gain2 = 2500, 241 367 }, 242 368 [4] = { 243 369 .num = ST_MAGN_FS_AVL_4700MG, 244 - .value = ST_MAGN_1_FS_AVL_4700_VAL, 245 - .gain = ST_MAGN_1_FS_AVL_4700_GAIN_XY, 246 - .gain2 = ST_MAGN_1_FS_AVL_4700_GAIN_Z, 370 + .value = 0x05, 371 + .gain = 2500, 372 + .gain2 = 2816, 247 373 }, 248 374 [5] = { 249 375 .num = ST_MAGN_FS_AVL_5600MG, 250 - .value = ST_MAGN_1_FS_AVL_5600_VAL, 251 - .gain = ST_MAGN_1_FS_AVL_5600_GAIN_XY, 252 - .gain2 = ST_MAGN_1_FS_AVL_5600_GAIN_Z, 376 + .value = 0x06, 377 + .gain = 3030, 378 + .gain2 = 3389, 253 379 }, 254 380 [6] = { 255 381 .num = ST_MAGN_FS_AVL_8100MG, 256 - .value = ST_MAGN_1_FS_AVL_8100_VAL, 257 - .gain = ST_MAGN_1_FS_AVL_8100_GAIN_XY, 258 - .gain2 = ST_MAGN_1_FS_AVL_8100_GAIN_Z, 382 + .value = 0x07, 383 + .gain = 4347, 384 + .gain2 = 4878, 259 385 }, 260 386 }, 261 387 }, 262 - .multi_read_bit = ST_MAGN_1_MULTIREAD_BIT, 388 + .multi_read_bit = false, 263 389 .bootime = 2, 264 390 }, 265 391 { 266 - .wai = ST_MAGN_2_WAI_EXP, 392 + .wai = 0x3d, 267 393 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, 268 394 .sensors_supported = { 269 395 [0] = LIS3MDL_MAGN_DEV_NAME, 270 396 }, 271 397 .ch = (struct iio_chan_spec *)st_magn_2_16bit_channels, 272 398 .odr = { 273 - .addr = ST_MAGN_2_ODR_ADDR, 274 - .mask = ST_MAGN_2_ODR_MASK, 399 + .addr = 0x20, 400 + .mask = 0x1c, 275 401 .odr_avl = { 276 - { 1, ST_MAGN_2_ODR_AVL_1HZ_VAL, }, 277 - { 2, ST_MAGN_2_ODR_AVL_2HZ_VAL, }, 278 - { 3, ST_MAGN_2_ODR_AVL_3HZ_VAL, }, 279 - { 5, ST_MAGN_2_ODR_AVL_5HZ_VAL, }, 280 - { 10, ST_MAGN_2_ODR_AVL_10HZ_VAL, }, 281 - { 20, ST_MAGN_2_ODR_AVL_20HZ_VAL, }, 282 - { 40, ST_MAGN_2_ODR_AVL_40HZ_VAL, }, 283 - { 80, ST_MAGN_2_ODR_AVL_80HZ_VAL, }, 402 + { .hz = 1, .value = 0x00 }, 403 + { .hz = 2, .value = 0x01 }, 404 + { .hz = 3, .value = 0x02 }, 405 + { .hz = 5, .value = 0x03 }, 406 + { .hz = 10, .value = 0x04 }, 407 + { .hz = 20, .value = 0x05 }, 408 + { .hz = 40, .value = 0x06 }, 409 + { .hz = 80, .value = 0x07 }, 284 410 }, 285 411 }, 286 412 .pw = { 287 - .addr = ST_MAGN_2_PW_ADDR, 288 - .mask = ST_MAGN_2_PW_MASK, 289 - .value_on = ST_MAGN_2_PW_ON, 290 - .value_off = ST_MAGN_2_PW_OFF, 413 + .addr = 0x22, 414 + .mask = 0x03, 415 + .value_on = 0x00, 416 + .value_off = 0x03, 291 417 }, 292 418 .fs = { 293 - .addr = ST_MAGN_2_FS_ADDR, 294 - .mask = ST_MAGN_2_FS_MASK, 419 + .addr = 0x21, 420 + .mask = 0x60, 295 421 .fs_avl = { 296 422 [0] = { 297 423 .num = ST_MAGN_FS_AVL_4000MG, 298 - .value = ST_MAGN_2_FS_AVL_4000_VAL, 299 - .gain = ST_MAGN_2_FS_AVL_4000_GAIN, 424 + .value = 0x00, 425 + .gain = 146, 300 426 }, 301 427 [1] = { 302 428 .num = ST_MAGN_FS_AVL_8000MG, 303 - .value = ST_MAGN_2_FS_AVL_8000_VAL, 304 - .gain = ST_MAGN_2_FS_AVL_8000_GAIN, 429 + .value = 0x01, 430 + .gain = 292, 305 431 }, 306 432 [2] = { 307 433 .num = ST_MAGN_FS_AVL_12000MG, 308 - .value = ST_MAGN_2_FS_AVL_12000_VAL, 309 - .gain = ST_MAGN_2_FS_AVL_12000_GAIN, 434 + .value = 0x02, 435 + .gain = 438, 310 436 }, 311 437 [3] = { 312 438 .num = ST_MAGN_FS_AVL_16000MG, 313 - .value = ST_MAGN_2_FS_AVL_16000_VAL, 314 - .gain = ST_MAGN_2_FS_AVL_16000_GAIN, 439 + .value = 0x03, 440 + .gain = 584, 315 441 }, 316 442 }, 317 443 }, 318 - .multi_read_bit = ST_MAGN_2_MULTIREAD_BIT, 444 + .multi_read_bit = false, 319 445 .bootime = 2, 320 446 }, 321 447 { 322 - .wai = ST_MAGN_3_WAI_EXP, 323 - .wai_addr = ST_MAGN_3_WAI_ADDR, 448 + .wai = 0x40, 449 + .wai_addr = 0x4f, 324 450 .sensors_supported = { 325 451 [0] = LSM303AGR_MAGN_DEV_NAME, 326 452 }, 327 453 .ch = (struct iio_chan_spec *)st_magn_3_16bit_channels, 328 454 .odr = { 329 - .addr = ST_MAGN_3_ODR_ADDR, 330 - .mask = ST_MAGN_3_ODR_MASK, 455 + .addr = 0x60, 456 + .mask = 0x0c, 331 457 .odr_avl = { 332 - { 10, ST_MAGN_3_ODR_AVL_10HZ_VAL, }, 333 - { 20, ST_MAGN_3_ODR_AVL_20HZ_VAL, }, 334 - { 50, ST_MAGN_3_ODR_AVL_50HZ_VAL, }, 335 - { 100, ST_MAGN_3_ODR_AVL_100HZ_VAL, }, 458 + { .hz = 10, .value = 0x00 }, 459 + { .hz = 20, .value = 0x01 }, 460 + { .hz = 50, .value = 0x02 }, 461 + { .hz = 100, .value = 0x03 }, 336 462 }, 337 463 }, 338 464 .pw = { 339 - .addr = ST_MAGN_3_PW_ADDR, 340 - .mask = ST_MAGN_3_PW_MASK, 341 - .value_on = ST_MAGN_3_PW_ON, 342 - .value_off = ST_MAGN_3_PW_OFF, 465 + .addr = 0x60, 466 + .mask = 0x03, 467 + .value_on = 0x00, 468 + .value_off = 0x03, 343 469 }, 344 470 .fs = { 345 471 .fs_avl = { 346 472 [0] = { 347 473 .num = ST_MAGN_FS_AVL_15000MG, 348 - .gain = ST_MAGN_3_FS_AVL_15000_GAIN, 474 + .gain = 1500, 349 475 }, 350 476 }, 351 477 }, 352 478 .bdu = { 353 - .addr = ST_MAGN_3_BDU_ADDR, 354 - .mask = ST_MAGN_3_BDU_MASK, 479 + .addr = 0x62, 480 + .mask = 0x10, 355 481 }, 356 482 .drdy_irq = { 357 - .addr = ST_MAGN_3_DRDY_IRQ_ADDR, 358 - .mask_int1 = ST_MAGN_3_DRDY_INT_MASK, 359 - .addr_ihl = ST_MAGN_3_IHL_IRQ_ADDR, 360 - .mask_ihl = ST_MAGN_3_IHL_IRQ_MASK, 483 + .addr = 0x62, 484 + .mask_int1 = 0x01, 485 + .addr_ihl = 0x63, 486 + .mask_ihl = 0x04, 361 487 .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, 362 488 }, 363 - .multi_read_bit = ST_MAGN_3_MULTIREAD_BIT, 489 + .multi_read_bit = false, 364 490 .bootime = 2, 365 491 }, 366 492 };
+62 -42
drivers/iio/potentiometer/mcp4531.c
··· 38 38 39 39 struct mcp4531_cfg { 40 40 int wipers; 41 - int max_pos; 41 + int avail[3]; 42 42 int kohms; 43 43 }; 44 44 ··· 78 78 }; 79 79 80 80 static const struct mcp4531_cfg mcp4531_cfg[] = { 81 - [MCP453x_502] = { .wipers = 1, .max_pos = 128, .kohms = 5, }, 82 - [MCP453x_103] = { .wipers = 1, .max_pos = 128, .kohms = 10, }, 83 - [MCP453x_503] = { .wipers = 1, .max_pos = 128, .kohms = 50, }, 84 - [MCP453x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, }, 85 - [MCP454x_502] = { .wipers = 1, .max_pos = 128, .kohms = 5, }, 86 - [MCP454x_103] = { .wipers = 1, .max_pos = 128, .kohms = 10, }, 87 - [MCP454x_503] = { .wipers = 1, .max_pos = 128, .kohms = 50, }, 88 - [MCP454x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, }, 89 - [MCP455x_502] = { .wipers = 1, .max_pos = 256, .kohms = 5, }, 90 - [MCP455x_103] = { .wipers = 1, .max_pos = 256, .kohms = 10, }, 91 - [MCP455x_503] = { .wipers = 1, .max_pos = 256, .kohms = 50, }, 92 - [MCP455x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, }, 93 - [MCP456x_502] = { .wipers = 1, .max_pos = 256, .kohms = 5, }, 94 - [MCP456x_103] = { .wipers = 1, .max_pos = 256, .kohms = 10, }, 95 - [MCP456x_503] = { .wipers = 1, .max_pos = 256, .kohms = 50, }, 96 - [MCP456x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, }, 97 - [MCP463x_502] = { .wipers = 2, .max_pos = 128, .kohms = 5, }, 98 - [MCP463x_103] = { .wipers = 2, .max_pos = 128, .kohms = 10, }, 99 - [MCP463x_503] = { .wipers = 2, .max_pos = 128, .kohms = 50, }, 100 - [MCP463x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, }, 101 - [MCP464x_502] = { .wipers = 2, .max_pos = 128, .kohms = 5, }, 102 - [MCP464x_103] = { .wipers = 2, .max_pos = 128, .kohms = 10, }, 103 - [MCP464x_503] = { .wipers = 2, .max_pos = 128, .kohms = 50, }, 104 - [MCP464x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, }, 105 - [MCP465x_502] = { .wipers = 2, .max_pos = 256, .kohms = 5, }, 106 - [MCP465x_103] = { .wipers = 2, .max_pos = 256, .kohms = 10, }, 107 - [MCP465x_503] = { .wipers = 2, .max_pos = 256, .kohms = 50, }, 108 - [MCP465x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, }, 109 - [MCP466x_502] = { .wipers = 2, .max_pos = 256, .kohms = 5, }, 110 - [MCP466x_103] = { .wipers = 2, .max_pos = 256, .kohms = 10, }, 111 - [MCP466x_503] = { .wipers = 2, .max_pos = 256, .kohms = 50, }, 112 - [MCP466x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, }, 81 + [MCP453x_502] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 5, }, 82 + [MCP453x_103] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 10, }, 83 + [MCP453x_503] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 50, }, 84 + [MCP453x_104] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 100, }, 85 + [MCP454x_502] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 5, }, 86 + [MCP454x_103] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 10, }, 87 + [MCP454x_503] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 50, }, 88 + [MCP454x_104] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 100, }, 89 + [MCP455x_502] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 5, }, 90 + [MCP455x_103] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 10, }, 91 + [MCP455x_503] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 50, }, 92 + [MCP455x_104] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 100, }, 93 + [MCP456x_502] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 5, }, 94 + [MCP456x_103] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 10, }, 95 + [MCP456x_503] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 50, }, 96 + [MCP456x_104] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 100, }, 97 + [MCP463x_502] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 5, }, 98 + [MCP463x_103] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 10, }, 99 + [MCP463x_503] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 50, }, 100 + [MCP463x_104] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 100, }, 101 + [MCP464x_502] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 5, }, 102 + [MCP464x_103] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 10, }, 103 + [MCP464x_503] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 50, }, 104 + [MCP464x_104] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 100, }, 105 + [MCP465x_502] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 5, }, 106 + [MCP465x_103] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 10, }, 107 + [MCP465x_503] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 50, }, 108 + [MCP465x_104] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 100, }, 109 + [MCP466x_502] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 5, }, 110 + [MCP466x_103] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 10, }, 111 + [MCP466x_503] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 50, }, 112 + [MCP466x_104] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 100, }, 113 113 }; 114 114 115 115 #define MCP4531_WRITE (0 << 2) ··· 124 124 const struct mcp4531_cfg *cfg; 125 125 }; 126 126 127 - #define MCP4531_CHANNEL(ch) { \ 128 - .type = IIO_RESISTANCE, \ 129 - .indexed = 1, \ 130 - .output = 1, \ 131 - .channel = (ch), \ 132 - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 133 - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 127 + #define MCP4531_CHANNEL(ch) { \ 128 + .type = IIO_RESISTANCE, \ 129 + .indexed = 1, \ 130 + .output = 1, \ 131 + .channel = (ch), \ 132 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 133 + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 134 + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_RAW), \ 134 135 } 135 136 136 137 static const struct iio_chan_spec mcp4531_channels[] = { ··· 157 156 return IIO_VAL_INT; 158 157 case IIO_CHAN_INFO_SCALE: 159 158 *val = 1000 * data->cfg->kohms; 160 - *val2 = data->cfg->max_pos; 159 + *val2 = data->cfg->avail[2]; 161 160 return IIO_VAL_FRACTIONAL; 161 + } 162 + 163 + return -EINVAL; 164 + } 165 + 166 + static int mcp4531_read_avail(struct iio_dev *indio_dev, 167 + struct iio_chan_spec const *chan, 168 + const int **vals, int *type, int *length, 169 + long mask) 170 + { 171 + struct mcp4531_data *data = iio_priv(indio_dev); 172 + 173 + switch (mask) { 174 + case IIO_CHAN_INFO_RAW: 175 + *length = ARRAY_SIZE(data->cfg->avail); 176 + *vals = data->cfg->avail; 177 + *type = IIO_VAL_INT; 178 + return IIO_AVAIL_RANGE; 162 179 } 163 180 164 181 return -EINVAL; ··· 191 172 192 173 switch (mask) { 193 174 case IIO_CHAN_INFO_RAW: 194 - if (val > data->cfg->max_pos || val < 0) 175 + if (val > data->cfg->avail[2] || val < 0) 195 176 return -EINVAL; 196 177 break; 197 178 default: ··· 205 186 206 187 static const struct iio_info mcp4531_info = { 207 188 .read_raw = mcp4531_read_raw, 189 + .read_avail = mcp4531_read_avail, 208 190 .write_raw = mcp4531_write_raw, 209 191 .driver_module = THIS_MODULE, 210 192 };
+92 -165
drivers/iio/pressure/st_pressure_core.c
··· 112 112 #define ST_PRESS_1_OUT_XL_ADDR 0x28 113 113 #define ST_TEMP_1_OUT_L_ADDR 0x2b 114 114 115 - /* 116 - * CUSTOM VALUES FOR LPS331AP SENSOR 117 - * See LPS331AP datasheet: 118 - * http://www2.st.com/resource/en/datasheet/lps331ap.pdf 119 - */ 120 - #define ST_PRESS_LPS331AP_WAI_EXP 0xbb 121 - #define ST_PRESS_LPS331AP_ODR_ADDR 0x20 122 - #define ST_PRESS_LPS331AP_ODR_MASK 0x70 123 - #define ST_PRESS_LPS331AP_ODR_AVL_1HZ_VAL 0x01 124 - #define ST_PRESS_LPS331AP_ODR_AVL_7HZ_VAL 0x05 125 - #define ST_PRESS_LPS331AP_ODR_AVL_13HZ_VAL 0x06 126 - #define ST_PRESS_LPS331AP_ODR_AVL_25HZ_VAL 0x07 127 - #define ST_PRESS_LPS331AP_PW_ADDR 0x20 128 - #define ST_PRESS_LPS331AP_PW_MASK 0x80 129 - #define ST_PRESS_LPS331AP_FS_ADDR 0x23 130 - #define ST_PRESS_LPS331AP_FS_MASK 0x30 131 - #define ST_PRESS_LPS331AP_BDU_ADDR 0x20 132 - #define ST_PRESS_LPS331AP_BDU_MASK 0x04 133 - #define ST_PRESS_LPS331AP_DRDY_IRQ_ADDR 0x22 134 - #define ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK 0x04 135 - #define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK 0x20 136 - #define ST_PRESS_LPS331AP_IHL_IRQ_ADDR 0x22 137 - #define ST_PRESS_LPS331AP_IHL_IRQ_MASK 0x80 138 - #define ST_PRESS_LPS331AP_OD_IRQ_ADDR 0x22 139 - #define ST_PRESS_LPS331AP_OD_IRQ_MASK 0x40 140 - #define ST_PRESS_LPS331AP_MULTIREAD_BIT true 141 - 142 - /* 143 - * CUSTOM VALUES FOR THE OBSOLETE LPS001WP SENSOR 144 - */ 145 - 146 115 /* LPS001WP pressure resolution */ 147 116 #define ST_PRESS_LPS001WP_LSB_PER_MBAR 16UL 148 117 /* LPS001WP temperature resolution */ 149 118 #define ST_PRESS_LPS001WP_LSB_PER_CELSIUS 64UL 150 - 151 - #define ST_PRESS_LPS001WP_WAI_EXP 0xba 152 - #define ST_PRESS_LPS001WP_ODR_ADDR 0x20 153 - #define ST_PRESS_LPS001WP_ODR_MASK 0x30 154 - #define ST_PRESS_LPS001WP_ODR_AVL_1HZ_VAL 0x01 155 - #define ST_PRESS_LPS001WP_ODR_AVL_7HZ_VAL 0x02 156 - #define ST_PRESS_LPS001WP_ODR_AVL_13HZ_VAL 0x03 157 - #define ST_PRESS_LPS001WP_PW_ADDR 0x20 158 - #define ST_PRESS_LPS001WP_PW_MASK 0x40 119 + /* LPS001WP pressure gain */ 159 120 #define ST_PRESS_LPS001WP_FS_AVL_PRESS_GAIN \ 160 121 (100000000UL / ST_PRESS_LPS001WP_LSB_PER_MBAR) 161 - #define ST_PRESS_LPS001WP_BDU_ADDR 0x20 162 - #define ST_PRESS_LPS001WP_BDU_MASK 0x04 163 - #define ST_PRESS_LPS001WP_MULTIREAD_BIT true 122 + /* LPS001WP pressure and temp L addresses */ 164 123 #define ST_PRESS_LPS001WP_OUT_L_ADDR 0x28 165 124 #define ST_TEMP_LPS001WP_OUT_L_ADDR 0x2a 166 125 167 - /* 168 - * CUSTOM VALUES FOR LPS25H SENSOR 169 - * See LPS25H datasheet: 170 - * http://www2.st.com/resource/en/datasheet/lps25h.pdf 171 - */ 172 - #define ST_PRESS_LPS25H_WAI_EXP 0xbd 173 - #define ST_PRESS_LPS25H_ODR_ADDR 0x20 174 - #define ST_PRESS_LPS25H_ODR_MASK 0x70 175 - #define ST_PRESS_LPS25H_ODR_AVL_1HZ_VAL 0x01 176 - #define ST_PRESS_LPS25H_ODR_AVL_7HZ_VAL 0x02 177 - #define ST_PRESS_LPS25H_ODR_AVL_13HZ_VAL 0x03 178 - #define ST_PRESS_LPS25H_ODR_AVL_25HZ_VAL 0x04 179 - #define ST_PRESS_LPS25H_PW_ADDR 0x20 180 - #define ST_PRESS_LPS25H_PW_MASK 0x80 181 - #define ST_PRESS_LPS25H_BDU_ADDR 0x20 182 - #define ST_PRESS_LPS25H_BDU_MASK 0x04 183 - #define ST_PRESS_LPS25H_DRDY_IRQ_ADDR 0x23 184 - #define ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK 0x01 185 - #define ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK 0x10 186 - #define ST_PRESS_LPS25H_IHL_IRQ_ADDR 0x22 187 - #define ST_PRESS_LPS25H_IHL_IRQ_MASK 0x80 188 - #define ST_PRESS_LPS25H_OD_IRQ_ADDR 0x22 189 - #define ST_PRESS_LPS25H_OD_IRQ_MASK 0x40 190 - #define ST_PRESS_LPS25H_MULTIREAD_BIT true 126 + /* LPS25H pressure and temp L addresses */ 191 127 #define ST_PRESS_LPS25H_OUT_XL_ADDR 0x28 192 128 #define ST_TEMP_LPS25H_OUT_L_ADDR 0x2b 193 129 194 - /* 195 - * CUSTOM VALUES FOR LPS22HB SENSOR 196 - * See LPS22HB datasheet: 197 - * http://www2.st.com/resource/en/datasheet/lps22hb.pdf 198 - */ 199 - 200 130 /* LPS22HB temperature sensitivity */ 201 131 #define ST_PRESS_LPS22HB_LSB_PER_CELSIUS 100UL 202 - 203 - #define ST_PRESS_LPS22HB_WAI_EXP 0xb1 204 - #define ST_PRESS_LPS22HB_ODR_ADDR 0x10 205 - #define ST_PRESS_LPS22HB_ODR_MASK 0x70 206 - #define ST_PRESS_LPS22HB_ODR_AVL_1HZ_VAL 0x01 207 - #define ST_PRESS_LPS22HB_ODR_AVL_10HZ_VAL 0x02 208 - #define ST_PRESS_LPS22HB_ODR_AVL_25HZ_VAL 0x03 209 - #define ST_PRESS_LPS22HB_ODR_AVL_50HZ_VAL 0x04 210 - #define ST_PRESS_LPS22HB_ODR_AVL_75HZ_VAL 0x05 211 - #define ST_PRESS_LPS22HB_PW_ADDR 0x10 212 - #define ST_PRESS_LPS22HB_PW_MASK 0x70 213 - #define ST_PRESS_LPS22HB_BDU_ADDR 0x10 214 - #define ST_PRESS_LPS22HB_BDU_MASK 0x02 215 - #define ST_PRESS_LPS22HB_DRDY_IRQ_ADDR 0x12 216 - #define ST_PRESS_LPS22HB_DRDY_IRQ_INT1_MASK 0x04 217 - #define ST_PRESS_LPS22HB_DRDY_IRQ_INT2_MASK 0x08 218 - #define ST_PRESS_LPS22HB_IHL_IRQ_ADDR 0x12 219 - #define ST_PRESS_LPS22HB_IHL_IRQ_MASK 0x80 220 - #define ST_PRESS_LPS22HB_OD_IRQ_ADDR 0x12 221 - #define ST_PRESS_LPS22HB_OD_IRQ_MASK 0x40 222 - #define ST_PRESS_LPS22HB_MULTIREAD_BIT true 223 132 224 133 static const struct iio_chan_spec st_press_1_channels[] = { 225 134 { ··· 230 321 231 322 static const struct st_sensor_settings st_press_sensors_settings[] = { 232 323 { 233 - .wai = ST_PRESS_LPS331AP_WAI_EXP, 324 + /* 325 + * CUSTOM VALUES FOR LPS331AP SENSOR 326 + * See LPS331AP datasheet: 327 + * http://www2.st.com/resource/en/datasheet/lps331ap.pdf 328 + */ 329 + .wai = 0xbb, 234 330 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, 235 331 .sensors_supported = { 236 332 [0] = LPS331AP_PRESS_DEV_NAME, ··· 243 329 .ch = (struct iio_chan_spec *)st_press_1_channels, 244 330 .num_ch = ARRAY_SIZE(st_press_1_channels), 245 331 .odr = { 246 - .addr = ST_PRESS_LPS331AP_ODR_ADDR, 247 - .mask = ST_PRESS_LPS331AP_ODR_MASK, 332 + .addr = 0x20, 333 + .mask = 0x70, 248 334 .odr_avl = { 249 - { 1, ST_PRESS_LPS331AP_ODR_AVL_1HZ_VAL, }, 250 - { 7, ST_PRESS_LPS331AP_ODR_AVL_7HZ_VAL, }, 251 - { 13, ST_PRESS_LPS331AP_ODR_AVL_13HZ_VAL, }, 252 - { 25, ST_PRESS_LPS331AP_ODR_AVL_25HZ_VAL, }, 335 + { .hz = 1, .value = 0x01 }, 336 + { .hz = 7, .value = 0x05 }, 337 + { .hz = 13, .value = 0x06 }, 338 + { .hz = 25, .value = 0x07 }, 253 339 }, 254 340 }, 255 341 .pw = { 256 - .addr = ST_PRESS_LPS331AP_PW_ADDR, 257 - .mask = ST_PRESS_LPS331AP_PW_MASK, 342 + .addr = 0x20, 343 + .mask = 0x80, 258 344 .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, 259 345 .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, 260 346 }, 261 347 .fs = { 262 - .addr = ST_PRESS_LPS331AP_FS_ADDR, 263 - .mask = ST_PRESS_LPS331AP_FS_MASK, 348 + .addr = 0x23, 349 + .mask = 0x30, 264 350 .fs_avl = { 265 351 /* 266 352 * Pressure and temperature sensitivity values ··· 274 360 }, 275 361 }, 276 362 .bdu = { 277 - .addr = ST_PRESS_LPS331AP_BDU_ADDR, 278 - .mask = ST_PRESS_LPS331AP_BDU_MASK, 363 + .addr = 0x20, 364 + .mask = 0x04, 279 365 }, 280 366 .drdy_irq = { 281 - .addr = ST_PRESS_LPS331AP_DRDY_IRQ_ADDR, 282 - .mask_int1 = ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK, 283 - .mask_int2 = ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK, 284 - .addr_ihl = ST_PRESS_LPS331AP_IHL_IRQ_ADDR, 285 - .mask_ihl = ST_PRESS_LPS331AP_IHL_IRQ_MASK, 286 - .addr_od = ST_PRESS_LPS331AP_OD_IRQ_ADDR, 287 - .mask_od = ST_PRESS_LPS331AP_OD_IRQ_MASK, 367 + .addr = 0x22, 368 + .mask_int1 = 0x04, 369 + .mask_int2 = 0x20, 370 + .addr_ihl = 0x22, 371 + .mask_ihl = 0x80, 372 + .addr_od = 0x22, 373 + .mask_od = 0x40, 288 374 .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, 289 375 }, 290 - .multi_read_bit = ST_PRESS_LPS331AP_MULTIREAD_BIT, 376 + .multi_read_bit = true, 291 377 .bootime = 2, 292 378 }, 293 379 { 294 - .wai = ST_PRESS_LPS001WP_WAI_EXP, 380 + /* 381 + * CUSTOM VALUES FOR LPS001WP SENSOR 382 + */ 383 + .wai = 0xba, 295 384 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, 296 385 .sensors_supported = { 297 386 [0] = LPS001WP_PRESS_DEV_NAME, ··· 302 385 .ch = (struct iio_chan_spec *)st_press_lps001wp_channels, 303 386 .num_ch = ARRAY_SIZE(st_press_lps001wp_channels), 304 387 .odr = { 305 - .addr = ST_PRESS_LPS001WP_ODR_ADDR, 306 - .mask = ST_PRESS_LPS001WP_ODR_MASK, 388 + .addr = 0x20, 389 + .mask = 0x30, 307 390 .odr_avl = { 308 - { 1, ST_PRESS_LPS001WP_ODR_AVL_1HZ_VAL, }, 309 - { 7, ST_PRESS_LPS001WP_ODR_AVL_7HZ_VAL, }, 310 - { 13, ST_PRESS_LPS001WP_ODR_AVL_13HZ_VAL, }, 391 + { .hz = 1, .value = 0x01 }, 392 + { .hz = 7, .value = 0x02 }, 393 + { .hz = 13, .value = 0x03 }, 311 394 }, 312 395 }, 313 396 .pw = { 314 - .addr = ST_PRESS_LPS001WP_PW_ADDR, 315 - .mask = ST_PRESS_LPS001WP_PW_MASK, 397 + .addr = 0x20, 398 + .mask = 0x40, 316 399 .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, 317 400 .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, 318 401 }, ··· 330 413 }, 331 414 }, 332 415 .bdu = { 333 - .addr = ST_PRESS_LPS001WP_BDU_ADDR, 334 - .mask = ST_PRESS_LPS001WP_BDU_MASK, 416 + .addr = 0x20, 417 + .mask = 0x04, 335 418 }, 336 419 .drdy_irq = { 337 420 .addr = 0, 338 421 }, 339 - .multi_read_bit = ST_PRESS_LPS001WP_MULTIREAD_BIT, 422 + .multi_read_bit = true, 340 423 .bootime = 2, 341 424 }, 342 425 { 343 - .wai = ST_PRESS_LPS25H_WAI_EXP, 426 + /* 427 + * CUSTOM VALUES FOR LPS25H SENSOR 428 + * See LPS25H datasheet: 429 + * http://www2.st.com/resource/en/datasheet/lps25h.pdf 430 + */ 431 + .wai = 0xbd, 344 432 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, 345 433 .sensors_supported = { 346 434 [0] = LPS25H_PRESS_DEV_NAME, ··· 353 431 .ch = (struct iio_chan_spec *)st_press_1_channels, 354 432 .num_ch = ARRAY_SIZE(st_press_1_channels), 355 433 .odr = { 356 - .addr = ST_PRESS_LPS25H_ODR_ADDR, 357 - .mask = ST_PRESS_LPS25H_ODR_MASK, 434 + .addr = 0x20, 435 + .mask = 0x70, 358 436 .odr_avl = { 359 - { 1, ST_PRESS_LPS25H_ODR_AVL_1HZ_VAL, }, 360 - { 7, ST_PRESS_LPS25H_ODR_AVL_7HZ_VAL, }, 361 - { 13, ST_PRESS_LPS25H_ODR_AVL_13HZ_VAL, }, 362 - { 25, ST_PRESS_LPS25H_ODR_AVL_25HZ_VAL, }, 437 + { .hz = 1, .value = 0x01 }, 438 + { .hz = 7, .value = 0x02 }, 439 + { .hz = 13, .value = 0x03 }, 440 + { .hz = 25, .value = 0x04 }, 363 441 }, 364 442 }, 365 443 .pw = { 366 - .addr = ST_PRESS_LPS25H_PW_ADDR, 367 - .mask = ST_PRESS_LPS25H_PW_MASK, 444 + .addr = 0x20, 445 + .mask = 0x80, 368 446 .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, 369 447 .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, 370 448 }, ··· 382 460 }, 383 461 }, 384 462 .bdu = { 385 - .addr = ST_PRESS_LPS25H_BDU_ADDR, 386 - .mask = ST_PRESS_LPS25H_BDU_MASK, 463 + .addr = 0x20, 464 + .mask = 0x04, 387 465 }, 388 466 .drdy_irq = { 389 - .addr = ST_PRESS_LPS25H_DRDY_IRQ_ADDR, 390 - .mask_int1 = ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK, 391 - .mask_int2 = ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK, 392 - .addr_ihl = ST_PRESS_LPS25H_IHL_IRQ_ADDR, 393 - .mask_ihl = ST_PRESS_LPS25H_IHL_IRQ_MASK, 394 - .addr_od = ST_PRESS_LPS25H_OD_IRQ_ADDR, 395 - .mask_od = ST_PRESS_LPS25H_OD_IRQ_MASK, 467 + .addr = 0x23, 468 + .mask_int1 = 0x01, 469 + .mask_int2 = 0x10, 470 + .addr_ihl = 0x22, 471 + .mask_ihl = 0x80, 472 + .addr_od = 0x22, 473 + .mask_od = 0x40, 396 474 .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, 397 475 }, 398 - .multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT, 476 + .multi_read_bit = true, 399 477 .bootime = 2, 400 478 }, 401 479 { 402 - .wai = ST_PRESS_LPS22HB_WAI_EXP, 480 + /* 481 + * CUSTOM VALUES FOR LPS22HB SENSOR 482 + * See LPS22HB datasheet: 483 + * http://www2.st.com/resource/en/datasheet/lps22hb.pdf 484 + */ 485 + .wai = 0xb1, 403 486 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, 404 487 .sensors_supported = { 405 488 [0] = LPS22HB_PRESS_DEV_NAME, ··· 412 485 .ch = (struct iio_chan_spec *)st_press_lps22hb_channels, 413 486 .num_ch = ARRAY_SIZE(st_press_lps22hb_channels), 414 487 .odr = { 415 - .addr = ST_PRESS_LPS22HB_ODR_ADDR, 416 - .mask = ST_PRESS_LPS22HB_ODR_MASK, 488 + .addr = 0x10, 489 + .mask = 0x70, 417 490 .odr_avl = { 418 - { 1, ST_PRESS_LPS22HB_ODR_AVL_1HZ_VAL, }, 419 - { 10, ST_PRESS_LPS22HB_ODR_AVL_10HZ_VAL, }, 420 - { 25, ST_PRESS_LPS22HB_ODR_AVL_25HZ_VAL, }, 421 - { 50, ST_PRESS_LPS22HB_ODR_AVL_50HZ_VAL, }, 422 - { 75, ST_PRESS_LPS22HB_ODR_AVL_75HZ_VAL, }, 491 + { .hz = 1, .value = 0x01 }, 492 + { .hz = 10, .value = 0x02 }, 493 + { .hz = 25, .value = 0x03 }, 494 + { .hz = 50, .value = 0x04 }, 495 + { .hz = 75, .value = 0x05 }, 423 496 }, 424 497 }, 425 498 .pw = { 426 - .addr = ST_PRESS_LPS22HB_PW_ADDR, 427 - .mask = ST_PRESS_LPS22HB_PW_MASK, 499 + .addr = 0x10, 500 + .mask = 0x70, 428 501 .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, 429 502 }, 430 503 .fs = { ··· 441 514 }, 442 515 }, 443 516 .bdu = { 444 - .addr = ST_PRESS_LPS22HB_BDU_ADDR, 445 - .mask = ST_PRESS_LPS22HB_BDU_MASK, 517 + .addr = 0x10, 518 + .mask = 0x02, 446 519 }, 447 520 .drdy_irq = { 448 - .addr = ST_PRESS_LPS22HB_DRDY_IRQ_ADDR, 449 - .mask_int1 = ST_PRESS_LPS22HB_DRDY_IRQ_INT1_MASK, 450 - .mask_int2 = ST_PRESS_LPS22HB_DRDY_IRQ_INT2_MASK, 451 - .addr_ihl = ST_PRESS_LPS22HB_IHL_IRQ_ADDR, 452 - .mask_ihl = ST_PRESS_LPS22HB_IHL_IRQ_MASK, 453 - .addr_od = ST_PRESS_LPS22HB_OD_IRQ_ADDR, 454 - .mask_od = ST_PRESS_LPS22HB_OD_IRQ_MASK, 521 + .addr = 0x12, 522 + .mask_int1 = 0x04, 523 + .mask_int2 = 0x08, 524 + .addr_ihl = 0x12, 525 + .mask_ihl = 0x80, 526 + .addr_od = 0x12, 527 + .mask_od = 0x40, 455 528 .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, 456 529 }, 457 - .multi_read_bit = ST_PRESS_LPS22HB_MULTIREAD_BIT, 530 + .multi_read_bit = true, 458 531 }, 459 532 }; 460 533
-6
drivers/staging/iio/Documentation/light/sysfs-bus-iio-light-tsl2583
··· 1 - What: /sys/bus/iio/devices/device[n]/in_illuminance0_calibrate 2 - KernelVersion: 2.6.37 3 - Contact: linux-iio@vger.kernel.org 4 - Description: 5 - This property causes an internal calibration of the als gain trim 6 - value which is later used in calculating illuminance in lux.
-20
drivers/staging/iio/Documentation/sysfs-bus-iio-light-tsl2583
··· 1 - What: /sys/bus/iio/devices/device[n]/lux_table 2 - KernelVersion: 2.6.37 3 - Contact: linux-iio@vger.kernel.org 4 - Description: 5 - This property gets/sets the table of coefficients 6 - used in calculating illuminance in lux. 7 - 8 - What: /sys/bus/iio/devices/device[n]/illuminance0_calibrate 9 - KernelVersion: 2.6.37 10 - Contact: linux-iio@vger.kernel.org 11 - Description: 12 - This property causes an internal calibration of the als gain trim 13 - value which is later used in calculating illuminance in lux. 14 - 15 - What: /sys/bus/iio/devices/device[n]/illuminance0_input_target 16 - KernelVersion: 2.6.37 17 - Contact: linux-iio@vger.kernel.org 18 - Description: 19 - This property is the known externally illuminance (in lux). 20 - It is used in the process of calibrating the device accuracy.
+7 -7
drivers/staging/iio/frequency/ad9832.c
··· 211 211 return -ENODEV; 212 212 } 213 213 214 + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 215 + if (!indio_dev) 216 + return -ENOMEM; 217 + 218 + spi_set_drvdata(spi, indio_dev); 219 + st = iio_priv(indio_dev); 220 + 214 221 st->avdd = devm_regulator_get(&spi->dev, "avdd"); 215 222 if (IS_ERR(st->avdd)) 216 223 return PTR_ERR(st->avdd); ··· 240 233 goto error_disable_avdd; 241 234 } 242 235 243 - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 244 - if (!indio_dev) { 245 - ret = -ENOMEM; 246 - goto error_disable_dvdd; 247 - } 248 - spi_set_drvdata(spi, indio_dev); 249 - st = iio_priv(indio_dev); 250 236 st->mclk = pdata->mclk; 251 237 st->spi = spi; 252 238
-7
drivers/staging/iio/light/Kconfig
··· 13 13 Proximity value via iio. The ISL29028 provides the concurrent sensing 14 14 of ambient light and proximity. 15 15 16 - config TSL2583 17 - tristate "TAOS TSL2580, TSL2581 and TSL2583 light-to-digital converters" 18 - depends on I2C 19 - help 20 - Provides support for the TAOS tsl2580, tsl2581 and tsl2583 devices. 21 - Access ALS data via iio, sysfs. 22 - 23 16 config TSL2x7x 24 17 tristate "TAOS TSL/TMD2x71 and TSL/TMD2x72 Family of light and proximity sensors" 25 18 depends on I2C
-1
drivers/staging/iio/light/Makefile
··· 3 3 # 4 4 5 5 obj-$(CONFIG_SENSORS_ISL29028) += isl29028.o 6 - obj-$(CONFIG_TSL2583) += tsl2583.o 7 6 obj-$(CONFIG_TSL2x7x) += tsl2x7x_core.o
+314 -293
drivers/staging/iio/light/tsl2583.c drivers/iio/light/tsl2583.c
··· 1 1 /* 2 2 * Device driver for monitoring ambient light intensity (lux) 3 - * within the TAOS tsl258x family of devices (tsl2580, tsl2581). 3 + * within the TAOS tsl258x family of devices (tsl2580, tsl2581, tsl2583). 4 4 * 5 5 * Copyright (c) 2011, TAOS Corporation. 6 + * Copyright (c) 2016 Brian Masney <masneyb@onstation.org> 6 7 * 7 8 * This program is free software; you can redistribute it and/or modify 8 9 * it under the terms of the GNU General Public License as published by ··· 14 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 16 15 * more details. 17 - * 18 - * You should have received a copy of the GNU General Public License along 19 - * with this program; if not, write to the Free Software Foundation, Inc., 20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 16 */ 22 17 23 18 #include <linux/kernel.h> ··· 28 31 #include <linux/iio/iio.h> 29 32 #include <linux/iio/sysfs.h> 30 33 31 - /* Triton register offsets */ 32 - #define TSL258X_REG_MAX 8 33 - 34 34 /* Device Registers and Masks */ 35 - #define TSL258X_CNTRL 0x00 36 - #define TSL258X_ALS_TIME 0X01 37 - #define TSL258X_INTERRUPT 0x02 38 - #define TSL258X_GAIN 0x07 39 - #define TSL258X_REVID 0x11 40 - #define TSL258X_CHIPID 0x12 41 - #define TSL258X_ALS_CHAN0LO 0x14 42 - #define TSL258X_ALS_CHAN0HI 0x15 43 - #define TSL258X_ALS_CHAN1LO 0x16 44 - #define TSL258X_ALS_CHAN1HI 0x17 45 - #define TSL258X_TMR_LO 0x18 46 - #define TSL258X_TMR_HI 0x19 35 + #define TSL2583_CNTRL 0x00 36 + #define TSL2583_ALS_TIME 0X01 37 + #define TSL2583_INTERRUPT 0x02 38 + #define TSL2583_GAIN 0x07 39 + #define TSL2583_REVID 0x11 40 + #define TSL2583_CHIPID 0x12 41 + #define TSL2583_ALS_CHAN0LO 0x14 42 + #define TSL2583_ALS_CHAN0HI 0x15 43 + #define TSL2583_ALS_CHAN1LO 0x16 44 + #define TSL2583_ALS_CHAN1HI 0x17 45 + #define TSL2583_TMR_LO 0x18 46 + #define TSL2583_TMR_HI 0x19 47 47 48 48 /* tsl2583 cmd reg masks */ 49 - #define TSL258X_CMD_REG 0x80 50 - #define TSL258X_CMD_SPL_FN 0x60 51 - #define TSL258X_CMD_ALS_INT_CLR 0X01 49 + #define TSL2583_CMD_REG 0x80 50 + #define TSL2583_CMD_SPL_FN 0x60 51 + #define TSL2583_CMD_ALS_INT_CLR 0x01 52 52 53 53 /* tsl2583 cntrl reg masks */ 54 - #define TSL258X_CNTL_ADC_ENBL 0x02 55 - #define TSL258X_CNTL_PWR_ON 0x01 54 + #define TSL2583_CNTL_ADC_ENBL 0x02 55 + #define TSL2583_CNTL_PWR_OFF 0x00 56 + #define TSL2583_CNTL_PWR_ON 0x01 56 57 57 58 /* tsl2583 status reg masks */ 58 - #define TSL258X_STA_ADC_VALID 0x01 59 - #define TSL258X_STA_ADC_INTR 0x10 59 + #define TSL2583_STA_ADC_VALID 0x01 60 + #define TSL2583_STA_ADC_INTR 0x10 60 61 61 62 /* Lux calculation constants */ 62 - #define TSL258X_LUX_CALC_OVER_FLOW 65535 63 + #define TSL2583_LUX_CALC_OVER_FLOW 65535 64 + 65 + #define TSL2583_INTERRUPT_DISABLED 0x00 63 66 64 67 #define TSL2583_CHIP_ID 0x90 65 68 #define TSL2583_CHIP_ID_MASK 0xf0 66 69 67 - enum { 68 - TSL258X_CHIP_UNKNOWN = 0, 69 - TSL258X_CHIP_WORKING = 1, 70 - TSL258X_CHIP_SUSPENDED = 2 71 - }; 72 - 73 70 /* Per-device data */ 74 - struct taos_als_info { 71 + struct tsl2583_als_info { 75 72 u16 als_ch0; 76 73 u16 als_ch1; 77 74 u16 lux; 78 75 }; 79 76 80 - struct taos_settings { 81 - int als_time; 82 - int als_gain; 83 - int als_gain_trim; 84 - int als_cal_target; 85 - }; 86 - 87 - struct tsl2583_chip { 88 - struct mutex als_mutex; 89 - struct i2c_client *client; 90 - struct taos_als_info als_cur_info; 91 - struct taos_settings taos_settings; 92 - int als_time_scale; 93 - int als_saturation; 94 - int taos_chip_status; 95 - u8 taos_config[8]; 96 - }; 97 - 98 - /* 99 - * Initial values for device - this values can/will be changed by driver. 100 - * and applications as needed. 101 - * These values are dynamic. 102 - */ 103 - static const u8 taos_config[8] = { 104 - 0x00, 0xee, 0x00, 0x03, 0x00, 0xFF, 0xFF, 0x00 105 - }; /* cntrl atime intC Athl0 Athl1 Athh0 Athh1 gain */ 106 - 107 - struct taos_lux { 77 + struct tsl2583_lux { 108 78 unsigned int ratio; 109 79 unsigned int ch0; 110 80 unsigned int ch1; 111 81 }; 112 82 113 - /* This structure is intentionally large to accommodate updates via sysfs. */ 114 - /* Sized to 11 = max 10 segments + 1 termination segment */ 115 - /* Assumption is one and only one type of glass used */ 116 - static struct taos_lux taos_device_lux[11] = { 83 + static const struct tsl2583_lux tsl2583_default_lux[] = { 117 84 { 9830, 8520, 15729 }, 118 85 { 12452, 10807, 23344 }, 119 86 { 14746, 6383, 11705 }, 120 87 { 17695, 4063, 6554 }, 88 + { 0, 0, 0 } /* Termination segment */ 89 + }; 90 + 91 + #define TSL2583_MAX_LUX_TABLE_ENTRIES 11 92 + 93 + struct tsl2583_settings { 94 + int als_time; 95 + int als_gain; 96 + int als_gain_trim; 97 + int als_cal_target; 98 + 99 + /* 100 + * This structure is intentionally large to accommodate updates via 101 + * sysfs. Sized to 11 = max 10 segments + 1 termination segment. 102 + * Assumption is that one and only one type of glass used. 103 + */ 104 + struct tsl2583_lux als_device_lux[TSL2583_MAX_LUX_TABLE_ENTRIES]; 105 + }; 106 + 107 + struct tsl2583_chip { 108 + struct mutex als_mutex; 109 + struct i2c_client *client; 110 + struct tsl2583_als_info als_cur_info; 111 + struct tsl2583_settings als_settings; 112 + int als_time_scale; 113 + int als_saturation; 114 + bool suspended; 121 115 }; 122 116 123 117 struct gainadj { ··· 129 141 * Provides initial operational parameter defaults. 130 142 * These defaults may be changed through the device's sysfs files. 131 143 */ 132 - static void taos_defaults(struct tsl2583_chip *chip) 144 + static void tsl2583_defaults(struct tsl2583_chip *chip) 133 145 { 134 146 /* 135 147 * The integration time must be a multiple of 50ms and within the 136 148 * range [50, 600] ms. 137 149 */ 138 - chip->taos_settings.als_time = 100; 150 + chip->als_settings.als_time = 100; 139 151 140 152 /* 141 153 * This is an index into the gainadj table. Assume clear glass as the 142 154 * default. 143 155 */ 144 - chip->taos_settings.als_gain = 0; 156 + chip->als_settings.als_gain = 0; 145 157 146 158 /* Default gain trim to account for aperture effects */ 147 - chip->taos_settings.als_gain_trim = 1000; 159 + chip->als_settings.als_gain_trim = 1000; 148 160 149 161 /* Known external ALS reading used for calibration */ 150 - chip->taos_settings.als_cal_target = 130; 162 + chip->als_settings.als_cal_target = 130; 163 + 164 + /* Default lux table. */ 165 + memcpy(chip->als_settings.als_device_lux, tsl2583_default_lux, 166 + sizeof(tsl2583_default_lux)); 151 167 } 152 168 153 169 /* ··· 161 169 * Time scale factor array values are adjusted based on the integration time. 162 170 * The raw values are multiplied by a scale factor, and device gain is obtained 163 171 * using gain index. Limit checks are done next, then the ratio of a multiple 164 - * of ch1 value, to the ch0 value, is calculated. The array taos_device_lux[] 172 + * of ch1 value, to the ch0 value, is calculated. The array als_device_lux[] 165 173 * declared above is then scanned to find the first ratio value that is just 166 174 * above the ratio we just calculated. The ch0 and ch1 multiplier constants in 167 175 * the array are then used along with the time scale factor array values, to 168 176 * calculate the lux. 169 177 */ 170 - static int taos_get_lux(struct iio_dev *indio_dev) 178 + static int tsl2583_get_lux(struct iio_dev *indio_dev) 171 179 { 172 180 u16 ch0, ch1; /* separated ch0/ch1 data from device */ 173 181 u32 lux; /* raw lux calculated from device data */ 174 182 u64 lux64; 175 183 u32 ratio; 176 184 u8 buf[5]; 177 - struct taos_lux *p; 185 + struct tsl2583_lux *p; 178 186 struct tsl2583_chip *chip = iio_priv(indio_dev); 179 187 int i, ret; 180 - u32 ch0lux = 0; 181 - u32 ch1lux = 0; 182 188 183 - if (chip->taos_chip_status != TSL258X_CHIP_WORKING) { 184 - /* device is not enabled */ 185 - dev_err(&chip->client->dev, "taos_get_lux device is not enabled\n"); 186 - ret = -EBUSY; 187 - goto done; 188 - } 189 - 190 - ret = i2c_smbus_read_byte_data(chip->client, TSL258X_CMD_REG); 189 + ret = i2c_smbus_read_byte_data(chip->client, TSL2583_CMD_REG); 191 190 if (ret < 0) { 192 - dev_err(&chip->client->dev, "taos_get_lux failed to read CMD_REG\n"); 191 + dev_err(&chip->client->dev, "%s: failed to read CMD_REG register\n", 192 + __func__); 193 193 goto done; 194 194 } 195 195 196 196 /* is data new & valid */ 197 - if (!(ret & TSL258X_STA_ADC_INTR)) { 198 - dev_err(&chip->client->dev, "taos_get_lux data not valid\n"); 197 + if (!(ret & TSL2583_STA_ADC_INTR)) { 198 + dev_err(&chip->client->dev, "%s: data not valid; returning last value\n", 199 + __func__); 199 200 ret = chip->als_cur_info.lux; /* return LAST VALUE */ 200 201 goto done; 201 202 } 202 203 203 204 for (i = 0; i < 4; i++) { 204 - int reg = TSL258X_CMD_REG | (TSL258X_ALS_CHAN0LO + i); 205 + int reg = TSL2583_CMD_REG | (TSL2583_ALS_CHAN0LO + i); 205 206 206 207 ret = i2c_smbus_read_byte_data(chip->client, reg); 207 208 if (ret < 0) { 208 - dev_err(&chip->client->dev, 209 - "taos_get_lux failed to read register %x\n", 210 - reg); 209 + dev_err(&chip->client->dev, "%s: failed to read register %x\n", 210 + __func__, reg); 211 211 goto done; 212 212 } 213 213 buf[i] = ret; 214 214 } 215 215 216 216 /* 217 - * clear status, really interrupt status (interrupts are off), but 218 - * we use the bit anyway - don't forget 0x80 - this is a command 217 + * Clear the pending interrupt status bit on the chip to allow the next 218 + * integration cycle to start. This has to be done even though this 219 + * driver currently does not support interrupts. 219 220 */ 220 221 ret = i2c_smbus_write_byte(chip->client, 221 - (TSL258X_CMD_REG | TSL258X_CMD_SPL_FN | 222 - TSL258X_CMD_ALS_INT_CLR)); 223 - 222 + (TSL2583_CMD_REG | TSL2583_CMD_SPL_FN | 223 + TSL2583_CMD_ALS_INT_CLR)); 224 224 if (ret < 0) { 225 - dev_err(&chip->client->dev, 226 - "taos_i2c_write_command failed in taos_get_lux, err = %d\n", 227 - ret); 225 + dev_err(&chip->client->dev, "%s: failed to clear the interrupt bit\n", 226 + __func__); 228 227 goto done; /* have no data, so return failure */ 229 228 } 230 229 ··· 230 247 goto return_max; 231 248 232 249 if (!ch0) { 233 - /* have no data, so return LAST VALUE */ 250 + /* 251 + * The sensor appears to be in total darkness so set the 252 + * calculated lux to 0 and return early to avoid a division by 253 + * zero below when calculating the ratio. 254 + */ 234 255 ret = 0; 235 256 chip->als_cur_info.lux = 0; 236 257 goto done; 237 258 } 259 + 238 260 /* calculate ratio */ 239 261 ratio = (ch1 << 15) / ch0; 262 + 240 263 /* convert to unscaled lux using the pointer to the table */ 241 - for (p = (struct taos_lux *)taos_device_lux; 264 + for (p = (struct tsl2583_lux *)chip->als_settings.als_device_lux; 242 265 p->ratio != 0 && p->ratio < ratio; p++) 243 266 ; 244 267 245 268 if (p->ratio == 0) { 246 269 lux = 0; 247 270 } else { 248 - ch0lux = ((ch0 * p->ch0) + 249 - (gainadj[chip->taos_settings.als_gain].ch0 >> 1)) 250 - / gainadj[chip->taos_settings.als_gain].ch0; 251 - ch1lux = ((ch1 * p->ch1) + 252 - (gainadj[chip->taos_settings.als_gain].ch1 >> 1)) 253 - / gainadj[chip->taos_settings.als_gain].ch1; 254 - lux = ch0lux - ch1lux; 255 - } 271 + u32 ch0lux, ch1lux; 256 272 257 - /* note: lux is 31 bit max at this point */ 258 - if (ch1lux > ch0lux) { 259 - dev_dbg(&chip->client->dev, "No Data - Return last value\n"); 260 - ret = 0; 261 - chip->als_cur_info.lux = 0; 262 - goto done; 273 + ch0lux = ((ch0 * p->ch0) + 274 + (gainadj[chip->als_settings.als_gain].ch0 >> 1)) 275 + / gainadj[chip->als_settings.als_gain].ch0; 276 + ch1lux = ((ch1 * p->ch1) + 277 + (gainadj[chip->als_settings.als_gain].ch1 >> 1)) 278 + / gainadj[chip->als_settings.als_gain].ch1; 279 + 280 + /* note: lux is 31 bit max at this point */ 281 + if (ch1lux > ch0lux) { 282 + dev_dbg(&chip->client->dev, "%s: No Data - Returning 0\n", 283 + __func__); 284 + ret = 0; 285 + chip->als_cur_info.lux = 0; 286 + goto done; 287 + } 288 + 289 + lux = ch0lux - ch1lux; 263 290 } 264 291 265 292 /* adjust for active time scale */ ··· 279 286 lux = (lux + (chip->als_time_scale >> 1)) / 280 287 chip->als_time_scale; 281 288 282 - /* Adjust for active gain scale. 283 - * The taos_device_lux tables above have a factor of 8192 built in, 289 + /* 290 + * Adjust for active gain scale. 291 + * The tsl2583_default_lux tables above have a factor of 8192 built in, 284 292 * so we need to shift right. 285 293 * User-specified gain provides a multiplier. 286 294 * Apply user-specified gain before shifting right to retain precision. ··· 289 295 * Then go back to 32 bits before division to avoid using div_u64(). 290 296 */ 291 297 lux64 = lux; 292 - lux64 = lux64 * chip->taos_settings.als_gain_trim; 298 + lux64 = lux64 * chip->als_settings.als_gain_trim; 293 299 lux64 >>= 13; 294 300 lux = lux64; 295 301 lux = (lux + 500) / 1000; 296 - if (lux > TSL258X_LUX_CALC_OVER_FLOW) { /* check for overflow */ 302 + 303 + if (lux > TSL2583_LUX_CALC_OVER_FLOW) { /* check for overflow */ 297 304 return_max: 298 - lux = TSL258X_LUX_CALC_OVER_FLOW; 305 + lux = TSL2583_LUX_CALC_OVER_FLOW; 299 306 } 300 307 301 308 /* Update the structure with the latest VALID lux. */ ··· 312 317 * to derive actual lux). 313 318 * Return updated gain_trim value. 314 319 */ 315 - static int taos_als_calibrate(struct iio_dev *indio_dev) 320 + static int tsl2583_als_calibrate(struct iio_dev *indio_dev) 316 321 { 317 322 struct tsl2583_chip *chip = iio_priv(indio_dev); 318 323 unsigned int gain_trim_val; ··· 320 325 int lux_val; 321 326 322 327 ret = i2c_smbus_read_byte_data(chip->client, 323 - TSL258X_CMD_REG | TSL258X_CNTRL); 328 + TSL2583_CMD_REG | TSL2583_CNTRL); 324 329 if (ret < 0) { 325 330 dev_err(&chip->client->dev, 326 - "%s failed to read from the CNTRL register\n", 331 + "%s: failed to read from the CNTRL register\n", 327 332 __func__); 328 333 return ret; 329 334 } 330 335 331 - if ((ret & (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) 332 - != (TSL258X_CNTL_ADC_ENBL | TSL258X_CNTL_PWR_ON)) { 336 + if ((ret & (TSL2583_CNTL_ADC_ENBL | TSL2583_CNTL_PWR_ON)) 337 + != (TSL2583_CNTL_ADC_ENBL | TSL2583_CNTL_PWR_ON)) { 333 338 dev_err(&chip->client->dev, 334 - "taos_als_calibrate failed: device not powered on with ADC enabled\n"); 339 + "%s: Device is not powered on and/or ADC is not enabled\n", 340 + __func__); 335 341 return -EINVAL; 336 - } else if ((ret & TSL258X_STA_ADC_VALID) != TSL258X_STA_ADC_VALID) { 342 + } else if ((ret & TSL2583_STA_ADC_VALID) != TSL2583_STA_ADC_VALID) { 337 343 dev_err(&chip->client->dev, 338 - "taos_als_calibrate failed: STATUS - ADC not valid.\n"); 344 + "%s: The two ADC channels have not completed an integration cycle\n", 345 + __func__); 339 346 return -ENODATA; 340 347 } 341 - lux_val = taos_get_lux(indio_dev); 348 + 349 + lux_val = tsl2583_get_lux(indio_dev); 342 350 if (lux_val < 0) { 343 - dev_err(&chip->client->dev, "taos_als_calibrate failed to get lux\n"); 351 + dev_err(&chip->client->dev, "%s: failed to get lux\n", 352 + __func__); 344 353 return lux_val; 345 354 } 346 - gain_trim_val = (unsigned int)(((chip->taos_settings.als_cal_target) 347 - * chip->taos_settings.als_gain_trim) / lux_val); 348 355 356 + gain_trim_val = (unsigned int)(((chip->als_settings.als_cal_target) 357 + * chip->als_settings.als_gain_trim) / lux_val); 349 358 if ((gain_trim_val < 250) || (gain_trim_val > 4000)) { 350 359 dev_err(&chip->client->dev, 351 - "taos_als_calibrate failed: trim_val of %d is out of range\n", 352 - gain_trim_val); 360 + "%s: trim_val of %d is not within the range [250, 4000]\n", 361 + __func__, gain_trim_val); 353 362 return -ENODATA; 354 363 } 355 - chip->taos_settings.als_gain_trim = (int)gain_trim_val; 356 364 357 - return (int)gain_trim_val; 365 + chip->als_settings.als_gain_trim = (int)gain_trim_val; 366 + 367 + return 0; 368 + } 369 + 370 + static int tsl2583_set_als_time(struct tsl2583_chip *chip) 371 + { 372 + int als_count, als_time, ret; 373 + u8 val; 374 + 375 + /* determine als integration register */ 376 + als_count = (chip->als_settings.als_time * 100 + 135) / 270; 377 + if (!als_count) 378 + als_count = 1; /* ensure at least one cycle */ 379 + 380 + /* convert back to time (encompasses overrides) */ 381 + als_time = (als_count * 27 + 5) / 10; 382 + 383 + val = 256 - als_count; 384 + ret = i2c_smbus_write_byte_data(chip->client, 385 + TSL2583_CMD_REG | TSL2583_ALS_TIME, 386 + val); 387 + if (ret < 0) { 388 + dev_err(&chip->client->dev, "%s: failed to set the als time to %d\n", 389 + __func__, val); 390 + return ret; 391 + } 392 + 393 + /* set chip struct re scaling and saturation */ 394 + chip->als_saturation = als_count * 922; /* 90% of full scale */ 395 + chip->als_time_scale = (als_time + 25) / 50; 396 + 397 + return ret; 398 + } 399 + 400 + static int tsl2583_set_als_gain(struct tsl2583_chip *chip) 401 + { 402 + int ret; 403 + 404 + /* Set the gain based on als_settings struct */ 405 + ret = i2c_smbus_write_byte_data(chip->client, 406 + TSL2583_CMD_REG | TSL2583_GAIN, 407 + chip->als_settings.als_gain); 408 + if (ret < 0) 409 + dev_err(&chip->client->dev, 410 + "%s: failed to set the gain to %d\n", __func__, 411 + chip->als_settings.als_gain); 412 + 413 + return ret; 414 + } 415 + 416 + static int tsl2583_set_power_state(struct tsl2583_chip *chip, u8 state) 417 + { 418 + int ret; 419 + 420 + ret = i2c_smbus_write_byte_data(chip->client, 421 + TSL2583_CMD_REG | TSL2583_CNTRL, state); 422 + if (ret < 0) 423 + dev_err(&chip->client->dev, 424 + "%s: failed to set the power state to %d\n", __func__, 425 + state); 426 + 427 + return ret; 358 428 } 359 429 360 430 /* 361 431 * Turn the device on. 362 432 * Configuration must be set before calling this function. 363 433 */ 364 - static int taos_chip_on(struct iio_dev *indio_dev) 434 + static int tsl2583_chip_init_and_power_on(struct iio_dev *indio_dev) 365 435 { 366 - int i; 367 - int ret; 368 - u8 *uP; 369 - u8 utmp; 370 - int als_count; 371 - int als_time; 372 436 struct tsl2583_chip *chip = iio_priv(indio_dev); 373 - 374 - /* and make sure we're not already on */ 375 - if (chip->taos_chip_status == TSL258X_CHIP_WORKING) { 376 - /* if forcing a register update - turn off, then on */ 377 - dev_info(&chip->client->dev, "device is already enabled\n"); 378 - return -EINVAL; 379 - } 380 - 381 - /* determine als integration register */ 382 - als_count = (chip->taos_settings.als_time * 100 + 135) / 270; 383 - if (!als_count) 384 - als_count = 1; /* ensure at least one cycle */ 385 - 386 - /* convert back to time (encompasses overrides) */ 387 - als_time = (als_count * 27 + 5) / 10; 388 - chip->taos_config[TSL258X_ALS_TIME] = 256 - als_count; 389 - 390 - /* Set the gain based on taos_settings struct */ 391 - chip->taos_config[TSL258X_GAIN] = chip->taos_settings.als_gain; 392 - 393 - /* set chip struct re scaling and saturation */ 394 - chip->als_saturation = als_count * 922; /* 90% of full scale */ 395 - chip->als_time_scale = (als_time + 25) / 50; 437 + int ret; 396 438 397 439 /* Power on the device; ADC off. */ 398 - chip->taos_config[TSL258X_CNTRL] = TSL258X_CNTL_PWR_ON; 440 + ret = tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_ON); 441 + if (ret < 0) 442 + return ret; 399 443 400 - /* 401 - * Use the following shadow copy for our delay before enabling ADC. 402 - * Write all the registers. 403 - */ 404 - for (i = 0, uP = chip->taos_config; i < TSL258X_REG_MAX; i++) { 405 - ret = i2c_smbus_write_byte_data(chip->client, 406 - TSL258X_CMD_REG + i, 407 - *uP++); 408 - if (ret < 0) { 409 - dev_err(&chip->client->dev, 410 - "taos_chip_on failed on reg %d.\n", i); 411 - return ret; 412 - } 413 - } 414 - 415 - usleep_range(3000, 3500); 416 - /* 417 - * NOW enable the ADC 418 - * initialize the desired mode of operation 419 - */ 420 - utmp = TSL258X_CNTL_PWR_ON | TSL258X_CNTL_ADC_ENBL; 421 444 ret = i2c_smbus_write_byte_data(chip->client, 422 - TSL258X_CMD_REG | TSL258X_CNTRL, 423 - utmp); 445 + TSL2583_CMD_REG | TSL2583_INTERRUPT, 446 + TSL2583_INTERRUPT_DISABLED); 424 447 if (ret < 0) { 425 - dev_err(&chip->client->dev, "taos_chip_on failed on 2nd CTRL reg.\n"); 448 + dev_err(&chip->client->dev, 449 + "%s: failed to disable interrupts\n", __func__); 426 450 return ret; 427 451 } 428 - chip->taos_chip_status = TSL258X_CHIP_WORKING; 452 + 453 + ret = tsl2583_set_als_time(chip); 454 + if (ret < 0) 455 + return ret; 456 + 457 + ret = tsl2583_set_als_gain(chip); 458 + if (ret < 0) 459 + return ret; 460 + 461 + usleep_range(3000, 3500); 462 + 463 + ret = tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_ON | 464 + TSL2583_CNTL_ADC_ENBL); 465 + if (ret < 0) 466 + return ret; 467 + 468 + chip->suspended = false; 429 469 430 470 return ret; 431 - } 432 - 433 - static int taos_chip_off(struct iio_dev *indio_dev) 434 - { 435 - struct tsl2583_chip *chip = iio_priv(indio_dev); 436 - 437 - /* turn device off */ 438 - chip->taos_chip_status = TSL258X_CHIP_SUSPENDED; 439 - return i2c_smbus_write_byte_data(chip->client, 440 - TSL258X_CMD_REG | TSL258X_CNTRL, 441 - 0x00); 442 471 } 443 472 444 473 /* Sysfs Interface Functions */ ··· 476 457 int ret; 477 458 478 459 mutex_lock(&chip->als_mutex); 479 - ret = sprintf(buf, "%d\n", chip->taos_settings.als_cal_target); 460 + ret = sprintf(buf, "%d\n", chip->als_settings.als_cal_target); 480 461 mutex_unlock(&chip->als_mutex); 481 462 482 463 return ret; ··· 494 475 return -EINVAL; 495 476 496 477 mutex_lock(&chip->als_mutex); 497 - chip->taos_settings.als_cal_target = value; 478 + chip->als_settings.als_cal_target = value; 498 479 mutex_unlock(&chip->als_mutex); 499 480 500 481 return len; ··· 506 487 { 507 488 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 508 489 struct tsl2583_chip *chip = iio_priv(indio_dev); 509 - int value; 490 + int value, ret; 510 491 511 492 if (kstrtoint(buf, 0, &value) || value != 1) 512 493 return -EINVAL; 513 494 514 495 mutex_lock(&chip->als_mutex); 515 - taos_als_calibrate(indio_dev); 496 + 497 + if (chip->suspended) { 498 + ret = -EBUSY; 499 + goto done; 500 + } 501 + 502 + ret = tsl2583_als_calibrate(indio_dev); 503 + if (ret < 0) 504 + goto done; 505 + 506 + ret = len; 507 + done: 516 508 mutex_unlock(&chip->als_mutex); 517 509 518 - return len; 510 + return ret; 519 511 } 520 512 521 513 static ssize_t in_illuminance_lux_table_show(struct device *dev, 522 514 struct device_attribute *attr, 523 515 char *buf) 524 516 { 525 - int i; 517 + struct iio_dev *indio_dev = dev_to_iio_dev(dev); 518 + struct tsl2583_chip *chip = iio_priv(indio_dev); 519 + unsigned int i; 526 520 int offset = 0; 527 521 528 - for (i = 0; i < ARRAY_SIZE(taos_device_lux); i++) { 522 + for (i = 0; i < ARRAY_SIZE(chip->als_settings.als_device_lux); i++) { 529 523 offset += sprintf(buf + offset, "%u,%u,%u,", 530 - taos_device_lux[i].ratio, 531 - taos_device_lux[i].ch0, 532 - taos_device_lux[i].ch1); 533 - if (taos_device_lux[i].ratio == 0) { 524 + chip->als_settings.als_device_lux[i].ratio, 525 + chip->als_settings.als_device_lux[i].ch0, 526 + chip->als_settings.als_device_lux[i].ch1); 527 + if (chip->als_settings.als_device_lux[i].ratio == 0) { 534 528 /* 535 529 * We just printed the first "0" entry. 536 530 * Now get rid of the extra "," and break. ··· 554 522 } 555 523 556 524 offset += sprintf(buf + offset, "\n"); 525 + 557 526 return offset; 558 527 } 559 528 ··· 564 531 { 565 532 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 566 533 struct tsl2583_chip *chip = iio_priv(indio_dev); 567 - int value[ARRAY_SIZE(taos_device_lux) * 3 + 1]; 568 - int n, ret = -EINVAL; 534 + const unsigned int max_ints = TSL2583_MAX_LUX_TABLE_ENTRIES * 3; 535 + int value[TSL2583_MAX_LUX_TABLE_ENTRIES * 3]; 536 + int ret = -EINVAL; 537 + unsigned int n; 569 538 570 539 mutex_lock(&chip->als_mutex); 571 540 572 541 get_options(buf, ARRAY_SIZE(value), value); 573 542 574 - /* We now have an array of ints starting at value[1], and 543 + /* 544 + * We now have an array of ints starting at value[1], and 575 545 * enumerated by value[0]. 576 546 * We expect each group of three ints is one table entry, 577 547 * and the last table entry is all 0. 578 548 */ 579 549 n = value[0]; 580 - if ((n % 3) || n < 6 || n > ((ARRAY_SIZE(taos_device_lux) - 1) * 3)) { 581 - dev_info(dev, "LUX TABLE INPUT ERROR 1 Value[0]=%d\n", n); 550 + if ((n % 3) || n < 6 || n > max_ints) { 551 + dev_err(dev, 552 + "%s: The number of entries in the lux table must be a multiple of 3 and within the range [6, %d]\n", 553 + __func__, max_ints); 582 554 goto done; 583 555 } 584 - if ((value[(n - 2)] | value[(n - 1)] | value[n]) != 0) { 585 - dev_info(dev, "LUX TABLE INPUT ERROR 2 Value[0]=%d\n", n); 556 + if ((value[n - 2] | value[n - 1] | value[n]) != 0) { 557 + dev_err(dev, "%s: The last 3 entries in the lux table must be zeros.\n", 558 + __func__); 586 559 goto done; 587 560 } 588 561 589 - /* Zero out the table */ 590 - memset(taos_device_lux, 0, sizeof(taos_device_lux)); 591 - memcpy(taos_device_lux, &value[1], (value[0] * 4)); 562 + memcpy(chip->als_settings.als_device_lux, &value[1], 563 + value[0] * sizeof(value[1])); 592 564 593 565 ret = len; 594 566 ··· 654 616 655 617 mutex_lock(&chip->als_mutex); 656 618 657 - if (chip->taos_chip_status != TSL258X_CHIP_WORKING) { 619 + if (chip->suspended) { 658 620 ret = -EBUSY; 659 621 goto read_done; 660 622 } ··· 662 624 switch (mask) { 663 625 case IIO_CHAN_INFO_RAW: 664 626 if (chan->type == IIO_LIGHT) { 665 - ret = taos_get_lux(indio_dev); 627 + ret = tsl2583_get_lux(indio_dev); 666 628 if (ret < 0) 667 629 goto read_done; 668 630 ··· 685 647 break; 686 648 case IIO_CHAN_INFO_PROCESSED: 687 649 if (chan->type == IIO_LIGHT) { 688 - ret = taos_get_lux(indio_dev); 650 + ret = tsl2583_get_lux(indio_dev); 689 651 if (ret < 0) 690 652 goto read_done; 691 653 ··· 695 657 break; 696 658 case IIO_CHAN_INFO_CALIBBIAS: 697 659 if (chan->type == IIO_LIGHT) { 698 - *val = chip->taos_settings.als_gain_trim; 660 + *val = chip->als_settings.als_gain_trim; 699 661 ret = IIO_VAL_INT; 700 662 } 701 663 break; 702 664 case IIO_CHAN_INFO_CALIBSCALE: 703 665 if (chan->type == IIO_LIGHT) { 704 - *val = gainadj[chip->taos_settings.als_gain].mean; 666 + *val = gainadj[chip->als_settings.als_gain].mean; 705 667 ret = IIO_VAL_INT; 706 668 } 707 669 break; 708 670 case IIO_CHAN_INFO_INT_TIME: 709 671 if (chan->type == IIO_LIGHT) { 710 672 *val = 0; 711 - *val2 = chip->taos_settings.als_time; 673 + *val2 = chip->als_settings.als_time; 712 674 ret = IIO_VAL_INT_PLUS_MICRO; 713 675 } 714 676 break; ··· 731 693 732 694 mutex_lock(&chip->als_mutex); 733 695 734 - if (chip->taos_chip_status != TSL258X_CHIP_WORKING) { 696 + if (chip->suspended) { 735 697 ret = -EBUSY; 736 698 goto write_done; 737 699 } ··· 739 701 switch (mask) { 740 702 case IIO_CHAN_INFO_CALIBBIAS: 741 703 if (chan->type == IIO_LIGHT) { 742 - chip->taos_settings.als_gain_trim = val; 704 + chip->als_settings.als_gain_trim = val; 743 705 ret = 0; 744 706 } 745 707 break; 746 708 case IIO_CHAN_INFO_CALIBSCALE: 747 709 if (chan->type == IIO_LIGHT) { 748 - int i; 710 + unsigned int i; 749 711 750 712 for (i = 0; i < ARRAY_SIZE(gainadj); i++) { 751 713 if (gainadj[i].mean == val) { 752 - chip->taos_settings.als_gain = i; 753 - ret = 0; 714 + chip->als_settings.als_gain = i; 715 + ret = tsl2583_set_als_gain(chip); 754 716 break; 755 717 } 756 718 } ··· 759 721 case IIO_CHAN_INFO_INT_TIME: 760 722 if (chan->type == IIO_LIGHT && !val && val2 >= 50 && 761 723 val2 <= 650 && !(val2 % 50)) { 762 - chip->taos_settings.als_time = val2; 763 - ret = 0; 724 + chip->als_settings.als_time = val2; 725 + ret = tsl2583_set_als_time(chip); 764 726 } 765 727 break; 766 728 default: ··· 780 742 .write_raw = tsl2583_write_raw, 781 743 }; 782 744 783 - /* 784 - * Client probe function - When a valid device is found, the driver's device 785 - * data structure is updated, and initialization completes successfully. 786 - */ 787 - static int taos_probe(struct i2c_client *clientp, 788 - const struct i2c_device_id *idp) 745 + static int tsl2583_probe(struct i2c_client *clientp, 746 + const struct i2c_device_id *idp) 789 747 { 790 748 int ret; 791 749 struct tsl2583_chip *chip; ··· 789 755 790 756 if (!i2c_check_functionality(clientp->adapter, 791 757 I2C_FUNC_SMBUS_BYTE_DATA)) { 792 - dev_err(&clientp->dev, "taos_probe() - i2c smbus byte data func unsupported\n"); 758 + dev_err(&clientp->dev, "%s: i2c smbus byte data functionality is unsupported\n", 759 + __func__); 793 760 return -EOPNOTSUPP; 794 761 } 795 762 796 763 indio_dev = devm_iio_device_alloc(&clientp->dev, sizeof(*chip)); 797 764 if (!indio_dev) 798 765 return -ENOMEM; 766 + 799 767 chip = iio_priv(indio_dev); 800 768 chip->client = clientp; 801 769 i2c_set_clientdata(clientp, indio_dev); 802 770 803 771 mutex_init(&chip->als_mutex); 804 - chip->taos_chip_status = TSL258X_CHIP_UNKNOWN; 805 - memcpy(chip->taos_config, taos_config, sizeof(chip->taos_config)); 772 + chip->suspended = true; 806 773 807 774 ret = i2c_smbus_read_byte_data(clientp, 808 - TSL258X_CMD_REG | TSL258X_CHIPID); 775 + TSL2583_CMD_REG | TSL2583_CHIPID); 809 776 if (ret < 0) { 810 777 dev_err(&clientp->dev, 811 - "%s failed to read the chip ID register\n", __func__); 778 + "%s: failed to read the chip ID register\n", __func__); 812 779 return ret; 813 780 } 814 781 815 782 if ((ret & TSL2583_CHIP_ID_MASK) != TSL2583_CHIP_ID) { 816 - dev_info(&clientp->dev, "%s received an unknown chip ID %x\n", 817 - __func__, ret); 783 + dev_err(&clientp->dev, "%s: received an unknown chip ID %x\n", 784 + __func__, ret); 818 785 return -EINVAL; 819 - } 820 - 821 - ret = i2c_smbus_write_byte(clientp, (TSL258X_CMD_REG | TSL258X_CNTRL)); 822 - if (ret < 0) { 823 - dev_err(&clientp->dev, 824 - "i2c_smbus_write_byte() to cmd reg failed in taos_probe(), err = %d\n", 825 - ret); 826 - return ret; 827 786 } 828 787 829 788 indio_dev->info = &tsl2583_info; ··· 825 798 indio_dev->dev.parent = &clientp->dev; 826 799 indio_dev->modes = INDIO_DIRECT_MODE; 827 800 indio_dev->name = chip->client->name; 801 + 828 802 ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev); 829 803 if (ret) { 830 - dev_err(&clientp->dev, "iio registration failed\n"); 804 + dev_err(&clientp->dev, "%s: iio registration failed\n", 805 + __func__); 831 806 return ret; 832 807 } 833 808 834 809 /* Load up the V2 defaults (these are hard coded defaults for now) */ 835 - taos_defaults(chip); 810 + tsl2583_defaults(chip); 836 811 837 812 /* Make sure the chip is on */ 838 - ret = taos_chip_on(indio_dev); 813 + ret = tsl2583_chip_init_and_power_on(indio_dev); 839 814 if (ret < 0) 840 815 return ret; 841 816 842 817 dev_info(&clientp->dev, "Light sensor found.\n"); 818 + 843 819 return 0; 844 820 } 845 821 846 - #ifdef CONFIG_PM_SLEEP 847 - static int taos_suspend(struct device *dev) 822 + static int __maybe_unused tsl2583_suspend(struct device *dev) 848 823 { 849 824 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 850 825 struct tsl2583_chip *chip = iio_priv(indio_dev); 851 - int ret = 0; 826 + int ret; 852 827 853 828 mutex_lock(&chip->als_mutex); 854 829 855 - if (chip->taos_chip_status == TSL258X_CHIP_WORKING) { 856 - ret = taos_chip_off(indio_dev); 857 - chip->taos_chip_status = TSL258X_CHIP_SUSPENDED; 858 - } 830 + ret = tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_OFF); 831 + chip->suspended = true; 859 832 860 833 mutex_unlock(&chip->als_mutex); 834 + 861 835 return ret; 862 836 } 863 837 864 - static int taos_resume(struct device *dev) 838 + static int __maybe_unused tsl2583_resume(struct device *dev) 865 839 { 866 840 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 867 841 struct tsl2583_chip *chip = iio_priv(indio_dev); 868 - int ret = 0; 842 + int ret; 869 843 870 844 mutex_lock(&chip->als_mutex); 871 845 872 - if (chip->taos_chip_status == TSL258X_CHIP_SUSPENDED) 873 - ret = taos_chip_on(indio_dev); 846 + ret = tsl2583_chip_init_and_power_on(indio_dev); 874 847 875 848 mutex_unlock(&chip->als_mutex); 849 + 876 850 return ret; 877 851 } 878 852 879 - static SIMPLE_DEV_PM_OPS(taos_pm_ops, taos_suspend, taos_resume); 880 - #define TAOS_PM_OPS (&taos_pm_ops) 881 - #else 882 - #define TAOS_PM_OPS NULL 883 - #endif 853 + static SIMPLE_DEV_PM_OPS(tsl2583_pm_ops, tsl2583_suspend, tsl2583_resume); 884 854 885 - static struct i2c_device_id taos_idtable[] = { 855 + static struct i2c_device_id tsl2583_idtable[] = { 886 856 { "tsl2580", 0 }, 887 857 { "tsl2581", 1 }, 888 858 { "tsl2583", 2 }, 889 859 {} 890 860 }; 891 - MODULE_DEVICE_TABLE(i2c, taos_idtable); 861 + MODULE_DEVICE_TABLE(i2c, tsl2583_idtable); 892 862 893 - #ifdef CONFIG_OF 894 - static const struct of_device_id taos2583_of_match[] = { 863 + static const struct of_device_id tsl2583_of_match[] = { 895 864 { .compatible = "amstaos,tsl2580", }, 896 865 { .compatible = "amstaos,tsl2581", }, 897 866 { .compatible = "amstaos,tsl2583", }, 898 867 { }, 899 868 }; 900 - MODULE_DEVICE_TABLE(of, taos2583_of_match); 901 - #else 902 - #define taos2583_of_match NULL 903 - #endif 869 + MODULE_DEVICE_TABLE(of, tsl2583_of_match); 904 870 905 871 /* Driver definition */ 906 - static struct i2c_driver taos_driver = { 872 + static struct i2c_driver tsl2583_driver = { 907 873 .driver = { 908 874 .name = "tsl2583", 909 - .pm = TAOS_PM_OPS, 910 - .of_match_table = taos2583_of_match, 875 + .pm = &tsl2583_pm_ops, 876 + .of_match_table = tsl2583_of_match, 911 877 }, 912 - .id_table = taos_idtable, 913 - .probe = taos_probe, 878 + .id_table = tsl2583_idtable, 879 + .probe = tsl2583_probe, 914 880 }; 915 - module_i2c_driver(taos_driver); 881 + module_i2c_driver(tsl2583_driver); 916 882 917 - MODULE_AUTHOR("J. August Brenner<jbrenner@taosinc.com>"); 883 + MODULE_AUTHOR("J. August Brenner <jbrenner@taosinc.com>"); 884 + MODULE_AUTHOR("Brian Masney <masneyb@onstation.org>"); 918 885 MODULE_DESCRIPTION("TAOS tsl2583 ambient light sensor driver"); 919 886 MODULE_LICENSE("GPL");
+28
include/linux/iio/consumer.h
··· 226 226 int iio_write_channel_raw(struct iio_channel *chan, int val); 227 227 228 228 /** 229 + * iio_read_max_channel_raw() - read maximum available raw value from a given 230 + * channel, i.e. the maximum possible value. 231 + * @chan: The channel being queried. 232 + * @val: Value read back. 233 + * 234 + * Note raw reads from iio channels are in adc counts and hence 235 + * scale will need to be applied if standard units are required. 236 + */ 237 + int iio_read_max_channel_raw(struct iio_channel *chan, int *val); 238 + 239 + /** 240 + * iio_read_avail_channel_raw() - read available raw values from a given channel 241 + * @chan: The channel being queried. 242 + * @vals: Available values read back. 243 + * @length: Number of entries in vals. 244 + * 245 + * Returns an error code, IIO_AVAIL_RANGE or IIO_AVAIL_LIST. 246 + * 247 + * For ranges, three vals are always returned; min, step and max. 248 + * For lists, all the possible values are enumerated. 249 + * 250 + * Note raw available values from iio channels are in adc counts and 251 + * hence scale will need to be applied if standard units are required. 252 + */ 253 + int iio_read_avail_channel_raw(struct iio_channel *chan, 254 + const int **vals, int *length); 255 + 256 + /** 229 257 * iio_get_channel_type() - get the type of a channel 230 258 * @channel: The channel being queried. 231 259 * @type: The type of the channel.
+46
include/linux/iio/iio.h
··· 225 225 * endianness: little or big endian 226 226 * @info_mask_separate: What information is to be exported that is specific to 227 227 * this channel. 228 + * @info_mask_separate_available: What availability information is to be 229 + * exported that is specific to this channel. 228 230 * @info_mask_shared_by_type: What information is to be exported that is shared 229 231 * by all channels of the same type. 232 + * @info_mask_shared_by_type_available: What availability information is to be 233 + * exported that is shared by all channels of the same 234 + * type. 230 235 * @info_mask_shared_by_dir: What information is to be exported that is shared 231 236 * by all channels of the same direction. 237 + * @info_mask_shared_by_dir_available: What availability information is to be 238 + * exported that is shared by all channels of the same 239 + * direction. 232 240 * @info_mask_shared_by_all: What information is to be exported that is shared 233 241 * by all channels. 242 + * @info_mask_shared_by_all_available: What availability information is to be 243 + * exported that is shared by all channels. 234 244 * @event_spec: Array of events which should be registered for this 235 245 * channel. 236 246 * @num_event_specs: Size of the event_spec array. ··· 279 269 enum iio_endian endianness; 280 270 } scan_type; 281 271 long info_mask_separate; 272 + long info_mask_separate_available; 282 273 long info_mask_shared_by_type; 274 + long info_mask_shared_by_type_available; 283 275 long info_mask_shared_by_dir; 276 + long info_mask_shared_by_dir_available; 284 277 long info_mask_shared_by_all; 278 + long info_mask_shared_by_all_available; 285 279 const struct iio_event_spec *event_spec; 286 280 unsigned int num_event_specs; 287 281 const struct iio_chan_spec_ext_info *ext_info; ··· 313 299 (chan->info_mask_shared_by_type & BIT(type)) | 314 300 (chan->info_mask_shared_by_dir & BIT(type)) | 315 301 (chan->info_mask_shared_by_all & BIT(type)); 302 + } 303 + 304 + /** 305 + * iio_channel_has_available() - Checks if a channel has an available attribute 306 + * @chan: The channel to be queried 307 + * @type: Type of the available attribute to be checked 308 + * 309 + * Returns true if the channel supports reporting available values for the 310 + * given attribute type, false otherwise. 311 + */ 312 + static inline bool iio_channel_has_available(const struct iio_chan_spec *chan, 313 + enum iio_chan_info_enum type) 314 + { 315 + return (chan->info_mask_separate_available & BIT(type)) | 316 + (chan->info_mask_shared_by_type_available & BIT(type)) | 317 + (chan->info_mask_shared_by_dir_available & BIT(type)) | 318 + (chan->info_mask_shared_by_all_available & BIT(type)); 316 319 } 317 320 318 321 #define IIO_CHAN_SOFT_TIMESTAMP(_si) { \ ··· 380 349 * max_len specifies maximum number of elements 381 350 * vals pointer can contain. val_len is used to return 382 351 * length of valid elements in vals. 352 + * @read_avail: function to return the available values from the device. 353 + * mask specifies which value. Note 0 means the available 354 + * values for the channel in question. Return value 355 + * specifies if a IIO_AVAIL_LIST or a IIO_AVAIL_RANGE is 356 + * returned in vals. The type of the vals are returned in 357 + * type and the number of vals is returned in length. For 358 + * ranges, there are always three vals returned; min, step 359 + * and max. For lists, all possible values are enumerated. 383 360 * @write_raw: function to write a value to the device. 384 361 * Parameters are the same as for read_raw. 385 362 * @write_raw_get_fmt: callback function to query the expected ··· 435 396 int *vals, 436 397 int *val_len, 437 398 long mask); 399 + 400 + int (*read_avail)(struct iio_dev *indio_dev, 401 + struct iio_chan_spec const *chan, 402 + const int **vals, 403 + int *type, 404 + int *length, 405 + long mask); 438 406 439 407 int (*write_raw)(struct iio_dev *indio_dev, 440 408 struct iio_chan_spec const *chan,
+5
include/linux/iio/types.h
··· 29 29 #define IIO_VAL_FRACTIONAL 10 30 30 #define IIO_VAL_FRACTIONAL_LOG2 11 31 31 32 + enum iio_available_type { 33 + IIO_AVAIL_LIST, 34 + IIO_AVAIL_RANGE, 35 + }; 36 + 32 37 #endif /* _IIO_TYPES_H_ */