diff options
-rw-r--r-- | arch/arm/mach-omap2/omap_twl.c | 166 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm.h | 5 |
3 files changed, 172 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c index b8f08742a6f0..15f8c6c1bb0f 100644 --- a/arch/arm/mach-omap2/omap_twl.c +++ b/arch/arm/mach-omap2/omap_twl.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/i2c/twl.h> | ||
19 | 20 | ||
20 | #include <plat/voltage.h> | 21 | #include <plat/voltage.h> |
21 | 22 | ||
@@ -37,6 +38,28 @@ | |||
37 | #define OMAP3630_VP2_VLIMITTO_VDDMIN 0x18 | 38 | #define OMAP3630_VP2_VLIMITTO_VDDMIN 0x18 |
38 | #define OMAP3630_VP2_VLIMITTO_VDDMAX 0x30 | 39 | #define OMAP3630_VP2_VLIMITTO_VDDMAX 0x30 |
39 | 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 | |||
40 | unsigned long twl4030_vsel_to_uv(const u8 vsel) | 63 | unsigned long twl4030_vsel_to_uv(const u8 vsel) |
41 | { | 64 | { |
42 | return (((vsel * 125) + 6000)) * 100; | 65 | return (((vsel * 125) + 6000)) * 100; |
@@ -47,6 +70,70 @@ u8 twl4030_uv_to_vsel(unsigned long uv) | |||
47 | return DIV_ROUND_UP(uv - 600000, 12500); | 70 | return DIV_ROUND_UP(uv - 600000, 12500); |
48 | } | 71 | } |
49 | 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 | |||
50 | static struct omap_volt_pmic_info omap3_mpu_volt_info = { | 137 | static struct omap_volt_pmic_info omap3_mpu_volt_info = { |
51 | .slew_rate = 4000, | 138 | .slew_rate = 4000, |
52 | .step_size = 12500, | 139 | .step_size = 12500, |
@@ -87,6 +174,85 @@ static struct omap_volt_pmic_info omap3_core_volt_info = { | |||
87 | .uv_to_vsel = twl4030_uv_to_vsel, | 174 | .uv_to_vsel = twl4030_uv_to_vsel, |
88 | }; | 175 | }; |
89 | 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 | |||
90 | int __init omap3_twl_init(void) | 256 | int __init omap3_twl_init(void) |
91 | { | 257 | { |
92 | struct voltagedomain *voltdm; | 258 | struct voltagedomain *voltdm; |
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index d849e0071b94..aac9bacf1bd1 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c | |||
@@ -240,6 +240,7 @@ static int __init omap2_common_pm_late_init(void) | |||
240 | { | 240 | { |
241 | /* Init the OMAP TWL parameters */ | 241 | /* Init the OMAP TWL parameters */ |
242 | omap3_twl_init(); | 242 | omap3_twl_init(); |
243 | omap4_twl_init(); | ||
243 | 244 | ||
244 | /* Init the voltage layer */ | 245 | /* Init the voltage layer */ |
245 | omap_voltage_late_init(); | 246 | omap_voltage_late_init(); |
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index c975a79691b7..1c1b0ab5b978 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h | |||
@@ -126,11 +126,16 @@ static inline void omap_enable_smartreflex_on_init(void) {} | |||
126 | 126 | ||
127 | #ifdef CONFIG_TWL4030_CORE | 127 | #ifdef CONFIG_TWL4030_CORE |
128 | extern int omap3_twl_init(void); | 128 | extern int omap3_twl_init(void); |
129 | extern int omap4_twl_init(void); | ||
129 | #else | 130 | #else |
130 | static inline int omap3_twl_init(void) | 131 | static inline int omap3_twl_init(void) |
131 | { | 132 | { |
132 | return -EINVAL; | 133 | return -EINVAL; |
133 | } | 134 | } |
135 | static inline int omap4_twl_init(void) | ||
136 | { | ||
137 | return -EINVAL; | ||
138 | } | ||
134 | #endif | 139 | #endif |
135 | 140 | ||
136 | #endif | 141 | #endif |