Merge branch 'master' of git://git.denx.de/u-boot-sh
- MMC fixes for R-Car Gen3
This commit is contained in:
commit
ec0d0d8742
@ -46,6 +46,54 @@
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
vcc_sdhi0: regulator-vcc-sdhi0 {
|
||||
compatible = "regulator-fixed";
|
||||
|
||||
regulator-name = "SDHI0 Vcc";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
|
||||
gpio = <&gpio5 17 GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
vccq_sdhi0: regulator-vccq-sdhi0 {
|
||||
compatible = "regulator-gpio";
|
||||
|
||||
regulator-name = "SDHI0 VccQ";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
|
||||
gpios = <&gpio5 18 GPIO_ACTIVE_HIGH>;
|
||||
gpios-states = <1>;
|
||||
states = <3300000 1
|
||||
1800000 0>;
|
||||
};
|
||||
|
||||
vcc_sdhi1: regulator-vcc-sdhi1 {
|
||||
compatible = "regulator-fixed";
|
||||
|
||||
regulator-name = "SDHI1 Vcc";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
|
||||
gpio = <&gpio0 4 GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
vccq_sdhi1: regulator-vccq-sdhi1 {
|
||||
compatible = "regulator-gpio";
|
||||
|
||||
regulator-name = "SDHI1 VccQ";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
|
||||
gpios = <&gpio3 15 GPIO_ACTIVE_HIGH>;
|
||||
gpios-states = <1>;
|
||||
states = <3300000 1
|
||||
1800000 0>;
|
||||
};
|
||||
};
|
||||
|
||||
&avb {
|
||||
@ -94,14 +142,38 @@
|
||||
function = "scif_clk";
|
||||
};
|
||||
|
||||
sdhi0_pins: sd0 {
|
||||
groups = "sdhi0_data4", "sdhi0_ctrl";
|
||||
function = "sdhi0";
|
||||
power-source = <3300>;
|
||||
};
|
||||
|
||||
sdhi0_pins_uhs: sd0_uhs {
|
||||
groups = "sdhi0_data4", "sdhi0_ctrl";
|
||||
function = "sdhi0";
|
||||
power-source = <1800>;
|
||||
};
|
||||
|
||||
sdhi1_pins: sd1 {
|
||||
groups = "sdhi1_data4", "sdhi1_ctrl";
|
||||
function = "sdhi1";
|
||||
power-source = <3300>;
|
||||
};
|
||||
|
||||
sdhi1_pins_uhs: sd1_uhs {
|
||||
groups = "sdhi1_data4", "sdhi1_ctrl";
|
||||
function = "sdhi1";
|
||||
power-source = <1800>;
|
||||
};
|
||||
|
||||
sdhi3_pins: sd2 {
|
||||
groups = "sdhi3_data8", "sdhi3_ctrl";
|
||||
groups = "sdhi3_data8", "sdhi3_ctrl", "sdhi3_ds";
|
||||
function = "sdhi3";
|
||||
power-source = <1800>;
|
||||
};
|
||||
|
||||
sdhi3_pins_uhs: sd2_uhs {
|
||||
groups = "sdhi3_data8", "sdhi3_ctrl";
|
||||
groups = "sdhi3_data8", "sdhi3_ctrl", "sdhi3_ds";
|
||||
function = "sdhi3";
|
||||
power-source = <1800>;
|
||||
};
|
||||
@ -120,11 +192,40 @@
|
||||
};
|
||||
|
||||
&sdhi0 {
|
||||
/* full size SD */
|
||||
pinctrl-0 = <&sdhi0_pins>;
|
||||
pinctrl-1 = <&sdhi0_pins_uhs>;
|
||||
pinctrl-names = "default", "state_uhs";
|
||||
|
||||
vmmc-supply = <&vcc_sdhi0>;
|
||||
vqmmc-supply = <&vccq_sdhi0>;
|
||||
cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
|
||||
wp-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
|
||||
bus-width = <4>;
|
||||
sd-uhs-sdr12;
|
||||
sd-uhs-sdr25;
|
||||
sd-uhs-sdr50;
|
||||
sd-uhs-sdr104;
|
||||
status = "okay";
|
||||
max-frequency = <208000000>;
|
||||
};
|
||||
|
||||
&sdhi1 {
|
||||
/* microSD */
|
||||
pinctrl-0 = <&sdhi1_pins>;
|
||||
pinctrl-1 = <&sdhi1_pins_uhs>;
|
||||
pinctrl-names = "default", "state_uhs";
|
||||
|
||||
vmmc-supply = <&vcc_sdhi1>;
|
||||
vqmmc-supply = <&vccq_sdhi1>;
|
||||
cd-gpios = <&gpio3 14 GPIO_ACTIVE_LOW>;
|
||||
bus-width = <4>;
|
||||
sd-uhs-sdr12;
|
||||
sd-uhs-sdr25;
|
||||
sd-uhs-sdr50;
|
||||
sd-uhs-sdr104;
|
||||
status = "okay";
|
||||
max-frequency = <208000000>;
|
||||
};
|
||||
|
||||
&sdhi3 {
|
||||
@ -137,6 +238,7 @@
|
||||
vqmmc-supply = <®_1p8v>;
|
||||
bus-width = <8>;
|
||||
mmc-hs200-1_8v;
|
||||
mmc-hs400-1_8v;
|
||||
non-removable;
|
||||
status = "okay";
|
||||
};
|
||||
|
@ -480,13 +480,13 @@
|
||||
};
|
||||
|
||||
sdhi2_pins: sd2 {
|
||||
groups = "sdhi2_data8", "sdhi2_ctrl";
|
||||
groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds";
|
||||
function = "sdhi2";
|
||||
power-source = <1800>;
|
||||
};
|
||||
|
||||
sdhi2_pins_uhs: sd2_uhs {
|
||||
groups = "sdhi2_data8", "sdhi2_ctrl";
|
||||
groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds";
|
||||
function = "sdhi2";
|
||||
power-source = <1800>;
|
||||
};
|
||||
@ -618,8 +618,13 @@
|
||||
cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
|
||||
wp-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
|
||||
bus-width = <4>;
|
||||
sd-uhs-sdr12;
|
||||
sd-uhs-sdr25;
|
||||
sd-uhs-sdr50;
|
||||
sd-uhs-sdr104;
|
||||
status = "okay";
|
||||
|
||||
max-frequency = <208000000>;
|
||||
};
|
||||
|
||||
&sdhi2 {
|
||||
@ -632,9 +637,11 @@
|
||||
vqmmc-supply = <®_1p8v>;
|
||||
bus-width = <8>;
|
||||
mmc-hs200-1_8v;
|
||||
mmc-hs400-1_8v;
|
||||
non-removable;
|
||||
fixed-emmc-driver-type = <1>;
|
||||
status = "okay";
|
||||
max-frequency = <200000000>;
|
||||
};
|
||||
|
||||
&sdhi3 {
|
||||
@ -647,8 +654,12 @@
|
||||
cd-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>;
|
||||
wp-gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>;
|
||||
bus-width = <4>;
|
||||
sd-uhs-sdr12;
|
||||
sd-uhs-sdr25;
|
||||
sd-uhs-sdr50;
|
||||
sd-uhs-sdr104;
|
||||
status = "okay";
|
||||
max-frequency = <208000000>;
|
||||
};
|
||||
|
||||
&ssi1 {
|
||||
|
@ -308,13 +308,13 @@
|
||||
};
|
||||
|
||||
sdhi2_pins: sd2 {
|
||||
groups = "sdhi2_data8", "sdhi2_ctrl";
|
||||
groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds";
|
||||
function = "sdhi2";
|
||||
power-source = <1800>;
|
||||
};
|
||||
|
||||
sdhi2_pins_uhs: sd2_uhs {
|
||||
groups = "sdhi2_data8", "sdhi2_ctrl";
|
||||
groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds";
|
||||
function = "sdhi2";
|
||||
power-source = <1800>;
|
||||
};
|
||||
@ -396,8 +396,12 @@
|
||||
vqmmc-supply = <&vccq_sdhi0>;
|
||||
cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
|
||||
bus-width = <4>;
|
||||
sd-uhs-sdr12;
|
||||
sd-uhs-sdr25;
|
||||
sd-uhs-sdr50;
|
||||
sd-uhs-sdr104;
|
||||
status = "okay";
|
||||
max-frequency = <208000000>;
|
||||
};
|
||||
|
||||
&sdhi2 {
|
||||
@ -410,8 +414,10 @@
|
||||
vqmmc-supply = <®_1p8v>;
|
||||
bus-width = <8>;
|
||||
mmc-hs200-1_8v;
|
||||
mmc-hs400-1_8v;
|
||||
non-removable;
|
||||
status = "okay";
|
||||
max-frequency = <200000000>;
|
||||
};
|
||||
|
||||
&ssi1 {
|
||||
|
@ -41,6 +41,7 @@ CONFIG_DM_MMC=y
|
||||
CONFIG_MMC_IO_VOLTAGE=y
|
||||
CONFIG_MMC_UHS_SUPPORT=y
|
||||
CONFIG_MMC_HS200_SUPPORT=y
|
||||
CONFIG_MMC_HS400_SUPPORT=y
|
||||
CONFIG_RENESAS_SDHI=y
|
||||
CONFIG_PHY_MICREL=y
|
||||
CONFIG_PHY_MICREL_KSZ90X1=y
|
||||
|
@ -41,6 +41,7 @@ CONFIG_DM_MMC=y
|
||||
CONFIG_MMC_IO_VOLTAGE=y
|
||||
CONFIG_MMC_UHS_SUPPORT=y
|
||||
CONFIG_MMC_HS200_SUPPORT=y
|
||||
CONFIG_MMC_HS400_SUPPORT=y
|
||||
CONFIG_RENESAS_SDHI=y
|
||||
CONFIG_PHY_MICREL=y
|
||||
CONFIG_PHY_MICREL_KSZ90X1=y
|
||||
|
@ -42,6 +42,7 @@ CONFIG_DM_MMC=y
|
||||
CONFIG_MMC_IO_VOLTAGE=y
|
||||
CONFIG_MMC_UHS_SUPPORT=y
|
||||
CONFIG_MMC_HS200_SUPPORT=y
|
||||
CONFIG_MMC_HS400_SUPPORT=y
|
||||
CONFIG_RENESAS_SDHI=y
|
||||
CONFIG_PHY_MICREL=y
|
||||
CONFIG_PHY_MICREL_KSZ90X1=y
|
||||
|
@ -42,6 +42,7 @@ CONFIG_DM_MMC=y
|
||||
CONFIG_MMC_IO_VOLTAGE=y
|
||||
CONFIG_MMC_UHS_SUPPORT=y
|
||||
CONFIG_MMC_HS200_SUPPORT=y
|
||||
CONFIG_MMC_HS400_SUPPORT=y
|
||||
CONFIG_RENESAS_SDHI=y
|
||||
CONFIG_PHY_MICREL=y
|
||||
CONFIG_PHY_MICREL_KSZ90X1=y
|
||||
|
@ -42,6 +42,7 @@ CONFIG_DM_MMC=y
|
||||
CONFIG_MMC_IO_VOLTAGE=y
|
||||
CONFIG_MMC_UHS_SUPPORT=y
|
||||
CONFIG_MMC_HS200_SUPPORT=y
|
||||
CONFIG_MMC_HS400_SUPPORT=y
|
||||
CONFIG_RENESAS_SDHI=y
|
||||
CONFIG_PHY_MICREL=y
|
||||
CONFIG_PHY_MICREL_KSZ90X1=y
|
||||
|
@ -42,6 +42,7 @@ CONFIG_DM_MMC=y
|
||||
CONFIG_MMC_IO_VOLTAGE=y
|
||||
CONFIG_MMC_UHS_SUPPORT=y
|
||||
CONFIG_MMC_HS200_SUPPORT=y
|
||||
CONFIG_MMC_HS400_SUPPORT=y
|
||||
CONFIG_RENESAS_SDHI=y
|
||||
CONFIG_PHY_MICREL=y
|
||||
CONFIG_PHY_MICREL_KSZ90X1=y
|
||||
|
@ -107,7 +107,7 @@ static int gen3_clk_get_parent(struct gen3_clk_priv *priv, struct clk *clk,
|
||||
return renesas_clk_get_parent(clk, info, parent);
|
||||
}
|
||||
|
||||
static int gen3_clk_setup_sdif_div(struct clk *clk)
|
||||
static int gen3_clk_setup_sdif_div(struct clk *clk, ulong rate)
|
||||
{
|
||||
struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
struct cpg_mssr_info *info = priv->info;
|
||||
@ -133,7 +133,7 @@ static int gen3_clk_setup_sdif_div(struct clk *clk)
|
||||
|
||||
debug("%s[%i] SDIF offset=%x\n", __func__, __LINE__, core->offset);
|
||||
|
||||
writel(1, priv->base + core->offset);
|
||||
writel((rate == 400000000) ? 0x4 : 0x1, priv->base + core->offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -141,10 +141,6 @@ static int gen3_clk_setup_sdif_div(struct clk *clk)
|
||||
static int gen3_clk_enable(struct clk *clk)
|
||||
{
|
||||
struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
int ret = gen3_clk_setup_sdif_div(clk);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return renesas_clk_endisable(clk, priv->base, true);
|
||||
}
|
||||
@ -328,7 +324,7 @@ static ulong gen3_clk_get_rate(struct clk *clk)
|
||||
static ulong gen3_clk_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
/* Force correct SD-IF divider configuration if applicable */
|
||||
gen3_clk_setup_sdif_div(clk);
|
||||
gen3_clk_setup_sdif_div(clk, rate);
|
||||
return gen3_clk_get_rate64(clk);
|
||||
}
|
||||
|
||||
|
@ -166,6 +166,10 @@ int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg)
|
||||
cfg->host_caps |= MMC_CAP(MMC_HS_200);
|
||||
if (dev_read_bool(dev, "mmc-hs200-1_2v"))
|
||||
cfg->host_caps |= MMC_CAP(MMC_HS_200);
|
||||
if (dev_read_bool(dev, "mmc-hs400-1_8v"))
|
||||
cfg->host_caps |= MMC_CAP(MMC_HS_400);
|
||||
if (dev_read_bool(dev, "mmc-hs400-1_2v"))
|
||||
cfg->host_caps |= MMC_CAP(MMC_HS_400);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -17,7 +17,9 @@
|
||||
|
||||
#include "tmio-common.h"
|
||||
|
||||
#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
|
||||
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
|
||||
|
||||
/* SCC registers */
|
||||
#define RENESAS_SDHI_SCC_DTCNTL 0x800
|
||||
@ -107,6 +109,56 @@ static void renesas_sdhi_reset_tuning(struct tmio_sd_priv *priv)
|
||||
tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL);
|
||||
}
|
||||
|
||||
static int renesas_sdhi_hs400(struct udevice *dev)
|
||||
{
|
||||
struct tmio_sd_priv *priv = dev_get_priv(dev);
|
||||
struct mmc *mmc = mmc_get_mmc_dev(dev);
|
||||
bool hs400 = (mmc->selected_mode == MMC_HS_400);
|
||||
int ret, taps = hs400 ? priv->nrtaps : 8;
|
||||
u32 reg;
|
||||
|
||||
if (taps == 4) /* HS400 on 4tap SoC needs different clock */
|
||||
ret = clk_set_rate(&priv->clk, 400000000);
|
||||
else
|
||||
ret = clk_set_rate(&priv->clk, 200000000);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_RVSREQ);
|
||||
|
||||
reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_TMPPORT2);
|
||||
if (hs400) {
|
||||
reg |= RENESAS_SDHI_SCC_TMPPORT2_HS400EN |
|
||||
RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL;
|
||||
} else {
|
||||
reg &= ~(RENESAS_SDHI_SCC_TMPPORT2_HS400EN |
|
||||
RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL);
|
||||
}
|
||||
|
||||
tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_TMPPORT2);
|
||||
|
||||
tmio_sd_writel(priv, (taps << RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) |
|
||||
RENESAS_SDHI_SCC_DTCNTL_TAPEN,
|
||||
RENESAS_SDHI_SCC_DTCNTL);
|
||||
|
||||
if (taps == 4) {
|
||||
tmio_sd_writel(priv, priv->tap_set >> 1,
|
||||
RENESAS_SDHI_SCC_TAPSET);
|
||||
} else {
|
||||
tmio_sd_writel(priv, priv->tap_set, RENESAS_SDHI_SCC_TAPSET);
|
||||
}
|
||||
|
||||
reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_CKSEL);
|
||||
reg |= RENESAS_SDHI_SCC_CKSEL_DTSEL;
|
||||
tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_CKSEL);
|
||||
|
||||
reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSCNTL);
|
||||
reg |= RENESAS_SDHI_SCC_RVSCNTL_RVSEN;
|
||||
tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void renesas_sdhi_prepare_tuning(struct tmio_sd_priv *priv,
|
||||
unsigned long tap)
|
||||
{
|
||||
@ -125,7 +177,6 @@ static int renesas_sdhi_select_tuning(struct tmio_sd_priv *priv,
|
||||
unsigned int smpcmp)
|
||||
{
|
||||
unsigned long tap_cnt; /* counter of tuning success */
|
||||
unsigned long tap_set; /* tap position */
|
||||
unsigned long tap_start;/* start position of tuning success */
|
||||
unsigned long tap_end; /* end position of tuning success */
|
||||
unsigned long ntap; /* temporary counter of tuning success */
|
||||
@ -209,12 +260,12 @@ static int renesas_sdhi_select_tuning(struct tmio_sd_priv *priv,
|
||||
select = true;
|
||||
|
||||
if (select)
|
||||
tap_set = ((tap_start + tap_end) / 2) % tap_num;
|
||||
priv->tap_set = ((tap_start + tap_end) / 2) % tap_num;
|
||||
else
|
||||
return -EIO;
|
||||
|
||||
/* Set SCC */
|
||||
tmio_sd_writel(priv, tap_set, RENESAS_SDHI_SCC_TAPSET);
|
||||
tmio_sd_writel(priv, priv->tap_set, RENESAS_SDHI_SCC_TAPSET);
|
||||
|
||||
/* Enable auto re-tuning */
|
||||
reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSCNTL);
|
||||
@ -240,6 +291,7 @@ int renesas_sdhi_execute_tuning(struct udevice *dev, uint opcode)
|
||||
|
||||
/* clock tuning is not needed for upto 52MHz */
|
||||
if (!((mmc->selected_mode == MMC_HS_200) ||
|
||||
(mmc->selected_mode == MMC_HS_400) ||
|
||||
(mmc->selected_mode == UHS_SDR104) ||
|
||||
(mmc->selected_mode == UHS_SDR50)))
|
||||
return 0;
|
||||
@ -287,19 +339,42 @@ out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static int renesas_sdhi_hs400(struct udevice *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int renesas_sdhi_set_ios(struct udevice *dev)
|
||||
{
|
||||
int ret = tmio_sd_set_ios(dev);
|
||||
struct tmio_sd_priv *priv = dev_get_priv(dev);
|
||||
u32 tmp;
|
||||
int ret;
|
||||
|
||||
/* Stop the clock before changing its rate to avoid a glitch signal */
|
||||
tmp = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
|
||||
tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
|
||||
tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
|
||||
|
||||
ret = renesas_sdhi_hs400(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = tmio_sd_set_ios(dev);
|
||||
|
||||
mdelay(10);
|
||||
|
||||
#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
|
||||
struct tmio_sd_priv *priv = dev_get_priv(dev);
|
||||
|
||||
if (priv->caps & TMIO_SD_CAP_RCAR_UHS)
|
||||
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
|
||||
struct mmc *mmc = mmc_get_mmc_dev(dev);
|
||||
if ((priv->caps & TMIO_SD_CAP_RCAR_UHS) &&
|
||||
(mmc->selected_mode != UHS_SDR104) &&
|
||||
(mmc->selected_mode != MMC_HS_200) &&
|
||||
(mmc->selected_mode != MMC_HS_400)) {
|
||||
renesas_sdhi_reset_tuning(priv);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
@ -331,7 +406,9 @@ static const struct dm_mmc_ops renesas_sdhi_ops = {
|
||||
.send_cmd = tmio_sd_send_cmd,
|
||||
.set_ios = renesas_sdhi_set_ios,
|
||||
.get_cd = tmio_sd_get_cd,
|
||||
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
|
||||
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
|
||||
.execute_tuning = renesas_sdhi_execute_tuning,
|
||||
#endif
|
||||
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
|
||||
@ -358,15 +435,45 @@ static const struct udevice_id renesas_sdhi_match[] = {
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static ulong renesas_sdhi_clk_get_rate(struct tmio_sd_priv *priv)
|
||||
{
|
||||
return clk_get_rate(&priv->clk);
|
||||
}
|
||||
|
||||
static void renesas_sdhi_filter_caps(struct udevice *dev)
|
||||
{
|
||||
struct tmio_sd_plat *plat = dev_get_platdata(dev);
|
||||
struct tmio_sd_priv *priv = dev_get_priv(dev);
|
||||
|
||||
if (!(priv->caps & TMIO_SD_CAP_RCAR_GEN3))
|
||||
return;
|
||||
|
||||
/* HS400 is not supported on H3 ES1.x and M3W ES1.0,ES1.1 */
|
||||
if (((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7795) &&
|
||||
(rmobile_get_cpu_rev_integer() <= 1)) ||
|
||||
((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7796) &&
|
||||
(rmobile_get_cpu_rev_integer() == 1) &&
|
||||
(rmobile_get_cpu_rev_fraction() <= 1)))
|
||||
plat->cfg.host_caps &= ~MMC_MODE_HS400;
|
||||
|
||||
/* H3 ES2.0 uses 4 tuning taps */
|
||||
if ((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7795) &&
|
||||
(rmobile_get_cpu_rev_integer() == 2))
|
||||
priv->nrtaps = 4;
|
||||
else
|
||||
priv->nrtaps = 8;
|
||||
}
|
||||
|
||||
static int renesas_sdhi_probe(struct udevice *dev)
|
||||
{
|
||||
struct tmio_sd_priv *priv = dev_get_priv(dev);
|
||||
u32 quirks = dev_get_driver_data(dev);
|
||||
struct fdt_resource reg_res;
|
||||
struct clk clk;
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
int ret;
|
||||
|
||||
priv->clk_get_rate = renesas_sdhi_clk_get_rate;
|
||||
|
||||
if (quirks == RENESAS_GEN2_QUIRKS) {
|
||||
ret = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev),
|
||||
"reg", 0, ®_res);
|
||||
@ -380,29 +487,33 @@ static int renesas_sdhi_probe(struct udevice *dev)
|
||||
quirks |= TMIO_SD_CAP_16BIT;
|
||||
}
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &clk);
|
||||
ret = clk_get_by_index(dev, 0, &priv->clk);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to get host clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set to max rate */
|
||||
priv->mclk = clk_set_rate(&clk, ULONG_MAX);
|
||||
if (IS_ERR_VALUE(priv->mclk)) {
|
||||
ret = clk_set_rate(&priv->clk, 200000000);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to set rate for host clock\n");
|
||||
clk_free(&clk);
|
||||
return priv->mclk;
|
||||
clk_free(&priv->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_enable(&clk);
|
||||
clk_free(&clk);
|
||||
ret = clk_enable(&priv->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable host clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = tmio_sd_probe(dev, quirks);
|
||||
#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
|
||||
|
||||
renesas_sdhi_filter_caps(dev);
|
||||
|
||||
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
|
||||
if (!ret && (priv->caps & TMIO_SD_CAP_RCAR_UHS))
|
||||
renesas_sdhi_reset_tuning(priv);
|
||||
#endif
|
||||
|
@ -555,55 +555,76 @@ static void tmio_sd_set_ddr_mode(struct tmio_sd_priv *priv,
|
||||
tmio_sd_writel(priv, tmp, TMIO_SD_IF_MODE);
|
||||
}
|
||||
|
||||
static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv,
|
||||
struct mmc *mmc)
|
||||
static ulong tmio_sd_clk_get_rate(struct tmio_sd_priv *priv)
|
||||
{
|
||||
return priv->clk_get_rate(priv);
|
||||
}
|
||||
|
||||
static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv, struct mmc *mmc)
|
||||
{
|
||||
unsigned int divisor;
|
||||
u32 val, tmp;
|
||||
u32 tmp, val = 0;
|
||||
ulong mclk;
|
||||
|
||||
if (!mmc->clock)
|
||||
return;
|
||||
if (mmc->clock) {
|
||||
mclk = tmio_sd_clk_get_rate(priv);
|
||||
|
||||
divisor = DIV_ROUND_UP(priv->mclk, mmc->clock);
|
||||
divisor = DIV_ROUND_UP(mclk, mmc->clock);
|
||||
|
||||
if (divisor <= 1)
|
||||
val = (priv->caps & TMIO_SD_CAP_RCAR) ?
|
||||
TMIO_SD_CLKCTL_RCAR_DIV1 : TMIO_SD_CLKCTL_DIV1;
|
||||
else if (divisor <= 2)
|
||||
val = TMIO_SD_CLKCTL_DIV2;
|
||||
else if (divisor <= 4)
|
||||
val = TMIO_SD_CLKCTL_DIV4;
|
||||
else if (divisor <= 8)
|
||||
val = TMIO_SD_CLKCTL_DIV8;
|
||||
else if (divisor <= 16)
|
||||
val = TMIO_SD_CLKCTL_DIV16;
|
||||
else if (divisor <= 32)
|
||||
val = TMIO_SD_CLKCTL_DIV32;
|
||||
else if (divisor <= 64)
|
||||
val = TMIO_SD_CLKCTL_DIV64;
|
||||
else if (divisor <= 128)
|
||||
val = TMIO_SD_CLKCTL_DIV128;
|
||||
else if (divisor <= 256)
|
||||
val = TMIO_SD_CLKCTL_DIV256;
|
||||
else if (divisor <= 512 || !(priv->caps & TMIO_SD_CAP_DIV1024))
|
||||
val = TMIO_SD_CLKCTL_DIV512;
|
||||
else
|
||||
val = TMIO_SD_CLKCTL_DIV1024;
|
||||
/* Do not set divider to 0xff in DDR mode */
|
||||
if (mmc->ddr_mode && (divisor == 1))
|
||||
divisor = 2;
|
||||
|
||||
if (divisor <= 1)
|
||||
val = (priv->caps & TMIO_SD_CAP_RCAR) ?
|
||||
TMIO_SD_CLKCTL_RCAR_DIV1 : TMIO_SD_CLKCTL_DIV1;
|
||||
else if (divisor <= 2)
|
||||
val = TMIO_SD_CLKCTL_DIV2;
|
||||
else if (divisor <= 4)
|
||||
val = TMIO_SD_CLKCTL_DIV4;
|
||||
else if (divisor <= 8)
|
||||
val = TMIO_SD_CLKCTL_DIV8;
|
||||
else if (divisor <= 16)
|
||||
val = TMIO_SD_CLKCTL_DIV16;
|
||||
else if (divisor <= 32)
|
||||
val = TMIO_SD_CLKCTL_DIV32;
|
||||
else if (divisor <= 64)
|
||||
val = TMIO_SD_CLKCTL_DIV64;
|
||||
else if (divisor <= 128)
|
||||
val = TMIO_SD_CLKCTL_DIV128;
|
||||
else if (divisor <= 256)
|
||||
val = TMIO_SD_CLKCTL_DIV256;
|
||||
else if (divisor <= 512 || !(priv->caps & TMIO_SD_CAP_DIV1024))
|
||||
val = TMIO_SD_CLKCTL_DIV512;
|
||||
else
|
||||
val = TMIO_SD_CLKCTL_DIV1024;
|
||||
}
|
||||
|
||||
tmp = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
|
||||
if (tmp & TMIO_SD_CLKCTL_SCLKEN &&
|
||||
(tmp & TMIO_SD_CLKCTL_DIV_MASK) == val)
|
||||
return;
|
||||
if (mmc->clock &&
|
||||
!((tmp & TMIO_SD_CLKCTL_SCLKEN) &&
|
||||
((tmp & TMIO_SD_CLKCTL_DIV_MASK) == val))) {
|
||||
/*
|
||||
* Stop the clock before changing its rate
|
||||
* to avoid a glitch signal
|
||||
*/
|
||||
tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
|
||||
tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
|
||||
|
||||
/* stop the clock before changing its rate to avoid a glitch signal */
|
||||
tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
|
||||
tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
|
||||
/* Change the clock rate. */
|
||||
tmp &= ~TMIO_SD_CLKCTL_DIV_MASK;
|
||||
tmp |= val;
|
||||
}
|
||||
|
||||
tmp &= ~TMIO_SD_CLKCTL_DIV_MASK;
|
||||
tmp |= val | TMIO_SD_CLKCTL_OFFEN;
|
||||
tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
|
||||
/* Enable or Disable the clock */
|
||||
if (mmc->clk_disable) {
|
||||
tmp |= TMIO_SD_CLKCTL_OFFEN;
|
||||
tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
|
||||
} else {
|
||||
tmp &= ~TMIO_SD_CLKCTL_OFFEN;
|
||||
tmp |= TMIO_SD_CLKCTL_SCLKEN;
|
||||
}
|
||||
|
||||
tmp |= TMIO_SD_CLKCTL_SCLKEN;
|
||||
tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
|
||||
|
||||
udelay(1000);
|
||||
@ -708,6 +729,7 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
|
||||
struct tmio_sd_priv *priv = dev_get_priv(dev);
|
||||
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
|
||||
fdt_addr_t base;
|
||||
ulong mclk;
|
||||
int ret;
|
||||
|
||||
base = devfdt_get_addr(dev);
|
||||
@ -750,10 +772,12 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
|
||||
|
||||
tmio_sd_host_init(priv);
|
||||
|
||||
mclk = tmio_sd_clk_get_rate(priv);
|
||||
|
||||
plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
|
||||
plat->cfg.f_min = priv->mclk /
|
||||
plat->cfg.f_min = mclk /
|
||||
(priv->caps & TMIO_SD_CAP_DIV1024 ? 1024 : 512);
|
||||
plat->cfg.f_max = priv->mclk;
|
||||
plat->cfg.f_max = mclk;
|
||||
plat->cfg.b_max = U32_MAX; /* max value of TMIO_SD_SECCNT */
|
||||
|
||||
upriv->mmc = &plat->mmc;
|
||||
|
@ -117,7 +117,6 @@ struct tmio_sd_plat {
|
||||
|
||||
struct tmio_sd_priv {
|
||||
void __iomem *regbase;
|
||||
unsigned long mclk;
|
||||
unsigned int version;
|
||||
u32 caps;
|
||||
#define TMIO_SD_CAP_NONREMOVABLE BIT(0) /* Nonremovable e.g. eMMC */
|
||||
@ -133,6 +132,14 @@ struct tmio_sd_priv {
|
||||
#ifdef CONFIG_DM_REGULATOR
|
||||
struct udevice *vqmmc_dev;
|
||||
#endif
|
||||
#if CONFIG_IS_ENABLED(CLK)
|
||||
struct clk clk;
|
||||
#endif
|
||||
#if CONFIG_IS_ENABLED(RENESAS_SDHI)
|
||||
u8 tap_set;
|
||||
u8 nrtaps;
|
||||
#endif
|
||||
ulong (*clk_get_rate)(struct tmio_sd_priv *);
|
||||
};
|
||||
|
||||
int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
|
||||
|
@ -31,35 +31,45 @@ static const struct udevice_id uniphier_sd_match[] = {
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static ulong uniphier_sd_clk_get_rate(struct tmio_sd_priv *priv)
|
||||
{
|
||||
#if CONFIG_IS_ENABLED(CLK)
|
||||
return clk_get_rate(&priv->clk);
|
||||
#elif CONFIG_SPL_BUILD
|
||||
return 100000000;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int uniphier_sd_probe(struct udevice *dev)
|
||||
{
|
||||
struct tmio_sd_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->clk_get_rate = uniphier_sd_clk_get_rate;
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
struct clk clk;
|
||||
int ret;
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &clk);
|
||||
ret = clk_get_by_index(dev, 0, &priv->clk);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to get host clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set to max rate */
|
||||
priv->mclk = clk_set_rate(&clk, ULONG_MAX);
|
||||
if (IS_ERR_VALUE(priv->mclk)) {
|
||||
ret = clk_set_rate(&priv->clk, ULONG_MAX);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to set rate for host clock\n");
|
||||
clk_free(&clk);
|
||||
return priv->mclk;
|
||||
clk_free(&priv->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_enable(&clk);
|
||||
clk_free(&clk);
|
||||
ret = clk_enable(&priv->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable host clock\n");
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
priv->mclk = 100000000;
|
||||
#endif
|
||||
|
||||
return tmio_sd_probe(dev, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user