提交 bf1d6b2c 编写于 作者: L Linus Torvalds

Merge tag 'staging-4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging

Pull staging/IIO driver updates from Greg KH:
 "Here is the big staging and IIO driver update for 4.14-rc1.

  Lots of staging driver fixes and cleanups, including some reorginizing
  of the lustre header files to try to impose some sanity on what is,
  and what is not, the uapi for that filesystem.

  There are some tty core changes in here as well, as the speakup
  drivers need them, and that's ok with me, they are sane and the
  speakup code is getting nicer because of it.

  There is also the addition of the obiligatory new wifi driver, just
  because it has been a release or two since we added our last one...

  Other than that, lots and lots of small coding style fixes, as usual.

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'staging-4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (612 commits)
  staging:rtl8188eu:core Fix remove unneccessary else block
  staging: typec: fusb302: make structure fusb302_psy_desc static
  staging: unisys: visorbus: make two functions static
  staging: fsl-dpaa2/eth: fix off-by-one FD ctrl bitmaks
  staging: r8822be: Simplify deinit_priv()
  staging: r8822be: Remove some dead code
  staging: vboxvideo: Use CONFIG_DRM_KMS_FB_HELPER to check for fbdefio availability
  staging:rtl8188eu Fix comparison to NULL
  staging: rts5208: rename mmc_ddr_tunning_rx_cmd to mmc_ddr_tuning_rx_cmd
  Staging: Pi433: style fix - tabs and spaces
  staging: pi433: fix spelling mistake: "preample" -> "preamble"
  staging:rtl8188eu:core Fix Code Indent
  staging: typec: fusb302: Export current-limit through a power_supply class dev
  staging: typec: fusb302: Add support for USB2 charger detection through extcon
  staging: typec: fusb302: Use client->irq as irq if set
  staging: typec: fusb302: Get max snk mv/ma/mw from device-properties
  staging: typec: fusb302: Set max supply voltage to 5V
  staging: typec: tcpm: Add get_current_limit tcpc_dev callback
  staging:rtl8188eu Use __func__ instead of function name
  staging: lustre: coding style fixes found by checkpatch.pl
  ...
...@@ -119,6 +119,15 @@ Description: ...@@ -119,6 +119,15 @@ Description:
unique to allow association with event codes. Units after unique to allow association with event codes. Units after
application of scale and offset are milliamps. application of scale and offset are milliamps.
What: /sys/bus/iio/devices/iio:deviceX/in_powerY_raw
KernelVersion: 4.5
Contact: linux-iio@vger.kernel.org
Description:
Raw (unscaled no bias removal etc.) power measurement from
channel Y. The number must always be specified and
unique to allow association with event codes. Units after
application of scale and offset are milliwatts.
What: /sys/bus/iio/devices/iio:deviceX/in_capacitanceY_raw What: /sys/bus/iio/devices/iio:deviceX/in_capacitanceY_raw
KernelVersion: 3.2 KernelVersion: 3.2
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
......
...@@ -11,6 +11,11 @@ Required properties: ...@@ -11,6 +11,11 @@ Required properties:
- atmel,min-sample-rate-hz: Minimum sampling rate, it depends on SoC. - atmel,min-sample-rate-hz: Minimum sampling rate, it depends on SoC.
- atmel,max-sample-rate-hz: Maximum sampling rate, it depends on SoC. - atmel,max-sample-rate-hz: Maximum sampling rate, it depends on SoC.
- atmel,startup-time-ms: Startup time expressed in ms, it depends on SoC. - atmel,startup-time-ms: Startup time expressed in ms, it depends on SoC.
- atmel,trigger-edge-type: One of possible edge types for the ADTRG hardware
trigger pin. When the specific edge type is detected, the conversion will
start. Possible values are rising, falling, or both.
This property uses the IRQ edge types values: IRQ_TYPE_EDGE_RISING ,
IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_BOTH
Example: Example:
...@@ -25,4 +30,5 @@ adc: adc@fc030000 { ...@@ -25,4 +30,5 @@ adc: adc@fc030000 {
atmel,startup-time-ms = <4>; atmel,startup-time-ms = <4>;
vddana-supply = <&vdd_3v3_lp_reg>; vddana-supply = <&vdd_3v3_lp_reg>;
vref-supply = <&vdd_3v3_lp_reg>; vref-supply = <&vdd_3v3_lp_reg>;
atmel,trigger-edge-type = <IRQ_TYPE_EDGE_BOTH>;
} }
...@@ -12,6 +12,7 @@ for the Thermal Controller which holds a phandle to the AUXADC. ...@@ -12,6 +12,7 @@ for the Thermal Controller which holds a phandle to the AUXADC.
Required properties: Required properties:
- compatible: Should be one of: - compatible: Should be one of:
- "mediatek,mt2701-auxadc": For MT2701 family of SoCs - "mediatek,mt2701-auxadc": For MT2701 family of SoCs
- "mediatek,mt7622-auxadc": For MT7622 family of SoCs
- "mediatek,mt8173-auxadc": For MT8173 family of SoCs - "mediatek,mt8173-auxadc": For MT8173 family of SoCs
- reg: Address range of the AUXADC unit. - reg: Address range of the AUXADC unit.
- clocks: Should contain a clock specifier for each entry in clock-names - clocks: Should contain a clock specifier for each entry in clock-names
......
...@@ -6,6 +6,7 @@ Required properties: ...@@ -6,6 +6,7 @@ Required properties:
- "rockchip,rk3066-tsadc": for rk3036 - "rockchip,rk3066-tsadc": for rk3036
- "rockchip,rk3328-saradc", "rockchip,rk3399-saradc": for rk3328 - "rockchip,rk3328-saradc", "rockchip,rk3399-saradc": for rk3328
- "rockchip,rk3399-saradc": for rk3399 - "rockchip,rk3399-saradc": for rk3399
- "rockchip,rv1108-saradc", "rockchip,rk3399-saradc": for rv1108
- reg: physical base address of the controller and length of memory mapped - reg: physical base address of the controller and length of memory mapped
region. region.
......
...@@ -74,6 +74,11 @@ Optional properties: ...@@ -74,6 +74,11 @@ Optional properties:
* can be 6, 8, 10 or 12 on stm32f4 * can be 6, 8, 10 or 12 on stm32f4
* can be 8, 10, 12, 14 or 16 on stm32h7 * can be 8, 10, 12, 14 or 16 on stm32h7
Default is maximum resolution if unset. Default is maximum resolution if unset.
- st,min-sample-time-nsecs: Minimum sampling time in nanoseconds.
Depending on hardware (board) e.g. high/low analog input source impedance,
fine tune of ADC sampling time may be recommended.
This can be either one value or an array that matches 'st,adc-channels' list,
to set sample time resp. for all channels, or independently for each channel.
Example: Example:
adc: adc@40012000 { adc: adc@40012000 {
......
...@@ -10,7 +10,9 @@ current. ...@@ -10,7 +10,9 @@ current.
Contents of a stm32 dac root node: Contents of a stm32 dac root node:
----------------------------------- -----------------------------------
Required properties: Required properties:
- compatible: Must be "st,stm32h7-dac-core". - compatible: Should be one of:
"st,stm32f4-dac-core"
"st,stm32h7-dac-core"
- reg: Offset and length of the device's register set. - reg: Offset and length of the device's register set.
- clocks: Must contain an entry for pclk (which feeds the peripheral bus - clocks: Must contain an entry for pclk (which feeds the peripheral bus
interface) interface)
......
* HDC100x temperature + humidity sensors
Required properties:
- compatible: Should contain one of the following:
ti,hdc1000
ti,hdc1008
ti,hdc1010
ti,hdc1050
ti,hdc1080
- reg: i2c address of the sensor
Example:
hdc100x@40 {
compatible = "ti,hdc1000";
reg = <0x40>;
};
...@@ -5,9 +5,18 @@ Required properties: ...@@ -5,9 +5,18 @@ Required properties:
- reg: i2c address of the sensor / spi cs line - reg: i2c address of the sensor / spi cs line
Optional properties: Optional properties:
- drive-open-drain: the interrupt/data ready line will be configured
as open drain, which is useful if several sensors share the same
interrupt line. This is a boolean property.
If the requested interrupt is configured as IRQ_TYPE_LEVEL_HIGH or
IRQ_TYPE_EDGE_RISING a pull-down resistor is needed to drive the line
when it is not active, whereas a pull-up one is needed when interrupt
line is configured as IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_EDGE_FALLING.
Refer to pinctrl/pinctrl-bindings.txt for the property description.
- interrupt-parent: should be the phandle for the interrupt controller - interrupt-parent: should be the phandle for the interrupt controller
- interrupts: interrupt mapping for IRQ. It should be configured with - interrupts: interrupt mapping for IRQ. It should be configured with
flags IRQ_TYPE_LEVEL_HIGH or IRQ_TYPE_EDGE_RISING. flags IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_EDGE_RISING, IRQ_TYPE_LEVEL_LOW or
IRQ_TYPE_EDGE_FALLING.
Refer to interrupt-controller/interrupts.txt for generic interrupt Refer to interrupt-controller/interrupts.txt for generic interrupt
client node bindings. client node bindings.
......
*HTU21 - Measurement-Specialties htu21 temperature & humidity sensor and humidity part of MS8607 sensor
Required properties:
- compatible: should be "meas,htu21" or "meas,ms8607-humidity"
- reg: I2C address of the sensor
Example:
htu21@40 {
compatible = "meas,htu21";
reg = <0x40>;
};
...@@ -11,6 +11,14 @@ Required properties: ...@@ -11,6 +11,14 @@ Required properties:
Optional properties: Optional properties:
- st,drdy-int-pin: the pin on the package that will be used to signal - st,drdy-int-pin: the pin on the package that will be used to signal
"data ready" (valid values: 1 or 2). "data ready" (valid values: 1 or 2).
- drive-open-drain: the interrupt/data ready line will be configured
as open drain, which is useful if several sensors share the same
interrupt line. This is a boolean property.
(This binding is taken from pinctrl/pinctrl-bindings.txt)
If the requested interrupt is configured as IRQ_TYPE_LEVEL_HIGH or
IRQ_TYPE_EDGE_RISING a pull-down resistor is needed to drive the line
when it is not active, whereas a pull-up one is needed when interrupt
line is configured as IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_EDGE_FALLING.
- interrupt-parent: should be the phandle for the interrupt controller - interrupt-parent: should be the phandle for the interrupt controller
- interrupts: interrupt mapping for IRQ. It should be configured with - interrupts: interrupt mapping for IRQ. It should be configured with
flags IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_EDGE_RISING, IRQ_TYPE_LEVEL_LOW or flags IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_EDGE_RISING, IRQ_TYPE_LEVEL_LOW or
......
* MS5637 - Measurement-Specialties MS5637, MS5805, MS5837 and MS8607 pressure & temperature sensor
Required properties:
-compatible: should be one of the following
meas,ms5637
meas,ms5805
meas,ms5837
meas,ms8607-temppressure
-reg: I2C address of the sensor
Example:
ms5637@76 {
compatible = "meas,ms5637";
reg = <0x76>;
};
...@@ -45,6 +45,7 @@ Accelerometers: ...@@ -45,6 +45,7 @@ Accelerometers:
- st,lis2dh12-accel - st,lis2dh12-accel
- st,h3lis331dl-accel - st,h3lis331dl-accel
- st,lng2dm-accel - st,lng2dm-accel
- st,lis3l02dq
Gyroscopes: Gyroscopes:
- st,l3g4200d-gyro - st,l3g4200d-gyro
...@@ -52,6 +53,7 @@ Gyroscopes: ...@@ -52,6 +53,7 @@ Gyroscopes:
- st,lsm330dl-gyro - st,lsm330dl-gyro
- st,lsm330dlc-gyro - st,lsm330dlc-gyro
- st,l3gd20-gyro - st,l3gd20-gyro
- st,l3gd20h-gyro
- st,l3g4is-gyro - st,l3g4is-gyro
- st,lsm330-gyro - st,lsm330-gyro
- st,lsm9ds0-gyro - st,lsm9ds0-gyro
...@@ -62,6 +64,7 @@ Magnetometers: ...@@ -62,6 +64,7 @@ Magnetometers:
- st,lsm303dlhc-magn - st,lsm303dlhc-magn
- st,lsm303dlm-magn - st,lsm303dlm-magn
- st,lis3mdl-magn - st,lis3mdl-magn
- st,lis2mdl
Pressure sensors: Pressure sensors:
- st,lps001wp-press - st,lps001wp-press
......
* TSYS01 - Measurement Specialties temperature sensor
Required properties:
- compatible: should be "meas,tsys01"
- reg: I2C address of the sensor (changeable via CSB pin)
------------------------
| CSB | Device Address |
------------------------
1 0x76
0 0x77
Example:
tsys01@76 {
compatible = "meas,tsys01";
reg = <0x76>;
};
...@@ -4,7 +4,9 @@ Must be a sub-node of an STM32 Timers device tree node. ...@@ -4,7 +4,9 @@ Must be a sub-node of an STM32 Timers device tree node.
See ../mfd/stm32-timers.txt for details about the parent node. See ../mfd/stm32-timers.txt for details about the parent node.
Required parameters: Required parameters:
- compatible: Must be "st,stm32-timer-trigger". - compatible: Must be one of:
"st,stm32-timer-trigger"
"st,stm32h7-timer-trigger"
- reg: Identify trigger hardware block. - reg: Identify trigger hardware block.
Example: Example:
...@@ -14,7 +16,7 @@ Example: ...@@ -14,7 +16,7 @@ Example:
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x40010000 0x400>; reg = <0x40010000 0x400>;
clocks = <&rcc 0 160>; clocks = <&rcc 0 160>;
clock-names = "clk_int"; clock-names = "int";
timer@0 { timer@0 {
compatible = "st,stm32-timer-trigger"; compatible = "st,stm32-timer-trigger";
......
Fairchild FUSB302 Type-C Port controllers
Required properties :
- compatible : "fcs,fusb302"
- reg : I2C slave address
- interrupts : Interrupt specifier
Optional properties :
- fcs,max-sink-microvolt : Maximum voltage to negotiate when configured as sink
- fcs,max-sink-microamp : Maximum current to negotiate when configured as sink
- fcs,max-sink-microwatt : Maximum power to negotiate when configured as sink
If this is less then max-sink-microvolt *
max-sink-microamp then the configured current will
be clamped.
- fcs,operating-sink-microwatt :
Minimum amount of power accepted from a sink
when negotiating
Example:
fusb302: typec-portc@54 {
compatible = "fcs,fusb302";
reg = <0x54>;
interrupt-parent = <&nmi_intc>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
fcs,max-sink-microvolt = <12000000>;
fcs,max-sink-microamp = <3000000>;
fcs,max-sink-microwatt = <36000000>;
};
Cirrus Logic EP93xx ADC driver.
1. Overview
The driver is intended to work on both low-end (EP9301, EP9302) devices with
5-channel ADC and high-end (EP9307, EP9312, EP9315) devices with 10-channel
touchscreen/ADC module.
2. Channel numbering
Numbering scheme for channels 0..4 is defined in EP9301 and EP9302 datasheets.
EP9307, EP9312 and EP9312 have 3 channels more (total 8), but the numbering is
not defined. So the last three are numbered randomly, let's say.
Assuming ep93xx_adc is IIO device0, you'd find the following entries under
/sys/bus/iio/devices/iio:device0/:
+-----------------+---------------+
| sysfs entry | ball/pin name |
+-----------------+---------------+
| in_voltage0_raw | YM |
| in_voltage1_raw | SXP |
| in_voltage2_raw | SXM |
| in_voltage3_raw | SYP |
| in_voltage4_raw | SYM |
| in_voltage5_raw | XP |
| in_voltage6_raw | XM |
| in_voltage7_raw | YP |
+-----------------+---------------+
...@@ -842,7 +842,7 @@ static SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume); ...@@ -842,7 +842,7 @@ static SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume);
#define BMA180_PM_OPS NULL #define BMA180_PM_OPS NULL
#endif #endif
static struct i2c_device_id bma180_ids[] = { static const struct i2c_device_id bma180_ids[] = {
{ "bma180", BMA180 }, { "bma180", BMA180 },
{ "bma250", BMA250 }, { "bma250", BMA250 },
{ } { }
......
...@@ -64,6 +64,7 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = { ...@@ -64,6 +64,7 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = {
{"BMA250E", bma250e}, {"BMA250E", bma250e},
{"BMA222E", bma222e}, {"BMA222E", bma222e},
{"BMA0280", bma280}, {"BMA0280", bma280},
{"BOSC0200"},
{ }, { },
}; };
MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match); MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
......
...@@ -139,7 +139,7 @@ static int da311_register_mask_write(struct i2c_client *client, u16 addr, ...@@ -139,7 +139,7 @@ static int da311_register_mask_write(struct i2c_client *client, u16 addr,
/* Init sequence taken from the android driver */ /* Init sequence taken from the android driver */
static int da311_reset(struct i2c_client *client) static int da311_reset(struct i2c_client *client)
{ {
const struct { static const struct {
u16 addr; u16 addr;
u8 mask; u8 mask;
u8 data; u8 data;
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#define SCA3000_LOCKED BIT(5) #define SCA3000_LOCKED BIT(5)
#define SCA3000_EEPROM_CS_ERROR BIT(1) #define SCA3000_EEPROM_CS_ERROR BIT(1)
#define SCA3000_SPI_FRAME_ERROR BIT(0) #define SCA3000_SPI_FRAME_ERROR BIT(0)
/* All reads done using register decrement so no need to directly access LSBs */ /* All reads done using register decrement so no need to directly access LSBs */
#define SCA3000_REG_X_MSB_ADDR 0x05 #define SCA3000_REG_X_MSB_ADDR 0x05
#define SCA3000_REG_Y_MSB_ADDR 0x07 #define SCA3000_REG_Y_MSB_ADDR 0x07
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
#define SCA3000_REG_INT_STATUS_ADDR 0x16 #define SCA3000_REG_INT_STATUS_ADDR 0x16
#define SCA3000_REG_INT_STATUS_THREE_QUARTERS BIT(7) #define SCA3000_REG_INT_STATUS_THREE_QUARTERS BIT(7)
#define SCA3000_REG_INT_STATUS_HALF BIT(6) #define SCA3000_REG_INT_STATUS_HALF BIT(6)
#define SCA3000_INT_STATUS_FREE_FALL BIT(3) #define SCA3000_INT_STATUS_FREE_FALL BIT(3)
#define SCA3000_INT_STATUS_Y_TRIGGER BIT(2) #define SCA3000_INT_STATUS_Y_TRIGGER BIT(2)
#define SCA3000_INT_STATUS_X_TRIGGER BIT(1) #define SCA3000_INT_STATUS_X_TRIGGER BIT(1)
...@@ -124,7 +124,7 @@ ...@@ -124,7 +124,7 @@
#define SCA3000_REG_INT_MASK_ADDR 0x21 #define SCA3000_REG_INT_MASK_ADDR 0x21
#define SCA3000_REG_INT_MASK_PROT_MASK 0x1C #define SCA3000_REG_INT_MASK_PROT_MASK 0x1C
#define SCA3000_REG_INT_MASK_RING_THREE_QUARTER BIT(7) #define SCA3000_REG_INT_MASK_RING_THREE_QUARTER BIT(7)
#define SCA3000_REG_INT_MASK_RING_HALF BIT(6) #define SCA3000_REG_INT_MASK_RING_HALF BIT(6)
......
...@@ -29,10 +29,13 @@ enum st_accel_type { ...@@ -29,10 +29,13 @@ enum st_accel_type {
LIS2DH12, LIS2DH12,
LIS3L02DQ, LIS3L02DQ,
LNG2DM, LNG2DM,
H3LIS331DL,
LIS331DL,
LIS3LV02DL,
ST_ACCEL_MAX, ST_ACCEL_MAX,
}; };
#define H3LIS331DL_DRIVER_NAME "h3lis331dl_accel" #define H3LIS331DL_ACCEL_DEV_NAME "h3lis331dl_accel"
#define LIS3LV02DL_ACCEL_DEV_NAME "lis3lv02dl_accel" #define LIS3LV02DL_ACCEL_DEV_NAME "lis3lv02dl_accel"
#define LSM303DLHC_ACCEL_DEV_NAME "lsm303dlhc_accel" #define LSM303DLHC_ACCEL_DEV_NAME "lsm303dlhc_accel"
#define LIS3DH_ACCEL_DEV_NAME "lis3dh" #define LIS3DH_ACCEL_DEV_NAME "lis3dh"
......
...@@ -161,7 +161,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { ...@@ -161,7 +161,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.drdy_irq = { .drdy_irq = {
.addr = 0x22, .addr = 0x22,
.mask_int1 = 0x10, .mask_int1 = 0x10,
.mask_int2 = 0x08, .mask_int2 = 0x00,
.addr_ihl = 0x25, .addr_ihl = 0x25,
.mask_ihl = 0x02, .mask_ihl = 0x02,
.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
...@@ -464,7 +464,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { ...@@ -464,7 +464,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.wai = 0x32, .wai = 0x32,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = { .sensors_supported = {
[0] = H3LIS331DL_DRIVER_NAME, [0] = H3LIS331DL_ACCEL_DEV_NAME,
}, },
.ch = (struct iio_chan_spec *)st_accel_12bit_channels, .ch = (struct iio_chan_spec *)st_accel_12bit_channels,
.odr = { .odr = {
...@@ -637,7 +637,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { ...@@ -637,7 +637,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.drdy_irq = { .drdy_irq = {
.addr = 0x22, .addr = 0x22,
.mask_int1 = 0x10, .mask_int1 = 0x10,
.mask_int2 = 0x08, .mask_int2 = 0x00,
.addr_ihl = 0x25, .addr_ihl = 0x25,
.mask_ihl = 0x02, .mask_ihl = 0x02,
.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
......
...@@ -84,7 +84,7 @@ static const struct of_device_id st_accel_of_match[] = { ...@@ -84,7 +84,7 @@ static const struct of_device_id st_accel_of_match[] = {
}, },
{ {
.compatible = "st,h3lis331dl-accel", .compatible = "st,h3lis331dl-accel",
.data = H3LIS331DL_DRIVER_NAME, .data = H3LIS331DL_ACCEL_DEV_NAME,
}, },
{ {
.compatible = "st,lis3l02dq", .compatible = "st,lis3l02dq",
...@@ -126,6 +126,9 @@ static const struct i2c_device_id st_accel_id_table[] = { ...@@ -126,6 +126,9 @@ static const struct i2c_device_id st_accel_id_table[] = {
{ LIS2DH12_ACCEL_DEV_NAME, LIS2DH12 }, { LIS2DH12_ACCEL_DEV_NAME, LIS2DH12 },
{ LIS3L02DQ_ACCEL_DEV_NAME, LIS3L02DQ }, { LIS3L02DQ_ACCEL_DEV_NAME, LIS3L02DQ },
{ LNG2DM_ACCEL_DEV_NAME, LNG2DM }, { LNG2DM_ACCEL_DEV_NAME, LNG2DM },
{ H3LIS331DL_ACCEL_DEV_NAME, H3LIS331DL },
{ LIS331DL_ACCEL_DEV_NAME, LIS331DL },
{ LIS3LV02DL_ACCEL_DEV_NAME, LIS3LV02DL },
{}, {},
}; };
MODULE_DEVICE_TABLE(i2c, st_accel_id_table); MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
...@@ -144,7 +147,8 @@ static int st_accel_i2c_probe(struct i2c_client *client, ...@@ -144,7 +147,8 @@ static int st_accel_i2c_probe(struct i2c_client *client,
adata = iio_priv(indio_dev); adata = iio_priv(indio_dev);
if (client->dev.of_node) { if (client->dev.of_node) {
st_sensors_of_i2c_probe(client, st_accel_of_match); st_sensors_of_name_probe(&client->dev, st_accel_of_match,
client->name, sizeof(client->name));
} else if (ACPI_HANDLE(&client->dev)) { } else if (ACPI_HANDLE(&client->dev)) {
ret = st_sensors_match_acpi_device(&client->dev); ret = st_sensors_match_acpi_device(&client->dev);
if ((ret < 0) || (ret >= ST_ACCEL_MAX)) if ((ret < 0) || (ret >= ST_ACCEL_MAX))
......
...@@ -18,6 +18,77 @@ ...@@ -18,6 +18,77 @@
#include <linux/iio/common/st_sensors_spi.h> #include <linux/iio/common/st_sensors_spi.h>
#include "st_accel.h" #include "st_accel.h"
#ifdef CONFIG_OF
/*
* For new single-chip sensors use <device_name> as compatible string.
* For old single-chip devices keep <device_name>-accel to maintain
* compatibility
*/
static const struct of_device_id st_accel_of_match[] = {
{
/* An older compatible */
.compatible = "st,lis302dl-spi",
.data = LIS3LV02DL_ACCEL_DEV_NAME,
},
{
.compatible = "st,lis3lv02dl-accel",
.data = LIS3LV02DL_ACCEL_DEV_NAME,
},
{
.compatible = "st,lis3dh-accel",
.data = LIS3DH_ACCEL_DEV_NAME,
},
{
.compatible = "st,lsm330d-accel",
.data = LSM330D_ACCEL_DEV_NAME,
},
{
.compatible = "st,lsm330dl-accel",
.data = LSM330DL_ACCEL_DEV_NAME,
},
{
.compatible = "st,lsm330dlc-accel",
.data = LSM330DLC_ACCEL_DEV_NAME,
},
{
.compatible = "st,lis331dlh-accel",
.data = LIS331DLH_ACCEL_DEV_NAME,
},
{
.compatible = "st,lsm330-accel",
.data = LSM330_ACCEL_DEV_NAME,
},
{
.compatible = "st,lsm303agr-accel",
.data = LSM303AGR_ACCEL_DEV_NAME,
},
{
.compatible = "st,lis2dh12-accel",
.data = LIS2DH12_ACCEL_DEV_NAME,
},
{
.compatible = "st,lis3l02dq",
.data = LIS3L02DQ_ACCEL_DEV_NAME,
},
{
.compatible = "st,lng2dm-accel",
.data = LNG2DM_ACCEL_DEV_NAME,
},
{
.compatible = "st,h3lis331dl-accel",
.data = H3LIS331DL_ACCEL_DEV_NAME,
},
{
.compatible = "st,lis331dl-accel",
.data = LIS331DL_ACCEL_DEV_NAME,
},
{}
};
MODULE_DEVICE_TABLE(of, st_accel_of_match);
#else
#define st_accel_of_match NULL
#endif
static int st_accel_spi_probe(struct spi_device *spi) static int st_accel_spi_probe(struct spi_device *spi)
{ {
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
...@@ -30,6 +101,8 @@ static int st_accel_spi_probe(struct spi_device *spi) ...@@ -30,6 +101,8 @@ static int st_accel_spi_probe(struct spi_device *spi)
adata = iio_priv(indio_dev); adata = iio_priv(indio_dev);
st_sensors_of_name_probe(&spi->dev, st_accel_of_match,
spi->modalias, sizeof(spi->modalias));
st_sensors_spi_configure(indio_dev, spi, adata); st_sensors_spi_configure(indio_dev, spi, adata);
err = st_accel_common_probe(indio_dev); err = st_accel_common_probe(indio_dev);
...@@ -57,22 +130,17 @@ static const struct spi_device_id st_accel_id_table[] = { ...@@ -57,22 +130,17 @@ static const struct spi_device_id st_accel_id_table[] = {
{ LIS2DH12_ACCEL_DEV_NAME }, { LIS2DH12_ACCEL_DEV_NAME },
{ LIS3L02DQ_ACCEL_DEV_NAME }, { LIS3L02DQ_ACCEL_DEV_NAME },
{ LNG2DM_ACCEL_DEV_NAME }, { LNG2DM_ACCEL_DEV_NAME },
{ H3LIS331DL_ACCEL_DEV_NAME },
{ LIS331DL_ACCEL_DEV_NAME },
{ LIS3LV02DL_ACCEL_DEV_NAME },
{}, {},
}; };
MODULE_DEVICE_TABLE(spi, st_accel_id_table); MODULE_DEVICE_TABLE(spi, st_accel_id_table);
#ifdef CONFIG_OF
static const struct of_device_id lis302dl_spi_dt_ids[] = {
{ .compatible = "st,lis302dl-spi" },
{}
};
MODULE_DEVICE_TABLE(of, lis302dl_spi_dt_ids);
#endif
static struct spi_driver st_accel_driver = { static struct spi_driver st_accel_driver = {
.driver = { .driver = {
.name = "st-accel-spi", .name = "st-accel-spi",
.of_match_table = of_match_ptr(lis302dl_spi_dt_ids), .of_match_table = of_match_ptr(st_accel_of_match),
}, },
.probe = st_accel_spi_probe, .probe = st_accel_spi_probe,
.remove = st_accel_spi_remove, .remove = st_accel_spi_remove,
......
...@@ -158,6 +158,7 @@ config AT91_SAMA5D2_ADC ...@@ -158,6 +158,7 @@ config AT91_SAMA5D2_ADC
tristate "Atmel AT91 SAMA5D2 ADC" tristate "Atmel AT91 SAMA5D2 ADC"
depends on ARCH_AT91 || COMPILE_TEST depends on ARCH_AT91 || COMPILE_TEST
depends on HAS_IOMEM depends on HAS_IOMEM
select IIO_TRIGGERED_BUFFER
help help
Say yes here to build support for Atmel SAMA5D2 ADC which is Say yes here to build support for Atmel SAMA5D2 ADC which is
available on SAMA5D2 SoC family. available on SAMA5D2 SoC family.
...@@ -239,6 +240,15 @@ config DA9150_GPADC ...@@ -239,6 +240,15 @@ config DA9150_GPADC
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called berlin2-adc. called berlin2-adc.
config DLN2_ADC
tristate "Diolan DLN-2 ADC driver support"
depends on MFD_DLN2
help
Say yes here to build support for Diolan DLN-2 ADC.
This driver can also be built as a module. If so, the module will be
called adc_dln2.
config ENVELOPE_DETECTOR config ENVELOPE_DETECTOR
tristate "Envelope detector using a DAC and a comparator" tristate "Envelope detector using a DAC and a comparator"
depends on OF depends on OF
...@@ -249,6 +259,17 @@ config ENVELOPE_DETECTOR ...@@ -249,6 +259,17 @@ config ENVELOPE_DETECTOR
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called envelope-detector. called envelope-detector.
config EP93XX_ADC
tristate "Cirrus Logic EP93XX ADC driver"
depends on ARCH_EP93XX
help
Driver for the ADC module on the EP93XX series of SoC from Cirrus Logic.
It's recommended to switch on CONFIG_HIGH_RES_TIMERS option, in this
case driver will reduce its CPU usage by 90% in some use cases.
To compile this driver as a module, choose M here: the module will be
called ep93xx_adc.
config EXYNOS_ADC config EXYNOS_ADC
tristate "Exynos ADC driver support" tristate "Exynos ADC driver support"
depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST) depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST)
...@@ -322,7 +343,7 @@ config INA2XX_ADC ...@@ -322,7 +343,7 @@ config INA2XX_ADC
This driver is mutually exclusive with the HWMON version. This driver is mutually exclusive with the HWMON version.
config IMX7D_ADC config IMX7D_ADC
tristate "IMX7D ADC driver" tristate "Freescale IMX7D ADC driver"
depends on ARCH_MXC || COMPILE_TEST depends on ARCH_MXC || COMPILE_TEST
depends on HAS_IOMEM depends on HAS_IOMEM
help help
...@@ -362,6 +383,16 @@ config LPC32XX_ADC ...@@ -362,6 +383,16 @@ config LPC32XX_ADC
activate only one via device tree selection. Provides direct access activate only one via device tree selection. Provides direct access
via sysfs. via sysfs.
config LTC2471
tristate "Linear Technology LTC2471 and LTC2473 ADC driver"
depends on I2C
help
Say yes here to build support for Linear Technology LTC2471 and
LTC2473 16-bit I2C ADC.
This driver can also be built as a module. If so, the module will
be called ltc2471.
config LTC2485 config LTC2485
tristate "Linear Technology LTC2485 ADC driver" tristate "Linear Technology LTC2485 ADC driver"
depends on I2C depends on I2C
......
...@@ -24,7 +24,9 @@ obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o ...@@ -24,7 +24,9 @@ obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o
obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o
obj-$(CONFIG_CPCAP_ADC) += cpcap-adc.o obj-$(CONFIG_CPCAP_ADC) += cpcap-adc.o
obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
obj-$(CONFIG_DLN2_ADC) += dln2-adc.o
obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o
obj-$(CONFIG_EP93XX_ADC) += ep93xx_adc.o
obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o
obj-$(CONFIG_HI8435) += hi8435.o obj-$(CONFIG_HI8435) += hi8435.o
...@@ -34,6 +36,7 @@ obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o ...@@ -34,6 +36,7 @@ obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
obj-$(CONFIG_LTC2471) += ltc2471.o
obj-$(CONFIG_LTC2485) += ltc2485.o obj-$(CONFIG_LTC2485) += ltc2485.o
obj-$(CONFIG_LTC2497) += ltc2497.o obj-$(CONFIG_LTC2497) += ltc2497.o
obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1027) += max1027.o
......
...@@ -103,8 +103,7 @@ static int ad7766_preenable(struct iio_dev *indio_dev) ...@@ -103,8 +103,7 @@ static int ad7766_preenable(struct iio_dev *indio_dev)
return ret; return ret;
} }
if (ad7766->pd_gpio) gpiod_set_value(ad7766->pd_gpio, 0);
gpiod_set_value(ad7766->pd_gpio, 0);
return 0; return 0;
} }
...@@ -113,8 +112,7 @@ static int ad7766_postdisable(struct iio_dev *indio_dev) ...@@ -113,8 +112,7 @@ static int ad7766_postdisable(struct iio_dev *indio_dev)
{ {
struct ad7766 *ad7766 = iio_priv(indio_dev); struct ad7766 *ad7766 = iio_priv(indio_dev);
if (ad7766->pd_gpio) gpiod_set_value(ad7766->pd_gpio, 1);
gpiod_set_value(ad7766->pd_gpio, 1);
/* /*
* The PD pin is synchronous to the clock, so give it some time to * The PD pin is synchronous to the clock, so give it some time to
......
...@@ -25,6 +25,11 @@ ...@@ -25,6 +25,11 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
/* Control Register */ /* Control Register */
...@@ -132,6 +137,17 @@ ...@@ -132,6 +137,17 @@
#define AT91_SAMA5D2_PRESSR 0xbc #define AT91_SAMA5D2_PRESSR 0xbc
/* Trigger Register */ /* Trigger Register */
#define AT91_SAMA5D2_TRGR 0xc0 #define AT91_SAMA5D2_TRGR 0xc0
/* Mask for TRGMOD field of TRGR register */
#define AT91_SAMA5D2_TRGR_TRGMOD_MASK GENMASK(2, 0)
/* No trigger, only software trigger can start conversions */
#define AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER 0
/* Trigger Mode external trigger rising edge */
#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE 1
/* Trigger Mode external trigger falling edge */
#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL 2
/* Trigger Mode external trigger any edge */
#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY 3
/* Correction Select Register */ /* Correction Select Register */
#define AT91_SAMA5D2_COSR 0xd0 #define AT91_SAMA5D2_COSR 0xd0
/* Correction Value Register */ /* Correction Value Register */
...@@ -145,14 +161,29 @@ ...@@ -145,14 +161,29 @@
/* Version Register */ /* Version Register */
#define AT91_SAMA5D2_VERSION 0xfc #define AT91_SAMA5D2_VERSION 0xfc
#define AT91_SAMA5D2_HW_TRIG_CNT 3
#define AT91_SAMA5D2_SINGLE_CHAN_CNT 12
#define AT91_SAMA5D2_DIFF_CHAN_CNT 6
/*
* Maximum number of bytes to hold conversion from all channels
* plus the timestamp
*/
#define AT91_BUFFER_MAX_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT + \
AT91_SAMA5D2_DIFF_CHAN_CNT) * 2 + 8)
#define AT91_BUFFER_MAX_HWORDS (AT91_BUFFER_MAX_BYTES / 2)
#define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \ #define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \
{ \ { \
.type = IIO_VOLTAGE, \ .type = IIO_VOLTAGE, \
.channel = num, \ .channel = num, \
.address = addr, \ .address = addr, \
.scan_index = num, \
.scan_type = { \ .scan_type = { \
.sign = 'u', \ .sign = 'u', \
.realbits = 12, \ .realbits = 12, \
.storagebits = 16, \
}, \ }, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
...@@ -168,9 +199,11 @@ ...@@ -168,9 +199,11 @@
.channel = num, \ .channel = num, \
.channel2 = num2, \ .channel2 = num2, \
.address = addr, \ .address = addr, \
.scan_index = num + AT91_SAMA5D2_SINGLE_CHAN_CNT, \
.scan_type = { \ .scan_type = { \
.sign = 's', \ .sign = 's', \
.realbits = 12, \ .realbits = 12, \
.storagebits = 16, \
}, \ }, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
...@@ -188,6 +221,12 @@ struct at91_adc_soc_info { ...@@ -188,6 +221,12 @@ struct at91_adc_soc_info {
unsigned max_sample_rate; unsigned max_sample_rate;
}; };
struct at91_adc_trigger {
char *name;
unsigned int trgmod_value;
unsigned int edge_type;
};
struct at91_adc_state { struct at91_adc_state {
void __iomem *base; void __iomem *base;
int irq; int irq;
...@@ -195,11 +234,14 @@ struct at91_adc_state { ...@@ -195,11 +234,14 @@ struct at91_adc_state {
struct regulator *reg; struct regulator *reg;
struct regulator *vref; struct regulator *vref;
int vref_uv; int vref_uv;
struct iio_trigger *trig;
const struct at91_adc_trigger *selected_trig;
const struct iio_chan_spec *chan; const struct iio_chan_spec *chan;
bool conversion_done; bool conversion_done;
u32 conversion_value; u32 conversion_value;
struct at91_adc_soc_info soc_info; struct at91_adc_soc_info soc_info;
wait_queue_head_t wq_data_available; wait_queue_head_t wq_data_available;
u16 buffer[AT91_BUFFER_MAX_HWORDS];
/* /*
* lock to prevent concurrent 'single conversion' requests through * lock to prevent concurrent 'single conversion' requests through
* sysfs. * sysfs.
...@@ -207,6 +249,24 @@ struct at91_adc_state { ...@@ -207,6 +249,24 @@ struct at91_adc_state {
struct mutex lock; struct mutex lock;
}; };
static const struct at91_adc_trigger at91_adc_trigger_list[] = {
{
.name = "external_rising",
.trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE,
.edge_type = IRQ_TYPE_EDGE_RISING,
},
{
.name = "external_falling",
.trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL,
.edge_type = IRQ_TYPE_EDGE_FALLING,
},
{
.name = "external_any",
.trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY,
.edge_type = IRQ_TYPE_EDGE_BOTH,
},
};
static const struct iio_chan_spec at91_adc_channels[] = { static const struct iio_chan_spec at91_adc_channels[] = {
AT91_SAMA5D2_CHAN_SINGLE(0, 0x50), AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
AT91_SAMA5D2_CHAN_SINGLE(1, 0x54), AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
...@@ -226,12 +286,132 @@ static const struct iio_chan_spec at91_adc_channels[] = { ...@@ -226,12 +286,132 @@ static const struct iio_chan_spec at91_adc_channels[] = {
AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68), AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70), AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78), AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_SINGLE_CHAN_CNT
+ AT91_SAMA5D2_DIFF_CHAN_CNT + 1),
};
static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
{
struct iio_dev *indio = iio_trigger_get_drvdata(trig);
struct at91_adc_state *st = iio_priv(indio);
u32 status = at91_adc_readl(st, AT91_SAMA5D2_TRGR);
u8 bit;
/* clear TRGMOD */
status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK;
if (state)
status |= st->selected_trig->trgmod_value;
/* set/unset hw trigger */
at91_adc_writel(st, AT91_SAMA5D2_TRGR, status);
for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
struct iio_chan_spec const *chan = indio->channels + bit;
if (state) {
at91_adc_writel(st, AT91_SAMA5D2_CHER,
BIT(chan->channel));
at91_adc_writel(st, AT91_SAMA5D2_IER,
BIT(chan->channel));
} else {
at91_adc_writel(st, AT91_SAMA5D2_IDR,
BIT(chan->channel));
at91_adc_writel(st, AT91_SAMA5D2_CHDR,
BIT(chan->channel));
}
}
return 0;
}
static int at91_adc_reenable_trigger(struct iio_trigger *trig)
{
struct iio_dev *indio = iio_trigger_get_drvdata(trig);
struct at91_adc_state *st = iio_priv(indio);
enable_irq(st->irq);
/* Needed to ACK the DRDY interruption */
at91_adc_readl(st, AT91_SAMA5D2_LCDR);
return 0;
}
static const struct iio_trigger_ops at91_adc_trigger_ops = {
.owner = THIS_MODULE,
.set_trigger_state = &at91_adc_configure_trigger,
.try_reenable = &at91_adc_reenable_trigger,
}; };
static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,
char *trigger_name)
{
struct iio_trigger *trig;
int ret;
trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name,
indio->id, trigger_name);
if (!trig)
return NULL;
trig->dev.parent = indio->dev.parent;
iio_trigger_set_drvdata(trig, indio);
trig->ops = &at91_adc_trigger_ops;
ret = devm_iio_trigger_register(&indio->dev, trig);
if (ret)
return ERR_PTR(ret);
return trig;
}
static int at91_adc_trigger_init(struct iio_dev *indio)
{
struct at91_adc_state *st = iio_priv(indio);
st->trig = at91_adc_allocate_trigger(indio, st->selected_trig->name);
if (IS_ERR(st->trig)) {
dev_err(&indio->dev,
"could not allocate trigger\n");
return PTR_ERR(st->trig);
}
return 0;
}
static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio = pf->indio_dev;
struct at91_adc_state *st = iio_priv(indio);
int i = 0;
u8 bit;
for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
struct iio_chan_spec const *chan = indio->channels + bit;
st->buffer[i] = at91_adc_readl(st, chan->address);
i++;
}
iio_push_to_buffers_with_timestamp(indio, st->buffer, pf->timestamp);
iio_trigger_notify_done(indio->trig);
return IRQ_HANDLED;
}
static int at91_adc_buffer_init(struct iio_dev *indio)
{
return devm_iio_triggered_buffer_setup(&indio->dev, indio,
&iio_pollfunc_store_time,
&at91_adc_trigger_handler, NULL);
}
static unsigned at91_adc_startup_time(unsigned startup_time_min, static unsigned at91_adc_startup_time(unsigned startup_time_min,
unsigned adc_clk_khz) unsigned adc_clk_khz)
{ {
const unsigned startup_lookup[] = { static const unsigned int startup_lookup[] = {
0, 8, 16, 24, 0, 8, 16, 24,
64, 80, 96, 112, 64, 80, 96, 112,
512, 576, 640, 704, 512, 576, 640, 704,
...@@ -293,14 +473,18 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private) ...@@ -293,14 +473,18 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR); u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR);
u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR); u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR);
if (status & imr) { if (!(status & imr))
return IRQ_NONE;
if (iio_buffer_enabled(indio)) {
disable_irq_nosync(irq);
iio_trigger_poll(indio->trig);
} else {
st->conversion_value = at91_adc_readl(st, st->chan->address); st->conversion_value = at91_adc_readl(st, st->chan->address);
st->conversion_done = true; st->conversion_done = true;
wake_up_interruptible(&st->wq_data_available); wake_up_interruptible(&st->wq_data_available);
return IRQ_HANDLED;
} }
return IRQ_HANDLED;
return IRQ_NONE;
} }
static int at91_adc_read_raw(struct iio_dev *indio_dev, static int at91_adc_read_raw(struct iio_dev *indio_dev,
...@@ -313,6 +497,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, ...@@ -313,6 +497,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
/* we cannot use software trigger if hw trigger enabled */
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
mutex_lock(&st->lock); mutex_lock(&st->lock);
st->chan = chan; st->chan = chan;
...@@ -344,6 +533,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, ...@@ -344,6 +533,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel)); at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
mutex_unlock(&st->lock); mutex_unlock(&st->lock);
iio_device_release_direct_mode(indio_dev);
return ret; return ret;
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
...@@ -386,12 +577,27 @@ static const struct iio_info at91_adc_info = { ...@@ -386,12 +577,27 @@ static const struct iio_info at91_adc_info = {
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
}; };
static void at91_adc_hw_init(struct at91_adc_state *st)
{
at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST);
at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff);
/*
* Transfer field must be set to 2 according to the datasheet and
* allows different analog settings for each channel.
*/
at91_adc_writel(st, AT91_SAMA5D2_MR,
AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH);
at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate);
}
static int at91_adc_probe(struct platform_device *pdev) static int at91_adc_probe(struct platform_device *pdev)
{ {
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct at91_adc_state *st; struct at91_adc_state *st;
struct resource *res; struct resource *res;
int ret; int ret, i;
u32 edge_type;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st)); indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
if (!indio_dev) if (!indio_dev)
...@@ -432,6 +638,27 @@ static int at91_adc_probe(struct platform_device *pdev) ...@@ -432,6 +638,27 @@ static int at91_adc_probe(struct platform_device *pdev)
return ret; return ret;
} }
ret = of_property_read_u32(pdev->dev.of_node,
"atmel,trigger-edge-type", &edge_type);
if (ret) {
dev_err(&pdev->dev,
"invalid or missing value for atmel,trigger-edge-type\n");
return ret;
}
st->selected_trig = NULL;
for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT; i++)
if (at91_adc_trigger_list[i].edge_type == edge_type) {
st->selected_trig = &at91_adc_trigger_list[i];
break;
}
if (!st->selected_trig) {
dev_err(&pdev->dev, "invalid external trigger edge value\n");
return -EINVAL;
}
init_waitqueue_head(&st->wq_data_available); init_waitqueue_head(&st->wq_data_available);
mutex_init(&st->lock); mutex_init(&st->lock);
...@@ -482,16 +709,7 @@ static int at91_adc_probe(struct platform_device *pdev) ...@@ -482,16 +709,7 @@ static int at91_adc_probe(struct platform_device *pdev)
goto vref_disable; goto vref_disable;
} }
at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); at91_adc_hw_init(st);
at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff);
/*
* Transfer field must be set to 2 according to the datasheet and
* allows different analog settings for each channel.
*/
at91_adc_writel(st, AT91_SAMA5D2_MR,
AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH);
at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate);
ret = clk_prepare_enable(st->per_clk); ret = clk_prepare_enable(st->per_clk);
if (ret) if (ret)
...@@ -499,10 +717,25 @@ static int at91_adc_probe(struct platform_device *pdev) ...@@ -499,10 +717,25 @@ static int at91_adc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, indio_dev); platform_set_drvdata(pdev, indio_dev);
ret = at91_adc_buffer_init(indio_dev);
if (ret < 0) {
dev_err(&pdev->dev, "couldn't initialize the buffer.\n");
goto per_clk_disable_unprepare;
}
ret = at91_adc_trigger_init(indio_dev);
if (ret < 0) {
dev_err(&pdev->dev, "couldn't setup the triggers.\n");
goto per_clk_disable_unprepare;
}
ret = iio_device_register(indio_dev); ret = iio_device_register(indio_dev);
if (ret < 0) if (ret < 0)
goto per_clk_disable_unprepare; goto per_clk_disable_unprepare;
dev_info(&pdev->dev, "setting up trigger as %s\n",
st->selected_trig->name);
dev_info(&pdev->dev, "version: %x\n", dev_info(&pdev->dev, "version: %x\n",
readl_relaxed(st->base + AT91_SAMA5D2_VERSION)); readl_relaxed(st->base + AT91_SAMA5D2_VERSION));
...@@ -532,6 +765,69 @@ static int at91_adc_remove(struct platform_device *pdev) ...@@ -532,6 +765,69 @@ static int at91_adc_remove(struct platform_device *pdev)
return 0; return 0;
} }
static __maybe_unused int at91_adc_suspend(struct device *dev)
{
struct iio_dev *indio_dev =
platform_get_drvdata(to_platform_device(dev));
struct at91_adc_state *st = iio_priv(indio_dev);
/*
* Do a sofware reset of the ADC before we go to suspend.
* this will ensure that all pins are free from being muxed by the ADC
* and can be used by for other devices.
* Otherwise, ADC will hog them and we can't go to suspend mode.
*/
at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST);
clk_disable_unprepare(st->per_clk);
regulator_disable(st->vref);
regulator_disable(st->reg);
return pinctrl_pm_select_sleep_state(dev);
}
static __maybe_unused int at91_adc_resume(struct device *dev)
{
struct iio_dev *indio_dev =
platform_get_drvdata(to_platform_device(dev));
struct at91_adc_state *st = iio_priv(indio_dev);
int ret;
ret = pinctrl_pm_select_default_state(dev);
if (ret)
goto resume_failed;
ret = regulator_enable(st->reg);
if (ret)
goto resume_failed;
ret = regulator_enable(st->vref);
if (ret)
goto reg_disable_resume;
ret = clk_prepare_enable(st->per_clk);
if (ret)
goto vref_disable_resume;
at91_adc_hw_init(st);
/* reconfiguring trigger hardware state */
if (iio_buffer_enabled(indio_dev))
at91_adc_configure_trigger(st->trig, true);
return 0;
vref_disable_resume:
regulator_disable(st->vref);
reg_disable_resume:
regulator_disable(st->reg);
resume_failed:
dev_err(&indio_dev->dev, "failed to resume\n");
return ret;
}
static SIMPLE_DEV_PM_OPS(at91_adc_pm_ops, at91_adc_suspend, at91_adc_resume);
static const struct of_device_id at91_adc_dt_match[] = { static const struct of_device_id at91_adc_dt_match[] = {
{ {
.compatible = "atmel,sama5d2-adc", .compatible = "atmel,sama5d2-adc",
...@@ -547,6 +843,7 @@ static struct platform_driver at91_adc_driver = { ...@@ -547,6 +843,7 @@ static struct platform_driver at91_adc_driver = {
.driver = { .driver = {
.name = "at91-sama5d2_adc", .name = "at91-sama5d2_adc",
.of_match_table = at91_adc_dt_match, .of_match_table = at91_adc_dt_match,
.pm = &at91_adc_pm_ops,
}, },
}; };
module_platform_driver(at91_adc_driver) module_platform_driver(at91_adc_driver)
......
...@@ -799,7 +799,7 @@ static u32 calc_startup_ticks_9x5(u32 startup_time, u32 adc_clk_khz) ...@@ -799,7 +799,7 @@ static u32 calc_startup_ticks_9x5(u32 startup_time, u32 adc_clk_khz)
* For sama5d3x and at91sam9x5, the formula changes to: * For sama5d3x and at91sam9x5, the formula changes to:
* Startup Time = <lookup_table_value> / ADC Clock * Startup Time = <lookup_table_value> / ADC Clock
*/ */
const int startup_lookup[] = { static const int startup_lookup[] = {
0, 8, 16, 24, 0, 8, 16, 24,
64, 80, 96, 112, 64, 80, 96, 112,
512, 576, 640, 704, 512, 576, 640, 704,
......
/*
* Driver for the Diolan DLN-2 USB-ADC adapter
*
* Copyright (c) 2017 Jack Andersen
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/mfd/dln2.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/buffer.h>
#include <linux/iio/kfifo_buf.h>
#define DLN2_ADC_MOD_NAME "dln2-adc"
#define DLN2_ADC_ID 0x06
#define DLN2_ADC_GET_CHANNEL_COUNT DLN2_CMD(0x01, DLN2_ADC_ID)
#define DLN2_ADC_ENABLE DLN2_CMD(0x02, DLN2_ADC_ID)
#define DLN2_ADC_DISABLE DLN2_CMD(0x03, DLN2_ADC_ID)
#define DLN2_ADC_CHANNEL_ENABLE DLN2_CMD(0x05, DLN2_ADC_ID)
#define DLN2_ADC_CHANNEL_DISABLE DLN2_CMD(0x06, DLN2_ADC_ID)
#define DLN2_ADC_SET_RESOLUTION DLN2_CMD(0x08, DLN2_ADC_ID)
#define DLN2_ADC_CHANNEL_GET_VAL DLN2_CMD(0x0A, DLN2_ADC_ID)
#define DLN2_ADC_CHANNEL_GET_ALL_VAL DLN2_CMD(0x0B, DLN2_ADC_ID)
#define DLN2_ADC_CHANNEL_SET_CFG DLN2_CMD(0x0C, DLN2_ADC_ID)
#define DLN2_ADC_CHANNEL_GET_CFG DLN2_CMD(0x0D, DLN2_ADC_ID)
#define DLN2_ADC_CONDITION_MET_EV DLN2_CMD(0x10, DLN2_ADC_ID)
#define DLN2_ADC_EVENT_NONE 0
#define DLN2_ADC_EVENT_BELOW 1
#define DLN2_ADC_EVENT_LEVEL_ABOVE 2
#define DLN2_ADC_EVENT_OUTSIDE 3
#define DLN2_ADC_EVENT_INSIDE 4
#define DLN2_ADC_EVENT_ALWAYS 5
#define DLN2_ADC_MAX_CHANNELS 8
#define DLN2_ADC_DATA_BITS 10
/*
* Plays similar role to iio_demux_table in subsystem core; except allocated
* in a fixed 8-element array.
*/
struct dln2_adc_demux_table {
unsigned int from;
unsigned int to;
unsigned int length;
};
struct dln2_adc {
struct platform_device *pdev;
struct iio_chan_spec iio_channels[DLN2_ADC_MAX_CHANNELS + 1];
int port, trigger_chan;
struct iio_trigger *trig;
struct mutex mutex;
/* Cached sample period in milliseconds */
unsigned int sample_period;
/* Demux table */
unsigned int demux_count;
struct dln2_adc_demux_table demux[DLN2_ADC_MAX_CHANNELS];
/* Precomputed timestamp padding offset and length */
unsigned int ts_pad_offset, ts_pad_length;
};
struct dln2_adc_port_chan {
u8 port;
u8 chan;
};
struct dln2_adc_get_all_vals {
__le16 channel_mask;
__le16 values[DLN2_ADC_MAX_CHANNELS];
};
static void dln2_adc_add_demux(struct dln2_adc *dln2,
unsigned int in_loc, unsigned int out_loc,
unsigned int length)
{
struct dln2_adc_demux_table *p = dln2->demux_count ?
&dln2->demux[dln2->demux_count - 1] : NULL;
if (p && p->from + p->length == in_loc &&
p->to + p->length == out_loc) {
p->length += length;
} else if (dln2->demux_count < DLN2_ADC_MAX_CHANNELS) {
p = &dln2->demux[dln2->demux_count++];
p->from = in_loc;
p->to = out_loc;
p->length = length;
}
}
static void dln2_adc_update_demux(struct dln2_adc *dln2)
{
int in_ind = -1, out_ind;
unsigned int in_loc = 0, out_loc = 0;
struct iio_dev *indio_dev = platform_get_drvdata(dln2->pdev);
/* Clear out any old demux */
dln2->demux_count = 0;
/* Optimize all 8-channels case */
if (indio_dev->masklength &&
(*indio_dev->active_scan_mask & 0xff) == 0xff) {
dln2_adc_add_demux(dln2, 0, 0, 16);
dln2->ts_pad_offset = 0;
dln2->ts_pad_length = 0;
return;
}
/* Build demux table from fixed 8-channels to active_scan_mask */
for_each_set_bit(out_ind,
indio_dev->active_scan_mask,
indio_dev->masklength) {
/* Handle timestamp separately */
if (out_ind == DLN2_ADC_MAX_CHANNELS)
break;
for (++in_ind; in_ind != out_ind; ++in_ind)
in_loc += 2;
dln2_adc_add_demux(dln2, in_loc, out_loc, 2);
out_loc += 2;
in_loc += 2;
}
if (indio_dev->scan_timestamp) {
size_t ts_offset = indio_dev->scan_bytes / sizeof(int64_t) - 1;
dln2->ts_pad_offset = out_loc;
dln2->ts_pad_length = ts_offset * sizeof(int64_t) - out_loc;
} else {
dln2->ts_pad_offset = 0;
dln2->ts_pad_length = 0;
}
}
static int dln2_adc_get_chan_count(struct dln2_adc *dln2)
{
int ret;
u8 port = dln2->port;
u8 count;
int olen = sizeof(count);
ret = dln2_transfer(dln2->pdev, DLN2_ADC_GET_CHANNEL_COUNT,
&port, sizeof(port), &count, &olen);
if (ret < 0) {
dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__);
return ret;
}
if (olen < sizeof(count))
return -EPROTO;
return count;
}
static int dln2_adc_set_port_resolution(struct dln2_adc *dln2)
{
int ret;
struct dln2_adc_port_chan port_chan = {
.port = dln2->port,
.chan = DLN2_ADC_DATA_BITS,
};
ret = dln2_transfer_tx(dln2->pdev, DLN2_ADC_SET_RESOLUTION,
&port_chan, sizeof(port_chan));
if (ret < 0)
dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__);
return ret;
}
static int dln2_adc_set_chan_enabled(struct dln2_adc *dln2,
int channel, bool enable)
{
int ret;
struct dln2_adc_port_chan port_chan = {
.port = dln2->port,
.chan = channel,
};
u16 cmd = enable ? DLN2_ADC_CHANNEL_ENABLE : DLN2_ADC_CHANNEL_DISABLE;
ret = dln2_transfer_tx(dln2->pdev, cmd, &port_chan, sizeof(port_chan));
if (ret < 0)
dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__);
return ret;
}
static int dln2_adc_set_port_enabled(struct dln2_adc *dln2, bool enable,
u16 *conflict_out)
{
int ret;
u8 port = dln2->port;
__le16 conflict;
int olen = sizeof(conflict);
u16 cmd = enable ? DLN2_ADC_ENABLE : DLN2_ADC_DISABLE;
if (conflict_out)
*conflict_out = 0;
ret = dln2_transfer(dln2->pdev, cmd, &port, sizeof(port),
&conflict, &olen);
if (ret < 0) {
dev_dbg(&dln2->pdev->dev, "Problem in %s(%d)\n",
__func__, (int)enable);
if (conflict_out && enable && olen >= sizeof(conflict))
*conflict_out = le16_to_cpu(conflict);
return ret;
}
if (enable && olen < sizeof(conflict))
return -EPROTO;
return ret;
}
static int dln2_adc_set_chan_period(struct dln2_adc *dln2,
unsigned int channel, unsigned int period)
{
int ret;
struct {
struct dln2_adc_port_chan port_chan;
__u8 type;
__le16 period;
__le16 low;
__le16 high;
} __packed set_cfg = {
.port_chan.port = dln2->port,
.port_chan.chan = channel,
.type = period ? DLN2_ADC_EVENT_ALWAYS : DLN2_ADC_EVENT_NONE,
.period = cpu_to_le16(period)
};
ret = dln2_transfer_tx(dln2->pdev, DLN2_ADC_CHANNEL_SET_CFG,
&set_cfg, sizeof(set_cfg));
if (ret < 0)
dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__);
return ret;
}
static int dln2_adc_read(struct dln2_adc *dln2, unsigned int channel)
{
int ret, i;
struct iio_dev *indio_dev = platform_get_drvdata(dln2->pdev);
u16 conflict;
__le16 value;
int olen = sizeof(value);
struct dln2_adc_port_chan port_chan = {
.port = dln2->port,
.chan = channel,
};
ret = iio_device_claim_direct_mode(indio_dev);
if (ret < 0)
return ret;
ret = dln2_adc_set_chan_enabled(dln2, channel, true);
if (ret < 0)
goto release_direct;
ret = dln2_adc_set_port_enabled(dln2, true, &conflict);
if (ret < 0) {
if (conflict) {
dev_err(&dln2->pdev->dev,
"ADC pins conflict with mask %04X\n",
(int)conflict);
ret = -EBUSY;
}
goto disable_chan;
}
/*
* Call GET_VAL twice due to initial zero-return immediately after
* enabling channel.
*/
for (i = 0; i < 2; ++i) {
ret = dln2_transfer(dln2->pdev, DLN2_ADC_CHANNEL_GET_VAL,
&port_chan, sizeof(port_chan),
&value, &olen);
if (ret < 0) {
dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__);
goto disable_port;
}
if (olen < sizeof(value)) {
ret = -EPROTO;
goto disable_port;
}
}
ret = le16_to_cpu(value);
disable_port:
dln2_adc_set_port_enabled(dln2, false, NULL);
disable_chan:
dln2_adc_set_chan_enabled(dln2, channel, false);
release_direct:
iio_device_release_direct_mode(indio_dev);
return ret;
}
static int dln2_adc_read_all(struct dln2_adc *dln2,
struct dln2_adc_get_all_vals *get_all_vals)
{
int ret;
__u8 port = dln2->port;
int olen = sizeof(*get_all_vals);
ret = dln2_transfer(dln2->pdev, DLN2_ADC_CHANNEL_GET_ALL_VAL,
&port, sizeof(port), get_all_vals, &olen);
if (ret < 0) {
dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__);
return ret;
}
if (olen < sizeof(*get_all_vals))
return -EPROTO;
return ret;
}
static int dln2_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val,
int *val2,
long mask)
{
int ret;
unsigned int microhertz;
struct dln2_adc *dln2 = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&dln2->mutex);
ret = dln2_adc_read(dln2, chan->channel);
mutex_unlock(&dln2->mutex);
if (ret < 0)
return ret;
*val = ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
/*
* Voltage reference is fixed at 3.3v
* 3.3 / (1 << 10) * 1000000000
*/
*val = 0;
*val2 = 3222656;
return IIO_VAL_INT_PLUS_NANO;
case IIO_CHAN_INFO_SAMP_FREQ:
if (dln2->sample_period) {
microhertz = 1000000000 / dln2->sample_period;
*val = microhertz / 1000000;
*val2 = microhertz % 1000000;
} else {
*val = 0;
*val2 = 0;
}
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
}
static int dln2_adc_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val,
int val2,
long mask)
{
int ret;
unsigned int microhertz;
struct dln2_adc *dln2 = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
microhertz = 1000000 * val + val2;
mutex_lock(&dln2->mutex);
dln2->sample_period =
microhertz ? 1000000000 / microhertz : UINT_MAX;
if (dln2->sample_period > 65535) {
dln2->sample_period = 65535;
dev_warn(&dln2->pdev->dev,
"clamping period to 65535ms\n");
}
/*
* The first requested channel is arbitrated as a shared
* trigger source, so only one event is registered with the
* DLN. The event handler will then read all enabled channel
* values using DLN2_ADC_CHANNEL_GET_ALL_VAL to maintain
* synchronization between ADC readings.
*/
if (dln2->trigger_chan != -1)
ret = dln2_adc_set_chan_period(dln2,
dln2->trigger_chan, dln2->sample_period);
else
ret = 0;
mutex_unlock(&dln2->mutex);
return ret;
default:
return -EINVAL;
}
}
static int dln2_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
struct dln2_adc *dln2 = iio_priv(indio_dev);
int chan_count = indio_dev->num_channels - 1;
int ret, i, j;
mutex_lock(&dln2->mutex);
for (i = 0; i < chan_count; ++i) {
ret = dln2_adc_set_chan_enabled(dln2, i,
test_bit(i, scan_mask));
if (ret < 0) {
for (j = 0; j < i; ++j)
dln2_adc_set_chan_enabled(dln2, j, false);
mutex_unlock(&dln2->mutex);
dev_err(&dln2->pdev->dev,
"Unable to enable ADC channel %d\n", i);
return -EBUSY;
}
}
dln2_adc_update_demux(dln2);
mutex_unlock(&dln2->mutex);
return 0;
}
#define DLN2_ADC_CHAN(lval, idx) { \
lval.type = IIO_VOLTAGE; \
lval.channel = idx; \
lval.indexed = 1; \
lval.info_mask_separate = BIT(IIO_CHAN_INFO_RAW); \
lval.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ); \
lval.scan_index = idx; \
lval.scan_type.sign = 'u'; \
lval.scan_type.realbits = DLN2_ADC_DATA_BITS; \
lval.scan_type.storagebits = 16; \
lval.scan_type.endianness = IIO_LE; \
}
/* Assignment version of IIO_CHAN_SOFT_TIMESTAMP */
#define IIO_CHAN_SOFT_TIMESTAMP_ASSIGN(lval, _si) { \
lval.type = IIO_TIMESTAMP; \
lval.channel = -1; \
lval.scan_index = _si; \
lval.scan_type.sign = 's'; \
lval.scan_type.realbits = 64; \
lval.scan_type.storagebits = 64; \
}
static const struct iio_info dln2_adc_info = {
.read_raw = dln2_adc_read_raw,
.write_raw = dln2_adc_write_raw,
.update_scan_mode = dln2_update_scan_mode,
.driver_module = THIS_MODULE,
};
static irqreturn_t dln2_adc_trigger_h(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct {
__le16 values[DLN2_ADC_MAX_CHANNELS];
int64_t timestamp_space;
} data;
struct dln2_adc_get_all_vals dev_data;
struct dln2_adc *dln2 = iio_priv(indio_dev);
const struct dln2_adc_demux_table *t;
int ret, i;
mutex_lock(&dln2->mutex);
ret = dln2_adc_read_all(dln2, &dev_data);
mutex_unlock(&dln2->mutex);
if (ret < 0)
goto done;
/* Demux operation */
for (i = 0; i < dln2->demux_count; ++i) {
t = &dln2->demux[i];
memcpy((void *)data.values + t->to,
(void *)dev_data.values + t->from, t->length);
}
/* Zero padding space between values and timestamp */
if (dln2->ts_pad_length)
memset((void *)data.values + dln2->ts_pad_offset,
0, dln2->ts_pad_length);
iio_push_to_buffers_with_timestamp(indio_dev, &data,
iio_get_time_ns(indio_dev));
done:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev)
{
int ret;
struct dln2_adc *dln2 = iio_priv(indio_dev);
u16 conflict;
unsigned int trigger_chan;
mutex_lock(&dln2->mutex);
/* Enable ADC */
ret = dln2_adc_set_port_enabled(dln2, true, &conflict);
if (ret < 0) {
mutex_unlock(&dln2->mutex);
dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__);
if (conflict) {
dev_err(&dln2->pdev->dev,
"ADC pins conflict with mask %04X\n",
(int)conflict);
ret = -EBUSY;
}
return ret;
}
/* Assign trigger channel based on first enabled channel */
trigger_chan = find_first_bit(indio_dev->active_scan_mask,
indio_dev->masklength);
if (trigger_chan < DLN2_ADC_MAX_CHANNELS) {
dln2->trigger_chan = trigger_chan;
ret = dln2_adc_set_chan_period(dln2, dln2->trigger_chan,
dln2->sample_period);
mutex_unlock(&dln2->mutex);
if (ret < 0) {
dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__);
return ret;
}
} else {
dln2->trigger_chan = -1;
mutex_unlock(&dln2->mutex);
}
return iio_triggered_buffer_postenable(indio_dev);
}
static int dln2_adc_triggered_buffer_predisable(struct iio_dev *indio_dev)
{
int ret;
struct dln2_adc *dln2 = iio_priv(indio_dev);
mutex_lock(&dln2->mutex);
/* Disable trigger channel */
if (dln2->trigger_chan != -1) {
dln2_adc_set_chan_period(dln2, dln2->trigger_chan, 0);
dln2->trigger_chan = -1;
}
/* Disable ADC */
ret = dln2_adc_set_port_enabled(dln2, false, NULL);
mutex_unlock(&dln2->mutex);
if (ret < 0) {
dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__);
return ret;
}
return iio_triggered_buffer_predisable(indio_dev);
}
static const struct iio_buffer_setup_ops dln2_adc_buffer_setup_ops = {
.postenable = dln2_adc_triggered_buffer_postenable,
.predisable = dln2_adc_triggered_buffer_predisable,
};
static void dln2_adc_event(struct platform_device *pdev, u16 echo,
const void *data, int len)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct dln2_adc *dln2 = iio_priv(indio_dev);
/* Called via URB completion handler */
iio_trigger_poll(dln2->trig);
}
static const struct iio_trigger_ops dln2_adc_trigger_ops = {
.owner = THIS_MODULE,
};
static int dln2_adc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dln2_adc *dln2;
struct dln2_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev;
int i, ret, chans;
indio_dev = devm_iio_device_alloc(dev, sizeof(*dln2));
if (!indio_dev) {
dev_err(dev, "failed allocating iio device\n");
return -ENOMEM;
}
dln2 = iio_priv(indio_dev);
dln2->pdev = pdev;
dln2->port = pdata->port;
dln2->trigger_chan = -1;
mutex_init(&dln2->mutex);
platform_set_drvdata(pdev, indio_dev);
ret = dln2_adc_set_port_resolution(dln2);
if (ret < 0) {
dev_err(dev, "failed to set ADC resolution to 10 bits\n");
return ret;
}
chans = dln2_adc_get_chan_count(dln2);
if (chans < 0) {
dev_err(dev, "failed to get channel count: %d\n", chans);
return chans;
}
if (chans > DLN2_ADC_MAX_CHANNELS) {
chans = DLN2_ADC_MAX_CHANNELS;
dev_warn(dev, "clamping channels to %d\n",
DLN2_ADC_MAX_CHANNELS);
}
for (i = 0; i < chans; ++i)
DLN2_ADC_CHAN(dln2->iio_channels[i], i)
IIO_CHAN_SOFT_TIMESTAMP_ASSIGN(dln2->iio_channels[i], i);
indio_dev->name = DLN2_ADC_MOD_NAME;
indio_dev->dev.parent = dev;
indio_dev->info = &dln2_adc_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = dln2->iio_channels;
indio_dev->num_channels = chans + 1;
indio_dev->setup_ops = &dln2_adc_buffer_setup_ops;
dln2->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
indio_dev->name, indio_dev->id);
if (!dln2->trig) {
dev_err(dev, "failed to allocate trigger\n");
return -ENOMEM;
}
dln2->trig->ops = &dln2_adc_trigger_ops;
iio_trigger_set_drvdata(dln2->trig, dln2);
devm_iio_trigger_register(dev, dln2->trig);
iio_trigger_set_immutable(indio_dev, dln2->trig);
ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
dln2_adc_trigger_h,
&dln2_adc_buffer_setup_ops);
if (ret) {
dev_err(dev, "failed to allocate triggered buffer: %d\n", ret);
return ret;
}
ret = dln2_register_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV,
dln2_adc_event);
if (ret) {
dev_err(dev, "failed to setup DLN2 periodic event: %d\n", ret);
return ret;
}
ret = iio_device_register(indio_dev);
if (ret) {
dev_err(dev, "failed to register iio device: %d\n", ret);
goto unregister_event;
}
return ret;
unregister_event:
dln2_unregister_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV);
return ret;
}
static int dln2_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
iio_device_unregister(indio_dev);
dln2_unregister_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV);
return 0;
}
static struct platform_driver dln2_adc_driver = {
.driver.name = DLN2_ADC_MOD_NAME,
.probe = dln2_adc_probe,
.remove = dln2_adc_remove,
};
module_platform_driver(dln2_adc_driver);
MODULE_AUTHOR("Jack Andersen <jackoalan@gmail.com");
MODULE_DESCRIPTION("Driver for the Diolan DLN2 ADC interface");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:dln2-adc");
/*
* Driver for ADC module on the Cirrus Logic EP93xx series of SoCs
*
* Copyright (C) 2015 Alexander Sverdlin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The driver uses polling to get the conversion status. According to EP93xx
* datasheets, reading ADCResult register starts the conversion, but user is also
* responsible for ensuring that delay between adjacent conversion triggers is
* long enough so that maximum allowed conversion rate is not exceeded. This
* basically renders IRQ mode unusable.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/iio/iio.h>
#include <linux/io.h>
#include <linux/irqflags.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
/*
* This code could benefit from real HR Timers, but jiffy granularity would
* lower ADC conversion rate down to CONFIG_HZ, so we fallback to busy wait
* in such case.
*
* HR Timers-based version loads CPU only up to 10% during back to back ADC
* conversion, while busy wait-based version consumes whole CPU power.
*/
#ifdef CONFIG_HIGH_RES_TIMERS
#define ep93xx_adc_delay(usmin, usmax) usleep_range(usmin, usmax)
#else
#define ep93xx_adc_delay(usmin, usmax) udelay(usmin)
#endif
#define EP93XX_ADC_RESULT 0x08
#define EP93XX_ADC_SDR BIT(31)
#define EP93XX_ADC_SWITCH 0x18
#define EP93XX_ADC_SW_LOCK 0x20
struct ep93xx_adc_priv {
struct clk *clk;
void __iomem *base;
int lastch;
struct mutex lock;
};
#define EP93XX_ADC_CH(index, dname, swcfg) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = index, \
.address = swcfg, \
.datasheet_name = dname, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_OFFSET), \
}
/*
* Numbering scheme for channels 0..4 is defined in EP9301 and EP9302 datasheets.
* EP9307, EP9312 and EP9312 have 3 channels more (total 8), but the numbering is
* not defined. So the last three are numbered randomly, let's say.
*/
static const struct iio_chan_spec ep93xx_adc_channels[8] = {
EP93XX_ADC_CH(0, "YM", 0x608),
EP93XX_ADC_CH(1, "SXP", 0x680),
EP93XX_ADC_CH(2, "SXM", 0x640),
EP93XX_ADC_CH(3, "SYP", 0x620),
EP93XX_ADC_CH(4, "SYM", 0x610),
EP93XX_ADC_CH(5, "XP", 0x601),
EP93XX_ADC_CH(6, "XM", 0x602),
EP93XX_ADC_CH(7, "YP", 0x604),
};
static int ep93xx_read_raw(struct iio_dev *iiodev,
struct iio_chan_spec const *channel, int *value,
int *shift, long mask)
{
struct ep93xx_adc_priv *priv = iio_priv(iiodev);
unsigned long timeout;
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&priv->lock);
if (priv->lastch != channel->channel) {
priv->lastch = channel->channel;
/*
* Switch register is software-locked, unlocking must be
* immediately followed by write
*/
local_irq_disable();
writel_relaxed(0xAA, priv->base + EP93XX_ADC_SW_LOCK);
writel_relaxed(channel->address,
priv->base + EP93XX_ADC_SWITCH);
local_irq_enable();
/*
* Settling delay depends on module clock and could be
* 2ms or 500us
*/
ep93xx_adc_delay(2000, 2000);
}
/* Start the conversion, eventually discarding old result */
readl_relaxed(priv->base + EP93XX_ADC_RESULT);
/* Ensure maximum conversion rate is not exceeded */
ep93xx_adc_delay(DIV_ROUND_UP(1000000, 925),
DIV_ROUND_UP(1000000, 925));
/* At this point conversion must be completed, but anyway... */
ret = IIO_VAL_INT;
timeout = jiffies + msecs_to_jiffies(1) + 1;
while (1) {
u32 t;
t = readl_relaxed(priv->base + EP93XX_ADC_RESULT);
if (t & EP93XX_ADC_SDR) {
*value = sign_extend32(t, 15);
break;
}
if (time_after(jiffies, timeout)) {
dev_err(&iiodev->dev, "Conversion timeout\n");
ret = -ETIMEDOUT;
break;
}
cpu_relax();
}
mutex_unlock(&priv->lock);
return ret;
case IIO_CHAN_INFO_OFFSET:
/* According to datasheet, range is -25000..25000 */
*value = 25000;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
/* Typical supply voltage is 3.3v */
*value = (1ULL << 32) * 3300 / 50000;
*shift = 32;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
static const struct iio_info ep93xx_adc_info = {
.driver_module = THIS_MODULE,
.read_raw = ep93xx_read_raw,
};
static int ep93xx_adc_probe(struct platform_device *pdev)
{
int ret;
struct iio_dev *iiodev;
struct ep93xx_adc_priv *priv;
struct clk *pclk;
struct resource *res;
iiodev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
if (!iiodev)
return -ENOMEM;
priv = iio_priv(iiodev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "Cannot obtain memory resource\n");
return -ENXIO;
}
priv->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(priv->base)) {
dev_err(&pdev->dev, "Cannot map memory resource\n");
return PTR_ERR(priv->base);
}
iiodev->dev.parent = &pdev->dev;
iiodev->name = dev_name(&pdev->dev);
iiodev->modes = INDIO_DIRECT_MODE;
iiodev->info = &ep93xx_adc_info;
iiodev->num_channels = ARRAY_SIZE(ep93xx_adc_channels);
iiodev->channels = ep93xx_adc_channels;
priv->lastch = -1;
mutex_init(&priv->lock);
platform_set_drvdata(pdev, iiodev);
priv->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev, "Cannot obtain clock\n");
return PTR_ERR(priv->clk);
}
pclk = clk_get_parent(priv->clk);
if (!pclk) {
dev_warn(&pdev->dev, "Cannot obtain parent clock\n");
} else {
/*
* This is actually a place for improvement:
* EP93xx ADC supports two clock divisors -- 4 and 16,
* resulting in conversion rates 3750 and 925 samples per second
* with 500us or 2ms settling time respectively.
* One might find this interesting enough to be configurable.
*/
ret = clk_set_rate(priv->clk, clk_get_rate(pclk) / 16);
if (ret)
dev_warn(&pdev->dev, "Cannot set clock rate\n");
/*
* We can tolerate rate setting failure because the module should
* work in any case.
*/
}
ret = clk_enable(priv->clk);
if (ret) {
dev_err(&pdev->dev, "Cannot enable clock\n");
return ret;
}
ret = iio_device_register(iiodev);
if (ret)
clk_disable(priv->clk);
return ret;
}
static int ep93xx_adc_remove(struct platform_device *pdev)
{
struct iio_dev *iiodev = platform_get_drvdata(pdev);
struct ep93xx_adc_priv *priv = iio_priv(iiodev);
iio_device_unregister(iiodev);
clk_disable(priv->clk);
return 0;
}
static struct platform_driver ep93xx_adc_driver = {
.driver = {
.name = "ep93xx-adc",
},
.probe = ep93xx_adc_probe,
.remove = ep93xx_adc_remove,
};
module_platform_driver(ep93xx_adc_driver);
MODULE_AUTHOR("Alexander Sverdlin <alexander.sverdlin@gmail.com>");
MODULE_DESCRIPTION("Cirrus Logic EP93XX ADC driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:ep93xx-adc");
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#define INA226_MASK_ENABLE 0x06 #define INA226_MASK_ENABLE 0x06
#define INA226_CVRF BIT(3) #define INA226_CVRF BIT(3)
#define INA219_CNVR BIT(1)
#define INA2XX_MAX_REGISTERS 8 #define INA2XX_MAX_REGISTERS 8
...@@ -592,6 +593,7 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) ...@@ -592,6 +593,7 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev)
int bit, ret, i = 0; int bit, ret, i = 0;
s64 time_a, time_b; s64 time_a, time_b;
unsigned int alert; unsigned int alert;
int cnvr_need_clear = 0;
time_a = iio_get_time_ns(indio_dev); time_a = iio_get_time_ns(indio_dev);
...@@ -603,22 +605,30 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) ...@@ -603,22 +605,30 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev)
* we check the ConVersionReadyFlag. * we check the ConVersionReadyFlag.
* On hardware that supports using the ALERT pin to toggle a * On hardware that supports using the ALERT pin to toggle a
* GPIO a triggered buffer could be used instead. * GPIO a triggered buffer could be used instead.
* For now, we pay for that extra read of the ALERT register * For now, we do an extra read of the MASK_ENABLE register (INA226)
* resp. the BUS_VOLTAGE register (INA219).
*/ */
if (!chip->allow_async_readout) if (!chip->allow_async_readout)
do { do {
ret = regmap_read(chip->regmap, INA226_MASK_ENABLE, if (chip->config->chip_id == ina226) {
&alert); ret = regmap_read(chip->regmap,
INA226_MASK_ENABLE, &alert);
alert &= INA226_CVRF;
} else {
ret = regmap_read(chip->regmap,
INA2XX_BUS_VOLTAGE, &alert);
alert &= INA219_CNVR;
cnvr_need_clear = alert;
}
if (ret < 0) if (ret < 0)
return ret; return ret;
alert &= INA226_CVRF;
} while (!alert); } while (!alert);
/* /*
* Single register reads: bulk_read will not work with ina226 * Single register reads: bulk_read will not work with ina226/219
* as there is no auto-increment of the address register for * as there is no auto-increment of the register pointer.
* data length longer than 16bits.
*/ */
for_each_set_bit(bit, indio_dev->active_scan_mask, for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->masklength) { indio_dev->masklength) {
...@@ -630,6 +640,18 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) ...@@ -630,6 +640,18 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev)
return ret; return ret;
data[i++] = val; data[i++] = val;
if (INA2XX_SHUNT_VOLTAGE + bit == INA2XX_POWER)
cnvr_need_clear = 0;
}
/* Dummy read on INA219 power register to clear CNVR flag */
if (cnvr_need_clear && chip->config->chip_id == ina219) {
unsigned int val;
ret = regmap_read(chip->regmap, INA2XX_POWER, &val);
if (ret < 0)
return ret;
} }
time_b = iio_get_time_ns(indio_dev); time_b = iio_get_time_ns(indio_dev);
......
/*
* Driver for Linear Technology LTC2471 and LTC2473 voltage monitors
* The LTC2473 is identical to the 2471, but reports a differential signal.
*
* Copyright (C) 2017 Topic Embedded Products
* Author: Mike Looijmans <mike.looijmans@topic.nl>
*
* License: GPLv2
*/
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
enum ltc2471_chips {
ltc2471,
ltc2473,
};
struct ltc2471_data {
struct i2c_client *client;
};
/* Reference voltage is 1.25V */
#define LTC2471_VREF 1250
/* Read two bytes from the I2C bus to obtain the ADC result */
static int ltc2471_get_value(struct i2c_client *client)
{
int ret;
__be16 buf;
ret = i2c_master_recv(client, (char *)&buf, sizeof(buf));
if (ret < 0)
return ret;
if (ret != sizeof(buf))
return -EIO;
/* MSB first */
return be16_to_cpu(buf);
}
static int ltc2471_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long info)
{
struct ltc2471_data *data = iio_priv(indio_dev);
int ret;
switch (info) {
case IIO_CHAN_INFO_RAW:
ret = ltc2471_get_value(data->client);
if (ret < 0)
return ret;
*val = ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
if (chan->differential)
/* Output ranges from -VREF to +VREF */
*val = 2 * LTC2471_VREF;
else
/* Output ranges from 0 to VREF */
*val = LTC2471_VREF;
*val2 = 16; /* 16 data bits */
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_OFFSET:
/* Only differential chip has this property */
*val = -LTC2471_VREF;
return IIO_VAL_INT;
default:
return -EINVAL;
}
}
static const struct iio_chan_spec ltc2471_channel[] = {
{
.type = IIO_VOLTAGE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
},
};
static const struct iio_chan_spec ltc2473_channel[] = {
{
.type = IIO_VOLTAGE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OFFSET),
.differential = 1,
},
};
static const struct iio_info ltc2471_info = {
.read_raw = ltc2471_read_raw,
.driver_module = THIS_MODULE,
};
static int ltc2471_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct iio_dev *indio_dev;
struct ltc2471_data *data;
int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -EOPNOTSUPP;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
data->client = client;
indio_dev->dev.parent = &client->dev;
indio_dev->name = id->name;
indio_dev->info = &ltc2471_info;
indio_dev->modes = INDIO_DIRECT_MODE;
if (id->driver_data == ltc2473)
indio_dev->channels = ltc2473_channel;
else
indio_dev->channels = ltc2471_channel;
indio_dev->num_channels = 1;
/* Trigger once to start conversion and check if chip is there */
ret = ltc2471_get_value(client);
if (ret < 0) {
dev_err(&client->dev, "Cannot read from device.\n");
return ret;
}
return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct i2c_device_id ltc2471_i2c_id[] = {
{ "ltc2471", ltc2471 },
{ "ltc2473", ltc2473 },
{}
};
MODULE_DEVICE_TABLE(i2c, ltc2471_i2c_id);
static struct i2c_driver ltc2471_i2c_driver = {
.driver = {
.name = "ltc2471",
},
.probe = ltc2471_i2c_probe,
.id_table = ltc2471_i2c_id,
};
module_i2c_driver(ltc2471_i2c_driver);
MODULE_DESCRIPTION("LTC2471/LTC2473 ADC driver");
MODULE_AUTHOR("Topic Embedded Products");
MODULE_LICENSE("GPL v2");
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/driver.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
...@@ -127,13 +128,14 @@ static int ltc2497_read_raw(struct iio_dev *indio_dev, ...@@ -127,13 +128,14 @@ static int ltc2497_read_raw(struct iio_dev *indio_dev,
} }
} }
#define LTC2497_CHAN(_chan, _addr) { \ #define LTC2497_CHAN(_chan, _addr, _ds_name) { \
.type = IIO_VOLTAGE, \ .type = IIO_VOLTAGE, \
.indexed = 1, \ .indexed = 1, \
.channel = (_chan), \ .channel = (_chan), \
.address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \ .address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.datasheet_name = (_ds_name), \
} }
#define LTC2497_CHAN_DIFF(_chan, _addr) { \ #define LTC2497_CHAN_DIFF(_chan, _addr) { \
...@@ -148,22 +150,22 @@ static int ltc2497_read_raw(struct iio_dev *indio_dev, ...@@ -148,22 +150,22 @@ static int ltc2497_read_raw(struct iio_dev *indio_dev,
} }
static const struct iio_chan_spec ltc2497_channel[] = { static const struct iio_chan_spec ltc2497_channel[] = {
LTC2497_CHAN(0, LTC2497_SGL), LTC2497_CHAN(0, LTC2497_SGL, "CH0"),
LTC2497_CHAN(1, LTC2497_SGL), LTC2497_CHAN(1, LTC2497_SGL, "CH1"),
LTC2497_CHAN(2, LTC2497_SGL), LTC2497_CHAN(2, LTC2497_SGL, "CH2"),
LTC2497_CHAN(3, LTC2497_SGL), LTC2497_CHAN(3, LTC2497_SGL, "CH3"),
LTC2497_CHAN(4, LTC2497_SGL), LTC2497_CHAN(4, LTC2497_SGL, "CH4"),
LTC2497_CHAN(5, LTC2497_SGL), LTC2497_CHAN(5, LTC2497_SGL, "CH5"),
LTC2497_CHAN(6, LTC2497_SGL), LTC2497_CHAN(6, LTC2497_SGL, "CH6"),
LTC2497_CHAN(7, LTC2497_SGL), LTC2497_CHAN(7, LTC2497_SGL, "CH7"),
LTC2497_CHAN(8, LTC2497_SGL), LTC2497_CHAN(8, LTC2497_SGL, "CH8"),
LTC2497_CHAN(9, LTC2497_SGL), LTC2497_CHAN(9, LTC2497_SGL, "CH9"),
LTC2497_CHAN(10, LTC2497_SGL), LTC2497_CHAN(10, LTC2497_SGL, "CH10"),
LTC2497_CHAN(11, LTC2497_SGL), LTC2497_CHAN(11, LTC2497_SGL, "CH11"),
LTC2497_CHAN(12, LTC2497_SGL), LTC2497_CHAN(12, LTC2497_SGL, "CH12"),
LTC2497_CHAN(13, LTC2497_SGL), LTC2497_CHAN(13, LTC2497_SGL, "CH13"),
LTC2497_CHAN(14, LTC2497_SGL), LTC2497_CHAN(14, LTC2497_SGL, "CH14"),
LTC2497_CHAN(15, LTC2497_SGL), LTC2497_CHAN(15, LTC2497_SGL, "CH15"),
LTC2497_CHAN_DIFF(0, LTC2497_DIFF), LTC2497_CHAN_DIFF(0, LTC2497_DIFF),
LTC2497_CHAN_DIFF(1, LTC2497_DIFF), LTC2497_CHAN_DIFF(1, LTC2497_DIFF),
LTC2497_CHAN_DIFF(2, LTC2497_DIFF), LTC2497_CHAN_DIFF(2, LTC2497_DIFF),
...@@ -192,6 +194,7 @@ static int ltc2497_probe(struct i2c_client *client, ...@@ -192,6 +194,7 @@ static int ltc2497_probe(struct i2c_client *client,
{ {
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct ltc2497_st *st; struct ltc2497_st *st;
struct iio_map *plat_data;
int ret; int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
...@@ -221,19 +224,31 @@ static int ltc2497_probe(struct i2c_client *client, ...@@ -221,19 +224,31 @@ static int ltc2497_probe(struct i2c_client *client,
if (ret < 0) if (ret < 0)
return ret; return ret;
if (client->dev.platform_data) {
plat_data = ((struct iio_map *)client->dev.platform_data);
ret = iio_map_array_register(indio_dev, plat_data);
if (ret) {
dev_err(&indio_dev->dev, "iio map err: %d\n", ret);
goto err_regulator_disable;
}
}
ret = i2c_smbus_write_byte(st->client, LTC2497_CONFIG_DEFAULT); ret = i2c_smbus_write_byte(st->client, LTC2497_CONFIG_DEFAULT);
if (ret < 0) if (ret < 0)
goto err_regulator_disable; goto err_array_unregister;
st->addr_prev = LTC2497_CONFIG_DEFAULT; st->addr_prev = LTC2497_CONFIG_DEFAULT;
st->time_prev = ktime_get(); st->time_prev = ktime_get();
ret = iio_device_register(indio_dev); ret = iio_device_register(indio_dev);
if (ret < 0) if (ret < 0)
goto err_regulator_disable; goto err_array_unregister;
return 0; return 0;
err_array_unregister:
iio_map_array_unregister(indio_dev);
err_regulator_disable: err_regulator_disable:
regulator_disable(st->ref); regulator_disable(st->ref);
...@@ -245,6 +260,7 @@ static int ltc2497_remove(struct i2c_client *client) ...@@ -245,6 +260,7 @@ static int ltc2497_remove(struct i2c_client *client)
struct iio_dev *indio_dev = i2c_get_clientdata(client); struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct ltc2497_st *st = iio_priv(indio_dev); struct ltc2497_st *st = iio_priv(indio_dev);
iio_map_array_unregister(indio_dev);
iio_device_unregister(indio_dev); iio_device_unregister(indio_dev);
regulator_disable(st->ref); regulator_disable(st->ref);
......
...@@ -549,8 +549,8 @@ static int max9611_probe(struct i2c_client *client, ...@@ -549,8 +549,8 @@ static int max9611_probe(struct i2c_client *client,
ret = of_property_read_u32(of_node, shunt_res_prop, &of_shunt); ret = of_property_read_u32(of_node, shunt_res_prop, &of_shunt);
if (ret) { if (ret) {
dev_err(&client->dev, dev_err(&client->dev,
"Missing %s property for %s node\n", "Missing %s property for %pOF node\n",
shunt_res_prop, of_node->full_name); shunt_res_prop, of_node);
return ret; return ret;
} }
max9611->shunt_resistor_uohm = of_shunt; max9611->shunt_resistor_uohm = of_shunt;
......
...@@ -379,10 +379,12 @@ static int mcp3422_probe(struct i2c_client *client, ...@@ -379,10 +379,12 @@ static int mcp3422_probe(struct i2c_client *client,
/* meaningful default configuration */ /* meaningful default configuration */
config = (MCP3422_CONT_SAMPLING config = (MCP3422_CONT_SAMPLING
| MCP3422_CHANNEL_VALUE(1) | MCP3422_CHANNEL_VALUE(0)
| MCP3422_PGA_VALUE(MCP3422_PGA_1) | MCP3422_PGA_VALUE(MCP3422_PGA_1)
| MCP3422_SAMPLE_RATE_VALUE(MCP3422_SRATE_240)); | MCP3422_SAMPLE_RATE_VALUE(MCP3422_SRATE_240));
mcp3422_update_config(adc, config); err = mcp3422_update_config(adc, config);
if (err < 0)
return err;
err = devm_iio_device_register(&client->dev, indio_dev); err = devm_iio_device_register(&client->dev, indio_dev);
if (err < 0) if (err < 0)
......
...@@ -572,8 +572,8 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev, ...@@ -572,8 +572,8 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev,
struct clk_init_data init; struct clk_init_data init;
const char *clk_parents[1]; const char *clk_parents[1];
init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_div", init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%pOF#adc_div",
of_node_full_name(indio_dev->dev.of_node)); indio_dev->dev.of_node);
init.flags = 0; init.flags = 0;
init.ops = &clk_divider_ops; init.ops = &clk_divider_ops;
clk_parents[0] = __clk_get_name(priv->clkin); clk_parents[0] = __clk_get_name(priv->clkin);
...@@ -591,8 +591,8 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev, ...@@ -591,8 +591,8 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev,
if (WARN_ON(IS_ERR(priv->adc_div_clk))) if (WARN_ON(IS_ERR(priv->adc_div_clk)))
return PTR_ERR(priv->adc_div_clk); return PTR_ERR(priv->adc_div_clk);
init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_en", init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%pOF#adc_en",
of_node_full_name(indio_dev->dev.of_node)); indio_dev->dev.of_node);
init.flags = CLK_SET_RATE_PARENT; init.flags = CLK_SET_RATE_PARENT;
init.ops = &clk_gate_ops; init.ops = &clk_gate_ops;
clk_parents[0] = __clk_get_name(priv->adc_div_clk); clk_parents[0] = __clk_get_name(priv->adc_div_clk);
...@@ -915,6 +915,11 @@ static int meson_sar_adc_probe(struct platform_device *pdev) ...@@ -915,6 +915,11 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
init_completion(&priv->done); init_completion(&priv->done);
match = of_match_device(meson_sar_adc_of_match, &pdev->dev); match = of_match_device(meson_sar_adc_of_match, &pdev->dev);
if (!match) {
dev_err(&pdev->dev, "failed to match device\n");
return -ENODEV;
}
priv->data = match->data; priv->data = match->data;
indio_dev->name = priv->data->name; indio_dev->name = priv->data->name;
......
...@@ -184,6 +184,37 @@ static const struct iio_info mt6577_auxadc_info = { ...@@ -184,6 +184,37 @@ static const struct iio_info mt6577_auxadc_info = {
.read_raw = &mt6577_auxadc_read_raw, .read_raw = &mt6577_auxadc_read_raw,
}; };
static int __maybe_unused mt6577_auxadc_resume(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
int ret;
ret = clk_prepare_enable(adc_dev->adc_clk);
if (ret) {
pr_err("failed to enable auxadc clock\n");
return ret;
}
mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
MT6577_AUXADC_PDN_EN, 0);
mdelay(MT6577_AUXADC_POWER_READY_MS);
return 0;
}
static int __maybe_unused mt6577_auxadc_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
0, MT6577_AUXADC_PDN_EN);
clk_disable_unprepare(adc_dev->adc_clk);
return 0;
}
static int mt6577_auxadc_probe(struct platform_device *pdev) static int mt6577_auxadc_probe(struct platform_device *pdev)
{ {
struct mt6577_auxadc_device *adc_dev; struct mt6577_auxadc_device *adc_dev;
...@@ -269,8 +300,13 @@ static int mt6577_auxadc_remove(struct platform_device *pdev) ...@@ -269,8 +300,13 @@ static int mt6577_auxadc_remove(struct platform_device *pdev)
return 0; return 0;
} }
static SIMPLE_DEV_PM_OPS(mt6577_auxadc_pm_ops,
mt6577_auxadc_suspend,
mt6577_auxadc_resume);
static const struct of_device_id mt6577_auxadc_of_match[] = { static const struct of_device_id mt6577_auxadc_of_match[] = {
{ .compatible = "mediatek,mt2701-auxadc", }, { .compatible = "mediatek,mt2701-auxadc", },
{ .compatible = "mediatek,mt7622-auxadc", },
{ .compatible = "mediatek,mt8173-auxadc", }, { .compatible = "mediatek,mt8173-auxadc", },
{ } { }
}; };
...@@ -280,6 +316,7 @@ static struct platform_driver mt6577_auxadc_driver = { ...@@ -280,6 +316,7 @@ static struct platform_driver mt6577_auxadc_driver = {
.driver = { .driver = {
.name = "mt6577-auxadc", .name = "mt6577-auxadc",
.of_match_table = mt6577_auxadc_of_match, .of_match_table = mt6577_auxadc_of_match,
.pm = &mt6577_auxadc_pm_ops,
}, },
.probe = mt6577_auxadc_probe, .probe = mt6577_auxadc_probe,
.remove = mt6577_auxadc_remove, .remove = mt6577_auxadc_remove,
......
...@@ -224,6 +224,11 @@ static int rockchip_saradc_probe(struct platform_device *pdev) ...@@ -224,6 +224,11 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
info = iio_priv(indio_dev); info = iio_priv(indio_dev);
match = of_match_device(rockchip_saradc_match, &pdev->dev); match = of_match_device(rockchip_saradc_match, &pdev->dev);
if (!match) {
dev_err(&pdev->dev, "failed to match device\n");
return -ENODEV;
}
info->data = match->data; info->data = match->data;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -235,7 +240,8 @@ static int rockchip_saradc_probe(struct platform_device *pdev) ...@@ -235,7 +240,8 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
* The reset should be an optional property, as it should work * The reset should be an optional property, as it should work
* with old devicetrees as well * with old devicetrees as well
*/ */
info->reset = devm_reset_control_get(&pdev->dev, "saradc-apb"); info->reset = devm_reset_control_get_exclusive(&pdev->dev,
"saradc-apb");
if (IS_ERR(info->reset)) { if (IS_ERR(info->reset)) {
ret = PTR_ERR(info->reset); ret = PTR_ERR(info->reset);
if (ret != -ENOENT) if (ret != -ENOENT)
......
...@@ -172,7 +172,7 @@ struct stm32h7_adc_ck_spec { ...@@ -172,7 +172,7 @@ struct stm32h7_adc_ck_spec {
int div; int div;
}; };
const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = { static const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = {
/* 00: CK_ADC[1..3]: Asynchronous clock modes */ /* 00: CK_ADC[1..3]: Asynchronous clock modes */
{ 0, 0, 1 }, { 0, 0, 1 },
{ 0, 1, 2 }, { 0, 1, 2 },
......
...@@ -83,6 +83,8 @@ ...@@ -83,6 +83,8 @@
#define STM32H7_ADC_IER 0x04 #define STM32H7_ADC_IER 0x04
#define STM32H7_ADC_CR 0x08 #define STM32H7_ADC_CR 0x08
#define STM32H7_ADC_CFGR 0x0C #define STM32H7_ADC_CFGR 0x0C
#define STM32H7_ADC_SMPR1 0x14
#define STM32H7_ADC_SMPR2 0x18
#define STM32H7_ADC_PCSEL 0x1C #define STM32H7_ADC_PCSEL 0x1C
#define STM32H7_ADC_SQR1 0x30 #define STM32H7_ADC_SQR1 0x30
#define STM32H7_ADC_SQR2 0x34 #define STM32H7_ADC_SQR2 0x34
...@@ -151,6 +153,7 @@ enum stm32h7_adc_dmngt { ...@@ -151,6 +153,7 @@ enum stm32h7_adc_dmngt {
#define STM32H7_BOOST_CLKRATE 20000000UL #define STM32H7_BOOST_CLKRATE 20000000UL
#define STM32_ADC_MAX_SQ 16 /* SQ1..SQ16 */ #define STM32_ADC_MAX_SQ 16 /* SQ1..SQ16 */
#define STM32_ADC_MAX_SMP 7 /* SMPx range is [0..7] */
#define STM32_ADC_TIMEOUT_US 100000 #define STM32_ADC_TIMEOUT_US 100000
#define STM32_ADC_TIMEOUT (msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000)) #define STM32_ADC_TIMEOUT (msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000))
...@@ -227,6 +230,8 @@ struct stm32_adc_regs { ...@@ -227,6 +230,8 @@ struct stm32_adc_regs {
* @exten: trigger control register & bitfield * @exten: trigger control register & bitfield
* @extsel: trigger selection register & bitfield * @extsel: trigger selection register & bitfield
* @res: resolution selection register & bitfield * @res: resolution selection register & bitfield
* @smpr: smpr1 & smpr2 registers offset array
* @smp_bits: smpr1 & smpr2 index and bitfields
*/ */
struct stm32_adc_regspec { struct stm32_adc_regspec {
const u32 dr; const u32 dr;
...@@ -236,6 +241,8 @@ struct stm32_adc_regspec { ...@@ -236,6 +241,8 @@ struct stm32_adc_regspec {
const struct stm32_adc_regs exten; const struct stm32_adc_regs exten;
const struct stm32_adc_regs extsel; const struct stm32_adc_regs extsel;
const struct stm32_adc_regs res; const struct stm32_adc_regs res;
const u32 smpr[2];
const struct stm32_adc_regs *smp_bits;
}; };
struct stm32_adc; struct stm32_adc;
...@@ -251,6 +258,7 @@ struct stm32_adc; ...@@ -251,6 +258,7 @@ struct stm32_adc;
* @start_conv: routine to start conversions * @start_conv: routine to start conversions
* @stop_conv: routine to stop conversions * @stop_conv: routine to stop conversions
* @unprepare: optional unprepare routine (disable, power-down) * @unprepare: optional unprepare routine (disable, power-down)
* @smp_cycles: programmable sampling time (ADC clock cycles)
*/ */
struct stm32_adc_cfg { struct stm32_adc_cfg {
const struct stm32_adc_regspec *regs; const struct stm32_adc_regspec *regs;
...@@ -262,6 +270,7 @@ struct stm32_adc_cfg { ...@@ -262,6 +270,7 @@ struct stm32_adc_cfg {
void (*start_conv)(struct stm32_adc *, bool dma); void (*start_conv)(struct stm32_adc *, bool dma);
void (*stop_conv)(struct stm32_adc *); void (*stop_conv)(struct stm32_adc *);
void (*unprepare)(struct stm32_adc *); void (*unprepare)(struct stm32_adc *);
const unsigned int *smp_cycles;
}; };
/** /**
...@@ -283,6 +292,7 @@ struct stm32_adc_cfg { ...@@ -283,6 +292,7 @@ struct stm32_adc_cfg {
* @rx_dma_buf: dma rx buffer bus address * @rx_dma_buf: dma rx buffer bus address
* @rx_buf_sz: dma rx buffer size * @rx_buf_sz: dma rx buffer size
* @pcsel bitmask to preselect channels on some devices * @pcsel bitmask to preselect channels on some devices
* @smpr_val: sampling time settings (e.g. smpr1 / smpr2)
* @cal: optional calibration data on some devices * @cal: optional calibration data on some devices
*/ */
struct stm32_adc { struct stm32_adc {
...@@ -303,6 +313,7 @@ struct stm32_adc { ...@@ -303,6 +313,7 @@ struct stm32_adc {
dma_addr_t rx_dma_buf; dma_addr_t rx_dma_buf;
unsigned int rx_buf_sz; unsigned int rx_buf_sz;
u32 pcsel; u32 pcsel;
u32 smpr_val[2];
struct stm32_adc_calib cal; struct stm32_adc_calib cal;
}; };
...@@ -431,6 +442,39 @@ static struct stm32_adc_trig_info stm32f4_adc_trigs[] = { ...@@ -431,6 +442,39 @@ static struct stm32_adc_trig_info stm32f4_adc_trigs[] = {
{}, /* sentinel */ {}, /* sentinel */
}; };
/**
* stm32f4_smp_bits[] - describe sampling time register index & bit fields
* Sorted so it can be indexed by channel number.
*/
static const struct stm32_adc_regs stm32f4_smp_bits[] = {
/* STM32F4_ADC_SMPR2: smpr[] index, mask, shift for SMP0 to SMP9 */
{ 1, GENMASK(2, 0), 0 },
{ 1, GENMASK(5, 3), 3 },
{ 1, GENMASK(8, 6), 6 },
{ 1, GENMASK(11, 9), 9 },
{ 1, GENMASK(14, 12), 12 },
{ 1, GENMASK(17, 15), 15 },
{ 1, GENMASK(20, 18), 18 },
{ 1, GENMASK(23, 21), 21 },
{ 1, GENMASK(26, 24), 24 },
{ 1, GENMASK(29, 27), 27 },
/* STM32F4_ADC_SMPR1, smpr[] index, mask, shift for SMP10 to SMP18 */
{ 0, GENMASK(2, 0), 0 },
{ 0, GENMASK(5, 3), 3 },
{ 0, GENMASK(8, 6), 6 },
{ 0, GENMASK(11, 9), 9 },
{ 0, GENMASK(14, 12), 12 },
{ 0, GENMASK(17, 15), 15 },
{ 0, GENMASK(20, 18), 18 },
{ 0, GENMASK(23, 21), 21 },
{ 0, GENMASK(26, 24), 24 },
};
/* STM32F4 programmable sampling time (ADC clock cycles) */
static const unsigned int stm32f4_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = {
3, 15, 28, 56, 84, 112, 144, 480,
};
static const struct stm32_adc_regspec stm32f4_adc_regspec = { static const struct stm32_adc_regspec stm32f4_adc_regspec = {
.dr = STM32F4_ADC_DR, .dr = STM32F4_ADC_DR,
.ier_eoc = { STM32F4_ADC_CR1, STM32F4_EOCIE }, .ier_eoc = { STM32F4_ADC_CR1, STM32F4_EOCIE },
...@@ -440,6 +484,8 @@ static const struct stm32_adc_regspec stm32f4_adc_regspec = { ...@@ -440,6 +484,8 @@ static const struct stm32_adc_regspec stm32f4_adc_regspec = {
.extsel = { STM32F4_ADC_CR2, STM32F4_EXTSEL_MASK, .extsel = { STM32F4_ADC_CR2, STM32F4_EXTSEL_MASK,
STM32F4_EXTSEL_SHIFT }, STM32F4_EXTSEL_SHIFT },
.res = { STM32F4_ADC_CR1, STM32F4_RES_MASK, STM32F4_RES_SHIFT }, .res = { STM32F4_ADC_CR1, STM32F4_RES_MASK, STM32F4_RES_SHIFT },
.smpr = { STM32F4_ADC_SMPR1, STM32F4_ADC_SMPR2 },
.smp_bits = stm32f4_smp_bits,
}; };
static const struct stm32_adc_regs stm32h7_sq[STM32_ADC_MAX_SQ + 1] = { static const struct stm32_adc_regs stm32h7_sq[STM32_ADC_MAX_SQ + 1] = {
...@@ -483,6 +529,40 @@ static struct stm32_adc_trig_info stm32h7_adc_trigs[] = { ...@@ -483,6 +529,40 @@ static struct stm32_adc_trig_info stm32h7_adc_trigs[] = {
{}, {},
}; };
/**
* stm32h7_smp_bits - describe sampling time register index & bit fields
* Sorted so it can be indexed by channel number.
*/
static const struct stm32_adc_regs stm32h7_smp_bits[] = {
/* STM32H7_ADC_SMPR1, smpr[] index, mask, shift for SMP0 to SMP9 */
{ 0, GENMASK(2, 0), 0 },
{ 0, GENMASK(5, 3), 3 },
{ 0, GENMASK(8, 6), 6 },
{ 0, GENMASK(11, 9), 9 },
{ 0, GENMASK(14, 12), 12 },
{ 0, GENMASK(17, 15), 15 },
{ 0, GENMASK(20, 18), 18 },
{ 0, GENMASK(23, 21), 21 },
{ 0, GENMASK(26, 24), 24 },
{ 0, GENMASK(29, 27), 27 },
/* STM32H7_ADC_SMPR2, smpr[] index, mask, shift for SMP10 to SMP19 */
{ 1, GENMASK(2, 0), 0 },
{ 1, GENMASK(5, 3), 3 },
{ 1, GENMASK(8, 6), 6 },
{ 1, GENMASK(11, 9), 9 },
{ 1, GENMASK(14, 12), 12 },
{ 1, GENMASK(17, 15), 15 },
{ 1, GENMASK(20, 18), 18 },
{ 1, GENMASK(23, 21), 21 },
{ 1, GENMASK(26, 24), 24 },
{ 1, GENMASK(29, 27), 27 },
};
/* STM32H7 programmable sampling time (ADC clock cycles, rounded down) */
static const unsigned int stm32h7_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = {
1, 2, 8, 16, 32, 64, 387, 810,
};
static const struct stm32_adc_regspec stm32h7_adc_regspec = { static const struct stm32_adc_regspec stm32h7_adc_regspec = {
.dr = STM32H7_ADC_DR, .dr = STM32H7_ADC_DR,
.ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE }, .ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE },
...@@ -492,6 +572,8 @@ static const struct stm32_adc_regspec stm32h7_adc_regspec = { ...@@ -492,6 +572,8 @@ static const struct stm32_adc_regspec stm32h7_adc_regspec = {
.extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK, .extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK,
STM32H7_EXTSEL_SHIFT }, STM32H7_EXTSEL_SHIFT },
.res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT }, .res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT },
.smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 },
.smp_bits = stm32h7_smp_bits,
}; };
/** /**
...@@ -933,6 +1015,7 @@ static void stm32h7_adc_unprepare(struct stm32_adc *adc) ...@@ -933,6 +1015,7 @@ static void stm32h7_adc_unprepare(struct stm32_adc *adc)
* @scan_mask: channels to be converted * @scan_mask: channels to be converted
* *
* Conversion sequence : * Conversion sequence :
* Apply sampling time settings for all channels.
* Configure ADC scan sequence based on selected channels in scan_mask. * Configure ADC scan sequence based on selected channels in scan_mask.
* Add channels to SQR registers, from scan_mask LSB to MSB, then * Add channels to SQR registers, from scan_mask LSB to MSB, then
* program sequence len. * program sequence len.
...@@ -946,6 +1029,10 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev, ...@@ -946,6 +1029,10 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev,
u32 val, bit; u32 val, bit;
int i = 0; int i = 0;
/* Apply sampling time settings */
stm32_adc_writel(adc, adc->cfg->regs->smpr[0], adc->smpr_val[0]);
stm32_adc_writel(adc, adc->cfg->regs->smpr[1], adc->smpr_val[1]);
for_each_set_bit(bit, scan_mask, indio_dev->masklength) { for_each_set_bit(bit, scan_mask, indio_dev->masklength) {
chan = indio_dev->channels + bit; chan = indio_dev->channels + bit;
/* /*
...@@ -1079,6 +1166,7 @@ static const struct iio_enum stm32_adc_trig_pol = { ...@@ -1079,6 +1166,7 @@ static const struct iio_enum stm32_adc_trig_pol = {
* @res: conversion result * @res: conversion result
* *
* The function performs a single conversion on a given channel: * The function performs a single conversion on a given channel:
* - Apply sampling time settings
* - Program sequencer with one channel (e.g. in SQ1 with len = 1) * - Program sequencer with one channel (e.g. in SQ1 with len = 1)
* - Use SW trigger * - Use SW trigger
* - Start conversion, then wait for interrupt completion. * - Start conversion, then wait for interrupt completion.
...@@ -1103,6 +1191,10 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev, ...@@ -1103,6 +1191,10 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev,
return ret; return ret;
} }
/* Apply sampling time settings */
stm32_adc_writel(adc, regs->smpr[0], adc->smpr_val[0]);
stm32_adc_writel(adc, regs->smpr[1], adc->smpr_val[1]);
/* Program chan number in regular sequence (SQ1) */ /* Program chan number in regular sequence (SQ1) */
val = stm32_adc_readl(adc, regs->sqr[1].reg); val = stm32_adc_readl(adc, regs->sqr[1].reg);
val &= ~regs->sqr[1].mask; val &= ~regs->sqr[1].mask;
...@@ -1507,10 +1599,28 @@ static int stm32_adc_of_get_resolution(struct iio_dev *indio_dev) ...@@ -1507,10 +1599,28 @@ static int stm32_adc_of_get_resolution(struct iio_dev *indio_dev)
return 0; return 0;
} }
static void stm32_adc_smpr_init(struct stm32_adc *adc, int channel, u32 smp_ns)
{
const struct stm32_adc_regs *smpr = &adc->cfg->regs->smp_bits[channel];
u32 period_ns, shift = smpr->shift, mask = smpr->mask;
unsigned int smp, r = smpr->reg;
/* Determine sampling time (ADC clock cycles) */
period_ns = NSEC_PER_SEC / adc->common->rate;
for (smp = 0; smp <= STM32_ADC_MAX_SMP; smp++)
if ((period_ns * adc->cfg->smp_cycles[smp]) >= smp_ns)
break;
if (smp > STM32_ADC_MAX_SMP)
smp = STM32_ADC_MAX_SMP;
/* pre-build sampling time registers (e.g. smpr1, smpr2) */
adc->smpr_val[r] = (adc->smpr_val[r] & ~mask) | (smp << shift);
}
static void stm32_adc_chan_init_one(struct iio_dev *indio_dev, static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
struct iio_chan_spec *chan, struct iio_chan_spec *chan,
const struct stm32_adc_chan_spec *channel, const struct stm32_adc_chan_spec *channel,
int scan_index) int scan_index, u32 smp)
{ {
struct stm32_adc *adc = iio_priv(indio_dev); struct stm32_adc *adc = iio_priv(indio_dev);
...@@ -1526,6 +1636,9 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev, ...@@ -1526,6 +1636,9 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
chan->scan_type.storagebits = 16; chan->scan_type.storagebits = 16;
chan->ext_info = stm32_adc_ext_info; chan->ext_info = stm32_adc_ext_info;
/* Prepare sampling time settings */
stm32_adc_smpr_init(adc, chan->channel, smp);
/* pre-build selected channels mask */ /* pre-build selected channels mask */
adc->pcsel |= BIT(chan->channel); adc->pcsel |= BIT(chan->channel);
} }
...@@ -1538,8 +1651,8 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev) ...@@ -1538,8 +1651,8 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
struct property *prop; struct property *prop;
const __be32 *cur; const __be32 *cur;
struct iio_chan_spec *channels; struct iio_chan_spec *channels;
int scan_index = 0, num_channels; int scan_index = 0, num_channels, ret;
u32 val; u32 val, smp = 0;
num_channels = of_property_count_u32_elems(node, "st,adc-channels"); num_channels = of_property_count_u32_elems(node, "st,adc-channels");
if (num_channels < 0 || if (num_channels < 0 ||
...@@ -1548,6 +1661,13 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev) ...@@ -1548,6 +1661,13 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
return num_channels < 0 ? num_channels : -EINVAL; return num_channels < 0 ? num_channels : -EINVAL;
} }
/* Optional sample time is provided either for each, or all channels */
ret = of_property_count_u32_elems(node, "st,min-sample-time-nsecs");
if (ret > 1 && ret != num_channels) {
dev_err(&indio_dev->dev, "Invalid st,min-sample-time-nsecs\n");
return -EINVAL;
}
channels = devm_kcalloc(&indio_dev->dev, num_channels, channels = devm_kcalloc(&indio_dev->dev, num_channels,
sizeof(struct iio_chan_spec), GFP_KERNEL); sizeof(struct iio_chan_spec), GFP_KERNEL);
if (!channels) if (!channels)
...@@ -1558,9 +1678,19 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev) ...@@ -1558,9 +1678,19 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
dev_err(&indio_dev->dev, "Invalid channel %d\n", val); dev_err(&indio_dev->dev, "Invalid channel %d\n", val);
return -EINVAL; return -EINVAL;
} }
/*
* Using of_property_read_u32_index(), smp value will only be
* modified if valid u32 value can be decoded. This allows to
* get either no value, 1 shared value for all indexes, or one
* value per channel.
*/
of_property_read_u32_index(node, "st,min-sample-time-nsecs",
scan_index, &smp);
stm32_adc_chan_init_one(indio_dev, &channels[scan_index], stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
&adc_info->channels[val], &adc_info->channels[val],
scan_index); scan_index, smp);
scan_index++; scan_index++;
} }
...@@ -1755,6 +1885,7 @@ static const struct stm32_adc_cfg stm32f4_adc_cfg = { ...@@ -1755,6 +1885,7 @@ static const struct stm32_adc_cfg stm32f4_adc_cfg = {
.clk_required = true, .clk_required = true,
.start_conv = stm32f4_adc_start_conv, .start_conv = stm32f4_adc_start_conv,
.stop_conv = stm32f4_adc_stop_conv, .stop_conv = stm32f4_adc_stop_conv,
.smp_cycles = stm32f4_adc_smp_cycles,
}; };
static const struct stm32_adc_cfg stm32h7_adc_cfg = { static const struct stm32_adc_cfg stm32h7_adc_cfg = {
...@@ -1766,6 +1897,7 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = { ...@@ -1766,6 +1897,7 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = {
.stop_conv = stm32h7_adc_stop_conv, .stop_conv = stm32h7_adc_stop_conv,
.prepare = stm32h7_adc_prepare, .prepare = stm32h7_adc_prepare,
.unprepare = stm32h7_adc_unprepare, .unprepare = stm32h7_adc_unprepare,
.smp_cycles = stm32h7_adc_smp_cycles,
}; };
static const struct of_device_id stm32_adc_of_match[] = { static const struct of_device_id stm32_adc_of_match[] = {
......
此差异已折叠。
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include <linux/acpi.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/err.h> #include <linux/err.h>
...@@ -37,6 +38,12 @@ ...@@ -37,6 +38,12 @@
#include <linux/iio/trigger_consumer.h> #include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h> #include <linux/iio/triggered_buffer.h>
/*
* In case of ACPI, we use the 5000 mV as default for the reference pin.
* Device tree users encode that via the vref-supply regulator.
*/
#define TI_ADS7950_VA_MV_ACPI_DEFAULT 5000
#define TI_ADS7950_CR_MANUAL BIT(12) #define TI_ADS7950_CR_MANUAL BIT(12)
#define TI_ADS7950_CR_WRITE BIT(11) #define TI_ADS7950_CR_WRITE BIT(11)
#define TI_ADS7950_CR_CHAN(ch) ((ch) << 7) #define TI_ADS7950_CR_CHAN(ch) ((ch) << 7)
...@@ -58,6 +65,7 @@ struct ti_ads7950_state { ...@@ -58,6 +65,7 @@ struct ti_ads7950_state {
struct spi_message scan_single_msg; struct spi_message scan_single_msg;
struct regulator *reg; struct regulator *reg;
unsigned int vref_mv;
unsigned int settings; unsigned int settings;
...@@ -305,11 +313,15 @@ static int ti_ads7950_get_range(struct ti_ads7950_state *st) ...@@ -305,11 +313,15 @@ static int ti_ads7950_get_range(struct ti_ads7950_state *st)
{ {
int vref; int vref;
vref = regulator_get_voltage(st->reg); if (st->vref_mv) {
if (vref < 0) vref = st->vref_mv;
return vref; } else {
vref = regulator_get_voltage(st->reg);
if (vref < 0)
return vref;
vref /= 1000; vref /= 1000;
}
if (st->settings & TI_ADS7950_CR_RANGE_5V) if (st->settings & TI_ADS7950_CR_RANGE_5V)
vref *= 2; vref *= 2;
...@@ -411,6 +423,10 @@ static int ti_ads7950_probe(struct spi_device *spi) ...@@ -411,6 +423,10 @@ static int ti_ads7950_probe(struct spi_device *spi)
spi_message_init_with_transfers(&st->scan_single_msg, spi_message_init_with_transfers(&st->scan_single_msg,
st->scan_single_xfer, 3); st->scan_single_xfer, 3);
/* Use hard coded value for reference voltage in ACPI case */
if (ACPI_COMPANION(&spi->dev))
st->vref_mv = TI_ADS7950_VA_MV_ACPI_DEFAULT;
st->reg = devm_regulator_get(&spi->dev, "vref"); st->reg = devm_regulator_get(&spi->dev, "vref");
if (IS_ERR(st->reg)) { if (IS_ERR(st->reg)) {
dev_err(&spi->dev, "Failed get get regulator \"vref\"\n"); dev_err(&spi->dev, "Failed get get regulator \"vref\"\n");
...@@ -475,9 +491,27 @@ static const struct spi_device_id ti_ads7950_id[] = { ...@@ -475,9 +491,27 @@ static const struct spi_device_id ti_ads7950_id[] = {
}; };
MODULE_DEVICE_TABLE(spi, ti_ads7950_id); MODULE_DEVICE_TABLE(spi, ti_ads7950_id);
static const struct of_device_id ads7950_of_table[] = {
{ .compatible = "ti,ads7950", .data = &ti_ads7950_chip_info[TI_ADS7950] },
{ .compatible = "ti,ads7951", .data = &ti_ads7950_chip_info[TI_ADS7951] },
{ .compatible = "ti,ads7952", .data = &ti_ads7950_chip_info[TI_ADS7952] },
{ .compatible = "ti,ads7953", .data = &ti_ads7950_chip_info[TI_ADS7953] },
{ .compatible = "ti,ads7954", .data = &ti_ads7950_chip_info[TI_ADS7954] },
{ .compatible = "ti,ads7955", .data = &ti_ads7950_chip_info[TI_ADS7955] },
{ .compatible = "ti,ads7956", .data = &ti_ads7950_chip_info[TI_ADS7956] },
{ .compatible = "ti,ads7957", .data = &ti_ads7950_chip_info[TI_ADS7957] },
{ .compatible = "ti,ads7958", .data = &ti_ads7950_chip_info[TI_ADS7958] },
{ .compatible = "ti,ads7959", .data = &ti_ads7950_chip_info[TI_ADS7959] },
{ .compatible = "ti,ads7960", .data = &ti_ads7950_chip_info[TI_ADS7960] },
{ .compatible = "ti,ads7961", .data = &ti_ads7950_chip_info[TI_ADS7961] },
{ },
};
MODULE_DEVICE_TABLE(of, ads7950_of_table);
static struct spi_driver ti_ads7950_driver = { static struct spi_driver ti_ads7950_driver = {
.driver = { .driver = {
.name = "ads7950", .name = "ads7950",
.of_match_table = ads7950_of_table,
}, },
.probe = ti_ads7950_probe, .probe = ti_ads7950_probe,
.remove = ti_ads7950_remove, .remove = ti_ads7950_remove,
......
...@@ -68,7 +68,7 @@ void xadc_handle_events(struct iio_dev *indio_dev, unsigned long events) ...@@ -68,7 +68,7 @@ void xadc_handle_events(struct iio_dev *indio_dev, unsigned long events)
xadc_handle_event(indio_dev, i); xadc_handle_event(indio_dev, i);
} }
static unsigned xadc_get_threshold_offset(const struct iio_chan_spec *chan, static unsigned int xadc_get_threshold_offset(const struct iio_chan_spec *chan,
enum iio_event_direction dir) enum iio_event_direction dir)
{ {
unsigned int offset; unsigned int offset;
...@@ -90,26 +90,24 @@ static unsigned xadc_get_threshold_offset(const struct iio_chan_spec *chan, ...@@ -90,26 +90,24 @@ static unsigned xadc_get_threshold_offset(const struct iio_chan_spec *chan,
static unsigned int xadc_get_alarm_mask(const struct iio_chan_spec *chan) static unsigned int xadc_get_alarm_mask(const struct iio_chan_spec *chan)
{ {
if (chan->type == IIO_TEMP) { if (chan->type == IIO_TEMP)
return XADC_ALARM_OT_MASK; return XADC_ALARM_OT_MASK;
} else { switch (chan->channel) {
switch (chan->channel) { case 0:
case 0: return XADC_ALARM_VCCINT_MASK;
return XADC_ALARM_VCCINT_MASK; case 1:
case 1: return XADC_ALARM_VCCAUX_MASK;
return XADC_ALARM_VCCAUX_MASK; case 2:
case 2: return XADC_ALARM_VCCBRAM_MASK;
return XADC_ALARM_VCCBRAM_MASK; case 3:
case 3: return XADC_ALARM_VCCPINT_MASK;
return XADC_ALARM_VCCPINT_MASK; case 4:
case 4: return XADC_ALARM_VCCPAUX_MASK;
return XADC_ALARM_VCCPAUX_MASK; case 5:
case 5: return XADC_ALARM_VCCODDR_MASK;
return XADC_ALARM_VCCODDR_MASK; default:
default: /* We will never get here */
/* We will never get here */ return 0;
return 0;
}
} }
} }
......
...@@ -71,13 +71,13 @@ struct xadc { ...@@ -71,13 +71,13 @@ struct xadc {
}; };
struct xadc_ops { struct xadc_ops {
int (*read)(struct xadc *, unsigned int, uint16_t *); int (*read)(struct xadc *xadc, unsigned int reg, uint16_t *val);
int (*write)(struct xadc *, unsigned int, uint16_t); int (*write)(struct xadc *xadc, unsigned int reg, uint16_t val);
int (*setup)(struct platform_device *pdev, struct iio_dev *indio_dev, int (*setup)(struct platform_device *pdev, struct iio_dev *indio_dev,
int irq); int irq);
void (*update_alarm)(struct xadc *, unsigned int); void (*update_alarm)(struct xadc *xadc, unsigned int alarm);
unsigned long (*get_dclk_rate)(struct xadc *); unsigned long (*get_dclk_rate)(struct xadc *xadc);
irqreturn_t (*interrupt_handler)(int, void *); irqreturn_t (*interrupt_handler)(int irq, void *devid);
unsigned int flags; unsigned int flags;
}; };
......
...@@ -21,6 +21,15 @@ config ATLAS_PH_SENSOR ...@@ -21,6 +21,15 @@ config ATLAS_PH_SENSOR
To compile this driver as module, choose M here: the To compile this driver as module, choose M here: the
module will be called atlas-ph-sensor. module will be called atlas-ph-sensor.
config CCS811
tristate "AMS CCS811 VOC sensor"
depends on I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say Y here to build I2C interface support for the AMS
CCS811 VOC (Volatile Organic Compounds) sensor
config IAQCORE config IAQCORE
tristate "AMS iAQ-Core VOC sensors" tristate "AMS iAQ-Core VOC sensors"
depends on I2C depends on I2C
......
...@@ -4,5 +4,6 @@ ...@@ -4,5 +4,6 @@
# When adding new entries keep the list in alphabetical order # When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ATLAS_PH_SENSOR) += atlas-ph-sensor.o obj-$(CONFIG_ATLAS_PH_SENSOR) += atlas-ph-sensor.o
obj-$(CONFIG_CCS811) += ccs811.o
obj-$(CONFIG_IAQCORE) += ams-iaq-core.o obj-$(CONFIG_IAQCORE) += ams-iaq-core.o
obj-$(CONFIG_VZ89X) += vz89x.o obj-$(CONFIG_VZ89X) += vz89x.o
/*
* ccs811.c - Support for AMS CCS811 VOC Sensor
*
* Copyright (C) 2017 Narcisa Vasile <narcisaanamaria12@gmail.com>
*
* Datasheet: ams.com/content/download/951091/2269479/CCS811_DS000459_3-00.pdf
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* IIO driver for AMS CCS811 (I2C address 0x5A/0x5B set by ADDR Low/High)
*
* TODO:
* 1. Make the drive mode selectable form userspace
* 2. Add support for interrupts
* 3. Adjust time to wait for data to be ready based on selected operation mode
* 4. Read error register and put the information in logs
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/module.h>
#define CCS811_STATUS 0x00
#define CCS811_MEAS_MODE 0x01
#define CCS811_ALG_RESULT_DATA 0x02
#define CCS811_RAW_DATA 0x03
#define CCS811_HW_ID 0x20
#define CCS881_HW_ID_VALUE 0x81
#define CCS811_HW_VERSION 0x21
#define CCS811_HW_VERSION_VALUE 0x10
#define CCS811_HW_VERSION_MASK 0xF0
#define CCS811_ERR 0xE0
/* Used to transition from boot to application mode */
#define CCS811_APP_START 0xF4
/* Status register flags */
#define CCS811_STATUS_ERROR BIT(0)
#define CCS811_STATUS_DATA_READY BIT(3)
#define CCS811_STATUS_APP_VALID_MASK BIT(4)
#define CCS811_STATUS_APP_VALID_LOADED BIT(4)
/*
* Value of FW_MODE bit of STATUS register describes the sensor's state:
* 0: Firmware is in boot mode, this allows new firmware to be loaded
* 1: Firmware is in application mode. CCS811 is ready to take ADC measurements
*/
#define CCS811_STATUS_FW_MODE_MASK BIT(7)
#define CCS811_STATUS_FW_MODE_APPLICATION BIT(7)
/* Measurement modes */
#define CCS811_MODE_IDLE 0x00
#define CCS811_MODE_IAQ_1SEC 0x10
#define CCS811_MODE_IAQ_10SEC 0x20
#define CCS811_MODE_IAQ_60SEC 0x30
#define CCS811_MODE_RAW_DATA 0x40
#define CCS811_VOLTAGE_MASK 0x3FF
struct ccs811_reading {
__be16 co2;
__be16 voc;
u8 status;
u8 error;
__be16 resistance;
} __attribute__((__packed__));
struct ccs811_data {
struct i2c_client *client;
struct mutex lock; /* Protect readings */
struct ccs811_reading buffer;
};
static const struct iio_chan_spec ccs811_channels[] = {
{
.type = IIO_CURRENT,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.scan_index = -1,
}, {
.type = IIO_VOLTAGE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.scan_index = -1,
}, {
.type = IIO_CONCENTRATION,
.channel2 = IIO_MOD_CO2,
.modified = 1,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE),
.scan_index = 0,
.scan_type = {
.sign = 'u',
.realbits = 16,
.storagebits = 16,
.endianness = IIO_BE,
},
}, {
.type = IIO_CONCENTRATION,
.channel2 = IIO_MOD_VOC,
.modified = 1,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.scan_index = 1,
.scan_type = {
.sign = 'u',
.realbits = 16,
.storagebits = 16,
.endianness = IIO_BE,
},
},
IIO_CHAN_SOFT_TIMESTAMP(2),
};
/*
* The CCS811 powers-up in boot mode. A setup write to CCS811_APP_START will
* transition the sensor to application mode.
*/
static int ccs811_start_sensor_application(struct i2c_client *client)
{
int ret;
ret = i2c_smbus_read_byte_data(client, CCS811_STATUS);
if (ret < 0)
return ret;
if ((ret & CCS811_STATUS_APP_VALID_MASK) !=
CCS811_STATUS_APP_VALID_LOADED)
return -EIO;
ret = i2c_smbus_write_byte(client, CCS811_APP_START);
if (ret < 0)
return ret;
ret = i2c_smbus_read_byte_data(client, CCS811_STATUS);
if (ret < 0)
return ret;
if ((ret & CCS811_STATUS_FW_MODE_MASK) !=
CCS811_STATUS_FW_MODE_APPLICATION) {
dev_err(&client->dev, "Application failed to start. Sensor is still in boot mode.\n");
return -EIO;
}
return 0;
}
static int ccs811_setup(struct i2c_client *client)
{
int ret;
ret = ccs811_start_sensor_application(client);
if (ret < 0)
return ret;
return i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE,
CCS811_MODE_IAQ_1SEC);
}
static int ccs811_get_measurement(struct ccs811_data *data)
{
int ret, tries = 11;
/* Maximum waiting time: 1s, as measurements are made every second */
while (tries-- > 0) {
ret = i2c_smbus_read_byte_data(data->client, CCS811_STATUS);
if (ret < 0)
return ret;
if ((ret & CCS811_STATUS_DATA_READY) || tries == 0)
break;
msleep(100);
}
if (!(ret & CCS811_STATUS_DATA_READY))
return -EIO;
return i2c_smbus_read_i2c_block_data(data->client,
CCS811_ALG_RESULT_DATA, 8,
(char *)&data->buffer);
}
static int ccs811_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct ccs811_data *data = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&data->lock);
ret = ccs811_get_measurement(data);
if (ret < 0) {
mutex_unlock(&data->lock);
return ret;
}
switch (chan->type) {
case IIO_VOLTAGE:
*val = be16_to_cpu(data->buffer.resistance) &
CCS811_VOLTAGE_MASK;
ret = IIO_VAL_INT;
break;
case IIO_CURRENT:
*val = be16_to_cpu(data->buffer.resistance) >> 10;
ret = IIO_VAL_INT;
break;
case IIO_CONCENTRATION:
switch (chan->channel2) {
case IIO_MOD_CO2:
*val = be16_to_cpu(data->buffer.co2);
ret = IIO_VAL_INT;
break;
case IIO_MOD_VOC:
*val = be16_to_cpu(data->buffer.voc);
ret = IIO_VAL_INT;
break;
default:
ret = -EINVAL;
}
break;
default:
ret = -EINVAL;
}
mutex_unlock(&data->lock);
return ret;
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
*val = 1;
*val2 = 612903;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CURRENT:
*val = 0;
*val2 = 1000;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CONCENTRATION:
switch (chan->channel2) {
case IIO_MOD_CO2:
*val = 0;
*val2 = 12834;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_MOD_VOC:
*val = 0;
*val2 = 84246;
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
default:
return -EINVAL;
}
case IIO_CHAN_INFO_OFFSET:
if (!(chan->type == IIO_CONCENTRATION &&
chan->channel2 == IIO_MOD_CO2))
return -EINVAL;
*val = -400;
return IIO_VAL_INT;
default:
return -EINVAL;
}
}
static const struct iio_info ccs811_info = {
.read_raw = ccs811_read_raw,
.driver_module = THIS_MODULE,
};
static irqreturn_t ccs811_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct ccs811_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
s16 buf[8]; /* s16 eCO2 + s16 TVOC + padding + 8 byte timestamp */
int ret;
ret = i2c_smbus_read_i2c_block_data(client, CCS811_ALG_RESULT_DATA, 4,
(u8 *)&buf);
if (ret != 4) {
dev_err(&client->dev, "cannot read sensor data\n");
goto err;
}
iio_push_to_buffers_with_timestamp(indio_dev, buf,
iio_get_time_ns(indio_dev));
err:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
static int ccs811_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct iio_dev *indio_dev;
struct ccs811_data *data;
int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE
| I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_READ_I2C_BLOCK))
return -EOPNOTSUPP;
/* Check hardware id (should be 0x81 for this family of devices) */
ret = i2c_smbus_read_byte_data(client, CCS811_HW_ID);
if (ret < 0)
return ret;
if (ret != CCS881_HW_ID_VALUE) {
dev_err(&client->dev, "hardware id doesn't match CCS81x\n");
return -ENODEV;
}
ret = i2c_smbus_read_byte_data(client, CCS811_HW_VERSION);
if (ret < 0)
return ret;
if ((ret & CCS811_HW_VERSION_MASK) != CCS811_HW_VERSION_VALUE) {
dev_err(&client->dev, "no CCS811 sensor\n");
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
ret = ccs811_setup(client);
if (ret < 0)
return ret;
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
mutex_init(&data->lock);
indio_dev->dev.parent = &client->dev;
indio_dev->name = id->name;
indio_dev->info = &ccs811_info;
indio_dev->channels = ccs811_channels;
indio_dev->num_channels = ARRAY_SIZE(ccs811_channels);
ret = iio_triggered_buffer_setup(indio_dev, NULL,
ccs811_trigger_handler, NULL);
if (ret < 0) {
dev_err(&client->dev, "triggered buffer setup failed\n");
goto err_poweroff;
}
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "unable to register iio device\n");
goto err_buffer_cleanup;
}
return 0;
err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
err_poweroff:
i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE, CCS811_MODE_IDLE);
return ret;
}
static int ccs811_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
return i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE,
CCS811_MODE_IDLE);
}
static const struct i2c_device_id ccs811_id[] = {
{"ccs811", 0},
{ }
};
MODULE_DEVICE_TABLE(i2c, ccs811_id);
static struct i2c_driver ccs811_driver = {
.driver = {
.name = "ccs811",
},
.probe = ccs811_probe,
.remove = ccs811_remove,
.id_table = ccs811_id,
};
module_i2c_driver(ccs811_driver);
MODULE_AUTHOR("Narcisa Vasile <narcisaanamaria12@gmail.com>");
MODULE_DESCRIPTION("CCS811 volatile organic compounds sensor");
MODULE_LICENSE("GPL v2");
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <linux/iio/common/st_sensors.h> #include <linux/iio/common/st_sensors.h>
...@@ -345,6 +346,36 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, ...@@ -345,6 +346,36 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev,
return pdata; return pdata;
} }
/**
* st_sensors_of_name_probe() - device tree probe for ST sensor name
* @dev: driver model representation of the device.
* @match: the OF match table for the device, containing compatible strings
* but also a .data field with the corresponding internal kernel name
* used by this sensor.
* @name: device name buffer reference.
* @len: device name buffer length.
*
* In effect this function matches a compatible string to an internal kernel
* name for a certain sensor device, so that the rest of the autodetection can
* rely on that name from this point on. I2C/SPI devices will be renamed
* to match the internal kernel convention.
*/
void st_sensors_of_name_probe(struct device *dev,
const struct of_device_id *match,
char *name, int len)
{
const struct of_device_id *of_id;
of_id = of_match_device(match, dev);
if (!of_id || !of_id->data)
return;
/* The name from the OF match takes precedence if present */
strncpy(name, of_id->data, len);
name[len - 1] = '\0';
}
EXPORT_SYMBOL(st_sensors_of_name_probe);
#else #else
static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev,
struct st_sensors_platform_data *defdata) struct st_sensors_platform_data *defdata)
......
...@@ -79,35 +79,6 @@ void st_sensors_i2c_configure(struct iio_dev *indio_dev, ...@@ -79,35 +79,6 @@ void st_sensors_i2c_configure(struct iio_dev *indio_dev,
} }
EXPORT_SYMBOL(st_sensors_i2c_configure); EXPORT_SYMBOL(st_sensors_i2c_configure);
#ifdef CONFIG_OF
/**
* st_sensors_of_i2c_probe() - device tree probe for ST I2C sensors
* @client: the I2C client device for the sensor
* @match: the OF match table for the device, containing compatible strings
* but also a .data field with the corresponding internal kernel name
* used by this sensor.
*
* In effect this function matches a compatible string to an internal kernel
* name for a certain sensor device, so that the rest of the autodetection can
* rely on that name from this point on. I2C client devices will be renamed
* to match the internal kernel convention.
*/
void st_sensors_of_i2c_probe(struct i2c_client *client,
const struct of_device_id *match)
{
const struct of_device_id *of_id;
of_id = of_match_device(match, &client->dev);
if (!of_id)
return;
/* The name from the OF match takes precedence if present */
strncpy(client->name, of_id->data, sizeof(client->name));
client->name[sizeof(client->name) - 1] = '\0';
}
EXPORT_SYMBOL(st_sensors_of_i2c_probe);
#endif
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
int st_sensors_match_acpi_device(struct device *dev) int st_sensors_match_acpi_device(struct device *dev)
{ {
......
...@@ -42,6 +42,14 @@ struct stm32_dac_priv { ...@@ -42,6 +42,14 @@ struct stm32_dac_priv {
struct stm32_dac_common common; struct stm32_dac_common common;
}; };
/**
* struct stm32_dac_cfg - DAC configuration
* @has_hfsel: DAC has high frequency control
*/
struct stm32_dac_cfg {
bool has_hfsel;
};
static struct stm32_dac_priv *to_stm32_dac_priv(struct stm32_dac_common *com) static struct stm32_dac_priv *to_stm32_dac_priv(struct stm32_dac_common *com)
{ {
return container_of(com, struct stm32_dac_priv, common); return container_of(com, struct stm32_dac_priv, common);
...@@ -57,6 +65,7 @@ static const struct regmap_config stm32_dac_regmap_cfg = { ...@@ -57,6 +65,7 @@ static const struct regmap_config stm32_dac_regmap_cfg = {
static int stm32_dac_probe(struct platform_device *pdev) static int stm32_dac_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
const struct stm32_dac_cfg *cfg;
struct stm32_dac_priv *priv; struct stm32_dac_priv *priv;
struct regmap *regmap; struct regmap *regmap;
struct resource *res; struct resource *res;
...@@ -69,6 +78,8 @@ static int stm32_dac_probe(struct platform_device *pdev) ...@@ -69,6 +78,8 @@ static int stm32_dac_probe(struct platform_device *pdev)
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
cfg = (const struct stm32_dac_cfg *)
of_match_device(dev->driver->of_match_table, dev)->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mmio = devm_ioremap_resource(dev, res); mmio = devm_ioremap_resource(dev, res);
...@@ -114,19 +125,23 @@ static int stm32_dac_probe(struct platform_device *pdev) ...@@ -114,19 +125,23 @@ static int stm32_dac_probe(struct platform_device *pdev)
goto err_vref; goto err_vref;
} }
priv->rst = devm_reset_control_get(dev, NULL); priv->rst = devm_reset_control_get_exclusive(dev, NULL);
if (!IS_ERR(priv->rst)) { if (!IS_ERR(priv->rst)) {
reset_control_assert(priv->rst); reset_control_assert(priv->rst);
udelay(2); udelay(2);
reset_control_deassert(priv->rst); reset_control_deassert(priv->rst);
} }
/* When clock speed is higher than 80MHz, set HFSEL */ if (cfg && cfg->has_hfsel) {
priv->common.hfsel = (clk_get_rate(priv->pclk) > 80000000UL); /* When clock speed is higher than 80MHz, set HFSEL */
ret = regmap_update_bits(regmap, STM32_DAC_CR, STM32H7_DAC_CR_HFSEL, priv->common.hfsel = (clk_get_rate(priv->pclk) > 80000000UL);
priv->common.hfsel ? STM32H7_DAC_CR_HFSEL : 0); ret = regmap_update_bits(regmap, STM32_DAC_CR,
if (ret) STM32H7_DAC_CR_HFSEL,
goto err_pclk; priv->common.hfsel ?
STM32H7_DAC_CR_HFSEL : 0);
if (ret)
goto err_pclk;
}
platform_set_drvdata(pdev, &priv->common); platform_set_drvdata(pdev, &priv->common);
...@@ -158,8 +173,17 @@ static int stm32_dac_remove(struct platform_device *pdev) ...@@ -158,8 +173,17 @@ static int stm32_dac_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct stm32_dac_cfg stm32h7_dac_cfg = {
.has_hfsel = true,
};
static const struct of_device_id stm32_dac_of_match[] = { static const struct of_device_id stm32_dac_of_match[] = {
{ .compatible = "st,stm32h7-dac-core", }, {
.compatible = "st,stm32f4-dac-core",
}, {
.compatible = "st,stm32h7-dac-core",
.data = (void *)&stm32h7_dac_cfg,
},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, stm32_dac_of_match); MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
......
...@@ -268,7 +268,7 @@ static int stm32_dac_chan_of_init(struct iio_dev *indio_dev) ...@@ -268,7 +268,7 @@ static int stm32_dac_chan_of_init(struct iio_dev *indio_dev)
break; break;
} }
if (i >= ARRAY_SIZE(stm32_dac_channels)) { if (i >= ARRAY_SIZE(stm32_dac_channels)) {
dev_err(&indio_dev->dev, "Invalid st,dac-channel\n"); dev_err(&indio_dev->dev, "Invalid reg property\n");
return -EINVAL; return -EINVAL;
} }
......
...@@ -1063,11 +1063,6 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq) ...@@ -1063,11 +1063,6 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq)
case IRQF_TRIGGER_RISING: case IRQF_TRIGGER_RISING:
dev_info(&indio_dev->dev, dev_info(&indio_dev->dev,
"pulse interrupts on the rising edge\n"); "pulse interrupts on the rising edge\n");
if (mpu3050->irq_opendrain) {
dev_info(&indio_dev->dev,
"rising edge incompatible with open drain\n");
mpu3050->irq_opendrain = false;
}
break; break;
case IRQF_TRIGGER_FALLING: case IRQF_TRIGGER_FALLING:
mpu3050->irq_actl = true; mpu3050->irq_actl = true;
...@@ -1078,11 +1073,6 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq) ...@@ -1078,11 +1073,6 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq)
mpu3050->irq_latch = true; mpu3050->irq_latch = true;
dev_info(&indio_dev->dev, dev_info(&indio_dev->dev,
"interrupts active high level\n"); "interrupts active high level\n");
if (mpu3050->irq_opendrain) {
dev_info(&indio_dev->dev,
"active high incompatible with open drain\n");
mpu3050->irq_opendrain = false;
}
/* /*
* With level IRQs, we mask the IRQ until it is processed, * With level IRQs, we mask the IRQ until it is processed,
* but with edge IRQs (pulses) we can queue several interrupts * but with edge IRQs (pulses) we can queue several interrupts
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#define LSM330DL_GYRO_DEV_NAME "lsm330dl_gyro" #define LSM330DL_GYRO_DEV_NAME "lsm330dl_gyro"
#define LSM330DLC_GYRO_DEV_NAME "lsm330dlc_gyro" #define LSM330DLC_GYRO_DEV_NAME "lsm330dlc_gyro"
#define L3GD20_GYRO_DEV_NAME "l3gd20" #define L3GD20_GYRO_DEV_NAME "l3gd20"
#define L3GD20H_GYRO_DEV_NAME "l3gd20h"
#define L3G4IS_GYRO_DEV_NAME "l3g4is_ui" #define L3G4IS_GYRO_DEV_NAME "l3g4is_ui"
#define LSM330_GYRO_DEV_NAME "lsm330_gyro" #define LSM330_GYRO_DEV_NAME "lsm330_gyro"
#define LSM9DS0_GYRO_DEV_NAME "lsm9ds0_gyro" #define LSM9DS0_GYRO_DEV_NAME "lsm9ds0_gyro"
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#define ST_GYRO_DEFAULT_OUT_Z_L_ADDR 0x2c #define ST_GYRO_DEFAULT_OUT_Z_L_ADDR 0x2c
/* FULLSCALE */ /* FULLSCALE */
#define ST_GYRO_FS_AVL_245DPS 245
#define ST_GYRO_FS_AVL_250DPS 250 #define ST_GYRO_FS_AVL_250DPS 250
#define ST_GYRO_FS_AVL_500DPS 500 #define ST_GYRO_FS_AVL_500DPS 500
#define ST_GYRO_FS_AVL_2000DPS 2000 #define ST_GYRO_FS_AVL_2000DPS 2000
...@@ -196,17 +197,17 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { ...@@ -196,17 +197,17 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
.wai = 0xd7, .wai = 0xd7,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = { .sensors_supported = {
[0] = L3GD20_GYRO_DEV_NAME, [0] = L3GD20H_GYRO_DEV_NAME,
}, },
.ch = (struct iio_chan_spec *)st_gyro_16bit_channels, .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
.odr = { .odr = {
.addr = 0x20, .addr = 0x20,
.mask = 0xc0, .mask = 0xc0,
.odr_avl = { .odr_avl = {
{ .hz = 95, .value = 0x00, }, { .hz = 100, .value = 0x00, },
{ .hz = 190, .value = 0x01, }, { .hz = 200, .value = 0x01, },
{ .hz = 380, .value = 0x02, }, { .hz = 400, .value = 0x02, },
{ .hz = 760, .value = 0x03, }, { .hz = 800, .value = 0x03, },
}, },
}, },
.pw = { .pw = {
...@@ -224,7 +225,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { ...@@ -224,7 +225,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
.mask = 0x30, .mask = 0x30,
.fs_avl = { .fs_avl = {
[0] = { [0] = {
.num = ST_GYRO_FS_AVL_250DPS, .num = ST_GYRO_FS_AVL_245DPS,
.value = 0x00, .value = 0x00,
.gain = IIO_DEGREE_TO_RAD(8750), .gain = IIO_DEGREE_TO_RAD(8750),
}, },
......
...@@ -40,6 +40,10 @@ static const struct of_device_id st_gyro_of_match[] = { ...@@ -40,6 +40,10 @@ static const struct of_device_id st_gyro_of_match[] = {
.compatible = "st,l3gd20-gyro", .compatible = "st,l3gd20-gyro",
.data = L3GD20_GYRO_DEV_NAME, .data = L3GD20_GYRO_DEV_NAME,
}, },
{
.compatible = "st,l3gd20h-gyro",
.data = L3GD20H_GYRO_DEV_NAME,
},
{ {
.compatible = "st,l3g4is-gyro", .compatible = "st,l3g4is-gyro",
.data = L3G4IS_GYRO_DEV_NAME, .data = L3G4IS_GYRO_DEV_NAME,
...@@ -71,7 +75,8 @@ static int st_gyro_i2c_probe(struct i2c_client *client, ...@@ -71,7 +75,8 @@ static int st_gyro_i2c_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
gdata = iio_priv(indio_dev); gdata = iio_priv(indio_dev);
st_sensors_of_i2c_probe(client, st_gyro_of_match); st_sensors_of_name_probe(&client->dev, st_gyro_of_match,
client->name, sizeof(client->name));
st_sensors_i2c_configure(indio_dev, client, gdata); st_sensors_i2c_configure(indio_dev, client, gdata);
...@@ -95,6 +100,7 @@ static const struct i2c_device_id st_gyro_id_table[] = { ...@@ -95,6 +100,7 @@ static const struct i2c_device_id st_gyro_id_table[] = {
{ LSM330DL_GYRO_DEV_NAME }, { LSM330DL_GYRO_DEV_NAME },
{ LSM330DLC_GYRO_DEV_NAME }, { LSM330DLC_GYRO_DEV_NAME },
{ L3GD20_GYRO_DEV_NAME }, { L3GD20_GYRO_DEV_NAME },
{ L3GD20H_GYRO_DEV_NAME },
{ L3G4IS_GYRO_DEV_NAME }, { L3G4IS_GYRO_DEV_NAME },
{ LSM330_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME },
{ LSM9DS0_GYRO_DEV_NAME }, { LSM9DS0_GYRO_DEV_NAME },
......
...@@ -18,6 +18,56 @@ ...@@ -18,6 +18,56 @@
#include <linux/iio/common/st_sensors_spi.h> #include <linux/iio/common/st_sensors_spi.h>
#include "st_gyro.h" #include "st_gyro.h"
#ifdef CONFIG_OF
/*
* For new single-chip sensors use <device_name> as compatible string.
* For old single-chip devices keep <device_name>-gyro to maintain
* compatibility
*/
static const struct of_device_id st_gyro_of_match[] = {
{
.compatible = "st,l3g4200d-gyro",
.data = L3G4200D_GYRO_DEV_NAME,
},
{
.compatible = "st,lsm330d-gyro",
.data = LSM330D_GYRO_DEV_NAME,
},
{
.compatible = "st,lsm330dl-gyro",
.data = LSM330DL_GYRO_DEV_NAME,
},
{
.compatible = "st,lsm330dlc-gyro",
.data = LSM330DLC_GYRO_DEV_NAME,
},
{
.compatible = "st,l3gd20-gyro",
.data = L3GD20_GYRO_DEV_NAME,
},
{
.compatible = "st,l3gd20h-gyro",
.data = L3GD20H_GYRO_DEV_NAME,
},
{
.compatible = "st,l3g4is-gyro",
.data = L3G4IS_GYRO_DEV_NAME,
},
{
.compatible = "st,lsm330-gyro",
.data = LSM330_GYRO_DEV_NAME,
},
{
.compatible = "st,lsm9ds0-gyro",
.data = LSM9DS0_GYRO_DEV_NAME,
},
{},
};
MODULE_DEVICE_TABLE(of, st_gyro_of_match);
#else
#define st_gyro_of_match NULL
#endif
static int st_gyro_spi_probe(struct spi_device *spi) static int st_gyro_spi_probe(struct spi_device *spi)
{ {
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
...@@ -30,6 +80,8 @@ static int st_gyro_spi_probe(struct spi_device *spi) ...@@ -30,6 +80,8 @@ static int st_gyro_spi_probe(struct spi_device *spi)
gdata = iio_priv(indio_dev); gdata = iio_priv(indio_dev);
st_sensors_of_name_probe(&spi->dev, st_gyro_of_match,
spi->modalias, sizeof(spi->modalias));
st_sensors_spi_configure(indio_dev, spi, gdata); st_sensors_spi_configure(indio_dev, spi, gdata);
err = st_gyro_common_probe(indio_dev); err = st_gyro_common_probe(indio_dev);
...@@ -52,6 +104,7 @@ static const struct spi_device_id st_gyro_id_table[] = { ...@@ -52,6 +104,7 @@ static const struct spi_device_id st_gyro_id_table[] = {
{ LSM330DL_GYRO_DEV_NAME }, { LSM330DL_GYRO_DEV_NAME },
{ LSM330DLC_GYRO_DEV_NAME }, { LSM330DLC_GYRO_DEV_NAME },
{ L3GD20_GYRO_DEV_NAME }, { L3GD20_GYRO_DEV_NAME },
{ L3GD20H_GYRO_DEV_NAME },
{ L3G4IS_GYRO_DEV_NAME }, { L3G4IS_GYRO_DEV_NAME },
{ LSM330_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME },
{ LSM9DS0_GYRO_DEV_NAME }, { LSM9DS0_GYRO_DEV_NAME },
...@@ -62,6 +115,7 @@ MODULE_DEVICE_TABLE(spi, st_gyro_id_table); ...@@ -62,6 +115,7 @@ MODULE_DEVICE_TABLE(spi, st_gyro_id_table);
static struct spi_driver st_gyro_driver = { static struct spi_driver st_gyro_driver = {
.driver = { .driver = {
.name = "st-gyro-spi", .name = "st-gyro-spi",
.of_match_table = of_match_ptr(st_gyro_of_match),
}, },
.probe = st_gyro_spi_probe, .probe = st_gyro_spi_probe,
.remove = st_gyro_spi_remove, .remove = st_gyro_spi_remove,
......
...@@ -31,7 +31,8 @@ config HDC100X ...@@ -31,7 +31,8 @@ config HDC100X
select IIO_TRIGGERED_BUFFER select IIO_TRIGGERED_BUFFER
help help
Say yes here to build support for the Texas Instruments Say yes here to build support for the Texas Instruments
HDC1000 and HDC1008 relative humidity and temperature sensors. HDC1000, HDC1008, HDC1010, HDC1050, and HDC1080 relative
humidity and temperature sensors.
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called hdc100x. will be called hdc100x.
......
...@@ -13,6 +13,12 @@ ...@@ -13,6 +13,12 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* Datasheets:
* http://www.ti.com/product/HDC1000/datasheet
* http://www.ti.com/product/HDC1008/datasheet
* http://www.ti.com/product/HDC1010/datasheet
* http://www.ti.com/product/HDC1050/datasheet
* http://www.ti.com/product/HDC1080/datasheet
*/ */
#include <linux/delay.h> #include <linux/delay.h>
...@@ -414,13 +420,29 @@ static int hdc100x_remove(struct i2c_client *client) ...@@ -414,13 +420,29 @@ static int hdc100x_remove(struct i2c_client *client)
static const struct i2c_device_id hdc100x_id[] = { static const struct i2c_device_id hdc100x_id[] = {
{ "hdc100x", 0 }, { "hdc100x", 0 },
{ "hdc1000", 0 },
{ "hdc1008", 0 },
{ "hdc1010", 0 },
{ "hdc1050", 0 },
{ "hdc1080", 0 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, hdc100x_id); MODULE_DEVICE_TABLE(i2c, hdc100x_id);
static const struct of_device_id hdc100x_dt_ids[] = {
{ .compatible = "ti,hdc1000" },
{ .compatible = "ti,hdc1008" },
{ .compatible = "ti,hdc1010" },
{ .compatible = "ti,hdc1050" },
{ .compatible = "ti,hdc1080" },
{ }
};
MODULE_DEVICE_TABLE(of, hdc100x_dt_ids);
static struct i2c_driver hdc100x_driver = { static struct i2c_driver hdc100x_driver = {
.driver = { .driver = {
.name = "hdc100x", .name = "hdc100x",
.of_match_table = of_match_ptr(hdc100x_dt_ids),
}, },
.probe = hdc100x_probe, .probe = hdc100x_probe,
.remove = hdc100x_remove, .remove = hdc100x_remove,
......
...@@ -30,12 +30,6 @@ struct hts221_transfer_function { ...@@ -30,12 +30,6 @@ struct hts221_transfer_function {
int (*write)(struct device *dev, u8 addr, int len, u8 *data); int (*write)(struct device *dev, u8 addr, int len, u8 *data);
}; };
#define HTS221_AVG_DEPTH 8
struct hts221_avg_avl {
u16 avg;
u8 val;
};
enum hts221_sensor_type { enum hts221_sensor_type {
HTS221_SENSOR_H, HTS221_SENSOR_H,
HTS221_SENSOR_T, HTS221_SENSOR_T,
...@@ -66,10 +60,9 @@ struct hts221_hw { ...@@ -66,10 +60,9 @@ struct hts221_hw {
extern const struct dev_pm_ops hts221_pm_ops; extern const struct dev_pm_ops hts221_pm_ops;
int hts221_config_drdy(struct hts221_hw *hw, bool enable); int hts221_write_with_mask(struct hts221_hw *hw, u8 addr, u8 mask, u8 val);
int hts221_probe(struct iio_dev *iio_dev); int hts221_probe(struct iio_dev *iio_dev);
int hts221_power_on(struct hts221_hw *hw); int hts221_set_enable(struct hts221_hw *hw, bool enable);
int hts221_power_off(struct hts221_hw *hw);
int hts221_allocate_buffers(struct hts221_hw *hw); int hts221_allocate_buffers(struct hts221_hw *hw);
int hts221_allocate_trigger(struct hts221_hw *hw); int hts221_allocate_trigger(struct hts221_hw *hw);
......
...@@ -20,8 +20,16 @@ ...@@ -20,8 +20,16 @@
#include <linux/iio/triggered_buffer.h> #include <linux/iio/triggered_buffer.h>
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/platform_data/st_sensors_pdata.h>
#include "hts221.h" #include "hts221.h"
#define HTS221_REG_DRDY_HL_ADDR 0x22
#define HTS221_REG_DRDY_HL_MASK BIT(7)
#define HTS221_REG_DRDY_PP_OD_ADDR 0x22
#define HTS221_REG_DRDY_PP_OD_MASK BIT(6)
#define HTS221_REG_DRDY_EN_ADDR 0x22
#define HTS221_REG_DRDY_EN_MASK BIT(2)
#define HTS221_REG_STATUS_ADDR 0x27 #define HTS221_REG_STATUS_ADDR 0x27
#define HTS221_RH_DRDY_MASK BIT(1) #define HTS221_RH_DRDY_MASK BIT(1)
#define HTS221_TEMP_DRDY_MASK BIT(0) #define HTS221_TEMP_DRDY_MASK BIT(0)
...@@ -30,8 +38,12 @@ static int hts221_trig_set_state(struct iio_trigger *trig, bool state) ...@@ -30,8 +38,12 @@ static int hts221_trig_set_state(struct iio_trigger *trig, bool state)
{ {
struct iio_dev *iio_dev = iio_trigger_get_drvdata(trig); struct iio_dev *iio_dev = iio_trigger_get_drvdata(trig);
struct hts221_hw *hw = iio_priv(iio_dev); struct hts221_hw *hw = iio_priv(iio_dev);
int err;
err = hts221_write_with_mask(hw, HTS221_REG_DRDY_EN_ADDR,
HTS221_REG_DRDY_EN_MASK, state);
return hts221_config_drdy(hw, state); return err < 0 ? err : 0;
} }
static const struct iio_trigger_ops hts221_trigger_ops = { static const struct iio_trigger_ops hts221_trigger_ops = {
...@@ -67,6 +79,9 @@ static irqreturn_t hts221_trigger_handler_thread(int irq, void *private) ...@@ -67,6 +79,9 @@ static irqreturn_t hts221_trigger_handler_thread(int irq, void *private)
int hts221_allocate_trigger(struct hts221_hw *hw) int hts221_allocate_trigger(struct hts221_hw *hw)
{ {
struct iio_dev *iio_dev = iio_priv_to_dev(hw); struct iio_dev *iio_dev = iio_priv_to_dev(hw);
bool irq_active_low = false, open_drain = false;
struct device_node *np = hw->dev->of_node;
struct st_sensors_platform_data *pdata;
unsigned long irq_type; unsigned long irq_type;
int err; int err;
...@@ -76,6 +91,10 @@ int hts221_allocate_trigger(struct hts221_hw *hw) ...@@ -76,6 +91,10 @@ int hts221_allocate_trigger(struct hts221_hw *hw)
case IRQF_TRIGGER_HIGH: case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING: case IRQF_TRIGGER_RISING:
break; break;
case IRQF_TRIGGER_LOW:
case IRQF_TRIGGER_FALLING:
irq_active_low = true;
break;
default: default:
dev_info(hw->dev, dev_info(hw->dev,
"mode %lx unsupported, using IRQF_TRIGGER_RISING\n", "mode %lx unsupported, using IRQF_TRIGGER_RISING\n",
...@@ -84,6 +103,24 @@ int hts221_allocate_trigger(struct hts221_hw *hw) ...@@ -84,6 +103,24 @@ int hts221_allocate_trigger(struct hts221_hw *hw)
break; break;
} }
err = hts221_write_with_mask(hw, HTS221_REG_DRDY_HL_ADDR,
HTS221_REG_DRDY_HL_MASK, irq_active_low);
if (err < 0)
return err;
pdata = (struct st_sensors_platform_data *)hw->dev->platform_data;
if ((np && of_property_read_bool(np, "drive-open-drain")) ||
(pdata && pdata->open_drain)) {
irq_type |= IRQF_SHARED;
open_drain = true;
}
err = hts221_write_with_mask(hw, HTS221_REG_DRDY_PP_OD_ADDR,
HTS221_REG_DRDY_PP_OD_MASK,
open_drain);
if (err < 0)
return err;
err = devm_request_threaded_irq(hw->dev, hw->irq, NULL, err = devm_request_threaded_irq(hw->dev, hw->irq, NULL,
hts221_trigger_handler_thread, hts221_trigger_handler_thread,
irq_type | IRQF_ONESHOT, irq_type | IRQF_ONESHOT,
...@@ -109,12 +146,12 @@ int hts221_allocate_trigger(struct hts221_hw *hw) ...@@ -109,12 +146,12 @@ int hts221_allocate_trigger(struct hts221_hw *hw)
static int hts221_buffer_preenable(struct iio_dev *iio_dev) static int hts221_buffer_preenable(struct iio_dev *iio_dev)
{ {
return hts221_power_on(iio_priv(iio_dev)); return hts221_set_enable(iio_priv(iio_dev), true);
} }
static int hts221_buffer_postdisable(struct iio_dev *iio_dev) static int hts221_buffer_postdisable(struct iio_dev *iio_dev)
{ {
return hts221_power_off(iio_priv(iio_dev)); return hts221_set_enable(iio_priv(iio_dev), false);
} }
static const struct iio_buffer_setup_ops hts221_buffer_ops = { static const struct iio_buffer_setup_ops hts221_buffer_ops = {
......
此差异已折叠。
...@@ -238,11 +238,19 @@ static const struct i2c_device_id htu21_id[] = { ...@@ -238,11 +238,19 @@ static const struct i2c_device_id htu21_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, htu21_id); MODULE_DEVICE_TABLE(i2c, htu21_id);
static const struct of_device_id htu21_of_match[] = {
{ .compatible = "meas,htu21", },
{ .compatible = "meas,ms8607-humidity", },
{ },
};
MODULE_DEVICE_TABLE(of, htu21_of_match);
static struct i2c_driver htu21_driver = { static struct i2c_driver htu21_driver = {
.probe = htu21_probe, .probe = htu21_probe,
.id_table = htu21_id, .id_table = htu21_id,
.driver = { .driver = {
.name = "htu21", .name = "htu21",
.of_match_table = of_match_ptr(htu21_of_match),
}, },
}; };
......
...@@ -217,7 +217,7 @@ static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq) ...@@ -217,7 +217,7 @@ static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq)
return adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val); return adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val);
} }
static const unsigned adis16400_3db_divisors[] = { static const unsigned int adis16400_3db_divisors[] = {
[0] = 2, /* Special case */ [0] = 2, /* Special case */
[1] = 6, [1] = 6,
[2] = 12, [2] = 12,
...@@ -890,7 +890,7 @@ static const struct adis_data adis16400_data = { ...@@ -890,7 +890,7 @@ static const struct adis_data adis16400_data = {
static void adis16400_setup_chan_mask(struct adis16400_state *st) static void adis16400_setup_chan_mask(struct adis16400_state *st)
{ {
const struct adis16400_chip_info *chip_info = st->variant; const struct adis16400_chip_info *chip_info = st->variant;
unsigned i; unsigned int i;
for (i = 0; i < chip_info->num_channels; i++) { for (i = 0; i < chip_info->num_channels; i++) {
const struct iio_chan_spec *ch = &chip_info->channels[i]; const struct iio_chan_spec *ch = &chip_info->channels[i];
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/platform_data/st_sensors_pdata.h>
#include "st_lsm6dsx.h" #include "st_lsm6dsx.h"
#define ST_LSM6DSX_REG_FIFO_THL_ADDR 0x06 #define ST_LSM6DSX_REG_FIFO_THL_ADDR 0x06
...@@ -39,6 +41,8 @@ ...@@ -39,6 +41,8 @@
#define ST_LSM6DSX_REG_FIFO_DEC_GXL_ADDR 0x08 #define ST_LSM6DSX_REG_FIFO_DEC_GXL_ADDR 0x08
#define ST_LSM6DSX_REG_HLACTIVE_ADDR 0x12 #define ST_LSM6DSX_REG_HLACTIVE_ADDR 0x12
#define ST_LSM6DSX_REG_HLACTIVE_MASK BIT(5) #define ST_LSM6DSX_REG_HLACTIVE_MASK BIT(5)
#define ST_LSM6DSX_REG_PP_OD_ADDR 0x12
#define ST_LSM6DSX_REG_PP_OD_MASK BIT(4)
#define ST_LSM6DSX_REG_FIFO_MODE_ADDR 0x0a #define ST_LSM6DSX_REG_FIFO_MODE_ADDR 0x0a
#define ST_LSM6DSX_FIFO_MODE_MASK GENMASK(2, 0) #define ST_LSM6DSX_FIFO_MODE_MASK GENMASK(2, 0)
#define ST_LSM6DSX_FIFO_ODR_MASK GENMASK(6, 3) #define ST_LSM6DSX_FIFO_ODR_MASK GENMASK(6, 3)
...@@ -417,6 +421,8 @@ static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = { ...@@ -417,6 +421,8 @@ static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = {
int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw) int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
{ {
struct device_node *np = hw->dev->of_node;
struct st_sensors_platform_data *pdata;
struct iio_buffer *buffer; struct iio_buffer *buffer;
unsigned long irq_type; unsigned long irq_type;
bool irq_active_low; bool irq_active_low;
...@@ -444,6 +450,17 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw) ...@@ -444,6 +450,17 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
if (err < 0) if (err < 0)
return err; return err;
pdata = (struct st_sensors_platform_data *)hw->dev->platform_data;
if ((np && of_property_read_bool(np, "drive-open-drain")) ||
(pdata && pdata->open_drain)) {
err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_PP_OD_ADDR,
ST_LSM6DSX_REG_PP_OD_MASK, 1);
if (err < 0)
return err;
irq_type |= IRQF_SHARED;
}
err = devm_request_threaded_irq(hw->dev, hw->irq, err = devm_request_threaded_irq(hw->dev, hw->irq,
st_lsm6dsx_handler_irq, st_lsm6dsx_handler_irq,
st_lsm6dsx_handler_thread, st_lsm6dsx_handler_thread,
......
...@@ -44,7 +44,7 @@ int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps) ...@@ -44,7 +44,7 @@ int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps)
} }
mapi->map = &maps[i]; mapi->map = &maps[i];
mapi->indio_dev = indio_dev; mapi->indio_dev = indio_dev;
list_add(&mapi->l, &iio_map_list); list_add_tail(&mapi->l, &iio_map_list);
i++; i++;
} }
error_ret: error_ret:
...@@ -205,8 +205,8 @@ static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np, ...@@ -205,8 +205,8 @@ static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np,
if (!IS_ERR(chan) || PTR_ERR(chan) == -EPROBE_DEFER) if (!IS_ERR(chan) || PTR_ERR(chan) == -EPROBE_DEFER)
break; break;
else if (name && index >= 0) { else if (name && index >= 0) {
pr_err("ERROR: could not get IIO channel %s:%s(%i)\n", pr_err("ERROR: could not get IIO channel %pOF:%s(%i)\n",
np->full_name, name ? name : "", index); np, name ? name : "", index);
return NULL; return NULL;
} }
......
...@@ -505,7 +505,7 @@ static SIMPLE_DEV_PM_OPS(apds9300_pm_ops, apds9300_suspend, apds9300_resume); ...@@ -505,7 +505,7 @@ static SIMPLE_DEV_PM_OPS(apds9300_pm_ops, apds9300_suspend, apds9300_resume);
#define APDS9300_PM_OPS NULL #define APDS9300_PM_OPS NULL
#endif #endif
static struct i2c_device_id apds9300_id[] = { static const struct i2c_device_id apds9300_id[] = {
{ APDS9300_DRV_NAME, 0 }, { APDS9300_DRV_NAME, 0 },
{ } { }
}; };
......
此差异已折叠。
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
* 7-bit I2C slave address 0x39 (TCS34721, TCS34723) or 0x29 (TCS34725, * 7-bit I2C slave address 0x39 (TCS34721, TCS34723) or 0x29 (TCS34725,
* TCS34727) * TCS34727)
* *
* Datasheet: http://ams.com/eng/content/download/319364/1117183/file/TCS3472_Datasheet_EN_v2.pdf
*
* TODO: interrupt support, thresholds, wait time * TODO: interrupt support, thresholds, wait time
*/ */
...@@ -169,7 +171,7 @@ static int tcs3472_write_raw(struct iio_dev *indio_dev, ...@@ -169,7 +171,7 @@ static int tcs3472_write_raw(struct iio_dev *indio_dev,
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
if (val2 == (256 - i) * 2400) { if (val2 == (256 - i) * 2400) {
data->atime = i; data->atime = i;
return i2c_smbus_write_word_data( return i2c_smbus_write_byte_data(
data->client, TCS3472_ATIME, data->client, TCS3472_ATIME,
data->atime); data->atime);
} }
......
...@@ -924,7 +924,7 @@ static const struct dev_pm_ops tsl2583_pm_ops = { ...@@ -924,7 +924,7 @@ static const struct dev_pm_ops tsl2583_pm_ops = {
SET_RUNTIME_PM_OPS(tsl2583_suspend, tsl2583_resume, NULL) SET_RUNTIME_PM_OPS(tsl2583_suspend, tsl2583_resume, NULL)
}; };
static struct i2c_device_id tsl2583_idtable[] = { static const struct i2c_device_id tsl2583_idtable[] = {
{ "tsl2580", 0 }, { "tsl2580", 0 },
{ "tsl2581", 1 }, { "tsl2581", 1 },
{ "tsl2583", 2 }, { "tsl2583", 2 },
......
...@@ -13,8 +13,8 @@ config AK8974 ...@@ -13,8 +13,8 @@ config AK8974
select IIO_BUFFER select IIO_BUFFER
select IIO_TRIGGERED_BUFFER select IIO_TRIGGERED_BUFFER
help help
Say yes here to build support for Asahi Kasei AK8974 or Say yes here to build support for Asahi Kasei AK8974, AMI305 or
AMI305 I2C-based 3-axis magnetometer chips. AMI306 I2C-based 3-axis magnetometer chips.
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called ak8974. will be called ak8974.
......
此差异已折叠。
...@@ -784,6 +784,7 @@ static const struct iio_info ak8975_info = { ...@@ -784,6 +784,7 @@ static const struct iio_info ak8975_info = {
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
}; };
#ifdef CONFIG_ACPI
static const struct acpi_device_id ak_acpi_match[] = { static const struct acpi_device_id ak_acpi_match[] = {
{"AK8975", AK8975}, {"AK8975", AK8975},
{"AK8963", AK8963}, {"AK8963", AK8963},
...@@ -793,6 +794,7 @@ static const struct acpi_device_id ak_acpi_match[] = { ...@@ -793,6 +794,7 @@ static const struct acpi_device_id ak_acpi_match[] = {
{ }, { },
}; };
MODULE_DEVICE_TABLE(acpi, ak_acpi_match); MODULE_DEVICE_TABLE(acpi, ak_acpi_match);
#endif
static const char *ak8975_match_acpi_device(struct device *dev, static const char *ak8975_match_acpi_device(struct device *dev,
enum asahi_compass_chipset *chipset) enum asahi_compass_chipset *chipset)
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#define LSM303DLM_MAGN_DEV_NAME "lsm303dlm_magn" #define LSM303DLM_MAGN_DEV_NAME "lsm303dlm_magn"
#define LIS3MDL_MAGN_DEV_NAME "lis3mdl" #define LIS3MDL_MAGN_DEV_NAME "lis3mdl"
#define LSM303AGR_MAGN_DEV_NAME "lsm303agr_magn" #define LSM303AGR_MAGN_DEV_NAME "lsm303agr_magn"
#define LIS2MDL_MAGN_DEV_NAME "lis2mdl"
int st_magn_common_probe(struct iio_dev *indio_dev); int st_magn_common_probe(struct iio_dev *indio_dev);
void st_magn_common_remove(struct iio_dev *indio_dev); void st_magn_common_remove(struct iio_dev *indio_dev);
......
...@@ -315,7 +315,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = { ...@@ -315,7 +315,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
}, },
}, },
}, },
.multi_read_bit = false, .multi_read_bit = true,
.bootime = 2, .bootime = 2,
}, },
{ {
...@@ -323,6 +323,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = { ...@@ -323,6 +323,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
.wai_addr = 0x4f, .wai_addr = 0x4f,
.sensors_supported = { .sensors_supported = {
[0] = LSM303AGR_MAGN_DEV_NAME, [0] = LSM303AGR_MAGN_DEV_NAME,
[1] = LIS2MDL_MAGN_DEV_NAME,
}, },
.ch = (struct iio_chan_spec *)st_magn_3_16bit_channels, .ch = (struct iio_chan_spec *)st_magn_3_16bit_channels,
.odr = { .odr = {
......
...@@ -40,6 +40,10 @@ static const struct of_device_id st_magn_of_match[] = { ...@@ -40,6 +40,10 @@ static const struct of_device_id st_magn_of_match[] = {
.compatible = "st,lsm303agr-magn", .compatible = "st,lsm303agr-magn",
.data = LSM303AGR_MAGN_DEV_NAME, .data = LSM303AGR_MAGN_DEV_NAME,
}, },
{
.compatible = "st,lis2mdl",
.data = LIS2MDL_MAGN_DEV_NAME,
},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, st_magn_of_match); MODULE_DEVICE_TABLE(of, st_magn_of_match);
...@@ -59,7 +63,8 @@ static int st_magn_i2c_probe(struct i2c_client *client, ...@@ -59,7 +63,8 @@ static int st_magn_i2c_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
mdata = iio_priv(indio_dev); mdata = iio_priv(indio_dev);
st_sensors_of_i2c_probe(client, st_magn_of_match); st_sensors_of_name_probe(&client->dev, st_magn_of_match,
client->name, sizeof(client->name));
st_sensors_i2c_configure(indio_dev, client, mdata); st_sensors_i2c_configure(indio_dev, client, mdata);
...@@ -84,6 +89,7 @@ static const struct i2c_device_id st_magn_id_table[] = { ...@@ -84,6 +89,7 @@ static const struct i2c_device_id st_magn_id_table[] = {
{ LSM303DLM_MAGN_DEV_NAME }, { LSM303DLM_MAGN_DEV_NAME },
{ LIS3MDL_MAGN_DEV_NAME }, { LIS3MDL_MAGN_DEV_NAME },
{ LSM303AGR_MAGN_DEV_NAME }, { LSM303AGR_MAGN_DEV_NAME },
{ LIS2MDL_MAGN_DEV_NAME },
{}, {},
}; };
MODULE_DEVICE_TABLE(i2c, st_magn_id_table); MODULE_DEVICE_TABLE(i2c, st_magn_id_table);
......
...@@ -238,7 +238,7 @@ static int dev_rot_parse_report(struct platform_device *pdev, ...@@ -238,7 +238,7 @@ static int dev_rot_parse_report(struct platform_device *pdev,
static int hid_dev_rot_probe(struct platform_device *pdev) static int hid_dev_rot_probe(struct platform_device *pdev)
{ {
int ret; int ret;
static char *name; char *name;
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct dev_rot_state *rot_state; struct dev_rot_state *rot_state;
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
......
...@@ -181,11 +181,21 @@ static const struct i2c_device_id ms5637_id[] = { ...@@ -181,11 +181,21 @@ static const struct i2c_device_id ms5637_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, ms5637_id); MODULE_DEVICE_TABLE(i2c, ms5637_id);
static const struct of_device_id ms5637_of_match[] = {
{ .compatible = "meas,ms5637", },
{ .compatible = "meas,ms5805", },
{ .compatible = "meas,ms5837", },
{ .compatible = "meas,ms8607-temppressure", },
{ },
};
MODULE_DEVICE_TABLE(of, ms5637_of_match);
static struct i2c_driver ms5637_driver = { static struct i2c_driver ms5637_driver = {
.probe = ms5637_probe, .probe = ms5637_probe,
.id_table = ms5637_id, .id_table = ms5637_id,
.driver = { .driver = {
.name = "ms5637" .name = "ms5637",
.of_match_table = of_match_ptr(ms5637_of_match),
}, },
}; };
......
...@@ -390,7 +390,7 @@ static const struct st_sensor_settings st_press_sensors_settings[] = { ...@@ -390,7 +390,7 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
.drdy_irq = { .drdy_irq = {
.addr = 0x23, .addr = 0x23,
.mask_int1 = 0x01, .mask_int1 = 0x01,
.mask_int2 = 0x10, .mask_int2 = 0x00,
.addr_ihl = 0x22, .addr_ihl = 0x22,
.mask_ihl = 0x80, .mask_ihl = 0x80,
.addr_od = 0x22, .addr_od = 0x22,
...@@ -449,7 +449,7 @@ static const struct st_sensor_settings st_press_sensors_settings[] = { ...@@ -449,7 +449,7 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
.drdy_irq = { .drdy_irq = {
.addr = 0x12, .addr = 0x12,
.mask_int1 = 0x04, .mask_int1 = 0x04,
.mask_int2 = 0x08, .mask_int2 = 0x00,
.addr_ihl = 0x12, .addr_ihl = 0x12,
.mask_ihl = 0x80, .mask_ihl = 0x80,
.addr_od = 0x12, .addr_od = 0x12,
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册