File Index
Files and directories
Sign in
FILE

da9150-gpadc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/adc/da9150-gpadc.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * DA9150 GPADC Driver
  4 *
  5 * Copyright (c) 2014 Dialog Semiconductor
  6 *
  7 * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
  8 */
  9
 10#include <linux/kernel.h>
 11#include <linux/slab.h>
 12#include <linux/module.h>
 13#include <linux/platform_device.h>
 14#include <linux/interrupt.h>
 15#include <linux/mutex.h>
 16#include <linux/completion.h>
 17#include <linux/iio/iio.h>
 18#include <linux/iio/machine.h>
 19#include <linux/iio/driver.h>
 20#include <linux/mfd/da9150/core.h>
 21#include <linux/mfd/da9150/registers.h>
 22
 23/* Channels */
 24enum da9150_gpadc_hw_channel {
 25	DA9150_GPADC_HW_CHAN_GPIOA_2V = 0,
 26	DA9150_GPADC_HW_CHAN_GPIOA_2V_,
 27	DA9150_GPADC_HW_CHAN_GPIOB_2V,
 28	DA9150_GPADC_HW_CHAN_GPIOB_2V_,
 29	DA9150_GPADC_HW_CHAN_GPIOC_2V,
 30	DA9150_GPADC_HW_CHAN_GPIOC_2V_,
 31	DA9150_GPADC_HW_CHAN_GPIOD_2V,
 32	DA9150_GPADC_HW_CHAN_GPIOD_2V_,
 33	DA9150_GPADC_HW_CHAN_IBUS_SENSE,
 34	DA9150_GPADC_HW_CHAN_IBUS_SENSE_,
 35	DA9150_GPADC_HW_CHAN_VBUS_DIV,
 36	DA9150_GPADC_HW_CHAN_VBUS_DIV_,
 37	DA9150_GPADC_HW_CHAN_ID,
 38	DA9150_GPADC_HW_CHAN_ID_,
 39	DA9150_GPADC_HW_CHAN_VSYS,
 40	DA9150_GPADC_HW_CHAN_VSYS_,
 41	DA9150_GPADC_HW_CHAN_GPIOA_6V,
 42	DA9150_GPADC_HW_CHAN_GPIOA_6V_,
 43	DA9150_GPADC_HW_CHAN_GPIOB_6V,
 44	DA9150_GPADC_HW_CHAN_GPIOB_6V_,
 45	DA9150_GPADC_HW_CHAN_GPIOC_6V,
 46	DA9150_GPADC_HW_CHAN_GPIOC_6V_,
 47	DA9150_GPADC_HW_CHAN_GPIOD_6V,
 48	DA9150_GPADC_HW_CHAN_GPIOD_6V_,
 49	DA9150_GPADC_HW_CHAN_VBAT,
 50	DA9150_GPADC_HW_CHAN_VBAT_,
 51	DA9150_GPADC_HW_CHAN_TBAT,
 52	DA9150_GPADC_HW_CHAN_TBAT_,
 53	DA9150_GPADC_HW_CHAN_TJUNC_CORE,
 54	DA9150_GPADC_HW_CHAN_TJUNC_CORE_,
 55	DA9150_GPADC_HW_CHAN_TJUNC_OVP,
 56	DA9150_GPADC_HW_CHAN_TJUNC_OVP_,
 57};
 58
 59enum da9150_gpadc_channel {
 60	DA9150_GPADC_CHAN_GPIOA = 0,
 61	DA9150_GPADC_CHAN_GPIOB,
 62	DA9150_GPADC_CHAN_GPIOC,
 63	DA9150_GPADC_CHAN_GPIOD,
 64	DA9150_GPADC_CHAN_IBUS,
 65	DA9150_GPADC_CHAN_VBUS,
 66	DA9150_GPADC_CHAN_VSYS,
 67	DA9150_GPADC_CHAN_VBAT,
 68	DA9150_GPADC_CHAN_TBAT,
 69	DA9150_GPADC_CHAN_TJUNC_CORE,
 70	DA9150_GPADC_CHAN_TJUNC_OVP,
 71};
 72
 73/* Private data */
 74struct da9150_gpadc {
 75	struct da9150 *da9150;
 76	struct device *dev;
 77
 78	struct mutex lock;
 79	struct completion complete;
 80};
 81
 82
 83static irqreturn_t da9150_gpadc_irq(int irq, void *data)
 84{
 85
 86	struct da9150_gpadc *gpadc = data;
 87
 88	complete(&gpadc->complete);
 89
 90	return IRQ_HANDLED;
 91}
 92
 93static int da9150_gpadc_read_adc(struct da9150_gpadc *gpadc, int hw_chan)
 94{
 95	u8 result_regs[2];
 96	int result;
 97
 98	mutex_lock(&gpadc->lock);
 99
100	/* Set channel & enable measurement */
101	da9150_reg_write(gpadc->da9150, DA9150_GPADC_MAN,
102			 (DA9150_GPADC_EN_MASK |
103			  hw_chan << DA9150_GPADC_MUX_SHIFT));
104
105	/* Consume left-over completion from a previous timeout */
106	try_wait_for_completion(&gpadc->complete);
107
108	/* Check for actual completion */
109	wait_for_completion_timeout(&gpadc->complete, msecs_to_jiffies(5));
110
111	/* Read result and status from device */
112	da9150_bulk_read(gpadc->da9150, DA9150_GPADC_RES_A, 2, result_regs);
113
114	mutex_unlock(&gpadc->lock);
115
116	/* Check to make sure device really has completed reading */
117	if (result_regs[1] & DA9150_GPADC_RUN_MASK) {
118		dev_err(gpadc->dev, "Timeout on channel %d of GPADC\n",
119			hw_chan);
120		return -ETIMEDOUT;
121	}
122
123	/* LSBs - 2 bits */
124	result = (result_regs[1] & DA9150_GPADC_RES_L_MASK) >>
125		 DA9150_GPADC_RES_L_SHIFT;
126	/* MSBs - 8 bits */
127	result |= result_regs[0] << DA9150_GPADC_RES_L_BITS;
128
129	return result;
130}
131
132static inline int da9150_gpadc_gpio_6v_voltage_now(int raw_val)
133{
134	/* Convert to mV */
135	return (6 * ((raw_val * 1000) + 500)) / 1024;
136}
137
138static inline int da9150_gpadc_ibus_current_avg(int raw_val)
139{
140	/* Convert to mA */
141	return (4 * ((raw_val * 1000) + 500)) / 2048;
142}
143
144static inline int da9150_gpadc_vbus_21v_voltage_now(int raw_val)
145{
146	/* Convert to mV */
147	return (21 * ((raw_val * 1000) + 500)) / 1024;
148}
149
150static inline int da9150_gpadc_vsys_6v_voltage_now(int raw_val)
151{
152	/* Convert to mV */
153	return (3 * ((raw_val * 1000) + 500)) / 512;
154}
155
156static int da9150_gpadc_read_processed(struct da9150_gpadc *gpadc, int channel,
157				       int hw_chan, int *val)
158{
159	int raw_val;
160
161	raw_val = da9150_gpadc_read_adc(gpadc, hw_chan);
162	if (raw_val < 0)
163		return raw_val;
164
165	switch (channel) {
166	case DA9150_GPADC_CHAN_GPIOA:
167	case DA9150_GPADC_CHAN_GPIOB:
168	case DA9150_GPADC_CHAN_GPIOC:
169	case DA9150_GPADC_CHAN_GPIOD:
170		*val = da9150_gpadc_gpio_6v_voltage_now(raw_val);
171		break;
172	case DA9150_GPADC_CHAN_IBUS:
173		*val = da9150_gpadc_ibus_current_avg(raw_val);
174		break;
175	case DA9150_GPADC_CHAN_VBUS:
176		*val = da9150_gpadc_vbus_21v_voltage_now(raw_val);
177		break;
178	case DA9150_GPADC_CHAN_VSYS:
179		*val = da9150_gpadc_vsys_6v_voltage_now(raw_val);
180		break;
181	default:
182		/* No processing for other channels so return raw value */
183		*val = raw_val;
184		break;
185	}
186
187	return IIO_VAL_INT;
188}
189
190static int da9150_gpadc_read_scale(int channel, int *val, int *val2)
191{
192	switch (channel) {
193	case DA9150_GPADC_CHAN_VBAT:
194		*val = 2932;
195		*val2 = 1000;
196		return IIO_VAL_FRACTIONAL;
197	case DA9150_GPADC_CHAN_TJUNC_CORE:
198	case DA9150_GPADC_CHAN_TJUNC_OVP:
199		*val = 1000000;
200		*val2 = 4420;
201		return IIO_VAL_FRACTIONAL;
202	default:
203		return -EINVAL;
204	}
205}
206
207static int da9150_gpadc_read_offset(int channel, int *val)
208{
209	switch (channel) {
210	case DA9150_GPADC_CHAN_VBAT:
211		*val = 1500000 / 2932;
212		return IIO_VAL_INT;
213	case DA9150_GPADC_CHAN_TJUNC_CORE:
214	case DA9150_GPADC_CHAN_TJUNC_OVP:
215		*val = -144;
216		return IIO_VAL_INT;
217	default:
218		return -EINVAL;
219	}
220}
221
222static int da9150_gpadc_read_raw(struct iio_dev *indio_dev,
223				 struct iio_chan_spec const *chan,
224				 int *val, int *val2, long mask)
225{
226	struct da9150_gpadc *gpadc = iio_priv(indio_dev);
227
228	if ((chan->channel < DA9150_GPADC_CHAN_GPIOA) ||
229	    (chan->channel > DA9150_GPADC_CHAN_TJUNC_OVP))
230		return -EINVAL;
231
232	switch (mask) {
233	case IIO_CHAN_INFO_RAW:
234	case IIO_CHAN_INFO_PROCESSED:
235		return da9150_gpadc_read_processed(gpadc, chan->channel,
236						   chan->address, val);
237	case IIO_CHAN_INFO_SCALE:
238		return da9150_gpadc_read_scale(chan->channel, val, val2);
239	case IIO_CHAN_INFO_OFFSET:
240		return da9150_gpadc_read_offset(chan->channel, val);
241	default:
242		return -EINVAL;
243	}
244}
245
246static const struct iio_info da9150_gpadc_info = {
247	.read_raw = &da9150_gpadc_read_raw,
248};
249
250#define DA9150_GPADC_CHANNEL(_id, _hw_id, _type, chan_info,	\
251			     _ext_name) {			\
252	.type = _type,						\
253	.indexed = 1,						\
254	.channel = DA9150_GPADC_CHAN_##_id,			\
255	.address = DA9150_GPADC_HW_CHAN_##_hw_id,		\
256	.info_mask_separate = chan_info,			\
257	.extend_name = _ext_name,				\
258	.datasheet_name = #_id,					\
259}
260
261#define DA9150_GPADC_CHANNEL_RAW(_id, _hw_id, _type, _ext_name)	\
262	DA9150_GPADC_CHANNEL(_id, _hw_id, _type,		\
263			     BIT(IIO_CHAN_INFO_RAW), _ext_name)
264
265#define DA9150_GPADC_CHANNEL_SCALED(_id, _hw_id, _type, _ext_name)	\
266	DA9150_GPADC_CHANNEL(_id, _hw_id, _type,			\
267			     BIT(IIO_CHAN_INFO_RAW) |			\
268			     BIT(IIO_CHAN_INFO_SCALE) |			\
269			     BIT(IIO_CHAN_INFO_OFFSET),			\
270			     _ext_name)
271
272#define DA9150_GPADC_CHANNEL_PROCESSED(_id, _hw_id, _type, _ext_name)	\
273	DA9150_GPADC_CHANNEL(_id, _hw_id, _type,			\
274			     BIT(IIO_CHAN_INFO_PROCESSED), _ext_name)
275
276/* Supported channels */
277static const struct iio_chan_spec da9150_gpadc_channels[] = {
278	DA9150_GPADC_CHANNEL_PROCESSED(GPIOA, GPIOA_6V, IIO_VOLTAGE, NULL),
279	DA9150_GPADC_CHANNEL_PROCESSED(GPIOB, GPIOB_6V, IIO_VOLTAGE, NULL),
280	DA9150_GPADC_CHANNEL_PROCESSED(GPIOC, GPIOC_6V, IIO_VOLTAGE, NULL),
281	DA9150_GPADC_CHANNEL_PROCESSED(GPIOD, GPIOD_6V, IIO_VOLTAGE, NULL),
282	DA9150_GPADC_CHANNEL_PROCESSED(IBUS, IBUS_SENSE, IIO_CURRENT, "ibus"),
283	DA9150_GPADC_CHANNEL_PROCESSED(VBUS, VBUS_DIV_, IIO_VOLTAGE, "vbus"),
284	DA9150_GPADC_CHANNEL_PROCESSED(VSYS, VSYS, IIO_VOLTAGE, "vsys"),
285	DA9150_GPADC_CHANNEL_SCALED(VBAT, VBAT, IIO_VOLTAGE, "vbat"),
286	DA9150_GPADC_CHANNEL_RAW(TBAT, TBAT, IIO_VOLTAGE, "tbat"),
287	DA9150_GPADC_CHANNEL_SCALED(TJUNC_CORE, TJUNC_CORE, IIO_TEMP,
288				    "tjunc_core"),
289	DA9150_GPADC_CHANNEL_SCALED(TJUNC_OVP, TJUNC_OVP, IIO_TEMP,
290				    "tjunc_ovp"),
291};
292
293/* Default maps used by da9150-charger */
294static const struct iio_map da9150_gpadc_default_maps[] = {
295	IIO_MAP("IBUS", "da9150-charger", "CHAN_IBUS"),
296	IIO_MAP("VBUS", "da9150-charger", "CHAN_VBUS"),
297	IIO_MAP("TJUNC_CORE", "da9150-charger", "CHAN_TJUNC"),
298	IIO_MAP("VBAT", "da9150-charger", "CHAN_VBAT"),
299	{ }
300};
301
302static int da9150_gpadc_probe(struct platform_device *pdev)
303{
304	struct device *dev = &pdev->dev;
305	struct da9150 *da9150 = dev_get_drvdata(dev->parent);
306	struct da9150_gpadc *gpadc;
307	struct iio_dev *indio_dev;
308	int irq, ret;
309
310	indio_dev = devm_iio_device_alloc(dev, sizeof(*gpadc));
311	if (!indio_dev)
312		return -ENOMEM;
313
314	gpadc = iio_priv(indio_dev);
315
316	gpadc->da9150 = da9150;
317	gpadc->dev = dev;
318	mutex_init(&gpadc->lock);
319	init_completion(&gpadc->complete);
320
321	irq = platform_get_irq_byname(pdev, "GPADC");
322	if (irq < 0)
323		return irq;
324
325	ret = devm_request_threaded_irq(dev, irq, NULL, da9150_gpadc_irq,
326					IRQF_ONESHOT, "GPADC", gpadc);
327	if (ret) {
328		dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
329		return ret;
330	}
331
332	ret = devm_iio_map_array_register(&pdev->dev, indio_dev, da9150_gpadc_default_maps);
333	if (ret) {
334		dev_err(dev, "Failed to register IIO maps: %d\n", ret);
335		return ret;
336	}
337
338	indio_dev->name = dev_name(dev);
339	indio_dev->info = &da9150_gpadc_info;
340	indio_dev->modes = INDIO_DIRECT_MODE;
341	indio_dev->channels = da9150_gpadc_channels;
342	indio_dev->num_channels = ARRAY_SIZE(da9150_gpadc_channels);
343
344	return devm_iio_device_register(&pdev->dev, indio_dev);
345}
346
347static struct platform_driver da9150_gpadc_driver = {
348	.driver = {
349		.name = "da9150-gpadc",
350	},
351	.probe = da9150_gpadc_probe,
352};
353
354module_platform_driver(da9150_gpadc_driver);
355
356MODULE_DESCRIPTION("GPADC Driver for DA9150");
357MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
358MODULE_LICENSE("GPL");
~/ Read-only file preview.