Linux 6.7-rc7
[linux-modified.git] / drivers / iio / potentiometer / x9250.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *
4  * x9250.c  --  Renesas X9250 potentiometers IIO driver
5  *
6  * Copyright 2023 CS GROUP France
7  *
8  * Author: Herve Codina <herve.codina@bootlin.com>
9  */
10
11 #include <linux/delay.h>
12 #include <linux/gpio/consumer.h>
13 #include <linux/iio/iio.h>
14 #include <linux/limits.h>
15 #include <linux/module.h>
16 #include <linux/regulator/consumer.h>
17 #include <linux/slab.h>
18 #include <linux/spi/spi.h>
19
20 struct x9250_cfg {
21         const char *name;
22         int kohms;
23 };
24
25 struct x9250 {
26         struct spi_device *spi;
27         const struct x9250_cfg *cfg;
28         struct gpio_desc *wp_gpio;
29 };
30
31 #define X9250_ID                0x50
32 #define X9250_CMD_RD_WCR(_p)    (0x90 | (_p))
33 #define X9250_CMD_WR_WCR(_p)    (0xa0 | (_p))
34
35 static int x9250_write8(struct x9250 *x9250, u8 cmd, u8 val)
36 {
37         u8 txbuf[3];
38
39         txbuf[0] = X9250_ID;
40         txbuf[1] = cmd;
41         txbuf[2] = val;
42
43         return spi_write_then_read(x9250->spi, txbuf, ARRAY_SIZE(txbuf), NULL, 0);
44 }
45
46 static int x9250_read8(struct x9250 *x9250, u8 cmd, u8 *val)
47 {
48         u8 txbuf[2];
49
50         txbuf[0] = X9250_ID;
51         txbuf[1] = cmd;
52
53         return spi_write_then_read(x9250->spi, txbuf, ARRAY_SIZE(txbuf), val, 1);
54 }
55
56 #define X9250_CHANNEL(ch) {                                             \
57         .type = IIO_RESISTANCE,                                         \
58         .indexed = 1,                                                   \
59         .output = 1,                                                    \
60         .channel = (ch),                                                \
61         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),                   \
62         .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),           \
63         .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_RAW),   \
64 }
65
66 static const struct iio_chan_spec x9250_channels[] = {
67         X9250_CHANNEL(0),
68         X9250_CHANNEL(1),
69         X9250_CHANNEL(2),
70         X9250_CHANNEL(3),
71 };
72
73 static int x9250_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
74                           int *val, int *val2, long mask)
75 {
76         struct x9250 *x9250 = iio_priv(indio_dev);
77         int ch = chan->channel;
78         int ret;
79         u8 v;
80
81         switch (mask) {
82         case IIO_CHAN_INFO_RAW:
83                 ret = x9250_read8(x9250, X9250_CMD_RD_WCR(ch), &v);
84                 if (ret)
85                         return ret;
86                 *val = v;
87                 return IIO_VAL_INT;
88
89         case IIO_CHAN_INFO_SCALE:
90                 *val = 1000 * x9250->cfg->kohms;
91                 *val2 = U8_MAX;
92                 return IIO_VAL_FRACTIONAL;
93         }
94
95         return -EINVAL;
96 }
97
98 static int x9250_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
99                             const int **vals, int *type, int *length, long mask)
100 {
101         static const int range[] = {0, 1, 255}; /* min, step, max */
102
103         switch (mask) {
104         case IIO_CHAN_INFO_RAW:
105                 *length = ARRAY_SIZE(range);
106                 *vals = range;
107                 *type = IIO_VAL_INT;
108                 return IIO_AVAIL_RANGE;
109         }
110
111         return -EINVAL;
112 }
113
114 static int x9250_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
115                            int val, int val2, long mask)
116 {
117         struct x9250 *x9250 = iio_priv(indio_dev);
118         int ch = chan->channel;
119         int ret;
120
121         if (mask != IIO_CHAN_INFO_RAW)
122                 return -EINVAL;
123
124         if (val > U8_MAX || val < 0)
125                 return -EINVAL;
126
127         gpiod_set_value_cansleep(x9250->wp_gpio, 0);
128         ret = x9250_write8(x9250, X9250_CMD_WR_WCR(ch), val);
129         gpiod_set_value_cansleep(x9250->wp_gpio, 1);
130
131         return ret;
132 }
133
134 static const struct iio_info x9250_info = {
135         .read_raw = x9250_read_raw,
136         .read_avail = x9250_read_avail,
137         .write_raw = x9250_write_raw,
138 };
139
140 enum x9250_type {
141         X9250T,
142         X9250U,
143 };
144
145 static const struct x9250_cfg x9250_cfg[] = {
146         [X9250T] = { .name = "x9250t", .kohms =  100, },
147         [X9250U] = { .name = "x9250u", .kohms =  50, },
148 };
149
150 static const char *const x9250_regulator_names[] = {
151         "vcc",
152         "avp",
153         "avn",
154 };
155
156 static int x9250_probe(struct spi_device *spi)
157 {
158         struct iio_dev *indio_dev;
159         struct x9250 *x9250;
160         int ret;
161
162         ret = devm_regulator_bulk_get_enable(&spi->dev, ARRAY_SIZE(x9250_regulator_names),
163                                              x9250_regulator_names);
164         if (ret)
165                 return dev_err_probe(&spi->dev, ret, "Failed to get regulators\n");
166
167         /*
168          * The x9250 needs a 5ms maximum delay after the power-supplies are set
169          * before performing the first write (1ms for the first read).
170          */
171         usleep_range(5000, 6000);
172
173         indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*x9250));
174         if (!indio_dev)
175                 return -ENOMEM;
176
177         x9250 = iio_priv(indio_dev);
178         x9250->spi = spi;
179         x9250->cfg = spi_get_device_match_data(spi);
180         x9250->wp_gpio = devm_gpiod_get_optional(&spi->dev, "wp", GPIOD_OUT_LOW);
181         if (IS_ERR(x9250->wp_gpio))
182                 return dev_err_probe(&spi->dev, PTR_ERR(x9250->wp_gpio),
183                                      "failed to get wp gpio\n");
184
185         indio_dev->info = &x9250_info;
186         indio_dev->channels = x9250_channels;
187         indio_dev->num_channels = ARRAY_SIZE(x9250_channels);
188         indio_dev->name = x9250->cfg->name;
189
190         return devm_iio_device_register(&spi->dev, indio_dev);
191 }
192
193 static const struct of_device_id x9250_of_match[] = {
194         { .compatible = "renesas,x9250t", .data = &x9250_cfg[X9250T]},
195         { .compatible = "renesas,x9250u", .data = &x9250_cfg[X9250U]},
196         { }
197 };
198 MODULE_DEVICE_TABLE(of, x9250_of_match);
199
200 static const struct spi_device_id x9250_id_table[] = {
201         { "x9250t", (kernel_ulong_t)&x9250_cfg[X9250T] },
202         { "x9250u", (kernel_ulong_t)&x9250_cfg[X9250U] },
203         { }
204 };
205 MODULE_DEVICE_TABLE(spi, x9250_id_table);
206
207 static struct spi_driver x9250_spi_driver = {
208         .driver  = {
209                 .name = "x9250",
210                 .of_match_table = x9250_of_match,
211         },
212         .id_table = x9250_id_table,
213         .probe  = x9250_probe,
214 };
215
216 module_spi_driver(x9250_spi_driver);
217
218 MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
219 MODULE_DESCRIPTION("X9250 ALSA SoC driver");
220 MODULE_LICENSE("GPL");