Re: [PATCH v5] iio: temperature: mcp9600: add threshold events support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue,  4 Jun 2024 15:36:39 +0200
Dimitri Fedrau <dima.fedrau@xxxxxxxxx> wrote:

> The device has four programmable temperature alert outputs which can be
> used to monitor hot or cold-junction temperatures and detect falling and
> rising temperatures. It supports up to 255 degree celsius programmable
> hysteresis. Each alert can be individually configured by setting following
> options in the associated alert configuration register:
> - monitor hot or cold junction temperature
> - monitor rising or falling temperature
> - set comparator or interrupt mode
> - set output polarity
> - enable alert
> 
> This patch binds alert outputs to iio events:
> - alert1: hot junction, rising temperature
> - alert2: hot junction, falling temperature
> - alert3: cold junction, rising temperature
> - alert4: cold junction, falling temperature
> 
> All outputs are set in comparator mode and polarity depends on interrupt
> configuration.
> 
> Signed-off-by: Dimitri Fedrau <dima.fedrau@xxxxxxxxx>

I think I'd have done this by taking a copy of the channels array and
putting just replacing the .event_spec and .num_event_specs fields
but what you have here works so fair enough.  It's always a fine
balance between when it makes sense to make everything data that you
pick from and when you use code to tweak that data a little.

Applied to the togreg branch of iio.git and pushed out as testing
for 0-day to take a look.

Thanks,

Jonathan

> ---
> 
> Changes in V2:
>   - Remove pretty printing patches from series
>   - Add patch for providing index for both channels(ABI change)!
>     Suggested by Jonathan, hope this okay.
>   - Remove formatting in a precursor patch
>   - Add lock documentation
>   - Add define MCP9600_TEMP_SCALE_NUM and use it instead of MICRO. MICRO is
>     type unsigned long which we have to cast to int when using
>     multiplication or division, because we are handling negative values.
>   - Use switch statement in mcp9600_write_thresh
>   - Replaced generic interrupt handler with four separate interrupt handler
>   - Use one lock instead of four
>   - Added error check for mcp9600_probe_alerts
> 
> Changes in V3:
>   - Remove patch for providing index for both channels(ABI change)!
>   - Treat hysteresis as offset and remove the lock, since dependency
>     between hysteresis and threshold doesn't exist anymore.
>   - Use helper function for handling alerts to avoid code duplication
>   - Scale max,min defines for hot and cold junction temperature to micro
> 
> Changes in V4:
>   - Added version number of patch
> 
> Changes in V5:
>   - move "struct iio_dev *indio_dev = private;" to mcp9600_alert_handler
>     instead of setting it in each alert handler to avoid code duplication
>   - Only create sysfs interfaces for events which are present.
> 
> ---
>  drivers/iio/temperature/mcp9600.c | 363 ++++++++++++++++++++++++++++--
>  1 file changed, 349 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/iio/temperature/mcp9600.c b/drivers/iio/temperature/mcp9600.c
> index 46845804292b..bfa873731d61 100644
> --- a/drivers/iio/temperature/mcp9600.c
> +++ b/drivers/iio/temperature/mcp9600.c
> @@ -6,39 +6,123 @@
>   * Author: <andrew.hepp@xxxxxxxxx>
>   */
>  
> +#include <linux/bitfield.h>
> +#include <linux/bitops.h>
> +#include <linux/bits.h>
>  #include <linux/err.h>
>  #include <linux/i2c.h>
>  #include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/math.h>
> +#include <linux/minmax.h>
>  #include <linux/mod_devicetable.h>
>  #include <linux/module.h>
>  
> +#include <linux/iio/events.h>
>  #include <linux/iio/iio.h>
>  
>  /* MCP9600 registers */
>  #define MCP9600_HOT_JUNCTION 0x0
>  #define MCP9600_COLD_JUNCTION 0x2
> +#define MCP9600_STATUS			0x4
> +#define MCP9600_STATUS_ALERT(x)		BIT(x)
> +#define MCP9600_ALERT_CFG1		0x8
> +#define MCP9600_ALERT_CFG(x)		(MCP9600_ALERT_CFG1 + (x - 1))
> +#define MCP9600_ALERT_CFG_ENABLE	BIT(0)
> +#define MCP9600_ALERT_CFG_ACTIVE_HIGH	BIT(2)
> +#define MCP9600_ALERT_CFG_FALLING	BIT(3)
> +#define MCP9600_ALERT_CFG_COLD_JUNCTION	BIT(4)
> +#define MCP9600_ALERT_HYSTERESIS1	0xc
> +#define MCP9600_ALERT_HYSTERESIS(x)	(MCP9600_ALERT_HYSTERESIS1 + (x - 1))
> +#define MCP9600_ALERT_LIMIT1		0x10
> +#define MCP9600_ALERT_LIMIT(x)		(MCP9600_ALERT_LIMIT1 + (x - 1))
> +#define MCP9600_ALERT_LIMIT_MASK	GENMASK(15, 2)
>  #define MCP9600_DEVICE_ID 0x20
>  
>  /* MCP9600 device id value */
>  #define MCP9600_DEVICE_ID_MCP9600 0x40
>  
> -static const struct iio_chan_spec mcp9600_channels[] = {
> +#define MCP9600_ALERT_COUNT		4
> +
> +#define MCP9600_MIN_TEMP_HOT_JUNCTION_MICRO	-200000000
> +#define MCP9600_MAX_TEMP_HOT_JUNCTION_MICRO	1800000000
> +
> +#define MCP9600_MIN_TEMP_COLD_JUNCTION_MICRO	-40000000
> +#define MCP9600_MAX_TEMP_COLD_JUNCTION_MICRO	125000000
> +
> +enum mcp9600_alert {
> +	MCP9600_ALERT1,
> +	MCP9600_ALERT2,
> +	MCP9600_ALERT3,
> +	MCP9600_ALERT4
> +};
> +
> +static const char * const mcp9600_alert_name[MCP9600_ALERT_COUNT] = {
> +	[MCP9600_ALERT1] = "alert1",
> +	[MCP9600_ALERT2] = "alert2",
> +	[MCP9600_ALERT3] = "alert3",
> +	[MCP9600_ALERT4] = "alert4",
> +};
> +
> +static const struct iio_event_spec mcp9600_events[] = {
>  	{
> -		.type = IIO_TEMP,
> -		.address = MCP9600_HOT_JUNCTION,
> -		.info_mask_separate =
> -			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> +		.type = IIO_EV_TYPE_THRESH,
> +		.dir = IIO_EV_DIR_RISING,
> +		.mask_separate = BIT(IIO_EV_INFO_ENABLE) |
> +				 BIT(IIO_EV_INFO_VALUE) |
> +				 BIT(IIO_EV_INFO_HYSTERESIS),
>  	},
>  	{
> -		.type = IIO_TEMP,
> -		.address = MCP9600_COLD_JUNCTION,
> -		.channel2 = IIO_MOD_TEMP_AMBIENT,
> -		.modified = 1,
> -		.info_mask_separate =
> -			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> +		.type = IIO_EV_TYPE_THRESH,
> +		.dir = IIO_EV_DIR_FALLING,
> +		.mask_separate = BIT(IIO_EV_INFO_ENABLE) |
> +				 BIT(IIO_EV_INFO_VALUE) |
> +				 BIT(IIO_EV_INFO_HYSTERESIS),
>  	},
>  };
>  
> +#define MCP9600_CHANNELS(hj_num_ev, hj_ev_spec_off, cj_num_ev, cj_ev_spec_off) \
> +	{								       \
> +		{							       \
> +			.type = IIO_TEMP,				       \
> +			.address = MCP9600_HOT_JUNCTION,		       \
> +			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |	       \
> +					      BIT(IIO_CHAN_INFO_SCALE),	       \
> +			.event_spec = &mcp9600_events[hj_ev_spec_off],	       \
> +			.num_event_specs = hj_num_ev,			       \
> +		},							       \
> +		{							       \
> +			.type = IIO_TEMP,				       \
> +			.address = MCP9600_COLD_JUNCTION,		       \
> +			.channel2 = IIO_MOD_TEMP_AMBIENT,		       \
> +			.modified = 1,					       \
> +			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |	       \
> +					      BIT(IIO_CHAN_INFO_SCALE),	       \
> +			.event_spec = &mcp9600_events[cj_ev_spec_off],	       \
> +			.num_event_specs = cj_num_ev,			       \
> +		},							       \
> +	}
> +
> +static const struct iio_chan_spec mcp9600_channels[][2] = {
> +	MCP9600_CHANNELS(0, 0, 0, 0), /* Alerts: - - - - */
> +	MCP9600_CHANNELS(1, 0, 0, 0), /* Alerts: 1 - - - */
> +	MCP9600_CHANNELS(1, 1, 0, 0), /* Alerts: - 2 - - */
> +	MCP9600_CHANNELS(2, 0, 0, 0), /* Alerts: 1 2 - - */
> +	MCP9600_CHANNELS(0, 0, 1, 0), /* Alerts: - - 3 - */
> +	MCP9600_CHANNELS(1, 0, 1, 0), /* Alerts: 1 - 3 - */
> +	MCP9600_CHANNELS(1, 1, 1, 0), /* Alerts: - 2 3 - */
> +	MCP9600_CHANNELS(2, 0, 1, 0), /* Alerts: 1 2 3 - */
> +	MCP9600_CHANNELS(0, 0, 1, 1), /* Alerts: - - - 4 */
> +	MCP9600_CHANNELS(1, 0, 1, 1), /* Alerts: 1 - - 4 */
> +	MCP9600_CHANNELS(1, 1, 1, 1), /* Alerts: - 2 - 4 */
> +	MCP9600_CHANNELS(2, 0, 1, 1), /* Alerts: 1 2 - 4 */
> +	MCP9600_CHANNELS(0, 0, 2, 0), /* Alerts: - - 3 4 */
> +	MCP9600_CHANNELS(1, 0, 2, 0), /* Alerts: 1 - 3 4 */
> +	MCP9600_CHANNELS(1, 1, 2, 0), /* Alerts: - 2 3 4 */
> +	MCP9600_CHANNELS(2, 0, 2, 0), /* Alerts: 1 2 3 4 */
> +};








[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux