--- linux-4.9.37/drivers/mmc/host/sdhci-gk7205v300.c 1970-01-01 03:00:00.000000000 +0300 +++ linux-4.9.y/drivers/mmc/host/sdhci-gk7205v300.c 2021-06-07 13:01:33.000000000 +0300 @@ -0,0 +1,510 @@ +/* + * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sdhci-pltfm.h" +#include "sdhci-proc.h" + +#ifdef CONFIG_MMC_SDHCI_GOKE +#define PHASE_SCALE 32 +#define EDGE_TUNING_PHASE_STEP 4 +#define NOT_FOUND (-1) +#define MAX_TUNING_NUM 1 +#define MAX_FREQ 200000000 + +#define GOKE_MMC_AUTOSUSPEND_DELAY_MS 50 + +#define REG_EMMC_DRV_DLL_CTRL 0x1fc +#define REG_SDIO0_DRV_DLL_CTRL 0x1fc +#define REG_SDIO1_DRV_DLL_CTRL 0x220 +#define REG_SDIO2_DRV_DLL_CTRL /* no sdio2 */ +#define SDIO_DRV_PHASE_SEL_MASK (0x1f << 24) +#define sdio_drv_sel(phase) ((phase) << 24) + +#define REG_EMMC_DRV_DLL_STATUS 0x210 +#define REG_SDIO0_DRV_DLL_STATUS 0x210 +#define REG_SDIO1_DRV_DLL_STATUS 0x228 +#define REG_SDIO2_DRV_DLL_STATUS /* no sdio2 */ +#define SDIO_DRV_DLL_LOCK BIT(15) +#define SDIO_DRV_DLL_READY BIT(14) + +#define REG_EMMC_SAMPL_DLL_STATUS 0x208 +#define REG_SDIO0_SAMPL_DLL_STATUS 0x208 +#define REG_SDIO1_SAMPL_DLL_STATUS 0x224 +#define REG_SDIO2_SAMPL_DLL_STATUS /* no sdio2 */ +#define SDIO_SAMPL_DLL_SLAVE_READY BIT(0) + +#define REG_EMMC_SAMPL_DLL_CTRL 0x1f4 +#define REG_SDIO0_SAMPL_DLL_CTRL 0x1f4 +#define REG_SDIO1_SAMPL_DLL_CTRL 0x22c +#define REG_SDIO2_SAMPL_DLL_CTRL /* no sdio2 */ +#define SDIO_SAMPL_DLL_SLAVE_EN BIT(16) + +#define REG_EMMC_SAMPLB_DLL_CTRL 0x1f8 +#define REG_SDIO0_SAMPLB_DLL_CTRL 0x1f8 +#define REG_SDIO1_SAMPLB_DLL_CTRL 0x21c +#define REG_SDIO2_SAMPLB_DLL_CTRL /* no sdio2 */ +#define SDIO_SAMPLB_DLL_CLK_MASK (0x1f << 0) +#define sdio_samplb_sel(phase) ((phase) << 0) + +#define REG_EMMC_DS_DLL_CTRL 0x200 +#define EMMC_DS_DLL_MODE_SSEL BIT(13) +#define EMMC_DS_DLL_SSEL_MASK 0x7f + +#define REG_EMMC_DS180_DLL_CTRL 0x204 +#define EMMC_DS180_DLL_BYPASS BIT(15) +#define REG_EMMC_DS180_DLL_STATUS 0x218 +#define EMMC_DS180_DLL_READY BIT(0) + +#define REG_EMMC_DS_DLL_STATUS 0x214 +#define EMMC_DS_DLL_READY BIT(0) + +#define REG_EMMC_CLK_CTRL 0x1f4 +#define REG_SDIO0_CLK_CTRL 0x1f4 +#define REG_SDIO1_CLK_CTRL 0x22c +#define REG_SDIO2_CLK_CTRL /* no sdio2 */ +#define SDIO_CLK_DRV_DLL_RST BIT(29) +#define SDIO_CLK_CRG_RST BIT(27) + +#define IO_CFG_SR BIT(10) +#define IO_CFG_PULL_DOWN BIT(9) +#define IO_CFG_PULL_UP BIT(8) +#define IO_CFG_DRV_STR_MASK (0xf << 4) +#define io_cfg_drv_str_sel(str) ((str) << 4) +#define IO_CFG_PIN_MUX_MASK (0xf << 0) +#define io_cfg_pin_mux_sel(type) ((type) << 0) +#define IO_CFG_PIN_MUX_TYPE_CLK_EMMC 0x0 +#define IO_CFG_PIN_MUX_TYPE_CLK_SD 0x1 + +#define IO_CFG_EMMC_DATA_LINE_COUNT 8 +#define REG_CTRL_EMMC_CLK 0x0014 +#define REG_CTRL_EMMC_CMD 0x0018 +#define REG_CTRL_EMMC_DATA0 0x001c +#define REG_CTRL_EMMC_DATA1 0x0028 +#define REG_CTRL_EMMC_DATA2 0x0024 +#define REG_CTRL_EMMC_DATA3 0x0020 +#define REG_CTRL_EMMC_DATA4 0x0030 +#define REG_CTRL_EMMC_DATA5 0x0034 +#define REG_CTRL_EMMC_DATA6 0x0038 +#define REG_CTRL_EMMC_DATA7 0x003c +#define REG_CTRL_EMMC_DS 0x0058 +#define REG_CTRL_EMMC_RST 0x005c +static unsigned int io_emmc_data_reg[IO_CFG_EMMC_DATA_LINE_COUNT] = { + REG_CTRL_EMMC_DATA0, REG_CTRL_EMMC_DATA1, + REG_CTRL_EMMC_DATA2, REG_CTRL_EMMC_DATA3, + REG_CTRL_EMMC_DATA4, REG_CTRL_EMMC_DATA5, + REG_CTRL_EMMC_DATA6, REG_CTRL_EMMC_DATA7 +}; + +#define IO_CFG_SDIO0_DATA_LINE_COUNT 4 +#define REG_CTRL_SDIO0_CLK 0x0040 +#define REG_CTRL_SDIO0_CMD 0x0044 +#define REG_CTRL_SDIO0_DATA0 0x0048 +#define REG_CTRL_SDIO0_DATA1 0x004C +#define REG_CTRL_SDIO0_DATA2 0x0050 +#define REG_CTRL_SDIO0_DATA3 0x0054 +static unsigned int io_sdio0_data_reg[IO_CFG_SDIO0_DATA_LINE_COUNT] = { + REG_CTRL_SDIO0_DATA0, REG_CTRL_SDIO0_DATA1, + REG_CTRL_SDIO0_DATA2, REG_CTRL_SDIO0_DATA3 +}; + +#define IO_CFG_SDIO1_DATA_LINE_COUNT 4 +#define REG_CTRL_SDIO1_CLK 0x0060 +#define REG_CTRL_SDIO1_CMD 0x0064 +#define REG_CTRL_SDIO1_DATA0 0x0068 +#define REG_CTRL_SDIO1_DATA1 0x006C +#define REG_CTRL_SDIO1_DATA2 0x0070 +#define REG_CTRL_SDIO1_DATA3 0x0074 +static unsigned int io_sdio1_data_reg[IO_CFG_SDIO1_DATA_LINE_COUNT] = { + REG_CTRL_SDIO1_DATA0, REG_CTRL_SDIO1_DATA1, + REG_CTRL_SDIO1_DATA2, REG_CTRL_SDIO1_DATA3 +}; + +struct sdhci_bsp_priv { + struct reset_control *crg_rst; + struct reset_control *dll_rst; + struct reset_control *sampl_rst; /* Not used */ + struct regmap *crg_regmap; + struct regmap *iocfg_regmap; + unsigned int f_max; + unsigned int devid; + unsigned int drv_phase; + unsigned int sampl_phase; + unsigned int tuning_phase; +}; + +static void bsp_mmc_crg_init(struct sdhci_host *host); +static void sdhci_bsp_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios); +static int sdhci_bsp_parse_dt(struct sdhci_host *host); + +static inline void *sdhci_get_pltfm_priv(struct sdhci_host *host) +{ + return sdhci_pltfm_priv(sdhci_priv(host)); +} + +static void sdhci_bsp_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios) +{ + u32 ctrl; + struct sdhci_host *host = mmc_priv(mmc); + + ctrl = sdhci_readl(host, SDHCI_EMMC_CTRL); + if (ios->enhanced_strobe) + ctrl |= SDHCI_ENH_STROBE_EN; + else + ctrl &= ~SDHCI_ENH_STROBE_EN; + + sdhci_writel(host, ctrl, SDHCI_EMMC_CTRL); + + ctrl = sdhci_readl(host, SDHCI_MULTI_CYCLE); + if (ios->enhanced_strobe) + ctrl |= SDHCI_CMD_DLY_EN; + else + ctrl &= ~SDHCI_CMD_DLY_EN; + + sdhci_writel(host, ctrl, SDHCI_MULTI_CYCLE); +} + +static int sdhci_bsp_pltfm_init(struct platform_device *pdev, struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_bsp_priv *bsp_priv = sdhci_pltfm_priv(pltfm_host); + struct device_node *np = pdev->dev.of_node; + struct clk *clk = NULL; + int ret; + + bsp_priv->crg_rst = devm_reset_control_get(&pdev->dev, "crg_reset"); + if (IS_ERR_OR_NULL(bsp_priv->crg_rst)) { + dev_err(&pdev->dev, "get crg_rst failed.\n"); + return PTR_ERR(bsp_priv->crg_rst); + } + + bsp_priv->dll_rst = devm_reset_control_get(&pdev->dev, "dll_reset"); + if (IS_ERR_OR_NULL(bsp_priv->dll_rst)) { + dev_err(&pdev->dev, "get dll_rst failed.\n"); + return PTR_ERR(bsp_priv->dll_rst); + } + + bsp_priv->sampl_rst = NULL; + + bsp_priv->crg_regmap = syscon_regmap_lookup_by_phandle(np, "crg_regmap"); + if (IS_ERR(bsp_priv->crg_regmap)) { + dev_err(&pdev->dev, "get crg regmap failed.\n"); + return PTR_ERR(bsp_priv->crg_regmap); + } + + bsp_priv->iocfg_regmap = syscon_regmap_lookup_by_phandle(np, "iocfg_regmap"); + if (IS_ERR(bsp_priv->iocfg_regmap)) { + dev_err(&pdev->dev, "get iocfg regmap failed.\n"); + return PTR_ERR(bsp_priv->iocfg_regmap); + } + + if (of_property_read_u32(np, "devid", &bsp_priv->devid)) + return -EINVAL; + + clk = devm_clk_get(mmc_dev(host->mmc), "mmc_clk"); + if (IS_ERR_OR_NULL(clk)) { + dev_err(mmc_dev(host->mmc), "get clk err\n"); + return -EINVAL; + } + + pltfm_host->clk = clk; + + bsp_mmc_crg_init(host); + ret = sdhci_bsp_parse_dt(host); + if (ret) + return ret; + + /* + * Only eMMC has a hw reset, and now eMMC signaling + * is fixed to 180 + */ + if (host->mmc->caps & MMC_CAP_HW_RESET) { + host->flags &= ~SDHCI_SIGNALING_330; + host->flags |= SDHCI_SIGNALING_180; + } + + /* + * We parse the support timings from dts, so we read the + * host capabilities early and clear the timing capabilities, + * SDHCI_QUIRK_MISSING_CAPS is set so that sdhci driver would + * not read it again + */ + host->caps = sdhci_readl(host, SDHCI_CAPABILITIES); + host->caps &= ~(SDHCI_CAN_DO_HISPD | SDHCI_CAN_VDD_300); + host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1); + host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 | + SDHCI_SUPPORT_DDR50 | SDHCI_CAN_DO_ADMA3); + host->quirks |= SDHCI_QUIRK_MISSING_CAPS | + SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | + SDHCI_QUIRK_SINGLE_POWER_WRITE; + + host->mmc_host_ops.hs400_enhanced_strobe = + sdhci_bsp_hs400_enhanced_strobe; + + mci_host[slot_index++] = host->mmc; + + return 0; +} + +static void bsp_wait_ds_dll_lock(struct sdhci_host *host) +{ + /* Do nothing */ +} + +static void bsp_wait_ds_180_dll_ready(struct sdhci_host *host) +{ + struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host); + unsigned int reg; + unsigned int timeout = 20; + + do { + reg = 0; + regmap_read(bsp_priv->crg_regmap, + REG_EMMC_DS180_DLL_STATUS, ®); + if (reg & EMMC_DS180_DLL_READY) + return; + + mdelay(1); + timeout--; + } while (timeout > 0); + + pr_err("%s: DS 180 DLL master not ready.\n", mmc_hostname(host->mmc)); +} + +static void bsp_set_ds_dll_delay(struct sdhci_host *host) +{ + /* Do nothing */ +} + +static void bsp_host_extra_init(struct sdhci_host *host) +{ + unsigned short ctrl; + unsigned int mbiiu_ctrl, val; + + ctrl = sdhci_readw(host, SDHCI_MSHC_CTRL); + ctrl &= ~SDHCI_CMD_CONFLIT_CHECK; + sdhci_writew(host, ctrl, SDHCI_MSHC_CTRL); + + mbiiu_ctrl = sdhci_readl(host, SDHCI_AXI_MBIIU_CTRL); + mbiiu_ctrl &= ~(SDHCI_GM_WR_OSRC_LMT_MASK | SDHCI_GM_RD_OSRC_LMT_MASK | + SDHCI_UNDEFL_INCR_EN); + mbiiu_ctrl |= (SDHCI_GM_WR_OSRC_LMT_SEL(0x7) | /* set write outstanding 8 (lmt + 1) */ + SDHCI_GM_RD_OSRC_LMT_SEL(0x7)); /* set read outstanding 8 (lmt + 1) */ + sdhci_writel(host, mbiiu_ctrl, SDHCI_AXI_MBIIU_CTRL); + + val = sdhci_readl(host, SDHCI_MULTI_CYCLE); + val &= ~SDHCI_CMD_DLY_EN; + val |= SDHCI_EDGE_DETECT_EN | SDHCI_DATA_DLY_EN; + val &= ~SDHCI_DOUT_EN_F_EDGE; + + sdhci_writel(host, val, SDHCI_MULTI_CYCLE); + host->error_count = 0; +} + +static void bsp_set_drv_str(struct regmap *iocfg_regmap, + unsigned int offset, unsigned int pull_up, + unsigned int pull_down, unsigned int sr, + unsigned int drv_str) +{ + unsigned int reg = 0; + + regmap_read(iocfg_regmap, offset, ®); + + reg &= ~(IO_CFG_PULL_UP | IO_CFG_PULL_DOWN | + IO_CFG_DRV_STR_MASK | IO_CFG_SR); + reg |= (pull_up ? IO_CFG_PULL_UP : 0); + reg |= (pull_down ? IO_CFG_PULL_DOWN : 0); + reg |= (sr ? IO_CFG_SR : 0); + reg |= io_cfg_drv_str_sel(drv_str); + + regmap_write(iocfg_regmap, offset, reg); +} + +static void bsp_set_emmc_ctrl(struct sdhci_host *host) +{ + unsigned int reg; + + reg = sdhci_readl(host, SDHCI_EMMC_CTRL); + reg |= SDHCI_CARD_IS_EMMC; + sdhci_writel(host, reg, SDHCI_EMMC_CTRL); +} + + +static void bsp_set_mmc_drv(struct sdhci_host *host) +{ + struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host); + void *iocfg_regmap = bsp_priv->iocfg_regmap; + int i; + + switch (host->timing) { + case MMC_TIMING_MMC_HS400: + bsp_set_emmc_ctrl(host); + bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 0, 0x3); /* set drv level 3 */ + bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 0, 0x5); /* set drv level 5 */ + for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++) + bsp_set_drv_str(iocfg_regmap, + io_emmc_data_reg[i], 1, 0, 0, 0x5); /* set drv level 5 */ + bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_DS, 0, 1, 1, 0x3); /* set drv level 3 */ + bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */ + break; + case MMC_TIMING_MMC_HS200: + bsp_set_emmc_ctrl(host); + bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 0, 0x2); /* set drv level 2 */ + bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 1, 0x4); /* set drv level 4 */ + for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++) + bsp_set_drv_str(iocfg_regmap, + io_emmc_data_reg[i], 1, 0, 1, 0x4); /* set drv level 4 */ + bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */ + break; + case MMC_TIMING_MMC_HS: + bsp_set_emmc_ctrl(host); + bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 1, 0x4); /* set drv level 4 */ + bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 1, 0x6); /* set drv level 6 */ + for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++) + bsp_set_drv_str(iocfg_regmap, + io_emmc_data_reg[i], 1, 0, 1, 0x6); /* set drv level 6 */ + bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */ + break; + case MMC_TIMING_LEGACY: + case MMC_TIMING_MMC_DDR52: + default: + bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 1, 0x5); /* set drv level 5 */ + bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 1, 0x6); /* set drv level 6 */ + for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++) + bsp_set_drv_str(iocfg_regmap, + io_emmc_data_reg[i], 1, 0, 1, 0x6); /* set drv level 6 */ + bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */ + break; + } +} + +static void bsp_set_sd_drv(struct sdhci_host *host) +{ + struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host); + void *iocfg_regmap = bsp_priv->iocfg_regmap; + int i; + + switch (host->timing) { + case MMC_TIMING_SD_HS: + bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CLK, 0, 1, 1, 0x5); /* set drv level 5 */ + bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CMD, 1, 0, 1, 0x7); /* set drv level 7 */ + for (i = 0; i < IO_CFG_SDIO0_DATA_LINE_COUNT; i++) + bsp_set_drv_str(iocfg_regmap, + io_sdio0_data_reg[i], 1, 0, 1, 0x7); /* set drv level 7 */ + break; + case MMC_TIMING_LEGACY: + default: + bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CLK, 0, 1, 1, 0x5); /* set drv level 5 */ + bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CMD, 1, 0, 1, 0x7); /* set drv level 7 */ + for (i = 0; i < IO_CFG_SDIO0_DATA_LINE_COUNT; i++) + bsp_set_drv_str(iocfg_regmap, + io_sdio0_data_reg[i], 1, 0, 1, 0x7); /* set drv level 7 */ + break; + } +} + +static void bsp_set_sdio_drv(struct sdhci_host *host) +{ + struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host); + void *iocfg_regmap = bsp_priv->iocfg_regmap; + int i; + + bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO1_CLK, 0, 1, 0, 0x3); /* 0x3 set drv level 5 */ + bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO1_CMD, 1, 0, 0, 0x6); /* 0x6 set drv level 2 */ + + bsp_set_drv_str(iocfg_regmap, io_sdio1_data_reg[0], 1, 0, 0, 0x6); /* 0x6 set drv level 2 */ + bsp_set_drv_str(iocfg_regmap, io_sdio1_data_reg[1], 1, 0, 0, 0x6); /* 0x6 set drv level 2 */ + bsp_set_drv_str(iocfg_regmap, io_sdio1_data_reg[2], 1, 0, 0, 0x2); /* 0x2 set drv level 2 */ + bsp_set_drv_str(iocfg_regmap, io_sdio1_data_reg[3], 1, 0, 0, 0x6); /* 0x6 set drv level 2 */ +} + +static void bsp_set_io_config(struct sdhci_host *host) +{ + struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host); + unsigned int devid = bsp_priv->devid; + void *iocfg_regmap = bsp_priv->iocfg_regmap; + unsigned int reg = 0; + + if (devid == 0) { + /* For mmc0: eMMC and SD card */ + regmap_read(iocfg_regmap, REG_CTRL_EMMC_CLK, ®); + if ((reg & IO_CFG_PIN_MUX_MASK) == + io_cfg_pin_mux_sel(IO_CFG_PIN_MUX_TYPE_CLK_EMMC)) + bsp_set_mmc_drv(host); + + regmap_read(iocfg_regmap, REG_CTRL_SDIO0_CLK, ®); + if ((reg & IO_CFG_PIN_MUX_MASK) == + io_cfg_pin_mux_sel(IO_CFG_PIN_MUX_TYPE_CLK_SD)) + bsp_set_sd_drv(host); + } else { + /* For mmc1: sdio wifi */ + bsp_set_sdio_drv(host); + } +} + +static void bsp_get_phase(struct sdhci_host *host) +{ + struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host); + unsigned int devid = bsp_priv->devid; + + if (devid == 0) { + /* For eMMC and SD card */ + if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400) { + bsp_priv->drv_phase = 9; /* 9 for 101.25 degree */ + bsp_priv->sampl_phase = bsp_priv->tuning_phase; + } else if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200) { + bsp_priv->drv_phase = 23; /* 23 for 258.75 degree */ + bsp_priv->sampl_phase = bsp_priv->tuning_phase; + } else if (host->mmc->ios.timing == MMC_TIMING_MMC_HS) { + bsp_priv->drv_phase = 16; /* 16 for 180 degree */ + bsp_priv->sampl_phase = 4; /* 4 for 45 degree */ + } else if (host->mmc->ios.timing == MMC_TIMING_SD_HS) { + bsp_priv->drv_phase = 20; /* 20 for 225 degree */ + bsp_priv->sampl_phase = 4; /* 4 for 45 degree */ + } else if (host->mmc->ios.timing == MMC_TIMING_LEGACY) { + bsp_priv->drv_phase = 16; /* 16 for 180 degree */ + bsp_priv->sampl_phase = 0; /* 0 for 0 degree */ + } else if (host->mmc->ios.timing == MMC_TIMING_MMC_DDR52) { + bsp_priv->drv_phase = 8; /* 8 for 90 degree */ + bsp_priv->sampl_phase = bsp_priv->tuning_phase; + } else { + bsp_priv->drv_phase = 16; /* 16 for 180 degree */ + bsp_priv->sampl_phase = 0; /* 0 for 0 degree */ + } + } else { + /* For SDIO device */ + if ((host->mmc->ios.timing == MMC_TIMING_SD_HS) || + (host->mmc->ios.timing == MMC_TIMING_UHS_SDR25)) { + bsp_priv->drv_phase = 16; /* 16 for 180 degree */ + bsp_priv->sampl_phase = 4; /* 4 for 45 degree */ + } else { + /* UHS_SDR12 */ + bsp_priv->drv_phase = 16; /* 16 for 180 degree */ + bsp_priv->sampl_phase = 0; /* 0 for 0 degree */ + } + } +} + +static int bsp_support_runtime_pm(struct sdhci_host *host) +{ + struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host); + unsigned int devid = bsp_priv->devid; + + /* Only enable for mmc0 eMMC and SD card */ + if (devid == 0) + return 1; + else + return 0; +} + +#include "sdhci-goke.c" +#endif \ No newline at end of file