1 /* SPDX-License-Identifier: GPL-2.0 */
3 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
6 #ifndef __QCOM_TSENS_H__
7 #define __QCOM_TSENS_H__
9 #define ONE_PT_CALIB 0x1
10 #define ONE_PT_CALIB2 0x2
11 #define TWO_PT_CALIB 0x3
12 #define CAL_DEGC_PT1 30
13 #define CAL_DEGC_PT2 120
14 #define SLOPE_FACTOR 1000
15 #define SLOPE_DEFAULT 3200
16 #define THRESHOLD_MAX_ADC_CODE 0x3ff
17 #define THRESHOLD_MIN_ADC_CODE 0x0
19 #include <linux/interrupt.h>
20 #include <linux/thermal.h>
21 #include <linux/regmap.h>
22 #include <linux/slab.h>
38 * struct tsens_sensor - data for each sensor connected to the tsens device
39 * @priv: tsens device instance that this sensor is connected to
40 * @tzd: pointer to the thermal zone that this sensor is in
41 * @offset: offset of temperature adjustment curve
42 * @hw_id: HW ID can be used in case of platform-specific IDs
43 * @slope: slope of temperature adjustment curve
44 * @status: 8960-specific variable to track 8960 and 8660 status register offset
47 struct tsens_priv
*priv
;
48 struct thermal_zone_device
*tzd
;
56 * struct tsens_ops - operations as supported by the tsens device
57 * @init: Function to initialize the tsens device
58 * @calibrate: Function to calibrate the tsens device
59 * @get_temp: Function which returns the temp in millidegC
60 * @enable: Function to enable (clocks/power) tsens device
61 * @disable: Function to disable the tsens device
62 * @suspend: Function to suspend the tsens device
63 * @resume: Function to resume the tsens device
64 * @get_trend: Function to get the thermal/temp trend
67 /* mandatory callbacks */
68 int (*init
)(struct tsens_priv
*priv
);
69 int (*calibrate
)(struct tsens_priv
*priv
);
70 int (*get_temp
)(struct tsens_sensor
*s
, int *temp
);
71 /* optional callbacks */
72 int (*enable
)(struct tsens_priv
*priv
, int i
);
73 void (*disable
)(struct tsens_priv
*priv
);
74 int (*suspend
)(struct tsens_priv
*priv
);
75 int (*resume
)(struct tsens_priv
*priv
);
76 int (*get_trend
)(struct tsens_sensor
*s
, enum thermal_trend
*trend
);
79 #define REG_FIELD_FOR_EACH_SENSOR11(_name, _offset, _startbit, _stopbit) \
80 [_name##_##0] = REG_FIELD(_offset, _startbit, _stopbit), \
81 [_name##_##1] = REG_FIELD(_offset + 4, _startbit, _stopbit), \
82 [_name##_##2] = REG_FIELD(_offset + 8, _startbit, _stopbit), \
83 [_name##_##3] = REG_FIELD(_offset + 12, _startbit, _stopbit), \
84 [_name##_##4] = REG_FIELD(_offset + 16, _startbit, _stopbit), \
85 [_name##_##5] = REG_FIELD(_offset + 20, _startbit, _stopbit), \
86 [_name##_##6] = REG_FIELD(_offset + 24, _startbit, _stopbit), \
87 [_name##_##7] = REG_FIELD(_offset + 28, _startbit, _stopbit), \
88 [_name##_##8] = REG_FIELD(_offset + 32, _startbit, _stopbit), \
89 [_name##_##9] = REG_FIELD(_offset + 36, _startbit, _stopbit), \
90 [_name##_##10] = REG_FIELD(_offset + 40, _startbit, _stopbit)
92 #define REG_FIELD_FOR_EACH_SENSOR16(_name, _offset, _startbit, _stopbit) \
93 [_name##_##0] = REG_FIELD(_offset, _startbit, _stopbit), \
94 [_name##_##1] = REG_FIELD(_offset + 4, _startbit, _stopbit), \
95 [_name##_##2] = REG_FIELD(_offset + 8, _startbit, _stopbit), \
96 [_name##_##3] = REG_FIELD(_offset + 12, _startbit, _stopbit), \
97 [_name##_##4] = REG_FIELD(_offset + 16, _startbit, _stopbit), \
98 [_name##_##5] = REG_FIELD(_offset + 20, _startbit, _stopbit), \
99 [_name##_##6] = REG_FIELD(_offset + 24, _startbit, _stopbit), \
100 [_name##_##7] = REG_FIELD(_offset + 28, _startbit, _stopbit), \
101 [_name##_##8] = REG_FIELD(_offset + 32, _startbit, _stopbit), \
102 [_name##_##9] = REG_FIELD(_offset + 36, _startbit, _stopbit), \
103 [_name##_##10] = REG_FIELD(_offset + 40, _startbit, _stopbit), \
104 [_name##_##11] = REG_FIELD(_offset + 44, _startbit, _stopbit), \
105 [_name##_##12] = REG_FIELD(_offset + 48, _startbit, _stopbit), \
106 [_name##_##13] = REG_FIELD(_offset + 52, _startbit, _stopbit), \
107 [_name##_##14] = REG_FIELD(_offset + 56, _startbit, _stopbit), \
108 [_name##_##15] = REG_FIELD(_offset + 60, _startbit, _stopbit)
110 #define REG_FIELD_SPLIT_BITS_0_15(_name, _offset) \
111 [_name##_##0] = REG_FIELD(_offset, 0, 0), \
112 [_name##_##1] = REG_FIELD(_offset, 1, 1), \
113 [_name##_##2] = REG_FIELD(_offset, 2, 2), \
114 [_name##_##3] = REG_FIELD(_offset, 3, 3), \
115 [_name##_##4] = REG_FIELD(_offset, 4, 4), \
116 [_name##_##5] = REG_FIELD(_offset, 5, 5), \
117 [_name##_##6] = REG_FIELD(_offset, 6, 6), \
118 [_name##_##7] = REG_FIELD(_offset, 7, 7), \
119 [_name##_##8] = REG_FIELD(_offset, 8, 8), \
120 [_name##_##9] = REG_FIELD(_offset, 9, 9), \
121 [_name##_##10] = REG_FIELD(_offset, 10, 10), \
122 [_name##_##11] = REG_FIELD(_offset, 11, 11), \
123 [_name##_##12] = REG_FIELD(_offset, 12, 12), \
124 [_name##_##13] = REG_FIELD(_offset, 13, 13), \
125 [_name##_##14] = REG_FIELD(_offset, 14, 14), \
126 [_name##_##15] = REG_FIELD(_offset, 15, 15)
128 #define REG_FIELD_SPLIT_BITS_16_31(_name, _offset) \
129 [_name##_##0] = REG_FIELD(_offset, 16, 16), \
130 [_name##_##1] = REG_FIELD(_offset, 17, 17), \
131 [_name##_##2] = REG_FIELD(_offset, 18, 18), \
132 [_name##_##3] = REG_FIELD(_offset, 19, 19), \
133 [_name##_##4] = REG_FIELD(_offset, 20, 20), \
134 [_name##_##5] = REG_FIELD(_offset, 21, 21), \
135 [_name##_##6] = REG_FIELD(_offset, 22, 22), \
136 [_name##_##7] = REG_FIELD(_offset, 23, 23), \
137 [_name##_##8] = REG_FIELD(_offset, 24, 24), \
138 [_name##_##9] = REG_FIELD(_offset, 25, 25), \
139 [_name##_##10] = REG_FIELD(_offset, 26, 26), \
140 [_name##_##11] = REG_FIELD(_offset, 27, 27), \
141 [_name##_##12] = REG_FIELD(_offset, 28, 28), \
142 [_name##_##13] = REG_FIELD(_offset, 29, 29), \
143 [_name##_##14] = REG_FIELD(_offset, 30, 30), \
144 [_name##_##15] = REG_FIELD(_offset, 31, 31)
147 * reg_field IDs to use as an index into an array
148 * If you change the order of the entries, check the devm_regmap_field_alloc()
149 * calls in init_common()
152 /* ----- SROT ------ */
163 /* ----- TM ------ */
166 /* INTERRUPT ENABLE */
167 INT_EN
, /* v2+ has separate enables for crit, upper and lower irq */
169 LAST_TEMP_0
, /* Last temperature reading */
185 VALID_0
, /* VALID reading or not */
201 LOWER_STATUS_0
, /* LOWER threshold violated */
217 LOW_INT_STATUS_0
, /* LOWER interrupt status */
233 LOW_INT_CLEAR_0
, /* LOWER interrupt clear */
249 LOW_INT_MASK_0
, /* LOWER interrupt mask */
265 LOW_THRESH_0
, /* LOWER threshold values */
281 UPPER_STATUS_0
, /* UPPER threshold violated */
297 UP_INT_STATUS_0
, /* UPPER interrupt status */
313 UP_INT_CLEAR_0
, /* UPPER interrupt clear */
329 UP_INT_MASK_0
, /* UPPER interrupt mask */
345 UP_THRESH_0
, /* UPPER threshold values */
361 CRITICAL_STATUS_0
, /* CRITICAL threshold violated */
377 MIN_STATUS_0
, /* MIN threshold violated */
393 MAX_STATUS_0
, /* MAX threshold violated */
415 * struct tsens_features - Features supported by the IP
416 * @ver_major: Major number of IP version
417 * @crit_int: does the IP support critical interrupts?
418 * @adc: do the sensors only output adc code (instead of temperature)?
419 * @srot_split: does the IP neatly splits the register space into SROT and TM,
420 * with SROT only being available to secure boot firmware?
421 * @max_sensors: maximum sensors supported by this version of the IP
423 struct tsens_features
{
424 unsigned int ver_major
;
425 unsigned int crit_int
:1;
427 unsigned int srot_split
:1;
428 unsigned int max_sensors
;
432 * struct tsens_plat_data - tsens compile-time platform data
433 * @num_sensors: Number of sensors supported by platform
434 * @ops: operations the tsens instance supports
435 * @hw_ids: Subset of sensors ids supported by platform, if not the first n
436 * @feat: features of the IP
437 * @fields: bitfield locations
439 struct tsens_plat_data
{
440 const u32 num_sensors
;
441 const struct tsens_ops
*ops
;
442 unsigned int *hw_ids
;
443 const struct tsens_features
*feat
;
444 const struct reg_field
*fields
;
448 * struct tsens_context - Registers to be saved/restored across a context loss
450 struct tsens_context
{
456 * struct tsens_priv - private data for each instance of the tsens IP
457 * @dev: pointer to struct device
458 * @num_sensors: number of sensors enabled on this device
459 * @tm_map: pointer to TM register address space
460 * @srot_map: pointer to SROT register address space
461 * @tm_offset: deal with old device trees that don't address TM and SROT
462 * address space separately
463 * @rf: array of regmap_fields used to store value of the field
464 * @ctx: registers to be saved and restored during suspend/resume
465 * @feat: features of the IP
466 * @fields: bitfield locations
467 * @ops: pointer to list of callbacks supported by this device
468 * @debug_root: pointer to debugfs dentry for all tsens
469 * @debug: pointer to debugfs dentry for tsens controller
470 * @sensor: list of sensors attached to this device
475 struct regmap
*tm_map
;
476 struct regmap
*srot_map
;
479 /* lock for upper/lower threshold interrupts */
482 struct regmap_field
*rf
[MAX_REGFIELDS
];
483 struct tsens_context ctx
;
484 const struct tsens_features
*feat
;
485 const struct reg_field
*fields
;
486 const struct tsens_ops
*ops
;
488 struct dentry
*debug_root
;
489 struct dentry
*debug
;
491 struct tsens_sensor sensor
[0];
494 char *qfprom_read(struct device
*dev
, const char *cname
);
495 void compute_intercept_slope(struct tsens_priv
*priv
, u32
*pt1
, u32
*pt2
, u32 mode
);
496 int init_common(struct tsens_priv
*priv
);
497 int get_temp_tsens_valid(struct tsens_sensor
*s
, int *temp
);
498 int get_temp_common(struct tsens_sensor
*s
, int *temp
);
499 int tsens_enable_irq(struct tsens_priv
*priv
);
500 void tsens_disable_irq(struct tsens_priv
*priv
);
501 int tsens_set_trips(void *_sensor
, int low
, int high
);
502 irqreturn_t
tsens_irq_thread(int irq
, void *data
);
505 extern const struct tsens_plat_data data_8960
;
507 /* TSENS v0.1 targets */
508 extern const struct tsens_plat_data data_8916
, data_8974
;
510 /* TSENS v1 targets */
511 extern const struct tsens_plat_data data_tsens_v1
, data_8976
;
513 /* TSENS v2 targets */
514 extern const struct tsens_plat_data data_8996
, data_tsens_v2
;
516 #endif /* __QCOM_TSENS_H__ */