MMC core:
- Fix host controller programming for eMMC fixed driver type MMC host: - dw_mmc-rockchip: Add missing private data for very old controllers - litex_mmc: Fix clock management - renesas_sdhi: Add OF entry for RZ/G2H SoC - sdhci: Manage signal voltage switch during system resume for some hosts - sdhci-of-dwcmshc: Fix reset, clk and SDIO support for Eswin EIC7700 -----BEGIN PGP SIGNATURE----- iQJEBAABCgAuFiEEugLDXPmKSktSkQsV/iaEJXNYjCkFAmof3pUQHHVsZmhAa2Vy bmVsLm9yZwAKCRD+JoQlc1iMKTM9D/40JpQ+GAHqNJSEHxnomty8kmgvOL91jBjA jwbIjU40sY2VQq7Q8e7zM46MQJZTU6I2extKLwEYqEaGXHaznNDnNfd2IzL7be7Y +isRKpOw0hx9+dOInMRyv8Zz/Qypz6cuGWkuc8Ac2fYEpcBOvs5afK9EvkHDBMwZ VlG5f71AzgUsU6DSMI6HdB+GN6rsXuaQKTQ414QkTSnTdrwdCn+c0nAXXVBztU00 twK+GAw+KSPpmnoy04gaDHFkEvxNor1ylFazrAp3W6PR0cHoXUwldDaU/V0cplLG NRKXl/heQJAnTbM8aTG+a7ALHrh0FEfbuLwn6uSL2cbWy5PkiYY++K5DbJs6YmDu MpQbNqCjyznWv7CGeFwbxVvFz/Dcb8zobvfcTUiSUT8zTIPRpoZKOWrhy0w7DO70 LiWrzUF5ImKDEK5g0GCzOGpcoYc8tPabf6PBUVndVYn+31JMIh0Gksog+vWidAqS Z+OGRiCxTqj9PWCelki3Qr8YdcXYmF/vw042aTvSClFaaJB4yXMFn4ObFoNdLg4k HTbfMI7MIw082q2dWlnnBDRQ0HfZZhwFiwG0HzYzVlCN8xdXGNbXsDTWLVaXclk2 RItWpBNMClCE1XhhzPPeYjObetagQTnUnhBEFwSGZJM/keAg2166X6R22JykH+sv kNPbaX/Psg== =pg25 -----END PGP SIGNATURE----- Merge tag 'mmc-v7.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc Pull MMC fixes from Ulf Hansson: "MMC core: - Fix host controller programming for eMMC fixed driver type MMC host: - dw_mmc-rockchip: Add missing private data for very old controllers - litex_mmc: Fix clock management - renesas_sdhi: Add OF entry for RZ/G2H SoC - sdhci: Manage signal voltage switch during system resume for some hosts - sdhci-of-dwcmshc: Fix reset, clk and SDIO support for Eswin EIC7700" * tag 'mmc-v7.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: mmc: sdhci: add signal voltage switch in sdhci_resume_host mmc: dw_mmc-rockchip: Add missing private data for very old controllers mmc: litex_mmc: Set mandatory idle clocks before CMD0 mmc: litex_mmc: Use DIV_ROUND_UP for more accurate clock calculation mmc: renesas_sdhi: Add OF entry for RZ/G2H SoC mmc: sdhci-of-dwcmshc: Fix reset, clk, and SDIO support for Eswin EIC7700 mmc: core: Fix host controller programming for fixed driver type
This commit is contained in:
commit
9154c4af78
6 changed files with 61 additions and 26 deletions
|
|
@ -1371,7 +1371,9 @@ static void mmc_select_driver_type(struct mmc_card *card)
|
|||
|
||||
card->drive_strength = drive_strength;
|
||||
|
||||
if (drv_type)
|
||||
if (fixed_drv_type >= 0 && drive_strength)
|
||||
mmc_set_driver_type(card->host, drive_strength);
|
||||
else if (drv_type)
|
||||
mmc_set_driver_type(card->host, drv_type);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -441,6 +441,22 @@ static int dw_mci_common_parse_dt(struct dw_mci *host)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dw_mci_rk2928_parse_dt(struct dw_mci *host)
|
||||
{
|
||||
struct dw_mci_rockchip_priv_data *priv;
|
||||
int err;
|
||||
|
||||
err = dw_mci_common_parse_dt(host);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
priv = host->priv;
|
||||
|
||||
priv->internal_phase = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_mci_rk3288_parse_dt(struct dw_mci *host)
|
||||
{
|
||||
struct dw_mci_rockchip_priv_data *priv;
|
||||
|
|
@ -514,6 +530,7 @@ static int dw_mci_rockchip_init(struct dw_mci *host)
|
|||
|
||||
static const struct dw_mci_drv_data rk2928_drv_data = {
|
||||
.init = dw_mci_rockchip_init,
|
||||
.parse_dt = dw_mci_rk2928_parse_dt,
|
||||
};
|
||||
|
||||
static const struct dw_mci_drv_data rk3288_drv_data = {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/litex.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
|
@ -68,6 +69,9 @@
|
|||
#define SD_SLEEP_US 5
|
||||
#define SD_TIMEOUT_US 20000
|
||||
|
||||
#define SD_INIT_DELAY_US 1000
|
||||
#define SD_INIT_CLK_HZ 400000
|
||||
|
||||
#define SDIRQ_CARD_DETECT 1
|
||||
#define SDIRQ_SD_TO_MEM_DONE 2
|
||||
#define SDIRQ_MEM_TO_SD_DONE 4
|
||||
|
|
@ -436,11 +440,10 @@ static void litex_mmc_setclk(struct litex_mmc_host *host, unsigned int freq)
|
|||
struct device *dev = mmc_dev(host->mmc);
|
||||
u32 div;
|
||||
|
||||
div = freq ? host->ref_clk / freq : 256U;
|
||||
div = roundup_pow_of_two(div);
|
||||
div = freq ? DIV_ROUND_UP(host->ref_clk, freq) : 256U;
|
||||
div = clamp(div, 2U, 256U);
|
||||
dev_dbg(dev, "sd_clk_freq=%d: set to %d via div=%d\n",
|
||||
freq, host->ref_clk / div, div);
|
||||
freq, host->ref_clk / ((div + 1) & ~1U), div);
|
||||
litex_write16(host->sdphy + LITEX_PHY_CLOCKERDIV, div);
|
||||
host->sd_clk = freq;
|
||||
}
|
||||
|
|
@ -449,6 +452,17 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
{
|
||||
struct litex_mmc_host *host = mmc_priv(mmc);
|
||||
|
||||
/*
|
||||
* The SD specification requires at least 74 idle clocks before CMD0.
|
||||
* These dummy cycles is generated by writing LITEX_PHY_INITIALIZE.
|
||||
*/
|
||||
if (ios->chip_select == MMC_CS_HIGH) {
|
||||
litex_mmc_setclk(host, SD_INIT_CLK_HZ);
|
||||
litex_write8(host->sdphy + LITEX_PHY_INITIALIZE, 1);
|
||||
fsleep(SD_INIT_DELAY_US);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: Ignore any ios->bus_width updates; they occur right after
|
||||
* the mmc core sends its own acmd6 bus-width change notification,
|
||||
|
|
|
|||
|
|
@ -279,6 +279,7 @@ static const struct renesas_sdhi_of_data_with_quirks of_rza2_compatible = {
|
|||
static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = {
|
||||
{ .compatible = "renesas,sdhi-r7s9210", .data = &of_rza2_compatible, },
|
||||
{ .compatible = "renesas,sdhi-mmc-r8a77470", .data = &of_rcar_gen3_compatible, },
|
||||
{ .compatible = "renesas,sdhi-r8a774e1", .data = &of_r8a7795_compatible, },
|
||||
{ .compatible = "renesas,sdhi-r8a7795", .data = &of_r8a7795_compatible, },
|
||||
{ .compatible = "renesas,sdhi-r8a77961", .data = &of_r8a77961_compatible, },
|
||||
{ .compatible = "renesas,sdhi-r8a77965", .data = &of_r8a77965_compatible, },
|
||||
|
|
|
|||
|
|
@ -277,6 +277,7 @@
|
|||
#define PHY_DELAY_CODE_MAX 0x7f
|
||||
#define PHY_DELAY_CODE_EMMC 0x17
|
||||
#define PHY_DELAY_CODE_SD 0x55
|
||||
#define PHY_DELAY_CODE_SDIO 0x29
|
||||
|
||||
struct rk35xx_priv {
|
||||
struct reset_control *reset;
|
||||
|
|
@ -1433,10 +1434,7 @@ static void sdhci_eic7700_set_clock(struct sdhci_host *host, unsigned int clock)
|
|||
clk_set_rate(pltfm_host->clk, clock);
|
||||
|
||||
clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
|
||||
clk |= SDHCI_CLOCK_INT_EN;
|
||||
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
|
||||
|
||||
dwcmshc_enable_card_clk(host);
|
||||
sdhci_enable_clk(host, clk);
|
||||
}
|
||||
|
||||
static void sdhci_eic7700_config_phy_delay(struct sdhci_host *host, int delay)
|
||||
|
|
@ -1497,7 +1495,7 @@ static void sdhci_eic7700_config_phy(struct sdhci_host *host)
|
|||
|
||||
static void sdhci_eic7700_reset(struct sdhci_host *host, u8 mask)
|
||||
{
|
||||
sdhci_reset(host, mask);
|
||||
dwcmshc_reset(host, mask);
|
||||
|
||||
/* after reset all, the phy's config will be clear */
|
||||
if (mask == SDHCI_RESET_ALL)
|
||||
|
|
@ -1594,18 +1592,17 @@ static int sdhci_eic7700_phase_code_tuning(struct sdhci_host *host, u32 opcode)
|
|||
{
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
|
||||
u32 sd_caps = MMC_CAP2_NO_MMC | MMC_CAP2_NO_SDIO;
|
||||
u32 emmc_caps = MMC_CAP2_NO_SD | MMC_CAP2_NO_SDIO;
|
||||
int phase_code = -1;
|
||||
int code_range = -1;
|
||||
bool is_sd = false;
|
||||
int code_min = -1;
|
||||
int code_max = -1;
|
||||
int cmd_error = 0;
|
||||
bool is_emmc;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
|
||||
if ((host->mmc->caps2 & sd_caps) == sd_caps)
|
||||
is_sd = true;
|
||||
is_emmc = (host->mmc->caps2 & emmc_caps) == emmc_caps;
|
||||
|
||||
for (i = 0; i <= MAX_PHASE_CODE; i++) {
|
||||
/* Centered Phase code */
|
||||
|
|
@ -1614,8 +1611,8 @@ static int sdhci_eic7700_phase_code_tuning(struct sdhci_host *host, u32 opcode)
|
|||
host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
|
||||
|
||||
if (ret) {
|
||||
/* SD specific range tracking */
|
||||
if (is_sd && code_min != -1 && code_max != -1) {
|
||||
/* SD/SDIO specific range tracking */
|
||||
if (!is_emmc && code_min != -1 && code_max != -1) {
|
||||
if (code_max - code_min > code_range) {
|
||||
code_range = code_max - code_min;
|
||||
phase_code = (code_min + code_max) / 2;
|
||||
|
|
@ -1626,17 +1623,17 @@ static int sdhci_eic7700_phase_code_tuning(struct sdhci_host *host, u32 opcode)
|
|||
code_max = -1;
|
||||
}
|
||||
/* EMMC breaks after first valid range */
|
||||
if (!is_sd && code_min != -1 && code_max != -1)
|
||||
if (is_emmc && code_min != -1 && code_max != -1)
|
||||
break;
|
||||
} else {
|
||||
/* Track valid phase code range */
|
||||
if (code_min == -1) {
|
||||
code_min = i;
|
||||
if (!is_sd)
|
||||
if (is_emmc)
|
||||
continue;
|
||||
}
|
||||
code_max = i;
|
||||
if (is_sd && i == MAX_PHASE_CODE) {
|
||||
if (!is_emmc && i == MAX_PHASE_CODE) {
|
||||
if (code_max - code_min > code_range) {
|
||||
code_range = code_max - code_min;
|
||||
phase_code = (code_min + code_max) / 2;
|
||||
|
|
@ -1646,19 +1643,19 @@ static int sdhci_eic7700_phase_code_tuning(struct sdhci_host *host, u32 opcode)
|
|||
}
|
||||
|
||||
/* Handle tuning failure case */
|
||||
if ((is_sd && phase_code == -1) ||
|
||||
(!is_sd && code_min == -1 && code_max == -1)) {
|
||||
if ((!is_emmc && phase_code == -1) ||
|
||||
(is_emmc && code_min == -1 && code_max == -1)) {
|
||||
pr_err("%s: phase code tuning failed!\n", mmc_hostname(host->mmc));
|
||||
sdhci_writew(host, 0, priv->vendor_specific_area1 + DWCMSHC_AT_STAT);
|
||||
return -EIO;
|
||||
}
|
||||
if (!is_sd)
|
||||
if (is_emmc)
|
||||
phase_code = (code_min + code_max) / 2;
|
||||
|
||||
sdhci_writew(host, phase_code, priv->vendor_specific_area1 + DWCMSHC_AT_STAT);
|
||||
|
||||
/* SD specific final verification */
|
||||
if (is_sd) {
|
||||
/* SD/SDIO specific final verification */
|
||||
if (!is_emmc) {
|
||||
ret = mmc_send_tuning(host->mmc, opcode, &cmd_error);
|
||||
host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
|
||||
if (ret) {
|
||||
|
|
@ -1756,9 +1753,9 @@ static void sdhci_eic7700_set_uhs_signaling(struct sdhci_host *host, unsigned in
|
|||
|
||||
static void sdhci_eic7700_set_uhs_wrapper(struct sdhci_host *host, unsigned int timing)
|
||||
{
|
||||
u32 sd_caps = MMC_CAP2_NO_MMC | MMC_CAP2_NO_SDIO;
|
||||
u32 emmc_caps = MMC_CAP2_NO_SD | MMC_CAP2_NO_SDIO;
|
||||
|
||||
if ((host->mmc->caps2 & sd_caps) == sd_caps)
|
||||
if ((host->mmc->caps2 & emmc_caps) != emmc_caps)
|
||||
sdhci_set_uhs_signaling(host, timing);
|
||||
else
|
||||
sdhci_eic7700_set_uhs_signaling(host, timing);
|
||||
|
|
@ -1767,6 +1764,7 @@ static void sdhci_eic7700_set_uhs_wrapper(struct sdhci_host *host, unsigned int
|
|||
static int eic7700_init(struct device *dev, struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
|
||||
{
|
||||
u32 emmc_caps = MMC_CAP2_NO_SD | MMC_CAP2_NO_SDIO;
|
||||
u32 sd_caps = MMC_CAP2_NO_MMC | MMC_CAP2_NO_SDIO;
|
||||
unsigned int val, hsp_int_status, hsp_pwr_ctrl;
|
||||
static const char * const clk_ids[] = {"axi"};
|
||||
struct of_phandle_args args;
|
||||
|
|
@ -1821,8 +1819,10 @@ static int eic7700_init(struct device *dev, struct sdhci_host *host, struct dwcm
|
|||
|
||||
if ((host->mmc->caps2 & emmc_caps) == emmc_caps)
|
||||
dwc_priv->delay_line = PHY_DELAY_CODE_EMMC;
|
||||
else
|
||||
else if ((host->mmc->caps2 & sd_caps) == sd_caps)
|
||||
dwc_priv->delay_line = PHY_DELAY_CODE_SD;
|
||||
else
|
||||
dwc_priv->delay_line = PHY_DELAY_CODE_SDIO;
|
||||
|
||||
if (!of_property_read_u32(dev->of_node, "eswin,drive-impedance-ohms", &val))
|
||||
priv->drive_impedance = eic7700_convert_drive_impedance_ohm(dev, val);
|
||||
|
|
|
|||
|
|
@ -3836,6 +3836,7 @@ int sdhci_resume_host(struct sdhci_host *host)
|
|||
host->pwr = 0;
|
||||
host->clock = 0;
|
||||
host->reinit_uhs = true;
|
||||
mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios);
|
||||
mmc->ops->set_ios(mmc, &mmc->ios);
|
||||
} else {
|
||||
sdhci_init(host, (mmc->pm_flags & MMC_PM_KEEP_POWER));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue