^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * TWL6030 GPADC module driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2009-2013 Texas Instruments Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Nishant Kamat <nskamat@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Balaji T K <balajitk@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Graeme Gregory <gg@slimlogic.co.uk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Girish S Ghongdemath <girishsg@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Ambresh K <ambresh@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Oleksandr Kozaruk <oleksandr.kozaruk@ti.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Based on twl4030-madc.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Copyright (C) 2008 Nokia Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Mikko Ylinen <mikko.k.ylinen@nokia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/mfd/twl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/iio/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define DRIVER_NAME "twl6030_gpadc"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * twl6030 per TRM has 17 channels, and twl6032 has 19 channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * 2 test network channels are not used,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * 2 die temperature channels are not used either, as it is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * defined how to convert ADC value to temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define TWL6030_GPADC_USED_CHANNELS 13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define TWL6030_GPADC_MAX_CHANNELS 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define TWL6032_GPADC_USED_CHANNELS 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define TWL6032_GPADC_MAX_CHANNELS 19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define TWL6030_GPADC_NUM_TRIM_REGS 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define TWL6030_GPADC_CTRL_P1 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define TWL6032_GPADC_GPSELECT_ISB 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define TWL6032_GPADC_CTRL_P1 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define TWL6032_GPADC_GPCH0_LSB 0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define TWL6032_GPADC_GPCH0_MSB 0x0e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define TWL6030_GPADC_CTRL_P1_SP1 BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define TWL6030_GPADC_GPCH0_LSB (0x29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define TWL6030_GPADC_RT_SW1_EOC_MASK BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define TWL6030_GPADC_TRIM1 0xCD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define TWL6030_REG_TOGGLE1 0x90
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define TWL6030_GPADCS BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define TWL6030_GPADCR BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * struct twl6030_chnl_calib - channel calibration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * @gain: slope coefficient for ideal curve
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * @gain_error: gain error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * @offset_error: offset of the real curve
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct twl6030_chnl_calib {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) s32 gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) s32 gain_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) s32 offset_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * struct twl6030_ideal_code - GPADC calibration parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * GPADC is calibrated in two points: close to the beginning and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * to the and of the measurable input range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * @channel: channel number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * @code1: ideal code for the input at the beginning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * @code2: ideal code for at the end of the range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * @volt1: voltage input at the beginning(low voltage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * @volt2: voltage input at the end(high voltage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct twl6030_ideal_code {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) u16 code1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) u16 code2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) u16 volt1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) u16 volt2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct twl6030_gpadc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * struct twl6030_gpadc_platform_data - platform specific data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * @nchannels: number of GPADC channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * @iio_channels: iio channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * @ideal: pointer to calibration parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * @start_conversion: pointer to ADC start conversion function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * @channel_to_reg: pointer to ADC function to convert channel to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * register address for reading conversion result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * @calibrate: pointer to calibration function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct twl6030_gpadc_platform_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) const int nchannels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) const struct iio_chan_spec *iio_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) const struct twl6030_ideal_code *ideal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) int (*start_conversion)(int channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u8 (*channel_to_reg)(int channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int (*calibrate)(struct twl6030_gpadc_data *gpadc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * struct twl6030_gpadc_data - GPADC data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * @dev: device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * @lock: mutual exclusion lock for the structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * @irq_complete: completion to signal end of conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * @twl6030_cal_tbl: pointer to calibration data for each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * channel with gain error and offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * @pdata: pointer to device specific data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct twl6030_gpadc_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct completion irq_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct twl6030_chnl_calib *twl6030_cal_tbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) const struct twl6030_gpadc_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * channels 11, 12, 13, 15 and 16 have no calibration data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * calibration offset is same for channels 1, 3, 4, 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * The data is taken from GPADC_TRIM registers description.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * GPADC_TRIM registers keep difference between the code measured
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * at volt1 and volt2 input voltages and corresponding code1 and code2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static const struct twl6030_ideal_code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) twl6030_ideal[TWL6030_GPADC_USED_CHANNELS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) [0] = { /* ch 0, external, battery type, resistor value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .channel = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .code1 = 116,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .code2 = 745,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .volt1 = 141,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .volt2 = 910,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) [1] = { /* ch 1, external, battery temperature, NTC resistor value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .channel = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .code1 = 82,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .code2 = 900,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .volt1 = 100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .volt2 = 1100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) [2] = { /* ch 2, external, audio accessory/general purpose */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .channel = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .code1 = 55,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .code2 = 818,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .volt1 = 101,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .volt2 = 1499,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) [3] = { /* ch 3, external, general purpose */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .channel = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .code1 = 82,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .code2 = 900,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .volt1 = 100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .volt2 = 1100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) [4] = { /* ch 4, external, temperature measurement/general purpose */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .channel = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .code1 = 82,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .code2 = 900,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .volt1 = 100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .volt2 = 1100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) [5] = { /* ch 5, external, general purpose */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .channel = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .code1 = 82,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .code2 = 900,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .volt1 = 100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .volt2 = 1100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) [6] = { /* ch 6, external, general purpose */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .channel = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .code1 = 82,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .code2 = 900,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .volt1 = 100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .volt2 = 1100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) [7] = { /* ch 7, internal, main battery */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .channel = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) .code1 = 614,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .code2 = 941,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .volt1 = 3001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .volt2 = 4599,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) [8] = { /* ch 8, internal, backup battery */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .channel = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .code1 = 82,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .code2 = 688,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .volt1 = 501,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .volt2 = 4203,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) [9] = { /* ch 9, internal, external charger input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .channel = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .code1 = 182,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .code2 = 818,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .volt1 = 2001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .volt2 = 8996,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) [10] = { /* ch 10, internal, VBUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .channel = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .code1 = 149,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .code2 = 818,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .volt1 = 1001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .volt2 = 5497,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) [11] = { /* ch 11, internal, VBUS charging current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .channel = 11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* ch 12, internal, Die temperature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /* ch 13, internal, Die temperature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) [12] = { /* ch 14, internal, USB ID line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .channel = 14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .code1 = 48,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .code2 = 714,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .volt1 = 323,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) .volt2 = 4800,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static const struct twl6030_ideal_code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) twl6032_ideal[TWL6032_GPADC_USED_CHANNELS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) [0] = { /* ch 0, external, battery type, resistor value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) .channel = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .code1 = 1441,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) .code2 = 3276,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .volt1 = 440,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .volt2 = 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) [1] = { /* ch 1, external, battery temperature, NTC resistor value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .channel = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .code1 = 1441,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .code2 = 3276,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .volt1 = 440,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .volt2 = 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) [2] = { /* ch 2, external, audio accessory/general purpose */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) .channel = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .code1 = 1441,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) .code2 = 3276,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) .volt1 = 660,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) .volt2 = 1500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) [3] = { /* ch 3, external, temperature with external diode/general
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) purpose */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .channel = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .code1 = 1441,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .code2 = 3276,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .volt1 = 440,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .volt2 = 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) [4] = { /* ch 4, external, temperature measurement/general purpose */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .channel = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .code1 = 1441,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .code2 = 3276,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .volt1 = 440,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .volt2 = 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) [5] = { /* ch 5, external, general purpose */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) .channel = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) .code1 = 1441,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .code2 = 3276,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) .volt1 = 440,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) .volt2 = 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) [6] = { /* ch 6, external, general purpose */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) .channel = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) .code1 = 1441,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) .code2 = 3276,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .volt1 = 440,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .volt2 = 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) [7] = { /* ch7, internal, system supply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .channel = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) .code1 = 1441,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) .code2 = 3276,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) .volt1 = 2200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) .volt2 = 5000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) [8] = { /* ch8, internal, backup battery */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .channel = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) .code1 = 1441,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .code2 = 3276,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .volt1 = 2200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) .volt2 = 5000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) [9] = { /* ch 9, internal, external charger input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) .channel = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) .code1 = 1441,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) .code2 = 3276,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) .volt1 = 3960,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .volt2 = 9000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) [10] = { /* ch10, internal, VBUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) .channel = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) .code1 = 150,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) .code2 = 751,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) .volt1 = 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) .volt2 = 5000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) [11] = { /* ch 11, internal, VBUS DC-DC output current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) .channel = 11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) .code1 = 1441,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) .code2 = 3276,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) .volt1 = 660,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) .volt2 = 1500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /* ch 12, internal, Die temperature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* ch 13, internal, Die temperature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) [12] = { /* ch 14, internal, USB ID line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) .channel = 14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) .code1 = 1441,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) .code2 = 3276,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) .volt1 = 2420,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) .volt2 = 5500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /* ch 15, internal, test network */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /* ch 16, internal, test network */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) [13] = { /* ch 17, internal, battery charging current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .channel = 17,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) [14] = { /* ch 18, internal, battery voltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) .channel = 18,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) .code1 = 1441,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) .code2 = 3276,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) .volt1 = 2200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) .volt2 = 5000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static inline int twl6030_gpadc_write(u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return twl_i2c_write_u8(TWL6030_MODULE_GPADC, val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static inline int twl6030_gpadc_read(u8 reg, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return twl_i2c_read(TWL6030_MODULE_GPADC, val, reg, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static int twl6030_gpadc_enable_irq(u8 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) ret = twl6030_interrupt_unmask(mask, REG_INT_MSK_LINE_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) ret = twl6030_interrupt_unmask(mask, REG_INT_MSK_STS_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static void twl6030_gpadc_disable_irq(u8 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) twl6030_interrupt_mask(mask, REG_INT_MSK_LINE_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) twl6030_interrupt_mask(mask, REG_INT_MSK_STS_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static irqreturn_t twl6030_gpadc_irq_handler(int irq, void *indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct twl6030_gpadc_data *gpadc = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) complete(&gpadc->irq_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static int twl6030_start_conversion(int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return twl6030_gpadc_write(TWL6030_GPADC_CTRL_P1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) TWL6030_GPADC_CTRL_P1_SP1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static int twl6032_start_conversion(int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) ret = twl6030_gpadc_write(TWL6032_GPADC_GPSELECT_ISB, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return twl6030_gpadc_write(TWL6032_GPADC_CTRL_P1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) TWL6030_GPADC_CTRL_P1_SP1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static u8 twl6030_channel_to_reg(int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return TWL6030_GPADC_GPCH0_LSB + 2 * channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) static u8 twl6032_channel_to_reg(int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * for any prior chosen channel, when the conversion is ready
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * the result is avalable in GPCH0_LSB, GPCH0_MSB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return TWL6032_GPADC_GPCH0_LSB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static int twl6030_gpadc_lookup(const struct twl6030_ideal_code *ideal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) int channel, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) for (i = 0; i < size; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (ideal[i].channel == channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) static int twl6030_channel_calibrated(const struct twl6030_gpadc_platform_data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) *pdata, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) const struct twl6030_ideal_code *ideal = pdata->ideal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) i = twl6030_gpadc_lookup(ideal, channel, pdata->nchannels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* not calibrated channels have 0 in all structure members */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return pdata->ideal[i].code2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static int twl6030_gpadc_make_correction(struct twl6030_gpadc_data *gpadc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) int channel, int raw_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) const struct twl6030_ideal_code *ideal = gpadc->pdata->ideal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) int corrected_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) i = twl6030_gpadc_lookup(ideal, channel, gpadc->pdata->nchannels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) corrected_code = ((raw_code * 1000) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) gpadc->twl6030_cal_tbl[i].offset_error) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) gpadc->twl6030_cal_tbl[i].gain_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return corrected_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static int twl6030_gpadc_get_raw(struct twl6030_gpadc_data *gpadc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) int channel, int *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) u8 reg = gpadc->pdata->channel_to_reg(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) __le16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) int raw_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) ret = twl6030_gpadc_read(reg, (u8 *)&val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) dev_dbg(gpadc->dev, "unable to read register 0x%X\n", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) raw_code = le16_to_cpu(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) dev_dbg(gpadc->dev, "GPADC raw code: %d", raw_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (twl6030_channel_calibrated(gpadc->pdata, channel))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) *res = twl6030_gpadc_make_correction(gpadc, channel, raw_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) *res = raw_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static int twl6030_gpadc_get_processed(struct twl6030_gpadc_data *gpadc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int channel, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) const struct twl6030_ideal_code *ideal = gpadc->pdata->ideal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) int corrected_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) int channel_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) ret = twl6030_gpadc_get_raw(gpadc, channel, &corrected_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) i = twl6030_gpadc_lookup(ideal, channel, gpadc->pdata->nchannels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) channel_value = corrected_code *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) gpadc->twl6030_cal_tbl[i].gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* Shift back into mV range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) channel_value /= 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) dev_dbg(gpadc->dev, "GPADC corrected code: %d", corrected_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) dev_dbg(gpadc->dev, "GPADC value: %d", channel_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) *val = channel_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) static int twl6030_gpadc_read_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) int *val, int *val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) struct twl6030_gpadc_data *gpadc = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) mutex_lock(&gpadc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) ret = gpadc->pdata->start_conversion(chan->channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) dev_err(gpadc->dev, "failed to start conversion\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /* wait for conversion to complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) timeout = wait_for_completion_interruptible_timeout(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) &gpadc->irq_complete, msecs_to_jiffies(5000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (timeout == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) } else if (timeout < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) ret = -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) case IIO_CHAN_INFO_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) ret = twl6030_gpadc_get_raw(gpadc, chan->channel, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) ret = ret ? -EIO : IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) case IIO_CHAN_INFO_PROCESSED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) ret = twl6030_gpadc_get_processed(gpadc, chan->channel, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) ret = ret ? -EIO : IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) mutex_unlock(&gpadc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * The GPADC channels are calibrated using a two point calibration method.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) * The channels measured with two known values: volt1 and volt2, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * ideal corresponding output codes are known: code1, code2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) * The difference(d1, d2) between ideal and measured codes stored in trim
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * The goal is to find offset and gain of the real curve for each calibrated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * gain: k = 1 + ((d2 - d1) / (x2 - x1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) * offset: b = d1 + (k - 1) * x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) static void twl6030_calibrate_channel(struct twl6030_gpadc_data *gpadc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) int channel, int d1, int d2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) int b, k, gain, x1, x2, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) const struct twl6030_ideal_code *ideal = gpadc->pdata->ideal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) i = twl6030_gpadc_lookup(ideal, channel, gpadc->pdata->nchannels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) /* Gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) gain = ((ideal[i].volt2 - ideal[i].volt1) * 1000) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) (ideal[i].code2 - ideal[i].code1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) x1 = ideal[i].code1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) x2 = ideal[i].code2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) /* k - real curve gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) k = 1000 + (((d2 - d1) * 1000) / (x2 - x1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) /* b - offset of the real curve gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) b = (d1 * 1000) - (k - 1000) * x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) gpadc->twl6030_cal_tbl[i].gain = gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) gpadc->twl6030_cal_tbl[i].gain_error = k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) gpadc->twl6030_cal_tbl[i].offset_error = b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) dev_dbg(gpadc->dev, "GPADC d1 for Chn: %d = %d\n", channel, d1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) dev_dbg(gpadc->dev, "GPADC d2 for Chn: %d = %d\n", channel, d2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) dev_dbg(gpadc->dev, "GPADC x1 for Chn: %d = %d\n", channel, x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) dev_dbg(gpadc->dev, "GPADC x2 for Chn: %d = %d\n", channel, x2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) dev_dbg(gpadc->dev, "GPADC Gain for Chn: %d = %d\n", channel, gain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) dev_dbg(gpadc->dev, "GPADC k for Chn: %d = %d\n", channel, k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) dev_dbg(gpadc->dev, "GPADC b for Chn: %d = %d\n", channel, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) static inline int twl6030_gpadc_get_trim_offset(s8 d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) * XXX NOTE!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) * bit 0 - sign, bit 7 - reserved, 6..1 - trim value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * though, the documentation states that trim value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) * is absolute value, the correct conversion results are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * obtained if the value is interpreted as 2's complement.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) __u32 temp = ((d & 0x7f) >> 1) | ((d & 1) << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return sign_extend32(temp, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) static int twl6030_calibration(struct twl6030_gpadc_data *gpadc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) int chn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) u8 trim_regs[TWL6030_GPADC_NUM_TRIM_REGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) s8 d1, d2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * for calibration two measurements have been performed at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * factory, for some channels, during the production test and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * have been stored in registers. This two stored values are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * used to correct the measurements. The values represent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * offsets for the given input from the output on ideal curve.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) ret = twl_i2c_read(TWL6030_MODULE_ID2, trim_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) TWL6030_GPADC_TRIM1, TWL6030_GPADC_NUM_TRIM_REGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) dev_err(gpadc->dev, "calibration failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) for (chn = 0; chn < TWL6030_GPADC_MAX_CHANNELS; chn++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) switch (chn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) d1 = trim_regs[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) d2 = trim_regs[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) d1 = trim_regs[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) d2 = trim_regs[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) d1 = trim_regs[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) d2 = trim_regs[13];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) d1 = trim_regs[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) d2 = trim_regs[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) d1 = trim_regs[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) d2 = trim_regs[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) case 9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) d1 = trim_regs[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) d2 = trim_regs[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) case 10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) d1 = trim_regs[10];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) d2 = trim_regs[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) case 14:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) d1 = trim_regs[14];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) d2 = trim_regs[15];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) d1 = twl6030_gpadc_get_trim_offset(d1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) d2 = twl6030_gpadc_get_trim_offset(d2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) twl6030_calibrate_channel(gpadc, chn, d1, d2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) static int twl6032_get_trim_value(u8 *trim_regs, unsigned int reg0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) unsigned int reg1, unsigned int mask0, unsigned int mask1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) unsigned int shift0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) val = (trim_regs[reg0] & mask0) << shift0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) val |= (trim_regs[reg1] & mask1) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (trim_regs[reg1] & 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) val = -val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) static int twl6032_calibration(struct twl6030_gpadc_data *gpadc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) int chn, d1 = 0, d2 = 0, temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) u8 trim_regs[TWL6030_GPADC_NUM_TRIM_REGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) ret = twl_i2c_read(TWL6030_MODULE_ID2, trim_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) TWL6030_GPADC_TRIM1, TWL6030_GPADC_NUM_TRIM_REGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) dev_err(gpadc->dev, "calibration failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) * Loop to calculate the value needed for returning voltages from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * GPADC not values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) * gain is calculated to 3 decimal places fixed point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) for (chn = 0; chn < TWL6032_GPADC_MAX_CHANNELS; chn++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) switch (chn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) case 11:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) case 14:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) d1 = twl6032_get_trim_value(trim_regs, 2, 0, 0x1f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 0x06, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) d2 = twl6032_get_trim_value(trim_regs, 3, 1, 0x3f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 0x06, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) temp = twl6032_get_trim_value(trim_regs, 2, 0, 0x1f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 0x06, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) d1 = temp + twl6032_get_trim_value(trim_regs, 7, 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 0x18, 0x1E, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) temp = twl6032_get_trim_value(trim_regs, 3, 1, 0x3F,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 0x06, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) d2 = temp + twl6032_get_trim_value(trim_regs, 9, 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 0x1F, 0x06, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) case 9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) temp = twl6032_get_trim_value(trim_regs, 2, 0, 0x1f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 0x06, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) d1 = temp + twl6032_get_trim_value(trim_regs, 13, 11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 0x18, 0x1E, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) temp = twl6032_get_trim_value(trim_regs, 3, 1, 0x3f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 0x06, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) d2 = temp + twl6032_get_trim_value(trim_regs, 15, 13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 0x1F, 0x06, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) case 10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) d1 = twl6032_get_trim_value(trim_regs, 10, 8, 0x0f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 0x0E, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) d2 = twl6032_get_trim_value(trim_regs, 14, 12, 0x0f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 0x0E, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) case 18:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) temp = twl6032_get_trim_value(trim_regs, 2, 0, 0x1f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 0x06, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) d1 = (trim_regs[4] & 0x7E) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (trim_regs[4] & 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) d1 = -d1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) d1 += temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) temp = twl6032_get_trim_value(trim_regs, 3, 1, 0x3f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 0x06, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) d2 = (trim_regs[5] & 0xFE) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (trim_regs[5] & 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) d2 = -d2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) d2 += temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) /* No data for other channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) twl6030_calibrate_channel(gpadc, chn, d1, d2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) #define TWL6030_GPADC_CHAN(chn, _type, chan_info) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .type = _type, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .channel = chn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .info_mask_separate = BIT(chan_info), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) .indexed = 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) static const struct iio_chan_spec twl6030_gpadc_iio_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) TWL6030_GPADC_CHAN(0, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) TWL6030_GPADC_CHAN(1, IIO_TEMP, IIO_CHAN_INFO_RAW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) TWL6030_GPADC_CHAN(2, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) TWL6030_GPADC_CHAN(3, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) TWL6030_GPADC_CHAN(4, IIO_TEMP, IIO_CHAN_INFO_RAW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) TWL6030_GPADC_CHAN(5, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) TWL6030_GPADC_CHAN(6, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) TWL6030_GPADC_CHAN(7, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) TWL6030_GPADC_CHAN(8, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) TWL6030_GPADC_CHAN(9, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) TWL6030_GPADC_CHAN(10, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) TWL6030_GPADC_CHAN(11, IIO_VOLTAGE, IIO_CHAN_INFO_RAW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) TWL6030_GPADC_CHAN(14, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) static const struct iio_chan_spec twl6032_gpadc_iio_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) TWL6030_GPADC_CHAN(0, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) TWL6030_GPADC_CHAN(1, IIO_TEMP, IIO_CHAN_INFO_RAW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) TWL6030_GPADC_CHAN(2, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) TWL6030_GPADC_CHAN(3, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) TWL6030_GPADC_CHAN(4, IIO_TEMP, IIO_CHAN_INFO_RAW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) TWL6030_GPADC_CHAN(5, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) TWL6030_GPADC_CHAN(6, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) TWL6030_GPADC_CHAN(7, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) TWL6030_GPADC_CHAN(8, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) TWL6030_GPADC_CHAN(9, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) TWL6030_GPADC_CHAN(10, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) TWL6030_GPADC_CHAN(11, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) TWL6030_GPADC_CHAN(14, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) TWL6030_GPADC_CHAN(17, IIO_VOLTAGE, IIO_CHAN_INFO_RAW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) TWL6030_GPADC_CHAN(18, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) static const struct iio_info twl6030_gpadc_iio_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) .read_raw = &twl6030_gpadc_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) static const struct twl6030_gpadc_platform_data twl6030_pdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) .iio_channels = twl6030_gpadc_iio_channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) .nchannels = TWL6030_GPADC_USED_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) .ideal = twl6030_ideal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) .start_conversion = twl6030_start_conversion,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) .channel_to_reg = twl6030_channel_to_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) .calibrate = twl6030_calibration,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) static const struct twl6030_gpadc_platform_data twl6032_pdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) .iio_channels = twl6032_gpadc_iio_channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) .nchannels = TWL6032_GPADC_USED_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) .ideal = twl6032_ideal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) .start_conversion = twl6032_start_conversion,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) .channel_to_reg = twl6032_channel_to_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) .calibrate = twl6032_calibration,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) static const struct of_device_id of_twl6030_match_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) .compatible = "ti,twl6030-gpadc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) .data = &twl6030_pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) .compatible = "ti,twl6032-gpadc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) .data = &twl6032_pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) { /* end */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) MODULE_DEVICE_TABLE(of, of_twl6030_match_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) static int twl6030_gpadc_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct twl6030_gpadc_data *gpadc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) const struct twl6030_gpadc_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) match = of_match_device(of_twl6030_match_tbl, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (!match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) pdata = match->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) indio_dev = devm_iio_device_alloc(dev, sizeof(*gpadc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if (!indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) gpadc = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) gpadc->twl6030_cal_tbl = devm_kcalloc(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) pdata->nchannels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) sizeof(*gpadc->twl6030_cal_tbl),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (!gpadc->twl6030_cal_tbl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) gpadc->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) gpadc->pdata = pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) platform_set_drvdata(pdev, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) mutex_init(&gpadc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) init_completion(&gpadc->irq_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) ret = pdata->calibrate(gpadc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) dev_err(&pdev->dev, "failed to read calibration registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) ret = devm_request_threaded_irq(dev, irq, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) twl6030_gpadc_irq_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) IRQF_ONESHOT, "twl6030_gpadc", indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) ret = twl6030_gpadc_enable_irq(TWL6030_GPADC_RT_SW1_EOC_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) dev_err(&pdev->dev, "failed to enable GPADC interrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, TWL6030_GPADCS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) TWL6030_REG_TOGGLE1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) dev_err(&pdev->dev, "failed to enable GPADC module\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) indio_dev->name = DRIVER_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) indio_dev->info = &twl6030_gpadc_iio_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) indio_dev->modes = INDIO_DIRECT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) indio_dev->channels = pdata->iio_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) indio_dev->num_channels = pdata->nchannels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) return iio_device_register(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) static int twl6030_gpadc_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) struct iio_dev *indio_dev = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) twl6030_gpadc_disable_irq(TWL6030_GPADC_RT_SW1_EOC_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) iio_device_unregister(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) static int twl6030_gpadc_suspend(struct device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, TWL6030_GPADCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) TWL6030_REG_TOGGLE1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) dev_err(pdev, "error resetting GPADC (%d)!\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) static int twl6030_gpadc_resume(struct device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, TWL6030_GPADCS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) TWL6030_REG_TOGGLE1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) dev_err(pdev, "error setting GPADC (%d)!\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) static SIMPLE_DEV_PM_OPS(twl6030_gpadc_pm_ops, twl6030_gpadc_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) twl6030_gpadc_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) static struct platform_driver twl6030_gpadc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) .probe = twl6030_gpadc_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) .remove = twl6030_gpadc_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) .pm = &twl6030_gpadc_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) .of_match_table = of_twl6030_match_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) module_platform_driver(twl6030_gpadc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) MODULE_ALIAS("platform:" DRIVER_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) MODULE_AUTHOR("Balaji T K <balajitk@ti.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) MODULE_AUTHOR("Oleksandr Kozaruk <oleksandr.kozaruk@ti.com");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) MODULE_DESCRIPTION("twl6030 ADC driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) MODULE_LICENSE("GPL");