// SPDX-License-Identifier: GPL-2.0-only
/*
* pmic - cpcap . c - CPCAP - specific functions for the OPP code
*
* Adapted from Motorola Mapphone Android Linux kernel
* Copyright ( C ) 2011 Motorola , Inc .
*/
#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include "soc.h"
#include "pm.h"
#include "voltage.h"
#include <linux/init.h>
#include "vc.h"
/**
* omap_cpcap_vsel_to_uv - convert CPCAP VSEL value to microvolts DC
* @ vsel : CPCAP VSEL value to convert
*
* Returns : the microvolts DC that the CPCAP PMIC should generate when
* programmed with @ vsel .
*/
static unsigned long omap_cpcap_vsel_to_uv(unsigned char vsel)
{
if (vsel > 0 x44)
vsel = 0 x44;
return (((vsel * 125 ) + 6000 )) * 100 ;
}
/**
* omap_cpcap_uv_to_vsel - convert microvolts DC to CPCAP VSEL value
* @ uv : microvolts DC to convert
*
* Returns : the VSEL value necessary for the CPCAP PMIC to
* generate an output voltage equal to or greater than @ uv microvolts DC .
*/
static unsigned char omap_cpcap_uv_to_vsel(unsigned long uv)
{
if (uv < 600000 )
uv = 600000 ;
else if (uv > 1450000 )
uv = 1450000 ;
return DIV_ROUND_UP(uv - 600000 , 12500 );
}
static struct omap_voltdm_pmic omap_cpcap_core = {
.slew_rate = 4000 ,
.step_size = 12500 ,
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
.vddmin = 900000 ,
.vddmax = 1350000 ,
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = 0 x02,
.volt_reg_addr = 0 x00,
.cmd_reg_addr = 0 x01,
.i2c_high_speed = false ,
.vsel_to_uv = omap_cpcap_vsel_to_uv,
.uv_to_vsel = omap_cpcap_uv_to_vsel,
};
static struct omap_voltdm_pmic omap_cpcap_iva = {
.slew_rate = 4000 ,
.step_size = 12500 ,
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
.vddmin = 900000 ,
.vddmax = 1375000 ,
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = 0 x44,
.volt_reg_addr = 0 x0,
.cmd_reg_addr = 0 x01,
.i2c_high_speed = false ,
.vsel_to_uv = omap_cpcap_vsel_to_uv,
.uv_to_vsel = omap_cpcap_uv_to_vsel,
};
/**
* omap_max8952_vsel_to_uv - convert MAX8952 VSEL value to microvolts DC
* @ vsel : MAX8952 VSEL value to convert
*
* Returns : the microvolts DC that the MAX8952 Regulator should generate when
* programmed with @ vsel .
*/
static unsigned long omap_max8952_vsel_to_uv(unsigned char vsel)
{
if (vsel > 0 x3F)
vsel = 0 x3F;
return (((vsel * 100 ) + 7700 )) * 100 ;
}
/**
* omap_max8952_uv_to_vsel - convert microvolts DC to MAX8952 VSEL value
* @ uv : microvolts DC to convert
*
* Returns : the VSEL value necessary for the MAX8952 Regulator to
* generate an output voltage equal to or greater than @ uv microvolts DC .
*/
static unsigned char omap_max8952_uv_to_vsel(unsigned long uv)
{
if (uv < 770000 )
uv = 770000 ;
else if (uv > 1400000 )
uv = 1400000 ;
return DIV_ROUND_UP(uv - 770000 , 10000 );
}
static struct omap_voltdm_pmic omap443x_max8952_mpu = {
.slew_rate = 16000 ,
.step_size = 10000 ,
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
.vddmin = 900000 ,
.vddmax = 1400000 ,
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = 0 x60,
.volt_reg_addr = 0 x03,
.cmd_reg_addr = 0 x03,
.i2c_high_speed = false ,
.vsel_to_uv = omap_max8952_vsel_to_uv,
.uv_to_vsel = omap_max8952_uv_to_vsel,
};
/**
* omap_fan535503_vsel_to_uv - convert FAN535503 VSEL value to microvolts DC
* @ vsel : FAN535503 VSEL value to convert
*
* Returns : the microvolts DC that the FAN535503 Regulator should generate when
* programmed with @ vsel .
*/
static unsigned long omap_fan535503_vsel_to_uv(unsigned char vsel)
{
/* Extract bits[5:0] */
vsel &= 0 x3F;
return (((vsel * 125 ) + 7500 )) * 100 ;
}
/**
* omap_fan535508_vsel_to_uv - convert FAN535508 VSEL value to microvolts DC
* @ vsel : FAN535508 VSEL value to convert
*
* Returns : the microvolts DC that the FAN535508 Regulator should generate when
* programmed with @ vsel .
*/
static unsigned long omap_fan535508_vsel_to_uv(unsigned char vsel)
{
/* Extract bits[5:0] */
vsel &= 0 x3F;
if (vsel > 0 x37)
vsel = 0 x37;
return (((vsel * 125 ) + 7500 )) * 100 ;
}
/**
* omap_fan535503_uv_to_vsel - convert microvolts DC to FAN535503 VSEL value
* @ uv : microvolts DC to convert
*
* Returns : the VSEL value necessary for the MAX8952 Regulator to
* generate an output voltage equal to or greater than @ uv microvolts DC .
*/
static unsigned char omap_fan535503_uv_to_vsel(unsigned long uv)
{
unsigned char vsel;
if (uv < 750000 )
uv = 750000 ;
else if (uv > 1537500 )
uv = 1537500 ;
vsel = DIV_ROUND_UP(uv - 750000 , 12500 );
return vsel | 0 xC0;
}
/**
* omap_fan535508_uv_to_vsel - convert microvolts DC to FAN535508 VSEL value
* @ uv : microvolts DC to convert
*
* Returns : the VSEL value necessary for the MAX8952 Regulator to
* generate an output voltage equal to or greater than @ uv microvolts DC .
*/
static unsigned char omap_fan535508_uv_to_vsel(unsigned long uv)
{
unsigned char vsel;
if (uv < 750000 )
uv = 750000 ;
else if (uv > 1437500 )
uv = 1437500 ;
vsel = DIV_ROUND_UP(uv - 750000 , 12500 );
return vsel | 0 xC0;
}
/* fan5335-core */
static struct omap_voltdm_pmic omap4_fan_core = {
.slew_rate = 4000 ,
.step_size = 12500 ,
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
.vddmin = 850000 ,
.vddmax = 1375000 ,
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = 0 x4A,
.i2c_high_speed = false ,
.volt_reg_addr = 0 x01,
.cmd_reg_addr = 0 x01,
.vsel_to_uv = omap_fan535508_vsel_to_uv,
.uv_to_vsel = omap_fan535508_uv_to_vsel,
};
/* fan5335 iva */
static struct omap_voltdm_pmic omap4_fan_iva = {
.slew_rate = 4000 ,
.step_size = 12500 ,
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
.vddmin = 850000 ,
.vddmax = 1375000 ,
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = 0 x48,
.volt_reg_addr = 0 x01,
.cmd_reg_addr = 0 x01,
.i2c_high_speed = false ,
.vsel_to_uv = omap_fan535503_vsel_to_uv,
.uv_to_vsel = omap_fan535503_uv_to_vsel,
};
int __init omap4_cpcap_init(void )
{
struct voltagedomain *voltdm;
if (!of_find_compatible_node(NULL, NULL, "motorola,cpcap" ))
return -ENODEV;
voltdm = voltdm_lookup("mpu" );
omap_voltage_register_pmic(voltdm, &omap443x_max8952_mpu);
if (of_machine_is_compatible("motorola,droid-bionic" )) {
voltdm = voltdm_lookup("core" );
omap_voltage_register_pmic(voltdm, &omap_cpcap_core);
voltdm = voltdm_lookup("iva" );
omap_voltage_register_pmic(voltdm, &omap_cpcap_iva);
} else {
voltdm = voltdm_lookup("core" );
omap_voltage_register_pmic(voltdm, &omap4_fan_core);
voltdm = voltdm_lookup("iva" );
omap_voltage_register_pmic(voltdm, &omap4_fan_iva);
}
return 0 ;
}
static int __init cpcap_late_init(void )
{
if (!of_find_compatible_node(NULL, NULL, "motorola,cpcap" ))
return 0 ;
if (soc_is_omap443x() || soc_is_omap446x() || soc_is_omap447x())
omap4_vc_set_pmic_signaling(PWRDM_POWER_RET);
return 0 ;
}
omap_late_initcall(cpcap_late_init);
Messung V0.5 in Prozent C=96 H=100 G=97
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-09-29)
¤
*© Formatika GbR, Deutschland