Commit dd36a2d9 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-4.13b' of...

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
parents cbf4b386 881b556f
...@@ -138,3 +138,18 @@ Description: ...@@ -138,3 +138,18 @@ Description:
Counting is enabled on rising edge of the connected Counting is enabled on rising edge of the connected
trigger, and remains enabled for the duration of this trigger, and remains enabled for the duration of this
selected mode. 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.
* 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, 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 which supports the SPI protocol of a selected few SPI ADCs. The SPI ADCs
......
...@@ -21,11 +21,19 @@ own configurable sequence and trigger: ...@@ -21,11 +21,19 @@ own configurable sequence and trigger:
Contents of a stm32 adc root node: Contents of a stm32 adc root node:
----------------------------------- -----------------------------------
Required properties: 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. - reg: Offset and length of the ADC block register set.
- interrupts: Must contain the interrupt for ADC block. - interrupts: Must contain the interrupt for ADC block.
- clocks: Clock for the analog circuitry (common to all ADCs). - clocks: Core can use up to two clocks, depending on part used:
- clock-names: Must be "adc". - "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 - interrupt-controller: Identifies the controller node as interrupt-parent
- vref-supply: Phandle to the vref input analog reference voltage. - vref-supply: Phandle to the vref input analog reference voltage.
- #interrupt-cells = <1>; - #interrupt-cells = <1>;
...@@ -42,14 +50,18 @@ An ADC block node should contain at least one subnode, representing an ...@@ -42,14 +50,18 @@ An ADC block node should contain at least one subnode, representing an
ADC instance available on the machine. ADC instance available on the machine.
Required properties: 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). - 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. - 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 - interrupts: IRQ Line for the ADC (e.g. may be 0 for adc@0, 1 for adc@100 or
2 for adc@200). 2 for adc@200).
- st,adc-channels: List of single-ended channels muxed for this ADC. - 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 - #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in
Documentation/devicetree/bindings/iio/iio-bindings.txt Documentation/devicetree/bindings/iio/iio-bindings.txt
...@@ -58,7 +70,9 @@ Optional properties: ...@@ -58,7 +70,9 @@ Optional properties:
See ../../dma/dma.txt for details. See ../../dma/dma.txt for details.
- dma-names: Must be "rx" when dmas property is being used. - dma-names: Must be "rx" when dmas property is being used.
- assigned-resolution-bits: Resolution (bits) to use for conversions. Must - 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. Default is maximum resolution if unset.
Example: Example:
......
...@@ -13,7 +13,8 @@ Optional properties: ...@@ -13,7 +13,8 @@ Optional properties:
"data ready" (valid values: 1 or 2). "data ready" (valid values: 1 or 2).
- 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.
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
* BMA250: 7-bit I2C slave address 0x18 or 0x19 * BMA250: 7-bit I2C slave address 0x18 or 0x19
*/ */
#include <linux/acpi.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -37,7 +36,6 @@ ...@@ -37,7 +36,6 @@
enum chip_ids { enum chip_ids {
BMA180, BMA180,
BMA250, BMA250,
BMA250E,
}; };
struct bma180_data; struct bma180_data;
...@@ -57,7 +55,6 @@ struct bma180_part_info { ...@@ -57,7 +55,6 @@ struct bma180_part_info {
u8 power_reg, power_mask, lowpower_val; u8 power_reg, power_mask, lowpower_val;
u8 int_enable_reg, int_enable_mask; u8 int_enable_reg, int_enable_mask;
u8 softreset_reg; u8 softreset_reg;
u8 chip_id;
int (*chip_config)(struct bma180_data *data); int (*chip_config)(struct bma180_data *data);
void (*chip_disable)(struct bma180_data *data); void (*chip_disable)(struct bma180_data *data);
...@@ -115,8 +112,6 @@ struct bma180_part_info { ...@@ -115,8 +112,6 @@ struct bma180_part_info {
#define BMA250_INT1_DATA_MASK BIT(0) #define BMA250_INT1_DATA_MASK BIT(0)
#define BMA250_INT_RESET_MASK BIT(7) /* Reset pending interrupts */ #define BMA250_INT_RESET_MASK BIT(7) /* Reset pending interrupts */
#define BMA250E_CHIP_ID 0xf9
struct bma180_data { struct bma180_data {
struct i2c_client *client; struct i2c_client *client;
struct iio_trigger *trig; struct iio_trigger *trig;
...@@ -314,7 +309,7 @@ static int bma180_chip_init(struct bma180_data *data) ...@@ -314,7 +309,7 @@ static int bma180_chip_init(struct bma180_data *data)
if (ret < 0) if (ret < 0)
return ret; return ret;
if (ret != data->part_info->chip_id) if (ret != BMA180_ID_REG_VAL)
return -ENODEV; return -ENODEV;
ret = bma180_soft_reset(data); ret = bma180_soft_reset(data);
...@@ -637,7 +632,6 @@ static const struct bma180_part_info bma180_part_info[] = { ...@@ -637,7 +632,6 @@ static const struct bma180_part_info bma180_part_info[] = {
BMA180_TCO_Z, BMA180_MODE_CONFIG, BMA180_LOW_POWER, BMA180_TCO_Z, BMA180_MODE_CONFIG, BMA180_LOW_POWER,
BMA180_CTRL_REG3, BMA180_NEW_DATA_INT, BMA180_CTRL_REG3, BMA180_NEW_DATA_INT,
BMA180_RESET, BMA180_RESET,
BMA180_CHIP_ID,
bma180_chip_config, bma180_chip_config,
bma180_chip_disable, bma180_chip_disable,
}, },
...@@ -652,22 +646,6 @@ static const struct bma180_part_info bma180_part_info[] = { ...@@ -652,22 +646,6 @@ static const struct bma180_part_info bma180_part_info[] = {
BMA250_POWER_REG, BMA250_LOWPOWER_MASK, 1, BMA250_POWER_REG, BMA250_LOWPOWER_MASK, 1,
BMA250_INT_ENABLE_REG, BMA250_DATA_INTEN_MASK, BMA250_INT_ENABLE_REG, BMA250_DATA_INTEN_MASK,
BMA250_RESET_REG, 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_config,
bma250_chip_disable, bma250_chip_disable,
}, },
...@@ -728,8 +706,6 @@ static const struct iio_trigger_ops bma180_trigger_ops = { ...@@ -728,8 +706,6 @@ static const struct iio_trigger_ops bma180_trigger_ops = {
static int bma180_probe(struct i2c_client *client, static int bma180_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct device *dev = &client->dev;
const struct acpi_device_id *acpi_id;
struct bma180_data *data; struct bma180_data *data;
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
enum chip_ids chip; enum chip_ids chip;
...@@ -742,17 +718,10 @@ static int bma180_probe(struct i2c_client *client, ...@@ -742,17 +718,10 @@ static int bma180_probe(struct i2c_client *client,
data = iio_priv(indio_dev); data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev); i2c_set_clientdata(client, indio_dev);
data->client = client; data->client = client;
if (dev->of_node) { if (client->dev.of_node)
chip = (enum chip_ids)of_device_get_match_data(&client->dev); chip = (enum chip_ids)of_device_get_match_data(&client->dev);
} else if (id) { else
chip = id->driver_data; 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]; data->part_info = &bma180_part_info[chip];
ret = data->part_info->chip_config(data); ret = data->part_info->chip_config(data);
...@@ -873,16 +842,9 @@ static SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume); ...@@ -873,16 +842,9 @@ 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 const struct acpi_device_id bma180_acpi_match[] = {
{ "BMA250E", BMA250E },
{ }
};
MODULE_DEVICE_TABLE(acpi, bma180_acpi_match);
static struct i2c_device_id bma180_ids[] = { static struct i2c_device_id bma180_ids[] = {
{ "bma180", BMA180 }, { "bma180", BMA180 },
{ "bma250", BMA250 }, { "bma250", BMA250 },
{ "bma250e", BMA250E },
{ } { }
}; };
...@@ -904,7 +866,6 @@ MODULE_DEVICE_TABLE(of, bma180_of_match); ...@@ -904,7 +866,6 @@ MODULE_DEVICE_TABLE(of, bma180_of_match);
static struct i2c_driver bma180_driver = { static struct i2c_driver bma180_driver = {
.driver = { .driver = {
.name = "bma180", .name = "bma180",
.acpi_match_table = ACPI_PTR(bma180_acpi_match),
.pm = BMA180_PM_OPS, .pm = BMA180_PM_OPS,
.of_match_table = bma180_of_match, .of_match_table = bma180_of_match,
}, },
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#define MMA9551_DRV_NAME "mma9551" #define MMA9551_DRV_NAME "mma9551"
#define MMA9551_IRQ_NAME "mma9551_event" #define MMA9551_IRQ_NAME "mma9551_event"
#define MMA9551_GPIO_NAME "mma9551_int"
#define MMA9551_GPIO_COUNT 4 #define MMA9551_GPIO_COUNT 4
/* Tilt application (inclination in IIO terms). */ /* Tilt application (inclination in IIO terms). */
...@@ -418,8 +417,7 @@ static int mma9551_gpio_probe(struct iio_dev *indio_dev) ...@@ -418,8 +417,7 @@ static int mma9551_gpio_probe(struct iio_dev *indio_dev)
struct device *dev = &data->client->dev; struct device *dev = &data->client->dev;
for (i = 0; i < MMA9551_GPIO_COUNT; i++) { for (i = 0; i < MMA9551_GPIO_COUNT; i++) {
gpio = devm_gpiod_get_index(dev, MMA9551_GPIO_NAME, i, gpio = devm_gpiod_get_index(dev, NULL, i, GPIOD_IN);
GPIOD_IN);
if (IS_ERR(gpio)) { if (IS_ERR(gpio)) {
dev_err(dev, "acpi gpio get index failed\n"); dev_err(dev, "acpi gpio get index failed\n");
return PTR_ERR(gpio); return PTR_ERR(gpio);
......
...@@ -47,15 +47,11 @@ static int st_accel_spi_remove(struct spi_device *spi) ...@@ -47,15 +47,11 @@ static int st_accel_spi_remove(struct spi_device *spi)
} }
static const struct spi_device_id st_accel_id_table[] = { static const struct spi_device_id st_accel_id_table[] = {
{ LSM303DLH_ACCEL_DEV_NAME },
{ LSM303DLHC_ACCEL_DEV_NAME },
{ LIS3DH_ACCEL_DEV_NAME }, { LIS3DH_ACCEL_DEV_NAME },
{ LSM330D_ACCEL_DEV_NAME }, { LSM330D_ACCEL_DEV_NAME },
{ LSM330DL_ACCEL_DEV_NAME }, { LSM330DL_ACCEL_DEV_NAME },
{ LSM330DLC_ACCEL_DEV_NAME }, { LSM330DLC_ACCEL_DEV_NAME },
{ LIS331DLH_ACCEL_DEV_NAME }, { LIS331DLH_ACCEL_DEV_NAME },
{ LSM303DL_ACCEL_DEV_NAME },
{ LSM303DLM_ACCEL_DEV_NAME },
{ LSM330_ACCEL_DEV_NAME }, { LSM330_ACCEL_DEV_NAME },
{ LSM303AGR_ACCEL_DEV_NAME }, { LSM303AGR_ACCEL_DEV_NAME },
{ LIS2DH12_ACCEL_DEV_NAME }, { LIS2DH12_ACCEL_DEV_NAME },
......
...@@ -272,11 +272,9 @@ static ssize_t ad7791_write_frequency(struct device *dev, ...@@ -272,11 +272,9 @@ static ssize_t ad7791_write_frequency(struct device *dev,
struct ad7791_state *st = iio_priv(indio_dev); struct ad7791_state *st = iio_priv(indio_dev);
int i, ret; int i, ret;
for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++) i = sysfs_match_string(ad7791_sample_freq_avail, buf);
if (sysfs_streq(ad7791_sample_freq_avail[i], buf)) if (i < 0)
break; return i;
if (i == ARRAY_SIZE(ad7791_sample_freq_avail))
return -EINVAL;
ret = iio_device_claim_direct_mode(indio_dev); ret = iio_device_claim_direct_mode(indio_dev);
if (ret) if (ret)
......
...@@ -212,7 +212,10 @@ static int aspeed_adc_probe(struct platform_device *pdev) ...@@ -212,7 +212,10 @@ static int aspeed_adc_probe(struct platform_device *pdev)
} }
/* Start all channels in normal mode. */ /* 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) | adc_engine_control_reg_val = GENMASK(31, 16) |
ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE; ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE;
writel(adc_engine_control_reg_val, writel(adc_engine_control_reg_val,
...@@ -236,6 +239,7 @@ static int aspeed_adc_probe(struct platform_device *pdev) ...@@ -236,6 +239,7 @@ static int aspeed_adc_probe(struct platform_device *pdev)
writel(ASPEED_OPERATION_MODE_POWER_DOWN, writel(ASPEED_OPERATION_MODE_POWER_DOWN,
data->base + ASPEED_REG_ENGINE_CONTROL); data->base + ASPEED_REG_ENGINE_CONTROL);
clk_disable_unprepare(data->clk_scaler->clk); clk_disable_unprepare(data->clk_scaler->clk);
clk_enable_error:
clk_hw_unregister_divider(data->clk_scaler); clk_hw_unregister_divider(data->clk_scaler);
scaler_error: scaler_error:
......
...@@ -52,6 +52,10 @@ ...@@ -52,6 +52,10 @@
#define CPCAP_BIT_RAND0 BIT(1) /* Set with CAL_MODE */ #define CPCAP_BIT_RAND0 BIT(1) /* Set with CAL_MODE */
#define CPCAP_BIT_ADEN BIT(0) /* Currently unused */ #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 */ /* Register CPCAP_REG_ADCC2 bits */
#define CPCAP_BIT_CAL_FACTOR_ENABLE BIT(15) /* Currently unused */ #define CPCAP_BIT_CAL_FACTOR_ENABLE BIT(15) /* Currently unused */
#define CPCAP_BIT_BATDETB_EN BIT(14) /* Currently unused */ #define CPCAP_BIT_BATDETB_EN BIT(14) /* Currently unused */
...@@ -62,7 +66,7 @@ ...@@ -62,7 +66,7 @@
#define CPCAP_BIT_ADC_PS_FACTOR0 BIT(9) #define CPCAP_BIT_ADC_PS_FACTOR0 BIT(9)
#define CPCAP_BIT_AD4_SELECT BIT(8) /* Currently unused */ #define CPCAP_BIT_AD4_SELECT BIT(8) /* Currently unused */
#define CPCAP_BIT_ADC_BUSY BIT(7) /* 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_ADTRIG_DIS BIT(5) /* Disable interrupt */
#define CPCAP_BIT_LIADC BIT(4) /* Currently unused */ #define CPCAP_BIT_LIADC BIT(4) /* Currently unused */
#define CPCAP_BIT_TS_REFEN BIT(3) /* Currently unused */ #define CPCAP_BIT_TS_REFEN BIT(3) /* Currently unused */
...@@ -70,6 +74,12 @@ ...@@ -70,6 +74,12 @@
#define CPCAP_BIT_TS_M1 BIT(1) /* Currently unused */ #define CPCAP_BIT_TS_M1 BIT(1) /* Currently unused */
#define CPCAP_BIT_TS_M0 BIT(0) /* 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_MAX_TEMP_LVL 27
#define CPCAP_FOUR_POINT_TWO_ADC 801 #define CPCAP_FOUR_POINT_TWO_ADC 801
#define ST_ADC_CAL_CHRGI_HIGH_THRESHOLD 530 #define ST_ADC_CAL_CHRGI_HIGH_THRESHOLD 530
...@@ -78,7 +88,7 @@ ...@@ -78,7 +88,7 @@
#define ST_ADC_CAL_BATTI_LOW_THRESHOLD 494 #define ST_ADC_CAL_BATTI_LOW_THRESHOLD 494
#define ST_ADC_CALIBRATE_DIFF_THRESHOLD 3 #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 * struct cpcap_adc_ato - timing settings for cpcap adc
...@@ -124,10 +134,10 @@ struct cpcap_adc { ...@@ -124,10 +134,10 @@ struct cpcap_adc {
*/ */
enum cpcap_adc_channel { enum cpcap_adc_channel {
/* Bank0 channels */ /* Bank0 channels */
CPCAP_ADC_AD0_BATTDETB, /* Battery detection */ CPCAP_ADC_AD0, /* Battery temperature */
CPCAP_ADC_BATTP, /* Battery voltage */ CPCAP_ADC_BATTP, /* Battery voltage */
CPCAP_ADC_VBUS, /* USB VBUS 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_BPLUS_AD4, /* Another battery or system voltage */
CPCAP_ADC_CHG_ISENSE, /* Calibrated charge current */ CPCAP_ADC_CHG_ISENSE, /* Calibrated charge current */
CPCAP_ADC_BATTI, /* Calibrated system current */ CPCAP_ADC_BATTI, /* Calibrated system current */
...@@ -217,7 +227,7 @@ struct cpcap_adc_request { ...@@ -217,7 +227,7 @@ struct cpcap_adc_request {
/* Phasing table for channels. Note that channels 16 & 17 use BATTP and BATTI */ /* Phasing table for channels. Note that channels 16 & 17 use BATTP and BATTI */
static const struct cpcap_adc_phasing_tbl bank_phasing[] = { static const struct cpcap_adc_phasing_tbl bank_phasing[] = {
/* Bank0 */ /* 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_BATTP] = {0, 0x80, 0x80, 0, 1023},
[CPCAP_ADC_VBUS] = {0, 0x80, 0x80, 0, 1023}, [CPCAP_ADC_VBUS] = {0, 0x80, 0x80, 0, 1023},
[CPCAP_ADC_AD3] = {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[] = { ...@@ -243,7 +253,7 @@ static const struct cpcap_adc_phasing_tbl bank_phasing[] = {
*/ */
static struct cpcap_adc_conversion_tbl bank_conversion[] = { static struct cpcap_adc_conversion_tbl bank_conversion[] = {
/* Bank0 */ /* Bank0 */
[CPCAP_ADC_AD0_BATTDETB] = { [CPCAP_ADC_AD0] = {
IIO_CHAN_INFO_PROCESSED, 0, 0, 0, 1, 1, IIO_CHAN_INFO_PROCESSED, 0, 0, 0, 1, 1,
}, },
[CPCAP_ADC_BATTP] = { [CPCAP_ADC_BATTP] = {
...@@ -541,6 +551,15 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata, ...@@ -541,6 +551,15 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata,
return; return;
switch (req->channel) { 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: case CPCAP_ADC_AD8 ... CPCAP_ADC_TSY2_AD15:
value1 |= CPCAP_BIT_AD_SEL1; value1 |= CPCAP_BIT_AD_SEL1;
break; break;
...@@ -583,7 +602,8 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata, ...@@ -583,7 +602,8 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata,
error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
CPCAP_BIT_ATOX_PS_FACTOR | CPCAP_BIT_ATOX_PS_FACTOR |
CPCAP_BIT_ADC_PS_FACTOR1 | CPCAP_BIT_ADC_PS_FACTOR1 |
CPCAP_BIT_ADC_PS_FACTOR0, CPCAP_BIT_ADC_PS_FACTOR0 |
CPCAP_BIT_THERMBIAS_EN,
value2); value2);
if (error) if (error)
return; return;
...@@ -614,27 +634,6 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata, ...@@ -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, static int cpcap_adc_start_bank(struct cpcap_adc *ddata,
struct cpcap_adc_request *req) struct cpcap_adc_request *req)
{ {
...@@ -652,7 +651,6 @@ static int cpcap_adc_start_bank(struct cpcap_adc *ddata, ...@@ -652,7 +651,6 @@ static int cpcap_adc_start_bank(struct cpcap_adc *ddata,
return 0; return 0;
if (error == 0) { if (error == 0) {
cpcap_adc_quirk_reset_lost_irq(ddata);
error = -ETIMEDOUT; error = -ETIMEDOUT;
continue; continue;
} }
...@@ -664,6 +662,21 @@ static int cpcap_adc_start_bank(struct cpcap_adc *ddata, ...@@ -664,6 +662,21 @@ static int cpcap_adc_start_bank(struct cpcap_adc *ddata,
return error; 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) static void cpcap_adc_phase(struct cpcap_adc_request *req)
{ {
const struct cpcap_adc_conversion_tbl *conv_tbl = req->conv_tbl; 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) ...@@ -758,7 +771,7 @@ static void cpcap_adc_convert(struct cpcap_adc_request *req)
return; return;
/* Temperatures use a lookup table instead of conversion table */ /* 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->channel == CPCAP_ADC_AD3)) {
req->result = req->result =
cpcap_adc_table_to_millicelcius(req->result); cpcap_adc_table_to_millicelcius(req->result);
...@@ -820,7 +833,7 @@ static int cpcap_adc_init_request(struct cpcap_adc_request *req, ...@@ -820,7 +833,7 @@ static int cpcap_adc_init_request(struct cpcap_adc_request *req,
req->conv_tbl = bank_conversion; req->conv_tbl = bank_conversion;
switch (channel) { switch (channel) {
case CPCAP_ADC_AD0_BATTDETB ... CPCAP_ADC_USB_ID: case CPCAP_ADC_AD0 ... CPCAP_ADC_USB_ID:
req->bank_index = channel; req->bank_index = channel;
break; break;
case CPCAP_ADC_AD8 ... CPCAP_ADC_TSY2_AD15: case CPCAP_ADC_AD8 ... CPCAP_ADC_TSY2_AD15:
...@@ -839,6 +852,22 @@ static int cpcap_adc_init_request(struct cpcap_adc_request *req, ...@@ -839,6 +852,22 @@ static int cpcap_adc_init_request(struct cpcap_adc_request *req,
return 0; 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, static int cpcap_adc_read(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, struct iio_chan_spec const *chan,
int *val, int *val2, long mask) int *val, int *val2, long mask)
...@@ -858,6 +887,9 @@ static int cpcap_adc_read(struct iio_dev *indio_dev, ...@@ -858,6 +887,9 @@ static int cpcap_adc_read(struct iio_dev *indio_dev,
if (error) if (error)
goto err_unlock; goto err_unlock;
error = regmap_read(ddata->reg, chan->address, val); error = regmap_read(ddata->reg, chan->address, val);
if (error)
goto err_unlock;
error = cpcap_adc_stop_bank(ddata);
if (error) if (error)
goto err_unlock; goto err_unlock;
mutex_unlock(&ddata->lock); mutex_unlock(&ddata->lock);
...@@ -867,9 +899,21 @@ static int cpcap_adc_read(struct iio_dev *indio_dev, ...@@ -867,9 +899,21 @@ static int cpcap_adc_read(struct iio_dev *indio_dev,
error = cpcap_adc_start_bank(ddata, &req); error = cpcap_adc_start_bank(ddata, &req);
if (error) if (error)
goto err_unlock; goto err_unlock;
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); error = cpcap_adc_read_bank_scaled(ddata, &req);
if (error) if (error)
goto err_unlock; goto err_unlock;
}
error = cpcap_adc_stop_bank(ddata);
if (error)
goto err_unlock;
mutex_unlock(&ddata->lock); mutex_unlock(&ddata->lock);
*val = req.result; *val = req.result;
break; break;
......
...@@ -410,11 +410,11 @@ static const struct iio_chan_spec hi8435_channels[] = { ...@@ -410,11 +410,11 @@ static const struct iio_chan_spec hi8435_channels[] = {
static const struct iio_info hi8435_info = { static const struct iio_info hi8435_info = {
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
.read_raw = hi8435_read_raw, .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, .write_event_config = hi8435_write_event_config,
.read_event_value = &hi8435_read_event_value, .read_event_value = hi8435_read_event_value,
.write_event_value = &hi8435_write_event_value, .write_event_value = hi8435_write_event_value,
.debugfs_reg_access = &hi8435_debugfs_reg_access, .debugfs_reg_access = hi8435_debugfs_reg_access,
}; };
static void hi8435_iio_push_event(struct iio_dev *idev, unsigned int val) 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) ...@@ -476,15 +476,13 @@ static int hi8435_probe(struct spi_device *spi)
priv->spi = spi; priv->spi = spi;
reset_gpio = devm_gpiod_get(&spi->dev, NULL, GPIOD_OUT_LOW); reset_gpio = devm_gpiod_get(&spi->dev, NULL, GPIOD_OUT_LOW);
if (!IS_ERR(reset_gpio)) { if (IS_ERR(reset_gpio)) {
/* need >=100ns low pulse to reset chip */ /* chip s/w reset if h/w reset failed */
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 */
hi8435_writeb(priv, HI8435_CTRL_REG, HI8435_CTRL_SRST); hi8435_writeb(priv, HI8435_CTRL_REG, HI8435_CTRL_SRST);
hi8435_writeb(priv, HI8435_CTRL_REG, 0); hi8435_writeb(priv, HI8435_CTRL_REG, 0);
} else {
udelay(5);
gpiod_set_value(reset_gpio, 1);
} }
spi_set_drvdata(spi, idev); spi_set_drvdata(spi, idev);
......
This diff is collapsed.
...@@ -76,10 +76,14 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev, ...@@ -76,10 +76,14 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
long mask) long mask)
{ {
struct lpc32xx_adc_state *st = iio_priv(indio_dev); struct lpc32xx_adc_state *st = iio_priv(indio_dev);
int ret;
if (mask == IIO_CHAN_INFO_RAW) { if (mask == IIO_CHAN_INFO_RAW) {
mutex_lock(&indio_dev->mlock); 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 */ /* Measurement setup */
__raw_writel(LPC32XXAD_INTERNAL | (chan->address) | __raw_writel(LPC32XXAD_INTERNAL | (chan->address) |
LPC32XXAD_REFp | LPC32XXAD_REFm, LPC32XXAD_REFp | LPC32XXAD_REFm,
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#define VREF_MV_BASE 1850 #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-channel0",
"mxs-lradc-channel1", "mxs-lradc-channel1",
"mxs-lradc-channel2", "mxs-lradc-channel2",
...@@ -57,7 +57,7 @@ const char *mx23_lradc_adc_irq_names[] = { ...@@ -57,7 +57,7 @@ const char *mx23_lradc_adc_irq_names[] = {
"mxs-lradc-channel5", "mxs-lradc-channel5",
}; };
const char *mx28_lradc_adc_irq_names[] = { static const char *mx28_lradc_adc_irq_names[] = {
"mxs-lradc-thresh0", "mxs-lradc-thresh0",
"mxs-lradc-thresh1", "mxs-lradc-thresh1",
"mxs-lradc-channel0", "mxs-lradc-channel0",
...@@ -344,20 +344,20 @@ static ssize_t mxs_lradc_adc_show_scale_avail(struct device *dev, ...@@ -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,\ IIO_DEVICE_ATTR(in_voltage##ch##_scale_available, 0444,\
mxs_lradc_adc_show_scale_avail, NULL, ch) mxs_lradc_adc_show_scale_avail, NULL, ch)
SHOW_SCALE_AVAILABLE_ATTR(0); static SHOW_SCALE_AVAILABLE_ATTR(0);
SHOW_SCALE_AVAILABLE_ATTR(1); static SHOW_SCALE_AVAILABLE_ATTR(1);
SHOW_SCALE_AVAILABLE_ATTR(2); static SHOW_SCALE_AVAILABLE_ATTR(2);
SHOW_SCALE_AVAILABLE_ATTR(3); static SHOW_SCALE_AVAILABLE_ATTR(3);
SHOW_SCALE_AVAILABLE_ATTR(4); static SHOW_SCALE_AVAILABLE_ATTR(4);
SHOW_SCALE_AVAILABLE_ATTR(5); static SHOW_SCALE_AVAILABLE_ATTR(5);
SHOW_SCALE_AVAILABLE_ATTR(6); static SHOW_SCALE_AVAILABLE_ATTR(6);
SHOW_SCALE_AVAILABLE_ATTR(7); static SHOW_SCALE_AVAILABLE_ATTR(7);
SHOW_SCALE_AVAILABLE_ATTR(10); static SHOW_SCALE_AVAILABLE_ATTR(10);
SHOW_SCALE_AVAILABLE_ATTR(11); static SHOW_SCALE_AVAILABLE_ATTR(11);
SHOW_SCALE_AVAILABLE_ATTR(12); static SHOW_SCALE_AVAILABLE_ATTR(12);
SHOW_SCALE_AVAILABLE_ATTR(13); static SHOW_SCALE_AVAILABLE_ATTR(13);
SHOW_SCALE_AVAILABLE_ATTR(14); static SHOW_SCALE_AVAILABLE_ATTR(14);
SHOW_SCALE_AVAILABLE_ATTR(15); static SHOW_SCALE_AVAILABLE_ATTR(15);
static struct attribute *mxs_lradc_adc_attributes[] = { static struct attribute *mxs_lradc_adc_attributes[] = {
&iio_dev_attr_in_voltage0_scale_available.dev_attr.attr, &iio_dev_attr_in_voltage0_scale_available.dev_attr.attr,
......
...@@ -49,19 +49,66 @@ ...@@ -49,19 +49,66 @@
/* STM32 F4 maximum analog clock rate (from datasheet) */ /* STM32 F4 maximum analog clock rate (from datasheet) */
#define STM32F4_ADC_MAX_CLK_RATE 36000000 #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 * struct stm32_adc_priv - stm32 ADC core private data
* @irq: irq for ADC block * @irq: irq for ADC block
* @domain: irq domain reference * @domain: irq domain reference
* @aclk: clock reference for the analog circuitry * @aclk: clock reference for the analog circuitry
* @bclk: bus clock common for all ADCs, depends on part used
* @vref: regulator reference * @vref: regulator reference
* @cfg: compatible configuration data
* @common: common data for all ADC instances * @common: common data for all ADC instances
*/ */
struct stm32_adc_priv { struct stm32_adc_priv {
int irq; int irq;
struct irq_domain *domain; struct irq_domain *domain;
struct clk *aclk; struct clk *aclk;
struct clk *bclk;
struct regulator *vref; struct regulator *vref;
const struct stm32_adc_priv_cfg *cfg;
struct stm32_adc_common common; struct stm32_adc_common common;
}; };
...@@ -85,14 +132,23 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev, ...@@ -85,14 +132,23 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev,
u32 val; u32 val;
int i; 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); rate = clk_get_rate(priv->aclk);
for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) { for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) {
if ((rate / stm32f4_pclk_div[i]) <= STM32F4_ADC_MAX_CLK_RATE) if ((rate / stm32f4_pclk_div[i]) <= STM32F4_ADC_MAX_CLK_RATE)
break; 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; return -EINVAL;
}
priv->common.rate = rate;
val = readl_relaxed(priv->common.base + STM32F4_ADC_CCR); val = readl_relaxed(priv->common.base + STM32F4_ADC_CCR);
val &= ~STM32F4_ADC_ADCPRE_MASK; val &= ~STM32F4_ADC_ADCPRE_MASK;
val |= i << STM32F4_ADC_ADCPRE_SHIFT; val |= i << STM32F4_ADC_ADCPRE_SHIFT;
...@@ -104,6 +160,126 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev, ...@@ -104,6 +160,126 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev,
return 0; 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 */ /* ADC common interrupt for all instances */
static void stm32_adc_irq_handler(struct irq_desc *desc) static void stm32_adc_irq_handler(struct irq_desc *desc)
{ {
...@@ -112,15 +288,15 @@ 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; u32 status;
chained_irq_enter(chip, desc); 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)); 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)); 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)); generic_handle_irq(irq_find_mapping(priv->domain, 2));
chained_irq_exit(chip, desc); chained_irq_exit(chip, desc);
...@@ -186,6 +362,7 @@ static void stm32_adc_irq_remove(struct platform_device *pdev, ...@@ -186,6 +362,7 @@ static void stm32_adc_irq_remove(struct platform_device *pdev,
static int stm32_adc_probe(struct platform_device *pdev) static int stm32_adc_probe(struct platform_device *pdev)
{ {
struct stm32_adc_priv *priv; struct stm32_adc_priv *priv;
struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct resource *res; struct resource *res;
int ret; int ret;
...@@ -197,6 +374,9 @@ static int stm32_adc_probe(struct platform_device *pdev) ...@@ -197,6 +374,9 @@ static int stm32_adc_probe(struct platform_device *pdev)
if (!priv) if (!priv)
return -ENOMEM; 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); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->common.base = devm_ioremap_resource(&pdev->dev, res); priv->common.base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(priv->common.base)) if (IS_ERR(priv->common.base))
...@@ -227,25 +407,48 @@ static int stm32_adc_probe(struct platform_device *pdev) ...@@ -227,25 +407,48 @@ static int stm32_adc_probe(struct platform_device *pdev)
priv->aclk = devm_clk_get(&pdev->dev, "adc"); priv->aclk = devm_clk_get(&pdev->dev, "adc");
if (IS_ERR(priv->aclk)) { if (IS_ERR(priv->aclk)) {
ret = PTR_ERR(priv->aclk); ret = PTR_ERR(priv->aclk);
if (ret == -ENOENT) {
priv->aclk = NULL;
} else {
dev_err(&pdev->dev, "Can't get 'adc' clock\n"); dev_err(&pdev->dev, "Can't get 'adc' clock\n");
goto err_regulator_disable; goto err_regulator_disable;
} }
}
if (priv->aclk) {
ret = clk_prepare_enable(priv->aclk); ret = clk_prepare_enable(priv->aclk);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "adc clk enable failed\n"); dev_err(&pdev->dev, "adc clk enable failed\n");
goto err_regulator_disable; goto err_regulator_disable;
} }
}
ret = stm32f4_adc_clk_sel(pdev, priv); 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) { if (ret < 0) {
dev_err(&pdev->dev, "adc clk selection failed\n"); dev_err(&pdev->dev, "adc clk enable failed\n");
goto err_clk_disable; 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); ret = stm32_adc_irq_probe(pdev, priv);
if (ret < 0) if (ret < 0)
goto err_clk_disable; goto err_bclk_disable;
platform_set_drvdata(pdev, &priv->common); platform_set_drvdata(pdev, &priv->common);
...@@ -260,7 +463,12 @@ static int stm32_adc_probe(struct platform_device *pdev) ...@@ -260,7 +463,12 @@ static int stm32_adc_probe(struct platform_device *pdev)
err_irq_remove: err_irq_remove:
stm32_adc_irq_remove(pdev, priv); stm32_adc_irq_remove(pdev, priv);
err_clk_disable: err_bclk_disable:
if (priv->bclk)
clk_disable_unprepare(priv->bclk);
err_aclk_disable:
if (priv->aclk)
clk_disable_unprepare(priv->aclk); clk_disable_unprepare(priv->aclk);
err_regulator_disable: err_regulator_disable:
...@@ -276,15 +484,34 @@ static int stm32_adc_remove(struct platform_device *pdev) ...@@ -276,15 +484,34 @@ static int stm32_adc_remove(struct platform_device *pdev)
of_platform_depopulate(&pdev->dev); of_platform_depopulate(&pdev->dev);
stm32_adc_irq_remove(pdev, priv); stm32_adc_irq_remove(pdev, priv);
if (priv->bclk)
clk_disable_unprepare(priv->bclk);
if (priv->aclk)
clk_disable_unprepare(priv->aclk); clk_disable_unprepare(priv->aclk);
regulator_disable(priv->vref); regulator_disable(priv->vref);
return 0; 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[] = { 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); MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
......
...@@ -43,11 +43,13 @@ ...@@ -43,11 +43,13 @@
* struct stm32_adc_common - stm32 ADC driver common data (for all instances) * struct stm32_adc_common - stm32 ADC driver common data (for all instances)
* @base: control registers base cpu addr * @base: control registers base cpu addr
* @phys_base: control registers base physical addr * @phys_base: control registers base physical addr
* @rate: clock rate used for analog circuitry
* @vref_mv: vref voltage (mv) * @vref_mv: vref voltage (mv)
*/ */
struct stm32_adc_common { struct stm32_adc_common {
void __iomem *base; void __iomem *base;
phys_addr_t phys_base; phys_addr_t phys_base;
unsigned long rate;
int vref_mv; int vref_mv;
}; };
......
This diff is collapsed.
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c/twl.h> #include <linux/i2c/twl.h>
#include <linux/i2c/twl4030-madc.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/mutex.h> #include <linux/mutex.h>
...@@ -49,9 +48,121 @@ ...@@ -49,9 +48,121 @@
#include <linux/iio/iio.h> #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_SEL_MADC_MCPC (1<<3)
#define TWL4030_USB_CARKIT_ANA_CTRL 0xBB #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 * struct twl4030_madc_data - a container for madc info
* @dev: Pointer to device structure for madc * @dev: Pointer to device structure for madc
...@@ -72,6 +183,8 @@ struct twl4030_madc_data { ...@@ -72,6 +183,8 @@ struct twl4030_madc_data {
u8 isr; u8 isr;
}; };
static int twl4030_madc_conversion(struct twl4030_madc_request *req);
static int twl4030_madc_read(struct iio_dev *iio_dev, static int twl4030_madc_read(struct iio_dev *iio_dev,
const struct iio_chan_spec *chan, const struct iio_chan_spec *chan,
int *val, int *val2, long mask) int *val, int *val2, long mask)
...@@ -84,7 +197,6 @@ static int twl4030_madc_read(struct iio_dev *iio_dev, ...@@ -84,7 +197,6 @@ static int twl4030_madc_read(struct iio_dev *iio_dev,
req.channels = BIT(chan->channel); req.channels = BIT(chan->channel);
req.active = false; req.active = false;
req.func_cb = NULL;
req.type = TWL4030_MADC_WAIT; req.type = TWL4030_MADC_WAIT;
req.raw = !(mask == IIO_CHAN_INFO_PROCESSED); req.raw = !(mask == IIO_CHAN_INFO_PROCESSED);
req.do_avg = (mask == IIO_CHAN_INFO_AVERAGE_RAW); req.do_avg = (mask == IIO_CHAN_INFO_AVERAGE_RAW);
...@@ -340,37 +452,6 @@ static int twl4030_madc_read_channels(struct twl4030_madc_data *madc, ...@@ -340,37 +452,6 @@ static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
return count; 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. * Disables irq.
* @madc - pointer to twl4030_madc_data struct * @madc - pointer to twl4030_madc_data struct
...@@ -440,11 +521,6 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc) ...@@ -440,11 +521,6 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
/* Read results */ /* Read results */
len = twl4030_madc_read_channels(madc, method->rbase, len = twl4030_madc_read_channels(madc, method->rbase,
r->channels, r->rbuf, r->raw); 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 */ /* Free request */
r->result_pending = 0; r->result_pending = 0;
r->active = 0; r->active = 0;
...@@ -466,11 +542,6 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc) ...@@ -466,11 +542,6 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
/* Read results */ /* Read results */
len = twl4030_madc_read_channels(madc, method->rbase, len = twl4030_madc_read_channels(madc, method->rbase,
r->channels, r->rbuf, r->raw); 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 */ /* Free request */
r->result_pending = 0; r->result_pending = 0;
r->active = 0; r->active = 0;
...@@ -480,23 +551,6 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc) ...@@ -480,23 +551,6 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
return IRQ_HANDLED; 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 * Function which enables the madc conversion
* by writing to the control register. * by writing to the control register.
...@@ -568,7 +622,7 @@ static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc, ...@@ -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. * be a negative error value in the corresponding array element.
* returns 0 if succeeds else error value * 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; const struct twl4030_madc_conversion_method *method;
int ret; int ret;
...@@ -605,17 +659,6 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req) ...@@ -605,17 +659,6 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
goto out; 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 */ /* With RT method we should not be here anymore */
if (req->method == TWL4030_MADC_RT) { if (req->method == TWL4030_MADC_RT) {
ret = -EINVAL; ret = -EINVAL;
...@@ -640,28 +683,6 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req) ...@@ -640,28 +683,6 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
return ret; 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 * twl4030_madc_set_current_generator() - setup bias current
......
...@@ -1204,7 +1204,10 @@ static int xadc_probe(struct platform_device *pdev) ...@@ -1204,7 +1204,10 @@ static int xadc_probe(struct platform_device *pdev)
ret = PTR_ERR(xadc->clk); ret = PTR_ERR(xadc->clk);
goto err_free_samplerate_trigger; 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); ret = xadc->ops->setup(pdev, indio_dev, irq);
if (ret) if (ret)
......
...@@ -16,7 +16,7 @@ config HID_SENSOR_IIO_COMMON ...@@ -16,7 +16,7 @@ config HID_SENSOR_IIO_COMMON
config HID_SENSOR_IIO_TRIGGER config HID_SENSOR_IIO_TRIGGER
tristate "Common module (trigger) for all HID Sensor IIO drivers" 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 select IIO_TRIGGER
help help
Say yes here to build trigger support for HID sensors. Say yes here to build trigger support for HID sensors.
......
...@@ -188,7 +188,6 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on) ...@@ -188,7 +188,6 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
int result = 0; int result = 0;
if (power_on) { if (power_on) {
/* Already under indio-dev->mlock mutex */
if (!st->powerup_count) if (!st->powerup_count)
result = regmap_write(st->map, st->reg->pwr_mgmt_1, 0); result = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
if (!result) if (!result)
...@@ -329,50 +328,37 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev, ...@@ -329,50 +328,37 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
int result; int result;
ret = IIO_VAL_INT; ret = IIO_VAL_INT;
result = 0; mutex_lock(&st->lock);
mutex_lock(&indio_dev->mlock); result = iio_device_claim_direct_mode(indio_dev);
if (!st->chip_config.enable) { if (result)
goto error_read_raw_unlock;
result = inv_mpu6050_set_power_itg(st, true); result = inv_mpu6050_set_power_itg(st, true);
if (result) if (result)
goto error_read_raw; goto error_read_raw_release;
}
/* when enable is on, power is already on */
switch (chan->type) { switch (chan->type) {
case IIO_ANGL_VEL: case IIO_ANGL_VEL:
if (!st->chip_config.gyro_fifo_enable ||
!st->chip_config.enable) {
result = inv_mpu6050_switch_engine(st, true, result = inv_mpu6050_switch_engine(st, true,
INV_MPU6050_BIT_PWR_GYRO_STBY); INV_MPU6050_BIT_PWR_GYRO_STBY);
if (result) if (result)
goto error_read_raw; goto error_read_raw_power_off;
}
ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro, ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro,
chan->channel2, val); chan->channel2, val);
if (!st->chip_config.gyro_fifo_enable ||
!st->chip_config.enable) {
result = inv_mpu6050_switch_engine(st, false, result = inv_mpu6050_switch_engine(st, false,
INV_MPU6050_BIT_PWR_GYRO_STBY); INV_MPU6050_BIT_PWR_GYRO_STBY);
if (result) if (result)
goto error_read_raw; goto error_read_raw_power_off;
}
break; break;
case IIO_ACCEL: case IIO_ACCEL:
if (!st->chip_config.accl_fifo_enable ||
!st->chip_config.enable) {
result = inv_mpu6050_switch_engine(st, true, result = inv_mpu6050_switch_engine(st, true,
INV_MPU6050_BIT_PWR_ACCL_STBY); INV_MPU6050_BIT_PWR_ACCL_STBY);
if (result) if (result)
goto error_read_raw; goto error_read_raw_power_off;
}
ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl, ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl,
chan->channel2, val); chan->channel2, val);
if (!st->chip_config.accl_fifo_enable ||
!st->chip_config.enable) {
result = inv_mpu6050_switch_engine(st, false, result = inv_mpu6050_switch_engine(st, false,
INV_MPU6050_BIT_PWR_ACCL_STBY); INV_MPU6050_BIT_PWR_ACCL_STBY);
if (result) if (result)
goto error_read_raw; goto error_read_raw_power_off;
}
break; break;
case IIO_TEMP: case IIO_TEMP:
/* wait for stablization */ /* wait for stablization */
...@@ -384,10 +370,12 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev, ...@@ -384,10 +370,12 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
error_read_raw: error_read_raw_power_off:
if (!st->chip_config.enable)
result |= inv_mpu6050_set_power_itg(st, false); result |= inv_mpu6050_set_power_itg(st, false);
mutex_unlock(&indio_dev->mlock); error_read_raw_release:
iio_device_release_direct_mode(indio_dev);
error_read_raw_unlock:
mutex_unlock(&st->lock);
if (result) if (result)
return result; return result;
...@@ -396,13 +384,17 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev, ...@@ -396,13 +384,17 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
switch (chan->type) { switch (chan->type) {
case IIO_ANGL_VEL: case IIO_ANGL_VEL:
mutex_lock(&st->lock);
*val = 0; *val = 0;
*val2 = gyro_scale_6050[st->chip_config.fsr]; *val2 = gyro_scale_6050[st->chip_config.fsr];
mutex_unlock(&st->lock);
return IIO_VAL_INT_PLUS_NANO; return IIO_VAL_INT_PLUS_NANO;
case IIO_ACCEL: case IIO_ACCEL:
mutex_lock(&st->lock);
*val = 0; *val = 0;
*val2 = accel_scale[st->chip_config.accl_fs]; *val2 = accel_scale[st->chip_config.accl_fs];
mutex_unlock(&st->lock);
return IIO_VAL_INT_PLUS_MICRO; return IIO_VAL_INT_PLUS_MICRO;
case IIO_TEMP: case IIO_TEMP:
...@@ -425,12 +417,16 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev, ...@@ -425,12 +417,16 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) { switch (chan->type) {
case IIO_ANGL_VEL: case IIO_ANGL_VEL:
mutex_lock(&st->lock);
ret = inv_mpu6050_sensor_show(st, st->reg->gyro_offset, ret = inv_mpu6050_sensor_show(st, st->reg->gyro_offset,
chan->channel2, val); chan->channel2, val);
mutex_unlock(&st->lock);
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_ACCEL: case IIO_ACCEL:
mutex_lock(&st->lock);
ret = inv_mpu6050_sensor_show(st, st->reg->accl_offset, ret = inv_mpu6050_sensor_show(st, st->reg->accl_offset,
chan->channel2, val); chan->channel2, val);
mutex_unlock(&st->lock);
return IIO_VAL_INT; return IIO_VAL_INT;
default: default:
...@@ -506,18 +502,17 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev, ...@@ -506,18 +502,17 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
struct inv_mpu6050_state *st = iio_priv(indio_dev); struct inv_mpu6050_state *st = iio_priv(indio_dev);
int result; int result;
mutex_lock(&indio_dev->mlock); mutex_lock(&st->lock);
/* /*
* we should only update scale when the chip is disabled, i.e. * we should only update scale when the chip is disabled, i.e.
* not running * not running
*/ */
if (st->chip_config.enable) { result = iio_device_claim_direct_mode(indio_dev);
result = -EBUSY; if (result)
goto error_write_raw; goto error_write_raw_unlock;
}
result = inv_mpu6050_set_power_itg(st, true); result = inv_mpu6050_set_power_itg(st, true);
if (result) if (result)
goto error_write_raw; goto error_write_raw_release;
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
...@@ -553,9 +548,11 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev, ...@@ -553,9 +548,11 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
break; break;
} }
error_write_raw:
result |= inv_mpu6050_set_power_itg(st, false); 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; return result;
} }
...@@ -611,31 +608,35 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr, ...@@ -611,31 +608,35 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr,
if (fifo_rate < INV_MPU6050_MIN_FIFO_RATE || if (fifo_rate < INV_MPU6050_MIN_FIFO_RATE ||
fifo_rate > INV_MPU6050_MAX_FIFO_RATE) fifo_rate > INV_MPU6050_MAX_FIFO_RATE)
return -EINVAL; return -EINVAL;
if (fifo_rate == st->chip_config.fifo_rate)
return count;
mutex_lock(&indio_dev->mlock); mutex_lock(&st->lock);
if (st->chip_config.enable) { if (fifo_rate == st->chip_config.fifo_rate) {
result = -EBUSY; result = 0;
goto fifo_rate_fail; 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); result = inv_mpu6050_set_power_itg(st, true);
if (result) if (result)
goto fifo_rate_fail; goto fifo_rate_fail_release;
d = INV_MPU6050_ONE_K_HZ / fifo_rate - 1; d = INV_MPU6050_ONE_K_HZ / fifo_rate - 1;
result = regmap_write(st->map, st->reg->sample_rate_div, d); result = regmap_write(st->map, st->reg->sample_rate_div, d);
if (result) if (result)
goto fifo_rate_fail; goto fifo_rate_fail_power_off;
st->chip_config.fifo_rate = fifo_rate; st->chip_config.fifo_rate = fifo_rate;
result = inv_mpu6050_set_lpf(st, fifo_rate); result = inv_mpu6050_set_lpf(st, fifo_rate);
if (result) 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); 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) if (result)
return result; return result;
...@@ -650,8 +651,13 @@ inv_fifo_rate_show(struct device *dev, struct device_attribute *attr, ...@@ -650,8 +651,13 @@ inv_fifo_rate_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev)); struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev));
unsigned fifo_rate;
mutex_lock(&st->lock);
fifo_rate = st->chip_config.fifo_rate;
mutex_unlock(&st->lock);
return sprintf(buf, "%d\n", st->chip_config.fifo_rate); 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, ...@@ -678,7 +684,8 @@ static ssize_t inv_attr_show(struct device *dev, struct device_attribute *attr,
case ATTR_ACCL_MATRIX: case ATTR_ACCL_MATRIX:
m = st->plat_data.orientation; 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]); m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
default: default:
return -EINVAL; return -EINVAL;
...@@ -803,26 +810,41 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) ...@@ -803,26 +810,41 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
{ {
int result; int result;
unsigned int regval; unsigned int regval;
int i;
st->hw = &hw_info[st->chip_type]; st->hw = &hw_info[st->chip_type];
st->reg = hw_info[st->chip_type].reg; st->reg = hw_info[st->chip_type].reg;
/* reset to make sure previous state are not there */
result = regmap_write(st->map, st->reg->pwr_mgmt_1,
INV_MPU6050_BIT_H_RESET);
if (result)
return result;
msleep(INV_MPU6050_POWER_UP_TIME);
/* check chip self-identification */ /* check chip self-identification */
result = regmap_read(st->map, INV_MPU6050_REG_WHOAMI, &regval); result = regmap_read(st->map, INV_MPU6050_REG_WHOAMI, &regval);
if (result) if (result)
return result; return result;
if (regval != st->hw->whoami) { 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), dev_warn(regmap_get_device(st->map),
"whoami mismatch got %#02x expected %#02hhx for %s\n", "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); 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);
if (result)
return result;
msleep(INV_MPU6050_POWER_UP_TIME);
/* /*
* toggle power state. After reset, the sleep bit could be on * toggle power state. After reset, the sleep bit could be on
...@@ -869,6 +891,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, ...@@ -869,6 +891,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
return -ENODEV; return -ENODEV;
} }
st = iio_priv(indio_dev); st = iio_priv(indio_dev);
mutex_init(&st->lock);
st->chip_type = chip_type; st->chip_type = chip_type;
st->powerup_count = 0; st->powerup_count = 0;
st->irq = irq; st->irq = irq;
...@@ -962,12 +985,26 @@ EXPORT_SYMBOL_GPL(inv_mpu_core_remove); ...@@ -962,12 +985,26 @@ EXPORT_SYMBOL_GPL(inv_mpu_core_remove);
static int inv_mpu_resume(struct device *dev) 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) 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 */ #endif /* CONFIG_PM_SLEEP */
......
...@@ -32,7 +32,7 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id) ...@@ -32,7 +32,7 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
int ret = 0; int ret = 0;
/* Use the same mutex which was used everywhere to protect power-op */ /* 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) { if (!st->powerup_count) {
ret = regmap_write(st->map, st->reg->pwr_mgmt_1, 0); ret = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
if (ret) if (ret)
...@@ -48,7 +48,7 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id) ...@@ -48,7 +48,7 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
INV_MPU6050_BIT_BYPASS_EN); INV_MPU6050_BIT_BYPASS_EN);
} }
write_error: write_error:
mutex_unlock(&indio_dev->mlock); mutex_unlock(&st->lock);
return ret; return ret;
} }
...@@ -58,14 +58,14 @@ static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id) ...@@ -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 iio_dev *indio_dev = i2c_mux_priv(muxc);
struct inv_mpu6050_state *st = iio_priv(indio_dev); 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 */ /* 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); regmap_write(st->map, st->reg->int_pin_cfg, INV_MPU6050_INT_PIN_CFG);
st->powerup_count--; st->powerup_count--;
if (!st->powerup_count) if (!st->powerup_count)
regmap_write(st->map, st->reg->pwr_mgmt_1, regmap_write(st->map, st->reg->pwr_mgmt_1,
INV_MPU6050_BIT_SLEEP); INV_MPU6050_BIT_SLEEP);
mutex_unlock(&indio_dev->mlock); mutex_unlock(&st->lock);
return 0; return 0;
} }
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/i2c-mux.h> #include <linux/i2c-mux.h>
#include <linux/kfifo.h> #include <linux/kfifo.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/regmap.h> #include <linux/regmap.h>
...@@ -82,7 +83,6 @@ enum inv_devices { ...@@ -82,7 +83,6 @@ enum inv_devices {
* @fsr: Full scale range. * @fsr: Full scale range.
* @lpf: Digital low pass filter frequency. * @lpf: Digital low pass filter frequency.
* @accl_fs: accel full scale range. * @accl_fs: accel full scale range.
* @enable: master enable state.
* @accl_fifo_enable: enable accel data output * @accl_fifo_enable: enable accel data output
* @gyro_fifo_enable: enable gyro data output * @gyro_fifo_enable: enable gyro data output
* @fifo_rate: FIFO update rate. * @fifo_rate: FIFO update rate.
...@@ -91,7 +91,6 @@ struct inv_mpu6050_chip_config { ...@@ -91,7 +91,6 @@ struct inv_mpu6050_chip_config {
unsigned int fsr:2; unsigned int fsr:2;
unsigned int lpf:3; unsigned int lpf:3;
unsigned int accl_fs:2; unsigned int accl_fs:2;
unsigned int enable:1;
unsigned int accl_fifo_enable:1; unsigned int accl_fifo_enable:1;
unsigned int gyro_fifo_enable:1; unsigned int gyro_fifo_enable:1;
u16 fifo_rate; u16 fifo_rate;
...@@ -114,6 +113,7 @@ struct inv_mpu6050_hw { ...@@ -114,6 +113,7 @@ struct inv_mpu6050_hw {
/* /*
* struct inv_mpu6050_state - Driver state variables. * struct inv_mpu6050_state - Driver state variables.
* @TIMESTAMP_FIFO_SIZE: fifo size for timestamp. * @TIMESTAMP_FIFO_SIZE: fifo size for timestamp.
* @lock: Chip access lock.
* @trig: IIO trigger. * @trig: IIO trigger.
* @chip_config: Cached attribute information. * @chip_config: Cached attribute information.
* @reg: Map of important registers. * @reg: Map of important registers.
...@@ -128,6 +128,7 @@ struct inv_mpu6050_hw { ...@@ -128,6 +128,7 @@ struct inv_mpu6050_hw {
*/ */
struct inv_mpu6050_state { struct inv_mpu6050_state {
#define TIMESTAMP_FIFO_SIZE 16 #define TIMESTAMP_FIFO_SIZE 16
struct mutex lock;
struct iio_trigger *trig; struct iio_trigger *trig;
struct inv_mpu6050_chip_config chip_config; struct inv_mpu6050_chip_config chip_config;
const struct inv_mpu6050_reg_map *reg; const struct inv_mpu6050_reg_map *reg;
......
...@@ -128,7 +128,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) ...@@ -128,7 +128,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
u16 fifo_count; u16 fifo_count;
s64 timestamp; s64 timestamp;
mutex_lock(&indio_dev->mlock); mutex_lock(&st->lock);
if (!(st->chip_config.accl_fifo_enable | if (!(st->chip_config.accl_fifo_enable |
st->chip_config.gyro_fifo_enable)) st->chip_config.gyro_fifo_enable))
goto end_session; goto end_session;
...@@ -178,7 +178,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) ...@@ -178,7 +178,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
} }
end_session: end_session:
mutex_unlock(&indio_dev->mlock); mutex_unlock(&st->lock);
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -186,7 +186,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) ...@@ -186,7 +186,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
flush_fifo: flush_fifo:
/* Flush HW and SW FIFOs. */ /* Flush HW and SW FIFOs. */
inv_reset_fifo(indio_dev); inv_reset_fifo(indio_dev);
mutex_unlock(&indio_dev->mlock); mutex_unlock(&st->lock);
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED; return IRQ_HANDLED;
......
...@@ -90,7 +90,6 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable) ...@@ -90,7 +90,6 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
if (result) if (result)
return result; return result;
} }
st->chip_config.enable = enable;
return 0; return 0;
} }
...@@ -103,7 +102,15 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable) ...@@ -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, static int inv_mpu_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state) 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 = { static const struct iio_trigger_ops inv_mpu_trigger_ops = {
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#define ST_LSM6DSX_REG_FIFO_THH_ADDR 0x07 #define ST_LSM6DSX_REG_FIFO_THH_ADDR 0x07
#define ST_LSM6DSX_FIFO_TH_MASK GENMASK(11, 0) #define ST_LSM6DSX_FIFO_TH_MASK GENMASK(11, 0)
#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_MASK BIT(5)
#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 +419,7 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw) ...@@ -417,6 +419,7 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
{ {
struct iio_buffer *buffer; struct iio_buffer *buffer;
unsigned long irq_type; unsigned long irq_type;
bool irq_active_low;
int i, err; int i, err;
irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq)); 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) ...@@ -424,12 +427,23 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
switch (irq_type) { switch (irq_type) {
case IRQF_TRIGGER_HIGH: case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING: case IRQF_TRIGGER_RISING:
irq_active_low = false;
break;
case IRQF_TRIGGER_LOW:
case IRQF_TRIGGER_FALLING:
irq_active_low = true;
break; break;
default: default:
dev_info(hw->dev, "mode %lx unsupported\n", irq_type); dev_info(hw->dev, "mode %lx unsupported\n", irq_type);
return -EINVAL; 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, 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,
......
...@@ -478,21 +478,16 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, ...@@ -478,21 +478,16 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev,
size_t len) size_t len)
{ {
const struct iio_enum *e = (const struct iio_enum *)priv; const struct iio_enum *e = (const struct iio_enum *)priv;
unsigned int i;
int ret; int ret;
if (!e->set) if (!e->set)
return -EINVAL; return -EINVAL;
for (i = 0; i < e->num_items; i++) { ret = __sysfs_match_string(e->items, e->num_items, buf);
if (sysfs_streq(buf, e->items[i])) if (ret < 0)
break; 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; return ret ? ret : len;
} }
EXPORT_SYMBOL_GPL(iio_enum_write); EXPORT_SYMBOL_GPL(iio_enum_write);
...@@ -1428,7 +1423,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) ...@@ -1428,7 +1423,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
static void iio_dev_release(struct device *device) static void iio_dev_release(struct device *device)
{ {
struct iio_dev *indio_dev = dev_to_iio_dev(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_trigger_consumer(indio_dev);
iio_device_unregister_eventset(indio_dev); iio_device_unregister_eventset(indio_dev);
iio_device_unregister_sysfs(indio_dev); iio_device_unregister_sysfs(indio_dev);
...@@ -1710,7 +1705,7 @@ int iio_device_register(struct iio_dev *indio_dev) ...@@ -1710,7 +1705,7 @@ int iio_device_register(struct iio_dev *indio_dev)
"Failed to register event set\n"); "Failed to register event set\n");
goto error_free_sysfs; 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); iio_device_register_trigger_consumer(indio_dev);
if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) && if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) &&
......
...@@ -48,8 +48,6 @@ static int st_magn_spi_remove(struct spi_device *spi) ...@@ -48,8 +48,6 @@ static int st_magn_spi_remove(struct spi_device *spi)
} }
static const struct spi_device_id st_magn_id_table[] = { static const struct spi_device_id st_magn_id_table[] = {
{ LSM303DLHC_MAGN_DEV_NAME },
{ LSM303DLM_MAGN_DEV_NAME },
{ LIS3MDL_MAGN_DEV_NAME }, { LIS3MDL_MAGN_DEV_NAME },
{ LSM303AGR_MAGN_DEV_NAME }, { LSM303AGR_MAGN_DEV_NAME },
{}, {},
......
...@@ -878,8 +878,7 @@ static void sx9500_gpio_probe(struct i2c_client *client, ...@@ -878,8 +878,7 @@ static void sx9500_gpio_probe(struct i2c_client *client,
dev = &client->dev; dev = &client->dev;
data->gpiod_rst = devm_gpiod_get_index(dev, SX9500_GPIO_RESET, data->gpiod_rst = devm_gpiod_get(dev, SX9500_GPIO_RESET, GPIOD_OUT_HIGH);
0, GPIOD_OUT_HIGH);
if (IS_ERR(data->gpiod_rst)) { if (IS_ERR(data->gpiod_rst)) {
dev_warn(dev, "gpio get reset pin failed\n"); dev_warn(dev, "gpio get reset pin failed\n");
data->gpiod_rst = NULL; data->gpiod_rst = NULL;
......
...@@ -417,12 +417,70 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev, ...@@ -417,12 +417,70 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev,
return -EINVAL; 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 = { static const struct iio_info stm32_trigger_info = {
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
.validate_trigger = stm32_counter_validate_trigger,
.read_raw = stm32_counter_read_raw, .read_raw = stm32_counter_read_raw,
.write_raw = stm32_counter_write_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[] = { static const char *const stm32_enable_modes[] = {
"always", "always",
"gated", "gated",
...@@ -606,6 +664,8 @@ static const struct iio_chan_spec_ext_info stm32_trigger_count_info[] = { ...@@ -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_AVAILABLE("quadrature_mode", &stm32_quadrature_mode_enum),
IIO_ENUM("enable_mode", IIO_SEPARATE, &stm32_enable_mode_enum), IIO_ENUM("enable_mode", IIO_SEPARATE, &stm32_enable_mode_enum),
IIO_ENUM_AVAILABLE("enable_mode", &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 ...@@ -630,6 +690,7 @@ static struct stm32_timer_trigger *stm32_setup_counter_device(struct device *dev
indio_dev->name = dev_name(dev); indio_dev->name = dev_name(dev);
indio_dev->dev.parent = dev; indio_dev->dev.parent = dev;
indio_dev->info = &stm32_trigger_info; indio_dev->info = &stm32_trigger_info;
indio_dev->modes = INDIO_HARDWARE_TRIGGERED;
indio_dev->num_channels = 1; indio_dev->num_channels = 1;
indio_dev->channels = &stm32_trigger_channel; indio_dev->channels = &stm32_trigger_channel;
indio_dev->dev.of_node = dev->of_node; indio_dev->dev.of_node = dev->of_node;
......
/*
* 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
...@@ -352,10 +352,16 @@ unsigned int iio_get_time_res(const struct iio_dev *indio_dev); ...@@ -352,10 +352,16 @@ unsigned int iio_get_time_res(const struct iio_dev *indio_dev);
#define INDIO_BUFFER_SOFTWARE 0x04 #define INDIO_BUFFER_SOFTWARE 0x04
#define INDIO_BUFFER_HARDWARE 0x08 #define INDIO_BUFFER_HARDWARE 0x08
#define INDIO_EVENT_TRIGGERED 0x10 #define INDIO_EVENT_TRIGGERED 0x10
#define INDIO_HARDWARE_TRIGGERED 0x20
#define INDIO_ALL_BUFFER_MODES \ #define INDIO_ALL_BUFFER_MODES \
(INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE | INDIO_BUFFER_SOFTWARE) (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 #define INDIO_MAX_RAW_ELEMENTS 4
struct iio_trigger; /* forward declaration */ struct iio_trigger; /* forward declaration */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment