mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
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 <nan.li@amlogic.com>
This commit is contained in:
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user