// SPDX-License-Identifier: GPL-2.0-only
/*
* palmas-adc.c -- TI PALMAS GPADC.
*
* Copyright (c) 2013, NVIDIA Corporation. All rights reserved.
*
* Author: Pradeep Goudagunta <pgoudagunta@nvidia.com>
*/
#include <linux/module.h>
#include <linux/err.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/mfd/palmas.h>
#include <linux/completion.h>
#include <linux/of.h>
#include <linux/iio/events.h>
#include <linux/iio/iio.h>
#include <linux/iio/machine.h>
#include <linux/iio/driver.h>
#define MOD_NAME "palmas-gpadc"
#define PALMAS_ADC_CONVERSION_TIMEOUT (msecs_to_jiffies(5000))
#define PALMAS_TO_BE_CALCULATED 0
#define PALMAS_GPADC_TRIMINVALID -1
struct palmas_gpadc_info {
/* calibration codes and regs */
int x1; /* lower ideal code */
int x2; /* higher ideal code */
int v1; /* expected lower volt reading */
int v2; /* expected higher volt reading */
u8 trim1_reg; /* register number for lower trim */
u8 trim2_reg; /* register number for upper trim */
int gain; /* calculated from above (after reading trim regs) */
int offset; /* calculated from above (after reading trim regs) */
int gain_error; /* calculated from above (after reading trim regs) */
bool is_uncalibrated; /* if channel has calibration data */
};
#define PALMAS_ADC_INFO(_chan, _x1, _x2, _v1, _v2, _t1, _t2, _is_uncalibrated) \
[PALMAS_ADC_CH_##_chan] = { \
.x1 = _x1, \
.x2 = _x2, \
.v1 = _v1, \
.v2 = _v2, \
.gain = PALMAS_TO_BE_CALCULATED, \
.offset = PALMAS_TO_BE_CALCULATED, \
.gain_error = PALMAS_TO_BE_CALCULATED, \
.trim1_reg = PALMAS_GPADC_TRIM##_t1, \
.trim2_reg = PALMAS_GPADC_TRIM##_t2, \
.is_uncalibrated = _is_uncalibrated \
}
static struct palmas_gpadc_info palmas_gpadc_info[] = {
PALMAS_ADC_INFO(IN0, 2064, 3112, 630, 950, 1, 2, false),
PALMAS_ADC_INFO(IN1, 2064, 3112, 630, 950, 1, 2, false),
PALMAS_ADC_INFO(IN2, 2064, 3112, 1260, 1900, 3, 4, false),
PALMAS_ADC_INFO(IN3, 2064, 3112, 630, 950, 1, 2, false),
PALMAS_ADC_INFO(IN4, 2064, 3112, 630, 950, 1, 2, false),
PALMAS_ADC_INFO(IN5, 2064, 3112, 630, 950, 1, 2, false),
PALMAS_ADC_INFO(IN6, 2064, 3112, 2520, 3800, 5, 6, false),
PALMAS_ADC_INFO(IN7, 2064, 3112, 2520, 3800, 7, 8, false),
PALMAS_ADC_INFO(IN8, 2064, 3112, 3150, 4750, 9, 10, false),
PALMAS_ADC_INFO(IN9, 2064, 3112, 5670, 8550, 11, 12, false),
PALMAS_ADC_INFO(IN10, 2064, 3112, 3465, 5225, 13, 14, false),
PALMAS_ADC_INFO(IN11, 0, 0, 0, 0, INVALID, INVALID, true),
PALMAS_ADC_INFO(IN12, 0, 0, 0, 0, INVALID, INVALID, true),
PALMAS_ADC_INFO(IN13, 0, 0, 0, 0, INVALID, INVALID, true),
PALMAS_ADC_INFO(IN14, 2064, 3112, 3645, 5225, 15, 16, false),
PALMAS_ADC_INFO(IN15, 0, 0, 0, 0, INVALID, INVALID, true),
};
struct palmas_adc_event {
bool enabled;
int channel;
enum iio_event_direction direction;
};
struct palmas_gpadc_thresholds {
int high;
int low;
};
/*
* struct palmas_gpadc - the palmas_gpadc structure
* @ch0_current: channel 0 current source setting
* 0: 0 uA
* 1: 5 uA
* 2: 15 uA
* 3: 20 uA
* @ch3_current: channel 0 current source setting
* 0: 0 uA
* 1: 10 uA
* 2: 400 uA
* 3: 800 uA
* @extended_delay: enable the gpadc extended delay mode
* @auto_conversion_period: define the auto_conversion_period
* @lock: Lock to protect the device state during a potential concurrent
* read access from userspace. Reading a raw value requires a sequence
* of register writes, then a wait for a completion callback,
* and finally a register read, during which userspace could issue
* another read request. This lock protects a read access from
* ocurring before another one has finished.
*
* This is the palmas_gpadc structure to store run-time information
* and pointers for this driver instance.
*/
struct palmas_gpadc {
struct device *dev;
struct palmas *palmas;
u8 ch0_current;
u8 ch3_current;
bool extended_delay;
int irq;
int irq_auto_0;
int irq_auto_1;
struct palmas_gpadc_info *adc_info;
struct completion