Lines Matching +full:xenon +full:- +full:phy +full:- +full:nr +full:- +full:success +full:- +full:tun
1 // SPDX-License-Identifier: GPL-2.0-only
3 * PHY support for Xenon SDHC
8 * Date: 2016-8-24
17 #include "sdhci-pltfm.h"
18 #include "sdhci-xenon.h"
20 /* Register base for eMMC PHY 5.0 Version */
22 /* Register base for eMMC PHY 5.1 Version */
116 * List offset of PHY registers and some special register values
117 * in eMMC PHY 5.0 or eMMC PHY 5.1
139 "emmc 5.0 phy",
140 "emmc 5.1 phy"
155 /* Register address of SoC PHY PAD ctrl */
157 /* SoC PHY PAD ctrl type */
159 /* SoC specific operation to set SoC PHY PAD */
187 * eMMC PHY configuration and operations
195 /* Nr of consecutive Sampling Points of a Valid Sampling Window */
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()
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.
237 * eMMC PHY init should be executed after:
239 * 2. SDCLK is stopped and re-enabled.
240 * 3. config in emmc_phy_regs->timing_adj and emmc_phy_regs->func_ctrl
249 struct xenon_emmc_phy_regs *phy_regs = priv->emmc_phy_regs; 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()
269 /* Add duration of waiting for PHY */ in xenon_emmc_phy_init()
276 clock = host->clock; 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()
327 * Set SoC PHY voltage PAD control register,
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()
346 * Enable eMMC PHY HW 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()
403 * Config to eMMC PHY to prepare for tuning.
410 struct xenon_emmc_phy_params *params = priv->phy_params; 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()
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()
488 * Xenon Enhanced Strobe should be enabled only when 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()
512 * If eMMC PHY Slow Mode is required in lower speed mode (SDCLK < 55MHz)
513 * in SDR mode, enable Slow Mode to bypass eMMC PHY.
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()
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()
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()
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()
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()
757 /* Set SoC PHY Voltage PAD */
765 * Setting PHY when card is working in High Speed Mode.
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()
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()
804 * Adjust PHY setting.
805 * PHY setting should be adjusted when SDCLK frequency, Bus Width
816 if (!host->clock) { in xenon_phy_adj()
817 priv->clock = 0; in xenon_phy_adj()
823 * better to set eMMC PHY based on current setting 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()
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()
858 "Unable to determine PHY name %s. Use default eMMC 5.1 PHY\n", 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()
874 if (!device_property_read_string(dev, "marvell,xenon-phy-type", &phy_type)) in xenon_phy_parse_params()
877 return xenon_add_phy(dev, host, "emmc 5.1 phy"); in xenon_phy_parse_params()