Jonathan writes: Second set of new device support, cleanups and features for IIO in the 5.8 cycle Usual mixed back but with a few subsystem wide or device type wide cleanups. New device support * adis16475 - New driver supporting adis16470, adis16475, adis16477, adis16465, adis16467, adis16500, adis16505 and adis16507. Includes some rework of the adis library to simplify using it for this new driver. * ak8974 - Add support for Alps hscdt008a. ID only. Related patches add support for scale. * atlas-sensor - Add support for RTD-SM OEM temperature sensor. * cm32181 - Add support for CM3218 including support for SMBUS alert via ACPI resources. * ltc2632 - Add support for ltc2634-12/10/8 DACS including handling per device type numbers of channels. Major Features * cm32181 - ACPI bindings including parsing CPM0 and CPM1 custom ACPI tables. Includes minor tidy ups and fixes. * vcnl4000 - Add event support - Add buffered data capture support - Add control of sampling frequency Cleanups and minor fixes. * core - Trivial rework of iio_device_alloc to use an early return and improve readability. - Precursors to addition of multiple buffer support. So far minor refactoring. * subsystem wide - Use get_unaligned_be24 slightly improve readability over open coding it. * adis drivers - Use iio_get_debugfs_dentry access function. * bh1780, cm32181, cm3232, gp2ap02a00f, opt3001, st_uvis25, vl6180, dmard06, kxsd9 - Drop use of of_match_ptr to allow ACPI based probing via PRP0001. Part of clear out of this to avoid cut and paste into new drivers. * ad5592r, ad5593r - Fix typos * ad5933 - Use managed interfaces to automate error handling and remove. * ak8974 - Fix wrong number of 'real bits' for buffered data. - Refactor to pull measurement code out as separate function. bmp280 - Fix lack of clamp on range during data capture. * at91-sama5d2_adc - Handle unfinished conversions correctly. - Allow use of triggers other than it's own. - Reorganize buffer setup and tear down as part of long running subsystem wide rework. * ccs811 - Add DT binding docs and match table. - Support external reset and wakeup pins. * hid-sensors - Reorganize buffer setup and tear down as part of long running subsystem wide rework. * ltr501 - Constify some structs. * vcnl4000 - Fix an endian issue by using explicit byte swapped i2c accessors. * tag 'iio-for-5.8b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (74 commits) iio: light: ltr501: Constify structs staging: iio: ad5933: attach life-cycle of kfifo buffer to parent device and use managed calls throughout iio: bmp280: fix compensation of humidity iio: light: cm32181: Fix integartion time typo iio: light: cm32181: Add support for parsing CPM0 and CPM1 ACPI tables iio: light: cm32181: Make lux_per_bit and lux_per_bit_base_it runtime settings iio: light: cm32181: Use units of 1/100000th for calibscale and lux_per_bit iio: light: cm32181: Change reg_init to use a bitmap of which registers to init iio: light: cm32181: Handle CM3218 ACPI devices with 2 I2C resources iio: light: cm32181: Clean up the probe function a bit iio: light: cm32181: Add support for the CM3218 iio: light: cm32181: Add some extra register defines iio: light: cm32181: Add support for ACPI enumeration iio: light: cm32181: Switch to new style i2c-driver probe function iio: hid-sensors: move triggered buffer setup into hid_sensor_setup_trigger iio: vcnl4000: Add buffer support for VCNL4010/20. iio: vcnl4000: Add sampling frequency support for VCNL4010/20. iio: vcnl4000: Add event support for VCNL4010/20. iio: vcnl4000: Factorize data reading and writing. iio: vcnl4000: Fix i2c swapped word reading. ...
Unified · Split
| @@ -0,0 +1,53 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/iio/chemical/ams,ccs811.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: AMS CCS811 VOC Sensor | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Narcisa Vasile <narcisaanamaria12@gmail.com> | |
| 11 | + | |
| 12 | +description: | | |
| 13 | + Ultra-Low Power Digital Gas Sensor for Monitoring Indoor Air Quality. | |
| 14 | + | |
| 15 | +properties: | |
| 16 | + compatible: | |
| 17 | + enum: | |
| 18 | + - ams,ccs811 | |
| 19 | + reg: | |
| 20 | + maxItems: 1 | |
| 21 | + | |
| 22 | + reset-gpios: | |
| 23 | + description: GPIO connected to the nRESET line. This is an active low | |
| 24 | + input to CCS811. | |
| 25 | + maxItems: 1 | |
| 26 | + | |
| 27 | + wakeup-gpios: | |
| 28 | + description: GPIO connected to the nWAKE line. This is an active low | |
| 29 | + input to CCS811. | |
| 30 | + maxItems: 1 | |
| 31 | + | |
| 32 | +required: | |
| 33 | + - compatible | |
| 34 | + - reg | |
| 35 | + | |
| 36 | +additionalProperties: false | |
| 37 | + | |
| 38 | +examples: | |
| 39 | + - | | |
| 40 | + #include <dt-bindings/gpio/gpio.h> | |
| 41 | + i2c { | |
| 42 | + #address-cells = <1>; | |
| 43 | + #size-cells = <0>; | |
| 44 | + | |
| 45 | + voc@5b { | |
| 46 | + compatible = "ams,ccs811"; | |
| 47 | + reg = <0x5b>; | |
| 48 | + reset-gpios = <&gpioa 11 GPIO_ACTIVE_LOW>; | |
| 49 | + wakeup-gpios = <&gpioa 12 GPIO_ACTIVE_LOW>; | |
| 50 | + }; | |
| 51 | + }; | |
| 52 | + | |
| 53 | +... | |
| @@ -17,6 +17,7 @@ description: | · 16 unmodified lines | ||
| 17 | 17 | http://www.atlas-scientific.com/_files/_datasheets/_oem/EC_oem_datasheet.pdf |
| 18 | 18 | http://www.atlas-scientific.com/_files/_datasheets/_oem/ORP_oem_datasheet.pdf |
| 19 | 19 | http://www.atlas-scientific.com/_files/_datasheets/_oem/pH_oem_datasheet.pdf |
| 20 | + http://www.atlas-scientific.com/_files/_datasheets/_oem/RTD_oem_datasheet.pdf | |
| 20 | 21 | |
| 21 | 22 | properties: |
| 22 | 23 | compatible: |
| @@ -25,6 +26,7 @@ properties: · 2 unmodified lines | ||
| 25 | 26 | - atlas,ec-sm |
| 26 | 27 | - atlas,orp-sm |
| 27 | 28 | - atlas,ph-sm |
| 29 | + - atlas,rtd-sm | |
| 28 | 30 | |
| 29 | 31 | reg: |
| 30 | 32 | maxItems: 1 |
| @@ -1,4 +1,4 @@ | ||
| 1 | −Linear Technology LTC2632/2636 DAC | |
| 1 | +Linear Technology LTC2632/2634/2636 DAC | |
| 2 | 2 | |
| 3 | 3 | Required properties: |
| 4 | 4 | - compatible: Has to contain one of the following: |
| @@ -8,6 +8,12 @@ Required properties: · 3 unmodified lines | ||
| 8 | 8 | lltc,ltc2632-h12 |
| 9 | 9 | lltc,ltc2632-h10 |
| 10 | 10 | lltc,ltc2632-h8 |
| 11 | + lltc,ltc2634-l12 | |
| 12 | + lltc,ltc2634-l10 | |
| 13 | + lltc,ltc2634-l8 | |
| 14 | + lltc,ltc2634-h12 | |
| 15 | + lltc,ltc2634-h10 | |
| 16 | + lltc,ltc2634-h8 | |
| 11 | 17 | lltc,ltc2636-l12 |
| 12 | 18 | lltc,ltc2636-l10 |
| 13 | 19 | lltc,ltc2636-l8 |
| @@ -0,0 +1,137 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/iio/imu/adi,adis16475.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Analog Devices ADIS16475 and similar IMUs | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Nuno Sá <nuno.sa@analog.com> | |
| 11 | + | |
| 12 | +description: | | |
| 13 | + Analog Devices ADIS16475 and similar IMUs | |
| 14 | + https://www.analog.com/media/en/technical-documentation/data-sheets/ADIS16475.pdf | |
| 15 | + | |
| 16 | +properties: | |
| 17 | + compatible: | |
| 18 | + enum: | |
| 19 | + - adi,adis16475-1 | |
| 20 | + - adi,adis16475-2 | |
| 21 | + - adi,adis16475-3 | |
| 22 | + - adi,adis16477-1 | |
| 23 | + - adi,adis16477-2 | |
| 24 | + - adi,adis16477-3 | |
| 25 | + - adi,adis16470 | |
| 26 | + - adi,adis16465-1 | |
| 27 | + - adi,adis16465-2 | |
| 28 | + - adi,adis16465-3 | |
| 29 | + - adi,adis16467-1 | |
| 30 | + - adi,adis16467-2 | |
| 31 | + - adi,adis16467-3 | |
| 32 | + - adi,adis16500 | |
| 33 | + - adi,adis16505-1 | |
| 34 | + - adi,adis16505-2 | |
| 35 | + - adi,adis16505-3 | |
| 36 | + - adi,adis16507-1 | |
| 37 | + - adi,adis16507-2 | |
| 38 | + - adi,adis16507-3 | |
| 39 | + | |
| 40 | + reg: | |
| 41 | + maxItems: 1 | |
| 42 | + | |
| 43 | + spi-cpha: true | |
| 44 | + | |
| 45 | + spi-cpol: true | |
| 46 | + | |
| 47 | + spi-max-frequency: | |
| 48 | + maximum: 2000000 | |
| 49 | + | |
| 50 | + interrupts: | |
| 51 | + maxItems: 1 | |
| 52 | + | |
| 53 | + clocks: | |
| 54 | + maxItems: 1 | |
| 55 | + | |
| 56 | + reset-gpios: | |
| 57 | + description: | |
| 58 | + Must be the device tree identifier of the RESET pin. If specified, | |
| 59 | + it will be asserted during driver probe. As the line is active low, | |
| 60 | + it should be marked GPIO_ACTIVE_LOW. | |
| 61 | + maxItems: 1 | |
| 62 | + | |
| 63 | + adi,sync-mode: | |
| 64 | + description: | |
| 65 | + Configures the device SYNC pin. The following modes are supported | |
| 66 | + 0 - output_sync | |
| 67 | + 1 - direct_sync | |
| 68 | + 2 - scaled_sync | |
| 69 | + 3 - pulse_sync | |
| 70 | + allOf: | |
| 71 | + - $ref: /schemas/types.yaml#/definitions/uint32 | |
| 72 | + minimum: 0 | |
| 73 | + maximum: 3 | |
| 74 | + | |
| 75 | + adi,scaled-output-hz: | |
| 76 | + description: | |
| 77 | + This property must be present if the clock mode is scaled-sync through | |
| 78 | + clock-names property. In this mode, the input clock can have a range | |
| 79 | + of 1Hz to 128HZ which must be scaled to originate an allowable sample | |
| 80 | + rate. This property specifies that rate. | |
| 81 | + minimum: 1900 | |
| 82 | + maximum: 2100 | |
| 83 | + | |
| 84 | +required: | |
| 85 | + - compatible | |
| 86 | + - reg | |
| 87 | + - interrupts | |
| 88 | + - spi-cpha | |
| 89 | + - spi-cpol | |
| 90 | + | |
| 91 | +allOf: | |
| 92 | + - if: | |
| 93 | + properties: | |
| 94 | + compatible: | |
| 95 | + contains: | |
| 96 | + enum: | |
| 97 | + - adi,adis16500 | |
| 98 | + - adi,adis16505-1 | |
| 99 | + - adi,adis16505-2 | |
| 100 | + - adi,adis16505-3 | |
| 101 | + - adi,adis16507-1 | |
| 102 | + - adi,adis16507-2 | |
| 103 | + - adi,adis16507-3 | |
| 104 | + | |
| 105 | + then: | |
| 106 | + properties: | |
| 107 | + adi,sync-mode: | |
| 108 | + minimum: 0 | |
| 109 | + maximum: 2 | |
| 110 | + | |
| 111 | + - if: | |
| 112 | + properties: | |
| 113 | + adi,sync-mode: | |
| 114 | + enum: [1, 2, 3] | |
| 115 | + | |
| 116 | + then: | |
| 117 | + dependencies: | |
| 118 | + adi,sync-mode: [ clocks ] | |
| 119 | + | |
| 120 | +examples: | |
| 121 | + - | | |
| 122 | + #include <dt-bindings/interrupt-controller/irq.h> | |
| 123 | + spi { | |
| 124 | + #address-cells = <1>; | |
| 125 | + #size-cells = <0>; | |
| 126 | + | |
| 127 | + adis16475: adis16475-3@0 { | |
| 128 | + compatible = "adi,adis16475-3"; | |
| 129 | + reg = <0>; | |
| 130 | + spi-cpha; | |
| 131 | + spi-cpol; | |
| 132 | + spi-max-frequency = <2000000>; | |
| 133 | + interrupts = <4 IRQ_TYPE_EDGE_RISING>; | |
| 134 | + interrupt-parent = <&gpio>; | |
| 135 | + }; | |
| 136 | + }; | |
| 137 | +... | |
| @@ -2,7 +2,9 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | Required properties: |
| 4 | 4 | |
| 5 | −- compatible : should be "asahi-kasei,ak8974" | |
| 5 | +- compatible: | |
| 6 | + * "asahi-kasei,ak8974" | |
| 7 | + * "alps,hscdtd008a" | |
| 6 | 8 | - reg : the I2C address of the magnetometer |
| 7 | 9 | |
| 8 | 10 | Optional properties: |
| @@ -1031,6 +1031,14 @@ W: http://ez.analog.com/community/linux-device-drivers · 1030 unmodified lines | ||
| 1031 | 1031 | F: Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml |
| 1032 | 1032 | F: drivers/iio/imu/adis16460.c |
| 1033 | 1033 | |
| 1034 | +ANALOG DEVICES INC ADIS16475 DRIVER | |
| 1035 | +M: Nuno Sa <nuno.sa@analog.com> | |
| 1036 | +L: linux-iio@vger.kernel.org | |
| 1037 | +W: http://ez.analog.com/community/linux-device-drivers | |
| 1038 | +S: Supported | |
| 1039 | +F: drivers/iio/imu/adis16475.c | |
| 1040 | +F: Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml | |
| 1041 | + | |
| 1034 | 1042 | ANALOG DEVICES INC ADM1177 DRIVER |
| 1035 | 1043 | M: Beniamin Bia <beniamin.bia@analog.com> |
| 1036 | 1044 | M: Michael Hennerich <Michael.Hennerich@analog.com> |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | #include <linux/module.h> |
| 9 | +#include <linux/mod_devicetable.h> | |
| 9 | 10 | #include <linux/i2c.h> |
| 10 | 11 | #include <linux/iio/iio.h> |
| 11 | 12 | |
| @@ -226,7 +227,7 @@ static struct i2c_driver dmard06_driver = { · 214 unmodified lines | ||
| 226 | 227 | .id_table = dmard06_id, |
| 227 | 228 | .driver = { |
| 228 | 229 | .name = DMARD06_DRV_NAME, |
| 229 | − .of_match_table = of_match_ptr(dmard06_of_match), | |
| 230 | + .of_match_table = dmard06_of_match, | |
| 230 | 231 | .pm = DMARD06_PM_OPS, |
| 231 | 232 | }, |
| 232 | 233 | }; |
| @@ -14,8 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/iio/iio.h> |
| 15 | 15 | #include <linux/iio/sysfs.h> |
| 16 | 16 | #include <linux/iio/buffer.h> |
| 17 | −#include <linux/iio/trigger_consumer.h> | |
| 18 | −#include <linux/iio/triggered_buffer.h> | |
| 19 | 17 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 20 | 18 | |
| 21 | 19 | enum accel_3d_channel { |
| @@ -391,18 +389,13 @@ static int hid_accel_3d_probe(struct platform_device *pdev) · 369 unmodified lines | ||
| 391 | 389 | indio_dev->name = name; |
| 392 | 390 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 393 | 391 | |
| 394 | − ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, | |
| 395 | − NULL, NULL); | |
| 396 | − if (ret) { | |
| 397 | − dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | |
| 398 | − goto error_free_dev_mem; | |
| 399 | − } | |
| 400 | 392 | atomic_set(&accel_state->common_attributes.data_ready, 0); |
| 393 | + | |
| 401 | 394 | ret = hid_sensor_setup_trigger(indio_dev, name, |
| 402 | 395 | &accel_state->common_attributes); |
| 403 | 396 | if (ret < 0) { |
| 404 | 397 | dev_err(&pdev->dev, "trigger setup failed\n"); |
| 405 | − goto error_unreg_buffer_funcs; | |
| 398 | + goto error_free_dev_mem; | |
| 406 | 399 | } |
| 407 | 400 | |
| 408 | 401 | ret = iio_device_register(indio_dev); |
| @@ -426,9 +419,7 @@ static int hid_accel_3d_probe(struct platform_device *pdev) · 17 unmodified lines | ||
| 426 | 419 | error_iio_unreg: |
| 427 | 420 | iio_device_unregister(indio_dev); |
| 428 | 421 | error_remove_trigger: |
| 429 | − hid_sensor_remove_trigger(&accel_state->common_attributes); | |
| 430 | −error_unreg_buffer_funcs: | |
| 431 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 422 | + hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes); | |
| 432 | 423 | error_free_dev_mem: |
| 433 | 424 | kfree(indio_dev->channels); |
| 434 | 425 | return ret; |
| @@ -443,8 +434,7 @@ static int hid_accel_3d_remove(struct platform_device *pdev) · 8 unmodified lines | ||
| 443 | 434 | |
| 444 | 435 | sensor_hub_remove_callback(hsdev, hsdev->usage); |
| 445 | 436 | iio_device_unregister(indio_dev); |
| 446 | − hid_sensor_remove_trigger(&accel_state->common_attributes); | |
| 447 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 437 | + hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes); | |
| 448 | 438 | kfree(indio_dev->channels); |
| 449 | 439 | |
| 450 | 440 | return 0; |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | #include <linux/device.h> |
| 3 | 3 | #include <linux/kernel.h> |
| 4 | 4 | #include <linux/module.h> |
| 5 | +#include <linux/mod_devicetable.h> | |
| 5 | 6 | #include <linux/slab.h> |
| 6 | 7 | #include <linux/i2c.h> |
| 7 | 8 | #include <linux/delay.h> |
| @@ -36,15 +37,11 @@ static int kxsd9_i2c_remove(struct i2c_client *client) · 28 unmodified lines | ||
| 36 | 37 | return kxsd9_common_remove(&client->dev); |
| 37 | 38 | } |
| 38 | 39 | |
| 39 | −#ifdef CONFIG_OF | |
| 40 | 40 | static const struct of_device_id kxsd9_of_match[] = { |
| 41 | 41 | { .compatible = "kionix,kxsd9", }, |
| 42 | 42 | { }, |
| 43 | 43 | }; |
| 44 | 44 | MODULE_DEVICE_TABLE(of, kxsd9_of_match); |
| 45 | −#else | |
| 46 | −#define kxsd9_of_match NULL | |
| 47 | −#endif | |
| 48 | 45 | |
| 49 | 46 | static const struct i2c_device_id kxsd9_i2c_id[] = { |
| 50 | 47 | {"kxsd9", 0}, |
| @@ -55,7 +52,7 @@ MODULE_DEVICE_TABLE(i2c, kxsd9_i2c_id); · 4 unmodified lines | ||
| 55 | 52 | static struct i2c_driver kxsd9_i2c_driver = { |
| 56 | 53 | .driver = { |
| 57 | 54 | .name = "kxsd9", |
| 58 | − .of_match_table = of_match_ptr(kxsd9_of_match), | |
| 55 | + .of_match_table = kxsd9_of_match, | |
| 59 | 56 | .pm = &kxsd9_dev_pm_ops, |
| 60 | 57 | }, |
| 61 | 58 | .probe = kxsd9_i2c_probe, |
| @@ -309,7 +309,7 @@ static int ad7476_probe(struct spi_device *spi) · 308 unmodified lines | ||
| 309 | 309 | indio_dev->num_channels = 2; |
| 310 | 310 | indio_dev->info = &ad7476_info; |
| 311 | 311 | |
| 312 | − if (st->convst_gpio && st->chip_info->convst_channel) | |
| 312 | + if (st->convst_gpio) | |
| 313 | 313 | indio_dev->channels = st->chip_info->convst_channel; |
| 314 | 314 | /* Setup default message */ |
| 315 | 315 | |
| @@ -70,9 +70,7 @@ int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg, · 69 unmodified lines | ||
| 70 | 70 | |
| 71 | 71 | switch (size) { |
| 72 | 72 | case 3: |
| 73 | − data[1] = val >> 16; | |
| 74 | − data[2] = val >> 8; | |
| 75 | − data[3] = val; | |
| 73 | + put_unaligned_be24(val, &data[1]); | |
| 76 | 74 | break; |
| 77 | 75 | case 2: |
| 78 | 76 | put_unaligned_be16(val, &data[1]); |
| @@ -157,9 +155,7 @@ int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta, · 78 unmodified lines | ||
| 157 | 155 | *val = get_unaligned_be32(sigma_delta->data); |
| 158 | 156 | break; |
| 159 | 157 | case 3: |
| 160 | − *val = (sigma_delta->data[0] << 16) | | |
| 161 | − (sigma_delta->data[1] << 8) | | |
| 162 | − sigma_delta->data[2]; | |
| 158 | + *val = get_unaligned_be24(&sigma_delta->data[0]); | |
| 163 | 159 | break; |
| 164 | 160 | case 2: |
| 165 | 161 | *val = get_unaligned_be16(sigma_delta->data); |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | |
| 9 | 9 | #include <linux/bitops.h> |
| 10 | 10 | #include <linux/clk.h> |
| 11 | +#include <linux/delay.h> | |
| 11 | 12 | #include <linux/dma-mapping.h> |
| 12 | 13 | #include <linux/dmaengine.h> |
| 13 | 14 | #include <linux/interrupt.h> |
| @@ -100,6 +101,8 @@ · 86 unmodified lines | ||
| 100 | 101 | #define AT91_SAMA5D2_IER_YRDY BIT(21) |
| 101 | 102 | /* Interrupt Enable Register - TS pressure measurement ready */ |
| 102 | 103 | #define AT91_SAMA5D2_IER_PRDY BIT(22) |
| 104 | +/* Interrupt Enable Register - Data ready */ | |
| 105 | +#define AT91_SAMA5D2_IER_DRDY BIT(24) | |
| 103 | 106 | /* Interrupt Enable Register - general overrun error */ |
| 104 | 107 | #define AT91_SAMA5D2_IER_GOVRE BIT(25) |
| 105 | 108 | /* Interrupt Enable Register - Pen detect */ |
| @@ -486,6 +489,21 @@ static inline int at91_adc_of_xlate(struct iio_dev *indio_dev, · 380 unmodified lines | ||
| 486 | 489 | return at91_adc_chan_xlate(indio_dev, iiospec->args[0]); |
| 487 | 490 | } |
| 488 | 491 | |
| 492 | +static unsigned int at91_adc_active_scan_mask_to_reg(struct iio_dev *indio_dev) | |
| 493 | +{ | |
| 494 | + u32 mask = 0; | |
| 495 | + u8 bit; | |
| 496 | + | |
| 497 | + for_each_set_bit(bit, indio_dev->active_scan_mask, | |
| 498 | + indio_dev->num_channels) { | |
| 499 | + struct iio_chan_spec const *chan = | |
| 500 | + at91_adc_chan_get(indio_dev, bit); | |
| 501 | + mask |= BIT(chan->channel); | |
| 502 | + } | |
| 503 | + | |
| 504 | + return mask & GENMASK(11, 0); | |
| 505 | +} | |
| 506 | + | |
| 489 | 507 | static void at91_adc_config_emr(struct at91_adc_state *st) |
| 490 | 508 | { |
| 491 | 509 | /* configure the extended mode register */ |
| @@ -710,7 +728,6 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state) · 218 unmodified lines | ||
| 710 | 728 | struct iio_dev *indio = iio_trigger_get_drvdata(trig); |
| 711 | 729 | struct at91_adc_state *st = iio_priv(indio); |
| 712 | 730 | u32 status = at91_adc_readl(st, AT91_SAMA5D2_TRGR); |
| 713 | − u8 bit; | |
| 714 | 731 | |
| 715 | 732 | /* clear TRGMOD */ |
| 716 | 733 | status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK; |
| @@ -721,50 +738,6 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state) · 4 unmodified lines | ||
| 721 | 738 | /* set/unset hw trigger */ |
| 722 | 739 | at91_adc_writel(st, AT91_SAMA5D2_TRGR, status); |
| 723 | 740 | |
| 724 | − for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) { | |
| 725 | − struct iio_chan_spec const *chan = at91_adc_chan_get(indio, bit); | |
| 726 | − u32 cor; | |
| 727 | − | |
| 728 | − if (!chan) | |
| 729 | − continue; | |
| 730 | − /* these channel types cannot be handled by this trigger */ | |
| 731 | − if (chan->type == IIO_POSITIONRELATIVE || | |
| 732 | − chan->type == IIO_PRESSURE) | |
| 733 | − continue; | |
| 734 | − | |
| 735 | − if (state) { | |
| 736 | − cor = at91_adc_readl(st, AT91_SAMA5D2_COR); | |
| 737 | − | |
| 738 | − if (chan->differential) | |
| 739 | − cor |= (BIT(chan->channel) | | |
| 740 | − BIT(chan->channel2)) << | |
| 741 | − AT91_SAMA5D2_COR_DIFF_OFFSET; | |
| 742 | − else | |
| 743 | − cor &= ~(BIT(chan->channel) << | |
| 744 | − AT91_SAMA5D2_COR_DIFF_OFFSET); | |
| 745 | − | |
| 746 | − at91_adc_writel(st, AT91_SAMA5D2_COR, cor); | |
| 747 | − } | |
| 748 | − | |
| 749 | − if (state) { | |
| 750 | − at91_adc_writel(st, AT91_SAMA5D2_CHER, | |
| 751 | − BIT(chan->channel)); | |
| 752 | − /* enable irq only if not using DMA */ | |
| 753 | − if (!st->dma_st.dma_chan) { | |
| 754 | − at91_adc_writel(st, AT91_SAMA5D2_IER, | |
| 755 | − BIT(chan->channel)); | |
| 756 | − } | |
| 757 | − } else { | |
| 758 | − /* disable irq only if not using DMA */ | |
| 759 | − if (!st->dma_st.dma_chan) { | |
| 760 | − at91_adc_writel(st, AT91_SAMA5D2_IDR, | |
| 761 | − BIT(chan->channel)); | |
| 762 | − } | |
| 763 | − at91_adc_writel(st, AT91_SAMA5D2_CHDR, | |
| 764 | − BIT(chan->channel)); | |
| 765 | − } | |
| 766 | − } | |
| 767 | − | |
| 768 | 741 | return 0; |
| 769 | 742 | } |
| 770 | 743 | |
| @@ -781,6 +754,7 @@ static int at91_adc_reenable_trigger(struct iio_trigger *trig) · 10 unmodified lines | ||
| 781 | 754 | |
| 782 | 755 | /* Needed to ACK the DRDY interruption */ |
| 783 | 756 | at91_adc_readl(st, AT91_SAMA5D2_LCDR); |
| 757 | + | |
| 784 | 758 | return 0; |
| 785 | 759 | } |
| 786 | 760 | |
| @@ -888,18 +862,37 @@ static int at91_adc_dma_start(struct iio_dev *indio_dev) · 101 unmodified lines | ||
| 888 | 862 | return 0; |
| 889 | 863 | } |
| 890 | 864 | |
| 891 | −static int at91_adc_buffer_postenable(struct iio_dev *indio_dev) | |
| 865 | +static bool at91_adc_buffer_check_use_irq(struct iio_dev *indio, | |
| 866 | + struct at91_adc_state *st) | |
| 867 | +{ | |
| 868 | + /* if using DMA, we do not use our own IRQ (we use DMA-controller) */ | |
| 869 | + if (st->dma_st.dma_chan) | |
| 870 | + return false; | |
| 871 | + /* if the trigger is not ours, then it has its own IRQ */ | |
| 872 | + if (iio_trigger_validate_own_device(indio->trig, indio)) | |
| 873 | + return false; | |
| 874 | + return true; | |
| 875 | +} | |
| 876 | + | |
| 877 | +static bool at91_adc_current_chan_is_touch(struct iio_dev *indio_dev) | |
| 878 | +{ | |
| 879 | + struct at91_adc_state *st = iio_priv(indio_dev); | |
| 880 | + | |
| 881 | + return !!bitmap_subset(indio_dev->active_scan_mask, | |
| 882 | + &st->touch_st.channels_bitmask, | |
| 883 | + AT91_SAMA5D2_MAX_CHAN_IDX + 1); | |
| 884 | +} | |
| 885 | + | |
| 886 | +static int at91_adc_buffer_preenable(struct iio_dev *indio_dev) | |
| 892 | 887 | { |
| 893 | 888 | int ret; |
| 889 | + u8 bit; | |
| 894 | 890 | struct at91_adc_state *st = iio_priv(indio_dev); |
| 895 | 891 | |
| 896 | 892 | /* check if we are enabling triggered buffer or the touchscreen */ |
| 897 | − if (bitmap_subset(indio_dev->active_scan_mask, | |
| 898 | − &st->touch_st.channels_bitmask, | |
| 899 | − AT91_SAMA5D2_MAX_CHAN_IDX + 1)) { | |
| 900 | − /* touchscreen enabling */ | |
| 893 | + if (at91_adc_current_chan_is_touch(indio_dev)) | |
| 901 | 894 | return at91_adc_configure_touch(st, true); |
| 902 | − } | |
| 895 | + | |
| 903 | 896 | /* if we are not in triggered mode, we cannot enable the buffer. */ |
| 904 | 897 | if (!(indio_dev->currentmode & INDIO_ALL_TRIGGERED_MODES)) |
| 905 | 898 | return -EINVAL; |
| @@ -911,41 +904,65 @@ static int at91_adc_buffer_postenable(struct iio_dev *indio_dev) · 5 unmodified lines | ||
| 911 | 904 | return ret; |
| 912 | 905 | } |
| 913 | 906 | |
| 907 | + for_each_set_bit(bit, indio_dev->active_scan_mask, | |
| 908 | + indio_dev->num_channels) { | |
| 909 | + struct iio_chan_spec const *chan = | |
| 910 | + at91_adc_chan_get(indio_dev, bit); | |
| 911 | + u32 cor; | |
| 912 | + | |
| 913 | + if (!chan) | |
| 914 | + continue; | |
| 915 | + /* these channel types cannot be handled by this trigger */ | |
| 916 | + if (chan->type == IIO_POSITIONRELATIVE || | |
| 917 | + chan->type == IIO_PRESSURE) | |
| 918 | + continue; | |
| 919 | + | |
| 920 | + cor = at91_adc_readl(st, AT91_SAMA5D2_COR); | |
| 921 | + | |
| 922 | + if (chan->differential) | |
| 923 | + cor |= (BIT(chan->channel) | BIT(chan->channel2)) << | |
| 924 | + AT91_SAMA5D2_COR_DIFF_OFFSET; | |
| 925 | + else | |
| 926 | + cor &= ~(BIT(chan->channel) << | |
| 927 | + AT91_SAMA5D2_COR_DIFF_OFFSET); | |
| 928 | + | |
| 929 | + at91_adc_writel(st, AT91_SAMA5D2_COR, cor); | |
| 930 | + | |
| 931 | + at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel)); | |
| 932 | + } | |
| 933 | + | |
| 934 | + if (at91_adc_buffer_check_use_irq(indio_dev, st)) | |
| 935 | + at91_adc_writel(st, AT91_SAMA5D2_IER, AT91_SAMA5D2_IER_DRDY); | |
| 936 | + | |
| 937 | + return 0; | |
| 938 | +} | |
| 939 | + | |
| 940 | +static int at91_adc_buffer_postenable(struct iio_dev *indio_dev) | |
| 941 | +{ | |
| 942 | + if (at91_adc_current_chan_is_touch(indio_dev)) | |
| 943 | + return 0; | |
| 944 | + | |
| 914 | 945 | return iio_triggered_buffer_postenable(indio_dev); |
| 915 | 946 | } |
| 916 | 947 | |
| 917 | −static int at91_adc_buffer_predisable(struct iio_dev *indio_dev) | |
| 948 | +static int at91_adc_buffer_postdisable(struct iio_dev *indio_dev) | |
| 918 | 949 | { |
| 919 | 950 | struct at91_adc_state *st = iio_priv(indio_dev); |
| 920 | − int ret; | |
| 921 | 951 | u8 bit; |
| 922 | 952 | |
| 923 | 953 | /* check if we are disabling triggered buffer or the touchscreen */ |
| 924 | − if (bitmap_subset(indio_dev->active_scan_mask, | |
| 925 | − &st->touch_st.channels_bitmask, | |
| 926 | − AT91_SAMA5D2_MAX_CHAN_IDX + 1)) { | |
| 927 | − /* touchscreen disable */ | |
| 954 | + if (at91_adc_current_chan_is_touch(indio_dev)) | |
| 928 | 955 | return at91_adc_configure_touch(st, false); |
| 929 | − } | |
| 956 | + | |
| 930 | 957 | /* if we are not in triggered mode, nothing to do here */ |
| 931 | 958 | if (!(indio_dev->currentmode & INDIO_ALL_TRIGGERED_MODES)) |
| 932 | 959 | return -EINVAL; |
| 933 | 960 | |
| 934 | − /* continue with the triggered buffer */ | |
| 935 | − ret = iio_triggered_buffer_predisable(indio_dev); | |
| 936 | − if (ret < 0) | |
| 937 | − dev_err(&indio_dev->dev, "buffer predisable failed\n"); | |
| 938 | − | |
| 939 | − if (!st->dma_st.dma_chan) | |
| 940 | − return ret; | |
| 941 | − | |
| 942 | − /* if we are using DMA we must clear registers and end DMA */ | |
| 943 | − dmaengine_terminate_sync(st->dma_st.dma_chan); | |
| 944 | − | |
| 945 | 961 | /* |
| 946 | − * For each enabled channel we must read the last converted value | |
| 962 | + * For each enable channel we must disable it in hardware. | |
| 963 | + * In the case of DMA, we must read the last converted value | |
| 947 | 964 | * to clear EOC status and not get a possible interrupt later. |
| 948 | − * This value is being read by DMA from LCDR anyway | |
| 965 | + * This value is being read by DMA from LCDR anyway, so it's not lost. | |
| 949 | 966 | */ |
| 950 | 967 | for_each_set_bit(bit, indio_dev->active_scan_mask, |
| 951 | 968 | indio_dev->num_channels) { |
| @@ -958,16 +975,37 @@ static int at91_adc_buffer_predisable(struct iio_dev *indio_dev) · 6 unmodified lines | ||
| 958 | 975 | if (chan->type == IIO_POSITIONRELATIVE || |
| 959 | 976 | chan->type == IIO_PRESSURE) |
| 960 | 977 | continue; |
| 978 | + | |
| 979 | + at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel)); | |
| 980 | + | |
| 961 | 981 | if (st->dma_st.dma_chan) |
| 962 | 982 | at91_adc_readl(st, chan->address); |
| 963 | 983 | } |
| 964 | 984 | |
| 985 | + if (at91_adc_buffer_check_use_irq(indio_dev, st)) | |
| 986 | + at91_adc_writel(st, AT91_SAMA5D2_IDR, AT91_SAMA5D2_IER_DRDY); | |
| 987 | + | |
| 965 | 988 | /* read overflow register to clear possible overflow status */ |
| 966 | 989 | at91_adc_readl(st, AT91_SAMA5D2_OVER); |
| 967 | − return ret; | |
| 990 | + | |
| 991 | + /* if we are using DMA we must clear registers and end DMA */ | |
| 992 | + if (st->dma_st.dma_chan) | |
| 993 | + dmaengine_terminate_sync(st->dma_st.dma_chan); | |
| 994 | + | |
| 995 | + return 0; | |
| 996 | +} | |
| 997 | + | |
| 998 | +static int at91_adc_buffer_predisable(struct iio_dev *indio_dev) | |
| 999 | +{ | |
| 1000 | + if (at91_adc_current_chan_is_touch(indio_dev)) | |
| 1001 | + return 0; | |
| 1002 | + | |
| 1003 | + return iio_triggered_buffer_predisable(indio_dev); | |
| 968 | 1004 | } |
| 969 | 1005 | |
| 970 | 1006 | static const struct iio_buffer_setup_ops at91_buffer_setup_ops = { |
| 1007 | + .preenable = &at91_adc_buffer_preenable, | |
| 1008 | + .postdisable = &at91_adc_buffer_postdisable, | |
| 971 | 1009 | .postenable = &at91_adc_buffer_postenable, |
| 972 | 1010 | .predisable = &at91_adc_buffer_predisable, |
| 973 | 1011 | }; |
| @@ -1015,6 +1053,22 @@ static void at91_adc_trigger_handler_nodma(struct iio_dev *indio_dev, · 41 unmodified lines | ||
| 1015 | 1053 | int i = 0; |
| 1016 | 1054 | int val; |
| 1017 | 1055 | u8 bit; |
| 1056 | + u32 mask = at91_adc_active_scan_mask_to_reg(indio_dev); | |
| 1057 | + unsigned int timeout = 50; | |
| 1058 | + | |
| 1059 | + /* | |
| 1060 | + * Check if the conversion is ready. If not, wait a little bit, and | |
| 1061 | + * in case of timeout exit with an error. | |
| 1062 | + */ | |
| 1063 | + while ((at91_adc_readl(st, AT91_SAMA5D2_ISR) & mask) != mask && | |
| 1064 | + timeout) { | |
| 1065 | + usleep_range(50, 100); | |
| 1066 | + timeout--; | |
| 1067 | + } | |
| 1068 | + | |
| 1069 | + /* Cannot read data, not ready. Continue without reporting data */ | |
| 1070 | + if (!timeout) | |
| 1071 | + return; | |
| 1018 | 1072 | |
| 1019 | 1073 | for_each_set_bit(bit, indio_dev->active_scan_mask, |
| 1020 | 1074 | indio_dev->num_channels) { |
| @@ -1102,6 +1156,13 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) · 81 unmodified lines | ||
| 1102 | 1156 | struct iio_dev *indio_dev = pf->indio_dev; |
| 1103 | 1157 | struct at91_adc_state *st = iio_priv(indio_dev); |
| 1104 | 1158 | |
| 1159 | + /* | |
| 1160 | + * If it's not our trigger, start a conversion now, as we are | |
| 1161 | + * actually polling the trigger now. | |
| 1162 | + */ | |
| 1163 | + if (iio_trigger_validate_own_device(indio_dev->trig, indio_dev)) | |
| 1164 | + at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START); | |
| 1165 | + | |
| 1105 | 1166 | if (st->dma_st.dma_chan) |
| 1106 | 1167 | at91_adc_trigger_handler_dma(indio_dev); |
| 1107 | 1168 | else |
| @@ -1114,20 +1175,9 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) · 6 unmodified lines | ||
| 1114 | 1175 | |
| 1115 | 1176 | static int at91_adc_buffer_init(struct iio_dev *indio) |
| 1116 | 1177 | { |
| 1117 | − struct at91_adc_state *st = iio_priv(indio); | |
| 1118 | − | |
| 1119 | − if (st->selected_trig->hw_trig) { | |
| 1120 | − return devm_iio_triggered_buffer_setup(&indio->dev, indio, | |
| 1121 | − &iio_pollfunc_store_time, | |
| 1122 | − &at91_adc_trigger_handler, &at91_buffer_setup_ops); | |
| 1123 | − } | |
| 1124 | − /* | |
| 1125 | − * we need to prepare the buffer ops in case we will get | |
| 1126 | − * another buffer attached (like a callback buffer for the touchscreen) | |
| 1127 | − */ | |
| 1128 | − indio->setup_ops = &at91_buffer_setup_ops; | |
| 1129 | − | |
| 1130 | − return 0; | |
| 1178 | + return devm_iio_triggered_buffer_setup(&indio->dev, indio, | |
| 1179 | + &iio_pollfunc_store_time, | |
| 1180 | + &at91_adc_trigger_handler, &at91_buffer_setup_ops); | |
| 1131 | 1181 | } |
| 1132 | 1182 | |
| 1133 | 1183 | static unsigned at91_adc_startup_time(unsigned startup_time_min, |
| @@ -1281,7 +1331,8 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private) · 147 unmodified lines | ||
| 1281 | 1331 | status = at91_adc_readl(st, AT91_SAMA5D2_XPOSR); |
| 1282 | 1332 | status = at91_adc_readl(st, AT91_SAMA5D2_YPOSR); |
| 1283 | 1333 | status = at91_adc_readl(st, AT91_SAMA5D2_PRESSR); |
| 1284 | − } else if (iio_buffer_enabled(indio) && !st->dma_st.dma_chan) { | |
| 1334 | + } else if (iio_buffer_enabled(indio) && | |
| 1335 | + (status & AT91_SAMA5D2_IER_DRDY)) { | |
| 1285 | 1336 | /* triggered buffer without DMA */ |
| 1286 | 1337 | disable_irq_nosync(irq); |
| 1287 | 1338 | iio_trigger_poll(indio->trig); |
| @@ -1901,14 +1952,10 @@ static __maybe_unused int at91_adc_resume(struct device *dev) · 613 unmodified lines | ||
| 1901 | 1952 | return 0; |
| 1902 | 1953 | |
| 1903 | 1954 | /* check if we are enabling triggered buffer or the touchscreen */ |
| 1904 | − if (bitmap_subset(indio_dev->active_scan_mask, | |
| 1905 | − &st->touch_st.channels_bitmask, | |
| 1906 | − AT91_SAMA5D2_MAX_CHAN_IDX + 1)) { | |
| 1907 | − /* touchscreen enabling */ | |
| 1955 | + if (at91_adc_current_chan_is_touch(indio_dev)) | |
| 1908 | 1956 | return at91_adc_configure_touch(st, true); |
| 1909 | − } else { | |
| 1957 | + else | |
| 1910 | 1958 | return at91_adc_configure_trigger(st->trig, true); |
| 1911 | − } | |
| 1912 | 1959 | |
| 1913 | 1960 | /* not needed but more explicit */ |
| 1914 | 1961 | return 0; |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/delay.h> |
| 20 | 20 | #include <linux/sysfs.h> |
| 21 | 21 | #include <linux/of.h> |
| 22 | +#include <asm/unaligned.h> | |
| 22 | 23 | |
| 23 | 24 | #include <linux/iio/iio.h> |
| 24 | 25 | #include <linux/iio/sysfs.h> |
| @@ -117,11 +118,11 @@ static int mcp3422_read(struct mcp3422 *adc, int *value, u8 *config) · 92 unmodified lines | ||
| 117 | 118 | |
| 118 | 119 | if (sample_rate == MCP3422_SRATE_3) { |
| 119 | 120 | ret = i2c_master_recv(adc->i2c, buf, 4); |
| 120 | − temp = buf[0] << 16 | buf[1] << 8 | buf[2]; | |
| 121 | + temp = get_unaligned_be24(&buf[0]); | |
| 121 | 122 | *config = buf[3]; |
| 122 | 123 | } else { |
| 123 | 124 | ret = i2c_master_recv(adc->i2c, buf, 3); |
| 124 | − temp = buf[0] << 8 | buf[1]; | |
| 125 | + temp = get_unaligned_be16(&buf[0]); | |
| 125 | 126 | *config = buf[2]; |
| 126 | 127 | } |
| 127 | 128 | |
| @@ -22,6 +22,8 @@ · 21 unmodified lines | ||
| 22 | 22 | #include <linux/iio/triggered_buffer.h> |
| 23 | 23 | #include <linux/iio/sysfs.h> |
| 24 | 24 | |
| 25 | +#include <asm/unaligned.h> | |
| 26 | + | |
| 25 | 27 | /* Commands */ |
| 26 | 28 | #define ADS124S08_CMD_NOP 0x00 |
| 27 | 29 | #define ADS124S08_CMD_WAKEUP 0x02 |
| @@ -188,7 +190,6 @@ static int ads124s_read(struct iio_dev *indio_dev, unsigned int chan) · 160 unmodified lines | ||
| 188 | 190 | { |
| 189 | 191 | struct ads124s_private *priv = iio_priv(indio_dev); |
| 190 | 192 | int ret; |
| 191 | − u32 tmp; | |
| 192 | 193 | struct spi_transfer t[] = { |
| 193 | 194 | { |
| 194 | 195 | .tx_buf = &priv->data[0], |
| @@ -208,9 +209,7 @@ static int ads124s_read(struct iio_dev *indio_dev, unsigned int chan) · 13 unmodified lines | ||
| 208 | 209 | if (ret < 0) |
| 209 | 210 | return ret; |
| 210 | 211 | |
| 211 | − tmp = priv->data[2] << 16 | priv->data[3] << 8 | priv->data[4]; | |
| 212 | − | |
| 213 | − return tmp; | |
| 212 | + return get_unaligned_be24(&priv->data[2]); | |
| 214 | 213 | } |
| 215 | 214 | |
| 216 | 215 | static int ads124s_read_raw(struct iio_dev *indio_dev, |
| @@ -53,6 +53,8 @@ · 52 unmodified lines | ||
| 53 | 53 | #define ATLAS_REG_DO_CALIB_STATUS_PRESSURE BIT(0) |
| 54 | 54 | #define ATLAS_REG_DO_CALIB_STATUS_DO BIT(1) |
| 55 | 55 | |
| 56 | +#define ATLAS_REG_RTD_DATA 0x0e | |
| 57 | + | |
| 56 | 58 | #define ATLAS_REG_PH_TEMP_DATA 0x0e |
| 57 | 59 | #define ATLAS_REG_PH_DATA 0x16 |
| 58 | 60 | |
| @@ -72,12 +74,14 @@ · 13 unmodified lines | ||
| 72 | 74 | #define ATLAS_EC_INT_TIME_IN_MS 650 |
| 73 | 75 | #define ATLAS_ORP_INT_TIME_IN_MS 450 |
| 74 | 76 | #define ATLAS_DO_INT_TIME_IN_MS 450 |
| 77 | +#define ATLAS_RTD_INT_TIME_IN_MS 450 | |
| 75 | 78 | |
| 76 | 79 | enum { |
| 77 | 80 | ATLAS_PH_SM, |
| 78 | 81 | ATLAS_EC_SM, |
| 79 | 82 | ATLAS_ORP_SM, |
| 80 | 83 | ATLAS_DO_SM, |
| 84 | + ATLAS_RTD_SM, | |
| 81 | 85 | }; |
| 82 | 86 | |
| 83 | 87 | struct atlas_data { |
| @@ -206,6 +210,22 @@ static const struct iio_chan_spec atlas_do_channels[] = { · 122 unmodified lines | ||
| 206 | 210 | }, |
| 207 | 211 | }; |
| 208 | 212 | |
| 213 | +static const struct iio_chan_spec atlas_rtd_channels[] = { | |
| 214 | + { | |
| 215 | + .type = IIO_TEMP, | |
| 216 | + .address = ATLAS_REG_RTD_DATA, | |
| 217 | + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), | |
| 218 | + .scan_index = 0, | |
| 219 | + .scan_type = { | |
| 220 | + .sign = 's', | |
| 221 | + .realbits = 32, | |
| 222 | + .storagebits = 32, | |
| 223 | + .endianness = IIO_BE, | |
| 224 | + }, | |
| 225 | + }, | |
| 226 | + IIO_CHAN_SOFT_TIMESTAMP(1), | |
| 227 | +}; | |
| 228 | + | |
| 209 | 229 | static int atlas_check_ph_calibration(struct atlas_data *data) |
| 210 | 230 | { |
| 211 | 231 | struct device *dev = &data->client->dev; |
| @@ -350,6 +370,12 @@ static struct atlas_device atlas_devices[] = { · 138 unmodified lines | ||
| 350 | 370 | .calibration = &atlas_check_do_calibration, |
| 351 | 371 | .delay = ATLAS_DO_INT_TIME_IN_MS, |
| 352 | 372 | }, |
| 373 | + [ATLAS_RTD_SM] = { | |
| 374 | + .channels = atlas_rtd_channels, | |
| 375 | + .num_channels = 2, | |
| 376 | + .data_reg = ATLAS_REG_RTD_DATA, | |
| 377 | + .delay = ATLAS_RTD_INT_TIME_IN_MS, | |
| 378 | + }, | |
| 353 | 379 | }; |
| 354 | 380 | |
| 355 | 381 | static int atlas_set_powermode(struct atlas_data *data, int on) |
| @@ -477,6 +503,7 @@ static int atlas_read_raw(struct iio_dev *indio_dev, · 121 unmodified lines | ||
| 477 | 503 | struct atlas_data *data = iio_priv(indio_dev); |
| 478 | 504 | |
| 479 | 505 | switch (mask) { |
| 506 | + case IIO_CHAN_INFO_PROCESSED: | |
| 480 | 507 | case IIO_CHAN_INFO_RAW: { |
| 481 | 508 | int ret; |
| 482 | 509 | __be32 reg; |
| @@ -565,6 +592,7 @@ static const struct i2c_device_id atlas_id[] = { · 82 unmodified lines | ||
| 565 | 592 | { "atlas-ec-sm", ATLAS_EC_SM}, |
| 566 | 593 | { "atlas-orp-sm", ATLAS_ORP_SM}, |
| 567 | 594 | { "atlas-do-sm", ATLAS_DO_SM}, |
| 595 | + { "atlas-rtd-sm", ATLAS_RTD_SM}, | |
| 568 | 596 | {} |
| 569 | 597 | }; |
| 570 | 598 | MODULE_DEVICE_TABLE(i2c, atlas_id); |
| @@ -574,6 +602,7 @@ static const struct of_device_id atlas_dt_ids[] = { · 3 unmodified lines | ||
| 574 | 602 | { .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, }, |
| 575 | 603 | { .compatible = "atlas,orp-sm", .data = (void *)ATLAS_ORP_SM, }, |
| 576 | 604 | { .compatible = "atlas,do-sm", .data = (void *)ATLAS_DO_SM, }, |
| 605 | + { .compatible = "atlas,rtd-sm", .data = (void *)ATLAS_RTD_SM, }, | |
| 577 | 606 | { } |
| 578 | 607 | }; |
| 579 | 608 | MODULE_DEVICE_TABLE(of, atlas_dt_ids); |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | */ |
| 17 | 17 | |
| 18 | 18 | #include <linux/delay.h> |
| 19 | +#include <linux/gpio/consumer.h> | |
| 19 | 20 | #include <linux/i2c.h> |
| 20 | 21 | #include <linux/iio/iio.h> |
| 21 | 22 | #include <linux/iio/buffer.h> |
| @@ -36,6 +37,7 @@ · 14 unmodified lines | ||
| 36 | 37 | #define CCS811_ERR 0xE0 |
| 37 | 38 | /* Used to transition from boot to application mode */ |
| 38 | 39 | #define CCS811_APP_START 0xF4 |
| 40 | +#define CCS811_SW_RESET 0xFF | |
| 39 | 41 | |
| 40 | 42 | /* Status register flags */ |
| 41 | 43 | #define CCS811_STATUS_ERROR BIT(0) |
| @@ -74,6 +76,7 @@ struct ccs811_data { · 32 unmodified lines | ||
| 74 | 76 | struct mutex lock; /* Protect readings */ |
| 75 | 77 | struct ccs811_reading buffer; |
| 76 | 78 | struct iio_trigger *drdy_trig; |
| 79 | + struct gpio_desc *wakeup_gpio; | |
| 77 | 80 | bool drdy_trig_on; |
| 78 | 81 | }; |
| 79 | 82 | |
| @@ -166,10 +169,25 @@ static int ccs811_setup(struct i2c_client *client) · 86 unmodified lines | ||
| 166 | 169 | CCS811_MODE_IAQ_1SEC); |
| 167 | 170 | } |
| 168 | 171 | |
| 172 | +static void ccs811_set_wakeup(struct ccs811_data *data, bool enable) | |
| 173 | +{ | |
| 174 | + if (!data->wakeup_gpio) | |
| 175 | + return; | |
| 176 | + | |
| 177 | + gpiod_set_value(data->wakeup_gpio, enable); | |
| 178 | + | |
| 179 | + if (enable) | |
| 180 | + usleep_range(50, 60); | |
| 181 | + else | |
| 182 | + usleep_range(20, 30); | |
| 183 | +} | |
| 184 | + | |
| 169 | 185 | static int ccs811_get_measurement(struct ccs811_data *data) |
| 170 | 186 | { |
| 171 | 187 | int ret, tries = 11; |
| 172 | 188 | |
| 189 | + ccs811_set_wakeup(data, true); | |
| 190 | + | |
| 173 | 191 | /* Maximum waiting time: 1s, as measurements are made every second */ |
| 174 | 192 | while (tries-- > 0) { |
| 175 | 193 | ret = i2c_smbus_read_byte_data(data->client, CCS811_STATUS); |
| @@ -183,9 +201,12 @@ static int ccs811_get_measurement(struct ccs811_data *data) · 7 unmodified lines | ||
| 183 | 201 | if (!(ret & CCS811_STATUS_DATA_READY)) |
| 184 | 202 | return -EIO; |
| 185 | 203 | |
| 186 | − return i2c_smbus_read_i2c_block_data(data->client, | |
| 204 | + ret = i2c_smbus_read_i2c_block_data(data->client, | |
| 187 | 205 | CCS811_ALG_RESULT_DATA, 8, |
| 188 | 206 | (char *)&data->buffer); |
| 207 | + ccs811_set_wakeup(data, false); | |
| 208 | + | |
| 209 | + return ret; | |
| 189 | 210 | } |
| 190 | 211 | |
| 191 | 212 | static int ccs811_read_raw(struct iio_dev *indio_dev, |
| @@ -336,6 +357,45 @@ static irqreturn_t ccs811_data_rdy_trigger_poll(int irq, void *private) · 144 unmodified lines | ||
| 336 | 357 | return IRQ_HANDLED; |
| 337 | 358 | } |
| 338 | 359 | |
| 360 | +static int ccs811_reset(struct i2c_client *client) | |
| 361 | +{ | |
| 362 | + struct gpio_desc *reset_gpio; | |
| 363 | + int ret; | |
| 364 | + | |
| 365 | + reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", | |
| 366 | + GPIOD_OUT_LOW); | |
| 367 | + if (IS_ERR(reset_gpio)) | |
| 368 | + return PTR_ERR(reset_gpio); | |
| 369 | + | |
| 370 | + /* Try to reset using nRESET pin if available else do SW reset */ | |
| 371 | + if (reset_gpio) { | |
| 372 | + gpiod_set_value(reset_gpio, 1); | |
| 373 | + usleep_range(20, 30); | |
| 374 | + gpiod_set_value(reset_gpio, 0); | |
| 375 | + } else { | |
| 376 | + /* | |
| 377 | + * As per the datasheet, this sequence of values needs to be | |
| 378 | + * written to the SW_RESET register for triggering the soft | |
| 379 | + * reset in the device and placing it in boot mode. | |
| 380 | + */ | |
| 381 | + static const u8 reset_seq[] = { | |
| 382 | + 0x11, 0xE5, 0x72, 0x8A, | |
| 383 | + }; | |
| 384 | + | |
| 385 | + ret = i2c_smbus_write_i2c_block_data(client, CCS811_SW_RESET, | |
| 386 | + sizeof(reset_seq), reset_seq); | |
| 387 | + if (ret < 0) { | |
| 388 | + dev_err(&client->dev, "Failed to reset sensor\n"); | |
| 389 | + return ret; | |
| 390 | + } | |
| 391 | + } | |
| 392 | + | |
| 393 | + /* tSTART delay required after reset */ | |
| 394 | + usleep_range(1000, 2000); | |
| 395 | + | |
| 396 | + return 0; | |
| 397 | +} | |
| 398 | + | |
| 339 | 399 | static int ccs811_probe(struct i2c_client *client, |
| 340 | 400 | const struct i2c_device_id *id) |
| 341 | 401 | { |
| @@ -348,36 +408,59 @@ static int ccs811_probe(struct i2c_client *client, · 6 unmodified lines | ||
| 348 | 408 | | I2C_FUNC_SMBUS_READ_I2C_BLOCK)) |
| 349 | 409 | return -EOPNOTSUPP; |
| 350 | 410 | |
| 411 | + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
| 412 | + if (!indio_dev) | |
| 413 | + return -ENOMEM; | |
| 414 | + | |
| 415 | + data = iio_priv(indio_dev); | |
| 416 | + i2c_set_clientdata(client, indio_dev); | |
| 417 | + data->client = client; | |
| 418 | + | |
| 419 | + data->wakeup_gpio = devm_gpiod_get_optional(&client->dev, "wakeup", | |
| 420 | + GPIOD_OUT_HIGH); | |
| 421 | + if (IS_ERR(data->wakeup_gpio)) | |
| 422 | + return PTR_ERR(data->wakeup_gpio); | |
| 423 | + | |
| 424 | + ccs811_set_wakeup(data, true); | |
| 425 | + | |
| 426 | + ret = ccs811_reset(client); | |
| 427 | + if (ret) { | |
| 428 | + ccs811_set_wakeup(data, false); | |
| 429 | + return ret; | |
| 430 | + } | |
| 431 | + | |
| 351 | 432 | /* Check hardware id (should be 0x81 for this family of devices) */ |
| 352 | 433 | ret = i2c_smbus_read_byte_data(client, CCS811_HW_ID); |
| 353 | − if (ret < 0) | |
| 434 | + if (ret < 0) { | |
| 435 | + ccs811_set_wakeup(data, false); | |
| 354 | 436 | return ret; |
| 437 | + } | |
| 355 | 438 | |
| 356 | 439 | if (ret != CCS811_HW_ID_VALUE) { |
| 357 | 440 | dev_err(&client->dev, "hardware id doesn't match CCS81x\n"); |
| 441 | + ccs811_set_wakeup(data, false); | |
| 358 | 442 | return -ENODEV; |
| 359 | 443 | } |
| 360 | 444 | |
| 361 | 445 | ret = i2c_smbus_read_byte_data(client, CCS811_HW_VERSION); |
| 362 | − if (ret < 0) | |
| 446 | + if (ret < 0) { | |
| 447 | + ccs811_set_wakeup(data, false); | |
| 363 | 448 | return ret; |
| 449 | + } | |
| 364 | 450 | |
| 365 | 451 | if ((ret & CCS811_HW_VERSION_MASK) != CCS811_HW_VERSION_VALUE) { |
| 366 | 452 | dev_err(&client->dev, "no CCS811 sensor\n"); |
| 453 | + ccs811_set_wakeup(data, false); | |
| 367 | 454 | return -ENODEV; |
| 368 | 455 | } |
| 369 | 456 | |
| 370 | − indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
| 371 | − if (!indio_dev) | |
| 372 | − return -ENOMEM; | |
| 373 | − | |
| 374 | 457 | ret = ccs811_setup(client); |
| 375 | − if (ret < 0) | |
| 458 | + if (ret < 0) { | |
| 459 | + ccs811_set_wakeup(data, false); | |
| 376 | 460 | return ret; |
| 461 | + } | |
| 377 | 462 | |
| 378 | − data = iio_priv(indio_dev); | |
| 379 | − i2c_set_clientdata(client, indio_dev); | |
| 380 | − data->client = client; | |
| 463 | + ccs811_set_wakeup(data, false); | |
| 381 | 464 | |
| 382 | 465 | mutex_init(&data->lock); |
| 383 | 466 | |
| @@ -466,9 +549,16 @@ static const struct i2c_device_id ccs811_id[] = { · 82 unmodified lines | ||
| 466 | 549 | }; |
| 467 | 550 | MODULE_DEVICE_TABLE(i2c, ccs811_id); |
| 468 | 551 | |
| 552 | +static const struct of_device_id ccs811_dt_ids[] = { | |
| 553 | + { .compatible = "ams,ccs811" }, | |
| 554 | + { } | |
| 555 | +}; | |
| 556 | +MODULE_DEVICE_TABLE(of, ccs811_dt_ids); | |
| 557 | + | |
| 469 | 558 | static struct i2c_driver ccs811_driver = { |
| 470 | 559 | .driver = { |
| 471 | 560 | .name = "ccs811", |
| 561 | + .of_match_table = ccs811_dt_ids, | |
| 472 | 562 | }, |
| 473 | 563 | .probe = ccs811_probe, |
| 474 | 564 | .remove = ccs811_remove, |
| @@ -13,6 +13,8 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/hid-sensor-hub.h> |
| 14 | 14 | #include <linux/iio/iio.h> |
| 15 | 15 | #include <linux/iio/trigger.h> |
| 16 | +#include <linux/iio/triggered_buffer.h> | |
| 17 | +#include <linux/iio/trigger_consumer.h> | |
| 16 | 18 | #include <linux/iio/buffer.h> |
| 17 | 19 | #include <linux/iio/sysfs.h> |
| 18 | 20 | #include "hid-sensor-trigger.h" |
| @@ -222,7 +224,8 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, · 203 unmodified lines | ||
| 222 | 224 | return hid_sensor_power_state(iio_trigger_get_drvdata(trig), state); |
| 223 | 225 | } |
| 224 | 226 | |
| 225 | −void hid_sensor_remove_trigger(struct hid_sensor_common *attrb) | |
| 227 | +void hid_sensor_remove_trigger(struct iio_dev *indio_dev, | |
| 228 | + struct hid_sensor_common *attrb) | |
| 226 | 229 | { |
| 227 | 230 | if (atomic_read(&attrb->runtime_pm_enable)) |
| 228 | 231 | pm_runtime_disable(&attrb->pdev->dev); |
| @@ -233,6 +236,7 @@ void hid_sensor_remove_trigger(struct hid_sensor_common *attrb) · 4 unmodified lines | ||
| 233 | 236 | cancel_work_sync(&attrb->work); |
| 234 | 237 | iio_trigger_unregister(attrb->trigger); |
| 235 | 238 | iio_trigger_free(attrb->trigger); |
| 239 | + iio_triggered_buffer_cleanup(indio_dev); | |
| 236 | 240 | } |
| 237 | 241 | EXPORT_SYMBOL(hid_sensor_remove_trigger); |
| 238 | 242 | |
| @@ -246,11 +250,18 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, · 7 unmodified lines | ||
| 246 | 250 | int ret; |
| 247 | 251 | struct iio_trigger *trig; |
| 248 | 252 | |
| 253 | + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, | |
| 254 | + NULL, NULL); | |
| 255 | + if (ret) { | |
| 256 | + dev_err(&indio_dev->dev, "Triggered Buffer Setup Failed\n"); | |
| 257 | + return ret; | |
| 258 | + } | |
| 259 | + | |
| 249 | 260 | trig = iio_trigger_alloc("%s-dev%d", name, indio_dev->id); |
| 250 | 261 | if (trig == NULL) { |
| 251 | 262 | dev_err(&indio_dev->dev, "Trigger Allocate Failed\n"); |
| 252 | 263 | ret = -ENOMEM; |
| 253 | − goto error_ret; | |
| 264 | + goto error_triggered_buffer_cleanup; | |
| 254 | 265 | } |
| 255 | 266 | |
| 256 | 267 | trig->dev.parent = indio_dev->dev.parent; |
| @@ -284,7 +295,8 @@ error_unreg_trigger: · 27 unmodified lines | ||
| 284 | 295 | iio_trigger_unregister(trig); |
| 285 | 296 | error_free_trig: |
| 286 | 297 | iio_trigger_free(trig); |
| 287 | −error_ret: | |
| 298 | +error_triggered_buffer_cleanup: | |
| 299 | + iio_triggered_buffer_cleanup(indio_dev); | |
| 288 | 300 | return ret; |
| 289 | 301 | } |
| 290 | 302 | EXPORT_SYMBOL(hid_sensor_setup_trigger); |
| @@ -13,7 +13,8 @@ extern const struct dev_pm_ops hid_sensor_pm_ops; · 12 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, |
| 15 | 15 | struct hid_sensor_common *attrb); |
| 16 | −void hid_sensor_remove_trigger(struct hid_sensor_common *attrb); | |
| 16 | +void hid_sensor_remove_trigger(struct iio_dev *indio_dev, | |
| 17 | + struct hid_sensor_common *attrb); | |
| 17 | 18 | int hid_sensor_power_state(struct hid_sensor_common *st, bool state); |
| 18 | 19 | |
| 19 | 20 | #endif |
| @@ -20,11 +20,6 @@ · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | #include "st_sensors_core.h" |
| 22 | 22 | |
| 23 | −static inline u32 st_sensors_get_unaligned_le24(const u8 *p) | |
| 24 | −{ | |
| 25 | − return (s32)((p[0] | p[1] << 8 | p[2] << 16) << 8) >> 8; | |
| 26 | −} | |
| 27 | − | |
| 28 | 23 | int st_sensors_write_data_with_mask(struct iio_dev *indio_dev, |
| 29 | 24 | u8 reg_addr, u8 mask, u8 data) |
| 30 | 25 | { |
| @@ -543,7 +538,7 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev, · 512 unmodified lines | ||
| 543 | 538 | else if (byte_for_channel == 2) |
| 544 | 539 | *data = (s16)get_unaligned_le16(outdata); |
| 545 | 540 | else if (byte_for_channel == 3) |
| 546 | − *data = (s32)st_sensors_get_unaligned_le24(outdata); | |
| 541 | + *data = (s32)sign_extend32(get_unaligned_le24(outdata), 23); | |
| 547 | 542 | |
| 548 | 543 | st_sensors_free_memory: |
| 549 | 544 | kfree(outdata); |
| @@ -279,12 +279,12 @@ config LTC1660 · 278 unmodified lines | ||
| 279 | 279 | module will be called ltc1660. |
| 280 | 280 | |
| 281 | 281 | config LTC2632 |
| 282 | − tristate "Linear Technology LTC2632-12/10/8 and LTC2636-12/10/8 DAC spi driver" | |
| 282 | + tristate "Linear Technology LTC2632-12/10/8 and similar DAC spi driver" | |
| 283 | 283 | depends on SPI |
| 284 | 284 | help |
| 285 | 285 | Say yes here to build support for Linear Technology |
| 286 | − LTC2632-12, LTC2632-10, LTC2632-8, LTC2636-12, LTC2636-10 and | |
| 287 | − LTC2636-8 converters (DAC). | |
| 286 | + LTC2632, LTC2634 and LTC2636 DAC resolution 12/10/8 bit | |
| 287 | + low 0-2.5V and high 0-4.096V range converters. | |
| 288 | 288 | |
| 289 | 289 | To compile this driver as a module, choose M here: the |
| 290 | 290 | module will be called ltc2632. |
| @@ -21,6 +21,8 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/iio/iio.h> |
| 22 | 22 | #include <linux/iio/sysfs.h> |
| 23 | 23 | |
| 24 | +#include <asm/unaligned.h> | |
| 25 | + | |
| 24 | 26 | #define MODE_PWRDWN_1k 0x1 |
| 25 | 27 | #define MODE_PWRDWN_100k 0x2 |
| 26 | 28 | #define MODE_PWRDWN_TRISTATE 0x3 |
| @@ -302,9 +304,7 @@ static int ad5660_write(struct ad5446_state *st, unsigned val) · 275 unmodified lines | ||
| 302 | 304 | struct spi_device *spi = to_spi_device(st->dev); |
| 303 | 305 | uint8_t data[3]; |
| 304 | 306 | |
| 305 | − data[0] = (val >> 16) & 0xFF; | |
| 306 | − data[1] = (val >> 8) & 0xFF; | |
| 307 | − data[2] = val & 0xFF; | |
| 307 | + put_unaligned_be24(val, &data[0]); | |
| 308 | 308 | |
| 309 | 309 | return spi_write(spi, data, sizeof(data)); |
| 310 | 310 | } |
| @@ -98,7 +98,7 @@ static int ad5592r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value) · 97 unmodified lines | ||
| 98 | 98 | return 0; |
| 99 | 99 | } |
| 100 | 100 | |
| 101 | −static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value) | |
| 101 | +static int ad5592r_gpio_read(struct ad5592r_state *st, u8 *value) | |
| 102 | 102 | { |
| 103 | 103 | int ret; |
| 104 | 104 | |
| @@ -121,7 +121,7 @@ static const struct ad5592r_rw_ops ad5592r_rw_ops = { · 16 unmodified lines | ||
| 121 | 121 | .read_adc = ad5592r_read_adc, |
| 122 | 122 | .reg_write = ad5592r_reg_write, |
| 123 | 123 | .reg_read = ad5592r_reg_read, |
| 124 | − .gpio_read = ad5593r_gpio_read, | |
| 124 | + .gpio_read = ad5592r_gpio_read, | |
| 125 | 125 | }; |
| 126 | 126 | |
| 127 | 127 | static int ad5592r_spi_probe(struct spi_device *spi) |
| @@ -134,5 +134,5 @@ static struct i2c_driver ad5593r_driver = { · 133 unmodified lines | ||
| 134 | 134 | module_i2c_driver(ad5593r_driver); |
| 135 | 135 | |
| 136 | 136 | MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>"); |
| 137 | −MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters"); | |
| 137 | +MODULE_DESCRIPTION("Analog Devices AD5593R multi-channel converters"); | |
| 138 | 138 | MODULE_LICENSE("GPL v2"); |
| @@ -18,6 +18,8 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/iio/iio.h> |
| 19 | 19 | #include <linux/iio/sysfs.h> |
| 20 | 20 | |
| 21 | +#include <asm/unaligned.h> | |
| 22 | + | |
| 21 | 23 | #include "ad5624r.h" |
| 22 | 24 | |
| 23 | 25 | static int ad5624r_spi_write(struct spi_device *spi, |
| @@ -35,11 +37,9 @@ static int ad5624r_spi_write(struct spi_device *spi, · 11 unmodified lines | ||
| 35 | 37 | * for the AD5664R, AD5644R, and AD5624R, respectively. |
| 36 | 38 | */ |
| 37 | 39 | data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << shift); |
| 38 | − msg[0] = data >> 16; | |
| 39 | − msg[1] = data >> 8; | |
| 40 | − msg[2] = data; | |
| 40 | + put_unaligned_be24(data, &msg[0]); | |
| 41 | 41 | |
| 42 | − return spi_write(spi, msg, 3); | |
| 42 | + return spi_write(spi, msg, sizeof(msg)); | |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | 45 | static int ad5624r_read_raw(struct iio_dev *indio_dev, |
| @@ -12,6 +12,8 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/iio/iio.h> |
| 13 | 13 | #include <linux/regulator/consumer.h> |
| 14 | 14 | |
| 15 | +#include <asm/unaligned.h> | |
| 16 | + | |
| 15 | 17 | #define LTC2632_CMD_WRITE_INPUT_N 0x0 |
| 16 | 18 | #define LTC2632_CMD_UPDATE_DAC_N 0x1 |
| 17 | 19 | #define LTC2632_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 |
| @@ -24,6 +26,7 @@ · 6 unmodified lines | ||
| 24 | 26 | /** |
| 25 | 27 | * struct ltc2632_chip_info - chip specific information |
| 26 | 28 | * @channels: channel spec for the DAC |
| 29 | + * @num_channels: DAC channel count of the chip | |
| 27 | 30 | * @vref_mv: internal reference voltage |
| 28 | 31 | */ |
| 29 | 32 | struct ltc2632_chip_info { |
| @@ -53,6 +56,12 @@ enum ltc2632_supported_device_ids { · 23 unmodified lines | ||
| 53 | 56 | ID_LTC2632H12, |
| 54 | 57 | ID_LTC2632H10, |
| 55 | 58 | ID_LTC2632H8, |
| 59 | + ID_LTC2634L12, | |
| 60 | + ID_LTC2634L10, | |
| 61 | + ID_LTC2634L8, | |
| 62 | + ID_LTC2634H12, | |
| 63 | + ID_LTC2634H10, | |
| 64 | + ID_LTC2634H8, | |
| 56 | 65 | ID_LTC2636L12, |
| 57 | 66 | ID_LTC2636L10, |
| 58 | 67 | ID_LTC2636L8, |
| @@ -75,9 +84,7 @@ static int ltc2632_spi_write(struct spi_device *spi, · 16 unmodified lines | ||
| 75 | 84 | * 10-, 8-bit input code followed by 4, 6, or 8 don't care bits. |
| 76 | 85 | */ |
| 77 | 86 | data = (cmd << 20) | (addr << 16) | (val << shift); |
| 78 | − msg[0] = data >> 16; | |
| 79 | − msg[1] = data >> 8; | |
| 80 | − msg[2] = data; | |
| 87 | + put_unaligned_be24(data, &msg[0]); | |
| 81 | 88 | |
| 82 | 89 | return spi_write(spi, msg, sizeof(msg)); |
| 83 | 90 | } |
| @@ -235,6 +242,36 @@ static const struct ltc2632_chip_info ltc2632_chip_info_tbl[] = { · 151 unmodified lines | ||
| 235 | 242 | .num_channels = 2, |
| 236 | 243 | .vref_mv = 4096, |
| 237 | 244 | }, |
| 245 | + [ID_LTC2634L12] = { | |
| 246 | + .channels = ltc2632x12_channels, | |
| 247 | + .num_channels = 4, | |
| 248 | + .vref_mv = 2500, | |
| 249 | + }, | |
| 250 | + [ID_LTC2634L10] = { | |
| 251 | + .channels = ltc2632x10_channels, | |
| 252 | + .num_channels = 4, | |
| 253 | + .vref_mv = 2500, | |
| 254 | + }, | |
| 255 | + [ID_LTC2634L8] = { | |
| 256 | + .channels = ltc2632x8_channels, | |
| 257 | + .num_channels = 4, | |
| 258 | + .vref_mv = 2500, | |
| 259 | + }, | |
| 260 | + [ID_LTC2634H12] = { | |
| 261 | + .channels = ltc2632x12_channels, | |
| 262 | + .num_channels = 4, | |
| 263 | + .vref_mv = 4096, | |
| 264 | + }, | |
| 265 | + [ID_LTC2634H10] = { | |
| 266 | + .channels = ltc2632x10_channels, | |
| 267 | + .num_channels = 4, | |
| 268 | + .vref_mv = 4096, | |
| 269 | + }, | |
| 270 | + [ID_LTC2634H8] = { | |
| 271 | + .channels = ltc2632x8_channels, | |
| 272 | + .num_channels = 4, | |
| 273 | + .vref_mv = 4096, | |
| 274 | + }, | |
| 238 | 275 | [ID_LTC2636L12] = { |
| 239 | 276 | .channels = ltc2632x12_channels, |
| 240 | 277 | .num_channels = 8, |
| @@ -356,6 +393,12 @@ static const struct spi_device_id ltc2632_id[] = { · 115 unmodified lines | ||
| 356 | 393 | { "ltc2632-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H12] }, |
| 357 | 394 | { "ltc2632-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H10] }, |
| 358 | 395 | { "ltc2632-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H8] }, |
| 396 | + { "ltc2634-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634L12] }, | |
| 397 | + { "ltc2634-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634L10] }, | |
| 398 | + { "ltc2634-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634L8] }, | |
| 399 | + { "ltc2634-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634H12] }, | |
| 400 | + { "ltc2634-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634H10] }, | |
| 401 | + { "ltc2634-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634H8] }, | |
| 359 | 402 | { "ltc2636-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L12] }, |
| 360 | 403 | { "ltc2636-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L10] }, |
| 361 | 404 | { "ltc2636-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L8] }, |
| @@ -385,6 +428,24 @@ static const struct of_device_id ltc2632_of_match[] = { · 23 unmodified lines | ||
| 385 | 428 | }, { |
| 386 | 429 | .compatible = "lltc,ltc2632-h8", |
| 387 | 430 | .data = <c2632_chip_info_tbl[ID_LTC2632H8] |
| 431 | + }, { | |
| 432 | + .compatible = "lltc,ltc2634-l12", | |
| 433 | + .data = <c2632_chip_info_tbl[ID_LTC2634L12] | |
| 434 | + }, { | |
| 435 | + .compatible = "lltc,ltc2634-l10", | |
| 436 | + .data = <c2632_chip_info_tbl[ID_LTC2634L10] | |
| 437 | + }, { | |
| 438 | + .compatible = "lltc,ltc2634-l8", | |
| 439 | + .data = <c2632_chip_info_tbl[ID_LTC2634L8] | |
| 440 | + }, { | |
| 441 | + .compatible = "lltc,ltc2634-h12", | |
| 442 | + .data = <c2632_chip_info_tbl[ID_LTC2634H12] | |
| 443 | + }, { | |
| 444 | + .compatible = "lltc,ltc2634-h10", | |
| 445 | + .data = <c2632_chip_info_tbl[ID_LTC2634H10] | |
| 446 | + }, { | |
| 447 | + .compatible = "lltc,ltc2634-h8", | |
| 448 | + .data = <c2632_chip_info_tbl[ID_LTC2634H8] | |
| 388 | 449 | }, { |
| 389 | 450 | .compatible = "lltc,ltc2636-l12", |
| 390 | 451 | .data = <c2632_chip_info_tbl[ID_LTC2636L12] |
| @@ -12,6 +12,8 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | #include <linux/iio/iio.h> |
| 14 | 14 | |
| 15 | +#include <asm/unaligned.h> | |
| 16 | + | |
| 15 | 17 | #define ADIS16130_CON 0x0 |
| 16 | 18 | #define ADIS16130_CON_RD (1 << 6) |
| 17 | 19 | #define ADIS16130_IOP 0x1 |
| @@ -59,7 +61,7 @@ static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val) · 41 unmodified lines | ||
| 59 | 61 | |
| 60 | 62 | ret = spi_sync_transfer(st->us, &xfer, 1); |
| 61 | 63 | if (ret == 0) |
| 62 | − *val = (st->buf[1] << 16) | (st->buf[2] << 8) | st->buf[3]; | |
| 64 | + *val = get_unaligned_be24(&st->buf[1]); | |
| 63 | 65 | mutex_unlock(&st->buf_lock); |
| 64 | 66 | |
| 65 | 67 | return ret; |
| @@ -148,16 +148,14 @@ DEFINE_DEBUGFS_ATTRIBUTE(adis16136_flash_count_fops, · 147 unmodified lines | ||
| 148 | 148 | static int adis16136_debugfs_init(struct iio_dev *indio_dev) |
| 149 | 149 | { |
| 150 | 150 | struct adis16136 *adis16136 = iio_priv(indio_dev); |
| 151 | + struct dentry *d = iio_get_debugfs_dentry(indio_dev); | |
| 151 | 152 | |
| 152 | 153 | debugfs_create_file_unsafe("serial_number", 0400, |
| 153 | − indio_dev->debugfs_dentry, adis16136, | |
| 154 | − &adis16136_serial_fops); | |
| 154 | + d, adis16136, &adis16136_serial_fops); | |
| 155 | 155 | debugfs_create_file_unsafe("product_id", 0400, |
| 156 | − indio_dev->debugfs_dentry, | |
| 157 | − adis16136, &adis16136_product_id_fops); | |
| 156 | + d, adis16136, &adis16136_product_id_fops); | |
| 158 | 157 | debugfs_create_file_unsafe("flash_count", 0400, |
| 159 | − indio_dev->debugfs_dentry, | |
| 160 | − adis16136, &adis16136_flash_count_fops); | |
| 158 | + d, adis16136, &adis16136_flash_count_fops); | |
| 161 | 159 | |
| 162 | 160 | return 0; |
| 163 | 161 | } |
| @@ -14,8 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/iio/iio.h> |
| 15 | 15 | #include <linux/iio/sysfs.h> |
| 16 | 16 | #include <linux/iio/buffer.h> |
| 17 | −#include <linux/iio/trigger_consumer.h> | |
| 18 | −#include <linux/iio/triggered_buffer.h> | |
| 19 | 17 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 20 | 18 | |
| 21 | 19 | enum gyro_3d_channel { |
| @@ -326,18 +324,13 @@ static int hid_gyro_3d_probe(struct platform_device *pdev) · 304 unmodified lines | ||
| 326 | 324 | indio_dev->name = name; |
| 327 | 325 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 328 | 326 | |
| 329 | − ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, | |
| 330 | − NULL, NULL); | |
| 331 | − if (ret) { | |
| 332 | − dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | |
| 333 | − goto error_free_dev_mem; | |
| 334 | − } | |
| 335 | 327 | atomic_set(&gyro_state->common_attributes.data_ready, 0); |
| 328 | + | |
| 336 | 329 | ret = hid_sensor_setup_trigger(indio_dev, name, |
| 337 | 330 | &gyro_state->common_attributes); |
| 338 | 331 | if (ret < 0) { |
| 339 | 332 | dev_err(&pdev->dev, "trigger setup failed\n"); |
| 340 | − goto error_unreg_buffer_funcs; | |
| 333 | + goto error_free_dev_mem; | |
| 341 | 334 | } |
| 342 | 335 | |
| 343 | 336 | ret = iio_device_register(indio_dev); |
| @@ -361,9 +354,7 @@ static int hid_gyro_3d_probe(struct platform_device *pdev) · 17 unmodified lines | ||
| 361 | 354 | error_iio_unreg: |
| 362 | 355 | iio_device_unregister(indio_dev); |
| 363 | 356 | error_remove_trigger: |
| 364 | − hid_sensor_remove_trigger(&gyro_state->common_attributes); | |
| 365 | −error_unreg_buffer_funcs: | |
| 366 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 357 | + hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes); | |
| 367 | 358 | error_free_dev_mem: |
| 368 | 359 | kfree(indio_dev->channels); |
| 369 | 360 | return ret; |
| @@ -378,8 +369,7 @@ static int hid_gyro_3d_remove(struct platform_device *pdev) · 8 unmodified lines | ||
| 378 | 369 | |
| 379 | 370 | sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D); |
| 380 | 371 | iio_device_unregister(indio_dev); |
| 381 | − hid_sensor_remove_trigger(&gyro_state->common_attributes); | |
| 382 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 372 | + hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes); | |
| 383 | 373 | kfree(indio_dev->channels); |
| 384 | 374 | |
| 385 | 375 | return 0; |
| @@ -23,6 +23,8 @@ · 22 unmodified lines | ||
| 23 | 23 | #include <linux/iio/triggered_buffer.h> |
| 24 | 24 | #include <linux/iio/trigger_consumer.h> |
| 25 | 25 | |
| 26 | +#include <asm/unaligned.h> | |
| 27 | + | |
| 26 | 28 | #include "afe440x.h" |
| 27 | 29 | |
| 28 | 30 | #define AFE4403_DRIVER_NAME "afe4403" |
| @@ -220,13 +222,11 @@ static int afe4403_read(struct afe4403_data *afe, unsigned int reg, u32 *val) · 191 unmodified lines | ||
| 220 | 222 | if (ret) |
| 221 | 223 | return ret; |
| 222 | 224 | |
| 223 | − ret = spi_write_then_read(afe->spi, ®, 1, rx, 3); | |
| 225 | + ret = spi_write_then_read(afe->spi, ®, 1, rx, sizeof(rx)); | |
| 224 | 226 | if (ret) |
| 225 | 227 | return ret; |
| 226 | 228 | |
| 227 | − *val = (rx[0] << 16) | | |
| 228 | − (rx[1] << 8) | | |
| 229 | − (rx[2]); | |
| 229 | + *val = get_unaligned_be24(&rx[0]); | |
| 230 | 230 | |
| 231 | 231 | /* Disable reading from the device */ |
| 232 | 232 | tx[3] = AFE440X_CONTROL0_WRITE; |
| @@ -322,13 +322,11 @@ static irqreturn_t afe4403_trigger_handler(int irq, void *private) · 89 unmodified lines | ||
| 322 | 322 | indio_dev->masklength) { |
| 323 | 323 | ret = spi_write_then_read(afe->spi, |
| 324 | 324 | &afe4403_channel_values[bit], 1, |
| 325 | − rx, 3); | |
| 325 | + rx, sizeof(rx)); | |
| 326 | 326 | if (ret) |
| 327 | 327 | goto err; |
| 328 | 328 | |
| 329 | − buffer[i++] = (rx[0] << 16) | | |
| 330 | − (rx[1] << 8) | | |
| 331 | − (rx[2]); | |
| 329 | + buffer[i++] = get_unaligned_be24(&rx[0]); | |
| 332 | 330 | } |
| 333 | 331 | |
| 334 | 332 | /* Disable reading from the device */ |
| @@ -7,8 +7,6 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/hid-sensor-hub.h> |
| 8 | 8 | #include <linux/iio/buffer.h> |
| 9 | 9 | #include <linux/iio/iio.h> |
| 10 | −#include <linux/iio/triggered_buffer.h> | |
| 11 | −#include <linux/iio/trigger_consumer.h> | |
| 12 | 10 | #include <linux/module.h> |
| 13 | 11 | #include <linux/platform_device.h> |
| 14 | 12 | |
| @@ -233,12 +231,8 @@ static int hid_humidity_probe(struct platform_device *pdev) · 218 unmodified lines | ||
| 233 | 231 | indio_dev->name = name; |
| 234 | 232 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 235 | 233 | |
| 236 | − ret = devm_iio_triggered_buffer_setup(&pdev->dev, indio_dev, | |
| 237 | − &iio_pollfunc_store_time, NULL, NULL); | |
| 238 | − if (ret) | |
| 239 | − return ret; | |
| 240 | − | |
| 241 | 234 | atomic_set(&humid_st->common_attributes.data_ready, 0); |
| 235 | + | |
| 242 | 236 | ret = hid_sensor_setup_trigger(indio_dev, name, |
| 243 | 237 | &humid_st->common_attributes); |
| 244 | 238 | if (ret) |
| @@ -261,7 +255,7 @@ static int hid_humidity_probe(struct platform_device *pdev) · 16 unmodified lines | ||
| 261 | 255 | error_remove_callback: |
| 262 | 256 | sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY); |
| 263 | 257 | error_remove_trigger: |
| 264 | − hid_sensor_remove_trigger(&humid_st->common_attributes); | |
| 258 | + hid_sensor_remove_trigger(indio_dev, &humid_st->common_attributes); | |
| 265 | 259 | return ret; |
| 266 | 260 | } |
| 267 | 261 | |
| @@ -274,7 +268,7 @@ static int hid_humidity_remove(struct platform_device *pdev) · 6 unmodified lines | ||
| 274 | 268 | |
| 275 | 269 | iio_device_unregister(indio_dev); |
| 276 | 270 | sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY); |
| 277 | − hid_sensor_remove_trigger(&humid_st->common_attributes); | |
| 271 | + hid_sensor_remove_trigger(indio_dev, &humid_st->common_attributes); | |
| 278 | 272 | |
| 279 | 273 | return 0; |
| 280 | 274 | } |
| @@ -29,6 +29,19 @@ config ADIS16460 · 28 unmodified lines | ||
| 29 | 29 | To compile this driver as a module, choose M here: the module will be |
| 30 | 30 | called adis16460. |
| 31 | 31 | |
| 32 | +config ADIS16475 | |
| 33 | + tristate "Analog Devices ADIS16475 and similar IMU driver" | |
| 34 | + depends on SPI | |
| 35 | + select IIO_ADIS_LIB | |
| 36 | + select IIO_ADIS_LIB_BUFFER if IIO_BUFFER | |
| 37 | + help | |
| 38 | + Say yes here to build support for Analog Devices ADIS16470, ADIS16475, | |
| 39 | + ADIS16477, ADIS16465, ADIS16467, ADIS16500, ADIS16505, ADIS16507 inertial | |
| 40 | + sensors. | |
| 41 | + | |
| 42 | + To compile this driver as a module, choose M here: the module will be | |
| 43 | + called adis16475. | |
| 44 | + | |
| 32 | 45 | config ADIS16480 |
| 33 | 46 | tristate "Analog Devices ADIS16480 and similar IMU driver" |
| 34 | 47 | depends on SPI |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | # When adding new entries keep the list in alphabetical order |
| 7 | 7 | obj-$(CONFIG_ADIS16400) += adis16400.o |
| 8 | 8 | obj-$(CONFIG_ADIS16460) += adis16460.o |
| 9 | +obj-$(CONFIG_ADIS16475) += adis16475.o | |
| 9 | 10 | obj-$(CONFIG_ADIS16480) += adis16480.o |
| 10 | 11 | |
| 11 | 12 | adis_lib-y += adis.o |
| @@ -223,6 +223,31 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, · 222 unmodified lines | ||
| 223 | 223 | return ret; |
| 224 | 224 | } |
| 225 | 225 | EXPORT_SYMBOL_GPL(__adis_read_reg); |
| 226 | +/** | |
| 227 | + * __adis_update_bits_base() - ADIS Update bits function - Unlocked version | |
| 228 | + * @adis: The adis device | |
| 229 | + * @reg: The address of the lower of the two registers | |
| 230 | + * @mask: Bitmask to change | |
| 231 | + * @val: Value to be written | |
| 232 | + * @size: Size of the register to update | |
| 233 | + * | |
| 234 | + * Updates the desired bits of @reg in accordance with @mask and @val. | |
| 235 | + */ | |
| 236 | +int __adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask, | |
| 237 | + const u32 val, u8 size) | |
| 238 | +{ | |
| 239 | + int ret; | |
| 240 | + u32 __val; | |
| 241 | + | |
| 242 | + ret = __adis_read_reg(adis, reg, &__val, size); | |
| 243 | + if (ret) | |
| 244 | + return ret; | |
| 245 | + | |
| 246 | + __val = (__val & ~mask) | (val & mask); | |
| 247 | + | |
| 248 | + return __adis_write_reg(adis, reg, __val, size); | |
| 249 | +} | |
| 250 | +EXPORT_SYMBOL_GPL(__adis_update_bits_base); | |
| 226 | 251 | |
| 227 | 252 | #ifdef CONFIG_DEBUG_FS |
| 228 | 253 | |
| @@ -281,18 +281,16 @@ DEFINE_DEBUGFS_ATTRIBUTE(adis16400_flash_count_fops, · 280 unmodified lines | ||
| 281 | 281 | static int adis16400_debugfs_init(struct iio_dev *indio_dev) |
| 282 | 282 | { |
| 283 | 283 | struct adis16400_state *st = iio_priv(indio_dev); |
| 284 | + struct dentry *d = iio_get_debugfs_dentry(indio_dev); | |
| 284 | 285 | |
| 285 | 286 | if (st->variant->flags & ADIS16400_HAS_SERIAL_NUMBER) |
| 286 | 287 | debugfs_create_file_unsafe("serial_number", 0400, |
| 287 | − indio_dev->debugfs_dentry, st, | |
| 288 | − &adis16400_serial_number_fops); | |
| 288 | + d, st, &adis16400_serial_number_fops); | |
| 289 | 289 | if (st->variant->flags & ADIS16400_HAS_PROD_ID) |
| 290 | 290 | debugfs_create_file_unsafe("product_id", 0400, |
| 291 | − indio_dev->debugfs_dentry, st, | |
| 292 | − &adis16400_product_id_fops); | |
| 291 | + d, st, &adis16400_product_id_fops); | |
| 293 | 292 | debugfs_create_file_unsafe("flash_count", 0400, |
| 294 | − indio_dev->debugfs_dentry, st, | |
| 295 | − &adis16400_flash_count_fops); | |
| 293 | + d, st, &adis16400_flash_count_fops); | |
| 296 | 294 | |
| 297 | 295 | return 0; |
| 298 | 296 | } |
| @@ -1195,7 +1193,7 @@ static int adis16400_probe(struct spi_device *spi) · 896 unmodified lines | ||
| 1195 | 1193 | indio_dev->available_scan_masks = st->avail_scan_mask; |
| 1196 | 1194 | st->adis.burst = &adis16400_burst; |
| 1197 | 1195 | if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) |
| 1198 | − st->adis.burst->extra_len = sizeof(u16); | |
| 1196 | + st->adis.burst_extra_len = sizeof(u16); | |
| 1199 | 1197 | } |
| 1200 | 1198 | |
| 1201 | 1199 | adis16400_data = &st->variant->adis_data; |
| @@ -129,16 +129,14 @@ DEFINE_DEBUGFS_ATTRIBUTE(adis16460_flash_count_fops, · 128 unmodified lines | ||
| 129 | 129 | static int adis16460_debugfs_init(struct iio_dev *indio_dev) |
| 130 | 130 | { |
| 131 | 131 | struct adis16460 *adis16460 = iio_priv(indio_dev); |
| 132 | + struct dentry *d = iio_get_debugfs_dentry(indio_dev); | |
| 132 | 133 | |
| 133 | 134 | debugfs_create_file_unsafe("serial_number", 0400, |
| 134 | − indio_dev->debugfs_dentry, adis16460, | |
| 135 | − &adis16460_serial_number_fops); | |
| 135 | + d, adis16460, &adis16460_serial_number_fops); | |
| 136 | 136 | debugfs_create_file_unsafe("product_id", 0400, |
| 137 | − indio_dev->debugfs_dentry, adis16460, | |
| 138 | − &adis16460_product_id_fops); | |
| 137 | + d, adis16460, &adis16460_product_id_fops); | |
| 139 | 138 | debugfs_create_file_unsafe("flash_count", 0400, |
| 140 | − indio_dev->debugfs_dentry, adis16460, | |
| 141 | − &adis16460_flash_count_fops); | |
| 139 | + d, adis16460, &adis16460_flash_count_fops); | |
| 142 | 140 | |
| 143 | 141 | return 0; |
| 144 | 142 | } |
| @@ -0,0 +1,1338 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | +/* | |
| 3 | + * ADIS16475 IMU driver | |
| 4 | + * | |
| 5 | + * Copyright 2019 Analog Devices Inc. | |
| 6 | + */ | |
| 7 | +#include <linux/bitfield.h> | |
| 8 | +#include <linux/bitops.h> | |
| 9 | +#include <linux/clk.h> | |
| 10 | +#include <linux/debugfs.h> | |
| 11 | +#include <linux/delay.h> | |
| 12 | +#include <linux/device.h> | |
| 13 | +#include <linux/kernel.h> | |
| 14 | +#include <linux/iio/buffer.h> | |
| 15 | +#include <linux/iio/iio.h> | |
| 16 | +#include <linux/iio/imu/adis.h> | |
| 17 | +#include <linux/iio/sysfs.h> | |
| 18 | +#include <linux/iio/trigger_consumer.h> | |
| 19 | +#include <linux/irq.h> | |
| 20 | +#include <linux/module.h> | |
| 21 | +#include <linux/mod_devicetable.h> | |
| 22 | +#include <linux/property.h> | |
| 23 | +#include <linux/spi/spi.h> | |
| 24 | + | |
| 25 | +#define ADIS16475_REG_DIAG_STAT 0x02 | |
| 26 | +#define ADIS16475_REG_X_GYRO_L 0x04 | |
| 27 | +#define ADIS16475_REG_Y_GYRO_L 0x08 | |
| 28 | +#define ADIS16475_REG_Z_GYRO_L 0x0C | |
| 29 | +#define ADIS16475_REG_X_ACCEL_L 0x10 | |
| 30 | +#define ADIS16475_REG_Y_ACCEL_L 0x14 | |
| 31 | +#define ADIS16475_REG_Z_ACCEL_L 0x18 | |
| 32 | +#define ADIS16475_REG_TEMP_OUT 0x1c | |
| 33 | +#define ADIS16475_REG_X_GYRO_BIAS_L 0x40 | |
| 34 | +#define ADIS16475_REG_Y_GYRO_BIAS_L 0x44 | |
| 35 | +#define ADIS16475_REG_Z_GYRO_BIAS_L 0x48 | |
| 36 | +#define ADIS16475_REG_X_ACCEL_BIAS_L 0x4c | |
| 37 | +#define ADIS16475_REG_Y_ACCEL_BIAS_L 0x50 | |
| 38 | +#define ADIS16475_REG_Z_ACCEL_BIAS_L 0x54 | |
| 39 | +#define ADIS16475_REG_FILT_CTRL 0x5c | |
| 40 | +#define ADIS16475_FILT_CTRL_MASK GENMASK(2, 0) | |
| 41 | +#define ADIS16475_FILT_CTRL(x) FIELD_PREP(ADIS16475_FILT_CTRL_MASK, x) | |
| 42 | +#define ADIS16475_REG_MSG_CTRL 0x60 | |
| 43 | +#define ADIS16475_MSG_CTRL_DR_POL_MASK BIT(0) | |
| 44 | +#define ADIS16475_MSG_CTRL_DR_POL(x) \ | |
| 45 | + FIELD_PREP(ADIS16475_MSG_CTRL_DR_POL_MASK, x) | |
| 46 | +#define ADIS16475_SYNC_MODE_MASK GENMASK(4, 2) | |
| 47 | +#define ADIS16475_SYNC_MODE(x) FIELD_PREP(ADIS16475_SYNC_MODE_MASK, x) | |
| 48 | +#define ADIS16475_REG_UP_SCALE 0x62 | |
| 49 | +#define ADIS16475_REG_DEC_RATE 0x64 | |
| 50 | +#define ADIS16475_REG_GLOB_CMD 0x68 | |
| 51 | +#define ADIS16475_REG_FIRM_REV 0x6c | |
| 52 | +#define ADIS16475_REG_FIRM_DM 0x6e | |
| 53 | +#define ADIS16475_REG_FIRM_Y 0x70 | |
| 54 | +#define ADIS16475_REG_PROD_ID 0x72 | |
| 55 | +#define ADIS16475_REG_SERIAL_NUM 0x74 | |
| 56 | +#define ADIS16475_REG_FLASH_CNT 0x7c | |
| 57 | +#define ADIS16500_BURST32_MASK BIT(9) | |
| 58 | +#define ADIS16500_BURST32(x) FIELD_PREP(ADIS16500_BURST32_MASK, x) | |
| 59 | +/* number of data elements in burst mode */ | |
| 60 | +#define ADIS16475_BURST32_MAX_DATA 32 | |
| 61 | +#define ADIS16475_BURST_MAX_DATA 20 | |
| 62 | +#define ADIS16475_MAX_SCAN_DATA 20 | |
| 63 | +/* spi max speed in brust mode */ | |
| 64 | +#define ADIS16475_BURST_MAX_SPEED 1000000 | |
| 65 | +#define ADIS16475_LSB_DEC_MASK BIT(0) | |
| 66 | +#define ADIS16475_LSB_FIR_MASK BIT(1) | |
| 67 | + | |
| 68 | +enum { | |
| 69 | + ADIS16475_SYNC_DIRECT = 1, | |
| 70 | + ADIS16475_SYNC_SCALED, | |
| 71 | + ADIS16475_SYNC_OUTPUT, | |
| 72 | + ADIS16475_SYNC_PULSE = 5, | |
| 73 | +}; | |
| 74 | + | |
| 75 | +struct adis16475_sync { | |
| 76 | + u16 sync_mode; | |
| 77 | + u16 min_rate; | |
| 78 | + u16 max_rate; | |
| 79 | +}; | |
| 80 | + | |
| 81 | +struct adis16475_chip_info { | |
| 82 | + const struct iio_chan_spec *channels; | |
| 83 | + const struct adis16475_sync *sync; | |
| 84 | + const struct adis_data adis_data; | |
| 85 | + const char *name; | |
| 86 | + u32 num_channels; | |
| 87 | + u32 gyro_max_val; | |
| 88 | + u32 gyro_max_scale; | |
| 89 | + u32 accel_max_val; | |
| 90 | + u32 accel_max_scale; | |
| 91 | + u32 temp_scale; | |
| 92 | + u32 int_clk; | |
| 93 | + u16 max_dec; | |
| 94 | + u8 num_sync; | |
| 95 | + bool has_burst32; | |
| 96 | +}; | |
| 97 | + | |
| 98 | +struct adis16475 { | |
| 99 | + const struct adis16475_chip_info *info; | |
| 100 | + struct adis adis; | |
| 101 | + u32 clk_freq; | |
| 102 | + bool burst32; | |
| 103 | + unsigned long lsb_flag; | |
| 104 | + /* Alignment needed for the timestamp */ | |
| 105 | + __be16 data[ADIS16475_MAX_SCAN_DATA] __aligned(8); | |
| 106 | +}; | |
| 107 | + | |
| 108 | +enum { | |
| 109 | + ADIS16475_SCAN_GYRO_X, | |
| 110 | + ADIS16475_SCAN_GYRO_Y, | |
| 111 | + ADIS16475_SCAN_GYRO_Z, | |
| 112 | + ADIS16475_SCAN_ACCEL_X, | |
| 113 | + ADIS16475_SCAN_ACCEL_Y, | |
| 114 | + ADIS16475_SCAN_ACCEL_Z, | |
| 115 | + ADIS16475_SCAN_TEMP, | |
| 116 | + ADIS16475_SCAN_DIAG_S_FLAGS, | |
| 117 | + ADIS16475_SCAN_CRC_FAILURE, | |
| 118 | +}; | |
| 119 | + | |
| 120 | +#ifdef CONFIG_DEBUG_FS | |
| 121 | +static ssize_t adis16475_show_firmware_revision(struct file *file, | |
| 122 | + char __user *userbuf, | |
| 123 | + size_t count, loff_t *ppos) | |
| 124 | +{ | |
| 125 | + struct adis16475 *st = file->private_data; | |
| 126 | + char buf[7]; | |
| 127 | + size_t len; | |
| 128 | + u16 rev; | |
| 129 | + int ret; | |
| 130 | + | |
| 131 | + ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIRM_REV, &rev); | |
| 132 | + if (ret) | |
| 133 | + return ret; | |
| 134 | + | |
| 135 | + len = scnprintf(buf, sizeof(buf), "%x.%x\n", rev >> 8, rev & 0xff); | |
| 136 | + | |
| 137 | + return simple_read_from_buffer(userbuf, count, ppos, buf, len); | |
| 138 | +} | |
| 139 | + | |
| 140 | +static const struct file_operations adis16475_firmware_revision_fops = { | |
| 141 | + .open = simple_open, | |
| 142 | + .read = adis16475_show_firmware_revision, | |
| 143 | + .llseek = default_llseek, | |
| 144 | + .owner = THIS_MODULE, | |
| 145 | +}; | |
| 146 | + | |
| 147 | +static ssize_t adis16475_show_firmware_date(struct file *file, | |
| 148 | + char __user *userbuf, | |
| 149 | + size_t count, loff_t *ppos) | |
| 150 | +{ | |
| 151 | + struct adis16475 *st = file->private_data; | |
| 152 | + u16 md, year; | |
| 153 | + char buf[12]; | |
| 154 | + size_t len; | |
| 155 | + int ret; | |
| 156 | + | |
| 157 | + ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIRM_Y, &year); | |
| 158 | + if (ret) | |
| 159 | + return ret; | |
| 160 | + | |
| 161 | + ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIRM_DM, &md); | |
| 162 | + if (ret) | |
| 163 | + return ret; | |
| 164 | + | |
| 165 | + len = snprintf(buf, sizeof(buf), "%.2x-%.2x-%.4x\n", md >> 8, md & 0xff, | |
| 166 | + year); | |
| 167 | + | |
| 168 | + return simple_read_from_buffer(userbuf, count, ppos, buf, len); | |
| 169 | +} | |
| 170 | + | |
| 171 | +static const struct file_operations adis16475_firmware_date_fops = { | |
| 172 | + .open = simple_open, | |
| 173 | + .read = adis16475_show_firmware_date, | |
| 174 | + .llseek = default_llseek, | |
| 175 | + .owner = THIS_MODULE, | |
| 176 | +}; | |
| 177 | + | |
| 178 | +static int adis16475_show_serial_number(void *arg, u64 *val) | |
| 179 | +{ | |
| 180 | + struct adis16475 *st = arg; | |
| 181 | + u16 serial; | |
| 182 | + int ret; | |
| 183 | + | |
| 184 | + ret = adis_read_reg_16(&st->adis, ADIS16475_REG_SERIAL_NUM, &serial); | |
| 185 | + if (ret) | |
| 186 | + return ret; | |
| 187 | + | |
| 188 | + *val = serial; | |
| 189 | + | |
| 190 | + return 0; | |
| 191 | +} | |
| 192 | +DEFINE_DEBUGFS_ATTRIBUTE(adis16475_serial_number_fops, | |
| 193 | + adis16475_show_serial_number, NULL, "0x%.4llx\n"); | |
| 194 | + | |
| 195 | +static int adis16475_show_product_id(void *arg, u64 *val) | |
| 196 | +{ | |
| 197 | + struct adis16475 *st = arg; | |
| 198 | + u16 prod_id; | |
| 199 | + int ret; | |
| 200 | + | |
| 201 | + ret = adis_read_reg_16(&st->adis, ADIS16475_REG_PROD_ID, &prod_id); | |
| 202 | + if (ret) | |
| 203 | + return ret; | |
| 204 | + | |
| 205 | + *val = prod_id; | |
| 206 | + | |
| 207 | + return 0; | |
| 208 | +} | |
| 209 | +DEFINE_DEBUGFS_ATTRIBUTE(adis16475_product_id_fops, | |
| 210 | + adis16475_show_product_id, NULL, "%llu\n"); | |
| 211 | + | |
| 212 | +static int adis16475_show_flash_count(void *arg, u64 *val) | |
| 213 | +{ | |
| 214 | + struct adis16475 *st = arg; | |
| 215 | + u32 flash_count; | |
| 216 | + int ret; | |
| 217 | + | |
| 218 | + ret = adis_read_reg_32(&st->adis, ADIS16475_REG_FLASH_CNT, | |
| 219 | + &flash_count); | |
| 220 | + if (ret) | |
| 221 | + return ret; | |
| 222 | + | |
| 223 | + *val = flash_count; | |
| 224 | + | |
| 225 | + return 0; | |
| 226 | +} | |
| 227 | +DEFINE_DEBUGFS_ATTRIBUTE(adis16475_flash_count_fops, | |
| 228 | + adis16475_show_flash_count, NULL, "%lld\n"); | |
| 229 | + | |
| 230 | +static void adis16475_debugfs_init(struct iio_dev *indio_dev) | |
| 231 | +{ | |
| 232 | + struct adis16475 *st = iio_priv(indio_dev); | |
| 233 | + struct dentry *d = iio_get_debugfs_dentry(indio_dev); | |
| 234 | + | |
| 235 | + debugfs_create_file_unsafe("serial_number", 0400, | |
| 236 | + d, st, &adis16475_serial_number_fops); | |
| 237 | + debugfs_create_file_unsafe("product_id", 0400, | |
| 238 | + d, st, &adis16475_product_id_fops); | |
| 239 | + debugfs_create_file_unsafe("flash_count", 0400, | |
| 240 | + d, st, &adis16475_flash_count_fops); | |
| 241 | + debugfs_create_file("firmware_revision", 0400, | |
| 242 | + d, st, &adis16475_firmware_revision_fops); | |
| 243 | + debugfs_create_file("firmware_date", 0400, d, | |
| 244 | + st, &adis16475_firmware_date_fops); | |
| 245 | +} | |
| 246 | +#else | |
| 247 | +static void adis16475_debugfs_init(struct iio_dev *indio_dev) | |
| 248 | +{ | |
| 249 | +} | |
| 250 | +#endif | |
| 251 | + | |
| 252 | +static int adis16475_get_freq(struct adis16475 *st, u32 *freq) | |
| 253 | +{ | |
| 254 | + int ret; | |
| 255 | + u16 dec; | |
| 256 | + | |
| 257 | + ret = adis_read_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, &dec); | |
| 258 | + if (ret) | |
| 259 | + return -EINVAL; | |
| 260 | + | |
| 261 | + *freq = DIV_ROUND_CLOSEST(st->clk_freq, dec + 1); | |
| 262 | + | |
| 263 | + return 0; | |
| 264 | +} | |
| 265 | + | |
| 266 | +static int adis16475_set_freq(struct adis16475 *st, const u32 freq) | |
| 267 | +{ | |
| 268 | + u16 dec; | |
| 269 | + int ret; | |
| 270 | + | |
| 271 | + if (!freq) | |
| 272 | + return -EINVAL; | |
| 273 | + | |
| 274 | + dec = DIV_ROUND_CLOSEST(st->clk_freq, freq); | |
| 275 | + | |
| 276 | + if (dec) | |
| 277 | + dec--; | |
| 278 | + | |
| 279 | + if (dec > st->info->max_dec) | |
| 280 | + dec = st->info->max_dec; | |
| 281 | + | |
| 282 | + ret = adis_write_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, dec); | |
| 283 | + if (ret) | |
| 284 | + return ret; | |
| 285 | + | |
| 286 | + /* | |
| 287 | + * If decimation is used, then gyro and accel data will have meaningful | |
| 288 | + * bits on the LSB registers. This info is used on the trigger handler. | |
| 289 | + */ | |
| 290 | + assign_bit(ADIS16475_LSB_DEC_MASK, &st->lsb_flag, dec); | |
| 291 | + | |
| 292 | + return 0; | |
| 293 | +} | |
| 294 | + | |
| 295 | +/* The values are approximated. */ | |
| 296 | +static const u32 adis16475_3db_freqs[] = { | |
| 297 | + [0] = 720, /* Filter disabled, full BW (~720Hz) */ | |
| 298 | + [1] = 360, | |
| 299 | + [2] = 164, | |
| 300 | + [3] = 80, | |
| 301 | + [4] = 40, | |
| 302 | + [5] = 20, | |
| 303 | + [6] = 10, | |
| 304 | +}; | |
| 305 | + | |
| 306 | +static int adis16475_get_filter(struct adis16475 *st, u32 *filter) | |
| 307 | +{ | |
| 308 | + u16 filter_sz; | |
| 309 | + int ret; | |
| 310 | + const int mask = ADIS16475_FILT_CTRL_MASK; | |
| 311 | + | |
| 312 | + ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FILT_CTRL, &filter_sz); | |
| 313 | + if (ret) | |
| 314 | + return ret; | |
| 315 | + | |
| 316 | + *filter = adis16475_3db_freqs[filter_sz & mask]; | |
| 317 | + | |
| 318 | + return 0; | |
| 319 | +} | |
| 320 | + | |
| 321 | +static int adis16475_set_filter(struct adis16475 *st, const u32 filter) | |
| 322 | +{ | |
| 323 | + int i = ARRAY_SIZE(adis16475_3db_freqs); | |
| 324 | + int ret; | |
| 325 | + | |
| 326 | + while (--i) { | |
| 327 | + if (adis16475_3db_freqs[i] >= filter) | |
| 328 | + break; | |
| 329 | + } | |
| 330 | + | |
| 331 | + ret = adis_write_reg_16(&st->adis, ADIS16475_REG_FILT_CTRL, | |
| 332 | + ADIS16475_FILT_CTRL(i)); | |
| 333 | + if (ret) | |
| 334 | + return ret; | |
| 335 | + | |
| 336 | + /* | |
| 337 | + * If FIR is used, then gyro and accel data will have meaningful | |
| 338 | + * bits on the LSB registers. This info is used on the trigger handler. | |
| 339 | + */ | |
| 340 | + assign_bit(ADIS16475_LSB_FIR_MASK, &st->lsb_flag, i); | |
| 341 | + | |
| 342 | + return 0; | |
| 343 | +} | |
| 344 | + | |
| 345 | +static const u32 adis16475_calib_regs[] = { | |
| 346 | + [ADIS16475_SCAN_GYRO_X] = ADIS16475_REG_X_GYRO_BIAS_L, | |
| 347 | + [ADIS16475_SCAN_GYRO_Y] = ADIS16475_REG_Y_GYRO_BIAS_L, | |
| 348 | + [ADIS16475_SCAN_GYRO_Z] = ADIS16475_REG_Z_GYRO_BIAS_L, | |
| 349 | + [ADIS16475_SCAN_ACCEL_X] = ADIS16475_REG_X_ACCEL_BIAS_L, | |
| 350 | + [ADIS16475_SCAN_ACCEL_Y] = ADIS16475_REG_Y_ACCEL_BIAS_L, | |
| 351 | + [ADIS16475_SCAN_ACCEL_Z] = ADIS16475_REG_Z_ACCEL_BIAS_L, | |
| 352 | +}; | |
| 353 | + | |
| 354 | +static int adis16475_read_raw(struct iio_dev *indio_dev, | |
| 355 | + const struct iio_chan_spec *chan, | |
| 356 | + int *val, int *val2, long info) | |
| 357 | +{ | |
| 358 | + struct adis16475 *st = iio_priv(indio_dev); | |
| 359 | + int ret; | |
| 360 | + u32 tmp; | |
| 361 | + | |
| 362 | + switch (info) { | |
| 363 | + case IIO_CHAN_INFO_RAW: | |
| 364 | + return adis_single_conversion(indio_dev, chan, 0, val); | |
| 365 | + case IIO_CHAN_INFO_SCALE: | |
| 366 | + switch (chan->type) { | |
| 367 | + case IIO_ANGL_VEL: | |
| 368 | + *val = st->info->gyro_max_val; | |
| 369 | + *val2 = st->info->gyro_max_scale; | |
| 370 | + return IIO_VAL_FRACTIONAL; | |
| 371 | + case IIO_ACCEL: | |
| 372 | + *val = st->info->accel_max_val; | |
| 373 | + *val2 = st->info->accel_max_scale; | |
| 374 | + return IIO_VAL_FRACTIONAL; | |
| 375 | + case IIO_TEMP: | |
| 376 | + *val = st->info->temp_scale; | |
| 377 | + return IIO_VAL_INT; | |
| 378 | + default: | |
| 379 | + return -EINVAL; | |
| 380 | + } | |
| 381 | + case IIO_CHAN_INFO_CALIBBIAS: | |
| 382 | + ret = adis_read_reg_32(&st->adis, | |
| 383 | + adis16475_calib_regs[chan->scan_index], | |
| 384 | + val); | |
| 385 | + if (ret) | |
| 386 | + return ret; | |
| 387 | + | |
| 388 | + return IIO_VAL_INT; | |
| 389 | + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: | |
| 390 | + ret = adis16475_get_filter(st, val); | |
| 391 | + if (ret) | |
| 392 | + return ret; | |
| 393 | + | |
| 394 | + return IIO_VAL_INT; | |
| 395 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 396 | + ret = adis16475_get_freq(st, &tmp); | |
| 397 | + if (ret) | |
| 398 | + return ret; | |
| 399 | + | |
| 400 | + *val = tmp / 1000; | |
| 401 | + *val2 = (tmp % 1000) * 1000; | |
| 402 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 403 | + default: | |
| 404 | + return -EINVAL; | |
| 405 | + } | |
| 406 | +} | |
| 407 | + | |
| 408 | +static int adis16475_write_raw(struct iio_dev *indio_dev, | |
| 409 | + const struct iio_chan_spec *chan, | |
| 410 | + int val, int val2, long info) | |
| 411 | +{ | |
| 412 | + struct adis16475 *st = iio_priv(indio_dev); | |
| 413 | + u32 tmp; | |
| 414 | + | |
| 415 | + switch (info) { | |
| 416 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 417 | + tmp = val * 1000 + val2 / 1000; | |
| 418 | + return adis16475_set_freq(st, tmp); | |
| 419 | + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: | |
| 420 | + return adis16475_set_filter(st, val); | |
| 421 | + case IIO_CHAN_INFO_CALIBBIAS: | |
| 422 | + return adis_write_reg_32(&st->adis, | |
| 423 | + adis16475_calib_regs[chan->scan_index], | |
| 424 | + val); | |
| 425 | + default: | |
| 426 | + return -EINVAL; | |
| 427 | + } | |
| 428 | +} | |
| 429 | + | |
| 430 | +#define ADIS16475_MOD_CHAN(_type, _mod, _address, _si, _r_bits, _s_bits) \ | |
| 431 | + { \ | |
| 432 | + .type = (_type), \ | |
| 433 | + .modified = 1, \ | |
| 434 | + .channel2 = (_mod), \ | |
| 435 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | |
| 436 | + BIT(IIO_CHAN_INFO_CALIBBIAS), \ | |
| 437 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | |
| 438 | + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ | |
| 439 | + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ | |
| 440 | + .address = (_address), \ | |
| 441 | + .scan_index = (_si), \ | |
| 442 | + .scan_type = { \ | |
| 443 | + .sign = 's', \ | |
| 444 | + .realbits = (_r_bits), \ | |
| 445 | + .storagebits = (_s_bits), \ | |
| 446 | + .endianness = IIO_BE, \ | |
| 447 | + }, \ | |
| 448 | + } | |
| 449 | + | |
| 450 | +#define ADIS16475_GYRO_CHANNEL(_mod) \ | |
| 451 | + ADIS16475_MOD_CHAN(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \ | |
| 452 | + ADIS16475_REG_ ## _mod ## _GYRO_L, \ | |
| 453 | + ADIS16475_SCAN_GYRO_ ## _mod, 32, 32) | |
| 454 | + | |
| 455 | +#define ADIS16475_ACCEL_CHANNEL(_mod) \ | |
| 456 | + ADIS16475_MOD_CHAN(IIO_ACCEL, IIO_MOD_ ## _mod, \ | |
| 457 | + ADIS16475_REG_ ## _mod ## _ACCEL_L, \ | |
| 458 | + ADIS16475_SCAN_ACCEL_ ## _mod, 32, 32) | |
| 459 | + | |
| 460 | +#define ADIS16475_TEMP_CHANNEL() { \ | |
| 461 | + .type = IIO_TEMP, \ | |
| 462 | + .indexed = 1, \ | |
| 463 | + .channel = 0, \ | |
| 464 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | |
| 465 | + BIT(IIO_CHAN_INFO_SCALE), \ | |
| 466 | + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ | |
| 467 | + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ | |
| 468 | + .address = ADIS16475_REG_TEMP_OUT, \ | |
| 469 | + .scan_index = ADIS16475_SCAN_TEMP, \ | |
| 470 | + .scan_type = { \ | |
| 471 | + .sign = 's', \ | |
| 472 | + .realbits = 16, \ | |
| 473 | + .storagebits = 16, \ | |
| 474 | + .endianness = IIO_BE, \ | |
| 475 | + }, \ | |
| 476 | + } | |
| 477 | + | |
| 478 | +static const struct iio_chan_spec adis16475_channels[] = { | |
| 479 | + ADIS16475_GYRO_CHANNEL(X), | |
| 480 | + ADIS16475_GYRO_CHANNEL(Y), | |
| 481 | + ADIS16475_GYRO_CHANNEL(Z), | |
| 482 | + ADIS16475_ACCEL_CHANNEL(X), | |
| 483 | + ADIS16475_ACCEL_CHANNEL(Y), | |
| 484 | + ADIS16475_ACCEL_CHANNEL(Z), | |
| 485 | + ADIS16475_TEMP_CHANNEL(), | |
| 486 | + IIO_CHAN_SOFT_TIMESTAMP(7) | |
| 487 | +}; | |
| 488 | + | |
| 489 | +enum adis16475_variant { | |
| 490 | + ADIS16470, | |
| 491 | + ADIS16475_1, | |
| 492 | + ADIS16475_2, | |
| 493 | + ADIS16475_3, | |
| 494 | + ADIS16477_1, | |
| 495 | + ADIS16477_2, | |
| 496 | + ADIS16477_3, | |
| 497 | + ADIS16465_1, | |
| 498 | + ADIS16465_2, | |
| 499 | + ADIS16465_3, | |
| 500 | + ADIS16467_1, | |
| 501 | + ADIS16467_2, | |
| 502 | + ADIS16467_3, | |
| 503 | + ADIS16500, | |
| 504 | + ADIS16505_1, | |
| 505 | + ADIS16505_2, | |
| 506 | + ADIS16505_3, | |
| 507 | + ADIS16507_1, | |
| 508 | + ADIS16507_2, | |
| 509 | + ADIS16507_3, | |
| 510 | +}; | |
| 511 | + | |
| 512 | +enum { | |
| 513 | + ADIS16475_DIAG_STAT_DATA_PATH = 1, | |
| 514 | + ADIS16475_DIAG_STAT_FLASH_MEM, | |
| 515 | + ADIS16475_DIAG_STAT_SPI, | |
| 516 | + ADIS16475_DIAG_STAT_STANDBY, | |
| 517 | + ADIS16475_DIAG_STAT_SENSOR, | |
| 518 | + ADIS16475_DIAG_STAT_MEMORY, | |
| 519 | + ADIS16475_DIAG_STAT_CLK, | |
| 520 | +}; | |
| 521 | + | |
| 522 | +static const char * const adis16475_status_error_msgs[] = { | |
| 523 | + [ADIS16475_DIAG_STAT_DATA_PATH] = "Data Path Overrun", | |
| 524 | + [ADIS16475_DIAG_STAT_FLASH_MEM] = "Flash memory update failure", | |
| 525 | + [ADIS16475_DIAG_STAT_SPI] = "SPI communication error", | |
| 526 | + [ADIS16475_DIAG_STAT_STANDBY] = "Standby mode", | |
| 527 | + [ADIS16475_DIAG_STAT_SENSOR] = "Sensor failure", | |
| 528 | + [ADIS16475_DIAG_STAT_MEMORY] = "Memory failure", | |
| 529 | + [ADIS16475_DIAG_STAT_CLK] = "Clock error", | |
| 530 | +}; | |
| 531 | + | |
| 532 | +static int adis16475_enable_irq(struct adis *adis, bool enable) | |
| 533 | +{ | |
| 534 | + /* | |
| 535 | + * There is no way to gate the data-ready signal internally inside the | |
| 536 | + * ADIS16475. We can only control it's polarity... | |
| 537 | + */ | |
| 538 | + if (enable) | |
| 539 | + enable_irq(adis->spi->irq); | |
| 540 | + else | |
| 541 | + disable_irq(adis->spi->irq); | |
| 542 | + | |
| 543 | + return 0; | |
| 544 | +} | |
| 545 | + | |
| 546 | +#define ADIS16475_DATA(_prod_id, _timeouts) \ | |
| 547 | +{ \ | |
| 548 | + .msc_ctrl_reg = ADIS16475_REG_MSG_CTRL, \ | |
| 549 | + .glob_cmd_reg = ADIS16475_REG_GLOB_CMD, \ | |
| 550 | + .diag_stat_reg = ADIS16475_REG_DIAG_STAT, \ | |
| 551 | + .prod_id_reg = ADIS16475_REG_PROD_ID, \ | |
| 552 | + .prod_id = (_prod_id), \ | |
| 553 | + .self_test_mask = BIT(2), \ | |
| 554 | + .self_test_reg = ADIS16475_REG_GLOB_CMD, \ | |
| 555 | + .cs_change_delay = 16, \ | |
| 556 | + .read_delay = 5, \ | |
| 557 | + .write_delay = 5, \ | |
| 558 | + .status_error_msgs = adis16475_status_error_msgs, \ | |
| 559 | + .status_error_mask = BIT(ADIS16475_DIAG_STAT_DATA_PATH) | \ | |
| 560 | + BIT(ADIS16475_DIAG_STAT_FLASH_MEM) | \ | |
| 561 | + BIT(ADIS16475_DIAG_STAT_SPI) | \ | |
| 562 | + BIT(ADIS16475_DIAG_STAT_STANDBY) | \ | |
| 563 | + BIT(ADIS16475_DIAG_STAT_SENSOR) | \ | |
| 564 | + BIT(ADIS16475_DIAG_STAT_MEMORY) | \ | |
| 565 | + BIT(ADIS16475_DIAG_STAT_CLK), \ | |
| 566 | + .enable_irq = adis16475_enable_irq, \ | |
| 567 | + .timeouts = (_timeouts), \ | |
| 568 | +} | |
| 569 | + | |
| 570 | +static const struct adis16475_sync adis16475_sync_mode[] = { | |
| 571 | + { ADIS16475_SYNC_OUTPUT }, | |
| 572 | + { ADIS16475_SYNC_DIRECT, 1900, 2100 }, | |
| 573 | + { ADIS16475_SYNC_SCALED, 1, 128 }, | |
| 574 | + { ADIS16475_SYNC_PULSE, 1000, 2100 }, | |
| 575 | +}; | |
| 576 | + | |
| 577 | +static const struct adis_timeout adis16475_timeouts = { | |
| 578 | + .reset_ms = 200, | |
| 579 | + .sw_reset_ms = 200, | |
| 580 | + .self_test_ms = 20, | |
| 581 | +}; | |
| 582 | + | |
| 583 | +static const struct adis_timeout adis1650x_timeouts = { | |
| 584 | + .reset_ms = 260, | |
| 585 | + .sw_reset_ms = 260, | |
| 586 | + .self_test_ms = 30, | |
| 587 | +}; | |
| 588 | + | |
| 589 | +static const struct adis16475_chip_info adis16475_chip_info[] = { | |
| 590 | + [ADIS16470] = { | |
| 591 | + .name = "adis16470", | |
| 592 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 593 | + .channels = adis16475_channels, | |
| 594 | + .gyro_max_val = 1, | |
| 595 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), | |
| 596 | + .accel_max_val = 1, | |
| 597 | + .accel_max_scale = IIO_M_S_2_TO_G(800 << 16), | |
| 598 | + .temp_scale = 100, | |
| 599 | + .int_clk = 2000, | |
| 600 | + .max_dec = 1999, | |
| 601 | + .sync = adis16475_sync_mode, | |
| 602 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode), | |
| 603 | + .adis_data = ADIS16475_DATA(16470, &adis16475_timeouts), | |
| 604 | + }, | |
| 605 | + [ADIS16475_1] = { | |
| 606 | + .name = "adis16475-1", | |
| 607 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 608 | + .channels = adis16475_channels, | |
| 609 | + .gyro_max_val = 1, | |
| 610 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16), | |
| 611 | + .accel_max_val = 1, | |
| 612 | + .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16), | |
| 613 | + .temp_scale = 100, | |
| 614 | + .int_clk = 2000, | |
| 615 | + .max_dec = 1999, | |
| 616 | + .sync = adis16475_sync_mode, | |
| 617 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode), | |
| 618 | + .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts), | |
| 619 | + }, | |
| 620 | + [ADIS16475_2] = { | |
| 621 | + .name = "adis16475-2", | |
| 622 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 623 | + .channels = adis16475_channels, | |
| 624 | + .gyro_max_val = 1, | |
| 625 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), | |
| 626 | + .accel_max_val = 1, | |
| 627 | + .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16), | |
| 628 | + .temp_scale = 100, | |
| 629 | + .int_clk = 2000, | |
| 630 | + .max_dec = 1999, | |
| 631 | + .sync = adis16475_sync_mode, | |
| 632 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode), | |
| 633 | + .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts), | |
| 634 | + }, | |
| 635 | + [ADIS16475_3] = { | |
| 636 | + .name = "adis16475-3", | |
| 637 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 638 | + .channels = adis16475_channels, | |
| 639 | + .gyro_max_val = 1, | |
| 640 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), | |
| 641 | + .accel_max_val = 1, | |
| 642 | + .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16), | |
| 643 | + .temp_scale = 100, | |
| 644 | + .int_clk = 2000, | |
| 645 | + .max_dec = 1999, | |
| 646 | + .sync = adis16475_sync_mode, | |
| 647 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode), | |
| 648 | + .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts), | |
| 649 | + }, | |
| 650 | + [ADIS16477_1] = { | |
| 651 | + .name = "adis16477-1", | |
| 652 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 653 | + .channels = adis16475_channels, | |
| 654 | + .gyro_max_val = 1, | |
| 655 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16), | |
| 656 | + .accel_max_val = 1, | |
| 657 | + .accel_max_scale = IIO_M_S_2_TO_G(800 << 16), | |
| 658 | + .temp_scale = 100, | |
| 659 | + .int_clk = 2000, | |
| 660 | + .max_dec = 1999, | |
| 661 | + .sync = adis16475_sync_mode, | |
| 662 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode), | |
| 663 | + .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts), | |
| 664 | + }, | |
| 665 | + [ADIS16477_2] = { | |
| 666 | + .name = "adis16477-2", | |
| 667 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 668 | + .channels = adis16475_channels, | |
| 669 | + .gyro_max_val = 1, | |
| 670 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), | |
| 671 | + .accel_max_val = 1, | |
| 672 | + .accel_max_scale = IIO_M_S_2_TO_G(800 << 16), | |
| 673 | + .temp_scale = 100, | |
| 674 | + .int_clk = 2000, | |
| 675 | + .max_dec = 1999, | |
| 676 | + .sync = adis16475_sync_mode, | |
| 677 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode), | |
| 678 | + .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts), | |
| 679 | + }, | |
| 680 | + [ADIS16477_3] = { | |
| 681 | + .name = "adis16477-3", | |
| 682 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 683 | + .channels = adis16475_channels, | |
| 684 | + .gyro_max_val = 1, | |
| 685 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), | |
| 686 | + .accel_max_val = 1, | |
| 687 | + .accel_max_scale = IIO_M_S_2_TO_G(800 << 16), | |
| 688 | + .temp_scale = 100, | |
| 689 | + .int_clk = 2000, | |
| 690 | + .max_dec = 1999, | |
| 691 | + .sync = adis16475_sync_mode, | |
| 692 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode), | |
| 693 | + .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts), | |
| 694 | + }, | |
| 695 | + [ADIS16465_1] = { | |
| 696 | + .name = "adis16465-1", | |
| 697 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 698 | + .channels = adis16475_channels, | |
| 699 | + .gyro_max_val = 1, | |
| 700 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16), | |
| 701 | + .accel_max_val = 1, | |
| 702 | + .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16), | |
| 703 | + .temp_scale = 100, | |
| 704 | + .int_clk = 2000, | |
| 705 | + .max_dec = 1999, | |
| 706 | + .sync = adis16475_sync_mode, | |
| 707 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode), | |
| 708 | + .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts), | |
| 709 | + }, | |
| 710 | + [ADIS16465_2] = { | |
| 711 | + .name = "adis16465-2", | |
| 712 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 713 | + .channels = adis16475_channels, | |
| 714 | + .gyro_max_val = 1, | |
| 715 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), | |
| 716 | + .accel_max_val = 1, | |
| 717 | + .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16), | |
| 718 | + .temp_scale = 100, | |
| 719 | + .int_clk = 2000, | |
| 720 | + .max_dec = 1999, | |
| 721 | + .sync = adis16475_sync_mode, | |
| 722 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode), | |
| 723 | + .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts), | |
| 724 | + }, | |
| 725 | + [ADIS16465_3] = { | |
| 726 | + .name = "adis16465-3", | |
| 727 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 728 | + .channels = adis16475_channels, | |
| 729 | + .gyro_max_val = 1, | |
| 730 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), | |
| 731 | + .accel_max_val = 1, | |
| 732 | + .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16), | |
| 733 | + .temp_scale = 100, | |
| 734 | + .int_clk = 2000, | |
| 735 | + .max_dec = 1999, | |
| 736 | + .sync = adis16475_sync_mode, | |
| 737 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode), | |
| 738 | + .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts), | |
| 739 | + }, | |
| 740 | + [ADIS16467_1] = { | |
| 741 | + .name = "adis16467-1", | |
| 742 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 743 | + .channels = adis16475_channels, | |
| 744 | + .gyro_max_val = 1, | |
| 745 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16), | |
| 746 | + .accel_max_val = 1, | |
| 747 | + .accel_max_scale = IIO_M_S_2_TO_G(800 << 16), | |
| 748 | + .temp_scale = 100, | |
| 749 | + .int_clk = 2000, | |
| 750 | + .max_dec = 1999, | |
| 751 | + .sync = adis16475_sync_mode, | |
| 752 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode), | |
| 753 | + .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts), | |
| 754 | + }, | |
| 755 | + [ADIS16467_2] = { | |
| 756 | + .name = "adis16467-2", | |
| 757 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 758 | + .channels = adis16475_channels, | |
| 759 | + .gyro_max_val = 1, | |
| 760 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), | |
| 761 | + .accel_max_val = 1, | |
| 762 | + .accel_max_scale = IIO_M_S_2_TO_G(800 << 16), | |
| 763 | + .temp_scale = 100, | |
| 764 | + .int_clk = 2000, | |
| 765 | + .max_dec = 1999, | |
| 766 | + .sync = adis16475_sync_mode, | |
| 767 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode), | |
| 768 | + .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts), | |
| 769 | + }, | |
| 770 | + [ADIS16467_3] = { | |
| 771 | + .name = "adis16467-3", | |
| 772 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 773 | + .channels = adis16475_channels, | |
| 774 | + .gyro_max_val = 1, | |
| 775 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), | |
| 776 | + .accel_max_val = 1, | |
| 777 | + .accel_max_scale = IIO_M_S_2_TO_G(800 << 16), | |
| 778 | + .temp_scale = 100, | |
| 779 | + .int_clk = 2000, | |
| 780 | + .max_dec = 1999, | |
| 781 | + .sync = adis16475_sync_mode, | |
| 782 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode), | |
| 783 | + .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts), | |
| 784 | + }, | |
| 785 | + [ADIS16500] = { | |
| 786 | + .name = "adis16500", | |
| 787 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 788 | + .channels = adis16475_channels, | |
| 789 | + .gyro_max_val = 1, | |
| 790 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), | |
| 791 | + .accel_max_val = 392, | |
| 792 | + .accel_max_scale = 32000 << 16, | |
| 793 | + .temp_scale = 100, | |
| 794 | + .int_clk = 2000, | |
| 795 | + .max_dec = 1999, | |
| 796 | + .sync = adis16475_sync_mode, | |
| 797 | + /* pulse sync not supported */ | |
| 798 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, | |
| 799 | + .has_burst32 = true, | |
| 800 | + .adis_data = ADIS16475_DATA(16500, &adis1650x_timeouts), | |
| 801 | + }, | |
| 802 | + [ADIS16505_1] = { | |
| 803 | + .name = "adis16505-1", | |
| 804 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 805 | + .channels = adis16475_channels, | |
| 806 | + .gyro_max_val = 1, | |
| 807 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16), | |
| 808 | + .accel_max_val = 78, | |
| 809 | + .accel_max_scale = 32000 << 16, | |
| 810 | + .temp_scale = 100, | |
| 811 | + .int_clk = 2000, | |
| 812 | + .max_dec = 1999, | |
| 813 | + .sync = adis16475_sync_mode, | |
| 814 | + /* pulse sync not supported */ | |
| 815 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, | |
| 816 | + .has_burst32 = true, | |
| 817 | + .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts), | |
| 818 | + }, | |
| 819 | + [ADIS16505_2] = { | |
| 820 | + .name = "adis16505-2", | |
| 821 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 822 | + .channels = adis16475_channels, | |
| 823 | + .gyro_max_val = 1, | |
| 824 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), | |
| 825 | + .accel_max_val = 78, | |
| 826 | + .accel_max_scale = 32000 << 16, | |
| 827 | + .temp_scale = 100, | |
| 828 | + .int_clk = 2000, | |
| 829 | + .max_dec = 1999, | |
| 830 | + .sync = adis16475_sync_mode, | |
| 831 | + /* pulse sync not supported */ | |
| 832 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, | |
| 833 | + .has_burst32 = true, | |
| 834 | + .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts), | |
| 835 | + }, | |
| 836 | + [ADIS16505_3] = { | |
| 837 | + .name = "adis16505-3", | |
| 838 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 839 | + .channels = adis16475_channels, | |
| 840 | + .gyro_max_val = 1, | |
| 841 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), | |
| 842 | + .accel_max_val = 78, | |
| 843 | + .accel_max_scale = 32000 << 16, | |
| 844 | + .temp_scale = 100, | |
| 845 | + .int_clk = 2000, | |
| 846 | + .max_dec = 1999, | |
| 847 | + .sync = adis16475_sync_mode, | |
| 848 | + /* pulse sync not supported */ | |
| 849 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, | |
| 850 | + .has_burst32 = true, | |
| 851 | + .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts), | |
| 852 | + }, | |
| 853 | + [ADIS16507_1] = { | |
| 854 | + .name = "adis16507-1", | |
| 855 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 856 | + .channels = adis16475_channels, | |
| 857 | + .gyro_max_val = 1, | |
| 858 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16), | |
| 859 | + .accel_max_val = 392, | |
| 860 | + .accel_max_scale = 32000 << 16, | |
| 861 | + .temp_scale = 100, | |
| 862 | + .int_clk = 2000, | |
| 863 | + .max_dec = 1999, | |
| 864 | + .sync = adis16475_sync_mode, | |
| 865 | + /* pulse sync not supported */ | |
| 866 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, | |
| 867 | + .has_burst32 = true, | |
| 868 | + .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts), | |
| 869 | + }, | |
| 870 | + [ADIS16507_2] = { | |
| 871 | + .name = "adis16507-2", | |
| 872 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 873 | + .channels = adis16475_channels, | |
| 874 | + .gyro_max_val = 1, | |
| 875 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), | |
| 876 | + .accel_max_val = 392, | |
| 877 | + .accel_max_scale = 32000 << 16, | |
| 878 | + .temp_scale = 100, | |
| 879 | + .int_clk = 2000, | |
| 880 | + .max_dec = 1999, | |
| 881 | + .sync = adis16475_sync_mode, | |
| 882 | + /* pulse sync not supported */ | |
| 883 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, | |
| 884 | + .has_burst32 = true, | |
| 885 | + .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts), | |
| 886 | + }, | |
| 887 | + [ADIS16507_3] = { | |
| 888 | + .name = "adis16507-3", | |
| 889 | + .num_channels = ARRAY_SIZE(adis16475_channels), | |
| 890 | + .channels = adis16475_channels, | |
| 891 | + .gyro_max_val = 1, | |
| 892 | + .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), | |
| 893 | + .accel_max_val = 392, | |
| 894 | + .accel_max_scale = 32000 << 16, | |
| 895 | + .temp_scale = 100, | |
| 896 | + .int_clk = 2000, | |
| 897 | + .max_dec = 1999, | |
| 898 | + .sync = adis16475_sync_mode, | |
| 899 | + /* pulse sync not supported */ | |
| 900 | + .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, | |
| 901 | + .has_burst32 = true, | |
| 902 | + .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts), | |
| 903 | + }, | |
| 904 | +}; | |
| 905 | + | |
| 906 | +static const struct iio_info adis16475_info = { | |
| 907 | + .read_raw = &adis16475_read_raw, | |
| 908 | + .write_raw = &adis16475_write_raw, | |
| 909 | + .update_scan_mode = adis_update_scan_mode, | |
| 910 | + .debugfs_reg_access = adis_debugfs_reg_access, | |
| 911 | +}; | |
| 912 | + | |
| 913 | +static struct adis_burst adis16475_burst = { | |
| 914 | + .en = true, | |
| 915 | + .reg_cmd = ADIS16475_REG_GLOB_CMD, | |
| 916 | + /* | |
| 917 | + * adis_update_scan_mode_burst() sets the burst length in respect with | |
| 918 | + * the number of channels and allocates 16 bits for each. However, | |
| 919 | + * adis1647x devices also need space for DIAG_STAT, DATA_CNTR or | |
| 920 | + * TIME_STAMP (depending on the clock mode but for us these bytes are | |
| 921 | + * don't care...) and CRC. | |
| 922 | + */ | |
| 923 | + .extra_len = 3 * sizeof(u16), | |
| 924 | + .burst_max_len = ADIS16475_BURST32_MAX_DATA, | |
| 925 | +}; | |
| 926 | + | |
| 927 | +static bool adis16475_validate_crc(const u8 *buffer, u16 crc, | |
| 928 | + const bool burst32) | |
| 929 | +{ | |
| 930 | + int i; | |
| 931 | + /* extra 6 elements for low gyro and accel */ | |
| 932 | + const u16 sz = burst32 ? ADIS16475_BURST32_MAX_DATA : | |
| 933 | + ADIS16475_BURST_MAX_DATA; | |
| 934 | + | |
| 935 | + for (i = 0; i < sz - 2; i++) | |
| 936 | + crc -= buffer[i]; | |
| 937 | + | |
| 938 | + return crc == 0; | |
| 939 | +} | |
| 940 | + | |
| 941 | +static void adis16475_burst32_check(struct adis16475 *st) | |
| 942 | +{ | |
| 943 | + int ret; | |
| 944 | + struct adis *adis = &st->adis; | |
| 945 | + | |
| 946 | + if (!st->info->has_burst32) | |
| 947 | + return; | |
| 948 | + | |
| 949 | + if (st->lsb_flag && !st->burst32) { | |
| 950 | + const u16 en = ADIS16500_BURST32(1); | |
| 951 | + | |
| 952 | + ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL, | |
| 953 | + ADIS16500_BURST32_MASK, en); | |
| 954 | + if (ret) | |
| 955 | + return; | |
| 956 | + | |
| 957 | + st->burst32 = true; | |
| 958 | + | |
| 959 | + /* | |
| 960 | + * In 32-bit mode we need extra 2 bytes for all gyro | |
| 961 | + * and accel channels. | |
| 962 | + */ | |
| 963 | + adis->burst_extra_len = 6 * sizeof(u16); | |
| 964 | + adis->xfer[1].len += 6 * sizeof(u16); | |
| 965 | + dev_dbg(&adis->spi->dev, "Enable burst32 mode, xfer:%d", | |
| 966 | + adis->xfer[1].len); | |
| 967 | + | |
| 968 | + } else if (!st->lsb_flag && st->burst32) { | |
| 969 | + const u16 en = ADIS16500_BURST32(0); | |
| 970 | + | |
| 971 | + ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL, | |
| 972 | + ADIS16500_BURST32_MASK, en); | |
| 973 | + if (ret) | |
| 974 | + return; | |
| 975 | + | |
| 976 | + st->burst32 = false; | |
| 977 | + | |
| 978 | + /* Remove the extra bits */ | |
| 979 | + adis->burst_extra_len = 0; | |
| 980 | + adis->xfer[1].len -= 6 * sizeof(u16); | |
| 981 | + dev_dbg(&adis->spi->dev, "Disable burst32 mode, xfer:%d\n", | |
| 982 | + adis->xfer[1].len); | |
| 983 | + } | |
| 984 | +} | |
| 985 | + | |
| 986 | +static irqreturn_t adis16475_trigger_handler(int irq, void *p) | |
| 987 | +{ | |
| 988 | + struct iio_poll_func *pf = p; | |
| 989 | + struct iio_dev *indio_dev = pf->indio_dev; | |
| 990 | + struct adis16475 *st = iio_priv(indio_dev); | |
| 991 | + struct adis *adis = &st->adis; | |
| 992 | + int ret, bit, i = 0; | |
| 993 | + __be16 *buffer; | |
| 994 | + u16 crc; | |
| 995 | + bool valid; | |
| 996 | + /* offset until the first element after gyro and accel */ | |
| 997 | + const u8 offset = st->burst32 ? 13 : 7; | |
| 998 | + const u32 cached_spi_speed_hz = adis->spi->max_speed_hz; | |
| 999 | + | |
| 1000 | + adis->spi->max_speed_hz = ADIS16475_BURST_MAX_SPEED; | |
| 1001 | + | |
| 1002 | + ret = spi_sync(adis->spi, &adis->msg); | |
| 1003 | + if (ret) | |
| 1004 | + return ret; | |
| 1005 | + | |
| 1006 | + adis->spi->max_speed_hz = cached_spi_speed_hz; | |
| 1007 | + buffer = adis->buffer; | |
| 1008 | + | |
| 1009 | + crc = be16_to_cpu(buffer[offset + 2]); | |
| 1010 | + valid = adis16475_validate_crc(adis->buffer, crc, st->burst32); | |
| 1011 | + if (!valid) { | |
| 1012 | + dev_err(&adis->spi->dev, "Invalid crc\n"); | |
| 1013 | + goto check_burst32; | |
| 1014 | + } | |
| 1015 | + | |
| 1016 | + for_each_set_bit(bit, indio_dev->active_scan_mask, | |
| 1017 | + indio_dev->masklength) { | |
| 1018 | + /* | |
| 1019 | + * When burst mode is used, system flags is the first data | |
| 1020 | + * channel in the sequence, but the scan index is 7. | |
| 1021 | + */ | |
| 1022 | + switch (bit) { | |
| 1023 | + case ADIS16475_SCAN_TEMP: | |
| 1024 | + st->data[i++] = buffer[offset]; | |
| 1025 | + break; | |
| 1026 | + case ADIS16475_SCAN_GYRO_X ... ADIS16475_SCAN_ACCEL_Z: | |
| 1027 | + /* | |
| 1028 | + * The first 2 bytes on the received data are the | |
| 1029 | + * DIAG_STAT reg, hence the +1 offset here... | |
| 1030 | + */ | |
| 1031 | + if (st->burst32) { | |
| 1032 | + /* upper 16 */ | |
| 1033 | + st->data[i++] = buffer[bit * 2 + 2]; | |
| 1034 | + /* lower 16 */ | |
| 1035 | + st->data[i++] = buffer[bit * 2 + 1]; | |
| 1036 | + } else { | |
| 1037 | + st->data[i++] = buffer[bit + 1]; | |
| 1038 | + /* | |
| 1039 | + * Don't bother in doing the manual read if the | |
| 1040 | + * device supports burst32. burst32 will be | |
| 1041 | + * enabled in the next call to | |
| 1042 | + * adis16475_burst32_check()... | |
| 1043 | + */ | |
| 1044 | + if (st->lsb_flag && !st->info->has_burst32) { | |
| 1045 | + u16 val = 0; | |
| 1046 | + const u32 reg = ADIS16475_REG_X_GYRO_L + | |
| 1047 | + bit * 4; | |
| 1048 | + | |
| 1049 | + adis_read_reg_16(adis, reg, &val); | |
| 1050 | + st->data[i++] = cpu_to_be16(val); | |
| 1051 | + } else { | |
| 1052 | + /* lower not used */ | |
| 1053 | + st->data[i++] = 0; | |
| 1054 | + } | |
| 1055 | + } | |
| 1056 | + break; | |
| 1057 | + } | |
| 1058 | + } | |
| 1059 | + | |
| 1060 | + iio_push_to_buffers_with_timestamp(indio_dev, st->data, pf->timestamp); | |
| 1061 | +check_burst32: | |
| 1062 | + /* | |
| 1063 | + * We only check the burst mode at the end of the current capture since | |
| 1064 | + * it takes a full data ready cycle for the device to update the burst | |
| 1065 | + * array. | |
| 1066 | + */ | |
| 1067 | + adis16475_burst32_check(st); | |
| 1068 | + iio_trigger_notify_done(indio_dev->trig); | |
| 1069 | + | |
| 1070 | + return IRQ_HANDLED; | |
| 1071 | +} | |
| 1072 | + | |
| 1073 | +static void adis16475_disable_clk(void *data) | |
| 1074 | +{ | |
| 1075 | + clk_disable_unprepare((struct clk *)data); | |
| 1076 | +} | |
| 1077 | + | |
| 1078 | +static int adis16475_config_sync_mode(struct adis16475 *st) | |
| 1079 | +{ | |
| 1080 | + int ret; | |
| 1081 | + struct device *dev = &st->adis.spi->dev; | |
| 1082 | + const struct adis16475_sync *sync; | |
| 1083 | + u32 sync_mode; | |
| 1084 | + | |
| 1085 | + /* default to internal clk */ | |
| 1086 | + st->clk_freq = st->info->int_clk * 1000; | |
| 1087 | + | |
| 1088 | + ret = device_property_read_u32(dev, "adi,sync-mode", &sync_mode); | |
| 1089 | + if (ret) | |
| 1090 | + return 0; | |
| 1091 | + | |
| 1092 | + if (sync_mode >= st->info->num_sync) { | |
| 1093 | + dev_err(dev, "Invalid sync mode: %u for %s\n", sync_mode, | |
| 1094 | + st->info->name); | |
| 1095 | + return -EINVAL; | |
| 1096 | + } | |
| 1097 | + | |
| 1098 | + sync = &st->info->sync[sync_mode]; | |
| 1099 | + | |
| 1100 | + /* All the other modes require external input signal */ | |
| 1101 | + if (sync->sync_mode != ADIS16475_SYNC_OUTPUT) { | |
| 1102 | + struct clk *clk = devm_clk_get(dev, NULL); | |
| 1103 | + | |
| 1104 | + if (IS_ERR(clk)) | |
| 1105 | + return PTR_ERR(clk); | |
| 1106 | + | |
| 1107 | + ret = clk_prepare_enable(clk); | |
| 1108 | + if (ret) | |
| 1109 | + return ret; | |
| 1110 | + | |
| 1111 | + ret = devm_add_action_or_reset(dev, adis16475_disable_clk, clk); | |
| 1112 | + if (ret) | |
| 1113 | + return ret; | |
| 1114 | + | |
| 1115 | + st->clk_freq = clk_get_rate(clk); | |
| 1116 | + if (st->clk_freq < sync->min_rate || | |
| 1117 | + st->clk_freq > sync->max_rate) { | |
| 1118 | + dev_err(dev, | |
| 1119 | + "Clk rate:%u not in a valid range:[%u %u]\n", | |
| 1120 | + st->clk_freq, sync->min_rate, sync->max_rate); | |
| 1121 | + return -EINVAL; | |
| 1122 | + } | |
| 1123 | + | |
| 1124 | + if (sync->sync_mode == ADIS16475_SYNC_SCALED) { | |
| 1125 | + u16 up_scale; | |
| 1126 | + u32 scaled_out_freq = 0; | |
| 1127 | + /* | |
| 1128 | + * If we are in scaled mode, we must have an up_scale. | |
| 1129 | + * In scaled mode the allowable input clock range is | |
| 1130 | + * 1 Hz to 128 Hz, and the allowable output range is | |
| 1131 | + * 1900 to 2100 Hz. Hence, a scale must be given to | |
| 1132 | + * get the allowable output. | |
| 1133 | + */ | |
| 1134 | + ret = device_property_read_u32(dev, | |
| 1135 | + "adi,scaled-output-hz", | |
| 1136 | + &scaled_out_freq); | |
| 1137 | + if (ret) { | |
| 1138 | + dev_err(dev, "adi,scaled-output-hz must be given when in scaled sync mode"); | |
| 1139 | + return -EINVAL; | |
| 1140 | + } else if (scaled_out_freq < 1900 || | |
| 1141 | + scaled_out_freq > 2100) { | |
| 1142 | + dev_err(dev, "Invalid value: %u for adi,scaled-output-hz", | |
| 1143 | + scaled_out_freq); | |
| 1144 | + return -EINVAL; | |
| 1145 | + } | |
| 1146 | + | |
| 1147 | + up_scale = DIV_ROUND_CLOSEST(scaled_out_freq, | |
| 1148 | + st->clk_freq); | |
| 1149 | + | |
| 1150 | + ret = __adis_write_reg_16(&st->adis, | |
| 1151 | + ADIS16475_REG_UP_SCALE, | |
| 1152 | + up_scale); | |
| 1153 | + if (ret) | |
| 1154 | + return ret; | |
| 1155 | + | |
| 1156 | + st->clk_freq = scaled_out_freq; | |
| 1157 | + } | |
| 1158 | + | |
| 1159 | + st->clk_freq *= 1000; | |
| 1160 | + } | |
| 1161 | + /* | |
| 1162 | + * Keep in mind that the mask for the clk modes in adis1650* | |
| 1163 | + * chips is different (1100 instead of 11100). However, we | |
| 1164 | + * are not configuring BIT(4) in these chips and the default | |
| 1165 | + * value is 0, so we are fine in doing the below operations. | |
| 1166 | + * I'm keeping this for simplicity and avoiding extra variables | |
| 1167 | + * in chip_info. | |
| 1168 | + */ | |
| 1169 | + ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL, | |
| 1170 | + ADIS16475_SYNC_MODE_MASK, sync->sync_mode); | |
| 1171 | + if (ret) | |
| 1172 | + return ret; | |
| 1173 | + | |
| 1174 | + usleep_range(250, 260); | |
| 1175 | + | |
| 1176 | + return 0; | |
| 1177 | +} | |
| 1178 | + | |
| 1179 | +static int adis16475_config_irq_pin(struct adis16475 *st) | |
| 1180 | +{ | |
| 1181 | + int ret; | |
| 1182 | + struct irq_data *desc; | |
| 1183 | + u32 irq_type; | |
| 1184 | + u16 val = 0; | |
| 1185 | + u8 polarity; | |
| 1186 | + struct spi_device *spi = st->adis.spi; | |
| 1187 | + | |
| 1188 | + desc = irq_get_irq_data(spi->irq); | |
| 1189 | + if (!desc) { | |
| 1190 | + dev_err(&spi->dev, "Could not find IRQ %d\n", spi->irq); | |
| 1191 | + return -EINVAL; | |
| 1192 | + } | |
| 1193 | + /* | |
| 1194 | + * It is possible to configure the data ready polarity. Furthermore, we | |
| 1195 | + * need to update the adis struct if we want data ready as active low. | |
| 1196 | + */ | |
| 1197 | + irq_type = irqd_get_trigger_type(desc); | |
| 1198 | + if (irq_type == IRQ_TYPE_EDGE_RISING) { | |
| 1199 | + polarity = 1; | |
| 1200 | + st->adis.irq_flag = IRQF_TRIGGER_RISING; | |
| 1201 | + } else if (irq_type == IRQ_TYPE_EDGE_FALLING) { | |
| 1202 | + polarity = 0; | |
| 1203 | + st->adis.irq_flag = IRQF_TRIGGER_FALLING; | |
| 1204 | + } else { | |
| 1205 | + dev_err(&spi->dev, "Invalid interrupt type 0x%x specified\n", | |
| 1206 | + irq_type); | |
| 1207 | + return -EINVAL; | |
| 1208 | + } | |
| 1209 | + | |
| 1210 | + val = ADIS16475_MSG_CTRL_DR_POL(polarity); | |
| 1211 | + ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL, | |
| 1212 | + ADIS16475_MSG_CTRL_DR_POL_MASK, val); | |
| 1213 | + if (ret) | |
| 1214 | + return ret; | |
| 1215 | + /* | |
| 1216 | + * There is a delay writing to any bits written to the MSC_CTRL | |
| 1217 | + * register. It should not be bigger than 200us, so 250 should be more | |
| 1218 | + * than enough! | |
| 1219 | + */ | |
| 1220 | + usleep_range(250, 260); | |
| 1221 | + | |
| 1222 | + return 0; | |
| 1223 | +} | |
| 1224 | + | |
| 1225 | +static const struct of_device_id adis16475_of_match[] = { | |
| 1226 | + { .compatible = "adi,adis16470", | |
| 1227 | + .data = &adis16475_chip_info[ADIS16470] }, | |
| 1228 | + { .compatible = "adi,adis16475-1", | |
| 1229 | + .data = &adis16475_chip_info[ADIS16475_1] }, | |
| 1230 | + { .compatible = "adi,adis16475-2", | |
| 1231 | + .data = &adis16475_chip_info[ADIS16475_2] }, | |
| 1232 | + { .compatible = "adi,adis16475-3", | |
| 1233 | + .data = &adis16475_chip_info[ADIS16475_3] }, | |
| 1234 | + { .compatible = "adi,adis16477-1", | |
| 1235 | + .data = &adis16475_chip_info[ADIS16477_1] }, | |
| 1236 | + { .compatible = "adi,adis16477-2", | |
| 1237 | + .data = &adis16475_chip_info[ADIS16477_2] }, | |
| 1238 | + { .compatible = "adi,adis16477-3", | |
| 1239 | + .data = &adis16475_chip_info[ADIS16477_3] }, | |
| 1240 | + { .compatible = "adi,adis16465-1", | |
| 1241 | + .data = &adis16475_chip_info[ADIS16465_1] }, | |
| 1242 | + { .compatible = "adi,adis16465-2", | |
| 1243 | + .data = &adis16475_chip_info[ADIS16465_2] }, | |
| 1244 | + { .compatible = "adi,adis16465-3", | |
| 1245 | + .data = &adis16475_chip_info[ADIS16465_3] }, | |
| 1246 | + { .compatible = "adi,adis16467-1", | |
| 1247 | + .data = &adis16475_chip_info[ADIS16467_1] }, | |
| 1248 | + { .compatible = "adi,adis16467-2", | |
| 1249 | + .data = &adis16475_chip_info[ADIS16467_2] }, | |
| 1250 | + { .compatible = "adi,adis16467-3", | |
| 1251 | + .data = &adis16475_chip_info[ADIS16467_3] }, | |
| 1252 | + { .compatible = "adi,adis16500", | |
| 1253 | + .data = &adis16475_chip_info[ADIS16500] }, | |
| 1254 | + { .compatible = "adi,adis16505-1", | |
| 1255 | + .data = &adis16475_chip_info[ADIS16505_1] }, | |
| 1256 | + { .compatible = "adi,adis16505-2", | |
| 1257 | + .data = &adis16475_chip_info[ADIS16505_2] }, | |
| 1258 | + { .compatible = "adi,adis16505-3", | |
| 1259 | + .data = &adis16475_chip_info[ADIS16505_3] }, | |
| 1260 | + { .compatible = "adi,adis16507-1", | |
| 1261 | + .data = &adis16475_chip_info[ADIS16507_1] }, | |
| 1262 | + { .compatible = "adi,adis16507-2", | |
| 1263 | + .data = &adis16475_chip_info[ADIS16507_2] }, | |
| 1264 | + { .compatible = "adi,adis16507-3", | |
| 1265 | + .data = &adis16475_chip_info[ADIS16507_3] }, | |
| 1266 | + { }, | |
| 1267 | +}; | |
| 1268 | +MODULE_DEVICE_TABLE(of, adis16475_of_match); | |
| 1269 | + | |
| 1270 | +static int adis16475_probe(struct spi_device *spi) | |
| 1271 | +{ | |
| 1272 | + struct iio_dev *indio_dev; | |
| 1273 | + struct adis16475 *st; | |
| 1274 | + int ret; | |
| 1275 | + | |
| 1276 | + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); | |
| 1277 | + if (!indio_dev) | |
| 1278 | + return -ENOMEM; | |
| 1279 | + | |
| 1280 | + st = iio_priv(indio_dev); | |
| 1281 | + spi_set_drvdata(spi, indio_dev); | |
| 1282 | + st->adis.burst = &adis16475_burst; | |
| 1283 | + | |
| 1284 | + st->info = device_get_match_data(&spi->dev); | |
| 1285 | + if (!st->info) | |
| 1286 | + return -EINVAL; | |
| 1287 | + | |
| 1288 | + ret = adis_init(&st->adis, indio_dev, spi, &st->info->adis_data); | |
| 1289 | + if (ret) | |
| 1290 | + return ret; | |
| 1291 | + | |
| 1292 | + indio_dev->dev.parent = &spi->dev; | |
| 1293 | + indio_dev->name = st->info->name; | |
| 1294 | + indio_dev->channels = st->info->channels; | |
| 1295 | + indio_dev->num_channels = st->info->num_channels; | |
| 1296 | + indio_dev->info = &adis16475_info; | |
| 1297 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 1298 | + | |
| 1299 | + ret = __adis_initial_startup(&st->adis); | |
| 1300 | + if (ret) | |
| 1301 | + return ret; | |
| 1302 | + | |
| 1303 | + ret = adis16475_config_irq_pin(st); | |
| 1304 | + if (ret) | |
| 1305 | + return ret; | |
| 1306 | + | |
| 1307 | + ret = adis16475_config_sync_mode(st); | |
| 1308 | + if (ret) | |
| 1309 | + return ret; | |
| 1310 | + | |
| 1311 | + ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, | |
| 1312 | + adis16475_trigger_handler); | |
| 1313 | + if (ret) | |
| 1314 | + return ret; | |
| 1315 | + | |
| 1316 | + adis16475_enable_irq(&st->adis, false); | |
| 1317 | + | |
| 1318 | + ret = devm_iio_device_register(&spi->dev, indio_dev); | |
| 1319 | + if (ret) | |
| 1320 | + return ret; | |
| 1321 | + | |
| 1322 | + adis16475_debugfs_init(indio_dev); | |
| 1323 | + | |
| 1324 | + return 0; | |
| 1325 | +} | |
| 1326 | + | |
| 1327 | +static struct spi_driver adis16475_driver = { | |
| 1328 | + .driver = { | |
| 1329 | + .name = "adis16475", | |
| 1330 | + .of_match_table = adis16475_of_match, | |
| 1331 | + }, | |
| 1332 | + .probe = adis16475_probe, | |
| 1333 | +}; | |
| 1334 | +module_spi_driver(adis16475_driver); | |
| 1335 | + | |
| 1336 | +MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>"); | |
| 1337 | +MODULE_DESCRIPTION("Analog Devices ADIS16475 IMU driver"); | |
| 1338 | +MODULE_LICENSE("GPL"); | |
| @@ -284,22 +284,18 @@ DEFINE_DEBUGFS_ATTRIBUTE(adis16480_flash_count_fops, · 283 unmodified lines | ||
| 284 | 284 | static int adis16480_debugfs_init(struct iio_dev *indio_dev) |
| 285 | 285 | { |
| 286 | 286 | struct adis16480 *adis16480 = iio_priv(indio_dev); |
| 287 | + struct dentry *d = iio_get_debugfs_dentry(indio_dev); | |
| 287 | 288 | |
| 288 | 289 | debugfs_create_file_unsafe("firmware_revision", 0400, |
| 289 | − indio_dev->debugfs_dentry, adis16480, | |
| 290 | − &adis16480_firmware_revision_fops); | |
| 290 | + d, adis16480, &adis16480_firmware_revision_fops); | |
| 291 | 291 | debugfs_create_file_unsafe("firmware_date", 0400, |
| 292 | − indio_dev->debugfs_dentry, adis16480, | |
| 293 | − &adis16480_firmware_date_fops); | |
| 292 | + d, adis16480, &adis16480_firmware_date_fops); | |
| 294 | 293 | debugfs_create_file_unsafe("serial_number", 0400, |
| 295 | − indio_dev->debugfs_dentry, adis16480, | |
| 296 | − &adis16480_serial_number_fops); | |
| 294 | + d, adis16480, &adis16480_serial_number_fops); | |
| 297 | 295 | debugfs_create_file_unsafe("product_id", 0400, |
| 298 | − indio_dev->debugfs_dentry, adis16480, | |
| 299 | − &adis16480_product_id_fops); | |
| 296 | + d, adis16480, &adis16480_product_id_fops); | |
| 300 | 297 | debugfs_create_file_unsafe("flash_count", 0400, |
| 301 | − indio_dev->debugfs_dentry, adis16480, | |
| 302 | − &adis16480_flash_count_fops); | |
| 298 | + d, adis16480, &adis16480_flash_count_fops); | |
| 303 | 299 | |
| 304 | 300 | return 0; |
| 305 | 301 | } |
| @@ -23,25 +23,30 @@ static int adis_update_scan_mode_burst(struct iio_dev *indio_dev, · 22 unmodified lines | ||
| 23 | 23 | const unsigned long *scan_mask) |
| 24 | 24 | { |
| 25 | 25 | struct adis *adis = iio_device_get_drvdata(indio_dev); |
| 26 | − unsigned int burst_length; | |
| 26 | + unsigned int burst_length, burst_max_length; | |
| 27 | 27 | u8 *tx; |
| 28 | 28 | |
| 29 | 29 | /* All but the timestamp channel */ |
| 30 | 30 | burst_length = (indio_dev->num_channels - 1) * sizeof(u16); |
| 31 | − burst_length += adis->burst->extra_len; | |
| 31 | + burst_length += adis->burst->extra_len + adis->burst_extra_len; | |
| 32 | + | |
| 33 | + if (adis->burst->burst_max_len) | |
| 34 | + burst_max_length = adis->burst->burst_max_len; | |
| 35 | + else | |
| 36 | + burst_max_length = burst_length; | |
| 32 | 37 | |
| 33 | 38 | adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL); |
| 34 | 39 | if (!adis->xfer) |
| 35 | 40 | return -ENOMEM; |
| 36 | 41 | |
| 37 | − adis->buffer = kzalloc(burst_length + sizeof(u16), GFP_KERNEL); | |
| 42 | + adis->buffer = kzalloc(burst_max_length + sizeof(u16), GFP_KERNEL); | |
| 38 | 43 | if (!adis->buffer) { |
| 39 | 44 | kfree(adis->xfer); |
| 40 | 45 | adis->xfer = NULL; |
| 41 | 46 | return -ENOMEM; |
| 42 | 47 | } |
| 43 | 48 | |
| 44 | − tx = adis->buffer + burst_length; | |
| 49 | + tx = adis->buffer + burst_max_length; | |
| 45 | 50 | tx[0] = ADIS_READ_REG(adis->burst->reg_cmd); |
| 46 | 51 | tx[1] = 0; |
| 47 | 52 | |
| @@ -156,6 +161,14 @@ static irqreturn_t adis_trigger_handler(int irq, void *p) · 108 unmodified lines | ||
| 156 | 161 | return IRQ_HANDLED; |
| 157 | 162 | } |
| 158 | 163 | |
| 164 | +static void adis_buffer_cleanup(void *arg) | |
| 165 | +{ | |
| 166 | + struct adis *adis = arg; | |
| 167 | + | |
| 168 | + kfree(adis->buffer); | |
| 169 | + kfree(adis->xfer); | |
| 170 | +} | |
| 171 | + | |
| 159 | 172 | /** |
| 160 | 173 | * adis_setup_buffer_and_trigger() - Sets up buffer and trigger for the adis device |
| 161 | 174 | * @adis: The adis device. |
| @@ -198,6 +211,43 @@ error_buffer_cleanup: · 36 unmodified lines | ||
| 198 | 211 | } |
| 199 | 212 | EXPORT_SYMBOL_GPL(adis_setup_buffer_and_trigger); |
| 200 | 213 | |
| 214 | +/** | |
| 215 | + * devm_adis_setup_buffer_and_trigger() - Sets up buffer and trigger for | |
| 216 | + * the managed adis device | |
| 217 | + * @adis: The adis device | |
| 218 | + * @indio_dev: The IIO device | |
| 219 | + * @trigger_handler: Optional trigger handler, may be NULL. | |
| 220 | + * | |
| 221 | + * Returns 0 on success, a negative error code otherwise. | |
| 222 | + * | |
| 223 | + * This function perfoms exactly the same as adis_setup_buffer_and_trigger() | |
| 224 | + */ | |
| 225 | +int | |
| 226 | +devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, | |
| 227 | + irq_handler_t trigger_handler) | |
| 228 | +{ | |
| 229 | + int ret; | |
| 230 | + | |
| 231 | + if (!trigger_handler) | |
| 232 | + trigger_handler = adis_trigger_handler; | |
| 233 | + | |
| 234 | + ret = devm_iio_triggered_buffer_setup(&adis->spi->dev, indio_dev, | |
| 235 | + &iio_pollfunc_store_time, | |
| 236 | + trigger_handler, NULL); | |
| 237 | + if (ret) | |
| 238 | + return ret; | |
| 239 | + | |
| 240 | + if (adis->spi->irq) { | |
| 241 | + ret = devm_adis_probe_trigger(adis, indio_dev); | |
| 242 | + if (ret) | |
| 243 | + return ret; | |
| 244 | + } | |
| 245 | + | |
| 246 | + return devm_add_action_or_reset(&adis->spi->dev, adis_buffer_cleanup, | |
| 247 | + adis); | |
| 248 | +} | |
| 249 | +EXPORT_SYMBOL_GPL(devm_adis_setup_buffer_and_trigger); | |
| 250 | + | |
| 201 | 251 | /** |
| 202 | 252 | * adis_cleanup_buffer_and_trigger() - Free buffer and trigger resources |
| 203 | 253 | * @adis: The adis device. |
| @@ -27,6 +27,34 @@ static const struct iio_trigger_ops adis_trigger_ops = { · 26 unmodified lines | ||
| 27 | 27 | .set_trigger_state = &adis_data_rdy_trigger_set_state, |
| 28 | 28 | }; |
| 29 | 29 | |
| 30 | +static void adis_trigger_setup(struct adis *adis) | |
| 31 | +{ | |
| 32 | + adis->trig->dev.parent = &adis->spi->dev; | |
| 33 | + adis->trig->ops = &adis_trigger_ops; | |
| 34 | + iio_trigger_set_drvdata(adis->trig, adis); | |
| 35 | +} | |
| 36 | + | |
| 37 | +static int adis_validate_irq_flag(struct adis *adis) | |
| 38 | +{ | |
| 39 | + /* | |
| 40 | + * Typically this devices have data ready either on the rising edge or | |
| 41 | + * on the falling edge of the data ready pin. This checks enforces that | |
| 42 | + * one of those is set in the drivers... It defaults to | |
| 43 | + * IRQF_TRIGGER_RISING for backward compatibility wiht devices that | |
| 44 | + * don't support changing the pin polarity. | |
| 45 | + */ | |
| 46 | + if (!adis->irq_flag) { | |
| 47 | + adis->irq_flag = IRQF_TRIGGER_RISING; | |
| 48 | + return 0; | |
| 49 | + } else if (adis->irq_flag != IRQF_TRIGGER_RISING && | |
| 50 | + adis->irq_flag != IRQF_TRIGGER_FALLING) { | |
| 51 | + dev_err(&adis->spi->dev, "Invalid IRQ mask: %08lx\n", | |
| 52 | + adis->irq_flag); | |
| 53 | + return -EINVAL; | |
| 54 | + } | |
| 55 | + | |
| 56 | + return 0; | |
| 57 | +} | |
| 30 | 58 | /** |
| 31 | 59 | * adis_probe_trigger() - Sets up trigger for a adis device |
| 32 | 60 | * @adis: The adis device |
| @@ -45,13 +73,15 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) · 12 unmodified lines | ||
| 45 | 73 | if (adis->trig == NULL) |
| 46 | 74 | return -ENOMEM; |
| 47 | 75 | |
| 48 | − adis->trig->dev.parent = &adis->spi->dev; | |
| 49 | − adis->trig->ops = &adis_trigger_ops; | |
| 50 | − iio_trigger_set_drvdata(adis->trig, adis); | |
| 76 | + adis_trigger_setup(adis); | |
| 77 | + | |
| 78 | + ret = adis_validate_irq_flag(adis); | |
| 79 | + if (ret) | |
| 80 | + return ret; | |
| 51 | 81 | |
| 52 | 82 | ret = request_irq(adis->spi->irq, |
| 53 | 83 | &iio_trigger_generic_data_rdy_poll, |
| 54 | − IRQF_TRIGGER_RISING, | |
| 84 | + adis->irq_flag, | |
| 55 | 85 | indio_dev->name, |
| 56 | 86 | adis->trig); |
| 57 | 87 | if (ret) |
| @@ -73,6 +103,40 @@ error_free_trig: · 15 unmodified lines | ||
| 73 | 103 | } |
| 74 | 104 | EXPORT_SYMBOL_GPL(adis_probe_trigger); |
| 75 | 105 | |
| 106 | +/** | |
| 107 | + * devm_adis_probe_trigger() - Sets up trigger for a managed adis device | |
| 108 | + * @adis: The adis device | |
| 109 | + * @indio_dev: The IIO device | |
| 110 | + * | |
| 111 | + * Returns 0 on success or a negative error code | |
| 112 | + */ | |
| 113 | +int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) | |
| 114 | +{ | |
| 115 | + int ret; | |
| 116 | + | |
| 117 | + adis->trig = devm_iio_trigger_alloc(&adis->spi->dev, "%s-dev%d", | |
| 118 | + indio_dev->name, indio_dev->id); | |
| 119 | + if (!adis->trig) | |
| 120 | + return -ENOMEM; | |
| 121 | + | |
| 122 | + adis_trigger_setup(adis); | |
| 123 | + | |
| 124 | + ret = adis_validate_irq_flag(adis); | |
| 125 | + if (ret) | |
| 126 | + return ret; | |
| 127 | + | |
| 128 | + ret = devm_request_irq(&adis->spi->dev, adis->spi->irq, | |
| 129 | + &iio_trigger_generic_data_rdy_poll, | |
| 130 | + adis->irq_flag, | |
| 131 | + indio_dev->name, | |
| 132 | + adis->trig); | |
| 133 | + if (ret) | |
| 134 | + return ret; | |
| 135 | + | |
| 136 | + return devm_iio_trigger_register(&adis->spi->dev, adis->trig); | |
| 137 | +} | |
| 138 | +EXPORT_SYMBOL_GPL(devm_adis_probe_trigger); | |
| 139 | + | |
| 76 | 140 | /** |
| 77 | 141 | * adis_remove_trigger() - Remove trigger for a adis devices |
| 78 | 142 | * @adis: The adis device |
| @@ -27,7 +27,8 @@ · 26 unmodified lines | ||
| 27 | 27 | * - FIFO size: 4KB |
| 28 | 28 | * |
| 29 | 29 | * - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX: |
| 30 | − * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 | |
| 30 | + * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416, | |
| 31 | + * 833 | |
| 31 | 32 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 |
| 32 | 33 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 |
| 33 | 34 | * - FIFO size: 3KB |
| @@ -791,7 +792,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 757 unmodified lines | ||
| 791 | 792 | .odr_avl[3] = { 104000, 0x04 }, |
| 792 | 793 | .odr_avl[4] = { 208000, 0x05 }, |
| 793 | 794 | .odr_avl[5] = { 416000, 0x06 }, |
| 794 | − .odr_len = 6, | |
| 795 | + .odr_avl[6] = { 833000, 0x07 }, | |
| 796 | + .odr_len = 7, | |
| 795 | 797 | }, |
| 796 | 798 | [ST_LSM6DSX_ID_GYRO] = { |
| 797 | 799 | .reg = { |
| @@ -804,7 +806,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 6 unmodified lines | ||
| 804 | 806 | .odr_avl[3] = { 104000, 0x04 }, |
| 805 | 807 | .odr_avl[4] = { 208000, 0x05 }, |
| 806 | 808 | .odr_avl[5] = { 416000, 0x06 }, |
| 807 | − .odr_len = 6, | |
| 809 | + .odr_avl[6] = { 833000, 0x07 }, | |
| 810 | + .odr_len = 7, | |
| 808 | 811 | }, |
| 809 | 812 | }, |
| 810 | 813 | .fs_table = { |
| @@ -994,7 +997,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 183 unmodified lines | ||
| 994 | 997 | .odr_avl[3] = { 104000, 0x04 }, |
| 995 | 998 | .odr_avl[4] = { 208000, 0x05 }, |
| 996 | 999 | .odr_avl[5] = { 416000, 0x06 }, |
| 997 | − .odr_len = 6, | |
| 1000 | + .odr_avl[6] = { 833000, 0x07 }, | |
| 1001 | + .odr_len = 7, | |
| 998 | 1002 | }, |
| 999 | 1003 | [ST_LSM6DSX_ID_GYRO] = { |
| 1000 | 1004 | .reg = { |
| @@ -1007,7 +1011,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 6 unmodified lines | ||
| 1007 | 1011 | .odr_avl[3] = { 104000, 0x04 }, |
| 1008 | 1012 | .odr_avl[4] = { 208000, 0x05 }, |
| 1009 | 1013 | .odr_avl[5] = { 416000, 0x06 }, |
| 1010 | − .odr_len = 6, | |
| 1014 | + .odr_avl[6] = { 833000, 0x07 }, | |
| 1015 | + .odr_len = 7, | |
| 1011 | 1016 | }, |
| 1012 | 1017 | }, |
| 1013 | 1018 | .fs_table = { |
| @@ -1171,7 +1176,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 157 unmodified lines | ||
| 1171 | 1176 | .odr_avl[3] = { 104000, 0x04 }, |
| 1172 | 1177 | .odr_avl[4] = { 208000, 0x05 }, |
| 1173 | 1178 | .odr_avl[5] = { 416000, 0x06 }, |
| 1174 | − .odr_len = 6, | |
| 1179 | + .odr_avl[6] = { 833000, 0x07 }, | |
| 1180 | + .odr_len = 7, | |
| 1175 | 1181 | }, |
| 1176 | 1182 | [ST_LSM6DSX_ID_GYRO] = { |
| 1177 | 1183 | .reg = { |
| @@ -1184,7 +1190,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 6 unmodified lines | ||
| 1184 | 1190 | .odr_avl[3] = { 104000, 0x04 }, |
| 1185 | 1191 | .odr_avl[4] = { 208000, 0x05 }, |
| 1186 | 1192 | .odr_avl[5] = { 416000, 0x06 }, |
| 1187 | − .odr_len = 6, | |
| 1193 | + .odr_avl[6] = { 833000, 0x07 }, | |
| 1194 | + .odr_len = 7, | |
| 1188 | 1195 | }, |
| 1189 | 1196 | }, |
| 1190 | 1197 | .fs_table = { |
| @@ -189,10 +189,12 @@ __poll_t iio_buffer_poll(struct file *filp, · 188 unmodified lines | ||
| 189 | 189 | */ |
| 190 | 190 | void iio_buffer_wakeup_poll(struct iio_dev *indio_dev) |
| 191 | 191 | { |
| 192 | − if (!indio_dev->buffer) | |
| 192 | + struct iio_buffer *buffer = indio_dev->buffer; | |
| 193 | + | |
| 194 | + if (!buffer) | |
| 193 | 195 | return; |
| 194 | 196 | |
| 195 | − wake_up(&indio_dev->buffer->pollq); | |
| 197 | + wake_up(&buffer->pollq); | |
| 196 | 198 | } |
| 197 | 199 | |
| 198 | 200 | void iio_buffer_init(struct iio_buffer *buffer) |
| @@ -262,10 +264,11 @@ static ssize_t iio_scan_el_show(struct device *dev, · 63 unmodified lines | ||
| 262 | 264 | { |
| 263 | 265 | int ret; |
| 264 | 266 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
| 267 | + struct iio_buffer *buffer = indio_dev->buffer; | |
| 265 | 268 | |
| 266 | 269 | /* Ensure ret is 0 or 1. */ |
| 267 | 270 | ret = !!test_bit(to_iio_dev_attr(attr)->address, |
| 268 | − indio_dev->buffer->scan_mask); | |
| 271 | + buffer->scan_mask); | |
| 269 | 272 | |
| 270 | 273 | return sprintf(buf, "%d\n", ret); |
| 271 | 274 | } |
| @@ -381,7 +384,7 @@ static ssize_t iio_scan_el_store(struct device *dev, · 109 unmodified lines | ||
| 381 | 384 | if (ret < 0) |
| 382 | 385 | return ret; |
| 383 | 386 | mutex_lock(&indio_dev->mlock); |
| 384 | − if (iio_buffer_is_active(indio_dev->buffer)) { | |
| 387 | + if (iio_buffer_is_active(buffer)) { | |
| 385 | 388 | ret = -EBUSY; |
| 386 | 389 | goto error_ret; |
| 387 | 390 | } |
| @@ -410,7 +413,9 @@ static ssize_t iio_scan_el_ts_show(struct device *dev, · 22 unmodified lines | ||
| 410 | 413 | char *buf) |
| 411 | 414 | { |
| 412 | 415 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
| 413 | − return sprintf(buf, "%d\n", indio_dev->buffer->scan_timestamp); | |
| 416 | + struct iio_buffer *buffer = indio_dev->buffer; | |
| 417 | + | |
| 418 | + return sprintf(buf, "%d\n", buffer->scan_timestamp); | |
| 414 | 419 | } |
| 415 | 420 | |
| 416 | 421 | static ssize_t iio_scan_el_ts_store(struct device *dev, |
| @@ -420,6 +425,7 @@ static ssize_t iio_scan_el_ts_store(struct device *dev, · 3 unmodified lines | ||
| 420 | 425 | { |
| 421 | 426 | int ret; |
| 422 | 427 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
| 428 | + struct iio_buffer *buffer = indio_dev->buffer; | |
| 423 | 429 | bool state; |
| 424 | 430 | |
| 425 | 431 | ret = strtobool(buf, &state); |
| @@ -427,11 +433,11 @@ static ssize_t iio_scan_el_ts_store(struct device *dev, · 1 unmodified line | ||
| 427 | 433 | return ret; |
| 428 | 434 | |
| 429 | 435 | mutex_lock(&indio_dev->mlock); |
| 430 | − if (iio_buffer_is_active(indio_dev->buffer)) { | |
| 436 | + if (iio_buffer_is_active(buffer)) { | |
| 431 | 437 | ret = -EBUSY; |
| 432 | 438 | goto error_ret; |
| 433 | 439 | } |
| 434 | − indio_dev->buffer->scan_timestamp = state; | |
| 440 | + buffer->scan_timestamp = state; | |
| 435 | 441 | error_ret: |
| 436 | 442 | mutex_unlock(&indio_dev->mlock); |
| 437 | 443 | |
| @@ -439,10 +445,10 @@ error_ret: · 1 unmodified line | ||
| 439 | 445 | } |
| 440 | 446 | |
| 441 | 447 | static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev, |
| 448 | + struct iio_buffer *buffer, | |
| 442 | 449 | const struct iio_chan_spec *chan) |
| 443 | 450 | { |
| 444 | 451 | int ret, attrcount = 0; |
| 445 | − struct iio_buffer *buffer = indio_dev->buffer; | |
| 446 | 452 | |
| 447 | 453 | ret = __iio_add_chan_devattr("index", |
| 448 | 454 | chan, |
| @@ -518,7 +524,7 @@ static ssize_t iio_buffer_write_length(struct device *dev, · 69 unmodified lines | ||
| 518 | 524 | return len; |
| 519 | 525 | |
| 520 | 526 | mutex_lock(&indio_dev->mlock); |
| 521 | − if (iio_buffer_is_active(indio_dev->buffer)) { | |
| 527 | + if (iio_buffer_is_active(buffer)) { | |
| 522 | 528 | ret = -EBUSY; |
| 523 | 529 | } else { |
| 524 | 530 | buffer->access->set_length(buffer, val); |
| @@ -539,7 +545,9 @@ static ssize_t iio_buffer_show_enable(struct device *dev, · 14 unmodified lines | ||
| 539 | 545 | char *buf) |
| 540 | 546 | { |
| 541 | 547 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
| 542 | − return sprintf(buf, "%d\n", iio_buffer_is_active(indio_dev->buffer)); | |
| 548 | + struct iio_buffer *buffer = indio_dev->buffer; | |
| 549 | + | |
| 550 | + return sprintf(buf, "%d\n", iio_buffer_is_active(buffer)); | |
| 543 | 551 | } |
| 544 | 552 | |
| 545 | 553 | static unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev, |
| @@ -1129,6 +1137,7 @@ static ssize_t iio_buffer_store_enable(struct device *dev, · 583 unmodified lines | ||
| 1129 | 1137 | int ret; |
| 1130 | 1138 | bool requested_state; |
| 1131 | 1139 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
| 1140 | + struct iio_buffer *buffer = indio_dev->buffer; | |
| 1132 | 1141 | bool inlist; |
| 1133 | 1142 | |
| 1134 | 1143 | ret = strtobool(buf, &requested_state); |
| @@ -1138,17 +1147,15 @@ static ssize_t iio_buffer_store_enable(struct device *dev, · 3 unmodified lines | ||
| 1138 | 1147 | mutex_lock(&indio_dev->mlock); |
| 1139 | 1148 | |
| 1140 | 1149 | /* Find out if it is in the list */ |
| 1141 | − inlist = iio_buffer_is_active(indio_dev->buffer); | |
| 1150 | + inlist = iio_buffer_is_active(buffer); | |
| 1142 | 1151 | /* Already in desired state */ |
| 1143 | 1152 | if (inlist == requested_state) |
| 1144 | 1153 | goto done; |
| 1145 | 1154 | |
| 1146 | 1155 | if (requested_state) |
| 1147 | − ret = __iio_update_buffers(indio_dev, | |
| 1148 | − indio_dev->buffer, NULL); | |
| 1156 | + ret = __iio_update_buffers(indio_dev, buffer, NULL); | |
| 1149 | 1157 | else |
| 1150 | − ret = __iio_update_buffers(indio_dev, | |
| 1151 | − NULL, indio_dev->buffer); | |
| 1158 | + ret = __iio_update_buffers(indio_dev, NULL, buffer); | |
| 1152 | 1159 | |
| 1153 | 1160 | done: |
| 1154 | 1161 | mutex_unlock(&indio_dev->mlock); |
| @@ -1190,7 +1197,7 @@ static ssize_t iio_buffer_store_watermark(struct device *dev, · 35 unmodified lines | ||
| 1190 | 1197 | goto out; |
| 1191 | 1198 | } |
| 1192 | 1199 | |
| 1193 | − if (iio_buffer_is_active(indio_dev->buffer)) { | |
| 1200 | + if (iio_buffer_is_active(buffer)) { | |
| 1194 | 1201 | ret = -EBUSY; |
| 1195 | 1202 | goto out; |
| 1196 | 1203 | } |
| @@ -1207,11 +1214,9 @@ static ssize_t iio_dma_show_data_available(struct device *dev, · 10 unmodified lines | ||
| 1207 | 1214 | char *buf) |
| 1208 | 1215 | { |
| 1209 | 1216 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
| 1210 | − size_t bytes; | |
| 1211 | − | |
| 1212 | − bytes = iio_buffer_data_available(indio_dev->buffer); | |
| 1217 | + struct iio_buffer *buffer = indio_dev->buffer; | |
| 1213 | 1218 | |
| 1214 | − return sprintf(buf, "%zu\n", bytes); | |
| 1219 | + return sprintf(buf, "%zu\n", iio_buffer_data_available(buffer)); | |
| 1215 | 1220 | } |
| 1216 | 1221 | |
| 1217 | 1222 | static DEVICE_ATTR(length, S_IRUGO | S_IWUSR, iio_buffer_read_length, |
| @@ -1292,7 +1297,7 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) · 74 unmodified lines | ||
| 1292 | 1297 | if (channels[i].scan_index < 0) |
| 1293 | 1298 | continue; |
| 1294 | 1299 | |
| 1295 | − ret = iio_buffer_add_channel_sysfs(indio_dev, | |
| 1300 | + ret = iio_buffer_add_channel_sysfs(indio_dev, buffer, | |
| 1296 | 1301 | &channels[i]); |
| 1297 | 1302 | if (ret < 0) |
| 1298 | 1303 | goto error_cleanup_dynamic; |
| @@ -1332,20 +1337,22 @@ error_free_scan_mask: · 33 unmodified lines | ||
| 1332 | 1337 | bitmap_free(buffer->scan_mask); |
| 1333 | 1338 | error_cleanup_dynamic: |
| 1334 | 1339 | iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list); |
| 1335 | − kfree(indio_dev->buffer->buffer_group.attrs); | |
| 1340 | + kfree(buffer->buffer_group.attrs); | |
| 1336 | 1341 | |
| 1337 | 1342 | return ret; |
| 1338 | 1343 | } |
| 1339 | 1344 | |
| 1340 | 1345 | void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) |
| 1341 | 1346 | { |
| 1342 | − if (!indio_dev->buffer) | |
| 1347 | + struct iio_buffer *buffer = indio_dev->buffer; | |
| 1348 | + | |
| 1349 | + if (!buffer) | |
| 1343 | 1350 | return; |
| 1344 | 1351 | |
| 1345 | − bitmap_free(indio_dev->buffer->scan_mask); | |
| 1346 | − kfree(indio_dev->buffer->buffer_group.attrs); | |
| 1347 | − kfree(indio_dev->buffer->scan_el_group.attrs); | |
| 1348 | − iio_free_chan_devattr_list(&indio_dev->buffer->scan_el_dev_attr_list); | |
| 1352 | + bitmap_free(buffer->scan_mask); | |
| 1353 | + kfree(buffer->buffer_group.attrs); | |
| 1354 | + kfree(buffer->scan_el_group.attrs); | |
| 1355 | + iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list); | |
| 1349 | 1356 | } |
| 1350 | 1357 | |
| 1351 | 1358 | /** |
| @@ -1507,27 +1507,27 @@ struct iio_dev *iio_device_alloc(int sizeof_priv) · 1506 unmodified lines | ||
| 1507 | 1507 | alloc_size += IIO_ALIGN - 1; |
| 1508 | 1508 | |
| 1509 | 1509 | dev = kzalloc(alloc_size, GFP_KERNEL); |
| 1510 | + if (!dev) | |
| 1511 | + return NULL; | |
| 1510 | 1512 | |
| 1511 | − if (dev) { | |
| 1512 | − dev->dev.groups = dev->groups; | |
| 1513 | − dev->dev.type = &iio_device_type; | |
| 1514 | − dev->dev.bus = &iio_bus_type; | |
| 1515 | − device_initialize(&dev->dev); | |
| 1516 | − dev_set_drvdata(&dev->dev, (void *)dev); | |
| 1517 | − mutex_init(&dev->mlock); | |
| 1518 | − mutex_init(&dev->info_exist_lock); | |
| 1519 | − INIT_LIST_HEAD(&dev->channel_attr_list); | |
| 1520 | − | |
| 1521 | − dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); | |
| 1522 | − if (dev->id < 0) { | |
| 1523 | − /* cannot use a dev_err as the name isn't available */ | |
| 1524 | − pr_err("failed to get device id\n"); | |
| 1525 | − kfree(dev); | |
| 1526 | − return NULL; | |
| 1527 | − } | |
| 1528 | − dev_set_name(&dev->dev, "iio:device%d", dev->id); | |
| 1529 | − INIT_LIST_HEAD(&dev->buffer_list); | |
| 1513 | + dev->dev.groups = dev->groups; | |
| 1514 | + dev->dev.type = &iio_device_type; | |
| 1515 | + dev->dev.bus = &iio_bus_type; | |
| 1516 | + device_initialize(&dev->dev); | |
| 1517 | + dev_set_drvdata(&dev->dev, (void *)dev); | |
| 1518 | + mutex_init(&dev->mlock); | |
| 1519 | + mutex_init(&dev->info_exist_lock); | |
| 1520 | + INIT_LIST_HEAD(&dev->channel_attr_list); | |
| 1521 | + | |
| 1522 | + dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); | |
| 1523 | + if (dev->id < 0) { | |
| 1524 | + /* cannot use a dev_err as the name isn't available */ | |
| 1525 | + pr_err("failed to get device id\n"); | |
| 1526 | + kfree(dev); | |
| 1527 | + return NULL; | |
| 1530 | 1528 | } |
| 1529 | + dev_set_name(&dev->dev, "iio:device%d", dev->id); | |
| 1530 | + INIT_LIST_HEAD(&dev->buffer_list); | |
| 1531 | 1531 | |
| 1532 | 1532 | return dev; |
| 1533 | 1533 | } |
| @@ -516,6 +516,8 @@ config US5182D · 515 unmodified lines | ||
| 516 | 516 | |
| 517 | 517 | config VCNL4000 |
| 518 | 518 | tristate "VCNL4000/4010/4020/4200 combined ALS and proximity sensor" |
| 519 | + select IIO_BUFFER | |
| 520 | + select IIO_TRIGGERED_BUFFER | |
| 519 | 521 | depends on I2C |
| 520 | 522 | help |
| 521 | 523 | Say Y here if you want to build a driver for the Vishay VCNL4000, |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/platform_device.h> |
| 14 | 14 | #include <linux/delay.h> |
| 15 | 15 | #include <linux/module.h> |
| 16 | −#include <linux/of.h> | |
| 16 | +#include <linux/mod_devicetable.h> | |
| 17 | 17 | #include <linux/pm_runtime.h> |
| 18 | 18 | #include <linux/iio/iio.h> |
| 19 | 19 | #include <linux/iio/sysfs.h> |
| @@ -273,13 +273,11 @@ static const struct i2c_device_id bh1780_id[] = { · 253 unmodified lines | ||
| 273 | 273 | |
| 274 | 274 | MODULE_DEVICE_TABLE(i2c, bh1780_id); |
| 275 | 275 | |
| 276 | −#ifdef CONFIG_OF | |
| 277 | 276 | static const struct of_device_id of_bh1780_match[] = { |
| 278 | 277 | { .compatible = "rohm,bh1780gli", }, |
| 279 | 278 | {}, |
| 280 | 279 | }; |
| 281 | 280 | MODULE_DEVICE_TABLE(of, of_bh1780_match); |
| 282 | −#endif | |
| 283 | 281 | |
| 284 | 282 | static struct i2c_driver bh1780_driver = { |
| 285 | 283 | .probe = bh1780_probe, |
| @@ -288,7 +286,7 @@ static struct i2c_driver bh1780_driver = { · 2 unmodified lines | ||
| 288 | 286 | .driver = { |
| 289 | 287 | .name = "bh1780", |
| 290 | 288 | .pm = &bh1780_dev_pm_ops, |
| 291 | − .of_match_table = of_match_ptr(of_bh1780_match), | |
| 289 | + .of_match_table = of_bh1780_match, | |
| 292 | 290 | }, |
| 293 | 291 | }; |
| 294 | 292 | |
| @@ -4,11 +4,13 @@ · 3 unmodified lines | ||
| 4 | 4 | * Author: Kevin Tsai <ktsai@capellamicro.com> |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | +#include <linux/acpi.h> | |
| 7 | 8 | #include <linux/delay.h> |
| 8 | 9 | #include <linux/err.h> |
| 9 | 10 | #include <linux/i2c.h> |
| 10 | 11 | #include <linux/mutex.h> |
| 11 | 12 | #include <linux/module.h> |
| 13 | +#include <linux/mod_devicetable.h> | |
| 12 | 14 | #include <linux/interrupt.h> |
| 13 | 15 | #include <linux/regulator/consumer.h> |
| 14 | 16 | #include <linux/iio/iio.h> |
| @@ -18,17 +20,24 @@ · 3 unmodified lines | ||
| 18 | 20 | |
| 19 | 21 | /* Registers Address */ |
| 20 | 22 | #define CM32181_REG_ADDR_CMD 0x00 |
| 23 | +#define CM32181_REG_ADDR_WH 0x01 | |
| 24 | +#define CM32181_REG_ADDR_WL 0x02 | |
| 25 | +#define CM32181_REG_ADDR_TEST 0x03 | |
| 21 | 26 | #define CM32181_REG_ADDR_ALS 0x04 |
| 22 | 27 | #define CM32181_REG_ADDR_STATUS 0x06 |
| 23 | 28 | #define CM32181_REG_ADDR_ID 0x07 |
| 24 | 29 | |
| 25 | 30 | /* Number of Configurable Registers */ |
| 26 | −#define CM32181_CONF_REG_NUM 0x01 | |
| 31 | +#define CM32181_CONF_REG_NUM 4 | |
| 27 | 32 | |
| 28 | 33 | /* CMD register */ |
| 29 | −#define CM32181_CMD_ALS_ENABLE 0x00 | |
| 30 | −#define CM32181_CMD_ALS_DISABLE 0x01 | |
| 31 | −#define CM32181_CMD_ALS_INT_EN 0x02 | |
| 34 | +#define CM32181_CMD_ALS_DISABLE BIT(0) | |
| 35 | +#define CM32181_CMD_ALS_INT_EN BIT(1) | |
| 36 | +#define CM32181_CMD_ALS_THRES_WINDOW BIT(2) | |
| 37 | + | |
| 38 | +#define CM32181_CMD_ALS_PERS_SHIFT 4 | |
| 39 | +#define CM32181_CMD_ALS_PERS_MASK (0x03 << CM32181_CMD_ALS_PERS_SHIFT) | |
| 40 | +#define CM32181_CMD_ALS_PERS_DEFAULT (0x01 << CM32181_CMD_ALS_PERS_SHIFT) | |
| 32 | 41 | |
| 33 | 42 | #define CM32181_CMD_ALS_IT_SHIFT 6 |
| 34 | 43 | #define CM32181_CMD_ALS_IT_MASK (0x0F << CM32181_CMD_ALS_IT_SHIFT) |
| @@ -38,27 +47,133 @@ · 3 unmodified lines | ||
| 38 | 47 | #define CM32181_CMD_ALS_SM_MASK (0x03 << CM32181_CMD_ALS_SM_SHIFT) |
| 39 | 48 | #define CM32181_CMD_ALS_SM_DEFAULT (0x01 << CM32181_CMD_ALS_SM_SHIFT) |
| 40 | 49 | |
| 41 | −#define CM32181_MLUX_PER_BIT 5 /* ALS_SM=01 IT=800ms */ | |
| 42 | −#define CM32181_MLUX_PER_BIT_BASE_IT 800000 /* Based on IT=800ms */ | |
| 43 | −#define CM32181_CALIBSCALE_DEFAULT 1000 | |
| 44 | −#define CM32181_CALIBSCALE_RESOLUTION 1000 | |
| 45 | −#define MLUX_PER_LUX 1000 | |
| 50 | +#define CM32181_LUX_PER_BIT 500 /* ALS_SM=01 IT=800ms */ | |
| 51 | +#define CM32181_LUX_PER_BIT_RESOLUTION 100000 | |
| 52 | +#define CM32181_LUX_PER_BIT_BASE_IT 800000 /* Based on IT=800ms */ | |
| 53 | +#define CM32181_CALIBSCALE_DEFAULT 100000 | |
| 54 | +#define CM32181_CALIBSCALE_RESOLUTION 100000 | |
| 46 | 55 | |
| 47 | −static const u8 cm32181_reg[CM32181_CONF_REG_NUM] = { | |
| 48 | − CM32181_REG_ADDR_CMD, | |
| 49 | −}; | |
| 56 | +#define SMBUS_ALERT_RESPONSE_ADDRESS 0x0c | |
| 57 | + | |
| 58 | +/* CPM0 Index 0: device-id (3218 or 32181), 1: Unknown, 2: init_regs_bitmap */ | |
| 59 | +#define CPM0_REGS_BITMAP 2 | |
| 60 | +#define CPM0_HEADER_SIZE 3 | |
| 50 | 61 | |
| 51 | −static const int als_it_bits[] = {12, 8, 0, 1, 2, 3}; | |
| 52 | −static const int als_it_value[] = {25000, 50000, 100000, 200000, 400000, | |
| 53 | − 800000}; | |
| 62 | +/* CPM1 Index 0: lux_per_bit, 1: calibscale, 2: resolution (100000) */ | |
| 63 | +#define CPM1_LUX_PER_BIT 0 | |
| 64 | +#define CPM1_CALIBSCALE 1 | |
| 65 | +#define CPM1_SIZE 3 | |
| 66 | + | |
| 67 | +/* CM3218 Family */ | |
| 68 | +static const int cm3218_als_it_bits[] = { 0, 1, 2, 3 }; | |
| 69 | +static const int cm3218_als_it_values[] = { 100000, 200000, 400000, 800000 }; | |
| 70 | + | |
| 71 | +/* CM32181 Family */ | |
| 72 | +static const int cm32181_als_it_bits[] = { 12, 8, 0, 1, 2, 3 }; | |
| 73 | +static const int cm32181_als_it_values[] = { | |
| 74 | + 25000, 50000, 100000, 200000, 400000, 800000 | |
| 75 | +}; | |
| 54 | 76 | |
| 55 | 77 | struct cm32181_chip { |
| 56 | 78 | struct i2c_client *client; |
| 79 | + struct device *dev; | |
| 57 | 80 | struct mutex lock; |
| 58 | 81 | u16 conf_regs[CM32181_CONF_REG_NUM]; |
| 82 | + unsigned long init_regs_bitmap; | |
| 59 | 83 | int calibscale; |
| 84 | + int lux_per_bit; | |
| 85 | + int lux_per_bit_base_it; | |
| 86 | + int num_als_it; | |
| 87 | + const int *als_it_bits; | |
| 88 | + const int *als_it_values; | |
| 60 | 89 | }; |
| 61 | 90 | |
| 91 | +static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val2); | |
| 92 | + | |
| 93 | +#ifdef CONFIG_ACPI | |
| 94 | +/** | |
| 95 | + * cm32181_acpi_get_cpm() - Get CPM object from ACPI | |
| 96 | + * @client pointer of struct i2c_client. | |
| 97 | + * @obj_name pointer of ACPI object name. | |
| 98 | + * @count maximum size of return array. | |
| 99 | + * @vals pointer of array for return elements. | |
| 100 | + * | |
| 101 | + * Convert ACPI CPM table to array. | |
| 102 | + * | |
| 103 | + * Return: -ENODEV for fail. Otherwise is number of elements. | |
| 104 | + */ | |
| 105 | +static int cm32181_acpi_get_cpm(struct device *dev, char *obj_name, | |
| 106 | + u64 *values, int count) | |
| 107 | +{ | |
| 108 | + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | |
| 109 | + union acpi_object *cpm, *elem; | |
| 110 | + acpi_handle handle; | |
| 111 | + acpi_status status; | |
| 112 | + int i; | |
| 113 | + | |
| 114 | + handle = ACPI_HANDLE(dev); | |
| 115 | + if (!handle) | |
| 116 | + return -ENODEV; | |
| 117 | + | |
| 118 | + status = acpi_evaluate_object(handle, obj_name, NULL, &buffer); | |
| 119 | + if (ACPI_FAILURE(status)) { | |
| 120 | + dev_err(dev, "object %s not found\n", obj_name); | |
| 121 | + return -ENODEV; | |
| 122 | + } | |
| 123 | + | |
| 124 | + cpm = buffer.pointer; | |
| 125 | + if (cpm->package.count > count) | |
| 126 | + dev_warn(dev, "%s table contains %u values, only using first %d values\n", | |
| 127 | + obj_name, cpm->package.count, count); | |
| 128 | + | |
| 129 | + count = min_t(int, cpm->package.count, count); | |
| 130 | + for (i = 0; i < count; i++) { | |
| 131 | + elem = &(cpm->package.elements[i]); | |
| 132 | + values[i] = elem->integer.value; | |
| 133 | + } | |
| 134 | + | |
| 135 | + kfree(buffer.pointer); | |
| 136 | + | |
| 137 | + return count; | |
| 138 | +} | |
| 139 | + | |
| 140 | +static void cm32181_acpi_parse_cpm_tables(struct cm32181_chip *cm32181) | |
| 141 | +{ | |
| 142 | + u64 vals[CPM0_HEADER_SIZE + CM32181_CONF_REG_NUM]; | |
| 143 | + struct device *dev = cm32181->dev; | |
| 144 | + int i, count; | |
| 145 | + | |
| 146 | + count = cm32181_acpi_get_cpm(dev, "CPM0", vals, ARRAY_SIZE(vals)); | |
| 147 | + if (count <= CPM0_HEADER_SIZE) | |
| 148 | + return; | |
| 149 | + | |
| 150 | + count -= CPM0_HEADER_SIZE; | |
| 151 | + | |
| 152 | + cm32181->init_regs_bitmap = vals[CPM0_REGS_BITMAP]; | |
| 153 | + cm32181->init_regs_bitmap &= GENMASK(count - 1, 0); | |
| 154 | + for_each_set_bit(i, &cm32181->init_regs_bitmap, count) | |
| 155 | + cm32181->conf_regs[i] = vals[CPM0_HEADER_SIZE + i]; | |
| 156 | + | |
| 157 | + count = cm32181_acpi_get_cpm(dev, "CPM1", vals, ARRAY_SIZE(vals)); | |
| 158 | + if (count != CPM1_SIZE) | |
| 159 | + return; | |
| 160 | + | |
| 161 | + cm32181->lux_per_bit = vals[CPM1_LUX_PER_BIT]; | |
| 162 | + | |
| 163 | + /* Check for uncalibrated devices */ | |
| 164 | + if (vals[CPM1_CALIBSCALE] == CM32181_CALIBSCALE_DEFAULT) | |
| 165 | + return; | |
| 166 | + | |
| 167 | + cm32181->calibscale = vals[CPM1_CALIBSCALE]; | |
| 168 | + /* CPM1 lux_per_bit is for the current it value */ | |
| 169 | + cm32181_read_als_it(cm32181, &cm32181->lux_per_bit_base_it); | |
| 170 | +} | |
| 171 | +#else | |
| 172 | +static void cm32181_acpi_parse_cpm_tables(struct cm32181_chip *cm32181) | |
| 173 | +{ | |
| 174 | +} | |
| 175 | +#endif /* CONFIG_ACPI */ | |
| 176 | + | |
| 62 | 177 | /** |
| 63 | 178 | * cm32181_reg_init() - Initialize CM32181 registers |
| 64 | 179 | * @cm32181: pointer of struct cm32181. |
| @@ -78,18 +193,37 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181) · 13 unmodified lines | ||
| 78 | 193 | return ret; |
| 79 | 194 | |
| 80 | 195 | /* check device ID */ |
| 81 | − if ((ret & 0xFF) != 0x81) | |
| 196 | + switch (ret & 0xFF) { | |
| 197 | + case 0x18: /* CM3218 */ | |
| 198 | + cm32181->num_als_it = ARRAY_SIZE(cm3218_als_it_bits); | |
| 199 | + cm32181->als_it_bits = cm3218_als_it_bits; | |
| 200 | + cm32181->als_it_values = cm3218_als_it_values; | |
| 201 | + break; | |
| 202 | + case 0x81: /* CM32181 */ | |
| 203 | + case 0x82: /* CM32182, fully compat. with CM32181 */ | |
| 204 | + cm32181->num_als_it = ARRAY_SIZE(cm32181_als_it_bits); | |
| 205 | + cm32181->als_it_bits = cm32181_als_it_bits; | |
| 206 | + cm32181->als_it_values = cm32181_als_it_values; | |
| 207 | + break; | |
| 208 | + default: | |
| 82 | 209 | return -ENODEV; |
| 210 | + } | |
| 83 | 211 | |
| 84 | 212 | /* Default Values */ |
| 85 | − cm32181->conf_regs[CM32181_REG_ADDR_CMD] = CM32181_CMD_ALS_ENABLE | | |
| 213 | + cm32181->conf_regs[CM32181_REG_ADDR_CMD] = | |
| 86 | 214 | CM32181_CMD_ALS_IT_DEFAULT | CM32181_CMD_ALS_SM_DEFAULT; |
| 215 | + cm32181->init_regs_bitmap = BIT(CM32181_REG_ADDR_CMD); | |
| 87 | 216 | cm32181->calibscale = CM32181_CALIBSCALE_DEFAULT; |
| 217 | + cm32181->lux_per_bit = CM32181_LUX_PER_BIT; | |
| 218 | + cm32181->lux_per_bit_base_it = CM32181_LUX_PER_BIT_BASE_IT; | |
| 219 | + | |
| 220 | + if (ACPI_HANDLE(cm32181->dev)) | |
| 221 | + cm32181_acpi_parse_cpm_tables(cm32181); | |
| 88 | 222 | |
| 89 | 223 | /* Initialize registers*/ |
| 90 | − for (i = 0; i < CM32181_CONF_REG_NUM; i++) { | |
| 91 | − ret = i2c_smbus_write_word_data(client, cm32181_reg[i], | |
| 92 | − cm32181->conf_regs[i]); | |
| 224 | + for_each_set_bit(i, &cm32181->init_regs_bitmap, CM32181_CONF_REG_NUM) { | |
| 225 | + ret = i2c_smbus_write_word_data(client, i, | |
| 226 | + cm32181->conf_regs[i]); | |
| 93 | 227 | if (ret < 0) |
| 94 | 228 | return ret; |
| 95 | 229 | } |
| @@ -102,7 +236,7 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181) · 6 unmodified lines | ||
| 102 | 236 | * @cm32181: pointer of struct cm32181 |
| 103 | 237 | * @val2: pointer of int to load the als_it value. |
| 104 | 238 | * |
| 105 | − * Report the current integartion time by millisecond. | |
| 239 | + * Report the current integration time in milliseconds. | |
| 106 | 240 | * |
| 107 | 241 | * Return: IIO_VAL_INT_PLUS_MICRO for success, otherwise -EINVAL. |
| 108 | 242 | */ |
| @@ -114,9 +248,9 @@ static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val2) · 5 unmodified lines | ||
| 114 | 248 | als_it = cm32181->conf_regs[CM32181_REG_ADDR_CMD]; |
| 115 | 249 | als_it &= CM32181_CMD_ALS_IT_MASK; |
| 116 | 250 | als_it >>= CM32181_CMD_ALS_IT_SHIFT; |
| 117 | − for (i = 0; i < ARRAY_SIZE(als_it_bits); i++) { | |
| 118 | − if (als_it == als_it_bits[i]) { | |
| 119 | − *val2 = als_it_value[i]; | |
| 251 | + for (i = 0; i < cm32181->num_als_it; i++) { | |
| 252 | + if (als_it == cm32181->als_it_bits[i]) { | |
| 253 | + *val2 = cm32181->als_it_values[i]; | |
| 120 | 254 | return IIO_VAL_INT_PLUS_MICRO; |
| 121 | 255 | } |
| 122 | 256 | } |
| @@ -139,14 +273,14 @@ static int cm32181_write_als_it(struct cm32181_chip *cm32181, int val) · 16 unmodified lines | ||
| 139 | 273 | u16 als_it; |
| 140 | 274 | int ret, i, n; |
| 141 | 275 | |
| 142 | − n = ARRAY_SIZE(als_it_value); | |
| 276 | + n = cm32181->num_als_it; | |
| 143 | 277 | for (i = 0; i < n; i++) |
| 144 | − if (val <= als_it_value[i]) | |
| 278 | + if (val <= cm32181->als_it_values[i]) | |
| 145 | 279 | break; |
| 146 | 280 | if (i >= n) |
| 147 | 281 | i = n - 1; |
| 148 | 282 | |
| 149 | − als_it = als_it_bits[i]; | |
| 283 | + als_it = cm32181->als_it_bits[i]; | |
| 150 | 284 | als_it <<= CM32181_CMD_ALS_IT_SHIFT; |
| 151 | 285 | |
| 152 | 286 | mutex_lock(&cm32181->lock); |
| @@ -175,15 +309,15 @@ static int cm32181_get_lux(struct cm32181_chip *cm32181) · 22 unmodified lines | ||
| 175 | 309 | struct i2c_client *client = cm32181->client; |
| 176 | 310 | int ret; |
| 177 | 311 | int als_it; |
| 178 | − unsigned long lux; | |
| 312 | + u64 lux; | |
| 179 | 313 | |
| 180 | 314 | ret = cm32181_read_als_it(cm32181, &als_it); |
| 181 | 315 | if (ret < 0) |
| 182 | 316 | return -EINVAL; |
| 183 | 317 | |
| 184 | − lux = CM32181_MLUX_PER_BIT; | |
| 185 | − lux *= CM32181_MLUX_PER_BIT_BASE_IT; | |
| 186 | − lux /= als_it; | |
| 318 | + lux = cm32181->lux_per_bit; | |
| 319 | + lux *= cm32181->lux_per_bit_base_it; | |
| 320 | + lux = div_u64(lux, als_it); | |
| 187 | 321 | |
| 188 | 322 | ret = i2c_smbus_read_word_data(client, CM32181_REG_ADDR_ALS); |
| 189 | 323 | if (ret < 0) |
| @@ -191,8 +325,8 @@ static int cm32181_get_lux(struct cm32181_chip *cm32181) · 1 unmodified line | ||
| 191 | 325 | |
| 192 | 326 | lux *= ret; |
| 193 | 327 | lux *= cm32181->calibscale; |
| 194 | − lux /= CM32181_CALIBSCALE_RESOLUTION; | |
| 195 | − lux /= MLUX_PER_LUX; | |
| 328 | + lux = div_u64(lux, CM32181_CALIBSCALE_RESOLUTION); | |
| 329 | + lux = div_u64(lux, CM32181_LUX_PER_BIT_RESOLUTION); | |
| 196 | 330 | |
| 197 | 331 | if (lux > 0xFFFF) |
| 198 | 332 | lux = 0xFFFF; |
| @@ -258,11 +392,12 @@ static int cm32181_write_raw(struct iio_dev *indio_dev, · 59 unmodified lines | ||
| 258 | 392 | static ssize_t cm32181_get_it_available(struct device *dev, |
| 259 | 393 | struct device_attribute *attr, char *buf) |
| 260 | 394 | { |
| 395 | + struct cm32181_chip *cm32181 = iio_priv(dev_to_iio_dev(dev)); | |
| 261 | 396 | int i, n, len; |
| 262 | 397 | |
| 263 | − n = ARRAY_SIZE(als_it_value); | |
| 398 | + n = cm32181->num_als_it; | |
| 264 | 399 | for (i = 0, len = 0; i < n; i++) |
| 265 | − len += sprintf(buf + len, "0.%06u ", als_it_value[i]); | |
| 400 | + len += sprintf(buf + len, "0.%06u ", cm32181->als_it_values[i]); | |
| 266 | 401 | return len + sprintf(buf + len, "\n"); |
| 267 | 402 | } |
| 268 | 403 | |
| @@ -294,70 +429,86 @@ static const struct iio_info cm32181_info = { · 25 unmodified lines | ||
| 294 | 429 | .attrs = &cm32181_attribute_group, |
| 295 | 430 | }; |
| 296 | 431 | |
| 297 | −static int cm32181_probe(struct i2c_client *client, | |
| 298 | − const struct i2c_device_id *id) | |
| 432 | +static int cm32181_probe(struct i2c_client *client) | |
| 299 | 433 | { |
| 434 | + struct device *dev = &client->dev; | |
| 300 | 435 | struct cm32181_chip *cm32181; |
| 301 | 436 | struct iio_dev *indio_dev; |
| 302 | 437 | int ret; |
| 303 | 438 | |
| 304 | − indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*cm32181)); | |
| 305 | − if (!indio_dev) { | |
| 306 | − dev_err(&client->dev, "devm_iio_device_alloc failed\n"); | |
| 439 | + indio_dev = devm_iio_device_alloc(dev, sizeof(*cm32181)); | |
| 440 | + if (!indio_dev) | |
| 307 | 441 | return -ENOMEM; |
| 442 | + | |
| 443 | + /* | |
| 444 | + * Some ACPI systems list 2 I2C resources for the CM3218 sensor, the | |
| 445 | + * SMBus Alert Response Address (ARA, 0x0c) and the actual I2C address. | |
| 446 | + * Detect this and take the following step to deal with it: | |
| 447 | + * 1. When a SMBus Alert capable sensor has an Alert asserted, it will | |
| 448 | + * not respond on its actual I2C address. Read a byte from the ARA | |
| 449 | + * to clear any pending Alerts. | |
| 450 | + * 2. Create a "dummy" client for the actual I2C address and | |
| 451 | + * use that client to communicate with the sensor. | |
| 452 | + */ | |
| 453 | + if (ACPI_HANDLE(dev) && client->addr == SMBUS_ALERT_RESPONSE_ADDRESS) { | |
| 454 | + struct i2c_board_info board_info = { .type = "dummy" }; | |
| 455 | + | |
| 456 | + i2c_smbus_read_byte(client); | |
| 457 | + | |
| 458 | + client = i2c_acpi_new_device(dev, 1, &board_info); | |
| 459 | + if (IS_ERR(client)) | |
| 460 | + return PTR_ERR(client); | |
| 308 | 461 | } |
| 309 | 462 | |
| 310 | 463 | cm32181 = iio_priv(indio_dev); |
| 311 | − i2c_set_clientdata(client, indio_dev); | |
| 312 | 464 | cm32181->client = client; |
| 465 | + cm32181->dev = dev; | |
| 313 | 466 | |
| 314 | 467 | mutex_init(&cm32181->lock); |
| 315 | − indio_dev->dev.parent = &client->dev; | |
| 468 | + indio_dev->dev.parent = dev; | |
| 316 | 469 | indio_dev->channels = cm32181_channels; |
| 317 | 470 | indio_dev->num_channels = ARRAY_SIZE(cm32181_channels); |
| 318 | 471 | indio_dev->info = &cm32181_info; |
| 319 | − indio_dev->name = id->name; | |
| 472 | + indio_dev->name = dev_name(dev); | |
| 320 | 473 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 321 | 474 | |
| 322 | 475 | ret = cm32181_reg_init(cm32181); |
| 323 | 476 | if (ret) { |
| 324 | − dev_err(&client->dev, | |
| 325 | − "%s: register init failed\n", | |
| 326 | − __func__); | |
| 477 | + dev_err(dev, "%s: register init failed\n", __func__); | |
| 327 | 478 | return ret; |
| 328 | 479 | } |
| 329 | 480 | |
| 330 | − ret = devm_iio_device_register(&client->dev, indio_dev); | |
| 481 | + ret = devm_iio_device_register(dev, indio_dev); | |
| 331 | 482 | if (ret) { |
| 332 | − dev_err(&client->dev, | |
| 333 | − "%s: regist device failed\n", | |
| 334 | − __func__); | |
| 483 | + dev_err(dev, "%s: regist device failed\n", __func__); | |
| 335 | 484 | return ret; |
| 336 | 485 | } |
| 337 | 486 | |
| 338 | 487 | return 0; |
| 339 | 488 | } |
| 340 | 489 | |
| 341 | −static const struct i2c_device_id cm32181_id[] = { | |
| 342 | − { "cm32181", 0 }, | |
| 343 | − { } | |
| 344 | −}; | |
| 345 | − | |
| 346 | −MODULE_DEVICE_TABLE(i2c, cm32181_id); | |
| 347 | − | |
| 348 | 490 | static const struct of_device_id cm32181_of_match[] = { |
| 491 | + { .compatible = "capella,cm3218" }, | |
| 349 | 492 | { .compatible = "capella,cm32181" }, |
| 350 | 493 | { } |
| 351 | 494 | }; |
| 352 | 495 | MODULE_DEVICE_TABLE(of, cm32181_of_match); |
| 353 | 496 | |
| 497 | +#ifdef CONFIG_ACPI | |
| 498 | +static const struct acpi_device_id cm32181_acpi_match[] = { | |
| 499 | + { "CPLM3218", 0 }, | |
| 500 | + { } | |
| 501 | +}; | |
| 502 | +MODULE_DEVICE_TABLE(acpi, cm32181_acpi_match); | |
| 503 | +#endif | |
| 504 | + | |
| 354 | 505 | static struct i2c_driver cm32181_driver = { |
| 355 | 506 | .driver = { |
| 356 | 507 | .name = "cm32181", |
| 357 | − .of_match_table = of_match_ptr(cm32181_of_match), | |
| 508 | + .acpi_match_table = ACPI_PTR(cm32181_acpi_match), | |
| 509 | + .of_match_table = cm32181_of_match, | |
| 358 | 510 | }, |
| 359 | − .id_table = cm32181_id, | |
| 360 | − .probe = cm32181_probe, | |
| 511 | + .probe_new = cm32181_probe, | |
| 361 | 512 | }; |
| 362 | 513 | |
| 363 | 514 | module_i2c_driver(cm32181_driver); |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | #include <linux/i2c.h> |
| 12 | 12 | #include <linux/module.h> |
| 13 | +#include <linux/mod_devicetable.h> | |
| 13 | 14 | #include <linux/iio/iio.h> |
| 14 | 15 | #include <linux/iio/sysfs.h> |
| 15 | 16 | #include <linux/init.h> |
| @@ -418,7 +419,7 @@ MODULE_DEVICE_TABLE(of, cm3232_of_match); · 402 unmodified lines | ||
| 418 | 419 | static struct i2c_driver cm3232_driver = { |
| 419 | 420 | .driver = { |
| 420 | 421 | .name = "cm3232", |
| 421 | − .of_match_table = of_match_ptr(cm3232_of_match), | |
| 422 | + .of_match_table = cm3232_of_match, | |
| 422 | 423 | #ifdef CONFIG_PM_SLEEP |
| 423 | 424 | .pm = &cm3232_pm_ops, |
| 424 | 425 | #endif |
| @@ -38,8 +38,8 @@ · 37 unmodified lines | ||
| 38 | 38 | #include <linux/irq.h> |
| 39 | 39 | #include <linux/irq_work.h> |
| 40 | 40 | #include <linux/module.h> |
| 41 | +#include <linux/mod_devicetable.h> | |
| 41 | 42 | #include <linux/mutex.h> |
| 42 | −#include <linux/of.h> | |
| 43 | 43 | #include <linux/regmap.h> |
| 44 | 44 | #include <linux/regulator/consumer.h> |
| 45 | 45 | #include <linux/slab.h> |
| @@ -1617,18 +1617,16 @@ static const struct i2c_device_id gp2ap020a00f_id[] = { · 1571 unmodified lines | ||
| 1617 | 1617 | |
| 1618 | 1618 | MODULE_DEVICE_TABLE(i2c, gp2ap020a00f_id); |
| 1619 | 1619 | |
| 1620 | −#ifdef CONFIG_OF | |
| 1621 | 1620 | static const struct of_device_id gp2ap020a00f_of_match[] = { |
| 1622 | 1621 | { .compatible = "sharp,gp2ap020a00f" }, |
| 1623 | 1622 | { } |
| 1624 | 1623 | }; |
| 1625 | 1624 | MODULE_DEVICE_TABLE(of, gp2ap020a00f_of_match); |
| 1626 | −#endif | |
| 1627 | 1625 | |
| 1628 | 1626 | static struct i2c_driver gp2ap020a00f_driver = { |
| 1629 | 1627 | .driver = { |
| 1630 | 1628 | .name = GP2A_I2C_NAME, |
| 1631 | − .of_match_table = of_match_ptr(gp2ap020a00f_of_match), | |
| 1629 | + .of_match_table = gp2ap020a00f_of_match, | |
| 1632 | 1630 | }, |
| 1633 | 1631 | .probe = gp2ap020a00f_probe, |
| 1634 | 1632 | .remove = gp2ap020a00f_remove, |
| @@ -14,8 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/iio/iio.h> |
| 15 | 15 | #include <linux/iio/sysfs.h> |
| 16 | 16 | #include <linux/iio/buffer.h> |
| 17 | −#include <linux/iio/trigger_consumer.h> | |
| 18 | −#include <linux/iio/triggered_buffer.h> | |
| 19 | 17 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 20 | 18 | |
| 21 | 19 | enum { |
| @@ -308,18 +306,13 @@ static int hid_als_probe(struct platform_device *pdev) · 286 unmodified lines | ||
| 308 | 306 | indio_dev->name = name; |
| 309 | 307 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 310 | 308 | |
| 311 | − ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, | |
| 312 | − NULL, NULL); | |
| 313 | − if (ret) { | |
| 314 | − dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | |
| 315 | − goto error_free_dev_mem; | |
| 316 | − } | |
| 317 | 309 | atomic_set(&als_state->common_attributes.data_ready, 0); |
| 310 | + | |
| 318 | 311 | ret = hid_sensor_setup_trigger(indio_dev, name, |
| 319 | 312 | &als_state->common_attributes); |
| 320 | 313 | if (ret < 0) { |
| 321 | 314 | dev_err(&pdev->dev, "trigger setup failed\n"); |
| 322 | − goto error_unreg_buffer_funcs; | |
| 315 | + goto error_free_dev_mem; | |
| 323 | 316 | } |
| 324 | 317 | |
| 325 | 318 | ret = iio_device_register(indio_dev); |
| @@ -343,9 +336,7 @@ static int hid_als_probe(struct platform_device *pdev) · 17 unmodified lines | ||
| 343 | 336 | error_iio_unreg: |
| 344 | 337 | iio_device_unregister(indio_dev); |
| 345 | 338 | error_remove_trigger: |
| 346 | − hid_sensor_remove_trigger(&als_state->common_attributes); | |
| 347 | −error_unreg_buffer_funcs: | |
| 348 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 339 | + hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes); | |
| 349 | 340 | error_free_dev_mem: |
| 350 | 341 | kfree(indio_dev->channels); |
| 351 | 342 | return ret; |
| @@ -360,8 +351,7 @@ static int hid_als_remove(struct platform_device *pdev) · 8 unmodified lines | ||
| 360 | 351 | |
| 361 | 352 | sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_ALS); |
| 362 | 353 | iio_device_unregister(indio_dev); |
| 363 | − hid_sensor_remove_trigger(&als_state->common_attributes); | |
| 364 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 354 | + hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes); | |
| 365 | 355 | kfree(indio_dev->channels); |
| 366 | 356 | |
| 367 | 357 | return 0; |
| @@ -14,8 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/iio/iio.h> |
| 15 | 15 | #include <linux/iio/sysfs.h> |
| 16 | 16 | #include <linux/iio/buffer.h> |
| 17 | −#include <linux/iio/trigger_consumer.h> | |
| 18 | −#include <linux/iio/triggered_buffer.h> | |
| 19 | 17 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 20 | 18 | |
| 21 | 19 | #define CHANNEL_SCAN_INDEX_PRESENCE 0 |
| @@ -286,18 +284,13 @@ static int hid_prox_probe(struct platform_device *pdev) · 264 unmodified lines | ||
| 286 | 284 | indio_dev->name = name; |
| 287 | 285 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 288 | 286 | |
| 289 | − ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, | |
| 290 | − NULL, NULL); | |
| 291 | − if (ret) { | |
| 292 | − dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | |
| 293 | − goto error_free_dev_mem; | |
| 294 | − } | |
| 295 | 287 | atomic_set(&prox_state->common_attributes.data_ready, 0); |
| 288 | + | |
| 296 | 289 | ret = hid_sensor_setup_trigger(indio_dev, name, |
| 297 | 290 | &prox_state->common_attributes); |
| 298 | 291 | if (ret) { |
| 299 | 292 | dev_err(&pdev->dev, "trigger setup failed\n"); |
| 300 | − goto error_unreg_buffer_funcs; | |
| 293 | + goto error_free_dev_mem; | |
| 301 | 294 | } |
| 302 | 295 | |
| 303 | 296 | ret = iio_device_register(indio_dev); |
| @@ -321,9 +314,7 @@ static int hid_prox_probe(struct platform_device *pdev) · 17 unmodified lines | ||
| 321 | 314 | error_iio_unreg: |
| 322 | 315 | iio_device_unregister(indio_dev); |
| 323 | 316 | error_remove_trigger: |
| 324 | − hid_sensor_remove_trigger(&prox_state->common_attributes); | |
| 325 | −error_unreg_buffer_funcs: | |
| 326 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 317 | + hid_sensor_remove_trigger(indio_dev, &prox_state->common_attributes); | |
| 327 | 318 | error_free_dev_mem: |
| 328 | 319 | kfree(indio_dev->channels); |
| 329 | 320 | return ret; |
| @@ -338,8 +329,7 @@ static int hid_prox_remove(struct platform_device *pdev) · 8 unmodified lines | ||
| 338 | 329 | |
| 339 | 330 | sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PROX); |
| 340 | 331 | iio_device_unregister(indio_dev); |
| 341 | − hid_sensor_remove_trigger(&prox_state->common_attributes); | |
| 342 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 332 | + hid_sensor_remove_trigger(indio_dev, &prox_state->common_attributes); | |
| 343 | 333 | kfree(indio_dev->channels); |
| 344 | 334 | |
| 345 | 335 | return 0; |
| @@ -101,12 +101,12 @@ struct ltr501_gain { · 100 unmodified lines | ||
| 101 | 101 | int uscale; |
| 102 | 102 | }; |
| 103 | 103 | |
| 104 | −static struct ltr501_gain ltr501_als_gain_tbl[] = { | |
| 104 | +static const struct ltr501_gain ltr501_als_gain_tbl[] = { | |
| 105 | 105 | {1, 0}, |
| 106 | 106 | {0, 5000}, |
| 107 | 107 | }; |
| 108 | 108 | |
| 109 | −static struct ltr501_gain ltr559_als_gain_tbl[] = { | |
| 109 | +static const struct ltr501_gain ltr559_als_gain_tbl[] = { | |
| 110 | 110 | {1, 0}, |
| 111 | 111 | {0, 500000}, |
| 112 | 112 | {0, 250000}, |
| @@ -117,14 +117,14 @@ static struct ltr501_gain ltr559_als_gain_tbl[] = { · 4 unmodified lines | ||
| 117 | 117 | {0, 10000}, |
| 118 | 118 | }; |
| 119 | 119 | |
| 120 | −static struct ltr501_gain ltr501_ps_gain_tbl[] = { | |
| 120 | +static const struct ltr501_gain ltr501_ps_gain_tbl[] = { | |
| 121 | 121 | {1, 0}, |
| 122 | 122 | {0, 250000}, |
| 123 | 123 | {0, 125000}, |
| 124 | 124 | {0, 62500}, |
| 125 | 125 | }; |
| 126 | 126 | |
| 127 | −static struct ltr501_gain ltr559_ps_gain_tbl[] = { | |
| 127 | +static const struct ltr501_gain ltr559_ps_gain_tbl[] = { | |
| 128 | 128 | {0, 62500}, /* x16 gain */ |
| 129 | 129 | {0, 31250}, /* x32 gain */ |
| 130 | 130 | {0, 15625}, /* bits X1 are for x64 gain */ |
| @@ -133,9 +133,9 @@ static struct ltr501_gain ltr559_ps_gain_tbl[] = { · 2 unmodified lines | ||
| 133 | 133 | |
| 134 | 134 | struct ltr501_chip_info { |
| 135 | 135 | u8 partid; |
| 136 | − struct ltr501_gain *als_gain; | |
| 136 | + const struct ltr501_gain *als_gain; | |
| 137 | 137 | int als_gain_tbl_size; |
| 138 | − struct ltr501_gain *ps_gain; | |
| 138 | + const struct ltr501_gain *ps_gain; | |
| 139 | 139 | int ps_gain_tbl_size; |
| 140 | 140 | u8 als_mode_active; |
| 141 | 141 | u8 als_gain_mask; |
| @@ -192,7 +192,7 @@ static int ltr501_match_samp_freq(const struct ltr501_samp_table *tab, · 50 unmodified lines | ||
| 192 | 192 | return -EINVAL; |
| 193 | 193 | } |
| 194 | 194 | |
| 195 | −static int ltr501_als_read_samp_freq(struct ltr501_data *data, | |
| 195 | +static int ltr501_als_read_samp_freq(const struct ltr501_data *data, | |
| 196 | 196 | int *val, int *val2) |
| 197 | 197 | { |
| 198 | 198 | int ret, i; |
| @@ -210,7 +210,7 @@ static int ltr501_als_read_samp_freq(struct ltr501_data *data, · 11 unmodified lines | ||
| 210 | 210 | return IIO_VAL_INT_PLUS_MICRO; |
| 211 | 211 | } |
| 212 | 212 | |
| 213 | −static int ltr501_ps_read_samp_freq(struct ltr501_data *data, | |
| 213 | +static int ltr501_ps_read_samp_freq(const struct ltr501_data *data, | |
| 214 | 214 | int *val, int *val2) |
| 215 | 215 | { |
| 216 | 216 | int ret, i; |
| @@ -266,7 +266,7 @@ static int ltr501_ps_write_samp_freq(struct ltr501_data *data, · 49 unmodified lines | ||
| 266 | 266 | return ret; |
| 267 | 267 | } |
| 268 | 268 | |
| 269 | −static int ltr501_als_read_samp_period(struct ltr501_data *data, int *val) | |
| 269 | +static int ltr501_als_read_samp_period(const struct ltr501_data *data, int *val) | |
| 270 | 270 | { |
| 271 | 271 | int ret, i; |
| 272 | 272 | |
| @@ -282,7 +282,7 @@ static int ltr501_als_read_samp_period(struct ltr501_data *data, int *val) · 9 unmodified lines | ||
| 282 | 282 | return IIO_VAL_INT; |
| 283 | 283 | } |
| 284 | 284 | |
| 285 | −static int ltr501_ps_read_samp_period(struct ltr501_data *data, int *val) | |
| 285 | +static int ltr501_ps_read_samp_period(const struct ltr501_data *data, int *val) | |
| 286 | 286 | { |
| 287 | 287 | int ret, i; |
| 288 | 288 | |
| @@ -321,7 +321,7 @@ static unsigned long ltr501_calculate_lux(u16 vis_data, u16 ir_data) · 32 unmodified lines | ||
| 321 | 321 | return lux / 1000; |
| 322 | 322 | } |
| 323 | 323 | |
| 324 | −static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) | |
| 324 | +static int ltr501_drdy(const struct ltr501_data *data, u8 drdy_mask) | |
| 325 | 325 | { |
| 326 | 326 | int tries = 100; |
| 327 | 327 | int ret, status; |
| @@ -373,7 +373,8 @@ static int ltr501_set_it_time(struct ltr501_data *data, int it) · 45 unmodified lines | ||
| 373 | 373 | } |
| 374 | 374 | |
| 375 | 375 | /* read int time in micro seconds */ |
| 376 | −static int ltr501_read_it_time(struct ltr501_data *data, int *val, int *val2) | |
| 376 | +static int ltr501_read_it_time(const struct ltr501_data *data, | |
| 377 | + int *val, int *val2) | |
| 377 | 378 | { |
| 378 | 379 | int ret, index; |
| 379 | 380 | |
| @@ -391,7 +392,7 @@ static int ltr501_read_it_time(struct ltr501_data *data, int *val, int *val2) · 11 unmodified lines | ||
| 391 | 392 | return IIO_VAL_INT_PLUS_MICRO; |
| 392 | 393 | } |
| 393 | 394 | |
| 394 | −static int ltr501_read_als(struct ltr501_data *data, __le16 buf[2]) | |
| 395 | +static int ltr501_read_als(const struct ltr501_data *data, __le16 buf[2]) | |
| 395 | 396 | { |
| 396 | 397 | int ret; |
| 397 | 398 | |
| @@ -403,7 +404,7 @@ static int ltr501_read_als(struct ltr501_data *data, __le16 buf[2]) · 5 unmodified lines | ||
| 403 | 404 | buf, 2 * sizeof(__le16)); |
| 404 | 405 | } |
| 405 | 406 | |
| 406 | −static int ltr501_read_ps(struct ltr501_data *data) | |
| 407 | +static int ltr501_read_ps(const struct ltr501_data *data) | |
| 407 | 408 | { |
| 408 | 409 | int ret, status; |
| 409 | 410 | |
| @@ -419,7 +420,7 @@ static int ltr501_read_ps(struct ltr501_data *data) · 9 unmodified lines | ||
| 419 | 420 | return status; |
| 420 | 421 | } |
| 421 | 422 | |
| 422 | −static int ltr501_read_intr_prst(struct ltr501_data *data, | |
| 423 | +static int ltr501_read_intr_prst(const struct ltr501_data *data, | |
| 423 | 424 | enum iio_chan_type type, |
| 424 | 425 | int *val2) |
| 425 | 426 | { |
| @@ -716,7 +717,7 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, · 290 unmodified lines | ||
| 716 | 717 | return -EINVAL; |
| 717 | 718 | } |
| 718 | 719 | |
| 719 | −static int ltr501_get_gain_index(struct ltr501_gain *gain, int size, | |
| 720 | +static int ltr501_get_gain_index(const struct ltr501_gain *gain, int size, | |
| 720 | 721 | int val, int val2) |
| 721 | 722 | { |
| 722 | 723 | int i; |
| @@ -848,14 +849,14 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, · 125 unmodified lines | ||
| 848 | 849 | return ret; |
| 849 | 850 | } |
| 850 | 851 | |
| 851 | −static int ltr501_read_thresh(struct iio_dev *indio_dev, | |
| 852 | +static int ltr501_read_thresh(const struct iio_dev *indio_dev, | |
| 852 | 853 | const struct iio_chan_spec *chan, |
| 853 | 854 | enum iio_event_type type, |
| 854 | 855 | enum iio_event_direction dir, |
| 855 | 856 | enum iio_event_info info, |
| 856 | 857 | int *val, int *val2) |
| 857 | 858 | { |
| 858 | − struct ltr501_data *data = iio_priv(indio_dev); | |
| 859 | + const struct ltr501_data *data = iio_priv(indio_dev); | |
| 859 | 860 | int ret, thresh_data; |
| 860 | 861 | |
| 861 | 862 | switch (chan->type) { |
| @@ -1359,7 +1360,7 @@ static bool ltr501_is_volatile_reg(struct device *dev, unsigned int reg) · 497 unmodified lines | ||
| 1359 | 1360 | } |
| 1360 | 1361 | } |
| 1361 | 1362 | |
| 1362 | −static struct regmap_config ltr501_regmap_config = { | |
| 1363 | +static const struct regmap_config ltr501_regmap_config = { | |
| 1363 | 1364 | .name = LTR501_REGMAP_NAME, |
| 1364 | 1365 | .reg_bits = 8, |
| 1365 | 1366 | .val_bits = 8, |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/irq.h> |
| 17 | 17 | #include <linux/kernel.h> |
| 18 | 18 | #include <linux/module.h> |
| 19 | +#include <linux/mod_devicetable.h> | |
| 19 | 20 | #include <linux/mutex.h> |
| 20 | 21 | #include <linux/slab.h> |
| 21 | 22 | #include <linux/types.h> |
| @@ -844,7 +845,7 @@ static struct i2c_driver opt3001_driver = { · 822 unmodified lines | ||
| 844 | 845 | |
| 845 | 846 | .driver = { |
| 846 | 847 | .name = "opt3001", |
| 847 | − .of_match_table = of_match_ptr(opt3001_of_match), | |
| 848 | + .of_match_table = opt3001_of_match, | |
| 848 | 849 | }, |
| 849 | 850 | }; |
| 850 | 851 | |
| @@ -17,6 +17,8 @@ · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | #include <linux/util_macros.h> |
| 19 | 19 | |
| 20 | +#include <asm/unaligned.h> | |
| 21 | + | |
| 20 | 22 | #define SI1133_REG_PART_ID 0x00 |
| 21 | 23 | #define SI1133_REG_REV_ID 0x01 |
| 22 | 24 | #define SI1133_REG_MFR_ID 0x02 |
| @@ -104,8 +106,6 @@ · 81 unmodified lines | ||
| 104 | 106 | #define SI1133_LUX_BUFFER_SIZE 9 |
| 105 | 107 | #define SI1133_MEASURE_BUFFER_SIZE 3 |
| 106 | 108 | |
| 107 | −#define SI1133_SIGN_BIT_INDEX 23 | |
| 108 | − | |
| 109 | 109 | static const int si1133_scale_available[] = { |
| 110 | 110 | 1, 2, 4, 8, 16, 32, 64, 128}; |
| 111 | 111 | |
| @@ -633,8 +633,7 @@ static int si1133_measure(struct si1133_data *data, · 521 unmodified lines | ||
| 633 | 633 | if (err) |
| 634 | 634 | return err; |
| 635 | 635 | |
| 636 | − *val = sign_extend32((buffer[0] << 16) | (buffer[1] << 8) | buffer[2], | |
| 637 | − SI1133_SIGN_BIT_INDEX); | |
| 636 | + *val = sign_extend32(get_unaligned_be24(&buffer[0]), 23); | |
| 638 | 637 | |
| 639 | 638 | return err; |
| 640 | 639 | } |
| @@ -723,16 +722,11 @@ static int si1133_get_lux(struct si1133_data *data, int *val) · 82 unmodified lines | ||
| 723 | 722 | if (err) |
| 724 | 723 | return err; |
| 725 | 724 | |
| 726 | − high_vis = | |
| 727 | − sign_extend32((buffer[0] << 16) | (buffer[1] << 8) | buffer[2], | |
| 728 | − SI1133_SIGN_BIT_INDEX); | |
| 725 | + high_vis = sign_extend32(get_unaligned_be24(&buffer[0]), 23); | |
| 729 | 726 | |
| 730 | − low_vis = | |
| 731 | − sign_extend32((buffer[3] << 16) | (buffer[4] << 8) | buffer[5], | |
| 732 | − SI1133_SIGN_BIT_INDEX); | |
| 727 | + low_vis = sign_extend32(get_unaligned_be24(&buffer[3]), 23); | |
| 733 | 728 | |
| 734 | − ir = sign_extend32((buffer[6] << 16) | (buffer[7] << 8) | buffer[8], | |
| 735 | − SI1133_SIGN_BIT_INDEX); | |
| 729 | + ir = sign_extend32(get_unaligned_be24(&buffer[6]), 23); | |
| 736 | 730 | |
| 737 | 731 | if (high_vis > SI1133_ADC_THRESHOLD || ir > SI1133_ADC_THRESHOLD) |
| 738 | 732 | lux = si1133_calc_polynomial(high_vis, ir, |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 10 | #include <linux/kernel.h> |
| 11 | 11 | #include <linux/module.h> |
| 12 | +#include <linux/mod_devicetable.h> | |
| 12 | 13 | #include <linux/i2c.h> |
| 13 | 14 | #include <linux/slab.h> |
| 14 | 15 | #include <linux/regmap.h> |
| @@ -55,7 +56,7 @@ static struct i2c_driver st_uvis25_driver = { · 40 unmodified lines | ||
| 55 | 56 | .driver = { |
| 56 | 57 | .name = "st_uvis25_i2c", |
| 57 | 58 | .pm = &st_uvis25_pm_ops, |
| 58 | − .of_match_table = of_match_ptr(st_uvis25_i2c_of_match), | |
| 59 | + .of_match_table = st_uvis25_i2c_of_match, | |
| 59 | 60 | }, |
| 60 | 61 | .probe = st_uvis25_i2c_probe, |
| 61 | 62 | .id_table = st_uvis25_i2c_id_table, |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 10 | #include <linux/kernel.h> |
| 11 | 11 | #include <linux/module.h> |
| 12 | +#include <linux/mod_devicetable.h> | |
| 12 | 13 | #include <linux/spi/spi.h> |
| 13 | 14 | #include <linux/slab.h> |
| 14 | 15 | #include <linux/regmap.h> |
| @@ -55,7 +56,7 @@ static struct spi_driver st_uvis25_driver = { · 40 unmodified lines | ||
| 55 | 56 | .driver = { |
| 56 | 57 | .name = "st_uvis25_spi", |
| 57 | 58 | .pm = &st_uvis25_pm_ops, |
| 58 | − .of_match_table = of_match_ptr(st_uvis25_spi_of_match), | |
| 59 | + .of_match_table = st_uvis25_spi_of_match, | |
| 59 | 60 | }, |
| 60 | 61 | .probe = st_uvis25_spi_probe, |
| 61 | 62 | .id_table = st_uvis25_spi_id_table, |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | * |
| 6 | 6 | * Copyright 2012 Peter Meerwald <pmeerw@pmeerw.net> |
| 7 | 7 | * Copyright 2019 Pursim SPC |
| 8 | + * Copyright 2020 Mathieu Othacehe <m.othacehe@gmail.com> | |
| 8 | 9 | * |
| 9 | 10 | * IIO driver for: |
| 10 | 11 | * VCNL4000/10/20 (7-bit I2C slave address 0x13) |
| @@ -13,9 +14,7 @@ · 2 unmodified lines | ||
| 13 | 14 | * |
| 14 | 15 | * TODO: |
| 15 | 16 | * allow to adjust IR current |
| 16 | − * proximity threshold and event handling | |
| 17 | − * periodic ALS/proximity measurement (VCNL4010/20) | |
| 18 | − * interrupts (VCNL4010/20/40, VCNL4200) | |
| 17 | + * interrupts (VCNL4040, VCNL4200) | |
| 19 | 18 | */ |
| 20 | 19 | |
| 21 | 20 | #include <linux/module.h> |
| @@ -23,9 +22,15 @@ · 1 unmodified line | ||
| 23 | 22 | #include <linux/err.h> |
| 24 | 23 | #include <linux/delay.h> |
| 25 | 24 | #include <linux/pm_runtime.h> |
| 25 | +#include <linux/interrupt.h> | |
| 26 | 26 | |
| 27 | +#include <linux/iio/buffer.h> | |
| 28 | +#include <linux/iio/events.h> | |
| 27 | 29 | #include <linux/iio/iio.h> |
| 28 | 30 | #include <linux/iio/sysfs.h> |
| 31 | +#include <linux/iio/trigger.h> | |
| 32 | +#include <linux/iio/trigger_consumer.h> | |
| 33 | +#include <linux/iio/triggered_buffer.h> | |
| 29 | 34 | |
| 30 | 35 | #define VCNL4000_DRV_NAME "vcnl4000" |
| 31 | 36 | #define VCNL4000_PROD_ID 0x01 |
| @@ -35,14 +40,22 @@ · 3 unmodified lines | ||
| 35 | 40 | |
| 36 | 41 | #define VCNL4000_COMMAND 0x80 /* Command register */ |
| 37 | 42 | #define VCNL4000_PROD_REV 0x81 /* Product ID and Revision ID */ |
| 43 | +#define VCNL4010_PROX_RATE 0x82 /* Proximity rate */ | |
| 38 | 44 | #define VCNL4000_LED_CURRENT 0x83 /* IR LED current for proximity mode */ |
| 39 | 45 | #define VCNL4000_AL_PARAM 0x84 /* Ambient light parameter register */ |
| 46 | +#define VCNL4010_ALS_PARAM 0x84 /* ALS rate */ | |
| 40 | 47 | #define VCNL4000_AL_RESULT_HI 0x85 /* Ambient light result register, MSB */ |
| 41 | 48 | #define VCNL4000_AL_RESULT_LO 0x86 /* Ambient light result register, LSB */ |
| 42 | 49 | #define VCNL4000_PS_RESULT_HI 0x87 /* Proximity result register, MSB */ |
| 43 | 50 | #define VCNL4000_PS_RESULT_LO 0x88 /* Proximity result register, LSB */ |
| 44 | 51 | #define VCNL4000_PS_MEAS_FREQ 0x89 /* Proximity test signal frequency */ |
| 52 | +#define VCNL4010_INT_CTRL 0x89 /* Interrupt control */ | |
| 45 | 53 | #define VCNL4000_PS_MOD_ADJ 0x8a /* Proximity modulator timing adjustment */ |
| 54 | +#define VCNL4010_LOW_THR_HI 0x8a /* Low threshold, MSB */ | |
| 55 | +#define VCNL4010_LOW_THR_LO 0x8b /* Low threshold, LSB */ | |
| 56 | +#define VCNL4010_HIGH_THR_HI 0x8c /* High threshold, MSB */ | |
| 57 | +#define VCNL4010_HIGH_THR_LO 0x8d /* High threshold, LSB */ | |
| 58 | +#define VCNL4010_ISR 0x8e /* Interrupt status */ | |
| 46 | 59 | |
| 47 | 60 | #define VCNL4200_AL_CONF 0x00 /* Ambient light configuration */ |
| 48 | 61 | #define VCNL4200_PS_CONF1 0x03 /* Proximity configuration */ |
| @@ -57,6 +70,36 @@ · 8 unmodified lines | ||
| 57 | 70 | #define VCNL4000_PS_RDY BIT(5) /* proximity data ready? */ |
| 58 | 71 | #define VCNL4000_AL_OD BIT(4) /* start on-demand ALS measurement */ |
| 59 | 72 | #define VCNL4000_PS_OD BIT(3) /* start on-demand proximity measurement */ |
| 73 | +#define VCNL4000_ALS_EN BIT(2) /* start ALS measurement */ | |
| 74 | +#define VCNL4000_PROX_EN BIT(1) /* start proximity measurement */ | |
| 75 | +#define VCNL4000_SELF_TIMED_EN BIT(0) /* start self-timed measurement */ | |
| 76 | + | |
| 77 | +/* Bit masks for interrupt registers. */ | |
| 78 | +#define VCNL4010_INT_THR_SEL BIT(0) /* Select threshold interrupt source */ | |
| 79 | +#define VCNL4010_INT_THR_EN BIT(1) /* Threshold interrupt type */ | |
| 80 | +#define VCNL4010_INT_ALS_EN BIT(2) /* Enable on ALS data ready */ | |
| 81 | +#define VCNL4010_INT_PROX_EN BIT(3) /* Enable on proximity data ready */ | |
| 82 | + | |
| 83 | +#define VCNL4010_INT_THR_HIGH 0 /* High threshold exceeded */ | |
| 84 | +#define VCNL4010_INT_THR_LOW 1 /* Low threshold exceeded */ | |
| 85 | +#define VCNL4010_INT_ALS 2 /* ALS data ready */ | |
| 86 | +#define VCNL4010_INT_PROXIMITY 3 /* Proximity data ready */ | |
| 87 | + | |
| 88 | +#define VCNL4010_INT_THR \ | |
| 89 | + (BIT(VCNL4010_INT_THR_LOW) | BIT(VCNL4010_INT_THR_HIGH)) | |
| 90 | +#define VCNL4010_INT_DRDY \ | |
| 91 | + (BIT(VCNL4010_INT_PROXIMITY) | BIT(VCNL4010_INT_ALS)) | |
| 92 | + | |
| 93 | +static const int vcnl4010_prox_sampling_frequency[][2] = { | |
| 94 | + {1, 950000}, | |
| 95 | + {3, 906250}, | |
| 96 | + {7, 812500}, | |
| 97 | + {16, 625000}, | |
| 98 | + {31, 250000}, | |
| 99 | + {62, 500000}, | |
| 100 | + {125, 0}, | |
| 101 | + {250, 0}, | |
| 102 | +}; | |
| 60 | 103 | |
| 61 | 104 | #define VCNL4000_SLEEP_DELAY_MS 2000 /* before we enter pm_runtime_suspend */ |
| 62 | 105 | |
| @@ -88,6 +131,10 @@ struct vcnl4000_data { · 25 unmodified lines | ||
| 88 | 131 | |
| 89 | 132 | struct vcnl4000_chip_spec { |
| 90 | 133 | const char *prod; |
| 134 | + struct iio_chan_spec const *channels; | |
| 135 | + const int num_channels; | |
| 136 | + const struct iio_info *info; | |
| 137 | + bool irq_support; | |
| 91 | 138 | int (*init)(struct vcnl4000_data *data); |
| 92 | 139 | int (*measure_light)(struct vcnl4000_data *data, int *val); |
| 93 | 140 | int (*measure_proximity)(struct vcnl4000_data *data, int *val); |
| @@ -216,11 +263,31 @@ static int vcnl4200_init(struct vcnl4000_data *data) · 122 unmodified lines | ||
| 216 | 263 | return 0; |
| 217 | 264 | }; |
| 218 | 265 | |
| 266 | +static int vcnl4000_read_data(struct vcnl4000_data *data, u8 data_reg, int *val) | |
| 267 | +{ | |
| 268 | + s32 ret; | |
| 269 | + | |
| 270 | + ret = i2c_smbus_read_word_swapped(data->client, data_reg); | |
| 271 | + if (ret < 0) | |
| 272 | + return ret; | |
| 273 | + | |
| 274 | + *val = ret; | |
| 275 | + return 0; | |
| 276 | +} | |
| 277 | + | |
| 278 | +static int vcnl4000_write_data(struct vcnl4000_data *data, u8 data_reg, int val) | |
| 279 | +{ | |
| 280 | + if (val > U16_MAX) | |
| 281 | + return -ERANGE; | |
| 282 | + | |
| 283 | + return i2c_smbus_write_word_swapped(data->client, data_reg, val); | |
| 284 | +} | |
| 285 | + | |
| 286 | + | |
| 219 | 287 | static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, |
| 220 | 288 | u8 rdy_mask, u8 data_reg, int *val) |
| 221 | 289 | { |
| 222 | 290 | int tries = 20; |
| 223 | − __be16 buf; | |
| 224 | 291 | int ret; |
| 225 | 292 | |
| 226 | 293 | mutex_lock(&data->vcnl4000_lock); |
| @@ -247,13 +314,11 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, · 20 unmodified lines | ||
| 247 | 314 | goto fail; |
| 248 | 315 | } |
| 249 | 316 | |
| 250 | − ret = i2c_smbus_read_i2c_block_data(data->client, | |
| 251 | − data_reg, sizeof(buf), (u8 *) &buf); | |
| 317 | + ret = vcnl4000_read_data(data, data_reg, val); | |
| 252 | 318 | if (ret < 0) |
| 253 | 319 | goto fail; |
| 254 | 320 | |
| 255 | 321 | mutex_unlock(&data->vcnl4000_lock); |
| 256 | − *val = be16_to_cpu(buf); | |
| 257 | 322 | |
| 258 | 323 | return 0; |
| 259 | 324 | |
| @@ -313,67 +378,34 @@ static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val) · 53 unmodified lines | ||
| 313 | 378 | return vcnl4200_measure(data, &data->vcnl4200_ps, val); |
| 314 | 379 | } |
| 315 | 380 | |
| 316 | −static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { | |
| 317 | − [VCNL4000] = { | |
| 318 | − .prod = "VCNL4000", | |
| 319 | − .init = vcnl4000_init, | |
| 320 | − .measure_light = vcnl4000_measure_light, | |
| 321 | − .measure_proximity = vcnl4000_measure_proximity, | |
| 322 | − .set_power_state = vcnl4000_set_power_state, | |
| 323 | − }, | |
| 324 | − [VCNL4010] = { | |
| 325 | − .prod = "VCNL4010/4020", | |
| 326 | − .init = vcnl4000_init, | |
| 327 | − .measure_light = vcnl4000_measure_light, | |
| 328 | − .measure_proximity = vcnl4000_measure_proximity, | |
| 329 | − .set_power_state = vcnl4000_set_power_state, | |
| 330 | − }, | |
| 331 | − [VCNL4040] = { | |
| 332 | − .prod = "VCNL4040", | |
| 333 | − .init = vcnl4200_init, | |
| 334 | − .measure_light = vcnl4200_measure_light, | |
| 335 | − .measure_proximity = vcnl4200_measure_proximity, | |
| 336 | − .set_power_state = vcnl4200_set_power_state, | |
| 337 | − }, | |
| 338 | − [VCNL4200] = { | |
| 339 | − .prod = "VCNL4200", | |
| 340 | − .init = vcnl4200_init, | |
| 341 | − .measure_light = vcnl4200_measure_light, | |
| 342 | − .measure_proximity = vcnl4200_measure_proximity, | |
| 343 | − .set_power_state = vcnl4200_set_power_state, | |
| 344 | − }, | |
| 345 | −}; | |
| 346 | − | |
| 347 | −static ssize_t vcnl4000_read_near_level(struct iio_dev *indio_dev, | |
| 348 | − uintptr_t priv, | |
| 349 | − const struct iio_chan_spec *chan, | |
| 350 | − char *buf) | |
| 381 | +static int vcnl4010_read_proxy_samp_freq(struct vcnl4000_data *data, int *val, | |
| 382 | + int *val2) | |
| 351 | 383 | { |
| 352 | − struct vcnl4000_data *data = iio_priv(indio_dev); | |
| 384 | + int ret; | |
| 353 | 385 | |
| 354 | − return sprintf(buf, "%u\n", data->near_level); | |
| 386 | + ret = i2c_smbus_read_byte_data(data->client, VCNL4010_PROX_RATE); | |
| 387 | + if (ret < 0) | |
| 388 | + return ret; | |
| 389 | + | |
| 390 | + if (ret >= ARRAY_SIZE(vcnl4010_prox_sampling_frequency)) | |
| 391 | + return -EINVAL; | |
| 392 | + | |
| 393 | + *val = vcnl4010_prox_sampling_frequency[ret][0]; | |
| 394 | + *val2 = vcnl4010_prox_sampling_frequency[ret][1]; | |
| 395 | + | |
| 396 | + return 0; | |
| 355 | 397 | } |
| 356 | 398 | |
| 357 | −static const struct iio_chan_spec_ext_info vcnl4000_ext_info[] = { | |
| 358 | − { | |
| 359 | − .name = "nearlevel", | |
| 360 | − .shared = IIO_SEPARATE, | |
| 361 | − .read = vcnl4000_read_near_level, | |
| 362 | − }, | |
| 363 | − { /* sentinel */ } | |
| 364 | −}; | |
| 399 | +static bool vcnl4010_is_in_periodic_mode(struct vcnl4000_data *data) | |
| 400 | +{ | |
| 401 | + int ret; | |
| 365 | 402 | |
| 366 | −static const struct iio_chan_spec vcnl4000_channels[] = { | |
| 367 | − { | |
| 368 | − .type = IIO_LIGHT, | |
| 369 | − .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | |
| 370 | − BIT(IIO_CHAN_INFO_SCALE), | |
| 371 | − }, { | |
| 372 | − .type = IIO_PROXIMITY, | |
| 373 | − .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | |
| 374 | − .ext_info = vcnl4000_ext_info, | |
| 375 | − } | |
| 376 | −}; | |
| 403 | + ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND); | |
| 404 | + if (ret < 0) | |
| 405 | + return false; | |
| 406 | + | |
| 407 | + return !!(ret & VCNL4000_SELF_TIMED_EN); | |
| 408 | +} | |
| 377 | 409 | |
| 378 | 410 | static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on) |
| 379 | 411 | { |
| @@ -433,10 +465,571 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev, · 53 unmodified lines | ||
| 433 | 465 | } |
| 434 | 466 | } |
| 435 | 467 | |
| 468 | +static int vcnl4010_read_raw(struct iio_dev *indio_dev, | |
| 469 | + struct iio_chan_spec const *chan, | |
| 470 | + int *val, int *val2, long mask) | |
| 471 | +{ | |
| 472 | + int ret; | |
| 473 | + struct vcnl4000_data *data = iio_priv(indio_dev); | |
| 474 | + | |
| 475 | + switch (mask) { | |
| 476 | + case IIO_CHAN_INFO_RAW: | |
| 477 | + case IIO_CHAN_INFO_SCALE: | |
| 478 | + ret = iio_device_claim_direct_mode(indio_dev); | |
| 479 | + if (ret) | |
| 480 | + return ret; | |
| 481 | + | |
| 482 | + /* Protect against event capture. */ | |
| 483 | + if (vcnl4010_is_in_periodic_mode(data)) { | |
| 484 | + ret = -EBUSY; | |
| 485 | + } else { | |
| 486 | + ret = vcnl4000_read_raw(indio_dev, chan, val, val2, | |
| 487 | + mask); | |
| 488 | + } | |
| 489 | + | |
| 490 | + iio_device_release_direct_mode(indio_dev); | |
| 491 | + return ret; | |
| 492 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 493 | + switch (chan->type) { | |
| 494 | + case IIO_PROXIMITY: | |
| 495 | + ret = vcnl4010_read_proxy_samp_freq(data, val, val2); | |
| 496 | + if (ret < 0) | |
| 497 | + return ret; | |
| 498 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 499 | + default: | |
| 500 | + return -EINVAL; | |
| 501 | + } | |
| 502 | + default: | |
| 503 | + return -EINVAL; | |
| 504 | + } | |
| 505 | +} | |
| 506 | + | |
| 507 | +static int vcnl4010_read_avail(struct iio_dev *indio_dev, | |
| 508 | + struct iio_chan_spec const *chan, | |
| 509 | + const int **vals, int *type, int *length, | |
| 510 | + long mask) | |
| 511 | +{ | |
| 512 | + switch (mask) { | |
| 513 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 514 | + *vals = (int *)vcnl4010_prox_sampling_frequency; | |
| 515 | + *type = IIO_VAL_INT_PLUS_MICRO; | |
| 516 | + *length = 2 * ARRAY_SIZE(vcnl4010_prox_sampling_frequency); | |
| 517 | + return IIO_AVAIL_LIST; | |
| 518 | + default: | |
| 519 | + return -EINVAL; | |
| 520 | + } | |
| 521 | +} | |
| 522 | + | |
| 523 | +static int vcnl4010_write_proxy_samp_freq(struct vcnl4000_data *data, int val, | |
| 524 | + int val2) | |
| 525 | +{ | |
| 526 | + unsigned int i; | |
| 527 | + int index = -1; | |
| 528 | + | |
| 529 | + for (i = 0; i < ARRAY_SIZE(vcnl4010_prox_sampling_frequency); i++) { | |
| 530 | + if (val == vcnl4010_prox_sampling_frequency[i][0] && | |
| 531 | + val2 == vcnl4010_prox_sampling_frequency[i][1]) { | |
| 532 | + index = i; | |
| 533 | + break; | |
| 534 | + } | |
| 535 | + } | |
| 536 | + | |
| 537 | + if (index < 0) | |
| 538 | + return -EINVAL; | |
| 539 | + | |
| 540 | + return i2c_smbus_write_byte_data(data->client, VCNL4010_PROX_RATE, | |
| 541 | + index); | |
| 542 | +} | |
| 543 | + | |
| 544 | +static int vcnl4010_write_raw(struct iio_dev *indio_dev, | |
| 545 | + struct iio_chan_spec const *chan, | |
| 546 | + int val, int val2, long mask) | |
| 547 | +{ | |
| 548 | + int ret; | |
| 549 | + struct vcnl4000_data *data = iio_priv(indio_dev); | |
| 550 | + | |
| 551 | + ret = iio_device_claim_direct_mode(indio_dev); | |
| 552 | + if (ret) | |
| 553 | + return ret; | |
| 554 | + | |
| 555 | + /* Protect against event capture. */ | |
| 556 | + if (vcnl4010_is_in_periodic_mode(data)) { | |
| 557 | + ret = -EBUSY; | |
| 558 | + goto end; | |
| 559 | + } | |
| 560 | + | |
| 561 | + switch (mask) { | |
| 562 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 563 | + switch (chan->type) { | |
| 564 | + case IIO_PROXIMITY: | |
| 565 | + ret = vcnl4010_write_proxy_samp_freq(data, val, val2); | |
| 566 | + goto end; | |
| 567 | + default: | |
| 568 | + ret = -EINVAL; | |
| 569 | + goto end; | |
| 570 | + } | |
| 571 | + default: | |
| 572 | + ret = -EINVAL; | |
| 573 | + goto end; | |
| 574 | + } | |
| 575 | + | |
| 576 | +end: | |
| 577 | + iio_device_release_direct_mode(indio_dev); | |
| 578 | + return ret; | |
| 579 | +} | |
| 580 | + | |
| 581 | +static int vcnl4010_read_event(struct iio_dev *indio_dev, | |
| 582 | + const struct iio_chan_spec *chan, | |
| 583 | + enum iio_event_type type, | |
| 584 | + enum iio_event_direction dir, | |
| 585 | + enum iio_event_info info, | |
| 586 | + int *val, int *val2) | |
| 587 | +{ | |
| 588 | + int ret; | |
| 589 | + struct vcnl4000_data *data = iio_priv(indio_dev); | |
| 590 | + | |
| 591 | + switch (info) { | |
| 592 | + case IIO_EV_INFO_VALUE: | |
| 593 | + switch (dir) { | |
| 594 | + case IIO_EV_DIR_RISING: | |
| 595 | + ret = vcnl4000_read_data(data, VCNL4010_HIGH_THR_HI, | |
| 596 | + val); | |
| 597 | + if (ret < 0) | |
| 598 | + return ret; | |
| 599 | + return IIO_VAL_INT; | |
| 600 | + case IIO_EV_DIR_FALLING: | |
| 601 | + ret = vcnl4000_read_data(data, VCNL4010_LOW_THR_HI, | |
| 602 | + val); | |
| 603 | + if (ret < 0) | |
| 604 | + return ret; | |
| 605 | + return IIO_VAL_INT; | |
| 606 | + default: | |
| 607 | + return -EINVAL; | |
| 608 | + } | |
| 609 | + default: | |
| 610 | + return -EINVAL; | |
| 611 | + } | |
| 612 | +} | |
| 613 | + | |
| 614 | +static int vcnl4010_write_event(struct iio_dev *indio_dev, | |
| 615 | + const struct iio_chan_spec *chan, | |
| 616 | + enum iio_event_type type, | |
| 617 | + enum iio_event_direction dir, | |
| 618 | + enum iio_event_info info, | |
| 619 | + int val, int val2) | |
| 620 | +{ | |
| 621 | + int ret; | |
| 622 | + struct vcnl4000_data *data = iio_priv(indio_dev); | |
| 623 | + | |
| 624 | + switch (info) { | |
| 625 | + case IIO_EV_INFO_VALUE: | |
| 626 | + switch (dir) { | |
| 627 | + case IIO_EV_DIR_RISING: | |
| 628 | + ret = vcnl4000_write_data(data, VCNL4010_HIGH_THR_HI, | |
| 629 | + val); | |
| 630 | + if (ret < 0) | |
| 631 | + return ret; | |
| 632 | + return IIO_VAL_INT; | |
| 633 | + case IIO_EV_DIR_FALLING: | |
| 634 | + ret = vcnl4000_write_data(data, VCNL4010_LOW_THR_HI, | |
| 635 | + val); | |
| 636 | + if (ret < 0) | |
| 637 | + return ret; | |
| 638 | + return IIO_VAL_INT; | |
| 639 | + default: | |
| 640 | + return -EINVAL; | |
| 641 | + } | |
| 642 | + default: | |
| 643 | + return -EINVAL; | |
| 644 | + } | |
| 645 | +} | |
| 646 | + | |
| 647 | +static bool vcnl4010_is_thr_enabled(struct vcnl4000_data *data) | |
| 648 | +{ | |
| 649 | + int ret; | |
| 650 | + | |
| 651 | + ret = i2c_smbus_read_byte_data(data->client, VCNL4010_INT_CTRL); | |
| 652 | + if (ret < 0) | |
| 653 | + return false; | |
| 654 | + | |
| 655 | + return !!(ret & VCNL4010_INT_THR_EN); | |
| 656 | +} | |
| 657 | + | |
| 658 | +static int vcnl4010_read_event_config(struct iio_dev *indio_dev, | |
| 659 | + const struct iio_chan_spec *chan, | |
| 660 | + enum iio_event_type type, | |
| 661 | + enum iio_event_direction dir) | |
| 662 | +{ | |
| 663 | + struct vcnl4000_data *data = iio_priv(indio_dev); | |
| 664 | + | |
| 665 | + switch (chan->type) { | |
| 666 | + case IIO_PROXIMITY: | |
| 667 | + return vcnl4010_is_thr_enabled(data); | |
| 668 | + default: | |
| 669 | + return -EINVAL; | |
| 670 | + } | |
| 671 | +} | |
| 672 | + | |
| 673 | +static int vcnl4010_config_threshold(struct iio_dev *indio_dev, bool state) | |
| 674 | +{ | |
| 675 | + struct vcnl4000_data *data = iio_priv(indio_dev); | |
| 676 | + int ret; | |
| 677 | + int icr; | |
| 678 | + int command; | |
| 679 | + | |
| 680 | + if (state) { | |
| 681 | + ret = iio_device_claim_direct_mode(indio_dev); | |
| 682 | + if (ret) | |
| 683 | + return ret; | |
| 684 | + | |
| 685 | + /* Enable periodic measurement of proximity data. */ | |
| 686 | + command = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN; | |
| 687 | + | |
| 688 | + /* | |
| 689 | + * Enable interrupts on threshold, for proximity data by | |
| 690 | + * default. | |
| 691 | + */ | |
| 692 | + icr = VCNL4010_INT_THR_EN; | |
| 693 | + } else { | |
| 694 | + if (!vcnl4010_is_thr_enabled(data)) | |
| 695 | + return 0; | |
| 696 | + | |
| 697 | + command = 0; | |
| 698 | + icr = 0; | |
| 699 | + } | |
| 700 | + | |
| 701 | + ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, | |
| 702 | + command); | |
| 703 | + if (ret < 0) | |
| 704 | + goto end; | |
| 705 | + | |
| 706 | + ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, icr); | |
| 707 | + | |
| 708 | +end: | |
| 709 | + if (state) | |
| 710 | + iio_device_release_direct_mode(indio_dev); | |
| 711 | + | |
| 712 | + return ret; | |
| 713 | +} | |
| 714 | + | |
| 715 | +static int vcnl4010_write_event_config(struct iio_dev *indio_dev, | |
| 716 | + const struct iio_chan_spec *chan, | |
| 717 | + enum iio_event_type type, | |
| 718 | + enum iio_event_direction dir, | |
| 719 | + int state) | |
| 720 | +{ | |
| 721 | + switch (chan->type) { | |
| 722 | + case IIO_PROXIMITY: | |
| 723 | + return vcnl4010_config_threshold(indio_dev, state); | |
| 724 | + default: | |
| 725 | + return -EINVAL; | |
| 726 | + } | |
| 727 | +} | |
| 728 | + | |
| 729 | +static ssize_t vcnl4000_read_near_level(struct iio_dev *indio_dev, | |
| 730 | + uintptr_t priv, | |
| 731 | + const struct iio_chan_spec *chan, | |
| 732 | + char *buf) | |
| 733 | +{ | |
| 734 | + struct vcnl4000_data *data = iio_priv(indio_dev); | |
| 735 | + | |
| 736 | + return sprintf(buf, "%u\n", data->near_level); | |
| 737 | +} | |
| 738 | + | |
| 739 | +static const struct iio_chan_spec_ext_info vcnl4000_ext_info[] = { | |
| 740 | + { | |
| 741 | + .name = "nearlevel", | |
| 742 | + .shared = IIO_SEPARATE, | |
| 743 | + .read = vcnl4000_read_near_level, | |
| 744 | + }, | |
| 745 | + { /* sentinel */ } | |
| 746 | +}; | |
| 747 | + | |
| 748 | +static const struct iio_event_spec vcnl4000_event_spec[] = { | |
| 749 | + { | |
| 750 | + .type = IIO_EV_TYPE_THRESH, | |
| 751 | + .dir = IIO_EV_DIR_RISING, | |
| 752 | + .mask_separate = BIT(IIO_EV_INFO_VALUE), | |
| 753 | + }, { | |
| 754 | + .type = IIO_EV_TYPE_THRESH, | |
| 755 | + .dir = IIO_EV_DIR_FALLING, | |
| 756 | + .mask_separate = BIT(IIO_EV_INFO_VALUE), | |
| 757 | + }, { | |
| 758 | + .type = IIO_EV_TYPE_THRESH, | |
| 759 | + .dir = IIO_EV_DIR_EITHER, | |
| 760 | + .mask_separate = BIT(IIO_EV_INFO_ENABLE), | |
| 761 | + } | |
| 762 | +}; | |
| 763 | + | |
| 764 | +static const struct iio_chan_spec vcnl4000_channels[] = { | |
| 765 | + { | |
| 766 | + .type = IIO_LIGHT, | |
| 767 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | |
| 768 | + BIT(IIO_CHAN_INFO_SCALE), | |
| 769 | + }, { | |
| 770 | + .type = IIO_PROXIMITY, | |
| 771 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | |
| 772 | + .ext_info = vcnl4000_ext_info, | |
| 773 | + } | |
| 774 | +}; | |
| 775 | + | |
| 776 | +static const struct iio_chan_spec vcnl4010_channels[] = { | |
| 777 | + { | |
| 778 | + .type = IIO_LIGHT, | |
| 779 | + .scan_index = -1, | |
| 780 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | |
| 781 | + BIT(IIO_CHAN_INFO_SCALE), | |
| 782 | + }, { | |
| 783 | + .type = IIO_PROXIMITY, | |
| 784 | + .scan_index = 0, | |
| 785 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | |
| 786 | + BIT(IIO_CHAN_INFO_SAMP_FREQ), | |
| 787 | + .info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), | |
| 788 | + .event_spec = vcnl4000_event_spec, | |
| 789 | + .num_event_specs = ARRAY_SIZE(vcnl4000_event_spec), | |
| 790 | + .ext_info = vcnl4000_ext_info, | |
| 791 | + .scan_type = { | |
| 792 | + .sign = 'u', | |
| 793 | + .realbits = 16, | |
| 794 | + .storagebits = 16, | |
| 795 | + .endianness = IIO_CPU, | |
| 796 | + }, | |
| 797 | + }, | |
| 798 | + IIO_CHAN_SOFT_TIMESTAMP(1), | |
| 799 | +}; | |
| 800 | + | |
| 436 | 801 | static const struct iio_info vcnl4000_info = { |
| 437 | 802 | .read_raw = vcnl4000_read_raw, |
| 438 | 803 | }; |
| 439 | 804 | |
| 805 | +static const struct iio_info vcnl4010_info = { | |
| 806 | + .read_raw = vcnl4010_read_raw, | |
| 807 | + .read_avail = vcnl4010_read_avail, | |
| 808 | + .write_raw = vcnl4010_write_raw, | |
| 809 | + .read_event_value = vcnl4010_read_event, | |
| 810 | + .write_event_value = vcnl4010_write_event, | |
| 811 | + .read_event_config = vcnl4010_read_event_config, | |
| 812 | + .write_event_config = vcnl4010_write_event_config, | |
| 813 | +}; | |
| 814 | + | |
| 815 | +static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { | |
| 816 | + [VCNL4000] = { | |
| 817 | + .prod = "VCNL4000", | |
| 818 | + .init = vcnl4000_init, | |
| 819 | + .measure_light = vcnl4000_measure_light, | |
| 820 | + .measure_proximity = vcnl4000_measure_proximity, | |
| 821 | + .set_power_state = vcnl4000_set_power_state, | |
| 822 | + .channels = vcnl4000_channels, | |
| 823 | + .num_channels = ARRAY_SIZE(vcnl4000_channels), | |
| 824 | + .info = &vcnl4000_info, | |
| 825 | + .irq_support = false, | |
| 826 | + }, | |
| 827 | + [VCNL4010] = { | |
| 828 | + .prod = "VCNL4010/4020", | |
| 829 | + .init = vcnl4000_init, | |
| 830 | + .measure_light = vcnl4000_measure_light, | |
| 831 | + .measure_proximity = vcnl4000_measure_proximity, | |
| 832 | + .set_power_state = vcnl4000_set_power_state, | |
| 833 | + .channels = vcnl4010_channels, | |
| 834 | + .num_channels = ARRAY_SIZE(vcnl4010_channels), | |
| 835 | + .info = &vcnl4010_info, | |
| 836 | + .irq_support = true, | |
| 837 | + }, | |
| 838 | + [VCNL4040] = { | |
| 839 | + .prod = "VCNL4040", | |
| 840 | + .init = vcnl4200_init, | |
| 841 | + .measure_light = vcnl4200_measure_light, | |
| 842 | + .measure_proximity = vcnl4200_measure_proximity, | |
| 843 | + .set_power_state = vcnl4200_set_power_state, | |
| 844 | + .channels = vcnl4000_channels, | |
| 845 | + .num_channels = ARRAY_SIZE(vcnl4000_channels), | |
| 846 | + .info = &vcnl4000_info, | |
| 847 | + .irq_support = false, | |
| 848 | + }, | |
| 849 | + [VCNL4200] = { | |
| 850 | + .prod = "VCNL4200", | |
| 851 | + .init = vcnl4200_init, | |
| 852 | + .measure_light = vcnl4200_measure_light, | |
| 853 | + .measure_proximity = vcnl4200_measure_proximity, | |
| 854 | + .set_power_state = vcnl4200_set_power_state, | |
| 855 | + .channels = vcnl4000_channels, | |
| 856 | + .num_channels = ARRAY_SIZE(vcnl4000_channels), | |
| 857 | + .info = &vcnl4000_info, | |
| 858 | + .irq_support = false, | |
| 859 | + }, | |
| 860 | +}; | |
| 861 | + | |
| 862 | +static irqreturn_t vcnl4010_irq_thread(int irq, void *p) | |
| 863 | +{ | |
| 864 | + struct iio_dev *indio_dev = p; | |
| 865 | + struct vcnl4000_data *data = iio_priv(indio_dev); | |
| 866 | + unsigned long isr; | |
| 867 | + int ret; | |
| 868 | + | |
| 869 | + ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR); | |
| 870 | + if (ret < 0) | |
| 871 | + goto end; | |
| 872 | + | |
| 873 | + isr = ret; | |
| 874 | + | |
| 875 | + if (isr & VCNL4010_INT_THR) { | |
| 876 | + if (test_bit(VCNL4010_INT_THR_LOW, &isr)) { | |
| 877 | + iio_push_event(indio_dev, | |
| 878 | + IIO_UNMOD_EVENT_CODE( | |
| 879 | + IIO_PROXIMITY, | |
| 880 | + 1, | |
| 881 | + IIO_EV_TYPE_THRESH, | |
| 882 | + IIO_EV_DIR_FALLING), | |
| 883 | + iio_get_time_ns(indio_dev)); | |
| 884 | + } | |
| 885 | + | |
| 886 | + if (test_bit(VCNL4010_INT_THR_HIGH, &isr)) { | |
| 887 | + iio_push_event(indio_dev, | |
| 888 | + IIO_UNMOD_EVENT_CODE( | |
| 889 | + IIO_PROXIMITY, | |
| 890 | + 1, | |
| 891 | + IIO_EV_TYPE_THRESH, | |
| 892 | + IIO_EV_DIR_RISING), | |
| 893 | + iio_get_time_ns(indio_dev)); | |
| 894 | + } | |
| 895 | + | |
| 896 | + i2c_smbus_write_byte_data(data->client, VCNL4010_ISR, | |
| 897 | + isr & VCNL4010_INT_THR); | |
| 898 | + } | |
| 899 | + | |
| 900 | + if (isr & VCNL4010_INT_DRDY && iio_buffer_enabled(indio_dev)) | |
| 901 | + iio_trigger_poll_chained(indio_dev->trig); | |
| 902 | + | |
| 903 | +end: | |
| 904 | + return IRQ_HANDLED; | |
| 905 | +} | |
| 906 | + | |
| 907 | +static irqreturn_t vcnl4010_trigger_handler(int irq, void *p) | |
| 908 | +{ | |
| 909 | + struct iio_poll_func *pf = p; | |
| 910 | + struct iio_dev *indio_dev = pf->indio_dev; | |
| 911 | + struct vcnl4000_data *data = iio_priv(indio_dev); | |
| 912 | + const unsigned long *active_scan_mask = indio_dev->active_scan_mask; | |
| 913 | + u16 buffer[8] = {0}; /* 1x16-bit + ts */ | |
| 914 | + bool data_read = false; | |
| 915 | + unsigned long isr; | |
| 916 | + int val = 0; | |
| 917 | + int ret; | |
| 918 | + | |
| 919 | + ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR); | |
| 920 | + if (ret < 0) | |
| 921 | + goto end; | |
| 922 | + | |
| 923 | + isr = ret; | |
| 924 | + | |
| 925 | + if (test_bit(0, active_scan_mask)) { | |
| 926 | + if (test_bit(VCNL4010_INT_PROXIMITY, &isr)) { | |
| 927 | + ret = vcnl4000_read_data(data, | |
| 928 | + VCNL4000_PS_RESULT_HI, | |
| 929 | + &val); | |
| 930 | + if (ret < 0) | |
| 931 | + goto end; | |
| 932 | + | |
| 933 | + buffer[0] = val; | |
| 934 | + data_read = true; | |
| 935 | + } | |
| 936 | + } | |
| 937 | + | |
| 938 | + ret = i2c_smbus_write_byte_data(data->client, VCNL4010_ISR, | |
| 939 | + isr & VCNL4010_INT_DRDY); | |
| 940 | + if (ret < 0) | |
| 941 | + goto end; | |
| 942 | + | |
| 943 | + if (!data_read) | |
| 944 | + goto end; | |
| 945 | + | |
| 946 | + iio_push_to_buffers_with_timestamp(indio_dev, buffer, | |
| 947 | + iio_get_time_ns(indio_dev)); | |
| 948 | + | |
| 949 | +end: | |
| 950 | + iio_trigger_notify_done(indio_dev->trig); | |
| 951 | + return IRQ_HANDLED; | |
| 952 | +} | |
| 953 | + | |
| 954 | +static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev) | |
| 955 | +{ | |
| 956 | + struct vcnl4000_data *data = iio_priv(indio_dev); | |
| 957 | + int ret; | |
| 958 | + int cmd; | |
| 959 | + | |
| 960 | + ret = iio_triggered_buffer_postenable(indio_dev); | |
| 961 | + if (ret) | |
| 962 | + return ret; | |
| 963 | + | |
| 964 | + /* Do not enable the buffer if we are already capturing events. */ | |
| 965 | + if (vcnl4010_is_in_periodic_mode(data)) { | |
| 966 | + ret = -EBUSY; | |
| 967 | + goto end; | |
| 968 | + } | |
| 969 | + | |
| 970 | + ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, | |
| 971 | + VCNL4010_INT_PROX_EN); | |
| 972 | + if (ret < 0) | |
| 973 | + goto end; | |
| 974 | + | |
| 975 | + cmd = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN; | |
| 976 | + ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd); | |
| 977 | + if (ret < 0) | |
| 978 | + goto end; | |
| 979 | + | |
| 980 | + return 0; | |
| 981 | +end: | |
| 982 | + iio_triggered_buffer_predisable(indio_dev); | |
| 983 | + | |
| 984 | + return ret; | |
| 985 | +} | |
| 986 | + | |
| 987 | +static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev) | |
| 988 | +{ | |
| 989 | + struct vcnl4000_data *data = iio_priv(indio_dev); | |
| 990 | + int ret, ret_disable; | |
| 991 | + | |
| 992 | + ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0); | |
| 993 | + if (ret < 0) | |
| 994 | + goto end; | |
| 995 | + | |
| 996 | + ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0); | |
| 997 | + | |
| 998 | +end: | |
| 999 | + ret_disable = iio_triggered_buffer_predisable(indio_dev); | |
| 1000 | + if (ret == 0) | |
| 1001 | + ret = ret_disable; | |
| 1002 | + | |
| 1003 | + return ret; | |
| 1004 | +} | |
| 1005 | + | |
| 1006 | +static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = { | |
| 1007 | + .postenable = &vcnl4010_buffer_postenable, | |
| 1008 | + .predisable = &vcnl4010_buffer_predisable, | |
| 1009 | +}; | |
| 1010 | + | |
| 1011 | +static const struct iio_trigger_ops vcnl4010_trigger_ops = { | |
| 1012 | + .validate_device = iio_trigger_validate_own_device, | |
| 1013 | +}; | |
| 1014 | + | |
| 1015 | +static int vcnl4010_probe_trigger(struct iio_dev *indio_dev) | |
| 1016 | +{ | |
| 1017 | + struct vcnl4000_data *data = iio_priv(indio_dev); | |
| 1018 | + struct i2c_client *client = data->client; | |
| 1019 | + struct iio_trigger *trigger; | |
| 1020 | + | |
| 1021 | + trigger = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", | |
| 1022 | + indio_dev->name, indio_dev->id); | |
| 1023 | + if (!trigger) | |
| 1024 | + return -ENOMEM; | |
| 1025 | + | |
| 1026 | + trigger->dev.parent = &client->dev; | |
| 1027 | + trigger->ops = &vcnl4010_trigger_ops; | |
| 1028 | + iio_trigger_set_drvdata(trigger, indio_dev); | |
| 1029 | + | |
| 1030 | + return devm_iio_trigger_register(&client->dev, trigger); | |
| 1031 | +} | |
| 1032 | + | |
| 440 | 1033 | static int vcnl4000_probe(struct i2c_client *client, |
| 441 | 1034 | const struct i2c_device_id *id) |
| 442 | 1035 | { |
| @@ -466,12 +1059,39 @@ static int vcnl4000_probe(struct i2c_client *client, · 23 unmodified lines | ||
| 466 | 1059 | data->near_level = 0; |
| 467 | 1060 | |
| 468 | 1061 | indio_dev->dev.parent = &client->dev; |
| 469 | − indio_dev->info = &vcnl4000_info; | |
| 470 | − indio_dev->channels = vcnl4000_channels; | |
| 471 | − indio_dev->num_channels = ARRAY_SIZE(vcnl4000_channels); | |
| 1062 | + indio_dev->info = data->chip_spec->info; | |
| 1063 | + indio_dev->channels = data->chip_spec->channels; | |
| 1064 | + indio_dev->num_channels = data->chip_spec->num_channels; | |
| 472 | 1065 | indio_dev->name = VCNL4000_DRV_NAME; |
| 473 | 1066 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 474 | 1067 | |
| 1068 | + if (client->irq && data->chip_spec->irq_support) { | |
| 1069 | + ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, | |
| 1070 | + NULL, | |
| 1071 | + vcnl4010_trigger_handler, | |
| 1072 | + &vcnl4010_buffer_ops); | |
| 1073 | + if (ret < 0) { | |
| 1074 | + dev_err(&client->dev, | |
| 1075 | + "unable to setup iio triggered buffer\n"); | |
| 1076 | + return ret; | |
| 1077 | + } | |
| 1078 | + | |
| 1079 | + ret = devm_request_threaded_irq(&client->dev, client->irq, | |
| 1080 | + NULL, vcnl4010_irq_thread, | |
| 1081 | + IRQF_TRIGGER_FALLING | | |
| 1082 | + IRQF_ONESHOT, | |
| 1083 | + "vcnl4010_irq", | |
| 1084 | + indio_dev); | |
| 1085 | + if (ret < 0) { | |
| 1086 | + dev_err(&client->dev, "irq request failed\n"); | |
| 1087 | + return ret; | |
| 1088 | + } | |
| 1089 | + | |
| 1090 | + ret = vcnl4010_probe_trigger(indio_dev); | |
| 1091 | + if (ret < 0) | |
| 1092 | + return ret; | |
| 1093 | + } | |
| 1094 | + | |
| 475 | 1095 | ret = pm_runtime_set_active(&client->dev); |
| 476 | 1096 | if (ret < 0) |
| 477 | 1097 | goto fail_poweroff; |
| @@ -565,5 +1185,6 @@ static struct i2c_driver vcnl4000_driver = { · 87 unmodified lines | ||
| 565 | 1185 | module_i2c_driver(vcnl4000_driver); |
| 566 | 1186 | |
| 567 | 1187 | MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); |
| 1188 | +MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>"); | |
| 568 | 1189 | MODULE_DESCRIPTION("Vishay VCNL4000 proximity/ambient light sensor driver"); |
| 569 | 1190 | MODULE_LICENSE("GPL"); |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | */ |
| 17 | 17 | |
| 18 | 18 | #include <linux/module.h> |
| 19 | +#include <linux/mod_devicetable.h> | |
| 19 | 20 | #include <linux/i2c.h> |
| 20 | 21 | #include <linux/mutex.h> |
| 21 | 22 | #include <linux/err.h> |
| @@ -537,7 +538,7 @@ MODULE_DEVICE_TABLE(i2c, vl6180_id); · 515 unmodified lines | ||
| 537 | 538 | static struct i2c_driver vl6180_driver = { |
| 538 | 539 | .driver = { |
| 539 | 540 | .name = VL6180_DRV_NAME, |
| 540 | − .of_match_table = of_match_ptr(vl6180_of_match), | |
| 541 | + .of_match_table = vl6180_of_match, | |
| 541 | 542 | }, |
| 542 | 543 | .probe = vl6180_probe, |
| 543 | 544 | .id_table = vl6180_id, |
| @@ -19,6 +19,8 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/iio/iio.h> |
| 20 | 20 | #include <linux/iio/sysfs.h> |
| 21 | 21 | |
| 22 | +#include <asm/unaligned.h> | |
| 23 | + | |
| 22 | 24 | #define ZOPT2201_DRV_NAME "zopt2201" |
| 23 | 25 | |
| 24 | 26 | /* Registers */ |
| @@ -219,7 +221,7 @@ static int zopt2201_read(struct zopt2201_data *data, u8 reg) · 194 unmodified lines | ||
| 219 | 221 | goto fail; |
| 220 | 222 | mutex_unlock(&data->lock); |
| 221 | 223 | |
| 222 | − return (buf[2] << 16) | (buf[1] << 8) | buf[0]; | |
| 224 | + return get_unaligned_le24(&buf[0]); | |
| 223 | 225 | |
| 224 | 226 | fail: |
| 225 | 227 | mutex_unlock(&data->lock); |
| @@ -49,6 +49,7 @@ · 48 unmodified lines | ||
| 49 | 49 | #define AK8974_WHOAMI_VALUE_AMI306 0x46 |
| 50 | 50 | #define AK8974_WHOAMI_VALUE_AMI305 0x47 |
| 51 | 51 | #define AK8974_WHOAMI_VALUE_AK8974 0x48 |
| 52 | +#define AK8974_WHOAMI_VALUE_HSCDTD008A 0x49 | |
| 52 | 53 | |
| 53 | 54 | #define AK8974_DATA_X 0x10 |
| 54 | 55 | #define AK8974_DATA_Y 0x12 |
| @@ -140,6 +141,12 @@ · 85 unmodified lines | ||
| 140 | 141 | #define AK8974_INT_CTRL_PULSE BIT(1) /* 0 = latched; 1 = pulse (50 usec) */ |
| 141 | 142 | #define AK8974_INT_CTRL_RESDEF (AK8974_INT_CTRL_XYZEN | AK8974_INT_CTRL_POL) |
| 142 | 143 | |
| 144 | +/* HSCDTD008A-specific control register */ | |
| 145 | +#define HSCDTD008A_CTRL4 0x1E | |
| 146 | +#define HSCDTD008A_CTRL4_MMD BIT(7) /* must be set to 1 */ | |
| 147 | +#define HSCDTD008A_CTRL4_RANGE BIT(4) /* 0 = 14-bit output; 1 = 15-bit output */ | |
| 148 | +#define HSCDTD008A_CTRL4_RESDEF (HSCDTD008A_CTRL4_MMD | HSCDTD008A_CTRL4_RANGE) | |
| 149 | + | |
| 143 | 150 | /* The AMI305 has elaborate FW version and serial number registers */ |
| 144 | 151 | #define AMI305_VER 0xE8 |
| 145 | 152 | #define AMI305_SN 0xEA |
| @@ -241,10 +248,17 @@ static int ak8974_reset(struct ak8974 *ak8974) · 95 unmodified lines | ||
| 241 | 248 | ret = regmap_write(ak8974->map, AK8974_CTRL3, AK8974_CTRL3_RESDEF); |
| 242 | 249 | if (ret) |
| 243 | 250 | return ret; |
| 244 | − ret = regmap_write(ak8974->map, AK8974_INT_CTRL, | |
| 245 | − AK8974_INT_CTRL_RESDEF); | |
| 246 | − if (ret) | |
| 247 | − return ret; | |
| 251 | + if (ak8974->variant != AK8974_WHOAMI_VALUE_HSCDTD008A) { | |
| 252 | + ret = regmap_write(ak8974->map, AK8974_INT_CTRL, | |
| 253 | + AK8974_INT_CTRL_RESDEF); | |
| 254 | + if (ret) | |
| 255 | + return ret; | |
| 256 | + } else { | |
| 257 | + ret = regmap_write(ak8974->map, HSCDTD008A_CTRL4, | |
| 258 | + HSCDTD008A_CTRL4_RESDEF); | |
| 259 | + if (ret) | |
| 260 | + return ret; | |
| 261 | + } | |
| 248 | 262 | |
| 249 | 263 | /* After reset, power off is default state */ |
| 250 | 264 | return ak8974_set_power(ak8974, AK8974_PWR_OFF); |
| @@ -267,6 +281,8 @@ static int ak8974_configure(struct ak8974 *ak8974) · 16 unmodified lines | ||
| 267 | 281 | if (ret) |
| 268 | 282 | return ret; |
| 269 | 283 | } |
| 284 | + if (ak8974->variant == AK8974_WHOAMI_VALUE_HSCDTD008A) | |
| 285 | + return 0; | |
| 270 | 286 | ret = regmap_write(ak8974->map, AK8974_INT_CTRL, AK8974_INT_CTRL_POL); |
| 271 | 287 | if (ret) |
| 272 | 288 | return ret; |
| @@ -495,6 +511,10 @@ static int ak8974_detect(struct ak8974 *ak8974) · 222 unmodified lines | ||
| 495 | 511 | name = "ak8974"; |
| 496 | 512 | dev_info(&ak8974->i2c->dev, "detected AK8974\n"); |
| 497 | 513 | break; |
| 514 | + case AK8974_WHOAMI_VALUE_HSCDTD008A: | |
| 515 | + name = "hscdtd008a"; | |
| 516 | + dev_info(&ak8974->i2c->dev, "detected hscdtd008a\n"); | |
| 517 | + break; | |
| 498 | 518 | default: |
| 499 | 519 | dev_err(&ak8974->i2c->dev, "unsupported device (%02x) ", |
| 500 | 520 | whoami); |
| @@ -534,47 +554,103 @@ static int ak8974_detect(struct ak8974 *ak8974) · 33 unmodified lines | ||
| 534 | 554 | return 0; |
| 535 | 555 | } |
| 536 | 556 | |
| 557 | +static int ak8974_measure_channel(struct ak8974 *ak8974, unsigned long address, | |
| 558 | + int *val) | |
| 559 | +{ | |
| 560 | + __le16 hw_values[3]; | |
| 561 | + int ret; | |
| 562 | + | |
| 563 | + pm_runtime_get_sync(&ak8974->i2c->dev); | |
| 564 | + mutex_lock(&ak8974->lock); | |
| 565 | + | |
| 566 | + /* | |
| 567 | + * We read all axes and discard all but one, for optimized | |
| 568 | + * reading, use the triggered buffer. | |
| 569 | + */ | |
| 570 | + ret = ak8974_trigmeas(ak8974); | |
| 571 | + if (ret) | |
| 572 | + goto out_unlock; | |
| 573 | + ret = ak8974_getresult(ak8974, hw_values); | |
| 574 | + if (ret) | |
| 575 | + goto out_unlock; | |
| 576 | + /* | |
| 577 | + * This explicit cast to (s16) is necessary as the measurement | |
| 578 | + * is done in 2's complement with positive and negative values. | |
| 579 | + * The follwing assignment to *val will then convert the signed | |
| 580 | + * s16 value to a signed int value. | |
| 581 | + */ | |
| 582 | + *val = (s16)le16_to_cpu(hw_values[address]); | |
| 583 | +out_unlock: | |
| 584 | + mutex_unlock(&ak8974->lock); | |
| 585 | + pm_runtime_mark_last_busy(&ak8974->i2c->dev); | |
| 586 | + pm_runtime_put_autosuspend(&ak8974->i2c->dev); | |
| 587 | + | |
| 588 | + return ret; | |
| 589 | +} | |
| 590 | + | |
| 537 | 591 | static int ak8974_read_raw(struct iio_dev *indio_dev, |
| 538 | 592 | struct iio_chan_spec const *chan, |
| 539 | 593 | int *val, int *val2, |
| 540 | 594 | long mask) |
| 541 | 595 | { |
| 542 | 596 | struct ak8974 *ak8974 = iio_priv(indio_dev); |
| 543 | − __le16 hw_values[3]; | |
| 544 | − int ret = -EINVAL; | |
| 545 | − | |
| 546 | − pm_runtime_get_sync(&ak8974->i2c->dev); | |
| 547 | − mutex_lock(&ak8974->lock); | |
| 597 | + int ret; | |
| 548 | 598 | |
| 549 | 599 | switch (mask) { |
| 550 | 600 | case IIO_CHAN_INFO_RAW: |
| 551 | 601 | if (chan->address > 2) { |
| 552 | 602 | dev_err(&ak8974->i2c->dev, "faulty channel address\n"); |
| 553 | − ret = -EIO; | |
| 554 | − goto out_unlock; | |
| 603 | + return -EIO; | |
| 555 | 604 | } |
| 556 | − ret = ak8974_trigmeas(ak8974); | |
| 557 | − if (ret) | |
| 558 | − goto out_unlock; | |
| 559 | − ret = ak8974_getresult(ak8974, hw_values); | |
| 605 | + ret = ak8974_measure_channel(ak8974, chan->address, val); | |
| 560 | 606 | if (ret) |
| 561 | − goto out_unlock; | |
| 562 | − | |
| 563 | − /* | |
| 564 | − * We read all axes and discard all but one, for optimized | |
| 565 | − * reading, use the triggered buffer. | |
| 566 | − */ | |
| 567 | − *val = (s16)le16_to_cpu(hw_values[chan->address]); | |
| 568 | − | |
| 569 | − ret = IIO_VAL_INT; | |
| 607 | + return ret; | |
| 608 | + return IIO_VAL_INT; | |
| 609 | + case IIO_CHAN_INFO_SCALE: | |
| 610 | + switch (ak8974->variant) { | |
| 611 | + case AK8974_WHOAMI_VALUE_AMI306: | |
| 612 | + case AK8974_WHOAMI_VALUE_AMI305: | |
| 613 | + /* | |
| 614 | + * The datasheet for AMI305 and AMI306, page 6 | |
| 615 | + * specifies the range of the sensor to be | |
| 616 | + * +/- 12 Gauss. | |
| 617 | + */ | |
| 618 | + *val = 12; | |
| 619 | + /* | |
| 620 | + * 12 bits are used, +/- 2^11 | |
| 621 | + * [ -2048 .. 2047 ] (manual page 20) | |
| 622 | + * [ 0xf800 .. 0x07ff ] | |
| 623 | + */ | |
| 624 | + *val2 = 11; | |
| 625 | + return IIO_VAL_FRACTIONAL_LOG2; | |
| 626 | + case AK8974_WHOAMI_VALUE_HSCDTD008A: | |
| 627 | + /* | |
| 628 | + * The datasheet for HSCDTF008A, page 3 specifies the | |
| 629 | + * range of the sensor as +/- 2.4 mT per axis, which | |
| 630 | + * corresponds to +/- 2400 uT = +/- 24 Gauss. | |
| 631 | + */ | |
| 632 | + *val = 24; | |
| 633 | + /* | |
| 634 | + * 15 bits are used (set up in CTRL4), +/- 2^14 | |
| 635 | + * [ -16384 .. 16383 ] (manual page 24) | |
| 636 | + * [ 0xc000 .. 0x3fff ] | |
| 637 | + */ | |
| 638 | + *val2 = 14; | |
| 639 | + return IIO_VAL_FRACTIONAL_LOG2; | |
| 640 | + default: | |
| 641 | + /* GUESSING +/- 12 Gauss */ | |
| 642 | + *val = 12; | |
| 643 | + /* GUESSING 12 bits ADC +/- 2^11 */ | |
| 644 | + *val2 = 11; | |
| 645 | + return IIO_VAL_FRACTIONAL_LOG2; | |
| 646 | + } | |
| 647 | + break; | |
| 648 | + default: | |
| 649 | + /* Unknown request */ | |
| 650 | + break; | |
| 570 | 651 | } |
| 571 | 652 | |
| 572 | − out_unlock: | |
| 573 | − mutex_unlock(&ak8974->lock); | |
| 574 | − pm_runtime_mark_last_busy(&ak8974->i2c->dev); | |
| 575 | − pm_runtime_put_autosuspend(&ak8974->i2c->dev); | |
| 576 | − | |
| 577 | − return ret; | |
| 653 | + return -EINVAL; | |
| 578 | 654 | } |
| 579 | 655 | |
| 580 | 656 | static void ak8974_fill_buffer(struct iio_dev *indio_dev) |
| @@ -631,27 +707,44 @@ static const struct iio_chan_spec_ext_info ak8974_ext_info[] = { · 50 unmodified lines | ||
| 631 | 707 | { }, |
| 632 | 708 | }; |
| 633 | 709 | |
| 634 | −#define AK8974_AXIS_CHANNEL(axis, index) \ | |
| 710 | +#define AK8974_AXIS_CHANNEL(axis, index, bits) \ | |
| 635 | 711 | { \ |
| 636 | 712 | .type = IIO_MAGN, \ |
| 637 | 713 | .modified = 1, \ |
| 638 | 714 | .channel2 = IIO_MOD_##axis, \ |
| 639 | − .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
| 715 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | |
| 716 | + BIT(IIO_CHAN_INFO_SCALE), \ | |
| 640 | 717 | .ext_info = ak8974_ext_info, \ |
| 641 | 718 | .address = index, \ |
| 642 | 719 | .scan_index = index, \ |
| 643 | 720 | .scan_type = { \ |
| 644 | 721 | .sign = 's', \ |
| 645 | − .realbits = 16, \ | |
| 722 | + .realbits = bits, \ | |
| 646 | 723 | .storagebits = 16, \ |
| 647 | 724 | .endianness = IIO_LE \ |
| 648 | 725 | }, \ |
| 649 | 726 | } |
| 650 | 727 | |
| 651 | −static const struct iio_chan_spec ak8974_channels[] = { | |
| 652 | − AK8974_AXIS_CHANNEL(X, 0), | |
| 653 | − AK8974_AXIS_CHANNEL(Y, 1), | |
| 654 | − AK8974_AXIS_CHANNEL(Z, 2), | |
| 728 | +/* | |
| 729 | + * We have no datasheet for the AK8974 but we guess that its | |
| 730 | + * ADC is 12 bits. The AMI305 and AMI306 certainly has 12bit | |
| 731 | + * ADC. | |
| 732 | + */ | |
| 733 | +static const struct iio_chan_spec ak8974_12_bits_channels[] = { | |
| 734 | + AK8974_AXIS_CHANNEL(X, 0, 12), | |
| 735 | + AK8974_AXIS_CHANNEL(Y, 1, 12), | |
| 736 | + AK8974_AXIS_CHANNEL(Z, 2, 12), | |
| 737 | + IIO_CHAN_SOFT_TIMESTAMP(3), | |
| 738 | +}; | |
| 739 | + | |
| 740 | +/* | |
| 741 | + * The HSCDTD008A has 15 bits resolution the way we set it up | |
| 742 | + * in CTRL4. | |
| 743 | + */ | |
| 744 | +static const struct iio_chan_spec ak8974_15_bits_channels[] = { | |
| 745 | + AK8974_AXIS_CHANNEL(X, 0, 15), | |
| 746 | + AK8974_AXIS_CHANNEL(Y, 1, 15), | |
| 747 | + AK8974_AXIS_CHANNEL(Z, 2, 15), | |
| 655 | 748 | IIO_CHAN_SOFT_TIMESTAMP(3), |
| 656 | 749 | }; |
| 657 | 750 | |
| @@ -674,18 +767,18 @@ static bool ak8974_writeable_reg(struct device *dev, unsigned int reg) · 16 unmodified lines | ||
| 674 | 767 | case AK8974_INT_CTRL: |
| 675 | 768 | case AK8974_INT_THRES: |
| 676 | 769 | case AK8974_INT_THRES + 1: |
| 770 | + return true; | |
| 677 | 771 | case AK8974_PRESET: |
| 678 | 772 | case AK8974_PRESET + 1: |
| 679 | − return true; | |
| 773 | + return ak8974->variant != AK8974_WHOAMI_VALUE_HSCDTD008A; | |
| 680 | 774 | case AK8974_OFFSET_X: |
| 681 | 775 | case AK8974_OFFSET_X + 1: |
| 682 | 776 | case AK8974_OFFSET_Y: |
| 683 | 777 | case AK8974_OFFSET_Y + 1: |
| 684 | 778 | case AK8974_OFFSET_Z: |
| 685 | 779 | case AK8974_OFFSET_Z + 1: |
| 686 | − if (ak8974->variant == AK8974_WHOAMI_VALUE_AK8974) | |
| 687 | − return true; | |
| 688 | − return false; | |
| 780 | + return ak8974->variant == AK8974_WHOAMI_VALUE_AK8974 || | |
| 781 | + ak8974->variant == AK8974_WHOAMI_VALUE_HSCDTD008A; | |
| 689 | 782 | case AMI305_OFFSET_X: |
| 690 | 783 | case AMI305_OFFSET_X + 1: |
| 691 | 784 | case AMI305_OFFSET_Y: |
| @@ -800,8 +893,21 @@ static int ak8974_probe(struct i2c_client *i2c, · 108 unmodified lines | ||
| 800 | 893 | pm_runtime_put(&i2c->dev); |
| 801 | 894 | |
| 802 | 895 | indio_dev->dev.parent = &i2c->dev; |
| 803 | − indio_dev->channels = ak8974_channels; | |
| 804 | − indio_dev->num_channels = ARRAY_SIZE(ak8974_channels); | |
| 896 | + switch (ak8974->variant) { | |
| 897 | + case AK8974_WHOAMI_VALUE_AMI306: | |
| 898 | + case AK8974_WHOAMI_VALUE_AMI305: | |
| 899 | + indio_dev->channels = ak8974_12_bits_channels; | |
| 900 | + indio_dev->num_channels = ARRAY_SIZE(ak8974_12_bits_channels); | |
| 901 | + break; | |
| 902 | + case AK8974_WHOAMI_VALUE_HSCDTD008A: | |
| 903 | + indio_dev->channels = ak8974_15_bits_channels; | |
| 904 | + indio_dev->num_channels = ARRAY_SIZE(ak8974_15_bits_channels); | |
| 905 | + break; | |
| 906 | + default: | |
| 907 | + indio_dev->channels = ak8974_12_bits_channels; | |
| 908 | + indio_dev->num_channels = ARRAY_SIZE(ak8974_12_bits_channels); | |
| 909 | + break; | |
| 910 | + } | |
| 805 | 911 | indio_dev->info = &ak8974_info; |
| 806 | 912 | indio_dev->available_scan_masks = ak8974_scan_masks; |
| 807 | 913 | indio_dev->modes = INDIO_DIRECT_MODE; |
| @@ -931,12 +1037,14 @@ static const struct i2c_device_id ak8974_id[] = { · 123 unmodified lines | ||
| 931 | 1037 | {"ami305", 0 }, |
| 932 | 1038 | {"ami306", 0 }, |
| 933 | 1039 | {"ak8974", 0 }, |
| 1040 | + {"hscdtd008a", 0 }, | |
| 934 | 1041 | {} |
| 935 | 1042 | }; |
| 936 | 1043 | MODULE_DEVICE_TABLE(i2c, ak8974_id); |
| 937 | 1044 | |
| 938 | 1045 | static const struct of_device_id ak8974_of_match[] = { |
| 939 | 1046 | { .compatible = "asahi-kasei,ak8974", }, |
| 1047 | + { .compatible = "alps,hscdtd008a", }, | |
| 940 | 1048 | {} |
| 941 | 1049 | }; |
| 942 | 1050 | MODULE_DEVICE_TABLE(of, ak8974_of_match); |
| @@ -14,8 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/iio/iio.h> |
| 15 | 15 | #include <linux/iio/sysfs.h> |
| 16 | 16 | #include <linux/iio/buffer.h> |
| 17 | −#include <linux/iio/trigger_consumer.h> | |
| 18 | −#include <linux/iio/triggered_buffer.h> | |
| 19 | 17 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 20 | 18 | |
| 21 | 19 | enum magn_3d_channel { |
| @@ -519,18 +517,13 @@ static int hid_magn_3d_probe(struct platform_device *pdev) · 497 unmodified lines | ||
| 519 | 517 | indio_dev->name = name; |
| 520 | 518 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 521 | 519 | |
| 522 | − ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, | |
| 523 | − NULL, NULL); | |
| 524 | − if (ret) { | |
| 525 | − dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | |
| 526 | − return ret; | |
| 527 | − } | |
| 528 | 520 | atomic_set(&magn_state->magn_flux_attributes.data_ready, 0); |
| 521 | + | |
| 529 | 522 | ret = hid_sensor_setup_trigger(indio_dev, name, |
| 530 | 523 | &magn_state->magn_flux_attributes); |
| 531 | 524 | if (ret < 0) { |
| 532 | 525 | dev_err(&pdev->dev, "trigger setup failed\n"); |
| 533 | − goto error_unreg_buffer_funcs; | |
| 526 | + return ret; | |
| 534 | 527 | } |
| 535 | 528 | |
| 536 | 529 | ret = iio_device_register(indio_dev); |
| @@ -554,9 +547,7 @@ static int hid_magn_3d_probe(struct platform_device *pdev) · 17 unmodified lines | ||
| 554 | 547 | error_iio_unreg: |
| 555 | 548 | iio_device_unregister(indio_dev); |
| 556 | 549 | error_remove_trigger: |
| 557 | − hid_sensor_remove_trigger(&magn_state->magn_flux_attributes); | |
| 558 | −error_unreg_buffer_funcs: | |
| 559 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 550 | + hid_sensor_remove_trigger(indio_dev, &magn_state->magn_flux_attributes); | |
| 560 | 551 | return ret; |
| 561 | 552 | } |
| 562 | 553 | |
| @@ -569,8 +560,7 @@ static int hid_magn_3d_remove(struct platform_device *pdev) · 6 unmodified lines | ||
| 569 | 560 | |
| 570 | 561 | sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D); |
| 571 | 562 | iio_device_unregister(indio_dev); |
| 572 | − hid_sensor_remove_trigger(&magn_state->magn_flux_attributes); | |
| 573 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 563 | + hid_sensor_remove_trigger(indio_dev, &magn_state->magn_flux_attributes); | |
| 574 | 564 | |
| 575 | 565 | return 0; |
| 576 | 566 | } |
| @@ -22,6 +22,8 @@ · 21 unmodified lines | ||
| 22 | 22 | #include <linux/iio/triggered_buffer.h> |
| 23 | 23 | #include <linux/iio/trigger_consumer.h> |
| 24 | 24 | |
| 25 | +#include <asm/unaligned.h> | |
| 26 | + | |
| 25 | 27 | #include "rm3100.h" |
| 26 | 28 | |
| 27 | 29 | /* Cycle Count Registers. */ |
| @@ -223,8 +225,7 @@ static int rm3100_read_mag(struct rm3100_data *data, int idx, int *val) · 195 unmodified lines | ||
| 223 | 225 | goto unlock_return; |
| 224 | 226 | mutex_unlock(&data->lock); |
| 225 | 227 | |
| 226 | − *val = sign_extend32((buffer[0] << 16) | (buffer[1] << 8) | buffer[2], | |
| 227 | − 23); | |
| 228 | + *val = sign_extend32(get_unaligned_be24(&buffer[0]), 23); | |
| 228 | 229 | |
| 229 | 230 | return IIO_VAL_INT; |
| 230 | 231 | |
| @@ -15,8 +15,6 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/iio/iio.h> |
| 16 | 16 | #include <linux/iio/sysfs.h> |
| 17 | 17 | #include <linux/iio/buffer.h> |
| 18 | −#include <linux/iio/trigger_consumer.h> | |
| 19 | −#include <linux/iio/triggered_buffer.h> | |
| 20 | 18 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 21 | 19 | |
| 22 | 20 | enum incl_3d_channel { |
| @@ -346,18 +344,13 @@ static int hid_incl_3d_probe(struct platform_device *pdev) · 323 unmodified lines | ||
| 346 | 344 | indio_dev->name = name; |
| 347 | 345 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 348 | 346 | |
| 349 | − ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, | |
| 350 | − NULL, NULL); | |
| 351 | − if (ret) { | |
| 352 | − dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | |
| 353 | − goto error_free_dev_mem; | |
| 354 | − } | |
| 355 | 347 | atomic_set(&incl_state->common_attributes.data_ready, 0); |
| 348 | + | |
| 356 | 349 | ret = hid_sensor_setup_trigger(indio_dev, name, |
| 357 | 350 | &incl_state->common_attributes); |
| 358 | 351 | if (ret) { |
| 359 | 352 | dev_err(&pdev->dev, "trigger setup failed\n"); |
| 360 | − goto error_unreg_buffer_funcs; | |
| 353 | + goto error_free_dev_mem; | |
| 361 | 354 | } |
| 362 | 355 | |
| 363 | 356 | ret = iio_device_register(indio_dev); |
| @@ -382,9 +375,7 @@ static int hid_incl_3d_probe(struct platform_device *pdev) · 18 unmodified lines | ||
| 382 | 375 | error_iio_unreg: |
| 383 | 376 | iio_device_unregister(indio_dev); |
| 384 | 377 | error_remove_trigger: |
| 385 | − hid_sensor_remove_trigger(&incl_state->common_attributes); | |
| 386 | −error_unreg_buffer_funcs: | |
| 387 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 378 | + hid_sensor_remove_trigger(indio_dev, &incl_state->common_attributes); | |
| 388 | 379 | error_free_dev_mem: |
| 389 | 380 | kfree(indio_dev->channels); |
| 390 | 381 | return ret; |
| @@ -399,8 +390,7 @@ static int hid_incl_3d_remove(struct platform_device *pdev) · 8 unmodified lines | ||
| 399 | 390 | |
| 400 | 391 | sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_INCLINOMETER_3D); |
| 401 | 392 | iio_device_unregister(indio_dev); |
| 402 | − hid_sensor_remove_trigger(&incl_state->common_attributes); | |
| 403 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 393 | + hid_sensor_remove_trigger(indio_dev, &incl_state->common_attributes); | |
| 404 | 394 | kfree(indio_dev->channels); |
| 405 | 395 | |
| 406 | 396 | return 0; |
| @@ -14,8 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/iio/iio.h> |
| 15 | 15 | #include <linux/iio/sysfs.h> |
| 16 | 16 | #include <linux/iio/buffer.h> |
| 17 | −#include <linux/iio/trigger_consumer.h> | |
| 18 | −#include <linux/iio/triggered_buffer.h> | |
| 19 | 17 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 20 | 18 | |
| 21 | 19 | struct dev_rot_state { |
| @@ -288,18 +286,13 @@ static int hid_dev_rot_probe(struct platform_device *pdev) · 266 unmodified lines | ||
| 288 | 286 | indio_dev->name = name; |
| 289 | 287 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 290 | 288 | |
| 291 | − ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, | |
| 292 | − NULL, NULL); | |
| 293 | − if (ret) { | |
| 294 | − dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | |
| 295 | − return ret; | |
| 296 | − } | |
| 297 | 289 | atomic_set(&rot_state->common_attributes.data_ready, 0); |
| 290 | + | |
| 298 | 291 | ret = hid_sensor_setup_trigger(indio_dev, name, |
| 299 | 292 | &rot_state->common_attributes); |
| 300 | 293 | if (ret) { |
| 301 | 294 | dev_err(&pdev->dev, "trigger setup failed\n"); |
| 302 | − goto error_unreg_buffer_funcs; | |
| 295 | + return ret; | |
| 303 | 296 | } |
| 304 | 297 | |
| 305 | 298 | ret = iio_device_register(indio_dev); |
| @@ -323,9 +316,7 @@ static int hid_dev_rot_probe(struct platform_device *pdev) · 17 unmodified lines | ||
| 323 | 316 | error_iio_unreg: |
| 324 | 317 | iio_device_unregister(indio_dev); |
| 325 | 318 | error_remove_trigger: |
| 326 | − hid_sensor_remove_trigger(&rot_state->common_attributes); | |
| 327 | −error_unreg_buffer_funcs: | |
| 328 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 319 | + hid_sensor_remove_trigger(indio_dev, &rot_state->common_attributes); | |
| 329 | 320 | return ret; |
| 330 | 321 | } |
| 331 | 322 | |
| @@ -338,8 +329,7 @@ static int hid_dev_rot_remove(struct platform_device *pdev) · 6 unmodified lines | ||
| 338 | 329 | |
| 339 | 330 | sensor_hub_remove_callback(hsdev, hsdev->usage); |
| 340 | 331 | iio_device_unregister(indio_dev); |
| 341 | − hid_sensor_remove_trigger(&rot_state->common_attributes); | |
| 342 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 332 | + hid_sensor_remove_trigger(indio_dev, &rot_state->common_attributes); | |
| 343 | 333 | |
| 344 | 334 | return 0; |
| 345 | 335 | } |
| @@ -271,6 +271,8 @@ static u32 bmp280_compensate_humidity(struct bmp280_data *data, · 270 unmodified lines | ||
| 271 | 271 | + (s32)2097152) * calib->H2 + 8192) >> 14); |
| 272 | 272 | var -= ((((var >> 15) * (var >> 15)) >> 7) * (s32)calib->H1) >> 4; |
| 273 | 273 | |
| 274 | + var = clamp_val(var, 0, 419430400); | |
| 275 | + | |
| 274 | 276 | return var >> 12; |
| 275 | 277 | }; |
| 276 | 278 | |
| @@ -14,8 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/iio/iio.h> |
| 15 | 15 | #include <linux/iio/sysfs.h> |
| 16 | 16 | #include <linux/iio/buffer.h> |
| 17 | −#include <linux/iio/trigger_consumer.h> | |
| 18 | −#include <linux/iio/triggered_buffer.h> | |
| 19 | 17 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 20 | 18 | |
| 21 | 19 | #define CHANNEL_SCAN_INDEX_PRESSURE 0 |
| @@ -290,18 +288,13 @@ static int hid_press_probe(struct platform_device *pdev) · 268 unmodified lines | ||
| 290 | 288 | indio_dev->name = name; |
| 291 | 289 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 292 | 290 | |
| 293 | − ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, | |
| 294 | − NULL, NULL); | |
| 295 | − if (ret) { | |
| 296 | − dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); | |
| 297 | − goto error_free_dev_mem; | |
| 298 | − } | |
| 299 | 291 | atomic_set(&press_state->common_attributes.data_ready, 0); |
| 292 | + | |
| 300 | 293 | ret = hid_sensor_setup_trigger(indio_dev, name, |
| 301 | 294 | &press_state->common_attributes); |
| 302 | 295 | if (ret) { |
| 303 | 296 | dev_err(&pdev->dev, "trigger setup failed\n"); |
| 304 | − goto error_unreg_buffer_funcs; | |
| 297 | + goto error_free_dev_mem; | |
| 305 | 298 | } |
| 306 | 299 | |
| 307 | 300 | ret = iio_device_register(indio_dev); |
| @@ -325,9 +318,7 @@ static int hid_press_probe(struct platform_device *pdev) · 17 unmodified lines | ||
| 325 | 318 | error_iio_unreg: |
| 326 | 319 | iio_device_unregister(indio_dev); |
| 327 | 320 | error_remove_trigger: |
| 328 | − hid_sensor_remove_trigger(&press_state->common_attributes); | |
| 329 | −error_unreg_buffer_funcs: | |
| 330 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 321 | + hid_sensor_remove_trigger(indio_dev, &press_state->common_attributes); | |
| 331 | 322 | error_free_dev_mem: |
| 332 | 323 | kfree(indio_dev->channels); |
| 333 | 324 | return ret; |
| @@ -342,8 +333,7 @@ static int hid_press_remove(struct platform_device *pdev) · 8 unmodified lines | ||
| 342 | 333 | |
| 343 | 334 | sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PRESSURE); |
| 344 | 335 | iio_device_unregister(indio_dev); |
| 345 | − hid_sensor_remove_trigger(&press_state->common_attributes); | |
| 346 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 336 | + hid_sensor_remove_trigger(indio_dev, &press_state->common_attributes); | |
| 347 | 337 | kfree(indio_dev->channels); |
| 348 | 338 | |
| 349 | 339 | return 0; |
| @@ -18,6 +18,8 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/util_macros.h> |
| 19 | 19 | #include <linux/acpi.h> |
| 20 | 20 | |
| 21 | +#include <asm/unaligned.h> | |
| 22 | + | |
| 21 | 23 | /* I2C commands: */ |
| 22 | 24 | #define HP206C_CMD_SOFT_RST 0x06 |
| 23 | 25 | |
| @@ -93,12 +95,12 @@ static int hp206c_read_20bit(struct i2c_client *client, u8 cmd) · 69 unmodified lines | ||
| 93 | 95 | int ret; |
| 94 | 96 | u8 values[3]; |
| 95 | 97 | |
| 96 | − ret = i2c_smbus_read_i2c_block_data(client, cmd, 3, values); | |
| 98 | + ret = i2c_smbus_read_i2c_block_data(client, cmd, sizeof(values), values); | |
| 97 | 99 | if (ret < 0) |
| 98 | 100 | return ret; |
| 99 | − if (ret != 3) | |
| 101 | + if (ret != sizeof(values)) | |
| 100 | 102 | return -EIO; |
| 101 | − return ((values[0] & 0xF) << 16) | (values[1] << 8) | (values[2]); | |
| 103 | + return get_unaligned_be24(&values[0]) & GENMASK(19, 0); | |
| 102 | 104 | } |
| 103 | 105 | |
| 104 | 106 | /* Spin for max 160ms until DEV_RDY is 1, or return error. */ |
| @@ -16,6 +16,8 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/module.h> |
| 17 | 17 | #include <linux/of_device.h> |
| 18 | 18 | |
| 19 | +#include <asm/unaligned.h> | |
| 20 | + | |
| 19 | 21 | #include "ms5611.h" |
| 20 | 22 | |
| 21 | 23 | static int ms5611_i2c_reset(struct device *dev) |
| @@ -50,7 +52,7 @@ static int ms5611_i2c_read_adc(struct ms5611_state *st, s32 *val) · 28 unmodified lines | ||
| 50 | 52 | if (ret < 0) |
| 51 | 53 | return ret; |
| 52 | 54 | |
| 53 | − *val = (buf[0] << 16) | (buf[1] << 8) | buf[2]; | |
| 55 | + *val = get_unaligned_be24(&buf[0]); | |
| 54 | 56 | |
| 55 | 57 | return 0; |
| 56 | 58 | } |
| @@ -11,6 +11,8 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/spi/spi.h> |
| 12 | 12 | #include <linux/of_device.h> |
| 13 | 13 | |
| 14 | +#include <asm/unaligned.h> | |
| 15 | + | |
| 14 | 16 | #include "ms5611.h" |
| 15 | 17 | |
| 16 | 18 | static int ms5611_spi_reset(struct device *dev) |
| @@ -45,7 +47,7 @@ static int ms5611_spi_read_adc(struct device *dev, s32 *val) · 28 unmodified lines | ||
| 45 | 47 | if (ret < 0) |
| 46 | 48 | return ret; |
| 47 | 49 | |
| 48 | − *val = (buf[0] << 16) | (buf[1] << 8) | buf[2]; | |
| 50 | + *val = get_unaligned_be24(&buf[0]); | |
| 49 | 51 | |
| 50 | 52 | return 0; |
| 51 | 53 | } |
| @@ -64,6 +64,7 @@ · 63 unmodified lines | ||
| 64 | 64 | #include <linux/iio/trigger.h> |
| 65 | 65 | #include <linux/iio/trigger_consumer.h> |
| 66 | 66 | #include <linux/iio/triggered_buffer.h> |
| 67 | +#include <asm/unaligned.h> | |
| 67 | 68 | #include "zpa2326.h" |
| 68 | 69 | |
| 69 | 70 | /* 200 ms should be enough for the longest conversion time in one-shot mode. */ |
| @@ -1005,22 +1006,20 @@ static int zpa2326_fetch_raw_sample(const struct iio_dev *indio_dev, · 935 unmodified lines | ||
| 1005 | 1006 | struct regmap *regs = ((struct zpa2326_private *) |
| 1006 | 1007 | iio_priv(indio_dev))->regmap; |
| 1007 | 1008 | int err; |
| 1009 | + u8 v[3]; | |
| 1008 | 1010 | |
| 1009 | 1011 | switch (type) { |
| 1010 | 1012 | case IIO_PRESSURE: |
| 1011 | 1013 | zpa2326_dbg(indio_dev, "fetching raw pressure sample"); |
| 1012 | 1014 | |
| 1013 | − err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, value, | |
| 1014 | − 3); | |
| 1015 | + err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, v, sizeof(v)); | |
| 1015 | 1016 | if (err) { |
| 1016 | 1017 | zpa2326_warn(indio_dev, "failed to fetch pressure (%d)", |
| 1017 | 1018 | err); |
| 1018 | 1019 | return err; |
| 1019 | 1020 | } |
| 1020 | 1021 | |
| 1021 | − /* Pressure is a 24 bits wide little-endian unsigned int. */ | |
| 1022 | − *value = (((u8 *)value)[2] << 16) | (((u8 *)value)[1] << 8) | | |
| 1023 | − ((u8 *)value)[0]; | |
| 1022 | + *value = get_unaligned_le24(&v[0]); | |
| 1024 | 1023 | |
| 1025 | 1024 | return IIO_VAL_INT; |
| 1026 | 1025 | |
| @@ -7,8 +7,6 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/hid-sensor-hub.h> |
| 8 | 8 | #include <linux/iio/buffer.h> |
| 9 | 9 | #include <linux/iio/iio.h> |
| 10 | −#include <linux/iio/triggered_buffer.h> | |
| 11 | −#include <linux/iio/trigger_consumer.h> | |
| 12 | 10 | #include <linux/module.h> |
| 13 | 11 | #include <linux/platform_device.h> |
| 14 | 12 | |
| @@ -230,12 +228,8 @@ static int hid_temperature_probe(struct platform_device *pdev) · 215 unmodified lines | ||
| 230 | 228 | indio_dev->name = name; |
| 231 | 229 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 232 | 230 | |
| 233 | − ret = devm_iio_triggered_buffer_setup(&pdev->dev, indio_dev, | |
| 234 | − &iio_pollfunc_store_time, NULL, NULL); | |
| 235 | − if (ret) | |
| 236 | − return ret; | |
| 237 | − | |
| 238 | 231 | atomic_set(&temp_st->common_attributes.data_ready, 0); |
| 232 | + | |
| 239 | 233 | ret = hid_sensor_setup_trigger(indio_dev, name, |
| 240 | 234 | &temp_st->common_attributes); |
| 241 | 235 | if (ret) |
| @@ -258,7 +252,7 @@ static int hid_temperature_probe(struct platform_device *pdev) · 16 unmodified lines | ||
| 258 | 252 | error_remove_callback: |
| 259 | 253 | sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE); |
| 260 | 254 | error_remove_trigger: |
| 261 | − hid_sensor_remove_trigger(&temp_st->common_attributes); | |
| 255 | + hid_sensor_remove_trigger(indio_dev, &temp_st->common_attributes); | |
| 262 | 256 | return ret; |
| 263 | 257 | } |
| 264 | 258 | |
| @@ -270,7 +264,7 @@ static int hid_temperature_remove(struct platform_device *pdev) · 5 unmodified lines | ||
| 270 | 264 | struct temperature_state *temp_st = iio_priv(indio_dev); |
| 271 | 265 | |
| 272 | 266 | sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE); |
| 273 | − hid_sensor_remove_trigger(&temp_st->common_attributes); | |
| 267 | + hid_sensor_remove_trigger(indio_dev, &temp_st->common_attributes); | |
| 274 | 268 | |
| 275 | 269 | return 0; |
| 276 | 270 | } |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/iio/iio.h> |
| 15 | 15 | #include <linux/iio/sysfs.h> |
| 16 | 16 | #include <linux/util_macros.h> |
| 17 | +#include <asm/unaligned.h> | |
| 17 | 18 | #include <dt-bindings/iio/temperature/thermocouple.h> |
| 18 | 19 | /* |
| 19 | 20 | * The MSB of the register value determines whether the following byte will |
| @@ -168,7 +169,7 @@ static int max31856_thermocouple_read(struct max31856_data *data, · 148 unmodified lines | ||
| 168 | 169 | if (ret) |
| 169 | 170 | return ret; |
| 170 | 171 | /* Skip last 5 dead bits of LTCBL */ |
| 171 | − *val = (reg_val[0] << 16 | reg_val[1] << 8 | reg_val[2]) >> 5; | |
| 172 | + *val = get_unaligned_be24(®_val[0]) >> 5; | |
| 172 | 173 | /* Check 7th bit of LTCBH reg. value for sign*/ |
| 173 | 174 | if (reg_val[0] & 0x80) |
| 174 | 175 | *val -= 0x80000; |
| @@ -185,7 +186,7 @@ static int max31856_thermocouple_read(struct max31856_data *data, · 10 unmodified lines | ||
| 185 | 186 | /* Get Cold Junction Temp. offset register value */ |
| 186 | 187 | offset_cjto = reg_val[0]; |
| 187 | 188 | /* Get CJTH and CJTL value and skip last 2 dead bits of CJTL */ |
| 188 | − *val = (reg_val[1] << 8 | reg_val[2]) >> 2; | |
| 189 | + *val = get_unaligned_be16(®_val[1]) >> 2; | |
| 189 | 190 | /* As per datasheet add offset into CJTH and CJTL */ |
| 190 | 191 | *val += offset_cjto; |
| 191 | 192 | /* Check 7th bit of CJTH reg. value for sign */ |
| @@ -602,11 +602,12 @@ static const struct iio_buffer_setup_ops ad5933_ring_setup_ops = { · 601 unmodified lines | ||
| 602 | 602 | .postdisable = ad5933_ring_postdisable, |
| 603 | 603 | }; |
| 604 | 604 | |
| 605 | −static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) | |
| 605 | +static int ad5933_register_ring_funcs_and_init(struct device *dev, | |
| 606 | + struct iio_dev *indio_dev) | |
| 606 | 607 | { |
| 607 | 608 | struct iio_buffer *buffer; |
| 608 | 609 | |
| 609 | − buffer = iio_kfifo_allocate(); | |
| 610 | + buffer = devm_iio_kfifo_allocate(dev); | |
| 610 | 611 | if (!buffer) |
| 611 | 612 | return -ENOMEM; |
| 612 | 613 | |
| @@ -676,6 +677,20 @@ static void ad5933_work(struct work_struct *work) · 63 unmodified lines | ||
| 676 | 677 | } |
| 677 | 678 | } |
| 678 | 679 | |
| 680 | +static void ad5933_reg_disable(void *data) | |
| 681 | +{ | |
| 682 | + struct ad5933_state *st = data; | |
| 683 | + | |
| 684 | + regulator_disable(st->reg); | |
| 685 | +} | |
| 686 | + | |
| 687 | +static void ad5933_clk_disable(void *data) | |
| 688 | +{ | |
| 689 | + struct ad5933_state *st = data; | |
| 690 | + | |
| 691 | + clk_disable_unprepare(st->mclk); | |
| 692 | +} | |
| 693 | + | |
| 679 | 694 | static int ad5933_probe(struct i2c_client *client, |
| 680 | 695 | const struct i2c_device_id *id) |
| 681 | 696 | { |
| @@ -703,23 +718,32 @@ static int ad5933_probe(struct i2c_client *client, · 21 unmodified lines | ||
| 703 | 718 | dev_err(&client->dev, "Failed to enable specified VDD supply\n"); |
| 704 | 719 | return ret; |
| 705 | 720 | } |
| 706 | − ret = regulator_get_voltage(st->reg); | |
| 707 | 721 | |
| 722 | + ret = devm_add_action_or_reset(&client->dev, ad5933_reg_disable, st); | |
| 723 | + if (ret) | |
| 724 | + return ret; | |
| 725 | + | |
| 726 | + ret = regulator_get_voltage(st->reg); | |
| 708 | 727 | if (ret < 0) |
| 709 | − goto error_disable_reg; | |
| 728 | + return ret; | |
| 710 | 729 | |
| 711 | 730 | st->vref_mv = ret / 1000; |
| 712 | 731 | |
| 713 | 732 | st->mclk = devm_clk_get(&client->dev, "mclk"); |
| 714 | − if (IS_ERR(st->mclk) && PTR_ERR(st->mclk) != -ENOENT) { | |
| 715 | − ret = PTR_ERR(st->mclk); | |
| 716 | − goto error_disable_reg; | |
| 717 | − } | |
| 733 | + if (IS_ERR(st->mclk) && PTR_ERR(st->mclk) != -ENOENT) | |
| 734 | + return PTR_ERR(st->mclk); | |
| 718 | 735 | |
| 719 | 736 | if (!IS_ERR(st->mclk)) { |
| 720 | 737 | ret = clk_prepare_enable(st->mclk); |
| 721 | 738 | if (ret < 0) |
| 722 | − goto error_disable_reg; | |
| 739 | + return ret; | |
| 740 | + | |
| 741 | + ret = devm_add_action_or_reset(&client->dev, | |
| 742 | + ad5933_clk_disable, | |
| 743 | + st); | |
| 744 | + if (ret) | |
| 745 | + return ret; | |
| 746 | + | |
| 723 | 747 | ext_clk_hz = clk_get_rate(st->mclk); |
| 724 | 748 | } |
| 725 | 749 | |
| @@ -742,41 +766,15 @@ static int ad5933_probe(struct i2c_client *client, · 16 unmodified lines | ||
| 742 | 766 | indio_dev->channels = ad5933_channels; |
| 743 | 767 | indio_dev->num_channels = ARRAY_SIZE(ad5933_channels); |
| 744 | 768 | |
| 745 | − ret = ad5933_register_ring_funcs_and_init(indio_dev); | |
| 769 | + ret = ad5933_register_ring_funcs_and_init(&client->dev, indio_dev); | |
| 746 | 770 | if (ret) |
| 747 | − goto error_disable_mclk; | |
| 771 | + return ret; | |
| 748 | 772 | |
| 749 | 773 | ret = ad5933_setup(st); |
| 750 | 774 | if (ret) |
| 751 | − goto error_unreg_ring; | |
| 752 | − | |
| 753 | − ret = iio_device_register(indio_dev); | |
| 754 | − if (ret) | |
| 755 | − goto error_unreg_ring; | |
| 756 | − | |
| 757 | − return 0; | |
| 758 | − | |
| 759 | −error_unreg_ring: | |
| 760 | − iio_kfifo_free(indio_dev->buffer); | |
| 761 | −error_disable_mclk: | |
| 762 | − clk_disable_unprepare(st->mclk); | |
| 763 | −error_disable_reg: | |
| 764 | − regulator_disable(st->reg); | |
| 765 | − | |
| 766 | − return ret; | |
| 767 | −} | |
| 768 | − | |
| 769 | −static int ad5933_remove(struct i2c_client *client) | |
| 770 | −{ | |
| 771 | − struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 772 | − struct ad5933_state *st = iio_priv(indio_dev); | |
| 773 | − | |
| 774 | − iio_device_unregister(indio_dev); | |
| 775 | − iio_kfifo_free(indio_dev->buffer); | |
| 776 | − regulator_disable(st->reg); | |
| 777 | − clk_disable_unprepare(st->mclk); | |
| 775 | + return ret; | |
| 778 | 776 | |
| 779 | − return 0; | |
| 777 | + return devm_iio_device_register(&client->dev, indio_dev); | |
| 780 | 778 | } |
| 781 | 779 | |
| 782 | 780 | static const struct i2c_device_id ad5933_id[] = { |
| @@ -801,7 +799,6 @@ static struct i2c_driver ad5933_driver = { · 18 unmodified lines | ||
| 801 | 799 | .of_match_table = ad5933_of_match, |
| 802 | 800 | }, |
| 803 | 801 | .probe = ad5933_probe, |
| 804 | − .remove = ad5933_remove, | |
| 805 | 802 | .id_table = ad5933_id, |
| 806 | 803 | }; |
| 807 | 804 | module_i2c_driver(ad5933_driver); |
| @@ -83,10 +83,13 @@ struct adis_data { · 82 unmodified lines | ||
| 83 | 83 | * @trig: IIO trigger object data |
| 84 | 84 | * @data: ADIS chip variant specific data |
| 85 | 85 | * @burst: ADIS burst transfer information |
| 86 | + * @burst_extra_len: Burst extra length. Should only be used by devices that can | |
| 87 | + * dynamically change their burst mode length. | |
| 86 | 88 | * @state_lock: Lock used by the device to protect state |
| 87 | 89 | * @msg: SPI message object |
| 88 | 90 | * @xfer: SPI transfer objects to be used for a @msg |
| 89 | 91 | * @current_page: Some ADIS devices have registers, this selects current page |
| 92 | + * @irq_flag: IRQ handling flags as passed to request_irq() | |
| 90 | 93 | * @buffer: Data buffer for information read from the device |
| 91 | 94 | * @tx: DMA safe TX buffer for SPI transfers |
| 92 | 95 | * @rx: DMA safe RX buffer for SPI transfers |
| @@ -97,7 +100,7 @@ struct adis { · 4 unmodified lines | ||
| 97 | 100 | |
| 98 | 101 | const struct adis_data *data; |
| 99 | 102 | struct adis_burst *burst; |
| 100 | − | |
| 103 | + unsigned int burst_extra_len; | |
| 101 | 104 | /** |
| 102 | 105 | * The state_lock is meant to be used during operations that require |
| 103 | 106 | * a sequence of SPI R/W in order to protect the SPI transfer |
| @@ -113,6 +116,7 @@ struct adis { · 9 unmodified lines | ||
| 113 | 116 | struct spi_message msg; |
| 114 | 117 | struct spi_transfer *xfer; |
| 115 | 118 | unsigned int current_page; |
| 119 | + unsigned long irq_flag; | |
| 116 | 120 | void *buffer; |
| 117 | 121 | |
| 118 | 122 | uint8_t tx[10] ____cacheline_aligned; |
| @@ -331,6 +335,65 @@ static inline int adis_read_reg_32(struct adis *adis, unsigned int reg, · 212 unmodified lines | ||
| 331 | 335 | return ret; |
| 332 | 336 | } |
| 333 | 337 | |
| 338 | +int __adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask, | |
| 339 | + const u32 val, u8 size); | |
| 340 | +/** | |
| 341 | + * adis_update_bits_base() - ADIS Update bits function - Locked version | |
| 342 | + * @adis: The adis device | |
| 343 | + * @reg: The address of the lower of the two registers | |
| 344 | + * @mask: Bitmask to change | |
| 345 | + * @val: Value to be written | |
| 346 | + * @size: Size of the register to update | |
| 347 | + * | |
| 348 | + * Updates the desired bits of @reg in accordance with @mask and @val. | |
| 349 | + */ | |
| 350 | +static inline int adis_update_bits_base(struct adis *adis, unsigned int reg, | |
| 351 | + const u32 mask, const u32 val, u8 size) | |
| 352 | +{ | |
| 353 | + int ret; | |
| 354 | + | |
| 355 | + mutex_lock(&adis->state_lock); | |
| 356 | + ret = __adis_update_bits_base(adis, reg, mask, val, size); | |
| 357 | + mutex_unlock(&adis->state_lock); | |
| 358 | + return ret; | |
| 359 | +} | |
| 360 | + | |
| 361 | +/** | |
| 362 | + * adis_update_bits() - Wrapper macro for adis_update_bits_base - Locked version | |
| 363 | + * @adis: The adis device | |
| 364 | + * @reg: The address of the lower of the two registers | |
| 365 | + * @mask: Bitmask to change | |
| 366 | + * @val: Value to be written | |
| 367 | + * | |
| 368 | + * This macro evaluates the sizeof of @val at compile time and calls | |
| 369 | + * adis_update_bits_base() accordingly. Be aware that using MACROS/DEFINES for | |
| 370 | + * @val can lead to undesired behavior if the register to update is 16bit. | |
| 371 | + */ | |
| 372 | +#define adis_update_bits(adis, reg, mask, val) ({ \ | |
| 373 | + BUILD_BUG_ON(sizeof(val) == 1 || sizeof(val) == 8); \ | |
| 374 | + __builtin_choose_expr(sizeof(val) == 4, \ | |
| 375 | + adis_update_bits_base(adis, reg, mask, val, 4), \ | |
| 376 | + adis_update_bits_base(adis, reg, mask, val, 2)); \ | |
| 377 | +}) | |
| 378 | + | |
| 379 | +/** | |
| 380 | + * adis_update_bits() - Wrapper macro for adis_update_bits_base | |
| 381 | + * @adis: The adis device | |
| 382 | + * @reg: The address of the lower of the two registers | |
| 383 | + * @mask: Bitmask to change | |
| 384 | + * @val: Value to be written | |
| 385 | + * | |
| 386 | + * This macro evaluates the sizeof of @val at compile time and calls | |
| 387 | + * adis_update_bits_base() accordingly. Be aware that using MACROS/DEFINES for | |
| 388 | + * @val can lead to undesired behavior if the register to update is 16bit. | |
| 389 | + */ | |
| 390 | +#define __adis_update_bits(adis, reg, mask, val) ({ \ | |
| 391 | + BUILD_BUG_ON(sizeof(val) == 1 || sizeof(val) == 8); \ | |
| 392 | + __builtin_choose_expr(sizeof(val) == 4, \ | |
| 393 | + __adis_update_bits_base(adis, reg, mask, val, 4), \ | |
| 394 | + __adis_update_bits_base(adis, reg, mask, val, 2)); \ | |
| 395 | +}) | |
| 396 | + | |
| 334 | 397 | int adis_enable_irq(struct adis *adis, bool enable); |
| 335 | 398 | int __adis_check_status(struct adis *adis); |
| 336 | 399 | int __adis_initial_startup(struct adis *adis); |
| @@ -441,18 +504,25 @@ int adis_single_conversion(struct iio_dev *indio_dev, · 104 unmodified lines | ||
| 441 | 504 | * @en burst mode enabled |
| 442 | 505 | * @reg_cmd register command that triggers burst |
| 443 | 506 | * @extra_len extra length to account in the SPI RX buffer |
| 507 | + * @burst_max_len holds the maximum burst size when the device supports | |
| 508 | + * more than one burst mode with different sizes | |
| 444 | 509 | */ |
| 445 | 510 | struct adis_burst { |
| 446 | 511 | bool en; |
| 447 | 512 | unsigned int reg_cmd; |
| 448 | − unsigned int extra_len; | |
| 513 | + const u32 extra_len; | |
| 514 | + const u32 burst_max_len; | |
| 449 | 515 | }; |
| 450 | 516 | |
| 517 | +int | |
| 518 | +devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, | |
| 519 | + irq_handler_t trigger_handler); | |
| 451 | 520 | int adis_setup_buffer_and_trigger(struct adis *adis, |
| 452 | 521 | struct iio_dev *indio_dev, irqreturn_t (*trigger_handler)(int, void *)); |
| 453 | 522 | void adis_cleanup_buffer_and_trigger(struct adis *adis, |
| 454 | 523 | struct iio_dev *indio_dev); |
| 455 | 524 | |
| 525 | +int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev); | |
| 456 | 526 | int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev); |
| 457 | 527 | void adis_remove_trigger(struct adis *adis); |
| 458 | 528 | |
| @@ -461,6 +531,13 @@ int adis_update_scan_mode(struct iio_dev *indio_dev, · 2 unmodified lines | ||
| 461 | 531 | |
| 462 | 532 | #else /* CONFIG_IIO_BUFFER */ |
| 463 | 533 | |
| 534 | +static inline int | |
| 535 | +devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, | |
| 536 | + irq_handler_t trigger_handler) | |
| 537 | +{ | |
| 538 | + return 0; | |
| 539 | +} | |
| 540 | + | |
| 464 | 541 | static inline int adis_setup_buffer_and_trigger(struct adis *adis, |
| 465 | 542 | struct iio_dev *indio_dev, irqreturn_t (*trigger_handler)(int, void *)) |
| 466 | 543 | { |
| @@ -472,6 +549,12 @@ static inline void adis_cleanup_buffer_and_trigger(struct adis *adis, · 5 unmodified lines | ||
| 472 | 549 | { |
| 473 | 550 | } |
| 474 | 551 | |
| 552 | +static inline int devm_adis_probe_trigger(struct adis *adis, | |
| 553 | + struct iio_dev *indio_dev) | |
| 554 | +{ | |
| 555 | + return 0; | |
| 556 | +} | |
| 557 | + | |
| 475 | 558 | static inline int adis_probe_trigger(struct adis *adis, |
| 476 | 559 | struct iio_dev *indio_dev) |
| 477 | 560 | { |