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