1 // SPDX-License-Identifier: GPL-2.0
3 * HMC425A and similar Gain Amplifiers
5 * Copyright 2020 Analog Devices Inc.
8 #include <linux/device.h>
10 #include <linux/gpio/consumer.h>
11 #include <linux/iio/iio.h>
12 #include <linux/iio/sysfs.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/of_device.h>
16 #include <linux/of_platform.h>
17 #include <linux/platform_device.h>
18 #include <linux/slab.h>
19 #include <linux/regulator/consumer.h>
20 #include <linux/sysfs.h>
26 struct hmc425a_chip_info
{
28 const struct iio_chan_spec
*channels
;
29 unsigned int num_channels
;
30 unsigned int num_gpios
;
36 struct hmc425a_state
{
37 struct regulator
*reg
;
38 struct mutex lock
; /* protect sensor state */
39 struct hmc425a_chip_info
*chip_info
;
40 struct gpio_descs
*gpios
;
41 enum hmc425a_type type
;
45 static int hmc425a_write(struct iio_dev
*indio_dev
, u32 value
)
47 struct hmc425a_state
*st
= iio_priv(indio_dev
);
48 DECLARE_BITMAP(values
, BITS_PER_TYPE(value
));
52 gpiod_set_array_value_cansleep(st
->gpios
->ndescs
, st
->gpios
->desc
,
57 static int hmc425a_read_raw(struct iio_dev
*indio_dev
,
58 struct iio_chan_spec
const *chan
, int *val
,
61 struct hmc425a_state
*st
= iio_priv(indio_dev
);
65 mutex_lock(&st
->lock
);
67 case IIO_CHAN_INFO_HARDWAREGAIN
:
77 *val2
= (gain
% 1000) * 1000;
79 ret
= IIO_VAL_INT_PLUS_MICRO_DB
;
84 mutex_unlock(&st
->lock
);
89 static int hmc425a_write_raw(struct iio_dev
*indio_dev
,
90 struct iio_chan_spec
const *chan
, int val
,
93 struct hmc425a_state
*st
= iio_priv(indio_dev
);
94 struct hmc425a_chip_info
*inf
= st
->chip_info
;
99 gain
= (val
* 1000) - (val2
/ 1000);
101 gain
= (val
* 1000) + (val2
/ 1000);
103 if (gain
> inf
->gain_max
|| gain
< inf
->gain_min
)
108 code
= ~((abs(gain
) / 500) & 0x3F);
112 mutex_lock(&st
->lock
);
114 case IIO_CHAN_INFO_HARDWAREGAIN
:
117 ret
= hmc425a_write(indio_dev
, st
->gain
);
122 mutex_unlock(&st
->lock
);
127 static int hmc425a_write_raw_get_fmt(struct iio_dev
*indio_dev
,
128 struct iio_chan_spec
const *chan
,
132 case IIO_CHAN_INFO_HARDWAREGAIN
:
133 return IIO_VAL_INT_PLUS_MICRO_DB
;
139 static const struct iio_info hmc425a_info
= {
140 .read_raw
= &hmc425a_read_raw
,
141 .write_raw
= &hmc425a_write_raw
,
142 .write_raw_get_fmt
= &hmc425a_write_raw_get_fmt
,
145 #define HMC425A_CHAN(_channel) \
147 .type = IIO_VOLTAGE, \
150 .channel = _channel, \
151 .info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN), \
154 static const struct iio_chan_spec hmc425a_channels
[] = {
158 /* Match table for of_platform binding */
159 static const struct of_device_id hmc425a_of_match
[] = {
160 { .compatible
= "adi,hmc425a", .data
= (void *)ID_HMC425A
},
163 MODULE_DEVICE_TABLE(of
, hmc425a_of_match
);
165 static void hmc425a_reg_disable(void *data
)
167 struct hmc425a_state
*st
= data
;
169 regulator_disable(st
->reg
);
172 static struct hmc425a_chip_info hmc425a_chip_info_tbl
[] = {
175 .channels
= hmc425a_channels
,
176 .num_channels
= ARRAY_SIZE(hmc425a_channels
),
180 .default_gain
= -0x40, /* set default gain -31.5db*/
184 static int hmc425a_probe(struct platform_device
*pdev
)
186 struct iio_dev
*indio_dev
;
187 struct hmc425a_state
*st
;
190 indio_dev
= devm_iio_device_alloc(&pdev
->dev
, sizeof(*st
));
194 st
= iio_priv(indio_dev
);
195 st
->type
= (enum hmc425a_type
)of_device_get_match_data(&pdev
->dev
);
197 st
->chip_info
= &hmc425a_chip_info_tbl
[st
->type
];
198 indio_dev
->num_channels
= st
->chip_info
->num_channels
;
199 indio_dev
->channels
= st
->chip_info
->channels
;
200 indio_dev
->name
= st
->chip_info
->name
;
201 st
->gain
= st
->chip_info
->default_gain
;
203 st
->gpios
= devm_gpiod_get_array(&pdev
->dev
, "ctrl", GPIOD_OUT_LOW
);
204 if (IS_ERR(st
->gpios
))
205 return dev_err_probe(&pdev
->dev
, PTR_ERR(st
->gpios
),
206 "failed to get gpios\n");
208 if (st
->gpios
->ndescs
!= st
->chip_info
->num_gpios
) {
209 dev_err(&pdev
->dev
, "%d GPIOs needed to operate\n",
210 st
->chip_info
->num_gpios
);
214 st
->reg
= devm_regulator_get(&pdev
->dev
, "vcc-supply");
216 return PTR_ERR(st
->reg
);
218 ret
= regulator_enable(st
->reg
);
221 ret
= devm_add_action_or_reset(&pdev
->dev
, hmc425a_reg_disable
, st
);
225 mutex_init(&st
->lock
);
227 indio_dev
->info
= &hmc425a_info
;
228 indio_dev
->modes
= INDIO_DIRECT_MODE
;
230 return devm_iio_device_register(&pdev
->dev
, indio_dev
);
233 static struct platform_driver hmc425a_driver
= {
235 .name
= KBUILD_MODNAME
,
236 .of_match_table
= hmc425a_of_match
,
238 .probe
= hmc425a_probe
,
240 module_platform_driver(hmc425a_driver
);
242 MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
243 MODULE_DESCRIPTION("Analog Devices HMC425A and similar GPIO control Gain Amplifiers");
244 MODULE_LICENSE("GPL v2");