First set of IIO and counter fixes for the 5.10 cycle.
IIO cros_ec - Provide defauts for max and min frequency when older machines fail to return them correctly. ingenic-adc - Fix wrong vref value for JZ4770 SoC - Fix AUX / VBAT readings when touchscreen in use by pausing touchscreen readings during a read of these channels. kxcjk1013 - Fix an issue with KIOX010A ACPI id using devices which need to run a ACPI device specific method to avoid leaving the keyboard disabled. Includes a minor precursor patch to make this fix easier to do. mt6577-auxadc - Fix an issue with dev_comp not being set resulting in a null ptr deref. st_lsm6dsx - Set a 10ms min shub slave timeout to handle fast snesors where more time is needed to set up the config than the cycles allowed. stm32-adc - Fix an issue due to a clash between an ADC configured to use IRQs and a second configured to use DMA cause by some incorrect register masking. vcnl4035 - Kconfig missing dependency Counter ti-eqep - wrong value for max_register as one beyond the end instead of the end. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEbilms4eEBlKRJoGxVIU0mcT0FogFAl+yyk8RHGppYzIzQGtl cm5lbC5vcmcACgkQVIU0mcT0FohJURAAi5xCdV2cUQoAUCi2ldlwEVaIb+yCdHzk V1mB6O9sdJTmkaJx6qopkx/Dn0Sou1G48paKlzOFznno0no0PRY4IXDZq5TdR+M+ 0WTR6TR0UwT1AIVELzhMPuW9+G1YbWdxRDBEeXOAT+HrJftZLpgU2Mk3Of8h7p0n /CAaT60wwVf13VJ9ESjr7UKqisuMIt0zsqN5lS8sXRNnIx1mCZe1DFb6v1cs3w6n G77lub5ylNxu+u6l6YTYILNZ+Sj6NCiUzxVE7R5eSpmfk0+t7bFtA6tXXekZCdvq +DxzM2vnLXmx1PwNJOd97sArLI0I94AmOwrcphKaa/HAb4akRfcPhapsNjGMny/n I8AlCDrLcFZq//dAd0mt7A676CyL1sNG8w7wu91IDfsPkfYgInNemlft5nmwokGu f+crhtKoNJjaV5n1yIXDPgXpH0s6U5Hmy+ELMLr2rw85hwpwzJF0pYd4+DqRr8aI RCogkKP2ey80RfZlDl8qRTiz/wUSmlxsujjZPAYG+1Spaj08EiT3e5Oad+NmVuKr jcehdqOFZHXML7nK2ntpuQ7UW1xY4USyxjtPJ6q6IUVEiF4wTOGhHX9ePM1y38b1 W/F4Lcq2mAQ9rxoWP+FUHuB36zMB0cZ1KXVohvlciTkdl6DSyF4eio19M5MAYqxI RolkTf2Fa4A= =QQWq -----END PGP SIGNATURE----- Merge tag 'iio-fixes-for-5.10a' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-linus Jonathan writes: First set of IIO and counter fixes for the 5.10 cycle. IIO cros_ec - Provide defauts for max and min frequency when older machines fail to return them correctly. ingenic-adc - Fix wrong vref value for JZ4770 SoC - Fix AUX / VBAT readings when touchscreen in use by pausing touchscreen readings during a read of these channels. kxcjk1013 - Fix an issue with KIOX010A ACPI id using devices which need to run a ACPI device specific method to avoid leaving the keyboard disabled. Includes a minor precursor patch to make this fix easier to do. mt6577-auxadc - Fix an issue with dev_comp not being set resulting in a null ptr deref. st_lsm6dsx - Set a 10ms min shub slave timeout to handle fast snesors where more time is needed to set up the config than the cycles allowed. stm32-adc - Fix an issue due to a clash between an ADC configured to use IRQs and a second configured to use DMA cause by some incorrect register masking. vcnl4035 - Kconfig missing dependency Counter ti-eqep - wrong value for max_register as one beyond the end instead of the end. * tag 'iio-fixes-for-5.10a' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: iio: accel: kxcjk1013: Add support for KIOX010A ACPI DSM for setting tablet-mode iio: accel: kxcjk1013: Replace is_smo8500_device with an acpi_type enum iio: light: fix kconfig dependency bug for VCNL4035 iio/adc: ingenic: Fix AUX/VBAT readings when touchscreen is used iio/adc: ingenic: Fix battery VREF for JZ4770 SoC iio: imu: st_lsm6dsx: set 10ms as min shub slave timeout counter/ti-eqep: Fix regmap max_register iio: adc: stm32-adc: fix a regression when using dma and irq iio: adc: mediatek: fix unset field iio: cros_ec: Use default frequencies when EC returns invalid information
This commit is contained in:
commit
2dde2821b5
@ -368,7 +368,7 @@ static const struct regmap_config ti_eqep_regmap32_config = {
|
|||||||
.reg_bits = 32,
|
.reg_bits = 32,
|
||||||
.val_bits = 32,
|
.val_bits = 32,
|
||||||
.reg_stride = 4,
|
.reg_stride = 4,
|
||||||
.max_register = 0x24,
|
.max_register = QUPRD,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct regmap_config ti_eqep_regmap16_config = {
|
static const struct regmap_config ti_eqep_regmap16_config = {
|
||||||
@ -376,7 +376,7 @@ static const struct regmap_config ti_eqep_regmap16_config = {
|
|||||||
.reg_bits = 16,
|
.reg_bits = 16,
|
||||||
.val_bits = 16,
|
.val_bits = 16,
|
||||||
.reg_stride = 2,
|
.reg_stride = 2,
|
||||||
.max_register = 0x1e,
|
.max_register = QCPRDLAT,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ti_eqep_probe(struct platform_device *pdev)
|
static int ti_eqep_probe(struct platform_device *pdev)
|
||||||
|
@ -126,6 +126,12 @@ enum kx_chipset {
|
|||||||
KX_MAX_CHIPS /* this must be last */
|
KX_MAX_CHIPS /* this must be last */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum kx_acpi_type {
|
||||||
|
ACPI_GENERIC,
|
||||||
|
ACPI_SMO8500,
|
||||||
|
ACPI_KIOX010A,
|
||||||
|
};
|
||||||
|
|
||||||
struct kxcjk1013_data {
|
struct kxcjk1013_data {
|
||||||
struct i2c_client *client;
|
struct i2c_client *client;
|
||||||
struct iio_trigger *dready_trig;
|
struct iio_trigger *dready_trig;
|
||||||
@ -143,7 +149,7 @@ struct kxcjk1013_data {
|
|||||||
bool motion_trigger_on;
|
bool motion_trigger_on;
|
||||||
int64_t timestamp;
|
int64_t timestamp;
|
||||||
enum kx_chipset chipset;
|
enum kx_chipset chipset;
|
||||||
bool is_smo8500_device;
|
enum kx_acpi_type acpi_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum kxcjk1013_axis {
|
enum kxcjk1013_axis {
|
||||||
@ -270,6 +276,32 @@ static const struct {
|
|||||||
{19163, 1, 0},
|
{19163, 1, 0},
|
||||||
{38326, 0, 1} };
|
{38326, 0, 1} };
|
||||||
|
|
||||||
|
#ifdef CONFIG_ACPI
|
||||||
|
enum kiox010a_fn_index {
|
||||||
|
KIOX010A_SET_LAPTOP_MODE = 1,
|
||||||
|
KIOX010A_SET_TABLET_MODE = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int kiox010a_dsm(struct device *dev, int fn_index)
|
||||||
|
{
|
||||||
|
acpi_handle handle = ACPI_HANDLE(dev);
|
||||||
|
guid_t kiox010a_dsm_guid;
|
||||||
|
union acpi_object *obj;
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
guid_parse("1f339696-d475-4e26-8cad-2e9f8e6d7a91", &kiox010a_dsm_guid);
|
||||||
|
|
||||||
|
obj = acpi_evaluate_dsm(handle, &kiox010a_dsm_guid, 1, fn_index, NULL);
|
||||||
|
if (!obj)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
ACPI_FREE(obj);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
|
static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
|
||||||
enum kxcjk1013_mode mode)
|
enum kxcjk1013_mode mode)
|
||||||
{
|
{
|
||||||
@ -347,6 +379,13 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
#ifdef CONFIG_ACPI
|
||||||
|
if (data->acpi_type == ACPI_KIOX010A) {
|
||||||
|
/* Make sure the kbd and touchpad on 2-in-1s using 2 KXCJ91008-s work */
|
||||||
|
kiox010a_dsm(&data->client->dev, KIOX010A_SET_LAPTOP_MODE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_WHO_AM_I);
|
ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_WHO_AM_I);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&data->client->dev, "Error reading who_am_i\n");
|
dev_err(&data->client->dev, "Error reading who_am_i\n");
|
||||||
@ -1247,7 +1286,7 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private)
|
|||||||
|
|
||||||
static const char *kxcjk1013_match_acpi_device(struct device *dev,
|
static const char *kxcjk1013_match_acpi_device(struct device *dev,
|
||||||
enum kx_chipset *chipset,
|
enum kx_chipset *chipset,
|
||||||
bool *is_smo8500_device)
|
enum kx_acpi_type *acpi_type)
|
||||||
{
|
{
|
||||||
const struct acpi_device_id *id;
|
const struct acpi_device_id *id;
|
||||||
|
|
||||||
@ -1256,7 +1295,9 @@ static const char *kxcjk1013_match_acpi_device(struct device *dev,
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (strcmp(id->id, "SMO8500") == 0)
|
if (strcmp(id->id, "SMO8500") == 0)
|
||||||
*is_smo8500_device = true;
|
*acpi_type = ACPI_SMO8500;
|
||||||
|
else if (strcmp(id->id, "KIOX010A") == 0)
|
||||||
|
*acpi_type = ACPI_KIOX010A;
|
||||||
|
|
||||||
*chipset = (enum kx_chipset)id->driver_data;
|
*chipset = (enum kx_chipset)id->driver_data;
|
||||||
|
|
||||||
@ -1299,7 +1340,7 @@ static int kxcjk1013_probe(struct i2c_client *client,
|
|||||||
} else if (ACPI_HANDLE(&client->dev)) {
|
} else if (ACPI_HANDLE(&client->dev)) {
|
||||||
name = kxcjk1013_match_acpi_device(&client->dev,
|
name = kxcjk1013_match_acpi_device(&client->dev,
|
||||||
&data->chipset,
|
&data->chipset,
|
||||||
&data->is_smo8500_device);
|
&data->acpi_type);
|
||||||
} else
|
} else
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
@ -1316,7 +1357,7 @@ static int kxcjk1013_probe(struct i2c_client *client,
|
|||||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||||
indio_dev->info = &kxcjk1013_info;
|
indio_dev->info = &kxcjk1013_info;
|
||||||
|
|
||||||
if (client->irq > 0 && !data->is_smo8500_device) {
|
if (client->irq > 0 && data->acpi_type != ACPI_SMO8500) {
|
||||||
ret = devm_request_threaded_irq(&client->dev, client->irq,
|
ret = devm_request_threaded_irq(&client->dev, client->irq,
|
||||||
kxcjk1013_data_rdy_trig_poll,
|
kxcjk1013_data_rdy_trig_poll,
|
||||||
kxcjk1013_event_handler,
|
kxcjk1013_event_handler,
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
#define JZ4725B_ADC_BATTERY_HIGH_VREF_BITS 10
|
#define JZ4725B_ADC_BATTERY_HIGH_VREF_BITS 10
|
||||||
#define JZ4740_ADC_BATTERY_HIGH_VREF (7500 * 0.986)
|
#define JZ4740_ADC_BATTERY_HIGH_VREF (7500 * 0.986)
|
||||||
#define JZ4740_ADC_BATTERY_HIGH_VREF_BITS 12
|
#define JZ4740_ADC_BATTERY_HIGH_VREF_BITS 12
|
||||||
#define JZ4770_ADC_BATTERY_VREF 6600
|
#define JZ4770_ADC_BATTERY_VREF 1200
|
||||||
#define JZ4770_ADC_BATTERY_VREF_BITS 12
|
#define JZ4770_ADC_BATTERY_VREF_BITS 12
|
||||||
|
|
||||||
#define JZ_ADC_IRQ_AUX BIT(0)
|
#define JZ_ADC_IRQ_AUX BIT(0)
|
||||||
@ -177,13 +177,12 @@ static void ingenic_adc_set_config(struct ingenic_adc *adc,
|
|||||||
mutex_unlock(&adc->lock);
|
mutex_unlock(&adc->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ingenic_adc_enable(struct ingenic_adc *adc,
|
static void ingenic_adc_enable_unlocked(struct ingenic_adc *adc,
|
||||||
int engine,
|
int engine,
|
||||||
bool enabled)
|
bool enabled)
|
||||||
{
|
{
|
||||||
u8 val;
|
u8 val;
|
||||||
|
|
||||||
mutex_lock(&adc->lock);
|
|
||||||
val = readb(adc->base + JZ_ADC_REG_ENABLE);
|
val = readb(adc->base + JZ_ADC_REG_ENABLE);
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
@ -192,20 +191,41 @@ static void ingenic_adc_enable(struct ingenic_adc *adc,
|
|||||||
val &= ~BIT(engine);
|
val &= ~BIT(engine);
|
||||||
|
|
||||||
writeb(val, adc->base + JZ_ADC_REG_ENABLE);
|
writeb(val, adc->base + JZ_ADC_REG_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ingenic_adc_enable(struct ingenic_adc *adc,
|
||||||
|
int engine,
|
||||||
|
bool enabled)
|
||||||
|
{
|
||||||
|
mutex_lock(&adc->lock);
|
||||||
|
ingenic_adc_enable_unlocked(adc, engine, enabled);
|
||||||
mutex_unlock(&adc->lock);
|
mutex_unlock(&adc->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ingenic_adc_capture(struct ingenic_adc *adc,
|
static int ingenic_adc_capture(struct ingenic_adc *adc,
|
||||||
int engine)
|
int engine)
|
||||||
{
|
{
|
||||||
|
u32 cfg;
|
||||||
u8 val;
|
u8 val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ingenic_adc_enable(adc, engine, true);
|
/*
|
||||||
|
* Disable CMD_SEL temporarily, because it causes wrong VBAT readings,
|
||||||
|
* probably due to the switch of VREF. We must keep the lock here to
|
||||||
|
* avoid races with the buffer enable/disable functions.
|
||||||
|
*/
|
||||||
|
mutex_lock(&adc->lock);
|
||||||
|
cfg = readl(adc->base + JZ_ADC_REG_CFG);
|
||||||
|
writel(cfg & ~JZ_ADC_REG_CFG_CMD_SEL, adc->base + JZ_ADC_REG_CFG);
|
||||||
|
|
||||||
|
ingenic_adc_enable_unlocked(adc, engine, true);
|
||||||
ret = readb_poll_timeout(adc->base + JZ_ADC_REG_ENABLE, val,
|
ret = readb_poll_timeout(adc->base + JZ_ADC_REG_ENABLE, val,
|
||||||
!(val & BIT(engine)), 250, 1000);
|
!(val & BIT(engine)), 250, 1000);
|
||||||
if (ret)
|
if (ret)
|
||||||
ingenic_adc_enable(adc, engine, false);
|
ingenic_adc_enable_unlocked(adc, engine, false);
|
||||||
|
|
||||||
|
writel(cfg, adc->base + JZ_ADC_REG_CFG);
|
||||||
|
mutex_unlock(&adc->lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of.h>
|
#include <linux/mod_devicetable.h>
|
||||||
#include <linux/of_device.h>
|
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/property.h>
|
||||||
#include <linux/iopoll.h>
|
#include <linux/iopoll.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
@ -276,6 +276,8 @@ static int mt6577_auxadc_probe(struct platform_device *pdev)
|
|||||||
goto err_disable_clk;
|
goto err_disable_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
adc_dev->dev_comp = device_get_match_data(&pdev->dev);
|
||||||
|
|
||||||
mutex_init(&adc_dev->lock);
|
mutex_init(&adc_dev->lock);
|
||||||
|
|
||||||
mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
|
mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
|
||||||
|
@ -41,18 +41,16 @@
|
|||||||
* struct stm32_adc_common_regs - stm32 common registers
|
* struct stm32_adc_common_regs - stm32 common registers
|
||||||
* @csr: common status register offset
|
* @csr: common status register offset
|
||||||
* @ccr: common control register offset
|
* @ccr: common control register offset
|
||||||
* @eoc1_msk: adc1 end of conversion flag in @csr
|
* @eoc_msk: array of eoc (end of conversion flag) masks in csr for adc1..n
|
||||||
* @eoc2_msk: adc2 end of conversion flag in @csr
|
* @ovr_msk: array of ovr (overrun flag) masks in csr for adc1..n
|
||||||
* @eoc3_msk: adc3 end of conversion flag in @csr
|
|
||||||
* @ier: interrupt enable register offset for each adc
|
* @ier: interrupt enable register offset for each adc
|
||||||
* @eocie_msk: end of conversion interrupt enable mask in @ier
|
* @eocie_msk: end of conversion interrupt enable mask in @ier
|
||||||
*/
|
*/
|
||||||
struct stm32_adc_common_regs {
|
struct stm32_adc_common_regs {
|
||||||
u32 csr;
|
u32 csr;
|
||||||
u32 ccr;
|
u32 ccr;
|
||||||
u32 eoc1_msk;
|
u32 eoc_msk[STM32_ADC_MAX_ADCS];
|
||||||
u32 eoc2_msk;
|
u32 ovr_msk[STM32_ADC_MAX_ADCS];
|
||||||
u32 eoc3_msk;
|
|
||||||
u32 ier;
|
u32 ier;
|
||||||
u32 eocie_msk;
|
u32 eocie_msk;
|
||||||
};
|
};
|
||||||
@ -282,21 +280,20 @@ out:
|
|||||||
static const struct stm32_adc_common_regs stm32f4_adc_common_regs = {
|
static const struct stm32_adc_common_regs stm32f4_adc_common_regs = {
|
||||||
.csr = STM32F4_ADC_CSR,
|
.csr = STM32F4_ADC_CSR,
|
||||||
.ccr = STM32F4_ADC_CCR,
|
.ccr = STM32F4_ADC_CCR,
|
||||||
.eoc1_msk = STM32F4_EOC1 | STM32F4_OVR1,
|
.eoc_msk = { STM32F4_EOC1, STM32F4_EOC2, STM32F4_EOC3},
|
||||||
.eoc2_msk = STM32F4_EOC2 | STM32F4_OVR2,
|
.ovr_msk = { STM32F4_OVR1, STM32F4_OVR2, STM32F4_OVR3},
|
||||||
.eoc3_msk = STM32F4_EOC3 | STM32F4_OVR3,
|
|
||||||
.ier = STM32F4_ADC_CR1,
|
.ier = STM32F4_ADC_CR1,
|
||||||
.eocie_msk = STM32F4_EOCIE | STM32F4_OVRIE,
|
.eocie_msk = STM32F4_EOCIE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* STM32H7 common registers definitions */
|
/* STM32H7 common registers definitions */
|
||||||
static const struct stm32_adc_common_regs stm32h7_adc_common_regs = {
|
static const struct stm32_adc_common_regs stm32h7_adc_common_regs = {
|
||||||
.csr = STM32H7_ADC_CSR,
|
.csr = STM32H7_ADC_CSR,
|
||||||
.ccr = STM32H7_ADC_CCR,
|
.ccr = STM32H7_ADC_CCR,
|
||||||
.eoc1_msk = STM32H7_EOC_MST | STM32H7_OVR_MST,
|
.eoc_msk = { STM32H7_EOC_MST, STM32H7_EOC_SLV},
|
||||||
.eoc2_msk = STM32H7_EOC_SLV | STM32H7_OVR_SLV,
|
.ovr_msk = { STM32H7_OVR_MST, STM32H7_OVR_SLV},
|
||||||
.ier = STM32H7_ADC_IER,
|
.ier = STM32H7_ADC_IER,
|
||||||
.eocie_msk = STM32H7_EOCIE | STM32H7_OVRIE,
|
.eocie_msk = STM32H7_EOCIE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = {
|
static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = {
|
||||||
@ -318,6 +315,7 @@ static void stm32_adc_irq_handler(struct irq_desc *desc)
|
|||||||
{
|
{
|
||||||
struct stm32_adc_priv *priv = irq_desc_get_handler_data(desc);
|
struct stm32_adc_priv *priv = irq_desc_get_handler_data(desc);
|
||||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||||
|
int i;
|
||||||
u32 status;
|
u32 status;
|
||||||
|
|
||||||
chained_irq_enter(chip, desc);
|
chained_irq_enter(chip, desc);
|
||||||
@ -335,17 +333,12 @@ static void stm32_adc_irq_handler(struct irq_desc *desc)
|
|||||||
* before invoking the interrupt handler (e.g. call ISR only for
|
* before invoking the interrupt handler (e.g. call ISR only for
|
||||||
* IRQ-enabled ADCs).
|
* IRQ-enabled ADCs).
|
||||||
*/
|
*/
|
||||||
if (status & priv->cfg->regs->eoc1_msk &&
|
for (i = 0; i < priv->cfg->num_irqs; i++) {
|
||||||
stm32_adc_eoc_enabled(priv, 0))
|
if ((status & priv->cfg->regs->eoc_msk[i] &&
|
||||||
generic_handle_irq(irq_find_mapping(priv->domain, 0));
|
stm32_adc_eoc_enabled(priv, i)) ||
|
||||||
|
(status & priv->cfg->regs->ovr_msk[i]))
|
||||||
if (status & priv->cfg->regs->eoc2_msk &&
|
generic_handle_irq(irq_find_mapping(priv->domain, i));
|
||||||
stm32_adc_eoc_enabled(priv, 1))
|
}
|
||||||
generic_handle_irq(irq_find_mapping(priv->domain, 1));
|
|
||||||
|
|
||||||
if (status & priv->cfg->regs->eoc3_msk &&
|
|
||||||
stm32_adc_eoc_enabled(priv, 2))
|
|
||||||
generic_handle_irq(irq_find_mapping(priv->domain, 2));
|
|
||||||
|
|
||||||
chained_irq_exit(chip, desc);
|
chained_irq_exit(chip, desc);
|
||||||
};
|
};
|
||||||
|
@ -154,6 +154,7 @@ struct stm32_adc;
|
|||||||
* @start_conv: routine to start conversions
|
* @start_conv: routine to start conversions
|
||||||
* @stop_conv: routine to stop conversions
|
* @stop_conv: routine to stop conversions
|
||||||
* @unprepare: optional unprepare routine (disable, power-down)
|
* @unprepare: optional unprepare routine (disable, power-down)
|
||||||
|
* @irq_clear: routine to clear irqs
|
||||||
* @smp_cycles: programmable sampling time (ADC clock cycles)
|
* @smp_cycles: programmable sampling time (ADC clock cycles)
|
||||||
*/
|
*/
|
||||||
struct stm32_adc_cfg {
|
struct stm32_adc_cfg {
|
||||||
@ -166,6 +167,7 @@ struct stm32_adc_cfg {
|
|||||||
void (*start_conv)(struct iio_dev *, bool dma);
|
void (*start_conv)(struct iio_dev *, bool dma);
|
||||||
void (*stop_conv)(struct iio_dev *);
|
void (*stop_conv)(struct iio_dev *);
|
||||||
void (*unprepare)(struct iio_dev *);
|
void (*unprepare)(struct iio_dev *);
|
||||||
|
void (*irq_clear)(struct iio_dev *indio_dev, u32 msk);
|
||||||
const unsigned int *smp_cycles;
|
const unsigned int *smp_cycles;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -621,6 +623,13 @@ static void stm32f4_adc_stop_conv(struct iio_dev *indio_dev)
|
|||||||
STM32F4_ADON | STM32F4_DMA | STM32F4_DDS);
|
STM32F4_ADON | STM32F4_DMA | STM32F4_DDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void stm32f4_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
|
||||||
|
{
|
||||||
|
struct stm32_adc *adc = iio_priv(indio_dev);
|
||||||
|
|
||||||
|
stm32_adc_clr_bits(adc, adc->cfg->regs->isr_eoc.reg, msk);
|
||||||
|
}
|
||||||
|
|
||||||
static void stm32h7_adc_start_conv(struct iio_dev *indio_dev, bool dma)
|
static void stm32h7_adc_start_conv(struct iio_dev *indio_dev, bool dma)
|
||||||
{
|
{
|
||||||
struct stm32_adc *adc = iio_priv(indio_dev);
|
struct stm32_adc *adc = iio_priv(indio_dev);
|
||||||
@ -659,6 +668,13 @@ static void stm32h7_adc_stop_conv(struct iio_dev *indio_dev)
|
|||||||
stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK);
|
stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void stm32h7_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
|
||||||
|
{
|
||||||
|
struct stm32_adc *adc = iio_priv(indio_dev);
|
||||||
|
/* On STM32H7 IRQs are cleared by writing 1 into ISR register */
|
||||||
|
stm32_adc_set_bits(adc, adc->cfg->regs->isr_eoc.reg, msk);
|
||||||
|
}
|
||||||
|
|
||||||
static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev)
|
static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev)
|
||||||
{
|
{
|
||||||
struct stm32_adc *adc = iio_priv(indio_dev);
|
struct stm32_adc *adc = iio_priv(indio_dev);
|
||||||
@ -1235,25 +1251,52 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void stm32_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
|
||||||
|
{
|
||||||
|
struct stm32_adc *adc = iio_priv(indio_dev);
|
||||||
|
|
||||||
|
adc->cfg->irq_clear(indio_dev, msk);
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t stm32_adc_threaded_isr(int irq, void *data)
|
static irqreturn_t stm32_adc_threaded_isr(int irq, void *data)
|
||||||
{
|
{
|
||||||
struct iio_dev *indio_dev = data;
|
struct iio_dev *indio_dev = data;
|
||||||
struct stm32_adc *adc = iio_priv(indio_dev);
|
struct stm32_adc *adc = iio_priv(indio_dev);
|
||||||
const struct stm32_adc_regspec *regs = adc->cfg->regs;
|
const struct stm32_adc_regspec *regs = adc->cfg->regs;
|
||||||
u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
|
u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
|
||||||
|
u32 mask = stm32_adc_readl(adc, regs->ier_eoc.reg);
|
||||||
|
|
||||||
if (status & regs->isr_ovr.mask)
|
/* Check ovr status right now, as ovr mask should be already disabled */
|
||||||
|
if (status & regs->isr_ovr.mask) {
|
||||||
|
/*
|
||||||
|
* Clear ovr bit to avoid subsequent calls to IRQ handler.
|
||||||
|
* This requires to stop ADC first. OVR bit state in ISR,
|
||||||
|
* is propaged to CSR register by hardware.
|
||||||
|
*/
|
||||||
|
adc->cfg->stop_conv(indio_dev);
|
||||||
|
stm32_adc_irq_clear(indio_dev, regs->isr_ovr.mask);
|
||||||
dev_err(&indio_dev->dev, "Overrun, stopping: restart needed\n");
|
dev_err(&indio_dev->dev, "Overrun, stopping: restart needed\n");
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(status & mask))
|
||||||
|
dev_err_ratelimited(&indio_dev->dev,
|
||||||
|
"Unexpected IRQ: IER=0x%08x, ISR=0x%08x\n",
|
||||||
|
mask, status);
|
||||||
|
|
||||||
|
return IRQ_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t stm32_adc_isr(int irq, void *data)
|
static irqreturn_t stm32_adc_isr(int irq, void *data)
|
||||||
{
|
{
|
||||||
struct iio_dev *indio_dev = data;
|
struct iio_dev *indio_dev = data;
|
||||||
struct stm32_adc *adc = iio_priv(indio_dev);
|
struct stm32_adc *adc = iio_priv(indio_dev);
|
||||||
const struct stm32_adc_regspec *regs = adc->cfg->regs;
|
const struct stm32_adc_regspec *regs = adc->cfg->regs;
|
||||||
u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
|
u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
|
||||||
|
u32 mask = stm32_adc_readl(adc, regs->ier_eoc.reg);
|
||||||
|
|
||||||
|
if (!(status & mask))
|
||||||
|
return IRQ_WAKE_THREAD;
|
||||||
|
|
||||||
if (status & regs->isr_ovr.mask) {
|
if (status & regs->isr_ovr.mask) {
|
||||||
/*
|
/*
|
||||||
@ -2046,6 +2089,7 @@ static const struct stm32_adc_cfg stm32f4_adc_cfg = {
|
|||||||
.start_conv = stm32f4_adc_start_conv,
|
.start_conv = stm32f4_adc_start_conv,
|
||||||
.stop_conv = stm32f4_adc_stop_conv,
|
.stop_conv = stm32f4_adc_stop_conv,
|
||||||
.smp_cycles = stm32f4_adc_smp_cycles,
|
.smp_cycles = stm32f4_adc_smp_cycles,
|
||||||
|
.irq_clear = stm32f4_adc_irq_clear,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct stm32_adc_cfg stm32h7_adc_cfg = {
|
static const struct stm32_adc_cfg stm32h7_adc_cfg = {
|
||||||
@ -2057,6 +2101,7 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = {
|
|||||||
.prepare = stm32h7_adc_prepare,
|
.prepare = stm32h7_adc_prepare,
|
||||||
.unprepare = stm32h7_adc_unprepare,
|
.unprepare = stm32h7_adc_unprepare,
|
||||||
.smp_cycles = stm32h7_adc_smp_cycles,
|
.smp_cycles = stm32h7_adc_smp_cycles,
|
||||||
|
.irq_clear = stm32h7_adc_irq_clear,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
|
static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
|
||||||
@ -2069,6 +2114,7 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
|
|||||||
.prepare = stm32h7_adc_prepare,
|
.prepare = stm32h7_adc_prepare,
|
||||||
.unprepare = stm32h7_adc_unprepare,
|
.unprepare = stm32h7_adc_unprepare,
|
||||||
.smp_cycles = stm32h7_adc_smp_cycles,
|
.smp_cycles = stm32h7_adc_smp_cycles,
|
||||||
|
.irq_clear = stm32h7_adc_irq_clear,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id stm32_adc_of_match[] = {
|
static const struct of_device_id stm32_adc_of_match[] = {
|
||||||
|
@ -256,7 +256,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
|
|||||||
struct cros_ec_sensorhub *sensor_hub = dev_get_drvdata(dev->parent);
|
struct cros_ec_sensorhub *sensor_hub = dev_get_drvdata(dev->parent);
|
||||||
struct cros_ec_dev *ec = sensor_hub->ec;
|
struct cros_ec_dev *ec = sensor_hub->ec;
|
||||||
struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
|
struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
|
||||||
u32 ver_mask;
|
u32 ver_mask, temp;
|
||||||
int frequencies[ARRAY_SIZE(state->frequencies) / 2] = { 0 };
|
int frequencies[ARRAY_SIZE(state->frequencies) / 2] = { 0 };
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
@ -310,11 +310,17 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
|
|||||||
&frequencies[1],
|
&frequencies[1],
|
||||||
&frequencies[2],
|
&frequencies[2],
|
||||||
&state->fifo_max_event_count);
|
&state->fifo_max_event_count);
|
||||||
|
} else {
|
||||||
|
if (state->resp->info_3.max_frequency == 0) {
|
||||||
|
get_default_min_max_freq(state->resp->info.type,
|
||||||
|
&frequencies[1],
|
||||||
|
&frequencies[2],
|
||||||
|
&temp);
|
||||||
} else {
|
} else {
|
||||||
frequencies[1] = state->resp->info_3.min_frequency;
|
frequencies[1] = state->resp->info_3.min_frequency;
|
||||||
frequencies[2] = state->resp->info_3.max_frequency;
|
frequencies[2] = state->resp->info_3.max_frequency;
|
||||||
state->fifo_max_event_count =
|
}
|
||||||
state->resp->info_3.fifo_max_event_count;
|
state->fifo_max_event_count = state->resp->info_3.fifo_max_event_count;
|
||||||
}
|
}
|
||||||
for (i = 0; i < ARRAY_SIZE(frequencies); i++) {
|
for (i = 0; i < ARRAY_SIZE(frequencies); i++) {
|
||||||
state->frequencies[2 * i] = frequencies[i] / 1000;
|
state->frequencies[2 * i] = frequencies[i] / 1000;
|
||||||
|
@ -156,11 +156,13 @@ static const struct st_lsm6dsx_ext_dev_settings st_lsm6dsx_ext_dev_table[] = {
|
|||||||
static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw)
|
static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw)
|
||||||
{
|
{
|
||||||
struct st_lsm6dsx_sensor *sensor;
|
struct st_lsm6dsx_sensor *sensor;
|
||||||
u32 odr;
|
u32 odr, timeout;
|
||||||
|
|
||||||
sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
|
sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
|
||||||
odr = (hw->enable_mask & BIT(ST_LSM6DSX_ID_ACC)) ? sensor->odr : 12500;
|
odr = (hw->enable_mask & BIT(ST_LSM6DSX_ID_ACC)) ? sensor->odr : 12500;
|
||||||
msleep((2000000U / odr) + 1);
|
/* set 10ms as minimum timeout for i2c slave configuration */
|
||||||
|
timeout = max_t(u32, 2000000U / odr + 1, 10);
|
||||||
|
msleep(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -544,6 +544,7 @@ config VCNL4000
|
|||||||
|
|
||||||
config VCNL4035
|
config VCNL4035
|
||||||
tristate "VCNL4035 combined ALS and proximity sensor"
|
tristate "VCNL4035 combined ALS and proximity sensor"
|
||||||
|
select IIO_BUFFER
|
||||||
select IIO_TRIGGERED_BUFFER
|
select IIO_TRIGGERED_BUFFER
|
||||||
select REGMAP_I2C
|
select REGMAP_I2C
|
||||||
depends on I2C
|
depends on I2C
|
||||||
|
Loading…
Reference in New Issue
Block a user