12af7dd8bSVictor Shih // SPDX-License-Identifier: GPL-2.0-or-later 22af7dd8bSVictor Shih /* 32af7dd8bSVictor Shih * linux/drivers/mmc/host/sdhci_uhs2.c - Secure Digital Host Controller 42af7dd8bSVictor Shih * Interface driver 52af7dd8bSVictor Shih * 62af7dd8bSVictor Shih * Copyright (C) 2014 Intel Corp, All Rights Reserved. 72af7dd8bSVictor Shih * Copyright (C) 2020 Genesys Logic, Inc. 82af7dd8bSVictor Shih * Authors: Ben Chuang <ben.chuang@genesyslogic.com.tw> 92af7dd8bSVictor Shih * Copyright (C) 2020 Linaro Limited 102af7dd8bSVictor Shih * Author: AKASHI Takahiro <takahiro.akashi@linaro.org> 112af7dd8bSVictor Shih */ 122af7dd8bSVictor Shih 139b1c779dSVictor Shih #include <linux/delay.h> 142af7dd8bSVictor Shih #include <linux/module.h> 159b1c779dSVictor Shih #include <linux/iopoll.h> 167e5b19f3SVictor Shih #include <linux/bitfield.h> 1706a0d072SVictor Shih #include <linux/regulator/consumer.h> 189cbb2358SVictor Shih #include <linux/mmc/mmc.h> 199cbb2358SVictor Shih #include <linux/mmc/host.h> 202af7dd8bSVictor Shih 212af7dd8bSVictor Shih #include "sdhci.h" 222af7dd8bSVictor Shih #include "sdhci-uhs2.h" 232af7dd8bSVictor Shih 242af7dd8bSVictor Shih #define DRIVER_NAME "sdhci_uhs2" 252af7dd8bSVictor Shih #define DBG(f, x...) \ 262af7dd8bSVictor Shih pr_debug(DRIVER_NAME " [%s()]: " f, __func__, ## x) 270f8186f1SVictor Shih #define SDHCI_UHS2_DUMP(f, x...) \ 280f8186f1SVictor Shih pr_err("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x) 290f8186f1SVictor Shih 309b1c779dSVictor Shih #define UHS2_RESET_TIMEOUT_100MS 100000 314f412f79SVictor Shih #define UHS2_CHECK_DORMANT_TIMEOUT_100MS 100000 324f412f79SVictor Shih #define UHS2_INTERFACE_DETECT_TIMEOUT_100MS 100000 334f412f79SVictor Shih #define UHS2_LANE_SYNC_TIMEOUT_150MS 150000 349b1c779dSVictor Shih 359cbb2358SVictor Shih #define UHS2_ARG_IOADR_MASK 0xfff 369cbb2358SVictor Shih 370f8186f1SVictor Shih void sdhci_uhs2_dump_regs(struct sdhci_host *host) 380f8186f1SVictor Shih { 390f8186f1SVictor Shih if (!(mmc_card_uhs2(host->mmc))) 400f8186f1SVictor Shih return; 410f8186f1SVictor Shih 420f8186f1SVictor Shih SDHCI_UHS2_DUMP("==================== UHS2 ==================\n"); 430f8186f1SVictor Shih SDHCI_UHS2_DUMP("Blk Size: 0x%08x | Blk Cnt: 0x%08x\n", 440f8186f1SVictor Shih sdhci_readw(host, SDHCI_UHS2_BLOCK_SIZE), 450f8186f1SVictor Shih sdhci_readl(host, SDHCI_UHS2_BLOCK_COUNT)); 460f8186f1SVictor Shih SDHCI_UHS2_DUMP("Cmd: 0x%08x | Trn mode: 0x%08x\n", 470f8186f1SVictor Shih sdhci_readw(host, SDHCI_UHS2_CMD), 480f8186f1SVictor Shih sdhci_readw(host, SDHCI_UHS2_TRANS_MODE)); 490f8186f1SVictor Shih SDHCI_UHS2_DUMP("Int Stat: 0x%08x | Dev Sel : 0x%08x\n", 500f8186f1SVictor Shih sdhci_readw(host, SDHCI_UHS2_DEV_INT_STATUS), 510f8186f1SVictor Shih sdhci_readb(host, SDHCI_UHS2_DEV_SELECT)); 520f8186f1SVictor Shih SDHCI_UHS2_DUMP("Dev Int Code: 0x%08x\n", 530f8186f1SVictor Shih sdhci_readb(host, SDHCI_UHS2_DEV_INT_CODE)); 540f8186f1SVictor Shih SDHCI_UHS2_DUMP("Reset: 0x%08x | Timer: 0x%08x\n", 550f8186f1SVictor Shih sdhci_readw(host, SDHCI_UHS2_SW_RESET), 560f8186f1SVictor Shih sdhci_readw(host, SDHCI_UHS2_TIMER_CTRL)); 570f8186f1SVictor Shih SDHCI_UHS2_DUMP("ErrInt: 0x%08x | ErrIntEn: 0x%08x\n", 580f8186f1SVictor Shih sdhci_readl(host, SDHCI_UHS2_INT_STATUS), 590f8186f1SVictor Shih sdhci_readl(host, SDHCI_UHS2_INT_STATUS_ENABLE)); 600f8186f1SVictor Shih SDHCI_UHS2_DUMP("ErrSigEn: 0x%08x\n", 610f8186f1SVictor Shih sdhci_readl(host, SDHCI_UHS2_INT_SIGNAL_ENABLE)); 620f8186f1SVictor Shih } 630f8186f1SVictor Shih EXPORT_SYMBOL_GPL(sdhci_uhs2_dump_regs); 642af7dd8bSVictor Shih 652af7dd8bSVictor Shih /*****************************************************************************\ 662af7dd8bSVictor Shih * * 679b1c779dSVictor Shih * Low level functions * 689b1c779dSVictor Shih * * 699b1c779dSVictor Shih \*****************************************************************************/ 709b1c779dSVictor Shih 719cbb2358SVictor Shih static inline u16 uhs2_dev_cmd(struct mmc_command *cmd) 729cbb2358SVictor Shih { 73*dd92de9fSVictor Shih return be16_to_cpu((__force __be16)cmd->uhs2_cmd->arg) & UHS2_ARG_IOADR_MASK; 749cbb2358SVictor Shih } 759cbb2358SVictor Shih 766eb2c8e1SVictor Shih static inline int mmc_opt_regulator_set_ocr(struct mmc_host *mmc, 776eb2c8e1SVictor Shih struct regulator *supply, 786eb2c8e1SVictor Shih unsigned short vdd_bit) 796eb2c8e1SVictor Shih { 806eb2c8e1SVictor Shih return IS_ERR_OR_NULL(supply) ? 0 : mmc_regulator_set_ocr(mmc, supply, vdd_bit); 816eb2c8e1SVictor Shih } 826eb2c8e1SVictor Shih 839b1c779dSVictor Shih /** 849b1c779dSVictor Shih * sdhci_uhs2_reset - invoke SW reset 859b1c779dSVictor Shih * @host: SDHCI host 869b1c779dSVictor Shih * @mask: Control mask 879b1c779dSVictor Shih * 889b1c779dSVictor Shih * Invoke SW reset, depending on a bit in @mask and wait for completion. 899b1c779dSVictor Shih */ 909b1c779dSVictor Shih void sdhci_uhs2_reset(struct sdhci_host *host, u16 mask) 919b1c779dSVictor Shih { 929b1c779dSVictor Shih u32 val; 939b1c779dSVictor Shih 949b1c779dSVictor Shih sdhci_writew(host, mask, SDHCI_UHS2_SW_RESET); 959b1c779dSVictor Shih 969b1c779dSVictor Shih if (mask & SDHCI_UHS2_SW_RESET_FULL) 979b1c779dSVictor Shih host->clock = 0; 989b1c779dSVictor Shih 999b1c779dSVictor Shih /* hw clears the bit when it's done */ 1009b1c779dSVictor Shih if (read_poll_timeout_atomic(sdhci_readw, val, !(val & mask), 10, 1019b1c779dSVictor Shih UHS2_RESET_TIMEOUT_100MS, true, host, SDHCI_UHS2_SW_RESET)) { 1029b1c779dSVictor Shih pr_warn("%s: %s: Reset 0x%x never completed. %s: clean reset bit.\n", __func__, 1039b1c779dSVictor Shih mmc_hostname(host->mmc), (int)mask, mmc_hostname(host->mmc)); 1049b1c779dSVictor Shih sdhci_writeb(host, 0, SDHCI_UHS2_SW_RESET); 1059b1c779dSVictor Shih return; 1069b1c779dSVictor Shih } 1079b1c779dSVictor Shih } 1089b1c779dSVictor Shih EXPORT_SYMBOL_GPL(sdhci_uhs2_reset); 1099b1c779dSVictor Shih 110fca267f0SVictor Shih static void sdhci_uhs2_reset_cmd_data(struct sdhci_host *host) 111fca267f0SVictor Shih { 112fca267f0SVictor Shih sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 113fca267f0SVictor Shih 114fca267f0SVictor Shih if (host->mmc->uhs2_sd_tran) { 115fca267f0SVictor Shih sdhci_uhs2_reset(host, SDHCI_UHS2_SW_RESET_SD); 116fca267f0SVictor Shih 117fca267f0SVictor Shih sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 118fca267f0SVictor Shih sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 119fca267f0SVictor Shih sdhci_uhs2_clear_set_irqs(host, SDHCI_INT_ALL_MASK, SDHCI_UHS2_INT_ERROR_MASK); 120fca267f0SVictor Shih } 121fca267f0SVictor Shih } 122fca267f0SVictor Shih 1236eb2c8e1SVictor Shih void sdhci_uhs2_set_power(struct sdhci_host *host, unsigned char mode, unsigned short vdd) 1246eb2c8e1SVictor Shih { 1256eb2c8e1SVictor Shih struct mmc_host *mmc = host->mmc; 1266eb2c8e1SVictor Shih u8 pwr = 0; 1276eb2c8e1SVictor Shih 1286eb2c8e1SVictor Shih if (mode != MMC_POWER_OFF) { 1296eb2c8e1SVictor Shih pwr = sdhci_get_vdd_value(vdd); 1306eb2c8e1SVictor Shih if (!pwr) 1316eb2c8e1SVictor Shih WARN(1, "%s: Invalid vdd %#x\n", 1326eb2c8e1SVictor Shih mmc_hostname(host->mmc), vdd); 1336eb2c8e1SVictor Shih pwr |= SDHCI_VDD2_POWER_180; 1346eb2c8e1SVictor Shih } 1356eb2c8e1SVictor Shih 1366eb2c8e1SVictor Shih if (host->pwr == pwr) 1376eb2c8e1SVictor Shih return; 1386eb2c8e1SVictor Shih host->pwr = pwr; 1396eb2c8e1SVictor Shih 1406eb2c8e1SVictor Shih if (pwr == 0) { 1416eb2c8e1SVictor Shih sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 1426eb2c8e1SVictor Shih 1436eb2c8e1SVictor Shih mmc_opt_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); 1446eb2c8e1SVictor Shih mmc_regulator_set_vqmmc2(mmc, &mmc->ios); 1456eb2c8e1SVictor Shih } else { 1466eb2c8e1SVictor Shih mmc_opt_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); 1476eb2c8e1SVictor Shih /* support 1.8v only for now */ 1486eb2c8e1SVictor Shih mmc_regulator_set_vqmmc2(mmc, &mmc->ios); 1496eb2c8e1SVictor Shih 1506eb2c8e1SVictor Shih /* Clear the power reg before setting a new value */ 1516eb2c8e1SVictor Shih sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 1526eb2c8e1SVictor Shih 1536eb2c8e1SVictor Shih /* vdd first */ 1546eb2c8e1SVictor Shih pwr |= SDHCI_POWER_ON; 1556eb2c8e1SVictor Shih sdhci_writeb(host, pwr & 0xf, SDHCI_POWER_CONTROL); 1566eb2c8e1SVictor Shih mdelay(5); 1576eb2c8e1SVictor Shih 1586eb2c8e1SVictor Shih pwr |= SDHCI_VDD2_POWER_ON; 1596eb2c8e1SVictor Shih sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 1606eb2c8e1SVictor Shih mdelay(5); 1616eb2c8e1SVictor Shih } 1626eb2c8e1SVictor Shih } 1636eb2c8e1SVictor Shih EXPORT_SYMBOL_GPL(sdhci_uhs2_set_power); 1646eb2c8e1SVictor Shih 1657e5b19f3SVictor Shih static u8 sdhci_calc_timeout_uhs2(struct sdhci_host *host, u8 *cmd_res, u8 *dead_lock) 1667e5b19f3SVictor Shih { 1677e5b19f3SVictor Shih /* timeout in us */ 1687e5b19f3SVictor Shih unsigned int dead_lock_timeout = 1 * 1000 * 1000; 1697e5b19f3SVictor Shih unsigned int cmd_res_timeout = 5 * 1000; 1707e5b19f3SVictor Shih unsigned int current_timeout; 1717e5b19f3SVictor Shih u8 count; 1727e5b19f3SVictor Shih 1737e5b19f3SVictor Shih /* 1747e5b19f3SVictor Shih * Figure out needed cycles. 1757e5b19f3SVictor Shih * We do this in steps in order to fit inside a 32 bit int. 1767e5b19f3SVictor Shih * The first step is the minimum timeout, which will have a 1777e5b19f3SVictor Shih * minimum resolution of 6 bits: 1787e5b19f3SVictor Shih * (1) 2^13*1000 > 2^22, 1797e5b19f3SVictor Shih * (2) host->timeout_clk < 2^16 1807e5b19f3SVictor Shih * => 1817e5b19f3SVictor Shih * (1) / (2) > 2^6 1827e5b19f3SVictor Shih */ 1837e5b19f3SVictor Shih count = 0; 1847e5b19f3SVictor Shih current_timeout = (1 << 13) * 1000 / host->timeout_clk; 1857e5b19f3SVictor Shih while (current_timeout < cmd_res_timeout) { 1867e5b19f3SVictor Shih count++; 1877e5b19f3SVictor Shih current_timeout <<= 1; 1887e5b19f3SVictor Shih if (count >= 0xF) 1897e5b19f3SVictor Shih break; 1907e5b19f3SVictor Shih } 1917e5b19f3SVictor Shih 1927e5b19f3SVictor Shih if (count >= 0xF) { 1937e5b19f3SVictor Shih DBG("%s: Too large timeout 0x%x requested for CMD_RES!\n", 1947e5b19f3SVictor Shih mmc_hostname(host->mmc), count); 1957e5b19f3SVictor Shih count = 0xE; 1967e5b19f3SVictor Shih } 1977e5b19f3SVictor Shih *cmd_res = count; 1987e5b19f3SVictor Shih 1997e5b19f3SVictor Shih count = 0; 2007e5b19f3SVictor Shih current_timeout = (1 << 13) * 1000 / host->timeout_clk; 2017e5b19f3SVictor Shih while (current_timeout < dead_lock_timeout) { 2027e5b19f3SVictor Shih count++; 2037e5b19f3SVictor Shih current_timeout <<= 1; 2047e5b19f3SVictor Shih if (count >= 0xF) 2057e5b19f3SVictor Shih break; 2067e5b19f3SVictor Shih } 2077e5b19f3SVictor Shih 2087e5b19f3SVictor Shih if (count >= 0xF) { 2097e5b19f3SVictor Shih DBG("%s: Too large timeout 0x%x requested for DEADLOCK!\n", 2107e5b19f3SVictor Shih mmc_hostname(host->mmc), count); 2117e5b19f3SVictor Shih count = 0xE; 2127e5b19f3SVictor Shih } 2137e5b19f3SVictor Shih *dead_lock = count; 2147e5b19f3SVictor Shih 2157e5b19f3SVictor Shih return count; 2167e5b19f3SVictor Shih } 2177e5b19f3SVictor Shih 2187e5b19f3SVictor Shih static void __sdhci_uhs2_set_timeout(struct sdhci_host *host) 2197e5b19f3SVictor Shih { 2207e5b19f3SVictor Shih u8 cmd_res, dead_lock; 2217e5b19f3SVictor Shih 2227e5b19f3SVictor Shih sdhci_calc_timeout_uhs2(host, &cmd_res, &dead_lock); 2237e5b19f3SVictor Shih cmd_res |= FIELD_PREP(SDHCI_UHS2_TIMER_CTRL_DEADLOCK_MASK, dead_lock); 2247e5b19f3SVictor Shih sdhci_writeb(host, cmd_res, SDHCI_UHS2_TIMER_CTRL); 2257e5b19f3SVictor Shih } 2267e5b19f3SVictor Shih 2277e5b19f3SVictor Shih void sdhci_uhs2_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) 2287e5b19f3SVictor Shih { 2297e5b19f3SVictor Shih __sdhci_set_timeout(host, cmd); 2307e5b19f3SVictor Shih 2317e5b19f3SVictor Shih if (mmc_card_uhs2(host->mmc)) 2327e5b19f3SVictor Shih __sdhci_uhs2_set_timeout(host); 2337e5b19f3SVictor Shih } 2347e5b19f3SVictor Shih EXPORT_SYMBOL_GPL(sdhci_uhs2_set_timeout); 2357e5b19f3SVictor Shih 23610c8298aSVictor Shih /** 23710c8298aSVictor Shih * sdhci_uhs2_clear_set_irqs - set Error Interrupt Status Enable register 23810c8298aSVictor Shih * @host: SDHCI host 23910c8298aSVictor Shih * @clear: bit-wise clear mask 24010c8298aSVictor Shih * @set: bit-wise set mask 24110c8298aSVictor Shih * 24210c8298aSVictor Shih * Set/unset bits in UHS-II Error Interrupt Status Enable register 24310c8298aSVictor Shih */ 24410c8298aSVictor Shih void sdhci_uhs2_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set) 24510c8298aSVictor Shih { 24610c8298aSVictor Shih u32 ier; 24710c8298aSVictor Shih 24810c8298aSVictor Shih ier = sdhci_readl(host, SDHCI_UHS2_INT_STATUS_ENABLE); 24910c8298aSVictor Shih ier &= ~clear; 25010c8298aSVictor Shih ier |= set; 25110c8298aSVictor Shih sdhci_writel(host, ier, SDHCI_UHS2_INT_STATUS_ENABLE); 25210c8298aSVictor Shih sdhci_writel(host, ier, SDHCI_UHS2_INT_SIGNAL_ENABLE); 25310c8298aSVictor Shih } 25410c8298aSVictor Shih EXPORT_SYMBOL_GPL(sdhci_uhs2_clear_set_irqs); 25510c8298aSVictor Shih 25610c8298aSVictor Shih static void __sdhci_uhs2_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 25710c8298aSVictor Shih { 25810c8298aSVictor Shih struct sdhci_host *host = mmc_priv(mmc); 25910c8298aSVictor Shih u8 cmd_res, dead_lock; 26010c8298aSVictor Shih u16 ctrl_2; 26110c8298aSVictor Shih 26210c8298aSVictor Shih /* UHS2 Timeout Control */ 26310c8298aSVictor Shih sdhci_calc_timeout_uhs2(host, &cmd_res, &dead_lock); 26410c8298aSVictor Shih 26510c8298aSVictor Shih /* change to use calculate value */ 26610c8298aSVictor Shih cmd_res |= FIELD_PREP(SDHCI_UHS2_TIMER_CTRL_DEADLOCK_MASK, dead_lock); 26710c8298aSVictor Shih 26810c8298aSVictor Shih sdhci_uhs2_clear_set_irqs(host, 26910c8298aSVictor Shih SDHCI_UHS2_INT_CMD_TIMEOUT | 27010c8298aSVictor Shih SDHCI_UHS2_INT_DEADLOCK_TIMEOUT, 27110c8298aSVictor Shih 0); 27210c8298aSVictor Shih sdhci_writeb(host, cmd_res, SDHCI_UHS2_TIMER_CTRL); 27310c8298aSVictor Shih sdhci_uhs2_clear_set_irqs(host, 0, 27410c8298aSVictor Shih SDHCI_UHS2_INT_CMD_TIMEOUT | 27510c8298aSVictor Shih SDHCI_UHS2_INT_DEADLOCK_TIMEOUT); 27610c8298aSVictor Shih 27710c8298aSVictor Shih /* UHS2 timing. Note, UHS2 timing is disabled when powering off */ 27810c8298aSVictor Shih ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 27910c8298aSVictor Shih if (ios->power_mode != MMC_POWER_OFF && 28010c8298aSVictor Shih (ios->timing == MMC_TIMING_UHS2_SPEED_A || 28110c8298aSVictor Shih ios->timing == MMC_TIMING_UHS2_SPEED_A_HD || 28210c8298aSVictor Shih ios->timing == MMC_TIMING_UHS2_SPEED_B || 28310c8298aSVictor Shih ios->timing == MMC_TIMING_UHS2_SPEED_B_HD)) 28410c8298aSVictor Shih ctrl_2 |= SDHCI_CTRL_UHS2 | SDHCI_CTRL_UHS2_ENABLE; 28510c8298aSVictor Shih else 28610c8298aSVictor Shih ctrl_2 &= ~(SDHCI_CTRL_UHS2 | SDHCI_CTRL_UHS2_ENABLE); 28710c8298aSVictor Shih sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 28810c8298aSVictor Shih host->timing = ios->timing; 28910c8298aSVictor Shih 29010c8298aSVictor Shih if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) 29110c8298aSVictor Shih sdhci_enable_preset_value(host, true); 29210c8298aSVictor Shih 29310c8298aSVictor Shih if (host->ops->set_power) 29410c8298aSVictor Shih host->ops->set_power(host, ios->power_mode, ios->vdd); 29510c8298aSVictor Shih else 29610c8298aSVictor Shih sdhci_uhs2_set_power(host, ios->power_mode, ios->vdd); 29710c8298aSVictor Shih 29810c8298aSVictor Shih sdhci_set_clock(host, host->clock); 29910c8298aSVictor Shih } 30010c8298aSVictor Shih 30110c8298aSVictor Shih static int sdhci_uhs2_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 30210c8298aSVictor Shih { 30310c8298aSVictor Shih struct sdhci_host *host = mmc_priv(mmc); 30410c8298aSVictor Shih 30510c8298aSVictor Shih pr_debug("%s: clock %uHz powermode %u Vdd %u timing %u\n", 30610c8298aSVictor Shih mmc_hostname(mmc), ios->clock, ios->power_mode, ios->vdd, ios->timing); 30710c8298aSVictor Shih 30810c8298aSVictor Shih if (!mmc_card_uhs2(mmc)) { 30910c8298aSVictor Shih sdhci_set_ios(mmc, ios); 31010c8298aSVictor Shih return 0; 31110c8298aSVictor Shih } 31210c8298aSVictor Shih 31310c8298aSVictor Shih if (ios->power_mode == MMC_POWER_UNDEFINED) 31410c8298aSVictor Shih return 0; 31510c8298aSVictor Shih 31610c8298aSVictor Shih if (host->flags & SDHCI_DEVICE_DEAD) { 31710c8298aSVictor Shih if (ios->power_mode == MMC_POWER_OFF) { 31810c8298aSVictor Shih mmc_opt_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); 31910c8298aSVictor Shih mmc_regulator_set_vqmmc2(mmc, ios); 32010c8298aSVictor Shih } 32110c8298aSVictor Shih return -1; 32210c8298aSVictor Shih } 32310c8298aSVictor Shih 32410c8298aSVictor Shih sdhci_set_ios_common(mmc, ios); 32510c8298aSVictor Shih 32610c8298aSVictor Shih __sdhci_uhs2_set_ios(mmc, ios); 32710c8298aSVictor Shih 32810c8298aSVictor Shih return 0; 32910c8298aSVictor Shih } 33010c8298aSVictor Shih 3314f412f79SVictor Shih static int sdhci_uhs2_interface_detect(struct sdhci_host *host) 3324f412f79SVictor Shih { 3334f412f79SVictor Shih u32 val; 3344f412f79SVictor Shih 3354f412f79SVictor Shih if (read_poll_timeout(sdhci_readl, val, (val & SDHCI_UHS2_IF_DETECT), 3364f412f79SVictor Shih 100, UHS2_INTERFACE_DETECT_TIMEOUT_100MS, true, 3374f412f79SVictor Shih host, SDHCI_PRESENT_STATE)) { 3384f412f79SVictor Shih pr_warn("%s: not detect UHS2 interface in 100ms.\n", mmc_hostname(host->mmc)); 3394f412f79SVictor Shih sdhci_dumpregs(host); 3404f412f79SVictor Shih return -EIO; 3414f412f79SVictor Shih } 3424f412f79SVictor Shih 3434f412f79SVictor Shih /* Enable UHS2 error interrupts */ 3444f412f79SVictor Shih sdhci_uhs2_clear_set_irqs(host, SDHCI_INT_ALL_MASK, SDHCI_UHS2_INT_ERROR_MASK); 3454f412f79SVictor Shih 3464f412f79SVictor Shih if (read_poll_timeout(sdhci_readl, val, (val & SDHCI_UHS2_LANE_SYNC), 3474f412f79SVictor Shih 100, UHS2_LANE_SYNC_TIMEOUT_150MS, true, host, SDHCI_PRESENT_STATE)) { 3484f412f79SVictor Shih pr_warn("%s: UHS2 Lane sync fail in 150ms.\n", mmc_hostname(host->mmc)); 3494f412f79SVictor Shih sdhci_dumpregs(host); 3504f412f79SVictor Shih return -EIO; 3514f412f79SVictor Shih } 3524f412f79SVictor Shih 3534f412f79SVictor Shih DBG("%s: UHS2 Lane synchronized in UHS2 mode, PHY is initialized.\n", 3544f412f79SVictor Shih mmc_hostname(host->mmc)); 3554f412f79SVictor Shih return 0; 3564f412f79SVictor Shih } 3574f412f79SVictor Shih 3584f412f79SVictor Shih static int sdhci_uhs2_init(struct sdhci_host *host) 3594f412f79SVictor Shih { 3604f412f79SVictor Shih u16 caps_ptr = 0; 3614f412f79SVictor Shih u32 caps_gen = 0; 3624f412f79SVictor Shih u32 caps_phy = 0; 3634f412f79SVictor Shih u32 caps_tran[2] = {0, 0}; 3644f412f79SVictor Shih struct mmc_host *mmc = host->mmc; 3654f412f79SVictor Shih 3664f412f79SVictor Shih caps_ptr = sdhci_readw(host, SDHCI_UHS2_CAPS_PTR); 3674f412f79SVictor Shih if (caps_ptr < 0x100 || caps_ptr > 0x1FF) { 3684f412f79SVictor Shih pr_err("%s: SDHCI_UHS2_CAPS_PTR(%d) is wrong.\n", 3694f412f79SVictor Shih mmc_hostname(mmc), caps_ptr); 3704f412f79SVictor Shih return -ENODEV; 3714f412f79SVictor Shih } 3724f412f79SVictor Shih caps_gen = sdhci_readl(host, caps_ptr + SDHCI_UHS2_CAPS_OFFSET); 3734f412f79SVictor Shih caps_phy = sdhci_readl(host, caps_ptr + SDHCI_UHS2_CAPS_PHY_OFFSET); 3744f412f79SVictor Shih caps_tran[0] = sdhci_readl(host, caps_ptr + SDHCI_UHS2_CAPS_TRAN_OFFSET); 3754f412f79SVictor Shih caps_tran[1] = sdhci_readl(host, caps_ptr + SDHCI_UHS2_CAPS_TRAN_1_OFFSET); 3764f412f79SVictor Shih 3774f412f79SVictor Shih /* General Caps */ 3784f412f79SVictor Shih mmc->uhs2_caps.dap = caps_gen & SDHCI_UHS2_CAPS_DAP_MASK; 3794f412f79SVictor Shih mmc->uhs2_caps.gap = FIELD_GET(SDHCI_UHS2_CAPS_GAP_MASK, caps_gen); 3804f412f79SVictor Shih mmc->uhs2_caps.n_lanes = FIELD_GET(SDHCI_UHS2_CAPS_LANE_MASK, caps_gen); 3814f412f79SVictor Shih mmc->uhs2_caps.addr64 = (caps_gen & SDHCI_UHS2_CAPS_ADDR_64) ? 1 : 0; 3824f412f79SVictor Shih mmc->uhs2_caps.card_type = FIELD_GET(SDHCI_UHS2_CAPS_DEV_TYPE_MASK, caps_gen); 3834f412f79SVictor Shih 3844f412f79SVictor Shih /* PHY Caps */ 3854f412f79SVictor Shih mmc->uhs2_caps.phy_rev = caps_phy & SDHCI_UHS2_CAPS_PHY_REV_MASK; 3864f412f79SVictor Shih mmc->uhs2_caps.speed_range = FIELD_GET(SDHCI_UHS2_CAPS_PHY_RANGE_MASK, caps_phy); 3874f412f79SVictor Shih mmc->uhs2_caps.n_lss_sync = FIELD_GET(SDHCI_UHS2_CAPS_PHY_N_LSS_SYN_MASK, caps_phy); 3884f412f79SVictor Shih mmc->uhs2_caps.n_lss_dir = FIELD_GET(SDHCI_UHS2_CAPS_PHY_N_LSS_DIR_MASK, caps_phy); 3894f412f79SVictor Shih if (mmc->uhs2_caps.n_lss_sync == 0) 3904f412f79SVictor Shih mmc->uhs2_caps.n_lss_sync = 16 << 2; 3914f412f79SVictor Shih else 3924f412f79SVictor Shih mmc->uhs2_caps.n_lss_sync <<= 2; 3934f412f79SVictor Shih if (mmc->uhs2_caps.n_lss_dir == 0) 3944f412f79SVictor Shih mmc->uhs2_caps.n_lss_dir = 16 << 3; 3954f412f79SVictor Shih else 3964f412f79SVictor Shih mmc->uhs2_caps.n_lss_dir <<= 3; 3974f412f79SVictor Shih 3984f412f79SVictor Shih /* LINK/TRAN Caps */ 3994f412f79SVictor Shih mmc->uhs2_caps.link_rev = caps_tran[0] & SDHCI_UHS2_CAPS_TRAN_LINK_REV_MASK; 4004f412f79SVictor Shih mmc->uhs2_caps.n_fcu = FIELD_GET(SDHCI_UHS2_CAPS_TRAN_N_FCU_MASK, caps_tran[0]); 4014f412f79SVictor Shih if (mmc->uhs2_caps.n_fcu == 0) 4024f412f79SVictor Shih mmc->uhs2_caps.n_fcu = 256; 4034f412f79SVictor Shih mmc->uhs2_caps.host_type = FIELD_GET(SDHCI_UHS2_CAPS_TRAN_HOST_TYPE_MASK, caps_tran[0]); 4044f412f79SVictor Shih mmc->uhs2_caps.maxblk_len = FIELD_GET(SDHCI_UHS2_CAPS_TRAN_BLK_LEN_MASK, caps_tran[0]); 4054f412f79SVictor Shih mmc->uhs2_caps.n_data_gap = caps_tran[1] & SDHCI_UHS2_CAPS_TRAN_1_N_DATA_GAP_MASK; 4064f412f79SVictor Shih 4074f412f79SVictor Shih return 0; 4084f412f79SVictor Shih } 4094f412f79SVictor Shih 4104f412f79SVictor Shih static int sdhci_uhs2_do_detect_init(struct mmc_host *mmc) 4114f412f79SVictor Shih { 4124f412f79SVictor Shih struct sdhci_host *host = mmc_priv(mmc); 4134f412f79SVictor Shih 4144f412f79SVictor Shih DBG("Begin do uhs2 detect init.\n"); 4154f412f79SVictor Shih 41654ef4b39SBen Chuang if (host->ops->uhs2_pre_detect_init) 417379e4dc5SBen Chuang host->ops->uhs2_pre_detect_init(host); 418379e4dc5SBen Chuang 4194f412f79SVictor Shih if (sdhci_uhs2_interface_detect(host)) { 4204f412f79SVictor Shih pr_warn("%s: cannot detect UHS2 interface.\n", mmc_hostname(host->mmc)); 4214f412f79SVictor Shih return -EIO; 4224f412f79SVictor Shih } 4234f412f79SVictor Shih 4244f412f79SVictor Shih if (sdhci_uhs2_init(host)) { 4254f412f79SVictor Shih pr_warn("%s: UHS2 init fail.\n", mmc_hostname(host->mmc)); 4264f412f79SVictor Shih return -EIO; 4274f412f79SVictor Shih } 4284f412f79SVictor Shih 4294f412f79SVictor Shih /* Init complete, do soft reset and enable UHS2 error irqs. */ 4304f412f79SVictor Shih sdhci_uhs2_reset(host, SDHCI_UHS2_SW_RESET_SD); 4314f412f79SVictor Shih sdhci_uhs2_clear_set_irqs(host, SDHCI_INT_ALL_MASK, SDHCI_UHS2_INT_ERROR_MASK); 4324f412f79SVictor Shih /* 4334f412f79SVictor Shih * N.B SDHCI_INT_ENABLE and SDHCI_SIGNAL_ENABLE was cleared 4344f412f79SVictor Shih * by SDHCI_UHS2_SW_RESET_SD 4354f412f79SVictor Shih */ 4364f412f79SVictor Shih sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 4374f412f79SVictor Shih sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 4384f412f79SVictor Shih 4394f412f79SVictor Shih return 0; 4404f412f79SVictor Shih } 4414f412f79SVictor Shih 4424f412f79SVictor Shih static int sdhci_uhs2_disable_clk(struct mmc_host *mmc) 4434f412f79SVictor Shih { 4444f412f79SVictor Shih struct sdhci_host *host = mmc_priv(mmc); 4454f412f79SVictor Shih u16 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 4464f412f79SVictor Shih 4474f412f79SVictor Shih clk &= ~SDHCI_CLOCK_CARD_EN; 4484f412f79SVictor Shih sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 4494f412f79SVictor Shih 4504f412f79SVictor Shih return 0; 4514f412f79SVictor Shih } 4524f412f79SVictor Shih 4534f412f79SVictor Shih static int sdhci_uhs2_enable_clk(struct mmc_host *mmc) 4544f412f79SVictor Shih { 4554f412f79SVictor Shih struct sdhci_host *host = mmc_priv(mmc); 4564f412f79SVictor Shih u16 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 4574f412f79SVictor Shih int timeout_us = 20000; /* 20ms */ 4584f412f79SVictor Shih u32 val; 4594f412f79SVictor Shih 4604f412f79SVictor Shih clk |= SDHCI_CLOCK_CARD_EN; 4614f412f79SVictor Shih sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 4624f412f79SVictor Shih 4634f412f79SVictor Shih if (read_poll_timeout(sdhci_readw, val, (val & SDHCI_CLOCK_INT_STABLE), 4644f412f79SVictor Shih 10, timeout_us, true, host, SDHCI_CLOCK_CONTROL)) { 4654f412f79SVictor Shih pr_err("%s: Internal clock never stabilised.\n", mmc_hostname(host->mmc)); 4664f412f79SVictor Shih sdhci_dumpregs(host); 4674f412f79SVictor Shih return -EIO; 4684f412f79SVictor Shih } 4694f412f79SVictor Shih return 0; 4704f412f79SVictor Shih } 4714f412f79SVictor Shih 4724f412f79SVictor Shih static void sdhci_uhs2_set_config(struct sdhci_host *host) 4734f412f79SVictor Shih { 4744f412f79SVictor Shih u32 value; 4754f412f79SVictor Shih u16 sdhci_uhs2_set_ptr = sdhci_readw(host, SDHCI_UHS2_SETTINGS_PTR); 4764f412f79SVictor Shih u16 sdhci_uhs2_gen_set_reg = sdhci_uhs2_set_ptr; 4774f412f79SVictor Shih u16 sdhci_uhs2_phy_set_reg = sdhci_uhs2_set_ptr + 4; 4784f412f79SVictor Shih u16 sdhci_uhs2_tran_set_reg = sdhci_uhs2_set_ptr + 8; 4794f412f79SVictor Shih u16 sdhci_uhs2_tran_set_1_reg = sdhci_uhs2_set_ptr + 12; 4804f412f79SVictor Shih 4814f412f79SVictor Shih /* Set Gen Settings */ 4824f412f79SVictor Shih value = FIELD_PREP(SDHCI_UHS2_GEN_SETTINGS_N_LANES_MASK, host->mmc->uhs2_caps.n_lanes_set); 4834f412f79SVictor Shih sdhci_writel(host, value, sdhci_uhs2_gen_set_reg); 4844f412f79SVictor Shih 4854f412f79SVictor Shih /* Set PHY Settings */ 4864f412f79SVictor Shih value = FIELD_PREP(SDHCI_UHS2_PHY_N_LSS_DIR_MASK, host->mmc->uhs2_caps.n_lss_dir_set) | 4874f412f79SVictor Shih FIELD_PREP(SDHCI_UHS2_PHY_N_LSS_SYN_MASK, host->mmc->uhs2_caps.n_lss_sync_set); 4884f412f79SVictor Shih if (host->mmc->ios.timing == MMC_TIMING_UHS2_SPEED_B || 4894f412f79SVictor Shih host->mmc->ios.timing == MMC_TIMING_UHS2_SPEED_B_HD) 4904f412f79SVictor Shih value |= SDHCI_UHS2_PHY_SET_SPEED_B; 4914f412f79SVictor Shih sdhci_writel(host, value, sdhci_uhs2_phy_set_reg); 4924f412f79SVictor Shih 4934f412f79SVictor Shih /* Set LINK-TRAN Settings */ 4944f412f79SVictor Shih value = FIELD_PREP(SDHCI_UHS2_TRAN_RETRY_CNT_MASK, host->mmc->uhs2_caps.max_retry_set) | 4954f412f79SVictor Shih FIELD_PREP(SDHCI_UHS2_TRAN_N_FCU_MASK, host->mmc->uhs2_caps.n_fcu_set); 4964f412f79SVictor Shih sdhci_writel(host, value, sdhci_uhs2_tran_set_reg); 4974f412f79SVictor Shih sdhci_writel(host, host->mmc->uhs2_caps.n_data_gap_set, sdhci_uhs2_tran_set_1_reg); 4984f412f79SVictor Shih } 4994f412f79SVictor Shih 5004f412f79SVictor Shih static int sdhci_uhs2_check_dormant(struct sdhci_host *host) 5014f412f79SVictor Shih { 5024f412f79SVictor Shih u32 val; 5034f412f79SVictor Shih 5044f412f79SVictor Shih if (read_poll_timeout(sdhci_readl, val, (val & SDHCI_UHS2_IN_DORMANT_STATE), 5054f412f79SVictor Shih 100, UHS2_CHECK_DORMANT_TIMEOUT_100MS, true, host, 5064f412f79SVictor Shih SDHCI_PRESENT_STATE)) { 5074f412f79SVictor Shih pr_warn("%s: UHS2 IN_DORMANT fail in 100ms.\n", mmc_hostname(host->mmc)); 5084f412f79SVictor Shih sdhci_dumpregs(host); 5094f412f79SVictor Shih return -EIO; 5104f412f79SVictor Shih } 5114f412f79SVictor Shih return 0; 5124f412f79SVictor Shih } 5134f412f79SVictor Shih 51410c8298aSVictor Shih static int sdhci_uhs2_control(struct mmc_host *mmc, enum sd_uhs2_operation op) 51510c8298aSVictor Shih { 51610c8298aSVictor Shih struct sdhci_host *host = mmc_priv(mmc); 51710c8298aSVictor Shih struct mmc_ios *ios = &mmc->ios; 51810c8298aSVictor Shih int err = 0; 51910c8298aSVictor Shih 52010c8298aSVictor Shih DBG("Begin uhs2 control, act %d.\n", op); 52110c8298aSVictor Shih 52210c8298aSVictor Shih switch (op) { 5234f412f79SVictor Shih case UHS2_PHY_INIT: 5244f412f79SVictor Shih err = sdhci_uhs2_do_detect_init(mmc); 5254f412f79SVictor Shih break; 5264f412f79SVictor Shih case UHS2_SET_CONFIG: 5274f412f79SVictor Shih sdhci_uhs2_set_config(host); 5284f412f79SVictor Shih break; 5294f412f79SVictor Shih case UHS2_ENABLE_INT: 5304f412f79SVictor Shih sdhci_uhs2_clear_set_irqs(host, 0, SDHCI_INT_CARD_INT); 5314f412f79SVictor Shih break; 5324f412f79SVictor Shih case UHS2_DISABLE_INT: 5334f412f79SVictor Shih sdhci_uhs2_clear_set_irqs(host, SDHCI_INT_CARD_INT, 0); 5344f412f79SVictor Shih break; 5354f412f79SVictor Shih case UHS2_CHECK_DORMANT: 5364f412f79SVictor Shih err = sdhci_uhs2_check_dormant(host); 5374f412f79SVictor Shih break; 5384f412f79SVictor Shih case UHS2_DISABLE_CLK: 5394f412f79SVictor Shih err = sdhci_uhs2_disable_clk(mmc); 5404f412f79SVictor Shih break; 5414f412f79SVictor Shih case UHS2_ENABLE_CLK: 5424f412f79SVictor Shih err = sdhci_uhs2_enable_clk(mmc); 5434f412f79SVictor Shih break; 54410c8298aSVictor Shih case UHS2_SET_IOS: 54510c8298aSVictor Shih err = sdhci_uhs2_set_ios(mmc, ios); 54610c8298aSVictor Shih break; 54710c8298aSVictor Shih default: 54810c8298aSVictor Shih pr_err("%s: input sd uhs2 operation %d is wrong!\n", 54910c8298aSVictor Shih mmc_hostname(host->mmc), op); 55010c8298aSVictor Shih err = -EIO; 55110c8298aSVictor Shih break; 55210c8298aSVictor Shih } 55310c8298aSVictor Shih 55410c8298aSVictor Shih return err; 55510c8298aSVictor Shih } 55610c8298aSVictor Shih 5579b1c779dSVictor Shih /*****************************************************************************\ 5589b1c779dSVictor Shih * * 5599cbb2358SVictor Shih * Core functions * 5609cbb2358SVictor Shih * * 5619cbb2358SVictor Shih \*****************************************************************************/ 5629cbb2358SVictor Shih 5639cbb2358SVictor Shih static void sdhci_uhs2_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) 5649cbb2358SVictor Shih { 5659cbb2358SVictor Shih struct mmc_data *data = cmd->data; 5669cbb2358SVictor Shih 5679cbb2358SVictor Shih sdhci_initialize_data(host, data); 5689cbb2358SVictor Shih 5699cbb2358SVictor Shih sdhci_prepare_dma(host, data); 5709cbb2358SVictor Shih 5719cbb2358SVictor Shih sdhci_writew(host, data->blksz, SDHCI_UHS2_BLOCK_SIZE); 5729cbb2358SVictor Shih sdhci_writew(host, data->blocks, SDHCI_UHS2_BLOCK_COUNT); 5739cbb2358SVictor Shih } 5749cbb2358SVictor Shih 5759cbb2358SVictor Shih static void sdhci_uhs2_finish_data(struct sdhci_host *host) 5769cbb2358SVictor Shih { 5779cbb2358SVictor Shih struct mmc_data *data = host->data; 5789cbb2358SVictor Shih 5799cbb2358SVictor Shih __sdhci_finish_data_common(host, true); 5809cbb2358SVictor Shih 5819cbb2358SVictor Shih __sdhci_finish_mrq(host, data->mrq); 5829cbb2358SVictor Shih } 5839cbb2358SVictor Shih 5849cbb2358SVictor Shih static void sdhci_uhs2_set_transfer_mode(struct sdhci_host *host, struct mmc_command *cmd) 5859cbb2358SVictor Shih { 5869cbb2358SVictor Shih u16 mode; 5879cbb2358SVictor Shih struct mmc_data *data = cmd->data; 5889cbb2358SVictor Shih 5899cbb2358SVictor Shih if (!data) { 5909cbb2358SVictor Shih /* clear Auto CMD settings for no data CMDs */ 5919cbb2358SVictor Shih if (uhs2_dev_cmd(cmd) == UHS2_DEV_CMD_TRANS_ABORT) { 5929cbb2358SVictor Shih mode = 0; 5939cbb2358SVictor Shih } else { 5949cbb2358SVictor Shih mode = sdhci_readw(host, SDHCI_UHS2_TRANS_MODE); 5959cbb2358SVictor Shih if (cmd->opcode == MMC_STOP_TRANSMISSION || cmd->opcode == MMC_ERASE) 5969cbb2358SVictor Shih mode |= SDHCI_UHS2_TRNS_WAIT_EBSY; 5979cbb2358SVictor Shih else 5989cbb2358SVictor Shih /* send status mode */ 5999cbb2358SVictor Shih if (cmd->opcode == MMC_SEND_STATUS) 6009cbb2358SVictor Shih mode = 0; 6019cbb2358SVictor Shih } 6029cbb2358SVictor Shih 6039cbb2358SVictor Shih DBG("UHS2 no data trans mode is 0x%x.\n", mode); 6049cbb2358SVictor Shih 6059cbb2358SVictor Shih sdhci_writew(host, mode, SDHCI_UHS2_TRANS_MODE); 6069cbb2358SVictor Shih return; 6079cbb2358SVictor Shih } 6089cbb2358SVictor Shih 6099cbb2358SVictor Shih WARN_ON(!host->data); 6109cbb2358SVictor Shih 6119cbb2358SVictor Shih mode = SDHCI_UHS2_TRNS_BLK_CNT_EN | SDHCI_UHS2_TRNS_WAIT_EBSY; 6129cbb2358SVictor Shih if (data->flags & MMC_DATA_WRITE) 6139cbb2358SVictor Shih mode |= SDHCI_UHS2_TRNS_DATA_TRNS_WRT; 6149cbb2358SVictor Shih 6159cbb2358SVictor Shih if (data->blocks == 1 && 6169cbb2358SVictor Shih data->blksz != 512 && 6179cbb2358SVictor Shih cmd->opcode != MMC_READ_SINGLE_BLOCK && 6189cbb2358SVictor Shih cmd->opcode != MMC_WRITE_BLOCK) { 6199cbb2358SVictor Shih mode &= ~SDHCI_UHS2_TRNS_BLK_CNT_EN; 6209cbb2358SVictor Shih mode |= SDHCI_UHS2_TRNS_BLK_BYTE_MODE; 6219cbb2358SVictor Shih } 6229cbb2358SVictor Shih 6239cbb2358SVictor Shih if (host->flags & SDHCI_REQ_USE_DMA) 6249cbb2358SVictor Shih mode |= SDHCI_UHS2_TRNS_DMA; 6259cbb2358SVictor Shih 6269cbb2358SVictor Shih if (cmd->uhs2_cmd->tmode_half_duplex) 6279cbb2358SVictor Shih mode |= SDHCI_UHS2_TRNS_2L_HD; 6289cbb2358SVictor Shih 6299cbb2358SVictor Shih sdhci_writew(host, mode, SDHCI_UHS2_TRANS_MODE); 6309cbb2358SVictor Shih 6319cbb2358SVictor Shih DBG("UHS2 trans mode is 0x%x.\n", mode); 6329cbb2358SVictor Shih } 6339cbb2358SVictor Shih 6349cbb2358SVictor Shih static void __sdhci_uhs2_send_command(struct sdhci_host *host, struct mmc_command *cmd) 6359cbb2358SVictor Shih { 6369cbb2358SVictor Shih int i, j; 6379cbb2358SVictor Shih int cmd_reg; 6389cbb2358SVictor Shih 6399cbb2358SVictor Shih i = 0; 6409cbb2358SVictor Shih sdhci_writel(host, 6419cbb2358SVictor Shih ((u32)cmd->uhs2_cmd->arg << 16) | 6429cbb2358SVictor Shih (u32)cmd->uhs2_cmd->header, 6439cbb2358SVictor Shih SDHCI_UHS2_CMD_PACKET + i); 6449cbb2358SVictor Shih i += 4; 6459cbb2358SVictor Shih 6469cbb2358SVictor Shih /* 6479cbb2358SVictor Shih * Per spec, payload (config) should be MSB before sending out. 6489cbb2358SVictor Shih * But we don't need convert here because had set payload as 6499cbb2358SVictor Shih * MSB when preparing config read/write commands. 6509cbb2358SVictor Shih */ 6519cbb2358SVictor Shih for (j = 0; j < cmd->uhs2_cmd->payload_len / sizeof(u32); j++) { 652259d262eSVictor Shih sdhci_writel(host, *(__force u32 *)(cmd->uhs2_cmd->payload + j), 653259d262eSVictor Shih SDHCI_UHS2_CMD_PACKET + i); 6549cbb2358SVictor Shih i += 4; 6559cbb2358SVictor Shih } 6569cbb2358SVictor Shih 6579cbb2358SVictor Shih for ( ; i < SDHCI_UHS2_CMD_PACK_MAX_LEN; i += 4) 6589cbb2358SVictor Shih sdhci_writel(host, 0, SDHCI_UHS2_CMD_PACKET + i); 6599cbb2358SVictor Shih 6609cbb2358SVictor Shih DBG("UHS2 CMD packet_len = %d.\n", cmd->uhs2_cmd->packet_len); 6619cbb2358SVictor Shih for (i = 0; i < cmd->uhs2_cmd->packet_len; i++) 6629cbb2358SVictor Shih DBG("UHS2 CMD_PACKET[%d] = 0x%x.\n", i, 6639cbb2358SVictor Shih sdhci_readb(host, SDHCI_UHS2_CMD_PACKET + i)); 6649cbb2358SVictor Shih 6659cbb2358SVictor Shih cmd_reg = FIELD_PREP(SDHCI_UHS2_CMD_PACK_LEN_MASK, cmd->uhs2_cmd->packet_len); 6669cbb2358SVictor Shih if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) 6679cbb2358SVictor Shih cmd_reg |= SDHCI_UHS2_CMD_DATA; 6689cbb2358SVictor Shih if (cmd->opcode == MMC_STOP_TRANSMISSION) 6699cbb2358SVictor Shih cmd_reg |= SDHCI_UHS2_CMD_CMD12; 6709cbb2358SVictor Shih 6719cbb2358SVictor Shih /* UHS2 Native ABORT */ 6729cbb2358SVictor Shih if ((cmd->uhs2_cmd->header & UHS2_NATIVE_PACKET) && 6739cbb2358SVictor Shih (uhs2_dev_cmd(cmd) == UHS2_DEV_CMD_TRANS_ABORT)) 6749cbb2358SVictor Shih cmd_reg |= SDHCI_UHS2_CMD_TRNS_ABORT; 6759cbb2358SVictor Shih 6769cbb2358SVictor Shih /* UHS2 Native DORMANT */ 6779cbb2358SVictor Shih if ((cmd->uhs2_cmd->header & UHS2_NATIVE_PACKET) && 6789cbb2358SVictor Shih (uhs2_dev_cmd(cmd) == UHS2_DEV_CMD_GO_DORMANT_STATE)) 6799cbb2358SVictor Shih cmd_reg |= SDHCI_UHS2_CMD_DORMANT; 6809cbb2358SVictor Shih 6819cbb2358SVictor Shih DBG("0x%x is set to UHS2 CMD register.\n", cmd_reg); 6829cbb2358SVictor Shih 6839cbb2358SVictor Shih sdhci_writew(host, cmd_reg, SDHCI_UHS2_CMD); 6849cbb2358SVictor Shih } 6859cbb2358SVictor Shih 6869cbb2358SVictor Shih static bool sdhci_uhs2_send_command(struct sdhci_host *host, struct mmc_command *cmd) 6879cbb2358SVictor Shih { 6889cbb2358SVictor Shih u32 mask; 6899cbb2358SVictor Shih unsigned long timeout; 6909cbb2358SVictor Shih 6919cbb2358SVictor Shih WARN_ON(host->cmd); 6929cbb2358SVictor Shih 6939cbb2358SVictor Shih /* Initially, a command has no error */ 6949cbb2358SVictor Shih cmd->error = 0; 6959cbb2358SVictor Shih 6969cbb2358SVictor Shih if (cmd->opcode == MMC_STOP_TRANSMISSION) 6979cbb2358SVictor Shih cmd->flags |= MMC_RSP_BUSY; 6989cbb2358SVictor Shih 6999cbb2358SVictor Shih mask = SDHCI_CMD_INHIBIT; 7009cbb2358SVictor Shih 7019cbb2358SVictor Shih if (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) 7029cbb2358SVictor Shih return false; 7039cbb2358SVictor Shih 7049cbb2358SVictor Shih host->cmd = cmd; 7059cbb2358SVictor Shih host->data_timeout = 0; 7069cbb2358SVictor Shih if (sdhci_data_line_cmd(cmd)) { 7079cbb2358SVictor Shih WARN_ON(host->data_cmd); 7089cbb2358SVictor Shih host->data_cmd = cmd; 7099cbb2358SVictor Shih __sdhci_uhs2_set_timeout(host); 7109cbb2358SVictor Shih } 7119cbb2358SVictor Shih 7129cbb2358SVictor Shih if (cmd->data) 7139cbb2358SVictor Shih sdhci_uhs2_prepare_data(host, cmd); 7149cbb2358SVictor Shih 7159cbb2358SVictor Shih sdhci_uhs2_set_transfer_mode(host, cmd); 7169cbb2358SVictor Shih 7179cbb2358SVictor Shih timeout = jiffies; 7189cbb2358SVictor Shih if (host->data_timeout) 7199cbb2358SVictor Shih timeout += nsecs_to_jiffies(host->data_timeout); 7209cbb2358SVictor Shih else if (!cmd->data && cmd->busy_timeout > 9000) 7219cbb2358SVictor Shih timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; 7229cbb2358SVictor Shih else 7239cbb2358SVictor Shih timeout += 10 * HZ; 7249cbb2358SVictor Shih sdhci_mod_timer(host, cmd->mrq, timeout); 7259cbb2358SVictor Shih 7269cbb2358SVictor Shih __sdhci_uhs2_send_command(host, cmd); 7279cbb2358SVictor Shih 7289cbb2358SVictor Shih return true; 7299cbb2358SVictor Shih } 7309cbb2358SVictor Shih 7319cbb2358SVictor Shih static bool sdhci_uhs2_send_command_retry(struct sdhci_host *host, 7329cbb2358SVictor Shih struct mmc_command *cmd, 7339cbb2358SVictor Shih unsigned long flags) 7349cbb2358SVictor Shih __releases(host->lock) 7359cbb2358SVictor Shih __acquires(host->lock) 7369cbb2358SVictor Shih { 7379cbb2358SVictor Shih struct mmc_command *deferred_cmd = host->deferred_cmd; 7389cbb2358SVictor Shih int timeout = 10; /* Approx. 10 ms */ 7399cbb2358SVictor Shih bool present; 7409cbb2358SVictor Shih 7419cbb2358SVictor Shih while (!sdhci_uhs2_send_command(host, cmd)) { 7429cbb2358SVictor Shih if (!timeout--) { 7439cbb2358SVictor Shih pr_err("%s: Controller never released inhibit bit(s).\n", 7449cbb2358SVictor Shih mmc_hostname(host->mmc)); 7459cbb2358SVictor Shih sdhci_dumpregs(host); 7469cbb2358SVictor Shih cmd->error = -EIO; 7479cbb2358SVictor Shih return false; 7489cbb2358SVictor Shih } 7499cbb2358SVictor Shih 7509cbb2358SVictor Shih spin_unlock_irqrestore(&host->lock, flags); 7519cbb2358SVictor Shih 7529cbb2358SVictor Shih usleep_range(1000, 1250); 7539cbb2358SVictor Shih 7549cbb2358SVictor Shih present = host->mmc->ops->get_cd(host->mmc); 7559cbb2358SVictor Shih 7569cbb2358SVictor Shih spin_lock_irqsave(&host->lock, flags); 7579cbb2358SVictor Shih 7589cbb2358SVictor Shih /* A deferred command might disappear, handle that */ 7599cbb2358SVictor Shih if (cmd == deferred_cmd && cmd != host->deferred_cmd) 7609cbb2358SVictor Shih return true; 7619cbb2358SVictor Shih 7629cbb2358SVictor Shih if (sdhci_present_error(host, cmd, present)) 7639cbb2358SVictor Shih return false; 7649cbb2358SVictor Shih } 7659cbb2358SVictor Shih 7669cbb2358SVictor Shih if (cmd == host->deferred_cmd) 7679cbb2358SVictor Shih host->deferred_cmd = NULL; 7689cbb2358SVictor Shih 7699cbb2358SVictor Shih return true; 7709cbb2358SVictor Shih } 7719cbb2358SVictor Shih 7729cbb2358SVictor Shih static void __sdhci_uhs2_finish_command(struct sdhci_host *host) 7739cbb2358SVictor Shih { 7749cbb2358SVictor Shih struct mmc_command *cmd = host->cmd; 7759cbb2358SVictor Shih u8 resp; 7769cbb2358SVictor Shih u8 error_code; 7779cbb2358SVictor Shih bool breada0 = 0; 7789cbb2358SVictor Shih int i; 7799cbb2358SVictor Shih 7809cbb2358SVictor Shih if (host->mmc->uhs2_sd_tran) { 7819cbb2358SVictor Shih resp = sdhci_readb(host, SDHCI_UHS2_RESPONSE + 2); 7829cbb2358SVictor Shih if (resp & UHS2_RES_NACK_MASK) { 7839cbb2358SVictor Shih error_code = (resp >> UHS2_RES_ECODE_POS) & UHS2_RES_ECODE_MASK; 7849cbb2358SVictor Shih pr_err("%s: NACK response, ECODE=0x%x.\n", 7859cbb2358SVictor Shih mmc_hostname(host->mmc), error_code); 7869cbb2358SVictor Shih } 7879cbb2358SVictor Shih breada0 = 1; 7889cbb2358SVictor Shih } 7899cbb2358SVictor Shih 7909cbb2358SVictor Shih if (cmd->uhs2_cmd->uhs2_resp_len) { 7919cbb2358SVictor Shih int len = min_t(int, cmd->uhs2_cmd->uhs2_resp_len, UHS2_MAX_RESP_LEN); 7929cbb2358SVictor Shih 7939cbb2358SVictor Shih /* Get whole response of some native CCMD, like 7949cbb2358SVictor Shih * DEVICE_INIT, ENUMERATE. 7959cbb2358SVictor Shih */ 7969cbb2358SVictor Shih for (i = 0; i < len; i++) 7979cbb2358SVictor Shih cmd->uhs2_cmd->uhs2_resp[i] = sdhci_readb(host, SDHCI_UHS2_RESPONSE + i); 7989cbb2358SVictor Shih } else { 7999cbb2358SVictor Shih /* Get SD CMD response and Payload for some read 8009cbb2358SVictor Shih * CCMD, like INQUIRY_CFG. 8019cbb2358SVictor Shih */ 8029cbb2358SVictor Shih /* Per spec (p136), payload field is divided into 8039cbb2358SVictor Shih * a unit of DWORD and transmission order within 8049cbb2358SVictor Shih * a DWORD is big endian. 8059cbb2358SVictor Shih */ 8069cbb2358SVictor Shih if (!breada0) 8079cbb2358SVictor Shih sdhci_readl(host, SDHCI_UHS2_RESPONSE); 8089cbb2358SVictor Shih for (i = 4; i < 20; i += 4) { 8099cbb2358SVictor Shih cmd->resp[i / 4 - 1] = 8109cbb2358SVictor Shih (sdhci_readb(host, 8119cbb2358SVictor Shih SDHCI_UHS2_RESPONSE + i) << 24) | 8129cbb2358SVictor Shih (sdhci_readb(host, 8139cbb2358SVictor Shih SDHCI_UHS2_RESPONSE + i + 1) 8149cbb2358SVictor Shih << 16) | 8159cbb2358SVictor Shih (sdhci_readb(host, 8169cbb2358SVictor Shih SDHCI_UHS2_RESPONSE + i + 2) 8179cbb2358SVictor Shih << 8) | 8189cbb2358SVictor Shih sdhci_readb(host, SDHCI_UHS2_RESPONSE + i + 3); 8199cbb2358SVictor Shih } 8209cbb2358SVictor Shih } 8219cbb2358SVictor Shih } 8229cbb2358SVictor Shih 8239cbb2358SVictor Shih static void sdhci_uhs2_finish_command(struct sdhci_host *host) 8249cbb2358SVictor Shih { 8259cbb2358SVictor Shih struct mmc_command *cmd = host->cmd; 8269cbb2358SVictor Shih 8279cbb2358SVictor Shih __sdhci_uhs2_finish_command(host); 8289cbb2358SVictor Shih 8299cbb2358SVictor Shih host->cmd = NULL; 8309cbb2358SVictor Shih 8319cbb2358SVictor Shih if (cmd->mrq->cap_cmd_during_tfr && cmd == cmd->mrq->cmd) 8329cbb2358SVictor Shih mmc_command_done(host->mmc, cmd->mrq); 8339cbb2358SVictor Shih 8349cbb2358SVictor Shih /* 8359cbb2358SVictor Shih * The host can send and interrupt when the busy state has 8369cbb2358SVictor Shih * ended, allowing us to wait without wasting CPU cycles. 8379cbb2358SVictor Shih * The busy signal uses DAT0 so this is similar to waiting 8389cbb2358SVictor Shih * for data to complete. 8399cbb2358SVictor Shih * 8409cbb2358SVictor Shih * Note: The 1.0 specification is a bit ambiguous about this 8419cbb2358SVictor Shih * feature so there might be some problems with older 8429cbb2358SVictor Shih * controllers. 8439cbb2358SVictor Shih */ 8449cbb2358SVictor Shih if (cmd->flags & MMC_RSP_BUSY) { 8459cbb2358SVictor Shih if (cmd->data) { 8469cbb2358SVictor Shih DBG("Cannot wait for busy signal when also doing a data transfer"); 8479cbb2358SVictor Shih } else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) && 8489cbb2358SVictor Shih cmd == host->data_cmd) { 8499cbb2358SVictor Shih /* Command complete before busy is ended */ 8509cbb2358SVictor Shih return; 8519cbb2358SVictor Shih } 8529cbb2358SVictor Shih } 8539cbb2358SVictor Shih 8549cbb2358SVictor Shih /* Processed actual command. */ 8559cbb2358SVictor Shih if (host->data && host->data_early) 8569cbb2358SVictor Shih sdhci_uhs2_finish_data(host); 8579cbb2358SVictor Shih 8589cbb2358SVictor Shih if (!cmd->data) 8599cbb2358SVictor Shih __sdhci_finish_mrq(host, cmd->mrq); 8609cbb2358SVictor Shih } 8619cbb2358SVictor Shih 8629cbb2358SVictor Shih static void sdhci_uhs2_request(struct mmc_host *mmc, struct mmc_request *mrq) 8639cbb2358SVictor Shih { 8649cbb2358SVictor Shih struct sdhci_host *host = mmc_priv(mmc); 8659cbb2358SVictor Shih struct mmc_command *cmd; 8669cbb2358SVictor Shih unsigned long flags; 8679cbb2358SVictor Shih bool present; 8689cbb2358SVictor Shih 8699cbb2358SVictor Shih if (!(mmc_card_uhs2(mmc))) { 8709cbb2358SVictor Shih sdhci_request(mmc, mrq); 8719cbb2358SVictor Shih return; 8729cbb2358SVictor Shih } 8739cbb2358SVictor Shih 8749cbb2358SVictor Shih mrq->stop = NULL; 8759cbb2358SVictor Shih mrq->sbc = NULL; 8769cbb2358SVictor Shih if (mrq->data) 8779cbb2358SVictor Shih mrq->data->stop = NULL; 8789cbb2358SVictor Shih 8799cbb2358SVictor Shih /* Firstly check card presence */ 8809cbb2358SVictor Shih present = mmc->ops->get_cd(mmc); 8819cbb2358SVictor Shih 8829cbb2358SVictor Shih spin_lock_irqsave(&host->lock, flags); 8839cbb2358SVictor Shih 8849cbb2358SVictor Shih if (sdhci_present_error(host, mrq->cmd, present)) 8859cbb2358SVictor Shih goto out_finish; 8869cbb2358SVictor Shih 8879cbb2358SVictor Shih cmd = mrq->cmd; 8889cbb2358SVictor Shih 8899cbb2358SVictor Shih if (!sdhci_uhs2_send_command_retry(host, cmd, flags)) 8909cbb2358SVictor Shih goto out_finish; 8919cbb2358SVictor Shih 8929cbb2358SVictor Shih spin_unlock_irqrestore(&host->lock, flags); 8939cbb2358SVictor Shih 8949cbb2358SVictor Shih return; 8959cbb2358SVictor Shih 8969cbb2358SVictor Shih out_finish: 8979cbb2358SVictor Shih sdhci_finish_mrq(host, mrq); 8989cbb2358SVictor Shih spin_unlock_irqrestore(&host->lock, flags); 8999cbb2358SVictor Shih } 9009cbb2358SVictor Shih 9019cbb2358SVictor Shih /*****************************************************************************\ 9029cbb2358SVictor Shih * * 903fca267f0SVictor Shih * Request done * 904fca267f0SVictor Shih * * 905fca267f0SVictor Shih \*****************************************************************************/ 906fca267f0SVictor Shih 907fca267f0SVictor Shih static bool sdhci_uhs2_needs_reset(struct sdhci_host *host, struct mmc_request *mrq) 908fca267f0SVictor Shih { 909fca267f0SVictor Shih return sdhci_needs_reset(host, mrq) || 910fca267f0SVictor Shih (!(host->flags & SDHCI_DEVICE_DEAD) && mrq->data && mrq->data->error); 911fca267f0SVictor Shih } 912fca267f0SVictor Shih 913fca267f0SVictor Shih static bool sdhci_uhs2_request_done(struct sdhci_host *host) 914fca267f0SVictor Shih { 915fca267f0SVictor Shih unsigned long flags; 916fca267f0SVictor Shih struct mmc_request *mrq; 917fca267f0SVictor Shih int i; 918fca267f0SVictor Shih 919fca267f0SVictor Shih spin_lock_irqsave(&host->lock, flags); 920fca267f0SVictor Shih 921fca267f0SVictor Shih for (i = 0; i < SDHCI_MAX_MRQS; i++) { 922fca267f0SVictor Shih mrq = host->mrqs_done[i]; 923fca267f0SVictor Shih if (mrq) 924fca267f0SVictor Shih break; 925fca267f0SVictor Shih } 926fca267f0SVictor Shih 927fca267f0SVictor Shih if (!mrq) { 928fca267f0SVictor Shih spin_unlock_irqrestore(&host->lock, flags); 929fca267f0SVictor Shih return true; 930fca267f0SVictor Shih } 931fca267f0SVictor Shih 932fca267f0SVictor Shih /* 933fca267f0SVictor Shih * Always unmap the data buffers if they were mapped by 934fca267f0SVictor Shih * sdhci_prepare_data() whenever we finish with a request. 935fca267f0SVictor Shih * This avoids leaking DMA mappings on error. 936fca267f0SVictor Shih */ 937fca267f0SVictor Shih if (host->flags & SDHCI_REQ_USE_DMA) 938fca267f0SVictor Shih sdhci_request_done_dma(host, mrq); 939fca267f0SVictor Shih 940fca267f0SVictor Shih /* 941fca267f0SVictor Shih * The controller needs a reset of internal state machines 942fca267f0SVictor Shih * upon error conditions. 943fca267f0SVictor Shih */ 944fca267f0SVictor Shih if (sdhci_uhs2_needs_reset(host, mrq)) { 945fca267f0SVictor Shih /* 946fca267f0SVictor Shih * Do not finish until command and data lines are available for 947fca267f0SVictor Shih * reset. Note there can only be one other mrq, so it cannot 948fca267f0SVictor Shih * also be in mrqs_done, otherwise host->cmd and host->data_cmd 949fca267f0SVictor Shih * would both be null. 950fca267f0SVictor Shih */ 951fca267f0SVictor Shih if (host->cmd || host->data_cmd) { 952fca267f0SVictor Shih spin_unlock_irqrestore(&host->lock, flags); 953fca267f0SVictor Shih return true; 954fca267f0SVictor Shih } 955fca267f0SVictor Shih 956fca267f0SVictor Shih if (mrq->cmd->error || mrq->data->error) 957fca267f0SVictor Shih sdhci_uhs2_reset_cmd_data(host); 958fca267f0SVictor Shih else 959fca267f0SVictor Shih sdhci_uhs2_reset(host, SDHCI_UHS2_SW_RESET_SD); 960fca267f0SVictor Shih host->pending_reset = false; 961fca267f0SVictor Shih } 962fca267f0SVictor Shih 963fca267f0SVictor Shih host->mrqs_done[i] = NULL; 964fca267f0SVictor Shih 965fca267f0SVictor Shih spin_unlock_irqrestore(&host->lock, flags); 966fca267f0SVictor Shih 967fca267f0SVictor Shih if (host->ops->request_done) 968fca267f0SVictor Shih host->ops->request_done(host, mrq); 969fca267f0SVictor Shih else 970fca267f0SVictor Shih mmc_request_done(host->mmc, mrq); 971fca267f0SVictor Shih 972fca267f0SVictor Shih return false; 973fca267f0SVictor Shih } 974fca267f0SVictor Shih 975fca267f0SVictor Shih static void sdhci_uhs2_complete_work(struct work_struct *work) 976fca267f0SVictor Shih { 977fca267f0SVictor Shih struct sdhci_host *host = container_of(work, struct sdhci_host, 978fca267f0SVictor Shih complete_work); 979fca267f0SVictor Shih 980fca267f0SVictor Shih if (!mmc_card_uhs2(host->mmc)) { 981fca267f0SVictor Shih sdhci_complete_work(work); 982fca267f0SVictor Shih return; 983fca267f0SVictor Shih } 984fca267f0SVictor Shih 985fca267f0SVictor Shih while (!sdhci_uhs2_request_done(host)) 986fca267f0SVictor Shih ; 987fca267f0SVictor Shih } 988fca267f0SVictor Shih 989fca267f0SVictor Shih /*****************************************************************************\ 990fca267f0SVictor Shih * * 991fca267f0SVictor Shih * Interrupt handling * 992fca267f0SVictor Shih * * 993fca267f0SVictor Shih \*****************************************************************************/ 994fca267f0SVictor Shih 995fca267f0SVictor Shih static void __sdhci_uhs2_irq(struct sdhci_host *host, u32 uhs2mask) 996fca267f0SVictor Shih { 9979cbb2358SVictor Shih struct mmc_command *cmd = host->cmd; 9989cbb2358SVictor Shih 999fca267f0SVictor Shih DBG("*** %s got UHS2 error interrupt: 0x%08x\n", 1000fca267f0SVictor Shih mmc_hostname(host->mmc), uhs2mask); 1001fca267f0SVictor Shih 1002fca267f0SVictor Shih if (uhs2mask & SDHCI_UHS2_INT_CMD_ERR_MASK) { 1003fca267f0SVictor Shih if (!host->cmd) { 1004fca267f0SVictor Shih pr_err("%s: Got cmd interrupt 0x%08x but no cmd.\n", 1005fca267f0SVictor Shih mmc_hostname(host->mmc), 1006fca267f0SVictor Shih (unsigned int)uhs2mask); 1007fca267f0SVictor Shih sdhci_dumpregs(host); 1008fca267f0SVictor Shih return; 1009fca267f0SVictor Shih } 1010fca267f0SVictor Shih host->cmd->error = -EILSEQ; 1011fca267f0SVictor Shih if (uhs2mask & SDHCI_UHS2_INT_CMD_TIMEOUT) 1012fca267f0SVictor Shih host->cmd->error = -ETIMEDOUT; 1013fca267f0SVictor Shih } 1014fca267f0SVictor Shih 1015fca267f0SVictor Shih if (uhs2mask & SDHCI_UHS2_INT_DATA_ERR_MASK) { 1016fca267f0SVictor Shih if (!host->data) { 1017fca267f0SVictor Shih pr_err("%s: Got data interrupt 0x%08x but no data.\n", 1018fca267f0SVictor Shih mmc_hostname(host->mmc), 1019fca267f0SVictor Shih (unsigned int)uhs2mask); 1020fca267f0SVictor Shih sdhci_dumpregs(host); 1021fca267f0SVictor Shih return; 1022fca267f0SVictor Shih } 1023fca267f0SVictor Shih 1024fca267f0SVictor Shih if (uhs2mask & SDHCI_UHS2_INT_DEADLOCK_TIMEOUT) { 1025fca267f0SVictor Shih pr_err("%s: Got deadlock timeout interrupt 0x%08x\n", 1026fca267f0SVictor Shih mmc_hostname(host->mmc), 1027fca267f0SVictor Shih (unsigned int)uhs2mask); 1028fca267f0SVictor Shih host->data->error = -ETIMEDOUT; 1029fca267f0SVictor Shih } else if (uhs2mask & SDHCI_UHS2_INT_ADMA_ERROR) { 1030fca267f0SVictor Shih pr_err("%s: ADMA error = 0x %x\n", 1031fca267f0SVictor Shih mmc_hostname(host->mmc), 1032fca267f0SVictor Shih sdhci_readb(host, SDHCI_ADMA_ERROR)); 1033fca267f0SVictor Shih host->data->error = -EIO; 1034fca267f0SVictor Shih } else { 1035fca267f0SVictor Shih host->data->error = -EILSEQ; 1036fca267f0SVictor Shih } 1037fca267f0SVictor Shih } 10389cbb2358SVictor Shih 10399cbb2358SVictor Shih if (host->data && host->data->error) 10409cbb2358SVictor Shih sdhci_uhs2_finish_data(host); 10419cbb2358SVictor Shih else 10429cbb2358SVictor Shih sdhci_finish_mrq(host, cmd->mrq); 10439cbb2358SVictor Shih 1044fca267f0SVictor Shih } 1045fca267f0SVictor Shih 1046fca267f0SVictor Shih u32 sdhci_uhs2_irq(struct sdhci_host *host, u32 intmask) 1047fca267f0SVictor Shih { 1048fca267f0SVictor Shih u32 mask = intmask, uhs2mask; 1049fca267f0SVictor Shih 1050fca267f0SVictor Shih if (!mmc_card_uhs2(host->mmc)) 1051fca267f0SVictor Shih goto out; 1052fca267f0SVictor Shih 1053fca267f0SVictor Shih if (intmask & SDHCI_INT_ERROR) { 1054fca267f0SVictor Shih uhs2mask = sdhci_readl(host, SDHCI_UHS2_INT_STATUS); 1055fca267f0SVictor Shih if (!(uhs2mask & SDHCI_UHS2_INT_ERROR_MASK)) 1056fca267f0SVictor Shih goto cmd_irq; 1057fca267f0SVictor Shih 1058fca267f0SVictor Shih /* Clear error interrupts */ 1059fca267f0SVictor Shih sdhci_writel(host, uhs2mask & SDHCI_UHS2_INT_ERROR_MASK, 1060fca267f0SVictor Shih SDHCI_UHS2_INT_STATUS); 1061fca267f0SVictor Shih 1062fca267f0SVictor Shih /* Handle error interrupts */ 1063fca267f0SVictor Shih __sdhci_uhs2_irq(host, uhs2mask); 1064fca267f0SVictor Shih 1065fca267f0SVictor Shih /* Caller, sdhci_irq(), doesn't have to care about UHS-2 errors */ 1066fca267f0SVictor Shih intmask &= ~SDHCI_INT_ERROR; 1067fca267f0SVictor Shih mask &= SDHCI_INT_ERROR; 1068fca267f0SVictor Shih } 1069fca267f0SVictor Shih 1070fca267f0SVictor Shih cmd_irq: 1071fca267f0SVictor Shih if (intmask & SDHCI_INT_CMD_MASK) { 1072fca267f0SVictor Shih /* Clear command interrupt */ 1073fca267f0SVictor Shih sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, SDHCI_INT_STATUS); 1074fca267f0SVictor Shih 10759cbb2358SVictor Shih /* Handle command interrupt */ 10769cbb2358SVictor Shih if (intmask & SDHCI_INT_RESPONSE) 10779cbb2358SVictor Shih sdhci_uhs2_finish_command(host); 10789cbb2358SVictor Shih 1079fca267f0SVictor Shih /* Caller, sdhci_irq(), doesn't have to care about UHS-2 commands */ 1080fca267f0SVictor Shih intmask &= ~SDHCI_INT_CMD_MASK; 1081fca267f0SVictor Shih mask &= SDHCI_INT_CMD_MASK; 1082fca267f0SVictor Shih } 1083fca267f0SVictor Shih 1084fca267f0SVictor Shih /* Clear already-handled interrupts. */ 1085fca267f0SVictor Shih sdhci_writel(host, mask, SDHCI_INT_STATUS); 1086fca267f0SVictor Shih 1087fca267f0SVictor Shih out: 1088fca267f0SVictor Shih return intmask; 1089fca267f0SVictor Shih } 1090fca267f0SVictor Shih EXPORT_SYMBOL_GPL(sdhci_uhs2_irq); 1091fca267f0SVictor Shih 1092fca267f0SVictor Shih static irqreturn_t sdhci_uhs2_thread_irq(int irq, void *dev_id) 1093fca267f0SVictor Shih { 1094fca267f0SVictor Shih struct sdhci_host *host = dev_id; 1095fca267f0SVictor Shih struct mmc_command *cmd; 1096fca267f0SVictor Shih unsigned long flags; 1097fca267f0SVictor Shih u32 isr; 1098fca267f0SVictor Shih 1099fca267f0SVictor Shih if (!mmc_card_uhs2(host->mmc)) 1100fca267f0SVictor Shih return sdhci_thread_irq(irq, dev_id); 1101fca267f0SVictor Shih 1102fca267f0SVictor Shih while (!sdhci_uhs2_request_done(host)) 1103fca267f0SVictor Shih ; 1104fca267f0SVictor Shih 1105fca267f0SVictor Shih spin_lock_irqsave(&host->lock, flags); 1106fca267f0SVictor Shih 1107fca267f0SVictor Shih isr = host->thread_isr; 1108fca267f0SVictor Shih host->thread_isr = 0; 1109fca267f0SVictor Shih 1110fca267f0SVictor Shih cmd = host->deferred_cmd; 11119cbb2358SVictor Shih if (cmd && !sdhci_uhs2_send_command_retry(host, cmd, flags)) 11129cbb2358SVictor Shih sdhci_finish_mrq(host, cmd->mrq); 1113fca267f0SVictor Shih 1114fca267f0SVictor Shih spin_unlock_irqrestore(&host->lock, flags); 1115fca267f0SVictor Shih 1116fca267f0SVictor Shih if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { 1117fca267f0SVictor Shih struct mmc_host *mmc = host->mmc; 1118fca267f0SVictor Shih 1119fca267f0SVictor Shih mmc->ops->card_event(mmc); 1120fca267f0SVictor Shih mmc_detect_change(mmc, msecs_to_jiffies(200)); 1121fca267f0SVictor Shih } 1122fca267f0SVictor Shih 1123fca267f0SVictor Shih return IRQ_HANDLED; 1124fca267f0SVictor Shih } 1125fca267f0SVictor Shih 1126fca267f0SVictor Shih /*****************************************************************************\ 1127fca267f0SVictor Shih * * 11282af7dd8bSVictor Shih * Driver init/exit * 11292af7dd8bSVictor Shih * * 11302af7dd8bSVictor Shih \*****************************************************************************/ 11312af7dd8bSVictor Shih 113210c8298aSVictor Shih static int sdhci_uhs2_host_ops_init(struct sdhci_host *host) 113310c8298aSVictor Shih { 113410c8298aSVictor Shih host->mmc_host_ops.uhs2_control = sdhci_uhs2_control; 11359cbb2358SVictor Shih host->mmc_host_ops.request = sdhci_uhs2_request; 113610c8298aSVictor Shih 113710c8298aSVictor Shih return 0; 113810c8298aSVictor Shih } 113910c8298aSVictor Shih 11402af7dd8bSVictor Shih static int __init sdhci_uhs2_mod_init(void) 11412af7dd8bSVictor Shih { 11422af7dd8bSVictor Shih return 0; 11432af7dd8bSVictor Shih } 11442af7dd8bSVictor Shih module_init(sdhci_uhs2_mod_init); 11452af7dd8bSVictor Shih 11462af7dd8bSVictor Shih static void __exit sdhci_uhs2_mod_exit(void) 11472af7dd8bSVictor Shih { 11482af7dd8bSVictor Shih } 11492af7dd8bSVictor Shih module_exit(sdhci_uhs2_mod_exit); 11502af7dd8bSVictor Shih 115106a0d072SVictor Shih /*****************************************************************************\ 115206a0d072SVictor Shih * 115306a0d072SVictor Shih * Device allocation/registration * 115406a0d072SVictor Shih * * 115506a0d072SVictor Shih \*****************************************************************************/ 115606a0d072SVictor Shih 115706a0d072SVictor Shih static void __sdhci_uhs2_add_host_v4(struct sdhci_host *host, u32 caps1) 115806a0d072SVictor Shih { 115906a0d072SVictor Shih struct mmc_host *mmc; 116006a0d072SVictor Shih u32 max_current_caps2; 116106a0d072SVictor Shih 116206a0d072SVictor Shih mmc = host->mmc; 116306a0d072SVictor Shih 116406a0d072SVictor Shih /* Support UHS2 */ 116506a0d072SVictor Shih if (caps1 & SDHCI_SUPPORT_UHS2) 116606a0d072SVictor Shih mmc->caps2 |= MMC_CAP2_SD_UHS2; 116706a0d072SVictor Shih 116806a0d072SVictor Shih max_current_caps2 = sdhci_readl(host, SDHCI_MAX_CURRENT_1); 116906a0d072SVictor Shih 117006a0d072SVictor Shih if ((caps1 & SDHCI_CAN_VDD2_180) && 117106a0d072SVictor Shih !max_current_caps2 && 117206a0d072SVictor Shih !IS_ERR(mmc->supply.vqmmc2)) { 117306a0d072SVictor Shih /* UHS2 - VDD2 */ 117406a0d072SVictor Shih int curr = regulator_get_current_limit(mmc->supply.vqmmc2); 117506a0d072SVictor Shih 117606a0d072SVictor Shih if (curr > 0) { 117706a0d072SVictor Shih /* convert to SDHCI_MAX_CURRENT format */ 117806a0d072SVictor Shih curr = curr / 1000; /* convert to mA */ 117906a0d072SVictor Shih curr = curr / SDHCI_MAX_CURRENT_MULTIPLIER; 118006a0d072SVictor Shih curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT); 118106a0d072SVictor Shih max_current_caps2 = curr; 118206a0d072SVictor Shih } 118306a0d072SVictor Shih } 118406a0d072SVictor Shih 118506a0d072SVictor Shih if (!(caps1 & SDHCI_CAN_VDD2_180)) 118606a0d072SVictor Shih mmc->caps2 &= ~MMC_CAP2_SD_UHS2; 118706a0d072SVictor Shih } 118806a0d072SVictor Shih 118906a0d072SVictor Shih static void __sdhci_uhs2_remove_host(struct sdhci_host *host, int dead) 119006a0d072SVictor Shih { 119106a0d072SVictor Shih if (!mmc_card_uhs2(host->mmc)) 119206a0d072SVictor Shih return; 119306a0d072SVictor Shih 119406a0d072SVictor Shih if (!dead) 119506a0d072SVictor Shih sdhci_uhs2_reset(host, SDHCI_UHS2_SW_RESET_FULL); 119606a0d072SVictor Shih } 119706a0d072SVictor Shih 119806a0d072SVictor Shih int sdhci_uhs2_add_host(struct sdhci_host *host) 119906a0d072SVictor Shih { 120006a0d072SVictor Shih struct mmc_host *mmc = host->mmc; 120106a0d072SVictor Shih int ret; 120206a0d072SVictor Shih 120306a0d072SVictor Shih ret = sdhci_setup_host(host); 120406a0d072SVictor Shih if (ret) 120506a0d072SVictor Shih return ret; 120606a0d072SVictor Shih 120706a0d072SVictor Shih if (host->version >= SDHCI_SPEC_400) 120806a0d072SVictor Shih __sdhci_uhs2_add_host_v4(host, host->caps1); 120906a0d072SVictor Shih 121006a0d072SVictor Shih if ((mmc->caps2 & MMC_CAP2_SD_UHS2) && !host->v4_mode) 121106a0d072SVictor Shih /* host doesn't want to enable UHS2 support */ 121206a0d072SVictor Shih mmc->caps2 &= ~MMC_CAP2_SD_UHS2; 121306a0d072SVictor Shih 121410c8298aSVictor Shih /* overwrite ops */ 121510c8298aSVictor Shih if (mmc->caps2 & MMC_CAP2_SD_UHS2) 121610c8298aSVictor Shih sdhci_uhs2_host_ops_init(host); 121710c8298aSVictor Shih 1218fca267f0SVictor Shih host->complete_work_fn = sdhci_uhs2_complete_work; 1219fca267f0SVictor Shih host->thread_irq_fn = sdhci_uhs2_thread_irq; 1220fca267f0SVictor Shih 122106a0d072SVictor Shih /* LED support not implemented for UHS2 */ 122206a0d072SVictor Shih host->quirks |= SDHCI_QUIRK_NO_LED; 122306a0d072SVictor Shih 122406a0d072SVictor Shih ret = __sdhci_add_host(host); 122506a0d072SVictor Shih if (ret) 122606a0d072SVictor Shih goto cleanup; 122706a0d072SVictor Shih 122806a0d072SVictor Shih return 0; 122906a0d072SVictor Shih 123006a0d072SVictor Shih cleanup: 123106a0d072SVictor Shih if (host->version >= SDHCI_SPEC_400) 123206a0d072SVictor Shih __sdhci_uhs2_remove_host(host, 0); 123306a0d072SVictor Shih 123406a0d072SVictor Shih sdhci_cleanup_host(host); 123506a0d072SVictor Shih 123606a0d072SVictor Shih return ret; 123706a0d072SVictor Shih } 123806a0d072SVictor Shih EXPORT_SYMBOL_GPL(sdhci_uhs2_add_host); 123906a0d072SVictor Shih 124006a0d072SVictor Shih void sdhci_uhs2_remove_host(struct sdhci_host *host, int dead) 124106a0d072SVictor Shih { 124206a0d072SVictor Shih __sdhci_uhs2_remove_host(host, dead); 124306a0d072SVictor Shih 124406a0d072SVictor Shih sdhci_remove_host(host, dead); 124506a0d072SVictor Shih } 124606a0d072SVictor Shih EXPORT_SYMBOL_GPL(sdhci_uhs2_remove_host); 124706a0d072SVictor Shih 12482af7dd8bSVictor Shih MODULE_AUTHOR("Intel, Genesys Logic, Linaro"); 12492af7dd8bSVictor Shih MODULE_DESCRIPTION("MMC UHS-II Support"); 12502af7dd8bSVictor Shih MODULE_LICENSE("GPL"); 1251