This is needed to avoid code duplication in SD-combo support. --- drivers/mmc/core/sd.c | 256 ++++++++++++++++++++++++++++-------------------- drivers/mmc/core/sd.h | 17 ++++ 2 files changed, 166 insertions(+), 107 deletions(-) create mode 100644 drivers/mmc/core/sd.h diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 5eac21d..75fad9a 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -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; @@ -238,22 +238,22 @@ out: /* * 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; if (card->scr.sda_vsn < SCR_SPEC_VER_1) - return 0; + return -EOPNOTSUPP; if (!(card->csd.cmdclass & CCC_SWITCH)) - return 0; + return -EOPNOTSUPP; if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) - return 0; + return -EOPNOTSUPP; if (card->sw_caps.hs_max_dtr == 0) - return 0; + return -EOPNOTSUPP; err = -EIO; @@ -272,9 +272,7 @@ 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)); - } else { - mmc_card_set_highspeed(card); - mmc_set_timing(card->host, MMC_TIMING_SD_HS); + err = -EOPNOTSUPP; } out: @@ -320,26 +318,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 @@ -361,23 +349,137 @@ 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]; + unsigned int max_dtr; + + 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 { @@ -385,10 +487,8 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, * 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)); @@ -400,22 +500,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); } @@ -426,60 +519,27 @@ 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; - } + err = mmc_sd_setup_card(host, card, oldcard != NULL); + 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. + * Attempt to change to high-speed (if supported) */ - if (mmc_host_is_spi(host)) { - err = mmc_spi_set_crc(host, use_spi_crc); - if (err) + err = mmc_sd_switch_hs(card); + if (err) { + if (err != -EOPNOTSUPP) goto free_card; + mmc_sd_go_highspeed(card); } /* - * Attempt to change to high-speed (if supported) - */ - err = mmc_switch_hs(card); - if (err) - goto free_card; - - /* * Compute 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; - } - + max_dtr = mmc_sd_get_max_clock(card); mmc_set_clock(host, max_dtr); /* @@ -494,30 +554,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; } diff --git a/drivers/mmc/core/sd.h b/drivers/mmc/core/sd.h new file mode 100644 index 0000000..3d8800f --- /dev/null +++ b/drivers/mmc/core/sd.h @@ -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 -- 1.6.4.4 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html