mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-21 06:31:31 +00:00
mmc: xenon: set signal voltage and max base clock
- The SDIO signal voltage and max base clock frequency setting are missing in driver, which causes SDIO not working. - The patch adds SDIO signal voltage switch support, which is based on regulator-gpio of vqmmc-supply, and sets the max base clock frequency. - Fix the zero clock value in call to sdhci_setup_cfg() function. Change-Id: I79c8860c65b8db166f4f70db56ede4097f71f1fa Signed-off-by: Evan Wang <xswang@marvell.com> Reviewed-on: http://vgitil04.il.marvell.com:8080/53589 Reviewed-by: Hua Jing <jinghua@marvell.com> Tested-by: Hua Jing <jinghua@marvell.com> [pali: Amended fixup patch] Signed-off-by: Pali Rohár <pali@kernel.org> Reviewed-by: Konstantin Porotchkin <kostap@marvell.com> Reviewed-by: Stefan Roese <sr@denx.de> Tested-by: Andre Heider <a.heider@gmail.com>
This commit is contained in:
parent
828d326216
commit
91b85e25b6
1 changed files with 78 additions and 1 deletions
|
@ -22,6 +22,7 @@
|
|||
#include <linux/libfdt.h>
|
||||
#include <malloc.h>
|
||||
#include <sdhci.h>
|
||||
#include <power/regulator.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -42,6 +43,14 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
#define SDHC_SYS_EXT_OP_CTRL 0x010C
|
||||
#define MASK_CMD_CONFLICT_ERROR BIT(8)
|
||||
|
||||
#define SDHC_SLOT_EMMC_CTRL 0x0130
|
||||
#define ENABLE_DATA_STROBE_SHIFT 24
|
||||
#define SET_EMMC_RSTN_SHIFT 16
|
||||
#define EMMC_VCCQ_MASK 0x3
|
||||
#define EMMC_VCCQ_1_8V 0x1
|
||||
#define EMMC_VCCQ_1_2V 0x2
|
||||
#define EMMC_VCCQ_3_3V 0x3
|
||||
|
||||
#define SDHC_SLOT_RETUNING_REQ_CTRL 0x0144
|
||||
/* retuning compatible */
|
||||
#define RETUNING_COMPATIBLE 0x1
|
||||
|
@ -108,6 +117,8 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
#define MMC_TIMING_MMC_HS400 10
|
||||
|
||||
#define XENON_MMC_MAX_CLK 400000000
|
||||
#define XENON_MMC_3V3_UV 3300000
|
||||
#define XENON_MMC_1V8_UV 1800000
|
||||
|
||||
enum soc_pad_ctrl_type {
|
||||
SOC_PAD_SD,
|
||||
|
@ -128,6 +139,8 @@ struct xenon_sdhci_priv {
|
|||
|
||||
void *pad_ctrl_reg;
|
||||
int pad_type;
|
||||
|
||||
struct udevice *vqmmc;
|
||||
};
|
||||
|
||||
static int xenon_mmc_phy_init(struct sdhci_host *host)
|
||||
|
@ -208,6 +221,51 @@ static void armada_3700_soc_pad_voltage_set(struct sdhci_host *host)
|
|||
writel(ARMADA_3700_SOC_PAD_3_3V, priv->pad_ctrl_reg);
|
||||
}
|
||||
|
||||
static int xenon_mmc_start_signal_voltage_switch(struct sdhci_host *host)
|
||||
{
|
||||
struct xenon_sdhci_priv *priv = host->mmc->priv;
|
||||
u8 voltage;
|
||||
u32 ctrl;
|
||||
int ret = 0;
|
||||
|
||||
/* If there is no vqmmc regulator, return */
|
||||
if (!priv->vqmmc)
|
||||
return 0;
|
||||
|
||||
if (priv->pad_type == SOC_PAD_FIXED_1_8V) {
|
||||
/* Switch to 1.8v */
|
||||
ret = regulator_set_value(priv->vqmmc,
|
||||
XENON_MMC_1V8_UV);
|
||||
} else if (priv->pad_type == SOC_PAD_SD) {
|
||||
/* Get voltage info */
|
||||
voltage = sdhci_readb(host, SDHCI_POWER_CONTROL);
|
||||
voltage &= ~SDHCI_POWER_ON;
|
||||
|
||||
if (voltage == SDHCI_POWER_330) {
|
||||
/* Switch to 3.3v */
|
||||
ret = regulator_set_value(priv->vqmmc,
|
||||
XENON_MMC_3V3_UV);
|
||||
} else {
|
||||
/* Switch to 1.8v */
|
||||
ret = regulator_set_value(priv->vqmmc,
|
||||
XENON_MMC_1V8_UV);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set VCCQ, eMMC mode: 1.8V; SD/SDIO mode: 3.3V */
|
||||
ctrl = sdhci_readl(host, SDHC_SLOT_EMMC_CTRL);
|
||||
if (IS_SD(host->mmc))
|
||||
ctrl |= EMMC_VCCQ_3_3V;
|
||||
else
|
||||
ctrl |= EMMC_VCCQ_1_8V;
|
||||
sdhci_writel(host, ctrl, SDHC_SLOT_EMMC_CTRL);
|
||||
|
||||
if (ret)
|
||||
printf("Signal voltage switch fail\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void xenon_mmc_phy_set(struct sdhci_host *host)
|
||||
{
|
||||
struct xenon_sdhci_priv *priv = host->mmc->priv;
|
||||
|
@ -334,6 +392,13 @@ static int xenon_sdhci_set_ios_post(struct sdhci_host *host)
|
|||
uint speed = host->mmc->tran_speed;
|
||||
int pwr_18v = 0;
|
||||
|
||||
/*
|
||||
* Signal Voltage Switching is only applicable for Host Controllers
|
||||
* v3.00 and above.
|
||||
*/
|
||||
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
|
||||
xenon_mmc_start_signal_voltage_switch(host);
|
||||
|
||||
if ((sdhci_readb(host, SDHCI_POWER_CONTROL) & ~SDHCI_POWER_ON) ==
|
||||
SDHCI_POWER_180)
|
||||
pwr_18v = 1;
|
||||
|
@ -394,6 +459,18 @@ static int xenon_sdhci_probe(struct udevice *dev)
|
|||
/* Set default timing */
|
||||
priv->timing = MMC_TIMING_LEGACY;
|
||||
|
||||
/* Get the vqmmc regulator if there is */
|
||||
device_get_supply_regulator(dev, "vqmmc-supply", &priv->vqmmc);
|
||||
/* Set the initial voltage value to 3.3V if there is regulator */
|
||||
if (priv->vqmmc) {
|
||||
ret = regulator_set_value(priv->vqmmc,
|
||||
XENON_MMC_3V3_UV);
|
||||
if (ret) {
|
||||
printf("Failed to set VQMMC regulator to 3.3V\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable auto clock gating during init */
|
||||
xenon_mmc_set_acg(host, false);
|
||||
|
||||
|
@ -426,7 +503,7 @@ static int xenon_sdhci_probe(struct udevice *dev)
|
|||
host->ops = &xenon_sdhci_ops;
|
||||
|
||||
host->max_clk = XENON_MMC_MAX_CLK;
|
||||
ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
|
||||
ret = sdhci_setup_cfg(&plat->cfg, host, XENON_MMC_MAX_CLK, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue