^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) * Copyright (C) 2017 Tony Lindgren <tony@atomide.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Rewritten for Linux IIO framework with some code based on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * earlier driver found in the Motorola Linux kernel:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2009-2010 Motorola, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mod_devicetable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/iio/buffer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/iio/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/iio/kfifo_buf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/mfd/motorola-cpcap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* Register CPCAP_REG_ADCC1 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define CPCAP_BIT_ADEN_AUTO_CLR BIT(15) /* Currently unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define CPCAP_BIT_CAL_MODE BIT(14) /* Set with BIT_RAND0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define CPCAP_BIT_ADC_CLK_SEL1 BIT(13) /* Currently unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define CPCAP_BIT_ADC_CLK_SEL0 BIT(12) /* Currently unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define CPCAP_BIT_ATOX BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define CPCAP_BIT_ATO3 BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define CPCAP_BIT_ATO2 BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define CPCAP_BIT_ATO1 BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define CPCAP_BIT_ATO0 BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define CPCAP_BIT_ADA2 BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define CPCAP_BIT_ADA1 BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define CPCAP_BIT_ADA0 BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define CPCAP_BIT_AD_SEL1 BIT(3) /* Set for bank1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define CPCAP_BIT_RAND1 BIT(2) /* Set for channel 16 & 17 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define CPCAP_BIT_RAND0 BIT(1) /* Set with CAL_MODE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define CPCAP_BIT_ADEN BIT(0) /* Currently unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define CPCAP_REG_ADCC1_DEFAULTS (CPCAP_BIT_ADEN_AUTO_CLR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) CPCAP_BIT_ADC_CLK_SEL0 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) CPCAP_BIT_RAND1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* Register CPCAP_REG_ADCC2 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define CPCAP_BIT_CAL_FACTOR_ENABLE BIT(15) /* Currently unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define CPCAP_BIT_BATDETB_EN BIT(14) /* Currently unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define CPCAP_BIT_ADTRIG_ONESHOT BIT(13) /* Set for !TIMING_IMM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define CPCAP_BIT_ASC BIT(12) /* Set for TIMING_IMM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define CPCAP_BIT_ATOX_PS_FACTOR BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define CPCAP_BIT_ADC_PS_FACTOR1 BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define CPCAP_BIT_ADC_PS_FACTOR0 BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define CPCAP_BIT_AD4_SELECT BIT(8) /* Currently unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define CPCAP_BIT_ADC_BUSY BIT(7) /* Currently unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define CPCAP_BIT_THERMBIAS_EN BIT(6) /* Bias for AD0_BATTDETB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define CPCAP_BIT_ADTRIG_DIS BIT(5) /* Disable interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define CPCAP_BIT_LIADC BIT(4) /* Currently unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define CPCAP_BIT_TS_REFEN BIT(3) /* Currently unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define CPCAP_BIT_TS_M2 BIT(2) /* Currently unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define CPCAP_BIT_TS_M1 BIT(1) /* Currently unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define CPCAP_BIT_TS_M0 BIT(0) /* Currently unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define CPCAP_REG_ADCC2_DEFAULTS (CPCAP_BIT_AD4_SELECT | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) CPCAP_BIT_ADTRIG_DIS | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) CPCAP_BIT_LIADC | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) CPCAP_BIT_TS_M2 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) CPCAP_BIT_TS_M1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define CPCAP_MAX_TEMP_LVL 27
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define CPCAP_FOUR_POINT_TWO_ADC 801
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define ST_ADC_CAL_CHRGI_HIGH_THRESHOLD 530
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define ST_ADC_CAL_CHRGI_LOW_THRESHOLD 494
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define ST_ADC_CAL_BATTI_HIGH_THRESHOLD 530
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define ST_ADC_CAL_BATTI_LOW_THRESHOLD 494
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define ST_ADC_CALIBRATE_DIFF_THRESHOLD 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define CPCAP_ADC_MAX_RETRIES 5 /* Calibration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * struct cpcap_adc_ato - timing settings for cpcap adc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * Unfortunately no cpcap documentation available, please document when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * using these.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct cpcap_adc_ato {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) unsigned short ato_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned short atox_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) unsigned short adc_ps_factor_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned short atox_ps_factor_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) unsigned short ato_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) unsigned short atox_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) unsigned short adc_ps_factor_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) unsigned short atox_ps_factor_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * struct cpcap-adc - cpcap adc device driver data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * @reg: cpcap regmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * @dev: struct device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * @vendor: cpcap vendor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * @irq: interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * @lock: mutex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * @ato: request timings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * @wq_data_avail: work queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * @done: work done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct cpcap_adc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct regmap *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) u16 vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct mutex lock; /* ADC register access lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) const struct cpcap_adc_ato *ato;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) wait_queue_head_t wq_data_avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) bool done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * enum cpcap_adc_channel - cpcap adc channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) enum cpcap_adc_channel {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* Bank0 channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) CPCAP_ADC_AD0, /* Battery temperature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) CPCAP_ADC_BATTP, /* Battery voltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) CPCAP_ADC_VBUS, /* USB VBUS voltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) CPCAP_ADC_AD3, /* Die temperature when charging */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) CPCAP_ADC_BPLUS_AD4, /* Another battery or system voltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) CPCAP_ADC_CHG_ISENSE, /* Calibrated charge current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) CPCAP_ADC_BATTI, /* Calibrated system current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) CPCAP_ADC_USB_ID, /* USB OTG ID, unused on droid 4? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* Bank1 channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) CPCAP_ADC_AD8, /* Seems unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) CPCAP_ADC_AD9, /* Seems unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) CPCAP_ADC_LICELL, /* Maybe system voltage? Always 3V */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) CPCAP_ADC_HV_BATTP, /* Another battery detection? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) CPCAP_ADC_TSX1_AD12, /* Seems unused, for touchscreen? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) CPCAP_ADC_TSX2_AD13, /* Seems unused, for touchscreen? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) CPCAP_ADC_TSY1_AD14, /* Seems unused, for touchscreen? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) CPCAP_ADC_TSY2_AD15, /* Seems unused, for touchscreen? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* Remuxed channels using bank0 entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) CPCAP_ADC_BATTP_PI16, /* Alternative mux mode for BATTP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) CPCAP_ADC_BATTI_PI17, /* Alternative mux mode for BATTI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) CPCAP_ADC_CHANNEL_NUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * enum cpcap_adc_timing - cpcap adc timing options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * CPCAP_ADC_TIMING_IMM seems to be immediate with no timings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * Please document when using.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) enum cpcap_adc_timing {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) CPCAP_ADC_TIMING_IMM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) CPCAP_ADC_TIMING_IN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) CPCAP_ADC_TIMING_OUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * struct cpcap_adc_phasing_tbl - cpcap phasing table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * @offset: offset in the phasing table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * @multiplier: multiplier in the phasing table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * @divider: divider in the phasing table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * @min: minimum value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * @max: maximum value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct cpcap_adc_phasing_tbl {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) short offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) unsigned short multiplier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) unsigned short divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) short min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) short max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * struct cpcap_adc_conversion_tbl - cpcap conversion table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * @conv_type: conversion type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * @align_offset: align offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * @conv_offset: conversion offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * @cal_offset: calibration offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * @multiplier: conversion multiplier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * @divider: conversion divider
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct cpcap_adc_conversion_tbl {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) enum iio_chan_info_enum conv_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) int align_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) int conv_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) int cal_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) int multiplier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) int divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * struct cpcap_adc_request - cpcap adc request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * @channel: request channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * @phase_tbl: channel phasing table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * @conv_tbl: channel conversion table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * @bank_index: channel index within the bank
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * @timing: timing settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * @result: result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct cpcap_adc_request {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) int channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) const struct cpcap_adc_phasing_tbl *phase_tbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) const struct cpcap_adc_conversion_tbl *conv_tbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int bank_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) enum cpcap_adc_timing timing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* Phasing table for channels. Note that channels 16 & 17 use BATTP and BATTI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static const struct cpcap_adc_phasing_tbl bank_phasing[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /* Bank0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) [CPCAP_ADC_AD0] = {0, 0x80, 0x80, 0, 1023},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) [CPCAP_ADC_BATTP] = {0, 0x80, 0x80, 0, 1023},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) [CPCAP_ADC_VBUS] = {0, 0x80, 0x80, 0, 1023},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) [CPCAP_ADC_AD3] = {0, 0x80, 0x80, 0, 1023},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) [CPCAP_ADC_BPLUS_AD4] = {0, 0x80, 0x80, 0, 1023},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) [CPCAP_ADC_CHG_ISENSE] = {0, 0x80, 0x80, -512, 511},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) [CPCAP_ADC_BATTI] = {0, 0x80, 0x80, -512, 511},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) [CPCAP_ADC_USB_ID] = {0, 0x80, 0x80, 0, 1023},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* Bank1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) [CPCAP_ADC_AD8] = {0, 0x80, 0x80, 0, 1023},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) [CPCAP_ADC_AD9] = {0, 0x80, 0x80, 0, 1023},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) [CPCAP_ADC_LICELL] = {0, 0x80, 0x80, 0, 1023},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) [CPCAP_ADC_HV_BATTP] = {0, 0x80, 0x80, 0, 1023},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) [CPCAP_ADC_TSX1_AD12] = {0, 0x80, 0x80, 0, 1023},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) [CPCAP_ADC_TSX2_AD13] = {0, 0x80, 0x80, 0, 1023},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) [CPCAP_ADC_TSY1_AD14] = {0, 0x80, 0x80, 0, 1023},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) [CPCAP_ADC_TSY2_AD15] = {0, 0x80, 0x80, 0, 1023},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * Conversion table for channels. Updated during init based on calibration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * Here too channels 16 & 17 use BATTP and BATTI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static struct cpcap_adc_conversion_tbl bank_conversion[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* Bank0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) [CPCAP_ADC_AD0] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) IIO_CHAN_INFO_PROCESSED, 0, 0, 0, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) [CPCAP_ADC_BATTP] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) IIO_CHAN_INFO_PROCESSED, 0, 2400, 0, 2300, 1023,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) [CPCAP_ADC_VBUS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) IIO_CHAN_INFO_PROCESSED, 0, 0, 0, 10000, 1023,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) [CPCAP_ADC_AD3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) IIO_CHAN_INFO_PROCESSED, 0, 0, 0, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) [CPCAP_ADC_BPLUS_AD4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) IIO_CHAN_INFO_PROCESSED, 0, 2400, 0, 2300, 1023,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) [CPCAP_ADC_CHG_ISENSE] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) IIO_CHAN_INFO_PROCESSED, -512, 2, 0, 5000, 1023,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) [CPCAP_ADC_BATTI] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) IIO_CHAN_INFO_PROCESSED, -512, 2, 0, 5000, 1023,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) [CPCAP_ADC_USB_ID] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* Bank1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) [CPCAP_ADC_AD8] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) [CPCAP_ADC_AD9] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) [CPCAP_ADC_LICELL] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) IIO_CHAN_INFO_PROCESSED, 0, 0, 0, 3400, 1023,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) [CPCAP_ADC_HV_BATTP] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) [CPCAP_ADC_TSX1_AD12] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) [CPCAP_ADC_TSX2_AD13] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) [CPCAP_ADC_TSY1_AD14] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) [CPCAP_ADC_TSY2_AD15] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) IIO_CHAN_INFO_RAW, 0, 0, 0, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * Temperature lookup table of register values to milliCelcius.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * REVISIT: Check the duplicate 0x3ff entry in a freezer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static const int temp_map[CPCAP_MAX_TEMP_LVL][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) { 0x03ff, -40000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) { 0x03ff, -35000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) { 0x03ef, -30000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) { 0x03b2, -25000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) { 0x036c, -20000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) { 0x0320, -15000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) { 0x02d0, -10000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) { 0x027f, -5000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) { 0x022f, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) { 0x01e4, 5000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) { 0x019f, 10000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) { 0x0161, 15000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) { 0x012b, 20000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) { 0x00fc, 25000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) { 0x00d4, 30000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) { 0x00b2, 35000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) { 0x0095, 40000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) { 0x007d, 45000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) { 0x0069, 50000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) { 0x0059, 55000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) { 0x004b, 60000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) { 0x003f, 65000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) { 0x0036, 70000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) { 0x002e, 75000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) { 0x0027, 80000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) { 0x0022, 85000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) { 0x001d, 90000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) #define CPCAP_CHAN(_type, _index, _address, _datasheet_name) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) .type = (_type), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) .address = (_address), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) .indexed = 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) .channel = (_index), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) BIT(IIO_CHAN_INFO_PROCESSED), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) .scan_index = (_index), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) .scan_type = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) .sign = 'u', \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) .realbits = 10, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) .storagebits = 16, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) .endianness = IIO_CPU, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) .datasheet_name = (_datasheet_name), \
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * The datasheet names are from Motorola mapphone Linux kernel except
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * for the last two which might be uncalibrated charge voltage and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * current.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static const struct iio_chan_spec cpcap_adc_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /* Bank0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) CPCAP_CHAN(IIO_TEMP, 0, CPCAP_REG_ADCD0, "battdetb"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) CPCAP_CHAN(IIO_VOLTAGE, 1, CPCAP_REG_ADCD1, "battp"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) CPCAP_CHAN(IIO_VOLTAGE, 2, CPCAP_REG_ADCD2, "vbus"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) CPCAP_CHAN(IIO_TEMP, 3, CPCAP_REG_ADCD3, "ad3"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) CPCAP_CHAN(IIO_VOLTAGE, 4, CPCAP_REG_ADCD4, "ad4"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) CPCAP_CHAN(IIO_CURRENT, 5, CPCAP_REG_ADCD5, "chg_isense"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) CPCAP_CHAN(IIO_CURRENT, 6, CPCAP_REG_ADCD6, "batti"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) CPCAP_CHAN(IIO_VOLTAGE, 7, CPCAP_REG_ADCD7, "usb_id"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /* Bank1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) CPCAP_CHAN(IIO_CURRENT, 8, CPCAP_REG_ADCD0, "ad8"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) CPCAP_CHAN(IIO_VOLTAGE, 9, CPCAP_REG_ADCD1, "ad9"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) CPCAP_CHAN(IIO_VOLTAGE, 10, CPCAP_REG_ADCD2, "licell"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) CPCAP_CHAN(IIO_VOLTAGE, 11, CPCAP_REG_ADCD3, "hv_battp"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) CPCAP_CHAN(IIO_VOLTAGE, 12, CPCAP_REG_ADCD4, "tsx1_ad12"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) CPCAP_CHAN(IIO_VOLTAGE, 13, CPCAP_REG_ADCD5, "tsx2_ad13"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) CPCAP_CHAN(IIO_VOLTAGE, 14, CPCAP_REG_ADCD6, "tsy1_ad14"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) CPCAP_CHAN(IIO_VOLTAGE, 15, CPCAP_REG_ADCD7, "tsy2_ad15"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /* There are two registers with multiplexed functionality */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) CPCAP_CHAN(IIO_VOLTAGE, 16, CPCAP_REG_ADCD0, "chg_vsense"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) CPCAP_CHAN(IIO_CURRENT, 17, CPCAP_REG_ADCD1, "batti2"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static irqreturn_t cpcap_adc_irq_thread(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct iio_dev *indio_dev = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct cpcap_adc *ddata = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) CPCAP_BIT_ADTRIG_DIS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) CPCAP_BIT_ADTRIG_DIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) ddata->done = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) wake_up_interruptible(&ddata->wq_data_avail);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /* ADC calibration functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static void cpcap_adc_setup_calibrate(struct cpcap_adc *ddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) enum cpcap_adc_channel chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) unsigned int value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) unsigned long timeout = jiffies + msecs_to_jiffies(3000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if ((chan != CPCAP_ADC_CHG_ISENSE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) (chan != CPCAP_ADC_BATTI))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) value |= CPCAP_BIT_CAL_MODE | CPCAP_BIT_RAND0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) value |= ((chan << 4) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) (CPCAP_BIT_ADA2 | CPCAP_BIT_ADA1 | CPCAP_BIT_ADA0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) CPCAP_BIT_CAL_MODE | CPCAP_BIT_ATOX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) CPCAP_BIT_ATO3 | CPCAP_BIT_ATO2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) CPCAP_BIT_ATO1 | CPCAP_BIT_ATO0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) CPCAP_BIT_ADA2 | CPCAP_BIT_ADA1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) CPCAP_BIT_ADA0 | CPCAP_BIT_AD_SEL1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) CPCAP_BIT_RAND1 | CPCAP_BIT_RAND0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) CPCAP_BIT_ATOX_PS_FACTOR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) CPCAP_BIT_ADC_PS_FACTOR1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) CPCAP_BIT_ADC_PS_FACTOR0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) CPCAP_BIT_ADTRIG_DIS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) CPCAP_BIT_ADTRIG_DIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) CPCAP_BIT_ASC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) CPCAP_BIT_ASC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) schedule_timeout_uninterruptible(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) error = regmap_read(ddata->reg, CPCAP_REG_ADCC2, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) } while ((value & CPCAP_BIT_ASC) && time_before(jiffies, timeout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (value & CPCAP_BIT_ASC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) dev_err(ddata->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) "Timeout waiting for calibration to complete\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) CPCAP_BIT_CAL_MODE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return;
^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) static int cpcap_adc_calibrate_one(struct cpcap_adc *ddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) int channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) u16 calibration_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) int lower_threshold,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) int upper_threshold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) unsigned int calibration_data[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) unsigned short cal_data_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) int i, error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) for (i = 0; i < CPCAP_ADC_MAX_RETRIES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) calibration_data[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) calibration_data[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) cal_data_diff = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) cpcap_adc_setup_calibrate(ddata, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) error = regmap_read(ddata->reg, calibration_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) &calibration_data[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) cpcap_adc_setup_calibrate(ddata, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) error = regmap_read(ddata->reg, calibration_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) &calibration_data[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (calibration_data[0] > calibration_data[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) cal_data_diff =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) calibration_data[0] - calibration_data[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) cal_data_diff =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) calibration_data[1] - calibration_data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (((calibration_data[1] >= lower_threshold) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) (calibration_data[1] <= upper_threshold) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) (cal_data_diff <= ST_ADC_CALIBRATE_DIFF_THRESHOLD)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) (ddata->vendor == CPCAP_VENDOR_TI)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) bank_conversion[channel].cal_offset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) ((short)calibration_data[1] * -1) + 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) dev_dbg(ddata->dev, "ch%i calibration complete: %i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) channel, bank_conversion[channel].cal_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) usleep_range(5000, 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static int cpcap_adc_calibrate(struct cpcap_adc *ddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) error = cpcap_adc_calibrate_one(ddata, CPCAP_ADC_CHG_ISENSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) CPCAP_REG_ADCAL1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) ST_ADC_CAL_CHRGI_LOW_THRESHOLD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) ST_ADC_CAL_CHRGI_HIGH_THRESHOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) error = cpcap_adc_calibrate_one(ddata, CPCAP_ADC_BATTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) CPCAP_REG_ADCAL2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) ST_ADC_CAL_BATTI_LOW_THRESHOLD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) ST_ADC_CAL_BATTI_HIGH_THRESHOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /* ADC setup, read and scale functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) static void cpcap_adc_setup_bank(struct cpcap_adc *ddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct cpcap_adc_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) const struct cpcap_adc_ato *ato = ddata->ato;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) unsigned short value1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) unsigned short value2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (!ato)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) switch (req->channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) case CPCAP_ADC_AD0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) value2 |= CPCAP_BIT_THERMBIAS_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) CPCAP_BIT_THERMBIAS_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) value2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) usleep_range(800, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) case CPCAP_ADC_AD8 ... CPCAP_ADC_TSY2_AD15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) value1 |= CPCAP_BIT_AD_SEL1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) case CPCAP_ADC_BATTP_PI16 ... CPCAP_ADC_BATTI_PI17:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) value1 |= CPCAP_BIT_RAND1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) switch (req->timing) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) case CPCAP_ADC_TIMING_IN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) value1 |= ato->ato_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) value1 |= ato->atox_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) value2 |= ato->adc_ps_factor_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) value2 |= ato->atox_ps_factor_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) case CPCAP_ADC_TIMING_OUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) value1 |= ato->ato_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) value1 |= ato->atox_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) value2 |= ato->adc_ps_factor_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) value2 |= ato->atox_ps_factor_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) case CPCAP_ADC_TIMING_IMM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) CPCAP_BIT_CAL_MODE | CPCAP_BIT_ATOX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) CPCAP_BIT_ATO3 | CPCAP_BIT_ATO2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) CPCAP_BIT_ATO1 | CPCAP_BIT_ATO0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) CPCAP_BIT_ADA2 | CPCAP_BIT_ADA1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) CPCAP_BIT_ADA0 | CPCAP_BIT_AD_SEL1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) CPCAP_BIT_RAND1 | CPCAP_BIT_RAND0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) value1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) CPCAP_BIT_ATOX_PS_FACTOR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) CPCAP_BIT_ADC_PS_FACTOR1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) CPCAP_BIT_ADC_PS_FACTOR0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) CPCAP_BIT_THERMBIAS_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) value2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (req->timing == CPCAP_ADC_TIMING_IMM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) CPCAP_BIT_ADTRIG_DIS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) CPCAP_BIT_ADTRIG_DIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) CPCAP_BIT_ASC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) CPCAP_BIT_ASC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) CPCAP_BIT_ADTRIG_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) CPCAP_BIT_ADTRIG_ONESHOT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) CPCAP_BIT_ADTRIG_DIS, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^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) static int cpcap_adc_start_bank(struct cpcap_adc *ddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) struct cpcap_adc_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) int i, error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) req->timing = CPCAP_ADC_TIMING_IMM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) ddata->done = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) for (i = 0; i < CPCAP_ADC_MAX_RETRIES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) cpcap_adc_setup_bank(ddata, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) error = wait_event_interruptible_timeout(ddata->wq_data_avail,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) ddata->done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) msecs_to_jiffies(50));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (error > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (error == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) error = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (error < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) static int cpcap_adc_stop_bank(struct cpcap_adc *ddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) CPCAP_REG_ADCC1_DEFAULTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 0xffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) CPCAP_REG_ADCC2_DEFAULTS);
^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) static void cpcap_adc_phase(struct cpcap_adc_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) const struct cpcap_adc_conversion_tbl *conv_tbl = req->conv_tbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) const struct cpcap_adc_phasing_tbl *phase_tbl = req->phase_tbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) int index = req->channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* Remuxed channels 16 and 17 use BATTP and BATTI entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) switch (req->channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) case CPCAP_ADC_BATTP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) case CPCAP_ADC_BATTP_PI16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) index = req->bank_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) req->result -= phase_tbl[index].offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) req->result -= CPCAP_FOUR_POINT_TWO_ADC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) req->result *= phase_tbl[index].multiplier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (phase_tbl[index].divider == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) req->result /= phase_tbl[index].divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) req->result += CPCAP_FOUR_POINT_TWO_ADC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) case CPCAP_ADC_BATTI_PI17:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) index = req->bank_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) req->result += conv_tbl[index].cal_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) req->result += conv_tbl[index].align_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) req->result *= phase_tbl[index].multiplier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (phase_tbl[index].divider == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) req->result /= phase_tbl[index].divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) req->result += phase_tbl[index].offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (req->result < phase_tbl[index].min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) req->result = phase_tbl[index].min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) else if (req->result > phase_tbl[index].max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) req->result = phase_tbl[index].max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) /* Looks up temperatures in a table and calculates averages if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static int cpcap_adc_table_to_millicelcius(unsigned short value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) int i, result = 0, alpha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (value <= temp_map[CPCAP_MAX_TEMP_LVL - 1][0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return temp_map[CPCAP_MAX_TEMP_LVL - 1][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (value >= temp_map[0][0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return temp_map[0][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) for (i = 0; i < CPCAP_MAX_TEMP_LVL - 1; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if ((value <= temp_map[i][0]) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) (value >= temp_map[i + 1][0])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (value == temp_map[i][0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) result = temp_map[i][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) } else if (value == temp_map[i + 1][0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) result = temp_map[i + 1][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) alpha = ((value - temp_map[i][0]) * 1000) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) (temp_map[i + 1][0] - temp_map[i][0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) result = temp_map[i][1] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) ((alpha * (temp_map[i + 1][1] -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) temp_map[i][1])) / 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) static void cpcap_adc_convert(struct cpcap_adc_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) const struct cpcap_adc_conversion_tbl *conv_tbl = req->conv_tbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) int index = req->channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /* Remuxed channels 16 and 17 use BATTP and BATTI entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) switch (req->channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) case CPCAP_ADC_BATTP_PI16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) index = CPCAP_ADC_BATTP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) case CPCAP_ADC_BATTI_PI17:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) index = CPCAP_ADC_BATTI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) /* No conversion for raw channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (conv_tbl[index].conv_type == IIO_CHAN_INFO_RAW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) /* Temperatures use a lookup table instead of conversion table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if ((req->channel == CPCAP_ADC_AD0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) (req->channel == CPCAP_ADC_AD3)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) req->result =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) cpcap_adc_table_to_millicelcius(req->result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) /* All processed channels use a conversion table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) req->result *= conv_tbl[index].multiplier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (conv_tbl[index].divider == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) req->result /= conv_tbl[index].divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) req->result += conv_tbl[index].conv_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^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) * REVISIT: Check if timed sampling can use multiple channels at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) * same time. If not, replace channel_mask with just channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) static int cpcap_adc_read_bank_scaled(struct cpcap_adc *ddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) struct cpcap_adc_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) int calibration_data, error, addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (ddata->vendor == CPCAP_VENDOR_TI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) error = regmap_read(ddata->reg, CPCAP_REG_ADCAL1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) &calibration_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) bank_conversion[CPCAP_ADC_CHG_ISENSE].cal_offset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) ((short)calibration_data * -1) + 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) error = regmap_read(ddata->reg, CPCAP_REG_ADCAL2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) &calibration_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) bank_conversion[CPCAP_ADC_BATTI].cal_offset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) ((short)calibration_data * -1) + 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) addr = CPCAP_REG_ADCD0 + req->bank_index * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) error = regmap_read(ddata->reg, addr, &req->result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) req->result &= 0x3ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) cpcap_adc_phase(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) cpcap_adc_convert(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) static int cpcap_adc_init_request(struct cpcap_adc_request *req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) req->channel = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) req->phase_tbl = bank_phasing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) req->conv_tbl = bank_conversion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) switch (channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) case CPCAP_ADC_AD0 ... CPCAP_ADC_USB_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) req->bank_index = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) case CPCAP_ADC_AD8 ... CPCAP_ADC_TSY2_AD15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) req->bank_index = channel - 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) case CPCAP_ADC_BATTP_PI16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) req->bank_index = CPCAP_ADC_BATTP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) case CPCAP_ADC_BATTI_PI17:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) req->bank_index = CPCAP_ADC_BATTI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) static int cpcap_adc_read_st_die_temp(struct cpcap_adc *ddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) int addr, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) error = regmap_read(ddata->reg, addr, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) *val -= 282;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) *val *= 114;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) *val += 25000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) static int cpcap_adc_read(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) int *val, int *val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) struct cpcap_adc *ddata = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct cpcap_adc_request req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) error = cpcap_adc_init_request(&req, chan->channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) case IIO_CHAN_INFO_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) mutex_lock(&ddata->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) error = cpcap_adc_start_bank(ddata, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) error = regmap_read(ddata->reg, chan->address, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) error = cpcap_adc_stop_bank(ddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) mutex_unlock(&ddata->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) case IIO_CHAN_INFO_PROCESSED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) mutex_lock(&ddata->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) error = cpcap_adc_start_bank(ddata, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if ((ddata->vendor == CPCAP_VENDOR_ST) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) (chan->channel == CPCAP_ADC_AD3)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) error = cpcap_adc_read_st_die_temp(ddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) chan->address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) &req.result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) error = cpcap_adc_read_bank_scaled(ddata, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) error = cpcap_adc_stop_bank(ddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) mutex_unlock(&ddata->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) *val = req.result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) err_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) mutex_unlock(&ddata->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) dev_err(ddata->dev, "error reading ADC: %i\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) static const struct iio_info cpcap_adc_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) .read_raw = &cpcap_adc_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) };
^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) * Configuration for Motorola mapphone series such as droid 4.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) * Copied from the Motorola mapphone kernel tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) static const struct cpcap_adc_ato mapphone_adc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) .ato_in = 0x0480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) .atox_in = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) .adc_ps_factor_in = 0x0200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) .atox_ps_factor_in = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) .ato_out = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) .atox_out = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) .adc_ps_factor_out = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) .atox_ps_factor_out = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) static const struct of_device_id cpcap_adc_id_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) .compatible = "motorola,cpcap-adc",
^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) .compatible = "motorola,mapphone-cpcap-adc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) .data = &mapphone_adc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) { /* sentinel */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) MODULE_DEVICE_TABLE(of, cpcap_adc_id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) static int cpcap_adc_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) struct cpcap_adc *ddata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*ddata));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if (!indio_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) dev_err(&pdev->dev, "failed to allocate iio device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) ddata = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) ddata->ato = device_get_match_data(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if (!ddata->ato)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) ddata->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) mutex_init(&ddata->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) init_waitqueue_head(&ddata->wq_data_avail);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) indio_dev->channels = cpcap_adc_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) indio_dev->num_channels = ARRAY_SIZE(cpcap_adc_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) indio_dev->name = dev_name(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) indio_dev->info = &cpcap_adc_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) ddata->reg = dev_get_regmap(pdev->dev.parent, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (!ddata->reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) error = cpcap_get_vendor(ddata->dev, ddata->reg, &ddata->vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) platform_set_drvdata(pdev, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) ddata->irq = platform_get_irq_byname(pdev, "adcdone");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (ddata->irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) error = devm_request_threaded_irq(&pdev->dev, ddata->irq, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) cpcap_adc_irq_thread,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) IRQF_TRIGGER_NONE | IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) "cpcap-adc", indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) dev_err(&pdev->dev, "could not get irq: %i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) error = cpcap_adc_calibrate(ddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) dev_info(&pdev->dev, "CPCAP ADC device probed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) return devm_iio_device_register(&pdev->dev, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) static struct platform_driver cpcap_adc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) .name = "cpcap_adc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) .of_match_table = cpcap_adc_id_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) .probe = cpcap_adc_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) module_platform_driver(cpcap_adc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) MODULE_ALIAS("platform:cpcap_adc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) MODULE_DESCRIPTION("CPCAP ADC driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) MODULE_AUTHOR("Tony Lindgren <tony@atomide.com");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) MODULE_LICENSE("GPL v2");