aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/omap.c48
1 files changed, 42 insertions, 6 deletions
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 3d59c5d81b3d..ab0974d261e5 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -138,6 +138,11 @@ struct mmc_omap_host {
138 unsigned abort:1; 138 unsigned abort:1;
139 struct timer_list cmd_abort_timer; 139 struct timer_list cmd_abort_timer;
140 140
141 struct work_struct slot_release_work;
142 struct mmc_omap_slot *next_slot;
143 struct work_struct send_stop_work;
144 struct mmc_data *stop_data;
145
141 unsigned int sg_len; 146 unsigned int sg_len;
142 int sg_idx; 147 int sg_idx;
143 u16 * buffer; 148 u16 * buffer;
@@ -236,6 +241,21 @@ no_claim:
236static void mmc_omap_start_request(struct mmc_omap_host *host, 241static void mmc_omap_start_request(struct mmc_omap_host *host,
237 struct mmc_request *req); 242 struct mmc_request *req);
238 243
244static void mmc_omap_slot_release_work(struct work_struct *work)
245{
246 struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
247 slot_release_work);
248 struct mmc_omap_slot *next_slot = host->next_slot;
249 struct mmc_request *rq;
250
251 host->next_slot = NULL;
252 mmc_omap_select_slot(next_slot, 1);
253
254 rq = next_slot->mrq;
255 next_slot->mrq = NULL;
256 mmc_omap_start_request(host, rq);
257}
258
239static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled) 259static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled)
240{ 260{
241 struct mmc_omap_host *host = slot->host; 261 struct mmc_omap_host *host = slot->host;
@@ -257,21 +277,19 @@ static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled)
257 /* Check for any pending requests */ 277 /* Check for any pending requests */
258 for (i = 0; i < host->nr_slots; i++) { 278 for (i = 0; i < host->nr_slots; i++) {
259 struct mmc_omap_slot *new_slot; 279 struct mmc_omap_slot *new_slot;
260 struct mmc_request *rq;
261 280
262 if (host->slots[i] == NULL || host->slots[i]->mrq == NULL) 281 if (host->slots[i] == NULL || host->slots[i]->mrq == NULL)
263 continue; 282 continue;
264 283
284 BUG_ON(host->next_slot != NULL);
265 new_slot = host->slots[i]; 285 new_slot = host->slots[i];
266 /* The current slot should not have a request in queue */ 286 /* The current slot should not have a request in queue */
267 BUG_ON(new_slot == host->current_slot); 287 BUG_ON(new_slot == host->current_slot);
268 288
289 host->next_slot = new_slot;
269 host->mmc = new_slot->mmc; 290 host->mmc = new_slot->mmc;
270 spin_unlock_irqrestore(&host->slot_lock, flags); 291 spin_unlock_irqrestore(&host->slot_lock, flags);
271 mmc_omap_select_slot(new_slot, 1); 292 schedule_work(&host->slot_release_work);
272 rq = new_slot->mrq;
273 new_slot->mrq = NULL;
274 mmc_omap_start_request(host, rq);
275 return; 293 return;
276 } 294 }
277 295
@@ -400,6 +418,20 @@ mmc_omap_release_dma(struct mmc_omap_host *host, struct mmc_data *data,
400 dma_data_dir); 418 dma_data_dir);
401} 419}
402 420
421static void mmc_omap_send_stop_work(struct work_struct *work)
422{
423 struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
424 send_stop_work);
425 struct mmc_omap_slot *slot = host->current_slot;
426 struct mmc_data *data = host->stop_data;
427 unsigned long tick_ns;
428
429 tick_ns = (1000000000 + slot->fclk_freq - 1)/slot->fclk_freq;
430 ndelay(8*tick_ns);
431
432 mmc_omap_start_command(host, data->stop);
433}
434
403static void 435static void
404mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data) 436mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
405{ 437{
@@ -424,7 +456,8 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
424 return; 456 return;
425 } 457 }
426 458
427 mmc_omap_start_command(host, data->stop); 459 host->stop_data = data;
460 schedule_work(&host->send_stop_work);
428} 461}
429 462
430static void 463static void
@@ -1389,6 +1422,9 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
1389 goto err_free_mem_region; 1422 goto err_free_mem_region;
1390 } 1423 }
1391 1424
1425 INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work);
1426 INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work);
1427
1392 INIT_WORK(&host->cmd_abort_work, mmc_omap_abort_command); 1428 INIT_WORK(&host->cmd_abort_work, mmc_omap_abort_command);
1393 setup_timer(&host->cmd_abort_timer, mmc_omap_cmd_timer, 1429 setup_timer(&host->cmd_abort_timer, mmc_omap_cmd_timer,
1394 (unsigned long) host); 1430 (unsigned long) host);