diff options
Diffstat (limited to 'arch/arm/mach-tegra/board-harmony-power.c')
-rw-r--r-- | arch/arm/mach-tegra/board-harmony-power.c | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/board-harmony-power.c b/arch/arm/mach-tegra/board-harmony-power.c new file mode 100644 index 00000000000..39473f5d9a3 --- /dev/null +++ b/arch/arm/mach-tegra/board-harmony-power.c | |||
@@ -0,0 +1,332 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010-2011 NVIDIA, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
16 | * 02111-1307, USA | ||
17 | */ | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/gpio.h> | ||
21 | |||
22 | #include <linux/regulator/machine.h> | ||
23 | #include <linux/regulator/fixed.h> | ||
24 | #include <linux/mfd/tps6586x.h> | ||
25 | #include <linux/io.h> | ||
26 | |||
27 | #include <mach/iomap.h> | ||
28 | #include <mach/irqs.h> | ||
29 | |||
30 | #include "board-harmony.h" | ||
31 | #include "pm.h" | ||
32 | |||
33 | #define PMC_CTRL 0x0 | ||
34 | #define PMC_CTRL_INTR_LOW (1 << 17) | ||
35 | |||
36 | static struct regulator_consumer_supply tps658621_sm0_supply[] = { | ||
37 | REGULATOR_SUPPLY("vdd_core", NULL), | ||
38 | }; | ||
39 | |||
40 | static struct regulator_consumer_supply tps658621_sm1_supply[] = { | ||
41 | REGULATOR_SUPPLY("vdd_cpu", NULL), | ||
42 | }; | ||
43 | |||
44 | static struct regulator_consumer_supply tps658621_sm2_supply[] = { | ||
45 | REGULATOR_SUPPLY("vdd_sm2", NULL), | ||
46 | }; | ||
47 | |||
48 | static struct regulator_consumer_supply tps658621_ldo0_supply[] = { | ||
49 | REGULATOR_SUPPLY("p_cam_avdd", NULL), | ||
50 | }; | ||
51 | |||
52 | static struct regulator_consumer_supply tps658621_ldo1_supply[] = { | ||
53 | REGULATOR_SUPPLY("avdd_pll", NULL), | ||
54 | }; | ||
55 | |||
56 | static struct regulator_consumer_supply tps658621_ldo2_supply[] = { | ||
57 | REGULATOR_SUPPLY("vdd_rtc", NULL), | ||
58 | }; | ||
59 | |||
60 | static struct regulator_consumer_supply tps658621_ldo3_supply[] = { | ||
61 | REGULATOR_SUPPLY("avdd_usb", NULL), | ||
62 | REGULATOR_SUPPLY("avdd_usb_pll", NULL), | ||
63 | REGULATOR_SUPPLY("avdd_lvds", NULL), | ||
64 | }; | ||
65 | |||
66 | static struct regulator_consumer_supply tps658621_ldo4_supply[] = { | ||
67 | REGULATOR_SUPPLY("avdd_osc", NULL), | ||
68 | REGULATOR_SUPPLY("vddio_sys", "panjit_touch"), | ||
69 | }; | ||
70 | |||
71 | static struct regulator_consumer_supply tps658621_ldo5_supply[] = { | ||
72 | REGULATOR_SUPPLY("vcore_mmc", "sdhci-tegra.1"), | ||
73 | REGULATOR_SUPPLY("vcore_mmc", "sdhci-tegra.3"), | ||
74 | }; | ||
75 | |||
76 | static struct regulator_consumer_supply tps658621_ldo6_supply[] = { | ||
77 | REGULATOR_SUPPLY("avdd_vdac", NULL), | ||
78 | }; | ||
79 | |||
80 | static struct regulator_consumer_supply tps658621_ldo7_supply[] = { | ||
81 | REGULATOR_SUPPLY("avdd_hdmi", NULL), | ||
82 | REGULATOR_SUPPLY("vdd_fuse", NULL), | ||
83 | }; | ||
84 | |||
85 | static struct regulator_consumer_supply tps658621_ldo8_supply[] = { | ||
86 | REGULATOR_SUPPLY("avdd_hdmi_pll", NULL), | ||
87 | }; | ||
88 | |||
89 | static struct regulator_consumer_supply tps658621_ldo9_supply[] = { | ||
90 | REGULATOR_SUPPLY("avdd_2v85", NULL), | ||
91 | REGULATOR_SUPPLY("vdd_ddr_rx", NULL), | ||
92 | REGULATOR_SUPPLY("avdd_amp", NULL), | ||
93 | }; | ||
94 | |||
95 | /* regulator supplies power to WWAN - by default disable */ | ||
96 | static struct regulator_consumer_supply vdd_1v5_consumer_supply[] = { | ||
97 | REGULATOR_SUPPLY("vdd_1v5", NULL), | ||
98 | }; | ||
99 | |||
100 | static struct regulator_init_data vdd_1v5_initdata = { | ||
101 | .consumer_supplies = vdd_1v5_consumer_supply, | ||
102 | .num_consumer_supplies = 1, | ||
103 | .constraints = { | ||
104 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | ||
105 | .always_on = 0, | ||
106 | }, | ||
107 | }; | ||
108 | |||
109 | static struct fixed_voltage_config vdd_1v5 = { | ||
110 | .supply_name = "vdd_1v5", | ||
111 | .microvolts = 1500000, /* Enable 1.5V */ | ||
112 | .gpio = TPS_GPIO_EN_1V5, /* GPIO BASE+0 */ | ||
113 | .startup_delay = 0, | ||
114 | .enable_high = 0, | ||
115 | .enabled_at_boot = 0, | ||
116 | .init_data = &vdd_1v5_initdata, | ||
117 | }; | ||
118 | |||
119 | /* regulator supplies power to WLAN - enable here, to satisfy SDIO probing */ | ||
120 | static struct regulator_consumer_supply vdd_1v2_consumer_supply[] = { | ||
121 | REGULATOR_SUPPLY("vdd_1v2", NULL), | ||
122 | }; | ||
123 | |||
124 | static struct regulator_init_data vdd_1v2_initdata = { | ||
125 | .consumer_supplies = vdd_1v2_consumer_supply, | ||
126 | .num_consumer_supplies = 1, | ||
127 | .constraints = { | ||
128 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | ||
129 | .always_on = 1, | ||
130 | }, | ||
131 | }; | ||
132 | |||
133 | static struct fixed_voltage_config vdd_1v2 = { | ||
134 | .supply_name = "vdd_1v2", | ||
135 | .microvolts = 1200000, /* Enable 1.2V */ | ||
136 | .gpio = TPS_GPIO_EN_1V2, /* GPIO BASE+1 */ | ||
137 | .startup_delay = 0, | ||
138 | .enable_high = 1, | ||
139 | .enabled_at_boot = 1, | ||
140 | .init_data = &vdd_1v2_initdata, | ||
141 | }; | ||
142 | |||
143 | /* regulator supplies power to PLL - enable here */ | ||
144 | static struct regulator_consumer_supply vdd_1v05_consumer_supply[] = { | ||
145 | REGULATOR_SUPPLY("vdd_1v05", NULL), | ||
146 | }; | ||
147 | |||
148 | static struct regulator_init_data vdd_1v05_initdata = { | ||
149 | .consumer_supplies = vdd_1v05_consumer_supply, | ||
150 | .num_consumer_supplies = 1, | ||
151 | .constraints = { | ||
152 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | ||
153 | .always_on = 1, | ||
154 | }, | ||
155 | }; | ||
156 | |||
157 | static struct fixed_voltage_config vdd_1v05 = { | ||
158 | .supply_name = "vdd_1v05", | ||
159 | .microvolts = 1050000, /* Enable 1.05V */ | ||
160 | .gpio = TPS_GPIO_EN_1V05, /* BASE+2 */ | ||
161 | .startup_delay = 0, | ||
162 | .enable_high = 1, | ||
163 | .enabled_at_boot = 0, | ||
164 | .init_data = &vdd_1v05_initdata, | ||
165 | }; | ||
166 | |||
167 | /* mode pin for 1.05V regulator - enable here */ | ||
168 | static struct regulator_consumer_supply vdd_1v05_mode_consumer_supply[] = { | ||
169 | REGULATOR_SUPPLY("vdd_1v05_mode", NULL), | ||
170 | }; | ||
171 | |||
172 | static struct regulator_init_data vdd_1v05_mode_initdata = { | ||
173 | .consumer_supplies = vdd_1v05_mode_consumer_supply, | ||
174 | .num_consumer_supplies = 1, | ||
175 | .constraints = { | ||
176 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | ||
177 | .always_on = 1, | ||
178 | }, | ||
179 | }; | ||
180 | |||
181 | static struct fixed_voltage_config vdd_1v05_mode = { | ||
182 | .supply_name = "vdd_1v05_mode", | ||
183 | .microvolts = 1050000, /* Enable 1.05V */ | ||
184 | .gpio = TPS_GPIO_MODE_1V05, /* BASE+3 */ | ||
185 | .startup_delay = 0, | ||
186 | .enable_high = 1, | ||
187 | .enabled_at_boot = 0, | ||
188 | .init_data = &vdd_1v05_mode_initdata, | ||
189 | }; | ||
190 | |||
191 | #define REGULATOR_INIT(_id, _minmv, _maxmv) \ | ||
192 | { \ | ||
193 | .constraints = { \ | ||
194 | .min_uV = (_minmv)*1000, \ | ||
195 | .max_uV = (_maxmv)*1000, \ | ||
196 | .valid_modes_mask = (REGULATOR_MODE_NORMAL | \ | ||
197 | REGULATOR_MODE_STANDBY), \ | ||
198 | .valid_ops_mask = (REGULATOR_CHANGE_MODE | \ | ||
199 | REGULATOR_CHANGE_STATUS | \ | ||
200 | REGULATOR_CHANGE_VOLTAGE), \ | ||
201 | }, \ | ||
202 | .num_consumer_supplies = ARRAY_SIZE(tps658621_##_id##_supply),\ | ||
203 | .consumer_supplies = tps658621_##_id##_supply, \ | ||
204 | } | ||
205 | |||
206 | static struct regulator_init_data sm0_data = REGULATOR_INIT(sm0, 725, 1500); | ||
207 | static struct regulator_init_data sm1_data = REGULATOR_INIT(sm1, 725, 1500); | ||
208 | static struct regulator_init_data sm2_data = REGULATOR_INIT(sm2, 3000, 4550); | ||
209 | static struct regulator_init_data ldo0_data = REGULATOR_INIT(ldo0, 1250, 3300); | ||
210 | static struct regulator_init_data ldo1_data = REGULATOR_INIT(ldo1, 725, 1500); | ||
211 | static struct regulator_init_data ldo2_data = REGULATOR_INIT(ldo2, 725, 1500); | ||
212 | static struct regulator_init_data ldo3_data = REGULATOR_INIT(ldo3, 1250, 3300); | ||
213 | static struct regulator_init_data ldo4_data = REGULATOR_INIT(ldo4, 1700, 2475); | ||
214 | static struct regulator_init_data ldo5_data = REGULATOR_INIT(ldo5, 1250, 3300); | ||
215 | static struct regulator_init_data ldo6_data = REGULATOR_INIT(ldo6, 1250, 3300); | ||
216 | static struct regulator_init_data ldo7_data = REGULATOR_INIT(ldo7, 1250, 3300); | ||
217 | static struct regulator_init_data ldo8_data = REGULATOR_INIT(ldo8, 1250, 3300); | ||
218 | static struct regulator_init_data ldo9_data = REGULATOR_INIT(ldo9, 1250, 3300); | ||
219 | |||
220 | static struct tps6586x_rtc_platform_data rtc_data = { | ||
221 | .irq = TEGRA_NR_IRQS + TPS6586X_INT_RTC_ALM1, | ||
222 | .start = { | ||
223 | .year = 2009, | ||
224 | .month = 1, | ||
225 | .day = 1, | ||
226 | }, | ||
227 | .cl_sel = TPS6586X_RTC_CL_SEL_1_5PF /* use lowest (external 20pF cap) */ | ||
228 | }; | ||
229 | |||
230 | #define TPS_REG(_id, _data) \ | ||
231 | { \ | ||
232 | .id = TPS6586X_ID_##_id, \ | ||
233 | .name = "tps6586x-regulator", \ | ||
234 | .platform_data = _data, \ | ||
235 | } | ||
236 | |||
237 | #define TPS_GPIO_FIXED_REG(_id, _data) \ | ||
238 | { \ | ||
239 | .id = _id, \ | ||
240 | .name = "reg-fixed-voltage", \ | ||
241 | .platform_data = _data, \ | ||
242 | } | ||
243 | |||
244 | static struct tps6586x_subdev_info tps_devs[] = { | ||
245 | TPS_REG(SM_0, &sm0_data), | ||
246 | TPS_REG(SM_1, &sm1_data), | ||
247 | TPS_REG(SM_2, &sm2_data), | ||
248 | TPS_REG(LDO_0, &ldo0_data), | ||
249 | TPS_REG(LDO_1, &ldo1_data), | ||
250 | TPS_REG(LDO_2, &ldo2_data), | ||
251 | TPS_REG(LDO_3, &ldo3_data), | ||
252 | TPS_REG(LDO_4, &ldo4_data), | ||
253 | TPS_REG(LDO_5, &ldo5_data), | ||
254 | TPS_REG(LDO_6, &ldo6_data), | ||
255 | TPS_REG(LDO_7, &ldo7_data), | ||
256 | TPS_REG(LDO_8, &ldo8_data), | ||
257 | TPS_REG(LDO_9, &ldo9_data), | ||
258 | TPS_GPIO_FIXED_REG(0, &vdd_1v5), | ||
259 | TPS_GPIO_FIXED_REG(1, &vdd_1v2), | ||
260 | TPS_GPIO_FIXED_REG(2, &vdd_1v05), | ||
261 | TPS_GPIO_FIXED_REG(3, &vdd_1v05_mode), | ||
262 | { | ||
263 | .id = 0, | ||
264 | .name = "tps6586x-rtc", | ||
265 | .platform_data = &rtc_data, | ||
266 | }, | ||
267 | }; | ||
268 | |||
269 | static struct tps6586x_platform_data tps_platform = { | ||
270 | .irq_base = TEGRA_NR_IRQS, | ||
271 | .num_subdevs = ARRAY_SIZE(tps_devs), | ||
272 | .subdevs = tps_devs, | ||
273 | .gpio_base = HARMONY_GPIO_TPS6586X(0), | ||
274 | .use_power_off = true, | ||
275 | }; | ||
276 | |||
277 | static struct i2c_board_info __initdata harmony_regulators[] = { | ||
278 | { | ||
279 | I2C_BOARD_INFO("tps6586x", 0x34), | ||
280 | .irq = INT_EXTERNAL_PMU, | ||
281 | .platform_data = &tps_platform, | ||
282 | }, | ||
283 | }; | ||
284 | |||
285 | static void harmony_board_suspend(int lp_state, enum suspend_stage stg) | ||
286 | { | ||
287 | if ((lp_state == TEGRA_SUSPEND_LP1) && (stg == TEGRA_SUSPEND_BEFORE_CPU)) | ||
288 | tegra_console_uart_suspend(); | ||
289 | } | ||
290 | |||
291 | static void harmony_board_resume(int lp_state, enum resume_stage stg) | ||
292 | { | ||
293 | if ((lp_state == TEGRA_SUSPEND_LP1) && (stg == TEGRA_RESUME_AFTER_CPU)) | ||
294 | tegra_console_uart_resume(); | ||
295 | } | ||
296 | |||
297 | static struct tegra_suspend_platform_data harmony_suspend_data = { | ||
298 | /* | ||
299 | * Check power on time and crystal oscillator start time | ||
300 | * for appropriate settings. | ||
301 | */ | ||
302 | .cpu_timer = 5000, | ||
303 | .cpu_off_timer = 5000, | ||
304 | .suspend_mode = TEGRA_SUSPEND_LP0, | ||
305 | .core_timer = 0x7e7e, | ||
306 | .core_off_timer = 0x7f, | ||
307 | .corereq_high = false, | ||
308 | .sysclkreq_high = true, | ||
309 | .board_suspend = harmony_board_suspend, | ||
310 | .board_resume = harmony_board_resume, | ||
311 | }; | ||
312 | |||
313 | int __init harmony_suspend_init(void) | ||
314 | { | ||
315 | tegra_init_suspend(&harmony_suspend_data); | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | int __init harmony_regulator_init(void) | ||
320 | { | ||
321 | void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); | ||
322 | u32 pmc_ctrl; | ||
323 | |||
324 | /* configure the power management controller to trigger PMU | ||
325 | * interrupts when low */ | ||
326 | pmc_ctrl = readl(pmc + PMC_CTRL); | ||
327 | writel(pmc_ctrl | PMC_CTRL_INTR_LOW, pmc + PMC_CTRL); | ||
328 | |||
329 | i2c_register_board_info(4, harmony_regulators, 1); | ||
330 | |||
331 | return 0; | ||
332 | } | ||