core.c revision af51715079e7fb6b290e1881d63d815dc4de5011
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2aaac1b470bd0dccb30912356617069dc6199cc80Pierre Ossman * linux/drivers/mmc/core/core.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2003-2004 Russell King, All Rights Reserved. 55b4fd9aef778e223968dfab1b90f905b3f2bd23dPierre Ossman * SD support Copyright (C) 2004 Ian Molton, All Rights Reserved. 6b855885e3b60cf6f9452848712a62517b94583ebPierre Ossman * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. 7bce40a36de574376f41f1ff3c4d212a7da2a3c90Philip Langdale * MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved. 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License version 2 as 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * published by the Free Software Foundation. 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/completion.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/device.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pagemap.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/err.h> 21b57c43ad81602589afca3948a5a7121e40026e17Pierre Ossman#include <asm/scatterlist.h> 22b57c43ad81602589afca3948a5a7121e40026e17Pierre Ossman#include <linux/scatterlist.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mmc/card.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mmc/host.h> 26da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include <linux/mmc/mmc.h> 27da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include <linux/mmc/sd.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29aaac1b470bd0dccb30912356617069dc6199cc80Pierre Ossman#include "core.h" 30ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman#include "bus.h" 31ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman#include "host.h" 32e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include "sdio_bus.h" 33da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman 34da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include "mmc_ops.h" 35da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include "sd_ops.h" 365c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman#include "sdio_ops.h" 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 387ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossmanextern int mmc_attach_mmc(struct mmc_host *host, u32 ocr); 397ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossmanextern int mmc_attach_sd(struct mmc_host *host, u32 ocr); 405c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossmanextern int mmc_attach_sdio(struct mmc_host *host, u32 ocr); 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossmanstatic struct workqueue_struct *workqueue; 43ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman 44ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman/* 45ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman * Enabling software CRCs on the data blocks can be a significant (30%) 46ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman * performance cost, and for other reasons may not always be desired. 47ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman * So we allow it it to be disabled. 48ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman */ 49ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossmanint use_spi_crc = 1; 50ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossmanmodule_param(use_spi_crc, bool, 0); 51ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman 52ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman/* 53ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman * Internal function. Schedule delayed work in the MMC work queue. 54ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman */ 55ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossmanstatic int mmc_schedule_delayed_work(struct delayed_work *work, 56ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman unsigned long delay) 57ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman{ 58ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman return queue_delayed_work(workqueue, work, delay); 59ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman} 60ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 62fe10c6abea8bc83291a13e0580b3e4c355710b09Russell King * Internal function. Flush all scheduled work from the MMC work queue. 63fe10c6abea8bc83291a13e0580b3e4c355710b09Russell King */ 64fe10c6abea8bc83291a13e0580b3e4c355710b09Russell Kingstatic void mmc_flush_scheduled_work(void) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flush_workqueue(workqueue); 67fe10c6abea8bc83291a13e0580b3e4c355710b09Russell King} 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mmc_request_done - finish processing an MMC request 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @host: MMC host which completed request 72920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King * @mrq: MMC request which request 73920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King * 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MMC drivers should call this function when they have completed 75e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman * their processing of a request. 76e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman */ 77e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossmanvoid mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_command *cmd = mrq->cmd; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = cmd->error; 81e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman 82e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman if (err && cmd->retries && mmc_host_is_spi(host)) { 83e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND) 84e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman cmd->retries = 0; 85e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman } 86e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman 87e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman if (err && cmd->retries) { 88e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman pr_debug("%s: req failed (CMD%u): %d, retrying...\n", 89e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman mmc_hostname(host), cmd->opcode, err); 90e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman 91e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman cmd->retries--; 92e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman cmd->error = 0; 93e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman host->ops->request(host, mrq); 94e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman } else { 95e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n", 96e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman mmc_hostname(host), cmd->opcode, err, 97e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman cmd->resp[0], cmd->resp[1], 98e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman cmd->resp[2], cmd->resp[3]); 99e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman 100e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman if (mrq->data) { 101e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman pr_debug("%s: %d bytes transferred: %d\n", 102e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman mmc_hostname(host), 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mrq->data->bytes_xfered, mrq->data->error); 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mrq->stop) { 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pr_debug("%s: (CMD%u): %d: %08x %08x %08x %08x\n", 108393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk mmc_hostname(host), mrq->stop->opcode, 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mrq->stop->error, 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mrq->stop->resp[0], mrq->stop->resp[1], 111976d9276c826d6b35e4a2478fd4978dbd63bdd6fPierre Ossman mrq->stop->resp[2], mrq->stop->resp[3]); 112976d9276c826d6b35e4a2478fd4978dbd63bdd6fPierre Ossman } 113976d9276c826d6b35e4a2478fd4978dbd63bdd6fPierre Ossman 114976d9276c826d6b35e4a2478fd4978dbd63bdd6fPierre Ossman if (mrq->done) 115920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King mrq->done(mrq); 116920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King } 117920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King} 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 119e4d217087458914a6d5d9fd034d7237e6530c619Pierre OssmanEXPORT_SYMBOL(mmc_request_done); 120e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman 121e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossmanstatic void 122e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossmanmmc_start_request(struct mmc_host *host, struct mmc_request *mrq) 123e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman{ 124ce252edd869ba1fee6a9a6f83e20f349d4c4d669Pierre Ossman#ifdef CONFIG_MMC_DEBUG 125e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman unsigned int i, sz; 126e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman#endif 127e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman 128e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman pr_debug("%s: starting CMD%u arg %08x flags %08x\n", 129e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman mmc_hostname(host), mrq->cmd->opcode, 130e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman mrq->cmd->arg, mrq->cmd->flags); 131e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman 132e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman if (mrq->data) { 133e4d217087458914a6d5d9fd034d7237e6530c619Pierre Ossman pr_debug("%s: blksz %d blocks %d flags %08x " 134f22ee4edf63e7480511112d9965c71e07be3f8b7Pierre Ossman "tsac %d ms nsac %d\n", 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_hostname(host), mrq->data->blksz, 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mrq->data->blocks, mrq->data->flags, 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mrq->data->timeout_ns / 1000000, 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mrq->data->timeout_clks); 139fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman } 14055db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman 14155db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman if (mrq->stop) { 14255db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman pr_debug("%s: CMD%u arg %08x flags %08x\n", 143fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman mmc_hostname(host), mrq->stop->opcode, 144976d9276c826d6b35e4a2478fd4978dbd63bdd6fPierre Ossman mrq->stop->arg, mrq->stop->flags); 145976d9276c826d6b35e4a2478fd4978dbd63bdd6fPierre Ossman } 146976d9276c826d6b35e4a2478fd4978dbd63bdd6fPierre Ossman 147976d9276c826d6b35e4a2478fd4978dbd63bdd6fPierre Ossman WARN_ON(!host->claimed); 148976d9276c826d6b35e4a2478fd4978dbd63bdd6fPierre Ossman 149976d9276c826d6b35e4a2478fd4978dbd63bdd6fPierre Ossman mrq->cmd->error = 0; 150976d9276c826d6b35e4a2478fd4978dbd63bdd6fPierre Ossman mrq->cmd->mrq = mrq; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mrq->data) { 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG_ON(mrq->data->blksz > host->max_blk_size); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG_ON(mrq->data->blocks > host->max_blk_count); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG_ON(mrq->data->blocks * mrq->data->blksz > 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->max_req_size); 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_MMC_DEBUG 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz = 0; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i < mrq->data->sg_len;i++) 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz += mrq->data->sg[i].length; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG_ON(sz != mrq->data->blocks * mrq->data->blksz); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mrq->cmd->data = mrq->data; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mrq->data->error = 0; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mrq->data->mrq = mrq; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mrq->stop) { 16867a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossman mrq->data->stop = mrq->stop; 16967a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossman mrq->stop->error = 0; 17067a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossman mrq->stop->mrq = mrq; 17167a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossman } 17267a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossman } 17367a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossman host->ops->request(host, mrq); 17467a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossman} 17567a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossman 17667a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossmanstatic void mmc_wait_done(struct mmc_request *mrq) 17767a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossman{ 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds complete(mrq->done_data); 1790afffc723c8041a005134099847ac2a2fd0316a0Ingo Molnar} 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mmc_wait_for_req - start a request and wait for completion 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @host: MMC host to start command 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @mrq: MMC request to start 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Start a new MMC custom command request for a host, and wait 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for the command to complete. Does not attempt to parse the 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * response. 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DECLARE_COMPLETION_ONSTACK(complete); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mrq->done_data = &complete; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mrq->done = mmc_wait_done; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_start_request(host, mrq); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_for_completion(&complete); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(mmc_wait_for_req); 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 205f22ee4edf63e7480511112d9965c71e07be3f8b7Pierre Ossman * mmc_wait_for_cmd - start a command and wait for completion 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @host: MMC host to start command 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @cmd: MMC command to start 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @retries: maximum number of retries 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Start a new MMC command for a host, and wait for the command 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to complete. Return any error that occurred while the command 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * was executing. Do not attempt to parse the response. 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries) 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_request mrq; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WARN_ON(!host->claimed); 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&mrq, 0, sizeof(struct mmc_request)); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 222335eadf2ef6a1122a720aea98e758e5d431da87dPierre Ossman memset(cmd->resp, 0, sizeof(cmd->resp)); 223d773d7255199a6c8934e197756f54a1115dd127bRussell King cmd->retries = retries; 224d773d7255199a6c8934e197756f54a1115dd127bRussell King 225d773d7255199a6c8934e197756f54a1115dd127bRussell King mrq.cmd = cmd; 22667a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossman cmd->data = NULL; 22767a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossman 22867a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossman mmc_wait_for_req(host, &mrq); 229d773d7255199a6c8934e197756f54a1115dd127bRussell King 230b146d26a61e0feab2f12a98ae83fd352830899c0Pierre Ossman return cmd->error; 231d773d7255199a6c8934e197756f54a1115dd127bRussell King} 232d773d7255199a6c8934e197756f54a1115dd127bRussell King 233d773d7255199a6c8934e197756f54a1115dd127bRussell KingEXPORT_SYMBOL(mmc_wait_for_cmd); 234d773d7255199a6c8934e197756f54a1115dd127bRussell King 235e6f918bf39773d712ab5b457bff54ade3bda0cb1Pierre Ossman/** 236e6f918bf39773d712ab5b457bff54ade3bda0cb1Pierre Ossman * mmc_set_data_timeout - set the timeout for a data command 237e6f918bf39773d712ab5b457bff54ade3bda0cb1Pierre Ossman * @data: data phase for command 238e6f918bf39773d712ab5b457bff54ade3bda0cb1Pierre Ossman * @card: the MMC card associated with the data transfer 239e6f918bf39773d712ab5b457bff54ade3bda0cb1Pierre Ossman * 240e6f918bf39773d712ab5b457bff54ade3bda0cb1Pierre Ossman * Computes the data timeout parameters according to the 241e6f918bf39773d712ab5b457bff54ade3bda0cb1Pierre Ossman * correct algorithm given the card type. 242e6f918bf39773d712ab5b457bff54ade3bda0cb1Pierre Ossman */ 243e6f918bf39773d712ab5b457bff54ade3bda0cb1Pierre Ossmanvoid mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) 244d773d7255199a6c8934e197756f54a1115dd127bRussell King{ 245d773d7255199a6c8934e197756f54a1115dd127bRussell King unsigned int mult; 246d773d7255199a6c8934e197756f54a1115dd127bRussell King 247d773d7255199a6c8934e197756f54a1115dd127bRussell King /* 248d773d7255199a6c8934e197756f54a1115dd127bRussell King * SDIO cards only define an upper 1 s limit on access. 249d773d7255199a6c8934e197756f54a1115dd127bRussell King */ 250d773d7255199a6c8934e197756f54a1115dd127bRussell King if (mmc_card_sdio(card)) { 251d773d7255199a6c8934e197756f54a1115dd127bRussell King data->timeout_ns = 1000000000; 252b146d26a61e0feab2f12a98ae83fd352830899c0Pierre Ossman data->timeout_clks = 0; 253d773d7255199a6c8934e197756f54a1115dd127bRussell King return; 254d773d7255199a6c8934e197756f54a1115dd127bRussell King } 255d773d7255199a6c8934e197756f54a1115dd127bRussell King 256d773d7255199a6c8934e197756f54a1115dd127bRussell King /* 257d773d7255199a6c8934e197756f54a1115dd127bRussell King * SD cards use a 100 multiplier rather than 10 258d773d7255199a6c8934e197756f54a1115dd127bRussell King */ 259d773d7255199a6c8934e197756f54a1115dd127bRussell King mult = mmc_card_sd(card) ? 100 : 10; 260d773d7255199a6c8934e197756f54a1115dd127bRussell King 261d773d7255199a6c8934e197756f54a1115dd127bRussell King /* 262d773d7255199a6c8934e197756f54a1115dd127bRussell King * Scale up the multiplier (and therefore the timeout) by 263d773d7255199a6c8934e197756f54a1115dd127bRussell King * the r2w factor for writes. 264d773d7255199a6c8934e197756f54a1115dd127bRussell King */ 265d773d7255199a6c8934e197756f54a1115dd127bRussell King if (data->flags & MMC_DATA_WRITE) 266d773d7255199a6c8934e197756f54a1115dd127bRussell King mult <<= card->csd.r2w_factor; 267d773d7255199a6c8934e197756f54a1115dd127bRussell King 268b146d26a61e0feab2f12a98ae83fd352830899c0Pierre Ossman data->timeout_ns = card->csd.tacc_ns * mult; 269d773d7255199a6c8934e197756f54a1115dd127bRussell King data->timeout_clks = card->csd.tacc_clks * mult; 270d773d7255199a6c8934e197756f54a1115dd127bRussell King 271d773d7255199a6c8934e197756f54a1115dd127bRussell King /* 272d773d7255199a6c8934e197756f54a1115dd127bRussell King * SD cards also have an upper limit on the timeout. 273fba68bd2dab1ac99af3c5a963ec9581cfa9f1725Philip Langdale */ 274fba68bd2dab1ac99af3c5a963ec9581cfa9f1725Philip Langdale if (mmc_card_sd(card)) { 275fba68bd2dab1ac99af3c5a963ec9581cfa9f1725Philip Langdale unsigned int timeout_us, limit_us; 276fba68bd2dab1ac99af3c5a963ec9581cfa9f1725Philip Langdale 277d773d7255199a6c8934e197756f54a1115dd127bRussell King timeout_us = data->timeout_ns / 1000; 278d773d7255199a6c8934e197756f54a1115dd127bRussell King timeout_us += data->timeout_clks * 1000 / 279d773d7255199a6c8934e197756f54a1115dd127bRussell King (card->host->ios.clock / 1000); 280d773d7255199a6c8934e197756f54a1115dd127bRussell King 281d773d7255199a6c8934e197756f54a1115dd127bRussell King if (data->flags & MMC_DATA_WRITE) 282d773d7255199a6c8934e197756f54a1115dd127bRussell King limit_us = 250000; 283d773d7255199a6c8934e197756f54a1115dd127bRussell King else 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds limit_us = 100000; 2852342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitre 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2872342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitre * SDHC cards always use these fixed values. 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2892342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitre if (timeout_us > limit_us || mmc_card_blockaddr(card)) { 2902342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitre data->timeout_ns = limit_us * 1000; 2912342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitre data->timeout_clks = 0; 2922342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitre } 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2942342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitre} 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(mmc_set_data_timeout); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2982342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitre * __mmc_claim_host - exclusively claim a host 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @host: mmc host to claim 300cf795bfb3ad4e2f8f6bb346aa8edb8272d4c70a2Pierre Ossman * @abort: whether or not the operation should be aborted 301cf795bfb3ad4e2f8f6bb346aa8edb8272d4c70a2Pierre Ossman * 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Claim a host for a set of operations. If @abort is non null and 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dereference a non-zero value then this will return prematurely with 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that non-zero value without acquiring the lock. Returns zero 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with the lock held otherwise. 3062342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitre */ 3072342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitreint __mmc_claim_host(struct mmc_host *host, atomic_t *abort) 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DECLARE_WAITQUEUE(wait, current); 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int stop; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds might_sleep(); 3142342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitre 3152342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitre add_wait_queue(&host->wq, &wait); 3162342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitre spin_lock_irqsave(&host->lock, flags); 3172342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitre while (1) { 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_current_state(TASK_UNINTERRUPTIBLE); 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop = abort ? atomic_read(abort) : 0; 3202342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitre if (stop || !host->claimed) 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&host->lock, flags); 3232342f3323c9a76367a1d7f9a35525ee3cb3911dfNicolas Pitre schedule(); 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&host->lock, flags); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_current_state(TASK_RUNNING); 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!stop) 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->claimed = 1; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up(&host->wq); 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&host->lock, flags); 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_wait_queue(&host->wq, &wait); 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return stop; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 336f22ee4edf63e7480511112d9965c71e07be3f8b7Pierre OssmanEXPORT_SYMBOL(__mmc_claim_host); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 339f22ee4edf63e7480511112d9965c71e07be3f8b7Pierre Ossman * mmc_release_host - release a host 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @host: mmc host to release 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Release a MMC host, allowing others to claim the host 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for their operations. 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mmc_release_host(struct mmc_host *host) 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3477ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman unsigned long flags; 3487ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 3497ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman WARN_ON(!host->claimed); 3507ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 351920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King spin_lock_irqsave(&host->lock, flags); 352920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King host->claimed = 0; 353920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King spin_unlock_irqrestore(&host->lock, flags); 354920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King 355cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman wake_up(&host->wq); 356cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman} 357920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King 358920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell KingEXPORT_SYMBOL(mmc_release_host); 359cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman 360fba68bd2dab1ac99af3c5a963ec9581cfa9f1725Philip Langdale/* 361920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King * Internal function that does the actual ios call to the host driver, 362920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King * optionally printing some debug output. 363920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King */ 3647ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossmanstatic inline void mmc_set_ios(struct mmc_host *host) 3657ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman{ 3667ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman struct mmc_ios *ios = &host->ios; 367da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u " 369da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman "width %u timing %u\n", 370da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman mmc_hostname(host), ios->clock, ios->bus_mode, 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ios->power_mode, ios->chip_select, ios->vdd, 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ios->bus_width, ios->timing); 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3747ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman host->ops->set_ios(host, ios); 3757ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman} 3767ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 3777ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman/* 3787ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman * Control chip select pin on a host. 3797ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman */ 3807ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossmanvoid mmc_set_chip_select(struct mmc_host *host, int mode) 3817ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman{ 3827ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman host->ios.chip_select = mode; 3837ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman mmc_set_ios(host); 3847ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman} 3857ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 3867ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman/* 3877ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman * Sets the host clock to the highest possible frequency that 3887ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman * is below "hz". 3897ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman */ 3907ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossmanvoid mmc_set_clock(struct mmc_host *host, unsigned int hz) 3917ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman{ 3927ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman WARN_ON(hz < host->f_min); 3937ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 3947ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman if (hz > host->f_max) 3957ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman hz = host->f_max; 3967ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 3977ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman host->ios.clock = hz; 3987ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman mmc_set_ios(host); 3997ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman} 4007ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 4017ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman/* 4027ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman * Change the bus mode (open drain/push-pull) of a host. 4037ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman */ 4047ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossmanvoid mmc_set_bus_mode(struct mmc_host *host, unsigned int mode) 4057ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman{ 4067ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman host->ios.bus_mode = mode; 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_set_ios(host); 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4107ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman/* 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Change data bus width of a host. 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mmc_set_bus_width(struct mmc_host *host, unsigned int width) 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->ios.bus_width = width; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_set_ios(host); 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 42063ef731aa6a81e286de78dcc92241d123424ed39Timo Teras * Mask off any voltages we don't support and select 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the lowest voltage 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 423920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell Kingu32 mmc_select_voltage(struct mmc_host *host, u32 ocr) 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bit; 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ocr &= host->ocr_avail; 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bit = ffs(ocr); 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bit) { 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bit -= 1; 4327ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 433b57c43ad81602589afca3948a5a7121e40026e17Pierre Ossman ocr &= 3 << bit; 4347ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 435b57c43ad81602589afca3948a5a7121e40026e17Pierre Ossman host->ios.vdd = bit; 4367ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman mmc_set_ios(host); 4377ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman } else { 438b57c43ad81602589afca3948a5a7121e40026e17Pierre Ossman ocr = 0; 439b57c43ad81602589afca3948a5a7121e40026e17Pierre Ossman } 440b57c43ad81602589afca3948a5a7121e40026e17Pierre Ossman 44145f8245b972e360c19aec9032e2a2033b8ac3719Russell King return ocr; 44245f8245b972e360c19aec9032e2a2033b8ac3719Russell King} 44345f8245b972e360c19aec9032e2a2033b8ac3719Russell King 44445f8245b972e360c19aec9032e2a2033b8ac3719Russell King/* 44545f8245b972e360c19aec9032e2a2033b8ac3719Russell King * Select timing parameters for host. 44645f8245b972e360c19aec9032e2a2033b8ac3719Russell King */ 44745f8245b972e360c19aec9032e2a2033b8ac3719Russell Kingvoid mmc_set_timing(struct mmc_host *host, unsigned int timing) 44845f8245b972e360c19aec9032e2a2033b8ac3719Russell King{ 44945f8245b972e360c19aec9032e2a2033b8ac3719Russell King host->ios.timing = timing; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_set_ios(host); 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Apply power to the MMC stack. This is a two-stage process. 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * First, we enable power to the card without the clock running. 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We then wait a bit for the power to stabilise. Finally, 457865e9f13c94891daed4f6a5f69c5d6ec04d4932fPierre Ossman * enable the bus drivers and clock to the card. 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 459f218278a456b3c272b480443c89004c3d2a49f18Pierre Ossman * We must _NOT_ enable the clock prior to power stablising. 460cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman * 461920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King * If a host does all the power sequencing itself, ignore the 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * initial MMC_POWER_UP stage. 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmc_power_up(struct mmc_host *host) 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bit = fls(host->ocr_avail) - 1; 467920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->ios.vdd = bit; 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mmc_host_is_spi(host)) { 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->ios.chip_select = MMC_CS_HIGH; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->ios.chip_select = MMC_CS_DONTCARE; 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->ios.power_mode = MMC_POWER_UP; 477865e9f13c94891daed4f6a5f69c5d6ec04d4932fPierre Ossman host->ios.bus_width = MMC_BUS_WIDTH_1; 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->ios.timing = MMC_TIMING_LEGACY; 479f218278a456b3c272b480443c89004c3d2a49f18Pierre Ossman mmc_set_ios(host); 480cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman 481920e70c5c603ada05dd480ca0ccc0ae12a5fdc39Russell King /* 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This delay should be sufficient to allow the power supply 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to reach the minimum voltage. 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 485393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk mmc_delay(2); 486393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk 487393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk host->ios.clock = host->f_min; 488393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk host->ios.power_mode = MMC_POWER_ON; 489393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk mmc_set_ios(host); 490393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk 491393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk /* 492393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk * This delay must be at least 74 clock sizes, or 1 ms, or the 493393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk * time required to reach a stable voltage. 494393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk */ 495393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk mmc_delay(2); 496393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk} 497393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk 498393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunkstatic void mmc_power_off(struct mmc_host *host) 499393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk{ 500393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk host->ios.clock = 0; 501393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk host->ios.vdd = 0; 502393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk if (!mmc_host_is_spi(host)) { 503393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; 504393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk host->ios.chip_select = MMC_CS_DONTCARE; 505393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk } 506393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk host->ios.power_mode = MMC_POWER_OFF; 507393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk host->ios.bus_width = MMC_BUS_WIDTH_1; 508393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk host->ios.timing = MMC_TIMING_LEGACY; 509393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk mmc_set_ios(host); 510393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk} 511393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk 512393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk/* 513393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk * Cleanup when the last reference to the bus operator is dropped. 514393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk */ 515393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunkvoid __mmc_release_bus(struct mmc_host *host) 516393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk{ 517393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk BUG_ON(!host); 518393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk BUG_ON(host->bus_refs); 519393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk BUG_ON(!host->bus_dead); 520393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk 521393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk host->bus_ops = NULL; 522393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk} 523393618510d5349e07d71dc28fb6fc49baf0d96a0Adrian Bunk 5247ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman/* 5257ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman * Increase reference count of bus operator 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5277ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossmanstatic inline void mmc_bus_get(struct mmc_host *host) 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5297ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman unsigned long flags; 530e45a1bd20fa5b920901879e85cdf5eda21f78d7cPhilip Langdale 5317ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman spin_lock_irqsave(&host->lock, flags); 5327ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman host->bus_refs++; 533b855885e3b60cf6f9452848712a62517b94583ebPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 5347ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman} 535bce40a36de574376f41f1ff3c4d212a7da2a3c90Philip Langdale 5367ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman/* 537bce40a36de574376f41f1ff3c4d212a7da2a3c90Philip Langdale * Decrease reference count of bus operator and free it if 5387ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman * it is the last reference. 5397ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman */ 540b57c43ad81602589afca3948a5a7121e40026e17Pierre Ossmanstatic inline void mmc_bus_put(struct mmc_host *host) 5417ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman{ 5427ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman unsigned long flags; 5437ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 544b57c43ad81602589afca3948a5a7121e40026e17Pierre Ossman spin_lock_irqsave(&host->lock, flags); 5457ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman host->bus_refs--; 546b57c43ad81602589afca3948a5a7121e40026e17Pierre Ossman if ((host->bus_refs == 0) && host->bus_ops) 547b57c43ad81602589afca3948a5a7121e40026e17Pierre Ossman __mmc_release_bus(host); 5487ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman spin_unlock_irqrestore(&host->lock, flags); 5497ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman} 5507ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 5517ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman/* 5527ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman * Assign a mmc bus handler to a host. Only one bus handler may control a 5537ccd266e676a3f0c6f8f897f58b684cac3dd1650Pierre Ossman * host at any given time. 5547ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman */ 5557ccd266e676a3f0c6f8f897f58b684cac3dd1650Pierre Ossmanvoid mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops) 5567ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman{ 5577ccd266e676a3f0c6f8f897f58b684cac3dd1650Pierre Ossman unsigned long flags; 5587ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 5597ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman BUG_ON(!host); 560cd9277c011a99769fa371521b460ed57f6d280b1Pierre Ossman BUG_ON(!ops); 5617ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 5627ccd266e676a3f0c6f8f897f58b684cac3dd1650Pierre Ossman WARN_ON(!host->claimed); 5637ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 5647ccd266e676a3f0c6f8f897f58b684cac3dd1650Pierre Ossman spin_lock_irqsave(&host->lock, flags); 5657ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG_ON(host->bus_ops); 5677ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman BUG_ON(host->bus_refs); 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5697ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman host->bus_ops = ops; 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->bus_refs = 1; 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->bus_dead = 0; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&host->lock, flags); 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5758dc003359cc3996abad9e53a7b2280b272610283Richard Purdie 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 57767a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossman * Remove the current bus handler from a host. Assumes that there are 57867a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossman * no interesting cards left, so the bus is powered down. 57967a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossman */ 58067a61c484735de9bf4f099830ecb4ef2eca95c38Pierre Ossmanvoid mmc_detach_bus(struct mmc_host *host) 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5828dc003359cc3996abad9e53a7b2280b272610283Richard Purdie unsigned long flags; 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5843b91e5507cddaca53bccf1524ff11a0ac5c85531Pierre Ossman BUG_ON(!host); 5851efd48b3ae8f89a1d04f1e36be96764d7bf43ae9Pierre Ossman 58601f41ec7b36e14da18a4e162ef697ae358f36e37Andrew Morton WARN_ON(!host->claimed); 5873b91e5507cddaca53bccf1524ff11a0ac5c85531Pierre Ossman WARN_ON(!host->bus_ops); 58801f41ec7b36e14da18a4e162ef697ae358f36e37Andrew Morton 5893b91e5507cddaca53bccf1524ff11a0ac5c85531Pierre Ossman spin_lock_irqsave(&host->lock, flags); 5903b91e5507cddaca53bccf1524ff11a0ac5c85531Pierre Ossman 591c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells host->bus_dead = 1; 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&host->lock, flags); 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_power_off(host); 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 597b93931a61a119575f84c33af2438b9384fde9eb7Pierre Ossman mmc_bus_put(host); 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 599c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells 600c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells/** 6017ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman * mmc_detect_change - process change of state on a MMC socket 6027ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman * @host: host which changed state. 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @delay: optional delay to wait before detection (jiffies) 6047ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman * 605b855885e3b60cf6f9452848712a62517b94583ebPierre Ossman * MMC drivers should call this when they detect a card has been 6067ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman * inserted or removed. The MMC layer will confirm that any 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * present card is still functional, and initialize any newly 6087ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman * inserted. 6097ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman */ 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mmc_detect_change(struct mmc_host *host, unsigned long delay) 6117ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman{ 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_MMC_DEBUG 6137ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman unsigned long flags; 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&host->lock, flags); 6157ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman WARN_ON(host->removed); 6167ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman spin_unlock_irqrestore(&host->lock, flags); 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6187ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_schedule_delayed_work(&host->detect, delay); 6205c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman} 6215c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman 6225c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre OssmanEXPORT_SYMBOL(mmc_detect_change); 6235c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman 6245c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman 6255c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossmanvoid mmc_rescan(struct work_struct *work) 6265c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman{ 6275c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman struct mmc_host *host = 6285c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman container_of(work, struct mmc_host, detect.work); 6295c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman u32 ocr; 6305c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman int err; 6315c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman 6325c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman mmc_bus_get(host); 6337ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 63417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (host->bus_ops == NULL) { 6357ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman /* 6367ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman * Only we can add a new handler, so it's safe to 6375c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman * release the lock here. 6385c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman */ 6395c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman mmc_bus_put(host); 6405c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman 6415c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman mmc_claim_host(host); 6425c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman 6435c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman mmc_power_up(host); 6445c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman mmc_go_idle(host); 6455c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman 6467ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman mmc_send_if_cond(host, host->ocr_avail); 6475c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman 6487ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman /* 6495c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman * First we search for SDIO... 6505c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman */ 6515c4e6f1301649d5b29dd0f70e6da83e728ab5ca5Pierre Ossman err = mmc_send_io_op_cond(host, 0, &ocr); 6527ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman if (!err) { 6537ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman if (mmc_attach_sdio(host, ocr)) 6547ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman mmc_power_off(host); 6557ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman return; 6567ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman } 6577ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ...then normal SD... 660b93931a61a119575f84c33af2438b9384fde9eb7Pierre Ossman */ 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = mmc_send_app_op_cond(host, 0, &ocr); 662b93931a61a119575f84c33af2438b9384fde9eb7Pierre Ossman if (!err) { 663b93931a61a119575f84c33af2438b9384fde9eb7Pierre Ossman if (mmc_attach_sd(host, ocr)) 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_power_off(host); 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 666b93931a61a119575f84c33af2438b9384fde9eb7Pierre Ossman } 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6683b91e5507cddaca53bccf1524ff11a0ac5c85531Pierre Ossman /* 6691efd48b3ae8f89a1d04f1e36be96764d7bf43ae9Pierre Ossman * ...and finally MMC. 6701efd48b3ae8f89a1d04f1e36be96764d7bf43ae9Pierre Ossman */ 6713b91e5507cddaca53bccf1524ff11a0ac5c85531Pierre Ossman err = mmc_send_op_cond(host, 0, &ocr); 6721efd48b3ae8f89a1d04f1e36be96764d7bf43ae9Pierre Ossman if (!err) { 6733b91e5507cddaca53bccf1524ff11a0ac5c85531Pierre Ossman if (mmc_attach_mmc(host, ocr)) 6743b91e5507cddaca53bccf1524ff11a0ac5c85531Pierre Ossman mmc_power_off(host); 6753b91e5507cddaca53bccf1524ff11a0ac5c85531Pierre Ossman return; 6763b91e5507cddaca53bccf1524ff11a0ac5c85531Pierre Ossman } 6777ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 6787ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman mmc_release_host(host); 6797ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman mmc_power_off(host); 6807ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman } else { 6817ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman if (host->bus_ops->detect && !host->bus_dead) 6827ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman host->bus_ops->detect(host); 6837ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 6847ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman mmc_bus_put(host); 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6867ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman} 6877ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 6887ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossmanvoid mmc_start_host(struct mmc_host *host) 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_power_off(host); 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_detect_change(host, 0); 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mmc_stop_host(struct mmc_host *host) 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_MMC_DEBUG 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&host->lock, flags); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->removed = 1; 700e5378ca8c0ab684bd9339dc6827dd5a042f9e6fcPavel Machek spin_unlock_irqrestore(&host->lock, flags); 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 702b5af25bee2de2f6cd1ac74ba737cbc4f3d303e5dPierre Ossman 703b5af25bee2de2f6cd1ac74ba737cbc4f3d303e5dPierre Ossman mmc_flush_scheduled_work(); 7047ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 7057ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman mmc_bus_get(host); 7066abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman if (host->bus_ops && !host->bus_dead) { 7076abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman if (host->bus_ops->remove) 7086abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman host->bus_ops->remove(host); 7096abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman 7106abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman mmc_claim_host(host); 7116abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman mmc_detach_bus(host); 7126abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman mmc_release_host(host); 7136abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman } 7146abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman mmc_bus_put(host); 7156abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman 716b5af25bee2de2f6cd1ac74ba737cbc4f3d303e5dPierre Ossman BUG_ON(host->card); 7177ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman 7187ea239d9e6d6993469a6a8ca83ff23834dfc3fcePierre Ossman mmc_power_off(host); 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PM 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mmc_suspend_host - suspend a host 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @host: mmc host 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @state: suspend mode (PM_SUSPEND_xxx) 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint mmc_suspend_host(struct mmc_host *host, pm_message_t state) 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_flush_scheduled_work(); 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7326abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman mmc_bus_get(host); 7336abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman if (host->bus_ops && !host->bus_dead) { 7346abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman if (host->bus_ops->suspend) 7356abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman host->bus_ops->suspend(host); 7366abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman if (!host->bus_ops->resume) { 7376abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman if (host->bus_ops->remove) 7386abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman host->bus_ops->remove(host); 7396abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman 7406abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman mmc_claim_host(host); 7416abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman mmc_detach_bus(host); 7426abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman mmc_release_host(host); 7436abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman } 7446abaa0c9fec563538f2a28a682af8c89bb9b125cPierre Ossman } 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_bus_put(host); 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_power_off(host); 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(mmc_suspend_host); 753ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman 754ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman/** 755ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman * mmc_resume_host - resume a previously suspended host 756ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman * @host: mmc host 757ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman */ 758ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossmanint mmc_resume_host(struct mmc_host *host) 759ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman{ 760ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman mmc_bus_get(host); 761ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman if (host->bus_ops && !host->bus_dead) { 762e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman mmc_power_up(host); 763e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman BUG_ON(!host->bus_ops->resume); 764e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman host->bus_ops->resume(host); 765e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman } 766e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman mmc_bus_put(host); 767e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 768e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman /* 769e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * We add a slight delay here so that resume can progress 770e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * in parallel. 771e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 772e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman mmc_detect_change(host, 1); 773e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 774e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return 0; 775e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 776e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 777e29a7d73f4277eb92aa64e17017dea33460828efPierre OssmanEXPORT_SYMBOL(mmc_resume_host); 778e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 779e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#endif 780e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 781e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int __init mmc_init(void) 782ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman{ 783ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman int ret; 784ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman 785ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman workqueue = create_singlethread_workqueue("kmmcd"); 786ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman if (!workqueue) 787e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return -ENOMEM; 788ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman 789ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman ret = mmc_register_bus(); 790ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman if (ret) 791ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman goto destroy_workqueue; 792ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman 79326074962e8f547b96614dbe248748ba2a1996ca3Nicolas Pitre ret = mmc_register_host_class(); 794ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman if (ret) 795ffce2e7e7060c949ccd703dacc9b3dd81b377373Pierre Ossman goto unregister_bus; 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 797 ret = sdio_register_bus(); 798 if (ret) 799 goto unregister_host_class; 800 801 return 0; 802 803unregister_host_class: 804 mmc_unregister_host_class(); 805unregister_bus: 806 mmc_unregister_bus(); 807destroy_workqueue: 808 destroy_workqueue(workqueue); 809 810 return ret; 811} 812 813static void __exit mmc_exit(void) 814{ 815 sdio_unregister_bus(); 816 mmc_unregister_host_class(); 817 mmc_unregister_bus(); 818 destroy_workqueue(workqueue); 819} 820 821subsys_initcall(mmc_init); 822module_exit(mmc_exit); 823 824MODULE_LICENSE("GPL"); 825