blob: 6d5bb98110cec33f8aaf8ac25b20c5ae9159c269 [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
89#define PM8921_GPIO_INPUT(_gpio, _pull) \
90 PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0, \
91 _pull, PM_GPIO_VIN_S4, \
92 PM_GPIO_STRENGTH_NO, \
93 PM_GPIO_FUNC_NORMAL, 0, 0)
94
95#define PM8921_GPIO_OUTPUT_FUNC(_gpio, _val, _func) \
96 PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
97 PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
98 PM_GPIO_STRENGTH_HIGH, \
99 _func, 0, 0)
100
101#define PM8921_GPIO_OUTPUT_VIN(_gpio, _val, _vin) \
102 PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
103 PM_GPIO_PULL_NO, _vin, \
104 PM_GPIO_STRENGTH_HIGH, \
105 PM_GPIO_FUNC_NORMAL, 0, 0)
106
107/* Initial PM8921 GPIO configurations */
108static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
David Collins390fc332012-02-07 14:38:16 -0800109 PM8921_GPIO_OUTPUT(23, 0, HIGH), /* touchscreen power FET */
Jay Chokshie8741282012-01-25 15:22:55 -0800110};
111
112/* Initial PM8XXX MPP configurations */
113static struct pm8xxx_mpp_init pm8xxx_mpps[] __initdata = {
David Collinsf0d00732012-01-25 15:46:50 -0800114 /* External 5V regulator enable; shared by HDMI and USB_OTG switches. */
115 PM8921_MPP_INIT(7, D_INPUT, PM8921_MPP_DIG_LEVEL_VPH, DIN_TO_INT),
Jay Chokshie8741282012-01-25 15:22:55 -0800116};
117
118void __init apq8064_pm8xxx_gpio_mpp_init(void)
119{
120 int i, rc;
121
122 for (i = 0; i < ARRAY_SIZE(pm8921_gpios); i++) {
123 rc = pm8xxx_gpio_config(pm8921_gpios[i].gpio,
124 &pm8921_gpios[i].config);
125 if (rc) {
126 pr_err("%s: pm8xxx_gpio_config: rc=%d\n", __func__, rc);
127 break;
128 }
129 }
130
131 for (i = 0; i < ARRAY_SIZE(pm8xxx_mpps); i++) {
132 rc = pm8xxx_mpp_config(pm8xxx_mpps[i].mpp,
133 &pm8xxx_mpps[i].config);
134 if (rc) {
135 pr_err("%s: pm8xxx_mpp_config: rc=%d\n", __func__, rc);
136 break;
137 }
138 }
139}
140
141static struct pm8xxx_pwrkey_platform_data apq8064_pm8921_pwrkey_pdata = {
142 .pull_up = 1,
143 .kpd_trigger_delay_us = 15625,
144 .wakeup = 1,
145};
146
147static struct pm8xxx_misc_platform_data apq8064_pm8921_misc_pdata = {
148 .priority = 0,
149};
150
151#define PM8921_LC_LED_MAX_CURRENT 4 /* I = 4mA */
152#define PM8921_LC_LED_LOW_CURRENT 1 /* I = 1mA */
153#define PM8XXX_LED_PWM_PERIOD 1000
154#define PM8XXX_LED_PWM_DUTY_MS 20
155/**
156 * PM8XXX_PWM_CHANNEL_NONE shall be used when LED shall not be
157 * driven using PWM feature.
158 */
159#define PM8XXX_PWM_CHANNEL_NONE -1
160
161static struct led_info pm8921_led_info[] = {
162 [0] = {
163 .name = "led:red",
164 .default_trigger = "ac-online",
165 },
166};
167
168static struct led_platform_data pm8921_led_core_pdata = {
169 .num_leds = ARRAY_SIZE(pm8921_led_info),
170 .leds = pm8921_led_info,
171};
172
173static int pm8921_led0_pwm_duty_pcts[56] = {
174 1, 4, 8, 12, 16, 20, 24, 28, 32, 36,
175 40, 44, 46, 52, 56, 60, 64, 68, 72, 76,
176 80, 84, 88, 92, 96, 100, 100, 100, 98, 95,
177 92, 88, 84, 82, 78, 74, 70, 66, 62, 58,
178 58, 54, 50, 48, 42, 38, 34, 30, 26, 22,
179 14, 10, 6, 4, 1
180};
181
182static struct pm8xxx_pwm_duty_cycles pm8921_led0_pwm_duty_cycles = {
183 .duty_pcts = (int *)&pm8921_led0_pwm_duty_pcts,
184 .num_duty_pcts = ARRAY_SIZE(pm8921_led0_pwm_duty_pcts),
185 .duty_ms = PM8XXX_LED_PWM_DUTY_MS,
186 .start_idx = 0,
187};
188
189static struct pm8xxx_led_config pm8921_led_configs[] = {
190 [0] = {
191 .id = PM8XXX_ID_LED_0,
192 .mode = PM8XXX_LED_MODE_PWM2,
193 .max_current = PM8921_LC_LED_MAX_CURRENT,
194 .pwm_channel = 5,
195 .pwm_period_us = PM8XXX_LED_PWM_PERIOD,
196 .pwm_duty_cycles = &pm8921_led0_pwm_duty_cycles,
197 },
198};
199
200static struct pm8xxx_led_platform_data apq8064_pm8921_leds_pdata = {
201 .led_core = &pm8921_led_core_pdata,
202 .configs = pm8921_led_configs,
203 .num_configs = ARRAY_SIZE(pm8921_led_configs),
204};
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800205
Jay Chokshif3a9ea82012-01-12 16:34:43 -0800206static struct pm8xxx_adc_amux apq8064_pm8921_adc_channels_data[] = {
207 {"vcoin", CHANNEL_VCOIN, CHAN_PATH_SCALING2, AMUX_RSV1,
208 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
209 {"vbat", CHANNEL_VBAT, CHAN_PATH_SCALING2, AMUX_RSV1,
210 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
211 {"dcin", CHANNEL_DCIN, CHAN_PATH_SCALING4, AMUX_RSV1,
212 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
213 {"ichg", CHANNEL_ICHG, CHAN_PATH_SCALING1, AMUX_RSV1,
214 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
215 {"vph_pwr", CHANNEL_VPH_PWR, CHAN_PATH_SCALING2, AMUX_RSV1,
216 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
217 {"ibat", CHANNEL_IBAT, CHAN_PATH_SCALING1, AMUX_RSV1,
218 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
219 {"batt_therm", CHANNEL_BATT_THERM, CHAN_PATH_SCALING1, AMUX_RSV2,
220 ADC_DECIMATION_TYPE2, ADC_SCALE_BATT_THERM},
221 {"batt_id", CHANNEL_BATT_ID, CHAN_PATH_SCALING1, AMUX_RSV1,
222 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
223 {"usbin", CHANNEL_USBIN, CHAN_PATH_SCALING3, AMUX_RSV1,
224 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
225 {"pmic_therm", CHANNEL_DIE_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
226 ADC_DECIMATION_TYPE2, ADC_SCALE_PMIC_THERM},
227 {"625mv", CHANNEL_625MV, CHAN_PATH_SCALING1, AMUX_RSV1,
228 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
229 {"125v", CHANNEL_125V, CHAN_PATH_SCALING1, AMUX_RSV1,
230 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
231 {"chg_temp", CHANNEL_CHG_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
232 ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
233 {"xo_therm", CHANNEL_MUXOFF, CHAN_PATH_SCALING1, AMUX_RSV0,
234 ADC_DECIMATION_TYPE2, ADC_SCALE_XOTHERM},
235};
236
237static struct pm8xxx_adc_properties apq8064_pm8921_adc_data = {
238 .adc_vdd_reference = 1800, /* milli-voltage for this adc */
239 .bitresolution = 15,
240 .bipolar = 0,
241};
242
243static struct pm8xxx_adc_platform_data apq8064_pm8921_adc_pdata = {
244 .adc_channel = apq8064_pm8921_adc_channels_data,
245 .adc_num_board_channel = ARRAY_SIZE(apq8064_pm8921_adc_channels_data),
246 .adc_prop = &apq8064_pm8921_adc_data,
247 .adc_mpp_base = PM8921_MPP_PM_TO_SYS(1),
248};
249
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800250static struct pm8xxx_mpp_platform_data
251apq8064_pm8921_mpp_pdata __devinitdata = {
252 .mpp_base = PM8921_MPP_PM_TO_SYS(1),
253};
254
255static struct pm8xxx_gpio_platform_data
256apq8064_pm8921_gpio_pdata __devinitdata = {
257 .gpio_base = PM8921_GPIO_PM_TO_SYS(1),
258};
259
260static struct pm8xxx_irq_platform_data
261apq8064_pm8921_irq_pdata __devinitdata = {
262 .irq_base = PM8921_IRQ_BASE,
263 .devirq = PM8921_USR_IRQ_N,
264 .irq_trigger_flag = IRQF_TRIGGER_HIGH,
265 .dev_id = 0,
266};
267
Ashay Jaiswal0b023dc2012-01-25 10:18:36 +0530268static struct pm8xxx_rtc_platform_data
269apq8064_pm8921_rtc_pdata = {
270 .rtc_write_enable = false,
271 .rtc_alarm_powerup = false,
272};
273
Jay Chokshi42fe9f02012-02-01 20:52:08 -0800274static int apq8064_pm8921_therm_mitigation[] = {
275 1100,
276 700,
277 600,
278 325,
279};
280
281#define MAX_VOLTAGE_MV 4200
282static struct pm8921_charger_platform_data
283apq8064_pm8921_chg_pdata __devinitdata = {
284 .safety_time = 180,
285 .update_time = 60000,
286 .max_voltage = MAX_VOLTAGE_MV,
287 .min_voltage = 3200,
288 .resume_voltage_delta = 100,
289 .term_current = 100,
290 .cool_temp = 10,
291 .warm_temp = 40,
292 .temp_check_period = 1,
293 .max_bat_chg_current = 1100,
294 .cool_bat_chg_current = 350,
295 .warm_bat_chg_current = 350,
296 .cool_bat_voltage = 4100,
297 .warm_bat_voltage = 4100,
298 .thermal_mitigation = apq8064_pm8921_therm_mitigation,
299 .thermal_levels = ARRAY_SIZE(apq8064_pm8921_therm_mitigation),
300};
301
302static struct pm8xxx_ccadc_platform_data
303apq8064_pm8xxx_ccadc_pdata = {
304 .r_sense = 10,
305};
306
307static struct pm8921_bms_platform_data
308apq8064_pm8921_bms_pdata __devinitdata = {
309 .r_sense = 10,
310 .i_test = 2500,
311 .v_failure = 3000,
312 .calib_delay_ms = 600000,
313 .max_voltage_uv = MAX_VOLTAGE_MV * 1000,
314};
315
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800316static struct pm8921_platform_data
317apq8064_pm8921_platform_data __devinitdata = {
318 .regulator_pdatas = msm8064_pm8921_regulator_pdata,
319 .irq_pdata = &apq8064_pm8921_irq_pdata,
320 .gpio_pdata = &apq8064_pm8921_gpio_pdata,
321 .mpp_pdata = &apq8064_pm8921_mpp_pdata,
Ashay Jaiswal0b023dc2012-01-25 10:18:36 +0530322 .rtc_pdata = &apq8064_pm8921_rtc_pdata,
Jay Chokshie8741282012-01-25 15:22:55 -0800323 .pwrkey_pdata = &apq8064_pm8921_pwrkey_pdata,
324 .misc_pdata = &apq8064_pm8921_misc_pdata,
325 .leds_pdata = &apq8064_pm8921_leds_pdata,
Jay Chokshif3a9ea82012-01-12 16:34:43 -0800326 .adc_pdata = &apq8064_pm8921_adc_pdata,
Jay Chokshi42fe9f02012-02-01 20:52:08 -0800327 .charger_pdata = &apq8064_pm8921_chg_pdata,
328 .bms_pdata = &apq8064_pm8921_bms_pdata,
329 .ccadc_pdata = &apq8064_pm8xxx_ccadc_pdata,
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800330};
331
332static struct pm8xxx_irq_platform_data
333apq8064_pm8821_irq_pdata __devinitdata = {
334 .irq_base = PM8821_IRQ_BASE,
Jay Chokshie8741282012-01-25 15:22:55 -0800335 .devirq = PM8821_SEC_IRQ_N,
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800336 .irq_trigger_flag = IRQF_TRIGGER_HIGH,
337 .dev_id = 1,
338};
339
340static struct pm8xxx_mpp_platform_data
341apq8064_pm8821_mpp_pdata __devinitdata = {
342 .mpp_base = PM8821_MPP_PM_TO_SYS(1),
343};
344
345static struct pm8821_platform_data
346apq8064_pm8821_platform_data __devinitdata = {
347 .irq_pdata = &apq8064_pm8821_irq_pdata,
348 .mpp_pdata = &apq8064_pm8821_mpp_pdata,
349};
350
351static struct msm_ssbi_platform_data apq8064_ssbi_pm8921_pdata __devinitdata = {
352 .controller_type = MSM_SBI_CTRL_PMIC_ARBITER,
353 .slave = {
354 .name = "pm8921-core",
355 .platform_data = &apq8064_pm8921_platform_data,
356 },
357};
358
359static struct msm_ssbi_platform_data apq8064_ssbi_pm8821_pdata __devinitdata = {
360 .controller_type = MSM_SBI_CTRL_PMIC_ARBITER,
361 .slave = {
362 .name = "pm8821-core",
363 .platform_data = &apq8064_pm8821_platform_data,
364 },
365};
366
367void __init apq8064_init_pmic(void)
368{
Jay Chokshie8741282012-01-25 15:22:55 -0800369 pmic_reset_irq = PM8921_IRQ_BASE + PM8921_RESOUT_IRQ;
370
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800371 apq8064_device_ssbi_pmic1.dev.platform_data =
372 &apq8064_ssbi_pm8921_pdata;
373 apq8064_device_ssbi_pmic2.dev.platform_data =
374 &apq8064_ssbi_pm8821_pdata;
375 apq8064_pm8921_platform_data.num_regulators =
376 msm8064_pm8921_regulator_pdata_len;
377
378 if (machine_is_apq8064_rumi3()) {
379 apq8064_pm8921_irq_pdata.devirq = 0;
380 apq8064_pm8821_irq_pdata.devirq = 0;
381 }
382}