aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2011-09-15 19:14:33 -0400
committerTony Lindgren <tony@atomide.com>2011-09-15 19:14:33 -0400
commit23618f7faa8fdac93d4823d0372f4101d642b8b1 (patch)
tree9cdc7fb633ec7c0f24eee93a968bb799f45608e2 /arch/arm/mach-omap2
parentceb1c532ba6220900e61ec7073a9234661efa450 (diff)
parentee7fbba63e334481049a7939b8071160824447d3 (diff)
Merge branch 'for_3.2/voltage-cleanup' of git://gitorious.org/khilman/linux-omap-pm into voltage
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/Makefile5
-rw-r--r--arch/arm/mach-omap2/io.c5
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c4
-rw-r--r--arch/arm/mach-omap2/omap_twl.c107
-rw-r--r--arch/arm/mach-omap2/pm.c6
-rw-r--r--arch/arm/mach-omap2/powerdomain.c23
-rw-r--r--arch/arm/mach-omap2/powerdomain.h10
-rw-r--r--arch/arm/mach-omap2/powerdomain2xxx_3xxx.c2
-rw-r--r--arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c2
-rw-r--r--arch/arm/mach-omap2/powerdomains2xxx_data.c4
-rw-r--r--arch/arm/mach-omap2/powerdomains3xxx_data.c16
-rw-r--r--arch/arm/mach-omap2/powerdomains44xx_data.c16
-rw-r--r--arch/arm/mach-omap2/prm2xxx_3xxx.c56
-rw-r--r--arch/arm/mach-omap2/prm2xxx_3xxx.h12
-rw-r--r--arch/arm/mach-omap2/prm44xx.c71
-rw-r--r--arch/arm/mach-omap2/prm44xx.h12
-rw-r--r--arch/arm/mach-omap2/smartreflex-class3.c4
-rw-r--r--arch/arm/mach-omap2/smartreflex.c29
-rw-r--r--arch/arm/mach-omap2/sr_device.c2
-rw-r--r--arch/arm/mach-omap2/vc.c367
-rw-r--r--arch/arm/mach-omap2/vc.h88
-rw-r--r--arch/arm/mach-omap2/vc3xxx_data.c31
-rw-r--r--arch/arm/mach-omap2/vc44xx_data.c44
-rw-r--r--arch/arm/mach-omap2/voltage.c1088
-rw-r--r--arch/arm/mach-omap2/voltage.h138
-rw-r--r--arch/arm/mach-omap2/voltagedomains2xxx_data.c32
-rw-r--r--arch/arm/mach-omap2/voltagedomains3xxx_data.c83
-rw-r--r--arch/arm/mach-omap2/voltagedomains44xx_data.c99
-rw-r--r--arch/arm/mach-omap2/vp.c278
-rw-r--r--arch/arm/mach-omap2/vp.h133
-rw-r--r--arch/arm/mach-omap2/vp3xxx_data.c35
-rw-r--r--arch/arm/mach-omap2/vp44xx_data.c47
32 files changed, 1579 insertions, 1270 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index cd45c045ab8c..8bd389d60138 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -90,8 +90,9 @@ obj-$(CONFIG_ARCH_OMAP4) += prcm.o cm2xxx_3xxx.o cminst44xx.o \
90 90
91# OMAP voltage domains 91# OMAP voltage domains
92ifeq ($(CONFIG_PM),y) 92ifeq ($(CONFIG_PM),y)
93voltagedomain-common := voltage.o 93voltagedomain-common := voltage.o vc.o vp.o
94obj-$(CONFIG_ARCH_OMAP2) += $(voltagedomain-common) 94obj-$(CONFIG_ARCH_OMAP2) += $(voltagedomain-common) \
95 voltagedomains2xxx_data.o
95obj-$(CONFIG_ARCH_OMAP3) += $(voltagedomain-common) \ 96obj-$(CONFIG_ARCH_OMAP3) += $(voltagedomain-common) \
96 voltagedomains3xxx_data.o 97 voltagedomains3xxx_data.o
97obj-$(CONFIG_ARCH_OMAP4) += $(voltagedomain-common) \ 98obj-$(CONFIG_ARCH_OMAP4) += $(voltagedomain-common) \
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 1a13b7916554..15f91c42be66 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -38,6 +38,7 @@
38#include "io.h" 38#include "io.h"
39 39
40#include <plat/omap-pm.h> 40#include <plat/omap-pm.h>
41#include "voltage.h"
41#include "powerdomain.h" 42#include "powerdomain.h"
42 43
43#include "clockdomain.h" 44#include "clockdomain.h"
@@ -341,18 +342,22 @@ void __init omap2_init_common_infrastructure(void)
341 u8 postsetup_state; 342 u8 postsetup_state;
342 343
343 if (cpu_is_omap242x()) { 344 if (cpu_is_omap242x()) {
345 omap2xxx_voltagedomains_init();
344 omap242x_powerdomains_init(); 346 omap242x_powerdomains_init();
345 omap242x_clockdomains_init(); 347 omap242x_clockdomains_init();
346 omap2420_hwmod_init(); 348 omap2420_hwmod_init();
347 } else if (cpu_is_omap243x()) { 349 } else if (cpu_is_omap243x()) {
350 omap2xxx_voltagedomains_init();
348 omap243x_powerdomains_init(); 351 omap243x_powerdomains_init();
349 omap243x_clockdomains_init(); 352 omap243x_clockdomains_init();
350 omap2430_hwmod_init(); 353 omap2430_hwmod_init();
351 } else if (cpu_is_omap34xx()) { 354 } else if (cpu_is_omap34xx()) {
355 omap3xxx_voltagedomains_init();
352 omap3xxx_powerdomains_init(); 356 omap3xxx_powerdomains_init();
353 omap3xxx_clockdomains_init(); 357 omap3xxx_clockdomains_init();
354 omap3xxx_hwmod_init(); 358 omap3xxx_hwmod_init();
355 } else if (cpu_is_omap44xx()) { 359 } else if (cpu_is_omap44xx()) {
360 omap44xx_voltagedomains_init();
356 omap44xx_powerdomains_init(); 361 omap44xx_powerdomains_init();
357 omap44xx_clockdomains_init(); 362 omap44xx_clockdomains_init();
358 omap44xx_hwmod_init(); 363 omap44xx_hwmod_init();
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index ab35acbc2d1d..e787731cf3dc 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -2542,7 +2542,7 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
2542 .name = "sr1_hwmod", 2542 .name = "sr1_hwmod",
2543 .class = &omap34xx_smartreflex_hwmod_class, 2543 .class = &omap34xx_smartreflex_hwmod_class,
2544 .main_clk = "sr1_fck", 2544 .main_clk = "sr1_fck",
2545 .vdd_name = "mpu", 2545 .vdd_name = "mpu_iva",
2546 .prcm = { 2546 .prcm = {
2547 .omap2 = { 2547 .omap2 = {
2548 .prcm_reg_id = 1, 2548 .prcm_reg_id = 1,
@@ -2561,7 +2561,7 @@ static struct omap_hwmod omap36xx_sr1_hwmod = {
2561 .name = "sr1_hwmod", 2561 .name = "sr1_hwmod",
2562 .class = &omap36xx_smartreflex_hwmod_class, 2562 .class = &omap36xx_smartreflex_hwmod_class,
2563 .main_clk = "sr1_fck", 2563 .main_clk = "sr1_fck",
2564 .vdd_name = "mpu", 2564 .vdd_name = "mpu_iva",
2565 .prcm = { 2565 .prcm = {
2566 .omap2 = { 2566 .omap2 = {
2567 .prcm_reg_id = 1, 2567 .prcm_reg_id = 1,
diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c
index 07d6140baa9d..f515a1a056d5 100644
--- a/arch/arm/mach-omap2/omap_twl.c
+++ b/arch/arm/mach-omap2/omap_twl.c
@@ -42,8 +42,11 @@
42 42
43#define OMAP4_SRI2C_SLAVE_ADDR 0x12 43#define OMAP4_SRI2C_SLAVE_ADDR 0x12
44#define OMAP4_VDD_MPU_SR_VOLT_REG 0x55 44#define OMAP4_VDD_MPU_SR_VOLT_REG 0x55
45#define OMAP4_VDD_MPU_SR_CMD_REG 0x56
45#define OMAP4_VDD_IVA_SR_VOLT_REG 0x5B 46#define OMAP4_VDD_IVA_SR_VOLT_REG 0x5B
47#define OMAP4_VDD_IVA_SR_CMD_REG 0x5C
46#define OMAP4_VDD_CORE_SR_VOLT_REG 0x61 48#define OMAP4_VDD_CORE_SR_VOLT_REG 0x61
49#define OMAP4_VDD_CORE_SR_CMD_REG 0x62
47 50
48#define OMAP4_VP_CONFIG_ERROROFFSET 0x00 51#define OMAP4_VP_CONFIG_ERROROFFSET 0x00
49#define OMAP4_VP_VSTEPMIN_VSTEPMIN 0x01 52#define OMAP4_VP_VSTEPMIN_VSTEPMIN 0x01
@@ -95,6 +98,8 @@ static unsigned long twl6030_vsel_to_uv(const u8 vsel)
95 is_offset_valid = true; 98 is_offset_valid = true;
96 } 99 }
97 100
101 if (!vsel)
102 return 0;
98 /* 103 /*
99 * There is no specific formula for voltage to vsel 104 * There is no specific formula for voltage to vsel
100 * conversion above 1.3V. There are special hardcoded 105 * conversion above 1.3V. There are special hardcoded
@@ -106,9 +111,9 @@ static unsigned long twl6030_vsel_to_uv(const u8 vsel)
106 return 1350000; 111 return 1350000;
107 112
108 if (smps_offset & 0x8) 113 if (smps_offset & 0x8)
109 return ((((vsel - 1) * 125) + 7000)) * 100; 114 return ((((vsel - 1) * 1266) + 70900)) * 10;
110 else 115 else
111 return ((((vsel - 1) * 125) + 6000)) * 100; 116 return ((((vsel - 1) * 1266) + 60770)) * 10;
112} 117}
113 118
114static u8 twl6030_uv_to_vsel(unsigned long uv) 119static u8 twl6030_uv_to_vsel(unsigned long uv)
@@ -127,6 +132,8 @@ static u8 twl6030_uv_to_vsel(unsigned long uv)
127 is_offset_valid = true; 132 is_offset_valid = true;
128 } 133 }
129 134
135 if (!uv)
136 return 0x00;
130 /* 137 /*
131 * There is no specific formula for voltage to vsel 138 * There is no specific formula for voltage to vsel
132 * conversion above 1.3V. There are special hardcoded 139 * conversion above 1.3V. There are special hardcoded
@@ -134,16 +141,21 @@ static u8 twl6030_uv_to_vsel(unsigned long uv)
134 * hardcoding only for 1.35 V which is used for 1GH OPP for 141 * hardcoding only for 1.35 V which is used for 1GH OPP for
135 * OMAP4430. 142 * OMAP4430.
136 */ 143 */
137 if (uv == 1350000) 144 if (uv > twl6030_vsel_to_uv(0x39)) {
145 if (uv == 1350000)
146 return 0x3A;
147 pr_err("%s:OUT OF RANGE! non mapped vsel for %ld Vs max %ld\n",
148 __func__, uv, twl6030_vsel_to_uv(0x39));
138 return 0x3A; 149 return 0x3A;
150 }
139 151
140 if (smps_offset & 0x8) 152 if (smps_offset & 0x8)
141 return DIV_ROUND_UP(uv - 700000, 12500) + 1; 153 return DIV_ROUND_UP(uv - 709000, 12660) + 1;
142 else 154 else
143 return DIV_ROUND_UP(uv - 600000, 12500) + 1; 155 return DIV_ROUND_UP(uv - 607700, 12660) + 1;
144} 156}
145 157
146static struct omap_volt_pmic_info omap3_mpu_volt_info = { 158static struct omap_voltdm_pmic omap3_mpu_pmic = {
147 .slew_rate = 4000, 159 .slew_rate = 4000,
148 .step_size = 12500, 160 .step_size = 12500,
149 .on_volt = 1200000, 161 .on_volt = 1200000,
@@ -158,12 +170,13 @@ static struct omap_volt_pmic_info omap3_mpu_volt_info = {
158 .vp_vddmax = OMAP3430_VP1_VLIMITTO_VDDMAX, 170 .vp_vddmax = OMAP3430_VP1_VLIMITTO_VDDMAX,
159 .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US, 171 .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
160 .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR, 172 .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
161 .pmic_reg = OMAP3_VDD_MPU_SR_CONTROL_REG, 173 .volt_reg_addr = OMAP3_VDD_MPU_SR_CONTROL_REG,
174 .i2c_high_speed = true,
162 .vsel_to_uv = twl4030_vsel_to_uv, 175 .vsel_to_uv = twl4030_vsel_to_uv,
163 .uv_to_vsel = twl4030_uv_to_vsel, 176 .uv_to_vsel = twl4030_uv_to_vsel,
164}; 177};
165 178
166static struct omap_volt_pmic_info omap3_core_volt_info = { 179static struct omap_voltdm_pmic omap3_core_pmic = {
167 .slew_rate = 4000, 180 .slew_rate = 4000,
168 .step_size = 12500, 181 .step_size = 12500,
169 .on_volt = 1200000, 182 .on_volt = 1200000,
@@ -178,18 +191,19 @@ static struct omap_volt_pmic_info omap3_core_volt_info = {
178 .vp_vddmax = OMAP3430_VP2_VLIMITTO_VDDMAX, 191 .vp_vddmax = OMAP3430_VP2_VLIMITTO_VDDMAX,
179 .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US, 192 .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
180 .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR, 193 .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
181 .pmic_reg = OMAP3_VDD_CORE_SR_CONTROL_REG, 194 .volt_reg_addr = OMAP3_VDD_CORE_SR_CONTROL_REG,
195 .i2c_high_speed = true,
182 .vsel_to_uv = twl4030_vsel_to_uv, 196 .vsel_to_uv = twl4030_vsel_to_uv,
183 .uv_to_vsel = twl4030_uv_to_vsel, 197 .uv_to_vsel = twl4030_uv_to_vsel,
184}; 198};
185 199
186static struct omap_volt_pmic_info omap4_mpu_volt_info = { 200static struct omap_voltdm_pmic omap4_mpu_pmic = {
187 .slew_rate = 4000, 201 .slew_rate = 4000,
188 .step_size = 12500, 202 .step_size = 12660,
189 .on_volt = 1350000, 203 .on_volt = 1375000,
190 .onlp_volt = 1350000, 204 .onlp_volt = 1375000,
191 .ret_volt = 837500, 205 .ret_volt = 830000,
192 .off_volt = 600000, 206 .off_volt = 0,
193 .volt_setup_time = 0, 207 .volt_setup_time = 0,
194 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, 208 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
195 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, 209 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
@@ -198,18 +212,20 @@ static struct omap_volt_pmic_info omap4_mpu_volt_info = {
198 .vp_vddmax = OMAP4_VP_MPU_VLIMITTO_VDDMAX, 212 .vp_vddmax = OMAP4_VP_MPU_VLIMITTO_VDDMAX,
199 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, 213 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
200 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, 214 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
201 .pmic_reg = OMAP4_VDD_MPU_SR_VOLT_REG, 215 .volt_reg_addr = OMAP4_VDD_MPU_SR_VOLT_REG,
216 .cmd_reg_addr = OMAP4_VDD_MPU_SR_CMD_REG,
217 .i2c_high_speed = true,
202 .vsel_to_uv = twl6030_vsel_to_uv, 218 .vsel_to_uv = twl6030_vsel_to_uv,
203 .uv_to_vsel = twl6030_uv_to_vsel, 219 .uv_to_vsel = twl6030_uv_to_vsel,
204}; 220};
205 221
206static struct omap_volt_pmic_info omap4_iva_volt_info = { 222static struct omap_voltdm_pmic omap4_iva_pmic = {
207 .slew_rate = 4000, 223 .slew_rate = 4000,
208 .step_size = 12500, 224 .step_size = 12660,
209 .on_volt = 1100000, 225 .on_volt = 1188000,
210 .onlp_volt = 1100000, 226 .onlp_volt = 1188000,
211 .ret_volt = 837500, 227 .ret_volt = 830000,
212 .off_volt = 600000, 228 .off_volt = 0,
213 .volt_setup_time = 0, 229 .volt_setup_time = 0,
214 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, 230 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
215 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, 231 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
@@ -218,18 +234,20 @@ static struct omap_volt_pmic_info omap4_iva_volt_info = {
218 .vp_vddmax = OMAP4_VP_IVA_VLIMITTO_VDDMAX, 234 .vp_vddmax = OMAP4_VP_IVA_VLIMITTO_VDDMAX,
219 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, 235 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
220 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, 236 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
221 .pmic_reg = OMAP4_VDD_IVA_SR_VOLT_REG, 237 .volt_reg_addr = OMAP4_VDD_IVA_SR_VOLT_REG,
238 .cmd_reg_addr = OMAP4_VDD_IVA_SR_CMD_REG,
239 .i2c_high_speed = true,
222 .vsel_to_uv = twl6030_vsel_to_uv, 240 .vsel_to_uv = twl6030_vsel_to_uv,
223 .uv_to_vsel = twl6030_uv_to_vsel, 241 .uv_to_vsel = twl6030_uv_to_vsel,
224}; 242};
225 243
226static struct omap_volt_pmic_info omap4_core_volt_info = { 244static struct omap_voltdm_pmic omap4_core_pmic = {
227 .slew_rate = 4000, 245 .slew_rate = 4000,
228 .step_size = 12500, 246 .step_size = 12660,
229 .on_volt = 1100000, 247 .on_volt = 1200000,
230 .onlp_volt = 1100000, 248 .onlp_volt = 1200000,
231 .ret_volt = 837500, 249 .ret_volt = 830000,
232 .off_volt = 600000, 250 .off_volt = 0,
233 .volt_setup_time = 0, 251 .volt_setup_time = 0,
234 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET, 252 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
235 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN, 253 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
@@ -238,7 +256,8 @@ static struct omap_volt_pmic_info omap4_core_volt_info = {
238 .vp_vddmax = OMAP4_VP_CORE_VLIMITTO_VDDMAX, 256 .vp_vddmax = OMAP4_VP_CORE_VLIMITTO_VDDMAX,
239 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, 257 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
240 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, 258 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
241 .pmic_reg = OMAP4_VDD_CORE_SR_VOLT_REG, 259 .volt_reg_addr = OMAP4_VDD_CORE_SR_VOLT_REG,
260 .cmd_reg_addr = OMAP4_VDD_CORE_SR_CMD_REG,
242 .vsel_to_uv = twl6030_vsel_to_uv, 261 .vsel_to_uv = twl6030_vsel_to_uv,
243 .uv_to_vsel = twl6030_uv_to_vsel, 262 .uv_to_vsel = twl6030_uv_to_vsel,
244}; 263};
@@ -250,14 +269,14 @@ int __init omap4_twl_init(void)
250 if (!cpu_is_omap44xx()) 269 if (!cpu_is_omap44xx())
251 return -ENODEV; 270 return -ENODEV;
252 271
253 voltdm = omap_voltage_domain_lookup("mpu"); 272 voltdm = voltdm_lookup("mpu");
254 omap_voltage_register_pmic(voltdm, &omap4_mpu_volt_info); 273 omap_voltage_register_pmic(voltdm, &omap4_mpu_pmic);
255 274
256 voltdm = omap_voltage_domain_lookup("iva"); 275 voltdm = voltdm_lookup("iva");
257 omap_voltage_register_pmic(voltdm, &omap4_iva_volt_info); 276 omap_voltage_register_pmic(voltdm, &omap4_iva_pmic);
258 277
259 voltdm = omap_voltage_domain_lookup("core"); 278 voltdm = voltdm_lookup("core");
260 omap_voltage_register_pmic(voltdm, &omap4_core_volt_info); 279 omap_voltage_register_pmic(voltdm, &omap4_core_pmic);
261 280
262 return 0; 281 return 0;
263} 282}
@@ -270,10 +289,10 @@ int __init omap3_twl_init(void)
270 return -ENODEV; 289 return -ENODEV;
271 290
272 if (cpu_is_omap3630()) { 291 if (cpu_is_omap3630()) {
273 omap3_mpu_volt_info.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN; 292 omap3_mpu_pmic.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN;
274 omap3_mpu_volt_info.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX; 293 omap3_mpu_pmic.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX;
275 omap3_core_volt_info.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN; 294 omap3_core_pmic.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN;
276 omap3_core_volt_info.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX; 295 omap3_core_pmic.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
277 } 296 }
278 297
279 /* 298 /*
@@ -288,11 +307,11 @@ int __init omap3_twl_init(void)
288 if (!twl_sr_enable_autoinit) 307 if (!twl_sr_enable_autoinit)
289 omap3_twl_set_sr_bit(true); 308 omap3_twl_set_sr_bit(true);
290 309
291 voltdm = omap_voltage_domain_lookup("mpu"); 310 voltdm = voltdm_lookup("mpu_iva");
292 omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info); 311 omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic);
293 312
294 voltdm = omap_voltage_domain_lookup("core"); 313 voltdm = voltdm_lookup("core");
295 omap_voltage_register_pmic(voltdm, &omap3_core_volt_info); 314 omap_voltage_register_pmic(voltdm, &omap3_core_pmic);
296 315
297 return 0; 316 return 0;
298} 317}
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 472bf22d5e84..d34fc5206b4a 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -181,7 +181,7 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
181 goto exit; 181 goto exit;
182 } 182 }
183 183
184 voltdm = omap_voltage_domain_lookup(vdd_name); 184 voltdm = voltdm_lookup(vdd_name);
185 if (IS_ERR(voltdm)) { 185 if (IS_ERR(voltdm)) {
186 printk(KERN_ERR "%s: Unable to get vdd pointer for vdd_%s\n", 186 printk(KERN_ERR "%s: Unable to get vdd pointer for vdd_%s\n",
187 __func__, vdd_name); 187 __func__, vdd_name);
@@ -212,7 +212,7 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
212 goto exit; 212 goto exit;
213 } 213 }
214 214
215 omap_voltage_scale_vdd(voltdm, bootup_volt); 215 voltdm_scale(voltdm, bootup_volt);
216 return 0; 216 return 0;
217 217
218exit: 218exit:
@@ -226,7 +226,7 @@ static void __init omap3_init_voltages(void)
226 if (!cpu_is_omap34xx()) 226 if (!cpu_is_omap34xx())
227 return; 227 return;
228 228
229 omap2_set_init_voltage("mpu", "dpll1_ck", mpu_dev); 229 omap2_set_init_voltage("mpu_iva", "dpll1_ck", mpu_dev);
230 omap2_set_init_voltage("core", "l3_ick", l3_dev); 230 omap2_set_init_voltage("core", "l3_ick", l3_dev);
231} 231}
232 232
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 896cb4c5eb1a..5164d587ef52 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -77,6 +77,7 @@ static struct powerdomain *_pwrdm_lookup(const char *name)
77static int _pwrdm_register(struct powerdomain *pwrdm) 77static int _pwrdm_register(struct powerdomain *pwrdm)
78{ 78{
79 int i; 79 int i;
80 struct voltagedomain *voltdm;
80 81
81 if (!pwrdm || !pwrdm->name) 82 if (!pwrdm || !pwrdm->name)
82 return -EINVAL; 83 return -EINVAL;
@@ -91,6 +92,16 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
91 if (_pwrdm_lookup(pwrdm->name)) 92 if (_pwrdm_lookup(pwrdm->name))
92 return -EEXIST; 93 return -EEXIST;
93 94
95 voltdm = voltdm_lookup(pwrdm->voltdm.name);
96 if (!voltdm) {
97 pr_err("powerdomain: %s: voltagedomain %s does not exist\n",
98 pwrdm->name, pwrdm->voltdm.name);
99 return -EINVAL;
100 }
101 pwrdm->voltdm.ptr = voltdm;
102 INIT_LIST_HEAD(&pwrdm->voltdm_node);
103 voltdm_add_pwrdm(voltdm, pwrdm);
104
94 list_add(&pwrdm->node, &pwrdm_list); 105 list_add(&pwrdm->node, &pwrdm_list);
95 106
96 /* Initialize the powerdomain's state counter */ 107 /* Initialize the powerdomain's state counter */
@@ -427,6 +438,18 @@ int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
427} 438}
428 439
429/** 440/**
441 * pwrdm_get_voltdm - return a ptr to the voltdm that this pwrdm resides in
442 * @pwrdm: struct powerdomain *
443 *
444 * Return a pointer to the struct voltageomain that the specified powerdomain
445 * @pwrdm exists in.
446 */
447struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm)
448{
449 return pwrdm->voltdm.ptr;
450}
451
452/**
430 * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain 453 * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
431 * @pwrdm: struct powerdomain * 454 * @pwrdm: struct powerdomain *
432 * 455 *
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index 8febd84e5e31..42e6dd8f2a78 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -24,6 +24,8 @@
24 24
25#include <plat/cpu.h> 25#include <plat/cpu.h>
26 26
27#include "voltage.h"
28
27/* Powerdomain basic power states */ 29/* Powerdomain basic power states */
28#define PWRDM_POWER_OFF 0x0 30#define PWRDM_POWER_OFF 0x0
29#define PWRDM_POWER_RET 0x1 31#define PWRDM_POWER_RET 0x1
@@ -78,6 +80,7 @@ struct powerdomain;
78/** 80/**
79 * struct powerdomain - OMAP powerdomain 81 * struct powerdomain - OMAP powerdomain
80 * @name: Powerdomain name 82 * @name: Powerdomain name
83 * @voltdm: voltagedomain containing this powerdomain
81 * @prcm_offs: the address offset from CM_BASE/PRM_BASE 84 * @prcm_offs: the address offset from CM_BASE/PRM_BASE
82 * @prcm_partition: (OMAP4 only) the PRCM partition ID containing @prcm_offs 85 * @prcm_partition: (OMAP4 only) the PRCM partition ID containing @prcm_offs
83 * @pwrsts: Possible powerdomain power states 86 * @pwrsts: Possible powerdomain power states
@@ -88,6 +91,7 @@ struct powerdomain;
88 * @pwrsts_mem_on: Possible memory bank pwrstates when pwrdm in ON 91 * @pwrsts_mem_on: Possible memory bank pwrstates when pwrdm in ON
89 * @pwrdm_clkdms: Clockdomains in this powerdomain 92 * @pwrdm_clkdms: Clockdomains in this powerdomain
90 * @node: list_head linking all powerdomains 93 * @node: list_head linking all powerdomains
94 * @voltdm_node: list_head linking all powerdomains in a voltagedomain
91 * @state: 95 * @state:
92 * @state_counter: 96 * @state_counter:
93 * @timer: 97 * @timer:
@@ -97,6 +101,10 @@ struct powerdomain;
97 */ 101 */
98struct powerdomain { 102struct powerdomain {
99 const char *name; 103 const char *name;
104 union {
105 const char *name;
106 struct voltagedomain *ptr;
107 } voltdm;
100 const s16 prcm_offs; 108 const s16 prcm_offs;
101 const u8 pwrsts; 109 const u8 pwrsts;
102 const u8 pwrsts_logic_ret; 110 const u8 pwrsts_logic_ret;
@@ -107,6 +115,7 @@ struct powerdomain {
107 const u8 prcm_partition; 115 const u8 prcm_partition;
108 struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS]; 116 struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
109 struct list_head node; 117 struct list_head node;
118 struct list_head voltdm_node;
110 int state; 119 int state;
111 unsigned state_counter[PWRDM_MAX_PWRSTS]; 120 unsigned state_counter[PWRDM_MAX_PWRSTS];
112 unsigned ret_logic_off_counter; 121 unsigned ret_logic_off_counter;
@@ -176,6 +185,7 @@ int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
176int pwrdm_for_each_clkdm(struct powerdomain *pwrdm, 185int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
177 int (*fn)(struct powerdomain *pwrdm, 186 int (*fn)(struct powerdomain *pwrdm,
178 struct clockdomain *clkdm)); 187 struct clockdomain *clkdm));
188struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
179 189
180int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm); 190int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
181 191
diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
index cf600e22bf8e..6a17e4ca1d79 100644
--- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * OMAP2 and OMAP3 powerdomain control 2 * OMAP2 and OMAP3 powerdomain control
3 * 3 *
4 * Copyright (C) 2009-2010 Texas Instruments, Inc. 4 * Copyright (C) 2009-2011 Texas Instruments, Inc.
5 * Copyright (C) 2007-2009 Nokia Corporation 5 * Copyright (C) 2007-2009 Nokia Corporation
6 * 6 *
7 * Derived from mach-omap2/powerdomain.c written by Paul Walmsley 7 * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
diff --git a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
index bf30483d5cb0..d3a5399091ad 100644
--- a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
@@ -54,10 +54,12 @@ struct powerdomain gfx_omap2_pwrdm = {
54 .pwrsts_mem_on = { 54 .pwrsts_mem_on = {
55 [0] = PWRSTS_ON, /* MEMONSTATE */ 55 [0] = PWRSTS_ON, /* MEMONSTATE */
56 }, 56 },
57 .voltdm = { .name = "core" },
57}; 58};
58 59
59struct powerdomain wkup_omap2_pwrdm = { 60struct powerdomain wkup_omap2_pwrdm = {
60 .name = "wkup_pwrdm", 61 .name = "wkup_pwrdm",
61 .prcm_offs = WKUP_MOD, 62 .prcm_offs = WKUP_MOD,
62 .pwrsts = PWRSTS_ON, 63 .pwrsts = PWRSTS_ON,
64 .voltdm = { .name = "wakeup" },
63}; 65};
diff --git a/arch/arm/mach-omap2/powerdomains2xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_data.c
index bb4394e3b621..2385c1f009ee 100644
--- a/arch/arm/mach-omap2/powerdomains2xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains2xxx_data.c
@@ -37,6 +37,7 @@ static struct powerdomain dsp_pwrdm = {
37 .pwrsts_mem_on = { 37 .pwrsts_mem_on = {
38 [0] = PWRSTS_ON, 38 [0] = PWRSTS_ON,
39 }, 39 },
40 .voltdm = { .name = "core" },
40}; 41};
41 42
42static struct powerdomain mpu_24xx_pwrdm = { 43static struct powerdomain mpu_24xx_pwrdm = {
@@ -51,6 +52,7 @@ static struct powerdomain mpu_24xx_pwrdm = {
51 .pwrsts_mem_on = { 52 .pwrsts_mem_on = {
52 [0] = PWRSTS_ON, 53 [0] = PWRSTS_ON,
53 }, 54 },
55 .voltdm = { .name = "core" },
54}; 56};
55 57
56static struct powerdomain core_24xx_pwrdm = { 58static struct powerdomain core_24xx_pwrdm = {
@@ -68,6 +70,7 @@ static struct powerdomain core_24xx_pwrdm = {
68 [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */ 70 [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
69 [2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */ 71 [2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */
70 }, 72 },
73 .voltdm = { .name = "core" },
71}; 74};
72 75
73 76
@@ -89,6 +92,7 @@ static struct powerdomain mdm_pwrdm = {
89 .pwrsts_mem_on = { 92 .pwrsts_mem_on = {
90 [0] = PWRSTS_ON, /* MEMONSTATE */ 93 [0] = PWRSTS_ON, /* MEMONSTATE */
91 }, 94 },
95 .voltdm = { .name = "core" },
92}; 96};
93 97
94/* 98/*
diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c
index e4f3a7d6ecfc..8ef26daeed68 100644
--- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
@@ -51,6 +51,7 @@ static struct powerdomain iva2_pwrdm = {
51 [2] = PWRSTS_OFF_ON, 51 [2] = PWRSTS_OFF_ON,
52 [3] = PWRSTS_ON, 52 [3] = PWRSTS_ON,
53 }, 53 },
54 .voltdm = { .name = "mpu_iva" },
54}; 55};
55 56
56static struct powerdomain mpu_3xxx_pwrdm = { 57static struct powerdomain mpu_3xxx_pwrdm = {
@@ -66,6 +67,7 @@ static struct powerdomain mpu_3xxx_pwrdm = {
66 .pwrsts_mem_on = { 67 .pwrsts_mem_on = {
67 [0] = PWRSTS_OFF_ON, 68 [0] = PWRSTS_OFF_ON,
68 }, 69 },
70 .voltdm = { .name = "mpu_iva" },
69}; 71};
70 72
71/* 73/*
@@ -92,6 +94,7 @@ static struct powerdomain core_3xxx_pre_es3_1_pwrdm = {
92 [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */ 94 [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
93 [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */ 95 [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
94 }, 96 },
97 .voltdm = { .name = "core" },
95}; 98};
96 99
97static struct powerdomain core_3xxx_es3_1_pwrdm = { 100static struct powerdomain core_3xxx_es3_1_pwrdm = {
@@ -113,6 +116,7 @@ static struct powerdomain core_3xxx_es3_1_pwrdm = {
113 [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */ 116 [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
114 [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */ 117 [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
115 }, 118 },
119 .voltdm = { .name = "core" },
116}; 120};
117 121
118static struct powerdomain dss_pwrdm = { 122static struct powerdomain dss_pwrdm = {
@@ -127,6 +131,7 @@ static struct powerdomain dss_pwrdm = {
127 .pwrsts_mem_on = { 131 .pwrsts_mem_on = {
128 [0] = PWRSTS_ON, /* MEMONSTATE */ 132 [0] = PWRSTS_ON, /* MEMONSTATE */
129 }, 133 },
134 .voltdm = { .name = "core" },
130}; 135};
131 136
132/* 137/*
@@ -147,6 +152,7 @@ static struct powerdomain sgx_pwrdm = {
147 .pwrsts_mem_on = { 152 .pwrsts_mem_on = {
148 [0] = PWRSTS_ON, /* MEMONSTATE */ 153 [0] = PWRSTS_ON, /* MEMONSTATE */
149 }, 154 },
155 .voltdm = { .name = "core" },
150}; 156};
151 157
152static struct powerdomain cam_pwrdm = { 158static struct powerdomain cam_pwrdm = {
@@ -161,6 +167,7 @@ static struct powerdomain cam_pwrdm = {
161 .pwrsts_mem_on = { 167 .pwrsts_mem_on = {
162 [0] = PWRSTS_ON, /* MEMONSTATE */ 168 [0] = PWRSTS_ON, /* MEMONSTATE */
163 }, 169 },
170 .voltdm = { .name = "core" },
164}; 171};
165 172
166static struct powerdomain per_pwrdm = { 173static struct powerdomain per_pwrdm = {
@@ -175,11 +182,13 @@ static struct powerdomain per_pwrdm = {
175 .pwrsts_mem_on = { 182 .pwrsts_mem_on = {
176 [0] = PWRSTS_ON, /* MEMONSTATE */ 183 [0] = PWRSTS_ON, /* MEMONSTATE */
177 }, 184 },
185 .voltdm = { .name = "core" },
178}; 186};
179 187
180static struct powerdomain emu_pwrdm = { 188static struct powerdomain emu_pwrdm = {
181 .name = "emu_pwrdm", 189 .name = "emu_pwrdm",
182 .prcm_offs = OMAP3430_EMU_MOD, 190 .prcm_offs = OMAP3430_EMU_MOD,
191 .voltdm = { .name = "core" },
183}; 192};
184 193
185static struct powerdomain neon_pwrdm = { 194static struct powerdomain neon_pwrdm = {
@@ -187,6 +196,7 @@ static struct powerdomain neon_pwrdm = {
187 .prcm_offs = OMAP3430_NEON_MOD, 196 .prcm_offs = OMAP3430_NEON_MOD,
188 .pwrsts = PWRSTS_OFF_RET_ON, 197 .pwrsts = PWRSTS_OFF_RET_ON,
189 .pwrsts_logic_ret = PWRSTS_RET, 198 .pwrsts_logic_ret = PWRSTS_RET,
199 .voltdm = { .name = "mpu_iva" },
190}; 200};
191 201
192static struct powerdomain usbhost_pwrdm = { 202static struct powerdomain usbhost_pwrdm = {
@@ -208,31 +218,37 @@ static struct powerdomain usbhost_pwrdm = {
208 .pwrsts_mem_on = { 218 .pwrsts_mem_on = {
209 [0] = PWRSTS_ON, /* MEMONSTATE */ 219 [0] = PWRSTS_ON, /* MEMONSTATE */
210 }, 220 },
221 .voltdm = { .name = "core" },
211}; 222};
212 223
213static struct powerdomain dpll1_pwrdm = { 224static struct powerdomain dpll1_pwrdm = {
214 .name = "dpll1_pwrdm", 225 .name = "dpll1_pwrdm",
215 .prcm_offs = MPU_MOD, 226 .prcm_offs = MPU_MOD,
227 .voltdm = { .name = "mpu_iva" },
216}; 228};
217 229
218static struct powerdomain dpll2_pwrdm = { 230static struct powerdomain dpll2_pwrdm = {
219 .name = "dpll2_pwrdm", 231 .name = "dpll2_pwrdm",
220 .prcm_offs = OMAP3430_IVA2_MOD, 232 .prcm_offs = OMAP3430_IVA2_MOD,
233 .voltdm = { .name = "mpu_iva" },
221}; 234};
222 235
223static struct powerdomain dpll3_pwrdm = { 236static struct powerdomain dpll3_pwrdm = {
224 .name = "dpll3_pwrdm", 237 .name = "dpll3_pwrdm",
225 .prcm_offs = PLL_MOD, 238 .prcm_offs = PLL_MOD,
239 .voltdm = { .name = "core" },
226}; 240};
227 241
228static struct powerdomain dpll4_pwrdm = { 242static struct powerdomain dpll4_pwrdm = {
229 .name = "dpll4_pwrdm", 243 .name = "dpll4_pwrdm",
230 .prcm_offs = PLL_MOD, 244 .prcm_offs = PLL_MOD,
245 .voltdm = { .name = "core" },
231}; 246};
232 247
233static struct powerdomain dpll5_pwrdm = { 248static struct powerdomain dpll5_pwrdm = {
234 .name = "dpll5_pwrdm", 249 .name = "dpll5_pwrdm",
235 .prcm_offs = PLL_MOD, 250 .prcm_offs = PLL_MOD,
251 .voltdm = { .name = "core" },
236}; 252};
237 253
238/* As powerdomains are added or removed above, this list must also be changed */ 254/* As powerdomains are added or removed above, this list must also be changed */
diff --git a/arch/arm/mach-omap2/powerdomains44xx_data.c b/arch/arm/mach-omap2/powerdomains44xx_data.c
index cbce0c9069cd..704664c0e259 100644
--- a/arch/arm/mach-omap2/powerdomains44xx_data.c
+++ b/arch/arm/mach-omap2/powerdomains44xx_data.c
@@ -33,6 +33,7 @@
33/* core_44xx_pwrdm: CORE power domain */ 33/* core_44xx_pwrdm: CORE power domain */
34static struct powerdomain core_44xx_pwrdm = { 34static struct powerdomain core_44xx_pwrdm = {
35 .name = "core_pwrdm", 35 .name = "core_pwrdm",
36 .voltdm = { .name = "core" },
36 .prcm_offs = OMAP4430_PRM_CORE_INST, 37 .prcm_offs = OMAP4430_PRM_CORE_INST,
37 .prcm_partition = OMAP4430_PRM_PARTITION, 38 .prcm_partition = OMAP4430_PRM_PARTITION,
38 .pwrsts = PWRSTS_RET_ON, 39 .pwrsts = PWRSTS_RET_ON,
@@ -58,6 +59,7 @@ static struct powerdomain core_44xx_pwrdm = {
58/* gfx_44xx_pwrdm: 3D accelerator power domain */ 59/* gfx_44xx_pwrdm: 3D accelerator power domain */
59static struct powerdomain gfx_44xx_pwrdm = { 60static struct powerdomain gfx_44xx_pwrdm = {
60 .name = "gfx_pwrdm", 61 .name = "gfx_pwrdm",
62 .voltdm = { .name = "core" },
61 .prcm_offs = OMAP4430_PRM_GFX_INST, 63 .prcm_offs = OMAP4430_PRM_GFX_INST,
62 .prcm_partition = OMAP4430_PRM_PARTITION, 64 .prcm_partition = OMAP4430_PRM_PARTITION,
63 .pwrsts = PWRSTS_OFF_ON, 65 .pwrsts = PWRSTS_OFF_ON,
@@ -74,6 +76,7 @@ static struct powerdomain gfx_44xx_pwrdm = {
74/* abe_44xx_pwrdm: Audio back end power domain */ 76/* abe_44xx_pwrdm: Audio back end power domain */
75static struct powerdomain abe_44xx_pwrdm = { 77static struct powerdomain abe_44xx_pwrdm = {
76 .name = "abe_pwrdm", 78 .name = "abe_pwrdm",
79 .voltdm = { .name = "iva" },
77 .prcm_offs = OMAP4430_PRM_ABE_INST, 80 .prcm_offs = OMAP4430_PRM_ABE_INST,
78 .prcm_partition = OMAP4430_PRM_PARTITION, 81 .prcm_partition = OMAP4430_PRM_PARTITION,
79 .pwrsts = PWRSTS_OFF_RET_ON, 82 .pwrsts = PWRSTS_OFF_RET_ON,
@@ -93,6 +96,7 @@ static struct powerdomain abe_44xx_pwrdm = {
93/* dss_44xx_pwrdm: Display subsystem power domain */ 96/* dss_44xx_pwrdm: Display subsystem power domain */
94static struct powerdomain dss_44xx_pwrdm = { 97static struct powerdomain dss_44xx_pwrdm = {
95 .name = "dss_pwrdm", 98 .name = "dss_pwrdm",
99 .voltdm = { .name = "core" },
96 .prcm_offs = OMAP4430_PRM_DSS_INST, 100 .prcm_offs = OMAP4430_PRM_DSS_INST,
97 .prcm_partition = OMAP4430_PRM_PARTITION, 101 .prcm_partition = OMAP4430_PRM_PARTITION,
98 .pwrsts = PWRSTS_OFF_RET_ON, 102 .pwrsts = PWRSTS_OFF_RET_ON,
@@ -110,6 +114,7 @@ static struct powerdomain dss_44xx_pwrdm = {
110/* tesla_44xx_pwrdm: Tesla processor power domain */ 114/* tesla_44xx_pwrdm: Tesla processor power domain */
111static struct powerdomain tesla_44xx_pwrdm = { 115static struct powerdomain tesla_44xx_pwrdm = {
112 .name = "tesla_pwrdm", 116 .name = "tesla_pwrdm",
117 .voltdm = { .name = "iva" },
113 .prcm_offs = OMAP4430_PRM_TESLA_INST, 118 .prcm_offs = OMAP4430_PRM_TESLA_INST,
114 .prcm_partition = OMAP4430_PRM_PARTITION, 119 .prcm_partition = OMAP4430_PRM_PARTITION,
115 .pwrsts = PWRSTS_OFF_RET_ON, 120 .pwrsts = PWRSTS_OFF_RET_ON,
@@ -131,6 +136,7 @@ static struct powerdomain tesla_44xx_pwrdm = {
131/* wkup_44xx_pwrdm: Wake-up power domain */ 136/* wkup_44xx_pwrdm: Wake-up power domain */
132static struct powerdomain wkup_44xx_pwrdm = { 137static struct powerdomain wkup_44xx_pwrdm = {
133 .name = "wkup_pwrdm", 138 .name = "wkup_pwrdm",
139 .voltdm = { .name = "wakeup" },
134 .prcm_offs = OMAP4430_PRM_WKUP_INST, 140 .prcm_offs = OMAP4430_PRM_WKUP_INST,
135 .prcm_partition = OMAP4430_PRM_PARTITION, 141 .prcm_partition = OMAP4430_PRM_PARTITION,
136 .pwrsts = PWRSTS_ON, 142 .pwrsts = PWRSTS_ON,
@@ -146,6 +152,7 @@ static struct powerdomain wkup_44xx_pwrdm = {
146/* cpu0_44xx_pwrdm: MPU0 processor and Neon coprocessor power domain */ 152/* cpu0_44xx_pwrdm: MPU0 processor and Neon coprocessor power domain */
147static struct powerdomain cpu0_44xx_pwrdm = { 153static struct powerdomain cpu0_44xx_pwrdm = {
148 .name = "cpu0_pwrdm", 154 .name = "cpu0_pwrdm",
155 .voltdm = { .name = "mpu" },
149 .prcm_offs = OMAP4430_PRCM_MPU_CPU0_INST, 156 .prcm_offs = OMAP4430_PRCM_MPU_CPU0_INST,
150 .prcm_partition = OMAP4430_PRCM_MPU_PARTITION, 157 .prcm_partition = OMAP4430_PRCM_MPU_PARTITION,
151 .pwrsts = PWRSTS_OFF_RET_ON, 158 .pwrsts = PWRSTS_OFF_RET_ON,
@@ -162,6 +169,7 @@ static struct powerdomain cpu0_44xx_pwrdm = {
162/* cpu1_44xx_pwrdm: MPU1 processor and Neon coprocessor power domain */ 169/* cpu1_44xx_pwrdm: MPU1 processor and Neon coprocessor power domain */
163static struct powerdomain cpu1_44xx_pwrdm = { 170static struct powerdomain cpu1_44xx_pwrdm = {
164 .name = "cpu1_pwrdm", 171 .name = "cpu1_pwrdm",
172 .voltdm = { .name = "mpu" },
165 .prcm_offs = OMAP4430_PRCM_MPU_CPU1_INST, 173 .prcm_offs = OMAP4430_PRCM_MPU_CPU1_INST,
166 .prcm_partition = OMAP4430_PRCM_MPU_PARTITION, 174 .prcm_partition = OMAP4430_PRCM_MPU_PARTITION,
167 .pwrsts = PWRSTS_OFF_RET_ON, 175 .pwrsts = PWRSTS_OFF_RET_ON,
@@ -178,6 +186,7 @@ static struct powerdomain cpu1_44xx_pwrdm = {
178/* emu_44xx_pwrdm: Emulation power domain */ 186/* emu_44xx_pwrdm: Emulation power domain */
179static struct powerdomain emu_44xx_pwrdm = { 187static struct powerdomain emu_44xx_pwrdm = {
180 .name = "emu_pwrdm", 188 .name = "emu_pwrdm",
189 .voltdm = { .name = "wakeup" },
181 .prcm_offs = OMAP4430_PRM_EMU_INST, 190 .prcm_offs = OMAP4430_PRM_EMU_INST,
182 .prcm_partition = OMAP4430_PRM_PARTITION, 191 .prcm_partition = OMAP4430_PRM_PARTITION,
183 .pwrsts = PWRSTS_OFF_ON, 192 .pwrsts = PWRSTS_OFF_ON,
@@ -193,6 +202,7 @@ static struct powerdomain emu_44xx_pwrdm = {
193/* mpu_44xx_pwrdm: Modena processor and the Neon coprocessor power domain */ 202/* mpu_44xx_pwrdm: Modena processor and the Neon coprocessor power domain */
194static struct powerdomain mpu_44xx_pwrdm = { 203static struct powerdomain mpu_44xx_pwrdm = {
195 .name = "mpu_pwrdm", 204 .name = "mpu_pwrdm",
205 .voltdm = { .name = "mpu" },
196 .prcm_offs = OMAP4430_PRM_MPU_INST, 206 .prcm_offs = OMAP4430_PRM_MPU_INST,
197 .prcm_partition = OMAP4430_PRM_PARTITION, 207 .prcm_partition = OMAP4430_PRM_PARTITION,
198 .pwrsts = PWRSTS_RET_ON, 208 .pwrsts = PWRSTS_RET_ON,
@@ -213,6 +223,7 @@ static struct powerdomain mpu_44xx_pwrdm = {
213/* ivahd_44xx_pwrdm: IVA-HD power domain */ 223/* ivahd_44xx_pwrdm: IVA-HD power domain */
214static struct powerdomain ivahd_44xx_pwrdm = { 224static struct powerdomain ivahd_44xx_pwrdm = {
215 .name = "ivahd_pwrdm", 225 .name = "ivahd_pwrdm",
226 .voltdm = { .name = "iva" },
216 .prcm_offs = OMAP4430_PRM_IVAHD_INST, 227 .prcm_offs = OMAP4430_PRM_IVAHD_INST,
217 .prcm_partition = OMAP4430_PRM_PARTITION, 228 .prcm_partition = OMAP4430_PRM_PARTITION,
218 .pwrsts = PWRSTS_OFF_RET_ON, 229 .pwrsts = PWRSTS_OFF_RET_ON,
@@ -236,6 +247,7 @@ static struct powerdomain ivahd_44xx_pwrdm = {
236/* cam_44xx_pwrdm: Camera subsystem power domain */ 247/* cam_44xx_pwrdm: Camera subsystem power domain */
237static struct powerdomain cam_44xx_pwrdm = { 248static struct powerdomain cam_44xx_pwrdm = {
238 .name = "cam_pwrdm", 249 .name = "cam_pwrdm",
250 .voltdm = { .name = "core" },
239 .prcm_offs = OMAP4430_PRM_CAM_INST, 251 .prcm_offs = OMAP4430_PRM_CAM_INST,
240 .prcm_partition = OMAP4430_PRM_PARTITION, 252 .prcm_partition = OMAP4430_PRM_PARTITION,
241 .pwrsts = PWRSTS_OFF_ON, 253 .pwrsts = PWRSTS_OFF_ON,
@@ -252,6 +264,7 @@ static struct powerdomain cam_44xx_pwrdm = {
252/* l3init_44xx_pwrdm: L3 initators pheripherals power domain */ 264/* l3init_44xx_pwrdm: L3 initators pheripherals power domain */
253static struct powerdomain l3init_44xx_pwrdm = { 265static struct powerdomain l3init_44xx_pwrdm = {
254 .name = "l3init_pwrdm", 266 .name = "l3init_pwrdm",
267 .voltdm = { .name = "core" },
255 .prcm_offs = OMAP4430_PRM_L3INIT_INST, 268 .prcm_offs = OMAP4430_PRM_L3INIT_INST,
256 .prcm_partition = OMAP4430_PRM_PARTITION, 269 .prcm_partition = OMAP4430_PRM_PARTITION,
257 .pwrsts = PWRSTS_RET_ON, 270 .pwrsts = PWRSTS_RET_ON,
@@ -269,6 +282,7 @@ static struct powerdomain l3init_44xx_pwrdm = {
269/* l4per_44xx_pwrdm: Target peripherals power domain */ 282/* l4per_44xx_pwrdm: Target peripherals power domain */
270static struct powerdomain l4per_44xx_pwrdm = { 283static struct powerdomain l4per_44xx_pwrdm = {
271 .name = "l4per_pwrdm", 284 .name = "l4per_pwrdm",
285 .voltdm = { .name = "core" },
272 .prcm_offs = OMAP4430_PRM_L4PER_INST, 286 .prcm_offs = OMAP4430_PRM_L4PER_INST,
273 .prcm_partition = OMAP4430_PRM_PARTITION, 287 .prcm_partition = OMAP4430_PRM_PARTITION,
274 .pwrsts = PWRSTS_RET_ON, 288 .pwrsts = PWRSTS_RET_ON,
@@ -291,6 +305,7 @@ static struct powerdomain l4per_44xx_pwrdm = {
291 */ 305 */
292static struct powerdomain always_on_core_44xx_pwrdm = { 306static struct powerdomain always_on_core_44xx_pwrdm = {
293 .name = "always_on_core_pwrdm", 307 .name = "always_on_core_pwrdm",
308 .voltdm = { .name = "core" },
294 .prcm_offs = OMAP4430_PRM_ALWAYS_ON_INST, 309 .prcm_offs = OMAP4430_PRM_ALWAYS_ON_INST,
295 .prcm_partition = OMAP4430_PRM_PARTITION, 310 .prcm_partition = OMAP4430_PRM_PARTITION,
296 .pwrsts = PWRSTS_ON, 311 .pwrsts = PWRSTS_ON,
@@ -299,6 +314,7 @@ static struct powerdomain always_on_core_44xx_pwrdm = {
299/* cefuse_44xx_pwrdm: Customer efuse controller power domain */ 314/* cefuse_44xx_pwrdm: Customer efuse controller power domain */
300static struct powerdomain cefuse_44xx_pwrdm = { 315static struct powerdomain cefuse_44xx_pwrdm = {
301 .name = "cefuse_pwrdm", 316 .name = "cefuse_pwrdm",
317 .voltdm = { .name = "core" },
302 .prcm_offs = OMAP4430_PRM_CEFUSE_INST, 318 .prcm_offs = OMAP4430_PRM_CEFUSE_INST,
303 .prcm_partition = OMAP4430_PRM_PARTITION, 319 .prcm_partition = OMAP4430_PRM_PARTITION,
304 .pwrsts = PWRSTS_OFF_ON, 320 .pwrsts = PWRSTS_OFF_ON,
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c
index 051213fbc346..f02d87f68e54 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c
@@ -20,6 +20,8 @@
20#include <plat/cpu.h> 20#include <plat/cpu.h>
21#include <plat/prcm.h> 21#include <plat/prcm.h>
22 22
23#include "vp.h"
24
23#include "prm2xxx_3xxx.h" 25#include "prm2xxx_3xxx.h"
24#include "cm2xxx_3xxx.h" 26#include "cm2xxx_3xxx.h"
25#include "prm-regbits-24xx.h" 27#include "prm-regbits-24xx.h"
@@ -156,3 +158,57 @@ int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift)
156 158
157 return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0; 159 return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
158} 160}
161
162/* PRM VP */
163
164/*
165 * struct omap3_vp - OMAP3 VP register access description.
166 * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
167 */
168struct omap3_vp {
169 u32 tranxdone_status;
170};
171
172static struct omap3_vp omap3_vp[] = {
173 [OMAP3_VP_VDD_MPU_ID] = {
174 .tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
175 },
176 [OMAP3_VP_VDD_CORE_ID] = {
177 .tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
178 },
179};
180
181#define MAX_VP_ID ARRAY_SIZE(omap3_vp);
182
183u32 omap3_prm_vp_check_txdone(u8 vp_id)
184{
185 struct omap3_vp *vp = &omap3_vp[vp_id];
186 u32 irqstatus;
187
188 irqstatus = omap2_prm_read_mod_reg(OCP_MOD,
189 OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
190 return irqstatus & vp->tranxdone_status;
191}
192
193void omap3_prm_vp_clear_txdone(u8 vp_id)
194{
195 struct omap3_vp *vp = &omap3_vp[vp_id];
196
197 omap2_prm_write_mod_reg(vp->tranxdone_status,
198 OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
199}
200
201u32 omap3_prm_vcvp_read(u8 offset)
202{
203 return omap2_prm_read_mod_reg(OMAP3430_GR_MOD, offset);
204}
205
206void omap3_prm_vcvp_write(u32 val, u8 offset)
207{
208 omap2_prm_write_mod_reg(val, OMAP3430_GR_MOD, offset);
209}
210
211u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
212{
213 return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset);
214}
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h
index a1fc62a39dbb..cef533df0861 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.h
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h
@@ -303,7 +303,19 @@ extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
303extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift); 303extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
304extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift); 304extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift);
305 305
306/* OMAP3-specific VP functions */
307u32 omap3_prm_vp_check_txdone(u8 vp_id);
308void omap3_prm_vp_clear_txdone(u8 vp_id);
309
310/*
311 * OMAP3 access functions for voltage controller (VC) and
312 * voltage proccessor (VP) in the PRM.
313 */
314extern u32 omap3_prm_vcvp_read(u8 offset);
315extern void omap3_prm_vcvp_write(u32 val, u8 offset);
316extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
306#endif /* CONFIG_ARCH_OMAP4 */ 317#endif /* CONFIG_ARCH_OMAP4 */
318
307#endif 319#endif
308 320
309/* 321/*
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index 00165558fc4d..495a31a7e8a7 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -21,8 +21,11 @@
21#include <plat/cpu.h> 21#include <plat/cpu.h>
22#include <plat/prcm.h> 22#include <plat/prcm.h>
23 23
24#include "vp.h"
24#include "prm44xx.h" 25#include "prm44xx.h"
25#include "prm-regbits-44xx.h" 26#include "prm-regbits-44xx.h"
27#include "prcm44xx.h"
28#include "prminst44xx.h"
26 29
27/* PRM low-level functions */ 30/* PRM low-level functions */
28 31
@@ -50,3 +53,71 @@ u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
50 53
51 return v; 54 return v;
52} 55}
56
57/* PRM VP */
58
59/*
60 * struct omap4_vp - OMAP4 VP register access description.
61 * @irqstatus_mpu: offset to IRQSTATUS_MPU register for VP
62 * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
63 */
64struct omap4_vp {
65 u32 irqstatus_mpu;
66 u32 tranxdone_status;
67};
68
69static struct omap4_vp omap4_vp[] = {
70 [OMAP4_VP_VDD_MPU_ID] = {
71 .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
72 .tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
73 },
74 [OMAP4_VP_VDD_IVA_ID] = {
75 .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
76 .tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
77 },
78 [OMAP4_VP_VDD_CORE_ID] = {
79 .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
80 .tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
81 },
82};
83
84u32 omap4_prm_vp_check_txdone(u8 vp_id)
85{
86 struct omap4_vp *vp = &omap4_vp[vp_id];
87 u32 irqstatus;
88
89 irqstatus = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
90 OMAP4430_PRM_OCP_SOCKET_INST,
91 vp->irqstatus_mpu);
92 return irqstatus & vp->tranxdone_status;
93}
94
95void omap4_prm_vp_clear_txdone(u8 vp_id)
96{
97 struct omap4_vp *vp = &omap4_vp[vp_id];
98
99 omap4_prminst_write_inst_reg(vp->tranxdone_status,
100 OMAP4430_PRM_PARTITION,
101 OMAP4430_PRM_OCP_SOCKET_INST,
102 vp->irqstatus_mpu);
103};
104
105u32 omap4_prm_vcvp_read(u8 offset)
106{
107 return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
108 OMAP4430_PRM_DEVICE_INST, offset);
109}
110
111void omap4_prm_vcvp_write(u32 val, u8 offset)
112{
113 omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION,
114 OMAP4430_PRM_DEVICE_INST, offset);
115}
116
117u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
118{
119 return omap4_prminst_rmw_inst_reg_bits(mask, bits,
120 OMAP4430_PRM_PARTITION,
121 OMAP4430_PRM_DEVICE_INST,
122 offset);
123}
diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h
index 7dfa379b625d..3d66ccd849d2 100644
--- a/arch/arm/mach-omap2/prm44xx.h
+++ b/arch/arm/mach-omap2/prm44xx.h
@@ -751,6 +751,18 @@ extern u32 omap4_prm_read_inst_reg(s16 inst, u16 idx);
751extern void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 idx); 751extern void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 idx);
752extern u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx); 752extern u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
753 753
754/* OMAP4-specific VP functions */
755u32 omap4_prm_vp_check_txdone(u8 vp_id);
756void omap4_prm_vp_clear_txdone(u8 vp_id);
757
758/*
759 * OMAP4 access functions for voltage controller (VC) and
760 * voltage proccessor (VP) in the PRM.
761 */
762extern u32 omap4_prm_vcvp_read(u8 offset);
763extern void omap4_prm_vcvp_write(u32 val, u8 offset);
764extern u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
765
754# endif 766# endif
755 767
756#endif 768#endif
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index f438cf4d847b..53d9d0a5b39d 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -15,7 +15,7 @@
15 15
16static int sr_class3_enable(struct voltagedomain *voltdm) 16static int sr_class3_enable(struct voltagedomain *voltdm)
17{ 17{
18 unsigned long volt = omap_voltage_get_nom_volt(voltdm); 18 unsigned long volt = voltdm_get_voltage(voltdm);
19 19
20 if (!volt) { 20 if (!volt) {
21 pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n", 21 pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
@@ -32,7 +32,7 @@ static int sr_class3_disable(struct voltagedomain *voltdm, int is_volt_reset)
32 omap_vp_disable(voltdm); 32 omap_vp_disable(voltdm);
33 sr_disable(voltdm); 33 sr_disable(voltdm);
34 if (is_volt_reset) 34 if (is_volt_reset)
35 omap_voltage_reset(voltdm); 35 voltdm_reset(voltdm);
36 36
37 return 0; 37 return 0;
38} 38}
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 34c01a7de810..bb606c9709b2 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -62,6 +62,7 @@ static LIST_HEAD(sr_list);
62 62
63static struct omap_sr_class_data *sr_class; 63static struct omap_sr_class_data *sr_class;
64static struct omap_sr_pmic_data *sr_pmic_data; 64static struct omap_sr_pmic_data *sr_pmic_data;
65static struct dentry *sr_dbg_dir;
65 66
66static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value) 67static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
67{ 68{
@@ -826,9 +827,10 @@ static int __init omap_sr_probe(struct platform_device *pdev)
826 struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL); 827 struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
827 struct omap_sr_data *pdata = pdev->dev.platform_data; 828 struct omap_sr_data *pdata = pdev->dev.platform_data;
828 struct resource *mem, *irq; 829 struct resource *mem, *irq;
829 struct dentry *vdd_dbg_dir, *nvalue_dir; 830 struct dentry *nvalue_dir;
830 struct omap_volt_data *volt_data; 831 struct omap_volt_data *volt_data;
831 int i, ret = 0; 832 int i, ret = 0;
833 char *name;
832 834
833 if (!sr_info) { 835 if (!sr_info) {
834 dev_err(&pdev->dev, "%s: unable to allocate sr_info\n", 836 dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
@@ -899,18 +901,25 @@ static int __init omap_sr_probe(struct platform_device *pdev)
899 } 901 }
900 902
901 dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__); 903 dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
904 if (!sr_dbg_dir) {
905 sr_dbg_dir = debugfs_create_dir("smartreflex", NULL);
906 if (!sr_dbg_dir) {
907 ret = PTR_ERR(sr_dbg_dir);
908 pr_err("%s:sr debugfs dir creation failed(%d)\n",
909 __func__, ret);
910 goto err_iounmap;
911 }
912 }
902 913
903 /* 914 name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
904 * If the voltage domain debugfs directory is not created, do 915 if (!name) {
905 * not try to create rest of the debugfs entries. 916 dev_err(&pdev->dev, "%s: Unable to alloc debugfs name\n",
906 */ 917 __func__);
907 vdd_dbg_dir = omap_voltage_get_dbgdir(sr_info->voltdm); 918 ret = -ENOMEM;
908 if (!vdd_dbg_dir) {
909 ret = -EINVAL;
910 goto err_iounmap; 919 goto err_iounmap;
911 } 920 }
912 921 sr_info->dbg_dir = debugfs_create_dir(name, sr_dbg_dir);
913 sr_info->dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir); 922 kfree(name);
914 if (IS_ERR(sr_info->dbg_dir)) { 923 if (IS_ERR(sr_info->dbg_dir)) {
915 dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n", 924 dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
916 __func__); 925 __func__);
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index 10d3c5ee8018..2782d3f604ca 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -102,7 +102,7 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user)
102 sr_data->senn_mod = 0x1; 102 sr_data->senn_mod = 0x1;
103 sr_data->senp_mod = 0x1; 103 sr_data->senp_mod = 0x1;
104 104
105 sr_data->voltdm = omap_voltage_domain_lookup(oh->vdd_name); 105 sr_data->voltdm = voltdm_lookup(oh->vdd_name);
106 if (IS_ERR(sr_data->voltdm)) { 106 if (IS_ERR(sr_data->voltdm)) {
107 pr_err("%s: Unable to get voltage domain pointer for VDD %s\n", 107 pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
108 __func__, oh->vdd_name); 108 __func__, oh->vdd_name);
diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c
new file mode 100644
index 000000000000..031d116fbf10
--- /dev/null
+++ b/arch/arm/mach-omap2/vc.c
@@ -0,0 +1,367 @@
1/*
2 * OMAP Voltage Controller (VC) interface
3 *
4 * Copyright (C) 2011 Texas Instruments, Inc.
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10#include <linux/kernel.h>
11#include <linux/delay.h>
12#include <linux/init.h>
13
14#include <plat/cpu.h>
15
16#include "voltage.h"
17#include "vc.h"
18#include "prm-regbits-34xx.h"
19#include "prm-regbits-44xx.h"
20#include "prm44xx.h"
21
22/**
23 * struct omap_vc_channel_cfg - describe the cfg_channel bitfield
24 * @sa: bit for slave address
25 * @rav: bit for voltage configuration register
26 * @rac: bit for command configuration register
27 * @racen: enable bit for RAC
28 * @cmd: bit for command value set selection
29 *
30 * Channel configuration bits, common for OMAP3+
31 * OMAP3 register: PRM_VC_CH_CONF
32 * OMAP4 register: PRM_VC_CFG_CHANNEL
33 * OMAP5 register: PRM_VC_SMPS_<voltdm>_CONFIG
34 */
35struct omap_vc_channel_cfg {
36 u8 sa;
37 u8 rav;
38 u8 rac;
39 u8 racen;
40 u8 cmd;
41};
42
43static struct omap_vc_channel_cfg vc_default_channel_cfg = {
44 .sa = BIT(0),
45 .rav = BIT(1),
46 .rac = BIT(2),
47 .racen = BIT(3),
48 .cmd = BIT(4),
49};
50
51/*
52 * On OMAP3+, all VC channels have the above default bitfield
53 * configuration, except the OMAP4 MPU channel. This appears
54 * to be a freak accident as every other VC channel has the
55 * default configuration, thus creating a mutant channel config.
56 */
57static struct omap_vc_channel_cfg vc_mutant_channel_cfg = {
58 .sa = BIT(0),
59 .rav = BIT(2),
60 .rac = BIT(3),
61 .racen = BIT(4),
62 .cmd = BIT(1),
63};
64
65static struct omap_vc_channel_cfg *vc_cfg_bits;
66#define CFG_CHANNEL_MASK 0x1f
67
68/**
69 * omap_vc_config_channel - configure VC channel to PMIC mappings
70 * @voltdm: pointer to voltagdomain defining the desired VC channel
71 *
72 * Configures the VC channel to PMIC mappings for the following
73 * PMIC settings
74 * - i2c slave address (SA)
75 * - voltage configuration address (RAV)
76 * - command configuration address (RAC) and enable bit (RACEN)
77 * - command values for ON, ONLP, RET and OFF (CMD)
78 *
79 * This function currently only allows flexible configuration of the
80 * non-default channel. Starting with OMAP4, there are more than 2
81 * channels, with one defined as the default (on OMAP4, it's MPU.)
82 * Only the non-default channel can be configured.
83 */
84static int omap_vc_config_channel(struct voltagedomain *voltdm)
85{
86 struct omap_vc_channel *vc = voltdm->vc;
87
88 /*
89 * For default channel, the only configurable bit is RACEN.
90 * All others must stay at zero (see function comment above.)
91 */
92 if (vc->flags & OMAP_VC_CHANNEL_DEFAULT)
93 vc->cfg_channel &= vc_cfg_bits->racen;
94
95 voltdm->rmw(CFG_CHANNEL_MASK << vc->cfg_channel_sa_shift,
96 vc->cfg_channel << vc->cfg_channel_sa_shift,
97 vc->cfg_channel_reg);
98
99 return 0;
100}
101
102/* Voltage scale and accessory APIs */
103int omap_vc_pre_scale(struct voltagedomain *voltdm,
104 unsigned long target_volt,
105 u8 *target_vsel, u8 *current_vsel)
106{
107 struct omap_vc_channel *vc = voltdm->vc;
108 u32 vc_cmdval;
109
110 /* Check if sufficient pmic info is available for this vdd */
111 if (!voltdm->pmic) {
112 pr_err("%s: Insufficient pmic info to scale the vdd_%s\n",
113 __func__, voltdm->name);
114 return -EINVAL;
115 }
116
117 if (!voltdm->pmic->uv_to_vsel) {
118 pr_err("%s: PMIC function to convert voltage in uV to"
119 "vsel not registered. Hence unable to scale voltage"
120 "for vdd_%s\n", __func__, voltdm->name);
121 return -ENODATA;
122 }
123
124 if (!voltdm->read || !voltdm->write) {
125 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
126 __func__, voltdm->name);
127 return -EINVAL;
128 }
129
130 *target_vsel = voltdm->pmic->uv_to_vsel(target_volt);
131 *current_vsel = voltdm->pmic->uv_to_vsel(voltdm->nominal_volt);
132
133 /* Setting the ON voltage to the new target voltage */
134 vc_cmdval = voltdm->read(vc->cmdval_reg);
135 vc_cmdval &= ~vc->common->cmd_on_mask;
136 vc_cmdval |= (*target_vsel << vc->common->cmd_on_shift);
137 voltdm->write(vc_cmdval, vc->cmdval_reg);
138
139 omap_vp_update_errorgain(voltdm, target_volt);
140
141 return 0;
142}
143
144void omap_vc_post_scale(struct voltagedomain *voltdm,
145 unsigned long target_volt,
146 u8 target_vsel, u8 current_vsel)
147{
148 u32 smps_steps = 0, smps_delay = 0;
149
150 smps_steps = abs(target_vsel - current_vsel);
151 /* SMPS slew rate / step size. 2us added as buffer. */
152 smps_delay = ((smps_steps * voltdm->pmic->step_size) /
153 voltdm->pmic->slew_rate) + 2;
154 udelay(smps_delay);
155}
156
157/* vc_bypass_scale - VC bypass method of voltage scaling */
158int omap_vc_bypass_scale(struct voltagedomain *voltdm,
159 unsigned long target_volt)
160{
161 struct omap_vc_channel *vc = voltdm->vc;
162 u32 loop_cnt = 0, retries_cnt = 0;
163 u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
164 u8 target_vsel, current_vsel;
165 int ret;
166
167 ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
168 if (ret)
169 return ret;
170
171 vc_valid = vc->common->valid;
172 vc_bypass_val_reg = vc->common->bypass_val_reg;
173 vc_bypass_value = (target_vsel << vc->common->data_shift) |
174 (vc->volt_reg_addr << vc->common->regaddr_shift) |
175 (vc->i2c_slave_addr << vc->common->slaveaddr_shift);
176
177 voltdm->write(vc_bypass_value, vc_bypass_val_reg);
178 voltdm->write(vc_bypass_value | vc_valid, vc_bypass_val_reg);
179
180 vc_bypass_value = voltdm->read(vc_bypass_val_reg);
181 /*
182 * Loop till the bypass command is acknowledged from the SMPS.
183 * NOTE: This is legacy code. The loop count and retry count needs
184 * to be revisited.
185 */
186 while (!(vc_bypass_value & vc_valid)) {
187 loop_cnt++;
188
189 if (retries_cnt > 10) {
190 pr_warning("%s: Retry count exceeded\n", __func__);
191 return -ETIMEDOUT;
192 }
193
194 if (loop_cnt > 50) {
195 retries_cnt++;
196 loop_cnt = 0;
197 udelay(10);
198 }
199 vc_bypass_value = voltdm->read(vc_bypass_val_reg);
200 }
201
202 omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
203 return 0;
204}
205
206static void __init omap3_vfsm_init(struct voltagedomain *voltdm)
207{
208 /*
209 * Voltage Manager FSM parameters init
210 * XXX This data should be passed in from the board file
211 */
212 voltdm->write(OMAP3_CLKSETUP, OMAP3_PRM_CLKSETUP_OFFSET);
213 voltdm->write(OMAP3_VOLTOFFSET, OMAP3_PRM_VOLTOFFSET_OFFSET);
214 voltdm->write(OMAP3_VOLTSETUP2, OMAP3_PRM_VOLTSETUP2_OFFSET);
215}
216
217static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
218{
219 static bool is_initialized;
220
221 if (is_initialized)
222 return;
223
224 omap3_vfsm_init(voltdm);
225
226 is_initialized = true;
227}
228
229
230/* OMAP4 specific voltage init functions */
231static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
232{
233 static bool is_initialized;
234 u32 vc_val;
235
236 if (is_initialized)
237 return;
238
239 /* XXX These are magic numbers and do not belong! */
240 vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
241 voltdm->write(vc_val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
242
243 is_initialized = true;
244}
245
246/**
247 * omap_vc_i2c_init - initialize I2C interface to PMIC
248 * @voltdm: voltage domain containing VC data
249 *
250 * Use PMIC supplied seetings for I2C high-speed mode and
251 * master code (if set) and program the VC I2C configuration
252 * register.
253 *
254 * The VC I2C configuration is common to all VC channels,
255 * so this function only configures I2C for the first VC
256 * channel registers. All other VC channels will use the
257 * same configuration.
258 */
259static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
260{
261 struct omap_vc_channel *vc = voltdm->vc;
262 static bool initialized;
263 static bool i2c_high_speed;
264 u8 mcode;
265
266 if (initialized) {
267 if (voltdm->pmic->i2c_high_speed != i2c_high_speed)
268 pr_warn("%s: I2C config for all channels must match.",
269 __func__);
270 return;
271 }
272
273 i2c_high_speed = voltdm->pmic->i2c_high_speed;
274 if (i2c_high_speed)
275 voltdm->rmw(vc->common->i2c_cfg_hsen_mask,
276 vc->common->i2c_cfg_hsen_mask,
277 vc->common->i2c_cfg_reg);
278
279 mcode = voltdm->pmic->i2c_mcode;
280 if (mcode)
281 voltdm->rmw(vc->common->i2c_mcode_mask,
282 mcode << __ffs(vc->common->i2c_mcode_mask),
283 vc->common->i2c_cfg_reg);
284
285 initialized = true;
286}
287
288void __init omap_vc_init_channel(struct voltagedomain *voltdm)
289{
290 struct omap_vc_channel *vc = voltdm->vc;
291 u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
292 u32 val;
293
294 if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
295 pr_err("%s: PMIC info requried to configure vc for"
296 "vdd_%s not populated.Hence cannot initialize vc\n",
297 __func__, voltdm->name);
298 return;
299 }
300
301 if (!voltdm->read || !voltdm->write) {
302 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
303 __func__, voltdm->name);
304 return;
305 }
306
307 vc->cfg_channel = 0;
308 if (vc->flags & OMAP_VC_CHANNEL_CFG_MUTANT)
309 vc_cfg_bits = &vc_mutant_channel_cfg;
310 else
311 vc_cfg_bits = &vc_default_channel_cfg;
312
313 /* get PMIC/board specific settings */
314 vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr;
315 vc->volt_reg_addr = voltdm->pmic->volt_reg_addr;
316 vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr;
317 vc->setup_time = voltdm->pmic->volt_setup_time;
318
319 /* Configure the i2c slave address for this VC */
320 voltdm->rmw(vc->smps_sa_mask,
321 vc->i2c_slave_addr << __ffs(vc->smps_sa_mask),
322 vc->smps_sa_reg);
323 vc->cfg_channel |= vc_cfg_bits->sa;
324
325 /*
326 * Configure the PMIC register addresses.
327 */
328 voltdm->rmw(vc->smps_volra_mask,
329 vc->volt_reg_addr << __ffs(vc->smps_volra_mask),
330 vc->smps_volra_reg);
331 vc->cfg_channel |= vc_cfg_bits->rav;
332
333 if (vc->cmd_reg_addr) {
334 voltdm->rmw(vc->smps_cmdra_mask,
335 vc->cmd_reg_addr << __ffs(vc->smps_cmdra_mask),
336 vc->smps_cmdra_reg);
337 vc->cfg_channel |= vc_cfg_bits->rac | vc_cfg_bits->racen;
338 }
339
340 /* Set up the on, inactive, retention and off voltage */
341 on_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->on_volt);
342 onlp_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->onlp_volt);
343 ret_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->ret_volt);
344 off_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->off_volt);
345 val = ((on_vsel << vc->common->cmd_on_shift) |
346 (onlp_vsel << vc->common->cmd_onlp_shift) |
347 (ret_vsel << vc->common->cmd_ret_shift) |
348 (off_vsel << vc->common->cmd_off_shift));
349 voltdm->write(val, vc->cmdval_reg);
350 vc->cfg_channel |= vc_cfg_bits->cmd;
351
352 /* Channel configuration */
353 omap_vc_config_channel(voltdm);
354
355 /* Configure the setup times */
356 voltdm->rmw(voltdm->vfsm->voltsetup_mask,
357 vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask),
358 voltdm->vfsm->voltsetup_reg);
359
360 omap_vc_i2c_init(voltdm);
361
362 if (cpu_is_omap34xx())
363 omap3_vc_init_channel(voltdm);
364 else if (cpu_is_omap44xx())
365 omap4_vc_init_channel(voltdm);
366}
367
diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h
index e7767771de49..478bf6b432c4 100644
--- a/arch/arm/mach-omap2/vc.h
+++ b/arch/arm/mach-omap2/vc.h
@@ -19,12 +19,12 @@
19 19
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21 21
22struct voltagedomain;
23
22/** 24/**
23 * struct omap_vc_common_data - per-VC register/bitfield data 25 * struct omap_vc_common - per-VC register/bitfield data
24 * @cmd_on_mask: ON bitmask in PRM_VC_CMD_VAL* register 26 * @cmd_on_mask: ON bitmask in PRM_VC_CMD_VAL* register
25 * @valid: VALID bitmask in PRM_VC_BYPASS_VAL register 27 * @valid: VALID bitmask in PRM_VC_BYPASS_VAL register
26 * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start
27 * @smps_volra_reg: Offset of PRM_VC_SMPS_VOL_RA reg from PRM start
28 * @bypass_val_reg: Offset of PRM_VC_BYPASS_VAL reg from PRM start 28 * @bypass_val_reg: Offset of PRM_VC_BYPASS_VAL reg from PRM start
29 * @data_shift: DATA field shift in PRM_VC_BYPASS_VAL register 29 * @data_shift: DATA field shift in PRM_VC_BYPASS_VAL register
30 * @slaveaddr_shift: SLAVEADDR field shift in PRM_VC_BYPASS_VAL register 30 * @slaveaddr_shift: SLAVEADDR field shift in PRM_VC_BYPASS_VAL register
@@ -33,15 +33,16 @@
33 * @cmd_onlp_shift: ONLP field shift in PRM_VC_CMD_VAL_* register 33 * @cmd_onlp_shift: ONLP field shift in PRM_VC_CMD_VAL_* register
34 * @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register 34 * @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register
35 * @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register 35 * @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register
36 * @i2c_cfg_reg: I2C configuration register offset
37 * @i2c_cfg_hsen_mask: high-speed mode bit field mask in I2C config register
38 * @i2c_mcode_mask: MCODE field mask for I2C config register
36 * 39 *
37 * XXX One of cmd_on_mask and cmd_on_shift are not needed 40 * XXX One of cmd_on_mask and cmd_on_shift are not needed
38 * XXX VALID should probably be a shift, not a mask 41 * XXX VALID should probably be a shift, not a mask
39 */ 42 */
40struct omap_vc_common_data { 43struct omap_vc_common {
41 u32 cmd_on_mask; 44 u32 cmd_on_mask;
42 u32 valid; 45 u32 valid;
43 u8 smps_sa_reg;
44 u8 smps_volra_reg;
45 u8 bypass_val_reg; 46 u8 bypass_val_reg;
46 u8 data_shift; 47 u8 data_shift;
47 u8 slaveaddr_shift; 48 u8 slaveaddr_shift;
@@ -50,34 +51,75 @@ struct omap_vc_common_data {
50 u8 cmd_onlp_shift; 51 u8 cmd_onlp_shift;
51 u8 cmd_ret_shift; 52 u8 cmd_ret_shift;
52 u8 cmd_off_shift; 53 u8 cmd_off_shift;
54 u8 i2c_cfg_reg;
55 u8 i2c_cfg_hsen_mask;
56 u8 i2c_mcode_mask;
53}; 57};
54 58
59/* omap_vc_channel.flags values */
60#define OMAP_VC_CHANNEL_DEFAULT BIT(0)
61#define OMAP_VC_CHANNEL_CFG_MUTANT BIT(1)
62
55/** 63/**
56 * struct omap_vc_instance_data - VC per-instance data 64 * struct omap_vc_channel - VC per-instance data
57 * @vc_common: pointer to VC common data for this platform 65 * @i2c_slave_addr: I2C slave address of PMIC for this VC channel
58 * @smps_sa_mask: SA* bitmask in the PRM_VC_SMPS_SA register 66 * @volt_reg_addr: voltage configuration register address
59 * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register 67 * @cmd_reg_addr: command configuration register address
60 * @smps_sa_shift: SA* field shift in the PRM_VC_SMPS_SA register 68 * @setup_time: setup time (in sys_clk cycles) of regulator for this channel
61 * @smps_volra_shift: VOLRA* field shift in the PRM_VC_VOL_RA register 69 * @cfg_channel: current value of VC channel configuration register
70 * @i2c_high_speed: whether or not to use I2C high-speed mode
62 * 71 *
63 * XXX It is not necessary to have both a *_mask and a *_shift - 72 * @common: pointer to VC common data for this platform
64 * remove one 73 * @smps_sa_mask: i2c slave address bitmask in the PRM_VC_SMPS_SA register
74 * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register
75 * @smps_cmdra_mask: CMDRA* bitmask in the PRM_VC_CMD_RA register
76 * @cmdval_reg: register for on/ret/off voltage level values for this channel
77 * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start
78 * @smps_volra_reg: Offset of PRM_VC_SMPS_VOL_RA reg from PRM start
79 * @smps_cmdra_reg: Offset of PRM_VC_SMPS_CMD_RA reg from PRM start
80 * @cfg_channel_reg: VC channel configuration register
81 * @cfg_channel_sa_shift: bit shift for slave address cfg_channel register
82 * @flags: VC channel-specific flags (optional)
65 */ 83 */
66struct omap_vc_instance_data { 84struct omap_vc_channel {
67 const struct omap_vc_common_data *vc_common; 85 /* channel state */
86 u16 i2c_slave_addr;
87 u16 volt_reg_addr;
88 u16 cmd_reg_addr;
89 u16 setup_time;
90 u8 cfg_channel;
91 bool i2c_high_speed;
92
93 /* register access data */
94 const struct omap_vc_common *common;
68 u32 smps_sa_mask; 95 u32 smps_sa_mask;
69 u32 smps_volra_mask; 96 u32 smps_volra_mask;
97 u32 smps_cmdra_mask;
70 u8 cmdval_reg; 98 u8 cmdval_reg;
71 u8 smps_sa_shift; 99 u8 smps_sa_reg;
72 u8 smps_volra_shift; 100 u8 smps_volra_reg;
101 u8 smps_cmdra_reg;
102 u8 cfg_channel_reg;
103 u8 cfg_channel_sa_shift;
104 u8 flags;
73}; 105};
74 106
75extern struct omap_vc_instance_data omap3_vc1_data; 107extern struct omap_vc_channel omap3_vc_mpu;
76extern struct omap_vc_instance_data omap3_vc2_data; 108extern struct omap_vc_channel omap3_vc_core;
109
110extern struct omap_vc_channel omap4_vc_mpu;
111extern struct omap_vc_channel omap4_vc_iva;
112extern struct omap_vc_channel omap4_vc_core;
77 113
78extern struct omap_vc_instance_data omap4_vc_mpu_data; 114void omap_vc_init_channel(struct voltagedomain *voltdm);
79extern struct omap_vc_instance_data omap4_vc_iva_data; 115int omap_vc_pre_scale(struct voltagedomain *voltdm,
80extern struct omap_vc_instance_data omap4_vc_core_data; 116 unsigned long target_volt,
117 u8 *target_vsel, u8 *current_vsel);
118void omap_vc_post_scale(struct voltagedomain *voltdm,
119 unsigned long target_volt,
120 u8 target_vsel, u8 current_vsel);
121int omap_vc_bypass_scale(struct voltagedomain *voltdm,
122 unsigned long target_volt);
81 123
82#endif 124#endif
83 125
diff --git a/arch/arm/mach-omap2/vc3xxx_data.c b/arch/arm/mach-omap2/vc3xxx_data.c
index f37dc4bc379a..cfe348e1af0e 100644
--- a/arch/arm/mach-omap2/vc3xxx_data.c
+++ b/arch/arm/mach-omap2/vc3xxx_data.c
@@ -29,9 +29,7 @@
29 * VC data common to 34xx/36xx chips 29 * VC data common to 34xx/36xx chips
30 * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file. 30 * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
31 */ 31 */
32static struct omap_vc_common_data omap3_vc_common = { 32static struct omap_vc_common omap3_vc_common = {
33 .smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET,
34 .smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
35 .bypass_val_reg = OMAP3_PRM_VC_BYPASS_VAL_OFFSET, 33 .bypass_val_reg = OMAP3_PRM_VC_BYPASS_VAL_OFFSET,
36 .data_shift = OMAP3430_DATA_SHIFT, 34 .data_shift = OMAP3430_DATA_SHIFT,
37 .slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT, 35 .slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT,
@@ -42,22 +40,33 @@ static struct omap_vc_common_data omap3_vc_common = {
42 .cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT, 40 .cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT,
43 .cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT, 41 .cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT,
44 .cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT, 42 .cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT,
43 .i2c_cfg_hsen_mask = OMAP3430_HSEN_MASK,
44 .i2c_cfg_reg = OMAP3_PRM_VC_I2C_CFG_OFFSET,
45 .i2c_mcode_mask = OMAP3430_MCODE_MASK,
45}; 46};
46 47
47struct omap_vc_instance_data omap3_vc1_data = { 48struct omap_vc_channel omap3_vc_mpu = {
48 .vc_common = &omap3_vc_common, 49 .common = &omap3_vc_common,
50 .smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET,
51 .smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
52 .smps_cmdra_reg = OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET,
53 .cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET,
49 .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET, 54 .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET,
50 .smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT,
51 .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK, 55 .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK,
52 .smps_volra_shift = OMAP3430_VOLRA0_SHIFT,
53 .smps_volra_mask = OMAP3430_VOLRA0_MASK, 56 .smps_volra_mask = OMAP3430_VOLRA0_MASK,
57 .smps_cmdra_mask = OMAP3430_CMDRA0_MASK,
58 .cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT,
54}; 59};
55 60
56struct omap_vc_instance_data omap3_vc2_data = { 61struct omap_vc_channel omap3_vc_core = {
57 .vc_common = &omap3_vc_common, 62 .common = &omap3_vc_common,
63 .smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET,
64 .smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
65 .smps_cmdra_reg = OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET,
66 .cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET,
58 .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET, 67 .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET,
59 .smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
60 .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK, 68 .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK,
61 .smps_volra_shift = OMAP3430_VOLRA1_SHIFT,
62 .smps_volra_mask = OMAP3430_VOLRA1_MASK, 69 .smps_volra_mask = OMAP3430_VOLRA1_MASK,
70 .smps_cmdra_mask = OMAP3430_CMDRA1_MASK,
71 .cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
63}; 72};
diff --git a/arch/arm/mach-omap2/vc44xx_data.c b/arch/arm/mach-omap2/vc44xx_data.c
index a98da8ddec52..2740a968145e 100644
--- a/arch/arm/mach-omap2/vc44xx_data.c
+++ b/arch/arm/mach-omap2/vc44xx_data.c
@@ -30,9 +30,7 @@
30 * VC data common to 44xx chips 30 * VC data common to 44xx chips
31 * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file. 31 * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
32 */ 32 */
33static const struct omap_vc_common_data omap4_vc_common = { 33static const struct omap_vc_common omap4_vc_common = {
34 .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
35 .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
36 .bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET, 34 .bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET,
37 .data_shift = OMAP4430_DATA_SHIFT, 35 .data_shift = OMAP4430_DATA_SHIFT,
38 .slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT, 36 .slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT,
@@ -43,33 +41,49 @@ static const struct omap_vc_common_data omap4_vc_common = {
43 .cmd_onlp_shift = OMAP4430_ONLP_SHIFT, 41 .cmd_onlp_shift = OMAP4430_ONLP_SHIFT,
44 .cmd_ret_shift = OMAP4430_RET_SHIFT, 42 .cmd_ret_shift = OMAP4430_RET_SHIFT,
45 .cmd_off_shift = OMAP4430_OFF_SHIFT, 43 .cmd_off_shift = OMAP4430_OFF_SHIFT,
44 .i2c_cfg_reg = OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET,
45 .i2c_cfg_hsen_mask = OMAP4430_HSMODEEN_MASK,
46 .i2c_mcode_mask = OMAP4430_HSMCODE_MASK,
46}; 47};
47 48
48/* VC instance data for each controllable voltage line */ 49/* VC instance data for each controllable voltage line */
49struct omap_vc_instance_data omap4_vc_mpu_data = { 50struct omap_vc_channel omap4_vc_mpu = {
50 .vc_common = &omap4_vc_common, 51 .flags = OMAP_VC_CHANNEL_DEFAULT | OMAP_VC_CHANNEL_CFG_MUTANT,
52 .common = &omap4_vc_common,
53 .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
54 .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
55 .smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
56 .cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
51 .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET, 57 .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET,
52 .smps_sa_shift = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT,
53 .smps_sa_mask = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK, 58 .smps_sa_mask = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK,
54 .smps_volra_shift = OMAP4430_VOLRA_VDD_MPU_L_SHIFT,
55 .smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK, 59 .smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK,
60 .smps_cmdra_mask = OMAP4430_CMDRA_VDD_MPU_L_MASK,
61 .cfg_channel_sa_shift = OMAP4430_SA_VDD_MPU_L_SHIFT,
56}; 62};
57 63
58struct omap_vc_instance_data omap4_vc_iva_data = { 64struct omap_vc_channel omap4_vc_iva = {
59 .vc_common = &omap4_vc_common, 65 .common = &omap4_vc_common,
66 .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
67 .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
68 .smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
69 .cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
60 .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET, 70 .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET,
61 .smps_sa_shift = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT,
62 .smps_sa_mask = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK, 71 .smps_sa_mask = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK,
63 .smps_volra_shift = OMAP4430_VOLRA_VDD_IVA_L_SHIFT,
64 .smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK, 72 .smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK,
73 .smps_cmdra_mask = OMAP4430_CMDRA_VDD_IVA_L_MASK,
74 .cfg_channel_sa_shift = OMAP4430_SA_VDD_IVA_L_SHIFT,
65}; 75};
66 76
67struct omap_vc_instance_data omap4_vc_core_data = { 77struct omap_vc_channel omap4_vc_core = {
68 .vc_common = &omap4_vc_common, 78 .common = &omap4_vc_common,
79 .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
80 .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
81 .smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
82 .cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
69 .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET, 83 .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET,
70 .smps_sa_shift = OMAP4430_SA_VDD_CORE_L_0_6_SHIFT,
71 .smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK, 84 .smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK,
72 .smps_volra_shift = OMAP4430_VOLRA_VDD_CORE_L_SHIFT,
73 .smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK, 85 .smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK,
86 .smps_cmdra_mask = OMAP4430_CMDRA_VDD_CORE_L_MASK,
87 .cfg_channel_sa_shift = OMAP4430_SA_VDD_CORE_L_SHIFT,
74}; 88};
75 89
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 9ef3789ded4b..64070ac1e761 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -21,10 +21,10 @@
21 21
22#include <linux/delay.h> 22#include <linux/delay.h>
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/clk.h>
25#include <linux/err.h> 24#include <linux/err.h>
26#include <linux/debugfs.h> 25#include <linux/debugfs.h>
27#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/clk.h>
28 28
29#include <plat/common.h> 29#include <plat/common.h>
30 30
@@ -36,839 +36,88 @@
36#include "control.h" 36#include "control.h"
37 37
38#include "voltage.h" 38#include "voltage.h"
39#include "powerdomain.h"
39 40
40#include "vc.h" 41#include "vc.h"
41#include "vp.h" 42#include "vp.h"
42 43
43#define VOLTAGE_DIR_SIZE 16 44static LIST_HEAD(voltdm_list);
44
45
46static struct omap_vdd_info **vdd_info;
47
48/*
49 * Number of scalable voltage domains.
50 */
51static int nr_scalable_vdd;
52
53/* XXX document */
54static s16 prm_mod_offs;
55static s16 prm_irqst_ocp_mod_offs;
56
57static struct dentry *voltage_dir;
58
59/* Init function pointers */
60static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
61 unsigned long target_volt);
62
63static u32 omap3_voltage_read_reg(u16 mod, u8 offset)
64{
65 return omap2_prm_read_mod_reg(mod, offset);
66}
67
68static void omap3_voltage_write_reg(u32 val, u16 mod, u8 offset)
69{
70 omap2_prm_write_mod_reg(val, mod, offset);
71}
72
73static u32 omap4_voltage_read_reg(u16 mod, u8 offset)
74{
75 return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
76 mod, offset);
77}
78
79static void omap4_voltage_write_reg(u32 val, u16 mod, u8 offset)
80{
81 omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, mod, offset);
82}
83
84static int __init _config_common_vdd_data(struct omap_vdd_info *vdd)
85{
86 char *sys_ck_name;
87 struct clk *sys_ck;
88 u32 sys_clk_speed, timeout_val, waittime;
89
90 /*
91 * XXX Clockfw should handle this, or this should be in a
92 * struct record
93 */
94 if (cpu_is_omap24xx() || cpu_is_omap34xx())
95 sys_ck_name = "sys_ck";
96 else if (cpu_is_omap44xx())
97 sys_ck_name = "sys_clkin_ck";
98 else
99 return -EINVAL;
100
101 /*
102 * Sys clk rate is require to calculate vp timeout value and
103 * smpswaittimemin and smpswaittimemax.
104 */
105 sys_ck = clk_get(NULL, sys_ck_name);
106 if (IS_ERR(sys_ck)) {
107 pr_warning("%s: Could not get the sys clk to calculate"
108 "various vdd_%s params\n", __func__, vdd->voltdm.name);
109 return -EINVAL;
110 }
111 sys_clk_speed = clk_get_rate(sys_ck);
112 clk_put(sys_ck);
113 /* Divide to avoid overflow */
114 sys_clk_speed /= 1000;
115
116 /* Generic voltage parameters */
117 vdd->volt_scale = vp_forceupdate_scale_voltage;
118 vdd->vp_enabled = false;
119
120 vdd->vp_rt_data.vpconfig_erroroffset =
121 (vdd->pmic_info->vp_erroroffset <<
122 vdd->vp_data->vp_common->vpconfig_erroroffset_shift);
123
124 timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
125 vdd->vp_rt_data.vlimitto_timeout = timeout_val;
126 vdd->vp_rt_data.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
127 vdd->vp_rt_data.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
128
129 waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
130 sys_clk_speed) / 1000;
131 vdd->vp_rt_data.vstepmin_smpswaittimemin = waittime;
132 vdd->vp_rt_data.vstepmax_smpswaittimemax = waittime;
133 vdd->vp_rt_data.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
134 vdd->vp_rt_data.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
135
136 return 0;
137}
138
139/* Voltage debugfs support */
140static int vp_volt_debug_get(void *data, u64 *val)
141{
142 struct omap_vdd_info *vdd = (struct omap_vdd_info *) data;
143 u8 vsel;
144
145 if (!vdd) {
146 pr_warning("Wrong paramater passed\n");
147 return -EINVAL;
148 }
149
150 vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
151
152 if (!vdd->pmic_info->vsel_to_uv) {
153 pr_warning("PMIC function to convert vsel to voltage"
154 "in uV not registerd\n");
155 return -EINVAL;
156 }
157
158 *val = vdd->pmic_info->vsel_to_uv(vsel);
159 return 0;
160}
161
162static int nom_volt_debug_get(void *data, u64 *val)
163{
164 struct omap_vdd_info *vdd = (struct omap_vdd_info *) data;
165
166 if (!vdd) {
167 pr_warning("Wrong paramater passed\n");
168 return -EINVAL;
169 }
170
171 *val = omap_voltage_get_nom_volt(&vdd->voltdm);
172
173 return 0;
174}
175
176DEFINE_SIMPLE_ATTRIBUTE(vp_volt_debug_fops, vp_volt_debug_get, NULL, "%llu\n");
177DEFINE_SIMPLE_ATTRIBUTE(nom_volt_debug_fops, nom_volt_debug_get, NULL,
178 "%llu\n");
179static void vp_latch_vsel(struct omap_vdd_info *vdd)
180{
181 u32 vpconfig;
182 unsigned long uvdc;
183 char vsel;
184
185 uvdc = omap_voltage_get_nom_volt(&vdd->voltdm);
186 if (!uvdc) {
187 pr_warning("%s: unable to find current voltage for vdd_%s\n",
188 __func__, vdd->voltdm.name);
189 return;
190 }
191
192 if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
193 pr_warning("%s: PMIC function to convert voltage in uV to"
194 " vsel not registered\n", __func__);
195 return;
196 }
197
198 vsel = vdd->pmic_info->uv_to_vsel(uvdc);
199
200 vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
201 vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvoltage_mask |
202 vdd->vp_data->vp_common->vpconfig_initvdd);
203 vpconfig |= vsel << vdd->vp_data->vp_common->vpconfig_initvoltage_shift;
204
205 vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
206
207 /* Trigger initVDD value copy to voltage processor */
208 vdd->write_reg((vpconfig | vdd->vp_data->vp_common->vpconfig_initvdd),
209 prm_mod_offs, vdd->vp_data->vpconfig);
210
211 /* Clear initVDD copy trigger bit */
212 vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
213}
214
215/* Generic voltage init functions */
216static void __init vp_init(struct omap_vdd_info *vdd)
217{
218 u32 vp_val;
219
220 if (!vdd->read_reg || !vdd->write_reg) {
221 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
222 __func__, vdd->voltdm.name);
223 return;
224 }
225
226 vp_val = vdd->vp_rt_data.vpconfig_erroroffset |
227 (vdd->vp_rt_data.vpconfig_errorgain <<
228 vdd->vp_data->vp_common->vpconfig_errorgain_shift) |
229 vdd->vp_data->vp_common->vpconfig_timeouten;
230 vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vpconfig);
231
232 vp_val = ((vdd->vp_rt_data.vstepmin_smpswaittimemin <<
233 vdd->vp_data->vp_common->vstepmin_smpswaittimemin_shift) |
234 (vdd->vp_rt_data.vstepmin_stepmin <<
235 vdd->vp_data->vp_common->vstepmin_stepmin_shift));
236 vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmin);
237
238 vp_val = ((vdd->vp_rt_data.vstepmax_smpswaittimemax <<
239 vdd->vp_data->vp_common->vstepmax_smpswaittimemax_shift) |
240 (vdd->vp_rt_data.vstepmax_stepmax <<
241 vdd->vp_data->vp_common->vstepmax_stepmax_shift));
242 vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmax);
243
244 vp_val = ((vdd->vp_rt_data.vlimitto_vddmax <<
245 vdd->vp_data->vp_common->vlimitto_vddmax_shift) |
246 (vdd->vp_rt_data.vlimitto_vddmin <<
247 vdd->vp_data->vp_common->vlimitto_vddmin_shift) |
248 (vdd->vp_rt_data.vlimitto_timeout <<
249 vdd->vp_data->vp_common->vlimitto_timeout_shift));
250 vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vlimitto);
251}
252
253static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)
254{
255 char *name;
256
257 name = kzalloc(VOLTAGE_DIR_SIZE, GFP_KERNEL);
258 if (!name) {
259 pr_warning("%s: Unable to allocate memory for debugfs"
260 " directory name for vdd_%s",
261 __func__, vdd->voltdm.name);
262 return;
263 }
264 strcpy(name, "vdd_");
265 strcat(name, vdd->voltdm.name);
266
267 vdd->debug_dir = debugfs_create_dir(name, voltage_dir);
268 kfree(name);
269 if (IS_ERR(vdd->debug_dir)) {
270 pr_warning("%s: Unable to create debugfs directory for"
271 " vdd_%s\n", __func__, vdd->voltdm.name);
272 vdd->debug_dir = NULL;
273 return;
274 }
275
276 (void) debugfs_create_x16("vp_errorgain", S_IRUGO, vdd->debug_dir,
277 &(vdd->vp_rt_data.vpconfig_errorgain));
278 (void) debugfs_create_x16("vp_smpswaittimemin", S_IRUGO,
279 vdd->debug_dir,
280 &(vdd->vp_rt_data.vstepmin_smpswaittimemin));
281 (void) debugfs_create_x8("vp_stepmin", S_IRUGO, vdd->debug_dir,
282 &(vdd->vp_rt_data.vstepmin_stepmin));
283 (void) debugfs_create_x16("vp_smpswaittimemax", S_IRUGO,
284 vdd->debug_dir,
285 &(vdd->vp_rt_data.vstepmax_smpswaittimemax));
286 (void) debugfs_create_x8("vp_stepmax", S_IRUGO, vdd->debug_dir,
287 &(vdd->vp_rt_data.vstepmax_stepmax));
288 (void) debugfs_create_x8("vp_vddmax", S_IRUGO, vdd->debug_dir,
289 &(vdd->vp_rt_data.vlimitto_vddmax));
290 (void) debugfs_create_x8("vp_vddmin", S_IRUGO, vdd->debug_dir,
291 &(vdd->vp_rt_data.vlimitto_vddmin));
292 (void) debugfs_create_x16("vp_timeout", S_IRUGO, vdd->debug_dir,
293 &(vdd->vp_rt_data.vlimitto_timeout));
294 (void) debugfs_create_file("curr_vp_volt", S_IRUGO, vdd->debug_dir,
295 (void *) vdd, &vp_volt_debug_fops);
296 (void) debugfs_create_file("curr_nominal_volt", S_IRUGO,
297 vdd->debug_dir, (void *) vdd,
298 &nom_volt_debug_fops);
299}
300
301/* Voltage scale and accessory APIs */
302static int _pre_volt_scale(struct omap_vdd_info *vdd,
303 unsigned long target_volt, u8 *target_vsel, u8 *current_vsel)
304{
305 struct omap_volt_data *volt_data;
306 const struct omap_vc_common_data *vc_common;
307 const struct omap_vp_common_data *vp_common;
308 u32 vc_cmdval, vp_errgain_val;
309
310 vc_common = vdd->vc_data->vc_common;
311 vp_common = vdd->vp_data->vp_common;
312
313 /* Check if suffiecient pmic info is available for this vdd */
314 if (!vdd->pmic_info) {
315 pr_err("%s: Insufficient pmic info to scale the vdd_%s\n",
316 __func__, vdd->voltdm.name);
317 return -EINVAL;
318 }
319
320 if (!vdd->pmic_info->uv_to_vsel) {
321 pr_err("%s: PMIC function to convert voltage in uV to"
322 "vsel not registered. Hence unable to scale voltage"
323 "for vdd_%s\n", __func__, vdd->voltdm.name);
324 return -ENODATA;
325 }
326
327 if (!vdd->read_reg || !vdd->write_reg) {
328 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
329 __func__, vdd->voltdm.name);
330 return -EINVAL;
331 }
332
333 /* Get volt_data corresponding to target_volt */
334 volt_data = omap_voltage_get_voltdata(&vdd->voltdm, target_volt);
335 if (IS_ERR(volt_data))
336 volt_data = NULL;
337
338 *target_vsel = vdd->pmic_info->uv_to_vsel(target_volt);
339 *current_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
340
341 /* Setting the ON voltage to the new target voltage */
342 vc_cmdval = vdd->read_reg(prm_mod_offs, vdd->vc_data->cmdval_reg);
343 vc_cmdval &= ~vc_common->cmd_on_mask;
344 vc_cmdval |= (*target_vsel << vc_common->cmd_on_shift);
345 vdd->write_reg(vc_cmdval, prm_mod_offs, vdd->vc_data->cmdval_reg);
346
347 /* Setting vp errorgain based on the voltage */
348 if (volt_data) {
349 vp_errgain_val = vdd->read_reg(prm_mod_offs,
350 vdd->vp_data->vpconfig);
351 vdd->vp_rt_data.vpconfig_errorgain = volt_data->vp_errgain;
352 vp_errgain_val &= ~vp_common->vpconfig_errorgain_mask;
353 vp_errgain_val |= vdd->vp_rt_data.vpconfig_errorgain <<
354 vp_common->vpconfig_errorgain_shift;
355 vdd->write_reg(vp_errgain_val, prm_mod_offs,
356 vdd->vp_data->vpconfig);
357 }
358
359 return 0;
360}
361
362static void _post_volt_scale(struct omap_vdd_info *vdd,
363 unsigned long target_volt, u8 target_vsel, u8 current_vsel)
364{
365 u32 smps_steps = 0, smps_delay = 0;
366
367 smps_steps = abs(target_vsel - current_vsel);
368 /* SMPS slew rate / step size. 2us added as buffer. */
369 smps_delay = ((smps_steps * vdd->pmic_info->step_size) /
370 vdd->pmic_info->slew_rate) + 2;
371 udelay(smps_delay);
372
373 vdd->curr_volt = target_volt;
374}
375
376/* vc_bypass_scale_voltage - VC bypass method of voltage scaling */
377static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
378 unsigned long target_volt)
379{
380 u32 loop_cnt = 0, retries_cnt = 0;
381 u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
382 u8 target_vsel, current_vsel;
383 int ret;
384
385 ret = _pre_volt_scale(vdd, target_volt, &target_vsel, &current_vsel);
386 if (ret)
387 return ret;
388
389 vc_valid = vdd->vc_data->vc_common->valid;
390 vc_bypass_val_reg = vdd->vc_data->vc_common->bypass_val_reg;
391 vc_bypass_value = (target_vsel << vdd->vc_data->vc_common->data_shift) |
392 (vdd->pmic_info->pmic_reg <<
393 vdd->vc_data->vc_common->regaddr_shift) |
394 (vdd->pmic_info->i2c_slave_addr <<
395 vdd->vc_data->vc_common->slaveaddr_shift);
396
397 vdd->write_reg(vc_bypass_value, prm_mod_offs, vc_bypass_val_reg);
398 vdd->write_reg(vc_bypass_value | vc_valid, prm_mod_offs,
399 vc_bypass_val_reg);
400
401 vc_bypass_value = vdd->read_reg(prm_mod_offs, vc_bypass_val_reg);
402 /*
403 * Loop till the bypass command is acknowledged from the SMPS.
404 * NOTE: This is legacy code. The loop count and retry count needs
405 * to be revisited.
406 */
407 while (!(vc_bypass_value & vc_valid)) {
408 loop_cnt++;
409
410 if (retries_cnt > 10) {
411 pr_warning("%s: Retry count exceeded\n", __func__);
412 return -ETIMEDOUT;
413 }
414
415 if (loop_cnt > 50) {
416 retries_cnt++;
417 loop_cnt = 0;
418 udelay(10);
419 }
420 vc_bypass_value = vdd->read_reg(prm_mod_offs,
421 vc_bypass_val_reg);
422 }
423
424 _post_volt_scale(vdd, target_volt, target_vsel, current_vsel);
425 return 0;
426}
427
428/* VP force update method of voltage scaling */
429static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
430 unsigned long target_volt)
431{
432 u32 vpconfig;
433 u8 target_vsel, current_vsel, prm_irqst_reg;
434 int ret, timeout = 0;
435
436 ret = _pre_volt_scale(vdd, target_volt, &target_vsel, &current_vsel);
437 if (ret)
438 return ret;
439
440 prm_irqst_reg = vdd->vp_data->prm_irqst_data->prm_irqst_reg;
441
442 /*
443 * Clear all pending TransactionDone interrupt/status. Typical latency
444 * is <3us
445 */
446 while (timeout++ < VP_TRANXDONE_TIMEOUT) {
447 vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
448 prm_irqst_ocp_mod_offs, prm_irqst_reg);
449 if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
450 vdd->vp_data->prm_irqst_data->tranxdone_status))
451 break;
452 udelay(1);
453 }
454 if (timeout >= VP_TRANXDONE_TIMEOUT) {
455 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
456 "Voltage change aborted", __func__, vdd->voltdm.name);
457 return -ETIMEDOUT;
458 }
459
460 /* Configure for VP-Force Update */
461 vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
462 vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvdd |
463 vdd->vp_data->vp_common->vpconfig_forceupdate |
464 vdd->vp_data->vp_common->vpconfig_initvoltage_mask);
465 vpconfig |= ((target_vsel <<
466 vdd->vp_data->vp_common->vpconfig_initvoltage_shift));
467 vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
468
469 /* Trigger initVDD value copy to voltage processor */
470 vpconfig |= vdd->vp_data->vp_common->vpconfig_initvdd;
471 vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
472
473 /* Force update of voltage */
474 vpconfig |= vdd->vp_data->vp_common->vpconfig_forceupdate;
475 vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
476
477 /*
478 * Wait for TransactionDone. Typical latency is <200us.
479 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
480 */
481 timeout = 0;
482 omap_test_timeout((vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
483 vdd->vp_data->prm_irqst_data->tranxdone_status),
484 VP_TRANXDONE_TIMEOUT, timeout);
485 if (timeout >= VP_TRANXDONE_TIMEOUT)
486 pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
487 "TRANXDONE never got set after the voltage update\n",
488 __func__, vdd->voltdm.name);
489
490 _post_volt_scale(vdd, target_volt, target_vsel, current_vsel);
491
492 /*
493 * Disable TransactionDone interrupt , clear all status, clear
494 * control registers
495 */
496 timeout = 0;
497 while (timeout++ < VP_TRANXDONE_TIMEOUT) {
498 vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
499 prm_irqst_ocp_mod_offs, prm_irqst_reg);
500 if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
501 vdd->vp_data->prm_irqst_data->tranxdone_status))
502 break;
503 udelay(1);
504 }
505
506 if (timeout >= VP_TRANXDONE_TIMEOUT)
507 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
508 "to clear the TRANXDONE status\n",
509 __func__, vdd->voltdm.name);
510
511 vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
512 /* Clear initVDD copy trigger bit */
513 vpconfig &= ~vdd->vp_data->vp_common->vpconfig_initvdd;
514 vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
515 /* Clear force bit */
516 vpconfig &= ~vdd->vp_data->vp_common->vpconfig_forceupdate;
517 vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
518
519 return 0;
520}
521
522static void __init omap3_vfsm_init(struct omap_vdd_info *vdd)
523{
524 /*
525 * Voltage Manager FSM parameters init
526 * XXX This data should be passed in from the board file
527 */
528 vdd->write_reg(OMAP3_CLKSETUP, prm_mod_offs, OMAP3_PRM_CLKSETUP_OFFSET);
529 vdd->write_reg(OMAP3_VOLTOFFSET, prm_mod_offs,
530 OMAP3_PRM_VOLTOFFSET_OFFSET);
531 vdd->write_reg(OMAP3_VOLTSETUP2, prm_mod_offs,
532 OMAP3_PRM_VOLTSETUP2_OFFSET);
533}
534
535static void __init omap3_vc_init(struct omap_vdd_info *vdd)
536{
537 static bool is_initialized;
538 u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
539 u32 vc_val;
540
541 if (is_initialized)
542 return;
543
544 /* Set up the on, inactive, retention and off voltage */
545 on_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->on_volt);
546 onlp_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->onlp_volt);
547 ret_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->ret_volt);
548 off_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->off_volt);
549 vc_val = ((on_vsel << vdd->vc_data->vc_common->cmd_on_shift) |
550 (onlp_vsel << vdd->vc_data->vc_common->cmd_onlp_shift) |
551 (ret_vsel << vdd->vc_data->vc_common->cmd_ret_shift) |
552 (off_vsel << vdd->vc_data->vc_common->cmd_off_shift));
553 vdd->write_reg(vc_val, prm_mod_offs, vdd->vc_data->cmdval_reg);
554
555 /*
556 * Generic VC parameters init
557 * XXX This data should be abstracted out
558 */
559 vdd->write_reg(OMAP3430_CMD1_MASK | OMAP3430_RAV1_MASK, prm_mod_offs,
560 OMAP3_PRM_VC_CH_CONF_OFFSET);
561 vdd->write_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, prm_mod_offs,
562 OMAP3_PRM_VC_I2C_CFG_OFFSET);
563
564 omap3_vfsm_init(vdd);
565
566 is_initialized = true;
567}
568
569
570/* OMAP4 specific voltage init functions */
571static void __init omap4_vc_init(struct omap_vdd_info *vdd)
572{
573 static bool is_initialized;
574 u32 vc_val;
575
576 if (is_initialized)
577 return;
578
579 /* TODO: Configure setup times and CMD_VAL values*/
580
581 /*
582 * Generic VC parameters init
583 * XXX This data should be abstracted out
584 */
585 vc_val = (OMAP4430_RAV_VDD_MPU_L_MASK | OMAP4430_CMD_VDD_MPU_L_MASK |
586 OMAP4430_RAV_VDD_IVA_L_MASK | OMAP4430_CMD_VDD_IVA_L_MASK |
587 OMAP4430_RAV_VDD_CORE_L_MASK | OMAP4430_CMD_VDD_CORE_L_MASK);
588 vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_CHANNEL_OFFSET);
589
590 /* XXX These are magic numbers and do not belong! */
591 vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
592 vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
593
594 is_initialized = true;
595}
596
597static void __init omap_vc_init(struct omap_vdd_info *vdd)
598{
599 u32 vc_val;
600
601 if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
602 pr_err("%s: PMIC info requried to configure vc for"
603 "vdd_%s not populated.Hence cannot initialize vc\n",
604 __func__, vdd->voltdm.name);
605 return;
606 }
607
608 if (!vdd->read_reg || !vdd->write_reg) {
609 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
610 __func__, vdd->voltdm.name);
611 return;
612 }
613
614 /* Set up the SMPS_SA(i2c slave address in VC */
615 vc_val = vdd->read_reg(prm_mod_offs,
616 vdd->vc_data->vc_common->smps_sa_reg);
617 vc_val &= ~vdd->vc_data->smps_sa_mask;
618 vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_data->smps_sa_shift;
619 vdd->write_reg(vc_val, prm_mod_offs,
620 vdd->vc_data->vc_common->smps_sa_reg);
621
622 /* Setup the VOLRA(pmic reg addr) in VC */
623 vc_val = vdd->read_reg(prm_mod_offs,
624 vdd->vc_data->vc_common->smps_volra_reg);
625 vc_val &= ~vdd->vc_data->smps_volra_mask;
626 vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_data->smps_volra_shift;
627 vdd->write_reg(vc_val, prm_mod_offs,
628 vdd->vc_data->vc_common->smps_volra_reg);
629
630 /* Configure the setup times */
631 vc_val = vdd->read_reg(prm_mod_offs, vdd->vfsm->voltsetup_reg);
632 vc_val &= ~vdd->vfsm->voltsetup_mask;
633 vc_val |= vdd->pmic_info->volt_setup_time <<
634 vdd->vfsm->voltsetup_shift;
635 vdd->write_reg(vc_val, prm_mod_offs, vdd->vfsm->voltsetup_reg);
636
637 if (cpu_is_omap34xx())
638 omap3_vc_init(vdd);
639 else if (cpu_is_omap44xx())
640 omap4_vc_init(vdd);
641}
642
643static int __init omap_vdd_data_configure(struct omap_vdd_info *vdd)
644{
645 int ret = -EINVAL;
646
647 if (!vdd->pmic_info) {
648 pr_err("%s: PMIC info requried to configure vdd_%s not"
649 "populated.Hence cannot initialize vdd_%s\n",
650 __func__, vdd->voltdm.name, vdd->voltdm.name);
651 goto ovdc_out;
652 }
653
654 if (IS_ERR_VALUE(_config_common_vdd_data(vdd)))
655 goto ovdc_out;
656
657 if (cpu_is_omap34xx()) {
658 vdd->read_reg = omap3_voltage_read_reg;
659 vdd->write_reg = omap3_voltage_write_reg;
660 ret = 0;
661 } else if (cpu_is_omap44xx()) {
662 vdd->read_reg = omap4_voltage_read_reg;
663 vdd->write_reg = omap4_voltage_write_reg;
664 ret = 0;
665 }
666
667ovdc_out:
668 return ret;
669}
670 45
671/* Public functions */ 46/* Public functions */
672/** 47/**
673 * omap_voltage_get_nom_volt() - Gets the current non-auto-compensated voltage 48 * voltdm_get_voltage() - Gets the current non-auto-compensated voltage
674 * @voltdm: pointer to the VDD for which current voltage info is needed 49 * @voltdm: pointer to the voltdm for which current voltage info is needed
675 * 50 *
676 * API to get the current non-auto-compensated voltage for a VDD. 51 * API to get the current non-auto-compensated voltage for a voltage domain.
677 * Returns 0 in case of error else returns the current voltage for the VDD. 52 * Returns 0 in case of error else returns the current voltage.
678 */ 53 */
679unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm) 54unsigned long voltdm_get_voltage(struct voltagedomain *voltdm)
680{ 55{
681 struct omap_vdd_info *vdd;
682
683 if (!voltdm || IS_ERR(voltdm)) { 56 if (!voltdm || IS_ERR(voltdm)) {
684 pr_warning("%s: VDD specified does not exist!\n", __func__); 57 pr_warning("%s: VDD specified does not exist!\n", __func__);
685 return 0; 58 return 0;
686 } 59 }
687 60
688 vdd = container_of(voltdm, struct omap_vdd_info, voltdm); 61 return voltdm->nominal_volt;
689
690 return vdd->curr_volt;
691} 62}
692 63
693/** 64/**
694 * omap_vp_get_curr_volt() - API to get the current vp voltage. 65 * voltdm_scale() - API to scale voltage of a particular voltage domain.
695 * @voltdm: pointer to the VDD. 66 * @voltdm: pointer to the voltage domain which is to be scaled.
696 * 67 * @target_volt: The target voltage of the voltage domain
697 * This API returns the current voltage for the specified voltage processor
698 */
699unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)
700{
701 struct omap_vdd_info *vdd;
702 u8 curr_vsel;
703
704 if (!voltdm || IS_ERR(voltdm)) {
705 pr_warning("%s: VDD specified does not exist!\n", __func__);
706 return 0;
707 }
708
709 vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
710 if (!vdd->read_reg) {
711 pr_err("%s: No read API for reading vdd_%s regs\n",
712 __func__, voltdm->name);
713 return 0;
714 }
715
716 curr_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
717
718 if (!vdd->pmic_info || !vdd->pmic_info->vsel_to_uv) {
719 pr_warning("%s: PMIC function to convert vsel to voltage"
720 "in uV not registerd\n", __func__);
721 return 0;
722 }
723
724 return vdd->pmic_info->vsel_to_uv(curr_vsel);
725}
726
727/**
728 * omap_vp_enable() - API to enable a particular VP
729 * @voltdm: pointer to the VDD whose VP is to be enabled.
730 *
731 * This API enables a particular voltage processor. Needed by the smartreflex
732 * class drivers.
733 */
734void omap_vp_enable(struct voltagedomain *voltdm)
735{
736 struct omap_vdd_info *vdd;
737 u32 vpconfig;
738
739 if (!voltdm || IS_ERR(voltdm)) {
740 pr_warning("%s: VDD specified does not exist!\n", __func__);
741 return;
742 }
743
744 vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
745 if (!vdd->read_reg || !vdd->write_reg) {
746 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
747 __func__, voltdm->name);
748 return;
749 }
750
751 /* If VP is already enabled, do nothing. Return */
752 if (vdd->vp_enabled)
753 return;
754
755 vp_latch_vsel(vdd);
756
757 /* Enable VP */
758 vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
759 vpconfig |= vdd->vp_data->vp_common->vpconfig_vpenable;
760 vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
761 vdd->vp_enabled = true;
762}
763
764/**
765 * omap_vp_disable() - API to disable a particular VP
766 * @voltdm: pointer to the VDD whose VP is to be disabled.
767 *
768 * This API disables a particular voltage processor. Needed by the smartreflex
769 * class drivers.
770 */
771void omap_vp_disable(struct voltagedomain *voltdm)
772{
773 struct omap_vdd_info *vdd;
774 u32 vpconfig;
775 int timeout;
776
777 if (!voltdm || IS_ERR(voltdm)) {
778 pr_warning("%s: VDD specified does not exist!\n", __func__);
779 return;
780 }
781
782 vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
783 if (!vdd->read_reg || !vdd->write_reg) {
784 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
785 __func__, voltdm->name);
786 return;
787 }
788
789 /* If VP is already disabled, do nothing. Return */
790 if (!vdd->vp_enabled) {
791 pr_warning("%s: Trying to disable VP for vdd_%s when"
792 "it is already disabled\n", __func__, voltdm->name);
793 return;
794 }
795
796 /* Disable VP */
797 vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
798 vpconfig &= ~vdd->vp_data->vp_common->vpconfig_vpenable;
799 vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
800
801 /*
802 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
803 */
804 omap_test_timeout((vdd->read_reg(prm_mod_offs, vdd->vp_data->vstatus)),
805 VP_IDLE_TIMEOUT, timeout);
806
807 if (timeout >= VP_IDLE_TIMEOUT)
808 pr_warning("%s: vdd_%s idle timedout\n",
809 __func__, voltdm->name);
810
811 vdd->vp_enabled = false;
812
813 return;
814}
815
816/**
817 * omap_voltage_scale_vdd() - API to scale voltage of a particular
818 * voltage domain.
819 * @voltdm: pointer to the VDD which is to be scaled.
820 * @target_volt: The target voltage of the voltage domain
821 * 68 *
822 * This API should be called by the kernel to do the voltage scaling 69 * This API should be called by the kernel to do the voltage scaling
823 * for a particular voltage domain during dvfs or any other situation. 70 * for a particular voltage domain during DVFS.
824 */ 71 */
825int omap_voltage_scale_vdd(struct voltagedomain *voltdm, 72int voltdm_scale(struct voltagedomain *voltdm,
826 unsigned long target_volt) 73 unsigned long target_volt)
827{ 74{
828 struct omap_vdd_info *vdd; 75 int ret;
829 76
830 if (!voltdm || IS_ERR(voltdm)) { 77 if (!voltdm || IS_ERR(voltdm)) {
831 pr_warning("%s: VDD specified does not exist!\n", __func__); 78 pr_warning("%s: VDD specified does not exist!\n", __func__);
832 return -EINVAL; 79 return -EINVAL;
833 } 80 }
834 81
835 vdd = container_of(voltdm, struct omap_vdd_info, voltdm); 82 if (!voltdm->scale) {
836
837 if (!vdd->volt_scale) {
838 pr_err("%s: No voltage scale API registered for vdd_%s\n", 83 pr_err("%s: No voltage scale API registered for vdd_%s\n",
839 __func__, voltdm->name); 84 __func__, voltdm->name);
840 return -ENODATA; 85 return -ENODATA;
841 } 86 }
842 87
843 return vdd->volt_scale(vdd, target_volt); 88 ret = voltdm->scale(voltdm, target_volt);
89 if (!ret)
90 voltdm->nominal_volt = target_volt;
91
92 return ret;
844} 93}
845 94
846/** 95/**
847 * omap_voltage_reset() - Resets the voltage of a particular voltage domain 96 * voltdm_reset() - Resets the voltage of a particular voltage domain
848 * to that of the current OPP. 97 * to that of the current OPP.
849 * @voltdm: pointer to the VDD whose voltage is to be reset. 98 * @voltdm: pointer to the voltage domain whose voltage is to be reset.
850 * 99 *
851 * This API finds out the correct voltage the voltage domain is supposed 100 * This API finds out the correct voltage the voltage domain is supposed
852 * to be at and resets the voltage to that level. Should be used especially 101 * to be at and resets the voltage to that level. Should be used especially
853 * while disabling any voltage compensation modules. 102 * while disabling any voltage compensation modules.
854 */ 103 */
855void omap_voltage_reset(struct voltagedomain *voltdm) 104void voltdm_reset(struct voltagedomain *voltdm)
856{ 105{
857 unsigned long target_uvdc; 106 unsigned long target_volt;
858 107
859 if (!voltdm || IS_ERR(voltdm)) { 108 if (!voltdm || IS_ERR(voltdm)) {
860 pr_warning("%s: VDD specified does not exist!\n", __func__); 109 pr_warning("%s: VDD specified does not exist!\n", __func__);
861 return; 110 return;
862 } 111 }
863 112
864 target_uvdc = omap_voltage_get_nom_volt(voltdm); 113 target_volt = voltdm_get_voltage(voltdm);
865 if (!target_uvdc) { 114 if (!target_volt) {
866 pr_err("%s: unable to find current voltage for vdd_%s\n", 115 pr_err("%s: unable to find current voltage for vdd_%s\n",
867 __func__, voltdm->name); 116 __func__, voltdm->name);
868 return; 117 return;
869 } 118 }
870 119
871 omap_voltage_scale_vdd(voltdm, target_uvdc); 120 voltdm_scale(voltdm, target_volt);
872} 121}
873 122
874/** 123/**
@@ -884,18 +133,14 @@ void omap_voltage_reset(struct voltagedomain *voltdm)
884 * 133 *
885 */ 134 */
886void omap_voltage_get_volttable(struct voltagedomain *voltdm, 135void omap_voltage_get_volttable(struct voltagedomain *voltdm,
887 struct omap_volt_data **volt_data) 136 struct omap_volt_data **volt_data)
888{ 137{
889 struct omap_vdd_info *vdd;
890
891 if (!voltdm || IS_ERR(voltdm)) { 138 if (!voltdm || IS_ERR(voltdm)) {
892 pr_warning("%s: VDD specified does not exist!\n", __func__); 139 pr_warning("%s: VDD specified does not exist!\n", __func__);
893 return; 140 return;
894 } 141 }
895 142
896 vdd = container_of(voltdm, struct omap_vdd_info, voltdm); 143 *volt_data = voltdm->volt_data;
897
898 *volt_data = vdd->volt_data;
899} 144}
900 145
901/** 146/**
@@ -914,9 +159,8 @@ void omap_voltage_get_volttable(struct voltagedomain *voltdm,
914 * domain or if there is no matching entry. 159 * domain or if there is no matching entry.
915 */ 160 */
916struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm, 161struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
917 unsigned long volt) 162 unsigned long volt)
918{ 163{
919 struct omap_vdd_info *vdd;
920 int i; 164 int i;
921 165
922 if (!voltdm || IS_ERR(voltdm)) { 166 if (!voltdm || IS_ERR(voltdm)) {
@@ -924,17 +168,15 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
924 return ERR_PTR(-EINVAL); 168 return ERR_PTR(-EINVAL);
925 } 169 }
926 170
927 vdd = container_of(voltdm, struct omap_vdd_info, voltdm); 171 if (!voltdm->volt_data) {
928
929 if (!vdd->volt_data) {
930 pr_warning("%s: voltage table does not exist for vdd_%s\n", 172 pr_warning("%s: voltage table does not exist for vdd_%s\n",
931 __func__, voltdm->name); 173 __func__, voltdm->name);
932 return ERR_PTR(-ENODATA); 174 return ERR_PTR(-ENODATA);
933 } 175 }
934 176
935 for (i = 0; vdd->volt_data[i].volt_nominal != 0; i++) { 177 for (i = 0; voltdm->volt_data[i].volt_nominal != 0; i++) {
936 if (vdd->volt_data[i].volt_nominal == volt) 178 if (voltdm->volt_data[i].volt_nominal == volt)
937 return &vdd->volt_data[i]; 179 return &voltdm->volt_data[i];
938 } 180 }
939 181
940 pr_notice("%s: Unable to match the current voltage with the voltage" 182 pr_notice("%s: Unable to match the current voltage with the voltage"
@@ -947,54 +189,25 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
947 * omap_voltage_register_pmic() - API to register PMIC specific data 189 * omap_voltage_register_pmic() - API to register PMIC specific data
948 * @voltdm: pointer to the VDD for which the PMIC specific data is 190 * @voltdm: pointer to the VDD for which the PMIC specific data is
949 * to be registered 191 * to be registered
950 * @pmic_info: the structure containing pmic info 192 * @pmic: the structure containing pmic info
951 * 193 *
952 * This API is to be called by the SOC/PMIC file to specify the 194 * This API is to be called by the SOC/PMIC file to specify the
953 * pmic specific info as present in omap_volt_pmic_info structure. 195 * pmic specific info as present in omap_voltdm_pmic structure.
954 */ 196 */
955int omap_voltage_register_pmic(struct voltagedomain *voltdm, 197int omap_voltage_register_pmic(struct voltagedomain *voltdm,
956 struct omap_volt_pmic_info *pmic_info) 198 struct omap_voltdm_pmic *pmic)
957{ 199{
958 struct omap_vdd_info *vdd;
959
960 if (!voltdm || IS_ERR(voltdm)) { 200 if (!voltdm || IS_ERR(voltdm)) {
961 pr_warning("%s: VDD specified does not exist!\n", __func__); 201 pr_warning("%s: VDD specified does not exist!\n", __func__);
962 return -EINVAL; 202 return -EINVAL;
963 } 203 }
964 204
965 vdd = container_of(voltdm, struct omap_vdd_info, voltdm); 205 voltdm->pmic = pmic;
966
967 vdd->pmic_info = pmic_info;
968 206
969 return 0; 207 return 0;
970} 208}
971 209
972/** 210/**
973 * omap_voltage_get_dbgdir() - API to get pointer to the debugfs directory
974 * corresponding to a voltage domain.
975 *
976 * @voltdm: pointer to the VDD whose debug directory is required.
977 *
978 * This API returns pointer to the debugfs directory corresponding
979 * to the voltage domain. Should be used by drivers requiring to
980 * add any debug entry for a particular voltage domain. Returns NULL
981 * in case of error.
982 */
983struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm)
984{
985 struct omap_vdd_info *vdd;
986
987 if (!voltdm || IS_ERR(voltdm)) {
988 pr_warning("%s: VDD specified does not exist!\n", __func__);
989 return NULL;
990 }
991
992 vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
993
994 return vdd->debug_dir;
995}
996
997/**
998 * omap_change_voltscale_method() - API to change the voltage scaling method. 211 * omap_change_voltscale_method() - API to change the voltage scaling method.
999 * @voltdm: pointer to the VDD whose voltage scaling method 212 * @voltdm: pointer to the VDD whose voltage scaling method
1000 * has to be changed. 213 * has to be changed.
@@ -1005,23 +218,19 @@ struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm)
1005 * defined in voltage.h 218 * defined in voltage.h
1006 */ 219 */
1007void omap_change_voltscale_method(struct voltagedomain *voltdm, 220void omap_change_voltscale_method(struct voltagedomain *voltdm,
1008 int voltscale_method) 221 int voltscale_method)
1009{ 222{
1010 struct omap_vdd_info *vdd;
1011
1012 if (!voltdm || IS_ERR(voltdm)) { 223 if (!voltdm || IS_ERR(voltdm)) {
1013 pr_warning("%s: VDD specified does not exist!\n", __func__); 224 pr_warning("%s: VDD specified does not exist!\n", __func__);
1014 return; 225 return;
1015 } 226 }
1016 227
1017 vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
1018
1019 switch (voltscale_method) { 228 switch (voltscale_method) {
1020 case VOLTSCALE_VPFORCEUPDATE: 229 case VOLTSCALE_VPFORCEUPDATE:
1021 vdd->volt_scale = vp_forceupdate_scale_voltage; 230 voltdm->scale = omap_vp_forceupdate_scale;
1022 return; 231 return;
1023 case VOLTSCALE_VCBYPASS: 232 case VOLTSCALE_VCBYPASS:
1024 vdd->volt_scale = vc_bypass_scale_voltage; 233 voltdm->scale = omap_vc_bypass_scale;
1025 return; 234 return;
1026 default: 235 default:
1027 pr_warning("%s: Trying to change the method of voltage scaling" 236 pr_warning("%s: Trying to change the method of voltage scaling"
@@ -1030,77 +239,192 @@ void omap_change_voltscale_method(struct voltagedomain *voltdm,
1030} 239}
1031 240
1032/** 241/**
1033 * omap_voltage_domain_lookup() - API to get the voltage domain pointer 242 * omap_voltage_late_init() - Init the various voltage parameters
1034 * @name: Name of the voltage domain
1035 * 243 *
1036 * This API looks up in the global vdd_info struct for the 244 * This API is to be called in the later stages of the
1037 * existence of voltage domain <name>. If it exists, the API returns 245 * system boot to init the voltage controller and
1038 * a pointer to the voltage domain structure corresponding to the 246 * voltage processors.
1039 * VDD<name>. Else retuns error pointer.
1040 */ 247 */
1041struct voltagedomain *omap_voltage_domain_lookup(char *name) 248int __init omap_voltage_late_init(void)
1042{ 249{
1043 int i; 250 struct voltagedomain *voltdm;
1044 251
1045 if (!vdd_info) { 252 if (list_empty(&voltdm_list)) {
1046 pr_err("%s: Voltage driver init not yet happened.Faulting!\n", 253 pr_err("%s: Voltage driver support not added\n",
1047 __func__); 254 __func__);
1048 return ERR_PTR(-EINVAL); 255 return -EINVAL;
1049 } 256 }
1050 257
1051 if (!name) { 258 list_for_each_entry(voltdm, &voltdm_list, node) {
1052 pr_err("%s: No name to get the votage domain!\n", __func__); 259 struct clk *sys_ck;
1053 return ERR_PTR(-EINVAL); 260
261 if (!voltdm->scalable)
262 continue;
263
264 sys_ck = clk_get(NULL, voltdm->sys_clk.name);
265 if (IS_ERR(sys_ck)) {
266 pr_warning("%s: Could not get sys clk.\n", __func__);
267 return -EINVAL;
268 }
269 voltdm->sys_clk.rate = clk_get_rate(sys_ck);
270 WARN_ON(!voltdm->sys_clk.rate);
271 clk_put(sys_ck);
272
273 if (voltdm->vc) {
274 voltdm->scale = omap_vc_bypass_scale;
275 omap_vc_init_channel(voltdm);
276 }
277
278 if (voltdm->vp) {
279 voltdm->scale = omap_vp_forceupdate_scale;
280 omap_vp_init(voltdm);
281 }
1054 } 282 }
1055 283
1056 for (i = 0; i < nr_scalable_vdd; i++) { 284 return 0;
1057 if (!(strcmp(name, vdd_info[i]->voltdm.name))) 285}
1058 return &vdd_info[i]->voltdm; 286
287static struct voltagedomain *_voltdm_lookup(const char *name)
288{
289 struct voltagedomain *voltdm, *temp_voltdm;
290
291 voltdm = NULL;
292
293 list_for_each_entry(temp_voltdm, &voltdm_list, node) {
294 if (!strcmp(name, temp_voltdm->name)) {
295 voltdm = temp_voltdm;
296 break;
297 }
1059 } 298 }
1060 299
1061 return ERR_PTR(-EINVAL); 300 return voltdm;
1062} 301}
1063 302
1064/** 303/**
1065 * omap_voltage_late_init() - Init the various voltage parameters 304 * voltdm_add_pwrdm - add a powerdomain to a voltagedomain
305 * @voltdm: struct voltagedomain * to add the powerdomain to
306 * @pwrdm: struct powerdomain * to associate with a voltagedomain
1066 * 307 *
1067 * This API is to be called in the later stages of the 308 * Associate the powerdomain @pwrdm with a voltagedomain @voltdm. This
1068 * system boot to init the voltage controller and 309 * enables the use of voltdm_for_each_pwrdm(). Returns -EINVAL if
1069 * voltage processors. 310 * presented with invalid pointers; -ENOMEM if memory could not be allocated;
311 * or 0 upon success.
1070 */ 312 */
1071int __init omap_voltage_late_init(void) 313int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm)
1072{ 314{
1073 int i; 315 if (!voltdm || !pwrdm)
316 return -EINVAL;
1074 317
1075 if (!vdd_info) { 318 pr_debug("voltagedomain: associating powerdomain %s with voltagedomain "
1076 pr_err("%s: Voltage driver support not added\n", 319 "%s\n", pwrdm->name, voltdm->name);
1077 __func__); 320
321 list_add(&pwrdm->voltdm_node, &voltdm->pwrdm_list);
322
323 return 0;
324}
325
326/**
327 * voltdm_for_each_pwrdm - call function for each pwrdm in a voltdm
328 * @voltdm: struct voltagedomain * to iterate over
329 * @fn: callback function *
330 *
331 * Call the supplied function @fn for each powerdomain in the
332 * voltagedomain @voltdm. Returns -EINVAL if presented with invalid
333 * pointers; or passes along the last return value of the callback
334 * function, which should be 0 for success or anything else to
335 * indicate failure.
336 */
337int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
338 int (*fn)(struct voltagedomain *voltdm,
339 struct powerdomain *pwrdm))
340{
341 struct powerdomain *pwrdm;
342 int ret = 0;
343
344 if (!fn)
1078 return -EINVAL; 345 return -EINVAL;
1079 }
1080 346
1081 voltage_dir = debugfs_create_dir("voltage", NULL); 347 list_for_each_entry(pwrdm, &voltdm->pwrdm_list, voltdm_node)
1082 if (IS_ERR(voltage_dir)) 348 ret = (*fn)(voltdm, pwrdm);
1083 pr_err("%s: Unable to create voltage debugfs main dir\n", 349
1084 __func__); 350 return ret;
1085 for (i = 0; i < nr_scalable_vdd; i++) { 351}
1086 if (omap_vdd_data_configure(vdd_info[i])) 352
1087 continue; 353/**
1088 omap_vc_init(vdd_info[i]); 354 * voltdm_for_each - call function on each registered voltagedomain
1089 vp_init(vdd_info[i]); 355 * @fn: callback function *
1090 vdd_debugfs_init(vdd_info[i]); 356 *
357 * Call the supplied function @fn for each registered voltagedomain.
358 * The callback function @fn can return anything but 0 to bail out
359 * early from the iterator. Returns the last return value of the
360 * callback function, which should be 0 for success or anything else
361 * to indicate failure; or -EINVAL if the function pointer is null.
362 */
363int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user),
364 void *user)
365{
366 struct voltagedomain *temp_voltdm;
367 int ret = 0;
368
369 if (!fn)
370 return -EINVAL;
371
372 list_for_each_entry(temp_voltdm, &voltdm_list, node) {
373 ret = (*fn)(temp_voltdm, user);
374 if (ret)
375 break;
1091 } 376 }
1092 377
1093 return 0; 378 return ret;
1094} 379}
1095 380
1096/* XXX document */ 381static int _voltdm_register(struct voltagedomain *voltdm)
1097int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_ocp_mod,
1098 struct omap_vdd_info *omap_vdd_array[],
1099 u8 omap_vdd_count)
1100{ 382{
1101 prm_mod_offs = prm_mod; 383 if (!voltdm || !voltdm->name)
1102 prm_irqst_ocp_mod_offs = prm_irqst_ocp_mod; 384 return -EINVAL;
1103 vdd_info = omap_vdd_array; 385
1104 nr_scalable_vdd = omap_vdd_count; 386 INIT_LIST_HEAD(&voltdm->pwrdm_list);
387 list_add(&voltdm->node, &voltdm_list);
388
389 pr_debug("voltagedomain: registered %s\n", voltdm->name);
390
1105 return 0; 391 return 0;
1106} 392}
393
394/**
395 * voltdm_lookup - look up a voltagedomain by name, return a pointer
396 * @name: name of voltagedomain
397 *
398 * Find a registered voltagedomain by its name @name. Returns a pointer
399 * to the struct voltagedomain if found, or NULL otherwise.
400 */
401struct voltagedomain *voltdm_lookup(const char *name)
402{
403 struct voltagedomain *voltdm ;
404
405 if (!name)
406 return NULL;
407
408 voltdm = _voltdm_lookup(name);
409
410 return voltdm;
411}
412
413/**
414 * voltdm_init - set up the voltagedomain layer
415 * @voltdm_list: array of struct voltagedomain pointers to register
416 *
417 * Loop through the array of voltagedomains @voltdm_list, registering all
418 * that are available on the current CPU. If voltdm_list is supplied
419 * and not null, all of the referenced voltagedomains will be
420 * registered. No return value.
421 */
422void voltdm_init(struct voltagedomain **voltdms)
423{
424 struct voltagedomain **v;
425
426 if (voltdms) {
427 for (v = voltdms; *v; v++)
428 _voltdm_register(*v);
429 }
430}
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index e9f5408244e0..4c0980941991 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -19,6 +19,8 @@
19#include "vc.h" 19#include "vc.h"
20#include "vp.h" 20#include "vp.h"
21 21
22struct powerdomain;
23
22/* XXX document */ 24/* XXX document */
23#define VOLTSCALE_VPFORCEUPDATE 1 25#define VOLTSCALE_VPFORCEUPDATE 1
24#define VOLTSCALE_VCBYPASS 2 26#define VOLTSCALE_VCBYPASS 2
@@ -32,29 +34,60 @@
32#define OMAP3_VOLTSETUP2 0xff 34#define OMAP3_VOLTSETUP2 0xff
33 35
34/** 36/**
35 * struct omap_vfsm_instance_data - per-voltage manager FSM register/bitfield 37 * struct omap_vfsm_instance - per-voltage manager FSM register/bitfield
36 * data 38 * data
37 * @voltsetup_mask: SETUP_TIME* bitmask in the PRM_VOLTSETUP* register 39 * @voltsetup_mask: SETUP_TIME* bitmask in the PRM_VOLTSETUP* register
38 * @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base 40 * @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base
39 * @voltsetup_shift: SETUP_TIME* field shift in the PRM_VOLTSETUP* register
40 * 41 *
41 * XXX What about VOLTOFFSET/VOLTCTRL? 42 * XXX What about VOLTOFFSET/VOLTCTRL?
42 * XXX It is not necessary to have both a _mask and a _shift for the same
43 * bitfield - remove one!
44 */ 43 */
45struct omap_vfsm_instance_data { 44struct omap_vfsm_instance {
46 u32 voltsetup_mask; 45 u32 voltsetup_mask;
47 u8 voltsetup_reg; 46 u8 voltsetup_reg;
48 u8 voltsetup_shift;
49}; 47};
50 48
51/** 49/**
52 * struct voltagedomain - omap voltage domain global structure. 50 * struct voltagedomain - omap voltage domain global structure.
53 * @name: Name of the voltage domain which can be used as a unique 51 * @name: Name of the voltage domain which can be used as a unique identifier.
54 * identifier. 52 * @scalable: Whether or not this voltage domain is scalable
53 * @node: list_head linking all voltage domains
54 * @pwrdm_list: list_head linking all powerdomains in this voltagedomain
55 * @vc: pointer to VC channel associated with this voltagedomain
56 * @vp: pointer to VP associated with this voltagedomain
57 * @read: read a VC/VP register
58 * @write: write a VC/VP register
59 * @read: read-modify-write a VC/VP register
60 * @sys_clk: system clock name/frequency, used for various timing calculations
61 * @scale: function used to scale the voltage of the voltagedomain
62 * @nominal_volt: current nominal voltage for this voltage domain
63 * @volt_data: voltage table having the distinct voltages supported
64 * by the domain and other associated per voltage data.
55 */ 65 */
56struct voltagedomain { 66struct voltagedomain {
57 char *name; 67 char *name;
68 bool scalable;
69 struct list_head node;
70 struct list_head pwrdm_list;
71 struct omap_vc_channel *vc;
72 const struct omap_vfsm_instance *vfsm;
73 struct omap_vp_instance *vp;
74 struct omap_voltdm_pmic *pmic;
75
76 /* VC/VP register access functions: SoC specific */
77 u32 (*read) (u8 offset);
78 void (*write) (u32 val, u8 offset);
79 u32 (*rmw)(u32 mask, u32 bits, u8 offset);
80
81 union {
82 const char *name;
83 u32 rate;
84 } sys_clk;
85
86 int (*scale) (struct voltagedomain *voltdm,
87 unsigned long target_volt);
88
89 u32 nominal_volt;
90 struct omap_volt_data *volt_data;
58}; 91};
59 92
60/** 93/**
@@ -77,13 +110,18 @@ struct omap_volt_data {
77}; 110};
78 111
79/** 112/**
80 * struct omap_volt_pmic_info - PMIC specific data required by voltage driver. 113 * struct omap_voltdm_pmic - PMIC specific data required by voltage driver.
81 * @slew_rate: PMIC slew rate (in uv/us) 114 * @slew_rate: PMIC slew rate (in uv/us)
82 * @step_size: PMIC voltage step size (in uv) 115 * @step_size: PMIC voltage step size (in uv)
116 * @i2c_slave_addr: I2C slave address of PMIC
117 * @volt_reg_addr: voltage configuration register address
118 * @cmd_reg_addr: command (on, on-LP, ret, off) configuration register address
119 * @i2c_high_speed: whether VC uses I2C high-speed mode to PMIC
120 * @i2c_mcode: master code value for I2C high-speed preamble transmission
83 * @vsel_to_uv: PMIC API to convert vsel value to actual voltage in uV. 121 * @vsel_to_uv: PMIC API to convert vsel value to actual voltage in uV.
84 * @uv_to_vsel: PMIC API to convert voltage in uV to vsel value. 122 * @uv_to_vsel: PMIC API to convert voltage in uV to vsel value.
85 */ 123 */
86struct omap_volt_pmic_info { 124struct omap_voltdm_pmic {
87 int slew_rate; 125 int slew_rate;
88 int step_size; 126 int step_size;
89 u32 on_volt; 127 u32 on_volt;
@@ -91,81 +129,34 @@ struct omap_volt_pmic_info {
91 u32 ret_volt; 129 u32 ret_volt;
92 u32 off_volt; 130 u32 off_volt;
93 u16 volt_setup_time; 131 u16 volt_setup_time;
132 u16 i2c_slave_addr;
133 u16 volt_reg_addr;
134 u16 cmd_reg_addr;
94 u8 vp_erroroffset; 135 u8 vp_erroroffset;
95 u8 vp_vstepmin; 136 u8 vp_vstepmin;
96 u8 vp_vstepmax; 137 u8 vp_vstepmax;
97 u8 vp_vddmin; 138 u8 vp_vddmin;
98 u8 vp_vddmax; 139 u8 vp_vddmax;
99 u8 vp_timeout_us; 140 u8 vp_timeout_us;
100 u8 i2c_slave_addr; 141 bool i2c_high_speed;
101 u8 pmic_reg; 142 u8 i2c_mcode;
102 unsigned long (*vsel_to_uv) (const u8 vsel); 143 unsigned long (*vsel_to_uv) (const u8 vsel);
103 u8 (*uv_to_vsel) (unsigned long uV); 144 u8 (*uv_to_vsel) (unsigned long uV);
104}; 145};
105 146
106/**
107 * omap_vdd_info - Per Voltage Domain info
108 *
109 * @volt_data : voltage table having the distinct voltages supported
110 * by the domain and other associated per voltage data.
111 * @pmic_info : pmic specific parameters which should be populted by
112 * the pmic drivers.
113 * @vp_data : the register values, shifts, masks for various
114 * vp registers
115 * @vp_rt_data : VP data derived at runtime, not predefined
116 * @vc_data : structure containing various various vc registers,
117 * shifts, masks etc.
118 * @vfsm : voltage manager FSM data
119 * @voltdm : pointer to the voltage domain structure
120 * @debug_dir : debug directory for this voltage domain.
121 * @curr_volt : current voltage for this vdd.
122 * @vp_enabled : flag to keep track of whether vp is enabled or not
123 * @volt_scale : API to scale the voltage of the vdd.
124 */
125struct omap_vdd_info {
126 struct omap_volt_data *volt_data;
127 struct omap_volt_pmic_info *pmic_info;
128 struct omap_vp_instance_data *vp_data;
129 struct omap_vp_runtime_data vp_rt_data;
130 struct omap_vc_instance_data *vc_data;
131 const struct omap_vfsm_instance_data *vfsm;
132 struct voltagedomain voltdm;
133 struct dentry *debug_dir;
134 u32 curr_volt;
135 bool vp_enabled;
136 u32 (*read_reg) (u16 mod, u8 offset);
137 void (*write_reg) (u32 val, u16 mod, u8 offset);
138 int (*volt_scale) (struct omap_vdd_info *vdd,
139 unsigned long target_volt);
140};
141
142unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm);
143void omap_vp_enable(struct voltagedomain *voltdm);
144void omap_vp_disable(struct voltagedomain *voltdm);
145int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
146 unsigned long target_volt);
147void omap_voltage_reset(struct voltagedomain *voltdm);
148void omap_voltage_get_volttable(struct voltagedomain *voltdm, 147void omap_voltage_get_volttable(struct voltagedomain *voltdm,
149 struct omap_volt_data **volt_data); 148 struct omap_volt_data **volt_data);
150struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm, 149struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
151 unsigned long volt); 150 unsigned long volt);
152unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm);
153struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm);
154int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_mod,
155 struct omap_vdd_info *omap_vdd_array[],
156 u8 omap_vdd_count);
157#ifdef CONFIG_PM 151#ifdef CONFIG_PM
158int omap_voltage_register_pmic(struct voltagedomain *voltdm, 152int omap_voltage_register_pmic(struct voltagedomain *voltdm,
159 struct omap_volt_pmic_info *pmic_info); 153 struct omap_voltdm_pmic *pmic);
160void omap_change_voltscale_method(struct voltagedomain *voltdm, 154void omap_change_voltscale_method(struct voltagedomain *voltdm,
161 int voltscale_method); 155 int voltscale_method);
162/* API to get the voltagedomain pointer */
163struct voltagedomain *omap_voltage_domain_lookup(char *name);
164
165int omap_voltage_late_init(void); 156int omap_voltage_late_init(void);
166#else 157#else
167static inline int omap_voltage_register_pmic(struct voltagedomain *voltdm, 158static inline int omap_voltage_register_pmic(struct voltagedomain *voltdm,
168 struct omap_volt_pmic_info *pmic_info) 159 struct omap_voltdm_pmic *pmic)
169{ 160{
170 return -EINVAL; 161 return -EINVAL;
171} 162}
@@ -175,10 +166,21 @@ static inline int omap_voltage_late_init(void)
175{ 166{
176 return -EINVAL; 167 return -EINVAL;
177} 168}
178static inline struct voltagedomain *omap_voltage_domain_lookup(char *name)
179{
180 return ERR_PTR(-EINVAL);
181}
182#endif 169#endif
183 170
171extern void omap2xxx_voltagedomains_init(void);
172extern void omap3xxx_voltagedomains_init(void);
173extern void omap44xx_voltagedomains_init(void);
174
175struct voltagedomain *voltdm_lookup(const char *name);
176void voltdm_init(struct voltagedomain **voltdm_list);
177int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm);
178int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user),
179 void *user);
180int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
181 int (*fn)(struct voltagedomain *voltdm,
182 struct powerdomain *pwrdm));
183int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
184void voltdm_reset(struct voltagedomain *voltdm);
185unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
184#endif 186#endif
diff --git a/arch/arm/mach-omap2/voltagedomains2xxx_data.c b/arch/arm/mach-omap2/voltagedomains2xxx_data.c
new file mode 100644
index 000000000000..7a41349981e5
--- /dev/null
+++ b/arch/arm/mach-omap2/voltagedomains2xxx_data.c
@@ -0,0 +1,32 @@
1/*
2 * OMAP3 voltage domain data
3 *
4 * Copyright (C) 2011 Texas Instruments, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/kernel.h>
11#include <linux/init.h>
12
13#include "voltage.h"
14
15static struct voltagedomain omap2_voltdm_core = {
16 .name = "core",
17};
18
19static struct voltagedomain omap2_voltdm_wkup = {
20 .name = "wakeup",
21};
22
23static struct voltagedomain *voltagedomains_omap2[] __initdata = {
24 &omap2_voltdm_core,
25 &omap2_voltdm_wkup,
26 NULL,
27};
28
29void __init omap2xxx_voltagedomains_init(void)
30{
31 voltdm_init(voltagedomains_omap2);
32}
diff --git a/arch/arm/mach-omap2/voltagedomains3xxx_data.c b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
index def230fd2fde..071101debbbc 100644
--- a/arch/arm/mach-omap2/voltagedomains3xxx_data.c
+++ b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
@@ -31,65 +31,70 @@
31 * VDD data 31 * VDD data
32 */ 32 */
33 33
34static const struct omap_vfsm_instance_data omap3_vdd1_vfsm_data = { 34static const struct omap_vfsm_instance omap3_vdd1_vfsm = {
35 .voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET, 35 .voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
36 .voltsetup_shift = OMAP3430_SETUP_TIME1_SHIFT,
37 .voltsetup_mask = OMAP3430_SETUP_TIME1_MASK, 36 .voltsetup_mask = OMAP3430_SETUP_TIME1_MASK,
38}; 37};
39 38
40static struct omap_vdd_info omap3_vdd1_info = { 39static const struct omap_vfsm_instance omap3_vdd2_vfsm = {
41 .vp_data = &omap3_vp1_data,
42 .vc_data = &omap3_vc1_data,
43 .vfsm = &omap3_vdd1_vfsm_data,
44 .voltdm = {
45 .name = "mpu",
46 },
47};
48
49static const struct omap_vfsm_instance_data omap3_vdd2_vfsm_data = {
50 .voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET, 40 .voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
51 .voltsetup_shift = OMAP3430_SETUP_TIME2_SHIFT,
52 .voltsetup_mask = OMAP3430_SETUP_TIME2_MASK, 41 .voltsetup_mask = OMAP3430_SETUP_TIME2_MASK,
53}; 42};
54 43
55static struct omap_vdd_info omap3_vdd2_info = { 44static struct voltagedomain omap3_voltdm_mpu = {
56 .vp_data = &omap3_vp2_data, 45 .name = "mpu_iva",
57 .vc_data = &omap3_vc2_data, 46 .scalable = true,
58 .vfsm = &omap3_vdd2_vfsm_data, 47 .read = omap3_prm_vcvp_read,
59 .voltdm = { 48 .write = omap3_prm_vcvp_write,
60 .name = "core", 49 .rmw = omap3_prm_vcvp_rmw,
61 }, 50 .vc = &omap3_vc_mpu,
51 .vfsm = &omap3_vdd1_vfsm,
52 .vp = &omap3_vp_mpu,
62}; 53};
63 54
64/* OMAP3 VDD structures */ 55static struct voltagedomain omap3_voltdm_core = {
65static struct omap_vdd_info *omap3_vdd_info[] = { 56 .name = "core",
66 &omap3_vdd1_info, 57 .scalable = true,
67 &omap3_vdd2_info, 58 .read = omap3_prm_vcvp_read,
59 .write = omap3_prm_vcvp_write,
60 .rmw = omap3_prm_vcvp_rmw,
61 .vc = &omap3_vc_core,
62 .vfsm = &omap3_vdd2_vfsm,
63 .vp = &omap3_vp_core,
68}; 64};
69 65
70/* OMAP3 specific voltage init functions */ 66static struct voltagedomain omap3_voltdm_wkup = {
71static int __init omap3xxx_voltage_early_init(void) 67 .name = "wakeup",
72{ 68};
73 s16 prm_mod = OMAP3430_GR_MOD;
74 s16 prm_irqst_ocp_mod = OCP_MOD;
75 69
76 if (!cpu_is_omap34xx()) 70static struct voltagedomain *voltagedomains_omap3[] __initdata = {
77 return 0; 71 &omap3_voltdm_mpu,
72 &omap3_voltdm_core,
73 &omap3_voltdm_wkup,
74 NULL,
75};
76
77static const char *sys_clk_name __initdata = "sys_ck";
78
79void __init omap3xxx_voltagedomains_init(void)
80{
81 struct voltagedomain *voltdm;
82 int i;
78 83
79 /* 84 /*
80 * XXX Will depend on the process, validation, and binning 85 * XXX Will depend on the process, validation, and binning
81 * for the currently-running IC 86 * for the currently-running IC
82 */ 87 */
83 if (cpu_is_omap3630()) { 88 if (cpu_is_omap3630()) {
84 omap3_vdd1_info.volt_data = omap36xx_vddmpu_volt_data; 89 omap3_voltdm_mpu.volt_data = omap36xx_vddmpu_volt_data;
85 omap3_vdd2_info.volt_data = omap36xx_vddcore_volt_data; 90 omap3_voltdm_core.volt_data = omap36xx_vddcore_volt_data;
86 } else { 91 } else {
87 omap3_vdd1_info.volt_data = omap34xx_vddmpu_volt_data; 92 omap3_voltdm_mpu.volt_data = omap34xx_vddmpu_volt_data;
88 omap3_vdd2_info.volt_data = omap34xx_vddcore_volt_data; 93 omap3_voltdm_core.volt_data = omap34xx_vddcore_volt_data;
89 } 94 }
90 95
91 return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod, 96 for (i = 0; voltdm = voltagedomains_omap3[i], voltdm; i++)
92 omap3_vdd_info, 97 voltdm->sys_clk.name = sys_clk_name;
93 ARRAY_SIZE(omap3_vdd_info)); 98
99 voltdm_init(voltagedomains_omap3);
94}; 100};
95core_initcall(omap3xxx_voltage_early_init);
diff --git a/arch/arm/mach-omap2/voltagedomains44xx_data.c b/arch/arm/mach-omap2/voltagedomains44xx_data.c
index cb64996de0e1..c4584e9ac717 100644
--- a/arch/arm/mach-omap2/voltagedomains44xx_data.c
+++ b/arch/arm/mach-omap2/voltagedomains44xx_data.c
@@ -32,71 +32,80 @@
32#include "vc.h" 32#include "vc.h"
33#include "vp.h" 33#include "vp.h"
34 34
35static const struct omap_vfsm_instance_data omap4_vdd_mpu_vfsm_data = { 35static const struct omap_vfsm_instance omap4_vdd_mpu_vfsm = {
36 .voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET, 36 .voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET,
37}; 37};
38 38
39static struct omap_vdd_info omap4_vdd_mpu_info = { 39static const struct omap_vfsm_instance omap4_vdd_iva_vfsm = {
40 .vp_data = &omap4_vp_mpu_data, 40 .voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
41 .vc_data = &omap4_vc_mpu_data,
42 .vfsm = &omap4_vdd_mpu_vfsm_data,
43 .voltdm = {
44 .name = "mpu",
45 },
46}; 41};
47 42
48static const struct omap_vfsm_instance_data omap4_vdd_iva_vfsm_data = { 43static const struct omap_vfsm_instance omap4_vdd_core_vfsm = {
49 .voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET, 44 .voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET,
50}; 45};
51 46
52static struct omap_vdd_info omap4_vdd_iva_info = { 47static struct voltagedomain omap4_voltdm_mpu = {
53 .vp_data = &omap4_vp_iva_data, 48 .name = "mpu",
54 .vc_data = &omap4_vc_iva_data, 49 .scalable = true,
55 .vfsm = &omap4_vdd_iva_vfsm_data, 50 .read = omap4_prm_vcvp_read,
56 .voltdm = { 51 .write = omap4_prm_vcvp_write,
57 .name = "iva", 52 .rmw = omap4_prm_vcvp_rmw,
58 }, 53 .vc = &omap4_vc_mpu,
54 .vfsm = &omap4_vdd_mpu_vfsm,
55 .vp = &omap4_vp_mpu,
59}; 56};
60 57
61static const struct omap_vfsm_instance_data omap4_vdd_core_vfsm_data = { 58static struct voltagedomain omap4_voltdm_iva = {
62 .voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET, 59 .name = "iva",
60 .scalable = true,
61 .read = omap4_prm_vcvp_read,
62 .write = omap4_prm_vcvp_write,
63 .rmw = omap4_prm_vcvp_rmw,
64 .vc = &omap4_vc_iva,
65 .vfsm = &omap4_vdd_iva_vfsm,
66 .vp = &omap4_vp_iva,
63}; 67};
64 68
65static struct omap_vdd_info omap4_vdd_core_info = { 69static struct voltagedomain omap4_voltdm_core = {
66 .vp_data = &omap4_vp_core_data, 70 .name = "core",
67 .vc_data = &omap4_vc_core_data, 71 .scalable = true,
68 .vfsm = &omap4_vdd_core_vfsm_data, 72 .read = omap4_prm_vcvp_read,
69 .voltdm = { 73 .write = omap4_prm_vcvp_write,
70 .name = "core", 74 .rmw = omap4_prm_vcvp_rmw,
71 }, 75 .vc = &omap4_vc_core,
76 .vfsm = &omap4_vdd_core_vfsm,
77 .vp = &omap4_vp_core,
72}; 78};
73 79
74/* OMAP4 VDD structures */ 80static struct voltagedomain omap4_voltdm_wkup = {
75static struct omap_vdd_info *omap4_vdd_info[] = { 81 .name = "wakeup",
76 &omap4_vdd_mpu_info,
77 &omap4_vdd_iva_info,
78 &omap4_vdd_core_info,
79}; 82};
80 83
81/* OMAP4 specific voltage init functions */ 84static struct voltagedomain *voltagedomains_omap4[] __initdata = {
82static int __init omap44xx_voltage_early_init(void) 85 &omap4_voltdm_mpu,
83{ 86 &omap4_voltdm_iva,
84 s16 prm_mod = OMAP4430_PRM_DEVICE_INST; 87 &omap4_voltdm_core,
85 s16 prm_irqst_ocp_mod = OMAP4430_PRM_OCP_SOCKET_INST; 88 &omap4_voltdm_wkup,
89 NULL,
90};
91
92static const char *sys_clk_name __initdata = "sys_clkin_ck";
86 93
87 if (!cpu_is_omap44xx()) 94void __init omap44xx_voltagedomains_init(void)
88 return 0; 95{
96 struct voltagedomain *voltdm;
97 int i;
89 98
90 /* 99 /*
91 * XXX Will depend on the process, validation, and binning 100 * XXX Will depend on the process, validation, and binning
92 * for the currently-running IC 101 * for the currently-running IC
93 */ 102 */
94 omap4_vdd_mpu_info.volt_data = omap44xx_vdd_mpu_volt_data; 103 omap4_voltdm_mpu.volt_data = omap44xx_vdd_mpu_volt_data;
95 omap4_vdd_iva_info.volt_data = omap44xx_vdd_iva_volt_data; 104 omap4_voltdm_iva.volt_data = omap44xx_vdd_iva_volt_data;
96 omap4_vdd_core_info.volt_data = omap44xx_vdd_core_volt_data; 105 omap4_voltdm_core.volt_data = omap44xx_vdd_core_volt_data;
106
107 for (i = 0; voltdm = voltagedomains_omap4[i], voltdm; i++)
108 voltdm->sys_clk.name = sys_clk_name;
97 109
98 return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod, 110 voltdm_init(voltagedomains_omap4);
99 omap4_vdd_info,
100 ARRAY_SIZE(omap4_vdd_info));
101}; 111};
102core_initcall(omap44xx_voltage_early_init);
diff --git a/arch/arm/mach-omap2/vp.c b/arch/arm/mach-omap2/vp.c
new file mode 100644
index 000000000000..66bd700a2b98
--- /dev/null
+++ b/arch/arm/mach-omap2/vp.c
@@ -0,0 +1,278 @@
1#include <linux/kernel.h>
2#include <linux/init.h>
3
4#include <plat/common.h>
5
6#include "voltage.h"
7#include "vp.h"
8#include "prm-regbits-34xx.h"
9#include "prm-regbits-44xx.h"
10#include "prm44xx.h"
11
12static u32 _vp_set_init_voltage(struct voltagedomain *voltdm, u32 volt)
13{
14 struct omap_vp_instance *vp = voltdm->vp;
15 u32 vpconfig;
16 char vsel;
17
18 vsel = voltdm->pmic->uv_to_vsel(volt);
19
20 vpconfig = voltdm->read(vp->vpconfig);
21 vpconfig &= ~(vp->common->vpconfig_initvoltage_mask |
22 vp->common->vpconfig_forceupdate |
23 vp->common->vpconfig_initvdd);
24 vpconfig |= vsel << __ffs(vp->common->vpconfig_initvoltage_mask);
25 voltdm->write(vpconfig, vp->vpconfig);
26
27 /* Trigger initVDD value copy to voltage processor */
28 voltdm->write((vpconfig | vp->common->vpconfig_initvdd),
29 vp->vpconfig);
30
31 /* Clear initVDD copy trigger bit */
32 voltdm->write(vpconfig, vp->vpconfig);
33
34 return vpconfig;
35}
36
37/* Generic voltage init functions */
38void __init omap_vp_init(struct voltagedomain *voltdm)
39{
40 struct omap_vp_instance *vp = voltdm->vp;
41 u32 val, sys_clk_rate, timeout, waittime;
42 u32 vddmin, vddmax, vstepmin, vstepmax;
43
44 if (!voltdm->read || !voltdm->write) {
45 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
46 __func__, voltdm->name);
47 return;
48 }
49
50 vp->enabled = false;
51
52 /* Divide to avoid overflow */
53 sys_clk_rate = voltdm->sys_clk.rate / 1000;
54
55 timeout = (sys_clk_rate * voltdm->pmic->vp_timeout_us) / 1000;
56 vddmin = voltdm->pmic->vp_vddmin;
57 vddmax = voltdm->pmic->vp_vddmax;
58
59 waittime = ((voltdm->pmic->step_size / voltdm->pmic->slew_rate) *
60 sys_clk_rate) / 1000;
61 vstepmin = voltdm->pmic->vp_vstepmin;
62 vstepmax = voltdm->pmic->vp_vstepmax;
63
64 /*
65 * VP_CONFIG: error gain is not set here, it will be updated
66 * on each scale, based on OPP.
67 */
68 val = (voltdm->pmic->vp_erroroffset <<
69 __ffs(voltdm->vp->common->vpconfig_erroroffset_mask)) |
70 vp->common->vpconfig_timeouten;
71 voltdm->write(val, vp->vpconfig);
72
73 /* VSTEPMIN */
74 val = (waittime << vp->common->vstepmin_smpswaittimemin_shift) |
75 (vstepmin << vp->common->vstepmin_stepmin_shift);
76 voltdm->write(val, vp->vstepmin);
77
78 /* VSTEPMAX */
79 val = (vstepmax << vp->common->vstepmax_stepmax_shift) |
80 (waittime << vp->common->vstepmax_smpswaittimemax_shift);
81 voltdm->write(val, vp->vstepmax);
82
83 /* VLIMITTO */
84 val = (vddmax << vp->common->vlimitto_vddmax_shift) |
85 (vddmin << vp->common->vlimitto_vddmin_shift) |
86 (timeout << vp->common->vlimitto_timeout_shift);
87 voltdm->write(val, vp->vlimitto);
88}
89
90int omap_vp_update_errorgain(struct voltagedomain *voltdm,
91 unsigned long target_volt)
92{
93 struct omap_volt_data *volt_data;
94
95 if (!voltdm->vp)
96 return -EINVAL;
97
98 /* Get volt_data corresponding to target_volt */
99 volt_data = omap_voltage_get_voltdata(voltdm, target_volt);
100 if (IS_ERR(volt_data))
101 return -EINVAL;
102
103 /* Setting vp errorgain based on the voltage */
104 voltdm->rmw(voltdm->vp->common->vpconfig_errorgain_mask,
105 volt_data->vp_errgain <<
106 __ffs(voltdm->vp->common->vpconfig_errorgain_mask),
107 voltdm->vp->vpconfig);
108
109 return 0;
110}
111
112/* VP force update method of voltage scaling */
113int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
114 unsigned long target_volt)
115{
116 struct omap_vp_instance *vp = voltdm->vp;
117 u32 vpconfig;
118 u8 target_vsel, current_vsel;
119 int ret, timeout = 0;
120
121 ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
122 if (ret)
123 return ret;
124
125 /*
126 * Clear all pending TransactionDone interrupt/status. Typical latency
127 * is <3us
128 */
129 while (timeout++ < VP_TRANXDONE_TIMEOUT) {
130 vp->common->ops->clear_txdone(vp->id);
131 if (!vp->common->ops->check_txdone(vp->id))
132 break;
133 udelay(1);
134 }
135 if (timeout >= VP_TRANXDONE_TIMEOUT) {
136 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
137 "Voltage change aborted", __func__, voltdm->name);
138 return -ETIMEDOUT;
139 }
140
141 vpconfig = _vp_set_init_voltage(voltdm, target_volt);
142
143 /* Force update of voltage */
144 voltdm->write(vpconfig | vp->common->vpconfig_forceupdate,
145 voltdm->vp->vpconfig);
146
147 /*
148 * Wait for TransactionDone. Typical latency is <200us.
149 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
150 */
151 timeout = 0;
152 omap_test_timeout(vp->common->ops->check_txdone(vp->id),
153 VP_TRANXDONE_TIMEOUT, timeout);
154 if (timeout >= VP_TRANXDONE_TIMEOUT)
155 pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
156 "TRANXDONE never got set after the voltage update\n",
157 __func__, voltdm->name);
158
159 omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
160
161 /*
162 * Disable TransactionDone interrupt , clear all status, clear
163 * control registers
164 */
165 timeout = 0;
166 while (timeout++ < VP_TRANXDONE_TIMEOUT) {
167 vp->common->ops->clear_txdone(vp->id);
168 if (!vp->common->ops->check_txdone(vp->id))
169 break;
170 udelay(1);
171 }
172
173 if (timeout >= VP_TRANXDONE_TIMEOUT)
174 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
175 "to clear the TRANXDONE status\n",
176 __func__, voltdm->name);
177
178 /* Clear force bit */
179 voltdm->write(vpconfig, vp->vpconfig);
180
181 return 0;
182}
183
184/**
185 * omap_vp_enable() - API to enable a particular VP
186 * @voltdm: pointer to the VDD whose VP is to be enabled.
187 *
188 * This API enables a particular voltage processor. Needed by the smartreflex
189 * class drivers.
190 */
191void omap_vp_enable(struct voltagedomain *voltdm)
192{
193 struct omap_vp_instance *vp;
194 u32 vpconfig, volt;
195
196 if (!voltdm || IS_ERR(voltdm)) {
197 pr_warning("%s: VDD specified does not exist!\n", __func__);
198 return;
199 }
200
201 vp = voltdm->vp;
202 if (!voltdm->read || !voltdm->write) {
203 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
204 __func__, voltdm->name);
205 return;
206 }
207
208 /* If VP is already enabled, do nothing. Return */
209 if (vp->enabled)
210 return;
211
212 volt = voltdm_get_voltage(voltdm);
213 if (!volt) {
214 pr_warning("%s: unable to find current voltage for %s\n",
215 __func__, voltdm->name);
216 return;
217 }
218
219 vpconfig = _vp_set_init_voltage(voltdm, volt);
220
221 /* Enable VP */
222 vpconfig |= vp->common->vpconfig_vpenable;
223 voltdm->write(vpconfig, vp->vpconfig);
224
225 vp->enabled = true;
226}
227
228/**
229 * omap_vp_disable() - API to disable a particular VP
230 * @voltdm: pointer to the VDD whose VP is to be disabled.
231 *
232 * This API disables a particular voltage processor. Needed by the smartreflex
233 * class drivers.
234 */
235void omap_vp_disable(struct voltagedomain *voltdm)
236{
237 struct omap_vp_instance *vp;
238 u32 vpconfig;
239 int timeout;
240
241 if (!voltdm || IS_ERR(voltdm)) {
242 pr_warning("%s: VDD specified does not exist!\n", __func__);
243 return;
244 }
245
246 vp = voltdm->vp;
247 if (!voltdm->read || !voltdm->write) {
248 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
249 __func__, voltdm->name);
250 return;
251 }
252
253 /* If VP is already disabled, do nothing. Return */
254 if (!vp->enabled) {
255 pr_warning("%s: Trying to disable VP for vdd_%s when"
256 "it is already disabled\n", __func__, voltdm->name);
257 return;
258 }
259
260 /* Disable VP */
261 vpconfig = voltdm->read(vp->vpconfig);
262 vpconfig &= ~vp->common->vpconfig_vpenable;
263 voltdm->write(vpconfig, vp->vpconfig);
264
265 /*
266 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
267 */
268 omap_test_timeout((voltdm->read(vp->vstatus)),
269 VP_IDLE_TIMEOUT, timeout);
270
271 if (timeout >= VP_IDLE_TIMEOUT)
272 pr_warning("%s: vdd_%s idle timedout\n",
273 __func__, voltdm->name);
274
275 vp->enabled = false;
276
277 return;
278}
diff --git a/arch/arm/mach-omap2/vp.h b/arch/arm/mach-omap2/vp.h
index 7ce134f7de79..7c155d248aa3 100644
--- a/arch/arm/mach-omap2/vp.h
+++ b/arch/arm/mach-omap2/vp.h
@@ -19,44 +19,60 @@
19 19
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21 21
22struct voltagedomain;
23
24/*
25 * Voltage Processor (VP) identifiers
26 */
27#define OMAP3_VP_VDD_MPU_ID 0
28#define OMAP3_VP_VDD_CORE_ID 1
29#define OMAP4_VP_VDD_CORE_ID 0
30#define OMAP4_VP_VDD_IVA_ID 1
31#define OMAP4_VP_VDD_MPU_ID 2
32
22/* XXX document */ 33/* XXX document */
23#define VP_IDLE_TIMEOUT 200 34#define VP_IDLE_TIMEOUT 200
24#define VP_TRANXDONE_TIMEOUT 300 35#define VP_TRANXDONE_TIMEOUT 300
25 36
37/**
38 * struct omap_vp_ops - per-VP operations
39 * @check_txdone: check for VP transaction done
40 * @clear_txdone: clear VP transaction done status
41 */
42struct omap_vp_ops {
43 u32 (*check_txdone)(u8 vp_id);
44 void (*clear_txdone)(u8 vp_id);
45};
26 46
27/** 47/**
28 * struct omap_vp_common_data - register data common to all VDDs 48 * struct omap_vp_common - register data common to all VDDs
49 * @vpconfig_erroroffset_mask: ERROROFFSET bitmask in the PRM_VP*_CONFIG reg
29 * @vpconfig_errorgain_mask: ERRORGAIN bitmask in the PRM_VP*_CONFIG reg 50 * @vpconfig_errorgain_mask: ERRORGAIN bitmask in the PRM_VP*_CONFIG reg
30 * @vpconfig_initvoltage_mask: INITVOLTAGE bitmask in the PRM_VP*_CONFIG reg 51 * @vpconfig_initvoltage_mask: INITVOLTAGE bitmask in the PRM_VP*_CONFIG reg
31 * @vpconfig_timeouten_mask: TIMEOUT bitmask in the PRM_VP*_CONFIG reg 52 * @vpconfig_timeouten: TIMEOUT bitmask in the PRM_VP*_CONFIG reg
32 * @vpconfig_initvdd: INITVDD bitmask in the PRM_VP*_CONFIG reg 53 * @vpconfig_initvdd: INITVDD bitmask in the PRM_VP*_CONFIG reg
33 * @vpconfig_forceupdate: FORCEUPDATE bitmask in the PRM_VP*_CONFIG reg 54 * @vpconfig_forceupdate: FORCEUPDATE bitmask in the PRM_VP*_CONFIG reg
34 * @vpconfig_vpenable: VPENABLE bitmask in the PRM_VP*_CONFIG reg 55 * @vpconfig_vpenable: VPENABLE bitmask in the PRM_VP*_CONFIG reg
35 * @vpconfig_erroroffset_shift: ERROROFFSET field shift in PRM_VP*_CONFIG reg 56 * @vpconfig_erroroffset_shift: ERROROFFSET field shift in PRM_VP*_CONFIG reg
36 * @vpconfig_errorgain_shift: ERRORGAIN field shift in PRM_VP*_CONFIG reg 57 * @vpconfig_errorgain_shift: ERRORGAIN field shift in PRM_VP*_CONFIG reg
37 * @vpconfig_initvoltage_shift: INITVOLTAGE field shift in PRM_VP*_CONFIG reg 58 * @vpconfig_initvoltage_shift: INITVOLTAGE field shift in PRM_VP*_CONFIG reg
38 * @vpconfig_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg 59 * @vstepmin_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg
39 * @vpconfig_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg 60 * @vstepmin_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg
40 * @vpconfig_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg 61 * @vstepmax_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg
41 * @vpconfig_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg 62 * @vstepmax_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg
42 * @vpconfig_vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg 63 * @vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg
43 * @vpconfig_vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg 64 * @vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg
44 * @vpconfig_vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg 65 * @vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg
45 * 66 * @vpvoltage_mask: VPVOLTAGE field mask in PRM_VP*_VOLTAGE reg
46 * XXX It it not necessary to have both a mask and a shift for the same
47 * bitfield - remove one
48 * XXX Many of these fields are wrongly named -- e.g., vpconfig_smps* -- fix!
49 */ 67 */
50struct omap_vp_common_data { 68struct omap_vp_common {
69 u32 vpconfig_erroroffset_mask;
51 u32 vpconfig_errorgain_mask; 70 u32 vpconfig_errorgain_mask;
52 u32 vpconfig_initvoltage_mask; 71 u32 vpconfig_initvoltage_mask;
53 u32 vpconfig_timeouten; 72 u8 vpconfig_timeouten;
54 u32 vpconfig_initvdd; 73 u8 vpconfig_initvdd;
55 u32 vpconfig_forceupdate; 74 u8 vpconfig_forceupdate;
56 u32 vpconfig_vpenable; 75 u8 vpconfig_vpenable;
57 u8 vpconfig_erroroffset_shift;
58 u8 vpconfig_errorgain_shift;
59 u8 vpconfig_initvoltage_shift;
60 u8 vstepmin_stepmin_shift; 76 u8 vstepmin_stepmin_shift;
61 u8 vstepmin_smpswaittimemin_shift; 77 u8 vstepmin_smpswaittimemin_shift;
62 u8 vstepmax_stepmax_shift; 78 u8 vstepmax_stepmax_shift;
@@ -64,80 +80,49 @@ struct omap_vp_common_data {
64 u8 vlimitto_vddmin_shift; 80 u8 vlimitto_vddmin_shift;
65 u8 vlimitto_vddmax_shift; 81 u8 vlimitto_vddmax_shift;
66 u8 vlimitto_timeout_shift; 82 u8 vlimitto_timeout_shift;
67}; 83 u8 vpvoltage_mask;
68 84
69/** 85 const struct omap_vp_ops *ops;
70 * struct omap_vp_prm_irqst_data - PRM_IRQSTATUS_MPU.VP_TRANXDONE_ST data
71 * @prm_irqst_reg: reg offset for PRM_IRQSTATUS_MPU from top of PRM
72 * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
73 *
74 * XXX prm_irqst_reg does not belong here
75 * XXX Note that on OMAP3, VP_TRANXDONE interrupt may not work due to a
76 * hardware bug
77 * XXX This structure is probably not needed
78 */
79struct omap_vp_prm_irqst_data {
80 u8 prm_irqst_reg;
81 u32 tranxdone_status;
82}; 86};
83 87
84/** 88/**
85 * struct omap_vp_instance_data - VP register offsets (per-VDD) 89 * struct omap_vp_instance - VP register offsets (per-VDD)
86 * @vp_common: pointer to struct omap_vp_common_data * for this SoC 90 * @common: pointer to struct omap_vp_common * for this SoC
87 * @prm_irqst_data: pointer to struct omap_vp_prm_irqst_data for this VDD
88 * @vpconfig: PRM_VP*_CONFIG reg offset from PRM start 91 * @vpconfig: PRM_VP*_CONFIG reg offset from PRM start
89 * @vstepmin: PRM_VP*_VSTEPMIN reg offset from PRM start 92 * @vstepmin: PRM_VP*_VSTEPMIN reg offset from PRM start
90 * @vlimitto: PRM_VP*_VLIMITTO reg offset from PRM start 93 * @vlimitto: PRM_VP*_VLIMITTO reg offset from PRM start
91 * @vstatus: PRM_VP*_VSTATUS reg offset from PRM start 94 * @vstatus: PRM_VP*_VSTATUS reg offset from PRM start
92 * @voltage: PRM_VP*_VOLTAGE reg offset from PRM start 95 * @voltage: PRM_VP*_VOLTAGE reg offset from PRM start
96 * @id: Unique identifier for VP instance.
97 * @enabled: flag to keep track of whether vp is enabled or not
93 * 98 *
94 * XXX vp_common is probably not needed since it is per-SoC 99 * XXX vp_common is probably not needed since it is per-SoC
95 */ 100 */
96struct omap_vp_instance_data { 101struct omap_vp_instance {
97 const struct omap_vp_common_data *vp_common; 102 const struct omap_vp_common *common;
98 const struct omap_vp_prm_irqst_data *prm_irqst_data;
99 u8 vpconfig; 103 u8 vpconfig;
100 u8 vstepmin; 104 u8 vstepmin;
101 u8 vstepmax; 105 u8 vstepmax;
102 u8 vlimitto; 106 u8 vlimitto;
103 u8 vstatus; 107 u8 vstatus;
104 u8 voltage; 108 u8 voltage;
109 u8 id;
110 bool enabled;
105}; 111};
106 112
107/** 113extern struct omap_vp_instance omap3_vp_mpu;
108 * struct omap_vp_runtime_data - VP data populated at runtime by code 114extern struct omap_vp_instance omap3_vp_core;
109 * @vpconfig_erroroffset: value of ERROROFFSET bitfield in PRM_VP*_CONFIG
110 * @vpconfig_errorgain: value of ERRORGAIN bitfield in PRM_VP*_CONFIG
111 * @vstepmin_smpswaittimemin: value of SMPSWAITTIMEMIN bitfield in PRM_VP*_VSTEPMIN
112 * @vstepmax_smpswaittimemax: value of SMPSWAITTIMEMAX bitfield in PRM_VP*_VSTEPMAX
113 * @vlimitto_timeout: value of TIMEOUT bitfield in PRM_VP*_VLIMITTO
114 * @vstepmin_stepmin: value of VSTEPMIN bitfield in PRM_VP*_VSTEPMIN
115 * @vstepmax_stepmax: value of VSTEPMAX bitfield in PRM_VP*_VSTEPMAX
116 * @vlimitto_vddmin: value of VDDMIN bitfield in PRM_VP*_VLIMITTO
117 * @vlimitto_vddmax: value of VDDMAX bitfield in PRM_VP*_VLIMITTO
118 *
119 * XXX Is this structure really needed? Why not just program the
120 * device directly? They are in PRM space, therefore in the WKUP
121 * powerdomain, so register contents should not be lost in off-mode.
122 * XXX Some of these fields are incorrectly named, e.g., vstep*
123 */
124struct omap_vp_runtime_data {
125 u32 vpconfig_erroroffset;
126 u16 vpconfig_errorgain;
127 u16 vstepmin_smpswaittimemin;
128 u16 vstepmax_smpswaittimemax;
129 u16 vlimitto_timeout;
130 u8 vstepmin_stepmin;
131 u8 vstepmax_stepmax;
132 u8 vlimitto_vddmin;
133 u8 vlimitto_vddmax;
134};
135 115
136extern struct omap_vp_instance_data omap3_vp1_data; 116extern struct omap_vp_instance omap4_vp_mpu;
137extern struct omap_vp_instance_data omap3_vp2_data; 117extern struct omap_vp_instance omap4_vp_iva;
118extern struct omap_vp_instance omap4_vp_core;
138 119
139extern struct omap_vp_instance_data omap4_vp_mpu_data; 120void omap_vp_init(struct voltagedomain *voltdm);
140extern struct omap_vp_instance_data omap4_vp_iva_data; 121void omap_vp_enable(struct voltagedomain *voltdm);
141extern struct omap_vp_instance_data omap4_vp_core_data; 122void omap_vp_disable(struct voltagedomain *voltdm);
123int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
124 unsigned long target_volt);
125int omap_vp_update_errorgain(struct voltagedomain *voltdm,
126 unsigned long target_volt);
142 127
143#endif 128#endif
diff --git a/arch/arm/mach-omap2/vp3xxx_data.c b/arch/arm/mach-omap2/vp3xxx_data.c
index 645217094e51..260c554b1547 100644
--- a/arch/arm/mach-omap2/vp3xxx_data.c
+++ b/arch/arm/mach-omap2/vp3xxx_data.c
@@ -25,16 +25,20 @@
25#include "voltage.h" 25#include "voltage.h"
26 26
27#include "vp.h" 27#include "vp.h"
28#include "prm2xxx_3xxx.h"
29
30static const struct omap_vp_ops omap3_vp_ops = {
31 .check_txdone = omap3_prm_vp_check_txdone,
32 .clear_txdone = omap3_prm_vp_clear_txdone,
33};
28 34
29/* 35/*
30 * VP data common to 34xx/36xx chips 36 * VP data common to 34xx/36xx chips
31 * XXX This stuff presumably belongs in the vp3xxx.c or vp.c file. 37 * XXX This stuff presumably belongs in the vp3xxx.c or vp.c file.
32 */ 38 */
33static const struct omap_vp_common_data omap3_vp_common = { 39static const struct omap_vp_common omap3_vp_common = {
34 .vpconfig_erroroffset_shift = OMAP3430_ERROROFFSET_SHIFT, 40 .vpconfig_erroroffset_mask = OMAP3430_ERROROFFSET_MASK,
35 .vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK, 41 .vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK,
36 .vpconfig_errorgain_shift = OMAP3430_ERRORGAIN_SHIFT,
37 .vpconfig_initvoltage_shift = OMAP3430_INITVOLTAGE_SHIFT,
38 .vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK, 42 .vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK,
39 .vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK, 43 .vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK,
40 .vpconfig_initvdd = OMAP3430_INITVDD_MASK, 44 .vpconfig_initvdd = OMAP3430_INITVDD_MASK,
@@ -47,36 +51,29 @@ static const struct omap_vp_common_data omap3_vp_common = {
47 .vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT, 51 .vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT,
48 .vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT, 52 .vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT,
49 .vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT, 53 .vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT,
50}; 54 .vpvoltage_mask = OMAP3430_VPVOLTAGE_MASK,
51 55
52static const struct omap_vp_prm_irqst_data omap3_vp1_prm_irqst_data = { 56 .ops = &omap3_vp_ops,
53 .prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
54 .tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
55}; 57};
56 58
57struct omap_vp_instance_data omap3_vp1_data = { 59struct omap_vp_instance omap3_vp_mpu = {
58 .vp_common = &omap3_vp_common, 60 .id = OMAP3_VP_VDD_MPU_ID,
61 .common = &omap3_vp_common,
59 .vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET, 62 .vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET,
60 .vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET, 63 .vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET,
61 .vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET, 64 .vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET,
62 .vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET, 65 .vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET,
63 .vstatus = OMAP3_PRM_VP1_STATUS_OFFSET, 66 .vstatus = OMAP3_PRM_VP1_STATUS_OFFSET,
64 .voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET, 67 .voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET,
65 .prm_irqst_data = &omap3_vp1_prm_irqst_data,
66};
67
68static const struct omap_vp_prm_irqst_data omap3_vp2_prm_irqst_data = {
69 .prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
70 .tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
71}; 68};
72 69
73struct omap_vp_instance_data omap3_vp2_data = { 70struct omap_vp_instance omap3_vp_core = {
74 .vp_common = &omap3_vp_common, 71 .id = OMAP3_VP_VDD_CORE_ID,
72 .common = &omap3_vp_common,
75 .vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET, 73 .vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET,
76 .vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET, 74 .vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET,
77 .vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET, 75 .vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET,
78 .vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET, 76 .vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET,
79 .vstatus = OMAP3_PRM_VP2_STATUS_OFFSET, 77 .vstatus = OMAP3_PRM_VP2_STATUS_OFFSET,
80 .voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET, 78 .voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET,
81 .prm_irqst_data = &omap3_vp2_prm_irqst_data,
82}; 79};
diff --git a/arch/arm/mach-omap2/vp44xx_data.c b/arch/arm/mach-omap2/vp44xx_data.c
index 65d1ad63800a..b4e77044891e 100644
--- a/arch/arm/mach-omap2/vp44xx_data.c
+++ b/arch/arm/mach-omap2/vp44xx_data.c
@@ -27,15 +27,18 @@
27 27
28#include "vp.h" 28#include "vp.h"
29 29
30static const struct omap_vp_ops omap4_vp_ops = {
31 .check_txdone = omap4_prm_vp_check_txdone,
32 .clear_txdone = omap4_prm_vp_clear_txdone,
33};
34
30/* 35/*
31 * VP data common to 44xx chips 36 * VP data common to 44xx chips
32 * XXX This stuff presumably belongs in the vp44xx.c or vp.c file. 37 * XXX This stuff presumably belongs in the vp44xx.c or vp.c file.
33 */ 38 */
34static const struct omap_vp_common_data omap4_vp_common = { 39static const struct omap_vp_common omap4_vp_common = {
35 .vpconfig_erroroffset_shift = OMAP4430_ERROROFFSET_SHIFT, 40 .vpconfig_erroroffset_mask = OMAP4430_ERROROFFSET_MASK,
36 .vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK, 41 .vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK,
37 .vpconfig_errorgain_shift = OMAP4430_ERRORGAIN_SHIFT,
38 .vpconfig_initvoltage_shift = OMAP4430_INITVOLTAGE_SHIFT,
39 .vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK, 42 .vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK,
40 .vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK, 43 .vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK,
41 .vpconfig_initvdd = OMAP4430_INITVDD_MASK, 44 .vpconfig_initvdd = OMAP4430_INITVDD_MASK,
@@ -48,53 +51,39 @@ static const struct omap_vp_common_data omap4_vp_common = {
48 .vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT, 51 .vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT,
49 .vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT, 52 .vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT,
50 .vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT, 53 .vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT,
54 .vpvoltage_mask = OMAP4430_VPVOLTAGE_MASK,
55 .ops = &omap4_vp_ops,
51}; 56};
52 57
53static const struct omap_vp_prm_irqst_data omap4_vp_mpu_prm_irqst_data = { 58struct omap_vp_instance omap4_vp_mpu = {
54 .prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET, 59 .id = OMAP4_VP_VDD_MPU_ID,
55 .tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK, 60 .common = &omap4_vp_common,
56};
57
58struct omap_vp_instance_data omap4_vp_mpu_data = {
59 .vp_common = &omap4_vp_common,
60 .vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET, 61 .vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET,
61 .vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET, 62 .vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET,
62 .vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET, 63 .vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET,
63 .vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET, 64 .vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET,
64 .vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET, 65 .vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET,
65 .voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET, 66 .voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET,
66 .prm_irqst_data = &omap4_vp_mpu_prm_irqst_data,
67}; 67};
68 68
69static const struct omap_vp_prm_irqst_data omap4_vp_iva_prm_irqst_data = { 69struct omap_vp_instance omap4_vp_iva = {
70 .prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET, 70 .id = OMAP4_VP_VDD_IVA_ID,
71 .tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK, 71 .common = &omap4_vp_common,
72};
73
74struct omap_vp_instance_data omap4_vp_iva_data = {
75 .vp_common = &omap4_vp_common,
76 .vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET, 72 .vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET,
77 .vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET, 73 .vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET,
78 .vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET, 74 .vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET,
79 .vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET, 75 .vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET,
80 .vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET, 76 .vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET,
81 .voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET, 77 .voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET,
82 .prm_irqst_data = &omap4_vp_iva_prm_irqst_data,
83};
84
85static const struct omap_vp_prm_irqst_data omap4_vp_core_prm_irqst_data = {
86 .prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
87 .tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
88}; 78};
89 79
90struct omap_vp_instance_data omap4_vp_core_data = { 80struct omap_vp_instance omap4_vp_core = {
91 .vp_common = &omap4_vp_common, 81 .id = OMAP4_VP_VDD_CORE_ID,
82 .common = &omap4_vp_common,
92 .vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET, 83 .vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET,
93 .vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET, 84 .vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET,
94 .vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET, 85 .vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET,
95 .vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET, 86 .vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET,
96 .vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET, 87 .vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET,
97 .voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET, 88 .voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET,
98 .prm_irqst_data = &omap4_vp_core_prm_irqst_data,
99}; 89};
100