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