From 497d73bf437ab36446d3fe72687ac67758435bad Mon Sep 17 00:00:00 2001 From: lbt Date: Tue, 22 Mar 2011 19:09:19 +0800 Subject: [PATCH] update mmc stack from linux2.6.35 sdio: add quirk to clamp byte mode transfer Some SDIO cards expect byte transfers not to exceed the configured block transfer size. Add a quirk to that effect. --- drivers/mmc/core/sdio.c | 7 +++++++ drivers/mmc/core/sdio_io.c | 7 ++++++- drivers/mmc/host/rk29_sdmmc.c | 7 +++++++ include/linux/mmc/card.h | 6 ++++++ include/linux/mmc/host.h | 3 +++ 5 files changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index ac9102487e25..a0ea736432a0 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -262,6 +262,13 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, } card->type = MMC_TYPE_SDIO; + + /* + * Call the optional HC's init_card function to handle quirks. + */ + if (host->ops->init_card) + host->ops->init_card(host, card); + /* * For native busses: set card RCA and quit open drain mode. diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c index 6bb0654a0d4e..6c1d8474ce7d 100755 --- a/drivers/mmc/core/sdio_io.c +++ b/drivers/mmc/core/sdio_io.c @@ -189,7 +189,12 @@ static inline unsigned int sdio_max_byte_size(struct sdio_func *func) { unsigned mval = min(func->card->host->max_seg_size, func->card->host->max_blk_size); - mval = min(mval, func->max_blksize); + + if (mmc_blksz_for_byte_mode(func->card)) + mval = min(mval, func->cur_blksize); + else + mval = min(mval, func->max_blksize); + return min(mval, 512u); /* maximum size for byte mode */ } diff --git a/drivers/mmc/host/rk29_sdmmc.c b/drivers/mmc/host/rk29_sdmmc.c index 2af2f30095d1..f3a62f4c9998 100755 --- a/drivers/mmc/host/rk29_sdmmc.c +++ b/drivers/mmc/host/rk29_sdmmc.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -704,6 +705,11 @@ static void rk29_sdmmc_enable_sdio_irq(struct mmc_host *mmc, int enable) spin_unlock_irqrestore(&host->lock, flags); } +static void rk29_sdmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) +{ + card->quirks = MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; + +} static const struct mmc_host_ops rk29_sdmmc_ops[] = { { .request = rk29_sdmmc_request, @@ -715,6 +721,7 @@ static const struct mmc_host_ops rk29_sdmmc_ops[] = { .request = rk29_sdmmc_request, .set_ios = rk29_sdmmc_set_ios, .enable_sdio_irq = rk29_sdmmc_enable_sdio_irq, + .init_card = rk29_sdmmc_init_card, }, }; diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 2ee22e8af110..590a7e8043ba 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -99,6 +99,7 @@ struct mmc_card { #define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */ unsigned int quirks; /* card quirks */ #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ +#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ u32 raw_cid[4]; /* raw card CID */ u32 raw_csd[4]; /* raw card CSD */ @@ -139,6 +140,11 @@ static inline int mmc_card_lenient_fn0(const struct mmc_card *c) return c->quirks & MMC_QUIRK_LENIENT_FN0; } +static inline int mmc_blksz_for_byte_mode(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; +} + #define mmc_card_name(c) ((c)->cid.prod_name) #define mmc_card_id(c) (dev_name(&(c)->dev)) diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index c3b88ff5654f..6c731a48c962 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -107,6 +107,9 @@ struct mmc_host_ops { int (*get_cd)(struct mmc_host *host); void (*enable_sdio_irq)(struct mmc_host *host, int enable); + + /* optional callback for HC quirks */ + void (*init_card)(struct mmc_host *host, struct mmc_card *card); }; struct mmc_card; -- 2.34.1