📄 mmc.c.svn-base
字号:
/* * linux/drivers/mmc/mmc.c * * Copyright (C) 2003-2004 Russell King, All Rights Reserved. * SD support Copyright (C) 2004 Ian Molton, All Rights Reserved. * SD support Copyright (C) 2005 Pierre Ossman, All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/completion.h>#include <linux/device.h>#include <linux/delay.h>#include <linux/pagemap.h>#include <linux/err.h>#include <asm/scatterlist.h>#include <linux/scatterlist.h>#include <linux/mmc/card.h>#include <linux/mmc/host.h>#include <linux/mmc/protocol.h>#include "mmc.h"#ifdef CONFIG_MMC_DEBUG#define DBG(x...) printk(KERN_DEBUG x)#else#define DBG(x...) do { } while (0)#endif#define CMD_RETRIES 3/* * OCR Bit positions to 10s of Vdd mV. */static const unsigned short mmc_ocr_bit_to_vdd[] = { 150, 155, 160, 165, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360};static const unsigned int tran_exp[] = { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0};static const unsigned char tran_mant[] = { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80,};static const unsigned int tacc_exp[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,};static const unsigned int tacc_mant[] = { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80,};/** * mmc_request_done - finish processing an MMC command * @host: MMC host which completed command * @mrq: MMC request which completed * * MMC drivers should call this function when they have completed * their processing of a command. This should be called before the * data part of the command has completed. */void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq){ struct mmc_command *cmd = mrq->cmd; int err = mrq->cmd->error; DBG("MMC: req done (%02x): %d: %08x %08x %08x %08x\n", cmd->opcode, err, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); if (err && cmd->retries) { cmd->retries--; cmd->error = 0; host->ops->request(host, mrq); } else if (mrq->done) { mrq->done(mrq); }}EXPORT_SYMBOL(mmc_request_done);/** * mmc_start_request - start a command on a host * @host: MMC host to start command on * @mrq: MMC request to start * * Queue a command on the specified host. We expect the * caller to be holding the host lock with interrupts disabled. */voidmmc_start_request(struct mmc_host *host, struct mmc_request *mrq){ DBG("MMC: starting cmd 0x%02x arg 0x%08x flags %08x\n", mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags); WARN_ON(host->card_busy == NULL); mrq->cmd->error = 0; mrq->cmd->mrq = mrq; if (mrq->data) { mrq->cmd->data = mrq->data; mrq->data->error = 0; mrq->data->mrq = mrq; if (mrq->stop) { mrq->data->stop = mrq->stop; mrq->stop->error = 0; mrq->stop->mrq = mrq; } } host->ops->request(host, mrq);}EXPORT_SYMBOL(mmc_start_request);static void mmc_wait_done(struct mmc_request *mrq){ complete(mrq->done_data);}int mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq){ DECLARE_COMPLETION(complete); mrq->done_data = &complete; mrq->done = mmc_wait_done; mmc_start_request(host, mrq); wait_for_completion(&complete); return 0;}EXPORT_SYMBOL(mmc_wait_for_req);/** * mmc_wait_for_cmd - start a command and wait for completion * @host: MMC host to start command * @cmd: MMC command to start * @retries: maximum number of retries * * Start a new MMC command for a host, and wait for the command * to complete. Return any error that occurred while the command * was executing. Do not attempt to parse the response. */int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries){ struct mmc_request mrq; BUG_ON(host->card_busy == NULL); memset(&mrq, 0, sizeof(struct mmc_request)); memset(cmd->resp, 0, sizeof(cmd->resp)); cmd->retries = retries; mrq.cmd = cmd; cmd->data = NULL; mmc_wait_for_req(host, &mrq); return cmd->error;}EXPORT_SYMBOL(mmc_wait_for_cmd);/** * mmc_wait_for_app_cmd - start an application command and wait for completion * @host: MMC host to start command * @rca: RCA to send MMC_APP_CMD to * @cmd: MMC command to start * @retries: maximum number of retries * * Sends a MMC_APP_CMD, checks the card response, sends the command * in the parameter and waits for it to complete. Return any error * that occurred while the command was executing. Do not attempt to * parse the response. */int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca, struct mmc_command *cmd, int retries){ struct mmc_request mrq; struct mmc_command appcmd; int i, err; BUG_ON(host->card_busy == NULL); BUG_ON(retries < 0); err = MMC_ERR_INVALID; /* * We have to resend MMC_APP_CMD for each attempt so * we cannot use the retries field in mmc_command. */ for (i = 0;i <= retries;i++) { memset(&mrq, 0, sizeof(struct mmc_request)); appcmd.opcode = MMC_APP_CMD; appcmd.arg = rca << 16; appcmd.flags = MMC_RSP_R1; appcmd.retries = 0; memset(appcmd.resp, 0, sizeof(appcmd.resp)); appcmd.data = NULL; mrq.cmd = &appcmd; appcmd.data = NULL; mmc_wait_for_req(host, &mrq); if (appcmd.error) { err = appcmd.error; continue; } /* Check that card supported application commands */ if (!(appcmd.resp[0] & R1_APP_CMD)) return MMC_ERR_FAILED; memset(&mrq, 0, sizeof(struct mmc_request)); memset(cmd->resp, 0, sizeof(cmd->resp)); cmd->retries = 0; mrq.cmd = cmd; cmd->data = NULL; mmc_wait_for_req(host, &mrq); err = cmd->error; if (cmd->error == MMC_ERR_NONE) break; } return err;}EXPORT_SYMBOL(mmc_wait_for_app_cmd);static int mmc_select_card(struct mmc_host *host, struct mmc_card *card);/** * __mmc_claim_host - exclusively claim a host * @host: mmc host to claim * @card: mmc card to claim host for * * Claim a host for a set of operations. If a valid card * is passed and this wasn't the last card selected, select * the card before returning. * * Note: you should use mmc_card_claim_host or mmc_claim_host. */int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card){ DECLARE_WAITQUEUE(wait, current); unsigned long flags; int err = 0; add_wait_queue(&host->wq, &wait); spin_lock_irqsave(&host->lock, flags); while (1) { set_current_state(TASK_UNINTERRUPTIBLE); if (host->card_busy == NULL) break; spin_unlock_irqrestore(&host->lock, flags); schedule(); spin_lock_irqsave(&host->lock, flags); } set_current_state(TASK_RUNNING); host->card_busy = card; spin_unlock_irqrestore(&host->lock, flags); remove_wait_queue(&host->wq, &wait); if (card != (void *)-1) { err = mmc_select_card(host, card); if (err != MMC_ERR_NONE) return err; } return err;}EXPORT_SYMBOL(__mmc_claim_host);/** * mmc_release_host - release a host * @host: mmc host to release * * Release a MMC host, allowing others to claim the host * for their operations. */void mmc_release_host(struct mmc_host *host){ unsigned long flags; BUG_ON(host->card_busy == NULL); spin_lock_irqsave(&host->lock, flags); host->card_busy = NULL; spin_unlock_irqrestore(&host->lock, flags); wake_up(&host->wq);}EXPORT_SYMBOL(mmc_release_host);static int mmc_select_card(struct mmc_host *host, struct mmc_card *card){ int err; struct mmc_command cmd; BUG_ON(host->card_busy == NULL); if (host->card_selected == card) return MMC_ERR_NONE; host->card_selected = card; cmd.opcode = MMC_SELECT_CARD; cmd.arg = card->rca << 16; cmd.flags = MMC_RSP_R1; err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) return err; /* * Default bus width is 1 bit. */ host->ios.bus_width = MMC_BUS_WIDTH_1; /* * We can only change the bus width of the selected * card so therefore we have to put the handling * here. */ if (host->caps & MMC_CAP_4_BIT_DATA) { /* * The card is in 1 bit mode by default so * we only need to change if it supports the * wider version. */ if (mmc_card_sd(card) && (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { struct mmc_command cmd; cmd.opcode = SD_APP_SET_BUS_WIDTH; cmd.arg = SD_BUS_WIDTH_4; cmd.flags = MMC_RSP_R1; err = mmc_wait_for_app_cmd(host, card->rca, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) return err; host->ios.bus_width = MMC_BUS_WIDTH_4; } } host->ops->set_ios(host, &host->ios); return MMC_ERR_NONE;}/* * Ensure that no card is selected. */static void mmc_deselect_cards(struct mmc_host *host){ struct mmc_command cmd; if (host->card_selected) { host->card_selected = NULL; cmd.opcode = MMC_SELECT_CARD; cmd.arg = 0; cmd.flags = MMC_RSP_NONE; mmc_wait_for_cmd(host, &cmd, 0); }}static inline void mmc_delay(unsigned int ms){ if (ms < HZ / 1000) { yield(); mdelay(ms); } else { msleep_interruptible (ms); }}/* * Mask off any voltages we don't support and select * the lowest voltage */static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr){ int bit; ocr &= host->ocr_avail; bit = ffs(ocr); if (bit) { bit -= 1; ocr = 3 << bit; host->ios.vdd = bit; host->ops->set_ios(host, &host->ios); } else { ocr = 0; } return ocr;}#define UNSTUFF_BITS(resp,start,size) \ ({ \ const int __size = size; \ const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \ const int __off = 3 - ((start) / 32); \ const int __shft = (start) & 31; \ u32 __res; \ \ __res = resp[__off] >> __shft; \ if (__size + __shft > 32) \ __res |= resp[__off-1] << ((32 - __shft) % 32); \ __res & __mask; \ })/* * Given the decoded CSD structure, decode the raw CID to our CID structure. */static void mmc_decode_cid(struct mmc_card *card){ u32 *resp = card->raw_cid; memset(&card->cid, 0, sizeof(struct mmc_cid)); if (mmc_card_sd(card)) { /* * SD doesn't currently have a version field so we will * have to assume we can parse this. */ card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); card->cid.oemid = UNSTUFF_BITS(resp, 104, 16); card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); card->cid.hwrev = UNSTUFF_BITS(resp, 60, 4); card->cid.fwrev = UNSTUFF_BITS(resp, 56, 4); card->cid.serial = UNSTUFF_BITS(resp, 24, 32); card->cid.year = UNSTUFF_BITS(resp, 12, 8); card->cid.month = UNSTUFF_BITS(resp, 8, 4); card->cid.year += 2000; /* SD cards year offset */ } else { /* * The selection of the format here is based upon published * specs from sandisk and from what people have reported. */ switch (card->csd.mmca_vsn) { case 0: /* MMC v1.0 - v1.2 */ case 1: /* MMC v1.4 */ card->cid.manfid = UNSTUFF_BITS(resp, 104, 24); card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); card->cid.prod_name[6] = UNSTUFF_BITS(resp, 48, 8); card->cid.hwrev = UNSTUFF_BITS(resp, 44, 4); card->cid.fwrev = UNSTUFF_BITS(resp, 40, 4); card->cid.serial = UNSTUFF_BITS(resp, 16, 24); card->cid.month = UNSTUFF_BITS(resp, 12, 4); card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; break; case 2: /* MMC v2.0 - v2.2 */ case 3: /* MMC v3.1 - v3.3 */ card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); card->cid.oemid = UNSTUFF_BITS(resp, 104, 16); card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); card->cid.serial = UNSTUFF_BITS(resp, 16, 32); card->cid.month = UNSTUFF_BITS(resp, 12, 4); card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; break; default: printk("%s: card has unknown MMCA version %d\n", mmc_hostname(card->host), card->csd.mmca_vsn); mmc_card_set_bad(card); break; } } }/* * Given a 128-bit response, decode to our card CSD structure. */static void mmc_decode_csd(struct mmc_card *card){ struct mmc_csd *csd = &card->csd; unsigned int e, m, csd_struct; u32 *resp = card->raw_csd; if (mmc_card_sd(card)) { csd_struct = UNSTUFF_BITS(resp, 126, 2); if (csd_struct != 0) { printk("%s: unrecognised CSD structure version %d\n", mmc_hostname(card->host), csd_struct); mmc_card_set_bad(card); return; } m = UNSTUFF_BITS(resp, 115, 4); e = UNSTUFF_BITS(resp, 112, 3); csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; m = UNSTUFF_BITS(resp, 99, 4); e = UNSTUFF_BITS(resp, 96, 3); csd->max_dtr = tran_exp[e] * tran_mant[m]; csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); e = UNSTUFF_BITS(resp, 47, 3); m = UNSTUFF_BITS(resp, 62, 12); csd->capacity = (1 + m) << (e + 2); csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); } else { /* * We only understand CSD structure v1.1 and v1.2. * v1.2 has extra information in bits 15, 11 and 10. */ csd_struct = UNSTUFF_BITS(resp, 126, 2); if (csd_struct != 1 && csd_struct != 2) { printk("%s: unrecognised CSD structure version %d\n", mmc_hostname(card->host), csd_struct); mmc_card_set_bad(card); return; } csd->mmca_vsn = UNSTUFF_BITS(resp, 122, 4); m = UNSTUFF_BITS(resp, 115, 4); e = UNSTUFF_BITS(resp, 112, 3); csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; m = UNSTUFF_BITS(resp, 99, 4); e = UNSTUFF_BITS(resp, 96, 3); csd->max_dtr = tran_exp[e] * tran_mant[m]; csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); e = UNSTUFF_BITS(resp, 47, 3); m = UNSTUFF_BITS(resp, 62, 12); csd->capacity = (1 + m) << (e + 2); csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); }}/* * Given a 64-bit response, decode to our card SCR structure. */static void mmc_decode_scr(struct mmc_card *card){ struct sd_scr *scr = &card->scr; unsigned int scr_struct; u32 resp[4]; BUG_ON(!mmc_card_sd(card)); resp[3] = card->raw_scr[1]; resp[2] = card->raw_scr[0]; scr_struct = UNSTUFF_BITS(resp, 60, 4); if (scr_struct != 0) { printk("%s: unrecognised SCR structure version %d\n", mmc_hostname(card->host), scr_struct); mmc_card_set_bad(card); return; } scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4); scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);}/* * Locate a MMC card on this MMC host given a raw CID. */static struct mmc_card *mmc_find_card(struct mmc_host *host, u32 *raw_cid){ struct mmc_card *card; list_for_each_entry(card, &host->cards, node) { if (memcmp(card->raw_cid, raw_cid, sizeof(card->raw_cid)) == 0) return card; } return NULL;}/* * Allocate a new MMC card, and assign a unique RCA. */static struct mmc_card *mmc_alloc_card(struct mmc_host *host, u32 *raw_cid, unsigned int *frca){ struct mmc_card *card, *c; unsigned int rca = *frca; card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL); if (!card) return ERR_PTR(-ENOMEM); mmc_init_card(card, host); memcpy(card->raw_cid, raw_cid, sizeof(card->raw_cid)); again: list_for_each_entry(c, &host->cards, node) if (c->rca == rca) { rca++; goto again; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -