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