brintos

brintos / linux-shallow public Read only

0
0
Text · 31.7 KiB · 203cbbc Raw
1185 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * palmas-adc.c -- TI PALMAS GPADC.4 *5 * Copyright (c) 2013, NVIDIA Corporation. All rights reserved.6 *7 * Author: Pradeep Goudagunta <pgoudagunta@nvidia.com>8 */9 10#include <linux/module.h>11#include <linux/err.h>12#include <linux/irq.h>13#include <linux/interrupt.h>14#include <linux/platform_device.h>15#include <linux/slab.h>16#include <linux/delay.h>17#include <linux/pm.h>18#include <linux/mfd/palmas.h>19#include <linux/completion.h>20#include <linux/of.h>21#include <linux/iio/events.h>22#include <linux/iio/iio.h>23#include <linux/iio/machine.h>24#include <linux/iio/driver.h>25 26#define MOD_NAME "palmas-gpadc"27#define PALMAS_ADC_CONVERSION_TIMEOUT	(msecs_to_jiffies(5000))28#define PALMAS_TO_BE_CALCULATED 029#define PALMAS_GPADC_TRIMINVALID	-130 31struct palmas_gpadc_info {32/* calibration codes and regs */33	int x1;	/* lower ideal code */34	int x2;	/* higher ideal code */35	int v1;	/* expected lower volt reading */36	int v2;	/* expected higher volt reading */37	u8 trim1_reg;	/* register number for lower trim */38	u8 trim2_reg;	/* register number for upper trim */39	int gain;	/* calculated from above (after reading trim regs) */40	int offset;	/* calculated from above (after reading trim regs) */41	int gain_error;	/* calculated from above (after reading trim regs) */42	bool is_uncalibrated;	/* if channel has calibration data */43};44 45#define PALMAS_ADC_INFO(_chan, _x1, _x2, _v1, _v2, _t1, _t2, _is_uncalibrated) \46	[PALMAS_ADC_CH_##_chan] = { \47		.x1 = _x1, \48		.x2 = _x2, \49		.v1 = _v1, \50		.v2 = _v2, \51		.gain = PALMAS_TO_BE_CALCULATED, \52		.offset = PALMAS_TO_BE_CALCULATED, \53		.gain_error = PALMAS_TO_BE_CALCULATED, \54		.trim1_reg = PALMAS_GPADC_TRIM##_t1, \55		.trim2_reg = PALMAS_GPADC_TRIM##_t2,  \56		.is_uncalibrated = _is_uncalibrated \57	}58 59static struct palmas_gpadc_info palmas_gpadc_info[] = {60	PALMAS_ADC_INFO(IN0, 2064, 3112, 630, 950, 1, 2, false),61	PALMAS_ADC_INFO(IN1, 2064, 3112, 630, 950, 1, 2, false),62	PALMAS_ADC_INFO(IN2, 2064, 3112, 1260, 1900, 3, 4, false),63	PALMAS_ADC_INFO(IN3, 2064, 3112, 630, 950, 1, 2, false),64	PALMAS_ADC_INFO(IN4, 2064, 3112, 630, 950, 1, 2, false),65	PALMAS_ADC_INFO(IN5, 2064, 3112, 630, 950, 1, 2, false),66	PALMAS_ADC_INFO(IN6, 2064, 3112, 2520, 3800, 5, 6, false),67	PALMAS_ADC_INFO(IN7, 2064, 3112, 2520, 3800, 7, 8, false),68	PALMAS_ADC_INFO(IN8, 2064, 3112, 3150, 4750, 9, 10, false),69	PALMAS_ADC_INFO(IN9, 2064, 3112, 5670, 8550, 11, 12, false),70	PALMAS_ADC_INFO(IN10, 2064, 3112, 3465, 5225, 13, 14, false),71	PALMAS_ADC_INFO(IN11, 0, 0, 0, 0, INVALID, INVALID, true),72	PALMAS_ADC_INFO(IN12, 0, 0, 0, 0, INVALID, INVALID, true),73	PALMAS_ADC_INFO(IN13, 0, 0, 0, 0, INVALID, INVALID, true),74	PALMAS_ADC_INFO(IN14, 2064, 3112, 3645, 5225, 15, 16, false),75	PALMAS_ADC_INFO(IN15, 0, 0, 0, 0, INVALID, INVALID, true),76};77 78struct palmas_adc_event {79	bool enabled;80	int channel;81	enum iio_event_direction direction;82};83 84struct palmas_gpadc_thresholds {85	int high;86	int low;87};88 89/*90 * struct palmas_gpadc - the palmas_gpadc structure91 * @ch0_current:	channel 0 current source setting92 *			0: 0 uA93 *			1: 5 uA94 *			2: 15 uA95 *			3: 20 uA96 * @ch3_current:	channel 0 current source setting97 *			0: 0 uA98 *			1: 10 uA99 *			2: 400 uA100 *			3: 800 uA101 * @extended_delay:	enable the gpadc extended delay mode102 * @auto_conversion_period:	define the auto_conversion_period103 * @lock:	Lock to protect the device state during a potential concurrent104 *		read access from userspace. Reading a raw value requires a sequence105 *		of register writes, then a wait for a completion callback,106 *		and finally a register read, during which userspace could issue107 *		another read request. This lock protects a read access from108 *		ocurring before another one has finished.109 *110 * This is the palmas_gpadc structure to store run-time information111 * and pointers for this driver instance.112 */113struct palmas_gpadc {114	struct device			*dev;115	struct palmas			*palmas;116	u8				ch0_current;117	u8				ch3_current;118	bool				extended_delay;119	int				irq;120	int				irq_auto_0;121	int				irq_auto_1;122	struct palmas_gpadc_info	*adc_info;123	struct completion		conv_completion;124	struct palmas_adc_event		event0;125	struct palmas_adc_event		event1;126	struct palmas_gpadc_thresholds	thresholds[PALMAS_ADC_CH_MAX];127	int				auto_conversion_period;128	struct mutex			lock;129};130 131static struct palmas_adc_event *palmas_gpadc_get_event(struct palmas_gpadc *adc,132						       int adc_chan,133						       enum iio_event_direction dir)134{135	if (adc_chan == adc->event0.channel && dir == adc->event0.direction)136		return &adc->event0;137 138	if (adc_chan == adc->event1.channel && dir == adc->event1.direction)139		return &adc->event1;140 141	return NULL;142}143 144static bool palmas_gpadc_channel_is_freerunning(struct palmas_gpadc *adc,145						int adc_chan)146{147	return palmas_gpadc_get_event(adc, adc_chan, IIO_EV_DIR_RISING) ||148		palmas_gpadc_get_event(adc, adc_chan, IIO_EV_DIR_FALLING);149}150 151/*152 * GPADC lock issue in AUTO mode.153 * Impact: In AUTO mode, GPADC conversion can be locked after disabling AUTO154 *	   mode feature.155 * Details:156 *	When the AUTO mode is the only conversion mode enabled, if the AUTO157 *	mode feature is disabled with bit GPADC_AUTO_CTRL.  AUTO_CONV1_EN = 0158 *	or bit GPADC_AUTO_CTRL.  AUTO_CONV0_EN = 0 during a conversion, the159 *	conversion mechanism can be seen as locked meaning that all following160 *	conversion will give 0 as a result.  Bit GPADC_STATUS.GPADC_AVAILABLE161 *	will stay at 0 meaning that GPADC is busy.  An RT conversion can unlock162 *	the GPADC.163 *164 * Workaround(s):165 *	To avoid the lock mechanism, the workaround to follow before any stop166 *	conversion request is:167 *	Force the GPADC state machine to be ON by using the GPADC_CTRL1.168 *		GPADC_FORCE bit = 1169 *	Shutdown the GPADC AUTO conversion using170 *		GPADC_AUTO_CTRL.SHUTDOWN_CONV[01] = 0.171 *	After 100us, force the GPADC state machine to be OFF by using the172 *		GPADC_CTRL1.  GPADC_FORCE bit = 0173 */174 175static int palmas_disable_auto_conversion(struct palmas_gpadc *adc)176{177	int ret;178 179	ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE,180			PALMAS_GPADC_CTRL1,181			PALMAS_GPADC_CTRL1_GPADC_FORCE,182			PALMAS_GPADC_CTRL1_GPADC_FORCE);183	if (ret < 0) {184		dev_err(adc->dev, "GPADC_CTRL1 update failed: %d\n", ret);185		return ret;186	}187 188	ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE,189			PALMAS_GPADC_AUTO_CTRL,190			PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV1 |191			PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV0,192			0);193	if (ret < 0) {194		dev_err(adc->dev, "AUTO_CTRL update failed: %d\n", ret);195		return ret;196	}197 198	udelay(100);199 200	ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE,201			PALMAS_GPADC_CTRL1,202			PALMAS_GPADC_CTRL1_GPADC_FORCE, 0);203	if (ret < 0)204		dev_err(adc->dev, "GPADC_CTRL1 update failed: %d\n", ret);205 206	return ret;207}208 209static irqreturn_t palmas_gpadc_irq(int irq, void *data)210{211	struct palmas_gpadc *adc = data;212 213	complete(&adc->conv_completion);214 215	return IRQ_HANDLED;216}217 218static irqreturn_t palmas_gpadc_irq_auto(int irq, void *data)219{220	struct iio_dev *indio_dev = data;221	struct palmas_gpadc *adc = iio_priv(indio_dev);222	struct palmas_adc_event *ev;223 224	dev_dbg(adc->dev, "Threshold interrupt %d occurs\n", irq);225	palmas_disable_auto_conversion(adc);226 227	ev = (irq == adc->irq_auto_0) ? &adc->event0 : &adc->event1;228	if (ev->channel != -1) {229		enum iio_event_direction dir;230		u64 code;231 232		dir = ev->direction;233		code = IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, ev->channel,234					    IIO_EV_TYPE_THRESH, dir);235		iio_push_event(indio_dev, code, iio_get_time_ns(indio_dev));236	}237 238	return IRQ_HANDLED;239}240 241static int palmas_gpadc_start_mask_interrupt(struct palmas_gpadc *adc,242						bool mask)243{244	int ret;245 246	if (!mask)247		ret = palmas_update_bits(adc->palmas, PALMAS_INTERRUPT_BASE,248					PALMAS_INT3_MASK,249					PALMAS_INT3_MASK_GPADC_EOC_SW, 0);250	else251		ret = palmas_update_bits(adc->palmas, PALMAS_INTERRUPT_BASE,252					PALMAS_INT3_MASK,253					PALMAS_INT3_MASK_GPADC_EOC_SW,254					PALMAS_INT3_MASK_GPADC_EOC_SW);255	if (ret < 0)256		dev_err(adc->dev, "GPADC INT MASK update failed: %d\n", ret);257 258	return ret;259}260 261static int palmas_gpadc_enable(struct palmas_gpadc *adc, int adc_chan,262			       int enable)263{264	unsigned int mask, val;265	int ret;266 267	if (enable) {268		val = (adc->extended_delay269			<< PALMAS_GPADC_RT_CTRL_EXTEND_DELAY_SHIFT);270		ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE,271					PALMAS_GPADC_RT_CTRL,272					PALMAS_GPADC_RT_CTRL_EXTEND_DELAY, val);273		if (ret < 0) {274			dev_err(adc->dev, "RT_CTRL update failed: %d\n", ret);275			return ret;276		}277 278		mask = (PALMAS_GPADC_CTRL1_CURRENT_SRC_CH0_MASK |279			PALMAS_GPADC_CTRL1_CURRENT_SRC_CH3_MASK |280			PALMAS_GPADC_CTRL1_GPADC_FORCE);281		val = (adc->ch0_current282			<< PALMAS_GPADC_CTRL1_CURRENT_SRC_CH0_SHIFT);283		val |= (adc->ch3_current284			<< PALMAS_GPADC_CTRL1_CURRENT_SRC_CH3_SHIFT);285		val |= PALMAS_GPADC_CTRL1_GPADC_FORCE;286		ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE,287				PALMAS_GPADC_CTRL1, mask, val);288		if (ret < 0) {289			dev_err(adc->dev,290				"Failed to update current setting: %d\n", ret);291			return ret;292		}293 294		mask = (PALMAS_GPADC_SW_SELECT_SW_CONV0_SEL_MASK |295			PALMAS_GPADC_SW_SELECT_SW_CONV_EN);296		val = (adc_chan | PALMAS_GPADC_SW_SELECT_SW_CONV_EN);297		ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE,298				PALMAS_GPADC_SW_SELECT, mask, val);299		if (ret < 0) {300			dev_err(adc->dev, "SW_SELECT update failed: %d\n", ret);301			return ret;302		}303	} else {304		ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE,305				PALMAS_GPADC_SW_SELECT, 0);306		if (ret < 0)307			dev_err(adc->dev, "SW_SELECT write failed: %d\n", ret);308 309		ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE,310				PALMAS_GPADC_CTRL1,311				PALMAS_GPADC_CTRL1_GPADC_FORCE, 0);312		if (ret < 0) {313			dev_err(adc->dev, "CTRL1 update failed: %d\n", ret);314			return ret;315		}316	}317 318	return ret;319}320 321static int palmas_gpadc_read_prepare(struct palmas_gpadc *adc, int adc_chan)322{323	int ret;324 325	if (palmas_gpadc_channel_is_freerunning(adc, adc_chan))326		return 0; /* ADC already running */327 328	ret = palmas_gpadc_enable(adc, adc_chan, true);329	if (ret < 0)330		return ret;331 332	return palmas_gpadc_start_mask_interrupt(adc, 0);333}334 335static void palmas_gpadc_read_done(struct palmas_gpadc *adc, int adc_chan)336{337	palmas_gpadc_start_mask_interrupt(adc, 1);338	palmas_gpadc_enable(adc, adc_chan, false);339}340 341static int palmas_gpadc_calibrate(struct palmas_gpadc *adc, int adc_chan)342{343	int k;344	int d1;345	int d2;346	int ret;347	int gain;348	int x1 =  adc->adc_info[adc_chan].x1;349	int x2 =  adc->adc_info[adc_chan].x2;350	int v1 = adc->adc_info[adc_chan].v1;351	int v2 = adc->adc_info[adc_chan].v2;352 353	ret = palmas_read(adc->palmas, PALMAS_TRIM_GPADC_BASE,354				adc->adc_info[adc_chan].trim1_reg, &d1);355	if (ret < 0) {356		dev_err(adc->dev, "TRIM read failed: %d\n", ret);357		goto scrub;358	}359 360	ret = palmas_read(adc->palmas, PALMAS_TRIM_GPADC_BASE,361				adc->adc_info[adc_chan].trim2_reg, &d2);362	if (ret < 0) {363		dev_err(adc->dev, "TRIM read failed: %d\n", ret);364		goto scrub;365	}366 367	/* gain error calculation */368	k = (1000 + (1000 * (d2 - d1)) / (x2 - x1));369 370	/* gain calculation */371	gain = ((v2 - v1) * 1000) / (x2 - x1);372 373	adc->adc_info[adc_chan].gain_error = k;374	adc->adc_info[adc_chan].gain = gain;375	/* offset Calculation */376	adc->adc_info[adc_chan].offset = (d1 * 1000) - ((k - 1000) * x1);377 378scrub:379	return ret;380}381 382static int palmas_gpadc_start_conversion(struct palmas_gpadc *adc, int adc_chan)383{384	unsigned int val;385	int ret;386 387	if (palmas_gpadc_channel_is_freerunning(adc, adc_chan)) {388		int event = (adc_chan == adc->event0.channel) ? 0 : 1;389		unsigned int reg = (event == 0) ?390			PALMAS_GPADC_AUTO_CONV0_LSB :391			PALMAS_GPADC_AUTO_CONV1_LSB;392 393		ret = palmas_bulk_read(adc->palmas, PALMAS_GPADC_BASE,394					reg, &val, 2);395		if (ret < 0) {396			dev_err(adc->dev, "AUTO_CONV%x_LSB read failed: %d\n",397				event, ret);398			return ret;399		}400	} else {401		init_completion(&adc->conv_completion);402		ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE,403					PALMAS_GPADC_SW_SELECT,404					PALMAS_GPADC_SW_SELECT_SW_START_CONV0,405					PALMAS_GPADC_SW_SELECT_SW_START_CONV0);406		if (ret < 0) {407			dev_err(adc->dev, "SELECT_SW_START write failed: %d\n", ret);408			return ret;409		}410 411		ret = wait_for_completion_timeout(&adc->conv_completion,412					PALMAS_ADC_CONVERSION_TIMEOUT);413		if (ret == 0) {414			dev_err(adc->dev, "conversion not completed\n");415			return -ETIMEDOUT;416		}417 418		ret = palmas_bulk_read(adc->palmas, PALMAS_GPADC_BASE,419					PALMAS_GPADC_SW_CONV0_LSB, &val, 2);420		if (ret < 0) {421			dev_err(adc->dev, "SW_CONV0_LSB read failed: %d\n", ret);422			return ret;423		}424	}425 426	ret = val & 0xFFF;427 428	return ret;429}430 431static int palmas_gpadc_get_calibrated_code(struct palmas_gpadc *adc,432						int adc_chan, int val)433{434	if (!adc->adc_info[adc_chan].is_uncalibrated)435		val  = (val*1000 - adc->adc_info[adc_chan].offset) /436					adc->adc_info[adc_chan].gain_error;437 438	if (val < 0) {439		if (val < -10)440			dev_err(adc->dev, "Mismatch with calibration var = %d\n", val);441		return 0;442	}443 444	val = (val * adc->adc_info[adc_chan].gain) / 1000;445 446	return val;447}448 449/*450 * The high and low threshold values are calculated based on the advice given451 * in TI Application Report SLIA087A, "Guide to Using the GPADC in PS65903x,452 * TPS65917-Q1, TPS65919-Q1, and TPS65916 Devices". This document recommend453 * taking ADC tolerances into account and is based on the device integral non-454 * linearity (INL), offset error and gain error:455 *456 *   raw high threshold = (ideal threshold + INL) * gain error + offset error457 *458 * The gain error include both gain error, as specified in the datasheet, and459 * the gain error drift. These paramenters vary depending on device and whether460 * the channel is calibrated (trimmed) or not.461 */462static int palmas_gpadc_threshold_with_tolerance(int val, const int INL,463						 const int gain_error,464						 const int offset_error)465{466	val = ((val + INL) * (1000 + gain_error)) / 1000 + offset_error;467 468	return clamp(val, 0, 0xFFF);469}470 471/*472 * The values below are taken from the datasheet of TWL6035, TWL6037.473 * todo: get max INL, gain error, and offset error from OF.474 */475static int palmas_gpadc_get_high_threshold_raw(struct palmas_gpadc *adc,476					       struct palmas_adc_event *ev)477{478	const int adc_chan = ev->channel;479	int val = adc->thresholds[adc_chan].high;480	/* integral nonlinearity, measured in LSB */481	const int max_INL = 2;482	/* measured in LSB */483	int max_offset_error;484	/* 0.2% when calibrated */485	int max_gain_error = 2;486 487	val = (val * 1000) / adc->adc_info[adc_chan].gain;488 489	if (adc->adc_info[adc_chan].is_uncalibrated) {490		/* 2% worse */491		max_gain_error += 20;492		max_offset_error = 36;493	} else {494		val = (val * adc->adc_info[adc_chan].gain_error +495		       adc->adc_info[adc_chan].offset) /496			1000;497		max_offset_error = 2;498	}499 500	return palmas_gpadc_threshold_with_tolerance(val,501						     max_INL,502						     max_gain_error,503						     max_offset_error);504}505 506/*507 * The values below are taken from the datasheet of TWL6035, TWL6037.508 * todo: get min INL, gain error, and offset error from OF.509 */510static int palmas_gpadc_get_low_threshold_raw(struct palmas_gpadc *adc,511					      struct palmas_adc_event *ev)512{513	const int adc_chan = ev->channel;514	int val = adc->thresholds[adc_chan].low;515	/* integral nonlinearity, measured in LSB */516	const int min_INL = -2;517	/* measured in LSB */518	int min_offset_error;519	/* -0.6% when calibrated */520	int min_gain_error = -6;521 522	val = (val * 1000) / adc->adc_info[adc_chan].gain;523 524        if (adc->adc_info[adc_chan].is_uncalibrated) {525		/* 2% worse */526		min_gain_error -= 20;527		min_offset_error = -36;528        } else {529		val = (val * adc->adc_info[adc_chan].gain_error -530		       adc->adc_info[adc_chan].offset) /531			1000;532		min_offset_error = -2;533        }534 535	return palmas_gpadc_threshold_with_tolerance(val,536						     min_INL,537						     min_gain_error,538						     min_offset_error);539}540 541static int palmas_gpadc_read_raw(struct iio_dev *indio_dev,542	struct iio_chan_spec const *chan, int *val, int *val2, long mask)543{544	struct  palmas_gpadc *adc = iio_priv(indio_dev);545	int adc_chan = chan->channel;546	int ret = 0;547 548	if (adc_chan >= PALMAS_ADC_CH_MAX)549		return -EINVAL;550 551	mutex_lock(&adc->lock);552 553	switch (mask) {554	case IIO_CHAN_INFO_RAW:555	case IIO_CHAN_INFO_PROCESSED:556		ret = palmas_gpadc_read_prepare(adc, adc_chan);557		if (ret < 0)558			goto out;559 560		ret = palmas_gpadc_start_conversion(adc, adc_chan);561		if (ret < 0) {562			dev_err(adc->dev,563			"ADC start conversion failed\n");564			goto out;565		}566 567		if (mask == IIO_CHAN_INFO_PROCESSED)568			ret = palmas_gpadc_get_calibrated_code(569							adc, adc_chan, ret);570 571		*val = ret;572 573		ret = IIO_VAL_INT;574		goto out;575	}576 577	mutex_unlock(&adc->lock);578	return ret;579 580out:581	palmas_gpadc_read_done(adc, adc_chan);582	mutex_unlock(&adc->lock);583 584	return ret;585}586 587static int palmas_gpadc_read_event_config(struct iio_dev *indio_dev,588					  const struct iio_chan_spec *chan,589					  enum iio_event_type type,590					  enum iio_event_direction dir)591{592	struct palmas_gpadc *adc = iio_priv(indio_dev);593	int adc_chan = chan->channel;594	int ret = 0;595 596	if (adc_chan >= PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH)597		return -EINVAL;598 599	mutex_lock(&adc->lock);600 601	if (palmas_gpadc_get_event(adc, adc_chan, dir))602		ret = 1;603 604	mutex_unlock(&adc->lock);605 606	return ret;607}608 609static int palmas_adc_configure_events(struct palmas_gpadc *adc);610static int palmas_adc_reset_events(struct palmas_gpadc *adc);611 612static int palmas_gpadc_reconfigure_event_channels(struct palmas_gpadc *adc)613{614	return (adc->event0.enabled || adc->event1.enabled) ?615		palmas_adc_configure_events(adc) :616		palmas_adc_reset_events(adc);617}618 619static int palmas_gpadc_enable_event_config(struct palmas_gpadc *adc,620					    const struct iio_chan_spec *chan,621					    enum iio_event_direction dir)622{623	struct palmas_adc_event *ev;624	int adc_chan = chan->channel;625 626	if (palmas_gpadc_get_event(adc, adc_chan, dir))627		/* already enabled */628		return 0;629 630	if (adc->event0.channel == -1) {631		ev = &adc->event0;632	} else if (adc->event1.channel == -1) {633		/* event0 has to be the lowest channel */634		if (adc_chan < adc->event0.channel) {635			adc->event1 = adc->event0;636			ev = &adc->event0;637		} else {638			ev = &adc->event1;639		}640	} else { /* both AUTO channels already in use */641		dev_warn(adc->dev, "event0 - %d, event1 - %d\n",642			 adc->event0.channel, adc->event1.channel);643		return -EBUSY;644	}645 646	ev->enabled = true;647	ev->channel = adc_chan;648	ev->direction = dir;649 650	return palmas_gpadc_reconfigure_event_channels(adc);651}652 653static int palmas_gpadc_disable_event_config(struct palmas_gpadc *adc,654					     const struct iio_chan_spec *chan,655					     enum iio_event_direction dir)656{657	int adc_chan = chan->channel;658	struct palmas_adc_event *ev = palmas_gpadc_get_event(adc, adc_chan, dir);659 660	if (!ev)661		return 0;662 663	if (ev == &adc->event0) {664		adc->event0 = adc->event1;665		ev = &adc->event1;666	}667 668	ev->enabled = false;669	ev->channel = -1;670	ev->direction = IIO_EV_DIR_NONE;671 672	return palmas_gpadc_reconfigure_event_channels(adc);673}674 675static int palmas_gpadc_write_event_config(struct iio_dev *indio_dev,676					   const struct iio_chan_spec *chan,677					   enum iio_event_type type,678					   enum iio_event_direction dir,679					   int state)680{681	struct palmas_gpadc *adc = iio_priv(indio_dev);682	int adc_chan = chan->channel;683	int ret;684 685	if (adc_chan >= PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH)686		return -EINVAL;687 688	mutex_lock(&adc->lock);689 690	if (state)691		ret = palmas_gpadc_enable_event_config(adc, chan, dir);692	else693		ret = palmas_gpadc_disable_event_config(adc, chan, dir);694 695	mutex_unlock(&adc->lock);696 697	return ret;698}699 700static int palmas_gpadc_read_event_value(struct iio_dev *indio_dev,701					 const struct iio_chan_spec *chan,702					 enum iio_event_type type,703					 enum iio_event_direction dir,704					 enum iio_event_info info,705					 int *val, int *val2)706{707	struct palmas_gpadc *adc = iio_priv(indio_dev);708	int adc_chan = chan->channel;709	int ret;710 711	if (adc_chan >= PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH)712		return -EINVAL;713 714	mutex_lock(&adc->lock);715 716	switch (info) {717	case IIO_EV_INFO_VALUE:718		*val = (dir == IIO_EV_DIR_RISING) ?719			adc->thresholds[adc_chan].high :720			adc->thresholds[adc_chan].low;721		ret = IIO_VAL_INT;722		break;723	default:724		ret = -EINVAL;725		break;726	}727 728	mutex_unlock(&adc->lock);729 730	return ret;731}732 733static int palmas_gpadc_write_event_value(struct iio_dev *indio_dev,734					  const struct iio_chan_spec *chan,735					  enum iio_event_type type,736					  enum iio_event_direction dir,737					  enum iio_event_info info,738					  int val, int val2)739{740	struct palmas_gpadc *adc = iio_priv(indio_dev);741	int adc_chan = chan->channel;742	int old;743	int ret;744 745	if (adc_chan >= PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH)746		return -EINVAL;747 748	mutex_lock(&adc->lock);749	switch (info) {750	case IIO_EV_INFO_VALUE:751		if (val < 0 || val > 0xFFF) {752			ret = -EINVAL;753			goto out_unlock;754		}755		if (dir == IIO_EV_DIR_RISING) {756			old = adc->thresholds[adc_chan].high;757			adc->thresholds[adc_chan].high = val;758		} else {759			old = adc->thresholds[adc_chan].low;760			adc->thresholds[adc_chan].low = val;761		}762		ret = 0;763		break;764	default:765		ret = -EINVAL;766		goto out_unlock;767	}768 769	if (val != old && palmas_gpadc_get_event(adc, adc_chan, dir))770		ret = palmas_gpadc_reconfigure_event_channels(adc);771 772out_unlock:773	mutex_unlock(&adc->lock);774 775	return ret;776}777 778static const struct iio_info palmas_gpadc_iio_info = {779	.read_raw = palmas_gpadc_read_raw,780	.read_event_config = palmas_gpadc_read_event_config,781	.write_event_config = palmas_gpadc_write_event_config,782	.read_event_value = palmas_gpadc_read_event_value,783	.write_event_value = palmas_gpadc_write_event_value,784};785 786static const struct iio_event_spec palmas_gpadc_events[] = {787	{788		.type = IIO_EV_TYPE_THRESH,789		.dir = IIO_EV_DIR_RISING,790		.mask_separate = BIT(IIO_EV_INFO_VALUE) |791				BIT(IIO_EV_INFO_ENABLE),792	}, {793		.type = IIO_EV_TYPE_THRESH,794		.dir = IIO_EV_DIR_FALLING,795		.mask_separate = BIT(IIO_EV_INFO_VALUE) |796				BIT(IIO_EV_INFO_ENABLE),797	},798};799 800#define PALMAS_ADC_CHAN_IIO(chan, _type, chan_info)	\801{							\802	.datasheet_name = PALMAS_DATASHEET_NAME(chan),	\803	.type = _type,					\804	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |	\805			BIT(chan_info),			\806	.indexed = 1,					\807	.channel = PALMAS_ADC_CH_##chan,		\808	.event_spec = palmas_gpadc_events,		\809	.num_event_specs = ARRAY_SIZE(palmas_gpadc_events)	\810}811 812static const struct iio_chan_spec palmas_gpadc_iio_channel[] = {813	PALMAS_ADC_CHAN_IIO(IN0, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),814	PALMAS_ADC_CHAN_IIO(IN1, IIO_TEMP, IIO_CHAN_INFO_RAW),815	PALMAS_ADC_CHAN_IIO(IN2, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),816	PALMAS_ADC_CHAN_IIO(IN3, IIO_TEMP, IIO_CHAN_INFO_RAW),817	PALMAS_ADC_CHAN_IIO(IN4, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),818	PALMAS_ADC_CHAN_IIO(IN5, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),819	PALMAS_ADC_CHAN_IIO(IN6, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),820	PALMAS_ADC_CHAN_IIO(IN7, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),821	PALMAS_ADC_CHAN_IIO(IN8, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),822	PALMAS_ADC_CHAN_IIO(IN9, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),823	PALMAS_ADC_CHAN_IIO(IN10, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),824	PALMAS_ADC_CHAN_IIO(IN11, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),825	PALMAS_ADC_CHAN_IIO(IN12, IIO_TEMP, IIO_CHAN_INFO_RAW),826	PALMAS_ADC_CHAN_IIO(IN13, IIO_TEMP, IIO_CHAN_INFO_RAW),827	PALMAS_ADC_CHAN_IIO(IN14, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),828	PALMAS_ADC_CHAN_IIO(IN15, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),829};830 831static int palmas_gpadc_get_adc_dt_data(struct platform_device *pdev,832	struct palmas_gpadc_platform_data **gpadc_pdata)833{834	struct device_node *np = pdev->dev.of_node;835	struct palmas_gpadc_platform_data *gp_data;836	int ret;837	u32 pval;838 839	gp_data = devm_kzalloc(&pdev->dev, sizeof(*gp_data), GFP_KERNEL);840	if (!gp_data)841		return -ENOMEM;842 843	ret = of_property_read_u32(np, "ti,channel0-current-microamp", &pval);844	if (!ret)845		gp_data->ch0_current = pval;846 847	ret = of_property_read_u32(np, "ti,channel3-current-microamp", &pval);848	if (!ret)849		gp_data->ch3_current = pval;850 851	gp_data->extended_delay = of_property_read_bool(np,852					"ti,enable-extended-delay");853 854	*gpadc_pdata = gp_data;855 856	return 0;857}858 859static void palmas_gpadc_reset(void *data)860{861	struct palmas_gpadc *adc = data;862	if (adc->event0.enabled || adc->event1.enabled)863		palmas_adc_reset_events(adc);864}865 866static int palmas_gpadc_probe(struct platform_device *pdev)867{868	struct palmas_gpadc *adc;869	struct palmas_platform_data *pdata;870	struct palmas_gpadc_platform_data *gpadc_pdata = NULL;871	struct iio_dev *indio_dev;872	int ret, i;873 874	pdata = dev_get_platdata(pdev->dev.parent);875 876	if (pdata && pdata->gpadc_pdata)877		gpadc_pdata = pdata->gpadc_pdata;878 879	if (!gpadc_pdata && pdev->dev.of_node) {880		ret = palmas_gpadc_get_adc_dt_data(pdev, &gpadc_pdata);881		if (ret < 0)882			return ret;883	}884	if (!gpadc_pdata)885		return -EINVAL;886 887	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));888	if (!indio_dev) {889		dev_err(&pdev->dev, "iio_device_alloc failed\n");890		return -ENOMEM;891	}892 893	adc = iio_priv(indio_dev);894	adc->dev = &pdev->dev;895	adc->palmas = dev_get_drvdata(pdev->dev.parent);896	adc->adc_info = palmas_gpadc_info;897 898	mutex_init(&adc->lock);899 900	init_completion(&adc->conv_completion);901	platform_set_drvdata(pdev, indio_dev);902 903	adc->auto_conversion_period = gpadc_pdata->auto_conversion_period_ms;904	adc->irq = palmas_irq_get_virq(adc->palmas, PALMAS_GPADC_EOC_SW_IRQ);905	if (adc->irq < 0)906		return dev_err_probe(adc->dev, adc->irq, "get virq failed\n");907 908	ret = devm_request_threaded_irq(&pdev->dev, adc->irq, NULL,909					palmas_gpadc_irq,910					IRQF_ONESHOT, dev_name(adc->dev),911					adc);912	if (ret < 0)913		return dev_err_probe(adc->dev, ret,914				     "request irq %d failed\n", adc->irq);915 916	adc->irq_auto_0 = platform_get_irq(pdev, 1);917	if (adc->irq_auto_0 < 0)918		return adc->irq_auto_0;919 920	ret = devm_request_threaded_irq(&pdev->dev, adc->irq_auto_0, NULL,921					palmas_gpadc_irq_auto, IRQF_ONESHOT,922					"palmas-adc-auto-0", indio_dev);923	if (ret < 0)924		return dev_err_probe(adc->dev, ret,925				     "request auto0 irq %d failed\n",926				     adc->irq_auto_0);927 928	adc->irq_auto_1 = platform_get_irq(pdev, 2);929	if (adc->irq_auto_1 < 0)930		return adc->irq_auto_1;931 932	ret = devm_request_threaded_irq(&pdev->dev, adc->irq_auto_1, NULL,933					palmas_gpadc_irq_auto, IRQF_ONESHOT,934					"palmas-adc-auto-1", indio_dev);935	if (ret < 0)936		return dev_err_probe(adc->dev, ret,937				     "request auto1 irq %d failed\n",938				     adc->irq_auto_1);939 940	adc->event0.enabled = false;941	adc->event0.channel = -1;942	adc->event0.direction = IIO_EV_DIR_NONE;943	adc->event1.enabled = false;944	adc->event1.channel = -1;945	adc->event1.direction = IIO_EV_DIR_NONE;946 947	/* set the current source 0 (value 0/5/15/20 uA => 0..3) */948	if (gpadc_pdata->ch0_current <= 1)949		adc->ch0_current = PALMAS_ADC_CH0_CURRENT_SRC_0;950	else if (gpadc_pdata->ch0_current <= 5)951		adc->ch0_current = PALMAS_ADC_CH0_CURRENT_SRC_5;952	else if (gpadc_pdata->ch0_current <= 15)953		adc->ch0_current = PALMAS_ADC_CH0_CURRENT_SRC_15;954	else955		adc->ch0_current = PALMAS_ADC_CH0_CURRENT_SRC_20;956 957	/* set the current source 3 (value 0/10/400/800 uA => 0..3) */958	if (gpadc_pdata->ch3_current <= 1)959		adc->ch3_current = PALMAS_ADC_CH3_CURRENT_SRC_0;960	else if (gpadc_pdata->ch3_current <= 10)961		adc->ch3_current = PALMAS_ADC_CH3_CURRENT_SRC_10;962	else if (gpadc_pdata->ch3_current <= 400)963		adc->ch3_current = PALMAS_ADC_CH3_CURRENT_SRC_400;964	else965		adc->ch3_current = PALMAS_ADC_CH3_CURRENT_SRC_800;966 967	adc->extended_delay = gpadc_pdata->extended_delay;968 969	indio_dev->name = MOD_NAME;970	indio_dev->info = &palmas_gpadc_iio_info;971	indio_dev->modes = INDIO_DIRECT_MODE;972	indio_dev->channels = palmas_gpadc_iio_channel;973	indio_dev->num_channels = ARRAY_SIZE(palmas_gpadc_iio_channel);974 975	ret = devm_iio_device_register(&pdev->dev, indio_dev);976	if (ret < 0)977		return dev_err_probe(adc->dev, ret,978				     "iio_device_register() failed\n");979 980	device_set_wakeup_capable(&pdev->dev, 1);981	for (i = 0; i < PALMAS_ADC_CH_MAX; i++) {982		if (!(adc->adc_info[i].is_uncalibrated))983			palmas_gpadc_calibrate(adc, i);984	}985 986	ret = devm_add_action(&pdev->dev, palmas_gpadc_reset, adc);987	if (ret)988		return ret;989 990	return 0;991}992 993static int palmas_adc_configure_events(struct palmas_gpadc *adc)994{995	int adc_period, conv;996	int i;997	int ch0 = 0, ch1 = 0;998	int thres;999	int ret;1000 1001	adc_period = adc->auto_conversion_period;1002	for (i = 0; i < 16; ++i) {1003		if (((1000 * (1 << i)) / 32) >= adc_period)1004			break;1005	}1006	if (i > 0)1007		i--;1008	adc_period = i;1009	ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE,1010			PALMAS_GPADC_AUTO_CTRL,1011			PALMAS_GPADC_AUTO_CTRL_COUNTER_CONV_MASK,1012			adc_period);1013	if (ret < 0) {1014		dev_err(adc->dev, "AUTO_CTRL write failed: %d\n", ret);1015		return ret;1016	}1017 1018	conv = 0;1019	if (adc->event0.enabled) {1020		struct palmas_adc_event *ev = &adc->event0;1021		int polarity;1022 1023		ch0 = ev->channel;1024		conv |= PALMAS_GPADC_AUTO_CTRL_AUTO_CONV0_EN;1025		switch (ev->direction) {1026		case IIO_EV_DIR_RISING:1027			thres = palmas_gpadc_get_high_threshold_raw(adc, ev);1028			polarity = 0;1029			break;1030		case IIO_EV_DIR_FALLING:1031			thres = palmas_gpadc_get_low_threshold_raw(adc, ev);1032			polarity = PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_POL;1033			break;1034		default:1035			return -EINVAL;1036		}1037 1038		ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE,1039				PALMAS_GPADC_THRES_CONV0_LSB, thres & 0xFF);1040		if (ret < 0) {1041			dev_err(adc->dev,1042				"THRES_CONV0_LSB write failed: %d\n", ret);1043			return ret;1044		}1045 1046		ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE,1047				PALMAS_GPADC_THRES_CONV0_MSB,1048				((thres >> 8) & 0xF) | polarity);1049		if (ret < 0) {1050			dev_err(adc->dev,1051				"THRES_CONV0_MSB write failed: %d\n", ret);1052			return ret;1053		}1054	}1055 1056	if (adc->event1.enabled) {1057		struct palmas_adc_event *ev = &adc->event1;1058		int polarity;1059 1060		ch1 = ev->channel;1061		conv |= PALMAS_GPADC_AUTO_CTRL_AUTO_CONV1_EN;1062		switch (ev->direction) {1063		case IIO_EV_DIR_RISING:1064			thres = palmas_gpadc_get_high_threshold_raw(adc, ev);1065			polarity = 0;1066			break;1067		case IIO_EV_DIR_FALLING:1068			thres = palmas_gpadc_get_low_threshold_raw(adc, ev);1069			polarity = PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_POL;1070			break;1071		default:1072			return -EINVAL;1073		}1074 1075		ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE,1076				PALMAS_GPADC_THRES_CONV1_LSB, thres & 0xFF);1077		if (ret < 0) {1078			dev_err(adc->dev,1079				"THRES_CONV1_LSB write failed: %d\n", ret);1080			return ret;1081		}1082 1083		ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE,1084				PALMAS_GPADC_THRES_CONV1_MSB,1085				((thres >> 8) & 0xF) | polarity);1086		if (ret < 0) {1087			dev_err(adc->dev,1088				"THRES_CONV1_MSB write failed: %d\n", ret);1089			return ret;1090		}1091	}1092 1093	ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE,1094			PALMAS_GPADC_AUTO_SELECT, (ch1 << 4) | ch0);1095	if (ret < 0) {1096		dev_err(adc->dev, "AUTO_SELECT write failed: %d\n", ret);1097		return ret;1098	}1099 1100	ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE,1101			PALMAS_GPADC_AUTO_CTRL,1102			PALMAS_GPADC_AUTO_CTRL_AUTO_CONV1_EN |1103			PALMAS_GPADC_AUTO_CTRL_AUTO_CONV0_EN, conv);1104	if (ret < 0)1105		dev_err(adc->dev, "AUTO_CTRL write failed: %d\n", ret);1106 1107	return ret;1108}1109 1110static int palmas_adc_reset_events(struct palmas_gpadc *adc)1111{1112	int ret;1113 1114	ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE,1115			PALMAS_GPADC_AUTO_SELECT, 0);1116	if (ret < 0) {1117		dev_err(adc->dev, "AUTO_SELECT write failed: %d\n", ret);1118		return ret;1119	}1120 1121	ret = palmas_disable_auto_conversion(adc);1122	if (ret < 0)1123		dev_err(adc->dev, "Disable auto conversion failed: %d\n", ret);1124 1125	return ret;1126}1127 1128static int palmas_gpadc_suspend(struct device *dev)1129{1130	struct iio_dev *indio_dev = dev_get_drvdata(dev);1131	struct palmas_gpadc *adc = iio_priv(indio_dev);1132 1133	if (!device_may_wakeup(dev))1134		return 0;1135 1136	if (adc->event0.enabled)1137		enable_irq_wake(adc->irq_auto_0);1138 1139	if (adc->event1.enabled)1140		enable_irq_wake(adc->irq_auto_1);1141 1142	return 0;1143}1144 1145static int palmas_gpadc_resume(struct device *dev)1146{1147	struct iio_dev *indio_dev = dev_get_drvdata(dev);1148	struct palmas_gpadc *adc = iio_priv(indio_dev);1149 1150	if (!device_may_wakeup(dev))1151		return 0;1152 1153	if (adc->event0.enabled)1154		disable_irq_wake(adc->irq_auto_0);1155 1156	if (adc->event1.enabled)1157		disable_irq_wake(adc->irq_auto_1);1158 1159	return 0;1160};1161 1162static DEFINE_SIMPLE_DEV_PM_OPS(palmas_pm_ops, palmas_gpadc_suspend,1163				palmas_gpadc_resume);1164 1165static const struct of_device_id of_palmas_gpadc_match_tbl[] = {1166	{ .compatible = "ti,palmas-gpadc", },1167	{ /* end */ }1168};1169MODULE_DEVICE_TABLE(of, of_palmas_gpadc_match_tbl);1170 1171static struct platform_driver palmas_gpadc_driver = {1172	.probe = palmas_gpadc_probe,1173	.driver = {1174		.name = MOD_NAME,1175		.pm = pm_sleep_ptr(&palmas_pm_ops),1176		.of_match_table = of_palmas_gpadc_match_tbl,1177	},1178};1179module_platform_driver(palmas_gpadc_driver);1180 1181MODULE_DESCRIPTION("palmas GPADC driver");1182MODULE_AUTHOR("Pradeep Goudagunta<pgoudagunta@nvidia.com>");1183MODULE_ALIAS("platform:palmas-gpadc");1184MODULE_LICENSE("GPL v2");1185