ARM: cpu topology: Add debugfs interface for cpu_power
[cmplus.git] / arch / arm / mach-omap2 / omap_tps6236x.c
blob14327faaf88833121eabab67e1e38cc53ed6cb7b
1 /*
2 * OMAP and TPS6236x specific initialization
4 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
5 * Vishwanath BS
6 * Nishanth Menon
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <linux/gpio.h>
16 #include <linux/i2c/twl.h>
18 #include "pm.h"
19 #include "vc.h"
20 #include "mux.h"
22 /* Voltage limits supported */
23 #define MIN_VOLTAGE_TPS62360_62_UV 770000
24 #define MAX_VOLTAGE_TPS62360_62_UV 1400000
26 #define MIN_VOLTAGE_TPS62361_UV 500000
27 #define MAX_VOLTAGE_TPS62361_UV 1770000
29 #define MAX_VOLTAGE_RAMP_TPS6236X_UV 32000
32 * This is the voltage delta between 2 values in voltage register.
33 * when switching voltage V1 to V2, TPS62361 can ramp up or down
34 * initially with step sizes of 20mV with a last step of 10mV.
35 * In the case of TPS6236[0|2], it is a constant 10mV steps
36 * we choose the 10mV step for linearity when SR is configured.
38 #define STEP_SIZE_TPS6236X 10000
40 /* I2C access parameters */
41 #define I2C_TPS6236X_SLAVE_ADDR 0x60
43 #define DEF_SET_REG(VSEL0, VSEL1) (((VSEL1) << 1| (VSEL0) << 0) & 0x3)
44 #define REG_TPS6236X_SET_0 0x00
45 #define REG_TPS6236X_SET_1 0x01
46 #define REG_TPS6236X_SET_2 0x02
47 #define REG_TPS6236X_SET_3 0x03
48 #define REG_TPS6236X_CTRL 0x04
49 #define REG_TPS6236X_TEMP 0x05
50 #define REG_TPS6236X_RAMP_CTRL 0x06
51 #define REG_TPS6236X_CHIP_ID0 0x08
52 #define REG_TPS6236X_CHIP_ID1 0x09
54 #define MODE_TPS6236X_AUTO_PFM_PWM 0x00
55 #define MODE_TPS6236X_FORCE_PWM BIT(7)
57 /* We use Auto PFM/PWM mode currently seems to have the best trade off */
58 #define VOLTAGE_PFM_MODE_VAL MODE_TPS6236X_AUTO_PFM_PWM
60 #define REG_TPS6236X_RAMP_CTRL_RMP_MASK (0x7 << 5)
61 #define REG_TPS6236X_RAMP_CTRL_EN_DISC BIT(2)
62 #define REG_TPS6236X_RAMP_CTRL_RAMP_PFM BIT(1)
64 #define REG_TPS6236X_CTRL_PD_EN BIT(7)
65 #define REG_TPS6236X_CTRL_PD_VSEL0 BIT(6)
66 #define REG_TPS6236X_CTRL_PD_VSEL1 BIT(5)
68 /* TWL usage */
69 #define TWL6030_REG_SYSEN_CFG_GRP 0xB3
70 #define TWL6030_REG_SYSEN_CFG_TRANS 0xB4
71 #define TWL6030_REG_VCORE3_CFG_GRP 0x5E
72 #define TWL6030_REG_VMEM_CFG_GRP 0x64
73 #define TWL6030_REG_MSK_TRANSITION 0x20
74 #define TWL6030_BIT_APE_GRP BIT(0)
75 #define TWL6030_BIT_CON_GRP BIT(1)
76 #define TWL6030_BIT_MOD_GRP BIT(2)
77 #define TWL6030_MSK_PREQ1 BIT(5)
78 #define TWL6030_MSK_SYSEN_OFF (0x3 << 4)
79 #define TWL6030_MSK_SYSEN_SLEEP (0x3 << 2)
80 #define TWL6030_MSK_SYSEN_ACTIVE (0x3 << 0)
82 /* Voltage params of the attached device (all in uV) */
83 static unsigned long voltage_min;
84 static unsigned long voltage_max;
86 /* Which register do we use by default? */
87 static int __initdata default_reg = -1;;
89 /* Do we need to setup internal pullups? */
90 static int __initdata pd_vsel0 = -1;
91 static int __initdata pd_vsel1 = -1;
93 static int __init _bd_setup(char *name,int gpio_vsel, int *pull, int *pd_vsel)
95 int pull_dir;
96 int r;
98 if (gpio_vsel == -1) {
99 if (*pull != -1) {
100 *pd_vsel = (*pull == OMAP_PIN_OFF_OUTPUT_HIGH);
101 *pull = *pd_vsel;
102 } else {
103 *pull = 0;
105 return 0;
108 /* if we have a pull gpio, with bad dir, pull low */
109 if (*pull == -1 || (*pull != OMAP_PIN_OFF_OUTPUT_HIGH &&
110 *pull != OMAP_PIN_OFF_OUTPUT_LOW))
111 *pull = OMAP_PIN_OFF_OUTPUT_LOW;
113 r = omap_mux_init_gpio(gpio_vsel, *pull);
114 if (r) {
115 pr_err("%s: unable to mux gpio%d=%d\n", __func__,
116 gpio_vsel, r);
117 goto out;
120 pull_dir = (*pull == OMAP_PIN_OFF_OUTPUT_HIGH);
121 *pull = pull_dir;
123 r = gpio_request(gpio_vsel, name);
124 if (r) {
125 pr_err("%s: unable to req gpio%d=%d\n", __func__,
126 gpio_vsel, r);
127 goto out;
129 r = gpio_direction_output(gpio_vsel, pull_dir);
130 if (r) {
131 pr_err("%s: unable to pull[%d] gpio%d=%d\n", __func__,
132 gpio_vsel, pull_dir, r);
133 gpio_free(gpio_vsel);
134 goto out;
136 out:
137 return r;
140 /* Convert the ramp voltage to ramp value. */
141 static u8 __init tps6236x_ramp_value(unsigned long uv)
143 if (!uv)
144 return 0;
146 if (uv > MAX_VOLTAGE_RAMP_TPS6236X_UV) {
147 pr_err("%s: uv%ld greater than max %d\n", __func__,
148 uv, MAX_VOLTAGE_RAMP_TPS6236X_UV);
149 uv = MAX_VOLTAGE_RAMP_TPS6236X_UV;
151 return fls(MAX_VOLTAGE_RAMP_TPS6236X_UV / uv) - 1;
154 static unsigned long tps6236x_vsel_to_uv(const u8 vsel)
156 return (voltage_min +
157 (STEP_SIZE_TPS6236X * (vsel & ~VOLTAGE_PFM_MODE_VAL)));
160 static u8 tps6236x_uv_to_vsel(unsigned long uv)
162 if (!uv)
163 return 0;
165 /* Round off requests to limits */
166 if (uv > voltage_max) {
167 pr_err("%s:Request for overvoltage[%ld] than supported[%ld]\n",
168 __func__, uv, voltage_max);
169 uv = voltage_max;
171 if (uv < voltage_min) {
172 pr_err("%s:Request for undervoltage[%ld] than supported[%ld]\n",
173 __func__, uv, voltage_min);
174 uv = voltage_min;
176 return DIV_ROUND_UP(uv - voltage_min, STEP_SIZE_TPS6236X) |
177 VOLTAGE_PFM_MODE_VAL;
180 static struct omap_voltdm_pmic omap4_mpu_pmic = {
181 .slew_rate = 48000,
182 .step_size = STEP_SIZE_TPS6236X,
183 .on_volt = 1375000,
184 .onlp_volt = 1375000,
185 .ret_volt = 750000,
186 .off_volt = 0,
187 .volt_setup_time = 0,
188 .switch_on_time = 1000,
189 .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
190 .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
191 .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
192 .vp_vddmin = OMAP4_VP_MPU_VLIMITTO_VDDMIN,
193 .vp_vddmax = OMAP4_VP_MPU_VLIMITTO_VDDMAX,
194 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
195 .i2c_slave_addr = I2C_TPS6236X_SLAVE_ADDR,
196 .volt_reg_addr = REG_TPS6236X_SET_0,
197 .cmd_reg_addr = REG_TPS6236X_SET_0,
198 .i2c_high_speed = true,
199 .i2c_scll_low = 0x28,
200 .i2c_scll_high = 0x2C,
201 .i2c_hscll_low = 0x0B,
202 .i2c_hscll_high = 0x00,
203 .vsel_to_uv = tps6236x_vsel_to_uv,
204 .uv_to_vsel = tps6236x_uv_to_vsel,
207 /* As per SLVSAU9 */
208 static __initdata struct omap_pmic_description tps_pmic_desc = {
209 .pmic_lp_tshut = 1, /* T-OFF 1ns rounded */
210 .pmic_lp_tstart = 500, /* T-start */
213 * _twl_i2c_rmw_u8() - Tiny helper function to do a read modify write for twl
214 * @mod_no: module number
215 * @mask: mask for the val
216 * @value: value to write
217 * @reg: register to write to
219 static int __init _twl_i2c_rmw_u8(u8 mod_no, u8 mask, u8 value, u8 reg)
221 int ret;
222 u8 val;
224 ret = twl_i2c_read_u8(mod_no, &val, reg);
225 if (ret)
226 goto out;
228 val &= ~mask;
229 val |= (value & mask);
231 ret = twl_i2c_write_u8(mod_no, val, reg);
232 out:
233 return ret;
237 * omap4_twl_tps62361_enable() - Enable tps chip
239 * This function enables TPS chip by associating SYSEN signal
240 * to APE resource group of TWL6030.
242 * Returns 0 on sucess, error is returned if I2C read/write fails.
244 static int __init omap4_twl_tps62361_enable(struct voltagedomain *voltdm)
246 int ret = 0;
247 int ret1;
248 u8 val;
250 /* Dont trust the bootloader. start with max, pm will set to proper */
251 val = voltdm->pmic->uv_to_vsel(voltdm->pmic->vp_vddmax);
252 ret = omap_vc_bypass_send_i2c_msg(voltdm, voltdm->pmic->i2c_slave_addr,
253 default_reg, val);
255 /* Setup Ramp */
256 val = tps6236x_ramp_value(voltdm->pmic->slew_rate) <<
257 __ffs(REG_TPS6236X_RAMP_CTRL_RMP_MASK);
258 val &= REG_TPS6236X_RAMP_CTRL_RMP_MASK;
260 /* We would like to ramp the voltage asap */
261 val |= REG_TPS6236X_RAMP_CTRL_RAMP_PFM;
263 /* We would like to ramp down the voltage asap as well*/
264 val |= REG_TPS6236X_RAMP_CTRL_EN_DISC;
266 ret = omap_vc_bypass_send_i2c_msg(voltdm, voltdm->pmic->i2c_slave_addr,
267 REG_TPS6236X_RAMP_CTRL, val);
268 if (ret)
269 goto out;
271 /* Setup the internal pulls to select if needed */
272 if (pd_vsel0 != -1 || pd_vsel1 != -1) {
273 val = REG_TPS6236X_CTRL_PD_EN;
274 val |= (pd_vsel0) ? 0 : REG_TPS6236X_CTRL_PD_VSEL0;
275 val |= (pd_vsel1) ? 0 : REG_TPS6236X_CTRL_PD_VSEL1;
276 ret = omap_vc_bypass_send_i2c_msg(voltdm,
277 voltdm->pmic->i2c_slave_addr,
278 REG_TPS6236X_CTRL, val);
279 if (ret)
280 goto out;
283 /* Enable thermal shutdown - 0 is enable :) */
284 ret = omap_vc_bypass_send_i2c_msg(voltdm,
285 voltdm->pmic->i2c_slave_addr,
286 REG_TPS6236X_TEMP, 0x0);
287 if (ret)
288 goto out;
290 /* if we have to work with TWL */
291 #ifdef CONFIG_TWL4030_CORE
293 /* unmask PREQ transition Executes ACT2SLP and SLP2ACT sleep sequence */
294 ret1 = _twl_i2c_rmw_u8(TWL6030_MODULE_ID0, TWL6030_MSK_PREQ1,
295 0x00, TWL6030_REG_MSK_TRANSITION);
296 if (ret1) {
297 pr_err("%s:Err:TWL6030: map APE PREQ1(%d)\n", __func__, ret1);
298 ret = ret1;
301 /* Setup SYSEN to be 1 on Active and 0 for sleep and OFF states */
302 ret1 = _twl_i2c_rmw_u8(TWL6030_MODULE_ID0, TWL6030_MSK_SYSEN_ACTIVE,
303 0x01, TWL6030_REG_SYSEN_CFG_TRANS);
304 if (ret1) {
305 pr_err("%s:Err:TWL6030: sysen active(%d)\n", __func__, ret1);
306 ret = ret1;
308 ret1 = _twl_i2c_rmw_u8(TWL6030_MODULE_ID0, TWL6030_MSK_SYSEN_SLEEP,
309 0x00, TWL6030_REG_SYSEN_CFG_TRANS);
310 if (ret1) {
311 pr_err("%s:Err:TWL6030: sysen sleep(%d)\n", __func__, ret1);
312 ret = ret1;
314 ret1 = _twl_i2c_rmw_u8(TWL6030_MODULE_ID0, TWL6030_MSK_SYSEN_OFF,
315 0x00, TWL6030_REG_SYSEN_CFG_TRANS);
316 if (ret1) {
317 pr_err("%s:Err:TWL6030: sysen off(%d)\n", __func__, ret1);
318 ret = ret1;
321 /* Map up SYSEN on TWL core to control TPS */
322 ret1 = _twl_i2c_rmw_u8(TWL6030_MODULE_ID0, TWL6030_BIT_APE_GRP |
323 TWL6030_BIT_MOD_GRP | TWL6030_BIT_CON_GRP,
324 TWL6030_BIT_APE_GRP, TWL6030_REG_SYSEN_CFG_GRP);
325 if (ret1) {
326 pr_err("%s:Err:TWL6030: map APE SYEN(%d)\n", __func__, ret1);
327 ret = ret1;
330 /* Since we dont use VCORE3, this should not be associated with APE */
331 ret1 = _twl_i2c_rmw_u8(TWL6030_MODULE_ID0, TWL6030_BIT_APE_GRP,
332 0x00, TWL6030_REG_VCORE3_CFG_GRP);
333 if (ret1) {
334 pr_err("%s:Err:TWL6030:unmap APE VCORE3(%d)\n", __func__, ret1);
335 ret = ret1;
338 /* Since we dont use VMEM, this should not be associated with APE */
339 ret1 = _twl_i2c_rmw_u8(TWL6030_MODULE_ID0, TWL6030_BIT_APE_GRP,
340 0x00, TWL6030_REG_VMEM_CFG_GRP);
341 if (ret1) {
342 pr_err("%s:Err:TWL6030: unmap APE VMEM(%d)\n", __func__, ret1);
343 ret = ret1;
345 #endif
347 out:
348 if (ret)
349 pr_err("%s: Error enabling TPS(%d)\n", __func__, ret);
351 return ret;
354 static __initdata struct omap_pmic_map omap_tps_map[] = {
356 .name = "mpu",
357 .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP446X),
358 .pmic_data = &omap4_mpu_pmic,
359 .special_action = omap4_twl_tps62361_enable,
361 /* Terminator */
362 { .name = NULL,.pmic_data = NULL},
365 int __init omap_tps6236x_init(void)
367 struct omap_pmic_map *map;
369 /* Without registers, I wont proceed */
370 if (default_reg == -1)
371 return -EINVAL;
373 map = omap_tps_map;
375 /* setup all the pmic's voltage addresses to the default one */
376 while (map->name) {
377 map->pmic_data->volt_reg_addr = default_reg;
378 map->pmic_data->cmd_reg_addr = default_reg;
379 map++;
382 return omap_pmic_register_data(omap_tps_map, &tps_pmic_desc);
386 * omap_tps6236x_board_setup() - provide the board config for TPS connect
387 * @use_62361: Do we use TPS62361 variant?
388 * @gpio_vsel0: If using GPIO to control VSEL0, provide gpio number, else -1
389 * @gpio_vsel1: If using GPIO to control VSEL1, provide gpio number, else -1
390 * @pull0: If using GPIO, provide mux mode OMAP_PIN_OFF_OUTPUT_[HIGH|LOW]
391 * else provide any internal pull required, -1 if unused.
392 * @pull1: If using GPIO, provide mux mode OMAP_PIN_OFF_OUTPUT_[HIGH|LOW]
393 * else provide any internal pull required, -1 if unused.
395 * TPS6236x variants of PMIC can be hooked in numerous combinations on to the
396 * board. Some platforms can choose to hardwire and save on a GPIO for other
397 * uses, while others may hook a single line for GPIO control and may ground
398 * the other line. support these configurations.
400 * WARNING: for platforms using GPIO, be careful to provide MUX setting
401 * considering OFF mode configuration as well.
403 int __init omap_tps6236x_board_setup(bool use_62361, int gpio_vsel0,
404 int gpio_vsel1, int pull0, int pull1)
406 int r;
408 r = _bd_setup("tps6236x_vsel0", gpio_vsel0, &pull0, &pd_vsel0);
409 if (r)
410 goto out;
411 r = _bd_setup("tps6236x_vsel1", gpio_vsel1, &pull1, &pd_vsel1);
412 if (r) {
413 if (gpio_vsel0 != -1)
414 gpio_free(gpio_vsel0);
415 goto out;
418 default_reg = ((pull1 & 0x1) << 1) | (pull0 & 0x1);
420 if (use_62361) {
421 voltage_min = MIN_VOLTAGE_TPS62361_UV;
422 voltage_max = MAX_VOLTAGE_TPS62361_UV;
423 } else {
424 voltage_min = MIN_VOLTAGE_TPS62360_62_UV;
425 voltage_max = MAX_VOLTAGE_TPS62360_62_UV;
427 out:
428 return r;
431 int __init omap_tps6236x_update(char *name, u32 old_chip_id, u32 new_chip_id)
433 return omap_pmic_update(omap_tps_map, name, old_chip_id, new_chip_id);