blob: cdcc2cd52b7e61b8fb523fba6c355aea638d52e6 [file] [log] [blame]
Duy Truonge833aca2013-02-12 13:35:08 -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>
Subhash Jadavani83457bd2012-09-20 19:55:16 +053024#include <mach/socinfo.h>
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080025#include "devices.h"
Stepan Moskovchenko5a83dba2011-12-05 17:30:17 -080026#include "board-8064.h"
Subhash Jadavanibcd435f2012-04-24 18:26:49 +053027#include "board-storage-common-a.h"
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080028
29
30/* APQ8064 has 4 SDCC controllers */
31enum sdcc_controllers {
32 SDCC1,
33 SDCC2,
34 SDCC3,
35 SDCC4,
36 MAX_SDCC_CONTROLLER
37};
38
39/* All SDCC controllers require VDD/VCC voltage */
40static struct msm_mmc_reg_data mmc_vdd_reg_data[MAX_SDCC_CONTROLLER] = {
41 /* SDCC1 : eMMC card connected */
42 [SDCC1] = {
43 .name = "sdc_vdd",
44 .high_vol_level = 2950000,
45 .low_vol_level = 2950000,
46 .always_on = 1,
47 .lpm_sup = 1,
48 .lpm_uA = 9000,
49 .hpm_uA = 200000, /* 200mA */
50 },
51 /* SDCC3 : External card slot connected */
52 [SDCC3] = {
53 .name = "sdc_vdd",
54 .high_vol_level = 2950000,
55 .low_vol_level = 2950000,
Oluwafemi Adeyemiaafeeb02012-02-20 21:01:15 -080056 .hpm_uA = 800000, /* 800mA */
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080057 }
58};
59
Subhash Jadavani937c7502012-06-01 15:34:46 +053060/* SDCC controllers may require voting for VDD IO voltage */
61static struct msm_mmc_reg_data mmc_vdd_io_reg_data[MAX_SDCC_CONTROLLER] = {
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080062 /* SDCC1 : eMMC card connected */
63 [SDCC1] = {
Subhash Jadavani937c7502012-06-01 15:34:46 +053064 .name = "sdc_vdd_io",
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080065 .always_on = 1,
66 .high_vol_level = 1800000,
67 .low_vol_level = 1800000,
68 .hpm_uA = 200000, /* 200mA */
Subhash Jadavani937c7502012-06-01 15:34:46 +053069 },
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080070 /* SDCC3 : External card slot connected */
71 [SDCC3] = {
Subhash Jadavani937c7502012-06-01 15:34:46 +053072 .name = "sdc_vdd_io",
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080073 .high_vol_level = 2950000,
74 .low_vol_level = 1850000,
75 .always_on = 1,
76 .lpm_sup = 1,
77 /* Max. Active current required is 16 mA */
78 .hpm_uA = 16000,
79 /*
80 * Sleep current required is ~300 uA. But min. vote can be
81 * in terms of mA (min. 1 mA). So let's vote for 2 mA
82 * during sleep.
83 */
84 .lpm_uA = 2000,
85 }
86};
87
88static struct msm_mmc_slot_reg_data mmc_slot_vreg_data[MAX_SDCC_CONTROLLER] = {
89 /* SDCC1 : eMMC card connected */
90 [SDCC1] = {
91 .vdd_data = &mmc_vdd_reg_data[SDCC1],
Subhash Jadavani937c7502012-06-01 15:34:46 +053092 .vdd_io_data = &mmc_vdd_io_reg_data[SDCC1],
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080093 },
94 /* SDCC3 : External card slot connected */
95 [SDCC3] = {
96 .vdd_data = &mmc_vdd_reg_data[SDCC3],
Subhash Jadavani937c7502012-06-01 15:34:46 +053097 .vdd_io_data = &mmc_vdd_io_reg_data[SDCC3],
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -080098 }
99};
100
101/* SDC1 pad data */
102static struct msm_mmc_pad_drv sdc1_pad_drv_on_cfg[] = {
103 {TLMM_HDRV_SDC1_CLK, GPIO_CFG_16MA},
104 {TLMM_HDRV_SDC1_CMD, GPIO_CFG_10MA},
105 {TLMM_HDRV_SDC1_DATA, GPIO_CFG_10MA}
106};
107
108static struct msm_mmc_pad_drv sdc1_pad_drv_off_cfg[] = {
109 {TLMM_HDRV_SDC1_CLK, GPIO_CFG_2MA},
110 {TLMM_HDRV_SDC1_CMD, GPIO_CFG_2MA},
111 {TLMM_HDRV_SDC1_DATA, GPIO_CFG_2MA}
112};
113
114static struct msm_mmc_pad_pull sdc1_pad_pull_on_cfg[] = {
115 {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
116 {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
117 {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
118};
119
120static struct msm_mmc_pad_pull sdc1_pad_pull_off_cfg[] = {
121 {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
Oluwafemi Adeyemi4e196b62012-02-15 14:29:03 -0800122 {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
123 {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800124};
125
126/* SDC3 pad data */
127static struct msm_mmc_pad_drv sdc3_pad_drv_on_cfg[] = {
128 {TLMM_HDRV_SDC3_CLK, GPIO_CFG_8MA},
129 {TLMM_HDRV_SDC3_CMD, GPIO_CFG_8MA},
130 {TLMM_HDRV_SDC3_DATA, GPIO_CFG_8MA}
131};
132
133static struct msm_mmc_pad_drv sdc3_pad_drv_off_cfg[] = {
134 {TLMM_HDRV_SDC3_CLK, GPIO_CFG_2MA},
135 {TLMM_HDRV_SDC3_CMD, GPIO_CFG_2MA},
136 {TLMM_HDRV_SDC3_DATA, GPIO_CFG_2MA}
137};
138
139static struct msm_mmc_pad_pull sdc3_pad_pull_on_cfg[] = {
140 {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
141 {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
142 {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
143};
144
145static struct msm_mmc_pad_pull sdc3_pad_pull_off_cfg[] = {
146 {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
Oluwafemi Adeyemi4e196b62012-02-15 14:29:03 -0800147 {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
148 {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800149};
150
151static struct msm_mmc_pad_pull_data mmc_pad_pull_data[MAX_SDCC_CONTROLLER] = {
152 [SDCC1] = {
153 .on = sdc1_pad_pull_on_cfg,
154 .off = sdc1_pad_pull_off_cfg,
155 .size = ARRAY_SIZE(sdc1_pad_pull_on_cfg)
156 },
157 [SDCC3] = {
158 .on = sdc3_pad_pull_on_cfg,
159 .off = sdc3_pad_pull_off_cfg,
160 .size = ARRAY_SIZE(sdc3_pad_pull_on_cfg)
161 },
162};
163
164static struct msm_mmc_pad_drv_data mmc_pad_drv_data[MAX_SDCC_CONTROLLER] = {
165 [SDCC1] = {
166 .on = sdc1_pad_drv_on_cfg,
167 .off = sdc1_pad_drv_off_cfg,
168 .size = ARRAY_SIZE(sdc1_pad_drv_on_cfg)
169 },
170 [SDCC3] = {
171 .on = sdc3_pad_drv_on_cfg,
172 .off = sdc3_pad_drv_off_cfg,
173 .size = ARRAY_SIZE(sdc3_pad_drv_on_cfg)
174 },
175};
176
177static struct msm_mmc_pad_data mmc_pad_data[MAX_SDCC_CONTROLLER] = {
178 [SDCC1] = {
179 .pull = &mmc_pad_pull_data[SDCC1],
180 .drv = &mmc_pad_drv_data[SDCC1]
181 },
182 [SDCC3] = {
183 .pull = &mmc_pad_pull_data[SDCC3],
184 .drv = &mmc_pad_drv_data[SDCC3]
185 },
186};
187
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700188static struct msm_mmc_gpio sdc2_gpio[] = {
189 {59, "sdc2_clk"},
190 {57, "sdc2_cmd"},
191 {62, "sdc2_dat_0"},
192 {61, "sdc2_dat_1"},
193 {60, "sdc2_dat_2"},
194 {58, "sdc2_dat_3"},
195};
196
197static struct msm_mmc_gpio sdc4_gpio[] = {
198 {68, "sdc4_clk"},
199 {67, "sdc4_cmd"},
200 {66, "sdc4_dat_0"},
201 {65, "sdc4_dat_1"},
202 {64, "sdc4_dat_2"},
203 {63, "sdc4_dat_3"},
204};
205
206static struct msm_mmc_gpio_data mmc_gpio_data[MAX_SDCC_CONTROLLER] = {
207 [SDCC2] = {
208 .gpio = sdc2_gpio,
209 .size = ARRAY_SIZE(sdc2_gpio),
210 },
211 [SDCC4] = {
212 .gpio = sdc4_gpio,
213 .size = ARRAY_SIZE(sdc4_gpio),
214 }
215};
216
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800217static struct msm_mmc_pin_data mmc_slot_pin_data[MAX_SDCC_CONTROLLER] = {
218 [SDCC1] = {
219 .pad_data = &mmc_pad_data[SDCC1],
220 },
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700221 [SDCC2] = {
222 .is_gpio = 1,
223 .gpio_data = &mmc_gpio_data[SDCC2],
224 },
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800225 [SDCC3] = {
226 .pad_data = &mmc_pad_data[SDCC3],
227 },
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700228 [SDCC4] = {
229 .is_gpio = 1,
230 .gpio_data = &mmc_gpio_data[SDCC4],
231 },
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800232};
233
Subhash Jadavani55e188e2012-04-13 11:31:08 +0530234#define MSM_MPM_PIN_SDC1_DAT1 17
235#define MSM_MPM_PIN_SDC3_DAT1 21
236
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800237#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
238static unsigned int sdc1_sup_clk_rates[] = {
239 400000, 24000000, 48000000, 96000000
240};
241
Subhash Jadavani83457bd2012-09-20 19:55:16 +0530242static unsigned int sdc1_sup_clk_rates_all[] = {
243 400000, 24000000, 48000000, 96000000, 192000000
244};
245
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800246static struct mmc_platform_data sdc1_data = {
247 .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
248#ifdef CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT
249 .mmc_bus_width = MMC_CAP_8_BIT_DATA,
250#else
251 .mmc_bus_width = MMC_CAP_4_BIT_DATA,
252#endif
253 .sup_clk_table = sdc1_sup_clk_rates,
254 .sup_clk_cnt = ARRAY_SIZE(sdc1_sup_clk_rates),
Oluwafemi Adeyemi89ff2a12012-03-08 16:44:21 -0800255 .nonremovable = 1,
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800256 .pin_data = &mmc_slot_pin_data[SDCC1],
257 .vreg_data = &mmc_slot_vreg_data[SDCC1],
Oluwafemi Adeyemi1e770962012-03-23 13:08:11 -0700258 .uhs_caps = MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50,
Subhash Jadavanicb6f9ce2012-06-26 11:57:10 +0530259 .uhs_caps2 = MMC_CAP2_HS200_1_8V_SDR,
Maya Erez8d519992012-11-29 00:05:25 +0200260 .packed_write = MMC_CAP2_PACKED_WR | MMC_CAP2_PACKED_WR_CONTROL,
Subhash Jadavani55e188e2012-04-13 11:31:08 +0530261 .mpm_sdiowakeup_int = MSM_MPM_PIN_SDC1_DAT1,
Subhash Jadavanibcd435f2012-04-24 18:26:49 +0530262 .msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800263};
264static struct mmc_platform_data *apq8064_sdc1_pdata = &sdc1_data;
265#else
266static struct mmc_platform_data *apq8064_sdc1_pdata;
267#endif
268
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700269#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
270static unsigned int sdc2_sup_clk_rates[] = {
271 400000, 24000000, 48000000
272};
273
274static struct mmc_platform_data sdc2_data = {
275 .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
276 .mmc_bus_width = MMC_CAP_4_BIT_DATA,
277 .sup_clk_table = sdc2_sup_clk_rates,
278 .sup_clk_cnt = ARRAY_SIZE(sdc2_sup_clk_rates),
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700279 .pin_data = &mmc_slot_pin_data[SDCC2],
280 .sdiowakeup_irq = MSM_GPIO_TO_INT(61),
281 .msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
282};
283static struct mmc_platform_data *apq8064_sdc2_pdata = &sdc2_data;
284#else
285static struct mmc_platform_data *apq8064_sdc2_pdata;
286#endif
287
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800288#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
289static unsigned int sdc3_sup_clk_rates[] = {
Oluwafemi Adeyemi086ef862012-02-07 20:13:50 -0800290 400000, 24000000, 48000000, 96000000, 192000000
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800291};
292
293static struct mmc_platform_data sdc3_data = {
294 .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
295 .mmc_bus_width = MMC_CAP_4_BIT_DATA,
296 .sup_clk_table = sdc3_sup_clk_rates,
297 .sup_clk_cnt = ARRAY_SIZE(sdc3_sup_clk_rates),
298 .pin_data = &mmc_slot_pin_data[SDCC3],
299 .vreg_data = &mmc_slot_vreg_data[SDCC3],
Oluwafemi Adeyemi787ac482012-02-16 09:50:03 -0800300 .wpswitch_gpio = PM8921_GPIO_PM_TO_SYS(17),
Sujit Reddy Thumma8f912ea2012-06-22 16:18:43 +0530301 .is_wpswitch_active_low = true,
Oluwafemi Adeyemi83999672012-02-07 20:01:26 -0800302 .status_gpio = 26,
303 .status_irq = MSM_GPIO_TO_INT(26),
304 .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
305 .is_status_gpio_active_low = 1,
Oluwafemi Adeyemi086ef862012-02-07 20:13:50 -0800306 .xpc_cap = 1,
307 .uhs_caps = (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
308 MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50 |
309 MMC_CAP_UHS_SDR104 | MMC_CAP_MAX_CURRENT_800),
Subhash Jadavani55e188e2012-04-13 11:31:08 +0530310 .mpm_sdiowakeup_int = MSM_MPM_PIN_SDC3_DAT1,
Subhash Jadavanibcd435f2012-04-24 18:26:49 +0530311 .msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800312};
313static struct mmc_platform_data *apq8064_sdc3_pdata = &sdc3_data;
314#else
315static struct mmc_platform_data *apq8064_sdc3_pdata;
316#endif
317
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700318
319#ifdef CONFIG_MMC_MSM_SDC4_SUPPORT
320static unsigned int sdc4_sup_clk_rates[] = {
321 400000, 24000000, 48000000
322};
323
324static struct mmc_platform_data sdc4_data = {
325 .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
326 .mmc_bus_width = MMC_CAP_4_BIT_DATA,
327 .sup_clk_table = sdc4_sup_clk_rates,
328 .sup_clk_cnt = ARRAY_SIZE(sdc4_sup_clk_rates),
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700329 .pin_data = &mmc_slot_pin_data[SDCC4],
330 .sdiowakeup_irq = MSM_GPIO_TO_INT(65),
331 .msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
332};
333static struct mmc_platform_data *apq8064_sdc4_pdata = &sdc4_data;
334#else
335static struct mmc_platform_data *apq8064_sdc4_pdata;
336#endif
337
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800338void __init apq8064_init_mmc(void)
339{
Subhash Jadavani83457bd2012-09-20 19:55:16 +0530340 if (apq8064_sdc1_pdata) {
341 /* 8064 v2 supports upto 200MHz clock on SDC1 slot */
342 if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2) {
343 apq8064_sdc1_pdata->sup_clk_table =
344 sdc1_sup_clk_rates_all;
345 apq8064_sdc1_pdata->sup_clk_cnt =
346 ARRAY_SIZE(sdc1_sup_clk_rates_all);
347 }
Oluwafemi Adeyemif5a31422012-03-08 16:58:45 -0800348 apq8064_add_sdcc(1, apq8064_sdc1_pdata);
Subhash Jadavani83457bd2012-09-20 19:55:16 +0530349 }
Oluwafemi Adeyemi784b4392012-04-10 13:49:38 -0700350
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700351 if (apq8064_sdc2_pdata)
352 apq8064_add_sdcc(2, apq8064_sdc2_pdata);
353
Oluwafemi Adeyemif5a31422012-03-08 16:58:45 -0800354 if (apq8064_sdc3_pdata) {
Oluwafemi Adeyemi48fc3262012-03-19 13:26:52 -0700355 if (!machine_is_apq8064_cdp()) {
356 apq8064_sdc3_pdata->wpswitch_gpio = 0;
Sujit Reddy Thumma8f912ea2012-06-22 16:18:43 +0530357 apq8064_sdc3_pdata->is_wpswitch_active_low = false;
Oluwafemi Adeyemi48fc3262012-03-19 13:26:52 -0700358 }
Oluwafemi Adeyemi0d469ce2012-05-10 18:04:25 -0700359 if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
360 machine_is_mpq8064_dtv()) {
Sujit Reddy Thumma17108392012-06-06 14:41:47 +0530361 int rc;
362 struct pm_gpio sd_card_det_init_cfg = {
363 .direction = PM_GPIO_DIR_IN,
364 .output_buffer = PM_GPIO_OUT_BUF_CMOS,
365 .pull = PM_GPIO_PULL_UP_30,
366 .vin_sel = PM_GPIO_VIN_S4,
367 .out_strength = PM_GPIO_STRENGTH_NO,
368 .function = PM_GPIO_FUNC_NORMAL,
369 };
370
Oluwafemi Adeyemi0d469ce2012-05-10 18:04:25 -0700371 apq8064_sdc3_pdata->status_gpio =
372 PM8921_GPIO_PM_TO_SYS(31);
373 apq8064_sdc3_pdata->status_irq =
374 PM8921_GPIO_IRQ(PM8921_IRQ_BASE, 31);
Sujit Reddy Thumma17108392012-06-06 14:41:47 +0530375 rc = pm8xxx_gpio_config(apq8064_sdc3_pdata->status_gpio,
376 &sd_card_det_init_cfg);
377 if (rc) {
378 pr_info("%s: SD_CARD_DET GPIO%d config "
379 "failed(%d)\n", __func__,
380 apq8064_sdc3_pdata->status_gpio, rc);
381 apq8064_sdc3_pdata->status_gpio = 0;
382 apq8064_sdc3_pdata->status_irq = 0;
383 }
Oluwafemi Adeyemi0d469ce2012-05-10 18:04:25 -0700384 }
Subhash Jadavani990c8ed2012-07-04 12:30:48 +0530385 if (machine_is_apq8064_cdp()) {
386 int i;
387
388 for (i = 0;
389 i < apq8064_sdc3_pdata->pin_data->pad_data->\
390 drv->size;
391 i++)
392 apq8064_sdc3_pdata->pin_data->pad_data->\
393 drv->on[i].val = GPIO_CFG_10MA;
394 }
Oluwafemi Adeyemif5a31422012-03-08 16:58:45 -0800395 apq8064_add_sdcc(3, apq8064_sdc3_pdata);
396 }
Oluwafemi Adeyemia46d0322012-05-16 18:27:44 -0700397
398 if (apq8064_sdc4_pdata)
399 apq8064_add_sdcc(4, apq8064_sdc4_pdata);
Stepan Moskovchenkoe438b632011-12-06 13:44:03 -0800400}