sdio: optimize sd & wifi TDMA [1/1]
authorNan Li <nan.li@amlogic.com>
Tue, 30 Oct 2018 11:33:47 +0000 (19:33 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Mon, 19 Nov 2018 02:07:03 +0000 (18:07 -0800)
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 <nan.li@amlogic.com>
arch/arm/boot/dts/amlogic/mesong12a.dtsi
arch/arm64/boot/dts/amlogic/mesong12a.dtsi
drivers/amlogic/mmc/aml_sd_emmc.c
drivers/amlogic/mmc/aml_sd_emmc_v3.c
drivers/amlogic/mmc/amlsd.c
drivers/amlogic/mmc/amlsd_of.c
include/linux/amlogic/sd.h

index 1f050dc..6adb61f 100644 (file)
                        /*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>;
index 378950d..b10dfba 100644 (file)
                        /*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>;
index 4e6e178..365b461 100644 (file)
@@ -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))
index fac60fb..91df39d 100644 (file)
 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) {
index 83c98fa..eea5ccf 100644 (file)
@@ -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
 
index 9e4bee0..0f94379 100644 (file)
@@ -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);
index 0282f86..0d4e24d 100644 (file)
@@ -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;