Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 284532
b: refs/heads/master
c: 069c9f1
h: refs/heads/master
v: v3
  • Loading branch information
Girish K S authored and Chris Ball committed Jan 12, 2012
1 parent 5329fee commit cd0d7fe
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 16 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: a4924c71aa43d4f8a3f342b1f71788349472e684
refs/heads/master: 069c9f142822d552ec885572945d8bce9eff0519
57 changes: 42 additions & 15 deletions trunk/drivers/mmc/host/sdhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ static void sdhci_finish_data(struct sdhci_host *);

static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
static void sdhci_finish_command(struct sdhci_host *);
static int sdhci_execute_tuning(struct mmc_host *mmc);
static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
static void sdhci_tuning_timer(unsigned long data);

#ifdef CONFIG_PM_RUNTIME
Expand Down Expand Up @@ -1014,7 +1014,8 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
flags |= SDHCI_CMD_INDEX;

/* CMD19 is special in that the Data Present Select should be set */
if (cmd->data || (cmd->opcode == MMC_SEND_TUNING_BLOCK))
if (cmd->data || cmd->opcode == MMC_SEND_TUNING_BLOCK ||
cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200)
flags |= SDHCI_CMD_DATA;

sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
Expand Down Expand Up @@ -1287,7 +1288,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
if ((host->flags & SDHCI_NEEDS_RETUNING) &&
!(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) {
spin_unlock_irqrestore(&host->lock, flags);
sdhci_execute_tuning(mmc);
sdhci_execute_tuning(mmc, mrq->cmd->opcode);
spin_lock_irqsave(&host->lock, flags);

/* Restore original mmc_request structure */
Expand Down Expand Up @@ -1382,7 +1383,8 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
unsigned int clock;

/* In case of UHS-I modes, set High Speed Enable */
if ((ios->timing == MMC_TIMING_UHS_SDR50) ||
if ((ios->timing == MMC_TIMING_MMC_HS200) ||
(ios->timing == MMC_TIMING_UHS_SDR50) ||
(ios->timing == MMC_TIMING_UHS_SDR104) ||
(ios->timing == MMC_TIMING_UHS_DDR50) ||
(ios->timing == MMC_TIMING_UHS_SDR25))
Expand Down Expand Up @@ -1435,7 +1437,9 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
/* Select Bus Speed Mode for host */
ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
if (ios->timing == MMC_TIMING_UHS_SDR12)
if (ios->timing == MMC_TIMING_MMC_HS200)
ctrl_2 |= SDHCI_CTRL_HS_SDR200;
else if (ios->timing == MMC_TIMING_UHS_SDR12)
ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
else if (ios->timing == MMC_TIMING_UHS_SDR25)
ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
Expand Down Expand Up @@ -1682,14 +1686,15 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
return err;
}

static int sdhci_execute_tuning(struct mmc_host *mmc)
static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
{
struct sdhci_host *host;
u16 ctrl;
u32 ier;
int tuning_loop_counter = MAX_TUNING_LOOP;
unsigned long timeout;
int err = 0;
bool requires_tuning_nonuhs = false;

host = mmc_priv(mmc);

Expand All @@ -1700,13 +1705,19 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);

/*
* Host Controller needs tuning only in case of SDR104 mode
* and for SDR50 mode when Use Tuning for SDR50 is set in
* The Host Controller needs tuning only in case of SDR104 mode
* and for SDR50 mode when Use Tuning for SDR50 is set in the
* Capabilities register.
* If the Host Controller supports the HS200 mode then the
* tuning function has to be executed.
*/
if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) &&
(host->flags & SDHCI_SDR50_NEEDS_TUNING ||
host->flags & SDHCI_HS200_NEEDS_TUNING))
requires_tuning_nonuhs = true;

if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) ||
(((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) &&
(host->flags & SDHCI_SDR50_NEEDS_TUNING)))
requires_tuning_nonuhs)
ctrl |= SDHCI_CTRL_EXEC_TUNING;
else {
spin_unlock(&host->lock);
Expand Down Expand Up @@ -1742,7 +1753,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
if (!tuning_loop_counter && !timeout)
break;

cmd.opcode = MMC_SEND_TUNING_BLOCK;
cmd.opcode = opcode;
cmd.arg = 0;
cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
cmd.retries = 0;
Expand All @@ -1757,7 +1768,17 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
* block to the Host Controller. So we set the block size
* to 64 here.
*/
sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE);
if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200) {
if (mmc->ios.bus_width == MMC_BUS_WIDTH_8)
sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128),
SDHCI_BLOCK_SIZE);
else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4)
sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64),
SDHCI_BLOCK_SIZE);
} else {
sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64),
SDHCI_BLOCK_SIZE);
}

/*
* The tuning block is sent by the card to the host controller.
Expand Down Expand Up @@ -2140,12 +2161,14 @@ static void sdhci_show_adma_error(struct sdhci_host *host) { }

static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
{
u32 command;
BUG_ON(intmask == 0);

/* CMD19 generates _only_ Buffer Read Ready interrupt */
if (intmask & SDHCI_INT_DATA_AVAIL) {
if (SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) ==
MMC_SEND_TUNING_BLOCK) {
command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND));
if (command == MMC_SEND_TUNING_BLOCK ||
command == MMC_SEND_TUNING_BLOCK_HS200) {
host->tuning_done = 1;
wake_up(&host->buf_ready_int);
return;
Expand Down Expand Up @@ -2747,10 +2770,14 @@ int sdhci_add_host(struct sdhci_host *host)
if (caps[1] & SDHCI_SUPPORT_DDR50)
mmc->caps |= MMC_CAP_UHS_DDR50;

/* Does the host needs tuning for SDR50? */
/* Does the host need tuning for SDR50? */
if (caps[1] & SDHCI_USE_SDR50_TUNING)
host->flags |= SDHCI_SDR50_NEEDS_TUNING;

/* Does the host need tuning for HS200? */
if (mmc->caps2 & MMC_CAP2_HS200)
host->flags |= SDHCI_HS200_NEEDS_TUNING;

/* Driver Type(s) (A, C, D) supported by the host */
if (caps[1] & SDHCI_DRIVER_TYPE_A)
mmc->caps |= MMC_CAP_DRIVER_TYPE_A;
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/mmc/host/sdhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@
#define SDHCI_CTRL_UHS_SDR50 0x0002
#define SDHCI_CTRL_UHS_SDR104 0x0003
#define SDHCI_CTRL_UHS_DDR50 0x0004
#define SDHCI_CTRL_HS_SDR200 0x0005 /* reserved value in SDIO spec */
#define SDHCI_CTRL_VDD_180 0x0008
#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030
#define SDHCI_CTRL_DRV_TYPE_B 0x0000
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/mmc/sdhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ struct sdhci_host {
#define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */
#define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */
#define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */
#define SDHCI_HS200_NEEDS_TUNING (1<<10) /* HS200 needs tuning */

unsigned int version; /* SDHCI spec. version */

Expand Down

0 comments on commit cd0d7fe

Please sign in to comment.