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