• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * TI TPS68470 PMIC operation region driver
4  *
5  * Copyright (C) 2017 Intel Corporation. All rights reserved.
6  *
7  * Author: Rajmohan Mani <rajmohan.mani@intel.com>
8  *
9  * Based on drivers/acpi/pmic/intel_pmic* drivers
10  */
11 
12 #include <linux/acpi.h>
13 #include <linux/init.h>
14 #include <linux/mfd/tps68470.h>
15 #include <linux/platform_device.h>
16 #include <linux/regmap.h>
17 
18 struct tps68470_pmic_table {
19 	u32 address;		/* operation region address */
20 	u32 reg;		/* corresponding register */
21 	u32 bitmask;		/* bit mask for power, clock */
22 };
23 
24 #define TI_PMIC_POWER_OPREGION_ID		0xB0
25 #define TI_PMIC_VR_VAL_OPREGION_ID		0xB1
26 #define TI_PMIC_CLOCK_OPREGION_ID		0xB2
27 #define TI_PMIC_CLKFREQ_OPREGION_ID		0xB3
28 
29 struct tps68470_pmic_opregion {
30 	struct mutex lock;
31 	struct regmap *regmap;
32 };
33 
34 #define S_IO_I2C_EN	(BIT(0) | BIT(1))
35 
36 static const struct tps68470_pmic_table power_table[] = {
37 	{
38 		.address = 0x00,
39 		.reg = TPS68470_REG_S_I2C_CTL,
40 		.bitmask = S_IO_I2C_EN,
41 		/* S_I2C_CTL */
42 	},
43 	{
44 		.address = 0x04,
45 		.reg = TPS68470_REG_VCMCTL,
46 		.bitmask = BIT(0),
47 		/* VCMCTL */
48 	},
49 	{
50 		.address = 0x08,
51 		.reg = TPS68470_REG_VAUX1CTL,
52 		.bitmask = BIT(0),
53 		/* VAUX1_CTL */
54 	},
55 	{
56 		.address = 0x0C,
57 		.reg = TPS68470_REG_VAUX2CTL,
58 		.bitmask = BIT(0),
59 		/* VAUX2CTL */
60 	},
61 	{
62 		.address = 0x10,
63 		.reg = TPS68470_REG_VACTL,
64 		.bitmask = BIT(0),
65 		/* VACTL */
66 	},
67 	{
68 		.address = 0x14,
69 		.reg = TPS68470_REG_VDCTL,
70 		.bitmask = BIT(0),
71 		/* VDCTL */
72 	},
73 };
74 
75 /* Table to set voltage regulator value */
76 static const struct tps68470_pmic_table vr_val_table[] = {
77 	{
78 		.address = 0x00,
79 		.reg = TPS68470_REG_VSIOVAL,
80 		.bitmask = TPS68470_VSIOVAL_IOVOLT_MASK,
81 		/* TPS68470_REG_VSIOVAL */
82 	},
83 	{
84 		.address = 0x04,
85 		.reg = TPS68470_REG_VIOVAL,
86 		.bitmask = TPS68470_VIOVAL_IOVOLT_MASK,
87 		/* TPS68470_REG_VIOVAL */
88 	},
89 	{
90 		.address = 0x08,
91 		.reg = TPS68470_REG_VCMVAL,
92 		.bitmask = TPS68470_VCMVAL_VCVOLT_MASK,
93 		/* TPS68470_REG_VCMVAL */
94 	},
95 	{
96 		.address = 0x0C,
97 		.reg = TPS68470_REG_VAUX1VAL,
98 		.bitmask = TPS68470_VAUX1VAL_AUX1VOLT_MASK,
99 		/* TPS68470_REG_VAUX1VAL */
100 	},
101 	{
102 		.address = 0x10,
103 		.reg = TPS68470_REG_VAUX2VAL,
104 		.bitmask = TPS68470_VAUX2VAL_AUX2VOLT_MASK,
105 		/* TPS68470_REG_VAUX2VAL */
106 	},
107 	{
108 		.address = 0x14,
109 		.reg = TPS68470_REG_VAVAL,
110 		.bitmask = TPS68470_VAVAL_AVOLT_MASK,
111 		/* TPS68470_REG_VAVAL */
112 	},
113 	{
114 		.address = 0x18,
115 		.reg = TPS68470_REG_VDVAL,
116 		.bitmask = TPS68470_VDVAL_DVOLT_MASK,
117 		/* TPS68470_REG_VDVAL */
118 	},
119 };
120 
121 /* Table to configure clock frequency */
122 static const struct tps68470_pmic_table clk_freq_table[] = {
123 	{
124 		.address = 0x00,
125 		.reg = TPS68470_REG_POSTDIV2,
126 		.bitmask = BIT(0) | BIT(1),
127 		/* TPS68470_REG_POSTDIV2 */
128 	},
129 	{
130 		.address = 0x04,
131 		.reg = TPS68470_REG_BOOSTDIV,
132 		.bitmask = 0x1F,
133 		/* TPS68470_REG_BOOSTDIV */
134 	},
135 	{
136 		.address = 0x08,
137 		.reg = TPS68470_REG_BUCKDIV,
138 		.bitmask = 0x0F,
139 		/* TPS68470_REG_BUCKDIV */
140 	},
141 	{
142 		.address = 0x0C,
143 		.reg = TPS68470_REG_PLLSWR,
144 		.bitmask = 0x13,
145 		/* TPS68470_REG_PLLSWR */
146 	},
147 	{
148 		.address = 0x10,
149 		.reg = TPS68470_REG_XTALDIV,
150 		.bitmask = 0xFF,
151 		/* TPS68470_REG_XTALDIV */
152 	},
153 	{
154 		.address = 0x14,
155 		.reg = TPS68470_REG_PLLDIV,
156 		.bitmask = 0xFF,
157 		/* TPS68470_REG_PLLDIV */
158 	},
159 	{
160 		.address = 0x18,
161 		.reg = TPS68470_REG_POSTDIV,
162 		.bitmask = 0x83,
163 		/* TPS68470_REG_POSTDIV */
164 	},
165 };
166 
167 /* Table to configure and enable clocks */
168 static const struct tps68470_pmic_table clk_table[] = {
169 	{
170 		.address = 0x00,
171 		.reg = TPS68470_REG_PLLCTL,
172 		.bitmask = 0xF5,
173 		/* TPS68470_REG_PLLCTL */
174 	},
175 	{
176 		.address = 0x04,
177 		.reg = TPS68470_REG_PLLCTL2,
178 		.bitmask = BIT(0),
179 		/* TPS68470_REG_PLLCTL2 */
180 	},
181 	{
182 		.address = 0x08,
183 		.reg = TPS68470_REG_CLKCFG1,
184 		.bitmask = TPS68470_CLKCFG1_MODE_A_MASK |
185 			TPS68470_CLKCFG1_MODE_B_MASK,
186 		/* TPS68470_REG_CLKCFG1 */
187 	},
188 	{
189 		.address = 0x0C,
190 		.reg = TPS68470_REG_CLKCFG2,
191 		.bitmask = TPS68470_CLKCFG1_MODE_A_MASK |
192 			TPS68470_CLKCFG1_MODE_B_MASK,
193 		/* TPS68470_REG_CLKCFG2 */
194 	},
195 };
196 
pmic_get_reg_bit(u64 address,const struct tps68470_pmic_table * table,const unsigned int table_size,int * reg,int * bitmask)197 static int pmic_get_reg_bit(u64 address,
198 			    const struct tps68470_pmic_table *table,
199 			    const unsigned int table_size, int *reg,
200 			    int *bitmask)
201 {
202 	u64 i;
203 
204 	i = address / 4;
205 	if (i >= table_size)
206 		return -ENOENT;
207 
208 	if (!reg || !bitmask)
209 		return -EINVAL;
210 
211 	*reg = table[i].reg;
212 	*bitmask = table[i].bitmask;
213 
214 	return 0;
215 }
216 
tps68470_pmic_get_power(struct regmap * regmap,int reg,int bitmask,u64 * value)217 static int tps68470_pmic_get_power(struct regmap *regmap, int reg,
218 				       int bitmask, u64 *value)
219 {
220 	unsigned int data;
221 
222 	if (regmap_read(regmap, reg, &data))
223 		return -EIO;
224 
225 	*value = (data & bitmask) ? 1 : 0;
226 	return 0;
227 }
228 
tps68470_pmic_get_vr_val(struct regmap * regmap,int reg,int bitmask,u64 * value)229 static int tps68470_pmic_get_vr_val(struct regmap *regmap, int reg,
230 				       int bitmask, u64 *value)
231 {
232 	unsigned int data;
233 
234 	if (regmap_read(regmap, reg, &data))
235 		return -EIO;
236 
237 	*value = data & bitmask;
238 	return 0;
239 }
240 
tps68470_pmic_get_clk(struct regmap * regmap,int reg,int bitmask,u64 * value)241 static int tps68470_pmic_get_clk(struct regmap *regmap, int reg,
242 				       int bitmask, u64 *value)
243 {
244 	unsigned int data;
245 
246 	if (regmap_read(regmap, reg, &data))
247 		return -EIO;
248 
249 	*value = (data & bitmask) ? 1 : 0;
250 	return 0;
251 }
252 
tps68470_pmic_get_clk_freq(struct regmap * regmap,int reg,int bitmask,u64 * value)253 static int tps68470_pmic_get_clk_freq(struct regmap *regmap, int reg,
254 				       int bitmask, u64 *value)
255 {
256 	unsigned int data;
257 
258 	if (regmap_read(regmap, reg, &data))
259 		return -EIO;
260 
261 	*value = data & bitmask;
262 	return 0;
263 }
264 
ti_tps68470_regmap_update_bits(struct regmap * regmap,int reg,int bitmask,u64 value)265 static int ti_tps68470_regmap_update_bits(struct regmap *regmap, int reg,
266 					int bitmask, u64 value)
267 {
268 	return regmap_update_bits(regmap, reg, bitmask, value);
269 }
270 
tps68470_pmic_common_handler(u32 function,acpi_physical_address address,u32 bits,u64 * value,void * region_context,int (* get)(struct regmap *,int,int,u64 *),int (* update)(struct regmap *,int,int,u64),const struct tps68470_pmic_table * tbl,unsigned int tbl_size)271 static acpi_status tps68470_pmic_common_handler(u32 function,
272 					  acpi_physical_address address,
273 					  u32 bits, u64 *value,
274 					  void *region_context,
275 					  int (*get)(struct regmap *,
276 						     int, int, u64 *),
277 					  int (*update)(struct regmap *,
278 							int, int, u64),
279 					  const struct tps68470_pmic_table *tbl,
280 					  unsigned int tbl_size)
281 {
282 	struct tps68470_pmic_opregion *opregion = region_context;
283 	struct regmap *regmap = opregion->regmap;
284 	int reg, ret, bitmask;
285 
286 	if (bits != 32)
287 		return AE_BAD_PARAMETER;
288 
289 	ret = pmic_get_reg_bit(address, tbl, tbl_size, &reg, &bitmask);
290 	if (ret < 0)
291 		return AE_BAD_PARAMETER;
292 
293 	if (function == ACPI_WRITE && *value > bitmask)
294 		return AE_BAD_PARAMETER;
295 
296 	mutex_lock(&opregion->lock);
297 
298 	ret = (function == ACPI_READ) ?
299 		get(regmap, reg, bitmask, value) :
300 		update(regmap, reg, bitmask, *value);
301 
302 	mutex_unlock(&opregion->lock);
303 
304 	return ret ? AE_ERROR : AE_OK;
305 }
306 
tps68470_pmic_cfreq_handler(u32 function,acpi_physical_address address,u32 bits,u64 * value,void * handler_context,void * region_context)307 static acpi_status tps68470_pmic_cfreq_handler(u32 function,
308 					    acpi_physical_address address,
309 					    u32 bits, u64 *value,
310 					    void *handler_context,
311 					    void *region_context)
312 {
313 	return tps68470_pmic_common_handler(function, address, bits, value,
314 				region_context,
315 				tps68470_pmic_get_clk_freq,
316 				ti_tps68470_regmap_update_bits,
317 				clk_freq_table,
318 				ARRAY_SIZE(clk_freq_table));
319 }
320 
tps68470_pmic_clk_handler(u32 function,acpi_physical_address address,u32 bits,u64 * value,void * handler_context,void * region_context)321 static acpi_status tps68470_pmic_clk_handler(u32 function,
322 				       acpi_physical_address address, u32 bits,
323 				       u64 *value, void *handler_context,
324 				       void *region_context)
325 {
326 	return tps68470_pmic_common_handler(function, address, bits, value,
327 				region_context,
328 				tps68470_pmic_get_clk,
329 				ti_tps68470_regmap_update_bits,
330 				clk_table,
331 				ARRAY_SIZE(clk_table));
332 }
333 
tps68470_pmic_vrval_handler(u32 function,acpi_physical_address address,u32 bits,u64 * value,void * handler_context,void * region_context)334 static acpi_status tps68470_pmic_vrval_handler(u32 function,
335 					  acpi_physical_address address,
336 					  u32 bits, u64 *value,
337 					  void *handler_context,
338 					  void *region_context)
339 {
340 	return tps68470_pmic_common_handler(function, address, bits, value,
341 				region_context,
342 				tps68470_pmic_get_vr_val,
343 				ti_tps68470_regmap_update_bits,
344 				vr_val_table,
345 				ARRAY_SIZE(vr_val_table));
346 }
347 
tps68470_pmic_pwr_handler(u32 function,acpi_physical_address address,u32 bits,u64 * value,void * handler_context,void * region_context)348 static acpi_status tps68470_pmic_pwr_handler(u32 function,
349 					 acpi_physical_address address,
350 					 u32 bits, u64 *value,
351 					 void *handler_context,
352 					 void *region_context)
353 {
354 	if (bits != 32)
355 		return AE_BAD_PARAMETER;
356 
357 	/* set/clear for bit 0, bits 0 and 1 together */
358 	if (function == ACPI_WRITE &&
359 	    !(*value == 0 || *value == 1 || *value == 3)) {
360 		return AE_BAD_PARAMETER;
361 	}
362 
363 	return tps68470_pmic_common_handler(function, address, bits, value,
364 				region_context,
365 				tps68470_pmic_get_power,
366 				ti_tps68470_regmap_update_bits,
367 				power_table,
368 				ARRAY_SIZE(power_table));
369 }
370 
tps68470_pmic_opregion_probe(struct platform_device * pdev)371 static int tps68470_pmic_opregion_probe(struct platform_device *pdev)
372 {
373 	struct regmap *tps68470_regmap = dev_get_drvdata(pdev->dev.parent);
374 	acpi_handle handle = ACPI_HANDLE(pdev->dev.parent);
375 	struct device *dev = &pdev->dev;
376 	struct tps68470_pmic_opregion *opregion;
377 	acpi_status status;
378 
379 	if (!dev || !tps68470_regmap) {
380 		dev_warn(dev, "dev or regmap is NULL\n");
381 		return -EINVAL;
382 	}
383 
384 	if (!handle) {
385 		dev_warn(dev, "acpi handle is NULL\n");
386 		return -ENODEV;
387 	}
388 
389 	opregion = devm_kzalloc(dev, sizeof(*opregion), GFP_KERNEL);
390 	if (!opregion)
391 		return -ENOMEM;
392 
393 	mutex_init(&opregion->lock);
394 	opregion->regmap = tps68470_regmap;
395 
396 	status = acpi_install_address_space_handler(handle,
397 						    TI_PMIC_POWER_OPREGION_ID,
398 						    tps68470_pmic_pwr_handler,
399 						    NULL, opregion);
400 	if (ACPI_FAILURE(status))
401 		goto out_mutex_destroy;
402 
403 	status = acpi_install_address_space_handler(handle,
404 						    TI_PMIC_VR_VAL_OPREGION_ID,
405 						    tps68470_pmic_vrval_handler,
406 						    NULL, opregion);
407 	if (ACPI_FAILURE(status))
408 		goto out_remove_power_handler;
409 
410 	status = acpi_install_address_space_handler(handle,
411 						    TI_PMIC_CLOCK_OPREGION_ID,
412 						    tps68470_pmic_clk_handler,
413 						    NULL, opregion);
414 	if (ACPI_FAILURE(status))
415 		goto out_remove_vr_val_handler;
416 
417 	status = acpi_install_address_space_handler(handle,
418 						    TI_PMIC_CLKFREQ_OPREGION_ID,
419 						    tps68470_pmic_cfreq_handler,
420 						    NULL, opregion);
421 	if (ACPI_FAILURE(status))
422 		goto out_remove_clk_handler;
423 
424 	return 0;
425 
426 out_remove_clk_handler:
427 	acpi_remove_address_space_handler(handle, TI_PMIC_CLOCK_OPREGION_ID,
428 					  tps68470_pmic_clk_handler);
429 out_remove_vr_val_handler:
430 	acpi_remove_address_space_handler(handle, TI_PMIC_VR_VAL_OPREGION_ID,
431 					  tps68470_pmic_vrval_handler);
432 out_remove_power_handler:
433 	acpi_remove_address_space_handler(handle, TI_PMIC_POWER_OPREGION_ID,
434 					  tps68470_pmic_pwr_handler);
435 out_mutex_destroy:
436 	mutex_destroy(&opregion->lock);
437 	return -ENODEV;
438 }
439 
440 static struct platform_driver tps68470_pmic_opregion_driver = {
441 	.probe = tps68470_pmic_opregion_probe,
442 	.driver = {
443 		.name = "tps68470_pmic_opregion",
444 	},
445 };
446 
447 builtin_platform_driver(tps68470_pmic_opregion_driver)
448