blob: dd6c9ec31d189e500996d8fdc42ebb6547a21348 [file] [log] [blame]
Duy Truong790f06d2013-02-13 16:38:12 -08001/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -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>
Steve Mucklef132c6c2012-06-06 18:30:57 -070017#include <linux/gpio.h>
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080018#include <linux/bootmem.h>
19#include <asm/mach-types.h>
20#include <asm/mach/mmc.h>
21#include <mach/msm_bus_board.h>
22#include <mach/board.h>
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080023#include <mach/gpiomux.h>
24#include "devices.h"
Stepan Moskovchenko5a83dba2011-12-05 17:30:17 -080025#include "board-8064.h"
Subhash Jadavanibcd435f2012-04-24 18:26:49 +053026#include "board-storage-common-a.h"
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080027
28
29/* APQ8064 has 4 SDCC controllers */
30enum sdcc_controllers {
31 SDCC1,
32 SDCC2,
33 SDCC3,
34 SDCC4,
35 MAX_SDCC_CONTROLLER
36};
37
38/* All SDCC controllers require VDD/VCC voltage */
39static struct msm_mmc_reg_data mmc_vdd_reg_data[MAX_SDCC_CONTROLLER] = {
40 /* SDCC1 : eMMC card connected */
41 [SDCC1] = {
42 .name = "sdc_vdd",
43 .high_vol_level = 2950000,
44 .low_vol_level = 2950000,
45 .always_on = 1,
46 .lpm_sup = 1,
47 .lpm_uA = 9000,
48 .hpm_uA = 200000, /* 200mA */
49 },
50 /* SDCC3 : External card slot connected */
51 [SDCC3] = {
52 .name = "sdc_vdd",
53 .high_vol_level = 2950000,
54 .low_vol_level = 2950000,
Oluwafemi Adeyemiaafeeb02012-02-20 21:01:15 -080055 .hpm_uA = 800000, /* 800mA */
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080056 }
57};
58
Subhash Jadavani937c7502012-06-01 15:34:46 +053059/* SDCC controllers may require voting for VDD IO voltage */
60static struct msm_mmc_reg_data mmc_vdd_io_reg_data[MAX_SDCC_CONTROLLER] = {
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080061 /* SDCC1 : eMMC card connected */
62 [SDCC1] = {
Subhash Jadavani937c7502012-06-01 15:34:46 +053063 .name = "sdc_vdd_io",
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080064 .always_on = 1,
65 .high_vol_level = 1800000,
66 .low_vol_level = 1800000,
67 .hpm_uA = 200000, /* 200mA */
Subhash Jadavani937c7502012-06-01 15:34:46 +053068 },
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080069 /* SDCC3 : External card slot connected */
70 [SDCC3] = {
Subhash Jadavani937c7502012-06-01 15:34:46 +053071 .name = "sdc_vdd_io",
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080072 .high_vol_level = 2950000,
73 .low_vol_level = 1850000,
74 .always_on = 1,
75 .lpm_sup = 1,
76 /* Max. Active current required is 16 mA */
77 .hpm_uA = 16000,
78 /*
79 * Sleep current required is ~300 uA. But min. vote can be
80 * in terms of mA (min. 1 mA). So let's vote for 2 mA
81 * during sleep.
82 */
83 .lpm_uA = 2000,
84 }
85};
86
87static struct msm_mmc_slot_reg_data mmc_slot_vreg_data[MAX_SDCC_CONTROLLER] = {
88 /* SDCC1 : eMMC card connected */
89 [SDCC1] = {
90 .vdd_data = &mmc_vdd_reg_data[SDCC1],
Subhash Jadavani937c7502012-06-01 15:34:46 +053091 .vdd_io_data = &mmc_vdd_io_reg_data[SDCC1],
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080092 },
93 /* SDCC3 : External card slot connected */
94 [SDCC3] = {
95 .vdd_data = &mmc_vdd_reg_data[SDCC3],
Subhash Jadavani937c7502012-06-01 15:34:46 +053096 .vdd_io_data = &mmc_vdd_io_reg_data[SDCC3],
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080097 }
98};
99
100/* SDC1 pad data */
101static struct msm_mmc_pad_drv sdc1_pad_drv_on_cfg[] = {
102 {TLMM_HDRV_SDC1_CLK, GPIO_CFG_16MA},
103 {TLMM_HDRV_SDC1_CMD, GPIO_CFG_10MA},
104 {TLMM_HDRV_SDC1_DATA, GPIO_CFG_10MA}
105};
106
107static struct msm_mmc_pad_drv sdc1_pad_drv_off_cfg[] = {
108 {TLMM_HDRV_SDC1_CLK, GPIO_CFG_2MA},
109 {TLMM_HDRV_SDC1_CMD, GPIO_CFG_2MA},
110 {TLMM_HDRV_SDC1_DATA, GPIO_CFG_2MA}
111};
112
113static struct msm_mmc_pad_pull sdc1_pad_pull_on_cfg[] = {
114 {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
115 {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
116 {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
117};
118
119static struct msm_mmc_pad_pull sdc1_pad_pull_off_cfg[] = {
120 {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
Oluwafemi Adeyemi4e196b62012-02-15 14:29:03 -0800121 {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
122 {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800123};
124
125/* SDC3 pad data */
126static struct msm_mmc_pad_drv sdc3_pad_drv_on_cfg[] = {
127 {TLMM_HDRV_SDC3_CLK, GPIO_CFG_8MA},
128 {TLMM_HDRV_SDC3_CMD, GPIO_CFG_8MA},
129 {TLMM_HDRV_SDC3_DATA, GPIO_CFG_8MA}
130};
131
132static struct msm_mmc_pad_drv sdc3_pad_drv_off_cfg[] = {
133 {TLMM_HDRV_SDC3_CLK, GPIO_CFG_2MA},
134 {TLMM_HDRV_SDC3_CMD, GPIO_CFG_2MA},
135 {TLMM_HDRV_SDC3_DATA, GPIO_CFG_2MA}
136};
137
138static struct msm_mmc_pad_pull sdc3_pad_pull_on_cfg[] = {
139 {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
140 {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
141 {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
142};
143
144static struct msm_mmc_pad_pull sdc3_pad_pull_off_cfg[] = {
145 {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
Oluwafemi Adeyemi4e196b62012-02-15 14:29:03 -0800146 {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
147 {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800148};
149
150static struct msm_mmc_pad_pull_data mmc_pad_pull_data[MAX_SDCC_CONTROLLER] = {
151 [SDCC1] = {
152 .on = sdc1_pad_pull_on_cfg,
153 .off = sdc1_pad_pull_off_cfg,
154 .size = ARRAY_SIZE(sdc1_pad_pull_on_cfg)
155 },
156 [SDCC3] = {
157 .on = sdc3_pad_pull_on_cfg,
158 .off = sdc3_pad_pull_off_cfg,
159 .size = ARRAY_SIZE(sdc3_pad_pull_on_cfg)
160 },
161};
162
163static struct msm_mmc_pad_drv_data mmc_pad_drv_data[MAX_SDCC_CONTROLLER] = {
164 [SDCC1] = {
165 .on = sdc1_pad_drv_on_cfg,
166 .off = sdc1_pad_drv_off_cfg,
167 .size = ARRAY_SIZE(sdc1_pad_drv_on_cfg)
168 },
169 [SDCC3] = {
170 .on = sdc3_pad_drv_on_cfg,
171 .off = sdc3_pad_drv_off_cfg,
172 .size = ARRAY_SIZE(sdc3_pad_drv_on_cfg)
173 },
174};
175
176static struct msm_mmc_pad_data mmc_pad_data[MAX_SDCC_CONTROLLER] = {
177 [SDCC1] = {
178 .pull = &mmc_pad_pull_data[SDCC1],
179 .drv = &mmc_pad_drv_data[SDCC1]
180 },
181 [SDCC3] = {
182 .pull = &mmc_pad_pull_data[SDCC3],
183 .drv = &mmc_pad_drv_data[SDCC3]
184 },
185};
186
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700187static struct msm_mmc_gpio sdc2_gpio[] = {
188 {59, "sdc2_clk"},
189 {57, "sdc2_cmd"},
190 {62, "sdc2_dat_0"},
191 {61, "sdc2_dat_1"},
192 {60, "sdc2_dat_2"},
193 {58, "sdc2_dat_3"},
194};
195
196static struct msm_mmc_gpio sdc4_gpio[] = {
197 {68, "sdc4_clk"},
198 {67, "sdc4_cmd"},
199 {66, "sdc4_dat_0"},
200 {65, "sdc4_dat_1"},
201 {64, "sdc4_dat_2"},
202 {63, "sdc4_dat_3"},
203};
204
205static struct msm_mmc_gpio_data mmc_gpio_data[MAX_SDCC_CONTROLLER] = {
206 [SDCC2] = {
207 .gpio = sdc2_gpio,
208 .size = ARRAY_SIZE(sdc2_gpio),
209 },
210 [SDCC4] = {
211 .gpio = sdc4_gpio,
212 .size = ARRAY_SIZE(sdc4_gpio),
213 }
214};
215
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800216static struct msm_mmc_pin_data mmc_slot_pin_data[MAX_SDCC_CONTROLLER] = {
217 [SDCC1] = {
218 .pad_data = &mmc_pad_data[SDCC1],
219 },
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700220 [SDCC2] = {
221 .is_gpio = 1,
222 .gpio_data = &mmc_gpio_data[SDCC2],
223 },
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800224 [SDCC3] = {
225 .pad_data = &mmc_pad_data[SDCC3],
226 },
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700227 [SDCC4] = {
228 .is_gpio = 1,
229 .gpio_data = &mmc_gpio_data[SDCC4],
230 },
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800231};
232
Subhash Jadavani55e188e2012-04-13 11:31:08 +0530233#define MSM_MPM_PIN_SDC1_DAT1 17
234#define MSM_MPM_PIN_SDC3_DAT1 21
235
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800236#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
237static unsigned int sdc1_sup_clk_rates[] = {
238 400000, 24000000, 48000000, 96000000
239};
240
241static struct mmc_platform_data sdc1_data = {
242 .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
243#ifdef CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT
244 .mmc_bus_width = MMC_CAP_8_BIT_DATA,
245#else
246 .mmc_bus_width = MMC_CAP_4_BIT_DATA,
247#endif
248 .sup_clk_table = sdc1_sup_clk_rates,
249 .sup_clk_cnt = ARRAY_SIZE(sdc1_sup_clk_rates),
Oluwafemi Adeyemi89ff2a12012-03-08 16:44:21 -0800250 .nonremovable = 1,
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800251 .pin_data = &mmc_slot_pin_data[SDCC1],
252 .vreg_data = &mmc_slot_vreg_data[SDCC1],
Oluwafemi Adeyemi1e770962012-03-23 13:08:11 -0700253 .uhs_caps = MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50,
Subhash Jadavanicb6f9ce2012-06-26 11:57:10 +0530254 .uhs_caps2 = MMC_CAP2_HS200_1_8V_SDR,
Subhash Jadavani55e188e2012-04-13 11:31:08 +0530255 .mpm_sdiowakeup_int = MSM_MPM_PIN_SDC1_DAT1,
Subhash Jadavanibcd435f2012-04-24 18:26:49 +0530256 .msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800257};
258static struct mmc_platform_data *apq8064_sdc1_pdata = &sdc1_data;
259#else
260static struct mmc_platform_data *apq8064_sdc1_pdata;
261#endif
262
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700263#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
264static unsigned int sdc2_sup_clk_rates[] = {
265 400000, 24000000, 48000000
266};
267
268static struct mmc_platform_data sdc2_data = {
269 .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
270 .mmc_bus_width = MMC_CAP_4_BIT_DATA,
271 .sup_clk_table = sdc2_sup_clk_rates,
272 .sup_clk_cnt = ARRAY_SIZE(sdc2_sup_clk_rates),
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700273 .pin_data = &mmc_slot_pin_data[SDCC2],
274 .sdiowakeup_irq = MSM_GPIO_TO_INT(61),
275 .msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
276};
277static struct mmc_platform_data *apq8064_sdc2_pdata = &sdc2_data;
278#else
279static struct mmc_platform_data *apq8064_sdc2_pdata;
280#endif
281
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800282#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
283static unsigned int sdc3_sup_clk_rates[] = {
Oluwafemi Adeyemi086ef862012-02-07 20:13:50 -0800284 400000, 24000000, 48000000, 96000000, 192000000
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800285};
286
287static struct mmc_platform_data sdc3_data = {
288 .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
289 .mmc_bus_width = MMC_CAP_4_BIT_DATA,
290 .sup_clk_table = sdc3_sup_clk_rates,
291 .sup_clk_cnt = ARRAY_SIZE(sdc3_sup_clk_rates),
292 .pin_data = &mmc_slot_pin_data[SDCC3],
293 .vreg_data = &mmc_slot_vreg_data[SDCC3],
Oluwafemi Adeyemi787ac482012-02-16 09:50:03 -0800294 .wpswitch_gpio = PM8921_GPIO_PM_TO_SYS(17),
Sujit Reddy Thumma8f912ea2012-06-22 16:18:43 +0530295 .is_wpswitch_active_low = true,
Oluwafemi Adeyemi83999672012-02-07 20:01:26 -0800296 .status_gpio = 26,
297 .status_irq = MSM_GPIO_TO_INT(26),
298 .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
299 .is_status_gpio_active_low = 1,
Oluwafemi Adeyemi086ef862012-02-07 20:13:50 -0800300 .xpc_cap = 1,
301 .uhs_caps = (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
302 MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50 |
303 MMC_CAP_UHS_SDR104 | MMC_CAP_MAX_CURRENT_800),
Subhash Jadavani55e188e2012-04-13 11:31:08 +0530304 .mpm_sdiowakeup_int = MSM_MPM_PIN_SDC3_DAT1,
Subhash Jadavanibcd435f2012-04-24 18:26:49 +0530305 .msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800306};
307static struct mmc_platform_data *apq8064_sdc3_pdata = &sdc3_data;
308#else
309static struct mmc_platform_data *apq8064_sdc3_pdata;
310#endif
311
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700312
313#ifdef CONFIG_MMC_MSM_SDC4_SUPPORT
314static unsigned int sdc4_sup_clk_rates[] = {
315 400000, 24000000, 48000000
316};
317
318static struct mmc_platform_data sdc4_data = {
319 .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
320 .mmc_bus_width = MMC_CAP_4_BIT_DATA,
321 .sup_clk_table = sdc4_sup_clk_rates,
322 .sup_clk_cnt = ARRAY_SIZE(sdc4_sup_clk_rates),
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700323 .pin_data = &mmc_slot_pin_data[SDCC4],
324 .sdiowakeup_irq = MSM_GPIO_TO_INT(65),
325 .msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
326};
327static struct mmc_platform_data *apq8064_sdc4_pdata = &sdc4_data;
328#else
329static struct mmc_platform_data *apq8064_sdc4_pdata;
330#endif
331
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800332void __init apq8064_init_mmc(void)
333{
Oluwafemi Adeyemi784b4392012-04-10 13:49:38 -0700334 if (apq8064_sdc1_pdata)
Oluwafemi Adeyemif5a31422012-03-08 16:58:45 -0800335 apq8064_add_sdcc(1, apq8064_sdc1_pdata);
Oluwafemi Adeyemi784b4392012-04-10 13:49:38 -0700336
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700337 if (apq8064_sdc2_pdata)
338 apq8064_add_sdcc(2, apq8064_sdc2_pdata);
339
Oluwafemi Adeyemif5a31422012-03-08 16:58:45 -0800340 if (apq8064_sdc3_pdata) {
Pratibhasagar V6bdb54a2012-09-27 15:42:46 +0530341 if (machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv()) {
342 apq8064_sdc3_pdata->uhs_caps &= ~(MMC_CAP_UHS_SDR12 |
343 MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_DDR50 |
344 MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104);
345 }
Oluwafemi Adeyemi48fc3262012-03-19 13:26:52 -0700346 if (!machine_is_apq8064_cdp()) {
347 apq8064_sdc3_pdata->wpswitch_gpio = 0;
Sujit Reddy Thumma8f912ea2012-06-22 16:18:43 +0530348 apq8064_sdc3_pdata->is_wpswitch_active_low = false;
Oluwafemi Adeyemi48fc3262012-03-19 13:26:52 -0700349 }
Oluwafemi Adeyemi0d469ce2012-05-10 18:04:25 -0700350 if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
351 machine_is_mpq8064_dtv()) {
Sujit Reddy Thumma17108392012-06-06 14:41:47 +0530352 int rc;
353 struct pm_gpio sd_card_det_init_cfg = {
354 .direction = PM_GPIO_DIR_IN,
355 .output_buffer = PM_GPIO_OUT_BUF_CMOS,
356 .pull = PM_GPIO_PULL_UP_30,
357 .vin_sel = PM_GPIO_VIN_S4,
358 .out_strength = PM_GPIO_STRENGTH_NO,
359 .function = PM_GPIO_FUNC_NORMAL,
360 };
361
Oluwafemi Adeyemi0d469ce2012-05-10 18:04:25 -0700362 apq8064_sdc3_pdata->status_gpio =
363 PM8921_GPIO_PM_TO_SYS(31);
364 apq8064_sdc3_pdata->status_irq =
365 PM8921_GPIO_IRQ(PM8921_IRQ_BASE, 31);
Sujit Reddy Thumma17108392012-06-06 14:41:47 +0530366 rc = pm8xxx_gpio_config(apq8064_sdc3_pdata->status_gpio,
367 &sd_card_det_init_cfg);
368 if (rc) {
369 pr_info("%s: SD_CARD_DET GPIO%d config "
370 "failed(%d)\n", __func__,
371 apq8064_sdc3_pdata->status_gpio, rc);
372 apq8064_sdc3_pdata->status_gpio = 0;
373 apq8064_sdc3_pdata->status_irq = 0;
374 }
Oluwafemi Adeyemi0d469ce2012-05-10 18:04:25 -0700375 }
Subhash Jadavani990c8ed2012-07-04 12:30:48 +0530376 if (machine_is_apq8064_cdp()) {
377 int i;
378
379 for (i = 0;
380 i < apq8064_sdc3_pdata->pin_data->pad_data->\
381 drv->size;
382 i++)
383 apq8064_sdc3_pdata->pin_data->pad_data->\
384 drv->on[i].val = GPIO_CFG_10MA;
385 }
Pratibhasagar V30eb4c32012-10-08 15:51:49 +0530386 if (machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv()) {
387 apq8064_sdc3_pdata->pin_data->pad_data->\
388 drv->on[0].val = GPIO_CFG_16MA;
389 apq8064_sdc3_pdata->pin_data->pad_data->\
390 drv->on[1].val = GPIO_CFG_10MA;
391 apq8064_sdc3_pdata->pin_data->pad_data->\
392 drv->on[2].val = GPIO_CFG_10MA;
393 }
Oluwafemi Adeyemif5a31422012-03-08 16:58:45 -0800394 apq8064_add_sdcc(3, apq8064_sdc3_pdata);
395 }
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700396
397 if (apq8064_sdc4_pdata)
398 apq8064_add_sdcc(4, apq8064_sdc4_pdata);
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800399}