Skip to content

Commit 04c9a8e

Browse files
oknshnlag-linaro
authored andcommitted
iio: adc: max77541: Add ADI MAX77541 ADC Support
The MAX77541 has an 8-bit Successive Approximation Register (SAR) ADC with four multiplexers for supporting the telemetry feature. Signed-off-by: Okan Sahin <okan.sahin@analog.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://lore.kernel.org/r/20230412111256.40013-4-okan.sahin@analog.com Signed-off-by: Lee Jones <lee@kernel.org>
1 parent c2b2afe commit 04c9a8e

3 files changed

Lines changed: 206 additions & 0 deletions

File tree

drivers/iio/adc/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,17 @@ config MAX1363
735735
To compile this driver as a module, choose M here: the module will be
736736
called max1363.
737737

738+
config MAX77541_ADC
739+
tristate "Analog Devices MAX77541 ADC driver"
740+
depends on MFD_MAX77541
741+
help
742+
This driver controls a Analog Devices MAX77541 ADC
743+
via I2C bus. This device has one adc. Say yes here to build
744+
support for Analog Devices MAX77541 ADC interface.
745+
746+
To compile this driver as a module, choose M here:
747+
the module will be called max77541-adc.
748+
738749
config MAX9611
739750
tristate "Maxim max9611/max9612 ADC driver"
740751
depends on I2C

drivers/iio/adc/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ obj-$(CONFIG_MAX11205) += max11205.o
6767
obj-$(CONFIG_MAX11410) += max11410.o
6868
obj-$(CONFIG_MAX1241) += max1241.o
6969
obj-$(CONFIG_MAX1363) += max1363.o
70+
obj-$(CONFIG_MAX77541_ADC) += max77541-adc.o
7071
obj-$(CONFIG_MAX9611) += max9611.o
7172
obj-$(CONFIG_MCP320X) += mcp320x.o
7273
obj-$(CONFIG_MCP3422) += mcp3422.o

drivers/iio/adc/max77541-adc.c

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* Copyright (c) 2022 Analog Devices, Inc.
4+
* ADI MAX77541 ADC Driver with IIO interface
5+
*/
6+
7+
#include <linux/bitfield.h>
8+
#include <linux/iio/iio.h>
9+
#include <linux/mod_devicetable.h>
10+
#include <linux/platform_device.h>
11+
#include <linux/regmap.h>
12+
#include <linux/units.h>
13+
14+
#include <linux/mfd/max77541.h>
15+
16+
enum max77541_adc_range {
17+
LOW_RANGE,
18+
MID_RANGE,
19+
HIGH_RANGE,
20+
};
21+
22+
enum max77541_adc_channel {
23+
MAX77541_ADC_VSYS_V,
24+
MAX77541_ADC_VOUT1_V,
25+
MAX77541_ADC_VOUT2_V,
26+
MAX77541_ADC_TEMP,
27+
};
28+
29+
static int max77541_adc_offset(struct iio_dev *indio_dev,
30+
struct iio_chan_spec const *chan,
31+
int *val, int *val2)
32+
{
33+
switch (chan->channel) {
34+
case MAX77541_ADC_TEMP:
35+
*val = DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS, 1725);
36+
return IIO_VAL_INT;
37+
default:
38+
return -EINVAL;
39+
}
40+
}
41+
42+
static int max77541_adc_scale(struct iio_dev *indio_dev,
43+
struct iio_chan_spec const *chan,
44+
int *val, int *val2)
45+
{
46+
struct regmap **regmap = iio_priv(indio_dev);
47+
unsigned int reg_val;
48+
int ret;
49+
50+
switch (chan->channel) {
51+
case MAX77541_ADC_VSYS_V:
52+
*val = 25;
53+
return IIO_VAL_INT;
54+
case MAX77541_ADC_VOUT1_V:
55+
case MAX77541_ADC_VOUT2_V:
56+
ret = regmap_read(*regmap, MAX77541_REG_M2_CFG1, &reg_val);
57+
if (ret)
58+
return ret;
59+
60+
reg_val = FIELD_GET(MAX77541_BITS_MX_CFG1_RNG, reg_val);
61+
switch (reg_val) {
62+
case LOW_RANGE:
63+
*val = 6;
64+
*val2 = 250000;
65+
break;
66+
case MID_RANGE:
67+
*val = 12;
68+
*val2 = 500000;
69+
break;
70+
case HIGH_RANGE:
71+
*val = 25;
72+
return IIO_VAL_INT;
73+
default:
74+
return -EINVAL;
75+
}
76+
77+
return IIO_VAL_INT_PLUS_MICRO;
78+
case MAX77541_ADC_TEMP:
79+
*val = 1725;
80+
return IIO_VAL_INT;
81+
default:
82+
return -EINVAL;
83+
}
84+
}
85+
86+
static int max77541_adc_raw(struct iio_dev *indio_dev,
87+
struct iio_chan_spec const *chan,
88+
int *val)
89+
{
90+
struct regmap **regmap = iio_priv(indio_dev);
91+
int ret;
92+
93+
ret = regmap_read(*regmap, chan->address, val);
94+
if (ret)
95+
return ret;
96+
97+
return IIO_VAL_INT;
98+
}
99+
100+
#define MAX77541_ADC_CHANNEL_V(_channel, _name, _type, _reg) \
101+
{ \
102+
.type = _type, \
103+
.indexed = 1, \
104+
.channel = _channel, \
105+
.address = _reg, \
106+
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
107+
BIT(IIO_CHAN_INFO_SCALE), \
108+
.datasheet_name = _name, \
109+
}
110+
111+
#define MAX77541_ADC_CHANNEL_TEMP(_channel, _name, _type, _reg) \
112+
{ \
113+
.type = _type, \
114+
.indexed = 1, \
115+
.channel = _channel, \
116+
.address = _reg, \
117+
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
118+
BIT(IIO_CHAN_INFO_SCALE) |\
119+
BIT(IIO_CHAN_INFO_OFFSET),\
120+
.datasheet_name = _name, \
121+
}
122+
123+
static const struct iio_chan_spec max77541_adc_channels[] = {
124+
MAX77541_ADC_CHANNEL_V(MAX77541_ADC_VSYS_V, "vsys_v", IIO_VOLTAGE,
125+
MAX77541_REG_ADC_DATA_CH1),
126+
MAX77541_ADC_CHANNEL_V(MAX77541_ADC_VOUT1_V, "vout1_v", IIO_VOLTAGE,
127+
MAX77541_REG_ADC_DATA_CH2),
128+
MAX77541_ADC_CHANNEL_V(MAX77541_ADC_VOUT2_V, "vout2_v", IIO_VOLTAGE,
129+
MAX77541_REG_ADC_DATA_CH3),
130+
MAX77541_ADC_CHANNEL_TEMP(MAX77541_ADC_TEMP, "temp", IIO_TEMP,
131+
MAX77541_REG_ADC_DATA_CH6),
132+
};
133+
134+
static int max77541_adc_read_raw(struct iio_dev *indio_dev,
135+
struct iio_chan_spec const *chan,
136+
int *val, int *val2, long mask)
137+
{
138+
switch (mask) {
139+
case IIO_CHAN_INFO_OFFSET:
140+
return max77541_adc_offset(indio_dev, chan, val, val2);
141+
case IIO_CHAN_INFO_SCALE:
142+
return max77541_adc_scale(indio_dev, chan, val, val2);
143+
case IIO_CHAN_INFO_RAW:
144+
return max77541_adc_raw(indio_dev, chan, val);
145+
default:
146+
return -EINVAL;
147+
}
148+
}
149+
150+
static const struct iio_info max77541_adc_info = {
151+
.read_raw = max77541_adc_read_raw,
152+
};
153+
154+
static int max77541_adc_probe(struct platform_device *pdev)
155+
{
156+
struct device *dev = &pdev->dev;
157+
struct iio_dev *indio_dev;
158+
struct regmap **regmap;
159+
160+
indio_dev = devm_iio_device_alloc(dev, sizeof(*regmap));
161+
if (!indio_dev)
162+
return -ENOMEM;
163+
164+
regmap = iio_priv(indio_dev);
165+
166+
*regmap = dev_get_regmap(dev->parent, NULL);
167+
indio_dev->modes = INDIO_DIRECT_MODE;
168+
169+
indio_dev->name = "max77541";
170+
indio_dev->info = &max77541_adc_info;
171+
indio_dev->channels = max77541_adc_channels;
172+
indio_dev->num_channels = ARRAY_SIZE(max77541_adc_channels);
173+
174+
return devm_iio_device_register(dev, indio_dev);
175+
}
176+
177+
static const struct platform_device_id max77541_adc_platform_id[] = {
178+
{ "max77541-adc" },
179+
{ /* sentinel */ }
180+
};
181+
MODULE_DEVICE_TABLE(platform, max77541_adc_platform_id);
182+
183+
static struct platform_driver max77541_adc_driver = {
184+
.driver = {
185+
.name = "max77541-adc",
186+
},
187+
.probe = max77541_adc_probe,
188+
.id_table = max77541_adc_platform_id,
189+
};
190+
module_platform_driver(max77541_adc_driver);
191+
192+
MODULE_AUTHOR("Okan Sahin <Okan.Sahin@analog.com>");
193+
MODULE_DESCRIPTION("MAX77541 ADC driver");
194+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)