1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * OMAP and TWL PMIC specific initializations. 4 * 5 * Copyright (C) 2010 Texas Instruments Incorporated. 6 * Thara Gopinath 7 * Copyright (C) 2009 Texas Instruments Incorporated. 8 * Nishanth Menon 9 * Copyright (C) 2009 Nokia Corporation 10 * Paul Walmsley 11 */ 12 13 #include <linux/err.h> 14 #include <linux/io.h> 15 #include <linux/kernel.h> 16 #include <linux/mfd/twl.h> 17 18 #include "soc.h" 19 #include "voltage.h" 20 21 #include "pm.h" 22 23 #define OMAP3_SRI2C_SLAVE_ADDR 0x12 24 #define OMAP3_VDD_MPU_SR_CONTROL_REG 0x00 25 #define OMAP3_VDD_CORE_SR_CONTROL_REG 0x01 26 #define OMAP3_VP_CONFIG_ERROROFFSET 0x00 27 #define OMAP3_VP_VSTEPMIN_VSTEPMIN 0x1 28 #define OMAP3_VP_VSTEPMAX_VSTEPMAX 0x04 29 #define OMAP3_VP_VLIMITTO_TIMEOUT_US 200 30 31 #define OMAP4_SRI2C_SLAVE_ADDR 0x12 32 #define OMAP4_VDD_MPU_SR_VOLT_REG 0x55 33 #define OMAP4_VDD_MPU_SR_CMD_REG 0x56 34 #define OMAP4_VDD_IVA_SR_VOLT_REG 0x5B 35 #define OMAP4_VDD_IVA_SR_CMD_REG 0x5C 36 #define OMAP4_VDD_CORE_SR_VOLT_REG 0x61 37 #define OMAP4_VDD_CORE_SR_CMD_REG 0x62 38 39 static bool is_offset_valid; 40 static u8 smps_offset; 41 42 #define REG_SMPS_OFFSET 0xE0 43 44 static unsigned long twl4030_vsel_to_uv(const u8 vsel) 45 { 46 return (((vsel * 125) + 6000)) * 100; 47 } 48 49 static u8 twl4030_uv_to_vsel(unsigned long uv) 50 { 51 return DIV_ROUND_UP(uv - 600000, 12500); 52 } 53 54 static unsigned long twl6030_vsel_to_uv(const u8 vsel) 55 { 56 /* 57 * In TWL6030 depending on the value of SMPS_OFFSET 58 * efuse register the voltage range supported in 59 * standard mode can be either between 0.6V - 1.3V or 60 * 0.7V - 1.4V. In TWL6030 ES1.0 SMPS_OFFSET efuse 61 * is programmed to all 0's where as starting from 62 * TWL6030 ES1.1 the efuse is programmed to 1 63 */ 64 if (!is_offset_valid) { 65 twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset, 66 REG_SMPS_OFFSET); 67 is_offset_valid = true; 68 } 69 70 if (!vsel) 71 return 0; 72 /* 73 * There is no specific formula for voltage to vsel 74 * conversion above 1.3V. There are special hardcoded 75 * values for voltages above 1.3V. Currently we are 76 * hardcoding only for 1.35 V which is used for 1GH OPP for 77 * OMAP4430. 78 */ 79 if (vsel == 0x3A) 80 return 1350000; 81 82 if (smps_offset & 0x8) 83 return ((((vsel - 1) * 1266) + 70900)) * 10; 84 else 85 return ((((vsel - 1) * 1266) + 60770)) * 10; 86 } 87 88 static u8 twl6030_uv_to_vsel(unsigned long uv) 89 { 90 /* 91 * In TWL6030 depending on the value of SMPS_OFFSET 92 * efuse register the voltage range supported in 93 * standard mode can be either between 0.6V - 1.3V or 94 * 0.7V - 1.4V. In TWL6030 ES1.0 SMPS_OFFSET efuse 95 * is programmed to all 0's where as starting from 96 * TWL6030 ES1.1 the efuse is programmed to 1 97 */ 98 if (!is_offset_valid) { 99 twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset, 100 REG_SMPS_OFFSET); 101 is_offset_valid = true; 102 } 103 104 if (!uv) 105 return 0x00; 106 /* 107 * There is no specific formula for voltage to vsel 108 * conversion above 1.3V. There are special hardcoded 109 * values for voltages above 1.3V. Currently we are 110 * hardcoding only for 1.35 V which is used for 1GH OPP for 111 * OMAP4430. 112 */ 113 if (uv > twl6030_vsel_to_uv(0x39)) { 114 if (uv == 1350000) 115 return 0x3A; 116 pr_err("%s:OUT OF RANGE! non mapped vsel for %ld Vs max %ld\n", 117 __func__, uv, twl6030_vsel_to_uv(0x39)); 118 return 0x3A; 119 } 120 121 if (smps_offset & 0x8) 122 return DIV_ROUND_UP(uv - 709000, 12660) + 1; 123 else 124 return DIV_ROUND_UP(uv - 607700, 12660) + 1; 125 } 126 127 static struct omap_voltdm_pmic omap3_mpu_pmic = { 128 .slew_rate = 4000, 129 .step_size = 12500, 130 .vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET, 131 .vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN, 132 .vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX, 133 .vddmin = 600000, 134 .vddmax = 1450000, 135 .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US, 136 .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR, 137 .volt_reg_addr = OMAP3_VDD_MPU_SR_CONTROL_REG, 138 .i2c_high_speed = true, 139 .vsel_to_uv = twl4030_vsel_to_uv, 140 .uv_to_vsel = twl4030_uv_to_vsel, 141 }; 142 143 static struct omap_voltdm_pmic omap3_core_pmic = { 144 .slew_rate = 4000, 145 .step_size = 12500, 146 .vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET, 147 .vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN, 148 .vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX, 149 .vddmin = 600000, 150 .vddmax = 1450000, 151 .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US, 152 .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR, 153 .volt_reg_addr = OMAP3_VDD_CORE_SR_CONTROL_REG, 154 .i2c_high_speed = true, 155 .vsel_to_uv = twl4030_vsel_to_uv, 156 .uv_to_vsel = twl4030_uv_to_vsel, 157 }; 158 159 static struct omap_voltdm_pmic omap4_mpu_pmic = { 160 .slew_rate = 4000, 161 .step_size = 12660, 162 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, 163 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, 164 .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX, 165 .vddmin = 0, 166 .vddmax = 2100000, 167 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, 168 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, 169 .volt_reg_addr = OMAP4_VDD_MPU_SR_VOLT_REG, 170 .cmd_reg_addr = OMAP4_VDD_MPU_SR_CMD_REG, 171 .i2c_high_speed = true, 172 .i2c_pad_load = 3, 173 .vsel_to_uv = twl6030_vsel_to_uv, 174 .uv_to_vsel = twl6030_uv_to_vsel, 175 }; 176 177 static struct omap_voltdm_pmic omap4_iva_pmic = { 178 .slew_rate = 4000, 179 .step_size = 12660, 180 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, 181 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, 182 .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX, 183 .vddmin = 0, 184 .vddmax = 2100000, 185 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, 186 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, 187 .volt_reg_addr = OMAP4_VDD_IVA_SR_VOLT_REG, 188 .cmd_reg_addr = OMAP4_VDD_IVA_SR_CMD_REG, 189 .i2c_high_speed = true, 190 .i2c_pad_load = 3, 191 .vsel_to_uv = twl6030_vsel_to_uv, 192 .uv_to_vsel = twl6030_uv_to_vsel, 193 }; 194 195 static struct omap_voltdm_pmic omap4_core_pmic = { 196 .slew_rate = 4000, 197 .step_size = 12660, 198 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, 199 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, 200 .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX, 201 .vddmin = 0, 202 .vddmax = 2100000, 203 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, 204 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, 205 .volt_reg_addr = OMAP4_VDD_CORE_SR_VOLT_REG, 206 .cmd_reg_addr = OMAP4_VDD_CORE_SR_CMD_REG, 207 .i2c_high_speed = true, 208 .i2c_pad_load = 3, 209 .vsel_to_uv = twl6030_vsel_to_uv, 210 .uv_to_vsel = twl6030_uv_to_vsel, 211 }; 212 213 int __init omap4_twl_init(void) 214 { 215 struct voltagedomain *voltdm; 216 217 if (!cpu_is_omap44xx() || 218 of_find_compatible_node(NULL, NULL, "motorola,cpcap")) 219 return -ENODEV; 220 221 voltdm = voltdm_lookup("mpu"); 222 omap_voltage_register_pmic(voltdm, &omap4_mpu_pmic); 223 224 voltdm = voltdm_lookup("iva"); 225 omap_voltage_register_pmic(voltdm, &omap4_iva_pmic); 226 227 voltdm = voltdm_lookup("core"); 228 omap_voltage_register_pmic(voltdm, &omap4_core_pmic); 229 230 return 0; 231 } 232 233 int __init omap3_twl_init(void) 234 { 235 struct voltagedomain *voltdm; 236 237 if (!cpu_is_omap34xx()) 238 return -ENODEV; 239 240 voltdm = voltdm_lookup("mpu_iva"); 241 omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic); 242 243 voltdm = voltdm_lookup("core"); 244 omap_voltage_register_pmic(voltdm, &omap3_core_pmic); 245 246 return 0; 247 } 248
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.