0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/err.h>
0014 #include <linux/io.h>
0015 #include <linux/kernel.h>
0016 #include <linux/mfd/twl.h>
0017
0018 #include "soc.h"
0019 #include "voltage.h"
0020
0021 #include "pm.h"
0022
0023 #define OMAP3_SRI2C_SLAVE_ADDR 0x12
0024 #define OMAP3_VDD_MPU_SR_CONTROL_REG 0x00
0025 #define OMAP3_VDD_CORE_SR_CONTROL_REG 0x01
0026 #define OMAP3_VP_CONFIG_ERROROFFSET 0x00
0027 #define OMAP3_VP_VSTEPMIN_VSTEPMIN 0x1
0028 #define OMAP3_VP_VSTEPMAX_VSTEPMAX 0x04
0029 #define OMAP3_VP_VLIMITTO_TIMEOUT_US 200
0030
0031 #define OMAP4_SRI2C_SLAVE_ADDR 0x12
0032 #define OMAP4_VDD_MPU_SR_VOLT_REG 0x55
0033 #define OMAP4_VDD_MPU_SR_CMD_REG 0x56
0034 #define OMAP4_VDD_IVA_SR_VOLT_REG 0x5B
0035 #define OMAP4_VDD_IVA_SR_CMD_REG 0x5C
0036 #define OMAP4_VDD_CORE_SR_VOLT_REG 0x61
0037 #define OMAP4_VDD_CORE_SR_CMD_REG 0x62
0038
0039 static bool is_offset_valid;
0040 static u8 smps_offset;
0041
0042 #define REG_SMPS_OFFSET 0xE0
0043
0044 static unsigned long twl4030_vsel_to_uv(const u8 vsel)
0045 {
0046 return (((vsel * 125) + 6000)) * 100;
0047 }
0048
0049 static u8 twl4030_uv_to_vsel(unsigned long uv)
0050 {
0051 return DIV_ROUND_UP(uv - 600000, 12500);
0052 }
0053
0054 static unsigned long twl6030_vsel_to_uv(const u8 vsel)
0055 {
0056
0057
0058
0059
0060
0061
0062
0063
0064 if (!is_offset_valid) {
0065 twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset,
0066 REG_SMPS_OFFSET);
0067 is_offset_valid = true;
0068 }
0069
0070 if (!vsel)
0071 return 0;
0072
0073
0074
0075
0076
0077
0078
0079 if (vsel == 0x3A)
0080 return 1350000;
0081
0082 if (smps_offset & 0x8)
0083 return ((((vsel - 1) * 1266) + 70900)) * 10;
0084 else
0085 return ((((vsel - 1) * 1266) + 60770)) * 10;
0086 }
0087
0088 static u8 twl6030_uv_to_vsel(unsigned long uv)
0089 {
0090
0091
0092
0093
0094
0095
0096
0097
0098 if (!is_offset_valid) {
0099 twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset,
0100 REG_SMPS_OFFSET);
0101 is_offset_valid = true;
0102 }
0103
0104 if (!uv)
0105 return 0x00;
0106
0107
0108
0109
0110
0111
0112
0113 if (uv > twl6030_vsel_to_uv(0x39)) {
0114 if (uv == 1350000)
0115 return 0x3A;
0116 pr_err("%s:OUT OF RANGE! non mapped vsel for %ld Vs max %ld\n",
0117 __func__, uv, twl6030_vsel_to_uv(0x39));
0118 return 0x3A;
0119 }
0120
0121 if (smps_offset & 0x8)
0122 return DIV_ROUND_UP(uv - 709000, 12660) + 1;
0123 else
0124 return DIV_ROUND_UP(uv - 607700, 12660) + 1;
0125 }
0126
0127 static struct omap_voltdm_pmic omap3_mpu_pmic = {
0128 .slew_rate = 4000,
0129 .step_size = 12500,
0130 .vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET,
0131 .vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN,
0132 .vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX,
0133 .vddmin = 600000,
0134 .vddmax = 1450000,
0135 .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
0136 .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
0137 .volt_reg_addr = OMAP3_VDD_MPU_SR_CONTROL_REG,
0138 .i2c_high_speed = true,
0139 .vsel_to_uv = twl4030_vsel_to_uv,
0140 .uv_to_vsel = twl4030_uv_to_vsel,
0141 };
0142
0143 static struct omap_voltdm_pmic omap3_core_pmic = {
0144 .slew_rate = 4000,
0145 .step_size = 12500,
0146 .vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET,
0147 .vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN,
0148 .vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX,
0149 .vddmin = 600000,
0150 .vddmax = 1450000,
0151 .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
0152 .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
0153 .volt_reg_addr = OMAP3_VDD_CORE_SR_CONTROL_REG,
0154 .i2c_high_speed = true,
0155 .vsel_to_uv = twl4030_vsel_to_uv,
0156 .uv_to_vsel = twl4030_uv_to_vsel,
0157 };
0158
0159 static struct omap_voltdm_pmic omap4_mpu_pmic = {
0160 .slew_rate = 4000,
0161 .step_size = 12660,
0162 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
0163 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
0164 .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
0165 .vddmin = 0,
0166 .vddmax = 2100000,
0167 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
0168 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
0169 .volt_reg_addr = OMAP4_VDD_MPU_SR_VOLT_REG,
0170 .cmd_reg_addr = OMAP4_VDD_MPU_SR_CMD_REG,
0171 .i2c_high_speed = true,
0172 .i2c_pad_load = 3,
0173 .vsel_to_uv = twl6030_vsel_to_uv,
0174 .uv_to_vsel = twl6030_uv_to_vsel,
0175 };
0176
0177 static struct omap_voltdm_pmic omap4_iva_pmic = {
0178 .slew_rate = 4000,
0179 .step_size = 12660,
0180 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
0181 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
0182 .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
0183 .vddmin = 0,
0184 .vddmax = 2100000,
0185 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
0186 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
0187 .volt_reg_addr = OMAP4_VDD_IVA_SR_VOLT_REG,
0188 .cmd_reg_addr = OMAP4_VDD_IVA_SR_CMD_REG,
0189 .i2c_high_speed = true,
0190 .i2c_pad_load = 3,
0191 .vsel_to_uv = twl6030_vsel_to_uv,
0192 .uv_to_vsel = twl6030_uv_to_vsel,
0193 };
0194
0195 static struct omap_voltdm_pmic omap4_core_pmic = {
0196 .slew_rate = 4000,
0197 .step_size = 12660,
0198 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
0199 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
0200 .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
0201 .vddmin = 0,
0202 .vddmax = 2100000,
0203 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
0204 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
0205 .volt_reg_addr = OMAP4_VDD_CORE_SR_VOLT_REG,
0206 .cmd_reg_addr = OMAP4_VDD_CORE_SR_CMD_REG,
0207 .i2c_high_speed = true,
0208 .i2c_pad_load = 3,
0209 .vsel_to_uv = twl6030_vsel_to_uv,
0210 .uv_to_vsel = twl6030_uv_to_vsel,
0211 };
0212
0213 int __init omap4_twl_init(void)
0214 {
0215 struct voltagedomain *voltdm;
0216
0217 if (!cpu_is_omap44xx() ||
0218 of_find_compatible_node(NULL, NULL, "motorola,cpcap"))
0219 return -ENODEV;
0220
0221 voltdm = voltdm_lookup("mpu");
0222 omap_voltage_register_pmic(voltdm, &omap4_mpu_pmic);
0223
0224 voltdm = voltdm_lookup("iva");
0225 omap_voltage_register_pmic(voltdm, &omap4_iva_pmic);
0226
0227 voltdm = voltdm_lookup("core");
0228 omap_voltage_register_pmic(voltdm, &omap4_core_pmic);
0229
0230 return 0;
0231 }
0232
0233 int __init omap3_twl_init(void)
0234 {
0235 struct voltagedomain *voltdm;
0236
0237 if (!cpu_is_omap34xx())
0238 return -ENODEV;
0239
0240 voltdm = voltdm_lookup("mpu_iva");
0241 omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic);
0242
0243 voltdm = voltdm_lookup("core");
0244 omap_voltage_register_pmic(voltdm, &omap3_core_pmic);
0245
0246 return 0;
0247 }