Second set of IIO new device support, features and cleanups for the 4.13 cycle.

A few reverts here. One was a general failure to notice a device was already
 supported by another driver.  The second is due to a review comment pointing
 out that the original patch was a bad idea and would break existing systems.
 
 Reverts
 * bma180
   - Revert addition of support for the BMA250E it is already supported by
     the bmc150-accel and better supported at that. Oops.
 * hi8435
   - The fix for cleanup of the reset gpio stuff isn't a good way to go.  It
     breaks systems where an inverting level convertor is used.  The right fix
     is to make the original devicetree correct - even if it involves patching
     the devicetree in kernel.
 
 New Device Support
 * stm32-adc
   - STM32H7 support and bindings.
 
 Features
 * core
   - add a hardware triggered operating mode for systems in which the actual
     trigger is never seen by the kernel.  This is typically only used when
     a device 'can' use other triggers, but if a particular magic one is
     enabled the interrupt is effectively handled in hardware and we never see
     it.
 * st-lsm6dsx
   - support active low interrupts.
 * stm32-adc
   - Make the core adc clock optional as not all hardware supported requires it.
   - Make the bus clock optional in the per instance driver as it may be shared
     by all instances of the ADC and is handled by the core.
   - Rework to have a data structure representing the device type specific
     elements.
 * stm32-trigger (and counter)
   - Use the INDIO_HARDWARE_TRIGGERED_MODE where appropriate.
   - Add an attribute to configure device modes for quadrature counting etc.
 
 Clean ups and minor fixes
 * IIO core.
   - use __sysfs_match_string() helper rather than open coding the same.
 * ad7791
   - use sysfs_match_string() helper rather than open coding the same.
 * aspeed-adc
   - handle return value of clk_prepare_enable
 * cpcap
   - Fix default register values and ensure the battery thermistor is enabled
     correctly.
   - Fix the reported die temperature where we can - docs are lacking.
   - Remove the hung interrupt quirk as no longer happens due to fix in the
     mfd driver.
 * hi8435
   - Remove &s from hi8435_info definition as unneeded and inconsistent.
 * hid-sensor-trgger
   - Add kconfig depends on IIO_BUFFER (fixes patch in previous series)
 * ina2xx
   - Make the use of iio_info_mask* elements consistent for all channels.
     This doesn't have any visible effect, but acts as clear documentation of
     which channels various resulting attributes apply to.
 * lpc32xx
   - handle the return value of clk_prepare_enable.
 * meson-saradc
   - NULL instead of 0 for pointer.
 * mma9551
   - use NULL for GPIO connection ID to aid implementation fo ACPI support.
     Here the connection ID doesn't actually tell us anything and it is much
     easier to deal with the driver if it's not there.
 * mpu6050
   - Fix lock issues through use of a local mux.
   - Replace sprintf with scnprintf as appropriate.
   - Check whoami against all known values.  This allows for a small number of
     boards where we are really fishing for the part not being present at all.
     It is unfortunately common to have undescribed changes to use newer chips.
     We paper over this but just emitting a warning for those cases as long as
     we know about.
 * mxs-lradc
   - Fix some non static warnings.
 * rcar-adc
   - Part of making the naming for this part consistent across the kernel.
 * st_accel
   - drop some spi_device_id entries for variants with no SPI support
 * st_magn
   - drop some spi_device_id entries for variants with no SPI support.
 * sx9500
   - Use devm_gpiod_get instead of indexed value with an index of 0 on all
     occasions.
 * twl4030
   - Drop unused twl4030_get_madc_conversion as callers removed now throughout
     kernel.
   - Unexport twl4030_madc_conversion() as no used only within this driver.
   - Drop twl4030_madc_user_params as not used now.
   - Drop twl4030_madc_request.func_cb as not used now.
   - Fold the twl4030-madc.h header into the driver as no longer used anywhere
     else in the kernel.
 * xilinx
   - Handle the return value of clk_prepare_enable
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEEbilms4eEBlKRJoGxVIU0mcT0FogFAllJSCURHGppYzIzQGtl
 cm5lbC5vcmcACgkQVIU0mcT0FogTTQ//bbAzHKB0qTwusFN5jrz1JqjGj3+bMXH/
 KumP4nj7NzwKBe4tDe40FsdkZ4c+Um8pK2Aj7iJZojwTcCi02VVjbM++Gj0akMTZ
 MIlrEkTvqVsmVFG085hloSiFU2xXfTnfQmp19M9QtyDnHkgBMo9sOFnBK3EG+Se4
 NIliUvq8PJzCjTRVafSeSFNoDMwXXQTIKhfq8TDSeOG9o5mCTgAdy8yGiZ2ag/Ok
 peFfwauGs9Gg6tRour7UxccawuLnuzPNzwzUUSG3gkdIUTQVD6YHAzXzwblnB5P6
 0ZcErJpGSLAYcHQH310ZRTizhhW+vi+ftWUkps81xqpmFp3+EydVnJS0MZXYgM2o
 Cv6wbohp9w22I5/B9TMEfL7vnj1i4iZoJfi00Su1HBDHBiNpXISRc/fnkRMWavhr
 gvypyxngQmXm1JN/R8UMbJQsSpH3TN07AYF1qx0Tktfyx4S18rdW4hwt+kBNe9ni
 5G9xQU8IhmN8yvHMsTvZHbAmbuOR6iaghx3arf65qdHPvKSQ/nTSlran9U1JPvyJ
 tWVKtPaY5zEGgkQBmWee+qWkWOBGYDC4nmTwijB0u61Deq+5hGg55cZPd0fSXLMg
 6ecNg2v7zrdYldulOpfdNUEOrXa/NYBEAuYUNvccp8DArOqdazkCyO3DlDFDUXRw
 RKNE7Btx/rU=
 =2fJI
 -----END PGP SIGNATURE-----

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

Jonathan writes:

Second set of IIO new device support, features and cleanups for the 4.13 cycle.

A few reverts here. One was a general failure to notice a device was already
supported by another driver.  The second is due to a review comment pointing
out that the original patch was a bad idea and would break existing systems.

Reverts
* bma180
  - Revert addition of support for the BMA250E it is already supported by
    the bmc150-accel and better supported at that. Oops.
* hi8435
  - The fix for cleanup of the reset gpio stuff isn't a good way to go.  It
    breaks systems where an inverting level convertor is used.  The right fix
    is to make the original devicetree correct - even if it involves patching
    the devicetree in kernel.

New Device Support
* stm32-adc
  - STM32H7 support and bindings.

Features
* core
  - add a hardware triggered operating mode for systems in which the actual
    trigger is never seen by the kernel.  This is typically only used when
    a device 'can' use other triggers, but if a particular magic one is
    enabled the interrupt is effectively handled in hardware and we never see
    it.
* st-lsm6dsx
  - support active low interrupts.
* stm32-adc
  - Make the core adc clock optional as not all hardware supported requires it.
  - Make the bus clock optional in the per instance driver as it may be shared
    by all instances of the ADC and is handled by the core.
  - Rework to have a data structure representing the device type specific
    elements.
* stm32-trigger (and counter)
  - Use the INDIO_HARDWARE_TRIGGERED_MODE where appropriate.
  - Add an attribute to configure device modes for quadrature counting etc.

Clean ups and minor fixes
* IIO core.
  - use __sysfs_match_string() helper rather than open coding the same.
* ad7791
  - use sysfs_match_string() helper rather than open coding the same.
* aspeed-adc
  - handle return value of clk_prepare_enable
* cpcap
  - Fix default register values and ensure the battery thermistor is enabled
    correctly.
  - Fix the reported die temperature where we can - docs are lacking.
  - Remove the hung interrupt quirk as no longer happens due to fix in the
    mfd driver.
* hi8435
  - Remove &s from hi8435_info definition as unneeded and inconsistent.
* hid-sensor-trgger
  - Add kconfig depends on IIO_BUFFER (fixes patch in previous series)
* ina2xx
  - Make the use of iio_info_mask* elements consistent for all channels.
    This doesn't have any visible effect, but acts as clear documentation of
    which channels various resulting attributes apply to.
* lpc32xx
  - handle the return value of clk_prepare_enable.
* meson-saradc
  - NULL instead of 0 for pointer.
* mma9551
  - use NULL for GPIO connection ID to aid implementation fo ACPI support.
    Here the connection ID doesn't actually tell us anything and it is much
    easier to deal with the driver if it's not there.
* mpu6050
  - Fix lock issues through use of a local mux.
  - Replace sprintf with scnprintf as appropriate.
  - Check whoami against all known values.  This allows for a small number of
    boards where we are really fishing for the part not being present at all.
    It is unfortunately common to have undescribed changes to use newer chips.
    We paper over this but just emitting a warning for those cases as long as
    we know about.
* mxs-lradc
  - Fix some non static warnings.
* rcar-adc
  - Part of making the naming for this part consistent across the kernel.
* st_accel
  - drop some spi_device_id entries for variants with no SPI support
* st_magn
  - drop some spi_device_id entries for variants with no SPI support.
* sx9500
  - Use devm_gpiod_get instead of indexed value with an index of 0 on all
    occasions.
* twl4030
  - Drop unused twl4030_get_madc_conversion as callers removed now throughout
    kernel.
  - Unexport twl4030_madc_conversion() as no used only within this driver.
  - Drop twl4030_madc_user_params as not used now.
  - Drop twl4030_madc_request.func_cb as not used now.
  - Fold the twl4030-madc.h header into the driver as no longer used anywhere
    else in the kernel.
* xilinx
  - Handle the return value of clk_prepare_enable
This commit is contained in:
Greg Kroah-Hartman 2017-06-26 07:09:23 +02:00
commit dd36a2d9ad
32 changed files with 1631 additions and 572 deletions

View File

@ -138,3 +138,18 @@ Description:
Counting is enabled on rising edge of the connected
trigger, and remains enabled for the duration of this
selected mode.
What: /sys/bus/iio/devices/iio:deviceX/in_count_trigger_mode_available
KernelVersion: 4.13
Contact: benjamin.gaignard@st.com
Description:
Reading returns the list possible trigger modes.
What: /sys/bus/iio/devices/iio:deviceX/in_count0_trigger_mode
KernelVersion: 4.13
Contact: benjamin.gaignard@st.com
Description:
Configure the device counter trigger mode
counting direction is set by in_count0_count_direction
attribute and the counter is clocked by the connected trigger
rising edges.

View File

@ -1,4 +1,4 @@
* Renesas RCar GyroADC device driver
* Renesas R-Car GyroADC device driver
The GyroADC block is a reduced SPI block with up to 8 chipselect lines,
which supports the SPI protocol of a selected few SPI ADCs. The SPI ADCs

View File

@ -21,11 +21,19 @@ own configurable sequence and trigger:
Contents of a stm32 adc root node:
-----------------------------------
Required properties:
- compatible: Should be "st,stm32f4-adc-core".
- compatible: Should be one of:
"st,stm32f4-adc-core"
"st,stm32h7-adc-core"
- reg: Offset and length of the ADC block register set.
- interrupts: Must contain the interrupt for ADC block.
- clocks: Clock for the analog circuitry (common to all ADCs).
- clock-names: Must be "adc".
- clocks: Core can use up to two clocks, depending on part used:
- "adc" clock: for the analog circuitry, common to all ADCs.
It's required on stm32f4.
It's optional on stm32h7.
- "bus" clock: for registers access, common to all ADCs.
It's not present on stm32f4.
It's required on stm32h7.
- clock-names: Must be "adc" and/or "bus" depending on part used.
- interrupt-controller: Identifies the controller node as interrupt-parent
- vref-supply: Phandle to the vref input analog reference voltage.
- #interrupt-cells = <1>;
@ -42,14 +50,18 @@ An ADC block node should contain at least one subnode, representing an
ADC instance available on the machine.
Required properties:
- compatible: Should be "st,stm32f4-adc".
- compatible: Should be one of:
"st,stm32f4-adc"
"st,stm32h7-adc"
- reg: Offset of ADC instance in ADC block (e.g. may be 0x0, 0x100, 0x200).
- clocks: Input clock private to this ADC instance.
- clocks: Input clock private to this ADC instance. It's required only on
stm32f4, that has per instance clock input for registers access.
- interrupt-parent: Phandle to the parent interrupt controller.
- interrupts: IRQ Line for the ADC (e.g. may be 0 for adc@0, 1 for adc@100 or
2 for adc@200).
- st,adc-channels: List of single-ended channels muxed for this ADC.
It can have up to 16 channels, numbered from 0 to 15 (resp. for in0..in15).
It can have up to 16 channels on stm32f4 or 20 channels on stm32h7, numbered
from 0 to 15 or 19 (resp. for in0..in15 or in0..in19).
- #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in
Documentation/devicetree/bindings/iio/iio-bindings.txt
@ -58,7 +70,9 @@ Optional properties:
See ../../dma/dma.txt for details.
- dma-names: Must be "rx" when dmas property is being used.
- assigned-resolution-bits: Resolution (bits) to use for conversions. Must
match device available resolutions (e.g. can be 6, 8, 10 or 12 on stm32f4).
match device available resolutions:
* can be 6, 8, 10 or 12 on stm32f4
* can be 8, 10, 12, 14 or 16 on stm32h7
Default is maximum resolution if unset.
Example:

View File

@ -13,7 +13,8 @@ Optional properties:
"data ready" (valid values: 1 or 2).
- interrupt-parent: should be the phandle for the interrupt controller
- 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
client node bindings.

View File

@ -14,7 +14,6 @@
* BMA250: 7-bit I2C slave address 0x18 or 0x19
*/
#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
@ -37,7 +36,6 @@
enum chip_ids {
BMA180,
BMA250,
BMA250E,
};
struct bma180_data;
@ -57,7 +55,6 @@ struct bma180_part_info {
u8 power_reg, power_mask, lowpower_val;
u8 int_enable_reg, int_enable_mask;
u8 softreset_reg;
u8 chip_id;
int (*chip_config)(struct bma180_data *data);
void (*chip_disable)(struct bma180_data *data);
@ -115,8 +112,6 @@ struct bma180_part_info {
#define BMA250_INT1_DATA_MASK BIT(0)
#define BMA250_INT_RESET_MASK BIT(7) /* Reset pending interrupts */
#define BMA250E_CHIP_ID 0xf9
struct bma180_data {
struct i2c_client *client;
struct iio_trigger *trig;
@ -314,7 +309,7 @@ static int bma180_chip_init(struct bma180_data *data)
if (ret < 0)
return ret;
if (ret != data->part_info->chip_id)
if (ret != BMA180_ID_REG_VAL)
return -ENODEV;
ret = bma180_soft_reset(data);
@ -637,7 +632,6 @@ static const struct bma180_part_info bma180_part_info[] = {
BMA180_TCO_Z, BMA180_MODE_CONFIG, BMA180_LOW_POWER,
BMA180_CTRL_REG3, BMA180_NEW_DATA_INT,
BMA180_RESET,
BMA180_CHIP_ID,
bma180_chip_config,
bma180_chip_disable,
},
@ -652,22 +646,6 @@ static const struct bma180_part_info bma180_part_info[] = {
BMA250_POWER_REG, BMA250_LOWPOWER_MASK, 1,
BMA250_INT_ENABLE_REG, BMA250_DATA_INTEN_MASK,
BMA250_RESET_REG,
BMA180_CHIP_ID,
bma250_chip_config,
bma250_chip_disable,
},
[BMA250E] = {
bma250_channels, ARRAY_SIZE(bma250_channels),
bma250_scale_table, ARRAY_SIZE(bma250_scale_table),
bma250_bw_table, ARRAY_SIZE(bma250_bw_table),
BMA250_INT_RESET_REG, BMA250_INT_RESET_MASK,
BMA250_POWER_REG, BMA250_SUSPEND_MASK,
BMA250_BW_REG, BMA250_BW_MASK,
BMA250_RANGE_REG, BMA250_RANGE_MASK,
BMA250_POWER_REG, BMA250_LOWPOWER_MASK, 1,
BMA250_INT_ENABLE_REG, BMA250_DATA_INTEN_MASK,
BMA250_RESET_REG,
BMA250E_CHIP_ID,
bma250_chip_config,
bma250_chip_disable,
},
@ -728,8 +706,6 @@ static const struct iio_trigger_ops bma180_trigger_ops = {
static int bma180_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
const struct acpi_device_id *acpi_id;
struct bma180_data *data;
struct iio_dev *indio_dev;
enum chip_ids chip;
@ -742,17 +718,10 @@ static int bma180_probe(struct i2c_client *client,
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
if (dev->of_node) {
if (client->dev.of_node)
chip = (enum chip_ids)of_device_get_match_data(&client->dev);
} else if (id) {
else
chip = id->driver_data;
} else {
acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
if (!acpi_id)
return -ENODEV;
chip = acpi_id->driver_data;
}
data->part_info = &bma180_part_info[chip];
ret = data->part_info->chip_config(data);
@ -873,16 +842,9 @@ static SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume);
#define BMA180_PM_OPS NULL
#endif
static const struct acpi_device_id bma180_acpi_match[] = {
{ "BMA250E", BMA250E },
{ }
};
MODULE_DEVICE_TABLE(acpi, bma180_acpi_match);
static struct i2c_device_id bma180_ids[] = {
{ "bma180", BMA180 },
{ "bma250", BMA250 },
{ "bma250e", BMA250E },
{ }
};
@ -904,7 +866,6 @@ MODULE_DEVICE_TABLE(of, bma180_of_match);
static struct i2c_driver bma180_driver = {
.driver = {
.name = "bma180",
.acpi_match_table = ACPI_PTR(bma180_acpi_match),
.pm = BMA180_PM_OPS,
.of_match_table = bma180_of_match,
},

View File

@ -27,7 +27,6 @@
#define MMA9551_DRV_NAME "mma9551"
#define MMA9551_IRQ_NAME "mma9551_event"
#define MMA9551_GPIO_NAME "mma9551_int"
#define MMA9551_GPIO_COUNT 4
/* Tilt application (inclination in IIO terms). */
@ -418,8 +417,7 @@ static int mma9551_gpio_probe(struct iio_dev *indio_dev)
struct device *dev = &data->client->dev;
for (i = 0; i < MMA9551_GPIO_COUNT; i++) {
gpio = devm_gpiod_get_index(dev, MMA9551_GPIO_NAME, i,
GPIOD_IN);
gpio = devm_gpiod_get_index(dev, NULL, i, GPIOD_IN);
if (IS_ERR(gpio)) {
dev_err(dev, "acpi gpio get index failed\n");
return PTR_ERR(gpio);

View File

@ -47,15 +47,11 @@ static int st_accel_spi_remove(struct spi_device *spi)
}
static const struct spi_device_id st_accel_id_table[] = {
{ LSM303DLH_ACCEL_DEV_NAME },
{ LSM303DLHC_ACCEL_DEV_NAME },
{ LIS3DH_ACCEL_DEV_NAME },
{ LSM330D_ACCEL_DEV_NAME },
{ LSM330DL_ACCEL_DEV_NAME },
{ LSM330DLC_ACCEL_DEV_NAME },
{ LIS331DLH_ACCEL_DEV_NAME },
{ LSM303DL_ACCEL_DEV_NAME },
{ LSM303DLM_ACCEL_DEV_NAME },
{ LSM330_ACCEL_DEV_NAME },
{ LSM303AGR_ACCEL_DEV_NAME },
{ LIS2DH12_ACCEL_DEV_NAME },

View File

@ -272,11 +272,9 @@ static ssize_t ad7791_write_frequency(struct device *dev,
struct ad7791_state *st = iio_priv(indio_dev);
int i, ret;
for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++)
if (sysfs_streq(ad7791_sample_freq_avail[i], buf))
break;
if (i == ARRAY_SIZE(ad7791_sample_freq_avail))
return -EINVAL;
i = sysfs_match_string(ad7791_sample_freq_avail, buf);
if (i < 0)
return i;
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)

View File

@ -212,7 +212,10 @@ static int aspeed_adc_probe(struct platform_device *pdev)
}
/* Start all channels in normal mode. */
clk_prepare_enable(data->clk_scaler->clk);
ret = clk_prepare_enable(data->clk_scaler->clk);
if (ret)
goto clk_enable_error;
adc_engine_control_reg_val = GENMASK(31, 16) |
ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE;
writel(adc_engine_control_reg_val,
@ -236,6 +239,7 @@ iio_register_error:
writel(ASPEED_OPERATION_MODE_POWER_DOWN,
data->base + ASPEED_REG_ENGINE_CONTROL);
clk_disable_unprepare(data->clk_scaler->clk);
clk_enable_error:
clk_hw_unregister_divider(data->clk_scaler);
scaler_error:

View File

@ -52,6 +52,10 @@
#define CPCAP_BIT_RAND0 BIT(1) /* Set with CAL_MODE */
#define CPCAP_BIT_ADEN BIT(0) /* Currently unused */
#define CPCAP_REG_ADCC1_DEFAULTS (CPCAP_BIT_ADEN_AUTO_CLR | \
CPCAP_BIT_ADC_CLK_SEL0 | \
CPCAP_BIT_RAND1)
/* Register CPCAP_REG_ADCC2 bits */
#define CPCAP_BIT_CAL_FACTOR_ENABLE BIT(15) /* Currently unused */
#define CPCAP_BIT_BATDETB_EN BIT(14) /* Currently unused */
@ -62,7 +66,7 @@
#define CPCAP_BIT_ADC_PS_FACTOR0 BIT(9)
#define CPCAP_BIT_AD4_SELECT BIT(8) /* Currently unused */
#define CPCAP_BIT_ADC_BUSY BIT(7) /* Currently unused */
#define CPCAP_BIT_THERMBIAS_EN BIT(6) /* Currently unused */
#define CPCAP_BIT_THERMBIAS_EN BIT(6) /* Bias for AD0_BATTDETB */
#define CPCAP_BIT_ADTRIG_DIS BIT(5) /* Disable interrupt */
#define CPCAP_BIT_LIADC BIT(4) /* Currently unused */
#define CPCAP_BIT_TS_REFEN BIT(3) /* Currently unused */
@ -70,6 +74,12 @@
#define CPCAP_BIT_TS_M1 BIT(1) /* Currently unused */
#define CPCAP_BIT_TS_M0 BIT(0) /* Currently unused */
#define CPCAP_REG_ADCC2_DEFAULTS (CPCAP_BIT_AD4_SELECT | \
CPCAP_BIT_ADTRIG_DIS | \
CPCAP_BIT_LIADC | \
CPCAP_BIT_TS_M2 | \
CPCAP_BIT_TS_M1)
#define CPCAP_MAX_TEMP_LVL 27
#define CPCAP_FOUR_POINT_TWO_ADC 801
#define ST_ADC_CAL_CHRGI_HIGH_THRESHOLD 530
@ -78,7 +88,7 @@
#define ST_ADC_CAL_BATTI_LOW_THRESHOLD 494
#define ST_ADC_CALIBRATE_DIFF_THRESHOLD 3
#define CPCAP_ADC_MAX_RETRIES 5 /* Calibration and quirk */
#define CPCAP_ADC_MAX_RETRIES 5 /* Calibration */
/**
* struct cpcap_adc_ato - timing settings for cpcap adc
@ -124,10 +134,10 @@ struct cpcap_adc {
*/
enum cpcap_adc_channel {
/* Bank0 channels */
CPCAP_ADC_AD0_BATTDETB, /* Battery detection */
CPCAP_ADC_AD0, /* Battery temperature */
CPCAP_ADC_BATTP, /* Battery voltage */
CPCAP_ADC_VBUS, /* USB VBUS voltage */
CPCAP_ADC_AD3, /* Battery temperature when charging */
CPCAP_ADC_AD3, /* Die temperature when charging */
CPCAP_ADC_BPLUS_AD4, /* Another battery or system voltage */
CPCAP_ADC_CHG_ISENSE, /* Calibrated charge current */
CPCAP_ADC_BATTI, /* Calibrated system current */
@ -217,7 +227,7 @@ struct cpcap_adc_request {
/* Phasing table for channels. Note that channels 16 & 17 use BATTP and BATTI */
static const struct cpcap_adc_phasing_tbl bank_phasing[] = {
/* Bank0 */
[CPCAP_ADC_AD0_BATTDETB] = {0, 0x80, 0x80, 0, 1023},
[CPCAP_ADC_AD0] = {0, 0x80, 0x80, 0, 1023},
[CPCAP_ADC_BATTP] = {0, 0x80, 0x80, 0, 1023},
[CPCAP_ADC_VBUS] = {0, 0x80, 0x80, 0, 1023},
[CPCAP_ADC_AD3] = {0, 0x80, 0x80, 0, 1023},
@ -243,7 +253,7 @@ static const struct cpcap_adc_phasing_tbl bank_phasing[] = {
*/
static struct cpcap_adc_conversion_tbl bank_conversion[] = {
/* Bank0 */
[CPCAP_ADC_AD0_BATTDETB] = {
[CPCAP_ADC_AD0] = {
IIO_CHAN_INFO_PROCESSED, 0, 0, 0, 1, 1,
},
[CPCAP_ADC_BATTP] = {
@ -541,6 +551,15 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata,
return;
switch (req->channel) {
case CPCAP_ADC_AD0:
value2 |= CPCAP_BIT_THERMBIAS_EN;
error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
CPCAP_BIT_THERMBIAS_EN,
value2);
if (error)
return;
usleep_range(800, 1000);
break;
case CPCAP_ADC_AD8 ... CPCAP_ADC_TSY2_AD15:
value1 |= CPCAP_BIT_AD_SEL1;
break;
@ -583,7 +602,8 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata,
error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
CPCAP_BIT_ATOX_PS_FACTOR |
CPCAP_BIT_ADC_PS_FACTOR1 |
CPCAP_BIT_ADC_PS_FACTOR0,
CPCAP_BIT_ADC_PS_FACTOR0 |
CPCAP_BIT_THERMBIAS_EN,
value2);
if (error)
return;
@ -614,27 +634,6 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata,
}
}
/*
* Occasionally the ADC does not seem to start and there will be no
* interrupt. Let's re-init interrupt to prevent the ADC from hanging
* for the next request. It is unclear why this happens, but the next
* request will usually work after doing this.
*/
static void cpcap_adc_quirk_reset_lost_irq(struct cpcap_adc *ddata)
{
int error;
dev_info(ddata->dev, "lost ADC irq, attempting to reinit\n");
disable_irq(ddata->irq);
error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
CPCAP_BIT_ADTRIG_DIS,
CPCAP_BIT_ADTRIG_DIS);
if (error)
dev_warn(ddata->dev, "%s reset failed: %i\n",
__func__, error);
enable_irq(ddata->irq);
}
static int cpcap_adc_start_bank(struct cpcap_adc *ddata,
struct cpcap_adc_request *req)
{
@ -652,7 +651,6 @@ static int cpcap_adc_start_bank(struct cpcap_adc *ddata,
return 0;
if (error == 0) {
cpcap_adc_quirk_reset_lost_irq(ddata);
error = -ETIMEDOUT;
continue;
}
@ -664,6 +662,21 @@ static int cpcap_adc_start_bank(struct cpcap_adc *ddata,
return error;
}
static int cpcap_adc_stop_bank(struct cpcap_adc *ddata)
{
int error;
error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1,
0xffff,
CPCAP_REG_ADCC1_DEFAULTS);
if (error)
return error;
return regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
0xffff,
CPCAP_REG_ADCC2_DEFAULTS);
}
static void cpcap_adc_phase(struct cpcap_adc_request *req)
{
const struct cpcap_adc_conversion_tbl *conv_tbl = req->conv_tbl;
@ -758,7 +771,7 @@ static void cpcap_adc_convert(struct cpcap_adc_request *req)
return;
/* Temperatures use a lookup table instead of conversion table */
if ((req->channel == CPCAP_ADC_AD0_BATTDETB) ||
if ((req->channel == CPCAP_ADC_AD0) ||
(req->channel == CPCAP_ADC_AD3)) {
req->result =
cpcap_adc_table_to_millicelcius(req->result);
@ -820,7 +833,7 @@ static int cpcap_adc_init_request(struct cpcap_adc_request *req,
req->conv_tbl = bank_conversion;
switch (channel) {
case CPCAP_ADC_AD0_BATTDETB ... CPCAP_ADC_USB_ID:
case CPCAP_ADC_AD0 ... CPCAP_ADC_USB_ID:
req->bank_index = channel;
break;
case CPCAP_ADC_AD8 ... CPCAP_ADC_TSY2_AD15:
@ -839,6 +852,22 @@ static int cpcap_adc_init_request(struct cpcap_adc_request *req,
return 0;
}
static int cpcap_adc_read_st_die_temp(struct cpcap_adc *ddata,
int addr, int *val)
{
int error;
error = regmap_read(ddata->reg, addr, val);
if (error)
return error;
*val -= 282;
*val *= 114;
*val += 25000;
return 0;
}
static int cpcap_adc_read(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
@ -858,6 +887,9 @@ static int cpcap_adc_read(struct iio_dev *indio_dev,
if (error)
goto err_unlock;
error = regmap_read(ddata->reg, chan->address, val);
if (error)
goto err_unlock;
error = cpcap_adc_stop_bank(ddata);
if (error)
goto err_unlock;
mutex_unlock(&ddata->lock);
@ -867,7 +899,19 @@ static int cpcap_adc_read(struct iio_dev *indio_dev,
error = cpcap_adc_start_bank(ddata, &req);
if (error)
goto err_unlock;
error = cpcap_adc_read_bank_scaled(ddata, &req);
if ((ddata->vendor == CPCAP_VENDOR_ST) &&
(chan->channel == CPCAP_ADC_AD3)) {
error = cpcap_adc_read_st_die_temp(ddata,
chan->address,
&req.result);
if (error)
goto err_unlock;
} else {
error = cpcap_adc_read_bank_scaled(ddata, &req);
if (error)
goto err_unlock;
}
error = cpcap_adc_stop_bank(ddata);
if (error)
goto err_unlock;
mutex_unlock(&ddata->lock);

View File

@ -410,11 +410,11 @@ static const struct iio_chan_spec hi8435_channels[] = {
static const struct iio_info hi8435_info = {
.driver_module = THIS_MODULE,
.read_raw = hi8435_read_raw,
.read_event_config = &hi8435_read_event_config,
.read_event_config = hi8435_read_event_config,
.write_event_config = hi8435_write_event_config,
.read_event_value = &hi8435_read_event_value,
.write_event_value = &hi8435_write_event_value,
.debugfs_reg_access = &hi8435_debugfs_reg_access,
.read_event_value = hi8435_read_event_value,
.write_event_value = hi8435_write_event_value,
.debugfs_reg_access = hi8435_debugfs_reg_access,
};
static void hi8435_iio_push_event(struct iio_dev *idev, unsigned int val)
@ -476,15 +476,13 @@ static int hi8435_probe(struct spi_device *spi)
priv->spi = spi;
reset_gpio = devm_gpiod_get(&spi->dev, NULL, GPIOD_OUT_LOW);
if (!IS_ERR(reset_gpio)) {
/* need >=100ns low pulse to reset chip */
gpiod_set_raw_value_cansleep(reset_gpio, 0);
udelay(1);
gpiod_set_raw_value_cansleep(reset_gpio, 1);
} else {
/* s/w reset chip if h/w reset is not available */
if (IS_ERR(reset_gpio)) {
/* chip s/w reset if h/w reset failed */
hi8435_writeb(priv, HI8435_CTRL_REG, HI8435_CTRL_SRST);
hi8435_writeb(priv, HI8435_CTRL_REG, 0);
} else {
udelay(5);
gpiod_set_value(reset_gpio, 1);
}
spi_set_drvdata(spi, idev);

View File

@ -49,6 +49,7 @@
/* settings - depend on use case */
#define INA219_CONFIG_DEFAULT 0x399F /* PGA=8 */
#define INA219_DEFAULT_IT 532
#define INA226_CONFIG_DEFAULT 0x4327
#define INA226_DEFAULT_AVG 4
#define INA226_DEFAULT_IT 1110
@ -56,19 +57,24 @@
#define INA2XX_RSHUNT_DEFAULT 10000
/*
* bit mask for reading the averaging setting in the configuration register
* bit masks for reading the settings in the configuration register
* FIXME: use regmap_fields.
*/
#define INA2XX_MODE_MASK GENMASK(3, 0)
/* Averaging for VBus/VShunt/Power */
#define INA226_AVG_MASK GENMASK(11, 9)
#define INA226_SHIFT_AVG(val) ((val) << 9)
/* Integration time for VBus */
#define INA219_ITB_MASK GENMASK(10, 7)
#define INA219_SHIFT_ITB(val) ((val) << 7)
#define INA226_ITB_MASK GENMASK(8, 6)
#define INA226_SHIFT_ITB(val) ((val) << 6)
/* Integration time for VShunt */
#define INA219_ITS_MASK GENMASK(6, 3)
#define INA219_SHIFT_ITS(val) ((val) << 3)
#define INA226_ITS_MASK GENMASK(5, 3)
#define INA226_SHIFT_ITS(val) ((val) << 3)
@ -108,6 +114,7 @@ struct ina2xx_config {
int bus_voltage_shift;
int bus_voltage_lsb; /* uV */
int power_lsb; /* uW */
enum ina2xx_ids chip_id;
};
struct ina2xx_chip_info {
@ -130,6 +137,7 @@ static const struct ina2xx_config ina2xx_config[] = {
.bus_voltage_shift = 3,
.bus_voltage_lsb = 4000,
.power_lsb = 20000,
.chip_id = ina219,
},
[ina226] = {
.config_default = INA226_CONFIG_DEFAULT,
@ -138,6 +146,7 @@ static const struct ina2xx_config ina2xx_config[] = {
.bus_voltage_shift = 0,
.bus_voltage_lsb = 1250,
.power_lsb = 25000,
.chip_id = ina226,
},
};
@ -283,6 +292,66 @@ static int ina226_set_int_time_vshunt(struct ina2xx_chip_info *chip,
return 0;
}
/* Conversion times in uS. */
static const int ina219_conv_time_tab_subsample[] = { 84, 148, 276, 532 };
static const int ina219_conv_time_tab_average[] = { 532, 1060, 2130, 4260,
8510, 17020, 34050, 68100};
static int ina219_lookup_int_time(unsigned int *val_us, int *bits)
{
if (*val_us > 68100 || *val_us < 84)
return -EINVAL;
if (*val_us <= 532) {
*bits = find_closest(*val_us, ina219_conv_time_tab_subsample,
ARRAY_SIZE(ina219_conv_time_tab_subsample));
*val_us = ina219_conv_time_tab_subsample[*bits];
} else {
*bits = find_closest(*val_us, ina219_conv_time_tab_average,
ARRAY_SIZE(ina219_conv_time_tab_average));
*val_us = ina219_conv_time_tab_average[*bits];
*bits |= 0x8;
}
return 0;
}
static int ina219_set_int_time_vbus(struct ina2xx_chip_info *chip,
unsigned int val_us, unsigned int *config)
{
int bits, ret;
unsigned int val_us_best = val_us;
ret = ina219_lookup_int_time(&val_us_best, &bits);
if (ret)
return ret;
chip->int_time_vbus = val_us_best;
*config &= ~INA219_ITB_MASK;
*config |= INA219_SHIFT_ITB(bits) & INA219_ITB_MASK;
return 0;
}
static int ina219_set_int_time_vshunt(struct ina2xx_chip_info *chip,
unsigned int val_us, unsigned int *config)
{
int bits, ret;
unsigned int val_us_best = val_us;
ret = ina219_lookup_int_time(&val_us_best, &bits);
if (ret)
return ret;
chip->int_time_vshunt = val_us_best;
*config &= ~INA219_ITS_MASK;
*config |= INA219_SHIFT_ITS(bits) & INA219_ITS_MASK;
return 0;
}
static int ina2xx_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
@ -308,10 +377,21 @@ static int ina2xx_write_raw(struct iio_dev *indio_dev,
break;
case IIO_CHAN_INFO_INT_TIME:
if (chan->address == INA2XX_SHUNT_VOLTAGE)
ret = ina226_set_int_time_vshunt(chip, val2, &tmp);
else
ret = ina226_set_int_time_vbus(chip, val2, &tmp);
if (chip->config->chip_id == ina226) {
if (chan->address == INA2XX_SHUNT_VOLTAGE)
ret = ina226_set_int_time_vshunt(chip, val2,
&tmp);
else
ret = ina226_set_int_time_vbus(chip, val2,
&tmp);
} else {
if (chan->address == INA2XX_SHUNT_VOLTAGE)
ret = ina219_set_int_time_vshunt(chip, val2,
&tmp);
else
ret = ina219_set_int_time_vbus(chip, val2,
&tmp);
}
break;
default:
@ -412,7 +492,24 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
return len;
}
#define INA2XX_CHAN(_type, _index, _address) { \
#define INA219_CHAN(_type, _index, _address) { \
.type = (_type), \
.address = (_address), \
.indexed = 1, \
.channel = (_index), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.scan_index = (_index), \
.scan_type = { \
.sign = 'u', \
.realbits = 16, \
.storagebits = 16, \
.endianness = IIO_CPU, \
} \
}
#define INA226_CHAN(_type, _index, _address) { \
.type = (_type), \
.address = (_address), \
.indexed = 1, \
@ -434,7 +531,7 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
* Sampling Freq is a consequence of the integration times of
* the Voltage channels.
*/
#define INA2XX_CHAN_VOLTAGE(_index, _address) { \
#define INA219_CHAN_VOLTAGE(_index, _address) { \
.type = IIO_VOLTAGE, \
.address = (_address), \
.indexed = 1, \
@ -442,6 +539,7 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_INT_TIME), \
.info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.scan_index = (_index), \
.scan_type = { \
.sign = 'u', \
@ -451,11 +549,39 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
} \
}
static const struct iio_chan_spec ina2xx_channels[] = {
INA2XX_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE),
INA2XX_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE),
INA2XX_CHAN(IIO_POWER, 2, INA2XX_POWER),
INA2XX_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT),
#define INA226_CHAN_VOLTAGE(_index, _address) { \
.type = IIO_VOLTAGE, \
.address = (_address), \
.indexed = 1, \
.channel = (_index), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_INT_TIME), \
.info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
.scan_index = (_index), \
.scan_type = { \
.sign = 'u', \
.realbits = 16, \
.storagebits = 16, \
.endianness = IIO_LE, \
} \
}
static const struct iio_chan_spec ina226_channels[] = {
INA226_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE),
INA226_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE),
INA226_CHAN(IIO_POWER, 2, INA2XX_POWER),
INA226_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT),
IIO_CHAN_SOFT_TIMESTAMP(4),
};
static const struct iio_chan_spec ina219_channels[] = {
INA219_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE),
INA219_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE),
INA219_CHAN(IIO_POWER, 2, INA2XX_POWER),
INA219_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT),
IIO_CHAN_SOFT_TIMESTAMP(4),
};
@ -590,7 +716,14 @@ static int ina2xx_debug_reg(struct iio_dev *indio_dev,
}
/* Possible integration times for vshunt and vbus */
static IIO_CONST_ATTR_INT_TIME_AVAIL("0.000140 0.000204 0.000332 0.000588 0.001100 0.002116 0.004156 0.008244");
static IIO_CONST_ATTR_NAMED(ina219_integration_time_available,
integration_time_available,
"0.000084 0.000148 0.000276 0.000532 0.001060 0.002130 0.004260 0.008510 0.017020 0.034050 0.068100");
static IIO_CONST_ATTR_NAMED(ina226_integration_time_available,
integration_time_available,
"0.000140 0.000204 0.000332 0.000588 0.001100 0.002116 0.004156 0.008244");
static IIO_DEVICE_ATTR(in_allow_async_readout, S_IRUGO | S_IWUSR,
ina2xx_allow_async_readout_show,
@ -600,20 +733,39 @@ static IIO_DEVICE_ATTR(in_shunt_resistor, S_IRUGO | S_IWUSR,
ina2xx_shunt_resistor_show,
ina2xx_shunt_resistor_store, 0);
static struct attribute *ina2xx_attributes[] = {
static struct attribute *ina219_attributes[] = {
&iio_dev_attr_in_allow_async_readout.dev_attr.attr,
&iio_const_attr_integration_time_available.dev_attr.attr,
&iio_const_attr_ina219_integration_time_available.dev_attr.attr,
&iio_dev_attr_in_shunt_resistor.dev_attr.attr,
NULL,
};
static const struct attribute_group ina2xx_attribute_group = {
.attrs = ina2xx_attributes,
static struct attribute *ina226_attributes[] = {
&iio_dev_attr_in_allow_async_readout.dev_attr.attr,
&iio_const_attr_ina226_integration_time_available.dev_attr.attr,
&iio_dev_attr_in_shunt_resistor.dev_attr.attr,
NULL,
};
static const struct iio_info ina2xx_info = {
static const struct attribute_group ina219_attribute_group = {
.attrs = ina219_attributes,
};
static const struct attribute_group ina226_attribute_group = {
.attrs = ina226_attributes,
};
static const struct iio_info ina219_info = {
.driver_module = THIS_MODULE,
.attrs = &ina2xx_attribute_group,
.attrs = &ina219_attribute_group,
.read_raw = ina2xx_read_raw,
.write_raw = ina2xx_write_raw,
.debugfs_reg_access = ina2xx_debug_reg,
};
static const struct iio_info ina226_info = {
.driver_module = THIS_MODULE,
.attrs = &ina226_attribute_group,
.read_raw = ina2xx_read_raw,
.write_raw = ina2xx_write_raw,
.debugfs_reg_access = ina2xx_debug_reg,
@ -684,6 +836,10 @@ static int ina2xx_probe(struct i2c_client *client,
ina226_set_average(chip, INA226_DEFAULT_AVG, &val);
ina226_set_int_time_vbus(chip, INA226_DEFAULT_IT, &val);
ina226_set_int_time_vshunt(chip, INA226_DEFAULT_IT, &val);
} else {
chip->avg = 1;
ina219_set_int_time_vbus(chip, INA219_DEFAULT_IT, &val);
ina219_set_int_time_vshunt(chip, INA219_DEFAULT_IT, &val);
}
ret = ina2xx_init(chip, val);
@ -695,10 +851,16 @@ static int ina2xx_probe(struct i2c_client *client,
indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
indio_dev->dev.parent = &client->dev;
indio_dev->dev.of_node = client->dev.of_node;
indio_dev->channels = ina2xx_channels;
indio_dev->num_channels = ARRAY_SIZE(ina2xx_channels);
if (id->driver_data == ina226) {
indio_dev->channels = ina226_channels;
indio_dev->num_channels = ARRAY_SIZE(ina226_channels);
indio_dev->info = &ina226_info;
} else {
indio_dev->channels = ina219_channels;
indio_dev->num_channels = ARRAY_SIZE(ina219_channels);
indio_dev->info = &ina219_info;
}
indio_dev->name = id->name;
indio_dev->info = &ina2xx_info;
indio_dev->setup_ops = &ina2xx_setup_ops;
buffer = devm_iio_kfifo_allocate(&indio_dev->dev);

View File

@ -76,10 +76,14 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
long mask)
{
struct lpc32xx_adc_state *st = iio_priv(indio_dev);
int ret;
if (mask == IIO_CHAN_INFO_RAW) {
mutex_lock(&indio_dev->mlock);
clk_prepare_enable(st->clk);
ret = clk_prepare_enable(st->clk);
if (ret) {
mutex_unlock(&indio_dev->mlock);
return ret;
}
/* Measurement setup */
__raw_writel(LPC32XXAD_INTERNAL | (chan->address) |
LPC32XXAD_REFp | LPC32XXAD_REFm,

View File

@ -48,7 +48,7 @@
#define VREF_MV_BASE 1850
const char *mx23_lradc_adc_irq_names[] = {
static const char *mx23_lradc_adc_irq_names[] = {
"mxs-lradc-channel0",
"mxs-lradc-channel1",
"mxs-lradc-channel2",
@ -57,7 +57,7 @@ const char *mx23_lradc_adc_irq_names[] = {
"mxs-lradc-channel5",
};
const char *mx28_lradc_adc_irq_names[] = {
static const char *mx28_lradc_adc_irq_names[] = {
"mxs-lradc-thresh0",
"mxs-lradc-thresh1",
"mxs-lradc-channel0",
@ -344,20 +344,20 @@ static ssize_t mxs_lradc_adc_show_scale_avail(struct device *dev,
IIO_DEVICE_ATTR(in_voltage##ch##_scale_available, 0444,\
mxs_lradc_adc_show_scale_avail, NULL, ch)
SHOW_SCALE_AVAILABLE_ATTR(0);
SHOW_SCALE_AVAILABLE_ATTR(1);
SHOW_SCALE_AVAILABLE_ATTR(2);
SHOW_SCALE_AVAILABLE_ATTR(3);
SHOW_SCALE_AVAILABLE_ATTR(4);
SHOW_SCALE_AVAILABLE_ATTR(5);
SHOW_SCALE_AVAILABLE_ATTR(6);
SHOW_SCALE_AVAILABLE_ATTR(7);
SHOW_SCALE_AVAILABLE_ATTR(10);
SHOW_SCALE_AVAILABLE_ATTR(11);
SHOW_SCALE_AVAILABLE_ATTR(12);
SHOW_SCALE_AVAILABLE_ATTR(13);
SHOW_SCALE_AVAILABLE_ATTR(14);
SHOW_SCALE_AVAILABLE_ATTR(15);
static SHOW_SCALE_AVAILABLE_ATTR(0);
static SHOW_SCALE_AVAILABLE_ATTR(1);
static SHOW_SCALE_AVAILABLE_ATTR(2);
static SHOW_SCALE_AVAILABLE_ATTR(3);
static SHOW_SCALE_AVAILABLE_ATTR(4);
static SHOW_SCALE_AVAILABLE_ATTR(5);
static SHOW_SCALE_AVAILABLE_ATTR(6);
static SHOW_SCALE_AVAILABLE_ATTR(7);
static SHOW_SCALE_AVAILABLE_ATTR(10);
static SHOW_SCALE_AVAILABLE_ATTR(11);
static SHOW_SCALE_AVAILABLE_ATTR(12);
static SHOW_SCALE_AVAILABLE_ATTR(13);
static SHOW_SCALE_AVAILABLE_ATTR(14);
static SHOW_SCALE_AVAILABLE_ATTR(15);
static struct attribute *mxs_lradc_adc_attributes[] = {
&iio_dev_attr_in_voltage0_scale_available.dev_attr.attr,

View File

@ -49,19 +49,66 @@
/* STM32 F4 maximum analog clock rate (from datasheet) */
#define STM32F4_ADC_MAX_CLK_RATE 36000000
/* STM32H7 - common registers for all ADC instances */
#define STM32H7_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)
#define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08)
/* STM32H7_ADC_CSR - bit fields */
#define STM32H7_EOC_SLV BIT(18)
#define STM32H7_EOC_MST BIT(2)
/* STM32H7_ADC_CCR - bit fields */
#define STM32H7_PRESC_SHIFT 18
#define STM32H7_PRESC_MASK GENMASK(21, 18)
#define STM32H7_CKMODE_SHIFT 16
#define STM32H7_CKMODE_MASK GENMASK(17, 16)
/* STM32 H7 maximum analog clock rate (from datasheet) */
#define STM32H7_ADC_MAX_CLK_RATE 72000000
/**
* stm32_adc_common_regs - stm32 common registers, compatible dependent data
* @csr: common status register offset
* @eoc1: adc1 end of conversion flag in @csr
* @eoc2: adc2 end of conversion flag in @csr
* @eoc3: adc3 end of conversion flag in @csr
*/
struct stm32_adc_common_regs {
u32 csr;
u32 eoc1_msk;
u32 eoc2_msk;
u32 eoc3_msk;
};
struct stm32_adc_priv;
/**
* stm32_adc_priv_cfg - stm32 core compatible configuration data
* @regs: common registers for all instances
* @clk_sel: clock selection routine
*/
struct stm32_adc_priv_cfg {
const struct stm32_adc_common_regs *regs;
int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *);
};
/**
* struct stm32_adc_priv - stm32 ADC core private data
* @irq: irq for ADC block
* @domain: irq domain reference
* @aclk: clock reference for the analog circuitry
* @bclk: bus clock common for all ADCs, depends on part used
* @vref: regulator reference
* @cfg: compatible configuration data
* @common: common data for all ADC instances
*/
struct stm32_adc_priv {
int irq;
struct irq_domain *domain;
struct clk *aclk;
struct clk *bclk;
struct regulator *vref;
const struct stm32_adc_priv_cfg *cfg;
struct stm32_adc_common common;
};
@ -85,14 +132,23 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev,
u32 val;
int i;
/* stm32f4 has one clk input for analog (mandatory), enforce it here */
if (!priv->aclk) {
dev_err(&pdev->dev, "No 'adc' clock found\n");
return -ENOENT;
}
rate = clk_get_rate(priv->aclk);
for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) {
if ((rate / stm32f4_pclk_div[i]) <= STM32F4_ADC_MAX_CLK_RATE)
break;
}
if (i >= ARRAY_SIZE(stm32f4_pclk_div))
if (i >= ARRAY_SIZE(stm32f4_pclk_div)) {
dev_err(&pdev->dev, "adc clk selection failed\n");
return -EINVAL;
}
priv->common.rate = rate;
val = readl_relaxed(priv->common.base + STM32F4_ADC_CCR);
val &= ~STM32F4_ADC_ADCPRE_MASK;
val |= i << STM32F4_ADC_ADCPRE_SHIFT;
@ -104,6 +160,126 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev,
return 0;
}
/**
* struct stm32h7_adc_ck_spec - specification for stm32h7 adc clock
* @ckmode: ADC clock mode, Async or sync with prescaler.
* @presc: prescaler bitfield for async clock mode
* @div: prescaler division ratio
*/
struct stm32h7_adc_ck_spec {
u32 ckmode;
u32 presc;
int div;
};
const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = {
/* 00: CK_ADC[1..3]: Asynchronous clock modes */
{ 0, 0, 1 },
{ 0, 1, 2 },
{ 0, 2, 4 },
{ 0, 3, 6 },
{ 0, 4, 8 },
{ 0, 5, 10 },
{ 0, 6, 12 },
{ 0, 7, 16 },
{ 0, 8, 32 },
{ 0, 9, 64 },
{ 0, 10, 128 },
{ 0, 11, 256 },
/* HCLK used: Synchronous clock modes (1, 2 or 4 prescaler) */
{ 1, 0, 1 },
{ 2, 0, 2 },
{ 3, 0, 4 },
};
static int stm32h7_adc_clk_sel(struct platform_device *pdev,
struct stm32_adc_priv *priv)
{
u32 ckmode, presc, val;
unsigned long rate;
int i, div;
/* stm32h7 bus clock is common for all ADC instances (mandatory) */
if (!priv->bclk) {
dev_err(&pdev->dev, "No 'bus' clock found\n");
return -ENOENT;
}
/*
* stm32h7 can use either 'bus' or 'adc' clock for analog circuitry.
* So, choice is to have bus clock mandatory and adc clock optional.
* If optional 'adc' clock has been found, then try to use it first.
*/
if (priv->aclk) {
/*
* Asynchronous clock modes (e.g. ckmode == 0)
* From spec: PLL output musn't exceed max rate
*/
rate = clk_get_rate(priv->aclk);
for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
presc = stm32h7_adc_ckmodes_spec[i].presc;
div = stm32h7_adc_ckmodes_spec[i].div;
if (ckmode)
continue;
if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
goto out;
}
}
/* Synchronous clock modes (e.g. ckmode is 1, 2 or 3) */
rate = clk_get_rate(priv->bclk);
for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
presc = stm32h7_adc_ckmodes_spec[i].presc;
div = stm32h7_adc_ckmodes_spec[i].div;
if (!ckmode)
continue;
if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
goto out;
}
dev_err(&pdev->dev, "adc clk selection failed\n");
return -EINVAL;
out:
/* rate used later by each ADC instance to control BOOST mode */
priv->common.rate = rate;
/* Set common clock mode and prescaler */
val = readl_relaxed(priv->common.base + STM32H7_ADC_CCR);
val &= ~(STM32H7_CKMODE_MASK | STM32H7_PRESC_MASK);
val |= ckmode << STM32H7_CKMODE_SHIFT;
val |= presc << STM32H7_PRESC_SHIFT;
writel_relaxed(val, priv->common.base + STM32H7_ADC_CCR);
dev_dbg(&pdev->dev, "Using %s clock/%d source at %ld kHz\n",
ckmode ? "bus" : "adc", div, rate / (div * 1000));
return 0;
}
/* STM32F4 common registers definitions */
static const struct stm32_adc_common_regs stm32f4_adc_common_regs = {
.csr = STM32F4_ADC_CSR,
.eoc1_msk = STM32F4_EOC1,
.eoc2_msk = STM32F4_EOC2,
.eoc3_msk = STM32F4_EOC3,
};
/* STM32H7 common registers definitions */
static const struct stm32_adc_common_regs stm32h7_adc_common_regs = {
.csr = STM32H7_ADC_CSR,
.eoc1_msk = STM32H7_EOC_MST,
.eoc2_msk = STM32H7_EOC_SLV,
};
/* ADC common interrupt for all instances */
static void stm32_adc_irq_handler(struct irq_desc *desc)
{
@ -112,15 +288,15 @@ static void stm32_adc_irq_handler(struct irq_desc *desc)
u32 status;
chained_irq_enter(chip, desc);
status = readl_relaxed(priv->common.base + STM32F4_ADC_CSR);
status = readl_relaxed(priv->common.base + priv->cfg->regs->csr);
if (status & STM32F4_EOC1)
if (status & priv->cfg->regs->eoc1_msk)
generic_handle_irq(irq_find_mapping(priv->domain, 0));
if (status & STM32F4_EOC2)
if (status & priv->cfg->regs->eoc2_msk)
generic_handle_irq(irq_find_mapping(priv->domain, 1));
if (status & STM32F4_EOC3)
if (status & priv->cfg->regs->eoc3_msk)
generic_handle_irq(irq_find_mapping(priv->domain, 2));
chained_irq_exit(chip, desc);
@ -186,6 +362,7 @@ static void stm32_adc_irq_remove(struct platform_device *pdev,
static int stm32_adc_probe(struct platform_device *pdev)
{
struct stm32_adc_priv *priv;
struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
struct resource *res;
int ret;
@ -197,6 +374,9 @@ static int stm32_adc_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
priv->cfg = (const struct stm32_adc_priv_cfg *)
of_match_device(dev->driver->of_match_table, dev)->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->common.base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(priv->common.base))
@ -227,25 +407,48 @@ static int stm32_adc_probe(struct platform_device *pdev)
priv->aclk = devm_clk_get(&pdev->dev, "adc");
if (IS_ERR(priv->aclk)) {
ret = PTR_ERR(priv->aclk);
dev_err(&pdev->dev, "Can't get 'adc' clock\n");
goto err_regulator_disable;
if (ret == -ENOENT) {
priv->aclk = NULL;
} else {
dev_err(&pdev->dev, "Can't get 'adc' clock\n");
goto err_regulator_disable;
}
}
ret = clk_prepare_enable(priv->aclk);
if (ret < 0) {
dev_err(&pdev->dev, "adc clk enable failed\n");
goto err_regulator_disable;
if (priv->aclk) {
ret = clk_prepare_enable(priv->aclk);
if (ret < 0) {
dev_err(&pdev->dev, "adc clk enable failed\n");
goto err_regulator_disable;
}
}
ret = stm32f4_adc_clk_sel(pdev, priv);
if (ret < 0) {
dev_err(&pdev->dev, "adc clk selection failed\n");
goto err_clk_disable;
priv->bclk = devm_clk_get(&pdev->dev, "bus");
if (IS_ERR(priv->bclk)) {
ret = PTR_ERR(priv->bclk);
if (ret == -ENOENT) {
priv->bclk = NULL;
} else {
dev_err(&pdev->dev, "Can't get 'bus' clock\n");
goto err_aclk_disable;
}
}
if (priv->bclk) {
ret = clk_prepare_enable(priv->bclk);
if (ret < 0) {
dev_err(&pdev->dev, "adc clk enable failed\n");
goto err_aclk_disable;
}
}
ret = priv->cfg->clk_sel(pdev, priv);
if (ret < 0)
goto err_bclk_disable;
ret = stm32_adc_irq_probe(pdev, priv);
if (ret < 0)
goto err_clk_disable;
goto err_bclk_disable;
platform_set_drvdata(pdev, &priv->common);
@ -260,8 +463,13 @@ static int stm32_adc_probe(struct platform_device *pdev)
err_irq_remove:
stm32_adc_irq_remove(pdev, priv);
err_clk_disable:
clk_disable_unprepare(priv->aclk);
err_bclk_disable:
if (priv->bclk)
clk_disable_unprepare(priv->bclk);
err_aclk_disable:
if (priv->aclk)
clk_disable_unprepare(priv->aclk);
err_regulator_disable:
regulator_disable(priv->vref);
@ -276,15 +484,34 @@ static int stm32_adc_remove(struct platform_device *pdev)
of_platform_depopulate(&pdev->dev);
stm32_adc_irq_remove(pdev, priv);
clk_disable_unprepare(priv->aclk);
if (priv->bclk)
clk_disable_unprepare(priv->bclk);
if (priv->aclk)
clk_disable_unprepare(priv->aclk);
regulator_disable(priv->vref);
return 0;
}
static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = {
.regs = &stm32f4_adc_common_regs,
.clk_sel = stm32f4_adc_clk_sel,
};
static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = {
.regs = &stm32h7_adc_common_regs,
.clk_sel = stm32h7_adc_clk_sel,
};
static const struct of_device_id stm32_adc_of_match[] = {
{ .compatible = "st,stm32f4-adc-core" },
{},
{
.compatible = "st,stm32f4-adc-core",
.data = (void *)&stm32f4_adc_priv_cfg
}, {
.compatible = "st,stm32h7-adc-core",
.data = (void *)&stm32h7_adc_priv_cfg
}, {
},
};
MODULE_DEVICE_TABLE(of, stm32_adc_of_match);

View File

@ -43,11 +43,13 @@
* struct stm32_adc_common - stm32 ADC driver common data (for all instances)
* @base: control registers base cpu addr
* @phys_base: control registers base physical addr
* @rate: clock rate used for analog circuitry
* @vref_mv: vref voltage (mv)
*/
struct stm32_adc_common {
void __iomem *base;
phys_addr_t phys_base;
unsigned long rate;
int vref_mv;
};

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,6 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/i2c/twl.h>
#include <linux/i2c/twl4030-madc.h>
#include <linux/module.h>
#include <linux/stddef.h>
#include <linux/mutex.h>
@ -49,9 +48,121 @@
#include <linux/iio/iio.h>
#define TWL4030_MADC_MAX_CHANNELS 16
#define TWL4030_MADC_CTRL1 0x00
#define TWL4030_MADC_CTRL2 0x01
#define TWL4030_MADC_RTSELECT_LSB 0x02
#define TWL4030_MADC_SW1SELECT_LSB 0x06
#define TWL4030_MADC_SW2SELECT_LSB 0x0A
#define TWL4030_MADC_RTAVERAGE_LSB 0x04
#define TWL4030_MADC_SW1AVERAGE_LSB 0x08
#define TWL4030_MADC_SW2AVERAGE_LSB 0x0C
#define TWL4030_MADC_CTRL_SW1 0x12
#define TWL4030_MADC_CTRL_SW2 0x13
#define TWL4030_MADC_RTCH0_LSB 0x17
#define TWL4030_MADC_GPCH0_LSB 0x37
#define TWL4030_MADC_MADCON (1 << 0) /* MADC power on */
#define TWL4030_MADC_BUSY (1 << 0) /* MADC busy */
/* MADC conversion completion */
#define TWL4030_MADC_EOC_SW (1 << 1)
/* MADC SWx start conversion */
#define TWL4030_MADC_SW_START (1 << 5)
#define TWL4030_MADC_ADCIN0 (1 << 0)
#define TWL4030_MADC_ADCIN1 (1 << 1)
#define TWL4030_MADC_ADCIN2 (1 << 2)
#define TWL4030_MADC_ADCIN3 (1 << 3)
#define TWL4030_MADC_ADCIN4 (1 << 4)
#define TWL4030_MADC_ADCIN5 (1 << 5)
#define TWL4030_MADC_ADCIN6 (1 << 6)
#define TWL4030_MADC_ADCIN7 (1 << 7)
#define TWL4030_MADC_ADCIN8 (1 << 8)
#define TWL4030_MADC_ADCIN9 (1 << 9)
#define TWL4030_MADC_ADCIN10 (1 << 10)
#define TWL4030_MADC_ADCIN11 (1 << 11)
#define TWL4030_MADC_ADCIN12 (1 << 12)
#define TWL4030_MADC_ADCIN13 (1 << 13)
#define TWL4030_MADC_ADCIN14 (1 << 14)
#define TWL4030_MADC_ADCIN15 (1 << 15)
/* Fixed channels */
#define TWL4030_MADC_BTEMP TWL4030_MADC_ADCIN1
#define TWL4030_MADC_VBUS TWL4030_MADC_ADCIN8
#define TWL4030_MADC_VBKB TWL4030_MADC_ADCIN9
#define TWL4030_MADC_ICHG TWL4030_MADC_ADCIN10
#define TWL4030_MADC_VCHG TWL4030_MADC_ADCIN11
#define TWL4030_MADC_VBAT TWL4030_MADC_ADCIN12
/* Step size and prescaler ratio */
#define TEMP_STEP_SIZE 147
#define TEMP_PSR_R 100
#define CURR_STEP_SIZE 147
#define CURR_PSR_R1 44
#define CURR_PSR_R2 88
#define TWL4030_BCI_BCICTL1 0x23
#define TWL4030_BCI_CGAIN 0x020
#define TWL4030_BCI_MESBAT (1 << 1)
#define TWL4030_BCI_TYPEN (1 << 4)
#define TWL4030_BCI_ITHEN (1 << 3)
#define REG_BCICTL2 0x024
#define TWL4030_BCI_ITHSENS 0x007
/* Register and bits for GPBR1 register */
#define TWL4030_REG_GPBR1 0x0c
#define TWL4030_GPBR1_MADC_HFCLK_EN (1 << 7)
#define TWL4030_USB_SEL_MADC_MCPC (1<<3)
#define TWL4030_USB_CARKIT_ANA_CTRL 0xBB
struct twl4030_madc_conversion_method {
u8 sel;
u8 avg;
u8 rbase;
u8 ctrl;
};
/**
* struct twl4030_madc_request - madc request packet for channel conversion
* @channels: 16 bit bitmap for individual channels
* @do_avg: sample the input channel for 4 consecutive cycles
* @method: RT, SW1, SW2
* @type: Polling or interrupt based method
* @active: Flag if request is active
* @result_pending: Flag from irq handler, that result is ready
* @raw: Return raw value, do not convert it
* @rbuf: Result buffer
*/
struct twl4030_madc_request {
unsigned long channels;
bool do_avg;
u16 method;
u16 type;
bool active;
bool result_pending;
bool raw;
int rbuf[TWL4030_MADC_MAX_CHANNELS];
};
enum conversion_methods {
TWL4030_MADC_RT,
TWL4030_MADC_SW1,
TWL4030_MADC_SW2,
TWL4030_MADC_NUM_METHODS
};
enum sample_type {
TWL4030_MADC_WAIT,
TWL4030_MADC_IRQ_ONESHOT,
TWL4030_MADC_IRQ_REARM
};
/**
* struct twl4030_madc_data - a container for madc info
* @dev: Pointer to device structure for madc
@ -72,6 +183,8 @@ struct twl4030_madc_data {
u8 isr;
};
static int twl4030_madc_conversion(struct twl4030_madc_request *req);
static int twl4030_madc_read(struct iio_dev *iio_dev,
const struct iio_chan_spec *chan,
int *val, int *val2, long mask)
@ -84,7 +197,6 @@ static int twl4030_madc_read(struct iio_dev *iio_dev,
req.channels = BIT(chan->channel);
req.active = false;
req.func_cb = NULL;
req.type = TWL4030_MADC_WAIT;
req.raw = !(mask == IIO_CHAN_INFO_PROCESSED);
req.do_avg = (mask == IIO_CHAN_INFO_AVERAGE_RAW);
@ -340,37 +452,6 @@ static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
return count;
}
/*
* Enables irq.
* @madc - pointer to twl4030_madc_data struct
* @id - irq number to be enabled
* can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
* corresponding to RT, SW1, SW2 conversion requests.
* If the i2c read fails it returns an error else returns 0.
*/
static int twl4030_madc_enable_irq(struct twl4030_madc_data *madc, u8 id)
{
u8 val;
int ret;
ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
if (ret) {
dev_err(madc->dev, "unable to read imr register 0x%X\n",
madc->imr);
return ret;
}
val &= ~(1 << id);
ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
if (ret) {
dev_err(madc->dev,
"unable to write imr register 0x%X\n", madc->imr);
return ret;
}
return 0;
}
/*
* Disables irq.
* @madc - pointer to twl4030_madc_data struct
@ -440,11 +521,6 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
/* Read results */
len = twl4030_madc_read_channels(madc, method->rbase,
r->channels, r->rbuf, r->raw);
/* Return results to caller */
if (r->func_cb != NULL) {
r->func_cb(len, r->channels, r->rbuf);
r->func_cb = NULL;
}
/* Free request */
r->result_pending = 0;
r->active = 0;
@ -466,11 +542,6 @@ err_i2c:
/* Read results */
len = twl4030_madc_read_channels(madc, method->rbase,
r->channels, r->rbuf, r->raw);
/* Return results to caller */
if (r->func_cb != NULL) {
r->func_cb(len, r->channels, r->rbuf);
r->func_cb = NULL;
}
/* Free request */
r->result_pending = 0;
r->active = 0;
@ -480,23 +551,6 @@ err_i2c:
return IRQ_HANDLED;
}
static int twl4030_madc_set_irq(struct twl4030_madc_data *madc,
struct twl4030_madc_request *req)
{
struct twl4030_madc_request *p;
int ret;
p = &madc->requests[req->method];
memcpy(p, req, sizeof(*req));
ret = twl4030_madc_enable_irq(madc, req->method);
if (ret < 0) {
dev_err(madc->dev, "enable irq failed!!\n");
return ret;
}
return 0;
}
/*
* Function which enables the madc conversion
* by writing to the control register.
@ -568,7 +622,7 @@ static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc,
* be a negative error value in the corresponding array element.
* returns 0 if succeeds else error value
*/
int twl4030_madc_conversion(struct twl4030_madc_request *req)
static int twl4030_madc_conversion(struct twl4030_madc_request *req)
{
const struct twl4030_madc_conversion_method *method;
int ret;
@ -605,17 +659,6 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
goto out;
}
}
if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) {
ret = twl4030_madc_set_irq(twl4030_madc, req);
if (ret < 0)
goto out;
ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
if (ret < 0)
goto out;
twl4030_madc->requests[req->method].active = 1;
ret = 0;
goto out;
}
/* With RT method we should not be here anymore */
if (req->method == TWL4030_MADC_RT) {
ret = -EINVAL;
@ -640,28 +683,6 @@ out:
return ret;
}
EXPORT_SYMBOL_GPL(twl4030_madc_conversion);
int twl4030_get_madc_conversion(int channel_no)
{
struct twl4030_madc_request req;
int temp = 0;
int ret;
req.channels = (1 << channel_no);
req.method = TWL4030_MADC_SW2;
req.active = 0;
req.raw = 0;
req.func_cb = NULL;
ret = twl4030_madc_conversion(&req);
if (ret < 0)
return ret;
if (req.rbuf[channel_no] > 0)
temp = req.rbuf[channel_no];
return temp;
}
EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion);
/**
* twl4030_madc_set_current_generator() - setup bias current

View File

@ -1204,7 +1204,10 @@ static int xadc_probe(struct platform_device *pdev)
ret = PTR_ERR(xadc->clk);
goto err_free_samplerate_trigger;
}
clk_prepare_enable(xadc->clk);
ret = clk_prepare_enable(xadc->clk);
if (ret)
goto err_free_samplerate_trigger;
ret = xadc->ops->setup(pdev, indio_dev, irq);
if (ret)

View File

@ -16,7 +16,7 @@ config HID_SENSOR_IIO_COMMON
config HID_SENSOR_IIO_TRIGGER
tristate "Common module (trigger) for all HID Sensor IIO drivers"
depends on HID_SENSOR_HUB && HID_SENSOR_IIO_COMMON
depends on HID_SENSOR_HUB && HID_SENSOR_IIO_COMMON && IIO_BUFFER
select IIO_TRIGGER
help
Say yes here to build trigger support for HID sensors.

View File

@ -188,7 +188,6 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
int result = 0;
if (power_on) {
/* Already under indio-dev->mlock mutex */
if (!st->powerup_count)
result = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
if (!result)
@ -329,50 +328,37 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
int result;
ret = IIO_VAL_INT;
result = 0;
mutex_lock(&indio_dev->mlock);
if (!st->chip_config.enable) {
result = inv_mpu6050_set_power_itg(st, true);
if (result)
goto error_read_raw;
}
/* when enable is on, power is already on */
mutex_lock(&st->lock);
result = iio_device_claim_direct_mode(indio_dev);
if (result)
goto error_read_raw_unlock;
result = inv_mpu6050_set_power_itg(st, true);
if (result)
goto error_read_raw_release;
switch (chan->type) {
case IIO_ANGL_VEL:
if (!st->chip_config.gyro_fifo_enable ||
!st->chip_config.enable) {
result = inv_mpu6050_switch_engine(st, true,
INV_MPU6050_BIT_PWR_GYRO_STBY);
if (result)
goto error_read_raw;
}
result = inv_mpu6050_switch_engine(st, true,
INV_MPU6050_BIT_PWR_GYRO_STBY);
if (result)
goto error_read_raw_power_off;
ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro,
chan->channel2, val);
if (!st->chip_config.gyro_fifo_enable ||
!st->chip_config.enable) {
result = inv_mpu6050_switch_engine(st, false,
INV_MPU6050_BIT_PWR_GYRO_STBY);
if (result)
goto error_read_raw;
}
result = inv_mpu6050_switch_engine(st, false,
INV_MPU6050_BIT_PWR_GYRO_STBY);
if (result)
goto error_read_raw_power_off;
break;
case IIO_ACCEL:
if (!st->chip_config.accl_fifo_enable ||
!st->chip_config.enable) {
result = inv_mpu6050_switch_engine(st, true,
INV_MPU6050_BIT_PWR_ACCL_STBY);
if (result)
goto error_read_raw;
}
result = inv_mpu6050_switch_engine(st, true,
INV_MPU6050_BIT_PWR_ACCL_STBY);
if (result)
goto error_read_raw_power_off;
ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl,
chan->channel2, val);
if (!st->chip_config.accl_fifo_enable ||
!st->chip_config.enable) {
result = inv_mpu6050_switch_engine(st, false,
INV_MPU6050_BIT_PWR_ACCL_STBY);
if (result)
goto error_read_raw;
}
result = inv_mpu6050_switch_engine(st, false,
INV_MPU6050_BIT_PWR_ACCL_STBY);
if (result)
goto error_read_raw_power_off;
break;
case IIO_TEMP:
/* wait for stablization */
@ -384,10 +370,12 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
ret = -EINVAL;
break;
}
error_read_raw:
if (!st->chip_config.enable)
result |= inv_mpu6050_set_power_itg(st, false);
mutex_unlock(&indio_dev->mlock);
error_read_raw_power_off:
result |= inv_mpu6050_set_power_itg(st, false);
error_read_raw_release:
iio_device_release_direct_mode(indio_dev);
error_read_raw_unlock:
mutex_unlock(&st->lock);
if (result)
return result;
@ -396,13 +384,17 @@ error_read_raw:
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_ANGL_VEL:
mutex_lock(&st->lock);
*val = 0;
*val2 = gyro_scale_6050[st->chip_config.fsr];
mutex_unlock(&st->lock);
return IIO_VAL_INT_PLUS_NANO;
case IIO_ACCEL:
mutex_lock(&st->lock);
*val = 0;
*val2 = accel_scale[st->chip_config.accl_fs];
mutex_unlock(&st->lock);
return IIO_VAL_INT_PLUS_MICRO;
case IIO_TEMP:
@ -425,12 +417,16 @@ error_read_raw:
case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) {
case IIO_ANGL_VEL:
mutex_lock(&st->lock);
ret = inv_mpu6050_sensor_show(st, st->reg->gyro_offset,
chan->channel2, val);
mutex_unlock(&st->lock);
return IIO_VAL_INT;
case IIO_ACCEL:
mutex_lock(&st->lock);
ret = inv_mpu6050_sensor_show(st, st->reg->accl_offset,
chan->channel2, val);
mutex_unlock(&st->lock);
return IIO_VAL_INT;
default:
@ -506,18 +502,17 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
struct inv_mpu6050_state *st = iio_priv(indio_dev);
int result;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
/*
* we should only update scale when the chip is disabled, i.e.
* not running
*/
if (st->chip_config.enable) {
result = -EBUSY;
goto error_write_raw;
}
result = iio_device_claim_direct_mode(indio_dev);
if (result)
goto error_write_raw_unlock;
result = inv_mpu6050_set_power_itg(st, true);
if (result)
goto error_write_raw;
goto error_write_raw_release;
switch (mask) {
case IIO_CHAN_INFO_SCALE:
@ -553,9 +548,11 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
break;
}
error_write_raw:
result |= inv_mpu6050_set_power_itg(st, false);
mutex_unlock(&indio_dev->mlock);
error_write_raw_release:
iio_device_release_direct_mode(indio_dev);
error_write_raw_unlock:
mutex_unlock(&st->lock);
return result;
}
@ -611,31 +608,35 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr,
if (fifo_rate < INV_MPU6050_MIN_FIFO_RATE ||
fifo_rate > INV_MPU6050_MAX_FIFO_RATE)
return -EINVAL;
if (fifo_rate == st->chip_config.fifo_rate)
return count;
mutex_lock(&indio_dev->mlock);
if (st->chip_config.enable) {
result = -EBUSY;
goto fifo_rate_fail;
mutex_lock(&st->lock);
if (fifo_rate == st->chip_config.fifo_rate) {
result = 0;
goto fifo_rate_fail_unlock;
}
result = iio_device_claim_direct_mode(indio_dev);
if (result)
goto fifo_rate_fail_unlock;
result = inv_mpu6050_set_power_itg(st, true);
if (result)
goto fifo_rate_fail;
goto fifo_rate_fail_release;
d = INV_MPU6050_ONE_K_HZ / fifo_rate - 1;
result = regmap_write(st->map, st->reg->sample_rate_div, d);
if (result)
goto fifo_rate_fail;
goto fifo_rate_fail_power_off;
st->chip_config.fifo_rate = fifo_rate;
result = inv_mpu6050_set_lpf(st, fifo_rate);
if (result)
goto fifo_rate_fail;
goto fifo_rate_fail_power_off;
fifo_rate_fail:
fifo_rate_fail_power_off:
result |= inv_mpu6050_set_power_itg(st, false);
mutex_unlock(&indio_dev->mlock);
fifo_rate_fail_release:
iio_device_release_direct_mode(indio_dev);
fifo_rate_fail_unlock:
mutex_unlock(&st->lock);
if (result)
return result;
@ -650,8 +651,13 @@ inv_fifo_rate_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev));
unsigned fifo_rate;
return sprintf(buf, "%d\n", st->chip_config.fifo_rate);
mutex_lock(&st->lock);
fifo_rate = st->chip_config.fifo_rate;
mutex_unlock(&st->lock);
return scnprintf(buf, PAGE_SIZE, "%u\n", fifo_rate);
}
/**
@ -678,7 +684,8 @@ static ssize_t inv_attr_show(struct device *dev, struct device_attribute *attr,
case ATTR_ACCL_MATRIX:
m = st->plat_data.orientation;
return sprintf(buf, "%d, %d, %d; %d, %d, %d; %d, %d, %d\n",
return scnprintf(buf, PAGE_SIZE,
"%d, %d, %d; %d, %d, %d; %d, %d, %d\n",
m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
default:
return -EINVAL;
@ -803,10 +810,35 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
{
int result;
unsigned int regval;
int i;
st->hw = &hw_info[st->chip_type];
st->reg = hw_info[st->chip_type].reg;
/* check chip self-identification */
result = regmap_read(st->map, INV_MPU6050_REG_WHOAMI, &regval);
if (result)
return result;
if (regval != st->hw->whoami) {
/* check whoami against all possible values */
for (i = 0; i < INV_NUM_PARTS; ++i) {
if (regval == hw_info[i].whoami) {
dev_warn(regmap_get_device(st->map),
"whoami mismatch got %#02x (%s)"
"expected %#02hhx (%s)\n",
regval, hw_info[i].name,
st->hw->whoami, st->hw->name);
break;
}
}
if (i >= INV_NUM_PARTS) {
dev_err(regmap_get_device(st->map),
"invalid whoami %#02x expected %#02hhx (%s)\n",
regval, st->hw->whoami, st->hw->name);
return -ENODEV;
}
}
/* reset to make sure previous state are not there */
result = regmap_write(st->map, st->reg->pwr_mgmt_1,
INV_MPU6050_BIT_H_RESET);
@ -814,16 +846,6 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
return result;
msleep(INV_MPU6050_POWER_UP_TIME);
/* check chip self-identification */
result = regmap_read(st->map, INV_MPU6050_REG_WHOAMI, &regval);
if (result)
return result;
if (regval != st->hw->whoami) {
dev_warn(regmap_get_device(st->map),
"whoami mismatch got %#02x expected %#02hhx for %s\n",
regval, st->hw->whoami, st->hw->name);
}
/*
* toggle power state. After reset, the sleep bit could be on
* or off depending on the OTP settings. Toggling power would
@ -869,6 +891,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
return -ENODEV;
}
st = iio_priv(indio_dev);
mutex_init(&st->lock);
st->chip_type = chip_type;
st->powerup_count = 0;
st->irq = irq;
@ -962,12 +985,26 @@ EXPORT_SYMBOL_GPL(inv_mpu_core_remove);
static int inv_mpu_resume(struct device *dev)
{
return inv_mpu6050_set_power_itg(iio_priv(dev_get_drvdata(dev)), true);
struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev));
int result;
mutex_lock(&st->lock);
result = inv_mpu6050_set_power_itg(st, true);
mutex_unlock(&st->lock);
return result;
}
static int inv_mpu_suspend(struct device *dev)
{
return inv_mpu6050_set_power_itg(iio_priv(dev_get_drvdata(dev)), false);
struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev));
int result;
mutex_lock(&st->lock);
result = inv_mpu6050_set_power_itg(st, false);
mutex_unlock(&st->lock);
return result;
}
#endif /* CONFIG_PM_SLEEP */

View File

@ -32,7 +32,7 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
int ret = 0;
/* Use the same mutex which was used everywhere to protect power-op */
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
if (!st->powerup_count) {
ret = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
if (ret)
@ -48,7 +48,7 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
INV_MPU6050_BIT_BYPASS_EN);
}
write_error:
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -58,14 +58,14 @@ static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id)
struct iio_dev *indio_dev = i2c_mux_priv(muxc);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
/* It doesn't really mattter, if any of the calls fails */
regmap_write(st->map, st->reg->int_pin_cfg, INV_MPU6050_INT_PIN_CFG);
st->powerup_count--;
if (!st->powerup_count)
regmap_write(st->map, st->reg->pwr_mgmt_1,
INV_MPU6050_BIT_SLEEP);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return 0;
}

View File

@ -14,6 +14,7 @@
#include <linux/i2c-mux.h>
#include <linux/kfifo.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/regmap.h>
@ -82,7 +83,6 @@ enum inv_devices {
* @fsr: Full scale range.
* @lpf: Digital low pass filter frequency.
* @accl_fs: accel full scale range.
* @enable: master enable state.
* @accl_fifo_enable: enable accel data output
* @gyro_fifo_enable: enable gyro data output
* @fifo_rate: FIFO update rate.
@ -91,7 +91,6 @@ struct inv_mpu6050_chip_config {
unsigned int fsr:2;
unsigned int lpf:3;
unsigned int accl_fs:2;
unsigned int enable:1;
unsigned int accl_fifo_enable:1;
unsigned int gyro_fifo_enable:1;
u16 fifo_rate;
@ -114,6 +113,7 @@ struct inv_mpu6050_hw {
/*
* struct inv_mpu6050_state - Driver state variables.
* @TIMESTAMP_FIFO_SIZE: fifo size for timestamp.
* @lock: Chip access lock.
* @trig: IIO trigger.
* @chip_config: Cached attribute information.
* @reg: Map of important registers.
@ -128,6 +128,7 @@ struct inv_mpu6050_hw {
*/
struct inv_mpu6050_state {
#define TIMESTAMP_FIFO_SIZE 16
struct mutex lock;
struct iio_trigger *trig;
struct inv_mpu6050_chip_config chip_config;
const struct inv_mpu6050_reg_map *reg;

View File

@ -128,7 +128,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
u16 fifo_count;
s64 timestamp;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
if (!(st->chip_config.accl_fifo_enable |
st->chip_config.gyro_fifo_enable))
goto end_session;
@ -178,7 +178,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
}
end_session:
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
@ -186,7 +186,7 @@ end_session:
flush_fifo:
/* Flush HW and SW FIFOs. */
inv_reset_fifo(indio_dev);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;

View File

@ -90,7 +90,6 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
if (result)
return result;
}
st->chip_config.enable = enable;
return 0;
}
@ -103,7 +102,15 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
static int inv_mpu_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
return inv_mpu6050_set_enable(iio_trigger_get_drvdata(trig), state);
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
int result;
mutex_lock(&st->lock);
result = inv_mpu6050_set_enable(indio_dev, state);
mutex_unlock(&st->lock);
return result;
}
static const struct iio_trigger_ops inv_mpu_trigger_ops = {

View File

@ -37,6 +37,8 @@
#define ST_LSM6DSX_REG_FIFO_THH_ADDR 0x07
#define ST_LSM6DSX_FIFO_TH_MASK GENMASK(11, 0)
#define ST_LSM6DSX_REG_FIFO_DEC_GXL_ADDR 0x08
#define ST_LSM6DSX_REG_HLACTIVE_ADDR 0x12
#define ST_LSM6DSX_REG_HLACTIVE_MASK BIT(5)
#define ST_LSM6DSX_REG_FIFO_MODE_ADDR 0x0a
#define ST_LSM6DSX_FIFO_MODE_MASK GENMASK(2, 0)
#define ST_LSM6DSX_FIFO_ODR_MASK GENMASK(6, 3)
@ -417,6 +419,7 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
{
struct iio_buffer *buffer;
unsigned long irq_type;
bool irq_active_low;
int i, err;
irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
@ -424,12 +427,23 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
irq_active_low = false;
break;
case IRQF_TRIGGER_LOW:
case IRQF_TRIGGER_FALLING:
irq_active_low = true;
break;
default:
dev_info(hw->dev, "mode %lx unsupported\n", irq_type);
return -EINVAL;
}
err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_HLACTIVE_ADDR,
ST_LSM6DSX_REG_HLACTIVE_MASK,
irq_active_low);
if (err < 0)
return err;
err = devm_request_threaded_irq(hw->dev, hw->irq,
st_lsm6dsx_handler_irq,
st_lsm6dsx_handler_thread,

View File

@ -478,21 +478,16 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev,
size_t len)
{
const struct iio_enum *e = (const struct iio_enum *)priv;
unsigned int i;
int ret;
if (!e->set)
return -EINVAL;
for (i = 0; i < e->num_items; i++) {
if (sysfs_streq(buf, e->items[i]))
break;
}
ret = __sysfs_match_string(e->items, e->num_items, buf);
if (ret < 0)
return ret;
if (i == e->num_items)
return -EINVAL;
ret = e->set(indio_dev, chan, i);
ret = e->set(indio_dev, chan, ret);
return ret ? ret : len;
}
EXPORT_SYMBOL_GPL(iio_enum_write);
@ -1428,7 +1423,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
static void iio_dev_release(struct device *device)
{
struct iio_dev *indio_dev = dev_to_iio_dev(device);
if (indio_dev->modes & (INDIO_BUFFER_TRIGGERED | INDIO_EVENT_TRIGGERED))
if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES)
iio_device_unregister_trigger_consumer(indio_dev);
iio_device_unregister_eventset(indio_dev);
iio_device_unregister_sysfs(indio_dev);
@ -1710,7 +1705,7 @@ int iio_device_register(struct iio_dev *indio_dev)
"Failed to register event set\n");
goto error_free_sysfs;
}
if (indio_dev->modes & (INDIO_BUFFER_TRIGGERED | INDIO_EVENT_TRIGGERED))
if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES)
iio_device_register_trigger_consumer(indio_dev);
if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) &&

View File

@ -48,8 +48,6 @@ static int st_magn_spi_remove(struct spi_device *spi)
}
static const struct spi_device_id st_magn_id_table[] = {
{ LSM303DLHC_MAGN_DEV_NAME },
{ LSM303DLM_MAGN_DEV_NAME },
{ LIS3MDL_MAGN_DEV_NAME },
{ LSM303AGR_MAGN_DEV_NAME },
{},

View File

@ -878,8 +878,7 @@ static void sx9500_gpio_probe(struct i2c_client *client,
dev = &client->dev;
data->gpiod_rst = devm_gpiod_get_index(dev, SX9500_GPIO_RESET,
0, GPIOD_OUT_HIGH);
data->gpiod_rst = devm_gpiod_get(dev, SX9500_GPIO_RESET, GPIOD_OUT_HIGH);
if (IS_ERR(data->gpiod_rst)) {
dev_warn(dev, "gpio get reset pin failed\n");
data->gpiod_rst = NULL;

View File

@ -417,12 +417,70 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
static int stm32_counter_validate_trigger(struct iio_dev *indio_dev,
struct iio_trigger *trig)
{
struct stm32_timer_trigger *priv = iio_priv(indio_dev);
const char * const *cur = priv->valids;
unsigned int i = 0;
if (!is_stm32_timer_trigger(trig))
return -EINVAL;
while (cur && *cur) {
if (!strncmp(trig->name, *cur, strlen(trig->name))) {
regmap_update_bits(priv->regmap,
TIM_SMCR, TIM_SMCR_TS,
i << TIM_SMCR_TS_SHIFT);
return 0;
}
cur++;
i++;
}
return -EINVAL;
}
static const struct iio_info stm32_trigger_info = {
.driver_module = THIS_MODULE,
.validate_trigger = stm32_counter_validate_trigger,
.read_raw = stm32_counter_read_raw,
.write_raw = stm32_counter_write_raw
};
static const char *const stm32_trigger_modes[] = {
"trigger",
};
static int stm32_set_trigger_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
unsigned int mode)
{
struct stm32_timer_trigger *priv = iio_priv(indio_dev);
regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, TIM_SMCR_SMS);
return 0;
}
static int stm32_get_trigger_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
struct stm32_timer_trigger *priv = iio_priv(indio_dev);
u32 smcr;
regmap_read(priv->regmap, TIM_SMCR, &smcr);
return smcr == TIM_SMCR_SMS ? 0 : -EINVAL;
}
static const struct iio_enum stm32_trigger_mode_enum = {
.items = stm32_trigger_modes,
.num_items = ARRAY_SIZE(stm32_trigger_modes),
.set = stm32_set_trigger_mode,
.get = stm32_get_trigger_mode
};
static const char *const stm32_enable_modes[] = {
"always",
"gated",
@ -606,6 +664,8 @@ static const struct iio_chan_spec_ext_info stm32_trigger_count_info[] = {
IIO_ENUM_AVAILABLE("quadrature_mode", &stm32_quadrature_mode_enum),
IIO_ENUM("enable_mode", IIO_SEPARATE, &stm32_enable_mode_enum),
IIO_ENUM_AVAILABLE("enable_mode", &stm32_enable_mode_enum),
IIO_ENUM("trigger_mode", IIO_SEPARATE, &stm32_trigger_mode_enum),
IIO_ENUM_AVAILABLE("trigger_mode", &stm32_trigger_mode_enum),
{}
};
@ -630,6 +690,7 @@ static struct stm32_timer_trigger *stm32_setup_counter_device(struct device *dev
indio_dev->name = dev_name(dev);
indio_dev->dev.parent = dev;
indio_dev->info = &stm32_trigger_info;
indio_dev->modes = INDIO_HARDWARE_TRIGGERED;
indio_dev->num_channels = 1;
indio_dev->channels = &stm32_trigger_channel;
indio_dev->dev.of_node = dev->of_node;

View File

@ -1,147 +0,0 @@
/*
* twl4030_madc.h - Header for TWL4030 MADC
*
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
* J Keerthy <j-keerthy@ti.com>
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef _TWL4030_MADC_H
#define _TWL4030_MADC_H
struct twl4030_madc_conversion_method {
u8 sel;
u8 avg;
u8 rbase;
u8 ctrl;
};
#define TWL4030_MADC_MAX_CHANNELS 16
/*
* twl4030_madc_request- madc request packet for channel conversion
* @channels: 16 bit bitmap for individual channels
* @do_avgP: sample the input channel for 4 consecutive cycles
* @method: RT, SW1, SW2
* @type: Polling or interrupt based method
* @raw: Return raw value, do not convert it
*/
struct twl4030_madc_request {
unsigned long channels;
bool do_avg;
u16 method;
u16 type;
bool active;
bool result_pending;
bool raw;
int rbuf[TWL4030_MADC_MAX_CHANNELS];
void (*func_cb)(int len, int channels, int *buf);
};
enum conversion_methods {
TWL4030_MADC_RT,
TWL4030_MADC_SW1,
TWL4030_MADC_SW2,
TWL4030_MADC_NUM_METHODS
};
enum sample_type {
TWL4030_MADC_WAIT,
TWL4030_MADC_IRQ_ONESHOT,
TWL4030_MADC_IRQ_REARM
};
#define TWL4030_MADC_CTRL1 0x00
#define TWL4030_MADC_CTRL2 0x01
#define TWL4030_MADC_RTSELECT_LSB 0x02
#define TWL4030_MADC_SW1SELECT_LSB 0x06
#define TWL4030_MADC_SW2SELECT_LSB 0x0A
#define TWL4030_MADC_RTAVERAGE_LSB 0x04
#define TWL4030_MADC_SW1AVERAGE_LSB 0x08
#define TWL4030_MADC_SW2AVERAGE_LSB 0x0C
#define TWL4030_MADC_CTRL_SW1 0x12
#define TWL4030_MADC_CTRL_SW2 0x13
#define TWL4030_MADC_RTCH0_LSB 0x17
#define TWL4030_MADC_GPCH0_LSB 0x37
#define TWL4030_MADC_MADCON (1 << 0) /* MADC power on */
#define TWL4030_MADC_BUSY (1 << 0) /* MADC busy */
/* MADC conversion completion */
#define TWL4030_MADC_EOC_SW (1 << 1)
/* MADC SWx start conversion */
#define TWL4030_MADC_SW_START (1 << 5)
#define TWL4030_MADC_ADCIN0 (1 << 0)
#define TWL4030_MADC_ADCIN1 (1 << 1)
#define TWL4030_MADC_ADCIN2 (1 << 2)
#define TWL4030_MADC_ADCIN3 (1 << 3)
#define TWL4030_MADC_ADCIN4 (1 << 4)
#define TWL4030_MADC_ADCIN5 (1 << 5)
#define TWL4030_MADC_ADCIN6 (1 << 6)
#define TWL4030_MADC_ADCIN7 (1 << 7)
#define TWL4030_MADC_ADCIN8 (1 << 8)
#define TWL4030_MADC_ADCIN9 (1 << 9)
#define TWL4030_MADC_ADCIN10 (1 << 10)
#define TWL4030_MADC_ADCIN11 (1 << 11)
#define TWL4030_MADC_ADCIN12 (1 << 12)
#define TWL4030_MADC_ADCIN13 (1 << 13)
#define TWL4030_MADC_ADCIN14 (1 << 14)
#define TWL4030_MADC_ADCIN15 (1 << 15)
/* Fixed channels */
#define TWL4030_MADC_BTEMP TWL4030_MADC_ADCIN1
#define TWL4030_MADC_VBUS TWL4030_MADC_ADCIN8
#define TWL4030_MADC_VBKB TWL4030_MADC_ADCIN9
#define TWL4030_MADC_ICHG TWL4030_MADC_ADCIN10
#define TWL4030_MADC_VCHG TWL4030_MADC_ADCIN11
#define TWL4030_MADC_VBAT TWL4030_MADC_ADCIN12
/* Step size and prescaler ratio */
#define TEMP_STEP_SIZE 147
#define TEMP_PSR_R 100
#define CURR_STEP_SIZE 147
#define CURR_PSR_R1 44
#define CURR_PSR_R2 88
#define TWL4030_BCI_BCICTL1 0x23
#define TWL4030_BCI_CGAIN 0x020
#define TWL4030_BCI_MESBAT (1 << 1)
#define TWL4030_BCI_TYPEN (1 << 4)
#define TWL4030_BCI_ITHEN (1 << 3)
#define REG_BCICTL2 0x024
#define TWL4030_BCI_ITHSENS 0x007
/* Register and bits for GPBR1 register */
#define TWL4030_REG_GPBR1 0x0c
#define TWL4030_GPBR1_MADC_HFCLK_EN (1 << 7)
struct twl4030_madc_user_parms {
int channel;
int average;
int status;
u16 result;
};
int twl4030_madc_conversion(struct twl4030_madc_request *conv);
int twl4030_get_madc_conversion(int channel_no);
#endif

View File

@ -352,10 +352,16 @@ unsigned int iio_get_time_res(const struct iio_dev *indio_dev);
#define INDIO_BUFFER_SOFTWARE 0x04
#define INDIO_BUFFER_HARDWARE 0x08
#define INDIO_EVENT_TRIGGERED 0x10
#define INDIO_HARDWARE_TRIGGERED 0x20
#define INDIO_ALL_BUFFER_MODES \
(INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE | INDIO_BUFFER_SOFTWARE)
#define INDIO_ALL_TRIGGERED_MODES \
(INDIO_BUFFER_TRIGGERED \
| INDIO_EVENT_TRIGGERED \
| INDIO_HARDWARE_TRIGGERED)
#define INDIO_MAX_RAW_ELEMENTS 4
struct iio_trigger; /* forward declaration */