11696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk/*
21696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * TWL6030 GPADC module driver
31696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk *
41696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * Copyright (C) 2009-2013 Texas Instruments Inc.
51696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * Nishant Kamat <nskamat@ti.com>
61696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * Balaji T K <balajitk@ti.com>
71696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * Graeme Gregory <gg@slimlogic.co.uk>
81696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * Girish S Ghongdemath <girishsg@ti.com>
91696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * Ambresh K <ambresh@ti.com>
101696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * Oleksandr Kozaruk <oleksandr.kozaruk@ti.com
111696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk *
121696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * Based on twl4030-madc.c
131696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * Copyright (C) 2008 Nokia Corporation
141696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * Mikko Ylinen <mikko.k.ylinen@nokia.com>
151696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk *
161696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * This program is free software; you can redistribute it and/or
171696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * modify it under the terms of the GNU General Public License
181696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * version 2 as published by the Free Software Foundation.
191696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk *
201696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * This program is distributed in the hope that it will be useful, but
211696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * WITHOUT ANY WARRANTY; without even the implied warranty of
221696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
231696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * General Public License for more details.
241696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk *
251696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * You should have received a copy of the GNU General Public License
261696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * along with this program; if not, write to the Free Software
271696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
281696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * 02110-1301 USA
291696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk *
301696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk */
311696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#include <linux/interrupt.h>
321696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#include <linux/kernel.h>
331696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#include <linux/module.h>
341696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#include <linux/platform_device.h>
351696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#include <linux/of_platform.h>
361696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#include <linux/i2c/twl.h>
371696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#include <linux/iio/iio.h>
381696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#include <linux/iio/sysfs.h>
391696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
401696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define DRIVER_NAME		"twl6030_gpadc"
411696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
421696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk/*
431696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * twl6030 per TRM has 17 channels, and twl6032 has 19 channels
441696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * 2 test network channels are not used,
451696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * 2 die temperature channels are not used either, as it is not
461696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * defined how to convert ADC value to temperature
471696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk */
481696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6030_GPADC_USED_CHANNELS		13
491696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6030_GPADC_MAX_CHANNELS		15
501696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6032_GPADC_USED_CHANNELS		15
511696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6032_GPADC_MAX_CHANNELS		19
521696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6030_GPADC_NUM_TRIM_REGS		16
531696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
541696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6030_GPADC_CTRL_P1			0x05
551696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
561696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6032_GPADC_GPSELECT_ISB		0x07
571696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6032_GPADC_CTRL_P1			0x08
581696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
591696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6032_GPADC_GPCH0_LSB			0x0d
601696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6032_GPADC_GPCH0_MSB			0x0e
611696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
621696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6030_GPADC_CTRL_P1_SP1		BIT(3)
631696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
641696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6030_GPADC_GPCH0_LSB			(0x29)
651696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
661696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6030_GPADC_RT_SW1_EOC_MASK		BIT(5)
671696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
681696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6030_GPADC_TRIM1			0xCD
691696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
701696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6030_REG_TOGGLE1			0x90
711696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6030_GPADCS				BIT(1)
721696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6030_GPADCR				BIT(0)
731696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
741696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk/**
751696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * struct twl6030_chnl_calib - channel calibration
761696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @gain:		slope coefficient for ideal curve
771696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @gain_error:		gain error
781696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @offset_error:	offset of the real curve
791696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk */
801696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstruct twl6030_chnl_calib {
811696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	s32 gain;
821696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	s32 gain_error;
831696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	s32 offset_error;
841696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk};
851696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
861696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk/**
871696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * struct twl6030_ideal_code - GPADC calibration parameters
881696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * GPADC is calibrated in two points: close to the beginning and
891696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * to the and of the measurable input range
901696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk *
911696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @channel:	channel number
921696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @code1:	ideal code for the input at the beginning
931696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @code2:	ideal code for at the end of the range
941696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @volt1:	voltage input at the beginning(low voltage)
951696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @volt2:	voltage input at the end(high voltage)
961696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk */
971696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstruct twl6030_ideal_code {
981696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int channel;
991696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	u16 code1;
1001696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	u16 code2;
1011696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	u16 volt1;
1021696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	u16 volt2;
1031696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk};
1041696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
1051696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstruct twl6030_gpadc_data;
1061696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
1071696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk/**
1081696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * struct twl6030_gpadc_platform_data - platform specific data
1091696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @nchannels:		number of GPADC channels
1101696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @iio_channels:	iio channels
1111696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @twl6030_ideal:	pointer to calibration parameters
1121696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @start_conversion:	pointer to ADC start conversion function
1131696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @channel_to_reg	pointer to ADC function to convert channel to
1141696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk *			register address for reading conversion result
1151696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @calibrate:		pointer to calibration function
1161696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk */
1171696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstruct twl6030_gpadc_platform_data {
1181696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	const int nchannels;
1191696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	const struct iio_chan_spec *iio_channels;
1201696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	const struct twl6030_ideal_code *ideal;
1211696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int (*start_conversion)(int channel);
1221696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	u8 (*channel_to_reg)(int channel);
1231696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int (*calibrate)(struct twl6030_gpadc_data *gpadc);
1241696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk};
1251696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
1261696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk/**
1271696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * struct twl6030_gpadc_data - GPADC data
1281696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @dev:		device pointer
1291696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @lock:		mutual exclusion lock for the structure
1301696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @irq_complete:	completion to signal end of conversion
1311696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @twl6030_cal_tbl:	pointer to calibration data for each
1321696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk *			channel with gain error and offset
1331696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * @pdata:		pointer to device specific data
1341696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk */
1351696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstruct twl6030_gpadc_data {
1361696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	struct device	*dev;
1371696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	struct mutex	lock;
1381696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	struct completion	irq_complete;
1391696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	struct twl6030_chnl_calib	*twl6030_cal_tbl;
1401696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	const struct twl6030_gpadc_platform_data *pdata;
1411696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk};
1421696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
1431696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk/*
1441696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * channels 11, 12, 13, 15 and 16 have no calibration data
1451696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * calibration offset is same for channels 1, 3, 4, 5
1461696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk *
1471696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * The data is taken from GPADC_TRIM registers description.
1481696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * GPADC_TRIM registers keep difference between the code measured
1491696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * at volt1 and volt2 input voltages and corresponding code1 and code2
1501696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk */
1511696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic const struct twl6030_ideal_code
1521696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	twl6030_ideal[TWL6030_GPADC_USED_CHANNELS] = {
1531696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[0] = { /* ch 0, external, battery type, resistor value */
1541696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 0,
1551696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 116,
1561696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 745,
1571696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 141,
1581696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 910,
1591696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
1601696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[1] = { /* ch 1, external, battery temperature, NTC resistor value */
1611696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 1,
1621696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 82,
1631696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 900,
1641696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 100,
1651696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 1100,
1661696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
1671696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[2] = { /* ch 2, external, audio accessory/general purpose */
1681696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 2,
1691696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 55,
1701696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 818,
1711696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 101,
1721696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 1499,
1731696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
1741696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[3] = { /* ch 3, external, general purpose */
1751696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 3,
1761696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 82,
1771696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 900,
1781696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 100,
1791696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 1100,
1801696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
1811696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[4] = { /* ch 4, external, temperature measurement/general purpose */
1821696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 4,
1831696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 82,
1841696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 900,
1851696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 100,
1861696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 1100,
1871696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
1881696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[5] = { /* ch 5, external, general purpose */
1891696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 5,
1901696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 82,
1911696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 900,
1921696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 100,
1931696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 1100,
1941696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
1951696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[6] = { /* ch 6, external, general purpose */
1961696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 6,
1971696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 82,
1981696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 900,
1991696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 100,
2001696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 1100,
2011696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
2021696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[7] = { /* ch 7, internal, main battery */
2031696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 7,
2041696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 614,
2051696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 941,
2061696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 3001,
2071696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 4599,
2081696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
2091696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[8] = { /* ch 8, internal, backup battery */
2101696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 8,
2111696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 82,
2121696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 688,
2131696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 501,
2141696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 4203,
2151696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
2161696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[9] = { /* ch 9, internal, external charger input */
2171696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 9,
2181696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 182,
2191696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 818,
2201696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 2001,
2211696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 8996,
2221696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
2231696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[10] = { /* ch 10, internal, VBUS */
2241696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 10,
2251696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 149,
2261696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 818,
2271696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 1001,
2281696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 5497,
2291696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
2301696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[11] = { /* ch 11, internal, VBUS charging current */
2311696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 11,
2321696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
2331696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		/* ch 12, internal, Die temperature */
2341696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		/* ch 13, internal, Die temperature */
2351696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[12] = { /* ch 14, internal, USB ID line */
2361696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 14,
2371696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 48,
2381696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 714,
2391696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 323,
2401696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 4800,
2411696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
2421696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk};
2431696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
2441696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic const struct twl6030_ideal_code
2451696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			twl6032_ideal[TWL6032_GPADC_USED_CHANNELS] = {
2461696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[0] = { /* ch 0, external, battery type, resistor value */
2471696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 0,
2481696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 1441,
2491696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 3276,
2501696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 440,
2511696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 1000,
2521696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
2531696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[1] = { /* ch 1, external, battery temperature, NTC resistor value */
2541696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 1,
2551696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 1441,
2561696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 3276,
2571696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 440,
2581696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 1000,
2591696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
2601696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[2] = { /* ch 2, external, audio accessory/general purpose */
2611696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 2,
2621696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 1441,
2631696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 3276,
2641696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 660,
2651696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 1500,
2661696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
2671696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[3] = { /* ch 3, external, temperature with external diode/general
2681696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk								purpose */
2691696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 3,
2701696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 1441,
2711696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 3276,
2721696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 440,
2731696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 1000,
2741696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
2751696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[4] = { /* ch 4, external, temperature measurement/general purpose */
2761696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 4,
2771696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 1441,
2781696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 3276,
2791696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 440,
2801696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 1000,
2811696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
2821696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[5] = { /* ch 5, external, general purpose */
2831696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 5,
2841696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 1441,
2851696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 3276,
2861696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 440,
2871696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 1000,
2881696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
2891696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[6] = { /* ch 6, external, general purpose */
2901696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 6,
2911696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 1441,
2921696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 3276,
2931696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 440,
2941696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 1000,
2951696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
2961696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[7] = { /* ch7, internal, system supply */
2971696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 7,
2981696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 1441,
2991696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 3276,
3001696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 2200,
3011696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 5000,
3021696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
3031696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[8] = { /* ch8, internal, backup battery */
3041696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 8,
3051696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 1441,
3061696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 3276,
3071696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 2200,
3081696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 5000,
3091696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
3101696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[9] = { /* ch 9, internal, external charger input */
3111696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 9,
3121696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 1441,
3131696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 3276,
3141696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 3960,
3151696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 9000,
3161696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
3171696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[10] = { /* ch10, internal, VBUS */
3181696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 10,
3191696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 150,
3201696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 751,
3211696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 1000,
3221696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 5000,
3231696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
3241696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[11] = { /* ch 11, internal, VBUS DC-DC output current */
3251696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 11,
3261696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 1441,
3271696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 3276,
3281696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 660,
3291696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 1500,
3301696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
3311696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		/* ch 12, internal, Die temperature */
3321696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		/* ch 13, internal, Die temperature */
3331696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[12] = { /* ch 14, internal, USB ID line */
3341696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 14,
3351696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 1441,
3361696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 3276,
3371696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 2420,
3381696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 5500,
3391696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
3401696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		/* ch 15, internal, test network */
3411696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		/* ch 16, internal, test network */
3421696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[13] = { /* ch 17, internal, battery charging current */
3431696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 17,
3441696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
3451696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	[14] = { /* ch 18, internal, battery voltage */
3461696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.channel = 18,
3471696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code1 = 1441,
3481696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.code2 = 3276,
3491696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt1 = 2200,
3501696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.volt2 = 5000,
3511696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
3521696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk};
3531696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
3541696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic inline int twl6030_gpadc_write(u8 reg, u8 val)
3551696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
3561696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return twl_i2c_write_u8(TWL6030_MODULE_GPADC, val, reg);
3571696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
3581696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
3591696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic inline int twl6030_gpadc_read(u8 reg, u8 *val)
3601696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
3611696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
3621696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return twl_i2c_read(TWL6030_MODULE_GPADC, val, reg, 2);
3631696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
3641696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
3651696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6030_gpadc_enable_irq(u8 mask)
3661696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
3671696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int ret;
3681696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
3691696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	ret = twl6030_interrupt_unmask(mask, REG_INT_MSK_LINE_B);
3701696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (ret < 0)
3711696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		return ret;
3721696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
3731696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	ret = twl6030_interrupt_unmask(mask, REG_INT_MSK_STS_B);
3741696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
3751696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return ret;
3761696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
3771696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
3781696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic void twl6030_gpadc_disable_irq(u8 mask)
3791696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
3801696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	twl6030_interrupt_mask(mask, REG_INT_MSK_LINE_B);
3811696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	twl6030_interrupt_mask(mask, REG_INT_MSK_STS_B);
3821696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
3831696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
3841696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic irqreturn_t twl6030_gpadc_irq_handler(int irq, void *indio_dev)
3851696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
3861696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	struct twl6030_gpadc_data *gpadc = iio_priv(indio_dev);
3871696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
3881696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	complete(&gpadc->irq_complete);
3891696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
3901696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return IRQ_HANDLED;
3911696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
3921696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
3931696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6030_start_conversion(int channel)
3941696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
3951696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return twl6030_gpadc_write(TWL6030_GPADC_CTRL_P1,
3961696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk					TWL6030_GPADC_CTRL_P1_SP1);
3971696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
3981696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
3991696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6032_start_conversion(int channel)
4001696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
4011696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int ret;
4021696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4031696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	ret = twl6030_gpadc_write(TWL6032_GPADC_GPSELECT_ISB, channel);
4041696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (ret)
4051696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		return ret;
4061696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4071696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return twl6030_gpadc_write(TWL6032_GPADC_CTRL_P1,
4081696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk						TWL6030_GPADC_CTRL_P1_SP1);
4091696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
4101696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4111696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic u8 twl6030_channel_to_reg(int channel)
4121696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
4131696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return TWL6030_GPADC_GPCH0_LSB + 2 * channel;
4141696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
4151696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4161696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic u8 twl6032_channel_to_reg(int channel)
4171696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
4181696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	/*
4191696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 * for any prior chosen channel, when the conversion is ready
4201696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 * the result is avalable in GPCH0_LSB, GPCH0_MSB.
4211696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 */
4221696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4231696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return TWL6032_GPADC_GPCH0_LSB;
4241696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
4251696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4261696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6030_gpadc_lookup(const struct twl6030_ideal_code *ideal,
4271696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		int channel, int size)
4281696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
4291696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int i;
4301696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4311696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	for (i = 0; i < size; i++)
4321696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		if (ideal[i].channel == channel)
4331696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			break;
4341696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4351696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return i;
4361696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
4371696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4381696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6030_channel_calibrated(const struct twl6030_gpadc_platform_data
4391696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		*pdata, int channel)
4401696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
4411696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	const struct twl6030_ideal_code *ideal = pdata->ideal;
4421696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int i;
4431696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4441696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	i = twl6030_gpadc_lookup(ideal, channel, pdata->nchannels);
4451696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	/* not calibrated channels have 0 in all structure members */
4461696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return pdata->ideal[i].code2;
4471696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
4481696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4491696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6030_gpadc_make_correction(struct twl6030_gpadc_data *gpadc,
4501696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		int channel, int raw_code)
4511696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
4521696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	const struct twl6030_ideal_code *ideal = gpadc->pdata->ideal;
4531696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int corrected_code;
4541696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int i;
4551696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4561696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	i = twl6030_gpadc_lookup(ideal, channel, gpadc->pdata->nchannels);
4571696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	corrected_code = ((raw_code * 1000) -
4581696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		gpadc->twl6030_cal_tbl[i].offset_error) /
4591696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		gpadc->twl6030_cal_tbl[i].gain_error;
4601696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4611696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return corrected_code;
4621696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
4631696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4641696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6030_gpadc_get_raw(struct twl6030_gpadc_data *gpadc,
4651696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		int channel, int *res)
4661696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
4671696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	u8 reg = gpadc->pdata->channel_to_reg(channel);
4681696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	__le16 val;
4691696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int raw_code;
4701696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int ret;
4711696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4721696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	ret = twl6030_gpadc_read(reg, (u8 *)&val);
4731696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (ret) {
4741696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		dev_dbg(gpadc->dev, "unable to read register 0x%X\n", reg);
4751696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		return ret;
4761696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	}
4771696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4781696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	raw_code = le16_to_cpu(val);
4791696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	dev_dbg(gpadc->dev, "GPADC raw code: %d", raw_code);
4801696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4811696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (twl6030_channel_calibrated(gpadc->pdata, channel))
4821696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		*res = twl6030_gpadc_make_correction(gpadc, channel, raw_code);
4831696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	else
4841696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		*res = raw_code;
4851696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4861696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return ret;
4871696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
4881696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4891696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6030_gpadc_get_processed(struct twl6030_gpadc_data *gpadc,
4901696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		int channel, int *val)
4911696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
4921696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	const struct twl6030_ideal_code *ideal = gpadc->pdata->ideal;
4931696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int corrected_code;
4941696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int channel_value;
4951696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int i;
4961696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int ret;
4971696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
4981696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	ret = twl6030_gpadc_get_raw(gpadc, channel, &corrected_code);
4991696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (ret)
5001696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		return ret;
5011696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5021696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	i = twl6030_gpadc_lookup(ideal, channel, gpadc->pdata->nchannels);
5031696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	channel_value = corrected_code *
5041696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			gpadc->twl6030_cal_tbl[i].gain;
5051696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5061696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	/* Shift back into mV range */
5071696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	channel_value /= 1000;
5081696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5091696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	dev_dbg(gpadc->dev, "GPADC corrected code: %d", corrected_code);
5101696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	dev_dbg(gpadc->dev, "GPADC value: %d", channel_value);
5111696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5121696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	*val = channel_value;
5131696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5141696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return ret;
5151696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
5161696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5171696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6030_gpadc_read_raw(struct iio_dev *indio_dev,
5181696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			     const struct iio_chan_spec *chan,
5191696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			     int *val, int *val2, long mask)
5201696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
5211696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	struct twl6030_gpadc_data *gpadc = iio_priv(indio_dev);
5221696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int ret;
5231696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	long timeout;
5241696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5251696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	mutex_lock(&gpadc->lock);
5261696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5271696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	ret = gpadc->pdata->start_conversion(chan->channel);
5281696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (ret) {
5291696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		dev_err(gpadc->dev, "failed to start conversion\n");
5301696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		goto err;
5311696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	}
5321696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	/* wait for conversion to complete */
5331696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	timeout = wait_for_completion_interruptible_timeout(
5341696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk				&gpadc->irq_complete, msecs_to_jiffies(5000));
5351696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (timeout == 0) {
5361696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		ret = -ETIMEDOUT;
5371696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		goto err;
5381696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	} else if (timeout < 0) {
5391696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		ret = -EINTR;
5402d2da9fc7113ee5df06519e435f2f9430acf40c5Wei Yongjun		goto err;
5411696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	}
5421696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5431696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	switch (mask) {
5441696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	case IIO_CHAN_INFO_RAW:
5451696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		ret = twl6030_gpadc_get_raw(gpadc, chan->channel, val);
5461696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		ret = ret ? -EIO : IIO_VAL_INT;
5471696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		break;
5481696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5491696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	case IIO_CHAN_INFO_PROCESSED:
5501696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		ret = twl6030_gpadc_get_processed(gpadc, chan->channel, val);
5511696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		ret = ret ? -EIO : IIO_VAL_INT;
5521696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		break;
5531696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5541696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	default:
5551696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		break;
5561696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	}
5571696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukerr:
5581696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	mutex_unlock(&gpadc->lock);
5591696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5601696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return ret;
5611696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
5621696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5631696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk/*
5641696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * The GPADC channels are calibrated using a two point calibration method.
5651696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * The channels measured with two known values: volt1 and volt2, and
5661696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * ideal corresponding output codes are known: code1, code2.
5671696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * The difference(d1, d2) between ideal and measured codes stored in trim
5681696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * registers.
5691696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * The goal is to find offset and gain of the real curve for each calibrated
5701696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * channel.
5711696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * gain: k = 1 + ((d2 - d1) / (x2 - x1))
5721696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk * offset: b = d1 + (k - 1) * x1
5731696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk */
5741696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic void twl6030_calibrate_channel(struct twl6030_gpadc_data *gpadc,
5751696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		int channel, int d1, int d2)
5761696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
5771696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int b, k, gain, x1, x2, i;
5781696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	const struct twl6030_ideal_code *ideal = gpadc->pdata->ideal;
5791696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5801696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	i = twl6030_gpadc_lookup(ideal, channel, gpadc->pdata->nchannels);
5811696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5821696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	/* Gain */
5831696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	gain = ((ideal[i].volt2 - ideal[i].volt1) * 1000) /
5841696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		(ideal[i].code2 - ideal[i].code1);
5851696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5861696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	x1 = ideal[i].code1;
5871696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	x2 = ideal[i].code2;
5881696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5891696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	/* k - real curve gain */
5901696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	k = 1000 + (((d2 - d1) * 1000) / (x2 - x1));
5911696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5921696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	/* b - offset of the real curve gain */
5931696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	b = (d1 * 1000) - (k - 1000) * x1;
5941696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5951696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	gpadc->twl6030_cal_tbl[i].gain = gain;
5961696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	gpadc->twl6030_cal_tbl[i].gain_error = k;
5971696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	gpadc->twl6030_cal_tbl[i].offset_error = b;
5981696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
5991696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	dev_dbg(gpadc->dev, "GPADC d1   for Chn: %d = %d\n", channel, d1);
6001696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	dev_dbg(gpadc->dev, "GPADC d2   for Chn: %d = %d\n", channel, d2);
6011696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	dev_dbg(gpadc->dev, "GPADC x1   for Chn: %d = %d\n", channel, x1);
6021696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	dev_dbg(gpadc->dev, "GPADC x2   for Chn: %d = %d\n", channel, x2);
6031696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	dev_dbg(gpadc->dev, "GPADC Gain for Chn: %d = %d\n", channel, gain);
6041696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	dev_dbg(gpadc->dev, "GPADC k    for Chn: %d = %d\n", channel, k);
6051696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	dev_dbg(gpadc->dev, "GPADC b    for Chn: %d = %d\n", channel, b);
6061696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
6071696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
6081696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic inline int twl6030_gpadc_get_trim_offset(s8 d)
6091696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
6101696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	/*
6111696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 * XXX NOTE!
6121696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 * bit 0 - sign, bit 7 - reserved, 6..1 - trim value
6131696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 * though, the documentation states that trim value
6141696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 * is absolute value, the correct conversion results are
6151696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 * obtained if the value is interpreted as 2's complement.
6161696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 */
6171696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	__u32 temp = ((d & 0x7f) >> 1) | ((d & 1) << 6);
6181696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
6191696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return sign_extend32(temp, 6);
6201696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
6211696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
6221696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6030_calibration(struct twl6030_gpadc_data *gpadc)
6231696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
6241696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int ret;
6251696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int chn;
6261696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	u8 trim_regs[TWL6030_GPADC_NUM_TRIM_REGS];
6271696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	s8 d1, d2;
6281696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
6291696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	/*
6301696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 * for calibration two measurements have been performed at
6311696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 * factory, for some channels, during the production test and
6321696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 * have been stored in registers. This two stored values are
6331696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 * used to correct the measurements. The values represent
6341696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 * offsets for the given input from the output on ideal curve.
6351696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 */
6361696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	ret = twl_i2c_read(TWL6030_MODULE_ID2, trim_regs,
6371696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			TWL6030_GPADC_TRIM1, TWL6030_GPADC_NUM_TRIM_REGS);
6381696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (ret < 0) {
6391696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		dev_err(gpadc->dev, "calibration failed\n");
6401696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		return ret;
6411696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	}
6421696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
6431696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	for (chn = 0; chn < TWL6030_GPADC_MAX_CHANNELS; chn++) {
6441696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
6451696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		switch (chn) {
6461696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 0:
6471696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d1 = trim_regs[0];
6481696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d2 = trim_regs[1];
6491696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			break;
6501696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 1:
6511696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 3:
6521696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 4:
6531696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 5:
6541696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 6:
6551696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d1 = trim_regs[4];
6561696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d2 = trim_regs[5];
6571696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			break;
6581696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 2:
6591696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d1 = trim_regs[12];
6601696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d2 = trim_regs[13];
6611696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			break;
6621696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 7:
6631696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d1 = trim_regs[6];
6641696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d2 = trim_regs[7];
6651696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			break;
6661696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 8:
6671696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d1 = trim_regs[2];
6681696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d2 = trim_regs[3];
6691696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			break;
6701696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 9:
6711696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d1 = trim_regs[8];
6721696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d2 = trim_regs[9];
6731696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			break;
6741696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 10:
6751696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d1 = trim_regs[10];
6761696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d2 = trim_regs[11];
6771696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			break;
6781696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 14:
6791696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d1 = trim_regs[14];
6801696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d2 = trim_regs[15];
6811696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			break;
6821696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		default:
6831696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			continue;
6841696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		}
6851696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
6861696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		d1 = twl6030_gpadc_get_trim_offset(d1);
6871696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		d2 = twl6030_gpadc_get_trim_offset(d2);
6881696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
6891696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		twl6030_calibrate_channel(gpadc, chn, d1, d2);
6901696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	}
6911696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
6921696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return 0;
6931696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
6941696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
6951696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6032_get_trim_value(u8 *trim_regs, unsigned int reg0,
6961696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		unsigned int reg1, unsigned int mask0, unsigned int mask1,
6971696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		unsigned int shift0)
6981696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
6991696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int val;
7001696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
7011696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	val = (trim_regs[reg0] & mask0) << shift0;
7021696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	val |= (trim_regs[reg1] & mask1) >> 1;
7031696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (trim_regs[reg1] & 0x01)
7041696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		val = -val;
7051696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
7061696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return val;
7071696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
7081696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
7091696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6032_calibration(struct twl6030_gpadc_data *gpadc)
7101696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
7111696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int chn, d1 = 0, d2 = 0, temp;
7121696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	u8 trim_regs[TWL6030_GPADC_NUM_TRIM_REGS];
7131696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int ret;
7141696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
7151696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	ret = twl_i2c_read(TWL6030_MODULE_ID2, trim_regs,
7161696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			TWL6030_GPADC_TRIM1, TWL6030_GPADC_NUM_TRIM_REGS);
7171696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (ret < 0) {
7181696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		dev_err(gpadc->dev, "calibration failed\n");
7191696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		return ret;
7201696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	}
7211696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
7221696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	/*
7231696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 * Loop to calculate the value needed for returning voltages from
7241696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 * GPADC not values.
7251696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 *
7261696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 * gain is calculated to 3 decimal places fixed point.
7271696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	 */
7281696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	for (chn = 0; chn < TWL6032_GPADC_MAX_CHANNELS; chn++) {
7291696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
7301696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		switch (chn) {
7311696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 0:
7321696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 1:
7331696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 2:
7341696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 3:
7351696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 4:
7361696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 5:
7371696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 6:
7381696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 11:
7391696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 14:
7401696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d1 = twl6032_get_trim_value(trim_regs, 2, 0, 0x1f,
7411696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk								0x06, 2);
7421696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d2 = twl6032_get_trim_value(trim_regs, 3, 1, 0x3f,
7431696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk								0x06, 2);
7441696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			break;
7451696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 8:
7461696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			temp = twl6032_get_trim_value(trim_regs, 2, 0, 0x1f,
7471696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk								0x06, 2);
7481696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d1 = temp + twl6032_get_trim_value(trim_regs, 7, 6,
7491696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk								0x18, 0x1E, 1);
7501696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
7511696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			temp = twl6032_get_trim_value(trim_regs, 3, 1, 0x3F,
7521696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk								0x06, 2);
7531696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d2 = temp + twl6032_get_trim_value(trim_regs, 9, 7,
7541696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk								0x1F, 0x06, 2);
7551696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			break;
7561696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 9:
7571696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			temp = twl6032_get_trim_value(trim_regs, 2, 0, 0x1f,
7581696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk								0x06, 2);
7591696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d1 = temp + twl6032_get_trim_value(trim_regs, 13, 11,
7601696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk								0x18, 0x1E, 1);
7611696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
7621696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			temp = twl6032_get_trim_value(trim_regs, 3, 1, 0x3f,
7631696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk								0x06, 2);
7641696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d2 = temp + twl6032_get_trim_value(trim_regs, 15, 13,
7651696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk								0x1F, 0x06, 1);
7661696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			break;
7671696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 10:
7681696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d1 = twl6032_get_trim_value(trim_regs, 10, 8, 0x0f,
7691696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk								0x0E, 3);
7701696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d2 = twl6032_get_trim_value(trim_regs, 14, 12, 0x0f,
7711696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk								0x0E, 3);
7721696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			break;
7731696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 7:
7741696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		case 18:
7751696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			temp = twl6032_get_trim_value(trim_regs, 2, 0, 0x1f,
7761696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk								0x06, 2);
7771696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
7781696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d1 = (trim_regs[4] & 0x7E) >> 1;
7791696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			if (trim_regs[4] & 0x01)
7801696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk				d1 = -d1;
7811696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d1 += temp;
7821696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
7831696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			temp = twl6032_get_trim_value(trim_regs, 3, 1, 0x3f,
7841696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk								0x06, 2);
7851696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
7861696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d2 = (trim_regs[5] & 0xFE) >> 1;
7871696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			if (trim_regs[5] & 0x01)
7881696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk				d2 = -d2;
7891696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
7901696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			d2 += temp;
7911696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			break;
7921696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		default:
7931696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			/* No data for other channels */
7941696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk			continue;
7951696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		}
7961696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
7971696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		twl6030_calibrate_channel(gpadc, chn, d1, d2);
7981696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	}
7991696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
8001696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return 0;
8011696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
8021696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
8031696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#define TWL6030_GPADC_CHAN(chn, _type, chan_info) {	\
8041696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.type = _type,					\
8051696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.channel = chn,					\
8061696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.info_mask_separate = BIT(chan_info),		\
8071696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.indexed = 1,					\
8081696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
8091696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
8101696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic const struct iio_chan_spec twl6030_gpadc_iio_channels[] = {
8111696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(0, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8121696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(1, IIO_TEMP, IIO_CHAN_INFO_RAW),
8131696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(2, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8141696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(3, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8151696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(4, IIO_TEMP, IIO_CHAN_INFO_RAW),
8161696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(5, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8171696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(6, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8181696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(7, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8191696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(8, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8201696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(9, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8211696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(10, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8221696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(11, IIO_VOLTAGE, IIO_CHAN_INFO_RAW),
8231696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(14, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8241696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk};
8251696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
8261696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic const struct iio_chan_spec twl6032_gpadc_iio_channels[] = {
8271696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(0, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8281696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(1, IIO_TEMP, IIO_CHAN_INFO_RAW),
8291696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(2, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8301696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(3, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8311696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(4, IIO_TEMP, IIO_CHAN_INFO_RAW),
8321696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(5, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8331696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(6, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8341696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(7, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8351696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(8, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8361696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(9, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8371696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(10, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8381696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(11, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8391696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(14, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8401696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(17, IIO_VOLTAGE, IIO_CHAN_INFO_RAW),
8411696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	TWL6030_GPADC_CHAN(18, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
8421696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk};
8431696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
8441696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic const struct iio_info twl6030_gpadc_iio_info = {
8451696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.read_raw = &twl6030_gpadc_read_raw,
8461696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.driver_module = THIS_MODULE,
8471696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk};
8481696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
8491696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic const struct twl6030_gpadc_platform_data twl6030_pdata = {
8501696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.iio_channels = twl6030_gpadc_iio_channels,
8511696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.nchannels = TWL6030_GPADC_USED_CHANNELS,
8521696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.ideal = twl6030_ideal,
8531696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.start_conversion = twl6030_start_conversion,
8541696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.channel_to_reg = twl6030_channel_to_reg,
8551696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.calibrate = twl6030_calibration,
8561696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk};
8571696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
8581696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic const struct twl6030_gpadc_platform_data twl6032_pdata = {
8591696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.iio_channels = twl6032_gpadc_iio_channels,
8601696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.nchannels = TWL6032_GPADC_USED_CHANNELS,
8611696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.ideal = twl6032_ideal,
8621696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.start_conversion = twl6032_start_conversion,
8631696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.channel_to_reg = twl6032_channel_to_reg,
8641696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.calibrate = twl6032_calibration,
8651696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk};
8661696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
8671696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic const struct of_device_id of_twl6030_match_tbl[] = {
8681696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	{
8691696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.compatible = "ti,twl6030-gpadc",
8701696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.data = &twl6030_pdata,
8711696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
8721696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	{
8731696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.compatible = "ti,twl6032-gpadc",
8741696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.data = &twl6032_pdata,
8751696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
8761696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	{ /* end */ }
8771696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk};
8781696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
8791696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6030_gpadc_probe(struct platform_device *pdev)
8801696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
8811696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	struct device *dev = &pdev->dev;
8821696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	struct twl6030_gpadc_data *gpadc;
8831696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	const struct twl6030_gpadc_platform_data *pdata;
8841696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	const struct of_device_id *match;
8851696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	struct iio_dev *indio_dev;
8861696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int irq;
8871696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int ret;
8881696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
889fc21acc471d30ecb2c594400c613ed0d56a8a457Sachin Kamat	match = of_match_device(of_twl6030_match_tbl, dev);
8901696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (!match)
8911696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		return -EINVAL;
8921696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
8931696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	pdata = match->data;
8941696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
895fa659a40b80b06140390c364362d7ca942e2b2f6Oleksandr Kozaruk	indio_dev = devm_iio_device_alloc(dev, sizeof(*gpadc));
896fa659a40b80b06140390c364362d7ca942e2b2f6Oleksandr Kozaruk	if (!indio_dev)
897fa659a40b80b06140390c364362d7ca942e2b2f6Oleksandr Kozaruk		return -ENOMEM;
8981696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
8991696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	gpadc = iio_priv(indio_dev);
9001696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9011696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	gpadc->twl6030_cal_tbl = devm_kzalloc(dev,
9021696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk					sizeof(*gpadc->twl6030_cal_tbl) *
9031696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk					pdata->nchannels, GFP_KERNEL);
9041696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (!gpadc->twl6030_cal_tbl)
905fa659a40b80b06140390c364362d7ca942e2b2f6Oleksandr Kozaruk		return -ENOMEM;
9061696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9071696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	gpadc->dev = dev;
9081696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	gpadc->pdata = pdata;
9091696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9101696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	platform_set_drvdata(pdev, indio_dev);
9111696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	mutex_init(&gpadc->lock);
9121696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	init_completion(&gpadc->irq_complete);
9131696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9141696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	ret = pdata->calibrate(gpadc);
9151696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (ret < 0) {
9161696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		dev_err(&pdev->dev, "failed to read calibration registers\n");
917fa659a40b80b06140390c364362d7ca942e2b2f6Oleksandr Kozaruk		return ret;
9181696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	}
9191696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9201696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	irq = platform_get_irq(pdev, 0);
9211696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (irq < 0) {
9221696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		dev_err(&pdev->dev, "failed to get irq\n");
923fa659a40b80b06140390c364362d7ca942e2b2f6Oleksandr Kozaruk		return irq;
9241696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	}
9251696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
926fa659a40b80b06140390c364362d7ca942e2b2f6Oleksandr Kozaruk	ret = devm_request_threaded_irq(dev, irq, NULL,
927fa659a40b80b06140390c364362d7ca942e2b2f6Oleksandr Kozaruk				twl6030_gpadc_irq_handler,
9281696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk				IRQF_ONESHOT, "twl6030_gpadc", indio_dev);
9291696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9301696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	ret = twl6030_gpadc_enable_irq(TWL6030_GPADC_RT_SW1_EOC_MASK);
9311696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (ret < 0) {
9321696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		dev_err(&pdev->dev, "failed to enable GPADC interrupt\n");
933fa659a40b80b06140390c364362d7ca942e2b2f6Oleksandr Kozaruk		return ret;
9341696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	}
9351696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9361696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, TWL6030_GPADCS,
9371696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk					TWL6030_REG_TOGGLE1);
9381696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (ret < 0) {
9391696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		dev_err(&pdev->dev, "failed to enable GPADC module\n");
940fa659a40b80b06140390c364362d7ca942e2b2f6Oleksandr Kozaruk		return ret;
9411696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	}
9421696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9431696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	indio_dev->name = DRIVER_NAME;
9441696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	indio_dev->dev.parent = dev;
9451696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	indio_dev->info = &twl6030_gpadc_iio_info;
9461696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	indio_dev->modes = INDIO_DIRECT_MODE;
9471696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	indio_dev->channels = pdata->iio_channels;
9481696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	indio_dev->num_channels = pdata->nchannels;
9491696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
950ae0f29d1593fabb8eade5f93352e05f88f6245bdSachin Kamat	return iio_device_register(indio_dev);
9511696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
9521696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9531696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6030_gpadc_remove(struct platform_device *pdev)
9541696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
9551696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
9561696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9571696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	twl6030_gpadc_disable_irq(TWL6030_GPADC_RT_SW1_EOC_MASK);
9581696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	iio_device_unregister(indio_dev);
9591696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9601696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return 0;
9611696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk}
9621696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9631696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#ifdef CONFIG_PM_SLEEP
9641696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6030_gpadc_suspend(struct device *pdev)
9651696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
9661696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int ret;
9671696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9681696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, TWL6030_GPADCR,
9691696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk				TWL6030_REG_TOGGLE1);
9701696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (ret)
97177d84ff87e9d38072abcca665ca22cb1da41cb86Masanari Iida		dev_err(pdev, "error resetting GPADC (%d)!\n", ret);
9721696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9731696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return 0;
9741696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk};
9751696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9761696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic int twl6030_gpadc_resume(struct device *pdev)
9771696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk{
9781696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	int ret;
9791696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9801696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, TWL6030_GPADCS,
9811696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk				TWL6030_REG_TOGGLE1);
9821696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	if (ret)
9831696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		dev_err(pdev, "error setting GPADC (%d)!\n", ret);
9841696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9851696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	return 0;
9861696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk};
9871696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk#endif
9881696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9891696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic SIMPLE_DEV_PM_OPS(twl6030_gpadc_pm_ops, twl6030_gpadc_suspend,
9901696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk					twl6030_gpadc_resume);
9911696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
9921696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukstatic struct platform_driver twl6030_gpadc_driver = {
9931696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.probe		= twl6030_gpadc_probe,
9941696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.remove		= twl6030_gpadc_remove,
9951696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	.driver		= {
9961696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.name	= DRIVER_NAME,
9971696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.pm	= &twl6030_gpadc_pm_ops,
9981696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk		.of_match_table = of_twl6030_match_tbl,
9991696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk	},
10001696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk};
10011696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
10021696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozarukmodule_platform_driver(twl6030_gpadc_driver);
10031696f36482e7063051a1dad86a54be83fd847f4fOleksandr Kozaruk
10041696f36482e7063051a1dad86a54be83fd847f4fOleksandr KozarukMODULE_ALIAS("platform: " DRIVER_NAME);
10051696f36482e7063051a1dad86a54be83fd847f4fOleksandr KozarukMODULE_AUTHOR("Balaji T K <balajitk@ti.com>");
10061696f36482e7063051a1dad86a54be83fd847f4fOleksandr KozarukMODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
10071696f36482e7063051a1dad86a54be83fd847f4fOleksandr KozarukMODULE_AUTHOR("Oleksandr Kozaruk <oleksandr.kozaruk@ti.com");
10081696f36482e7063051a1dad86a54be83fd847f4fOleksandr KozarukMODULE_DESCRIPTION("twl6030 ADC driver");
10091696f36482e7063051a1dad86a54be83fd847f4fOleksandr KozarukMODULE_LICENSE("GPL");
1010