drivers/iio/adc/qcom-spmi-rradc.c

Source file repositories/reference/linux-study-clean/drivers/iio/adc/qcom-spmi-rradc.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/qcom-spmi-rradc.c
Extension
.c
Size
26916 bytes
Lines
1015
Domain
Driver Families
Bucket
drivers/iio
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct rradc_channel {
	const char *label;
	u8 lsb;
	u8 status;
	int size;
	int trigger_addr;
	int trigger_mask;
	int (*scale_fn)(struct rradc_chip *chip, u16 adc_code, int *result);
};

struct rradc_chip {
	struct device *dev;
	const struct qcom_spmi_pmic *pmic;
	/*
	 * Lock held while doing channel conversion
	 * involving multiple register read/writes
	 */
	struct mutex conversion_lock;
	struct regmap *regmap;
	u32 base;
	int batt_id_delay;
	u16 batt_id_data;
};

static const int batt_id_delays[] = { 0, 1, 4, 12, 20, 40, 60, 80 };
static const struct rradc_channel rradc_chans[RR_ADC_CHAN_MAX];
static const struct iio_chan_spec rradc_iio_chans[RR_ADC_CHAN_MAX];

static int rradc_read(struct rradc_chip *chip, u16 addr, __le16 *buf, int len)
{
	int ret, retry_cnt = 0;
	__le16 data_check[RR_ADC_CHAN_MAX_CONTINUOUS_BUFFER_LEN / 2];

	if (len > RR_ADC_CHAN_MAX_CONTINUOUS_BUFFER_LEN) {
		dev_err(chip->dev,
			"Can't read more than %d bytes, but asked to read %d bytes.\n",
			RR_ADC_CHAN_MAX_CONTINUOUS_BUFFER_LEN, len);
		return -EINVAL;
	}

	while (retry_cnt < RR_ADC_COHERENT_CHECK_RETRY) {
		ret = regmap_bulk_read(chip->regmap, chip->base + addr, buf,
				       len);
		if (ret < 0) {
			dev_err(chip->dev, "rr_adc reg 0x%x failed :%d\n", addr,
				ret);
			return ret;
		}

		ret = regmap_bulk_read(chip->regmap, chip->base + addr,
				       data_check, len);
		if (ret < 0) {
			dev_err(chip->dev, "rr_adc reg 0x%x failed :%d\n", addr,
				ret);
			return ret;
		}

		if (memcmp(buf, data_check, len) != 0) {
			retry_cnt++;
			dev_dbg(chip->dev,
				"coherent read error, retry_cnt:%d\n",
				retry_cnt);
			continue;
		}

		break;
	}

	if (retry_cnt == RR_ADC_COHERENT_CHECK_RETRY)
		dev_err(chip->dev, "Retry exceeded for coherency check\n");

	return ret;
}

static int rradc_get_fab_coeff(struct rradc_chip *chip, int64_t *offset,
			       int64_t *slope)
{
	if (chip->pmic->subtype == PM660_SUBTYPE) {
		switch (chip->pmic->fab_id) {
		case PM660_FAB_ID_GF:
			*offset = RR_ADC_CHG_TEMP_660_GF_OFFSET_UV;
			*slope = RR_ADC_CHG_TEMP_660_GF_SLOPE_UV_PER_C;
			return 0;
		case PM660_FAB_ID_TSMC:
			*offset = RR_ADC_CHG_TEMP_660_SMIC_OFFSET_UV;
			*slope = RR_ADC_CHG_TEMP_660_SMIC_SLOPE_UV_PER_C;
			return 0;
		default:
			*offset = RR_ADC_CHG_TEMP_660_MGNA_OFFSET_UV;
			*slope = RR_ADC_CHG_TEMP_660_MGNA_SLOPE_UV_PER_C;

Annotation

Implementation Notes