2023-04-08 11:48:54

by Patrik Dahlström

[permalink] [raw]
Subject: [PATCH v3 0/7] iio: adc: palmas_gpadc: add iio events

This series is based on linux-next/master [1] and [2].

The palmas gpadc block has support for monitoring up to 2 ADC channels
and issue an interrupt if they reach past a set threshold. This can be
configured statically with device tree today, but it only gets enabled
when reaching sleep mode. Also, it doesn't look like anyone is using it.

Instead of this one special case, change the code so userspace can
configure the ADC channels to their own needs through the iio events
subsystem. The high and low threshold values can be set for every
channel, but only 2 thresholds can be enabled at a time. Trying to
enable more than 2 thresholds will result in an error.

The configured thresholds will wake up the system from sleep mode if
wakeup is enabled in /sys/devices/.../power/wakeup.

The old platform data was removed.

Thresholds, events, and wakeup were tested on omap5-uevm board. It wakes
up from sleep mode when wakeup is enabled and a threshold is passed. A
userspace tool for monitoring events and adjusting thresholds can be
found at [3].

V2 -> V3:
* Rebased to linux-next.
* Avoid reconfiguring events on error and when old == new value.
V1 -> V2:
* Begin by removing adc_wakeupX_data instead of doing it last.
* Split changes in smaller patches

[1] git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
[2] https://lore.kernel.org/linux-iio/[email protected]/
[3] https://github.com/Risca/pyra_vol_mon

Patrik Dahlström (7):
iio: adc: palmas: remove adc_wakeupX_data
iio: adc: palmas: replace "wakeup" with "event"
iio: adc: palmas: use iio_event_direction for threshold polarity
iio: adc: palmas: move eventX_enable into palmas_adc_event
iio: adc: palmas: always reset events on unload
iio: adc: palmas: add support for iio threshold events
iio: adc: palmas: don't alter event config on suspend/resume

drivers/iio/adc/palmas_gpadc.c | 559 +++++++++++++++++++++++++++------
include/linux/mfd/palmas.h | 8 -
2 files changed, 464 insertions(+), 103 deletions(-)


base-commit: 8417c8f5007bf4567ccffda850a3157c7d905f67
prerequisite-patch-id: b0418c707db13f514400956596e9ebe91c25bba0
--
2.25.1


2023-04-08 11:48:54

by Patrik Dahlström

[permalink] [raw]
Subject: [PATCH v3 1/7] iio: adc: palmas: remove adc_wakeupX_data

It does not seem to be used by anyone and later patches in this series
are made simpler by first removing this. There is now a lot of dead code
that cannot be reached, until later patches revive it. Arguably, this is
preferred over removing the code only to add it again.

Signed-off-by: Patrik Dahlström <[email protected]>
---
drivers/iio/adc/palmas_gpadc.c | 50 ++++------------------------------
include/linux/mfd/palmas.h | 8 ------
2 files changed, 6 insertions(+), 52 deletions(-)

diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c
index 2921186458e0..03af6cd73ec8 100644
--- a/drivers/iio/adc/palmas_gpadc.c
+++ b/drivers/iio/adc/palmas_gpadc.c
@@ -76,6 +76,12 @@ static struct palmas_gpadc_info palmas_gpadc_info[] = {
PALMAS_ADC_INFO(IN15, 0, 0, 0, 0, INVALID, INVALID, true),
};

+struct palmas_adc_wakeup_property {
+ int adc_channel_number;
+ int adc_high_threshold;
+ int adc_low_threshold;
+};
+
/*
* struct palmas_gpadc - the palmas_gpadc structure
* @ch0_current: channel 0 current source setting
@@ -493,11 +499,6 @@ static int palmas_gpadc_get_adc_dt_data(struct platform_device *pdev,
return 0;
}

-static void palmas_disable_wakeup(void *dev)
-{
- device_wakeup_disable(dev);
-}
-
static int palmas_gpadc_probe(struct platform_device *pdev)
{
struct palmas_gpadc *adc;
@@ -548,36 +549,6 @@ static int palmas_gpadc_probe(struct platform_device *pdev)
return dev_err_probe(adc->dev, ret,
"request irq %d failed\n", adc->irq);

- if (gpadc_pdata->adc_wakeup1_data) {
- memcpy(&adc->wakeup1_data, gpadc_pdata->adc_wakeup1_data,
- sizeof(adc->wakeup1_data));
- adc->wakeup1_enable = true;
- adc->irq_auto_0 = platform_get_irq(pdev, 1);
- ret = devm_request_threaded_irq(&pdev->dev, adc->irq_auto_0,
- NULL, palmas_gpadc_irq_auto,
- IRQF_ONESHOT,
- "palmas-adc-auto-0", adc);
- if (ret < 0)
- return dev_err_probe(adc->dev, ret,
- "request auto0 irq %d failed\n",
- adc->irq_auto_0);
- }
-
- if (gpadc_pdata->adc_wakeup2_data) {
- memcpy(&adc->wakeup2_data, gpadc_pdata->adc_wakeup2_data,
- sizeof(adc->wakeup2_data));
- adc->wakeup2_enable = true;
- adc->irq_auto_1 = platform_get_irq(pdev, 2);
- ret = devm_request_threaded_irq(&pdev->dev, adc->irq_auto_1,
- NULL, palmas_gpadc_irq_auto,
- IRQF_ONESHOT,
- "palmas-adc-auto-1", adc);
- if (ret < 0)
- return dev_err_probe(adc->dev, ret,
- "request auto1 irq %d failed\n",
- adc->irq_auto_1);
- }
-
/* set the current source 0 (value 0/5/15/20 uA => 0..3) */
if (gpadc_pdata->ch0_current <= 1)
adc->ch0_current = PALMAS_ADC_CH0_CURRENT_SRC_0;
@@ -617,15 +588,6 @@ static int palmas_gpadc_probe(struct platform_device *pdev)
palmas_gpadc_calibrate(adc, i);
}

- if (adc->wakeup1_enable || adc->wakeup2_enable) {
- device_wakeup_enable(&pdev->dev);
- ret = devm_add_action_or_reset(&pdev->dev,
- palmas_disable_wakeup,
- &pdev->dev);
- if (ret)
- return ret;
- }
-
return 0;
}

diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index 117d02708439..eda1ffd99c1a 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -128,12 +128,6 @@ struct palmas_pmic_driver_data {
struct regulator_config config);
};

-struct palmas_adc_wakeup_property {
- int adc_channel_number;
- int adc_high_threshold;
- int adc_low_threshold;
-};
-
struct palmas_gpadc_platform_data {
/* Channel 3 current source is only enabled during conversion */
int ch3_current; /* 0: off; 1: 10uA; 2: 400uA; 3: 800 uA */
@@ -152,8 +146,6 @@ struct palmas_gpadc_platform_data {
int start_polarity;

int auto_conversion_period_ms;
- struct palmas_adc_wakeup_property *adc_wakeup1_data;
- struct palmas_adc_wakeup_property *adc_wakeup2_data;
};

struct palmas_reg_init {
--
2.25.1

2023-04-08 11:49:15

by Patrik Dahlström

[permalink] [raw]
Subject: [PATCH v3 2/7] iio: adc: palmas: replace "wakeup" with "event"

The palmas gpadc block has support for monitoring up to 2 ADC channels
and issue an interrupt if they reach past a set threshold. This is
currently used to wake up the system from sleep, but the functionality
is more generic than that. As such, change the naming of functions and
variables to refer to it as events instead, except during suspend and
resume where wakeup still make sense.

Signed-off-by: Patrik Dahlström <[email protected]>
---
drivers/iio/adc/palmas_gpadc.c | 50 +++++++++++++++++-----------------
1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c
index 03af6cd73ec8..55fdf59ef711 100644
--- a/drivers/iio/adc/palmas_gpadc.c
+++ b/drivers/iio/adc/palmas_gpadc.c
@@ -76,7 +76,7 @@ static struct palmas_gpadc_info palmas_gpadc_info[] = {
PALMAS_ADC_INFO(IN15, 0, 0, 0, 0, INVALID, INVALID, true),
};

-struct palmas_adc_wakeup_property {
+struct palmas_adc_event {
int adc_channel_number;
int adc_high_threshold;
int adc_low_threshold;
@@ -117,10 +117,10 @@ struct palmas_gpadc {
int irq_auto_1;
struct palmas_gpadc_info *adc_info;
struct completion conv_completion;
- struct palmas_adc_wakeup_property wakeup1_data;
- struct palmas_adc_wakeup_property wakeup2_data;
- bool wakeup1_enable;
- bool wakeup2_enable;
+ struct palmas_adc_event event0;
+ struct palmas_adc_event event1;
+ bool event0_enable;
+ bool event1_enable;
int auto_conversion_period;
struct mutex lock;
};
@@ -591,7 +591,7 @@ static int palmas_gpadc_probe(struct platform_device *pdev)
return 0;
}

-static int palmas_adc_wakeup_configure(struct palmas_gpadc *adc)
+static int palmas_adc_configure_events(struct palmas_gpadc *adc)
{
int adc_period, conv;
int i;
@@ -617,16 +617,16 @@ static int palmas_adc_wakeup_configure(struct palmas_gpadc *adc)
}

conv = 0;
- if (adc->wakeup1_enable) {
+ if (adc->event0_enable) {
int polarity;

- ch0 = adc->wakeup1_data.adc_channel_number;
+ ch0 = adc->event0.adc_channel_number;
conv |= PALMAS_GPADC_AUTO_CTRL_AUTO_CONV0_EN;
- if (adc->wakeup1_data.adc_high_threshold > 0) {
- thres = adc->wakeup1_data.adc_high_threshold;
+ if (adc->event0.adc_high_threshold > 0) {
+ thres = adc->event0.adc_high_threshold;
polarity = 0;
} else {
- thres = adc->wakeup1_data.adc_low_threshold;
+ thres = adc->event0.adc_low_threshold;
polarity = PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_POL;
}

@@ -648,16 +648,16 @@ static int palmas_adc_wakeup_configure(struct palmas_gpadc *adc)
}
}

- if (adc->wakeup2_enable) {
+ if (adc->event1_enable) {
int polarity;

- ch1 = adc->wakeup2_data.adc_channel_number;
+ ch1 = adc->event1.adc_channel_number;
conv |= PALMAS_GPADC_AUTO_CTRL_AUTO_CONV1_EN;
- if (adc->wakeup2_data.adc_high_threshold > 0) {
- thres = adc->wakeup2_data.adc_high_threshold;
+ if (adc->event1.adc_high_threshold > 0) {
+ thres = adc->event1.adc_high_threshold;
polarity = 0;
} else {
- thres = adc->wakeup2_data.adc_low_threshold;
+ thres = adc->event1.adc_low_threshold;
polarity = PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_POL;
}

@@ -696,7 +696,7 @@ static int palmas_adc_wakeup_configure(struct palmas_gpadc *adc)
return ret;
}

-static int palmas_adc_wakeup_reset(struct palmas_gpadc *adc)
+static int palmas_adc_reset_events(struct palmas_gpadc *adc)
{
int ret;

@@ -718,20 +718,20 @@ static int palmas_gpadc_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct palmas_gpadc *adc = iio_priv(indio_dev);
- int wakeup = adc->wakeup1_enable || adc->wakeup2_enable;
+ int wakeup = adc->event0_enable || adc->event1_enable;
int ret;

if (!device_may_wakeup(dev) || !wakeup)
return 0;

- ret = palmas_adc_wakeup_configure(adc);
+ ret = palmas_adc_configure_events(adc);
if (ret < 0)
return ret;

- if (adc->wakeup1_enable)
+ if (adc->event0_enable)
enable_irq_wake(adc->irq_auto_0);

- if (adc->wakeup2_enable)
+ if (adc->event1_enable)
enable_irq_wake(adc->irq_auto_1);

return 0;
@@ -741,20 +741,20 @@ static int palmas_gpadc_resume(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct palmas_gpadc *adc = iio_priv(indio_dev);
- int wakeup = adc->wakeup1_enable || adc->wakeup2_enable;
+ int wakeup = adc->event0_enable || adc->event1_enable;
int ret;

if (!device_may_wakeup(dev) || !wakeup)
return 0;

- ret = palmas_adc_wakeup_reset(adc);
+ ret = palmas_adc_reset_events(adc);
if (ret < 0)
return ret;

- if (adc->wakeup1_enable)
+ if (adc->event0_enable)
disable_irq_wake(adc->irq_auto_0);

- if (adc->wakeup2_enable)
+ if (adc->event1_enable)
disable_irq_wake(adc->irq_auto_1);

return 0;
--
2.25.1

2023-04-08 11:49:36

by Patrik Dahlström

[permalink] [raw]
Subject: [PATCH v3 3/7] iio: adc: palmas: use iio_event_direction for threshold polarity

Instead of having high_threshold > 0 as an indicator for upper threshold
event and lower threshold event otherwise, use enum iio_event_direction
instead. This is hopefully less ambiguous.

Signed-off-by: Patrik Dahlström <[email protected]>
---
drivers/iio/adc/palmas_gpadc.c | 36 ++++++++++++++++++++++------------
1 file changed, 23 insertions(+), 13 deletions(-)

diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c
index 55fdf59ef711..205a7628b235 100644
--- a/drivers/iio/adc/palmas_gpadc.c
+++ b/drivers/iio/adc/palmas_gpadc.c
@@ -77,9 +77,9 @@ static struct palmas_gpadc_info palmas_gpadc_info[] = {
};

struct palmas_adc_event {
- int adc_channel_number;
- int adc_high_threshold;
- int adc_low_threshold;
+ int channel;
+ int raw_thresh;
+ enum iio_event_direction direction;
};

/*
@@ -618,16 +618,21 @@ static int palmas_adc_configure_events(struct palmas_gpadc *adc)

conv = 0;
if (adc->event0_enable) {
+ struct palmas_adc_event *ev = &adc->event0;
int polarity;

- ch0 = adc->event0.adc_channel_number;
+ ch0 = ev->channel;
+ thres = ev->raw_thresh;
conv |= PALMAS_GPADC_AUTO_CTRL_AUTO_CONV0_EN;
- if (adc->event0.adc_high_threshold > 0) {
- thres = adc->event0.adc_high_threshold;
+ switch (ev->direction) {
+ case IIO_EV_DIR_RISING:
polarity = 0;
- } else {
- thres = adc->event0.adc_low_threshold;
+ break;
+ case IIO_EV_DIR_FALLING:
polarity = PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_POL;
+ break;
+ default:
+ return -EINVAL;
}

ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE,
@@ -649,16 +654,21 @@ static int palmas_adc_configure_events(struct palmas_gpadc *adc)
}

if (adc->event1_enable) {
+ struct palmas_adc_event *ev = &adc->event1;
int polarity;

- ch1 = adc->event1.adc_channel_number;
+ ch1 = ev->channel;
+ thres = ev->raw_thresh;
conv |= PALMAS_GPADC_AUTO_CTRL_AUTO_CONV1_EN;
- if (adc->event1.adc_high_threshold > 0) {
- thres = adc->event1.adc_high_threshold;
+ switch (ev->direction) {
+ case IIO_EV_DIR_RISING:
polarity = 0;
- } else {
- thres = adc->event1.adc_low_threshold;
+ break;
+ case IIO_EV_DIR_FALLING:
polarity = PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_POL;
+ break;
+ default:
+ return -EINVAL;
}

ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE,
--
2.25.1

2023-04-08 11:49:45

by Patrik Dahlström

[permalink] [raw]
Subject: Re: [PATCH v3 0/7] iio: adc: palmas_gpadc: add iio events

Please dis-regard this. I sent the wrong version :/


On Sat, Apr 08, 2023 at 01:46:17PM +0200, Patrik Dahlstr?m wrote:
> This series is based on linux-next/master [1] and [2].
>
> The palmas gpadc block has support for monitoring up to 2 ADC channels
> and issue an interrupt if they reach past a set threshold. This can be
> configured statically with device tree today, but it only gets enabled
> when reaching sleep mode. Also, it doesn't look like anyone is using it.
>
> Instead of this one special case, change the code so userspace can
> configure the ADC channels to their own needs through the iio events
> subsystem. The high and low threshold values can be set for every
> channel, but only 2 thresholds can be enabled at a time. Trying to
> enable more than 2 thresholds will result in an error.
>
> The configured thresholds will wake up the system from sleep mode if
> wakeup is enabled in /sys/devices/.../power/wakeup.
>
> The old platform data was removed.
>
> Thresholds, events, and wakeup were tested on omap5-uevm board. It wakes
> up from sleep mode when wakeup is enabled and a threshold is passed. A
> userspace tool for monitoring events and adjusting thresholds can be
> found at [3].
>
> V2 -> V3:
> * Rebased to linux-next.
> * Avoid reconfiguring events on error and when old == new value.
> V1 -> V2:
> * Begin by removing adc_wakeupX_data instead of doing it last.
> * Split changes in smaller patches
>
> [1] git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
> [2] https://lore.kernel.org/linux-iio/[email protected]/
> [3] https://github.com/Risca/pyra_vol_mon
>
> Patrik Dahlstr?m (7):
> iio: adc: palmas: remove adc_wakeupX_data
> iio: adc: palmas: replace "wakeup" with "event"
> iio: adc: palmas: use iio_event_direction for threshold polarity
> iio: adc: palmas: move eventX_enable into palmas_adc_event
> iio: adc: palmas: always reset events on unload
> iio: adc: palmas: add support for iio threshold events
> iio: adc: palmas: don't alter event config on suspend/resume
>
> drivers/iio/adc/palmas_gpadc.c | 559 +++++++++++++++++++++++++++------
> include/linux/mfd/palmas.h | 8 -
> 2 files changed, 464 insertions(+), 103 deletions(-)
>
>
> base-commit: 8417c8f5007bf4567ccffda850a3157c7d905f67
> prerequisite-patch-id: b0418c707db13f514400956596e9ebe91c25bba0
> --
> 2.25.1
>