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
20struct x9250_cfg {
21 const char *name;
22 int kohms;
23};
24
25struct 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
35static 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(spi: x9250->spi, txbuf, ARRAY_SIZE(txbuf), NULL, n_rx: 0);
44}
45
46static 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(spi: x9250->spi, txbuf, ARRAY_SIZE(txbuf), rxbuf: val, n_rx: 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
66static 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
73static 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), val: &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
98static 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
114static 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(desc: x9250->wp_gpio, value: 0);
128 ret = x9250_write8(x9250, X9250_CMD_WR_WCR(ch), val);
129 gpiod_set_value_cansleep(desc: x9250->wp_gpio, value: 1);
130
131 return ret;
132}
133
134static 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
140enum x9250_type {
141 X9250T,
142 X9250U,
143};
144
145static const struct x9250_cfg x9250_cfg[] = {
146 [X9250T] = { .name = "x9250t", .kohms = 100, },
147 [X9250U] = { .name = "x9250u", .kohms = 50, },
148};
149
150static const char *const x9250_regulator_names[] = {
151 "vcc",
152 "avp",
153 "avn",
154};
155
156static 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(dev: &spi->dev, ARRAY_SIZE(x9250_regulator_names),
163 id: x9250_regulator_names);
164 if (ret)
165 return dev_err_probe(dev: &spi->dev, err: ret, fmt: "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(min: 5000, max: 6000);
172
173 indio_dev = devm_iio_device_alloc(parent: &spi->dev, sizeof_priv: 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(sdev: spi);
180 x9250->wp_gpio = devm_gpiod_get_optional(dev: &spi->dev, con_id: "wp", flags: GPIOD_OUT_LOW);
181 if (IS_ERR(ptr: x9250->wp_gpio))
182 return dev_err_probe(dev: &spi->dev, err: PTR_ERR(ptr: x9250->wp_gpio),
183 fmt: "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
193static 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};
198MODULE_DEVICE_TABLE(of, x9250_of_match);
199
200static 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};
205MODULE_DEVICE_TABLE(spi, x9250_id_table);
206
207static 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
216module_spi_driver(x9250_spi_driver);
217
218MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
219MODULE_DESCRIPTION("X9250 ALSA SoC driver");
220MODULE_LICENSE("GPL");
221

source code of linux/drivers/iio/potentiometer/x9250.c