xref: /openbmc/linux/arch/arm/mach-omap2/pmic-cpcap.c (revision 818b26588994d9d95743fca0a427f08ec6c1c41d)
1d44fa156STony Lindgren // SPDX-License-Identifier: GPL-2.0-only
2d44fa156STony Lindgren /*
3d44fa156STony Lindgren  * pmic-cpcap.c - CPCAP-specific functions for the OPP code
4d44fa156STony Lindgren  *
5d44fa156STony Lindgren  * Adapted from Motorola Mapphone Android Linux kernel
6d44fa156STony Lindgren  * Copyright (C) 2011 Motorola, Inc.
7d44fa156STony Lindgren  */
8d44fa156STony Lindgren 
9d44fa156STony Lindgren #include <linux/err.h>
10d44fa156STony Lindgren #include <linux/io.h>
11d44fa156STony Lindgren #include <linux/kernel.h>
12d44fa156STony Lindgren 
13d44fa156STony Lindgren #include "soc.h"
14d44fa156STony Lindgren #include "pm.h"
15d44fa156STony Lindgren #include "voltage.h"
16d44fa156STony Lindgren 
17d44fa156STony Lindgren #include <linux/init.h>
18d44fa156STony Lindgren #include "vc.h"
19d44fa156STony Lindgren 
20d44fa156STony Lindgren /**
21d44fa156STony Lindgren  * omap_cpcap_vsel_to_vdc - convert CPCAP VSEL value to microvolts DC
22d44fa156STony Lindgren  * @vsel: CPCAP VSEL value to convert
23d44fa156STony Lindgren  *
24d44fa156STony Lindgren  * Returns the microvolts DC that the CPCAP PMIC should generate when
25d44fa156STony Lindgren  * programmed with @vsel.
26d44fa156STony Lindgren  */
omap_cpcap_vsel_to_uv(unsigned char vsel)27821093e1SYueHaibing static unsigned long omap_cpcap_vsel_to_uv(unsigned char vsel)
28d44fa156STony Lindgren {
29d44fa156STony Lindgren 	if (vsel > 0x44)
30d44fa156STony Lindgren 		vsel = 0x44;
31d44fa156STony Lindgren 	return (((vsel * 125) + 6000)) * 100;
32d44fa156STony Lindgren }
33d44fa156STony Lindgren 
34d44fa156STony Lindgren /**
35d44fa156STony Lindgren  * omap_cpcap_uv_to_vsel - convert microvolts DC to CPCAP VSEL value
36d44fa156STony Lindgren  * @uv: microvolts DC to convert
37d44fa156STony Lindgren  *
38d44fa156STony Lindgren  * Returns the VSEL value necessary for the CPCAP PMIC to
39d44fa156STony Lindgren  * generate an output voltage equal to or greater than @uv microvolts DC.
40d44fa156STony Lindgren  */
omap_cpcap_uv_to_vsel(unsigned long uv)41821093e1SYueHaibing static unsigned char omap_cpcap_uv_to_vsel(unsigned long uv)
42d44fa156STony Lindgren {
43d44fa156STony Lindgren 	if (uv < 600000)
44d44fa156STony Lindgren 		uv = 600000;
45d44fa156STony Lindgren 	else if (uv > 1450000)
46d44fa156STony Lindgren 		uv = 1450000;
47d44fa156STony Lindgren 	return DIV_ROUND_UP(uv - 600000, 12500);
48d44fa156STony Lindgren }
49d44fa156STony Lindgren 
50d44fa156STony Lindgren static struct omap_voltdm_pmic omap_cpcap_core = {
51d44fa156STony Lindgren 	.slew_rate = 4000,
52d44fa156STony Lindgren 	.step_size = 12500,
53d44fa156STony Lindgren 	.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
54d44fa156STony Lindgren 	.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
55d44fa156STony Lindgren 	.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
56d44fa156STony Lindgren 	.vddmin = 900000,
57d44fa156STony Lindgren 	.vddmax = 1350000,
58d44fa156STony Lindgren 	.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
59d44fa156STony Lindgren 	.i2c_slave_addr = 0x02,
60d44fa156STony Lindgren 	.volt_reg_addr = 0x00,
61d44fa156STony Lindgren 	.cmd_reg_addr = 0x01,
62c145649bSTony Lindgren 	.i2c_high_speed = false,
63d44fa156STony Lindgren 	.vsel_to_uv = omap_cpcap_vsel_to_uv,
64d44fa156STony Lindgren 	.uv_to_vsel = omap_cpcap_uv_to_vsel,
65d44fa156STony Lindgren };
66d44fa156STony Lindgren 
67d44fa156STony Lindgren static struct omap_voltdm_pmic omap_cpcap_iva = {
68d44fa156STony Lindgren 	.slew_rate = 4000,
69d44fa156STony Lindgren 	.step_size = 12500,
70d44fa156STony Lindgren 	.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
71d44fa156STony Lindgren 	.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
72d44fa156STony Lindgren 	.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
73d44fa156STony Lindgren 	.vddmin = 900000,
74c0bc969cSCarl Philipp Klemm 	.vddmax = 1375000,
75d44fa156STony Lindgren 	.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
76d44fa156STony Lindgren 	.i2c_slave_addr = 0x44,
77d44fa156STony Lindgren 	.volt_reg_addr = 0x0,
78d44fa156STony Lindgren 	.cmd_reg_addr = 0x01,
79c145649bSTony Lindgren 	.i2c_high_speed = false,
80d44fa156STony Lindgren 	.vsel_to_uv = omap_cpcap_vsel_to_uv,
81d44fa156STony Lindgren 	.uv_to_vsel = omap_cpcap_uv_to_vsel,
82d44fa156STony Lindgren };
83d44fa156STony Lindgren 
84d44fa156STony Lindgren /**
85d44fa156STony Lindgren  * omap_max8952_vsel_to_vdc - convert MAX8952 VSEL value to microvolts DC
86d44fa156STony Lindgren  * @vsel: MAX8952 VSEL value to convert
87d44fa156STony Lindgren  *
88d44fa156STony Lindgren  * Returns the microvolts DC that the MAX8952 Regulator should generate when
89d44fa156STony Lindgren  * programmed with @vsel.
90d44fa156STony Lindgren  */
omap_max8952_vsel_to_uv(unsigned char vsel)91821093e1SYueHaibing static unsigned long omap_max8952_vsel_to_uv(unsigned char vsel)
92d44fa156STony Lindgren {
93d44fa156STony Lindgren 	if (vsel > 0x3F)
94d44fa156STony Lindgren 		vsel = 0x3F;
95d44fa156STony Lindgren 	return (((vsel * 100) + 7700)) * 100;
96d44fa156STony Lindgren }
97d44fa156STony Lindgren 
98d44fa156STony Lindgren /**
99d44fa156STony Lindgren  * omap_max8952_uv_to_vsel - convert microvolts DC to MAX8952 VSEL value
100d44fa156STony Lindgren  * @uv: microvolts DC to convert
101d44fa156STony Lindgren  *
102d44fa156STony Lindgren  * Returns the VSEL value necessary for the MAX8952 Regulator to
103d44fa156STony Lindgren  * generate an output voltage equal to or greater than @uv microvolts DC.
104d44fa156STony Lindgren  */
omap_max8952_uv_to_vsel(unsigned long uv)105821093e1SYueHaibing static unsigned char omap_max8952_uv_to_vsel(unsigned long uv)
106d44fa156STony Lindgren {
107d44fa156STony Lindgren 	if (uv < 770000)
108d44fa156STony Lindgren 		uv = 770000;
109d44fa156STony Lindgren 	else if (uv > 1400000)
110d44fa156STony Lindgren 		uv = 1400000;
111d44fa156STony Lindgren 	return DIV_ROUND_UP(uv - 770000, 10000);
112d44fa156STony Lindgren }
113d44fa156STony Lindgren 
114d44fa156STony Lindgren static struct omap_voltdm_pmic omap443x_max8952_mpu = {
115d44fa156STony Lindgren 	.slew_rate = 16000,
116d44fa156STony Lindgren 	.step_size = 10000,
117d44fa156STony Lindgren 	.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
118d44fa156STony Lindgren 	.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
119d44fa156STony Lindgren 	.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
120d44fa156STony Lindgren 	.vddmin = 900000,
121d44fa156STony Lindgren 	.vddmax = 1400000,
122d44fa156STony Lindgren 	.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
123d44fa156STony Lindgren 	.i2c_slave_addr = 0x60,
124d44fa156STony Lindgren 	.volt_reg_addr = 0x03,
125d44fa156STony Lindgren 	.cmd_reg_addr = 0x03,
126c145649bSTony Lindgren 	.i2c_high_speed = false,
127d44fa156STony Lindgren 	.vsel_to_uv = omap_max8952_vsel_to_uv,
128d44fa156STony Lindgren 	.uv_to_vsel = omap_max8952_uv_to_vsel,
129d44fa156STony Lindgren };
130d44fa156STony Lindgren 
131d44fa156STony Lindgren /**
132d44fa156STony Lindgren  * omap_fan5355_vsel_to_vdc - convert FAN535503 VSEL value to microvolts DC
133d44fa156STony Lindgren  * @vsel: FAN535503 VSEL value to convert
134d44fa156STony Lindgren  *
135d44fa156STony Lindgren  * Returns the microvolts DC that the FAN535503 Regulator should generate when
136d44fa156STony Lindgren  * programmed with @vsel.
137d44fa156STony Lindgren  */
omap_fan535503_vsel_to_uv(unsigned char vsel)138821093e1SYueHaibing static unsigned long omap_fan535503_vsel_to_uv(unsigned char vsel)
139d44fa156STony Lindgren {
140d44fa156STony Lindgren 	/* Extract bits[5:0] */
141d44fa156STony Lindgren 	vsel &= 0x3F;
142d44fa156STony Lindgren 
143d44fa156STony Lindgren 	return (((vsel * 125) + 7500)) * 100;
144d44fa156STony Lindgren }
145d44fa156STony Lindgren 
146d44fa156STony Lindgren /**
147d44fa156STony Lindgren  * omap_fan535508_vsel_to_vdc - convert FAN535508 VSEL value to microvolts DC
148d44fa156STony Lindgren  * @vsel: FAN535508 VSEL value to convert
149d44fa156STony Lindgren  *
150d44fa156STony Lindgren  * Returns the microvolts DC that the FAN535508 Regulator should generate when
151d44fa156STony Lindgren  * programmed with @vsel.
152d44fa156STony Lindgren  */
omap_fan535508_vsel_to_uv(unsigned char vsel)153821093e1SYueHaibing static unsigned long omap_fan535508_vsel_to_uv(unsigned char vsel)
154d44fa156STony Lindgren {
155d44fa156STony Lindgren 	/* Extract bits[5:0] */
156d44fa156STony Lindgren 	vsel &= 0x3F;
157d44fa156STony Lindgren 
158d44fa156STony Lindgren 	if (vsel > 0x37)
159d44fa156STony Lindgren 		vsel = 0x37;
160d44fa156STony Lindgren 	return (((vsel * 125) + 7500)) * 100;
161d44fa156STony Lindgren }
162d44fa156STony Lindgren 
163d44fa156STony Lindgren 
164d44fa156STony Lindgren /**
165d44fa156STony Lindgren  * omap_fan535503_uv_to_vsel - convert microvolts DC to FAN535503 VSEL value
166d44fa156STony Lindgren  * @uv: microvolts DC to convert
167d44fa156STony Lindgren  *
168d44fa156STony Lindgren  * Returns the VSEL value necessary for the MAX8952 Regulator to
169d44fa156STony Lindgren  * generate an output voltage equal to or greater than @uv microvolts DC.
170d44fa156STony Lindgren  */
omap_fan535503_uv_to_vsel(unsigned long uv)171821093e1SYueHaibing static unsigned char omap_fan535503_uv_to_vsel(unsigned long uv)
172d44fa156STony Lindgren {
173d44fa156STony Lindgren 	unsigned char vsel;
174d44fa156STony Lindgren 	if (uv < 750000)
175d44fa156STony Lindgren 		uv = 750000;
176d44fa156STony Lindgren 	else if (uv > 1537500)
177d44fa156STony Lindgren 		uv = 1537500;
178d44fa156STony Lindgren 
179d44fa156STony Lindgren 	vsel = DIV_ROUND_UP(uv - 750000, 12500);
180d44fa156STony Lindgren 	return vsel | 0xC0;
181d44fa156STony Lindgren }
182d44fa156STony Lindgren 
183d44fa156STony Lindgren /**
184d44fa156STony Lindgren  * omap_fan535508_uv_to_vsel - convert microvolts DC to FAN535508 VSEL value
185d44fa156STony Lindgren  * @uv: microvolts DC to convert
186d44fa156STony Lindgren  *
187d44fa156STony Lindgren  * Returns the VSEL value necessary for the MAX8952 Regulator to
188d44fa156STony Lindgren  * generate an output voltage equal to or greater than @uv microvolts DC.
189d44fa156STony Lindgren  */
omap_fan535508_uv_to_vsel(unsigned long uv)190821093e1SYueHaibing static unsigned char omap_fan535508_uv_to_vsel(unsigned long uv)
191d44fa156STony Lindgren {
192d44fa156STony Lindgren 	unsigned char vsel;
193d44fa156STony Lindgren 	if (uv < 750000)
194d44fa156STony Lindgren 		uv = 750000;
195d44fa156STony Lindgren 	else if (uv > 1437500)
196d44fa156STony Lindgren 		uv = 1437500;
197d44fa156STony Lindgren 
198d44fa156STony Lindgren 	vsel = DIV_ROUND_UP(uv - 750000, 12500);
199d44fa156STony Lindgren 	return vsel | 0xC0;
200d44fa156STony Lindgren }
201d44fa156STony Lindgren 
202d44fa156STony Lindgren /* fan5335-core */
203d44fa156STony Lindgren static struct omap_voltdm_pmic omap4_fan_core = {
204d44fa156STony Lindgren 	.slew_rate = 4000,
205d44fa156STony Lindgren 	.step_size = 12500,
206d44fa156STony Lindgren 	.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
207d44fa156STony Lindgren 	.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
208d44fa156STony Lindgren 	.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
209d44fa156STony Lindgren 	.vddmin = 850000,
210d44fa156STony Lindgren 	.vddmax = 1375000,
211d44fa156STony Lindgren 	.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
212d44fa156STony Lindgren 	.i2c_slave_addr = 0x4A,
213c145649bSTony Lindgren 	.i2c_high_speed = false,
214d44fa156STony Lindgren 	.volt_reg_addr = 0x01,
215d44fa156STony Lindgren 	.cmd_reg_addr = 0x01,
216d44fa156STony Lindgren 	.vsel_to_uv = omap_fan535508_vsel_to_uv,
217d44fa156STony Lindgren 	.uv_to_vsel = omap_fan535508_uv_to_vsel,
218d44fa156STony Lindgren };
219d44fa156STony Lindgren 
220d44fa156STony Lindgren /* fan5335 iva */
221d44fa156STony Lindgren static struct omap_voltdm_pmic omap4_fan_iva = {
222d44fa156STony Lindgren 	.slew_rate = 4000,
223d44fa156STony Lindgren 	.step_size = 12500,
224d44fa156STony Lindgren 	.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
225d44fa156STony Lindgren 	.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
226d44fa156STony Lindgren 	.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
227d44fa156STony Lindgren 	.vddmin = 850000,
228d44fa156STony Lindgren 	.vddmax = 1375000,
229d44fa156STony Lindgren 	.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
230d44fa156STony Lindgren 	.i2c_slave_addr = 0x48,
231d44fa156STony Lindgren 	.volt_reg_addr = 0x01,
232d44fa156STony Lindgren 	.cmd_reg_addr = 0x01,
233c145649bSTony Lindgren 	.i2c_high_speed = false,
234d44fa156STony Lindgren 	.vsel_to_uv = omap_fan535503_vsel_to_uv,
235d44fa156STony Lindgren 	.uv_to_vsel = omap_fan535503_uv_to_vsel,
236d44fa156STony Lindgren };
237d44fa156STony Lindgren 
omap4_cpcap_init(void)238d44fa156STony Lindgren int __init omap4_cpcap_init(void)
239d44fa156STony Lindgren {
240d44fa156STony Lindgren 	struct voltagedomain *voltdm;
241d44fa156STony Lindgren 
242d44fa156STony Lindgren 	if (!of_find_compatible_node(NULL, NULL, "motorola,cpcap"))
243d44fa156STony Lindgren 		return -ENODEV;
244d44fa156STony Lindgren 
245d44fa156STony Lindgren 	voltdm = voltdm_lookup("mpu");
246d44fa156STony Lindgren 	omap_voltage_register_pmic(voltdm, &omap443x_max8952_mpu);
247d44fa156STony Lindgren 
248d44fa156STony Lindgren 	if (of_machine_is_compatible("motorola,droid-bionic")) {
249*30916faaSTony Lindgren 		voltdm = voltdm_lookup("core");
250d44fa156STony Lindgren 		omap_voltage_register_pmic(voltdm, &omap_cpcap_core);
251d44fa156STony Lindgren 
252*30916faaSTony Lindgren 		voltdm = voltdm_lookup("iva");
253d44fa156STony Lindgren 		omap_voltage_register_pmic(voltdm, &omap_cpcap_iva);
254d44fa156STony Lindgren 	} else {
255d44fa156STony Lindgren 		voltdm = voltdm_lookup("core");
256d44fa156STony Lindgren 		omap_voltage_register_pmic(voltdm, &omap4_fan_core);
257d44fa156STony Lindgren 
258d44fa156STony Lindgren 		voltdm = voltdm_lookup("iva");
259d44fa156STony Lindgren 		omap_voltage_register_pmic(voltdm, &omap4_fan_iva);
260d44fa156STony Lindgren 	}
261d44fa156STony Lindgren 
262d44fa156STony Lindgren 	return 0;
263d44fa156STony Lindgren }
264c145649bSTony Lindgren 
cpcap_late_init(void)265c145649bSTony Lindgren static int __init cpcap_late_init(void)
266c145649bSTony Lindgren {
267c145649bSTony Lindgren 	omap4_vc_set_pmic_signaling(PWRDM_POWER_RET);
268c145649bSTony Lindgren 
269c145649bSTony Lindgren 	return 0;
270c145649bSTony Lindgren }
271c145649bSTony Lindgren omap_late_initcall(cpcap_late_init);
272