diff options
Diffstat (limited to 'arch/arm/mach-omap2/omap_twl.c')
-rw-r--r-- | arch/arm/mach-omap2/omap_twl.c | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c new file mode 100644 index 00000000000..15f8c6c1bb0 --- /dev/null +++ b/arch/arm/mach-omap2/omap_twl.c | |||
@@ -0,0 +1,277 @@ | |||
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> | ||
19 | #include <linux/i2c/twl.h> | ||
20 | |||
21 | #include <plat/voltage.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 OMAP3430_VP1_VLIMITTO_VDDMIN 0x14 | ||
32 | #define OMAP3430_VP1_VLIMITTO_VDDMAX 0x42 | ||
33 | #define OMAP3430_VP2_VLIMITTO_VDDMIN 0x18 | ||
34 | #define OMAP3430_VP2_VLIMITTO_VDDMAX 0x2c | ||
35 | |||
36 | #define OMAP3630_VP1_VLIMITTO_VDDMIN 0x18 | ||
37 | #define OMAP3630_VP1_VLIMITTO_VDDMAX 0x3c | ||
38 | #define OMAP3630_VP2_VLIMITTO_VDDMIN 0x18 | ||
39 | #define OMAP3630_VP2_VLIMITTO_VDDMAX 0x30 | ||
40 | |||
41 | #define OMAP4_SRI2C_SLAVE_ADDR 0x12 | ||
42 | #define OMAP4_VDD_MPU_SR_VOLT_REG 0x55 | ||
43 | #define OMAP4_VDD_IVA_SR_VOLT_REG 0x5B | ||
44 | #define OMAP4_VDD_CORE_SR_VOLT_REG 0x61 | ||
45 | |||
46 | #define OMAP4_VP_CONFIG_ERROROFFSET 0x00 | ||
47 | #define OMAP4_VP_VSTEPMIN_VSTEPMIN 0x01 | ||
48 | #define OMAP4_VP_VSTEPMAX_VSTEPMAX 0x04 | ||
49 | #define OMAP4_VP_VLIMITTO_TIMEOUT_US 200 | ||
50 | |||
51 | #define OMAP4_VP_MPU_VLIMITTO_VDDMIN 0xA | ||
52 | #define OMAP4_VP_MPU_VLIMITTO_VDDMAX 0x39 | ||
53 | #define OMAP4_VP_IVA_VLIMITTO_VDDMIN 0xA | ||
54 | #define OMAP4_VP_IVA_VLIMITTO_VDDMAX 0x2D | ||
55 | #define OMAP4_VP_CORE_VLIMITTO_VDDMIN 0xA | ||
56 | #define OMAP4_VP_CORE_VLIMITTO_VDDMAX 0x28 | ||
57 | |||
58 | static bool is_offset_valid; | ||
59 | static u8 smps_offset; | ||
60 | |||
61 | #define REG_SMPS_OFFSET 0xE0 | ||
62 | |||
63 | unsigned long twl4030_vsel_to_uv(const u8 vsel) | ||
64 | { | ||
65 | return (((vsel * 125) + 6000)) * 100; | ||
66 | } | ||
67 | |||
68 | u8 twl4030_uv_to_vsel(unsigned long uv) | ||
69 | { | ||
70 | return DIV_ROUND_UP(uv - 600000, 12500); | ||
71 | } | ||
72 | |||
73 | unsigned long twl6030_vsel_to_uv(const u8 vsel) | ||
74 | { | ||
75 | /* | ||
76 | * In TWL6030 depending on the value of SMPS_OFFSET | ||
77 | * efuse register the voltage range supported in | ||
78 | * standard mode can be either between 0.6V - 1.3V or | ||
79 | * 0.7V - 1.4V. In TWL6030 ES1.0 SMPS_OFFSET efuse | ||
80 | * is programmed to all 0's where as starting from | ||
81 | * TWL6030 ES1.1 the efuse is programmed to 1 | ||
82 | */ | ||
83 | if (!is_offset_valid) { | ||
84 | twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset, | ||
85 | REG_SMPS_OFFSET); | ||
86 | is_offset_valid = true; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * There is no specific formula for voltage to vsel | ||
91 | * conversion above 1.3V. There are special hardcoded | ||
92 | * values for voltages above 1.3V. Currently we are | ||
93 | * hardcoding only for 1.35 V which is used for 1GH OPP for | ||
94 | * OMAP4430. | ||
95 | */ | ||
96 | if (vsel == 0x3A) | ||
97 | return 1350000; | ||
98 | |||
99 | if (smps_offset & 0x8) | ||
100 | return ((((vsel - 1) * 125) + 7000)) * 100; | ||
101 | else | ||
102 | return ((((vsel - 1) * 125) + 6000)) * 100; | ||
103 | } | ||
104 | |||
105 | u8 twl6030_uv_to_vsel(unsigned long uv) | ||
106 | { | ||
107 | /* | ||
108 | * In TWL6030 depending on the value of SMPS_OFFSET | ||
109 | * efuse register the voltage range supported in | ||
110 | * standard mode can be either between 0.6V - 1.3V or | ||
111 | * 0.7V - 1.4V. In TWL6030 ES1.0 SMPS_OFFSET efuse | ||
112 | * is programmed to all 0's where as starting from | ||
113 | * TWL6030 ES1.1 the efuse is programmed to 1 | ||
114 | */ | ||
115 | if (!is_offset_valid) { | ||
116 | twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset, | ||
117 | REG_SMPS_OFFSET); | ||
118 | is_offset_valid = true; | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * There is no specific formula for voltage to vsel | ||
123 | * conversion above 1.3V. There are special hardcoded | ||
124 | * values for voltages above 1.3V. Currently we are | ||
125 | * hardcoding only for 1.35 V which is used for 1GH OPP for | ||
126 | * OMAP4430. | ||
127 | */ | ||
128 | if (uv == 1350000) | ||
129 | return 0x3A; | ||
130 | |||
131 | if (smps_offset & 0x8) | ||
132 | return DIV_ROUND_UP(uv - 700000, 12500) + 1; | ||
133 | else | ||
134 | return DIV_ROUND_UP(uv - 600000, 12500) + 1; | ||
135 | } | ||
136 | |||
137 | static struct omap_volt_pmic_info omap3_mpu_volt_info = { | ||
138 | .slew_rate = 4000, | ||
139 | .step_size = 12500, | ||
140 | .on_volt = 1200000, | ||
141 | .onlp_volt = 1000000, | ||
142 | .ret_volt = 975000, | ||
143 | .off_volt = 600000, | ||
144 | .volt_setup_time = 0xfff, | ||
145 | .vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET, | ||
146 | .vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN, | ||
147 | .vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX, | ||
148 | .vp_vddmin = OMAP3430_VP1_VLIMITTO_VDDMIN, | ||
149 | .vp_vddmax = OMAP3430_VP1_VLIMITTO_VDDMAX, | ||
150 | .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US, | ||
151 | .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR, | ||
152 | .pmic_reg = OMAP3_VDD_MPU_SR_CONTROL_REG, | ||
153 | .vsel_to_uv = twl4030_vsel_to_uv, | ||
154 | .uv_to_vsel = twl4030_uv_to_vsel, | ||
155 | }; | ||
156 | |||
157 | static struct omap_volt_pmic_info omap3_core_volt_info = { | ||
158 | .slew_rate = 4000, | ||
159 | .step_size = 12500, | ||
160 | .on_volt = 1200000, | ||
161 | .onlp_volt = 1000000, | ||
162 | .ret_volt = 975000, | ||
163 | .off_volt = 600000, | ||
164 | .volt_setup_time = 0xfff, | ||
165 | .vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET, | ||
166 | .vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN, | ||
167 | .vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX, | ||
168 | .vp_vddmin = OMAP3430_VP2_VLIMITTO_VDDMIN, | ||
169 | .vp_vddmax = OMAP3430_VP2_VLIMITTO_VDDMAX, | ||
170 | .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US, | ||
171 | .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR, | ||
172 | .pmic_reg = OMAP3_VDD_CORE_SR_CONTROL_REG, | ||
173 | .vsel_to_uv = twl4030_vsel_to_uv, | ||
174 | .uv_to_vsel = twl4030_uv_to_vsel, | ||
175 | }; | ||
176 | |||
177 | static struct omap_volt_pmic_info omap4_mpu_volt_info = { | ||
178 | .slew_rate = 4000, | ||
179 | .step_size = 12500, | ||
180 | .on_volt = 1350000, | ||
181 | .onlp_volt = 1350000, | ||
182 | .ret_volt = 837500, | ||
183 | .off_volt = 600000, | ||
184 | .volt_setup_time = 0, | ||
185 | .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, | ||
186 | .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, | ||
187 | .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX, | ||
188 | .vp_vddmin = OMAP4_VP_MPU_VLIMITTO_VDDMIN, | ||
189 | .vp_vddmax = OMAP4_VP_MPU_VLIMITTO_VDDMAX, | ||
190 | .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, | ||
191 | .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, | ||
192 | .pmic_reg = OMAP4_VDD_MPU_SR_VOLT_REG, | ||
193 | .vsel_to_uv = twl6030_vsel_to_uv, | ||
194 | .uv_to_vsel = twl6030_uv_to_vsel, | ||
195 | }; | ||
196 | |||
197 | static struct omap_volt_pmic_info omap4_iva_volt_info = { | ||
198 | .slew_rate = 4000, | ||
199 | .step_size = 12500, | ||
200 | .on_volt = 1100000, | ||
201 | .onlp_volt = 1100000, | ||
202 | .ret_volt = 837500, | ||
203 | .off_volt = 600000, | ||
204 | .volt_setup_time = 0, | ||
205 | .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, | ||
206 | .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, | ||
207 | .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX, | ||
208 | .vp_vddmin = OMAP4_VP_IVA_VLIMITTO_VDDMIN, | ||
209 | .vp_vddmax = OMAP4_VP_IVA_VLIMITTO_VDDMAX, | ||
210 | .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, | ||
211 | .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, | ||
212 | .pmic_reg = OMAP4_VDD_IVA_SR_VOLT_REG, | ||
213 | .vsel_to_uv = twl6030_vsel_to_uv, | ||
214 | .uv_to_vsel = twl6030_uv_to_vsel, | ||
215 | }; | ||
216 | |||
217 | static struct omap_volt_pmic_info omap4_core_volt_info = { | ||
218 | .slew_rate = 4000, | ||
219 | .step_size = 12500, | ||
220 | .on_volt = 1100000, | ||
221 | .onlp_volt = 1100000, | ||
222 | .ret_volt = 837500, | ||
223 | .off_volt = 600000, | ||
224 | .volt_setup_time = 0, | ||
225 | .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, | ||
226 | .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, | ||
227 | .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX, | ||
228 | .vp_vddmin = OMAP4_VP_CORE_VLIMITTO_VDDMIN, | ||
229 | .vp_vddmax = OMAP4_VP_CORE_VLIMITTO_VDDMAX, | ||
230 | .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, | ||
231 | .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, | ||
232 | .pmic_reg = OMAP4_VDD_CORE_SR_VOLT_REG, | ||
233 | .vsel_to_uv = twl6030_vsel_to_uv, | ||
234 | .uv_to_vsel = twl6030_uv_to_vsel, | ||
235 | }; | ||
236 | |||
237 | int __init omap4_twl_init(void) | ||
238 | { | ||
239 | struct voltagedomain *voltdm; | ||
240 | |||
241 | if (!cpu_is_omap44xx()) | ||
242 | return -ENODEV; | ||
243 | |||
244 | voltdm = omap_voltage_domain_lookup("mpu"); | ||
245 | omap_voltage_register_pmic(voltdm, &omap4_mpu_volt_info); | ||
246 | |||
247 | voltdm = omap_voltage_domain_lookup("iva"); | ||
248 | omap_voltage_register_pmic(voltdm, &omap4_iva_volt_info); | ||
249 | |||
250 | voltdm = omap_voltage_domain_lookup("core"); | ||
251 | omap_voltage_register_pmic(voltdm, &omap4_core_volt_info); | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | int __init omap3_twl_init(void) | ||
257 | { | ||
258 | struct voltagedomain *voltdm; | ||
259 | |||
260 | if (!cpu_is_omap34xx()) | ||
261 | return -ENODEV; | ||
262 | |||
263 | if (cpu_is_omap3630()) { | ||
264 | omap3_mpu_volt_info.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN; | ||
265 | omap3_mpu_volt_info.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX; | ||
266 | omap3_core_volt_info.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN; | ||
267 | omap3_core_volt_info.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX; | ||
268 | } | ||
269 | |||
270 | voltdm = omap_voltage_domain_lookup("mpu"); | ||
271 | omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info); | ||
272 | |||
273 | voltdm = omap_voltage_domain_lookup("core"); | ||
274 | omap_voltage_register_pmic(voltdm, &omap3_core_volt_info); | ||
275 | |||
276 | return 0; | ||
277 | } | ||