^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) 2012-2014, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* IADC register and bit definition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define IADC_REVISION2 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define IADC_REVISION2_SUPPORTED_IADC 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define IADC_PERPH_TYPE 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define IADC_PERPH_TYPE_ADC 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define IADC_PERPH_SUBTYPE 0x5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define IADC_PERPH_SUBTYPE_IADC 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define IADC_STATUS1 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define IADC_STATUS1_OP_MODE 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define IADC_STATUS1_REQ_STS BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define IADC_STATUS1_EOC BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define IADC_STATUS1_REQ_STS_EOC_MASK 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define IADC_MODE_CTL 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define IADC_OP_MODE_SHIFT 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define IADC_OP_MODE_NORMAL 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define IADC_TRIM_EN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define IADC_EN_CTL1 0x46
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define IADC_EN_CTL1_SET BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define IADC_CH_SEL_CTL 0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define IADC_DIG_PARAM 0x50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define IADC_DIG_DEC_RATIO_SEL_SHIFT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define IADC_HW_SETTLE_DELAY 0x51
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define IADC_CONV_REQ 0x52
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define IADC_CONV_REQ_SET BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define IADC_FAST_AVG_CTL 0x5a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define IADC_FAST_AVG_EN 0x5b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define IADC_FAST_AVG_EN_SET BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define IADC_PERH_RESET_CTL3 0xda
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define IADC_FOLLOW_WARM_RB BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define IADC_DATA 0x60 /* 16 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define IADC_SEC_ACCESS 0xd0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define IADC_SEC_ACCESS_DATA 0xa5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define IADC_NOMINAL_RSENSE 0xf4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define IADC_NOMINAL_RSENSE_SIGN_MASK BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define IADC_REF_GAIN_MICRO_VOLTS 17857
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define IADC_INT_RSENSE_DEVIATION 15625 /* nano Ohms per bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define IADC_INT_RSENSE_IDEAL_VALUE 10000 /* micro Ohms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define IADC_INT_RSENSE_DEFAULT_VALUE 7800 /* micro Ohms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define IADC_INT_RSENSE_DEFAULT_GF 9000 /* micro Ohms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define IADC_INT_RSENSE_DEFAULT_SMIC 9700 /* micro Ohms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define IADC_CONV_TIME_MIN_US 2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define IADC_CONV_TIME_MAX_US 2100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define IADC_DEF_PRESCALING 0 /* 1:1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define IADC_DEF_DECIMATION 0 /* 512 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define IADC_DEF_HW_SETTLE_TIME 0 /* 0 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define IADC_DEF_AVG_SAMPLES 0 /* 1 sample */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* IADC channel list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define IADC_INT_RSENSE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define IADC_EXT_RSENSE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define IADC_GAIN_17P857MV 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define IADC_EXT_OFFSET_CSP_CSN 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define IADC_INT_OFFSET_CSP2_CSN2 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * struct iadc_chip - IADC Current ADC device structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * @regmap: regmap for register read/write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * @dev: This device pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * @base: base offset for the ADC peripheral.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * @rsense: Values of the internal and external sense resister in micro Ohms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * @poll_eoc: Poll for end of conversion instead of waiting for IRQ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * @offset: Raw offset values for the internal and external channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * @gain: Raw gain of the channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * @lock: ADC lock for access to the peripheral.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * @complete: ADC notification after end of conversion interrupt is received.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct iadc_chip {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) u16 base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) bool poll_eoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) u32 rsense[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) u16 offset[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) u16 gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct completion complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static int iadc_read(struct iadc_chip *iadc, u16 offset, u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ret = regmap_read(iadc->regmap, iadc->base + offset, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) *data = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static int iadc_write(struct iadc_chip *iadc, u16 offset, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return regmap_write(iadc->regmap, iadc->base + offset, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static int iadc_reset(struct iadc_chip *iadc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) u8 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ret = iadc_write(iadc, IADC_SEC_ACCESS, IADC_SEC_ACCESS_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ret = iadc_read(iadc, IADC_PERH_RESET_CTL3, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ret = iadc_write(iadc, IADC_SEC_ACCESS, IADC_SEC_ACCESS_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) data |= IADC_FOLLOW_WARM_RB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return iadc_write(iadc, IADC_PERH_RESET_CTL3, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int iadc_set_state(struct iadc_chip *iadc, bool state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return iadc_write(iadc, IADC_EN_CTL1, state ? IADC_EN_CTL1_SET : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static void iadc_status_show(struct iadc_chip *iadc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) u8 mode, sta1, chan, dig, en, req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ret = iadc_read(iadc, IADC_MODE_CTL, &mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ret = iadc_read(iadc, IADC_DIG_PARAM, &dig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) ret = iadc_read(iadc, IADC_CH_SEL_CTL, &chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ret = iadc_read(iadc, IADC_CONV_REQ, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) ret = iadc_read(iadc, IADC_STATUS1, &sta1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) ret = iadc_read(iadc, IADC_EN_CTL1, &en);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) dev_err(iadc->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) "mode:%02x en:%02x chan:%02x dig:%02x req:%02x sta1:%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) mode, en, chan, dig, req, sta1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static int iadc_configure(struct iadc_chip *iadc, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) u8 decim, mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* Mode selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) mode = (IADC_OP_MODE_NORMAL << IADC_OP_MODE_SHIFT) | IADC_TRIM_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) ret = iadc_write(iadc, IADC_MODE_CTL, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* Channel selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) ret = iadc_write(iadc, IADC_CH_SEL_CTL, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* Digital parameter setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) decim = IADC_DEF_DECIMATION << IADC_DIG_DEC_RATIO_SEL_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ret = iadc_write(iadc, IADC_DIG_PARAM, decim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* HW settle time delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ret = iadc_write(iadc, IADC_HW_SETTLE_DELAY, IADC_DEF_HW_SETTLE_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) ret = iadc_write(iadc, IADC_FAST_AVG_CTL, IADC_DEF_AVG_SAMPLES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (IADC_DEF_AVG_SAMPLES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ret = iadc_write(iadc, IADC_FAST_AVG_EN, IADC_FAST_AVG_EN_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) ret = iadc_write(iadc, IADC_FAST_AVG_EN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (!iadc->poll_eoc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) reinit_completion(&iadc->complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ret = iadc_set_state(iadc, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* Request conversion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return iadc_write(iadc, IADC_CONV_REQ, IADC_CONV_REQ_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static int iadc_poll_wait_eoc(struct iadc_chip *iadc, unsigned int interval_us)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) unsigned int count, retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) u8 sta1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) retry = interval_us / IADC_CONV_TIME_MIN_US;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) for (count = 0; count < retry; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) ret = iadc_read(iadc, IADC_STATUS1, &sta1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) sta1 &= IADC_STATUS1_REQ_STS_EOC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (sta1 == IADC_STATUS1_EOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) usleep_range(IADC_CONV_TIME_MIN_US, IADC_CONV_TIME_MAX_US);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) iadc_status_show(iadc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static int iadc_read_result(struct iadc_chip *iadc, u16 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return regmap_bulk_read(iadc->regmap, iadc->base + IADC_DATA, data, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static int iadc_do_conversion(struct iadc_chip *iadc, int chan, u16 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) unsigned int wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ret = iadc_configure(iadc, chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) wait = BIT(IADC_DEF_AVG_SAMPLES) * IADC_CONV_TIME_MIN_US * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (iadc->poll_eoc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) ret = iadc_poll_wait_eoc(iadc, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) ret = wait_for_completion_timeout(&iadc->complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) usecs_to_jiffies(wait));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /* double check conversion status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) ret = iadc_poll_wait_eoc(iadc, IADC_CONV_TIME_MIN_US);
^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) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) ret = iadc_read_result(iadc, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) iadc_set_state(iadc, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) dev_err(iadc->dev, "conversion failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static int iadc_read_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) int *val, int *val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) struct iadc_chip *iadc = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) s32 isense_ua, vsense_uv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) u16 adc_raw, vsense_raw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) case IIO_CHAN_INFO_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) mutex_lock(&iadc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) ret = iadc_do_conversion(iadc, chan->channel, &adc_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) mutex_unlock(&iadc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) vsense_raw = adc_raw - iadc->offset[chan->channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) vsense_uv = vsense_raw * IADC_REF_GAIN_MICRO_VOLTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) vsense_uv /= (s32)iadc->gain - iadc->offset[chan->channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) isense_ua = vsense_uv / iadc->rsense[chan->channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) dev_dbg(iadc->dev, "off %d gain %d adc %d %duV I %duA\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) iadc->offset[chan->channel], iadc->gain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) adc_raw, vsense_uv, isense_ua);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) *val = isense_ua;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) case IIO_CHAN_INFO_SCALE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) *val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) *val2 = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static const struct iio_info iadc_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) .read_raw = iadc_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static irqreturn_t iadc_isr(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct iadc_chip *iadc = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) complete(&iadc->complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) static int iadc_update_offset(struct iadc_chip *iadc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) ret = iadc_do_conversion(iadc, IADC_GAIN_17P857MV, &iadc->gain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) ret = iadc_do_conversion(iadc, IADC_INT_OFFSET_CSP2_CSN2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) &iadc->offset[IADC_INT_RSENSE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (iadc->gain == iadc->offset[IADC_INT_RSENSE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) dev_err(iadc->dev, "error: internal offset == gain %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) iadc->gain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) ret = iadc_do_conversion(iadc, IADC_EXT_OFFSET_CSP_CSN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) &iadc->offset[IADC_EXT_RSENSE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (iadc->gain == iadc->offset[IADC_EXT_RSENSE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) dev_err(iadc->dev, "error: external offset == gain %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) iadc->gain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static int iadc_version_check(struct iadc_chip *iadc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) ret = iadc_read(iadc, IADC_PERPH_TYPE, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (val < IADC_PERPH_TYPE_ADC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) dev_err(iadc->dev, "%d is not ADC\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return -EINVAL;
^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) ret = iadc_read(iadc, IADC_PERPH_SUBTYPE, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (val < IADC_PERPH_SUBTYPE_IADC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) dev_err(iadc->dev, "%d is not IADC\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ret = iadc_read(iadc, IADC_REVISION2, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (val < IADC_REVISION2_SUPPORTED_IADC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) dev_err(iadc->dev, "revision %d not supported\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static int iadc_rsense_read(struct iadc_chip *iadc, struct device_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) int ret, sign, int_sense;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) u8 deviation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) ret = of_property_read_u32(node, "qcom,external-resistor-micro-ohms",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) &iadc->rsense[IADC_EXT_RSENSE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) iadc->rsense[IADC_EXT_RSENSE] = IADC_INT_RSENSE_IDEAL_VALUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (!iadc->rsense[IADC_EXT_RSENSE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) dev_err(iadc->dev, "external resistor can't be zero Ohms");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) ret = iadc_read(iadc, IADC_NOMINAL_RSENSE, &deviation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return ret;
^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) * Deviation value stored is an offset from 10 mili Ohms, bit 7 is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * the sign, the remaining bits have an LSB of 15625 nano Ohms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) sign = (deviation & IADC_NOMINAL_RSENSE_SIGN_MASK) ? -1 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) deviation &= ~IADC_NOMINAL_RSENSE_SIGN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) /* Scale it to nono Ohms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) int_sense = IADC_INT_RSENSE_IDEAL_VALUE * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) int_sense += sign * deviation * IADC_INT_RSENSE_DEVIATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) int_sense /= 1000; /* micro Ohms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) iadc->rsense[IADC_INT_RSENSE] = int_sense;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static const struct iio_chan_spec iadc_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) .type = IIO_CURRENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) .datasheet_name = "INTERNAL_RSENSE",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) .channel = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) BIT(IIO_CHAN_INFO_SCALE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) .indexed = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) .type = IIO_CURRENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) .datasheet_name = "EXTERNAL_RSENSE",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) .channel = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) BIT(IIO_CHAN_INFO_SCALE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) .indexed = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static int iadc_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) struct device_node *node = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) struct iadc_chip *iadc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) int ret, irq_eoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) u32 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) indio_dev = devm_iio_device_alloc(dev, sizeof(*iadc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (!indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) iadc = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) iadc->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) iadc->regmap = dev_get_regmap(dev->parent, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (!iadc->regmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) init_completion(&iadc->complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) mutex_init(&iadc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) ret = of_property_read_u32(node, "reg", &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) iadc->base = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) ret = iadc_version_check(iadc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) ret = iadc_rsense_read(iadc, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) dev_dbg(iadc->dev, "sense resistors %d and %d micro Ohm\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) iadc->rsense[IADC_INT_RSENSE],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) iadc->rsense[IADC_EXT_RSENSE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) irq_eoc = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (irq_eoc == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return irq_eoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (irq_eoc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) iadc->poll_eoc = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ret = iadc_reset(iadc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) dev_err(dev, "reset failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (!iadc->poll_eoc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) ret = devm_request_irq(dev, irq_eoc, iadc_isr, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) "spmi-iadc", iadc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) enable_irq_wake(irq_eoc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) device_init_wakeup(iadc->dev, 1);
^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) ret = iadc_update_offset(iadc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) dev_err(dev, "failed offset calibration\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) indio_dev->name = pdev->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) indio_dev->modes = INDIO_DIRECT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) indio_dev->info = &iadc_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) indio_dev->channels = iadc_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) indio_dev->num_channels = ARRAY_SIZE(iadc_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return devm_iio_device_register(dev, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) static const struct of_device_id iadc_match_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) { .compatible = "qcom,spmi-iadc" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) MODULE_DEVICE_TABLE(of, iadc_match_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static struct platform_driver iadc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) .name = "qcom-spmi-iadc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) .of_match_table = iadc_match_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) .probe = iadc_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) module_platform_driver(iadc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) MODULE_ALIAS("platform:qcom-spmi-iadc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) MODULE_DESCRIPTION("Qualcomm SPMI PMIC current ADC driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) MODULE_AUTHOR("Ivan T. Ivanov <iivanov@mm-sol.com>");