firmware/br-ext-chip-goke/board/gk7205v200/kernel/patches/00_drivers-mmc-host-sdhci-g...

500 lines
16 KiB
Diff

--- linux-4.9.37/drivers/mmc/host/sdhci-gk7202v300.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/sdhci-gk7202v300.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/reset.h>
+#include <linux/mmc/host.h>
+#include <linux/pm_runtime.h>
+#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 4
+#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_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
+};
+
+#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 0x0048
+#define REG_CTRL_SDIO1_CMD 0x004C
+#define REG_CTRL_SDIO1_DATA0 0x0064
+#define REG_CTRL_SDIO1_DATA1 0x0060
+#define REG_CTRL_SDIO1_DATA2 0x005C
+#define REG_CTRL_SDIO1_DATA3 0x0058
+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);
+}
+
+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, &reg);
+ 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);
+
+ 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, 0x2); /* 0x2 set drv level 2 */
+ for (i = 0; i < IO_CFG_SDIO1_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_sdio1_data_reg[i], 1, 0, 0, 0x2); /* 0x2 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, &reg);
+ 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, &reg);
+ 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