arm64: dts: qcom: sm8550: add TRNG node
[linux-modified.git] / drivers / iio / amplifiers / hmc425a.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * HMC425A and similar Gain Amplifiers
4  *
5  * Copyright 2020 Analog Devices Inc.
6  */
7
8 #include <linux/device.h>
9 #include <linux/err.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/mod_devicetable.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/property.h>
18 #include <linux/slab.h>
19 #include <linux/regulator/consumer.h>
20 #include <linux/sysfs.h>
21
22 enum hmc425a_type {
23         ID_HMC425A,
24         ID_HMC540S,
25 };
26
27 struct hmc425a_chip_info {
28         const char                      *name;
29         const struct iio_chan_spec      *channels;
30         unsigned int                    num_channels;
31         unsigned int                    num_gpios;
32         int                             gain_min;
33         int                             gain_max;
34         int                             default_gain;
35 };
36
37 struct hmc425a_state {
38         struct  mutex lock; /* protect sensor state */
39         struct  hmc425a_chip_info *chip_info;
40         struct  gpio_descs *gpios;
41         enum    hmc425a_type type;
42         u32     gain;
43 };
44
45 static int hmc425a_write(struct iio_dev *indio_dev, u32 value)
46 {
47         struct hmc425a_state *st = iio_priv(indio_dev);
48         DECLARE_BITMAP(values, BITS_PER_TYPE(value));
49
50         values[0] = value;
51
52         gpiod_set_array_value_cansleep(st->gpios->ndescs, st->gpios->desc,
53                                        NULL, values);
54         return 0;
55 }
56
57 static int hmc425a_read_raw(struct iio_dev *indio_dev,
58                             struct iio_chan_spec const *chan, int *val,
59                             int *val2, long m)
60 {
61         struct hmc425a_state *st = iio_priv(indio_dev);
62         int code, gain = 0;
63         int ret;
64
65         mutex_lock(&st->lock);
66         switch (m) {
67         case IIO_CHAN_INFO_HARDWAREGAIN:
68                 code = st->gain;
69
70                 switch (st->type) {
71                 case ID_HMC425A:
72                         gain = ~code * -500;
73                         break;
74                 case ID_HMC540S:
75                         gain = ~code * -1000;
76                         break;
77                 }
78
79                 *val = gain / 1000;
80                 *val2 = (gain % 1000) * 1000;
81
82                 ret = IIO_VAL_INT_PLUS_MICRO_DB;
83                 break;
84         default:
85                 ret = -EINVAL;
86         }
87         mutex_unlock(&st->lock);
88
89         return ret;
90 };
91
92 static int hmc425a_write_raw(struct iio_dev *indio_dev,
93                              struct iio_chan_spec const *chan, int val,
94                              int val2, long mask)
95 {
96         struct hmc425a_state *st = iio_priv(indio_dev);
97         struct hmc425a_chip_info *inf = st->chip_info;
98         int code = 0, gain;
99         int ret;
100
101         if (val < 0)
102                 gain = (val * 1000) - (val2 / 1000);
103         else
104                 gain = (val * 1000) + (val2 / 1000);
105
106         if (gain > inf->gain_max || gain < inf->gain_min)
107                 return -EINVAL;
108
109         switch (st->type) {
110         case ID_HMC425A:
111                 code = ~((abs(gain) / 500) & 0x3F);
112                 break;
113         case ID_HMC540S:
114                 code = ~((abs(gain) / 1000) & 0xF);
115                 break;
116         }
117
118         mutex_lock(&st->lock);
119         switch (mask) {
120         case IIO_CHAN_INFO_HARDWAREGAIN:
121                 st->gain = code;
122
123                 ret = hmc425a_write(indio_dev, st->gain);
124                 break;
125         default:
126                 ret = -EINVAL;
127         }
128         mutex_unlock(&st->lock);
129
130         return ret;
131 }
132
133 static int hmc425a_write_raw_get_fmt(struct iio_dev *indio_dev,
134                                      struct iio_chan_spec const *chan,
135                                      long mask)
136 {
137         switch (mask) {
138         case IIO_CHAN_INFO_HARDWAREGAIN:
139                 return IIO_VAL_INT_PLUS_MICRO_DB;
140         default:
141                 return -EINVAL;
142         }
143 }
144
145 static const struct iio_info hmc425a_info = {
146         .read_raw = &hmc425a_read_raw,
147         .write_raw = &hmc425a_write_raw,
148         .write_raw_get_fmt = &hmc425a_write_raw_get_fmt,
149 };
150
151 #define HMC425A_CHAN(_channel)                                          \
152 {                                                                       \
153         .type = IIO_VOLTAGE,                                            \
154         .output = 1,                                                    \
155         .indexed = 1,                                                   \
156         .channel = _channel,                                            \
157         .info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN),          \
158 }
159
160 static const struct iio_chan_spec hmc425a_channels[] = {
161         HMC425A_CHAN(0),
162 };
163
164 /* Match table for of_platform binding */
165 static const struct of_device_id hmc425a_of_match[] = {
166         { .compatible = "adi,hmc425a", .data = (void *)ID_HMC425A },
167         { .compatible = "adi,hmc540s", .data = (void *)ID_HMC540S },
168         {},
169 };
170 MODULE_DEVICE_TABLE(of, hmc425a_of_match);
171
172 static struct hmc425a_chip_info hmc425a_chip_info_tbl[] = {
173         [ID_HMC425A] = {
174                 .name = "hmc425a",
175                 .channels = hmc425a_channels,
176                 .num_channels = ARRAY_SIZE(hmc425a_channels),
177                 .num_gpios = 6,
178                 .gain_min = -31500,
179                 .gain_max = 0,
180                 .default_gain = -0x40, /* set default gain -31.5db*/
181         },
182         [ID_HMC540S] = {
183                 .name = "hmc540s",
184                 .channels = hmc425a_channels,
185                 .num_channels = ARRAY_SIZE(hmc425a_channels),
186                 .num_gpios = 4,
187                 .gain_min = -15000,
188                 .gain_max = 0,
189                 .default_gain = -0x10, /* set default gain -15.0db*/
190         },
191 };
192
193 static int hmc425a_probe(struct platform_device *pdev)
194 {
195         struct iio_dev *indio_dev;
196         struct hmc425a_state *st;
197         int ret;
198
199         indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
200         if (!indio_dev)
201                 return -ENOMEM;
202
203         st = iio_priv(indio_dev);
204         st->type = (uintptr_t)device_get_match_data(&pdev->dev);
205
206         st->chip_info = &hmc425a_chip_info_tbl[st->type];
207         indio_dev->num_channels = st->chip_info->num_channels;
208         indio_dev->channels = st->chip_info->channels;
209         indio_dev->name = st->chip_info->name;
210         st->gain = st->chip_info->default_gain;
211
212         st->gpios = devm_gpiod_get_array(&pdev->dev, "ctrl", GPIOD_OUT_LOW);
213         if (IS_ERR(st->gpios))
214                 return dev_err_probe(&pdev->dev, PTR_ERR(st->gpios),
215                                      "failed to get gpios\n");
216
217         if (st->gpios->ndescs != st->chip_info->num_gpios) {
218                 dev_err(&pdev->dev, "%d GPIOs needed to operate\n",
219                         st->chip_info->num_gpios);
220                 return -ENODEV;
221         }
222
223         ret = devm_regulator_get_enable(&pdev->dev, "vcc-supply");
224         if (ret)
225                 return ret;
226
227         mutex_init(&st->lock);
228
229         indio_dev->info = &hmc425a_info;
230         indio_dev->modes = INDIO_DIRECT_MODE;
231
232         return devm_iio_device_register(&pdev->dev, indio_dev);
233 }
234
235 static struct platform_driver hmc425a_driver = {
236         .driver = {
237                 .name = KBUILD_MODNAME,
238                 .of_match_table = hmc425a_of_match,
239         },
240         .probe = hmc425a_probe,
241 };
242 module_platform_driver(hmc425a_driver);
243
244 MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
245 MODULE_DESCRIPTION("Analog Devices HMC425A and similar GPIO control Gain Amplifiers");
246 MODULE_LICENSE("GPL v2");