blob: 27952f4abc1bd8789912ba27a32fba106d46c923 [file] [log] [blame]
Jay Chokshie8741282012-01-25 15:22:55 -08001/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -08002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/init.h>
15#include <linux/ioport.h>
16#include <linux/platform_device.h>
17#include <linux/bootmem.h>
Jay Chokshie8741282012-01-25 15:22:55 -080018#include <linux/mfd/pm8xxx/pm8921.h>
19#include <linux/leds.h>
20#include <linux/leds-pm8xxx.h>
Jay Chokshif3a9ea82012-01-12 16:34:43 -080021#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -080022#include <asm/mach-types.h>
23#include <asm/mach/mmc.h>
24#include <mach/msm_bus_board.h>
25#include <mach/board.h>
26#include <mach/gpio.h>
27#include <mach/gpiomux.h>
Jay Chokshie8741282012-01-25 15:22:55 -080028#include <mach/restart.h>
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -080029#include "devices.h"
30#include "board-8064.h"
31
Jay Chokshie8741282012-01-25 15:22:55 -080032struct pm8xxx_gpio_init {
33 unsigned gpio;
34 struct pm_gpio config;
35};
36
37struct pm8xxx_mpp_init {
38 unsigned mpp;
39 struct pm8xxx_mpp_config_data config;
40};
41
42#define PM8921_GPIO_INIT(_gpio, _dir, _buf, _val, _pull, _vin, _out_strength, \
43 _func, _inv, _disable) \
44{ \
45 .gpio = PM8921_GPIO_PM_TO_SYS(_gpio), \
46 .config = { \
47 .direction = _dir, \
48 .output_buffer = _buf, \
49 .output_value = _val, \
50 .pull = _pull, \
51 .vin_sel = _vin, \
52 .out_strength = _out_strength, \
53 .function = _func, \
54 .inv_int_pol = _inv, \
55 .disable_pin = _disable, \
56 } \
57}
58
59#define PM8921_MPP_INIT(_mpp, _type, _level, _control) \
60{ \
61 .mpp = PM8921_MPP_PM_TO_SYS(_mpp), \
62 .config = { \
63 .type = PM8XXX_MPP_TYPE_##_type, \
64 .level = _level, \
65 .control = PM8XXX_MPP_##_control, \
66 } \
67}
68
69#define PM8821_MPP_INIT(_mpp, _type, _level, _control) \
70{ \
71 .mpp = PM8821_MPP_PM_TO_SYS(_mpp), \
72 .config = { \
73 .type = PM8XXX_MPP_TYPE_##_type, \
74 .level = _level, \
75 .control = PM8XXX_MPP_##_control, \
76 } \
77}
78
79#define PM8921_GPIO_DISABLE(_gpio) \
80 PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, 0, 0, 0, PM_GPIO_VIN_S4, \
81 0, 0, 0, 1)
82
83#define PM8921_GPIO_OUTPUT(_gpio, _val, _strength) \
84 PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
85 PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
86 PM_GPIO_STRENGTH_##_strength, \
87 PM_GPIO_FUNC_NORMAL, 0, 0)
88
Jay Chokshi1de4f9d2012-02-07 16:11:31 -080089#define PM8921_GPIO_OUTPUT_BUFCONF(_gpio, _val, _strength, _bufconf) \
90 PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT,\
91 PM_GPIO_OUT_BUF_##_bufconf, _val, \
92 PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
93 PM_GPIO_STRENGTH_##_strength, \
94 PM_GPIO_FUNC_NORMAL, 0, 0)
95
Jay Chokshie8741282012-01-25 15:22:55 -080096#define PM8921_GPIO_INPUT(_gpio, _pull) \
97 PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0, \
98 _pull, PM_GPIO_VIN_S4, \
99 PM_GPIO_STRENGTH_NO, \
100 PM_GPIO_FUNC_NORMAL, 0, 0)
101
102#define PM8921_GPIO_OUTPUT_FUNC(_gpio, _val, _func) \
103 PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
104 PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
105 PM_GPIO_STRENGTH_HIGH, \
106 _func, 0, 0)
107
108#define PM8921_GPIO_OUTPUT_VIN(_gpio, _val, _vin) \
109 PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
110 PM_GPIO_PULL_NO, _vin, \
111 PM_GPIO_STRENGTH_HIGH, \
112 PM_GPIO_FUNC_NORMAL, 0, 0)
113
114/* Initial PM8921 GPIO configurations */
115static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
David Collins390fc332012-02-07 14:38:16 -0800116 PM8921_GPIO_OUTPUT(23, 0, HIGH), /* touchscreen power FET */
Jay Chokshi1de4f9d2012-02-07 16:11:31 -0800117 PM8921_GPIO_OUTPUT_BUFCONF(25, 0, LOW, CMOS), /* DISP_RESET_N */
118 PM8921_GPIO_OUTPUT_FUNC(26, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
119 PM8921_GPIO_OUTPUT_BUFCONF(36, 1, LOW, OPEN_DRAIN),
Amy Maloche70090f992012-02-16 16:35:26 -0800120 PM8921_GPIO_OUTPUT_FUNC(44, 0, PM_GPIO_FUNC_2),
121 PM8921_GPIO_OUTPUT(33, 0, HIGH),
122 PM8921_GPIO_OUTPUT(20, 0, HIGH),
Mohan Pallaka474b94b2012-01-25 12:59:58 +0530123 PM8921_GPIO_INPUT(35, PM_GPIO_PULL_UP_1P5),
124 PM8921_GPIO_INPUT(38, PM_GPIO_PULL_UP_1P5),
125};
126
127static struct pm8xxx_gpio_init pm8921_mtp_kp_gpios[] __initdata = {
128 PM8921_GPIO_INPUT(3, PM_GPIO_PULL_UP_1P5),
129 PM8921_GPIO_INPUT(4, PM_GPIO_PULL_UP_1P5),
130};
131
132static struct pm8xxx_gpio_init pm8921_cdp_kp_gpios[] __initdata = {
133 PM8921_GPIO_INPUT(37, PM_GPIO_PULL_UP_1P5),
Jay Chokshie8741282012-01-25 15:22:55 -0800134};
135
136/* Initial PM8XXX MPP configurations */
137static struct pm8xxx_mpp_init pm8xxx_mpps[] __initdata = {
Jay Chokshi1de4f9d2012-02-07 16:11:31 -0800138 PM8921_MPP_INIT(3, D_OUTPUT, PM8921_MPP_DIG_LEVEL_VPH, DOUT_CTRL_LOW),
David Collinsf0d00732012-01-25 15:46:50 -0800139 /* External 5V regulator enable; shared by HDMI and USB_OTG switches. */
Jay Chokshi1de4f9d2012-02-07 16:11:31 -0800140 PM8921_MPP_INIT(7, D_OUTPUT, PM8921_MPP_DIG_LEVEL_VPH, DOUT_CTRL_LOW),
141 PM8921_MPP_INIT(8, D_OUTPUT, PM8921_MPP_DIG_LEVEL_S4, DOUT_CTRL_LOW),
Jay Chokshie8741282012-01-25 15:22:55 -0800142};
143
144void __init apq8064_pm8xxx_gpio_mpp_init(void)
145{
146 int i, rc;
147
148 for (i = 0; i < ARRAY_SIZE(pm8921_gpios); i++) {
149 rc = pm8xxx_gpio_config(pm8921_gpios[i].gpio,
150 &pm8921_gpios[i].config);
151 if (rc) {
152 pr_err("%s: pm8xxx_gpio_config: rc=%d\n", __func__, rc);
153 break;
154 }
155 }
156
Mohan Pallaka474b94b2012-01-25 12:59:58 +0530157 if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
158 for (i = 0; i < ARRAY_SIZE(pm8921_cdp_kp_gpios); i++) {
159 rc = pm8xxx_gpio_config(pm8921_cdp_kp_gpios[i].gpio,
160 &pm8921_cdp_kp_gpios[i].config);
161 if (rc) {
162 pr_err("%s: pm8xxx_gpio_config: rc=%d\n",
163 __func__, rc);
164 break;
165 }
166 }
167
168 if (machine_is_apq8064_mtp())
169 for (i = 0; i < ARRAY_SIZE(pm8921_mtp_kp_gpios); i++) {
170 rc = pm8xxx_gpio_config(pm8921_mtp_kp_gpios[i].gpio,
171 &pm8921_mtp_kp_gpios[i].config);
172 if (rc) {
173 pr_err("%s: pm8xxx_gpio_config: rc=%d\n",
174 __func__, rc);
175 break;
176 }
177 }
178
Jay Chokshie8741282012-01-25 15:22:55 -0800179 for (i = 0; i < ARRAY_SIZE(pm8xxx_mpps); i++) {
180 rc = pm8xxx_mpp_config(pm8xxx_mpps[i].mpp,
181 &pm8xxx_mpps[i].config);
182 if (rc) {
183 pr_err("%s: pm8xxx_mpp_config: rc=%d\n", __func__, rc);
184 break;
185 }
186 }
187}
188
189static struct pm8xxx_pwrkey_platform_data apq8064_pm8921_pwrkey_pdata = {
190 .pull_up = 1,
191 .kpd_trigger_delay_us = 15625,
192 .wakeup = 1,
193};
194
195static struct pm8xxx_misc_platform_data apq8064_pm8921_misc_pdata = {
196 .priority = 0,
197};
198
199#define PM8921_LC_LED_MAX_CURRENT 4 /* I = 4mA */
200#define PM8921_LC_LED_LOW_CURRENT 1 /* I = 1mA */
201#define PM8XXX_LED_PWM_PERIOD 1000
202#define PM8XXX_LED_PWM_DUTY_MS 20
203/**
204 * PM8XXX_PWM_CHANNEL_NONE shall be used when LED shall not be
205 * driven using PWM feature.
206 */
207#define PM8XXX_PWM_CHANNEL_NONE -1
208
209static struct led_info pm8921_led_info[] = {
210 [0] = {
211 .name = "led:red",
212 .default_trigger = "ac-online",
213 },
214};
215
216static struct led_platform_data pm8921_led_core_pdata = {
217 .num_leds = ARRAY_SIZE(pm8921_led_info),
218 .leds = pm8921_led_info,
219};
220
221static int pm8921_led0_pwm_duty_pcts[56] = {
222 1, 4, 8, 12, 16, 20, 24, 28, 32, 36,
223 40, 44, 46, 52, 56, 60, 64, 68, 72, 76,
224 80, 84, 88, 92, 96, 100, 100, 100, 98, 95,
225 92, 88, 84, 82, 78, 74, 70, 66, 62, 58,
226 58, 54, 50, 48, 42, 38, 34, 30, 26, 22,
227 14, 10, 6, 4, 1
228};
229
230static struct pm8xxx_pwm_duty_cycles pm8921_led0_pwm_duty_cycles = {
231 .duty_pcts = (int *)&pm8921_led0_pwm_duty_pcts,
232 .num_duty_pcts = ARRAY_SIZE(pm8921_led0_pwm_duty_pcts),
233 .duty_ms = PM8XXX_LED_PWM_DUTY_MS,
234 .start_idx = 0,
235};
236
237static struct pm8xxx_led_config pm8921_led_configs[] = {
238 [0] = {
239 .id = PM8XXX_ID_LED_0,
240 .mode = PM8XXX_LED_MODE_PWM2,
241 .max_current = PM8921_LC_LED_MAX_CURRENT,
242 .pwm_channel = 5,
243 .pwm_period_us = PM8XXX_LED_PWM_PERIOD,
244 .pwm_duty_cycles = &pm8921_led0_pwm_duty_cycles,
245 },
246};
247
248static struct pm8xxx_led_platform_data apq8064_pm8921_leds_pdata = {
249 .led_core = &pm8921_led_core_pdata,
250 .configs = pm8921_led_configs,
251 .num_configs = ARRAY_SIZE(pm8921_led_configs),
252};
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800253
Jay Chokshif3a9ea82012-01-12 16:34:43 -0800254static struct pm8xxx_adc_amux apq8064_pm8921_adc_channels_data[] = {
255 {"vcoin", CHANNEL_VCOIN, CHAN_PATH_SCALING2, AMUX_RSV1,
256 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
257 {"vbat", CHANNEL_VBAT, CHAN_PATH_SCALING2, AMUX_RSV1,
258 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
259 {"dcin", CHANNEL_DCIN, CHAN_PATH_SCALING4, AMUX_RSV1,
260 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
261 {"ichg", CHANNEL_ICHG, CHAN_PATH_SCALING1, AMUX_RSV1,
262 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
263 {"vph_pwr", CHANNEL_VPH_PWR, CHAN_PATH_SCALING2, AMUX_RSV1,
264 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
265 {"ibat", CHANNEL_IBAT, CHAN_PATH_SCALING1, AMUX_RSV1,
266 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
267 {"batt_therm", CHANNEL_BATT_THERM, CHAN_PATH_SCALING1, AMUX_RSV2,
268 ADC_DECIMATION_TYPE2, ADC_SCALE_BATT_THERM},
269 {"batt_id", CHANNEL_BATT_ID, CHAN_PATH_SCALING1, AMUX_RSV1,
270 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
271 {"usbin", CHANNEL_USBIN, CHAN_PATH_SCALING3, AMUX_RSV1,
272 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
273 {"pmic_therm", CHANNEL_DIE_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
274 ADC_DECIMATION_TYPE2, ADC_SCALE_PMIC_THERM},
275 {"625mv", CHANNEL_625MV, CHAN_PATH_SCALING1, AMUX_RSV1,
276 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
277 {"125v", CHANNEL_125V, CHAN_PATH_SCALING1, AMUX_RSV1,
278 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
279 {"chg_temp", CHANNEL_CHG_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
280 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
281 {"xo_therm", CHANNEL_MUXOFF, CHAN_PATH_SCALING1, AMUX_RSV0,
282 ADC_DECIMATION_TYPE2, ADC_SCALE_XOTHERM},
283};
284
285static struct pm8xxx_adc_properties apq8064_pm8921_adc_data = {
286 .adc_vdd_reference = 1800, /* milli-voltage for this adc */
287 .bitresolution = 15,
288 .bipolar = 0,
289};
290
291static struct pm8xxx_adc_platform_data apq8064_pm8921_adc_pdata = {
292 .adc_channel = apq8064_pm8921_adc_channels_data,
293 .adc_num_board_channel = ARRAY_SIZE(apq8064_pm8921_adc_channels_data),
294 .adc_prop = &apq8064_pm8921_adc_data,
295 .adc_mpp_base = PM8921_MPP_PM_TO_SYS(1),
296};
297
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800298static struct pm8xxx_mpp_platform_data
299apq8064_pm8921_mpp_pdata __devinitdata = {
300 .mpp_base = PM8921_MPP_PM_TO_SYS(1),
301};
302
303static struct pm8xxx_gpio_platform_data
304apq8064_pm8921_gpio_pdata __devinitdata = {
305 .gpio_base = PM8921_GPIO_PM_TO_SYS(1),
306};
307
308static struct pm8xxx_irq_platform_data
309apq8064_pm8921_irq_pdata __devinitdata = {
310 .irq_base = PM8921_IRQ_BASE,
311 .devirq = PM8921_USR_IRQ_N,
312 .irq_trigger_flag = IRQF_TRIGGER_HIGH,
313 .dev_id = 0,
314};
315
Ashay Jaiswal0b023dc2012-01-25 10:18:36 +0530316static struct pm8xxx_rtc_platform_data
317apq8064_pm8921_rtc_pdata = {
318 .rtc_write_enable = false,
319 .rtc_alarm_powerup = false,
320};
321
Jay Chokshi42fe9f02012-02-01 20:52:08 -0800322static int apq8064_pm8921_therm_mitigation[] = {
323 1100,
324 700,
325 600,
326 325,
327};
328
329#define MAX_VOLTAGE_MV 4200
330static struct pm8921_charger_platform_data
331apq8064_pm8921_chg_pdata __devinitdata = {
332 .safety_time = 180,
333 .update_time = 60000,
334 .max_voltage = MAX_VOLTAGE_MV,
335 .min_voltage = 3200,
336 .resume_voltage_delta = 100,
337 .term_current = 100,
338 .cool_temp = 10,
339 .warm_temp = 40,
340 .temp_check_period = 1,
341 .max_bat_chg_current = 1100,
342 .cool_bat_chg_current = 350,
343 .warm_bat_chg_current = 350,
344 .cool_bat_voltage = 4100,
345 .warm_bat_voltage = 4100,
346 .thermal_mitigation = apq8064_pm8921_therm_mitigation,
347 .thermal_levels = ARRAY_SIZE(apq8064_pm8921_therm_mitigation),
348};
349
350static struct pm8xxx_ccadc_platform_data
351apq8064_pm8xxx_ccadc_pdata = {
352 .r_sense = 10,
353};
354
355static struct pm8921_bms_platform_data
356apq8064_pm8921_bms_pdata __devinitdata = {
357 .r_sense = 10,
358 .i_test = 2500,
359 .v_failure = 3000,
360 .calib_delay_ms = 600000,
361 .max_voltage_uv = MAX_VOLTAGE_MV * 1000,
362};
363
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800364static struct pm8921_platform_data
365apq8064_pm8921_platform_data __devinitdata = {
366 .regulator_pdatas = msm8064_pm8921_regulator_pdata,
367 .irq_pdata = &apq8064_pm8921_irq_pdata,
368 .gpio_pdata = &apq8064_pm8921_gpio_pdata,
369 .mpp_pdata = &apq8064_pm8921_mpp_pdata,
Ashay Jaiswal0b023dc2012-01-25 10:18:36 +0530370 .rtc_pdata = &apq8064_pm8921_rtc_pdata,
Jay Chokshie8741282012-01-25 15:22:55 -0800371 .pwrkey_pdata = &apq8064_pm8921_pwrkey_pdata,
372 .misc_pdata = &apq8064_pm8921_misc_pdata,
373 .leds_pdata = &apq8064_pm8921_leds_pdata,
Jay Chokshif3a9ea82012-01-12 16:34:43 -0800374 .adc_pdata = &apq8064_pm8921_adc_pdata,
Jay Chokshi42fe9f02012-02-01 20:52:08 -0800375 .charger_pdata = &apq8064_pm8921_chg_pdata,
376 .bms_pdata = &apq8064_pm8921_bms_pdata,
377 .ccadc_pdata = &apq8064_pm8xxx_ccadc_pdata,
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800378};
379
380static struct pm8xxx_irq_platform_data
381apq8064_pm8821_irq_pdata __devinitdata = {
382 .irq_base = PM8821_IRQ_BASE,
Jay Chokshie8741282012-01-25 15:22:55 -0800383 .devirq = PM8821_SEC_IRQ_N,
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800384 .irq_trigger_flag = IRQF_TRIGGER_HIGH,
385 .dev_id = 1,
386};
387
388static struct pm8xxx_mpp_platform_data
389apq8064_pm8821_mpp_pdata __devinitdata = {
390 .mpp_base = PM8821_MPP_PM_TO_SYS(1),
391};
392
393static struct pm8821_platform_data
394apq8064_pm8821_platform_data __devinitdata = {
395 .irq_pdata = &apq8064_pm8821_irq_pdata,
396 .mpp_pdata = &apq8064_pm8821_mpp_pdata,
397};
398
399static struct msm_ssbi_platform_data apq8064_ssbi_pm8921_pdata __devinitdata = {
400 .controller_type = MSM_SBI_CTRL_PMIC_ARBITER,
401 .slave = {
402 .name = "pm8921-core",
403 .platform_data = &apq8064_pm8921_platform_data,
404 },
405};
406
407static struct msm_ssbi_platform_data apq8064_ssbi_pm8821_pdata __devinitdata = {
408 .controller_type = MSM_SBI_CTRL_PMIC_ARBITER,
409 .slave = {
410 .name = "pm8821-core",
411 .platform_data = &apq8064_pm8821_platform_data,
412 },
413};
414
415void __init apq8064_init_pmic(void)
416{
Jay Chokshie8741282012-01-25 15:22:55 -0800417 pmic_reset_irq = PM8921_IRQ_BASE + PM8921_RESOUT_IRQ;
418
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800419 apq8064_device_ssbi_pmic1.dev.platform_data =
420 &apq8064_ssbi_pm8921_pdata;
421 apq8064_device_ssbi_pmic2.dev.platform_data =
422 &apq8064_ssbi_pm8821_pdata;
423 apq8064_pm8921_platform_data.num_regulators =
424 msm8064_pm8921_regulator_pdata_len;
425
426 if (machine_is_apq8064_rumi3()) {
427 apq8064_pm8921_irq_pdata.devirq = 0;
428 apq8064_pm8821_irq_pdata.devirq = 0;
429 }
430}