From 11c07e41eba0e4911f27c7db8f1bc5ba12051ab8 Mon Sep 17 00:00:00 2001 From: Nan Li Date: Tue, 30 Oct 2018 19:33:47 +0800 Subject: [PATCH] sdio: optimize sd & wifi TDMA [1/1] PD#SWPL-1908 Problem: sdio wifi error TDMA. Solution: optimize host reg value set error. Verify: u211 & u212 Change-Id: I0e0d52ac2bce42cf163f0065d46badc938832a65 Signed-off-by: Nan Li --- arch/arm/boot/dts/amlogic/mesong12a.dtsi | 1 + arch/arm64/boot/dts/amlogic/mesong12a.dtsi | 1 + drivers/amlogic/mmc/aml_sd_emmc.c | 29 ++++++++++++++++++--- drivers/amlogic/mmc/aml_sd_emmc_v3.c | 42 ++++++++++++++++-------------- drivers/amlogic/mmc/amlsd.c | 17 ++++++------ drivers/amlogic/mmc/amlsd_of.c | 2 ++ include/linux/amlogic/sd.h | 2 ++ 7 files changed, 62 insertions(+), 32 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesong12a.dtsi b/arch/arm/boot/dts/amlogic/mesong12a.dtsi index 1f050dc..6adb61f 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a.dtsi @@ -1361,6 +1361,7 @@ /*caps defined in dts*/ tx_delay = <0>; co_phase = <3>; + calc_f = <1>; max_req_size = <0x20000>; /**128KB*/ gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index 378950d..b10dfba 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -1361,6 +1361,7 @@ /*caps defined in dts*/ tx_delay = <0>; co_phase = <3>; + calc_f = <1>; max_req_size = <0x20000>; /**128KB*/ gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index 4e6e178..365b461 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -1148,6 +1148,7 @@ void aml_sd_emmc_save_host_val(struct mmc_host *mmc) { u32 adj, dly1, dly2, intf3; u32 vconf = 0, vclkc = 0; + struct sd_emmc_clock_v3 *clkc = (struct sd_emmc_clock_v3 *)&(vclkc); struct sd_emmc_config *pconf = (struct sd_emmc_config *)&vconf; struct amlsd_platform *pdata = mmc_priv(mmc); struct amlsd_host *host = pdata->host; @@ -1166,6 +1167,7 @@ void aml_sd_emmc_save_host_val(struct mmc_host *mmc) && (pconf->stop_clk == pdata->stop_clk) && (mmc->actual_clock == clk_ios) && (vclkc == pdata->clkc) + && (clkc->irq_sdio_sleep == pdata->irq_sdio_sleep) && (adj == pdata->adj) && (dly1 == pdata->dly1) && (dly2 == pdata->dly2) @@ -1179,6 +1181,7 @@ void aml_sd_emmc_save_host_val(struct mmc_host *mmc) pconf->bl_len = pdata->bl_len; pconf->stop_clk = pdata->stop_clk; vclkc = pdata->clkc; + clkc->irq_sdio_sleep = pdata->irq_sdio_sleep; adj = pdata->adj; dly1 = pdata->dly1; dly2 = pdata->dly2; @@ -1915,7 +1918,7 @@ static void aml_sd_emmc_enable_sdio_irq(struct mmc_host *mmc, int enable) pclock->irq_sdio_sleep_ds = 0; writel(vclkc, host->base + SD_EMMC_CLOCK); } - pdata->clkc = vclkc; + pdata->irq_sdio_sleep = 1; if (enable) spin_unlock_irqrestore(&host->mrq_lock, flags); @@ -1952,6 +1955,7 @@ int meson_mmc_request_done(struct mmc_host *mmc, struct mmc_request *mrq) if (sdio_host) { if (pdata->xfer_pre) pdata->xfer_pre(mmc_priv(sdio_host)); + aml_sd_emmc_save_host_val(sdio_host); virqc = readl(host->base + SD_EMMC_IRQ_EN); if (irqc->irq_sdio != host->sdio_irqen) aml_sd_emmc_enable_sdio_irq(sdio_host, @@ -2611,9 +2615,9 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) pr_err("%s: warning... data crc, vstat:0x%x, virqc:%x", mmc_hostname(host->mmc), vstat, virqc); - pr_err("@ cmd %d with %p; stop %d, status %d\n", - mrq->cmd->opcode, mrq->data, - host->cmd_is_stop, + pr_err("@ cmd %d arg %x with %p; stop %d, status %d\n", + mrq->cmd->opcode, mrq->cmd->arg, + mrq->data, host->cmd_is_stop, host->status); } } else if (ista->desc_err) { @@ -2961,6 +2965,8 @@ static int aml_sd_emmc_card_busy(struct mmc_host *mmc) struct sd_emmc_status *ista = (struct sd_emmc_status *)&vstat; u32 vconf; struct sd_emmc_config *pconf = (struct sd_emmc_config *)&vconf; + u32 virqc = 0; + struct sd_emmc_irq_en *irqc = (struct sd_emmc_irq_en *)&virqc; if ((host->mem->start == host->data->port_b_base) && host->data->tdma_f @@ -2983,6 +2989,21 @@ static int aml_sd_emmc_card_busy(struct mmc_host *mmc) && host->data->tdma_f) host->init_volt = 0; } + + if ((host->mem->start == host->data->port_b_base) + && host->data->tdma_f + && strcmp(host->pinctrl_name, "sdio_")) { + if (sdio_host) { + if (pdata->xfer_pre) + pdata->xfer_pre(mmc_priv(sdio_host)); + aml_sd_emmc_save_host_val(sdio_host); + virqc = readl(host->base + SD_EMMC_IRQ_EN); + if (irqc->irq_sdio != host->sdio_irqen) + aml_sd_emmc_enable_sdio_irq(sdio_host, + host->sdio_irqen); + } + } + if ((host->mem->start == host->data->port_b_base) && host->data->tdma_f && (host->init_volt == 0)) diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index fac60fb..91df39d 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -45,10 +45,11 @@ int aml_fixdiv_calc(unsigned int *fixdiv, struct clock_lay_t *clk) { int ret = 0; - unsigned int full_div, source_cycle; /* in ns*/ - unsigned int sdclk_idx, todly_idx_max, todly_idx_min; - unsigned int inv_idx_min, inv_idx_max; - unsigned int val_idx_min, val_idx_max, val_idx_win, val_idx_sta; + unsigned int full_div = 0, source_cycle = 0; /* in ns*/ + unsigned int sdclk_idx = 0, todly_idx_max = 0, todly_idx_min = 0; + unsigned int inv_idx_min = 0, inv_idx_max = 0; + unsigned int val_idx_min = 0, val_idx_max = 0; + unsigned int val_idx_win = 0, val_idx_sta = 0; if (!fixdiv || !clk) return -EPERM; @@ -115,7 +116,6 @@ int meson_mmc_clk_init_v3(struct amlsd_host *host) u32 vconf = 0; struct sd_emmc_config *pconf = (struct sd_emmc_config *)&vconf; struct mmc_phase *init = &(host->data->sdmmc.init); - struct mmc_phase *calc = &(host->data->sdmmc.calc); writel(0, host->base + SD_EMMC_CLOCK_V3); #ifndef SD_EMMC_CLK_CTRL @@ -130,10 +130,6 @@ int meson_mmc_clk_init_v3(struct amlsd_host *host) pclkc->core_phase = init->core_phase; /* 2: 180 phase */ pclkc->rx_phase = init->rx_phase; pclkc->tx_phase = init->tx_phase; - if (host->data->chip_type >= MMC_CHIP_G12A) { - pclkc->core_phase = calc->core_phase; - pclkc->tx_phase = calc->tx_phase; - } pclkc->always_on = 1; /* Keep clock always on */ writel(vclkc, host->base + SD_EMMC_CLOCK_V3); @@ -216,7 +212,7 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, #else if (clk_ios == mmc->actual_clock) { pr_debug("[%s] clk_ios: %lu, return .............. clock: 0x%x\n", - __func__, clk_ios, + pdata->pinname, clk_ios, readl(host->base + SD_EMMC_CLOCK_V3)); return 0; } @@ -259,13 +255,13 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, } else mmc->actual_clock = clk_ios; - vclkc = readl(host->base + SD_EMMC_CLOCK_V3); - pdata->clk_lay.source = clk_get_rate(host->cfg_div_clk) * clkc->div; - pdata->clk_lay.core = clk_get_rate(host->cfg_div_clk); - - /* (re)start clock, if non-zero */ if (clk_ios) { + vclkc = readl(host->base + SD_EMMC_CLOCK_V3); + pdata->clk_lay.source + = clk_get_rate(host->cfg_div_clk) * clkc->div; + pdata->clk_lay.core = clk_get_rate(host->cfg_div_clk); + vcfg = readl(host->base + SD_EMMC_CFG); conf->stop_clk = 0; writel(vcfg, host->base + SD_EMMC_CFG); @@ -291,7 +287,7 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, struct sd_emmc_config *ctrl = (struct sd_emmc_config *)&vctrl; u32 vclkc = readl(host->base + SD_EMMC_CLOCK_V3); struct sd_emmc_clock_v3 *clkc = (struct sd_emmc_clock_v3 *)&vclkc; - u32 adjust; + u32 adjust = 0; struct sd_emmc_adjust_v3 *gadjust = (struct sd_emmc_adjust_v3 *)&adjust; u8 clk_div = 0; struct para_e *para = &(host->data->sdmmc); @@ -334,7 +330,7 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, /* overide co-phase by dts */ if (pdata->co_phase) clkc->core_phase = pdata->co_phase; - if (host->data->chip_type >= MMC_CHIP_G12A) { + if (pdata->calc_f) { clkc->core_phase = para->calc.core_phase; clkc->tx_phase = para->calc.tx_phase; } @@ -344,17 +340,23 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, } else if (timing == MMC_TIMING_SD_HS) { if (aml_card_type_non_sdio(pdata)) clkc->core_phase = para->sd_hs.core_phase; - if (host->data->chip_type >= MMC_CHIP_G12A) { + if (pdata->calc_f) { clkc->core_phase = para->calc.core_phase; clkc->tx_phase = para->calc.tx_phase; } } else if (timing == MMC_TIMING_UHS_SDR104) { clkc->core_phase = para->sdr104.core_phase; clkc->tx_phase = para->sdr104.tx_phase; - } else + } else { ctrl->ddr = 0; + /* timing == MMC_TIMING_LEGACY */ + if (pdata->calc_f) { + clkc->core_phase = para->calc.core_phase; + clkc->tx_phase = para->calc.tx_phase; + } + } - if (host->data->chip_type >= MMC_CHIP_G12A) { + if (pdata->calc_f) { if (timing <= MMC_TIMING_SD_HS) { ret = aml_fixdiv_calc(&fixdiv, &pdata->clk_lay); if (!ret) { diff --git a/drivers/amlogic/mmc/amlsd.c b/drivers/amlogic/mmc/amlsd.c index 83c98fa..eea5ccf 100644 --- a/drivers/amlogic/mmc/amlsd.c +++ b/drivers/amlogic/mmc/amlsd.c @@ -948,10 +948,6 @@ static int meson_cd_op(void *data) struct amlsd_host *host = pdata->host; int ret = 0; - if ((host->mem->start == host->data->port_b_base) - && host->data->tdma_f) - wait_for_completion(&host->drv_completion); - mutex_lock(&pdata->in_out_lock); if (card_dealed == 1) { card_dealed = 0; @@ -975,10 +971,6 @@ static int meson_cd_op(void *data) card_dealed = 0; - if ((host->mem->start == host->data->port_b_base) - && host->data->tdma_f) - complete(&host->drv_completion); - return 0; } @@ -986,8 +978,13 @@ void meson_mmc_cd_detect(struct work_struct *work) { struct amlsd_platform *pdata = container_of( work, struct amlsd_platform, cd_detect.work); + struct amlsd_host *host = pdata->host; int i = 0, ret = 0; + if ((host->mem->start == host->data->port_b_base) + && host->data->tdma_f) + wait_for_completion(&host->drv_completion); + for (i = 0; i < 5; i++) { ret = gpio_get_value(pdata->gpio_cd); if (pdata->gpio_cd_sta != ret) @@ -996,6 +993,10 @@ void meson_mmc_cd_detect(struct work_struct *work) mdelay(1); } schedule_delayed_work(&pdata->cd_detect, 50); + + if ((host->mem->start == host->data->port_b_base) + && host->data->tdma_f) + complete(&host->drv_completion); } #endif diff --git a/drivers/amlogic/mmc/amlsd_of.c b/drivers/amlogic/mmc/amlsd_of.c index 9e4bee0..0f94379 100644 --- a/drivers/amlogic/mmc/amlsd_of.c +++ b/drivers/amlogic/mmc/amlsd_of.c @@ -167,6 +167,8 @@ int amlsd_get_platform_data(struct platform_device *pdev, prop, pdata->power_level); SD_PARSE_GPIO_NUM_PROP(child, "gpio_power", str, pdata->gpio_power); + SD_PARSE_U32_PROP_DEC(child, "calc_f", + prop, pdata->calc_f); SD_PARSE_U32_PROP_DEC(child, "gpio_cd_level", prop, pdata->gpio_cd_level); diff --git a/include/linux/amlogic/sd.h b/include/linux/amlogic/sd.h index 0282f86..0d4e24d 100644 --- a/include/linux/amlogic/sd.h +++ b/include/linux/amlogic/sd.h @@ -278,6 +278,7 @@ struct amlsd_platform { unsigned int dly1; unsigned int dly2; unsigned int intf3; + unsigned int irq_sdio_sleep; unsigned int clock; /* signalling voltage (1.8V or 3.3V) */ unsigned char signal_voltage; @@ -294,6 +295,7 @@ struct amlsd_platform { unsigned int gpio_cd_sta; unsigned int gpio_power; unsigned int power_level; + unsigned int calc_f; unsigned int auto_clk_close; unsigned int vol_switch; -- 2.7.4