Loading drivers/mmc/host/sdhci.c +124 −92 Original line number Diff line number Diff line Loading @@ -1952,64 +1952,9 @@ static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) return 0; } static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) static void sdhci_start_tuning(struct sdhci_host *host) { struct sdhci_host *host = mmc_priv(mmc); u16 ctrl; int tuning_loop_counter = MAX_TUNING_LOOP; int err = 0; unsigned long flags; unsigned int tuning_count = 0; bool hs400_tuning; spin_lock_irqsave(&host->lock, flags); hs400_tuning = host->flags & SDHCI_HS400_TUNING; host->flags &= ~SDHCI_HS400_TUNING; if (host->tuning_mode == SDHCI_TUNING_MODE_1) tuning_count = host->tuning_count; /* * The Host Controller needs tuning in case of SDR104 and DDR50 * 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. */ switch (host->timing) { /* HS400 tuning is done in HS200 mode */ case MMC_TIMING_MMC_HS400: err = -EINVAL; goto out_unlock; case MMC_TIMING_MMC_HS200: /* * Periodic re-tuning for HS400 is not expected to be needed, so * disable it here. */ if (hs400_tuning) tuning_count = 0; break; case MMC_TIMING_UHS_SDR104: case MMC_TIMING_UHS_DDR50: break; case MMC_TIMING_UHS_SDR50: if (host->flags & SDHCI_SDR50_NEEDS_TUNING) break; /* FALLTHROUGH */ default: goto out_unlock; } if (host->ops->platform_execute_tuning) { spin_unlock_irqrestore(&host->lock, flags); err = host->ops->platform_execute_tuning(host, opcode); return err; } ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); ctrl |= SDHCI_CTRL_EXEC_TUNING; Loading @@ -2029,28 +1974,58 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) */ sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); } static void sdhci_end_tuning(struct sdhci_host *host) { sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); } static void sdhci_reset_tuning(struct sdhci_host *host) { u16 ctrl; ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); ctrl &= ~SDHCI_CTRL_TUNED_CLK; ctrl &= ~SDHCI_CTRL_EXEC_TUNING; sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); } static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode, unsigned long flags) { sdhci_reset_tuning(host); sdhci_do_reset(host, SDHCI_RESET_CMD); sdhci_do_reset(host, SDHCI_RESET_DATA); sdhci_end_tuning(host); spin_unlock_irqrestore(&host->lock, flags); mmc_abort_tuning(host->mmc, opcode); spin_lock_irqsave(&host->lock, flags); } /* * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number * of loops reaches 40 times. * We use sdhci_send_tuning() because mmc_send_tuning() is not a good fit. SDHCI * tuning command does not have a data payload (or rather the hardware does it * automatically) so mmc_send_tuning() will return -EIO. Also the tuning command * interrupt setup is different to other commands and there is no timeout * interrupt so special handling is needed. */ do { static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode, unsigned long flags) { struct mmc_host *mmc = host->mmc; struct mmc_command cmd = {0}; struct mmc_request mrq = {NULL}; cmd.opcode = opcode; cmd.arg = 0; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.retries = 0; cmd.data = NULL; cmd.mrq = &mrq; cmd.error = 0; if (tuning_loop_counter-- == 0) break; mrq.cmd = &cmd; /* * In response to CMD19, the card sends 64 bytes of tuning * block to the Host Controller. So we set the block size Loading Loading @@ -2079,37 +2054,97 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) sdhci_send_command(host, &cmd); host->cmd = NULL; sdhci_del_timer(host, &mrq); host->tuning_done = 0; spin_unlock_irqrestore(&host->lock, flags); /* Wait for Buffer Read Ready interrupt */ wait_event_timeout(host->buf_ready_int, (host->tuning_done == 1), wait_event_timeout(host->buf_ready_int, (host->tuning_done == 1), msecs_to_jiffies(50)); spin_lock_irqsave(&host->lock, flags); } if (!host->tuning_done) { pr_info(DRIVER_NAME ": Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock\n"); ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); ctrl &= ~SDHCI_CTRL_TUNED_CLK; ctrl &= ~SDHCI_CTRL_EXEC_TUNING; sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) { struct sdhci_host *host = mmc_priv(mmc); u16 ctrl; int tuning_loop_counter = MAX_TUNING_LOOP; int err = 0; unsigned long flags; unsigned int tuning_count = 0; bool hs400_tuning; sdhci_do_reset(host, SDHCI_RESET_CMD); sdhci_do_reset(host, SDHCI_RESET_DATA); spin_lock_irqsave(&host->lock, flags); sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); hs400_tuning = host->flags & SDHCI_HS400_TUNING; host->flags &= ~SDHCI_HS400_TUNING; if (host->tuning_mode == SDHCI_TUNING_MODE_1) tuning_count = host->tuning_count; /* * The Host Controller needs tuning in case of SDR104 and DDR50 * 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. */ switch (host->timing) { /* HS400 tuning is done in HS200 mode */ case MMC_TIMING_MMC_HS400: err = -EINVAL; goto out_unlock; case MMC_TIMING_MMC_HS200: /* * Periodic re-tuning for HS400 is not expected to be needed, so * disable it here. */ if (hs400_tuning) tuning_count = 0; break; case MMC_TIMING_UHS_SDR104: case MMC_TIMING_UHS_DDR50: break; case MMC_TIMING_UHS_SDR50: if (host->flags & SDHCI_SDR50_NEEDS_TUNING) break; /* FALLTHROUGH */ default: goto out_unlock; } if (host->ops->platform_execute_tuning) { spin_unlock_irqrestore(&host->lock, flags); mmc_abort_tuning(mmc, opcode); spin_lock_irqsave(&host->lock, flags); err = host->ops->platform_execute_tuning(host, opcode); return err; } sdhci_start_tuning(host); /* * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number * of loops reaches 40 times. */ do { if (tuning_loop_counter-- == 0) break; sdhci_send_tuning(host, opcode, flags); if (!host->tuning_done) { pr_info(DRIVER_NAME ": Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock\n"); sdhci_abort_tuning(host, opcode, flags); goto out; } host->tuning_done = 0; ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); /* eMMC spec does not require a delay between tuning cycles */ Loading @@ -2121,18 +2156,15 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) * The Host Driver has exhausted the maximum number of loops allowed, * so use fixed sampling frequency. */ if (tuning_loop_counter < 0) { ctrl &= ~SDHCI_CTRL_TUNED_CLK; ctrl &= ~SDHCI_CTRL_EXEC_TUNING; sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); } if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) if (tuning_loop_counter < 0) sdhci_reset_tuning(host); if (tuning_loop_counter < 0 || !(ctrl & SDHCI_CTRL_TUNED_CLK)) pr_info(DRIVER_NAME ": Tuning procedure failed, falling back to fixed sampling clock\n"); out: host->mmc->retune_period = tuning_count; sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); sdhci_end_tuning(host); out_unlock: spin_unlock_irqrestore(&host->lock, flags); return err; Loading Loading
drivers/mmc/host/sdhci.c +124 −92 Original line number Diff line number Diff line Loading @@ -1952,64 +1952,9 @@ static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) return 0; } static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) static void sdhci_start_tuning(struct sdhci_host *host) { struct sdhci_host *host = mmc_priv(mmc); u16 ctrl; int tuning_loop_counter = MAX_TUNING_LOOP; int err = 0; unsigned long flags; unsigned int tuning_count = 0; bool hs400_tuning; spin_lock_irqsave(&host->lock, flags); hs400_tuning = host->flags & SDHCI_HS400_TUNING; host->flags &= ~SDHCI_HS400_TUNING; if (host->tuning_mode == SDHCI_TUNING_MODE_1) tuning_count = host->tuning_count; /* * The Host Controller needs tuning in case of SDR104 and DDR50 * 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. */ switch (host->timing) { /* HS400 tuning is done in HS200 mode */ case MMC_TIMING_MMC_HS400: err = -EINVAL; goto out_unlock; case MMC_TIMING_MMC_HS200: /* * Periodic re-tuning for HS400 is not expected to be needed, so * disable it here. */ if (hs400_tuning) tuning_count = 0; break; case MMC_TIMING_UHS_SDR104: case MMC_TIMING_UHS_DDR50: break; case MMC_TIMING_UHS_SDR50: if (host->flags & SDHCI_SDR50_NEEDS_TUNING) break; /* FALLTHROUGH */ default: goto out_unlock; } if (host->ops->platform_execute_tuning) { spin_unlock_irqrestore(&host->lock, flags); err = host->ops->platform_execute_tuning(host, opcode); return err; } ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); ctrl |= SDHCI_CTRL_EXEC_TUNING; Loading @@ -2029,28 +1974,58 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) */ sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); } static void sdhci_end_tuning(struct sdhci_host *host) { sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); } static void sdhci_reset_tuning(struct sdhci_host *host) { u16 ctrl; ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); ctrl &= ~SDHCI_CTRL_TUNED_CLK; ctrl &= ~SDHCI_CTRL_EXEC_TUNING; sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); } static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode, unsigned long flags) { sdhci_reset_tuning(host); sdhci_do_reset(host, SDHCI_RESET_CMD); sdhci_do_reset(host, SDHCI_RESET_DATA); sdhci_end_tuning(host); spin_unlock_irqrestore(&host->lock, flags); mmc_abort_tuning(host->mmc, opcode); spin_lock_irqsave(&host->lock, flags); } /* * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number * of loops reaches 40 times. * We use sdhci_send_tuning() because mmc_send_tuning() is not a good fit. SDHCI * tuning command does not have a data payload (or rather the hardware does it * automatically) so mmc_send_tuning() will return -EIO. Also the tuning command * interrupt setup is different to other commands and there is no timeout * interrupt so special handling is needed. */ do { static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode, unsigned long flags) { struct mmc_host *mmc = host->mmc; struct mmc_command cmd = {0}; struct mmc_request mrq = {NULL}; cmd.opcode = opcode; cmd.arg = 0; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.retries = 0; cmd.data = NULL; cmd.mrq = &mrq; cmd.error = 0; if (tuning_loop_counter-- == 0) break; mrq.cmd = &cmd; /* * In response to CMD19, the card sends 64 bytes of tuning * block to the Host Controller. So we set the block size Loading Loading @@ -2079,37 +2054,97 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) sdhci_send_command(host, &cmd); host->cmd = NULL; sdhci_del_timer(host, &mrq); host->tuning_done = 0; spin_unlock_irqrestore(&host->lock, flags); /* Wait for Buffer Read Ready interrupt */ wait_event_timeout(host->buf_ready_int, (host->tuning_done == 1), wait_event_timeout(host->buf_ready_int, (host->tuning_done == 1), msecs_to_jiffies(50)); spin_lock_irqsave(&host->lock, flags); } if (!host->tuning_done) { pr_info(DRIVER_NAME ": Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock\n"); ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); ctrl &= ~SDHCI_CTRL_TUNED_CLK; ctrl &= ~SDHCI_CTRL_EXEC_TUNING; sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) { struct sdhci_host *host = mmc_priv(mmc); u16 ctrl; int tuning_loop_counter = MAX_TUNING_LOOP; int err = 0; unsigned long flags; unsigned int tuning_count = 0; bool hs400_tuning; sdhci_do_reset(host, SDHCI_RESET_CMD); sdhci_do_reset(host, SDHCI_RESET_DATA); spin_lock_irqsave(&host->lock, flags); sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); hs400_tuning = host->flags & SDHCI_HS400_TUNING; host->flags &= ~SDHCI_HS400_TUNING; if (host->tuning_mode == SDHCI_TUNING_MODE_1) tuning_count = host->tuning_count; /* * The Host Controller needs tuning in case of SDR104 and DDR50 * 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. */ switch (host->timing) { /* HS400 tuning is done in HS200 mode */ case MMC_TIMING_MMC_HS400: err = -EINVAL; goto out_unlock; case MMC_TIMING_MMC_HS200: /* * Periodic re-tuning for HS400 is not expected to be needed, so * disable it here. */ if (hs400_tuning) tuning_count = 0; break; case MMC_TIMING_UHS_SDR104: case MMC_TIMING_UHS_DDR50: break; case MMC_TIMING_UHS_SDR50: if (host->flags & SDHCI_SDR50_NEEDS_TUNING) break; /* FALLTHROUGH */ default: goto out_unlock; } if (host->ops->platform_execute_tuning) { spin_unlock_irqrestore(&host->lock, flags); mmc_abort_tuning(mmc, opcode); spin_lock_irqsave(&host->lock, flags); err = host->ops->platform_execute_tuning(host, opcode); return err; } sdhci_start_tuning(host); /* * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number * of loops reaches 40 times. */ do { if (tuning_loop_counter-- == 0) break; sdhci_send_tuning(host, opcode, flags); if (!host->tuning_done) { pr_info(DRIVER_NAME ": Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock\n"); sdhci_abort_tuning(host, opcode, flags); goto out; } host->tuning_done = 0; ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); /* eMMC spec does not require a delay between tuning cycles */ Loading @@ -2121,18 +2156,15 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) * The Host Driver has exhausted the maximum number of loops allowed, * so use fixed sampling frequency. */ if (tuning_loop_counter < 0) { ctrl &= ~SDHCI_CTRL_TUNED_CLK; ctrl &= ~SDHCI_CTRL_EXEC_TUNING; sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); } if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) if (tuning_loop_counter < 0) sdhci_reset_tuning(host); if (tuning_loop_counter < 0 || !(ctrl & SDHCI_CTRL_TUNED_CLK)) pr_info(DRIVER_NAME ": Tuning procedure failed, falling back to fixed sampling clock\n"); out: host->mmc->retune_period = tuning_count; sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); sdhci_end_tuning(host); out_unlock: spin_unlock_irqrestore(&host->lock, flags); return err; Loading