Linux Audio

Check our new training course

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