aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-msm/board-qsd8x50.c81
-rw-r--r--arch/arm/mach-msm/devices-qsd8x50.c196
-rw-r--r--arch/arm/mach-msm/gpiomux-8x50.c23
-rw-r--r--arch/arm/mach-msm/include/mach/mmc.h11
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap-8x50.h8
-rw-r--r--drivers/mmc/host/msm_sdcc.c92
-rw-r--r--drivers/mmc/host/msm_sdcc.h1
7 files changed, 376 insertions, 36 deletions
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index 6dde8185205f..29ef683c8048 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -1,4 +1,4 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. 1/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
2 * 2 *
3 * This program is free software; you can redistribute it and/or modify 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 4 * it under the terms of the GNU General Public License version 2 and
@@ -21,6 +21,7 @@
21#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/delay.h> 22#include <linux/delay.h>
23#include <linux/usb/msm_hsusb.h> 23#include <linux/usb/msm_hsusb.h>
24#include <linux/err.h>
24 25
25#include <asm/mach-types.h> 26#include <asm/mach-types.h>
26#include <asm/mach/arch.h> 27#include <asm/mach/arch.h>
@@ -31,6 +32,8 @@
31#include <mach/irqs.h> 32#include <mach/irqs.h>
32#include <mach/sirc.h> 33#include <mach/sirc.h>
33#include <mach/gpio.h> 34#include <mach/gpio.h>
35#include <mach/vreg.h>
36#include <mach/mmc.h>
34 37
35#include "devices.h" 38#include "devices.h"
36 39
@@ -95,6 +98,81 @@ static struct platform_device *devices[] __initdata = {
95 &msm_device_hsusb_host, 98 &msm_device_hsusb_host,
96}; 99};
97 100
101static struct msm_mmc_gpio sdc1_gpio_cfg[] = {
102 {51, "sdc1_dat_3"},
103 {52, "sdc1_dat_2"},
104 {53, "sdc1_dat_1"},
105 {54, "sdc1_dat_0"},
106 {55, "sdc1_cmd"},
107 {56, "sdc1_clk"}
108};
109
110static struct vreg *vreg_mmc;
111static unsigned long vreg_sts;
112
113static uint32_t msm_sdcc_setup_power(struct device *dv, unsigned int vdd)
114{
115 int rc = 0;
116 struct platform_device *pdev;
117
118 pdev = container_of(dv, struct platform_device, dev);
119
120 if (vdd == 0) {
121 if (!vreg_sts)
122 return 0;
123
124 clear_bit(pdev->id, &vreg_sts);
125
126 if (!vreg_sts) {
127 rc = vreg_disable(vreg_mmc);
128 if (rc)
129 pr_err("vreg_mmc disable failed for slot "
130 "%d: %d\n", pdev->id, rc);
131 }
132 return 0;
133 }
134
135 if (!vreg_sts) {
136 rc = vreg_set_level(vreg_mmc, 2900);
137 if (rc)
138 pr_err("vreg_mmc set level failed for slot %d: %d\n",
139 pdev->id, rc);
140 rc = vreg_enable(vreg_mmc);
141 if (rc)
142 pr_err("vreg_mmc enable failed for slot %d: %d\n",
143 pdev->id, rc);
144 }
145 set_bit(pdev->id, &vreg_sts);
146 return 0;
147}
148
149static struct msm_mmc_gpio_data sdc1_gpio = {
150 .gpio = sdc1_gpio_cfg,
151 .size = ARRAY_SIZE(sdc1_gpio_cfg),
152};
153
154static struct msm_mmc_platform_data qsd8x50_sdc1_data = {
155 .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
156 .translate_vdd = msm_sdcc_setup_power,
157 .gpio_data = &sdc1_gpio,
158};
159
160static void __init qsd8x50_init_mmc(void)
161{
162 if (machine_is_qsd8x50_ffa() || machine_is_qsd8x50a_ffa())
163 vreg_mmc = vreg_get(NULL, "gp6");
164 else
165 vreg_mmc = vreg_get(NULL, "gp5");
166
167 if (IS_ERR(vreg_mmc)) {
168 pr_err("vreg get for vreg_mmc failed (%ld)\n",
169 PTR_ERR(vreg_mmc));
170 return;
171 }
172
173 msm_add_sdcc(1, &qsd8x50_sdc1_data, 0, 0);
174}
175
98static void __init qsd8x50_map_io(void) 176static void __init qsd8x50_map_io(void)
99{ 177{
100 msm_map_qsd8x50_io(); 178 msm_map_qsd8x50_io();
@@ -113,6 +191,7 @@ static void __init qsd8x50_init(void)
113 msm_device_hsusb.dev.parent = &msm_device_otg.dev; 191 msm_device_hsusb.dev.parent = &msm_device_otg.dev;
114 msm_device_hsusb_host.dev.parent = &msm_device_otg.dev; 192 msm_device_hsusb_host.dev.parent = &msm_device_otg.dev;
115 platform_add_devices(devices, ARRAY_SIZE(devices)); 193 platform_add_devices(devices, ARRAY_SIZE(devices));
194 qsd8x50_init_mmc();
116} 195}
117 196
118MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF") 197MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index 93bddacad904..c9fa6552ff7d 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -125,6 +125,194 @@ struct platform_device msm_device_hsusb_host = {
125 }, 125 },
126}; 126};
127 127
128static struct resource resources_sdc1[] = {
129 {
130 .start = MSM_SDC1_PHYS,
131 .end = MSM_SDC1_PHYS + MSM_SDC1_SIZE - 1,
132 .flags = IORESOURCE_MEM,
133 },
134 {
135 .start = INT_SDC1_0,
136 .end = INT_SDC1_0,
137 .flags = IORESOURCE_IRQ,
138 .name = "cmd_irq",
139 },
140 {
141 .start = INT_SDC1_1,
142 .end = INT_SDC1_1,
143 .flags = IORESOURCE_IRQ,
144 .name = "pio_irq",
145 },
146 {
147 .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
148 .name = "status_irq"
149 },
150 {
151 .start = 8,
152 .end = 8,
153 .flags = IORESOURCE_DMA,
154 },
155};
156
157static struct resource resources_sdc2[] = {
158 {
159 .start = MSM_SDC2_PHYS,
160 .end = MSM_SDC2_PHYS + MSM_SDC2_SIZE - 1,
161 .flags = IORESOURCE_MEM,
162 },
163 {
164 .start = INT_SDC2_0,
165 .end = INT_SDC2_0,
166 .flags = IORESOURCE_IRQ,
167 .name = "cmd_irq",
168 },
169 {
170 .start = INT_SDC2_1,
171 .end = INT_SDC2_1,
172 .flags = IORESOURCE_IRQ,
173 .name = "pio_irq",
174 },
175 {
176 .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
177 .name = "status_irq"
178 },
179 {
180 .start = 8,
181 .end = 8,
182 .flags = IORESOURCE_DMA,
183 },
184};
185
186static struct resource resources_sdc3[] = {
187 {
188 .start = MSM_SDC3_PHYS,
189 .end = MSM_SDC3_PHYS + MSM_SDC3_SIZE - 1,
190 .flags = IORESOURCE_MEM,
191 },
192 {
193 .start = INT_SDC3_0,
194 .end = INT_SDC3_0,
195 .flags = IORESOURCE_IRQ,
196 .name = "cmd_irq",
197 },
198 {
199 .start = INT_SDC3_1,
200 .end = INT_SDC3_1,
201 .flags = IORESOURCE_IRQ,
202 .name = "pio_irq",
203 },
204 {
205 .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
206 .name = "status_irq"
207 },
208 {
209 .start = 8,
210 .end = 8,
211 .flags = IORESOURCE_DMA,
212 },
213};
214
215static struct resource resources_sdc4[] = {
216 {
217 .start = MSM_SDC4_PHYS,
218 .end = MSM_SDC4_PHYS + MSM_SDC4_SIZE - 1,
219 .flags = IORESOURCE_MEM,
220 },
221 {
222 .start = INT_SDC4_0,
223 .end = INT_SDC4_0,
224 .flags = IORESOURCE_IRQ,
225 .name = "cmd_irq",
226 },
227 {
228 .start = INT_SDC4_1,
229 .end = INT_SDC4_1,
230 .flags = IORESOURCE_IRQ,
231 .name = "pio_irq",
232 },
233 {
234 .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED,
235 .name = "status_irq"
236 },
237 {
238 .start = 8,
239 .end = 8,
240 .flags = IORESOURCE_DMA,
241 },
242};
243
244struct platform_device msm_device_sdc1 = {
245 .name = "msm_sdcc",
246 .id = 1,
247 .num_resources = ARRAY_SIZE(resources_sdc1),
248 .resource = resources_sdc1,
249 .dev = {
250 .coherent_dma_mask = 0xffffffff,
251 },
252};
253
254struct platform_device msm_device_sdc2 = {
255 .name = "msm_sdcc",
256 .id = 2,
257 .num_resources = ARRAY_SIZE(resources_sdc2),
258 .resource = resources_sdc2,
259 .dev = {
260 .coherent_dma_mask = 0xffffffff,
261 },
262};
263
264struct platform_device msm_device_sdc3 = {
265 .name = "msm_sdcc",
266 .id = 3,
267 .num_resources = ARRAY_SIZE(resources_sdc3),
268 .resource = resources_sdc3,
269 .dev = {
270 .coherent_dma_mask = 0xffffffff,
271 },
272};
273
274struct platform_device msm_device_sdc4 = {
275 .name = "msm_sdcc",
276 .id = 4,
277 .num_resources = ARRAY_SIZE(resources_sdc4),
278 .resource = resources_sdc4,
279 .dev = {
280 .coherent_dma_mask = 0xffffffff,
281 },
282};
283
284static struct platform_device *msm_sdcc_devices[] __initdata = {
285 &msm_device_sdc1,
286 &msm_device_sdc2,
287 &msm_device_sdc3,
288 &msm_device_sdc4,
289};
290
291int __init msm_add_sdcc(unsigned int controller,
292 struct msm_mmc_platform_data *plat,
293 unsigned int stat_irq, unsigned long stat_irq_flags)
294{
295 struct platform_device *pdev;
296 struct resource *res;
297
298 if (controller < 1 || controller > 4)
299 return -EINVAL;
300
301 pdev = msm_sdcc_devices[controller-1];
302 pdev->dev.platform_data = plat;
303
304 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "status_irq");
305 if (!res)
306 return -EINVAL;
307 else if (stat_irq) {
308 res->start = res->end = stat_irq;
309 res->flags &= ~IORESOURCE_DISABLED;
310 res->flags |= stat_irq_flags;
311 }
312
313 return platform_device_register(pdev);
314}
315
128struct clk msm_clocks_8x50[] = { 316struct clk msm_clocks_8x50[] = {
129 CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), 317 CLK_PCOM("adm_clk", ADM_CLK, NULL, 0),
130 CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN), 318 CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN),
@@ -145,6 +333,14 @@ struct clk msm_clocks_8x50[] = {
145 CLK_PCOM("pbus_clk", PBUS_CLK, NULL, CLK_MIN), 333 CLK_PCOM("pbus_clk", PBUS_CLK, NULL, CLK_MIN),
146 CLK_PCOM("pcm_clk", PCM_CLK, NULL, 0), 334 CLK_PCOM("pcm_clk", PCM_CLK, NULL, 0),
147 CLK_PCOM("sdac_clk", SDAC_CLK, NULL, OFF), 335 CLK_PCOM("sdac_clk", SDAC_CLK, NULL, OFF),
336 CLK_PCOM("sdc_clk", SDC1_CLK, &msm_device_sdc1.dev, OFF),
337 CLK_PCOM("sdc_pclk", SDC1_P_CLK, &msm_device_sdc1.dev, OFF),
338 CLK_PCOM("sdc_clk", SDC2_CLK, &msm_device_sdc2.dev, OFF),
339 CLK_PCOM("sdc_pclk", SDC2_P_CLK, &msm_device_sdc2.dev, OFF),
340 CLK_PCOM("sdc_clk", SDC3_CLK, &msm_device_sdc3.dev, OFF),
341 CLK_PCOM("sdc_pclk", SDC3_P_CLK, &msm_device_sdc3.dev, OFF),
342 CLK_PCOM("sdc_clk", SDC4_CLK, &msm_device_sdc4.dev, OFF),
343 CLK_PCOM("sdc_pclk", SDC4_P_CLK, &msm_device_sdc4.dev, OFF),
148 CLK_PCOM("spi_clk", SPI_CLK, NULL, 0), 344 CLK_PCOM("spi_clk", SPI_CLK, NULL, 0),
149 CLK_PCOM("tsif_clk", TSIF_CLK, NULL, 0), 345 CLK_PCOM("tsif_clk", TSIF_CLK, NULL, 0),
150 CLK_PCOM("tsif_ref_clk", TSIF_REF_CLK, NULL, 0), 346 CLK_PCOM("tsif_ref_clk", TSIF_REF_CLK, NULL, 0),
diff --git a/arch/arm/mach-msm/gpiomux-8x50.c b/arch/arm/mach-msm/gpiomux-8x50.c
index 4406e0f4ae95..f7a4ea593c95 100644
--- a/arch/arm/mach-msm/gpiomux-8x50.c
+++ b/arch/arm/mach-msm/gpiomux-8x50.c
@@ -16,6 +16,19 @@
16 */ 16 */
17#include "gpiomux.h" 17#include "gpiomux.h"
18 18
19#if defined(CONFIG_MMC_MSM) || defined(CONFIG_MMC_MSM_MODULE)
20 #define SDCC_DAT_0_3_CMD_ACTV_CFG (GPIOMUX_VALID | GPIOMUX_PULL_UP\
21 | GPIOMUX_FUNC_1 | GPIOMUX_DRV_8MA)
22 #define SDCC_CLK_ACTV_CFG (GPIOMUX_VALID | GPIOMUX_PULL_NONE\
23 | GPIOMUX_FUNC_1 | GPIOMUX_DRV_8MA)
24#else
25 #define SDCC_DAT_0_3_CMD_ACTV_CFG 0
26 #define SDCC_CLK_ACTV_CFG 0
27#endif
28
29#define SDC1_SUSPEND_CONFIG (GPIOMUX_VALID | GPIOMUX_PULL_DOWN\
30 | GPIOMUX_FUNC_GPIO | GPIOMUX_DRV_2MA)
31
19struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = { 32struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
20 [86] = { /* UART3 RX */ 33 [86] = { /* UART3 RX */
21 .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN | 34 .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
@@ -25,4 +38,14 @@ struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
25 .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN | 38 .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
26 GPIOMUX_FUNC_1 | GPIOMUX_VALID, 39 GPIOMUX_FUNC_1 | GPIOMUX_VALID,
27 }, 40 },
41 /* SDC1 data[3:0] & CMD */
42 [51 ... 55] = {
43 .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
44 .suspended = SDC1_SUSPEND_CONFIG
45 },
46 /* SDC1 CLK */
47 [56] = {
48 .active = SDCC_CLK_ACTV_CFG,
49 .suspended = SDC1_SUSPEND_CONFIG
50 },
28}; 51};
diff --git a/arch/arm/mach-msm/include/mach/mmc.h b/arch/arm/mach-msm/include/mach/mmc.h
index d54b6b086cff..5631b51cec46 100644
--- a/arch/arm/mach-msm/include/mach/mmc.h
+++ b/arch/arm/mach-msm/include/mach/mmc.h
@@ -15,12 +15,23 @@ struct embedded_sdio_data {
15 int num_funcs; 15 int num_funcs;
16}; 16};
17 17
18struct msm_mmc_gpio {
19 unsigned no;
20 const char *name;
21};
22
23struct msm_mmc_gpio_data {
24 struct msm_mmc_gpio *gpio;
25 u8 size;
26};
27
18struct msm_mmc_platform_data { 28struct msm_mmc_platform_data {
19 unsigned int ocr_mask; /* available voltages */ 29 unsigned int ocr_mask; /* available voltages */
20 u32 (*translate_vdd)(struct device *, unsigned int); 30 u32 (*translate_vdd)(struct device *, unsigned int);
21 unsigned int (*status)(struct device *); 31 unsigned int (*status)(struct device *);
22 struct embedded_sdio_data *embedded_sdio; 32 struct embedded_sdio_data *embedded_sdio;
23 int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id); 33 int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
34 struct msm_mmc_gpio_data *gpio_data;
24}; 35};
25 36
26#endif 37#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
index cf1c2df1d953..d4143201999f 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
@@ -124,16 +124,16 @@
124#define MSM_UART2DM_PHYS 0xA0900000 124#define MSM_UART2DM_PHYS 0xA0900000
125 125
126 126
127#define MSM_SDC1_PHYS 0xA0400000 127#define MSM_SDC1_PHYS 0xA0300000
128#define MSM_SDC1_SIZE SZ_4K 128#define MSM_SDC1_SIZE SZ_4K
129 129
130#define MSM_SDC2_PHYS 0xA0500000 130#define MSM_SDC2_PHYS 0xA0400000
131#define MSM_SDC2_SIZE SZ_4K 131#define MSM_SDC2_SIZE SZ_4K
132 132
133#define MSM_SDC3_PHYS 0xA0600000 133#define MSM_SDC3_PHYS 0xA0500000
134#define MSM_SDC3_SIZE SZ_4K 134#define MSM_SDC3_SIZE SZ_4K
135 135
136#define MSM_SDC4_PHYS 0xA0700000 136#define MSM_SDC4_PHYS 0xA0600000
137#define MSM_SDC4_SIZE SZ_4K 137#define MSM_SDC4_SIZE SZ_4K
138 138
139#endif 139#endif
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 5decfd0bd61d..97c9b3638d57 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -36,6 +36,7 @@
36#include <linux/io.h> 36#include <linux/io.h>
37#include <linux/memory.h> 37#include <linux/memory.h>
38#include <linux/gfp.h> 38#include <linux/gfp.h>
39#include <linux/gpio.h>
39 40
40#include <asm/cacheflush.h> 41#include <asm/cacheflush.h>
41#include <asm/div64.h> 42#include <asm/div64.h>
@@ -383,14 +384,30 @@ static int msmsdcc_config_dma(struct msmsdcc_host *host, struct mmc_data *data)
383 host->curr.user_pages = 0; 384 host->curr.user_pages = 0;
384 385
385 box = &nc->cmd[0]; 386 box = &nc->cmd[0];
386 for (i = 0; i < host->dma.num_ents; i++) {
387 box->cmd = CMD_MODE_BOX;
388 387
389 /* Initialize sg dma address */ 388 /* location of command block must be 64 bit aligned */
390 sg->dma_address = page_to_dma(mmc_dev(host->mmc), sg_page(sg)) 389 BUG_ON(host->dma.cmd_busaddr & 0x07);
391 + sg->offset; 390
391 nc->cmdptr = (host->dma.cmd_busaddr >> 3) | CMD_PTR_LP;
392 host->dma.hdr.cmdptr = DMOV_CMD_PTR_LIST |
393 DMOV_CMD_ADDR(host->dma.cmdptr_busaddr);
394 host->dma.hdr.complete_func = msmsdcc_dma_complete_func;
392 395
393 if (i == (host->dma.num_ents - 1)) 396 n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
397 host->dma.num_ents, host->dma.dir);
398 if (n == 0) {
399 printk(KERN_ERR "%s: Unable to map in all sg elements\n",
400 mmc_hostname(host->mmc));
401 host->dma.sg = NULL;
402 host->dma.num_ents = 0;
403 return -ENOMEM;
404 }
405
406 for_each_sg(host->dma.sg, sg, n, i) {
407
408 box->cmd = CMD_MODE_BOX;
409
410 if (i == n - 1)
394 box->cmd |= CMD_LC; 411 box->cmd |= CMD_LC;
395 rows = (sg_dma_len(sg) % MCI_FIFOSIZE) ? 412 rows = (sg_dma_len(sg) % MCI_FIFOSIZE) ?
396 (sg_dma_len(sg) / MCI_FIFOSIZE) + 1 : 413 (sg_dma_len(sg) / MCI_FIFOSIZE) + 1 :
@@ -418,27 +435,6 @@ static int msmsdcc_config_dma(struct msmsdcc_host *host, struct mmc_data *data)
418 box->cmd |= CMD_DST_CRCI(crci); 435 box->cmd |= CMD_DST_CRCI(crci);
419 } 436 }
420 box++; 437 box++;
421 sg++;
422 }
423
424 /* location of command block must be 64 bit aligned */
425 BUG_ON(host->dma.cmd_busaddr & 0x07);
426
427 nc->cmdptr = (host->dma.cmd_busaddr >> 3) | CMD_PTR_LP;
428 host->dma.hdr.cmdptr = DMOV_CMD_PTR_LIST |
429 DMOV_CMD_ADDR(host->dma.cmdptr_busaddr);
430 host->dma.hdr.complete_func = msmsdcc_dma_complete_func;
431
432 n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
433 host->dma.num_ents, host->dma.dir);
434/* dsb inside dma_map_sg will write nc out to mem as well */
435
436 if (n != host->dma.num_ents) {
437 printk(KERN_ERR "%s: Unable to map in all sg elements\n",
438 mmc_hostname(host->mmc));
439 host->dma.sg = NULL;
440 host->dma.num_ents = 0;
441 return -ENOMEM;
442 } 438 }
443 439
444 return 0; 440 return 0;
@@ -946,6 +942,38 @@ msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
946 spin_unlock_irqrestore(&host->lock, flags); 942 spin_unlock_irqrestore(&host->lock, flags);
947} 943}
948 944
945static void msmsdcc_setup_gpio(struct msmsdcc_host *host, bool enable)
946{
947 struct msm_mmc_gpio_data *curr;
948 int i, rc = 0;
949
950 if (!host->plat->gpio_data && host->gpio_config_status == enable)
951 return;
952
953 curr = host->plat->gpio_data;
954 for (i = 0; i < curr->size; i++) {
955 if (enable) {
956 rc = gpio_request(curr->gpio[i].no,
957 curr->gpio[i].name);
958 if (rc) {
959 pr_err("%s: gpio_request(%d, %s) failed %d\n",
960 mmc_hostname(host->mmc),
961 curr->gpio[i].no,
962 curr->gpio[i].name, rc);
963 goto free_gpios;
964 }
965 } else {
966 gpio_free(curr->gpio[i].no);
967 }
968 }
969 host->gpio_config_status = enable;
970 return;
971
972free_gpios:
973 for (; i >= 0; i--)
974 gpio_free(curr->gpio[i].no);
975}
976
949static void 977static void
950msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 978msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
951{ 979{
@@ -958,6 +986,8 @@ msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
958 986
959 msmsdcc_enable_clocks(host); 987 msmsdcc_enable_clocks(host);
960 988
989 spin_unlock_irqrestore(&host->lock, flags);
990
961 if (ios->clock) { 991 if (ios->clock) {
962 if (ios->clock != host->clk_rate) { 992 if (ios->clock != host->clk_rate) {
963 rc = clk_set_rate(host->clk, ios->clock); 993 rc = clk_set_rate(host->clk, ios->clock);
@@ -984,9 +1014,11 @@ msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
984 1014
985 switch (ios->power_mode) { 1015 switch (ios->power_mode) {
986 case MMC_POWER_OFF: 1016 case MMC_POWER_OFF:
1017 msmsdcc_setup_gpio(host, false);
987 break; 1018 break;
988 case MMC_POWER_UP: 1019 case MMC_POWER_UP:
989 pwr |= MCI_PWR_UP; 1020 pwr |= MCI_PWR_UP;
1021 msmsdcc_setup_gpio(host, true);
990 break; 1022 break;
991 case MMC_POWER_ON: 1023 case MMC_POWER_ON:
992 pwr |= MCI_PWR_ON; 1024 pwr |= MCI_PWR_ON;
@@ -1003,9 +1035,10 @@ msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1003 msmsdcc_writel(host, pwr, MMCIPOWER); 1035 msmsdcc_writel(host, pwr, MMCIPOWER);
1004 } 1036 }
1005#if BUSCLK_PWRSAVE 1037#if BUSCLK_PWRSAVE
1038 spin_lock_irqsave(&host->lock, flags);
1006 msmsdcc_disable_clocks(host, 1); 1039 msmsdcc_disable_clocks(host, 1);
1007#endif
1008 spin_unlock_irqrestore(&host->lock, flags); 1040 spin_unlock_irqrestore(&host->lock, flags);
1041#endif
1009} 1042}
1010 1043
1011static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable) 1044static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
@@ -1331,9 +1364,6 @@ msmsdcc_probe(struct platform_device *pdev)
1331 if (host->timer.function) 1364 if (host->timer.function)
1332 pr_info("%s: Polling status mode enabled\n", mmc_hostname(mmc)); 1365 pr_info("%s: Polling status mode enabled\n", mmc_hostname(mmc));
1333 1366
1334#if BUSCLK_PWRSAVE
1335 msmsdcc_disable_clocks(host, 1);
1336#endif
1337 return 0; 1367 return 0;
1338 cmd_irq_free: 1368 cmd_irq_free:
1339 free_irq(cmd_irqres->start, host); 1369 free_irq(cmd_irqres->start, host);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 939557af266d..42d7bbc977c5 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -243,6 +243,7 @@ struct msmsdcc_host {
243 unsigned int cmd_datactrl; 243 unsigned int cmd_datactrl;
244 struct mmc_command *cmd_cmd; 244 struct mmc_command *cmd_cmd;
245 u32 cmd_c; 245 u32 cmd_c;
246 bool gpio_config_status;
246 247
247 bool prog_scan; 248 bool prog_scan;
248 bool prog_enable; 249 bool prog_enable;