Lines Matching +full:hs200 +full:- +full:cmd +full:- +full:int +full:- +full:delay

1 // SPDX-License-Identifier: GPL-2.0-only
8 * Date: 2016-8-24
12 #include <linux/delay.h>
17 #include "sdhci-pltfm.h"
18 #include "sdhci-xenon.h"
203 static int xenon_alloc_emmc_phy(struct sdhci_host *host) in xenon_alloc_emmc_phy()
209 params = devm_kzalloc(mmc_dev(host->mmc), sizeof(*params), GFP_KERNEL); in xenon_alloc_emmc_phy()
211 return -ENOMEM; in xenon_alloc_emmc_phy()
213 priv->phy_params = params; in xenon_alloc_emmc_phy()
214 if (priv->phy_type == EMMC_5_0_PHY) in xenon_alloc_emmc_phy()
215 priv->emmc_phy_regs = &xenon_emmc_5_0_phy_regs; in xenon_alloc_emmc_phy()
217 priv->emmc_phy_regs = &xenon_emmc_5_1_phy_regs; in xenon_alloc_emmc_phy()
222 static int xenon_check_stability_internal_clk(struct sdhci_host *host) in xenon_check_stability_internal_clk()
225 int err; in xenon_check_stability_internal_clk()
230 dev_err(mmc_dev(host->mmc), "phy_init: Internal clock never stabilized.\n"); in xenon_check_stability_internal_clk()
236 * eMMC 5.0/5.1 PHY init/re-init.
239 * 2. SDCLK is stopped and re-enabled.
240 * 3. config in emmc_phy_regs->timing_adj and emmc_phy_regs->func_ctrl
243 static int xenon_emmc_phy_init(struct sdhci_host *host) in xenon_emmc_phy_init()
249 struct xenon_emmc_phy_regs *phy_regs = priv->emmc_phy_regs; in xenon_emmc_phy_init()
251 int ret = xenon_check_stability_internal_clk(host); in xenon_emmc_phy_init()
256 reg = sdhci_readl(host, phy_regs->timing_adj); in xenon_emmc_phy_init()
258 sdhci_writel(host, reg, phy_regs->timing_adj); in xenon_emmc_phy_init()
276 clock = host->clock; in xenon_emmc_phy_init()
291 * Cap that with 100 delay loops so we won't get in xenon_emmc_phy_init()
298 false, host, phy_regs->timing_adj); in xenon_emmc_phy_init()
300 dev_err(mmc_dev(host->mmc), "eMMC PHY init cannot complete after %d us\n", in xenon_emmc_phy_init()
314 struct xenon_emmc_phy_params *params = priv->phy_params; in armada_3700_soc_pad_voltage_set()
316 if (params->pad_ctrl.pad_type == SOC_PAD_FIXED_1_8V) { in armada_3700_soc_pad_voltage_set()
317 writel(ARMADA_3700_SOC_PAD_1_8V, params->pad_ctrl.reg); in armada_3700_soc_pad_voltage_set()
318 } else if (params->pad_ctrl.pad_type == SOC_PAD_SD) { in armada_3700_soc_pad_voltage_set()
320 writel(ARMADA_3700_SOC_PAD_1_8V, params->pad_ctrl.reg); in armada_3700_soc_pad_voltage_set()
322 writel(ARMADA_3700_SOC_PAD_3_3V, params->pad_ctrl.reg); in armada_3700_soc_pad_voltage_set()
336 struct xenon_emmc_phy_params *params = priv->phy_params; in xenon_emmc_phy_set_soc_pad()
338 if (!params->pad_ctrl.reg) in xenon_emmc_phy_set_soc_pad()
341 if (params->pad_ctrl.set_soc_pad) in xenon_emmc_phy_set_soc_pad()
342 params->pad_ctrl.set_soc_pad(host, signal_voltage); in xenon_emmc_phy_set_soc_pad()
347 * DLL should be enabled and stable before HS200/SDR104 tuning,
350 static int xenon_emmc_phy_enable_dll(struct sdhci_host *host) in xenon_emmc_phy_enable_dll()
355 struct xenon_emmc_phy_regs *phy_regs = priv->emmc_phy_regs; in xenon_emmc_phy_enable_dll()
358 if (WARN_ON(host->clock <= MMC_HIGH_52_MAX_DTR)) in xenon_emmc_phy_enable_dll()
359 return -EINVAL; in xenon_emmc_phy_enable_dll()
361 reg = sdhci_readl(host, phy_regs->dll_ctrl); in xenon_emmc_phy_enable_dll()
366 reg = sdhci_readl(host, phy_regs->dll_ctrl); in xenon_emmc_phy_enable_dll()
380 reg |= phy_regs->dll_update; in xenon_emmc_phy_enable_dll()
381 if (priv->phy_type == EMMC_5_1_PHY) in xenon_emmc_phy_enable_dll()
383 sdhci_writel(host, reg, phy_regs->dll_ctrl); in xenon_emmc_phy_enable_dll()
394 dev_err(mmc_dev(host->mmc), "Wait for DLL Lock time-out\n"); in xenon_emmc_phy_enable_dll()
395 return -ETIMEDOUT; in xenon_emmc_phy_enable_dll()
406 static int xenon_emmc_phy_config_tuning(struct sdhci_host *host) in xenon_emmc_phy_config_tuning()
410 struct xenon_emmc_phy_params *params = priv->phy_params; in xenon_emmc_phy_config_tuning()
412 int ret; in xenon_emmc_phy_config_tuning()
414 if (host->clock <= MMC_HIGH_52_MAX_DTR) in xenon_emmc_phy_config_tuning()
415 return -EINVAL; in xenon_emmc_phy_config_tuning()
423 tuning_step = reg / params->tun_step_divider; in xenon_emmc_phy_config_tuning()
425 dev_warn(mmc_dev(host->mmc), in xenon_emmc_phy_config_tuning()
426 "HS200 TUNING_STEP %d is larger than MAX value\n", in xenon_emmc_phy_config_tuning()
435 reg |= (params->nr_tun_times << XENON_TUN_CONSECUTIVE_TIMES_SHIFT); in xenon_emmc_phy_config_tuning()
455 if (priv->phy_type == EMMC_5_0_PHY) { in xenon_emmc_phy_disable_strobe()
473 if (WARN_ON(host->timing != MMC_TIMING_MMC_HS400)) in xenon_emmc_phy_strobe_delay_adj()
476 if (host->clock <= MMC_HIGH_52_MAX_DTR) in xenon_emmc_phy_strobe_delay_adj()
479 dev_dbg(mmc_dev(host->mmc), "starts HS400 strobe delay adjustment\n"); in xenon_emmc_phy_strobe_delay_adj()
493 if (host->mmc->ios.enhanced_strobe) in xenon_emmc_phy_strobe_delay_adj()
498 if (priv->phy_type == EMMC_5_0_PHY) { in xenon_emmc_phy_strobe_delay_adj()
524 struct xenon_emmc_phy_params *params = priv->phy_params; in xenon_emmc_phy_slow_mode()
525 struct xenon_emmc_phy_regs *phy_regs = priv->emmc_phy_regs; in xenon_emmc_phy_slow_mode()
527 int ret; in xenon_emmc_phy_slow_mode()
529 if (host->clock > MMC_HIGH_52_MAX_DTR) in xenon_emmc_phy_slow_mode()
532 reg = sdhci_readl(host, phy_regs->timing_adj); in xenon_emmc_phy_slow_mode()
542 if (params->slow_mode) { in xenon_emmc_phy_slow_mode()
554 if ((priv->init_card_type == MMC_TYPE_SDIO) || in xenon_emmc_phy_slow_mode()
555 params->slow_mode) { in xenon_emmc_phy_slow_mode()
566 sdhci_writel(host, reg, phy_regs->timing_adj); in xenon_emmc_phy_slow_mode()
571 * Set-up eMMC 5.0/5.1 PHY.
580 struct xenon_emmc_phy_params *params = priv->phy_params; in xenon_emmc_phy_set()
581 struct xenon_emmc_phy_regs *phy_regs = priv->emmc_phy_regs; in xenon_emmc_phy_set()
583 dev_dbg(mmc_dev(host->mmc), "eMMC PHY setting starts\n"); in xenon_emmc_phy_set()
586 reg = sdhci_readl(host, phy_regs->pad_ctrl); in xenon_emmc_phy_set()
591 sdhci_writel(host, reg, phy_regs->pad_ctrl); in xenon_emmc_phy_set()
593 /* Set CMD and DQ Pull Up */ in xenon_emmc_phy_set()
594 if (priv->phy_type == EMMC_5_0_PHY) { in xenon_emmc_phy_set()
615 reg = sdhci_readl(host, phy_regs->timing_adj); in xenon_emmc_phy_set()
616 if (priv->init_card_type == MMC_TYPE_SDIO) in xenon_emmc_phy_set()
620 sdhci_writel(host, reg, phy_regs->timing_adj); in xenon_emmc_phy_set()
628 * Define them both in sdhci-xenon-emmc-phy.h. in xenon_emmc_phy_set()
630 reg = sdhci_readl(host, phy_regs->pad_ctrl2); in xenon_emmc_phy_set()
632 reg |= ((params->znr << XENON_ZNR_SHIFT) | params->zpr); in xenon_emmc_phy_set()
633 sdhci_writel(host, reg, phy_regs->pad_ctrl2); in xenon_emmc_phy_set()
643 reg = sdhci_readl(host, phy_regs->func_ctrl); in xenon_emmc_phy_set()
660 sdhci_writel(host, reg, phy_regs->func_ctrl); in xenon_emmc_phy_set()
669 sdhci_writel(host, phy_regs->logic_timing_val, in xenon_emmc_phy_set()
670 phy_regs->logic_timing_adj); in xenon_emmc_phy_set()
677 dev_dbg(mmc_dev(host->mmc), "eMMC PHY setting completes\n"); in xenon_emmc_phy_set()
680 static int get_dt_pad_ctrl_data(struct sdhci_host *host, in get_dt_pad_ctrl_data()
686 int ret = 0; in get_dt_pad_ctrl_data()
690 if (priv->hw_version == XENON_A3700) in get_dt_pad_ctrl_data()
691 params->pad_ctrl.set_soc_pad = armada_3700_soc_pad_voltage_set; in get_dt_pad_ctrl_data()
696 dev_err(mmc_dev(host->mmc), "Unable to find SoC PAD ctrl register address for %pOFn\n", in get_dt_pad_ctrl_data()
698 return -EINVAL; in get_dt_pad_ctrl_data()
701 params->pad_ctrl.reg = devm_ioremap_resource(mmc_dev(host->mmc), in get_dt_pad_ctrl_data()
703 if (IS_ERR(params->pad_ctrl.reg)) in get_dt_pad_ctrl_data()
704 return PTR_ERR(params->pad_ctrl.reg); in get_dt_pad_ctrl_data()
706 ret = of_property_read_string(np, "marvell,pad-type", &name); in get_dt_pad_ctrl_data()
708 dev_err(mmc_dev(host->mmc), "Unable to determine SoC PHY PAD ctrl type\n"); in get_dt_pad_ctrl_data()
712 params->pad_ctrl.pad_type = SOC_PAD_SD; in get_dt_pad_ctrl_data()
713 } else if (!strcmp(name, "fixed-1-8v")) { in get_dt_pad_ctrl_data()
714 params->pad_ctrl.pad_type = SOC_PAD_FIXED_1_8V; in get_dt_pad_ctrl_data()
716 dev_err(mmc_dev(host->mmc), "Unsupported SoC PHY PAD ctrl type %s\n", in get_dt_pad_ctrl_data()
718 return -EINVAL; in get_dt_pad_ctrl_data()
724 static int xenon_emmc_phy_parse_params(struct sdhci_host *host, in xenon_emmc_phy_parse_params()
730 params->slow_mode = false; in xenon_emmc_phy_parse_params()
731 if (device_property_read_bool(dev, "marvell,xenon-phy-slow-mode")) in xenon_emmc_phy_parse_params()
732 params->slow_mode = true; in xenon_emmc_phy_parse_params()
734 params->znr = XENON_ZNR_DEF_VALUE; in xenon_emmc_phy_parse_params()
735 if (!device_property_read_u32(dev, "marvell,xenon-phy-znr", &value)) in xenon_emmc_phy_parse_params()
736 params->znr = value & XENON_ZNR_MASK; in xenon_emmc_phy_parse_params()
738 params->zpr = XENON_ZPR_DEF_VALUE; in xenon_emmc_phy_parse_params()
739 if (!device_property_read_u32(dev, "marvell,xenon-phy-zpr", &value)) in xenon_emmc_phy_parse_params()
740 params->zpr = value & XENON_ZPR_MASK; in xenon_emmc_phy_parse_params()
742 params->nr_tun_times = XENON_TUN_CONSECUTIVE_TIMES; in xenon_emmc_phy_parse_params()
743 if (!device_property_read_u32(dev, "marvell,xenon-phy-nr-success-tun", in xenon_emmc_phy_parse_params()
745 params->nr_tun_times = value & XENON_TUN_CONSECUTIVE_TIMES_MASK; in xenon_emmc_phy_parse_params()
747 params->tun_step_divider = XENON_TUNING_STEP_DIVIDER; in xenon_emmc_phy_parse_params()
748 if (!device_property_read_u32(dev, "marvell,xenon-phy-tun-step-divider", in xenon_emmc_phy_parse_params()
750 params->tun_step_divider = value & 0xFF; in xenon_emmc_phy_parse_params()
752 if (dev->of_node) in xenon_emmc_phy_parse_params()
753 return get_dt_pad_ctrl_data(host, dev->of_node, params); in xenon_emmc_phy_parse_params()
767 * HS200/SDR104 set tuning config to prepare for tuning.
769 static int xenon_hs_delay_adj(struct sdhci_host *host) in xenon_hs_delay_adj()
771 int ret = 0; in xenon_hs_delay_adj()
773 if (WARN_ON(host->clock <= XENON_DEFAULT_SDCLK_FREQ)) in xenon_hs_delay_adj()
774 return -EINVAL; in xenon_hs_delay_adj()
776 switch (host->timing) { in xenon_hs_delay_adj()
786 * DDR Mode requires driver to scan Sampling Fixed Delay Line, in xenon_hs_delay_adj()
790 * Thus so far just keep PHY Sampling Fixed Delay in in xenon_hs_delay_adj()
796 dev_warn_once(mmc_dev(host->mmc), "Timing issue might occur in DDR mode\n"); in xenon_hs_delay_adj()
810 int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios) in xenon_phy_adj()
814 int ret = 0; in xenon_phy_adj()
816 if (!host->clock) { in xenon_phy_adj()
817 priv->clock = 0; in xenon_phy_adj()
824 * and adjust Xenon SDHC delay. in xenon_phy_adj()
826 if ((host->clock == priv->clock) && in xenon_phy_adj()
827 (ios->bus_width == priv->bus_width) && in xenon_phy_adj()
828 (ios->timing == priv->timing)) in xenon_phy_adj()
831 xenon_emmc_phy_set(host, ios->timing); in xenon_phy_adj()
834 priv->bus_width = ios->bus_width; in xenon_phy_adj()
836 priv->timing = ios->timing; in xenon_phy_adj()
837 priv->clock = host->clock; in xenon_phy_adj()
840 if (ios->timing == MMC_TIMING_LEGACY) in xenon_phy_adj()
843 if (host->clock > XENON_DEFAULT_SDCLK_FREQ) in xenon_phy_adj()
848 static int xenon_add_phy(struct device *dev, struct sdhci_host *host, in xenon_add_phy()
853 int ret; in xenon_add_phy()
855 priv->phy_type = match_string(phy_types, NR_PHY_TYPES, phy_name); in xenon_add_phy()
856 if (priv->phy_type < 0) { in xenon_add_phy()
857 dev_err(mmc_dev(host->mmc), in xenon_add_phy()
860 priv->phy_type = EMMC_5_1_PHY; in xenon_add_phy()
867 return xenon_emmc_phy_parse_params(host, dev, priv->phy_params); in xenon_add_phy()
870 int xenon_phy_parse_params(struct device *dev, struct sdhci_host *host) in xenon_phy_parse_params()
874 if (!device_property_read_string(dev, "marvell,xenon-phy-type", &phy_type)) in xenon_phy_parse_params()