Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 41444
b: refs/heads/master
c: 7ccd266
h: refs/heads/master
v: v3
  • Loading branch information
Pierre Ossman committed Dec 1, 2006
1 parent 55a51b0 commit 6561db6
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 6 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: 73778120c4088a0a7b59c4c378904f7a230b4820
refs/heads/master: 7ccd266e676a3f0c6f8f897f58b684cac3dd1650
122 changes: 118 additions & 4 deletions trunk/drivers/mmc/mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1157,16 +1157,129 @@ static void mmc_read_scrs(struct mmc_host *host)
mmc_deselect_cards(host);
}

static void mmc_read_switch_caps(struct mmc_host *host)
{
int err;
struct mmc_card *card;
struct mmc_request mrq;
struct mmc_command cmd;
struct mmc_data data;
unsigned char *status;
struct scatterlist sg;

status = kmalloc(64, GFP_KERNEL);
if (!status) {
printk(KERN_WARNING "%s: Unable to allocate buffer for "
"reading switch capabilities.\n",
mmc_hostname(host));
return;
}

list_for_each_entry(card, &host->cards, node) {
if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
continue;
if (!mmc_card_sd(card))
continue;
if (card->scr.sda_vsn < SCR_SPEC_VER_1)
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 = SD_SWITCH;
cmd.arg = 0x00FFFFF1;
cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;

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

mmc_set_data_timeout(&data, card, 0);

data.blksz = 64;
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, status, 64);

mmc_wait_for_req(host, &mrq);

if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
mmc_card_set_dead(card);
continue;
}

if (status[13] & 0x02)
card->sw_caps.hs_max_dtr = 50000000;

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

cmd.opcode = SD_SWITCH;
cmd.arg = 0x80FFFFF1;
cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;

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

mmc_set_data_timeout(&data, card, 0);

data.blksz = 64;
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, status, 64);

mmc_wait_for_req(host, &mrq);

if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
mmc_card_set_dead(card);
continue;
}

if ((status[16] & 0xF) != 1) {
printk(KERN_WARNING "%s: Problem switching card "
"into high-speed mode!\n",
mmc_hostname(host));
continue;
}

mmc_card_set_highspeed(card);
}

kfree(status);

mmc_deselect_cards(host);
}

static unsigned int mmc_calculate_clock(struct mmc_host *host)
{
struct mmc_card *card;
unsigned int max_dtr = host->f_max;

list_for_each_entry(card, &host->cards, node)
if (!mmc_card_dead(card)) {
if (mmc_card_highspeed(card)) {
if (mmc_card_highspeed(card) && mmc_card_sd(card)) {
if (max_dtr > card->sw_caps.hs_max_dtr)
max_dtr = card->sw_caps.hs_max_dtr;
} else if (mmc_card_highspeed(card) && !mmc_card_sd(card)) {
if (max_dtr > card->ext_csd.hs_max_dtr)
max_dtr = card->ext_csd.hs_max_dtr;
max_dtr = card->ext_csd.hs_max_dtr;
} else if (max_dtr > card->csd.max_dtr) {
max_dtr = card->csd.max_dtr;
}
Expand Down Expand Up @@ -1288,9 +1401,10 @@ static void mmc_setup(struct mmc_host *host)

mmc_read_csds(host);

if (host->mode == MMC_MODE_SD)
if (host->mode == MMC_MODE_SD) {
mmc_read_scrs(host);
else
mmc_read_switch_caps(host);
} else
mmc_process_ext_csds(host);
}

Expand Down
7 changes: 6 additions & 1 deletion trunk/include/linux/mmc/card.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ struct sd_scr {
#define SD_SCR_BUS_WIDTH_4 (1<<2)
};

struct sd_switch_caps {
unsigned int hs_max_dtr;
};

struct mmc_host;

/*
Expand All @@ -66,14 +70,15 @@ struct mmc_card {
#define MMC_STATE_BAD (1<<2) /* unrecognised device */
#define MMC_STATE_SDCARD (1<<3) /* is an SD card */
#define MMC_STATE_READONLY (1<<4) /* card is read-only */
#define MMC_STATE_HIGHSPEED (1<<5) /* card is in mmc4 highspeed mode */
#define MMC_STATE_HIGHSPEED (1<<5) /* card is in high speed mode */
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 mmc_ext_csd ext_csd; /* mmc v4 extended card specific */
struct sd_scr scr; /* extra SD information */
struct sd_switch_caps sw_caps; /* switch (CMD6) caps */
};

#define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT)
Expand Down
22 changes: 22 additions & 0 deletions trunk/include/linux/mmc/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
/* class 8 */
/* This is basically the same command as for MMC with some quirks. */
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */

/* Application commands */
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
Expand All @@ -100,6 +101,19 @@
* [02:00] Command Set
*/

/*
* SD_SWITCH argument format:
*
* [31] Check (0) or switch (1)
* [30:24] Reserved (0)
* [23:20] Function group 6
* [19:16] Function group 5
* [15:12] Function group 4
* [11:8] Function group 3
* [7:4] Function group 2
* [3:0] Function group 1
*/

/*
MMC status in R1
Type
Expand Down Expand Up @@ -284,6 +298,14 @@ struct _mmc_csd {
#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */

/*
* SCR field definitions
*/

#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */
#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */
#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00 */

/*
* SD bus widths
*/
Expand Down

0 comments on commit 6561db6

Please sign in to comment.