1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/platform_device.h>
7#include <linux/delay.h>
8#include <linux/bitops.h>
9#include <linux/regmap.h>
10#include <linux/thermal.h>
11#include "tsens.h"
12
13#define CONFIG_ADDR		0x3640
14#define CONFIG_ADDR_8660	0x3620
15/* CONFIG_ADDR bitmasks */
16#define CONFIG			0x9b
17#define CONFIG_MASK		0xf
18#define CONFIG_8660		1
19#define CONFIG_SHIFT_8660	28
20#define CONFIG_MASK_8660	(3 << CONFIG_SHIFT_8660)
21
22#define CNTL_ADDR		0x3620
23/* CNTL_ADDR bitmasks */
24#define EN			BIT(0)
25#define SW_RST			BIT(1)
26
27#define MEASURE_PERIOD		BIT(18)
28#define SLP_CLK_ENA		BIT(26)
29#define SLP_CLK_ENA_8660	BIT(24)
30#define SENSOR0_SHIFT		3
31
32#define THRESHOLD_ADDR		0x3624
33
34#define INT_STATUS_ADDR		0x363c
35
36#define S0_STATUS_OFF		0x3628
37#define S1_STATUS_OFF		0x362c
38#define S2_STATUS_OFF		0x3630
39#define S3_STATUS_OFF		0x3634
40#define S4_STATUS_OFF		0x3638
41#define S5_STATUS_OFF		0x3664  /* Sensors 5-10 found on apq8064/msm8960 */
42#define S6_STATUS_OFF		0x3668
43#define S7_STATUS_OFF		0x366c
44#define S8_STATUS_OFF		0x3670
45#define S9_STATUS_OFF		0x3674
46#define S10_STATUS_OFF		0x3678
47
48/* Original slope - 350 to compensate mC to C inaccuracy */
49static u32 tsens_msm8960_slope[] = {
50			826, 826, 804, 826,
51			761, 782, 782, 849,
52			782, 849, 782
53			};
54
55static int suspend_8960(struct tsens_priv *priv)
56{
57	int ret;
58	unsigned int mask;
59	struct regmap *map = priv->tm_map;
60
61	ret = regmap_read(map, THRESHOLD_ADDR, &priv->ctx.threshold);
62	if (ret)
63		return ret;
64
65	ret = regmap_read(map, CNTL_ADDR, &priv->ctx.control);
66	if (ret)
67		return ret;
68
69	if (priv->num_sensors > 1)
70		mask = SLP_CLK_ENA | EN;
71	else
72		mask = SLP_CLK_ENA_8660 | EN;
73
74	ret = regmap_update_bits(map, CNTL_ADDR, mask, 0);
75	if (ret)
76		return ret;
77
78	return 0;
79}
80
81static int resume_8960(struct tsens_priv *priv)
82{
83	int ret;
84	struct regmap *map = priv->tm_map;
85
86	ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
87	if (ret)
88		return ret;
89
90	/*
91	 * Separate CONFIG restore is not needed only for 8660 as
92	 * config is part of CTRL Addr and its restored as such
93	 */
94	if (priv->num_sensors > 1) {
95		ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
96		if (ret)
97			return ret;
98	}
99
100	ret = regmap_write(map, THRESHOLD_ADDR, priv->ctx.threshold);
101	if (ret)
102		return ret;
103
104	ret = regmap_write(map, CNTL_ADDR, priv->ctx.control);
105	if (ret)
106		return ret;
107
108	return 0;
109}
110
111static int enable_8960(struct tsens_priv *priv, int id)
112{
113	int ret;
114	u32 reg, mask = BIT(id);
115
116	ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg);
117	if (ret)
118		return ret;
119
120	/* HARDWARE BUG:
121	 * On platforms with more than 6 sensors, all remaining sensors
122	 * must be enabled together, otherwise undefined results are expected.
123	 * (Sensor 6-7 disabled, Sensor 3 disabled...) In the original driver,
124	 * all the sensors are enabled in one step hence this bug is not
125	 * triggered.
126	 */
127	if (id > 5)
128		mask = GENMASK(10, 6);
129
130	mask <<= SENSOR0_SHIFT;
131
132	/* Sensors already enabled. Skip. */
133	if ((reg & mask) == mask)
134		return 0;
135
136	ret = regmap_write(priv->tm_map, CNTL_ADDR, reg | SW_RST);
137	if (ret)
138		return ret;
139
140	reg |= MEASURE_PERIOD;
141
142	if (priv->num_sensors > 1)
143		reg |= mask | SLP_CLK_ENA | EN;
144	else
145		reg |= mask | SLP_CLK_ENA_8660 | EN;
146
147	ret = regmap_write(priv->tm_map, CNTL_ADDR, reg);
148	if (ret)
149		return ret;
150
151	return 0;
152}
153
154static void disable_8960(struct tsens_priv *priv)
155{
156	int ret;
157	u32 reg_cntl;
158	u32 mask;
159
160	mask = GENMASK(priv->num_sensors - 1, 0);
161	mask <<= SENSOR0_SHIFT;
162	mask |= EN;
163
164	ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg_cntl);
165	if (ret)
166		return;
167
168	reg_cntl &= ~mask;
169
170	if (priv->num_sensors > 1)
171		reg_cntl &= ~SLP_CLK_ENA;
172	else
173		reg_cntl &= ~SLP_CLK_ENA_8660;
174
175	regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
176}
177
178static int calibrate_8960(struct tsens_priv *priv)
179{
180	int i;
181	char *data;
182	u32 p1[11];
183
184	data = qfprom_read(priv->dev, "calib");
185	if (IS_ERR(data))
186		data = qfprom_read(priv->dev, "calib_backup");
187	if (IS_ERR(data))
188		return PTR_ERR(data);
189
190	for (i = 0; i < priv->num_sensors; i++) {
191		p1[i] = data[i];
192		priv->sensor[i].slope = tsens_msm8960_slope[i];
193	}
194
195	compute_intercept_slope(priv, p1, NULL, ONE_PT_CALIB);
196
197	kfree(data);
198
199	return 0;
200}
201
202static const struct reg_field tsens_8960_regfields[MAX_REGFIELDS] = {
203	/* ----- SROT ------ */
204	/* No VERSION information */
205
206	/* CNTL */
207	[TSENS_EN]     = REG_FIELD(CNTL_ADDR,  0, 0),
208	[TSENS_SW_RST] = REG_FIELD(CNTL_ADDR,  1, 1),
209	/* 8960 has 5 sensors, 8660 has 11, we only handle 5 */
210	[SENSOR_EN]    = REG_FIELD(CNTL_ADDR,  3, 7),
211
212	/* ----- TM ------ */
213	/* INTERRUPT ENABLE */
214	/* NO INTERRUPT ENABLE */
215
216	/* Single UPPER/LOWER TEMPERATURE THRESHOLD for all sensors */
217	[LOW_THRESH_0]   = REG_FIELD(THRESHOLD_ADDR,  0,  7),
218	[UP_THRESH_0]    = REG_FIELD(THRESHOLD_ADDR,  8, 15),
219	/* MIN_THRESH_0 and MAX_THRESH_0 are not present in the regfield
220	 * Recycle CRIT_THRESH_0 and 1 to set the required regs to hardcoded temp
221	 * MIN_THRESH_0 -> CRIT_THRESH_1
222	 * MAX_THRESH_0 -> CRIT_THRESH_0
223	 */
224	[CRIT_THRESH_1]   = REG_FIELD(THRESHOLD_ADDR, 16, 23),
225	[CRIT_THRESH_0]   = REG_FIELD(THRESHOLD_ADDR, 24, 31),
226
227	/* UPPER/LOWER INTERRUPT [CLEAR/STATUS] */
228	/* 1 == clear, 0 == normal operation */
229	[LOW_INT_CLEAR_0]   = REG_FIELD(CNTL_ADDR,  9,  9),
230	[UP_INT_CLEAR_0]    = REG_FIELD(CNTL_ADDR, 10, 10),
231
232	/* NO CRITICAL INTERRUPT SUPPORT on 8960 */
233
234	/* Sn_STATUS */
235	[LAST_TEMP_0]  = REG_FIELD(S0_STATUS_OFF,  0,  7),
236	[LAST_TEMP_1]  = REG_FIELD(S1_STATUS_OFF,  0,  7),
237	[LAST_TEMP_2]  = REG_FIELD(S2_STATUS_OFF,  0,  7),
238	[LAST_TEMP_3]  = REG_FIELD(S3_STATUS_OFF,  0,  7),
239	[LAST_TEMP_4]  = REG_FIELD(S4_STATUS_OFF,  0,  7),
240	[LAST_TEMP_5]  = REG_FIELD(S5_STATUS_OFF,  0,  7),
241	[LAST_TEMP_6]  = REG_FIELD(S6_STATUS_OFF,  0,  7),
242	[LAST_TEMP_7]  = REG_FIELD(S7_STATUS_OFF,  0,  7),
243	[LAST_TEMP_8]  = REG_FIELD(S8_STATUS_OFF,  0,  7),
244	[LAST_TEMP_9]  = REG_FIELD(S9_STATUS_OFF,  0,  7),
245	[LAST_TEMP_10] = REG_FIELD(S10_STATUS_OFF, 0,  7),
246
247	/* No VALID field on 8960 */
248	/* TSENS_INT_STATUS bits: 1 == threshold violated */
249	[MIN_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 0, 0),
250	[LOWER_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 1, 1),
251	[UPPER_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 2, 2),
252	/* No CRITICAL field on 8960 */
253	[MAX_STATUS_0] = REG_FIELD(INT_STATUS_ADDR, 3, 3),
254
255	/* TRDY: 1=ready, 0=in progress */
256	[TRDY] = REG_FIELD(INT_STATUS_ADDR, 7, 7),
257};
258
259static const struct tsens_ops ops_8960 = {
260	.init		= init_common,
261	.calibrate	= calibrate_8960,
262	.get_temp	= get_temp_common,
263	.enable		= enable_8960,
264	.disable	= disable_8960,
265	.suspend	= suspend_8960,
266	.resume		= resume_8960,
267};
268
269static struct tsens_features tsens_8960_feat = {
270	.ver_major	= VER_0,
271	.crit_int	= 0,
272	.combo_int	= 0,
273	.adc		= 1,
274	.srot_split	= 0,
275	.max_sensors	= 11,
276	.trip_min_temp	= -40000,
277	.trip_max_temp	= 120000,
278};
279
280struct tsens_plat_data data_8960 = {
281	.num_sensors	= 11,
282	.ops		= &ops_8960,
283	.feat		= &tsens_8960_feat,
284	.fields		= tsens_8960_regfields,
285};
286