drivers: thermal: tsens: simplify get_temp_tsens_v2 routine
[linux-2.6-block.git] / drivers / thermal / qcom / tsens-v2.c
CommitLineData
770324a4 1// SPDX-License-Identifier: GPL-2.0
d059c739
RN
2/*
3 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
770324a4 4 * Copyright (c) 2018, Linaro Limited
d059c739
RN
5 */
6
432121ad 7#include <linux/bitops.h>
c1997054 8#include <linux/regmap.h>
d059c739
RN
9#include "tsens.h"
10
c1997054
AK
11/* ----- SROT ------ */
12#define SROT_HW_VER_OFF 0x0000
13#define SROT_CTRL_OFF 0x0004
14
15/* ----- TM ------ */
16#define TM_INT_EN_OFF 0x0004
17#define TM_UPPER_LOWER_INT_STATUS_OFF 0x0008
18#define TM_UPPER_LOWER_INT_CLEAR_OFF 0x000c
19#define TM_UPPER_LOWER_INT_MASK_OFF 0x0010
20#define TM_CRITICAL_INT_STATUS_OFF 0x0014
21#define TM_CRITICAL_INT_CLEAR_OFF 0x0018
22#define TM_CRITICAL_INT_MASK_OFF 0x001c
23#define TM_Sn_UPPER_LOWER_THRESHOLD_OFF 0x0020
24#define TM_Sn_CRITICAL_THRESHOLD_OFF 0x0060
25#define TM_Sn_STATUS_OFF 0x00a0
26#define TM_TRDY_OFF 0x00e4
27
dbdaa582 28static int get_temp_tsens_v2(struct tsens_priv *priv, int i, int *temp)
d059c739 29{
dbdaa582 30 struct tsens_sensor *s = &priv->sensor[i];
c1997054
AK
31 u32 temp_idx = LAST_TEMP_0 + s->hw_id;
32 u32 valid_idx = VALID_0 + s->hw_id;
dbdaa582 33 u32 last_temp = 0, valid, mask;
432121ad 34 int ret;
d059c739 35
c1997054 36 ret = regmap_field_read(priv->rf[valid_idx], &valid);
d059c739
RN
37 if (ret)
38 return ret;
dbdaa582
AK
39 while (!valid) {
40 /* Valid bit is 0 for 6 AHB clock cycles.
41 * At 19.2MHz, 1 AHB clock is ~60ns.
42 * We should enter this loop very, very rarely.
43 */
44 ndelay(400);
45 ret = regmap_field_read(priv->rf[valid_idx], &valid);
46 if (ret)
47 return ret;
d059c739
RN
48 }
49
dbdaa582
AK
50 /* Valid bit is set, OK to read the temperature */
51 ret = regmap_field_read(priv->rf[temp_idx], &last_temp);
c1997054
AK
52 if (ret)
53 return ret;
d059c739 54
dbdaa582
AK
55 mask = GENMASK(priv->fields[LAST_TEMP_0].msb,
56 priv->fields[LAST_TEMP_0].lsb);
432121ad 57 /* Convert temperature from deciCelsius to milliCelsius */
dbdaa582 58 *temp = sign_extend32(last_temp, fls(mask) - 1) * 100;
d059c739
RN
59
60 return 0;
61}
62
c1997054
AK
63/* v2.x: 8996, 8998, sdm845 */
64
65static const struct tsens_features tsens_v2_feat = {
66 .ver_major = VER_2_X,
67 .crit_int = 1,
68 .adc = 0,
69 .srot_split = 1,
1b6e3e51 70 .max_sensors = 16,
c1997054
AK
71};
72
73static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = {
74 /* ----- SROT ------ */
75 /* VERSION */
76 [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31),
77 [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27),
78 [VER_STEP] = REG_FIELD(SROT_HW_VER_OFF, 0, 15),
79 /* CTRL_OFF */
80 [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0),
81 [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1),
3e6a8fb3 82 [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 18),
c1997054
AK
83
84 /* ----- TM ------ */
85 /* INTERRUPT ENABLE */
86 /* v2 has separate enables for UPPER/LOWER/CRITICAL interrupts */
87 [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 2),
88
89 /* Sn_STATUS */
90 REG_FIELD_FOR_EACH_SENSOR16(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 11),
91 REG_FIELD_FOR_EACH_SENSOR16(VALID, TM_Sn_STATUS_OFF, 21, 21),
92 REG_FIELD_FOR_EACH_SENSOR16(MIN_STATUS, TM_Sn_STATUS_OFF, 16, 16),
93 REG_FIELD_FOR_EACH_SENSOR16(LOWER_STATUS, TM_Sn_STATUS_OFF, 17, 17),
94 REG_FIELD_FOR_EACH_SENSOR16(UPPER_STATUS, TM_Sn_STATUS_OFF, 18, 18),
95 REG_FIELD_FOR_EACH_SENSOR16(CRITICAL_STATUS, TM_Sn_STATUS_OFF, 19, 19),
96 REG_FIELD_FOR_EACH_SENSOR16(MAX_STATUS, TM_Sn_STATUS_OFF, 20, 20),
97
98 /* TRDY: 1=ready, 0=in progress */
99 [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
100};
101
770324a4 102static const struct tsens_ops ops_generic_v2 = {
d059c739 103 .init = init_common,
770324a4 104 .get_temp = get_temp_tsens_v2,
d059c739
RN
105};
106
3c040ce0 107const struct tsens_plat_data data_tsens_v2 = {
c1997054
AK
108 .ops = &ops_generic_v2,
109 .feat = &tsens_v2_feat,
110 .fields = tsens_v2_regfields,
191dc74b
AK
111};
112
113/* Kept around for backward compatibility with old msm8996.dtsi */
3c040ce0 114const struct tsens_plat_data data_8996 = {
d059c739 115 .num_sensors = 13,
770324a4 116 .ops = &ops_generic_v2,
c1997054
AK
117 .feat = &tsens_v2_feat,
118 .fields = tsens_v2_regfields,
d059c739 119};