Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 7468
b: refs/heads/master
c: b57c43a
h: refs/heads/master
v: v3
  • Loading branch information
Pierre Ossman authored and Linus Torvalds committed Sep 7, 2005
1 parent a19bdc7 commit d2955f0
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a00fc09029f02ca833cf90e5d5625f08c4ac4f51
refs/heads/master: b57c43ad81602589afca3948a5a7121e40026e17
143 changes: 133 additions & 10 deletions trunk/drivers/mmc/mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#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>
Expand Down Expand Up @@ -246,6 +248,8 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,

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
Expand Down Expand Up @@ -278,16 +282,10 @@ int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card)
spin_unlock_irqrestore(&host->lock, flags);
remove_wait_queue(&host->wq, &wait);

if (card != (void *)-1 && host->card_selected != card) {
struct mmc_command cmd;

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 (card != (void *)-1) {
err = mmc_select_card(host, card);
if (err != MMC_ERR_NONE)
return err;
}

return err;
Expand Down Expand Up @@ -317,6 +315,29 @@ void mmc_release_host(struct mmc_host *host)

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;

return MMC_ERR_NONE;
}

/*
* Ensure that no card is selected.
*/
Expand Down Expand Up @@ -525,6 +546,32 @@ static void mmc_decode_csd(struct mmc_card *card)
}
}

/*
* 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.
*/
Expand Down Expand Up @@ -789,6 +836,79 @@ static void mmc_read_csds(struct mmc_host *host)
}
}

static void mmc_read_scrs(struct mmc_host *host)
{
int err;
struct mmc_card *card;

struct mmc_request mrq;
struct mmc_command cmd;
struct mmc_data data;

struct scatterlist sg;

list_for_each_entry(card, &host->cards, node) {
if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
continue;
if (!mmc_card_sd(card))
continue;

err = mmc_select_card(host, card);
if (err != MMC_ERR_NONE) {
mmc_card_set_dead(card);
continue;
}

memset(&cmd, 0, sizeof(struct mmc_command));

cmd.opcode = MMC_APP_CMD;
cmd.arg = card->rca << 16;
cmd.flags = MMC_RSP_R1;

err = mmc_wait_for_cmd(host, &cmd, 0);
if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) {
mmc_card_set_dead(card);
continue;
}

memset(&cmd, 0, sizeof(struct mmc_command));

cmd.opcode = SD_APP_SEND_SCR;
cmd.arg = 0;
cmd.flags = MMC_RSP_R1;

memset(&data, 0, sizeof(struct mmc_data));

data.timeout_ns = card->csd.tacc_ns * 10;
data.timeout_clks = card->csd.tacc_clks * 10;
data.blksz_bits = 3;
data.blocks = 1;
data.flags = MMC_DATA_READ;
data.sg = &sg;
data.sg_len = 1;

memset(&mrq, 0, sizeof(struct mmc_request));

mrq.cmd = &cmd;
mrq.data = &data;

sg_init_one(&sg, (u8*)card->raw_scr, 8);

err = mmc_wait_for_req(host, &mrq);
if (err != MMC_ERR_NONE) {
mmc_card_set_dead(card);
continue;
}

card->raw_scr[0] = ntohl(card->raw_scr[0]);
card->raw_scr[1] = ntohl(card->raw_scr[1]);

mmc_decode_scr(card);
}

mmc_deselect_cards(host);
}

static unsigned int mmc_calculate_clock(struct mmc_host *host)
{
struct mmc_card *card;
Expand Down Expand Up @@ -912,6 +1032,9 @@ static void mmc_setup(struct mmc_host *host)
host->ops->set_ios(host, &host->ios);

mmc_read_csds(host);

if (host->mode == MMC_MODE_SD)
mmc_read_scrs(host);
}


Expand Down
9 changes: 9 additions & 0 deletions trunk/include/linux/mmc/card.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ struct mmc_csd {
unsigned int capacity;
};

struct sd_scr {
unsigned char sda_vsn;
unsigned char bus_widths;
#define SD_SCR_BUS_WIDTH_1 (1<<0)
#define SD_SCR_BUS_WIDTH_4 (1<<2)
};

struct mmc_host;

/*
Expand All @@ -51,8 +58,10 @@ struct mmc_card {
#define MMC_STATE_READONLY (1<<4) /* card is read-only */
u32 raw_cid[4]; /* raw card CID */
u32 raw_csd[4]; /* raw card CSD */
u32 raw_scr[2]; /* raw card SCR */
struct mmc_cid cid; /* card identification */
struct mmc_csd csd; /* card specific */
struct sd_scr scr; /* extra SD information */
};

#define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT)
Expand Down

0 comments on commit d2955f0

Please sign in to comment.