162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Industrial I/O driver for Microchip digital potentiometers
462306a36Sopenharmony_ci * Copyright (c) 2015  Axentia Technologies AB
562306a36Sopenharmony_ci * Author: Peter Rosin <peda@axentia.se>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Datasheet: http://www.microchip.com/downloads/en/DeviceDoc/22096b.pdf
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * DEVID	#Wipers	#Positions	Resistor Opts (kOhm)	i2c address
1062306a36Sopenharmony_ci * mcp4531	1	129		5, 10, 50, 100          010111x
1162306a36Sopenharmony_ci * mcp4532	1	129		5, 10, 50, 100          01011xx
1262306a36Sopenharmony_ci * mcp4541	1	129		5, 10, 50, 100          010111x
1362306a36Sopenharmony_ci * mcp4542	1	129		5, 10, 50, 100          01011xx
1462306a36Sopenharmony_ci * mcp4551	1	257		5, 10, 50, 100          010111x
1562306a36Sopenharmony_ci * mcp4552	1	257		5, 10, 50, 100          01011xx
1662306a36Sopenharmony_ci * mcp4561	1	257		5, 10, 50, 100          010111x
1762306a36Sopenharmony_ci * mcp4562	1	257		5, 10, 50, 100          01011xx
1862306a36Sopenharmony_ci * mcp4631	2	129		5, 10, 50, 100          0101xxx
1962306a36Sopenharmony_ci * mcp4632	2	129		5, 10, 50, 100          01011xx
2062306a36Sopenharmony_ci * mcp4641	2	129		5, 10, 50, 100          0101xxx
2162306a36Sopenharmony_ci * mcp4642	2	129		5, 10, 50, 100          01011xx
2262306a36Sopenharmony_ci * mcp4651	2	257		5, 10, 50, 100          0101xxx
2362306a36Sopenharmony_ci * mcp4652	2	257		5, 10, 50, 100          01011xx
2462306a36Sopenharmony_ci * mcp4661	2	257		5, 10, 50, 100          0101xxx
2562306a36Sopenharmony_ci * mcp4662	2	257		5, 10, 50, 100          01011xx
2662306a36Sopenharmony_ci */
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#include <linux/module.h>
2962306a36Sopenharmony_ci#include <linux/i2c.h>
3062306a36Sopenharmony_ci#include <linux/err.h>
3162306a36Sopenharmony_ci#include <linux/mod_devicetable.h>
3262306a36Sopenharmony_ci#include <linux/property.h>
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#include <linux/iio/iio.h>
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistruct mcp4531_cfg {
3762306a36Sopenharmony_ci	int wipers;
3862306a36Sopenharmony_ci	int avail[3];
3962306a36Sopenharmony_ci	int kohms;
4062306a36Sopenharmony_ci};
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cienum mcp4531_type {
4362306a36Sopenharmony_ci	MCP453x_502,
4462306a36Sopenharmony_ci	MCP453x_103,
4562306a36Sopenharmony_ci	MCP453x_503,
4662306a36Sopenharmony_ci	MCP453x_104,
4762306a36Sopenharmony_ci	MCP454x_502,
4862306a36Sopenharmony_ci	MCP454x_103,
4962306a36Sopenharmony_ci	MCP454x_503,
5062306a36Sopenharmony_ci	MCP454x_104,
5162306a36Sopenharmony_ci	MCP455x_502,
5262306a36Sopenharmony_ci	MCP455x_103,
5362306a36Sopenharmony_ci	MCP455x_503,
5462306a36Sopenharmony_ci	MCP455x_104,
5562306a36Sopenharmony_ci	MCP456x_502,
5662306a36Sopenharmony_ci	MCP456x_103,
5762306a36Sopenharmony_ci	MCP456x_503,
5862306a36Sopenharmony_ci	MCP456x_104,
5962306a36Sopenharmony_ci	MCP463x_502,
6062306a36Sopenharmony_ci	MCP463x_103,
6162306a36Sopenharmony_ci	MCP463x_503,
6262306a36Sopenharmony_ci	MCP463x_104,
6362306a36Sopenharmony_ci	MCP464x_502,
6462306a36Sopenharmony_ci	MCP464x_103,
6562306a36Sopenharmony_ci	MCP464x_503,
6662306a36Sopenharmony_ci	MCP464x_104,
6762306a36Sopenharmony_ci	MCP465x_502,
6862306a36Sopenharmony_ci	MCP465x_103,
6962306a36Sopenharmony_ci	MCP465x_503,
7062306a36Sopenharmony_ci	MCP465x_104,
7162306a36Sopenharmony_ci	MCP466x_502,
7262306a36Sopenharmony_ci	MCP466x_103,
7362306a36Sopenharmony_ci	MCP466x_503,
7462306a36Sopenharmony_ci	MCP466x_104,
7562306a36Sopenharmony_ci};
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic const struct mcp4531_cfg mcp4531_cfg[] = {
7862306a36Sopenharmony_ci	[MCP453x_502] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =   5, },
7962306a36Sopenharmony_ci	[MCP453x_103] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =  10, },
8062306a36Sopenharmony_ci	[MCP453x_503] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =  50, },
8162306a36Sopenharmony_ci	[MCP453x_104] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 100, },
8262306a36Sopenharmony_ci	[MCP454x_502] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =   5, },
8362306a36Sopenharmony_ci	[MCP454x_103] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =  10, },
8462306a36Sopenharmony_ci	[MCP454x_503] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =  50, },
8562306a36Sopenharmony_ci	[MCP454x_104] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 100, },
8662306a36Sopenharmony_ci	[MCP455x_502] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =   5, },
8762306a36Sopenharmony_ci	[MCP455x_103] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =  10, },
8862306a36Sopenharmony_ci	[MCP455x_503] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =  50, },
8962306a36Sopenharmony_ci	[MCP455x_104] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 100, },
9062306a36Sopenharmony_ci	[MCP456x_502] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =   5, },
9162306a36Sopenharmony_ci	[MCP456x_103] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =  10, },
9262306a36Sopenharmony_ci	[MCP456x_503] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =  50, },
9362306a36Sopenharmony_ci	[MCP456x_104] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 100, },
9462306a36Sopenharmony_ci	[MCP463x_502] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =   5, },
9562306a36Sopenharmony_ci	[MCP463x_103] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =  10, },
9662306a36Sopenharmony_ci	[MCP463x_503] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =  50, },
9762306a36Sopenharmony_ci	[MCP463x_104] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 100, },
9862306a36Sopenharmony_ci	[MCP464x_502] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =   5, },
9962306a36Sopenharmony_ci	[MCP464x_103] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =  10, },
10062306a36Sopenharmony_ci	[MCP464x_503] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =  50, },
10162306a36Sopenharmony_ci	[MCP464x_104] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 100, },
10262306a36Sopenharmony_ci	[MCP465x_502] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =   5, },
10362306a36Sopenharmony_ci	[MCP465x_103] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =  10, },
10462306a36Sopenharmony_ci	[MCP465x_503] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =  50, },
10562306a36Sopenharmony_ci	[MCP465x_104] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 100, },
10662306a36Sopenharmony_ci	[MCP466x_502] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =   5, },
10762306a36Sopenharmony_ci	[MCP466x_103] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =  10, },
10862306a36Sopenharmony_ci	[MCP466x_503] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =  50, },
10962306a36Sopenharmony_ci	[MCP466x_104] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 100, },
11062306a36Sopenharmony_ci};
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci#define MCP4531_WRITE (0 << 2)
11362306a36Sopenharmony_ci#define MCP4531_INCR  (1 << 2)
11462306a36Sopenharmony_ci#define MCP4531_DECR  (2 << 2)
11562306a36Sopenharmony_ci#define MCP4531_READ  (3 << 2)
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci#define MCP4531_WIPER_SHIFT (4)
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistruct mcp4531_data {
12062306a36Sopenharmony_ci	struct i2c_client *client;
12162306a36Sopenharmony_ci	const struct mcp4531_cfg *cfg;
12262306a36Sopenharmony_ci};
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci#define MCP4531_CHANNEL(ch) {						\
12562306a36Sopenharmony_ci	.type = IIO_RESISTANCE,						\
12662306a36Sopenharmony_ci	.indexed = 1,							\
12762306a36Sopenharmony_ci	.output = 1,							\
12862306a36Sopenharmony_ci	.channel = (ch),						\
12962306a36Sopenharmony_ci	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
13062306a36Sopenharmony_ci	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),		\
13162306a36Sopenharmony_ci	.info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_RAW),	\
13262306a36Sopenharmony_ci}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cistatic const struct iio_chan_spec mcp4531_channels[] = {
13562306a36Sopenharmony_ci	MCP4531_CHANNEL(0),
13662306a36Sopenharmony_ci	MCP4531_CHANNEL(1),
13762306a36Sopenharmony_ci};
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic int mcp4531_read_raw(struct iio_dev *indio_dev,
14062306a36Sopenharmony_ci			    struct iio_chan_spec const *chan,
14162306a36Sopenharmony_ci			    int *val, int *val2, long mask)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	struct mcp4531_data *data = iio_priv(indio_dev);
14462306a36Sopenharmony_ci	int address = chan->channel << MCP4531_WIPER_SHIFT;
14562306a36Sopenharmony_ci	s32 ret;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	switch (mask) {
14862306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
14962306a36Sopenharmony_ci		ret = i2c_smbus_read_word_swapped(data->client,
15062306a36Sopenharmony_ci						  MCP4531_READ | address);
15162306a36Sopenharmony_ci		if (ret < 0)
15262306a36Sopenharmony_ci			return ret;
15362306a36Sopenharmony_ci		*val = ret;
15462306a36Sopenharmony_ci		return IIO_VAL_INT;
15562306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
15662306a36Sopenharmony_ci		*val = 1000 * data->cfg->kohms;
15762306a36Sopenharmony_ci		*val2 = data->cfg->avail[2];
15862306a36Sopenharmony_ci		return IIO_VAL_FRACTIONAL;
15962306a36Sopenharmony_ci	}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	return -EINVAL;
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cistatic int mcp4531_read_avail(struct iio_dev *indio_dev,
16562306a36Sopenharmony_ci			      struct iio_chan_spec const *chan,
16662306a36Sopenharmony_ci			      const int **vals, int *type, int *length,
16762306a36Sopenharmony_ci			      long mask)
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	struct mcp4531_data *data = iio_priv(indio_dev);
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	switch (mask) {
17262306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
17362306a36Sopenharmony_ci		*length = ARRAY_SIZE(data->cfg->avail);
17462306a36Sopenharmony_ci		*vals = data->cfg->avail;
17562306a36Sopenharmony_ci		*type = IIO_VAL_INT;
17662306a36Sopenharmony_ci		return IIO_AVAIL_RANGE;
17762306a36Sopenharmony_ci	}
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	return -EINVAL;
18062306a36Sopenharmony_ci}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_cistatic int mcp4531_write_raw(struct iio_dev *indio_dev,
18362306a36Sopenharmony_ci			     struct iio_chan_spec const *chan,
18462306a36Sopenharmony_ci			     int val, int val2, long mask)
18562306a36Sopenharmony_ci{
18662306a36Sopenharmony_ci	struct mcp4531_data *data = iio_priv(indio_dev);
18762306a36Sopenharmony_ci	int address = chan->channel << MCP4531_WIPER_SHIFT;
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	switch (mask) {
19062306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
19162306a36Sopenharmony_ci		if (val > data->cfg->avail[2] || val < 0)
19262306a36Sopenharmony_ci			return -EINVAL;
19362306a36Sopenharmony_ci		break;
19462306a36Sopenharmony_ci	default:
19562306a36Sopenharmony_ci		return -EINVAL;
19662306a36Sopenharmony_ci	}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	return i2c_smbus_write_byte_data(data->client,
19962306a36Sopenharmony_ci					 MCP4531_WRITE | address | (val >> 8),
20062306a36Sopenharmony_ci					 val & 0xff);
20162306a36Sopenharmony_ci}
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_cistatic const struct iio_info mcp4531_info = {
20462306a36Sopenharmony_ci	.read_raw = mcp4531_read_raw,
20562306a36Sopenharmony_ci	.read_avail = mcp4531_read_avail,
20662306a36Sopenharmony_ci	.write_raw = mcp4531_write_raw,
20762306a36Sopenharmony_ci};
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci#define MCP4531_ID_TABLE(_name, cfg) {				\
21062306a36Sopenharmony_ci	.name = _name,						\
21162306a36Sopenharmony_ci	.driver_data = (kernel_ulong_t)&mcp4531_cfg[cfg],	\
21262306a36Sopenharmony_ci}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_cistatic const struct i2c_device_id mcp4531_id[] = {
21562306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4531-502", MCP453x_502),
21662306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4531-103", MCP453x_103),
21762306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4531-503", MCP453x_503),
21862306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4531-104", MCP453x_104),
21962306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4532-502", MCP453x_502),
22062306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4532-103", MCP453x_103),
22162306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4532-503", MCP453x_503),
22262306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4532-104", MCP453x_104),
22362306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4541-502", MCP454x_502),
22462306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4541-103", MCP454x_103),
22562306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4541-503", MCP454x_503),
22662306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4541-104", MCP454x_104),
22762306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4542-502", MCP454x_502),
22862306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4542-103", MCP454x_103),
22962306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4542-503", MCP454x_503),
23062306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4542-104", MCP454x_104),
23162306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4551-502", MCP455x_502),
23262306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4551-103", MCP455x_103),
23362306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4551-503", MCP455x_503),
23462306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4551-104", MCP455x_104),
23562306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4552-502", MCP455x_502),
23662306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4552-103", MCP455x_103),
23762306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4552-503", MCP455x_503),
23862306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4552-104", MCP455x_104),
23962306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4561-502", MCP456x_502),
24062306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4561-103", MCP456x_103),
24162306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4561-503", MCP456x_503),
24262306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4561-104", MCP456x_104),
24362306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4562-502", MCP456x_502),
24462306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4562-103", MCP456x_103),
24562306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4562-503", MCP456x_503),
24662306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4562-104", MCP456x_104),
24762306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4631-502", MCP463x_502),
24862306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4631-103", MCP463x_103),
24962306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4631-503", MCP463x_503),
25062306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4631-104", MCP463x_104),
25162306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4632-502", MCP463x_502),
25262306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4632-103", MCP463x_103),
25362306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4632-503", MCP463x_503),
25462306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4632-104", MCP463x_104),
25562306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4641-502", MCP464x_502),
25662306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4641-103", MCP464x_103),
25762306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4641-503", MCP464x_503),
25862306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4641-104", MCP464x_104),
25962306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4642-502", MCP464x_502),
26062306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4642-103", MCP464x_103),
26162306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4642-503", MCP464x_503),
26262306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4642-104", MCP464x_104),
26362306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4651-502", MCP465x_502),
26462306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4651-103", MCP465x_103),
26562306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4651-503", MCP465x_503),
26662306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4651-104", MCP465x_104),
26762306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4652-502", MCP465x_502),
26862306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4652-103", MCP465x_103),
26962306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4652-503", MCP465x_503),
27062306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4652-104", MCP465x_104),
27162306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4661-502", MCP466x_502),
27262306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4661-103", MCP466x_103),
27362306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4661-503", MCP466x_503),
27462306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4661-104", MCP466x_104),
27562306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4662-502", MCP466x_502),
27662306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4662-103", MCP466x_103),
27762306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4662-503", MCP466x_503),
27862306a36Sopenharmony_ci	MCP4531_ID_TABLE("mcp4662-104", MCP466x_104),
27962306a36Sopenharmony_ci	{ /* sentinel */ }
28062306a36Sopenharmony_ci};
28162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, mcp4531_id);
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci#define MCP4531_COMPATIBLE(of_compatible, cfg) {	\
28462306a36Sopenharmony_ci			.compatible = of_compatible,	\
28562306a36Sopenharmony_ci			.data = &mcp4531_cfg[cfg],	\
28662306a36Sopenharmony_ci}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_cistatic const struct of_device_id mcp4531_of_match[] = {
28962306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4531-502", MCP453x_502),
29062306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4531-103", MCP453x_103),
29162306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4531-503", MCP453x_503),
29262306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4531-104", MCP453x_104),
29362306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4532-502", MCP453x_502),
29462306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4532-103", MCP453x_103),
29562306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4532-503", MCP453x_503),
29662306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4532-104", MCP453x_104),
29762306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4541-502", MCP454x_502),
29862306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4541-103", MCP454x_103),
29962306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4541-503", MCP454x_503),
30062306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4541-104", MCP454x_104),
30162306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4542-502", MCP454x_502),
30262306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4542-103", MCP454x_103),
30362306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4542-503", MCP454x_503),
30462306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4542-104", MCP454x_104),
30562306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4551-502", MCP455x_502),
30662306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4551-103", MCP455x_103),
30762306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4551-503", MCP455x_503),
30862306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4551-104", MCP455x_104),
30962306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4552-502", MCP455x_502),
31062306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4552-103", MCP455x_103),
31162306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4552-503", MCP455x_503),
31262306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4552-104", MCP455x_104),
31362306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4561-502", MCP456x_502),
31462306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4561-103", MCP456x_103),
31562306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4561-503", MCP456x_503),
31662306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4561-104", MCP456x_104),
31762306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4562-502", MCP456x_502),
31862306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4562-103", MCP456x_103),
31962306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4562-503", MCP456x_503),
32062306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4562-104", MCP456x_104),
32162306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4631-502", MCP463x_502),
32262306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4631-103", MCP463x_103),
32362306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4631-503", MCP463x_503),
32462306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4631-104", MCP463x_104),
32562306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4632-502", MCP463x_502),
32662306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4632-103", MCP463x_103),
32762306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4632-503", MCP463x_503),
32862306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4632-104", MCP463x_104),
32962306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4641-502", MCP464x_502),
33062306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4641-103", MCP464x_103),
33162306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4641-503", MCP464x_503),
33262306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4641-104", MCP464x_104),
33362306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4642-502", MCP464x_502),
33462306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4642-103", MCP464x_103),
33562306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4642-503", MCP464x_503),
33662306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4642-104", MCP464x_104),
33762306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4651-502", MCP465x_502),
33862306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4651-103", MCP465x_103),
33962306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4651-503", MCP465x_503),
34062306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4651-104", MCP465x_104),
34162306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4652-502", MCP465x_502),
34262306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4652-103", MCP465x_103),
34362306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4652-503", MCP465x_503),
34462306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4652-104", MCP465x_104),
34562306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4661-502", MCP466x_502),
34662306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4661-103", MCP466x_103),
34762306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4661-503", MCP466x_503),
34862306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4661-104", MCP466x_104),
34962306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4662-502", MCP466x_502),
35062306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4662-103", MCP466x_103),
35162306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4662-503", MCP466x_503),
35262306a36Sopenharmony_ci	MCP4531_COMPATIBLE("microchip,mcp4662-104", MCP466x_104),
35362306a36Sopenharmony_ci	{ /* sentinel */ }
35462306a36Sopenharmony_ci};
35562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, mcp4531_of_match);
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_cistatic int mcp4531_probe(struct i2c_client *client)
35862306a36Sopenharmony_ci{
35962306a36Sopenharmony_ci	struct device *dev = &client->dev;
36062306a36Sopenharmony_ci	struct mcp4531_data *data;
36162306a36Sopenharmony_ci	struct iio_dev *indio_dev;
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	if (!i2c_check_functionality(client->adapter,
36462306a36Sopenharmony_ci				     I2C_FUNC_SMBUS_WORD_DATA)) {
36562306a36Sopenharmony_ci		dev_err(dev, "SMBUS Word Data not supported\n");
36662306a36Sopenharmony_ci		return -EOPNOTSUPP;
36762306a36Sopenharmony_ci	}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
37062306a36Sopenharmony_ci	if (!indio_dev)
37162306a36Sopenharmony_ci		return -ENOMEM;
37262306a36Sopenharmony_ci	data = iio_priv(indio_dev);
37362306a36Sopenharmony_ci	i2c_set_clientdata(client, indio_dev);
37462306a36Sopenharmony_ci	data->client = client;
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	data->cfg = i2c_get_match_data(client);
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	indio_dev->info = &mcp4531_info;
37962306a36Sopenharmony_ci	indio_dev->channels = mcp4531_channels;
38062306a36Sopenharmony_ci	indio_dev->num_channels = data->cfg->wipers;
38162306a36Sopenharmony_ci	indio_dev->name = client->name;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	return devm_iio_device_register(dev, indio_dev);
38462306a36Sopenharmony_ci}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_cistatic struct i2c_driver mcp4531_driver = {
38762306a36Sopenharmony_ci	.driver = {
38862306a36Sopenharmony_ci		.name	= "mcp4531",
38962306a36Sopenharmony_ci		.of_match_table = mcp4531_of_match,
39062306a36Sopenharmony_ci	},
39162306a36Sopenharmony_ci	.probe		= mcp4531_probe,
39262306a36Sopenharmony_ci	.id_table	= mcp4531_id,
39362306a36Sopenharmony_ci};
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_cimodule_i2c_driver(mcp4531_driver);
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ciMODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
39862306a36Sopenharmony_ciMODULE_DESCRIPTION("MCP4531 digital potentiometer");
39962306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
400