Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 208423
b: refs/heads/master
c: 71578a1
h: refs/heads/master
i:
  208421: a4c99ff
  208419: bae9fda
  208415: dffa01d
v: v3
  • Loading branch information
Michal Miroslaw authored and Linus Torvalds committed Aug 11, 2010
1 parent 3cb673f commit b98ba71
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 120 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: 6da24b786ed1963a7f872c1899627968c76d17d7
refs/heads/master: 71578a1eaa7b8b9bd3efc9c97d77ef2b63d5dc2b
249 changes: 145 additions & 104 deletions trunk/drivers/mmc/core/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ static const unsigned int tacc_mant[] = {
/*
* Given the decoded CSD structure, decode the raw CID to our CID structure.
*/
static void mmc_decode_cid(struct mmc_card *card)
void mmc_decode_cid(struct mmc_card *card)
{
u32 *resp = card->raw_cid;

Expand Down Expand Up @@ -238,7 +238,7 @@ static int mmc_read_switch(struct mmc_card *card)
/*
* Test if the card supports high-speed mode and, if so, switch to it.
*/
static int mmc_switch_hs(struct mmc_card *card)
int mmc_sd_switch_hs(struct mmc_card *card)
{
int err;
u8 *status;
Expand Down Expand Up @@ -272,9 +272,9 @@ static int mmc_switch_hs(struct mmc_card *card)
printk(KERN_WARNING "%s: Problem switching card "
"into high-speed mode!\n",
mmc_hostname(card->host));
err = 0;
} else {
mmc_card_set_highspeed(card);
mmc_set_timing(card->host, MMC_TIMING_SD_HS);
err = 1;
}

out:
Expand Down Expand Up @@ -320,26 +320,16 @@ static const struct attribute_group *sd_attr_groups[] = {
NULL,
};

static struct device_type sd_type = {
struct device_type sd_type = {
.groups = sd_attr_groups,
};

/*
* Handle the detection and initialisation of a card.
*
* In the case of a resume, "oldcard" will contain the card
* we're trying to reinitialise.
* Fetch CID from card.
*/
static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
struct mmc_card *oldcard)
int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid)
{
struct mmc_card *card;
int err;
u32 cid[4];
unsigned int max_dtr;

BUG_ON(!host);
WARN_ON(!host->claimed);

/*
* Since we're changing the OCR value, we seem to
Expand All @@ -361,34 +351,145 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,

err = mmc_send_app_op_cond(host, ocr, NULL);
if (err)
goto err;
return err;

/*
* Fetch CID from card.
*/
if (mmc_host_is_spi(host))
err = mmc_send_cid(host, cid);
else
err = mmc_all_send_cid(host, cid);

return err;
}

int mmc_sd_get_csd(struct mmc_host *host, struct mmc_card *card)
{
int err;

/*
* Fetch CSD from card.
*/
err = mmc_send_csd(card, card->raw_csd);
if (err)
goto err;
return err;

if (oldcard) {
if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
err = -ENOENT;
goto err;
err = mmc_decode_csd(card);
if (err)
return err;

return 0;
}

int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
bool reinit)
{
int err;

if (!reinit) {
/*
* Fetch SCR from card.
*/
err = mmc_app_send_scr(card, card->raw_scr);
if (err)
return err;

err = mmc_decode_scr(card);
if (err)
return err;

/*
* Fetch switch information from card.
*/
err = mmc_read_switch(card);
if (err)
return err;
}

/*
* For SPI, enable CRC as appropriate.
* This CRC enable is located AFTER the reading of the
* card registers because some SDHC cards are not able
* to provide valid CRCs for non-512-byte blocks.
*/
if (mmc_host_is_spi(host)) {
err = mmc_spi_set_crc(host, use_spi_crc);
if (err)
return err;
}

/*
* Check if read-only switch is active.
*/
if (!reinit) {
int ro = -1;

if (host->ops->get_ro)
ro = host->ops->get_ro(host);

if (ro < 0) {
printk(KERN_WARNING "%s: host does not "
"support reading read-only "
"switch. assuming write-enable.\n",
mmc_hostname(host));
} else if (ro > 0) {
mmc_card_set_readonly(card);
}
}

return 0;
}

unsigned mmc_sd_get_max_clock(struct mmc_card *card)
{
unsigned max_dtr = (unsigned int)-1;

if (mmc_card_highspeed(card)) {
if (max_dtr > card->sw_caps.hs_max_dtr)
max_dtr = card->sw_caps.hs_max_dtr;
} else if (max_dtr > card->csd.max_dtr) {
max_dtr = card->csd.max_dtr;
}

return max_dtr;
}

void mmc_sd_go_highspeed(struct mmc_card *card)
{
mmc_card_set_highspeed(card);
mmc_set_timing(card->host, MMC_TIMING_SD_HS);
}

/*
* Handle the detection and initialisation of a card.
*
* In the case of a resume, "oldcard" will contain the card
* we're trying to reinitialise.
*/
static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
struct mmc_card *oldcard)
{
struct mmc_card *card;
int err;
u32 cid[4];

BUG_ON(!host);
WARN_ON(!host->claimed);

err = mmc_sd_get_cid(host, ocr, cid);
if (err)
return err;

if (oldcard) {
if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
return -ENOENT;

card = oldcard;
} else {
/*
* Allocate card structure.
*/
card = mmc_alloc_card(host, &sd_type);
if (IS_ERR(card)) {
err = PTR_ERR(card);
goto err;
}
if (IS_ERR(card))
return PTR_ERR(card);

card->type = MMC_TYPE_SD;
memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
Expand All @@ -400,22 +501,15 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
if (!mmc_host_is_spi(host)) {
err = mmc_send_relative_addr(host, &card->rca);
if (err)
goto free_card;
return err;

mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
}

if (!oldcard) {
/*
* Fetch CSD from card.
*/
err = mmc_send_csd(card, card->raw_csd);
err = mmc_sd_get_csd(host, card);
if (err)
goto free_card;

err = mmc_decode_csd(card);
if (err)
goto free_card;
return err;

mmc_decode_cid(card);
}
Expand All @@ -426,61 +520,26 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
if (!mmc_host_is_spi(host)) {
err = mmc_select_card(card);
if (err)
goto free_card;
return err;
}

if (!oldcard) {
/*
* Fetch SCR from card.
*/
err = mmc_app_send_scr(card, card->raw_scr);
if (err)
goto free_card;

err = mmc_decode_scr(card);
if (err < 0)
goto free_card;

/*
* Fetch switch information from card.
*/
err = mmc_read_switch(card);
if (err)
goto free_card;
}

/*
* For SPI, enable CRC as appropriate.
* This CRC enable is located AFTER the reading of the
* card registers because some SDHC cards are not able
* to provide valid CRCs for non-512-byte blocks.
*/
if (mmc_host_is_spi(host)) {
err = mmc_spi_set_crc(host, use_spi_crc);
if (err)
goto free_card;
}
err = mmc_sd_setup_card(host, card, oldcard != NULL);
if (err)
goto free_card;

/*
* Attempt to change to high-speed (if supported)
*/
err = mmc_switch_hs(card);
if (err)
err = mmc_sd_switch_hs(card);
if (err > 0)
mmc_sd_go_highspeed(card);
else if (err)
goto free_card;

/*
* Compute bus speed.
* Set bus speed.
*/
max_dtr = (unsigned int)-1;

if (mmc_card_highspeed(card)) {
if (max_dtr > card->sw_caps.hs_max_dtr)
max_dtr = card->sw_caps.hs_max_dtr;
} else if (max_dtr > card->csd.max_dtr) {
max_dtr = card->csd.max_dtr;
}

mmc_set_clock(host, max_dtr);
mmc_set_clock(host, mmc_sd_get_max_clock(card));

/*
* Switch to wider bus (if supported).
Expand All @@ -494,30 +553,12 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
}

/*
* Check if read-only switch is active.
*/
if (!oldcard) {
if (!host->ops->get_ro || host->ops->get_ro(host) < 0) {
printk(KERN_WARNING "%s: host does not "
"support reading read-only "
"switch. assuming write-enable.\n",
mmc_hostname(host));
} else {
if (host->ops->get_ro(host) > 0)
mmc_card_set_readonly(card);
}
}

if (!oldcard)
host->card = card;

host->card = card;
return 0;

free_card:
if (!oldcard)
mmc_remove_card(card);
err:

return err;
}
Expand Down
17 changes: 17 additions & 0 deletions trunk/drivers/mmc/core/sd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef _MMC_CORE_SD_H
#define _MMC_CORE_SD_H

#include <linux/mmc/card.h>

extern struct device_type sd_type;

int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid);
int mmc_sd_get_csd(struct mmc_host *host, struct mmc_card *card);
void mmc_decode_cid(struct mmc_card *card);
int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
bool reinit);
unsigned mmc_sd_get_max_clock(struct mmc_card *card);
int mmc_sd_switch_hs(struct mmc_card *card);
void mmc_sd_go_highspeed(struct mmc_card *card);

#endif
Loading

0 comments on commit b98ba71

Please sign in to comment.