OMAP voltage layer updates towards supporting auto-retention/auto-off

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJQmaAOAAoJEFk3GJrT+8ZlkuEP/0Kb0u/yz54BzH3WMSdtklMS
 Ylmo/gX9I5wUT4RpdBYQCU8L+1DKie8c7ZRJUKJoVBMyGtFkRfry9XBEyU8QamGH
 8hTa1itQdal3V6o9q9ilc5W9HckBxKCY/K23VljgoJO/0RzjASfJ3RO6bf8jQKgs
 RnuRIO+uOev1QDbFSurVcHIPGLsz3m/WserXAxRajY4DJcKOyfJOk11z0hlADWaD
 8SRRqeoV5oGzBXwd98I6QddngOxaE/Nr4jGvW9KwJG0fzDsV3hjd5RbFFVoU0ISo
 Dw0JhFsz7hQ36dXOV1z71BhcxYPNv2PFILlvpkn471DNlG524sc2Eh6to1sDVlDY
 cSR7hDylvf4Do2xyNUk/YgZwf6l5m/Bg/uJ5vrltcHO4uUhM5JFSeNfP9UBC3ups
 r6vJc73XuMCx58G5kuSprVHe4kIWJ8WT8zLjZ7YBk38EB9iYWF9zLVijyKY9fsoT
 qUlrwXsh49HML8k07mRWLF/w2LgomFA28prLzay/CnCv8LfSwA/SpWI42QKFy+Y2
 cme57OkXDsMbAHDt6X1j5QH2HJ4aMhalfHiPbync5UobJx3nYvs1DeqLuqcqVbbD
 5cwaTmFc4KcFqMhDeUujLmNofGOauvVm5R13A1cZrTF/U85SYxq4KuIX7FEC2n02
 W0v+kAvCbY3nX0+0SMdj
 =mE28
 -----END PGP SIGNATURE-----

Merge tag 'for_3.8-pm-voltage' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into omap-for-v3.8/pm

OMAP voltage layer updates towards supporting auto-retention/auto-off
This commit is contained in:
Tony Lindgren 2012-11-06 17:06:37 -08:00
commit 46bf4a5622
17 changed files with 732 additions and 122 deletions

View File

@ -201,6 +201,7 @@
#define OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO 0x249
#define OMAP44XX_CONTROL_FUSE_CORE_OPP50 0x254
#define OMAP44XX_CONTROL_FUSE_CORE_OPP100 0x257
#define OMAP44XX_CONTROL_FUSE_CORE_OPP100OV 0x25A
/* AM35XX only CONTROL_GENERAL register offsets */
#define AM35XX_CONTROL_MSUSPENDMUX_6 (OMAP2_CONTROL_GENERAL + 0x0038)

View File

@ -89,8 +89,11 @@ extern struct omap_volt_data omap34xx_vddcore_volt_data[];
extern struct omap_volt_data omap36xx_vddmpu_volt_data[];
extern struct omap_volt_data omap36xx_vddcore_volt_data[];
extern struct omap_volt_data omap44xx_vdd_mpu_volt_data[];
extern struct omap_volt_data omap44xx_vdd_iva_volt_data[];
extern struct omap_volt_data omap44xx_vdd_core_volt_data[];
extern struct omap_volt_data omap443x_vdd_mpu_volt_data[];
extern struct omap_volt_data omap443x_vdd_iva_volt_data[];
extern struct omap_volt_data omap443x_vdd_core_volt_data[];
extern struct omap_volt_data omap446x_vdd_mpu_volt_data[];
extern struct omap_volt_data omap446x_vdd_iva_volt_data[];
extern struct omap_volt_data omap446x_vdd_core_volt_data[];
#endif /* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */

View File

@ -30,16 +30,6 @@
#define OMAP3_VP_VSTEPMAX_VSTEPMAX 0x04
#define OMAP3_VP_VLIMITTO_TIMEOUT_US 200
#define OMAP3430_VP1_VLIMITTO_VDDMIN 0x14
#define OMAP3430_VP1_VLIMITTO_VDDMAX 0x42
#define OMAP3430_VP2_VLIMITTO_VDDMIN 0x18
#define OMAP3430_VP2_VLIMITTO_VDDMAX 0x2c
#define OMAP3630_VP1_VLIMITTO_VDDMIN 0x18
#define OMAP3630_VP1_VLIMITTO_VDDMAX 0x3c
#define OMAP3630_VP2_VLIMITTO_VDDMIN 0x18
#define OMAP3630_VP2_VLIMITTO_VDDMAX 0x30
#define OMAP4_SRI2C_SLAVE_ADDR 0x12
#define OMAP4_VDD_MPU_SR_VOLT_REG 0x55
#define OMAP4_VDD_MPU_SR_CMD_REG 0x56
@ -53,13 +43,6 @@
#define OMAP4_VP_VSTEPMAX_VSTEPMAX 0x04
#define OMAP4_VP_VLIMITTO_TIMEOUT_US 200
#define OMAP4_VP_MPU_VLIMITTO_VDDMIN 0xA
#define OMAP4_VP_MPU_VLIMITTO_VDDMAX 0x39
#define OMAP4_VP_IVA_VLIMITTO_VDDMIN 0xA
#define OMAP4_VP_IVA_VLIMITTO_VDDMAX 0x2D
#define OMAP4_VP_CORE_VLIMITTO_VDDMIN 0xA
#define OMAP4_VP_CORE_VLIMITTO_VDDMAX 0x28
static bool is_offset_valid;
static u8 smps_offset;
/*
@ -158,16 +141,11 @@ static u8 twl6030_uv_to_vsel(unsigned long uv)
static struct omap_voltdm_pmic omap3_mpu_pmic = {
.slew_rate = 4000,
.step_size = 12500,
.on_volt = 1200000,
.onlp_volt = 1000000,
.ret_volt = 975000,
.off_volt = 600000,
.volt_setup_time = 0xfff,
.vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX,
.vp_vddmin = OMAP3430_VP1_VLIMITTO_VDDMIN,
.vp_vddmax = OMAP3430_VP1_VLIMITTO_VDDMAX,
.vddmin = 600000,
.vddmax = 1450000,
.vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
.volt_reg_addr = OMAP3_VDD_MPU_SR_CONTROL_REG,
@ -179,16 +157,11 @@ static struct omap_voltdm_pmic omap3_mpu_pmic = {
static struct omap_voltdm_pmic omap3_core_pmic = {
.slew_rate = 4000,
.step_size = 12500,
.on_volt = 1200000,
.onlp_volt = 1000000,
.ret_volt = 975000,
.off_volt = 600000,
.volt_setup_time = 0xfff,
.vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX,
.vp_vddmin = OMAP3430_VP2_VLIMITTO_VDDMIN,
.vp_vddmax = OMAP3430_VP2_VLIMITTO_VDDMAX,
.vddmin = 600000,
.vddmax = 1450000,
.vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
.volt_reg_addr = OMAP3_VDD_CORE_SR_CONTROL_REG,
@ -200,21 +173,17 @@ static struct omap_voltdm_pmic omap3_core_pmic = {
static struct omap_voltdm_pmic omap4_mpu_pmic = {
.slew_rate = 4000,
.step_size = 12660,
.on_volt = 1375000,
.onlp_volt = 1375000,
.ret_volt = 830000,
.off_volt = 0,
.volt_setup_time = 0,
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
.vp_vddmin = OMAP4_VP_MPU_VLIMITTO_VDDMIN,
.vp_vddmax = OMAP4_VP_MPU_VLIMITTO_VDDMAX,
.vddmin = 0,
.vddmax = 2100000,
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
.volt_reg_addr = OMAP4_VDD_MPU_SR_VOLT_REG,
.cmd_reg_addr = OMAP4_VDD_MPU_SR_CMD_REG,
.i2c_high_speed = true,
.i2c_pad_load = 3,
.vsel_to_uv = twl6030_vsel_to_uv,
.uv_to_vsel = twl6030_uv_to_vsel,
};
@ -222,21 +191,17 @@ static struct omap_voltdm_pmic omap4_mpu_pmic = {
static struct omap_voltdm_pmic omap4_iva_pmic = {
.slew_rate = 4000,
.step_size = 12660,
.on_volt = 1188000,
.onlp_volt = 1188000,
.ret_volt = 830000,
.off_volt = 0,
.volt_setup_time = 0,
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
.vp_vddmin = OMAP4_VP_IVA_VLIMITTO_VDDMIN,
.vp_vddmax = OMAP4_VP_IVA_VLIMITTO_VDDMAX,
.vddmin = 0,
.vddmax = 2100000,
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
.volt_reg_addr = OMAP4_VDD_IVA_SR_VOLT_REG,
.cmd_reg_addr = OMAP4_VDD_IVA_SR_CMD_REG,
.i2c_high_speed = true,
.i2c_pad_load = 3,
.vsel_to_uv = twl6030_vsel_to_uv,
.uv_to_vsel = twl6030_uv_to_vsel,
};
@ -244,20 +209,17 @@ static struct omap_voltdm_pmic omap4_iva_pmic = {
static struct omap_voltdm_pmic omap4_core_pmic = {
.slew_rate = 4000,
.step_size = 12660,
.on_volt = 1200000,
.onlp_volt = 1200000,
.ret_volt = 830000,
.off_volt = 0,
.volt_setup_time = 0,
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
.vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
.vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
.vp_vddmin = OMAP4_VP_CORE_VLIMITTO_VDDMIN,
.vp_vddmax = OMAP4_VP_CORE_VLIMITTO_VDDMAX,
.vddmin = 0,
.vddmax = 2100000,
.vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
.i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
.volt_reg_addr = OMAP4_VDD_CORE_SR_VOLT_REG,
.cmd_reg_addr = OMAP4_VDD_CORE_SR_CMD_REG,
.i2c_high_speed = true,
.i2c_pad_load = 3,
.vsel_to_uv = twl6030_vsel_to_uv,
.uv_to_vsel = twl6030_uv_to_vsel,
};
@ -288,13 +250,6 @@ int __init omap3_twl_init(void)
if (!cpu_is_omap34xx())
return -ENODEV;
if (cpu_is_omap3630()) {
omap3_mpu_pmic.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN;
omap3_mpu_pmic.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX;
omap3_core_pmic.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN;
omap3_core_pmic.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
}
/*
* The smartreflex bit on twl4030 specifies if the setting of voltage
* is done over the I2C_SR path. Since this setting is independent of

View File

@ -1,7 +1,7 @@
/*
* OMAP4 OPP table definitions.
*
* Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
* Copyright (C) 2010-2012 Texas Instruments Incorporated - http://www.ti.com/
* Nishanth Menon
* Kevin Hilman
* Thara Gopinath
@ -35,7 +35,7 @@
#define OMAP4430_VDD_MPU_OPPTURBO_UV 1313000
#define OMAP4430_VDD_MPU_OPPNITRO_UV 1375000
struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
struct omap_volt_data omap443x_vdd_mpu_volt_data[] = {
VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
@ -47,7 +47,7 @@ struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
#define OMAP4430_VDD_IVA_OPP100_UV 1188000
#define OMAP4430_VDD_IVA_OPPTURBO_UV 1300000
struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
struct omap_volt_data omap443x_vdd_iva_volt_data[] = {
VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
@ -57,14 +57,14 @@ struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
#define OMAP4430_VDD_CORE_OPP50_UV 1025000
#define OMAP4430_VDD_CORE_OPP100_UV 1200000
struct omap_volt_data omap44xx_vdd_core_volt_data[] = {
struct omap_volt_data omap443x_vdd_core_volt_data[] = {
VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
VOLT_DATA_DEFINE(0, 0, 0, 0),
};
static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
static struct omap_opp_def __initdata omap443x_opp_def_list[] = {
/* MPU OPP1 - OPP50 */
OPP_INITIALIZER("mpu", true, 300000000, OMAP4430_VDD_MPU_OPP50_UV),
/* MPU OPP2 - OPP100 */
@ -86,6 +86,82 @@ static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
/* TODO: add DSP, aess, fdif, gpu */
};
#define OMAP4460_VDD_MPU_OPP50_UV 1025000
#define OMAP4460_VDD_MPU_OPP100_UV 1200000
#define OMAP4460_VDD_MPU_OPPTURBO_UV 1313000
#define OMAP4460_VDD_MPU_OPPNITRO_UV 1375000
struct omap_volt_data omap446x_vdd_mpu_volt_data[] = {
VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
VOLT_DATA_DEFINE(0, 0, 0, 0),
};
#define OMAP4460_VDD_IVA_OPP50_UV 1025000
#define OMAP4460_VDD_IVA_OPP100_UV 1200000
#define OMAP4460_VDD_IVA_OPPTURBO_UV 1313000
#define OMAP4460_VDD_IVA_OPPNITRO_UV 1375000
struct omap_volt_data omap446x_vdd_iva_volt_data[] = {
VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPNITRO, 0xfa, 0x23),
VOLT_DATA_DEFINE(0, 0, 0, 0),
};
#define OMAP4460_VDD_CORE_OPP50_UV 1025000
#define OMAP4460_VDD_CORE_OPP100_UV 1200000
#define OMAP4460_VDD_CORE_OPP100_OV_UV 1250000
struct omap_volt_data omap446x_vdd_core_volt_data[] = {
VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_OV_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100OV, 0xf9, 0x16),
VOLT_DATA_DEFINE(0, 0, 0, 0),
};
static struct omap_opp_def __initdata omap446x_opp_def_list[] = {
/* MPU OPP1 - OPP50 */
OPP_INITIALIZER("mpu", true, 350000000, OMAP4460_VDD_MPU_OPP50_UV),
/* MPU OPP2 - OPP100 */
OPP_INITIALIZER("mpu", true, 700000000, OMAP4460_VDD_MPU_OPP100_UV),
/* MPU OPP3 - OPP-Turbo */
OPP_INITIALIZER("mpu", true, 920000000, OMAP4460_VDD_MPU_OPPTURBO_UV),
/*
* MPU OPP4 - OPP-Nitro + Disabled as the reference schematics
* recommends TPS623631 - confirm and enable the opp in board file
* XXX: May be we should enable these based on mpu capability and
* Exception board files disable it...
*/
OPP_INITIALIZER("mpu", false, 1200000000, OMAP4460_VDD_MPU_OPPNITRO_UV),
/* MPU OPP4 - OPP-Nitro SpeedBin */
OPP_INITIALIZER("mpu", false, 1500000000, OMAP4460_VDD_MPU_OPPNITRO_UV),
/* L3 OPP1 - OPP50 */
OPP_INITIALIZER("l3_main_1", true, 100000000, OMAP4460_VDD_CORE_OPP50_UV),
/* L3 OPP2 - OPP100 */
OPP_INITIALIZER("l3_main_1", true, 200000000, OMAP4460_VDD_CORE_OPP100_UV),
/* IVA OPP1 - OPP50 */
OPP_INITIALIZER("iva", true, 133000000, OMAP4460_VDD_IVA_OPP50_UV),
/* IVA OPP2 - OPP100 */
OPP_INITIALIZER("iva", true, 266100000, OMAP4460_VDD_IVA_OPP100_UV),
/*
* IVA OPP3 - OPP-Turbo + Disabled as the reference schematics
* recommends Phoenix VCORE2 which can supply only 600mA - so the ones
* above this OPP frequency, even though OMAP is capable, should be
* enabled by board file which is sure of the chip power capability
*/
OPP_INITIALIZER("iva", false, 332000000, OMAP4460_VDD_IVA_OPPTURBO_UV),
/* IVA OPP4 - OPP-Nitro */
OPP_INITIALIZER("iva", false, 430000000, OMAP4460_VDD_IVA_OPPNITRO_UV),
/* IVA OPP5 - OPP-Nitro SpeedBin*/
OPP_INITIALIZER("iva", false, 500000000, OMAP4460_VDD_IVA_OPPNITRO_UV),
/* TODO: add DSP, aess, fdif, gpu */
};
/**
* omap4_opp_init() - initialize omap4 opp table
*/
@ -93,12 +169,12 @@ int __init omap4_opp_init(void)
{
int r = -ENODEV;
if (!cpu_is_omap443x())
return r;
r = omap_init_opp_table(omap44xx_opp_def_list,
ARRAY_SIZE(omap44xx_opp_def_list));
if (cpu_is_omap443x())
r = omap_init_opp_table(omap443x_opp_def_list,
ARRAY_SIZE(omap443x_opp_def_list));
else if (cpu_is_omap446x())
r = omap_init_opp_table(omap446x_opp_def_list,
ARRAY_SIZE(omap446x_opp_def_list));
return r;
}
device_initcall(omap4_opp_init);

View File

@ -39,6 +39,36 @@ static struct omap_device_pm_latency *pm_lats;
*/
int (*omap_pm_suspend)(void);
/**
* struct omap2_oscillator - Describe the board main oscillator latencies
* @startup_time: oscillator startup latency
* @shutdown_time: oscillator shutdown latency
*/
struct omap2_oscillator {
u32 startup_time;
u32 shutdown_time;
};
static struct omap2_oscillator oscillator = {
.startup_time = ULONG_MAX,
.shutdown_time = ULONG_MAX,
};
void omap_pm_setup_oscillator(u32 tstart, u32 tshut)
{
oscillator.startup_time = tstart;
oscillator.shutdown_time = tshut;
}
void omap_pm_get_oscillator(u32 *tstart, u32 *tshut)
{
if (!tstart || !tshut)
return;
*tstart = oscillator.startup_time;
*tshut = oscillator.shutdown_time;
}
static int __init _init_omap_device(char *name)
{
struct omap_hwmod *oh;

View File

@ -129,4 +129,14 @@ static inline int omap4_twl_init(void)
}
#endif
#ifdef CONFIG_PM
extern void omap_pm_setup_oscillator(u32 tstart, u32 tshut);
extern void omap_pm_get_oscillator(u32 *tstart, u32 *tshut);
extern void omap_pm_setup_sr_i2c_pcb_length(u32 mm);
#else
static inline void omap_pm_setup_oscillator(u32 tstart, u32 tshut) { }
static inline void omap_pm_get_oscillator(u32 *tstart, u32 *tshut) { }
static inline void omap_pm_setup_sr_i2c_pcb_length(u32 mm) { }
#endif
#endif

View File

@ -11,13 +11,20 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/bug.h>
#include <linux/io.h>
#include <asm/div64.h>
#include "iomap.h"
#include "soc.h"
#include "voltage.h"
#include "vc.h"
#include "prm-regbits-34xx.h"
#include "prm-regbits-44xx.h"
#include "prm44xx.h"
#include "pm.h"
#include "scrm44xx.h"
#include "control.h"
/**
* struct omap_vc_channel_cfg - describe the cfg_channel bitfield
@ -63,6 +70,9 @@ static struct omap_vc_channel_cfg vc_mutant_channel_cfg = {
};
static struct omap_vc_channel_cfg *vc_cfg_bits;
/* Default I2C trace length on pcb, 6.3cm. Used for capacitance calculations. */
static u32 sr_i2c_pcb_length = 63;
#define CFG_CHANNEL_MASK 0x1f
/**
@ -135,6 +145,8 @@ int omap_vc_pre_scale(struct voltagedomain *voltdm,
vc_cmdval |= (*target_vsel << vc->common->cmd_on_shift);
voltdm->write(vc_cmdval, vc->cmdval_reg);
voltdm->vc_param->on = target_volt;
omap_vp_update_errorgain(voltdm, target_volt);
return 0;
@ -202,46 +214,389 @@ int omap_vc_bypass_scale(struct voltagedomain *voltdm,
return 0;
}
static void __init omap3_vfsm_init(struct voltagedomain *voltdm)
/* Convert microsecond value to number of 32kHz clock cycles */
static inline u32 omap_usec_to_32k(u32 usec)
{
return DIV_ROUND_UP_ULL(32768ULL * (u64)usec, 1000000ULL);
}
/* Set oscillator setup time for omap3 */
static void omap3_set_clksetup(u32 usec, struct voltagedomain *voltdm)
{
voltdm->write(omap_usec_to_32k(usec), OMAP3_PRM_CLKSETUP_OFFSET);
}
/**
* omap3_set_i2c_timings - sets i2c sleep timings for a channel
* @voltdm: channel to configure
* @off_mode: select whether retention or off mode values used
*
* Calculates and sets up voltage controller to use I2C based
* voltage scaling for sleep modes. This can be used for either off mode
* or retention. Off mode has additionally an option to use sys_off_mode
* pad, which uses a global signal to program the whole power IC to
* off-mode.
*/
static void omap3_set_i2c_timings(struct voltagedomain *voltdm, bool off_mode)
{
unsigned long voltsetup1;
u32 tgt_volt;
/*
* Voltage Manager FSM parameters init
* XXX This data should be passed in from the board file
* Oscillator is shut down only if we are using sys_off_mode pad,
* thus we set a minimal setup time here
*/
voltdm->write(OMAP3_CLKSETUP, OMAP3_PRM_CLKSETUP_OFFSET);
voltdm->write(OMAP3_VOLTOFFSET, OMAP3_PRM_VOLTOFFSET_OFFSET);
voltdm->write(OMAP3_VOLTSETUP2, OMAP3_PRM_VOLTSETUP2_OFFSET);
omap3_set_clksetup(1, voltdm);
if (off_mode)
tgt_volt = voltdm->vc_param->off;
else
tgt_volt = voltdm->vc_param->ret;
voltsetup1 = (voltdm->vc_param->on - tgt_volt) /
voltdm->pmic->slew_rate;
voltsetup1 = voltsetup1 * voltdm->sys_clk.rate / 8 / 1000000 + 1;
voltdm->rmw(voltdm->vfsm->voltsetup_mask,
voltsetup1 << __ffs(voltdm->vfsm->voltsetup_mask),
voltdm->vfsm->voltsetup_reg);
/*
* pmic is not controlling the voltage scaling during retention,
* thus set voltsetup2 to 0
*/
voltdm->write(0, OMAP3_PRM_VOLTSETUP2_OFFSET);
}
/**
* omap3_set_off_timings - sets off-mode timings for a channel
* @voltdm: channel to configure
*
* Calculates and sets up off-mode timings for a channel. Off-mode
* can use either I2C based voltage scaling, or alternatively
* sys_off_mode pad can be used to send a global command to power IC.
* This function first checks which mode is being used, and calls
* omap3_set_i2c_timings() if the system is using I2C control mode.
* sys_off_mode has the additional benefit that voltages can be
* scaled to zero volt level with TWL4030 / TWL5030, I2C can only
* scale to 600mV.
*/
static void omap3_set_off_timings(struct voltagedomain *voltdm)
{
unsigned long clksetup;
unsigned long voltsetup2;
unsigned long voltsetup2_old;
u32 val;
u32 tstart, tshut;
/* check if sys_off_mode is used to control off-mode voltages */
val = voltdm->read(OMAP3_PRM_VOLTCTRL_OFFSET);
if (!(val & OMAP3430_SEL_OFF_MASK)) {
/* No, omap is controlling them over I2C */
omap3_set_i2c_timings(voltdm, true);
return;
}
omap_pm_get_oscillator(&tstart, &tshut);
omap3_set_clksetup(tstart, voltdm);
clksetup = voltdm->read(OMAP3_PRM_CLKSETUP_OFFSET);
/* voltsetup 2 in us */
voltsetup2 = voltdm->vc_param->on / voltdm->pmic->slew_rate;
/* convert to 32k clk cycles */
voltsetup2 = DIV_ROUND_UP(voltsetup2 * 32768, 1000000);
voltsetup2_old = voltdm->read(OMAP3_PRM_VOLTSETUP2_OFFSET);
/*
* Update voltsetup2 if higher than current value (needed because
* we have multiple channels with different ramp times), also
* update voltoffset always to value recommended by TRM
*/
if (voltsetup2 > voltsetup2_old) {
voltdm->write(voltsetup2, OMAP3_PRM_VOLTSETUP2_OFFSET);
voltdm->write(clksetup - voltsetup2,
OMAP3_PRM_VOLTOFFSET_OFFSET);
} else
voltdm->write(clksetup - voltsetup2_old,
OMAP3_PRM_VOLTOFFSET_OFFSET);
/*
* omap is not controlling voltage scaling during off-mode,
* thus set voltsetup1 to 0
*/
voltdm->rmw(voltdm->vfsm->voltsetup_mask, 0,
voltdm->vfsm->voltsetup_reg);
/* voltoffset must be clksetup minus voltsetup2 according to TRM */
voltdm->write(clksetup - voltsetup2, OMAP3_PRM_VOLTOFFSET_OFFSET);
}
static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
{
static bool is_initialized;
if (is_initialized)
return;
omap3_vfsm_init(voltdm);
is_initialized = true;
omap3_set_off_timings(voltdm);
}
/**
* omap4_calc_volt_ramp - calculates voltage ramping delays on omap4
* @voltdm: channel to calculate values for
* @voltage_diff: voltage difference in microvolts
*
* Calculates voltage ramp prescaler + counter values for a voltage
* difference on omap4. Returns a field value suitable for writing to
* VOLTSETUP register for a channel in following format:
* bits[8:9] prescaler ... bits[0:5] counter. See OMAP4 TRM for reference.
*/
static u32 omap4_calc_volt_ramp(struct voltagedomain *voltdm, u32 voltage_diff)
{
u32 prescaler;
u32 cycles;
u32 time;
time = voltage_diff / voltdm->pmic->slew_rate;
cycles = voltdm->sys_clk.rate / 1000 * time / 1000;
cycles /= 64;
prescaler = 0;
/* shift to next prescaler until no overflow */
/* scale for div 256 = 64 * 4 */
if (cycles > 63) {
cycles /= 4;
prescaler++;
}
/* scale for div 512 = 256 * 2 */
if (cycles > 63) {
cycles /= 2;
prescaler++;
}
/* scale for div 2048 = 512 * 4 */
if (cycles > 63) {
cycles /= 4;
prescaler++;
}
/* check for overflow => invalid ramp time */
if (cycles > 63) {
pr_warn("%s: invalid setuptime for vdd_%s\n", __func__,
voltdm->name);
return 0;
}
cycles++;
return (prescaler << OMAP4430_RAMP_UP_PRESCAL_SHIFT) |
(cycles << OMAP4430_RAMP_UP_COUNT_SHIFT);
}
/**
* omap4_usec_to_val_scrm - convert microsecond value to SCRM module bitfield
* @usec: microseconds
* @shift: number of bits to shift left
* @mask: bitfield mask
*
* Converts microsecond value to OMAP4 SCRM bitfield. Bitfield is
* shifted to requested position, and checked agains the mask value.
* If larger, forced to the max value of the field (i.e. the mask itself.)
* Returns the SCRM bitfield value.
*/
static u32 omap4_usec_to_val_scrm(u32 usec, int shift, u32 mask)
{
u32 val;
val = omap_usec_to_32k(usec) << shift;
/* Check for overflow, if yes, force to max value */
if (val > mask)
val = mask;
return val;
}
/**
* omap4_set_timings - set voltage ramp timings for a channel
* @voltdm: channel to configure
* @off_mode: whether off-mode values are used
*
* Calculates and sets the voltage ramp up / down values for a channel.
*/
static void omap4_set_timings(struct voltagedomain *voltdm, bool off_mode)
{
u32 val;
u32 ramp;
int offset;
u32 tstart, tshut;
if (off_mode) {
ramp = omap4_calc_volt_ramp(voltdm,
voltdm->vc_param->on - voltdm->vc_param->off);
offset = voltdm->vfsm->voltsetup_off_reg;
} else {
ramp = omap4_calc_volt_ramp(voltdm,
voltdm->vc_param->on - voltdm->vc_param->ret);
offset = voltdm->vfsm->voltsetup_reg;
}
if (!ramp)
return;
val = voltdm->read(offset);
val |= ramp << OMAP4430_RAMP_DOWN_COUNT_SHIFT;
val |= ramp << OMAP4430_RAMP_UP_COUNT_SHIFT;
voltdm->write(val, offset);
omap_pm_get_oscillator(&tstart, &tshut);
val = omap4_usec_to_val_scrm(tstart, OMAP4_SETUPTIME_SHIFT,
OMAP4_SETUPTIME_MASK);
val |= omap4_usec_to_val_scrm(tshut, OMAP4_DOWNTIME_SHIFT,
OMAP4_DOWNTIME_MASK);
__raw_writel(val, OMAP4_SCRM_CLKSETUPTIME);
}
/* OMAP4 specific voltage init functions */
static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
{
static bool is_initialized;
u32 vc_val;
if (is_initialized)
return;
/* XXX These are magic numbers and do not belong! */
vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
voltdm->write(vc_val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
is_initialized = true;
omap4_set_timings(voltdm, true);
omap4_set_timings(voltdm, false);
}
struct i2c_init_data {
u8 loadbits;
u8 load;
u8 hsscll_38_4;
u8 hsscll_26;
u8 hsscll_19_2;
u8 hsscll_16_8;
u8 hsscll_12;
};
static const __initdata struct i2c_init_data omap4_i2c_timing_data[] = {
{
.load = 50,
.loadbits = 0x3,
.hsscll_38_4 = 13,
.hsscll_26 = 11,
.hsscll_19_2 = 9,
.hsscll_16_8 = 9,
.hsscll_12 = 8,
},
{
.load = 25,
.loadbits = 0x2,
.hsscll_38_4 = 13,
.hsscll_26 = 11,
.hsscll_19_2 = 9,
.hsscll_16_8 = 9,
.hsscll_12 = 8,
},
{
.load = 12,
.loadbits = 0x1,
.hsscll_38_4 = 11,
.hsscll_26 = 10,
.hsscll_19_2 = 9,
.hsscll_16_8 = 9,
.hsscll_12 = 8,
},
{
.load = 0,
.loadbits = 0x0,
.hsscll_38_4 = 12,
.hsscll_26 = 10,
.hsscll_19_2 = 9,
.hsscll_16_8 = 8,
.hsscll_12 = 8,
},
};
/**
* omap4_vc_i2c_timing_init - sets up board I2C timing parameters
* @voltdm: voltagedomain pointer to get data from
*
* Use PMIC + board supplied settings for calculating the total I2C
* channel capacitance and set the timing parameters based on this.
* Pre-calculated values are provided in data tables, as it is not
* too straightforward to calculate these runtime.
*/
static void __init omap4_vc_i2c_timing_init(struct voltagedomain *voltdm)
{
u32 capacitance;
u32 val;
u16 hsscll;
const struct i2c_init_data *i2c_data;
if (!voltdm->pmic->i2c_high_speed) {
pr_warn("%s: only high speed supported!\n", __func__);
return;
}
/* PCB trace capacitance, 0.125pF / mm => mm / 8 */
capacitance = DIV_ROUND_UP(sr_i2c_pcb_length, 8);
/* OMAP pad capacitance */
capacitance += 4;
/* PMIC pad capacitance */
capacitance += voltdm->pmic->i2c_pad_load;
/* Search for capacitance match in the table */
i2c_data = omap4_i2c_timing_data;
while (i2c_data->load > capacitance)
i2c_data++;
/* Select proper values based on sysclk frequency */
switch (voltdm->sys_clk.rate) {
case 38400000:
hsscll = i2c_data->hsscll_38_4;
break;
case 26000000:
hsscll = i2c_data->hsscll_26;
break;
case 19200000:
hsscll = i2c_data->hsscll_19_2;
break;
case 16800000:
hsscll = i2c_data->hsscll_16_8;
break;
case 12000000:
hsscll = i2c_data->hsscll_12;
break;
default:
pr_warn("%s: unsupported sysclk rate: %d!\n", __func__,
voltdm->sys_clk.rate);
return;
}
/* Loadbits define pull setup for the I2C channels */
val = i2c_data->loadbits << 25 | i2c_data->loadbits << 29;
/* Write to SYSCTRL_PADCONF_WKUP_CTRL_I2C_2 to setup I2C pull */
__raw_writel(val, OMAP2_L4_IO_ADDRESS(OMAP4_CTRL_MODULE_PAD_WKUP +
OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_I2C_2));
/* HSSCLH can always be zero */
val = hsscll << OMAP4430_HSSCLL_SHIFT;
val |= (0x28 << OMAP4430_SCLL_SHIFT | 0x2c << OMAP4430_SCLH_SHIFT);
/* Write setup times to I2C config register */
voltdm->write(val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
}
/**
* omap_vc_i2c_init - initialize I2C interface to PMIC
* @voltdm: voltage domain containing VC data
@ -281,9 +636,49 @@ static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
mcode << __ffs(vc->common->i2c_mcode_mask),
vc->common->i2c_cfg_reg);
if (cpu_is_omap44xx())
omap4_vc_i2c_timing_init(voltdm);
initialized = true;
}
/**
* omap_vc_calc_vsel - calculate vsel value for a channel
* @voltdm: channel to calculate value for
* @uvolt: microvolt value to convert to vsel
*
* Converts a microvolt value to vsel value for the used PMIC.
* This checks whether the microvolt value is out of bounds, and
* adjusts the value accordingly. If unsupported value detected,
* warning is thrown.
*/
static u8 omap_vc_calc_vsel(struct voltagedomain *voltdm, u32 uvolt)
{
if (voltdm->pmic->vddmin > uvolt)
uvolt = voltdm->pmic->vddmin;
if (voltdm->pmic->vddmax < uvolt) {
WARN(1, "%s: voltage not supported by pmic: %u vs max %u\n",
__func__, uvolt, voltdm->pmic->vddmax);
/* Lets try maximum value anyway */
uvolt = voltdm->pmic->vddmax;
}
return voltdm->pmic->uv_to_vsel(uvolt);
}
/**
* omap_pm_setup_sr_i2c_pcb_length - set length of SR I2C traces on PCB
* @mm: length of the PCB trace in millimetres
*
* Sets the PCB trace length for the I2C channel. By default uses 63mm.
* This is needed for properly calculating the capacitance value for
* the PCB trace, and for setting the SR I2C channel timing parameters.
*/
void __init omap_pm_setup_sr_i2c_pcb_length(u32 mm)
{
sr_i2c_pcb_length = mm;
}
void __init omap_vc_init_channel(struct voltagedomain *voltdm)
{
struct omap_vc_channel *vc = voltdm->vc;
@ -311,7 +706,6 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr;
vc->volt_reg_addr = voltdm->pmic->volt_reg_addr;
vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr;
vc->setup_time = voltdm->pmic->volt_setup_time;
/* Configure the i2c slave address for this VC */
voltdm->rmw(vc->smps_sa_mask,
@ -331,14 +725,18 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
voltdm->rmw(vc->smps_cmdra_mask,
vc->cmd_reg_addr << __ffs(vc->smps_cmdra_mask),
vc->smps_cmdra_reg);
vc->cfg_channel |= vc_cfg_bits->rac | vc_cfg_bits->racen;
vc->cfg_channel |= vc_cfg_bits->rac;
}
if (vc->cmd_reg_addr == vc->volt_reg_addr)
vc->cfg_channel |= vc_cfg_bits->racen;
/* Set up the on, inactive, retention and off voltage */
on_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->on_volt);
onlp_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->onlp_volt);
ret_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->ret_volt);
off_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->off_volt);
on_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->on);
onlp_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->onlp);
ret_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->ret);
off_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->off);
val = ((on_vsel << vc->common->cmd_on_shift) |
(onlp_vsel << vc->common->cmd_onlp_shift) |
(ret_vsel << vc->common->cmd_ret_shift) |
@ -349,11 +747,6 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
/* Channel configuration */
omap_vc_config_channel(voltdm);
/* Configure the setup times */
voltdm->rmw(voltdm->vfsm->voltsetup_mask,
vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask),
voltdm->vfsm->voltsetup_reg);
omap_vc_i2c_init(voltdm);
if (cpu_is_omap34xx())

View File

@ -86,7 +86,6 @@ struct omap_vc_channel {
u16 i2c_slave_addr;
u16 volt_reg_addr;
u16 cmd_reg_addr;
u16 setup_time;
u8 cfg_channel;
bool i2c_high_speed;
@ -111,6 +110,13 @@ extern struct omap_vc_channel omap4_vc_mpu;
extern struct omap_vc_channel omap4_vc_iva;
extern struct omap_vc_channel omap4_vc_core;
extern struct omap_vc_param omap3_mpu_vc_data;
extern struct omap_vc_param omap3_core_vc_data;
extern struct omap_vc_param omap4_mpu_vc_data;
extern struct omap_vc_param omap4_iva_vc_data;
extern struct omap_vc_param omap4_core_vc_data;
void omap_vc_init_channel(struct voltagedomain *voltdm);
int omap_vc_pre_scale(struct voltagedomain *voltdm,
unsigned long target_volt,

View File

@ -71,3 +71,25 @@ struct omap_vc_channel omap3_vc_core = {
.smps_cmdra_mask = OMAP3430_CMDRA1_MASK,
.cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
};
/*
* Voltage levels for different operating modes: on, sleep, retention and off
*/
#define OMAP3_ON_VOLTAGE_UV 1200000
#define OMAP3_ONLP_VOLTAGE_UV 1000000
#define OMAP3_RET_VOLTAGE_UV 975000
#define OMAP3_OFF_VOLTAGE_UV 600000
struct omap_vc_param omap3_mpu_vc_data = {
.on = OMAP3_ON_VOLTAGE_UV,
.onlp = OMAP3_ONLP_VOLTAGE_UV,
.ret = OMAP3_RET_VOLTAGE_UV,
.off = OMAP3_OFF_VOLTAGE_UV,
};
struct omap_vc_param omap3_core_vc_data = {
.on = OMAP3_ON_VOLTAGE_UV,
.onlp = OMAP3_ONLP_VOLTAGE_UV,
.ret = OMAP3_RET_VOLTAGE_UV,
.off = OMAP3_OFF_VOLTAGE_UV,
};

View File

@ -87,3 +87,31 @@ struct omap_vc_channel omap4_vc_core = {
.cfg_channel_sa_shift = OMAP4430_SA_VDD_CORE_L_SHIFT,
};
/*
* Voltage levels for different operating modes: on, sleep, retention and off
*/
#define OMAP4_ON_VOLTAGE_UV 1375000
#define OMAP4_ONLP_VOLTAGE_UV 1375000
#define OMAP4_RET_VOLTAGE_UV 837500
#define OMAP4_OFF_VOLTAGE_UV 0
struct omap_vc_param omap4_mpu_vc_data = {
.on = OMAP4_ON_VOLTAGE_UV,
.onlp = OMAP4_ONLP_VOLTAGE_UV,
.ret = OMAP4_RET_VOLTAGE_UV,
.off = OMAP4_OFF_VOLTAGE_UV,
};
struct omap_vc_param omap4_iva_vc_data = {
.on = OMAP4_ON_VOLTAGE_UV,
.onlp = OMAP4_ONLP_VOLTAGE_UV,
.ret = OMAP4_RET_VOLTAGE_UV,
.off = OMAP4_OFF_VOLTAGE_UV,
};
struct omap_vc_param omap4_core_vc_data = {
.on = OMAP4_ON_VOLTAGE_UV,
.onlp = OMAP4_ONLP_VOLTAGE_UV,
.ret = OMAP4_RET_VOLTAGE_UV,
.off = OMAP4_OFF_VOLTAGE_UV,
};

View File

@ -40,12 +40,14 @@ struct powerdomain;
* data
* @voltsetup_mask: SETUP_TIME* bitmask in the PRM_VOLTSETUP* register
* @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base
* @voltsetup_off_reg: register offset of PRM_VOLTSETUP_OFF from PRM base
*
* XXX What about VOLTOFFSET/VOLTCTRL?
*/
struct omap_vfsm_instance {
u32 voltsetup_mask;
u8 voltsetup_reg;
u8 voltsetup_off_reg;
};
/**
@ -74,6 +76,8 @@ struct voltagedomain {
const struct omap_vfsm_instance *vfsm;
struct omap_vp_instance *vp;
struct omap_voltdm_pmic *pmic;
struct omap_vp_param *vp_param;
struct omap_vc_param *vc_param;
/* VC/VP register access functions: SoC specific */
u32 (*read) (u8 offset);
@ -92,6 +96,24 @@ struct voltagedomain {
struct omap_volt_data *volt_data;
};
/* Min and max voltages from OMAP perspective */
#define OMAP3430_VP1_VLIMITTO_VDDMIN 850000
#define OMAP3430_VP1_VLIMITTO_VDDMAX 1425000
#define OMAP3430_VP2_VLIMITTO_VDDMIN 900000
#define OMAP3430_VP2_VLIMITTO_VDDMAX 1150000
#define OMAP3630_VP1_VLIMITTO_VDDMIN 900000
#define OMAP3630_VP1_VLIMITTO_VDDMAX 1350000
#define OMAP3630_VP2_VLIMITTO_VDDMIN 900000
#define OMAP3630_VP2_VLIMITTO_VDDMAX 1200000
#define OMAP4_VP_MPU_VLIMITTO_VDDMIN 830000
#define OMAP4_VP_MPU_VLIMITTO_VDDMAX 1410000
#define OMAP4_VP_IVA_VLIMITTO_VDDMIN 830000
#define OMAP4_VP_IVA_VLIMITTO_VDDMAX 1260000
#define OMAP4_VP_CORE_VLIMITTO_VDDMIN 830000
#define OMAP4_VP_CORE_VLIMITTO_VDDMAX 1200000
/**
* struct omap_voltdm_pmic - PMIC specific data required by voltage driver.
* @slew_rate: PMIC slew rate (in uv/us)
@ -107,26 +129,34 @@ struct voltagedomain {
struct omap_voltdm_pmic {
int slew_rate;
int step_size;
u32 on_volt;
u32 onlp_volt;
u32 ret_volt;
u32 off_volt;
u16 volt_setup_time;
u16 i2c_slave_addr;
u16 volt_reg_addr;
u16 cmd_reg_addr;
u8 vp_erroroffset;
u8 vp_vstepmin;
u8 vp_vstepmax;
u8 vp_vddmin;
u8 vp_vddmax;
u32 vddmin;
u32 vddmax;
u8 vp_timeout_us;
bool i2c_high_speed;
u32 i2c_pad_load;
u8 i2c_mcode;
unsigned long (*vsel_to_uv) (const u8 vsel);
u8 (*uv_to_vsel) (unsigned long uV);
};
struct omap_vp_param {
u32 vddmax;
u32 vddmin;
};
struct omap_vc_param {
u32 on;
u32 onlp;
u32 ret;
u32 off;
};
void omap_voltage_get_volttable(struct voltagedomain *voltdm,
struct omap_volt_data **volt_data);
struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,

View File

@ -117,6 +117,11 @@ void __init omap3xxx_voltagedomains_init(void)
}
#endif
omap3_voltdm_mpu.vp_param = &omap3_mpu_vp_data;
omap3_voltdm_core.vp_param = &omap3_core_vp_data;
omap3_voltdm_mpu.vc_param = &omap3_mpu_vc_data;
omap3_voltdm_core.vc_param = &omap3_core_vc_data;
if (soc_is_am35xx())
voltdms = voltagedomains_am35xx;
else

View File

@ -34,14 +34,17 @@
static const struct omap_vfsm_instance omap4_vdd_mpu_vfsm = {
.voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET,
.voltsetup_off_reg = OMAP4_PRM_VOLTSETUP_MPU_OFF_OFFSET,
};
static const struct omap_vfsm_instance omap4_vdd_iva_vfsm = {
.voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
.voltsetup_off_reg = OMAP4_PRM_VOLTSETUP_IVA_OFF_OFFSET,
};
static const struct omap_vfsm_instance omap4_vdd_core_vfsm = {
.voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET,
.voltsetup_off_reg = OMAP4_PRM_VOLTSETUP_CORE_OFF_OFFSET,
};
static struct voltagedomain omap4_voltdm_mpu = {
@ -101,11 +104,25 @@ void __init omap44xx_voltagedomains_init(void)
* for the currently-running IC
*/
#ifdef CONFIG_PM_OPP
omap4_voltdm_mpu.volt_data = omap44xx_vdd_mpu_volt_data;
omap4_voltdm_iva.volt_data = omap44xx_vdd_iva_volt_data;
omap4_voltdm_core.volt_data = omap44xx_vdd_core_volt_data;
if (cpu_is_omap443x()) {
omap4_voltdm_mpu.volt_data = omap443x_vdd_mpu_volt_data;
omap4_voltdm_iva.volt_data = omap443x_vdd_iva_volt_data;
omap4_voltdm_core.volt_data = omap443x_vdd_core_volt_data;
} else if (cpu_is_omap446x()) {
omap4_voltdm_mpu.volt_data = omap446x_vdd_mpu_volt_data;
omap4_voltdm_iva.volt_data = omap446x_vdd_iva_volt_data;
omap4_voltdm_core.volt_data = omap446x_vdd_core_volt_data;
}
#endif
omap4_voltdm_mpu.vp_param = &omap4_mpu_vp_data;
omap4_voltdm_iva.vp_param = &omap4_iva_vp_data;
omap4_voltdm_core.vp_param = &omap4_core_vp_data;
omap4_voltdm_mpu.vc_param = &omap4_mpu_vc_data;
omap4_voltdm_iva.vc_param = &omap4_iva_vc_data;
omap4_voltdm_core.vc_param = &omap4_core_vc_data;
for (i = 0; voltdm = voltagedomains_omap4[i], voltdm; i++)
voltdm->sys_clk.name = sys_clk_name;

View File

@ -58,8 +58,10 @@ void __init omap_vp_init(struct voltagedomain *voltdm)
sys_clk_rate = voltdm->sys_clk.rate / 1000;
timeout = (sys_clk_rate * voltdm->pmic->vp_timeout_us) / 1000;
vddmin = voltdm->pmic->vp_vddmin;
vddmax = voltdm->pmic->vp_vddmax;
vddmin = max(voltdm->vp_param->vddmin, voltdm->pmic->vddmin);
vddmax = min(voltdm->vp_param->vddmax, voltdm->pmic->vddmax);
vddmin = voltdm->pmic->uv_to_vsel(vddmin);
vddmax = voltdm->pmic->uv_to_vsel(vddmax);
waittime = DIV_ROUND_UP(voltdm->pmic->step_size * sys_clk_rate,
1000 * voltdm->pmic->slew_rate);

View File

@ -117,6 +117,13 @@ extern struct omap_vp_instance omap4_vp_mpu;
extern struct omap_vp_instance omap4_vp_iva;
extern struct omap_vp_instance omap4_vp_core;
extern struct omap_vp_param omap3_mpu_vp_data;
extern struct omap_vp_param omap3_core_vp_data;
extern struct omap_vp_param omap4_mpu_vp_data;
extern struct omap_vp_param omap4_iva_vp_data;
extern struct omap_vp_param omap4_core_vp_data;
void omap_vp_init(struct voltagedomain *voltdm);
void omap_vp_enable(struct voltagedomain *voltdm);
void omap_vp_disable(struct voltagedomain *voltdm);

View File

@ -77,3 +77,13 @@ struct omap_vp_instance omap3_vp_core = {
.vstatus = OMAP3_PRM_VP2_STATUS_OFFSET,
.voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET,
};
struct omap_vp_param omap3_mpu_vp_data = {
.vddmin = OMAP3430_VP1_VLIMITTO_VDDMIN,
.vddmax = OMAP3430_VP1_VLIMITTO_VDDMAX,
};
struct omap_vp_param omap3_core_vp_data = {
.vddmin = OMAP3430_VP2_VLIMITTO_VDDMIN,
.vddmax = OMAP3430_VP2_VLIMITTO_VDDMAX,
};

View File

@ -87,3 +87,18 @@ struct omap_vp_instance omap4_vp_core = {
.vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET,
.voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET,
};
struct omap_vp_param omap4_mpu_vp_data = {
.vddmin = OMAP4_VP_MPU_VLIMITTO_VDDMIN,
.vddmax = OMAP4_VP_MPU_VLIMITTO_VDDMAX,
};
struct omap_vp_param omap4_iva_vp_data = {
.vddmin = OMAP4_VP_IVA_VLIMITTO_VDDMIN,
.vddmax = OMAP4_VP_IVA_VLIMITTO_VDDMAX,
};
struct omap_vp_param omap4_core_vp_data = {
.vddmin = OMAP4_VP_CORE_VLIMITTO_VDDMIN,
.vddmax = OMAP4_VP_CORE_VLIMITTO_VDDMAX,
};