MMC core:
- Fix eMMC initialization with 1-bit bus connection MMC host: - mmci: Fix DMA API overlapping mappings for the stm32 variant - sdhci-xenon: Fix PHY stability issues -----BEGIN PGP SIGNATURE----- iQJLBAABCgA1FiEEugLDXPmKSktSkQsV/iaEJXNYjCkFAmXhqHMXHHVsZi5oYW5z c29uQGxpbmFyby5vcmcACgkQ/iaEJXNYjClzsA//QxUuGQKkjYZIRt0KKYfXA8v/ bHW1cAK+xMmklm2XLHCE2U7ckZGdWFRCNiotXQa4iYyVFAUpx5zFYdszXZbaJkqy 1Q4Zbl014NoxAijuJoMWPZPNThMwWtl11ZEw3hEO8d5it3g+kH7GafrdRINRDUeK VLhRpaUdMdjXLdEfrM9vv9slE4wA3qwGKRLm1D4H0YpDL/hPHa/tJRmcw3hCxEYO wzjza+tGKDi9oZdg/7H0HVZW2Yf0jImAAIvwXgLhF1Zm7LVzQxG5fW9VV5tc/Yi5 XDi/UtjJhqoEudLCd+tK59uJa8PE0x//Uo3wNJ1nujy/5Av6J9+RV0Dk/oamF/O2 o7wrWsdtZF/MoDQ3Fp7jjy3uqUFFMQreDM4TEEFr7+ZF0fT7mKPNB7YKms40+dI5 mzhDdIWKedJffmj8zRipqkGfp6oIX5bj3h8AwSjLmu7N1lRyJu0TuBLzVCwASdQj +dc/xS7k9/MjDPXj2vppiS2ALygMArMEFTk9rdJj4HMDsMAgjDcBkeGH7tn6Bs6S ntTdY8DH5E+N9n2IZezsUbm81gI84r/jfZ30Iol2rkfCAuryVVdmbTVGsKgCrCX0 M1oT7oPjMPfEjeXSw8qO0crZbBRugPANDxhTxahaGJ3jbJkY+aXjYBJuROYk+myR Px30aQTBJpDZM921Alw= =PO2r -----END PGP SIGNATURE----- Merge tag 'mmc-v6.8-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc Pull MMC fixes from Ulf Hansson: "MMC core: - Fix eMMC initialization with 1-bit bus connection MMC host: - mmci: Fix DMA API overlapping mappings for the stm32 variant - sdhci-xenon: Fix PHY stability issues" * tag 'mmc-v6.8-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: mmc: sdhci-xenon: add timeout for PHY init complete mmc: sdhci-xenon: fix PHY init clock stability mmc: mmci: stm32: fix DMA API overlapping mappings warning mmc: core: Fix eMMC initialization with 1-bit bus connection
This commit is contained in:
commit
371e4a1f91
@ -1015,10 +1015,12 @@ static int mmc_select_bus_width(struct mmc_card *card)
|
||||
static unsigned ext_csd_bits[] = {
|
||||
EXT_CSD_BUS_WIDTH_8,
|
||||
EXT_CSD_BUS_WIDTH_4,
|
||||
EXT_CSD_BUS_WIDTH_1,
|
||||
};
|
||||
static unsigned bus_widths[] = {
|
||||
MMC_BUS_WIDTH_8,
|
||||
MMC_BUS_WIDTH_4,
|
||||
MMC_BUS_WIDTH_1,
|
||||
};
|
||||
struct mmc_host *host = card->host;
|
||||
unsigned idx, bus_width = 0;
|
||||
|
@ -225,6 +225,8 @@ static int sdmmc_idma_start(struct mmci_host *host, unsigned int *datactrl)
|
||||
struct scatterlist *sg;
|
||||
int i;
|
||||
|
||||
host->dma_in_progress = true;
|
||||
|
||||
if (!host->variant->dma_lli || data->sg_len == 1 ||
|
||||
idma->use_bounce_buffer) {
|
||||
u32 dma_addr;
|
||||
@ -263,9 +265,30 @@ static int sdmmc_idma_start(struct mmci_host *host, unsigned int *datactrl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sdmmc_idma_error(struct mmci_host *host)
|
||||
{
|
||||
struct mmc_data *data = host->data;
|
||||
struct sdmmc_idma *idma = host->dma_priv;
|
||||
|
||||
if (!dma_inprogress(host))
|
||||
return;
|
||||
|
||||
writel_relaxed(0, host->base + MMCI_STM32_IDMACTRLR);
|
||||
host->dma_in_progress = false;
|
||||
data->host_cookie = 0;
|
||||
|
||||
if (!idma->use_bounce_buffer)
|
||||
dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
|
||||
mmc_get_dma_dir(data));
|
||||
}
|
||||
|
||||
static void sdmmc_idma_finalize(struct mmci_host *host, struct mmc_data *data)
|
||||
{
|
||||
if (!dma_inprogress(host))
|
||||
return;
|
||||
|
||||
writel_relaxed(0, host->base + MMCI_STM32_IDMACTRLR);
|
||||
host->dma_in_progress = false;
|
||||
|
||||
if (!data->host_cookie)
|
||||
sdmmc_idma_unprep_data(host, data, 0);
|
||||
@ -676,6 +699,7 @@ static struct mmci_host_ops sdmmc_variant_ops = {
|
||||
.dma_setup = sdmmc_idma_setup,
|
||||
.dma_start = sdmmc_idma_start,
|
||||
.dma_finalize = sdmmc_idma_finalize,
|
||||
.dma_error = sdmmc_idma_error,
|
||||
.set_clkreg = mmci_sdmmc_set_clkreg,
|
||||
.set_pwrreg = mmci_sdmmc_set_pwrreg,
|
||||
.busy_complete = sdmmc_busy_complete,
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include "sdhci-pltfm.h"
|
||||
@ -109,6 +110,8 @@
|
||||
#define XENON_EMMC_PHY_LOGIC_TIMING_ADJUST (XENON_EMMC_PHY_REG_BASE + 0x18)
|
||||
#define XENON_LOGIC_TIMING_VALUE 0x00AA8977
|
||||
|
||||
#define XENON_MAX_PHY_TIMEOUT_LOOPS 100
|
||||
|
||||
/*
|
||||
* List offset of PHY registers and some special register values
|
||||
* in eMMC PHY 5.0 or eMMC PHY 5.1
|
||||
@ -216,6 +219,19 @@ static int xenon_alloc_emmc_phy(struct sdhci_host *host)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xenon_check_stability_internal_clk(struct sdhci_host *host)
|
||||
{
|
||||
u32 reg;
|
||||
int err;
|
||||
|
||||
err = read_poll_timeout(sdhci_readw, reg, reg & SDHCI_CLOCK_INT_STABLE,
|
||||
1100, 20000, false, host, SDHCI_CLOCK_CONTROL);
|
||||
if (err)
|
||||
dev_err(mmc_dev(host->mmc), "phy_init: Internal clock never stabilized.\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* eMMC 5.0/5.1 PHY init/re-init.
|
||||
* eMMC PHY init should be executed after:
|
||||
@ -232,6 +248,11 @@ static int xenon_emmc_phy_init(struct sdhci_host *host)
|
||||
struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
|
||||
struct xenon_emmc_phy_regs *phy_regs = priv->emmc_phy_regs;
|
||||
|
||||
int ret = xenon_check_stability_internal_clk(host);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
reg = sdhci_readl(host, phy_regs->timing_adj);
|
||||
reg |= XENON_PHY_INITIALIZAION;
|
||||
sdhci_writel(host, reg, phy_regs->timing_adj);
|
||||
@ -259,18 +280,27 @@ static int xenon_emmc_phy_init(struct sdhci_host *host)
|
||||
/* get the wait time */
|
||||
wait /= clock;
|
||||
wait++;
|
||||
/* wait for host eMMC PHY init completes */
|
||||
udelay(wait);
|
||||
|
||||
reg = sdhci_readl(host, phy_regs->timing_adj);
|
||||
reg &= XENON_PHY_INITIALIZAION;
|
||||
if (reg) {
|
||||
/*
|
||||
* AC5X spec says bit must be polled until zero.
|
||||
* We see cases in which timeout can take longer
|
||||
* than the standard calculation on AC5X, which is
|
||||
* expected following the spec comment above.
|
||||
* According to the spec, we must wait as long as
|
||||
* it takes for that bit to toggle on AC5X.
|
||||
* Cap that with 100 delay loops so we won't get
|
||||
* stuck here forever:
|
||||
*/
|
||||
|
||||
ret = read_poll_timeout(sdhci_readl, reg,
|
||||
!(reg & XENON_PHY_INITIALIZAION),
|
||||
wait, XENON_MAX_PHY_TIMEOUT_LOOPS * wait,
|
||||
false, host, phy_regs->timing_adj);
|
||||
if (ret)
|
||||
dev_err(mmc_dev(host->mmc), "eMMC PHY init cannot complete after %d us\n",
|
||||
wait);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
wait * XENON_MAX_PHY_TIMEOUT_LOOPS);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define ARMADA_3700_SOC_PAD_1_8V 0x1
|
||||
|
Loading…
x
Reference in New Issue
Block a user