root/drivers/thermal/qcom/tsens.h
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
 */

#ifndef __QCOM_TSENS_H__
#define __QCOM_TSENS_H__

#define NO_PT_CALIB             0x0
#define ONE_PT_CALIB            0x1
#define ONE_PT_CALIB2           0x2
#define TWO_PT_CALIB            0x3
#define ONE_PT_CALIB2_NO_OFFSET 0x6
#define TWO_PT_CALIB_NO_OFFSET  0x7
#define CAL_DEGC_PT1            30
#define CAL_DEGC_PT2            120
#define SLOPE_FACTOR            1000
#define SLOPE_DEFAULT           3200
#define TIMEOUT_US              100
#define THRESHOLD_MAX_ADC_CODE  0x3ff
#define THRESHOLD_MIN_ADC_CODE  0x0

#define MAX_SENSORS 16

#include <linux/interrupt.h>
#include <linux/thermal.h>
#include <linux/regmap.h>
#include <linux/slab.h>

struct tsens_priv;

/* IP version numbers in ascending order */
enum tsens_ver {
        VER_0 = 0,
        VER_0_1,
        VER_1_X,
        VER_1_X_NO_RPM,
        VER_2_X,
        VER_2_X_NO_RPM,
};

enum tsens_irq_type {
        LOWER,
        UPPER,
        CRITICAL,
};

/**
 * struct tsens_sensor - data for each sensor connected to the tsens device
 * @priv: tsens device instance that this sensor is connected to
 * @tzd: pointer to the thermal zone that this sensor is in
 * @offset: offset of temperature adjustment curve
 * @hw_id: HW ID can be used in case of platform-specific IDs
 * @slope: slope of temperature adjustment curve
 * @status: 8960-specific variable to track 8960 and 8660 status register offset
 */
struct tsens_sensor {
        struct tsens_priv               *priv;
        struct thermal_zone_device      *tzd;
        int                             offset;
        unsigned int                    hw_id;
        int                             slope;
        u32                             status;
        int                             p1_calib_offset;
        int                             p2_calib_offset;
};

/**
 * struct tsens_ops - operations as supported by the tsens device
 * @init: Function to initialize the tsens device
 * @calibrate: Function to calibrate the tsens device
 * @get_temp: Function which returns the temp in millidegC
 * @enable: Function to enable (clocks/power) tsens device
 * @disable: Function to disable the tsens device
 * @suspend: Function to suspend the tsens device
 * @resume: Function to resume the tsens device
 */
struct tsens_ops {
        /* mandatory callbacks */
        int (*init)(struct tsens_priv *priv);
        int (*calibrate)(struct tsens_priv *priv);
        int (*get_temp)(const struct tsens_sensor *s, int *temp);
        /* optional callbacks */
        int (*enable)(struct tsens_priv *priv, int i);
        void (*disable)(struct tsens_priv *priv);
        int (*suspend)(struct tsens_priv *priv);
        int (*resume)(struct tsens_priv *priv);
};

#define REG_FIELD_FOR_EACH_SENSOR11(_name, _offset, _startbit, _stopbit) \
        [_name##_##0]  = REG_FIELD(_offset,      _startbit, _stopbit),  \
        [_name##_##1]  = REG_FIELD(_offset +  4, _startbit, _stopbit), \
        [_name##_##2]  = REG_FIELD(_offset +  8, _startbit, _stopbit), \
        [_name##_##3]  = REG_FIELD(_offset + 12, _startbit, _stopbit), \
        [_name##_##4]  = REG_FIELD(_offset + 16, _startbit, _stopbit), \
        [_name##_##5]  = REG_FIELD(_offset + 20, _startbit, _stopbit), \
        [_name##_##6]  = REG_FIELD(_offset + 24, _startbit, _stopbit), \
        [_name##_##7]  = REG_FIELD(_offset + 28, _startbit, _stopbit), \
        [_name##_##8]  = REG_FIELD(_offset + 32, _startbit, _stopbit), \
        [_name##_##9]  = REG_FIELD(_offset + 36, _startbit, _stopbit), \
        [_name##_##10] = REG_FIELD(_offset + 40, _startbit, _stopbit)

#define REG_FIELD_FOR_EACH_SENSOR16(_name, _offset, _startbit, _stopbit) \
        [_name##_##0]  = REG_FIELD(_offset,      _startbit, _stopbit),  \
        [_name##_##1]  = REG_FIELD(_offset +  4, _startbit, _stopbit), \
        [_name##_##2]  = REG_FIELD(_offset +  8, _startbit, _stopbit), \
        [_name##_##3]  = REG_FIELD(_offset + 12, _startbit, _stopbit), \
        [_name##_##4]  = REG_FIELD(_offset + 16, _startbit, _stopbit), \
        [_name##_##5]  = REG_FIELD(_offset + 20, _startbit, _stopbit), \
        [_name##_##6]  = REG_FIELD(_offset + 24, _startbit, _stopbit), \
        [_name##_##7]  = REG_FIELD(_offset + 28, _startbit, _stopbit), \
        [_name##_##8]  = REG_FIELD(_offset + 32, _startbit, _stopbit), \
        [_name##_##9]  = REG_FIELD(_offset + 36, _startbit, _stopbit), \
        [_name##_##10] = REG_FIELD(_offset + 40, _startbit, _stopbit), \
        [_name##_##11] = REG_FIELD(_offset + 44, _startbit, _stopbit), \
        [_name##_##12] = REG_FIELD(_offset + 48, _startbit, _stopbit), \
        [_name##_##13] = REG_FIELD(_offset + 52, _startbit, _stopbit), \
        [_name##_##14] = REG_FIELD(_offset + 56, _startbit, _stopbit), \
        [_name##_##15] = REG_FIELD(_offset + 60, _startbit, _stopbit)

#define REG_FIELD_SPLIT_BITS_0_15(_name, _offset)               \
        [_name##_##0]  = REG_FIELD(_offset,  0,  0),            \
        [_name##_##1]  = REG_FIELD(_offset,  1,  1),    \
        [_name##_##2]  = REG_FIELD(_offset,  2,  2),    \
        [_name##_##3]  = REG_FIELD(_offset,  3,  3),    \
        [_name##_##4]  = REG_FIELD(_offset,  4,  4),    \
        [_name##_##5]  = REG_FIELD(_offset,  5,  5),    \
        [_name##_##6]  = REG_FIELD(_offset,  6,  6),    \
        [_name##_##7]  = REG_FIELD(_offset,  7,  7),    \
        [_name##_##8]  = REG_FIELD(_offset,  8,  8),    \
        [_name##_##9]  = REG_FIELD(_offset,  9,  9),    \
        [_name##_##10] = REG_FIELD(_offset, 10, 10),    \
        [_name##_##11] = REG_FIELD(_offset, 11, 11),    \
        [_name##_##12] = REG_FIELD(_offset, 12, 12),    \
        [_name##_##13] = REG_FIELD(_offset, 13, 13),    \
        [_name##_##14] = REG_FIELD(_offset, 14, 14),    \
        [_name##_##15] = REG_FIELD(_offset, 15, 15)

#define REG_FIELD_SPLIT_BITS_16_31(_name, _offset)              \
        [_name##_##0]  = REG_FIELD(_offset, 16, 16),            \
        [_name##_##1]  = REG_FIELD(_offset, 17, 17),    \
        [_name##_##2]  = REG_FIELD(_offset, 18, 18),    \
        [_name##_##3]  = REG_FIELD(_offset, 19, 19),    \
        [_name##_##4]  = REG_FIELD(_offset, 20, 20),    \
        [_name##_##5]  = REG_FIELD(_offset, 21, 21),    \
        [_name##_##6]  = REG_FIELD(_offset, 22, 22),    \
        [_name##_##7]  = REG_FIELD(_offset, 23, 23),    \
        [_name##_##8]  = REG_FIELD(_offset, 24, 24),    \
        [_name##_##9]  = REG_FIELD(_offset, 25, 25),    \
        [_name##_##10] = REG_FIELD(_offset, 26, 26),    \
        [_name##_##11] = REG_FIELD(_offset, 27, 27),    \
        [_name##_##12] = REG_FIELD(_offset, 28, 28),    \
        [_name##_##13] = REG_FIELD(_offset, 29, 29),    \
        [_name##_##14] = REG_FIELD(_offset, 30, 30),    \
        [_name##_##15] = REG_FIELD(_offset, 31, 31)

/*
 * reg_field IDs to use as an index into an array
 * If you change the order of the entries, check the devm_regmap_field_alloc()
 * calls in init_common()
 */
enum regfield_ids {
        /* ----- SROT ------ */
        /* HW_VER */
        VER_MAJOR,
        VER_MINOR,
        VER_STEP,
        /* CTRL_OFFSET */
        TSENS_EN,
        TSENS_SW_RST,
        SENSOR_EN,
        CODE_OR_TEMP,
        MAIN_MEASURE_PERIOD,

        /* ----- TM ------ */
        /* TRDY */
        TRDY,
        /* INTERRUPT ENABLE */
        INT_EN, /* v2+ has separate enables for crit, upper and lower irq */
        /* STATUS */
        LAST_TEMP_0,    /* Last temperature reading */
        LAST_TEMP_1,
        LAST_TEMP_2,
        LAST_TEMP_3,
        LAST_TEMP_4,
        LAST_TEMP_5,
        LAST_TEMP_6,
        LAST_TEMP_7,
        LAST_TEMP_8,
        LAST_TEMP_9,
        LAST_TEMP_10,
        LAST_TEMP_11,
        LAST_TEMP_12,
        LAST_TEMP_13,
        LAST_TEMP_14,
        LAST_TEMP_15,
        VALID_0,                /* VALID reading or not */
        VALID_1,
        VALID_2,
        VALID_3,
        VALID_4,
        VALID_5,
        VALID_6,
        VALID_7,
        VALID_8,
        VALID_9,
        VALID_10,
        VALID_11,
        VALID_12,
        VALID_13,
        VALID_14,
        VALID_15,
        LOWER_STATUS_0, /* LOWER threshold violated */
        LOWER_STATUS_1,
        LOWER_STATUS_2,
        LOWER_STATUS_3,
        LOWER_STATUS_4,
        LOWER_STATUS_5,
        LOWER_STATUS_6,
        LOWER_STATUS_7,
        LOWER_STATUS_8,
        LOWER_STATUS_9,
        LOWER_STATUS_10,
        LOWER_STATUS_11,
        LOWER_STATUS_12,
        LOWER_STATUS_13,
        LOWER_STATUS_14,
        LOWER_STATUS_15,
        LOW_INT_STATUS_0,       /* LOWER interrupt status */
        LOW_INT_STATUS_1,
        LOW_INT_STATUS_2,
        LOW_INT_STATUS_3,
        LOW_INT_STATUS_4,
        LOW_INT_STATUS_5,
        LOW_INT_STATUS_6,
        LOW_INT_STATUS_7,
        LOW_INT_STATUS_8,
        LOW_INT_STATUS_9,
        LOW_INT_STATUS_10,
        LOW_INT_STATUS_11,
        LOW_INT_STATUS_12,
        LOW_INT_STATUS_13,
        LOW_INT_STATUS_14,
        LOW_INT_STATUS_15,
        LOW_INT_CLEAR_0,        /* LOWER interrupt clear */
        LOW_INT_CLEAR_1,
        LOW_INT_CLEAR_2,
        LOW_INT_CLEAR_3,
        LOW_INT_CLEAR_4,
        LOW_INT_CLEAR_5,
        LOW_INT_CLEAR_6,
        LOW_INT_CLEAR_7,
        LOW_INT_CLEAR_8,
        LOW_INT_CLEAR_9,
        LOW_INT_CLEAR_10,
        LOW_INT_CLEAR_11,
        LOW_INT_CLEAR_12,
        LOW_INT_CLEAR_13,
        LOW_INT_CLEAR_14,
        LOW_INT_CLEAR_15,
        LOW_INT_MASK_0, /* LOWER interrupt mask */
        LOW_INT_MASK_1,
        LOW_INT_MASK_2,
        LOW_INT_MASK_3,
        LOW_INT_MASK_4,
        LOW_INT_MASK_5,
        LOW_INT_MASK_6,
        LOW_INT_MASK_7,
        LOW_INT_MASK_8,
        LOW_INT_MASK_9,
        LOW_INT_MASK_10,
        LOW_INT_MASK_11,
        LOW_INT_MASK_12,
        LOW_INT_MASK_13,
        LOW_INT_MASK_14,
        LOW_INT_MASK_15,
        LOW_THRESH_0,           /* LOWER threshold values */
        LOW_THRESH_1,
        LOW_THRESH_2,
        LOW_THRESH_3,
        LOW_THRESH_4,
        LOW_THRESH_5,
        LOW_THRESH_6,
        LOW_THRESH_7,
        LOW_THRESH_8,
        LOW_THRESH_9,
        LOW_THRESH_10,
        LOW_THRESH_11,
        LOW_THRESH_12,
        LOW_THRESH_13,
        LOW_THRESH_14,
        LOW_THRESH_15,
        UPPER_STATUS_0, /* UPPER threshold violated */
        UPPER_STATUS_1,
        UPPER_STATUS_2,
        UPPER_STATUS_3,
        UPPER_STATUS_4,
        UPPER_STATUS_5,
        UPPER_STATUS_6,
        UPPER_STATUS_7,
        UPPER_STATUS_8,
        UPPER_STATUS_9,
        UPPER_STATUS_10,
        UPPER_STATUS_11,
        UPPER_STATUS_12,
        UPPER_STATUS_13,
        UPPER_STATUS_14,
        UPPER_STATUS_15,
        UP_INT_STATUS_0,        /* UPPER interrupt status */
        UP_INT_STATUS_1,
        UP_INT_STATUS_2,
        UP_INT_STATUS_3,
        UP_INT_STATUS_4,
        UP_INT_STATUS_5,
        UP_INT_STATUS_6,
        UP_INT_STATUS_7,
        UP_INT_STATUS_8,
        UP_INT_STATUS_9,
        UP_INT_STATUS_10,
        UP_INT_STATUS_11,
        UP_INT_STATUS_12,
        UP_INT_STATUS_13,
        UP_INT_STATUS_14,
        UP_INT_STATUS_15,
        UP_INT_CLEAR_0, /* UPPER interrupt clear */
        UP_INT_CLEAR_1,
        UP_INT_CLEAR_2,
        UP_INT_CLEAR_3,
        UP_INT_CLEAR_4,
        UP_INT_CLEAR_5,
        UP_INT_CLEAR_6,
        UP_INT_CLEAR_7,
        UP_INT_CLEAR_8,
        UP_INT_CLEAR_9,
        UP_INT_CLEAR_10,
        UP_INT_CLEAR_11,
        UP_INT_CLEAR_12,
        UP_INT_CLEAR_13,
        UP_INT_CLEAR_14,
        UP_INT_CLEAR_15,
        UP_INT_MASK_0,          /* UPPER interrupt mask */
        UP_INT_MASK_1,
        UP_INT_MASK_2,
        UP_INT_MASK_3,
        UP_INT_MASK_4,
        UP_INT_MASK_5,
        UP_INT_MASK_6,
        UP_INT_MASK_7,
        UP_INT_MASK_8,
        UP_INT_MASK_9,
        UP_INT_MASK_10,
        UP_INT_MASK_11,
        UP_INT_MASK_12,
        UP_INT_MASK_13,
        UP_INT_MASK_14,
        UP_INT_MASK_15,
        UP_THRESH_0,            /* UPPER threshold values */
        UP_THRESH_1,
        UP_THRESH_2,
        UP_THRESH_3,
        UP_THRESH_4,
        UP_THRESH_5,
        UP_THRESH_6,
        UP_THRESH_7,
        UP_THRESH_8,
        UP_THRESH_9,
        UP_THRESH_10,
        UP_THRESH_11,
        UP_THRESH_12,
        UP_THRESH_13,
        UP_THRESH_14,
        UP_THRESH_15,
        CRITICAL_STATUS_0,      /* CRITICAL threshold violated */
        CRITICAL_STATUS_1,
        CRITICAL_STATUS_2,
        CRITICAL_STATUS_3,
        CRITICAL_STATUS_4,
        CRITICAL_STATUS_5,
        CRITICAL_STATUS_6,
        CRITICAL_STATUS_7,
        CRITICAL_STATUS_8,
        CRITICAL_STATUS_9,
        CRITICAL_STATUS_10,
        CRITICAL_STATUS_11,
        CRITICAL_STATUS_12,
        CRITICAL_STATUS_13,
        CRITICAL_STATUS_14,
        CRITICAL_STATUS_15,
        CRIT_INT_STATUS_0,      /* CRITICAL interrupt status */
        CRIT_INT_STATUS_1,
        CRIT_INT_STATUS_2,
        CRIT_INT_STATUS_3,
        CRIT_INT_STATUS_4,
        CRIT_INT_STATUS_5,
        CRIT_INT_STATUS_6,
        CRIT_INT_STATUS_7,
        CRIT_INT_STATUS_8,
        CRIT_INT_STATUS_9,
        CRIT_INT_STATUS_10,
        CRIT_INT_STATUS_11,
        CRIT_INT_STATUS_12,
        CRIT_INT_STATUS_13,
        CRIT_INT_STATUS_14,
        CRIT_INT_STATUS_15,
        CRIT_INT_CLEAR_0,       /* CRITICAL interrupt clear */
        CRIT_INT_CLEAR_1,
        CRIT_INT_CLEAR_2,
        CRIT_INT_CLEAR_3,
        CRIT_INT_CLEAR_4,
        CRIT_INT_CLEAR_5,
        CRIT_INT_CLEAR_6,
        CRIT_INT_CLEAR_7,
        CRIT_INT_CLEAR_8,
        CRIT_INT_CLEAR_9,
        CRIT_INT_CLEAR_10,
        CRIT_INT_CLEAR_11,
        CRIT_INT_CLEAR_12,
        CRIT_INT_CLEAR_13,
        CRIT_INT_CLEAR_14,
        CRIT_INT_CLEAR_15,
        CRIT_INT_MASK_0,        /* CRITICAL interrupt mask */
        CRIT_INT_MASK_1,
        CRIT_INT_MASK_2,
        CRIT_INT_MASK_3,
        CRIT_INT_MASK_4,
        CRIT_INT_MASK_5,
        CRIT_INT_MASK_6,
        CRIT_INT_MASK_7,
        CRIT_INT_MASK_8,
        CRIT_INT_MASK_9,
        CRIT_INT_MASK_10,
        CRIT_INT_MASK_11,
        CRIT_INT_MASK_12,
        CRIT_INT_MASK_13,
        CRIT_INT_MASK_14,
        CRIT_INT_MASK_15,
        CRIT_THRESH_0,          /* CRITICAL threshold values */
        CRIT_THRESH_1,
        CRIT_THRESH_2,
        CRIT_THRESH_3,
        CRIT_THRESH_4,
        CRIT_THRESH_5,
        CRIT_THRESH_6,
        CRIT_THRESH_7,
        CRIT_THRESH_8,
        CRIT_THRESH_9,
        CRIT_THRESH_10,
        CRIT_THRESH_11,
        CRIT_THRESH_12,
        CRIT_THRESH_13,
        CRIT_THRESH_14,
        CRIT_THRESH_15,

        /* WATCHDOG */
        WDOG_BARK_STATUS,
        WDOG_BARK_CLEAR,
        WDOG_BARK_MASK,
        WDOG_BARK_COUNT,

        /* CYCLE COMPLETION MONITOR */
        CC_MON_STATUS,
        CC_MON_CLEAR,
        CC_MON_MASK,

        MIN_STATUS_0,           /* MIN threshold violated */
        MIN_STATUS_1,
        MIN_STATUS_2,
        MIN_STATUS_3,
        MIN_STATUS_4,
        MIN_STATUS_5,
        MIN_STATUS_6,
        MIN_STATUS_7,
        MIN_STATUS_8,
        MIN_STATUS_9,
        MIN_STATUS_10,
        MIN_STATUS_11,
        MIN_STATUS_12,
        MIN_STATUS_13,
        MIN_STATUS_14,
        MIN_STATUS_15,
        MAX_STATUS_0,           /* MAX threshold violated */
        MAX_STATUS_1,
        MAX_STATUS_2,
        MAX_STATUS_3,
        MAX_STATUS_4,
        MAX_STATUS_5,
        MAX_STATUS_6,
        MAX_STATUS_7,
        MAX_STATUS_8,
        MAX_STATUS_9,
        MAX_STATUS_10,
        MAX_STATUS_11,
        MAX_STATUS_12,
        MAX_STATUS_13,
        MAX_STATUS_14,
        MAX_STATUS_15,

        /* Keep last */
        MAX_REGFIELDS
};

/**
 * struct tsens_features - Features supported by the IP
 * @ver_major: Major number of IP version
 * @crit_int: does the IP support critical interrupts?
 * @combo_int: does the IP use one IRQ for up, low and critical thresholds?
 * @adc:      do the sensors only output adc code (instead of temperature)?
 * @srot_split: does the IP neatly splits the register space into SROT and TM,
 *              with SROT only being available to secure boot firmware?
 * @has_watchdog: does this IP support watchdog functionality?
 * @max_sensors: maximum sensors supported by this version of the IP
 * @trip_min_temp: minimum trip temperature supported by this version of the IP
 * @trip_max_temp: maximum trip temperature supported by this version of the IP
 */
struct tsens_features {
        unsigned int ver_major;
        unsigned int crit_int:1;
        unsigned int combo_int:1;
        unsigned int adc:1;
        unsigned int srot_split:1;
        unsigned int has_watchdog:1;
        unsigned int max_sensors;
        int trip_min_temp;
        int trip_max_temp;
};

/**
 * struct tsens_plat_data - tsens compile-time platform data
 * @num_sensors: Number of sensors supported by platform
 * @ops: operations the tsens instance supports
 * @hw_ids: Subset of sensors ids supported by platform, if not the first n
 * @feat: features of the IP
 * @fields: bitfield locations
 */
struct tsens_plat_data {
        const u32               num_sensors;
        const struct tsens_ops  *ops;
        unsigned int            *hw_ids;
        struct tsens_features   *feat;
        const struct reg_field          *fields;
};

/**
 * struct tsens_context - Registers to be saved/restored across a context loss
 * @threshold: Threshold register value
 * @control: Control register value
 */
struct tsens_context {
        int     threshold;
        int     control;
};

/**
 * struct tsens_priv - private data for each instance of the tsens IP
 * @dev: pointer to struct device
 * @num_sensors: number of sensors enabled on this device
 * @tm_map: pointer to TM register address space
 * @srot_map: pointer to SROT register address space
 * @tm_offset: deal with old device trees that don't address TM and SROT
 *             address space separately
 * @ul_lock: lock while processing upper/lower threshold interrupts
 * @crit_lock: lock while processing critical threshold interrupts
 * @rf: array of regmap_fields used to store value of the field
 * @ctx: registers to be saved and restored during suspend/resume
 * @feat: features of the IP
 * @fields: bitfield locations
 * @ops: pointer to list of callbacks supported by this device
 * @debug_root: pointer to debugfs dentry for all tsens
 * @debug: pointer to debugfs dentry for tsens controller
 * @sensor: list of sensors attached to this device
 */
struct tsens_priv {
        struct device                   *dev;
        u32                             num_sensors;
        struct regmap                   *tm_map;
        struct regmap                   *srot_map;
        u32                             tm_offset;

        /* lock for upper/lower threshold interrupts */
        spinlock_t                      ul_lock;

        struct regmap_field             *rf[MAX_REGFIELDS];
        struct tsens_context            ctx;
        struct tsens_features           *feat;
        const struct reg_field          *fields;
        const struct tsens_ops          *ops;

        struct dentry                   *debug_root;
        struct dentry                   *debug;

        struct tsens_sensor             sensor[] __counted_by(num_sensors);
};

/**
 * struct tsens_single_value - internal representation of a single field inside nvmem calibration data
 * @idx: index into the u32 data array
 * @shift: the shift of the first bit in the value
 * @blob: index of the data blob to use for this cell
 */
struct tsens_single_value {
        u8 idx;
        u8 shift;
        u8 blob;
};

/**
 * struct tsens_legacy_calibration_format - description of calibration data used when parsing the legacy nvmem blob
 * @base_len: the length of the base fields inside calibration data
 * @base_shift: the shift to be applied to base data
 * @sp_len: the length of the sN_pM fields inside calibration data
 * @mode: descriptor of the calibration mode field
 * @invalid: descriptor of the calibration mode invalid field
 * @base: descriptors of the base0 and base1 fields
 * @sp: descriptors of the sN_pM fields
 */
struct tsens_legacy_calibration_format {
        unsigned int base_len;
        unsigned int base_shift;
        unsigned int sp_len;
        /* just two bits */
        struct tsens_single_value mode;
        /* on all platforms except 8974 invalid is the third bit of what downstream calls 'mode' */
        struct tsens_single_value invalid;
        struct tsens_single_value base[2];
        struct tsens_single_value sp[][2];
};

char *qfprom_read(struct device *dev, const char *cname);
int tsens_read_calibration_legacy(struct tsens_priv *priv,
                                  const struct tsens_legacy_calibration_format *format,
                                  u32 *p1, u32 *p2,
                                  u32 *cdata, u32 *csel);
int tsens_read_calibration(struct tsens_priv *priv, int shift, u32 *p1, u32 *p2, bool backup);
int tsens_calibrate_nvmem(struct tsens_priv *priv, int shift);
int tsens_calibrate_common(struct tsens_priv *priv);
void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mode);
int init_common(struct tsens_priv *priv);
int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp);
int get_temp_common(const struct tsens_sensor *s, int *temp);
#ifdef CONFIG_SUSPEND
int tsens_resume_common(struct tsens_priv *priv);
#else
#define tsens_resume_common            NULL
#endif

/* TSENS target */
extern struct tsens_plat_data data_8960;

/* TSENS v0.1 targets */
extern struct tsens_plat_data data_8226, data_8909, data_8916, data_8939, data_8974, data_9607;

/* TSENS v1 targets */
extern struct tsens_plat_data data_tsens_v1, data_8937, data_8976, data_8956;

/* TSENS v1 with no RPM targets */
extern const struct tsens_plat_data data_ipq5018;

/* TSENS v2 targets */
extern struct tsens_plat_data data_8996, data_ipq8074, data_tsens_v2;
extern const struct tsens_plat_data data_ipq5332, data_ipq5424;

#endif /* __QCOM_TSENS_H__ */