mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +00:00
mmc: sdhci: Add support for HOST_CONTROL2 and setting UHS timings
The HOST_CONTROL2 register is a part of SDHC v3.00 and not just specific to arasan/zynq controllers. Add the same to sdhci.h. Also create a common API to set UHS timings in HOST_CONTROL2. Signed-off-by: Faiz Abbas <faiz_abbas@ti.com> Reviewed-by: Tom Rini <trini@konsulko.com>
This commit is contained in:
parent
5a6098fff0
commit
d1c0a2200a
3 changed files with 55 additions and 37 deletions
|
@ -534,6 +534,34 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
|
|||
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
|
||||
}
|
||||
|
||||
void sdhci_set_uhs_timing(struct sdhci_host *host)
|
||||
{
|
||||
struct mmc *mmc = (struct mmc *)host->mmc;
|
||||
u32 reg;
|
||||
|
||||
reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
|
||||
reg &= ~SDHCI_CTRL_UHS_MASK;
|
||||
|
||||
switch (mmc->selected_mode) {
|
||||
case UHS_SDR50:
|
||||
case MMC_HS_52:
|
||||
reg |= SDHCI_CTRL_UHS_SDR50;
|
||||
break;
|
||||
case UHS_DDR50:
|
||||
case MMC_DDR_52:
|
||||
reg |= SDHCI_CTRL_UHS_DDR50;
|
||||
break;
|
||||
case UHS_SDR104:
|
||||
case MMC_HS_200:
|
||||
reg |= SDHCI_CTRL_UHS_SDR104;
|
||||
break;
|
||||
default:
|
||||
reg |= SDHCI_CTRL_UHS_SDR12;
|
||||
}
|
||||
|
||||
sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DM_MMC
|
||||
static int sdhci_set_ios(struct udevice *dev)
|
||||
{
|
||||
|
|
|
@ -48,11 +48,6 @@ static const u8 mode2timing[] = {
|
|||
[MMC_HS_200] = MMC_HS200_BUS_SPEED,
|
||||
};
|
||||
|
||||
#define SDHCI_HOST_CTRL2 0x3E
|
||||
#define SDHCI_CTRL2_MODE_MASK 0x7
|
||||
#define SDHCI_18V_SIGNAL 0x8
|
||||
#define SDHCI_CTRL_EXEC_TUNING 0x0040
|
||||
#define SDHCI_CTRL_TUNED_CLK 0x80
|
||||
#define SDHCI_TUNING_LOOP_COUNT 40
|
||||
|
||||
static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
|
||||
|
@ -99,9 +94,9 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
|
|||
host = priv->host;
|
||||
deviceid = priv->deviceid;
|
||||
|
||||
ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
|
||||
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
|
||||
ctrl |= SDHCI_CTRL_EXEC_TUNING;
|
||||
sdhci_writew(host, ctrl, SDHCI_HOST_CTRL2);
|
||||
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
|
||||
|
||||
mdelay(1);
|
||||
|
||||
|
@ -133,7 +128,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
|
|||
sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
|
||||
|
||||
mmc_send_cmd(mmc, &cmd, NULL);
|
||||
ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
|
||||
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
|
||||
|
||||
if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
|
||||
udelay(1);
|
||||
|
@ -142,7 +137,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
|
|||
|
||||
if (tuning_loop_counter < 0) {
|
||||
ctrl &= ~SDHCI_CTRL_TUNED_CLK;
|
||||
sdhci_writel(host, ctrl, SDHCI_HOST_CTRL2);
|
||||
sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL2);
|
||||
}
|
||||
|
||||
if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
|
||||
|
@ -184,36 +179,14 @@ static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
|
|||
return;
|
||||
|
||||
if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
|
||||
reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
|
||||
reg |= SDHCI_18V_SIGNAL;
|
||||
sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
|
||||
reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
|
||||
reg |= SDHCI_CTRL_VDD_180;
|
||||
sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
|
||||
}
|
||||
|
||||
if (mmc->selected_mode > SD_HS &&
|
||||
mmc->selected_mode <= UHS_DDR50) {
|
||||
reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
|
||||
reg &= ~SDHCI_CTRL2_MODE_MASK;
|
||||
switch (mmc->selected_mode) {
|
||||
case UHS_SDR12:
|
||||
reg |= UHS_SDR12_BUS_SPEED;
|
||||
break;
|
||||
case UHS_SDR25:
|
||||
reg |= UHS_SDR25_BUS_SPEED;
|
||||
break;
|
||||
case UHS_SDR50:
|
||||
reg |= UHS_SDR50_BUS_SPEED;
|
||||
break;
|
||||
case UHS_SDR104:
|
||||
reg |= UHS_SDR104_BUS_SPEED;
|
||||
break;
|
||||
case UHS_DDR50:
|
||||
reg |= UHS_DDR50_BUS_SPEED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
|
||||
}
|
||||
mmc->selected_mode <= UHS_DDR50)
|
||||
sdhci_set_uhs_timing(host);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -144,7 +144,23 @@
|
|||
|
||||
#define SDHCI_ACMD12_ERR 0x3C
|
||||
|
||||
/* 3E-3F reserved */
|
||||
#define SDHCI_HOST_CONTROL2 0x3E
|
||||
#define SDHCI_CTRL_UHS_MASK 0x0007
|
||||
#define SDHCI_CTRL_UHS_SDR12 0x0000
|
||||
#define SDHCI_CTRL_UHS_SDR25 0x0001
|
||||
#define SDHCI_CTRL_UHS_SDR50 0x0002
|
||||
#define SDHCI_CTRL_UHS_SDR104 0x0003
|
||||
#define SDHCI_CTRL_UHS_DDR50 0x0004
|
||||
#define SDHCI_CTRL_HS400 0x0005 /* Non-standard */
|
||||
#define SDHCI_CTRL_VDD_180 0x0008
|
||||
#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030
|
||||
#define SDHCI_CTRL_DRV_TYPE_B 0x0000
|
||||
#define SDHCI_CTRL_DRV_TYPE_A 0x0010
|
||||
#define SDHCI_CTRL_DRV_TYPE_C 0x0020
|
||||
#define SDHCI_CTRL_DRV_TYPE_D 0x0030
|
||||
#define SDHCI_CTRL_EXEC_TUNING 0x0040
|
||||
#define SDHCI_CTRL_TUNED_CLK 0x0080
|
||||
#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000
|
||||
|
||||
#define SDHCI_CAPABILITIES 0x40
|
||||
#define SDHCI_TIMEOUT_CLK_MASK 0x0000003F
|
||||
|
@ -467,6 +483,7 @@ int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg);
|
|||
int add_sdhci(struct sdhci_host *host, u32 f_max, u32 f_min);
|
||||
#endif /* !CONFIG_BLK */
|
||||
|
||||
void sdhci_set_uhs_timing(struct sdhci_host *host);
|
||||
#ifdef CONFIG_DM_MMC
|
||||
/* Export the operations to drivers */
|
||||
int sdhci_probe(struct udevice *dev);
|
||||
|
|
Loading…
Reference in a new issue