xref: /linux/drivers/acpi/pmic/intel_pmic_bxtwc.c (revision 5c61f59824b5e46516ea5d0543ad7a8871567416)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Intel BXT WhiskeyCove PMIC operation region driver
4  *
5  * Copyright (C) 2015 Intel Corporation. All rights reserved.
6  */
7 
8 #include <linux/init.h>
9 #include <linux/acpi.h>
10 #include <linux/mfd/intel_soc_pmic.h>
11 #include <linux/regmap.h>
12 #include <linux/platform_device.h>
13 #include "intel_pmic.h"
14 
15 #define WHISKEY_COVE_ALRT_HIGH_BIT_MASK 0x0F
16 #define WHISKEY_COVE_ADC_HIGH_BIT(x)	(((x & 0x0F) << 8))
17 #define WHISKEY_COVE_ADC_CURSRC(x)	(((x & 0xF0) >> 4))
18 #define VR_MODE_DISABLED        0
19 #define VR_MODE_AUTO            BIT(0)
20 #define VR_MODE_NORMAL          BIT(1)
21 #define VR_MODE_SWITCH          BIT(2)
22 #define VR_MODE_ECO             (BIT(0)|BIT(1))
23 #define VSWITCH2_OUTPUT         BIT(5)
24 #define VSWITCH1_OUTPUT         BIT(4)
25 #define VUSBPHY_CHARGE          BIT(1)
26 
27 static const struct pmic_table power_table[] = {
28 	{
29 		.address = 0x0,
30 		.reg = 0x63,
31 		.bit = VR_MODE_AUTO,
32 	}, /* VDD1 -> VDD1CNT */
33 	{
34 		.address = 0x04,
35 		.reg = 0x65,
36 		.bit = VR_MODE_AUTO,
37 	}, /* VDD2 -> VDD2CNT */
38 	{
39 		.address = 0x08,
40 		.reg = 0x67,
41 		.bit = VR_MODE_AUTO,
42 	}, /* VDD3 -> VDD3CNT */
43 	{
44 		.address = 0x0c,
45 		.reg = 0x6d,
46 		.bit = VR_MODE_AUTO,
47 	}, /* VLFX -> VFLEXCNT */
48 	{
49 		.address = 0x10,
50 		.reg = 0x6f,
51 		.bit = VR_MODE_NORMAL,
52 	}, /* VP1A -> VPROG1ACNT */
53 	{
54 		.address = 0x14,
55 		.reg = 0x70,
56 		.bit = VR_MODE_NORMAL,
57 	}, /* VP1B -> VPROG1BCNT */
58 	{
59 		.address = 0x18,
60 		.reg = 0x71,
61 		.bit = VR_MODE_NORMAL,
62 	}, /* VP1C -> VPROG1CCNT */
63 	{
64 		.address = 0x1c,
65 		.reg = 0x72,
66 		.bit = VR_MODE_NORMAL,
67 	}, /* VP1D -> VPROG1DCNT */
68 	{
69 		.address = 0x20,
70 		.reg = 0x73,
71 		.bit = VR_MODE_NORMAL,
72 	}, /* VP2A -> VPROG2ACNT */
73 	{
74 		.address = 0x24,
75 		.reg = 0x74,
76 		.bit = VR_MODE_NORMAL,
77 	}, /* VP2B -> VPROG2BCNT */
78 	{
79 		.address = 0x28,
80 		.reg = 0x75,
81 		.bit = VR_MODE_NORMAL,
82 	}, /* VP2C -> VPROG2CCNT */
83 	{
84 		.address = 0x2c,
85 		.reg = 0x76,
86 		.bit = VR_MODE_NORMAL,
87 	}, /* VP3A -> VPROG3ACNT */
88 	{
89 		.address = 0x30,
90 		.reg = 0x77,
91 		.bit = VR_MODE_NORMAL,
92 	}, /* VP3B -> VPROG3BCNT */
93 	{
94 		.address = 0x34,
95 		.reg = 0x78,
96 		.bit = VSWITCH2_OUTPUT,
97 	}, /* VSW2 -> VLD0CNT Bit 5*/
98 	{
99 		.address = 0x38,
100 		.reg = 0x78,
101 		.bit = VSWITCH1_OUTPUT,
102 	}, /* VSW1 -> VLD0CNT Bit 4 */
103 	{
104 		.address = 0x3c,
105 		.reg = 0x78,
106 		.bit = VUSBPHY_CHARGE,
107 	}, /* VUPY -> VLDOCNT Bit 1 */
108 	{
109 		.address = 0x40,
110 		.reg = 0x7b,
111 		.bit = VR_MODE_NORMAL,
112 	}, /* VRSO -> VREFSOCCNT*/
113 	{
114 		.address = 0x44,
115 		.reg = 0xA0,
116 		.bit = VR_MODE_NORMAL,
117 	}, /* VP1E -> VPROG1ECNT */
118 	{
119 		.address = 0x48,
120 		.reg = 0xA1,
121 		.bit = VR_MODE_NORMAL,
122 	}, /* VP1F -> VPROG1FCNT */
123 	{
124 		.address = 0x4c,
125 		.reg = 0xA2,
126 		.bit = VR_MODE_NORMAL,
127 	}, /* VP2D -> VPROG2DCNT */
128 	{
129 		.address = 0x50,
130 		.reg = 0xA3,
131 		.bit = VR_MODE_NORMAL,
132 	}, /* VP4A -> VPROG4ACNT */
133 	{
134 		.address = 0x54,
135 		.reg = 0xA4,
136 		.bit = VR_MODE_NORMAL,
137 	}, /* VP4B -> VPROG4BCNT */
138 	{
139 		.address = 0x58,
140 		.reg = 0xA5,
141 		.bit = VR_MODE_NORMAL,
142 	}, /* VP4C -> VPROG4CCNT */
143 	{
144 		.address = 0x5c,
145 		.reg = 0xA6,
146 		.bit = VR_MODE_NORMAL,
147 	}, /* VP4D -> VPROG4DCNT */
148 	{
149 		.address = 0x60,
150 		.reg = 0xA7,
151 		.bit = VR_MODE_NORMAL,
152 	}, /* VP5A -> VPROG5ACNT */
153 	{
154 		.address = 0x64,
155 		.reg = 0xA8,
156 		.bit = VR_MODE_NORMAL,
157 	}, /* VP5B -> VPROG5BCNT */
158 	{
159 		.address = 0x68,
160 		.reg = 0xA9,
161 		.bit = VR_MODE_NORMAL,
162 	}, /* VP6A -> VPROG6ACNT */
163 	{
164 		.address = 0x6c,
165 		.reg = 0xAA,
166 		.bit = VR_MODE_NORMAL,
167 	}, /* VP6B -> VPROG6BCNT */
168 	{
169 		.address = 0x70,
170 		.reg = 0x36,
171 		.bit = BIT(2),
172 	}, /* SDWN_N -> MODEMCTRL Bit 2 */
173 	{
174 		.address = 0x74,
175 		.reg = 0x36,
176 		.bit = BIT(0),
177 	} /* MOFF -> MODEMCTRL Bit 0 */
178 };
179 
180 static const struct pmic_table thermal_table[] = {
181 	{
182 		.address = 0x00,
183 		.reg = 0x4F39
184 	},
185 	{
186 		.address = 0x04,
187 		.reg = 0x4F24
188 	},
189 	{
190 		.address = 0x08,
191 		.reg = 0x4F26
192 	},
193 	{
194 		.address = 0x0c,
195 		.reg = 0x4F3B
196 	},
197 	{
198 		.address = 0x10,
199 		.reg = 0x4F28
200 	},
201 	{
202 		.address = 0x14,
203 		.reg = 0x4F2A
204 	},
205 	{
206 		.address = 0x18,
207 		.reg = 0x4F3D
208 	},
209 	{
210 		.address = 0x1c,
211 		.reg = 0x4F2C
212 	},
213 	{
214 		.address = 0x20,
215 		.reg = 0x4F2E
216 	},
217 	{
218 		.address = 0x24,
219 		.reg = 0x4F3F
220 	},
221 	{
222 		.address = 0x28,
223 		.reg = 0x4F30
224 	},
225 	{
226 		.address = 0x30,
227 		.reg = 0x4F41
228 	},
229 	{
230 		.address = 0x34,
231 		.reg = 0x4F32
232 	},
233 	{
234 		.address = 0x3c,
235 		.reg = 0x4F43
236 	},
237 	{
238 		.address = 0x40,
239 		.reg = 0x4F34
240 	},
241 	{
242 		.address = 0x48,
243 		.reg = 0x4F6A,
244 		.bit = 0,
245 	},
246 	{
247 		.address = 0x4C,
248 		.reg = 0x4F6A,
249 		.bit = 1
250 	},
251 	{
252 		.address = 0x50,
253 		.reg = 0x4F6A,
254 		.bit = 2
255 	},
256 	{
257 		.address = 0x54,
258 		.reg = 0x4F6A,
259 		.bit = 4
260 	},
261 	{
262 		.address = 0x58,
263 		.reg = 0x4F6A,
264 		.bit = 5
265 	},
266 	{
267 		.address = 0x5C,
268 		.reg = 0x4F6A,
269 		.bit = 3
270 	},
271 };
272 
273 static int intel_bxtwc_pmic_get_power(struct regmap *regmap, int reg,
274 		int bit, u64 *value)
275 {
276 	int data;
277 
278 	if (regmap_read(regmap, reg, &data))
279 		return -EIO;
280 
281 	*value = (data & bit) ? 1 : 0;
282 	return 0;
283 }
284 
285 static int intel_bxtwc_pmic_update_power(struct regmap *regmap, int reg,
286 		int bit, bool on)
287 {
288 	u8 val, mask = bit;
289 
290 	if (on)
291 		val = 0xFF;
292 	else
293 		val = 0x0;
294 
295 	return regmap_update_bits(regmap, reg, mask, val);
296 }
297 
298 static int intel_bxtwc_pmic_get_raw_temp(struct regmap *regmap, int reg)
299 {
300 	unsigned int val, adc_val, reg_val;
301 	u8 temp_l, temp_h, cursrc;
302 	unsigned long rlsb;
303 	static const unsigned long rlsb_array[] = {
304 		0, 260420, 130210, 65100, 32550, 16280,
305 		8140, 4070, 2030, 0, 260420, 130210 };
306 
307 	if (regmap_read(regmap, reg, &val))
308 		return -EIO;
309 	temp_l = (u8) val;
310 
311 	if (regmap_read(regmap, (reg - 1), &val))
312 		return -EIO;
313 	temp_h = (u8) val;
314 
315 	reg_val = temp_l | WHISKEY_COVE_ADC_HIGH_BIT(temp_h);
316 	cursrc = WHISKEY_COVE_ADC_CURSRC(temp_h);
317 	rlsb = rlsb_array[cursrc];
318 	adc_val = reg_val * rlsb / 1000;
319 
320 	return adc_val;
321 }
322 
323 static int
324 intel_bxtwc_pmic_update_aux(struct regmap *regmap, int reg, int raw)
325 {
326 	u32 bsr_num;
327 	u16 resi_val, count = 0, thrsh = 0;
328 	u8 alrt_h, alrt_l, cursel = 0;
329 
330 	bsr_num = raw;
331 	bsr_num /= (1 << 5);
332 
333 	count = fls(bsr_num) - 1;
334 
335 	cursel = clamp_t(s8, (count - 7), 0, 7);
336 	thrsh = raw / (1 << (4 + cursel));
337 
338 	resi_val = (cursel << 9) | thrsh;
339 	alrt_h = (resi_val >> 8) & WHISKEY_COVE_ALRT_HIGH_BIT_MASK;
340 	if (regmap_update_bits(regmap,
341 				reg - 1,
342 				WHISKEY_COVE_ALRT_HIGH_BIT_MASK,
343 				alrt_h))
344 		return -EIO;
345 
346 	alrt_l = (u8)resi_val;
347 	return regmap_write(regmap, reg, alrt_l);
348 }
349 
350 static int
351 intel_bxtwc_pmic_get_policy(struct regmap *regmap, int reg, int bit, u64 *value)
352 {
353 	u8 mask = BIT(bit);
354 	unsigned int val;
355 
356 	if (regmap_read(regmap, reg, &val))
357 		return -EIO;
358 
359 	*value = (val & mask) >> bit;
360 	return 0;
361 }
362 
363 static int
364 intel_bxtwc_pmic_update_policy(struct regmap *regmap,
365 				int reg, int bit, int enable)
366 {
367 	u8 mask = BIT(bit), val = enable << bit;
368 
369 	return regmap_update_bits(regmap, reg, mask, val);
370 }
371 
372 static const struct intel_pmic_opregion_data intel_bxtwc_pmic_opregion_data = {
373 	.get_power      = intel_bxtwc_pmic_get_power,
374 	.update_power   = intel_bxtwc_pmic_update_power,
375 	.get_raw_temp   = intel_bxtwc_pmic_get_raw_temp,
376 	.update_aux     = intel_bxtwc_pmic_update_aux,
377 	.get_policy     = intel_bxtwc_pmic_get_policy,
378 	.update_policy  = intel_bxtwc_pmic_update_policy,
379 	.lpat_raw_to_temp = acpi_lpat_raw_to_temp,
380 	.power_table      = power_table,
381 	.power_table_count = ARRAY_SIZE(power_table),
382 	.thermal_table     = thermal_table,
383 	.thermal_table_count = ARRAY_SIZE(thermal_table),
384 };
385 
386 static int intel_bxtwc_pmic_opregion_probe(struct platform_device *pdev)
387 {
388 	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
389 
390 	return intel_pmic_install_opregion_handler(&pdev->dev,
391 			ACPI_HANDLE(pdev->dev.parent),
392 			pmic->regmap,
393 			&intel_bxtwc_pmic_opregion_data);
394 }
395 
396 static const struct platform_device_id bxt_wc_opregion_id_table[] = {
397 	{ .name = "bxt_wcove_region" },
398 	{},
399 };
400 
401 static struct platform_driver intel_bxtwc_pmic_opregion_driver = {
402 	.probe = intel_bxtwc_pmic_opregion_probe,
403 	.driver = {
404 		.name = "bxt_whiskey_cove_pmic",
405 	},
406 	.id_table = bxt_wc_opregion_id_table,
407 };
408 builtin_platform_driver(intel_bxtwc_pmic_opregion_driver);
409