blob: 7b12f975694494cab813f63e04f933841613915f [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>
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -080021#include <asm/mach-types.h>
22#include <asm/mach/mmc.h>
23#include <mach/msm_bus_board.h>
24#include <mach/board.h>
25#include <mach/gpio.h>
26#include <mach/gpiomux.h>
Jay Chokshie8741282012-01-25 15:22:55 -080027#include <mach/restart.h>
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -080028#include "devices.h"
29#include "board-8064.h"
30
Jay Chokshie8741282012-01-25 15:22:55 -080031struct pm8xxx_gpio_init {
32 unsigned gpio;
33 struct pm_gpio config;
34};
35
36struct pm8xxx_mpp_init {
37 unsigned mpp;
38 struct pm8xxx_mpp_config_data config;
39};
40
41#define PM8921_GPIO_INIT(_gpio, _dir, _buf, _val, _pull, _vin, _out_strength, \
42 _func, _inv, _disable) \
43{ \
44 .gpio = PM8921_GPIO_PM_TO_SYS(_gpio), \
45 .config = { \
46 .direction = _dir, \
47 .output_buffer = _buf, \
48 .output_value = _val, \
49 .pull = _pull, \
50 .vin_sel = _vin, \
51 .out_strength = _out_strength, \
52 .function = _func, \
53 .inv_int_pol = _inv, \
54 .disable_pin = _disable, \
55 } \
56}
57
58#define PM8921_MPP_INIT(_mpp, _type, _level, _control) \
59{ \
60 .mpp = PM8921_MPP_PM_TO_SYS(_mpp), \
61 .config = { \
62 .type = PM8XXX_MPP_TYPE_##_type, \
63 .level = _level, \
64 .control = PM8XXX_MPP_##_control, \
65 } \
66}
67
68#define PM8821_MPP_INIT(_mpp, _type, _level, _control) \
69{ \
70 .mpp = PM8821_MPP_PM_TO_SYS(_mpp), \
71 .config = { \
72 .type = PM8XXX_MPP_TYPE_##_type, \
73 .level = _level, \
74 .control = PM8XXX_MPP_##_control, \
75 } \
76}
77
78#define PM8921_GPIO_DISABLE(_gpio) \
79 PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, 0, 0, 0, PM_GPIO_VIN_S4, \
80 0, 0, 0, 1)
81
82#define PM8921_GPIO_OUTPUT(_gpio, _val, _strength) \
83 PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
84 PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
85 PM_GPIO_STRENGTH_##_strength, \
86 PM_GPIO_FUNC_NORMAL, 0, 0)
87
88#define PM8921_GPIO_INPUT(_gpio, _pull) \
89 PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0, \
90 _pull, PM_GPIO_VIN_S4, \
91 PM_GPIO_STRENGTH_NO, \
92 PM_GPIO_FUNC_NORMAL, 0, 0)
93
94#define PM8921_GPIO_OUTPUT_FUNC(_gpio, _val, _func) \
95 PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
96 PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
97 PM_GPIO_STRENGTH_HIGH, \
98 _func, 0, 0)
99
100#define PM8921_GPIO_OUTPUT_VIN(_gpio, _val, _vin) \
101 PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
102 PM_GPIO_PULL_NO, _vin, \
103 PM_GPIO_STRENGTH_HIGH, \
104 PM_GPIO_FUNC_NORMAL, 0, 0)
105
106/* Initial PM8921 GPIO configurations */
107static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
108};
109
110/* Initial PM8XXX MPP configurations */
111static struct pm8xxx_mpp_init pm8xxx_mpps[] __initdata = {
112};
113
114void __init apq8064_pm8xxx_gpio_mpp_init(void)
115{
116 int i, rc;
117
118 for (i = 0; i < ARRAY_SIZE(pm8921_gpios); i++) {
119 rc = pm8xxx_gpio_config(pm8921_gpios[i].gpio,
120 &pm8921_gpios[i].config);
121 if (rc) {
122 pr_err("%s: pm8xxx_gpio_config: rc=%d\n", __func__, rc);
123 break;
124 }
125 }
126
127 for (i = 0; i < ARRAY_SIZE(pm8xxx_mpps); i++) {
128 rc = pm8xxx_mpp_config(pm8xxx_mpps[i].mpp,
129 &pm8xxx_mpps[i].config);
130 if (rc) {
131 pr_err("%s: pm8xxx_mpp_config: rc=%d\n", __func__, rc);
132 break;
133 }
134 }
135}
136
137static struct pm8xxx_pwrkey_platform_data apq8064_pm8921_pwrkey_pdata = {
138 .pull_up = 1,
139 .kpd_trigger_delay_us = 15625,
140 .wakeup = 1,
141};
142
143static struct pm8xxx_misc_platform_data apq8064_pm8921_misc_pdata = {
144 .priority = 0,
145};
146
147#define PM8921_LC_LED_MAX_CURRENT 4 /* I = 4mA */
148#define PM8921_LC_LED_LOW_CURRENT 1 /* I = 1mA */
149#define PM8XXX_LED_PWM_PERIOD 1000
150#define PM8XXX_LED_PWM_DUTY_MS 20
151/**
152 * PM8XXX_PWM_CHANNEL_NONE shall be used when LED shall not be
153 * driven using PWM feature.
154 */
155#define PM8XXX_PWM_CHANNEL_NONE -1
156
157static struct led_info pm8921_led_info[] = {
158 [0] = {
159 .name = "led:red",
160 .default_trigger = "ac-online",
161 },
162};
163
164static struct led_platform_data pm8921_led_core_pdata = {
165 .num_leds = ARRAY_SIZE(pm8921_led_info),
166 .leds = pm8921_led_info,
167};
168
169static int pm8921_led0_pwm_duty_pcts[56] = {
170 1, 4, 8, 12, 16, 20, 24, 28, 32, 36,
171 40, 44, 46, 52, 56, 60, 64, 68, 72, 76,
172 80, 84, 88, 92, 96, 100, 100, 100, 98, 95,
173 92, 88, 84, 82, 78, 74, 70, 66, 62, 58,
174 58, 54, 50, 48, 42, 38, 34, 30, 26, 22,
175 14, 10, 6, 4, 1
176};
177
178static struct pm8xxx_pwm_duty_cycles pm8921_led0_pwm_duty_cycles = {
179 .duty_pcts = (int *)&pm8921_led0_pwm_duty_pcts,
180 .num_duty_pcts = ARRAY_SIZE(pm8921_led0_pwm_duty_pcts),
181 .duty_ms = PM8XXX_LED_PWM_DUTY_MS,
182 .start_idx = 0,
183};
184
185static struct pm8xxx_led_config pm8921_led_configs[] = {
186 [0] = {
187 .id = PM8XXX_ID_LED_0,
188 .mode = PM8XXX_LED_MODE_PWM2,
189 .max_current = PM8921_LC_LED_MAX_CURRENT,
190 .pwm_channel = 5,
191 .pwm_period_us = PM8XXX_LED_PWM_PERIOD,
192 .pwm_duty_cycles = &pm8921_led0_pwm_duty_cycles,
193 },
194};
195
196static struct pm8xxx_led_platform_data apq8064_pm8921_leds_pdata = {
197 .led_core = &pm8921_led_core_pdata,
198 .configs = pm8921_led_configs,
199 .num_configs = ARRAY_SIZE(pm8921_led_configs),
200};
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800201
202static struct pm8xxx_mpp_platform_data
203apq8064_pm8921_mpp_pdata __devinitdata = {
204 .mpp_base = PM8921_MPP_PM_TO_SYS(1),
205};
206
207static struct pm8xxx_gpio_platform_data
208apq8064_pm8921_gpio_pdata __devinitdata = {
209 .gpio_base = PM8921_GPIO_PM_TO_SYS(1),
210};
211
212static struct pm8xxx_irq_platform_data
213apq8064_pm8921_irq_pdata __devinitdata = {
214 .irq_base = PM8921_IRQ_BASE,
215 .devirq = PM8921_USR_IRQ_N,
216 .irq_trigger_flag = IRQF_TRIGGER_HIGH,
217 .dev_id = 0,
218};
219
Ashay Jaiswal0b023dc2012-01-25 10:18:36 +0530220static struct pm8xxx_rtc_platform_data
221apq8064_pm8921_rtc_pdata = {
222 .rtc_write_enable = false,
223 .rtc_alarm_powerup = false,
224};
225
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800226static struct pm8921_platform_data
227apq8064_pm8921_platform_data __devinitdata = {
228 .regulator_pdatas = msm8064_pm8921_regulator_pdata,
229 .irq_pdata = &apq8064_pm8921_irq_pdata,
230 .gpio_pdata = &apq8064_pm8921_gpio_pdata,
231 .mpp_pdata = &apq8064_pm8921_mpp_pdata,
Ashay Jaiswal0b023dc2012-01-25 10:18:36 +0530232 .rtc_pdata = &apq8064_pm8921_rtc_pdata,
Jay Chokshie8741282012-01-25 15:22:55 -0800233 .pwrkey_pdata = &apq8064_pm8921_pwrkey_pdata,
234 .misc_pdata = &apq8064_pm8921_misc_pdata,
235 .leds_pdata = &apq8064_pm8921_leds_pdata,
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800236};
237
238static struct pm8xxx_irq_platform_data
239apq8064_pm8821_irq_pdata __devinitdata = {
240 .irq_base = PM8821_IRQ_BASE,
Jay Chokshie8741282012-01-25 15:22:55 -0800241 .devirq = PM8821_SEC_IRQ_N,
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800242 .irq_trigger_flag = IRQF_TRIGGER_HIGH,
243 .dev_id = 1,
244};
245
246static struct pm8xxx_mpp_platform_data
247apq8064_pm8821_mpp_pdata __devinitdata = {
248 .mpp_base = PM8821_MPP_PM_TO_SYS(1),
249};
250
251static struct pm8821_platform_data
252apq8064_pm8821_platform_data __devinitdata = {
253 .irq_pdata = &apq8064_pm8821_irq_pdata,
254 .mpp_pdata = &apq8064_pm8821_mpp_pdata,
255};
256
257static struct msm_ssbi_platform_data apq8064_ssbi_pm8921_pdata __devinitdata = {
258 .controller_type = MSM_SBI_CTRL_PMIC_ARBITER,
259 .slave = {
260 .name = "pm8921-core",
261 .platform_data = &apq8064_pm8921_platform_data,
262 },
263};
264
265static struct msm_ssbi_platform_data apq8064_ssbi_pm8821_pdata __devinitdata = {
266 .controller_type = MSM_SBI_CTRL_PMIC_ARBITER,
267 .slave = {
268 .name = "pm8821-core",
269 .platform_data = &apq8064_pm8821_platform_data,
270 },
271};
272
273void __init apq8064_init_pmic(void)
274{
Jay Chokshie8741282012-01-25 15:22:55 -0800275 pmic_reset_irq = PM8921_IRQ_BASE + PM8921_RESOUT_IRQ;
276
Stepan Moskovchenkoc1074f02011-12-14 17:51:57 -0800277 apq8064_device_ssbi_pmic1.dev.platform_data =
278 &apq8064_ssbi_pm8921_pdata;
279 apq8064_device_ssbi_pmic2.dev.platform_data =
280 &apq8064_ssbi_pm8821_pdata;
281 apq8064_pm8921_platform_data.num_regulators =
282 msm8064_pm8921_regulator_pdata_len;
283
284 if (machine_is_apq8064_rumi3()) {
285 apq8064_pm8921_irq_pdata.devirq = 0;
286 apq8064_pm8821_irq_pdata.devirq = 0;
287 }
288}