diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2016-12-02 08:59:23 -0500 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2016-12-05 08:16:23 -0500 |
commit | da4bc4f2851e3c46076929a8c9a99ee3e076cf1f (patch) | |
tree | 583a180ee693e6c4e352827e1116201f2393a59f | |
parent | d0c3ab59105dd0192fc9bc3a578584a5b1c01dd0 (diff) |
mmc: sdhci: Factor out tuning helper functions
Factor out some functions to tidy up the code in sdhci_execute_tuning.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r-- | drivers/mmc/host/sdhci.c | 216 |
1 files changed, 124 insertions, 92 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index b841d0a57af1..a6f8e164b3fd 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -1952,6 +1952,122 @@ static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1952 | return 0; | 1952 | return 0; |
1953 | } | 1953 | } |
1954 | 1954 | ||
1955 | static void sdhci_start_tuning(struct sdhci_host *host) | ||
1956 | { | ||
1957 | u16 ctrl; | ||
1958 | |||
1959 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
1960 | ctrl |= SDHCI_CTRL_EXEC_TUNING; | ||
1961 | if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND) | ||
1962 | ctrl |= SDHCI_CTRL_TUNED_CLK; | ||
1963 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
1964 | |||
1965 | /* | ||
1966 | * As per the Host Controller spec v3.00, tuning command | ||
1967 | * generates Buffer Read Ready interrupt, so enable that. | ||
1968 | * | ||
1969 | * Note: The spec clearly says that when tuning sequence | ||
1970 | * is being performed, the controller does not generate | ||
1971 | * interrupts other than Buffer Read Ready interrupt. But | ||
1972 | * to make sure we don't hit a controller bug, we _only_ | ||
1973 | * enable Buffer Read Ready interrupt here. | ||
1974 | */ | ||
1975 | sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); | ||
1976 | sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); | ||
1977 | } | ||
1978 | |||
1979 | static void sdhci_end_tuning(struct sdhci_host *host) | ||
1980 | { | ||
1981 | sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); | ||
1982 | sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); | ||
1983 | } | ||
1984 | |||
1985 | static void sdhci_reset_tuning(struct sdhci_host *host) | ||
1986 | { | ||
1987 | u16 ctrl; | ||
1988 | |||
1989 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
1990 | ctrl &= ~SDHCI_CTRL_TUNED_CLK; | ||
1991 | ctrl &= ~SDHCI_CTRL_EXEC_TUNING; | ||
1992 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
1993 | } | ||
1994 | |||
1995 | static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode, | ||
1996 | unsigned long flags) | ||
1997 | { | ||
1998 | sdhci_reset_tuning(host); | ||
1999 | |||
2000 | sdhci_do_reset(host, SDHCI_RESET_CMD); | ||
2001 | sdhci_do_reset(host, SDHCI_RESET_DATA); | ||
2002 | |||
2003 | sdhci_end_tuning(host); | ||
2004 | |||
2005 | spin_unlock_irqrestore(&host->lock, flags); | ||
2006 | mmc_abort_tuning(host->mmc, opcode); | ||
2007 | spin_lock_irqsave(&host->lock, flags); | ||
2008 | } | ||
2009 | |||
2010 | /* | ||
2011 | * We use sdhci_send_tuning() because mmc_send_tuning() is not a good fit. SDHCI | ||
2012 | * tuning command does not have a data payload (or rather the hardware does it | ||
2013 | * automatically) so mmc_send_tuning() will return -EIO. Also the tuning command | ||
2014 | * interrupt setup is different to other commands and there is no timeout | ||
2015 | * interrupt so special handling is needed. | ||
2016 | */ | ||
2017 | static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode, | ||
2018 | unsigned long flags) | ||
2019 | { | ||
2020 | struct mmc_host *mmc = host->mmc; | ||
2021 | struct mmc_command cmd = {0}; | ||
2022 | struct mmc_request mrq = {NULL}; | ||
2023 | |||
2024 | cmd.opcode = opcode; | ||
2025 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | ||
2026 | cmd.mrq = &mrq; | ||
2027 | |||
2028 | mrq.cmd = &cmd; | ||
2029 | /* | ||
2030 | * In response to CMD19, the card sends 64 bytes of tuning | ||
2031 | * block to the Host Controller. So we set the block size | ||
2032 | * to 64 here. | ||
2033 | */ | ||
2034 | if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200) { | ||
2035 | if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) | ||
2036 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128), | ||
2037 | SDHCI_BLOCK_SIZE); | ||
2038 | else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) | ||
2039 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), | ||
2040 | SDHCI_BLOCK_SIZE); | ||
2041 | } else { | ||
2042 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), | ||
2043 | SDHCI_BLOCK_SIZE); | ||
2044 | } | ||
2045 | |||
2046 | /* | ||
2047 | * The tuning block is sent by the card to the host controller. | ||
2048 | * So we set the TRNS_READ bit in the Transfer Mode register. | ||
2049 | * This also takes care of setting DMA Enable and Multi Block | ||
2050 | * Select in the same register to 0. | ||
2051 | */ | ||
2052 | sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); | ||
2053 | |||
2054 | sdhci_send_command(host, &cmd); | ||
2055 | |||
2056 | host->cmd = NULL; | ||
2057 | |||
2058 | sdhci_del_timer(host, &mrq); | ||
2059 | |||
2060 | host->tuning_done = 0; | ||
2061 | |||
2062 | spin_unlock_irqrestore(&host->lock, flags); | ||
2063 | |||
2064 | /* Wait for Buffer Read Ready interrupt */ | ||
2065 | wait_event_timeout(host->buf_ready_int, (host->tuning_done == 1), | ||
2066 | msecs_to_jiffies(50)); | ||
2067 | |||
2068 | spin_lock_irqsave(&host->lock, flags); | ||
2069 | } | ||
2070 | |||
1955 | static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) | 2071 | static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) |
1956 | { | 2072 | { |
1957 | struct sdhci_host *host = mmc_priv(mmc); | 2073 | struct sdhci_host *host = mmc_priv(mmc); |
@@ -2011,105 +2127,24 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
2011 | return err; | 2127 | return err; |
2012 | } | 2128 | } |
2013 | 2129 | ||
2014 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 2130 | sdhci_start_tuning(host); |
2015 | ctrl |= SDHCI_CTRL_EXEC_TUNING; | ||
2016 | if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND) | ||
2017 | ctrl |= SDHCI_CTRL_TUNED_CLK; | ||
2018 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
2019 | |||
2020 | /* | ||
2021 | * As per the Host Controller spec v3.00, tuning command | ||
2022 | * generates Buffer Read Ready interrupt, so enable that. | ||
2023 | * | ||
2024 | * Note: The spec clearly says that when tuning sequence | ||
2025 | * is being performed, the controller does not generate | ||
2026 | * interrupts other than Buffer Read Ready interrupt. But | ||
2027 | * to make sure we don't hit a controller bug, we _only_ | ||
2028 | * enable Buffer Read Ready interrupt here. | ||
2029 | */ | ||
2030 | sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); | ||
2031 | sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); | ||
2032 | 2131 | ||
2033 | /* | 2132 | /* |
2034 | * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number | 2133 | * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number |
2035 | * of loops reaches 40 times. | 2134 | * of loops reaches 40 times. |
2036 | */ | 2135 | */ |
2037 | do { | 2136 | do { |
2038 | struct mmc_command cmd = {0}; | ||
2039 | struct mmc_request mrq = {NULL}; | ||
2040 | |||
2041 | cmd.opcode = opcode; | ||
2042 | cmd.arg = 0; | ||
2043 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | ||
2044 | cmd.retries = 0; | ||
2045 | cmd.data = NULL; | ||
2046 | cmd.mrq = &mrq; | ||
2047 | cmd.error = 0; | ||
2048 | |||
2049 | if (tuning_loop_counter-- == 0) | 2137 | if (tuning_loop_counter-- == 0) |
2050 | break; | 2138 | break; |
2051 | 2139 | ||
2052 | mrq.cmd = &cmd; | 2140 | sdhci_send_tuning(host, opcode, flags); |
2053 | |||
2054 | /* | ||
2055 | * In response to CMD19, the card sends 64 bytes of tuning | ||
2056 | * block to the Host Controller. So we set the block size | ||
2057 | * to 64 here. | ||
2058 | */ | ||
2059 | if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200) { | ||
2060 | if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) | ||
2061 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128), | ||
2062 | SDHCI_BLOCK_SIZE); | ||
2063 | else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) | ||
2064 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), | ||
2065 | SDHCI_BLOCK_SIZE); | ||
2066 | } else { | ||
2067 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), | ||
2068 | SDHCI_BLOCK_SIZE); | ||
2069 | } | ||
2070 | |||
2071 | /* | ||
2072 | * The tuning block is sent by the card to the host controller. | ||
2073 | * So we set the TRNS_READ bit in the Transfer Mode register. | ||
2074 | * This also takes care of setting DMA Enable and Multi Block | ||
2075 | * Select in the same register to 0. | ||
2076 | */ | ||
2077 | sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); | ||
2078 | |||
2079 | sdhci_send_command(host, &cmd); | ||
2080 | |||
2081 | host->cmd = NULL; | ||
2082 | sdhci_del_timer(host, &mrq); | ||
2083 | |||
2084 | spin_unlock_irqrestore(&host->lock, flags); | ||
2085 | /* Wait for Buffer Read Ready interrupt */ | ||
2086 | wait_event_timeout(host->buf_ready_int, | ||
2087 | (host->tuning_done == 1), | ||
2088 | msecs_to_jiffies(50)); | ||
2089 | spin_lock_irqsave(&host->lock, flags); | ||
2090 | 2141 | ||
2091 | if (!host->tuning_done) { | 2142 | if (!host->tuning_done) { |
2092 | pr_info(DRIVER_NAME ": Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock\n"); | 2143 | pr_info(DRIVER_NAME ": Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock\n"); |
2093 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 2144 | sdhci_abort_tuning(host, opcode, flags); |
2094 | ctrl &= ~SDHCI_CTRL_TUNED_CLK; | ||
2095 | ctrl &= ~SDHCI_CTRL_EXEC_TUNING; | ||
2096 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
2097 | |||
2098 | sdhci_do_reset(host, SDHCI_RESET_CMD); | ||
2099 | sdhci_do_reset(host, SDHCI_RESET_DATA); | ||
2100 | |||
2101 | sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); | ||
2102 | sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); | ||
2103 | |||
2104 | spin_unlock_irqrestore(&host->lock, flags); | ||
2105 | mmc_abort_tuning(mmc, opcode); | ||
2106 | spin_lock_irqsave(&host->lock, flags); | ||
2107 | |||
2108 | goto out; | 2145 | goto out; |
2109 | } | 2146 | } |
2110 | 2147 | ||
2111 | host->tuning_done = 0; | ||
2112 | |||
2113 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 2148 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
2114 | 2149 | ||
2115 | /* eMMC spec does not require a delay between tuning cycles */ | 2150 | /* eMMC spec does not require a delay between tuning cycles */ |
@@ -2121,18 +2156,15 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
2121 | * The Host Driver has exhausted the maximum number of loops allowed, | 2156 | * The Host Driver has exhausted the maximum number of loops allowed, |
2122 | * so use fixed sampling frequency. | 2157 | * so use fixed sampling frequency. |
2123 | */ | 2158 | */ |
2124 | if (tuning_loop_counter < 0) { | 2159 | if (tuning_loop_counter < 0) |
2125 | ctrl &= ~SDHCI_CTRL_TUNED_CLK; | 2160 | sdhci_reset_tuning(host); |
2126 | ctrl &= ~SDHCI_CTRL_EXEC_TUNING; | 2161 | |
2127 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | 2162 | if (tuning_loop_counter < 0 || !(ctrl & SDHCI_CTRL_TUNED_CLK)) |
2128 | } | ||
2129 | if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) | ||
2130 | pr_info(DRIVER_NAME ": Tuning procedure failed, falling back to fixed sampling clock\n"); | 2163 | pr_info(DRIVER_NAME ": Tuning procedure failed, falling back to fixed sampling clock\n"); |
2131 | out: | 2164 | out: |
2132 | host->mmc->retune_period = tuning_count; | 2165 | host->mmc->retune_period = tuning_count; |
2133 | 2166 | ||
2134 | sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); | 2167 | sdhci_end_tuning(host); |
2135 | sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); | ||
2136 | out_unlock: | 2168 | out_unlock: |
2137 | spin_unlock_irqrestore(&host->lock, flags); | 2169 | spin_unlock_irqrestore(&host->lock, flags); |
2138 | return err; | 2170 | return err; |