diff options
32 files changed, 1630 insertions, 571 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 index deb015935683..161c147d3c40 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 +++ b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 @@ -138,3 +138,18 @@ Description: Counting is enabled on rising edge of the connected trigger, and remains enabled for the duration of this selected mode. + +What: /sys/bus/iio/devices/iio:deviceX/in_count_trigger_mode_available +KernelVersion: 4.13 +Contact: benjamin.gaignard@st.com +Description: + Reading returns the list possible trigger modes. + +What: /sys/bus/iio/devices/iio:deviceX/in_count0_trigger_mode +KernelVersion: 4.13 +Contact: benjamin.gaignard@st.com +Description: + Configure the device counter trigger mode + counting direction is set by in_count0_count_direction + attribute and the counter is clocked by the connected trigger + rising edges. diff --git a/Documentation/devicetree/bindings/iio/adc/renesas,gyroadc.txt b/Documentation/devicetree/bindings/iio/adc/renesas,gyroadc.txt index 2a62908a774a..df5b9f2ad8d8 100644 --- a/Documentation/devicetree/bindings/iio/adc/renesas,gyroadc.txt +++ b/Documentation/devicetree/bindings/iio/adc/renesas,gyroadc.txt @@ -1,4 +1,4 @@ -* Renesas RCar GyroADC device driver +* Renesas R-Car GyroADC device driver The GyroADC block is a reduced SPI block with up to 8 chipselect lines, which supports the SPI protocol of a selected few SPI ADCs. The SPI ADCs diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt index e35f9f1b3200..8310073f14e1 100644 --- a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt @@ -21,11 +21,19 @@ own configurable sequence and trigger: Contents of a stm32 adc root node: ----------------------------------- Required properties: -- compatible: Should be "st,stm32f4-adc-core". +- compatible: Should be one of: + "st,stm32f4-adc-core" + "st,stm32h7-adc-core" - reg: Offset and length of the ADC block register set. - interrupts: Must contain the interrupt for ADC block. -- clocks: Clock for the analog circuitry (common to all ADCs). -- clock-names: Must be "adc". +- clocks: Core can use up to two clocks, depending on part used: + - "adc" clock: for the analog circuitry, common to all ADCs. + It's required on stm32f4. + It's optional on stm32h7. + - "bus" clock: for registers access, common to all ADCs. + It's not present on stm32f4. + It's required on stm32h7. +- clock-names: Must be "adc" and/or "bus" depending on part used. - interrupt-controller: Identifies the controller node as interrupt-parent - vref-supply: Phandle to the vref input analog reference voltage. - #interrupt-cells = <1>; @@ -42,14 +50,18 @@ An ADC block node should contain at least one subnode, representing an ADC instance available on the machine. Required properties: -- compatible: Should be "st,stm32f4-adc". +- compatible: Should be one of: + "st,stm32f4-adc" + "st,stm32h7-adc" - reg: Offset of ADC instance in ADC block (e.g. may be 0x0, 0x100, 0x200). -- clocks: Input clock private to this ADC instance. +- clocks: Input clock private to this ADC instance. It's required only on + stm32f4, that has per instance clock input for registers access. - interrupt-parent: Phandle to the parent interrupt controller. - interrupts: IRQ Line for the ADC (e.g. may be 0 for adc@0, 1 for adc@100 or 2 for adc@200). - st,adc-channels: List of single-ended channels muxed for this ADC. - It can have up to 16 channels, numbered from 0 to 15 (resp. for in0..in15). + It can have up to 16 channels on stm32f4 or 20 channels on stm32h7, numbered + from 0 to 15 or 19 (resp. for in0..in15 or in0..in19). - #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in Documentation/devicetree/bindings/iio/iio-bindings.txt @@ -58,7 +70,9 @@ Optional properties: See ../../dma/dma.txt for details. - dma-names: Must be "rx" when dmas property is being used. - assigned-resolution-bits: Resolution (bits) to use for conversions. Must - match device available resolutions (e.g. can be 6, 8, 10 or 12 on stm32f4). + match device available resolutions: + * can be 6, 8, 10 or 12 on stm32f4 + * can be 8, 10, 12, 14 or 16 on stm32h7 Default is maximum resolution if unset. Example: diff --git a/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt b/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt index 8305fb05ffda..6f28ff55f3ec 100644 --- a/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt +++ b/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt @@ -13,7 +13,8 @@ Optional properties: "data ready" (valid values: 1 or 2). - interrupt-parent: should be the phandle for the interrupt controller - interrupts: interrupt mapping for IRQ. It should be configured with - flags IRQ_TYPE_LEVEL_HIGH or IRQ_TYPE_EDGE_RISING. + flags IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_EDGE_RISING, IRQ_TYPE_LEVEL_LOW or + IRQ_TYPE_EDGE_FALLING. Refer to interrupt-controller/interrupts.txt for generic interrupt client node bindings. diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index 17b7953f2502..efc67739c28f 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -14,7 +14,6 @@ * BMA250: 7-bit I2C slave address 0x18 or 0x19 */ -#include <linux/acpi.h> #include <linux/module.h> #include <linux/i2c.h> #include <linux/interrupt.h> @@ -37,7 +36,6 @@ enum chip_ids { BMA180, BMA250, - BMA250E, }; struct bma180_data; @@ -57,7 +55,6 @@ struct bma180_part_info { u8 power_reg, power_mask, lowpower_val; u8 int_enable_reg, int_enable_mask; u8 softreset_reg; - u8 chip_id; int (*chip_config)(struct bma180_data *data); void (*chip_disable)(struct bma180_data *data); @@ -115,8 +112,6 @@ struct bma180_part_info { #define BMA250_INT1_DATA_MASK BIT(0) #define BMA250_INT_RESET_MASK BIT(7) /* Reset pending interrupts */ -#define BMA250E_CHIP_ID 0xf9 - struct bma180_data { struct i2c_client *client; struct iio_trigger *trig; @@ -314,7 +309,7 @@ static int bma180_chip_init(struct bma180_data *data) if (ret < 0) return ret; - if (ret != data->part_info->chip_id) + if (ret != BMA180_ID_REG_VAL) return -ENODEV; ret = bma180_soft_reset(data); @@ -637,7 +632,6 @@ static const struct bma180_part_info bma180_part_info[] = { BMA180_TCO_Z, BMA180_MODE_CONFIG, BMA180_LOW_POWER, BMA180_CTRL_REG3, BMA180_NEW_DATA_INT, BMA180_RESET, - BMA180_CHIP_ID, bma180_chip_config, bma180_chip_disable, }, @@ -652,22 +646,6 @@ static const struct bma180_part_info bma180_part_info[] = { BMA250_POWER_REG, BMA250_LOWPOWER_MASK, 1, BMA250_INT_ENABLE_REG, BMA250_DATA_INTEN_MASK, BMA250_RESET_REG, - BMA180_CHIP_ID, - bma250_chip_config, - bma250_chip_disable, - }, - [BMA250E] = { - bma250_channels, ARRAY_SIZE(bma250_channels), - bma250_scale_table, ARRAY_SIZE(bma250_scale_table), - bma250_bw_table, ARRAY_SIZE(bma250_bw_table), - BMA250_INT_RESET_REG, BMA250_INT_RESET_MASK, - BMA250_POWER_REG, BMA250_SUSPEND_MASK, - BMA250_BW_REG, BMA250_BW_MASK, - BMA250_RANGE_REG, BMA250_RANGE_MASK, - BMA250_POWER_REG, BMA250_LOWPOWER_MASK, 1, - BMA250_INT_ENABLE_REG, BMA250_DATA_INTEN_MASK, - BMA250_RESET_REG, - BMA250E_CHIP_ID, bma250_chip_config, bma250_chip_disable, }, @@ -728,8 +706,6 @@ static const struct iio_trigger_ops bma180_trigger_ops = { static int bma180_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct device *dev = &client->dev; - const struct acpi_device_id *acpi_id; struct bma180_data *data; struct iio_dev *indio_dev; enum chip_ids chip; @@ -742,17 +718,10 @@ static int bma180_probe(struct i2c_client *client, data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; - if (dev->of_node) { + if (client->dev.of_node) chip = (enum chip_ids)of_device_get_match_data(&client->dev); - } else if (id) { + else chip = id->driver_data; - } else { - acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev); - if (!acpi_id) - return -ENODEV; - - chip = acpi_id->driver_data; - } data->part_info = &bma180_part_info[chip]; ret = data->part_info->chip_config(data); @@ -873,16 +842,9 @@ static SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume); #define BMA180_PM_OPS NULL #endif -static const struct acpi_device_id bma180_acpi_match[] = { - { "BMA250E", BMA250E }, - { } -}; -MODULE_DEVICE_TABLE(acpi, bma180_acpi_match); - static struct i2c_device_id bma180_ids[] = { { "bma180", BMA180 }, { "bma250", BMA250 }, - { "bma250e", BMA250E }, { } }; @@ -904,7 +866,6 @@ MODULE_DEVICE_TABLE(of, bma180_of_match); static struct i2c_driver bma180_driver = { .driver = { .name = "bma180", - .acpi_match_table = ACPI_PTR(bma180_acpi_match), .pm = BMA180_PM_OPS, .of_match_table = bma180_of_match, }, diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c index bf2704435629..1f53f08476f5 100644 --- a/drivers/iio/accel/mma9551.c +++ b/drivers/iio/accel/mma9551.c @@ -27,7 +27,6 @@ #define MMA9551_DRV_NAME "mma9551" #define MMA9551_IRQ_NAME "mma9551_event" -#define MMA9551_GPIO_NAME "mma9551_int" #define MMA9551_GPIO_COUNT 4 /* Tilt application (inclination in IIO terms). */ @@ -418,8 +417,7 @@ static int mma9551_gpio_probe(struct iio_dev *indio_dev) struct device *dev = &data->client->dev; for (i = 0; i < MMA9551_GPIO_COUNT; i++) { - gpio = devm_gpiod_get_index(dev, MMA9551_GPIO_NAME, i, - GPIOD_IN); + gpio = devm_gpiod_get_index(dev, NULL, i, GPIOD_IN); if (IS_ERR(gpio)) { dev_err(dev, "acpi gpio get index failed\n"); return PTR_ERR(gpio); diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index 29a15f27a51b..1a867f5563a4 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -47,15 +47,11 @@ static int st_accel_spi_remove(struct spi_device *spi) } static const struct spi_device_id st_accel_id_table[] = { - { LSM303DLH_ACCEL_DEV_NAME }, - { LSM303DLHC_ACCEL_DEV_NAME }, { LIS3DH_ACCEL_DEV_NAME }, { LSM330D_ACCEL_DEV_NAME }, { LSM330DL_ACCEL_DEV_NAME }, { LSM330DLC_ACCEL_DEV_NAME }, { LIS331DLH_ACCEL_DEV_NAME }, - { LSM303DL_ACCEL_DEV_NAME }, - { LSM303DLM_ACCEL_DEV_NAME }, { LSM330_ACCEL_DEV_NAME }, { LSM303AGR_ACCEL_DEV_NAME }, { LIS2DH12_ACCEL_DEV_NAME }, diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index 1817ebf5ad84..34e353c43ac8 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -272,11 +272,9 @@ static ssize_t ad7791_write_frequency(struct device *dev, struct ad7791_state *st = iio_priv(indio_dev); int i, ret; - for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++) - if (sysfs_streq(ad7791_sample_freq_avail[i], buf)) - break; - if (i == ARRAY_SIZE(ad7791_sample_freq_avail)) - return -EINVAL; + i = sysfs_match_string(ad7791_sample_freq_avail, buf); + if (i < 0) + return i; ret = iio_device_claim_direct_mode(indio_dev); if (ret) diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c index 62670cbfa2bb..e0ea411a0b2d 100644 --- a/drivers/iio/adc/aspeed_adc.c +++ b/drivers/iio/adc/aspeed_adc.c @@ -212,7 +212,10 @@ static int aspeed_adc_probe(struct platform_device *pdev) } /* Start all channels in normal mode. */ - clk_prepare_enable(data->clk_scaler->clk); + ret = clk_prepare_enable(data->clk_scaler->clk); + if (ret) + goto clk_enable_error; + adc_engine_control_reg_val = GENMASK(31, 16) | ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE; writel(adc_engine_control_reg_val, @@ -236,6 +239,7 @@ iio_register_error: writel(ASPEED_OPERATION_MODE_POWER_DOWN, data->base + ASPEED_REG_ENGINE_CONTROL); clk_disable_unprepare(data->clk_scaler->clk); +clk_enable_error: clk_hw_unregister_divider(data->clk_scaler); scaler_error: diff --git a/drivers/iio/adc/cpcap-adc.c b/drivers/iio/adc/cpcap-adc.c index 62d37f8725b8..6e419d5a7c14 100644 --- a/drivers/iio/adc/cpcap-adc.c +++ b/drivers/iio/adc/cpcap-adc.c @@ -52,6 +52,10 @@ #define CPCAP_BIT_RAND0 BIT(1) /* Set with CAL_MODE */ #define CPCAP_BIT_ADEN BIT(0) /* Currently unused */ +#define CPCAP_REG_ADCC1_DEFAULTS (CPCAP_BIT_ADEN_AUTO_CLR | \ + CPCAP_BIT_ADC_CLK_SEL0 | \ + CPCAP_BIT_RAND1) + /* Register CPCAP_REG_ADCC2 bits */ #define CPCAP_BIT_CAL_FACTOR_ENABLE BIT(15) /* Currently unused */ #define CPCAP_BIT_BATDETB_EN BIT(14) /* Currently unused */ @@ -62,7 +66,7 @@ #define CPCAP_BIT_ADC_PS_FACTOR0 BIT(9) #define CPCAP_BIT_AD4_SELECT BIT(8) /* Currently unused */ #define CPCAP_BIT_ADC_BUSY BIT(7) /* Currently unused */ -#define CPCAP_BIT_THERMBIAS_EN BIT(6) /* Currently unused */ +#define CPCAP_BIT_THERMBIAS_EN BIT(6) /* Bias for AD0_BATTDETB */ #define CPCAP_BIT_ADTRIG_DIS BIT(5) /* Disable interrupt */ #define CPCAP_BIT_LIADC BIT(4) /* Currently unused */ #define CPCAP_BIT_TS_REFEN BIT(3) /* Currently unused */ @@ -70,6 +74,12 @@ #define CPCAP_BIT_TS_M1 BIT(1) /* Currently unused */ #define CPCAP_BIT_TS_M0 BIT(0) /* Currently unused */ +#define CPCAP_REG_ADCC2_DEFAULTS (CPCAP_BIT_AD4_SELECT | \ + CPCAP_BIT_ADTRIG_DIS | \ + CPCAP_BIT_LIADC | \ + CPCAP_BIT_TS_M2 | \ + CPCAP_BIT_TS_M1) + #define CPCAP_MAX_TEMP_LVL 27 #define CPCAP_FOUR_POINT_TWO_ADC 801 #define ST_ADC_CAL_CHRGI_HIGH_THRESHOLD 530 @@ -78,7 +88,7 @@ #define ST_ADC_CAL_BATTI_LOW_THRESHOLD 494 #define ST_ADC_CALIBRATE_DIFF_THRESHOLD 3 -#define CPCAP_ADC_MAX_RETRIES 5 /* Calibration and quirk */ +#define CPCAP_ADC_MAX_RETRIES 5 /* Calibration */ /** * struct cpcap_adc_ato - timing settings for cpcap adc @@ -124,10 +134,10 @@ struct cpcap_adc { */ enum cpcap_adc_channel { /* Bank0 channels */ - CPCAP_ADC_AD0_BATTDETB, /* Battery detection */ + CPCAP_ADC_AD0, /* Battery temperature */ CPCAP_ADC_BATTP, /* Battery voltage */ CPCAP_ADC_VBUS, /* USB VBUS voltage */ - CPCAP_ADC_AD3, /* Battery temperature when charging */ + CPCAP_ADC_AD3, /* Die temperature when charging */ CPCAP_ADC_BPLUS_AD4, /* Another battery or system voltage */ CPCAP_ADC_CHG_ISENSE, /* Calibrated charge current */ CPCAP_ADC_BATTI, /* Calibrated system current */ @@ -217,7 +227,7 @@ struct cpcap_adc_request { /* Phasing table for channels. Note that channels 16 & 17 use BATTP and BATTI */ static const struct cpcap_adc_phasing_tbl bank_phasing[] = { /* Bank0 */ - [CPCAP_ADC_AD0_BATTDETB] = {0, 0x80, 0x80, 0, 1023}, + [CPCAP_ADC_AD0] = {0, 0x80, 0x80, 0, 1023}, [CPCAP_ADC_BATTP] = {0, 0x80, 0x80, 0, 1023}, [CPCAP_ADC_VBUS] = {0, 0x80, 0x80, 0, 1023}, [CPCAP_ADC_AD3] = {0, 0x80, 0x80, 0, 1023}, @@ -243,7 +253,7 @@ static const struct cpcap_adc_phasing_tbl bank_phasing[] = { */ static struct cpcap_adc_conversion_tbl bank_conversion[] = { /* Bank0 */ - [CPCAP_ADC_AD0_BATTDETB] = { + [CPCAP_ADC_AD0] = { IIO_CHAN_INFO_PROCESSED, 0, 0, 0, 1, 1, }, [CPCAP_ADC_BATTP] = { @@ -541,6 +551,15 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata, return; switch (req->channel) { + case CPCAP_ADC_AD0: + value2 |= CPCAP_BIT_THERMBIAS_EN; + error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, + CPCAP_BIT_THERMBIAS_EN, + value2); + if (error) + return; + usleep_range(800, 1000); + break; case CPCAP_ADC_AD8 ... CPCAP_ADC_TSY2_AD15: value1 |= CPCAP_BIT_AD_SEL1; break; @@ -583,7 +602,8 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata, error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, CPCAP_BIT_ATOX_PS_FACTOR | CPCAP_BIT_ADC_PS_FACTOR1 | - CPCAP_BIT_ADC_PS_FACTOR0, + CPCAP_BIT_ADC_PS_FACTOR0 | + CPCAP_BIT_THERMBIAS_EN, value2); if (error) return; @@ -614,27 +634,6 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata, } } -/* - * Occasionally the ADC does not seem to start and there will be no - * interrupt. Let's re-init interrupt to prevent the ADC from hanging - * for the next request. It is unclear why this happens, but the next - * request will usually work after doing this. - */ -static void cpcap_adc_quirk_reset_lost_irq(struct cpcap_adc *ddata) -{ - int error; - - dev_info(ddata->dev, "lost ADC irq, attempting to reinit\n"); - disable_irq(ddata->irq); - error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, - CPCAP_BIT_ADTRIG_DIS, - CPCAP_BIT_ADTRIG_DIS); - if (error) - dev_warn(ddata->dev, "%s reset failed: %i\n", - __func__, error); - enable_irq(ddata->irq); -} - static int cpcap_adc_start_bank(struct cpcap_adc *ddata, struct cpcap_adc_request *req) { @@ -652,7 +651,6 @@ static int cpcap_adc_start_bank(struct cpcap_adc *ddata, return 0; if (error == 0) { - cpcap_adc_quirk_reset_lost_irq(ddata); error = -ETIMEDOUT; continue; } @@ -664,6 +662,21 @@ static int cpcap_adc_start_bank(struct cpcap_adc *ddata, return error; } +static int cpcap_adc_stop_bank(struct cpcap_adc *ddata) +{ + int error; + + error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1, + 0xffff, + CPCAP_REG_ADCC1_DEFAULTS); + if (error) + return error; + + return regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, + 0xffff, + CPCAP_REG_ADCC2_DEFAULTS); +} + static void cpcap_adc_phase(struct cpcap_adc_request *req) { const struct cpcap_adc_conversion_tbl *conv_tbl = req->conv_tbl; @@ -758,7 +771,7 @@ static void cpcap_adc_convert(struct cpcap_adc_request *req) return; /* Temperatures use a lookup table instead of conversion table */ - if ((req->channel == CPCAP_ADC_AD0_BATTDETB) || + if ((req->channel == CPCAP_ADC_AD0) || (req->channel == CPCAP_ADC_AD3)) { req->result = cpcap_adc_table_to_millicelcius(req->result); @@ -820,7 +833,7 @@ static int cpcap_adc_init_request(struct cpcap_adc_request *req, req->conv_tbl = bank_conversion; switch (channel) { - case CPCAP_ADC_AD0_BATTDETB ... CPCAP_ADC_USB_ID: + case CPCAP_ADC_AD0 ... CPCAP_ADC_USB_ID: req->bank_index = channel; break; case CPCAP_ADC_AD8 ... CPCAP_ADC_TSY2_AD15: @@ -839,6 +852,22 @@ static int cpcap_adc_init_request(struct cpcap_adc_request *req, return 0; } +static int cpcap_adc_read_st_die_temp(struct cpcap_adc *ddata, + int addr, int *val) +{ + int error; + + error = regmap_read(ddata->reg, addr, val); + if (error) + return error; + + *val -= 282; + *val *= 114; + *val += 25000; + + return 0; +} + static int cpcap_adc_read(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -860,6 +889,9 @@ static int cpcap_adc_read(struct iio_dev *indio_dev, error = regmap_read(ddata->reg, chan->address, val); if (error) goto err_unlock; + error = cpcap_adc_stop_bank(ddata); + if (error) + goto err_unlock; mutex_unlock(&ddata->lock); break; case IIO_CHAN_INFO_PROCESSED: @@ -867,7 +899,19 @@ static int cpcap_adc_read(struct iio_dev *indio_dev, error = cpcap_adc_start_bank(ddata, &req); if (error) goto err_unlock; - error = cpcap_adc_read_bank_scaled(ddata, &req); + if ((ddata->vendor == CPCAP_VENDOR_ST) && + (chan->channel == CPCAP_ADC_AD3)) { + error = cpcap_adc_read_st_die_temp(ddata, + chan->address, + &req.result); + if (error) + goto err_unlock; + } else { + error = cpcap_adc_read_bank_scaled(ddata, &req); + if (error) + goto err_unlock; + } + error = cpcap_adc_stop_bank(ddata); if (error) goto err_unlock; mutex_unlock(&ddata->lock); diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c index ab59969b7c49..adf7dc712937 100644 --- a/drivers/iio/adc/hi8435.c +++ b/drivers/iio/adc/hi8435.c @@ -410,11 +410,11 @@ static const struct iio_chan_spec hi8435_channels[] = { static const struct iio_info hi8435_info = { .driver_module = THIS_MODULE, .read_raw = hi8435_read_raw, - .read_event_config = &hi8435_read_event_config, + .read_event_config = hi8435_read_event_config, .write_event_config = hi8435_write_event_config, - .read_event_value = &hi8435_read_event_value, - .write_event_value = &hi8435_write_event_value, - .debugfs_reg_access = &hi8435_debugfs_reg_access, + .read_event_value = hi8435_read_event_value, + .write_event_value = hi8435_write_event_value, + .debugfs_reg_access = hi8435_debugfs_reg_access, }; static void hi8435_iio_push_event(struct iio_dev *idev, unsigned int val) @@ -476,15 +476,13 @@ static int hi8435_probe(struct spi_device *spi) priv->spi = spi; reset_gpio = devm_gpiod_get(&spi->dev, NULL, GPIOD_OUT_LOW); - if (!IS_ERR(reset_gpio)) { - /* need >=100ns low pulse to reset chip */ - gpiod_set_raw_value_cansleep(reset_gpio, 0); - udelay(1); - gpiod_set_raw_value_cansleep(reset_gpio, 1); - } else { - /* s/w reset chip if h/w reset is not available */ + if (IS_ERR(reset_gpio)) { + /* chip s/w reset if h/w reset failed */ hi8435_writeb(priv, HI8435_CTRL_REG, HI8435_CTRL_SRST); hi8435_writeb(priv, HI8435_CTRL_REG, 0); + } else { + udelay(5); + gpiod_set_value(reset_gpio, 1); } spi_set_drvdata(spi, idev); diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 6b588ac3130c..232c0b80d658 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -49,6 +49,7 @@ /* settings - depend on use case */ #define INA219_CONFIG_DEFAULT 0x399F /* PGA=8 */ +#define INA219_DEFAULT_IT 532 #define INA226_CONFIG_DEFAULT 0x4327 #define INA226_DEFAULT_AVG 4 #define INA226_DEFAULT_IT 1110 @@ -56,19 +57,24 @@ #define INA2XX_RSHUNT_DEFAULT 10000 /* - * bit mask for reading the averaging setting in the configuration register + * bit masks for reading the settings in the configuration register * FIXME: use regmap_fields. */ #define INA2XX_MODE_MASK GENMASK(3, 0) +/* Averaging for VBus/VShunt/Power */ #define INA226_AVG_MASK GENMASK(11, 9) #define INA226_SHIFT_AVG(val) ((val) << 9) /* Integration time for VBus */ +#define INA219_ITB_MASK GENMASK(10, 7) +#define INA219_SHIFT_ITB(val) ((val) << 7) #define INA226_ITB_MASK GENMASK(8, 6) #define INA226_SHIFT_ITB(val) ((val) << 6) /* Integration time for VShunt */ +#define INA219_ITS_MASK GENMASK(6, 3) +#define INA219_SHIFT_ITS(val) ((val) << 3) #define INA226_ITS_MASK GENMASK(5, 3) #define INA226_SHIFT_ITS(val) ((val) << 3) @@ -108,6 +114,7 @@ struct ina2xx_config { int bus_voltage_shift; int bus_voltage_lsb; /* uV */ int power_lsb; /* uW */ + enum ina2xx_ids chip_id; }; struct ina2xx_chip_info { @@ -130,6 +137,7 @@ static const struct ina2xx_config ina2xx_config[] = { .bus_voltage_shift = 3, .bus_voltage_lsb = 4000, .power_lsb = 20000, + .chip_id = ina219, }, [ina226] = { .config_default = INA226_CONFIG_DEFAULT, @@ -138,6 +146,7 @@ static const struct ina2xx_config ina2xx_config[] = { .bus_voltage_shift = 0, .bus_voltage_lsb = 1250, .power_lsb = 25000, + .chip_id = ina226, }, }; @@ -283,6 +292,66 @@ static int ina226_set_int_time_vshunt(struct ina2xx_chip_info *chip, return 0; } +/* Conversion times in uS. */ +static const int ina219_conv_time_tab_subsample[] = { 84, 148, 276, 532 }; +static const int ina219_conv_time_tab_average[] = { 532, 1060, 2130, 4260, + 8510, 17020, 34050, 68100}; + +static int ina219_lookup_int_time(unsigned int *val_us, int *bits) +{ + if (*val_us > 68100 || *val_us < 84) + return -EINVAL; + + if (*val_us <= 532) { + *bits = find_closest(*val_us, ina219_conv_time_tab_subsample, + ARRAY_SIZE(ina219_conv_time_tab_subsample)); + *val_us = ina219_conv_time_tab_subsample[*bits]; + } else { + *bits = find_closest(*val_us, ina219_conv_time_tab_average, + ARRAY_SIZE(ina219_conv_time_tab_average)); + *val_us = ina219_conv_time_tab_average[*bits]; + *bits |= 0x8; + } + + return 0; +} + +static int ina219_set_int_time_vbus(struct ina2xx_chip_info *chip, + unsigned int val_us, unsigned int *config) +{ + int bits, ret; + unsigned int val_us_best = val_us; + + ret = ina219_lookup_int_time(&val_us_best, &bits); + if (ret) + return ret; + + chip->int_time_vbus = val_us_best; + + *config &= ~INA219_ITB_MASK; + *config |= INA219_SHIFT_ITB(bits) & INA219_ITB_MASK; + + return 0; +} + +static int ina219_set_int_time_vshunt(struct ina2xx_chip_info *chip, + unsigned int val_us, unsigned int *config) +{ + int bits, ret; + unsigned int val_us_best = val_us; + + ret = ina219_lookup_int_time(&val_us_best, &bits); + if (ret) + return ret; + + chip->int_time_vshunt = val_us_best; + + *config &= ~INA219_ITS_MASK; + *config |= INA219_SHIFT_ITS(bits) & INA219_ITS_MASK; + + return 0; +} + static int ina2xx_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) @@ -308,10 +377,21 @@ static int ina2xx_write_raw(struct iio_dev *indio_dev, break; case IIO_CHAN_INFO_INT_TIME: - if (chan->address == INA2XX_SHUNT_VOLTAGE) - ret = ina226_set_int_time_vshunt(chip, val2, &tmp); - else - ret = ina226_set_int_time_vbus(chip, val2, &tmp); + if (chip->config->chip_id == ina226) { + if (chan->address == INA2XX_SHUNT_VOLTAGE) + ret = ina226_set_int_time_vshunt(chip, val2, + &tmp); + else + ret = ina226_set_int_time_vbus(chip, val2, + &tmp); + } else { + if (chan->address == INA2XX_SHUNT_VOLTAGE) + ret = ina219_set_int_time_vshunt(chip, val2, + &tmp); + else + ret = ina219_set_int_time_vbus(chip, val2, + &tmp); + } break; default: @@ -412,7 +492,24 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, return len; } -#define INA2XX_CHAN(_type, _index, _address) { \ +#define INA219_CHAN(_type, _index, _address) { \ + .type = (_type), \ + .address = (_address), \ + .indexed = 1, \ + .channel = (_index), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = (_index), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + } \ +} + +#define INA226_CHAN(_type, _index, _address) { \ .type = (_type), \ .address = (_address), \ .indexed = 1, \ @@ -434,7 +531,25 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, * Sampling Freq is a consequence of the integration times of * the Voltage channels. */ -#define INA2XX_CHAN_VOLTAGE(_index, _address) { \ +#define INA219_CHAN_VOLTAGE(_index, _address) { \ + .type = IIO_VOLTAGE, \ + .address = (_address), \ + .indexed = 1, \ + .channel = (_index), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_INT_TIME), \ + .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = (_index), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_LE, \ + } \ +} + +#define INA226_CHAN_VOLTAGE(_index, _address) { \ .type = IIO_VOLTAGE, \ .address = (_address), \ .indexed = 1, \ @@ -442,6 +557,8 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_INT_TIME), \ + .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .scan_index = (_index), \ .scan_type = { \ .sign = 'u', \ @@ -451,11 +568,20 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, } \ } -static const struct iio_chan_spec ina2xx_channels[] = { - INA2XX_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE), - INA2XX_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE), - INA2XX_CHAN(IIO_POWER, 2, INA2XX_POWER), - INA2XX_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT), + +static const struct iio_chan_spec ina226_channels[] = { + INA226_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE), + INA226_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE), + INA226_CHAN(IIO_POWER, 2, INA2XX_POWER), + INA226_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT), + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +static const struct iio_chan_spec ina219_channels[] = { + INA219_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE), + INA219_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE), + INA219_CHAN(IIO_POWER, 2, INA2XX_POWER), + INA219_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT), IIO_CHAN_SOFT_TIMESTAMP(4), }; @@ -590,7 +716,14 @@ static int ina2xx_debug_reg(struct iio_dev *indio_dev, } /* Possible integration times for vshunt and vbus */ -static IIO_CONST_ATTR_INT_TIME_AVAIL("0.000140 0.000204 0.000332 0.000588 0.001100 0.002116 0.004156 0.008244"); +static IIO_CONST_ATTR_NAMED(ina219_integration_time_available, + integration_time_available, + "0.000084 0.000148 0.000276 0.000532 0.001060 0.002130 0.004260 0.008510 0.017020 0.034050 0.068100"); + +static IIO_CONST_ATTR_NAMED(ina226_integration_time_available, + integration_time_available, + "0.000140 0.000204 0.000332 0.000588 0.001100 0.002116 0.004156 0.008244"); + static IIO_DEVICE_ATTR(in_allow_async_readout, S_IRUGO | S_IWUSR, ina2xx_allow_async_readout_show, @@ -600,20 +733,39 @@ static IIO_DEVICE_ATTR(in_shunt_resistor, S_IRUGO | S_IWUSR, ina2xx_shunt_resistor_show, ina2xx_shunt_resistor_store, 0); -static struct attribute *ina2xx_attributes[] = { +static struct attribute *ina219_attributes[] = { + &iio_dev_attr_in_allow_async_readout.dev_attr.attr, + &iio_const_attr_ina219_integration_time_available.dev_attr.attr, + &iio_dev_attr_in_shunt_resistor.dev_attr.attr, + NULL, +}; + +static struct attribute *ina226_attributes[] = { &iio_dev_attr_in_allow_async_readout.dev_attr.attr, - &iio_const_attr_integration_time_available.dev_attr.attr, + &iio_const_attr_ina226_integration_time_available.dev_attr.attr, &iio_dev_attr_in_shunt_resistor.dev_attr.attr, NULL, }; -static const struct attribute_group ina2xx_attribute_group = { - .attrs = ina2xx_attributes, +static const struct attribute_group ina219_attribute_group = { + .attrs = ina219_attributes, +}; + +static const struct attribute_group ina226_attribute_group = { + .attrs = ina226_attributes, }; -static const struct iio_info ina2xx_info = { +static const struct iio_info ina219_info = { .driver_module = THIS_MODULE, - .attrs = &ina2xx_attribute_group, + .attrs = &ina219_attribute_group, + .read_raw = ina2xx_read_raw, + .write_raw = ina2xx_write_raw, + .debugfs_reg_access = ina2xx_debug_reg, +}; + +static const struct iio_info ina226_info = { + .driver_module = THIS_MODULE, + .attrs = &ina226_attribute_group, .read_raw = ina2xx_read_raw, .write_raw = ina2xx_write_raw, .debugfs_reg_access = ina2xx_debug_reg, @@ -684,6 +836,10 @@ static int ina2xx_probe(struct i2c_client *client, ina226_set_average(chip, INA226_DEFAULT_AVG, &val); ina226_set_int_time_vbus(chip, INA226_DEFAULT_IT, &val); ina226_set_int_time_vshunt(chip, INA226_DEFAULT_IT, &val); + } else { + chip->avg = 1; + ina219_set_int_time_vbus(chip, INA219_DEFAULT_IT, &val); + ina219_set_int_time_vshunt(chip, INA219_DEFAULT_IT, &val); } ret = ina2xx_init(chip, val); @@ -695,10 +851,16 @@ static int ina2xx_probe(struct i2c_client *client, indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; indio_dev->dev.parent = &client->dev; indio_dev->dev.of_node = client->dev.of_node; - indio_dev->channels = ina2xx_channels; - indio_dev->num_channels = ARRAY_SIZE(ina2xx_channels); + if (id->driver_data == ina226) { + indio_dev->channels = ina226_channels; + indio_dev->num_channels = ARRAY_SIZE(ina226_channels); + indio_dev->info = &ina226_info; + } else { + indio_dev->channels = ina219_channels; + indio_dev->num_channels = ARRAY_SIZE(ina219_channels); + indio_dev->info = &ina219_info; + } indio_dev->name = id->name; - indio_dev->info = &ina2xx_info; indio_dev->setup_ops = &ina2xx_setup_ops; buffer = devm_iio_kfifo_allocate(&indio_dev->dev); diff --git a/drivers/iio/adc/lpc32xx_adc.c b/drivers/iio/adc/lpc32xx_adc.c index 0de709b4288b..6a5b9a9bc662 100644 --- a/drivers/iio/adc/lpc32xx_adc.c +++ b/drivers/iio/adc/lpc32xx_adc.c @@ -76,10 +76,14 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev, long mask) { struct lpc32xx_adc_state *st = iio_priv(indio_dev); - + int ret; if (mask == IIO_CHAN_INFO_RAW) { mutex_lock(&indio_dev->mlock); - clk_prepare_enable(st->clk); + ret = clk_prepare_enable(st->clk); + if (ret) { + mutex_unlock(&indio_dev->mlock); + return ret; + } /* Measurement setup */ __raw_writel(LPC32XXAD_INTERNAL | (chan->address) | LPC32XXAD_REFp | LPC32XXAD_REFm, diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c index 6888167ca1e6..d32b34638c2f 100644 --- a/drivers/iio/adc/mxs-lradc-adc.c +++ b/drivers/iio/adc/mxs-lradc-adc.c @@ -48,7 +48,7 @@ #define VREF_MV_BASE 1850 -const char *mx23_lradc_adc_irq_names[] = { +static const char *mx23_lradc_adc_irq_names[] = { "mxs-lradc-channel0", "mxs-lradc-channel1", "mxs-lradc-channel2", @@ -57,7 +57,7 @@ const char *mx23_lradc_adc_irq_names[] = { "mxs-lradc-channel5", }; -const char *mx28_lradc_adc_irq_names[] = { +static const char *mx28_lradc_adc_irq_names[] = { "mxs-lradc-thresh0", "mxs-lradc-thresh1", "mxs-lradc-channel0", @@ -344,20 +344,20 @@ static ssize_t mxs_lradc_adc_show_scale_avail(struct device *dev, IIO_DEVICE_ATTR(in_voltage##ch##_scale_available, 0444,\ mxs_lradc_adc_show_scale_avail, NULL, ch) -SHOW_SCALE_AVAILABLE_ATTR(0); -SHOW_SCALE_AVAILABLE_ATTR(1); -SHOW_SCALE_AVAILABLE_ATTR(2); -SHOW_SCALE_AVAILABLE_ATTR(3); -SHOW_SCALE_AVAILABLE_ATTR(4); -SHOW_SCALE_AVAILABLE_ATTR(5); -SHOW_SCALE_AVAILABLE_ATTR(6); -SHOW_SCALE_AVAILABLE_ATTR(7); -SHOW_SCALE_AVAILABLE_ATTR(10); -SHOW_SCALE_AVAILABLE_ATTR(11); -SHOW_SCALE_AVAILABLE_ATTR(12); -SHOW_SCALE_AVAILABLE_ATTR(13); -SHOW_SCALE_AVAILABLE_ATTR(14); -SHOW_SCALE_AVAILABLE_ATTR(15); +static SHOW_SCALE_AVAILABLE_ATTR(0); +static SHOW_SCALE_AVAILABLE_ATTR(1); +static SHOW_SCALE_AVAILABLE_ATTR(2); +static SHOW_SCALE_AVAILABLE_ATTR(3); +static SHOW_SCALE_AVAILABLE_ATTR(4); +static SHOW_SCALE_AVAILABLE_ATTR(5); +static SHOW_SCALE_AVAILABLE_ATTR(6); +static SHOW_SCALE_AVAILABLE_ATTR(7); +static SHOW_SCALE_AVAILABLE_ATTR(10); +static SHOW_SCALE_AVAILABLE_ATTR(11); +static SHOW_SCALE_AVAILABLE_ATTR(12); +static SHOW_SCALE_AVAILABLE_ATTR(13); +static SHOW_SCALE_AVAILABLE_ATTR(14); +static SHOW_SCALE_AVAILABLE_ATTR(15); static struct attribute *mxs_lradc_adc_attributes[] = { &iio_dev_attr_in_voltage0_scale_available.dev_attr.attr, diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index 22b7c9321e78..e09233b03c05 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -49,19 +49,66 @@ /* STM32 F4 maximum analog clock rate (from datasheet) */ #define STM32F4_ADC_MAX_CLK_RATE 36000000 +/* STM32H7 - common registers for all ADC instances */ +#define STM32H7_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00) +#define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08) + +/* STM32H7_ADC_CSR - bit fields */ +#define STM32H7_EOC_SLV BIT(18) +#define STM32H7_EOC_MST BIT(2) + +/* STM32H7_ADC_CCR - bit fields */ +#define STM32H7_PRESC_SHIFT 18 +#define STM32H7_PRESC_MASK GENMASK(21, 18) +#define STM32H7_CKMODE_SHIFT 16 +#define STM32H7_CKMODE_MASK GENMASK(17, 16) + +/* STM32 H7 maximum analog clock rate (from datasheet) */ +#define STM32H7_ADC_MAX_CLK_RATE 72000000 + +/** + * stm32_adc_common_regs - stm32 common registers, compatible dependent data + * @csr: common status register offset + * @eoc1: adc1 end of conversion flag in @csr + * @eoc2: adc2 end of conversion flag in @csr + * @eoc3: adc3 end of conversion flag in @csr + */ +struct stm32_adc_common_regs { + u32 csr; + u32 eoc1_msk; + u32 eoc2_msk; + u32 eoc3_msk; +}; + +struct stm32_adc_priv; + +/** + * stm32_adc_priv_cfg - stm32 core compatible configuration data + * @regs: common registers for all instances + * @clk_sel: clock selection routine + */ +struct stm32_adc_priv_cfg { + const struct stm32_adc_common_regs *regs; + int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *); +}; + /** * struct stm32_adc_priv - stm32 ADC core private data * @irq: irq for ADC block * @domain: irq domain reference * @aclk: clock reference for the analog circuitry + * @bclk: bus clock common for all ADCs, depends on part used * @vref: regulator reference + * @cfg: compatible configuration data * @common: common data for all ADC instances */ struct stm32_adc_priv { int irq; struct irq_domain *domain; struct clk *aclk; + struct clk *bclk; struct regulator *vref; + const struct stm32_adc_priv_cfg *cfg; struct stm32_adc_common common; }; @@ -85,14 +132,23 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev, u32 val; int i; + /* stm32f4 has one clk input for analog (mandatory), enforce it here */ + if (!priv->aclk) { + dev_err(&pdev->dev, "No 'adc' clock found\n"); + return -ENOENT; + } + rate = clk_get_rate(priv->aclk); for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) { if ((rate / stm32f4_pclk_div[i]) <= STM32F4_ADC_MAX_CLK_RATE) break; } - if (i >= ARRAY_SIZE(stm32f4_pclk_div)) + if (i >= ARRAY_SIZE(stm32f4_pclk_div)) { + dev_err(&pdev->dev, "adc clk selection failed\n"); return -EINVAL; + } + priv->common.rate = rate; val = readl_relaxed(priv->common.base + STM32F4_ADC_CCR); val &= ~STM32F4_ADC_ADCPRE_MASK; val |= i << STM32F4_ADC_ADCPRE_SHIFT; @@ -104,6 +160,126 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev, return 0; } +/** + * struct stm32h7_adc_ck_spec - specification for stm32h7 adc clock + * @ckmode: ADC clock mode, Async or sync with prescaler. + * @presc: prescaler bitfield for async clock mode + * @div: prescaler division ratio + */ +struct stm32h7_adc_ck_spec { + u32 ckmode; + u32 presc; + int div; +}; + +const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = { + /* 00: CK_ADC[1..3]: Asynchronous clock modes */ + { 0, 0, 1 }, + { 0, 1, 2 }, + { 0, 2, 4 }, + { 0, 3, 6 }, + { 0, 4, 8 }, + { 0, 5, 10 }, + { 0, 6, 12 }, + { 0, 7, 16 }, + { 0, 8, 32 }, + { 0, 9, 64 }, + { 0, 10, 128 }, + { 0, 11, 256 }, + /* HCLK used: Synchronous clock modes (1, 2 or 4 prescaler) */ + { 1, 0, 1 }, + { 2, 0, 2 }, + { 3, 0, 4 }, +}; + +static int stm32h7_adc_clk_sel(struct platform_device *pdev, + struct stm32_adc_priv *priv) +{ + u32 ckmode, presc, val; + unsigned long rate; + int i, div; + + /* stm32h7 bus clock is common for all ADC instances (mandatory) */ + if (!priv->bclk) { + dev_err(&pdev->dev, "No 'bus' clock found\n"); + return -ENOENT; + } + + /* + * stm32h7 can use either 'bus' or 'adc' clock for analog circuitry. + * So, choice is to have bus clock mandatory and adc clock optional. + * If optional 'adc' clock has been found, then try to use it first. + */ + if (priv->aclk) { + /* + * Asynchronous clock modes (e.g. ckmode == 0) + * From spec: PLL output musn't exceed max rate + */ + rate = clk_get_rate(priv->aclk); + + for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) { + ckmode = stm32h7_adc_ckmodes_spec[i].ckmode; + presc = stm32h7_adc_ckmodes_spec[i].presc; + div = stm32h7_adc_ckmodes_spec[i].div; + + if (ckmode) + continue; + + if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE) + goto out; + } + } + + /* Synchronous clock modes (e.g. ckmode is 1, 2 or 3) */ + rate = clk_get_rate(priv->bclk); + + for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) { + ckmode = stm32h7_adc_ckmodes_spec[i].ckmode; + presc = stm32h7_adc_ckmodes_spec[i].presc; + div = stm32h7_adc_ckmodes_spec[i].div; + + if (!ckmode) + continue; + + if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE) + goto out; + } + + dev_err(&pdev->dev, "adc clk selection failed\n"); + return -EINVAL; + +out: + /* rate used later by each ADC instance to control BOOST mode */ + priv->common.rate = rate; + + /* Set common clock mode and prescaler */ + val = readl_relaxed(priv->common.base + STM32H7_ADC_CCR); + val &= ~(STM32H7_CKMODE_MASK | STM32H7_PRESC_MASK); + val |= ckmode << STM32H7_CKMODE_SHIFT; + val |= presc << STM32H7_PRESC_SHIFT; + writel_relaxed(val, priv->common.base + STM32H7_ADC_CCR); + + dev_dbg(&pdev->dev, "Using %s clock/%d source at %ld kHz\n", + ckmode ? "bus" : "adc", div, rate / (div * 1000)); + + return 0; +} + +/* STM32F4 common registers definitions */ +static const struct stm32_adc_common_regs stm32f4_adc_common_regs = { + .csr = STM32F4_ADC_CSR, + .eoc1_msk = STM32F4_EOC1, + .eoc2_msk = STM32F4_EOC2, + .eoc3_msk = STM32F4_EOC3, +}; + +/* STM32H7 common registers definitions */ +static const struct stm32_adc_common_regs stm32h7_adc_common_regs = { + .csr = STM32H7_ADC_CSR, + .eoc1_msk = STM32H7_EOC_MST, + .eoc2_msk = STM32H7_EOC_SLV, +}; + /* ADC common interrupt for all instances */ static void stm32_adc_irq_handler(struct irq_desc *desc) { @@ -112,15 +288,15 @@ static void stm32_adc_irq_handler(struct irq_desc *desc) u32 status; chained_irq_enter(chip, desc); - status = readl_relaxed(priv->common.base + STM32F4_ADC_CSR); + status = readl_relaxed(priv->common.base + priv->cfg->regs->csr); - if (status & STM32F4_EOC1) + if (status & priv->cfg->regs->eoc1_msk) generic_handle_irq(irq_find_mapping(priv->domain, 0)); - if (status & STM32F4_EOC2) + if (status & priv->cfg->regs->eoc2_msk) generic_handle_irq(irq_find_mapping(priv->domain, 1)); - if (status & STM32F4_EOC3) + if (status & priv->cfg->regs->eoc3_msk) generic_handle_irq(irq_find_mapping(priv->domain, 2)); chained_irq_exit(chip, desc); @@ -186,6 +362,7 @@ static void stm32_adc_irq_remove(struct platform_device *pdev, static int stm32_adc_probe(struct platform_device *pdev) { struct stm32_adc_priv *priv; + struct device *dev = &pdev->dev; struct device_node *np = pdev->dev.of_node; struct resource *res; int ret; @@ -197,6 +374,9 @@ static int stm32_adc_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; + priv->cfg = (const struct stm32_adc_priv_cfg *) + of_match_device(dev->driver->of_match_table, dev)->data; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->common.base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->common.base)) @@ -227,25 +407,48 @@ static int stm32_adc_probe(struct platform_device *pdev) priv->aclk = devm_clk_get(&pdev->dev, "adc"); if (IS_ERR(priv->aclk)) { ret = PTR_ERR(priv->aclk); - dev_err(&pdev->dev, "Can't get 'adc' clock\n"); - goto err_regulator_disable; + if (ret == -ENOENT) { + priv->aclk = NULL; + } else { + dev_err(&pdev->dev, "Can't get 'adc' clock\n"); + goto err_regulator_disable; + } } - ret = clk_prepare_enable(priv->aclk); - if (ret < 0) { - dev_err(&pdev->dev, "adc clk enable failed\n"); - goto err_regulator_disable; + if (priv->aclk) { + ret = clk_prepare_enable(priv->aclk); + if (ret < 0) { + dev_err(&pdev->dev, "adc clk enable failed\n"); + goto err_regulator_disable; + } } - ret = stm32f4_adc_clk_sel(pdev, priv); - if (ret < 0) { - dev_err(&pdev->dev, "adc clk selection failed\n"); - goto err_clk_disable; + priv->bclk = devm_clk_get(&pdev->dev, "bus"); + if (IS_ERR(priv->bclk)) { + ret = PTR_ERR(priv->bclk); + if (ret == -ENOENT) { + priv->bclk = NULL; + } else { + dev_err(&pdev->dev, "Can't get 'bus' clock\n"); + goto err_aclk_disable; + } + } + + if (priv->bclk) { + ret = clk_prepare_enable(priv->bclk); + if (ret < 0) { + dev_err(&pdev->dev, "adc clk enable failed\n"); + goto err_aclk_disable; + } } + ret = priv->cfg->clk_sel(pdev, priv); + if (ret < 0) + goto err_bclk_disable; + ret = stm32_adc_irq_probe(pdev, priv); if (ret < 0) - goto err_clk_disable; + goto err_bclk_disable; platform_set_drvdata(pdev, &priv->common); @@ -260,8 +463,13 @@ static int stm32_adc_probe(struct platform_device *pdev) err_irq_remove: stm32_adc_irq_remove(pdev, priv); -err_clk_disable: - clk_disable_unprepare(priv->aclk); +err_bclk_disable: + if (priv->bclk) + clk_disable_unprepare(priv->bclk); + +err_aclk_disable: + if (priv->aclk) + clk_disable_unprepare(priv->aclk); err_regulator_disable: regulator_disable(priv->vref); @@ -276,15 +484,34 @@ static int stm32_adc_remove(struct platform_device *pdev) of_platform_depopulate(&pdev->dev); stm32_adc_irq_remove(pdev, priv); - clk_disable_unprepare(priv->aclk); + if (priv->bclk) + clk_disable_unprepare(priv->bclk); + if (priv->aclk) + clk_disable_unprepare(priv->aclk); regulator_disable(priv->vref); return 0; } +static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = { + .regs = &stm32f4_adc_common_regs, + .clk_sel = stm32f4_adc_clk_sel, +}; + +static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = { + .regs = &stm32h7_adc_common_regs, + .clk_sel = stm32h7_adc_clk_sel, +}; + static const struct of_device_id stm32_adc_of_match[] = { - { .compatible = "st,stm32f4-adc-core" }, - {}, + { + .compatible = "st,stm32f4-adc-core", + .data = (void *)&stm32f4_adc_priv_cfg + }, { + .compatible = "st,stm32h7-adc-core", + .data = (void *)&stm32h7_adc_priv_cfg + }, { + }, }; MODULE_DEVICE_TABLE(of, stm32_adc_of_match); diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h index 2ec7abbfbcaa..250ee958a669 100644 --- a/drivers/iio/adc/stm32-adc-core.h +++ b/drivers/iio/adc/stm32-adc-core.h @@ -43,11 +43,13 @@ * struct stm32_adc_common - stm32 ADC driver common data (for all instances) * @base: control registers base cpu addr * @phys_base: control registers base physical addr + * @rate: clock rate used for analog circuitry * @vref_mv: vref voltage (mv) */ struct stm32_adc_common { void __iomem *base; phys_addr_t phys_base; + unsigned long rate; int vref_mv; }; diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index c28e7ff80e11..5bfcc1f13105 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -31,9 +31,11 @@ #include <linux/iio/triggered_buffer.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/of.h> +#include <linux/of_device.h> #include "stm32-adc-core.h" @@ -76,6 +78,78 @@ #define STM32F4_DMA BIT(8) #define STM32F4_ADON BIT(0) +/* STM32H7 - Registers for each ADC instance */ +#define STM32H7_ADC_ISR 0x00 +#define STM32H7_ADC_IER 0x04 +#define STM32H7_ADC_CR 0x08 +#define STM32H7_ADC_CFGR 0x0C +#define STM32H7_ADC_PCSEL 0x1C +#define STM32H7_ADC_SQR1 0x30 +#define STM32H7_ADC_SQR2 0x34 +#define STM32H7_ADC_SQR3 0x38 +#define STM32H7_ADC_SQR4 0x3C +#define STM32H7_ADC_DR 0x40 +#define STM32H7_ADC_CALFACT 0xC4 +#define STM32H7_ADC_CALFACT2 0xC8 + +/* STM32H7_ADC_ISR - bit fields */ +#define STM32H7_EOC BIT(2) +#define STM32H7_ADRDY BIT(0) + +/* STM32H7_ADC_IER - bit fields */ +#define STM32H7_EOCIE STM32H7_EOC + +/* STM32H7_ADC_CR - bit fields */ +#define STM32H7_ADCAL BIT(31) +#define STM32H7_ADCALDIF BIT(30) +#define STM32H7_DEEPPWD BIT(29) +#define STM32H7_ADVREGEN BIT(28) +#define STM32H7_LINCALRDYW6 BIT(27) +#define STM32H7_LINCALRDYW5 BIT(26) +#define STM32H7_LINCALRDYW4 BIT(25) +#define STM32H7_LINCALRDYW3 BIT(24) +#define STM32H7_LINCALRDYW2 BIT(23) +#define STM32H7_LINCALRDYW1 BIT(22) +#define STM32H7_ADCALLIN BIT(16) +#define STM32H7_BOOST BIT(8) +#define STM32H7_ADSTP BIT(4) +#define STM32H7_ADSTART BIT(2) +#define STM32H7_ADDIS BIT(1) +#define STM32H7_ADEN BIT(0) + +/* STM32H7_ADC_CFGR bit fields */ +#define STM32H7_EXTEN_SHIFT 10 +#define STM32H7_EXTEN_MASK GENMASK(11, 10) +#define STM32H7_EXTSEL_SHIFT 5 +#define STM32H7_EXTSEL_MASK GENMASK(9, 5) +#define STM32H7_RES_SHIFT 2 +#define STM32H7_RES_MASK GENMASK(4, 2) +#define STM32H7_DMNGT_SHIFT 0 +#define STM32H7_DMNGT_MASK GENMASK(1, 0) + +enum stm32h7_adc_dmngt { + STM32H7_DMNGT_DR_ONLY, /* Regular data in DR only */ + STM32H7_DMNGT_DMA_ONESHOT, /* DMA one shot mode */ + STM32H7_DMNGT_DFSDM, /* DFSDM mode */ + STM32H7_DMNGT_DMA_CIRC, /* DMA circular mode */ +}; + +/* STM32H7_ADC_CALFACT - bit fields */ +#define STM32H7_CALFACT_D_SHIFT 16 +#define STM32H7_CALFACT_D_MASK GENMASK(26, 16) +#define STM32H7_CALFACT_S_SHIFT 0 +#define STM32H7_CALFACT_S_MASK GENMASK(10, 0) + +/* STM32H7_ADC_CALFACT2 - bit fields */ +#define STM32H7_LINCALFACT_SHIFT 0 +#define STM32H7_LINCALFACT_MASK GENMASK(29, 0) + +/* Number of linear calibration shadow registers / LINCALRDYW control bits */ +#define STM32H7_LINCALFACT_NUM 6 + +/* BOOST bit must be set on STM32H7 when ADC clock is above 20MHz */ +#define STM32H7_BOOST_CLKRATE 20000000UL + #define STM32_ADC_MAX_SQ 16 /* SQ1..SQ16 */ #define STM32_ADC_TIMEOUT_US 100000 #define STM32_ADC_TIMEOUT (msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000)) @@ -121,6 +195,18 @@ struct stm32_adc_trig_info { }; /** + * struct stm32_adc_calib - optional adc calibration data + * @calfact_s: Calibration offset for single ended channels + * @calfact_d: Calibration offset in differential + * @lincalfact: Linearity calibration factor + */ +struct stm32_adc_calib { + u32 calfact_s; + u32 calfact_d; + u32 lincalfact[STM32H7_LINCALFACT_NUM]; +}; + +/** * stm32_adc_regs - stm32 ADC misc registers & bitfield desc * @reg: register offset * @mask: bitfield mask @@ -133,9 +219,56 @@ struct stm32_adc_regs { }; /** + * stm32_adc_regspec - stm32 registers definition, compatible dependent data + * @dr: data register offset + * @ier_eoc: interrupt enable register & eocie bitfield + * @isr_eoc: interrupt status register & eoc bitfield + * @sqr: reference to sequence registers array + * @exten: trigger control register & bitfield + * @extsel: trigger selection register & bitfield + * @res: resolution selection register & bitfield + */ +struct stm32_adc_regspec { + const u32 dr; + const struct stm32_adc_regs ier_eoc; + const struct stm32_adc_regs isr_eoc; + const struct stm32_adc_regs *sqr; + const struct stm32_adc_regs exten; + const struct stm32_adc_regs extsel; + const struct stm32_adc_regs res; +}; + +struct stm32_adc; + +/** + * stm32_adc_cfg - stm32 compatible configuration data + * @regs: registers descriptions + * @adc_info: per instance input channels definitions + * @trigs: external trigger sources + * @clk_required: clock is required + * @selfcalib: optional routine for self-calibration + * @prepare: optional prepare routine (power-up, enable) + * @start_conv: routine to start conversions + * @stop_conv: routine to stop conversions + * @unprepare: optional unprepare routine (disable, power-down) + */ +struct stm32_adc_cfg { + const struct stm32_adc_regspec *regs; + const struct stm32_adc_info *adc_info; + struct stm32_adc_trig_info *trigs; + bool clk_required; + int (*selfcalib)(struct stm32_adc *); + int (*prepare)(struct stm32_adc *); + void (*start_conv)(struct stm32_adc *, bool dma); + void (*stop_conv)(struct stm32_adc *); + void (*unprepare)(struct stm32_adc *); +}; + +/** * struct stm32_adc - private data of each ADC IIO instance * @common: reference to ADC block common data * @offset: ADC instance register offset in ADC block + * @cfg: compatible configuration data * @completion: end of single conversion completion * @buffer: data buffer * @clk: clock for this adc instance @@ -149,10 +282,13 @@ struct stm32_adc_regs { * @rx_buf: dma rx buffer cpu address * @rx_dma_buf: dma rx buffer bus address * @rx_buf_sz: dma rx buffer size + * @pcsel bitmask to preselect channels on some devices + * @cal: optional calibration data on some devices */ struct stm32_adc { struct stm32_adc_common *common; u32 offset; + const struct stm32_adc_cfg *cfg; struct completion completion; u16 buffer[STM32_ADC_MAX_SQ]; struct clk *clk; @@ -166,6 +302,8 @@ struct stm32_adc { u8 *rx_buf; dma_addr_t rx_dma_buf; unsigned int rx_buf_sz; + u32 pcsel; + struct stm32_adc_calib cal; }; /** @@ -180,8 +318,26 @@ struct stm32_adc_chan_spec { const char *name; }; -/* Input definitions common for all STM32F4 instances */ -static const struct stm32_adc_chan_spec stm32f4_adc123_channels[] = { +/** + * struct stm32_adc_info - stm32 ADC, per instance config data + * @channels: Reference to stm32 channels spec + * @max_channels: Number of channels + * @resolutions: available resolutions + * @num_res: number of available resolutions + */ +struct stm32_adc_info { + const struct stm32_adc_chan_spec *channels; + int max_channels; + const unsigned int *resolutions; + const unsigned int num_res; +}; + +/* + * Input definitions common for all instances: + * stm32f4 can have up to 16 channels + * stm32h7 can have up to 20 channels + */ +static const struct stm32_adc_chan_spec stm32_adc_channels[] = { { IIO_VOLTAGE, 0, "in0" }, { IIO_VOLTAGE, 1, "in1" }, { IIO_VOLTAGE, 2, "in2" }, @@ -198,6 +354,10 @@ static const struct stm32_adc_chan_spec stm32f4_adc123_channels[] = { { IIO_VOLTAGE, 13, "in13" }, { IIO_VOLTAGE, 14, "in14" }, { IIO_VOLTAGE, 15, "in15" }, + { IIO_VOLTAGE, 16, "in16" }, + { IIO_VOLTAGE, 17, "in17" }, + { IIO_VOLTAGE, 18, "in18" }, + { IIO_VOLTAGE, 19, "in19" }, }; static const unsigned int stm32f4_adc_resolutions[] = { @@ -205,6 +365,25 @@ static const unsigned int stm32f4_adc_resolutions[] = { 12, 10, 8, 6, }; +static const struct stm32_adc_info stm32f4_adc_info = { + .channels = stm32_adc_channels, + .max_channels = 16, + .resolutions = stm32f4_adc_resolutions, + .num_res = ARRAY_SIZE(stm32f4_adc_resolutions), +}; + +static const unsigned int stm32h7_adc_resolutions[] = { + /* sorted values so the index matches RES[2:0] in STM32H7_ADC_CFGR */ + 16, 14, 12, 10, 8, +}; + +static const struct stm32_adc_info stm32h7_adc_info = { + .channels = stm32_adc_channels, + .max_channels = 20, + .resolutions = stm32h7_adc_resolutions, + .num_res = ARRAY_SIZE(stm32h7_adc_resolutions), +}; + /** * stm32f4_sq - describe regular sequence registers * - L: sequence len (register & bit field) @@ -252,6 +431,69 @@ static struct stm32_adc_trig_info stm32f4_adc_trigs[] = { {}, /* sentinel */ }; +static const struct stm32_adc_regspec stm32f4_adc_regspec = { + .dr = STM32F4_ADC_DR, + .ier_eoc = { STM32F4_ADC_CR1, STM32F4_EOCIE }, + .isr_eoc = { STM32F4_ADC_SR, STM32F4_EOC }, + .sqr = stm32f4_sq, + .exten = { STM32F4_ADC_CR2, STM32F4_EXTEN_MASK, STM32F4_EXTEN_SHIFT }, + .extsel = { STM32F4_ADC_CR2, STM32F4_EXTSEL_MASK, + STM32F4_EXTSEL_SHIFT }, + .res = { STM32F4_ADC_CR1, STM32F4_RES_MASK, STM32F4_RES_SHIFT }, +}; + +static const struct stm32_adc_regs stm32h7_sq[STM32_ADC_MAX_SQ + 1] = { + /* L: len bit field description to be kept as first element */ + { STM32H7_ADC_SQR1, GENMASK(3, 0), 0 }, + /* SQ1..SQ16 registers & bit fields (reg, mask, shift) */ + { STM32H7_ADC_SQR1, GENMASK(10, 6), 6 }, + { STM32H7_ADC_SQR1, GENMASK(16, 12), 12 }, + { STM32H7_ADC_SQR1, GENMASK(22, 18), 18 }, + { STM32H7_ADC_SQR1, GENMASK(28, 24), 24 }, + { STM32H7_ADC_SQR2, GENMASK(4, 0), 0 }, + { STM32H7_ADC_SQR2, GENMASK(10, 6), 6 }, + { STM32H7_ADC_SQR2, GENMASK(16, 12), 12 }, + { STM32H7_ADC_SQR2, GENMASK(22, 18), 18 }, + { STM32H7_ADC_SQR2, GENMASK(28, 24), 24 }, + { STM32H7_ADC_SQR3, GENMASK(4, 0), 0 }, + { STM32H7_ADC_SQR3, GENMASK(10, 6), 6 }, + { STM32H7_ADC_SQR3, GENMASK(16, 12), 12 }, + { STM32H7_ADC_SQR3, GENMASK(22, 18), 18 }, + { STM32H7_ADC_SQR3, GENMASK(28, 24), 24 }, + { STM32H7_ADC_SQR4, GENMASK(4, 0), 0 }, + { STM32H7_ADC_SQR4, GENMASK(10, 6), 6 }, +}; + +/* STM32H7 external trigger sources for all instances */ +static struct stm32_adc_trig_info stm32h7_adc_trigs[] = { + { TIM1_CH1, STM32_EXT0 }, + { TIM1_CH2, STM32_EXT1 }, + { TIM1_CH3, STM32_EXT2 }, + { TIM2_CH2, STM32_EXT3 }, + { TIM3_TRGO, STM32_EXT4 }, + { TIM4_CH4, STM32_EXT5 }, + { TIM8_TRGO, STM32_EXT7 }, + { TIM8_TRGO2, STM32_EXT8 }, + { TIM1_TRGO, STM32_EXT9 }, + { TIM1_TRGO2, STM32_EXT10 }, + { TIM2_TRGO, STM32_EXT11 }, + { TIM4_TRGO, STM32_EXT12 }, + { TIM6_TRGO, STM32_EXT13 }, + { TIM3_CH4, STM32_EXT15 }, + {}, +}; + +static const struct stm32_adc_regspec stm32h7_adc_regspec = { + .dr = STM32H7_ADC_DR, + .ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE }, + .isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC }, + .sqr = stm32h7_sq, + .exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT }, + .extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK, + STM32H7_EXTSEL_SHIFT }, + .res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT }, +}; + /** * STM32 ADC registers access routines * @adc: stm32 adc instance @@ -265,6 +507,12 @@ static u32 stm32_adc_readl(struct stm32_adc *adc, u32 reg) return readl_relaxed(adc->common->base + adc->offset + reg); } +#define stm32_adc_readl_addr(addr) stm32_adc_readl(adc, addr) + +#define stm32_adc_readl_poll_timeout(reg, val, cond, sleep_us, timeout_us) \ + readx_poll_timeout(stm32_adc_readl_addr, reg, val, \ + cond, sleep_us, timeout_us) + static u16 stm32_adc_readw(struct stm32_adc *adc, u32 reg) { return readw_relaxed(adc->common->base + adc->offset + reg); @@ -299,7 +547,8 @@ static void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits) */ static void stm32_adc_conv_irq_enable(struct stm32_adc *adc) { - stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_EOCIE); + stm32_adc_set_bits(adc, adc->cfg->regs->ier_eoc.reg, + adc->cfg->regs->ier_eoc.mask); }; /** @@ -308,19 +557,22 @@ static void stm32_adc_conv_irq_enable(struct stm32_adc *adc) */ static void stm32_adc_conv_irq_disable(struct stm32_adc *adc) { - stm32_adc_clr_bits(adc, STM32F4_ADC_CR1, STM32F4_EOCIE); + stm32_adc_clr_bits(adc, adc->cfg->regs->ier_eoc.reg, + adc->cfg->regs->ier_eoc.mask); } static void stm32_adc_set_res(struct stm32_adc *adc) { - u32 val = stm32_adc_readl(adc, STM32F4_ADC_CR1); + const struct stm32_adc_regs *res = &adc->cfg->regs->res; + u32 val; - val = (val & ~STM32F4_RES_MASK) | (adc->res << STM32F4_RES_SHIFT); - stm32_adc_writel(adc, STM32F4_ADC_CR1, val); + val = stm32_adc_readl(adc, res->reg); + val = (val & ~res->mask) | (adc->res << res->shift); + stm32_adc_writel(adc, res->reg, val); } /** - * stm32_adc_start_conv() - Start conversions for regular channels. + * stm32f4_adc_start_conv() - Start conversions for regular channels. * @adc: stm32 adc instance * @dma: use dma to transfer conversion result * @@ -329,7 +581,7 @@ static void stm32_adc_set_res(struct stm32_adc *adc) * conversions, in IIO buffer modes. Otherwise, use ADC interrupt with direct * DR read instead (e.g. read_raw, or triggered buffer mode without DMA). */ -static void stm32_adc_start_conv(struct stm32_adc *adc, bool dma) +static void stm32f4_adc_start_conv(struct stm32_adc *adc, bool dma) { stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN); @@ -347,7 +599,7 @@ static void stm32_adc_start_conv(struct stm32_adc *adc, bool dma) stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_SWSTART); } -static void stm32_adc_stop_conv(struct stm32_adc *adc) +static void stm32f4_adc_stop_conv(struct stm32_adc *adc) { stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK); stm32_adc_clr_bits(adc, STM32F4_ADC_SR, STM32F4_STRT); @@ -357,6 +609,324 @@ static void stm32_adc_stop_conv(struct stm32_adc *adc) STM32F4_ADON | STM32F4_DMA | STM32F4_DDS); } +static void stm32h7_adc_start_conv(struct stm32_adc *adc, bool dma) +{ + enum stm32h7_adc_dmngt dmngt; + unsigned long flags; + u32 val; + + if (dma) + dmngt = STM32H7_DMNGT_DMA_CIRC; + else + dmngt = STM32H7_DMNGT_DR_ONLY; + + spin_lock_irqsave(&adc->lock, flags); + val = stm32_adc_readl(adc, STM32H7_ADC_CFGR); + val = (val & ~STM32H7_DMNGT_MASK) | (dmngt << STM32H7_DMNGT_SHIFT); + stm32_adc_writel(adc, STM32H7_ADC_CFGR, val); + spin_unlock_irqrestore(&adc->lock, flags); + + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTART); +} + +static void stm32h7_adc_stop_conv(struct stm32_adc *adc) +{ + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + int ret; + u32 val; + + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTP); + + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val, + !(val & (STM32H7_ADSTART)), + 100, STM32_ADC_TIMEOUT_US); + if (ret) + dev_warn(&indio_dev->dev, "stop failed\n"); + + stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK); +} + +static void stm32h7_adc_exit_pwr_down(struct stm32_adc *adc) +{ + /* Exit deep power down, then enable ADC voltage regulator */ + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD); + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADVREGEN); + + if (adc->common->rate > STM32H7_BOOST_CLKRATE) + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST); + + /* Wait for startup time */ + usleep_range(10, 20); +} + +static void stm32h7_adc_enter_pwr_down(struct stm32_adc *adc) +{ + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST); + + /* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */ + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD); +} + +static int stm32h7_adc_enable(struct stm32_adc *adc) +{ + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + int ret; + u32 val; + + /* Clear ADRDY by writing one, then enable ADC */ + stm32_adc_set_bits(adc, STM32H7_ADC_ISR, STM32H7_ADRDY); + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADEN); + + /* Poll for ADRDY to be set (after adc startup time) */ + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_ISR, val, + val & STM32H7_ADRDY, + 100, STM32_ADC_TIMEOUT_US); + if (ret) { + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_ADEN); + dev_err(&indio_dev->dev, "Failed to enable ADC\n"); + } + + return ret; +} + +static void stm32h7_adc_disable(struct stm32_adc *adc) +{ + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + int ret; + u32 val; + + /* Disable ADC and wait until it's effectively disabled */ + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADDIS); + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val, + !(val & STM32H7_ADEN), 100, + STM32_ADC_TIMEOUT_US); + if (ret) + dev_warn(&indio_dev->dev, "Failed to disable\n"); +} + +/** + * stm32h7_adc_read_selfcalib() - read calibration shadow regs, save result + * @adc: stm32 adc instance + */ +static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc) +{ + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + int i, ret; + u32 lincalrdyw_mask, val; + + /* Enable adc so LINCALRDYW1..6 bits are writable */ + ret = stm32h7_adc_enable(adc); + if (ret) + return ret; + + /* Read linearity calibration */ + lincalrdyw_mask = STM32H7_LINCALRDYW6; + for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) { + /* Clear STM32H7_LINCALRDYW[6..1]: transfer calib to CALFACT2 */ + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask); + + /* Poll: wait calib data to be ready in CALFACT2 register */ + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val, + !(val & lincalrdyw_mask), + 100, STM32_ADC_TIMEOUT_US); + if (ret) { + dev_err(&indio_dev->dev, "Failed to read calfact\n"); + goto disable; + } + + val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT2); + adc->cal.lincalfact[i] = (val & STM32H7_LINCALFACT_MASK); + adc->cal.lincalfact[i] >>= STM32H7_LINCALFACT_SHIFT; + + lincalrdyw_mask >>= 1; + } + + /* Read offset calibration */ + val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT); + adc->cal.calfact_s = (val & STM32H7_CALFACT_S_MASK); + adc->cal.calfact_s >>= STM32H7_CALFACT_S_SHIFT; + adc->cal.calfact_d = (val & STM32H7_CALFACT_D_MASK); + adc->cal.calfact_d >>= STM32H7_CALFACT_D_SHIFT; + +disable: + stm32h7_adc_disable(adc); + + return ret; +} + +/** + * stm32h7_adc_restore_selfcalib() - Restore saved self-calibration result + * @adc: stm32 adc instance + * Note: ADC must be enabled, with no on-going conversions. + */ +static int stm32h7_adc_restore_selfcalib(struct stm32_adc *adc) +{ + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + int i, ret; + u32 lincalrdyw_mask, val; + + val = (adc->cal.calfact_s << STM32H7_CALFACT_S_SHIFT) | + (adc->cal.calfact_d << STM32H7_CALFACT_D_SHIFT); + stm32_adc_writel(adc, STM32H7_ADC_CALFACT, val); + + lincalrdyw_mask = STM32H7_LINCALRDYW6; + for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) { + /* + * Write saved calibration data to shadow registers: + * Write CALFACT2, and set LINCALRDYW[6..1] bit to trigger + * data write. Then poll to wait for complete transfer. + */ + val = adc->cal.lincalfact[i] << STM32H7_LINCALFACT_SHIFT; + stm32_adc_writel(adc, STM32H7_ADC_CALFACT2, val); + stm32_adc_set_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask); + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val, + val & lincalrdyw_mask, + 100, STM32_ADC_TIMEOUT_US); + if (ret) { + dev_err(&indio_dev->dev, "Failed to write calfact\n"); + return ret; + } + + /* + * Read back calibration data, has two effects: + * - It ensures bits LINCALRDYW[6..1] are kept cleared + * for next time calibration needs to be restored. + * - BTW, bit clear triggers a read, then check data has been + * correctly written. + */ + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask); + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val, + !(val & lincalrdyw_mask), + 100, STM32_ADC_TIMEOUT_US); + if (ret) { + dev_err(&indio_dev->dev, "Failed to read calfact\n"); + return ret; + } + val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT2); + if (val != adc->cal.lincalfact[i] << STM32H7_LINCALFACT_SHIFT) { + dev_err(&indio_dev->dev, "calfact not consistent\n"); + return -EIO; + } + + lincalrdyw_mask >>= 1; + } + + return 0; +} + +/** + * Fixed timeout value for ADC calibration. + * worst cases: + * - low clock frequency + * - maximum prescalers + * Calibration requires: + * - 131,072 ADC clock cycle for the linear calibration + * - 20 ADC clock cycle for the offset calibration + * + * Set to 100ms for now + */ +#define STM32H7_ADC_CALIB_TIMEOUT_US 100000 + +/** + * stm32h7_adc_selfcalib() - Procedure to calibrate ADC (from power down) + * @adc: stm32 adc instance + * Exit from power down, calibrate ADC, then return to power down. + */ +static int stm32h7_adc_selfcalib(struct stm32_adc *adc) +{ + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + int ret; + u32 val; + + stm32h7_adc_exit_pwr_down(adc); + + /* + * Select calibration mode: + * - Offset calibration for single ended inputs + * - No linearity calibration (do it later, before reading it) + */ + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_ADCALDIF); + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_ADCALLIN); + + /* Start calibration, then wait for completion */ + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADCAL); + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val, + !(val & STM32H7_ADCAL), 100, + STM32H7_ADC_CALIB_TIMEOUT_US); + if (ret) { + dev_err(&indio_dev->dev, "calibration failed\n"); + goto pwr_dwn; + } + + /* + * Select calibration mode, then start calibration: + * - Offset calibration for differential input + * - Linearity calibration (needs to be done only once for single/diff) + * will run simultaneously with offset calibration. + */ + stm32_adc_set_bits(adc, STM32H7_ADC_CR, + STM32H7_ADCALDIF | STM32H7_ADCALLIN); + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADCAL); + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val, + !(val & STM32H7_ADCAL), 100, + STM32H7_ADC_CALIB_TIMEOUT_US); + if (ret) { + dev_err(&indio_dev->dev, "calibration failed\n"); + goto pwr_dwn; + } + + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, + STM32H7_ADCALDIF | STM32H7_ADCALLIN); + + /* Read calibration result for future reference */ + ret = stm32h7_adc_read_selfcalib(adc); + +pwr_dwn: + stm32h7_adc_enter_pwr_down(adc); + + return ret; +} + +/** + * stm32h7_adc_prepare() - Leave power down mode to enable ADC. + * @adc: stm32 adc instance + * Leave power down mode. + * Enable ADC. + * Restore calibration data. + * Pre-select channels that may be used in PCSEL (required by input MUX / IO). + */ +static int stm32h7_adc_prepare(struct stm32_adc *adc) +{ + int ret; + + stm32h7_adc_exit_pwr_down(adc); + + ret = stm32h7_adc_enable(adc); + if (ret) + goto pwr_dwn; + + ret = stm32h7_adc_restore_selfcalib(adc); + if (ret) + goto disable; + + stm32_adc_writel(adc, STM32H7_ADC_PCSEL, adc->pcsel); + + return 0; + +disable: + stm32h7_adc_disable(adc); +pwr_dwn: + stm32h7_adc_enter_pwr_down(adc); + + return ret; +} + +static void stm32h7_adc_unprepare(struct stm32_adc *adc) +{ + stm32h7_adc_disable(adc); + stm32h7_adc_enter_pwr_down(adc); +} + /** * stm32_adc_conf_scan_seq() - Build regular channels scan sequence * @indio_dev: IIO device @@ -371,6 +941,7 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev, const unsigned long *scan_mask) { struct stm32_adc *adc = iio_priv(indio_dev); + const struct stm32_adc_regs *sqr = adc->cfg->regs->sqr; const struct iio_chan_spec *chan; u32 val, bit; int i = 0; @@ -388,20 +959,20 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev, dev_dbg(&indio_dev->dev, "%s chan %d to SQ%d\n", __func__, chan->channel, i); - val = stm32_adc_readl(adc, stm32f4_sq[i].reg); - val &= ~stm32f4_sq[i].mask; - val |= chan->channel << stm32f4_sq[i].shift; - stm32_adc_writel(adc, stm32f4_sq[i].reg, val); + val = stm32_adc_readl(adc, sqr[i].reg); + val &= ~sqr[i].mask; + val |= chan->channel << sqr[i].shift; + stm32_adc_writel(adc, sqr[i].reg, val); } if (!i) return -EINVAL; /* Sequence len */ - val = stm32_adc_readl(adc, stm32f4_sq[0].reg); - val &= ~stm32f4_sq[0].mask; - val |= ((i - 1) << stm32f4_sq[0].shift); - stm32_adc_writel(adc, stm32f4_sq[0].reg, val); + val = stm32_adc_readl(adc, sqr[0].reg); + val &= ~sqr[0].mask; + val |= ((i - 1) << sqr[0].shift); + stm32_adc_writel(adc, sqr[0].reg, val); return 0; } @@ -412,19 +983,21 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev, * * Returns trigger extsel value, if trig matches, -EINVAL otherwise. */ -static int stm32_adc_get_trig_extsel(struct iio_trigger *trig) +static int stm32_adc_get_trig_extsel(struct iio_dev *indio_dev, + struct iio_trigger *trig) { + struct stm32_adc *adc = iio_priv(indio_dev); int i; /* lookup triggers registered by stm32 timer trigger driver */ - for (i = 0; stm32f4_adc_trigs[i].name; i++) { + for (i = 0; adc->cfg->trigs[i].name; i++) { /** * Checking both stm32 timer trigger type and trig name * should be safe against arbitrary trigger names. */ if (is_stm32_timer_trigger(trig) && - !strcmp(stm32f4_adc_trigs[i].name, trig->name)) { - return stm32f4_adc_trigs[i].extsel; + !strcmp(adc->cfg->trigs[i].name, trig->name)) { + return adc->cfg->trigs[i].extsel; } } @@ -449,7 +1022,7 @@ static int stm32_adc_set_trig(struct iio_dev *indio_dev, int ret; if (trig) { - ret = stm32_adc_get_trig_extsel(trig); + ret = stm32_adc_get_trig_extsel(indio_dev, trig); if (ret < 0) return ret; @@ -459,11 +1032,11 @@ static int stm32_adc_set_trig(struct iio_dev *indio_dev, } spin_lock_irqsave(&adc->lock, flags); - val = stm32_adc_readl(adc, STM32F4_ADC_CR2); - val &= ~(STM32F4_EXTEN_MASK | STM32F4_EXTSEL_MASK); - val |= exten << STM32F4_EXTEN_SHIFT; - val |= extsel << STM32F4_EXTSEL_SHIFT; - stm32_adc_writel(adc, STM32F4_ADC_CR2, val); + val = stm32_adc_readl(adc, adc->cfg->regs->exten.reg); + val &= ~(adc->cfg->regs->exten.mask | adc->cfg->regs->extsel.mask); + val |= exten << adc->cfg->regs->exten.shift; + val |= extsel << adc->cfg->regs->extsel.shift; + stm32_adc_writel(adc, adc->cfg->regs->exten.reg, val); spin_unlock_irqrestore(&adc->lock, flags); return 0; @@ -515,6 +1088,7 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev, int *res) { struct stm32_adc *adc = iio_priv(indio_dev); + const struct stm32_adc_regspec *regs = adc->cfg->regs; long timeout; u32 val; int ret; @@ -523,21 +1097,27 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev, adc->bufi = 0; + if (adc->cfg->prepare) { + ret = adc->cfg->prepare(adc); + if (ret) + return ret; + } + /* Program chan number in regular sequence (SQ1) */ - val = stm32_adc_readl(adc, stm32f4_sq[1].reg); - val &= ~stm32f4_sq[1].mask; - val |= chan->channel << stm32f4_sq[1].shift; - stm32_adc_writel(adc, stm32f4_sq[1].reg, val); + val = stm32_adc_readl(adc, regs->sqr[1].reg); + val &= ~regs->sqr[1].mask; + val |= chan->channel << regs->sqr[1].shift; + stm32_adc_writel(adc, regs->sqr[1].reg, val); /* Set regular sequence len (0 for 1 conversion) */ - stm32_adc_clr_bits(adc, stm32f4_sq[0].reg, stm32f4_sq[0].mask); + stm32_adc_clr_bits(adc, regs->sqr[0].reg, regs->sqr[0].mask); /* Trigger detection disabled (conversion can be launched in SW) */ - stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK); + stm32_adc_clr_bits(adc, regs->exten.reg, regs->exten.mask); stm32_adc_conv_irq_enable(adc); - stm32_adc_start_conv(adc, false); + adc->cfg->start_conv(adc, false); timeout = wait_for_completion_interruptible_timeout( &adc->completion, STM32_ADC_TIMEOUT); @@ -550,10 +1130,13 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev, ret = IIO_VAL_INT; } - stm32_adc_stop_conv(adc); + adc->cfg->stop_conv(adc); stm32_adc_conv_irq_disable(adc); + if (adc->cfg->unprepare) + adc->cfg->unprepare(adc); + return ret; } @@ -590,11 +1173,12 @@ static irqreturn_t stm32_adc_isr(int irq, void *data) { struct stm32_adc *adc = data; struct iio_dev *indio_dev = iio_priv_to_dev(adc); - u32 status = stm32_adc_readl(adc, STM32F4_ADC_SR); + const struct stm32_adc_regspec *regs = adc->cfg->regs; + u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg); - if (status & STM32F4_EOC) { + if (status & regs->isr_eoc.mask) { /* Reading DR also clears EOC status flag */ - adc->buffer[adc->bufi] = stm32_adc_readw(adc, STM32F4_ADC_DR); + adc->buffer[adc->bufi] = stm32_adc_readw(adc, regs->dr); if (iio_buffer_enabled(indio_dev)) { adc->bufi++; if (adc->bufi >= adc->num_conv) { @@ -621,7 +1205,7 @@ static irqreturn_t stm32_adc_isr(int irq, void *data) static int stm32_adc_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig) { - return stm32_adc_get_trig_extsel(trig) < 0 ? -EINVAL : 0; + return stm32_adc_get_trig_extsel(indio_dev, trig) < 0 ? -EINVAL : 0; } static int stm32_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val) @@ -777,10 +1361,16 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev) struct stm32_adc *adc = iio_priv(indio_dev); int ret; + if (adc->cfg->prepare) { + ret = adc->cfg->prepare(adc); + if (ret) + return ret; + } + ret = stm32_adc_set_trig(indio_dev, indio_dev->trig); if (ret) { dev_err(&indio_dev->dev, "Can't set trigger\n"); - return ret; + goto err_unprepare; } ret = stm32_adc_dma_start(indio_dev); @@ -799,7 +1389,7 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev) if (!adc->dma_chan) stm32_adc_conv_irq_enable(adc); - stm32_adc_start_conv(adc, !!adc->dma_chan); + adc->cfg->start_conv(adc, !!adc->dma_chan); return 0; @@ -808,6 +1398,9 @@ err_stop_dma: dmaengine_terminate_all(adc->dma_chan); err_clr_trig: stm32_adc_set_trig(indio_dev, NULL); +err_unprepare: + if (adc->cfg->unprepare) + adc->cfg->unprepare(adc); return ret; } @@ -817,7 +1410,7 @@ static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev) struct stm32_adc *adc = iio_priv(indio_dev); int ret; - stm32_adc_stop_conv(adc); + adc->cfg->stop_conv(adc); if (!adc->dma_chan) stm32_adc_conv_irq_disable(adc); @@ -831,6 +1424,9 @@ static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev) if (stm32_adc_set_trig(indio_dev, NULL)) dev_err(&indio_dev->dev, "Can't clear trigger\n"); + if (adc->cfg->unprepare) + adc->cfg->unprepare(adc); + return ret; } @@ -895,12 +1491,12 @@ static int stm32_adc_of_get_resolution(struct iio_dev *indio_dev) u32 res; if (of_property_read_u32(node, "assigned-resolution-bits", &res)) - res = stm32f4_adc_resolutions[0]; + res = adc->cfg->adc_info->resolutions[0]; - for (i = 0; i < ARRAY_SIZE(stm32f4_adc_resolutions); i++) - if (res == stm32f4_adc_resolutions[i]) + for (i = 0; i < adc->cfg->adc_info->num_res; i++) + if (res == adc->cfg->adc_info->resolutions[i]) break; - if (i >= ARRAY_SIZE(stm32f4_adc_resolutions)) { + if (i >= adc->cfg->adc_info->num_res) { dev_err(&indio_dev->dev, "Bad resolution: %u bits\n", res); return -EINVAL; } @@ -926,14 +1522,19 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev, chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); chan->scan_type.sign = 'u'; - chan->scan_type.realbits = stm32f4_adc_resolutions[adc->res]; + chan->scan_type.realbits = adc->cfg->adc_info->resolutions[adc->res]; chan->scan_type.storagebits = 16; chan->ext_info = stm32_adc_ext_info; + + /* pre-build selected channels mask */ + adc->pcsel |= BIT(chan->channel); } static int stm32_adc_chan_of_init(struct iio_dev *indio_dev) { struct device_node *node = indio_dev->dev.of_node; + struct stm32_adc *adc = iio_priv(indio_dev); + const struct stm32_adc_info *adc_info = adc->cfg->adc_info; struct property *prop; const __be32 *cur; struct iio_chan_spec *channels; @@ -942,7 +1543,7 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev) num_channels = of_property_count_u32_elems(node, "st,adc-channels"); if (num_channels < 0 || - num_channels >= ARRAY_SIZE(stm32f4_adc123_channels)) { + num_channels >= adc_info->max_channels) { dev_err(&indio_dev->dev, "Bad st,adc-channels?\n"); return num_channels < 0 ? num_channels : -EINVAL; } @@ -953,12 +1554,12 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev) return -ENOMEM; of_property_for_each_u32(node, "st,adc-channels", prop, cur, val) { - if (val >= ARRAY_SIZE(stm32f4_adc123_channels)) { + if (val >= adc_info->max_channels) { dev_err(&indio_dev->dev, "Invalid channel %d\n", val); return -EINVAL; } stm32_adc_chan_init_one(indio_dev, &channels[scan_index], - &stm32f4_adc123_channels[val], + &adc_info->channels[val], scan_index); scan_index++; } @@ -990,7 +1591,7 @@ static int stm32_adc_dma_request(struct iio_dev *indio_dev) /* Configure DMA channel to read data register */ memset(&config, 0, sizeof(config)); config.src_addr = (dma_addr_t)adc->common->phys_base; - config.src_addr += adc->offset + STM32F4_ADC_DR; + config.src_addr += adc->offset + adc->cfg->regs->dr; config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; ret = dmaengine_slave_config(adc->dma_chan, &config); @@ -1011,6 +1612,7 @@ err_release: static int stm32_adc_probe(struct platform_device *pdev) { struct iio_dev *indio_dev; + struct device *dev = &pdev->dev; struct stm32_adc *adc; int ret; @@ -1025,6 +1627,8 @@ static int stm32_adc_probe(struct platform_device *pdev) adc->common = dev_get_drvdata(pdev->dev.parent); spin_lock_init(&adc->lock); init_completion(&adc->completion); + adc->cfg = (const struct stm32_adc_cfg *) + of_match_device(dev->driver->of_match_table, dev)->data; indio_dev->name = dev_name(&pdev->dev); indio_dev->dev.parent = &pdev->dev; @@ -1055,14 +1659,21 @@ static int stm32_adc_probe(struct platform_device *pdev) adc->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(adc->clk)) { - dev_err(&pdev->dev, "Can't get clock\n"); - return PTR_ERR(adc->clk); + ret = PTR_ERR(adc->clk); + if (ret == -ENOENT && !adc->cfg->clk_required) { + adc->clk = NULL; + } else { + dev_err(&pdev->dev, "Can't get clock\n"); + return ret; + } } - ret = clk_prepare_enable(adc->clk); - if (ret < 0) { - dev_err(&pdev->dev, "clk enable failed\n"); - return ret; + if (adc->clk) { + ret = clk_prepare_enable(adc->clk); + if (ret < 0) { + dev_err(&pdev->dev, "clk enable failed\n"); + return ret; + } } ret = stm32_adc_of_get_resolution(indio_dev); @@ -1070,6 +1681,12 @@ static int stm32_adc_probe(struct platform_device *pdev) goto err_clk_disable; stm32_adc_set_res(adc); + if (adc->cfg->selfcalib) { + ret = adc->cfg->selfcalib(adc); + if (ret) + goto err_clk_disable; + } + ret = stm32_adc_chan_of_init(indio_dev); if (ret < 0) goto err_clk_disable; @@ -1106,7 +1723,8 @@ err_dma_disable: dma_release_channel(adc->dma_chan); } err_clk_disable: - clk_disable_unprepare(adc->clk); + if (adc->clk) + clk_disable_unprepare(adc->clk); return ret; } @@ -1124,13 +1742,35 @@ static int stm32_adc_remove(struct platform_device *pdev) adc->rx_buf, adc->rx_dma_buf); dma_release_channel(adc->dma_chan); } - clk_disable_unprepare(adc->clk); + if (adc->clk) + clk_disable_unprepare(adc->clk); return 0; } +static const struct stm32_adc_cfg stm32f4_adc_cfg = { + .regs = &stm32f4_adc_regspec, + .adc_info = &stm32f4_adc_info, + .trigs = stm32f4_adc_trigs, + .clk_required = true, + .start_conv = stm32f4_adc_start_conv, + .stop_conv = stm32f4_adc_stop_conv, +}; + +static const struct stm32_adc_cfg stm32h7_adc_cfg = { + .regs = &stm32h7_adc_regspec, + .adc_info = &stm32h7_adc_info, + .trigs = stm32h7_adc_trigs, + .selfcalib = stm32h7_adc_selfcalib, + .start_conv = stm32h7_adc_start_conv, + .stop_conv = stm32h7_adc_stop_conv, + .prepare = stm32h7_adc_prepare, + .unprepare = stm32h7_adc_unprepare, +}; + static const struct of_device_id stm32_adc_of_match[] = { - { .compatible = "st,stm32f4-adc" }, + { .compatible = "st,stm32f4-adc", .data = (void *)&stm32f4_adc_cfg }, + { .compatible = "st,stm32h7-adc", .data = (void *)&stm32h7_adc_cfg }, {}, }; MODULE_DEVICE_TABLE(of, stm32_adc_of_match); diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c index 0c74869a540a..bd3d37fc2144 100644 --- a/drivers/iio/adc/twl4030-madc.c +++ b/drivers/iio/adc/twl4030-madc.c @@ -36,7 +36,6 @@ #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/i2c/twl.h> -#include <linux/i2c/twl4030-madc.h> #include <linux/module.h> #include <linux/stddef.h> #include <linux/mutex.h> @@ -49,9 +48,121 @@ #include <linux/iio/iio.h> +#define TWL4030_MADC_MAX_CHANNELS 16 + +#define TWL4030_MADC_CTRL1 0x00 +#define TWL4030_MADC_CTRL2 0x01 + +#define TWL4030_MADC_RTSELECT_LSB 0x02 +#define TWL4030_MADC_SW1SELECT_LSB 0x06 +#define TWL4030_MADC_SW2SELECT_LSB 0x0A + +#define TWL4030_MADC_RTAVERAGE_LSB 0x04 +#define TWL4030_MADC_SW1AVERAGE_LSB 0x08 +#define TWL4030_MADC_SW2AVERAGE_LSB 0x0C + +#define TWL4030_MADC_CTRL_SW1 0x12 +#define TWL4030_MADC_CTRL_SW2 0x13 + +#define TWL4030_MADC_RTCH0_LSB 0x17 +#define TWL4030_MADC_GPCH0_LSB 0x37 + +#define TWL4030_MADC_MADCON (1 << 0) /* MADC power on */ +#define TWL4030_MADC_BUSY (1 << 0) /* MADC busy */ +/* MADC conversion completion */ +#define TWL4030_MADC_EOC_SW (1 << 1) +/* MADC SWx start conversion */ +#define TWL4030_MADC_SW_START (1 << 5) +#define TWL4030_MADC_ADCIN0 (1 << 0) +#define TWL4030_MADC_ADCIN1 (1 << 1) +#define TWL4030_MADC_ADCIN2 (1 << 2) +#define TWL4030_MADC_ADCIN3 (1 << 3) +#define TWL4030_MADC_ADCIN4 (1 << 4) +#define TWL4030_MADC_ADCIN5 (1 << 5) +#define TWL4030_MADC_ADCIN6 (1 << 6) +#define TWL4030_MADC_ADCIN7 (1 << 7) +#define TWL4030_MADC_ADCIN8 (1 << 8) +#define TWL4030_MADC_ADCIN9 (1 << 9) +#define TWL4030_MADC_ADCIN10 (1 << 10) +#define TWL4030_MADC_ADCIN11 (1 << 11) +#define TWL4030_MADC_ADCIN12 (1 << 12) +#define TWL4030_MADC_ADCIN13 (1 << 13) +#define TWL4030_MADC_ADCIN14 (1 << 14) +#define TWL4030_MADC_ADCIN15 (1 << 15) + +/* Fixed channels */ +#define TWL4030_MADC_BTEMP TWL4030_MADC_ADCIN1 +#define TWL4030_MADC_VBUS TWL4030_MADC_ADCIN8 +#define TWL4030_MADC_VBKB TWL4030_MADC_ADCIN9 +#define TWL4030_MADC_ICHG TWL4030_MADC_ADCIN10 +#define TWL4030_MADC_VCHG TWL4030_MADC_ADCIN11 +#define TWL4030_MADC_VBAT TWL4030_MADC_ADCIN12 + +/* Step size and prescaler ratio */ +#define TEMP_STEP_SIZE 147 +#define TEMP_PSR_R 100 +#define CURR_STEP_SIZE 147 +#define CURR_PSR_R1 44 +#define CURR_PSR_R2 88 + +#define TWL4030_BCI_BCICTL1 0x23 +#define TWL4030_BCI_CGAIN 0x020 +#define TWL4030_BCI_MESBAT (1 << 1) +#define TWL4030_BCI_TYPEN (1 << 4) +#define TWL4030_BCI_ITHEN (1 << 3) + +#define REG_BCICTL2 0x024 +#define TWL4030_BCI_ITHSENS 0x007 + +/* Register and bits for GPBR1 register */ +#define TWL4030_REG_GPBR1 0x0c +#define TWL4030_GPBR1_MADC_HFCLK_EN (1 << 7) + #define TWL4030_USB_SEL_MADC_MCPC (1<<3) #define TWL4030_USB_CARKIT_ANA_CTRL 0xBB +struct twl4030_madc_conversion_method { + u8 sel; + u8 avg; + u8 rbase; + u8 ctrl; +}; + +/** + * struct twl4030_madc_request - madc request packet for channel conversion + * @channels: 16 bit bitmap for individual channels + * @do_avg: sample the input channel for 4 consecutive cycles + * @method: RT, SW1, SW2 + * @type: Polling or interrupt based method + * @active: Flag if request is active + * @result_pending: Flag from irq handler, that result is ready + * @raw: Return raw value, do not convert it + * @rbuf: Result buffer + */ +struct twl4030_madc_request { + unsigned long channels; + bool do_avg; + u16 method; + u16 type; + bool active; + bool result_pending; + bool raw; + int rbuf[TWL4030_MADC_MAX_CHANNELS]; +}; + +enum conversion_methods { + TWL4030_MADC_RT, + TWL4030_MADC_SW1, + TWL4030_MADC_SW2, + TWL4030_MADC_NUM_METHODS +}; + +enum sample_type { + TWL4030_MADC_WAIT, + TWL4030_MADC_IRQ_ONESHOT, + TWL4030_MADC_IRQ_REARM +}; + /** * struct twl4030_madc_data - a container for madc info * @dev: Pointer to device structure for madc @@ -72,6 +183,8 @@ struct twl4030_madc_data { u8 isr; }; +static int twl4030_madc_conversion(struct twl4030_madc_request *req); + static int twl4030_madc_read(struct iio_dev *iio_dev, const struct iio_chan_spec *chan, int *val, int *val2, long mask) @@ -84,7 +197,6 @@ static int twl4030_madc_read(struct iio_dev *iio_dev, req.channels = BIT(chan->channel); req.active = false; - req.func_cb = NULL; req.type = TWL4030_MADC_WAIT; req.raw = !(mask == IIO_CHAN_INFO_PROCESSED); req.do_avg = (mask == IIO_CHAN_INFO_AVERAGE_RAW); @@ -341,37 +453,6 @@ static int twl4030_madc_read_channels(struct twl4030_madc_data *madc, } /* - * Enables irq. - * @madc - pointer to twl4030_madc_data struct - * @id - irq number to be enabled - * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2 - * corresponding to RT, SW1, SW2 conversion requests. - * If the i2c read fails it returns an error else returns 0. - */ -static int twl4030_madc_enable_irq(struct twl4030_madc_data *madc, u8 id) -{ - u8 val; - int ret; - - ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr); - if (ret) { - dev_err(madc->dev, "unable to read imr register 0x%X\n", - madc->imr); - return ret; - } - - val &= ~(1 << id); - ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr); - if (ret) { - dev_err(madc->dev, - "unable to write imr register 0x%X\n", madc->imr); - return ret; - } - - return 0; -} - -/* * Disables irq. * @madc - pointer to twl4030_madc_data struct * @id - irq number to be disabled @@ -440,11 +521,6 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc) /* Read results */ len = twl4030_madc_read_channels(madc, method->rbase, r->channels, r->rbuf, r->raw); - /* Return results to caller */ - if (r->func_cb != NULL) { - r->func_cb(len, r->channels, r->rbuf); - r->func_cb = NULL; - } /* Free request */ r->result_pending = 0; r->active = 0; @@ -466,11 +542,6 @@ err_i2c: /* Read results */ len = twl4030_madc_read_channels(madc, method->rbase, r->channels, r->rbuf, r->raw); - /* Return results to caller */ - if (r->func_cb != NULL) { - r->func_cb(len, r->channels, r->rbuf); - r->func_cb = NULL; - } /* Free request */ r->result_pending = 0; r->active = 0; @@ -480,23 +551,6 @@ err_i2c: return IRQ_HANDLED; } -static int twl4030_madc_set_irq(struct twl4030_madc_data *madc, - struct twl4030_madc_request *req) -{ - struct twl4030_madc_request *p; - int ret; - - p = &madc->requests[req->method]; - memcpy(p, req, sizeof(*req)); - ret = twl4030_madc_enable_irq(madc, req->method); - if (ret < 0) { - dev_err(madc->dev, "enable irq failed!!\n"); - return ret; - } - - return 0; -} - /* * Function which enables the madc conversion * by writing to the control register. @@ -568,7 +622,7 @@ static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc, * be a negative error value in the corresponding array element. * returns 0 if succeeds else error value */ -int twl4030_madc_conversion(struct twl4030_madc_request *req) +static int twl4030_madc_conversion(struct twl4030_madc_request *req) { const struct twl4030_madc_conversion_method *method; int ret; @@ -605,17 +659,6 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req) goto out; } } - if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) { - ret = twl4030_madc_set_irq(twl4030_madc, req); - if (ret < 0) - goto out; - ret = twl4030_madc_start_conversion(twl4030_madc, req->method); - if (ret < 0) - goto out; - twl4030_madc->requests[req->method].active = 1; - ret = 0; - goto out; - } /* With RT method we should not be here anymore */ if (req->method == TWL4030_MADC_RT) { ret = -EINVAL; @@ -640,28 +683,6 @@ out: return ret; } -EXPORT_SYMBOL_GPL(twl4030_madc_conversion); - -int twl4030_get_madc_conversion(int channel_no) -{ - struct twl4030_madc_request req; - int temp = 0; - int ret; - - req.channels = (1 << channel_no); - req.method = TWL4030_MADC_SW2; - req.active = 0; - req.raw = 0; - req.func_cb = NULL; - ret = twl4030_madc_conversion(&req); - if (ret < 0) - return ret; - if (req.rbuf[channel_no] > 0) - temp = req.rbuf[channel_no]; - - return temp; -} -EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion); /** * twl4030_madc_set_current_generator() - setup bias current diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c index 56cf5907a5f0..4a60497a1f19 100644 --- a/drivers/iio/adc/xilinx-xadc-core.c +++ b/drivers/iio/adc/xilinx-xadc-core.c @@ -1204,7 +1204,10 @@ static int xadc_probe(struct platform_device *pdev) ret = PTR_ERR(xadc->clk); goto err_free_samplerate_trigger; } - clk_prepare_enable(xadc->clk); + + ret = clk_prepare_enable(xadc->clk); + if (ret) + goto err_free_samplerate_trigger; ret = xadc->ops->setup(pdev, indio_dev, irq); if (ret) diff --git a/drivers/iio/common/hid-sensors/Kconfig b/drivers/iio/common/hid-sensors/Kconfig index 39188b72cd3b..80105378b0ba 100644 --- a/drivers/iio/common/hid-sensors/Kconfig +++ b/drivers/iio/common/hid-sensors/Kconfig @@ -16,7 +16,7 @@ config HID_SENSOR_IIO_COMMON config HID_SENSOR_IIO_TRIGGER tristate "Common module (trigger) for all HID Sensor IIO drivers" - depends on HID_SENSOR_HUB && HID_SENSOR_IIO_COMMON + depends on HID_SENSOR_HUB && HID_SENSOR_IIO_COMMON && IIO_BUFFER select IIO_TRIGGER help Say yes here to build trigger support for HID sensors. diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 88a7c5d4e4d2..44830bce13df 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -188,7 +188,6 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on) int result = 0; if (power_on) { - /* Already under indio-dev->mlock mutex */ if (!st->powerup_count) result = regmap_write(st->map, st->reg->pwr_mgmt_1, 0); if (!result) @@ -329,50 +328,37 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev, int result; ret = IIO_VAL_INT; - result = 0; - mutex_lock(&indio_dev->mlock); - if (!st->chip_config.enable) { - result = inv_mpu6050_set_power_itg(st, true); - if (result) - goto error_read_raw; - } - /* when enable is on, power is already on */ + mutex_lock(&st->lock); + result = iio_device_claim_direct_mode(indio_dev); + if (result) + goto error_read_raw_unlock; + result = inv_mpu6050_set_power_itg(st, true); + if (result) + goto error_read_raw_release; switch (chan->type) { case IIO_ANGL_VEL: - if (!st->chip_config.gyro_fifo_enable || - !st->chip_config.enable) { - result = inv_mpu6050_switch_engine(st, true, - INV_MPU6050_BIT_PWR_GYRO_STBY); - if (result) - goto error_read_raw; - } + result = inv_mpu6050_switch_engine(st, true, + INV_MPU6050_BIT_PWR_GYRO_STBY); + if (result) + goto error_read_raw_power_off; ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro, chan->channel2, val); - if (!st->chip_config.gyro_fifo_enable || - !st->chip_config.enable) { - result = inv_mpu6050_switch_engine(st, false, - INV_MPU6050_BIT_PWR_GYRO_STBY); - if (result) - goto error_read_raw; - } + result = inv_mpu6050_switch_engine(st, false, + INV_MPU6050_BIT_PWR_GYRO_STBY); + if (result) + goto error_read_raw_power_off; break; case IIO_ACCEL: - if (!st->chip_config.accl_fifo_enable || - !st->chip_config.enable) { - result = inv_mpu6050_switch_engine(st, true, - INV_MPU6050_BIT_PWR_ACCL_STBY); - if (result) - goto error_read_raw; - } + result = inv_mpu6050_switch_engine(st, true, + INV_MPU6050_BIT_PWR_ACCL_STBY); + if (result) + goto error_read_raw_power_off; ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl, chan->channel2, val); - if (!st->chip_config.accl_fifo_enable || - !st->chip_config.enable) { - result = inv_mpu6050_switch_engine(st, false, - INV_MPU6050_BIT_PWR_ACCL_STBY); - if (result) - goto error_read_raw; - } + result = inv_mpu6050_switch_engine(st, false, + INV_MPU6050_BIT_PWR_ACCL_STBY); + if (result) + goto error_read_raw_power_off; break; case IIO_TEMP: /* wait for stablization */ @@ -384,10 +370,12 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev, ret = -EINVAL; break; } -error_read_raw: - if (!st->chip_config.enable) - result |= inv_mpu6050_set_power_itg(st, false); - mutex_unlock(&indio_dev->mlock); +error_read_raw_power_off: + result |= inv_mpu6050_set_power_itg(st, false); +error_read_raw_release: + iio_device_release_direct_mode(indio_dev); +error_read_raw_unlock: + mutex_unlock(&st->lock); if (result) return result; @@ -396,13 +384,17 @@ error_read_raw: case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_ANGL_VEL: + mutex_lock(&st->lock); *val = 0; *val2 = gyro_scale_6050[st->chip_config.fsr]; + mutex_unlock(&st->lock); return IIO_VAL_INT_PLUS_NANO; case IIO_ACCEL: + mutex_lock(&st->lock); *val = 0; *val2 = accel_scale[st->chip_config.accl_fs]; + mutex_unlock(&st->lock); return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: @@ -425,12 +417,16 @@ error_read_raw: case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { case IIO_ANGL_VEL: + mutex_lock(&st->lock); ret = inv_mpu6050_sensor_show(st, st->reg->gyro_offset, chan->channel2, val); + mutex_unlock(&st->lock); return IIO_VAL_INT; case IIO_ACCEL: + mutex_lock(&st->lock); ret = inv_mpu6050_sensor_show(st, st->reg->accl_offset, chan->channel2, val); + mutex_unlock(&st->lock); return IIO_VAL_INT; default: @@ -506,18 +502,17 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev, struct inv_mpu6050_state *st = iio_priv(indio_dev); int result; - mutex_lock(&indio_dev->mlock); + mutex_lock(&st->lock); /* * we should only update scale when the chip is disabled, i.e. * not running */ - if (st->chip_config.enable) { - result = -EBUSY; - goto error_write_raw; - } + result = iio_device_claim_direct_mode(indio_dev); + if (result) + goto error_write_raw_unlock; result = inv_mpu6050_set_power_itg(st, true); if (result) - goto error_write_raw; + goto error_write_raw_release; switch (mask) { case IIO_CHAN_INFO_SCALE: @@ -553,9 +548,11 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev, break; } -error_write_raw: result |= inv_mpu6050_set_power_itg(st, false); - mutex_unlock(&indio_dev->mlock); +error_write_raw_release: + iio_device_release_direct_mode(indio_dev); +error_write_raw_unlock: + mutex_unlock(&st->lock); return result; } @@ -611,31 +608,35 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr, if (fifo_rate < INV_MPU6050_MIN_FIFO_RATE || fifo_rate > INV_MPU6050_MAX_FIFO_RATE) return -EINVAL; - if (fifo_rate == st->chip_config.fifo_rate) - return count; - mutex_lock(&indio_dev->mlock); - if (st->chip_config.enable) { - result = -EBUSY; - goto fifo_rate_fail; + mutex_lock(&st->lock); + if (fifo_rate == st->chip_config.fifo_rate) { + result = 0; + goto fifo_rate_fail_unlock; } + result = iio_device_claim_direct_mode(indio_dev); + if (result) + goto fifo_rate_fail_unlock; result = inv_mpu6050_set_power_itg(st, true); if (result) - goto fifo_rate_fail; + goto fifo_rate_fail_release; d = INV_MPU6050_ONE_K_HZ / fifo_rate - 1; result = regmap_write(st->map, st->reg->sample_rate_div, d); if (result) - goto fifo_rate_fail; + goto fifo_rate_fail_power_off; st->chip_config.fifo_rate = fifo_rate; result = inv_mpu6050_set_lpf(st, fifo_rate); if (result) - goto fifo_rate_fail; + goto fifo_rate_fail_power_off; -fifo_rate_fail: +fifo_rate_fail_power_off: result |= inv_mpu6050_set_power_itg(st, false); - mutex_unlock(&indio_dev->mlock); +fifo_rate_fail_release: + iio_device_release_direct_mode(indio_dev); +fifo_rate_fail_unlock: + mutex_unlock(&st->lock); if (result) return result; @@ -650,8 +651,13 @@ inv_fifo_rate_show(struct device *dev, struct device_attribute *attr, char *buf) { struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev)); + unsigned fifo_rate; + + 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, case ATTR_ACCL_MATRIX: m = st->plat_data.orientation; - return sprintf(buf, "%d, %d, %d; %d, %d, %d; %d, %d, %d\n", + return scnprintf(buf, PAGE_SIZE, + "%d, %d, %d; %d, %d, %d; %d, %d, %d\n", m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]); default: return -EINVAL; @@ -803,27 +810,42 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) { int result; unsigned int regval; + int i; st->hw = &hw_info[st->chip_type]; st->reg = hw_info[st->chip_type].reg; - /* 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 */ result = regmap_read(st->map, INV_MPU6050_REG_WHOAMI, ®val); if (result) return result; if (regval != st->hw->whoami) { - dev_warn(regmap_get_device(st->map), - "whoami mismatch got %#02x expected %#02hhx for %s\n", + /* check whoami against all possible values */ + for (i = 0; i < INV_NUM_PARTS; ++i) { + if (regval == hw_info[i].whoami) { + dev_warn(regmap_get_device(st->map), + "whoami mismatch got %#02x (%s)" + "expected %#02hhx (%s)\n", + regval, hw_info[i].name, + st->hw->whoami, st->hw->name); + break; + } + } + if (i >= INV_NUM_PARTS) { + dev_err(regmap_get_device(st->map), + "invalid whoami %#02x expected %#02hhx (%s)\n", regval, st->hw->whoami, st->hw->name); + return -ENODEV; + } } + /* reset to make sure previous state are not there */ + result = regmap_write(st->map, st->reg->pwr_mgmt_1, + INV_MPU6050_BIT_H_RESET); + if (result) + return result; + msleep(INV_MPU6050_POWER_UP_TIME); + /* * toggle power state. After reset, the sleep bit could be on * or off depending on the OTP settings. Toggling power would @@ -869,6 +891,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, return -ENODEV; } st = iio_priv(indio_dev); + mutex_init(&st->lock); st->chip_type = chip_type; st->powerup_count = 0; st->irq = irq; @@ -962,12 +985,26 @@ EXPORT_SYMBOL_GPL(inv_mpu_core_remove); static int inv_mpu_resume(struct device *dev) { - return inv_mpu6050_set_power_itg(iio_priv(dev_get_drvdata(dev)), true); + struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev)); + int result; + + mutex_lock(&st->lock); + result = inv_mpu6050_set_power_itg(st, true); + mutex_unlock(&st->lock); + + return result; } static int inv_mpu_suspend(struct device *dev) { - return inv_mpu6050_set_power_itg(iio_priv(dev_get_drvdata(dev)), false); + struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev)); + int result; + + mutex_lock(&st->lock); + result = inv_mpu6050_set_power_itg(st, false); + mutex_unlock(&st->lock); + + return result; } #endif /* CONFIG_PM_SLEEP */ diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c index 64b5f5b92200..fcd7a92b6cf8 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c @@ -32,7 +32,7 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id) int ret = 0; /* Use the same mutex which was used everywhere to protect power-op */ - mutex_lock(&indio_dev->mlock); + mutex_lock(&st->lock); if (!st->powerup_count) { ret = regmap_write(st->map, st->reg->pwr_mgmt_1, 0); if (ret) @@ -48,7 +48,7 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id) INV_MPU6050_BIT_BYPASS_EN); } write_error: - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&st->lock); return ret; } @@ -58,14 +58,14 @@ static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id) struct iio_dev *indio_dev = i2c_mux_priv(muxc); struct inv_mpu6050_state *st = iio_priv(indio_dev); - mutex_lock(&indio_dev->mlock); + mutex_lock(&st->lock); /* It doesn't really mattter, if any of the calls fails */ regmap_write(st->map, st->reg->int_pin_cfg, INV_MPU6050_INT_PIN_CFG); st->powerup_count--; if (!st->powerup_count) regmap_write(st->map, st->reg->pwr_mgmt_1, INV_MPU6050_BIT_SLEEP); - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&st->lock); return 0; } diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index 953a0c09d568..065794162d65 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -14,6 +14,7 @@ #include <linux/i2c-mux.h> #include <linux/kfifo.h> #include <linux/spinlock.h> +#include <linux/mutex.h> #include <linux/iio/iio.h> #include <linux/iio/buffer.h> #include <linux/regmap.h> @@ -82,7 +83,6 @@ enum inv_devices { * @fsr: Full scale range. * @lpf: Digital low pass filter frequency. * @accl_fs: accel full scale range. - * @enable: master enable state. * @accl_fifo_enable: enable accel data output * @gyro_fifo_enable: enable gyro data output * @fifo_rate: FIFO update rate. @@ -91,7 +91,6 @@ struct inv_mpu6050_chip_config { unsigned int fsr:2; unsigned int lpf:3; unsigned int accl_fs:2; - unsigned int enable:1; unsigned int accl_fifo_enable:1; unsigned int gyro_fifo_enable:1; u16 fifo_rate; @@ -114,6 +113,7 @@ struct inv_mpu6050_hw { /* * struct inv_mpu6050_state - Driver state variables. * @TIMESTAMP_FIFO_SIZE: fifo size for timestamp. + * @lock: Chip access lock. * @trig: IIO trigger. * @chip_config: Cached attribute information. * @reg: Map of important registers. @@ -128,6 +128,7 @@ struct inv_mpu6050_hw { */ struct inv_mpu6050_state { #define TIMESTAMP_FIFO_SIZE 16 + struct mutex lock; struct iio_trigger *trig; struct inv_mpu6050_chip_config chip_config; const struct inv_mpu6050_reg_map *reg; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c index 3a9f3eac91ab..ff81c6aa009d 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c @@ -128,7 +128,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) u16 fifo_count; s64 timestamp; - mutex_lock(&indio_dev->mlock); + mutex_lock(&st->lock); if (!(st->chip_config.accl_fifo_enable | st->chip_config.gyro_fifo_enable)) goto end_session; @@ -178,7 +178,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) } end_session: - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&st->lock); iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; @@ -186,7 +186,7 @@ end_session: flush_fifo: /* Flush HW and SW FIFOs. */ inv_reset_fifo(indio_dev); - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&st->lock); iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c index e8818d4dd4b8..540070f0a230 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c @@ -90,7 +90,6 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable) if (result) return result; } - st->chip_config.enable = enable; return 0; } @@ -103,7 +102,15 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable) static int inv_mpu_data_rdy_trigger_set_state(struct iio_trigger *trig, bool state) { - return inv_mpu6050_set_enable(iio_trigger_get_drvdata(trig), state); + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct inv_mpu6050_state *st = iio_priv(indio_dev); + int result; + + mutex_lock(&st->lock); + result = inv_mpu6050_set_enable(indio_dev, state); + mutex_unlock(&st->lock); + + return result; } static const struct iio_trigger_ops inv_mpu_trigger_ops = { diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index b19a62d8c884..2a72acc6e049 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -37,6 +37,8 @@ #define ST_LSM6DSX_REG_FIFO_THH_ADDR 0x07 #define ST_LSM6DSX_FIFO_TH_MASK GENMASK(11, 0) #define ST_LSM6DSX_REG_FIFO_DEC_GXL_ADDR 0x08 +#define ST_LSM6DSX_REG_HLACTIVE_ADDR 0x12 +#define ST_LSM6DSX_REG_HLACTIVE_MASK BIT(5) #define ST_LSM6DSX_REG_FIFO_MODE_ADDR 0x0a #define ST_LSM6DSX_FIFO_MODE_MASK GENMASK(2, 0) #define ST_LSM6DSX_FIFO_ODR_MASK GENMASK(6, 3) @@ -417,6 +419,7 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw) { struct iio_buffer *buffer; unsigned long irq_type; + bool irq_active_low; int i, err; irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq)); @@ -424,12 +427,23 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw) switch (irq_type) { case IRQF_TRIGGER_HIGH: case IRQF_TRIGGER_RISING: + irq_active_low = false; + break; + case IRQF_TRIGGER_LOW: + case IRQF_TRIGGER_FALLING: + irq_active_low = true; break; default: dev_info(hw->dev, "mode %lx unsupported\n", irq_type); return -EINVAL; } + err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_HLACTIVE_ADDR, + ST_LSM6DSX_REG_HLACTIVE_MASK, + irq_active_low); + if (err < 0) + return err; + err = devm_request_threaded_irq(hw->dev, hw->irq, st_lsm6dsx_handler_irq, st_lsm6dsx_handler_thread, diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 4a1de59d153a..17ec4cee51dc 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -478,21 +478,16 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, size_t len) { const struct iio_enum *e = (const struct iio_enum *)priv; - unsigned int i; int ret; if (!e->set) return -EINVAL; - for (i = 0; i < e->num_items; i++) { - if (sysfs_streq(buf, e->items[i])) - break; - } - - if (i == e->num_items) - return -EINVAL; + ret = __sysfs_match_string(e->items, e->num_items, buf); + if (ret < 0) + return ret; - ret = e->set(indio_dev, chan, i); + ret = e->set(indio_dev, chan, ret); return ret ? ret : len; } EXPORT_SYMBOL_GPL(iio_enum_write); @@ -1428,7 +1423,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) static void iio_dev_release(struct device *device) { struct iio_dev *indio_dev = dev_to_iio_dev(device); - if (indio_dev->modes & (INDIO_BUFFER_TRIGGERED | INDIO_EVENT_TRIGGERED)) + if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES) iio_device_unregister_trigger_consumer(indio_dev); iio_device_unregister_eventset(indio_dev); iio_device_unregister_sysfs(indio_dev); @@ -1710,7 +1705,7 @@ int iio_device_register(struct iio_dev *indio_dev) "Failed to register event set\n"); goto error_free_sysfs; } - if (indio_dev->modes & (INDIO_BUFFER_TRIGGERED | INDIO_EVENT_TRIGGERED)) + if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES) iio_device_register_trigger_consumer(indio_dev); if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) && diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c index 6325e7dc8e03..f3cb4dc05391 100644 --- a/drivers/iio/magnetometer/st_magn_spi.c +++ b/drivers/iio/magnetometer/st_magn_spi.c @@ -48,8 +48,6 @@ static int st_magn_spi_remove(struct spi_device *spi) } static const struct spi_device_id st_magn_id_table[] = { - { LSM303DLHC_MAGN_DEV_NAME }, - { LSM303DLM_MAGN_DEV_NAME }, { LIS3MDL_MAGN_DEV_NAME }, { LSM303AGR_MAGN_DEV_NAME }, {}, diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index 9ea147f1a50d..f42b3a1c75ff 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -878,8 +878,7 @@ static void sx9500_gpio_probe(struct i2c_client *client, dev = &client->dev; - data->gpiod_rst = devm_gpiod_get_index(dev, SX9500_GPIO_RESET, - 0, GPIOD_OUT_HIGH); + data->gpiod_rst = devm_gpiod_get(dev, SX9500_GPIO_RESET, GPIOD_OUT_HIGH); if (IS_ERR(data->gpiod_rst)) { dev_warn(dev, "gpio get reset pin failed\n"); data->gpiod_rst = NULL; diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index 0797f2fe584f..d22bc56dd9fc 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -417,12 +417,70 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev, return -EINVAL; } +static int stm32_counter_validate_trigger(struct iio_dev *indio_dev, + struct iio_trigger *trig) +{ + struct stm32_timer_trigger *priv = iio_priv(indio_dev); + const char * const *cur = priv->valids; + unsigned int i = 0; + + if (!is_stm32_timer_trigger(trig)) + return -EINVAL; + + while (cur && *cur) { + if (!strncmp(trig->name, *cur, strlen(trig->name))) { + regmap_update_bits(priv->regmap, + TIM_SMCR, TIM_SMCR_TS, + i << TIM_SMCR_TS_SHIFT); + return 0; + } + cur++; + i++; + } + + return -EINVAL; +} + static const struct iio_info stm32_trigger_info = { .driver_module = THIS_MODULE, + .validate_trigger = stm32_counter_validate_trigger, .read_raw = stm32_counter_read_raw, .write_raw = stm32_counter_write_raw }; +static const char *const stm32_trigger_modes[] = { + "trigger", +}; + +static int stm32_set_trigger_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + unsigned int mode) +{ + struct stm32_timer_trigger *priv = iio_priv(indio_dev); + + regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, TIM_SMCR_SMS); + + return 0; +} + +static int stm32_get_trigger_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct stm32_timer_trigger *priv = iio_priv(indio_dev); + u32 smcr; + + regmap_read(priv->regmap, TIM_SMCR, &smcr); + + return smcr == TIM_SMCR_SMS ? 0 : -EINVAL; +} + +static const struct iio_enum stm32_trigger_mode_enum = { + .items = stm32_trigger_modes, + .num_items = ARRAY_SIZE(stm32_trigger_modes), + .set = stm32_set_trigger_mode, + .get = stm32_get_trigger_mode +}; + static const char *const stm32_enable_modes[] = { "always", "gated", @@ -606,6 +664,8 @@ static const struct iio_chan_spec_ext_info stm32_trigger_count_info[] = { IIO_ENUM_AVAILABLE("quadrature_mode", &stm32_quadrature_mode_enum), IIO_ENUM("enable_mode", IIO_SEPARATE, &stm32_enable_mode_enum), IIO_ENUM_AVAILABLE("enable_mode", &stm32_enable_mode_enum), + IIO_ENUM("trigger_mode", IIO_SEPARATE, &stm32_trigger_mode_enum), + IIO_ENUM_AVAILABLE("trigger_mode", &stm32_trigger_mode_enum), {} }; @@ -630,6 +690,7 @@ static struct stm32_timer_trigger *stm32_setup_counter_device(struct device *dev indio_dev->name = dev_name(dev); indio_dev->dev.parent = dev; indio_dev->info = &stm32_trigger_info; + indio_dev->modes = INDIO_HARDWARE_TRIGGERED; indio_dev->num_channels = 1; indio_dev->channels = &stm32_trigger_channel; indio_dev->dev.of_node = dev->of_node; diff --git a/include/linux/i2c/twl4030-madc.h b/include/linux/i2c/twl4030-madc.h deleted file mode 100644 index 1c0134dd3271..000000000000 --- a/include/linux/i2c/twl4030-madc.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * twl4030_madc.h - Header for TWL4030 MADC - * - * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ - * J Keerthy <j-keerthy@ti.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef _TWL4030_MADC_H -#define _TWL4030_MADC_H - -struct twl4030_madc_conversion_method { - u8 sel; - u8 avg; - u8 rbase; - u8 ctrl; -}; - -#define TWL4030_MADC_MAX_CHANNELS 16 - - -/* - * twl4030_madc_request- madc request packet for channel conversion - * @channels: 16 bit bitmap for individual channels - * @do_avgP: sample the input channel for 4 consecutive cycles - * @method: RT, SW1, SW2 - * @type: Polling or interrupt based method - * @raw: Return raw value, do not convert it - */ - -struct twl4030_madc_request { - unsigned long channels; - bool do_avg; - u16 method; - u16 type; - bool active; - bool result_pending; - bool raw; - int rbuf[TWL4030_MADC_MAX_CHANNELS]; - void (*func_cb)(int len, int channels, int *buf); -}; - -enum conversion_methods { - TWL4030_MADC_RT, - TWL4030_MADC_SW1, - TWL4030_MADC_SW2, - TWL4030_MADC_NUM_METHODS -}; - -enum sample_type { - TWL4030_MADC_WAIT, - TWL4030_MADC_IRQ_ONESHOT, - TWL4030_MADC_IRQ_REARM -}; - -#define TWL4030_MADC_CTRL1 0x00 -#define TWL4030_MADC_CTRL2 0x01 - -#define TWL4030_MADC_RTSELECT_LSB 0x02 -#define TWL4030_MADC_SW1SELECT_LSB 0x06 -#define TWL4030_MADC_SW2SELECT_LSB 0x0A - -#define TWL4030_MADC_RTAVERAGE_LSB 0x04 -#define TWL4030_MADC_SW1AVERAGE_LSB 0x08 -#define TWL4030_MADC_SW2AVERAGE_LSB 0x0C - -#define TWL4030_MADC_CTRL_SW1 0x12 -#define TWL4030_MADC_CTRL_SW2 0x13 - -#define TWL4030_MADC_RTCH0_LSB 0x17 -#define TWL4030_MADC_GPCH0_LSB 0x37 - -#define TWL4030_MADC_MADCON (1 << 0) /* MADC power on */ -#define TWL4030_MADC_BUSY (1 << 0) /* MADC busy */ -/* MADC conversion completion */ -#define TWL4030_MADC_EOC_SW (1 << 1) -/* MADC SWx start conversion */ -#define TWL4030_MADC_SW_START (1 << 5) -#define TWL4030_MADC_ADCIN0 (1 << 0) -#define TWL4030_MADC_ADCIN1 (1 << 1) -#define TWL4030_MADC_ADCIN2 (1 << 2) -#define TWL4030_MADC_ADCIN3 (1 << 3) -#define TWL4030_MADC_ADCIN4 (1 << 4) -#define TWL4030_MADC_ADCIN5 (1 << 5) -#define TWL4030_MADC_ADCIN6 (1 << 6) -#define TWL4030_MADC_ADCIN7 (1 << 7) -#define TWL4030_MADC_ADCIN8 (1 << 8) -#define TWL4030_MADC_ADCIN9 (1 << 9) -#define TWL4030_MADC_ADCIN10 (1 << 10) -#define TWL4030_MADC_ADCIN11 (1 << 11) -#define TWL4030_MADC_ADCIN12 (1 << 12) -#define TWL4030_MADC_ADCIN13 (1 << 13) -#define TWL4030_MADC_ADCIN14 (1 << 14) -#define TWL4030_MADC_ADCIN15 (1 << 15) - -/* Fixed channels */ -#define TWL4030_MADC_BTEMP TWL4030_MADC_ADCIN1 -#define TWL4030_MADC_VBUS TWL4030_MADC_ADCIN8 -#define TWL4030_MADC_VBKB TWL4030_MADC_ADCIN9 -#define TWL4030_MADC_ICHG TWL4030_MADC_ADCIN10 -#define TWL4030_MADC_VCHG TWL4030_MADC_ADCIN11 -#define TWL4030_MADC_VBAT TWL4030_MADC_ADCIN12 - -/* Step size and prescaler ratio */ -#define TEMP_STEP_SIZE 147 -#define TEMP_PSR_R 100 -#define CURR_STEP_SIZE 147 -#define CURR_PSR_R1 44 -#define CURR_PSR_R2 88 - -#define TWL4030_BCI_BCICTL1 0x23 -#define TWL4030_BCI_CGAIN 0x020 -#define TWL4030_BCI_MESBAT (1 << 1) -#define TWL4030_BCI_TYPEN (1 << 4) -#define TWL4030_BCI_ITHEN (1 << 3) - -#define REG_BCICTL2 0x024 -#define TWL4030_BCI_ITHSENS 0x007 - -/* Register and bits for GPBR1 register */ -#define TWL4030_REG_GPBR1 0x0c -#define TWL4030_GPBR1_MADC_HFCLK_EN (1 << 7) - -struct twl4030_madc_user_parms { - int channel; - int average; - int status; - u16 result; -}; - -int twl4030_madc_conversion(struct twl4030_madc_request *conv); -int twl4030_get_madc_conversion(int channel_no); -#endif diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 3f5ea2e9a39e..d68bec297a45 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -352,10 +352,16 @@ unsigned int iio_get_time_res(const struct iio_dev *indio_dev); #define INDIO_BUFFER_SOFTWARE 0x04 #define INDIO_BUFFER_HARDWARE 0x08 #define INDIO_EVENT_TRIGGERED 0x10 +#define INDIO_HARDWARE_TRIGGERED 0x20 #define INDIO_ALL_BUFFER_MODES \ (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE | INDIO_BUFFER_SOFTWARE) +#define INDIO_ALL_TRIGGERED_MODES \ + (INDIO_BUFFER_TRIGGERED \ + | INDIO_EVENT_TRIGGERED \ + | INDIO_HARDWARE_TRIGGERED) + #define INDIO_MAX_RAW_ELEMENTS 4 struct iio_trigger; /* forward declaration */ |