Skip to content

Commit 7e3cb16

Browse files
committed
Merge tag 'mmc-v4.17-3' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC fixes from Ulf Hansson: "A couple of MMC host fixes: - sdhci-pci: Fixup tuning for AMD for eMMC HS200 mode - renesas_sdhi_internal_dmac: Avoid data corruption by limiting DMA RX" * tag 'mmc-v4.17-3' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: mmc: renesas_sdhi_internal_dmac: limit DMA RX for old SoCs mmc: sdhci-pci: Only do AMD tuning for HS200
2 parents 7768ee3 + 0cbc94d commit 7e3cb16

File tree

2 files changed

+56
-8
lines changed

2 files changed

+56
-8
lines changed

drivers/mmc/host/renesas_sdhi_internal_dmac.c

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* published by the Free Software Foundation.
1010
*/
1111

12+
#include <linux/bitops.h>
1213
#include <linux/device.h>
1314
#include <linux/dma-mapping.h>
1415
#include <linux/io-64-nonatomic-hi-lo.h>
@@ -62,6 +63,17 @@
6263
* need a custom accessor.
6364
*/
6465

66+
static unsigned long global_flags;
67+
/*
68+
* Workaround for avoiding to use RX DMAC by multiple channels.
69+
* On R-Car H3 ES1.* and M3-W ES1.0, when multiple SDHI channels use
70+
* RX DMAC simultaneously, sometimes hundreds of bytes data are not
71+
* stored into the system memory even if the DMAC interrupt happened.
72+
* So, this driver then uses one RX DMAC channel only.
73+
*/
74+
#define SDHI_INTERNAL_DMAC_ONE_RX_ONLY 0
75+
#define SDHI_INTERNAL_DMAC_RX_IN_USE 1
76+
6577
/* Definitions for sampling clocks */
6678
static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = {
6779
{
@@ -126,6 +138,9 @@ renesas_sdhi_internal_dmac_abort_dma(struct tmio_mmc_host *host) {
126138
renesas_sdhi_internal_dmac_dm_write(host, DM_CM_RST,
127139
RST_RESERVED_BITS | val);
128140

141+
if (host->data && host->data->flags & MMC_DATA_READ)
142+
clear_bit(SDHI_INTERNAL_DMAC_RX_IN_USE, &global_flags);
143+
129144
renesas_sdhi_internal_dmac_enable_dma(host, true);
130145
}
131146

@@ -155,6 +170,9 @@ renesas_sdhi_internal_dmac_start_dma(struct tmio_mmc_host *host,
155170
if (data->flags & MMC_DATA_READ) {
156171
dtran_mode |= DTRAN_MODE_CH_NUM_CH1;
157172
dir = DMA_FROM_DEVICE;
173+
if (test_bit(SDHI_INTERNAL_DMAC_ONE_RX_ONLY, &global_flags) &&
174+
test_and_set_bit(SDHI_INTERNAL_DMAC_RX_IN_USE, &global_flags))
175+
goto force_pio;
158176
} else {
159177
dtran_mode |= DTRAN_MODE_CH_NUM_CH0;
160178
dir = DMA_TO_DEVICE;
@@ -208,6 +226,9 @@ static void renesas_sdhi_internal_dmac_complete_tasklet_fn(unsigned long arg)
208226
renesas_sdhi_internal_dmac_enable_dma(host, false);
209227
dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->sg_len, dir);
210228

229+
if (dir == DMA_FROM_DEVICE)
230+
clear_bit(SDHI_INTERNAL_DMAC_RX_IN_USE, &global_flags);
231+
211232
tmio_mmc_do_data_irq(host);
212233
out:
213234
spin_unlock_irq(&host->lock);
@@ -251,18 +272,24 @@ static const struct tmio_mmc_dma_ops renesas_sdhi_internal_dmac_dma_ops = {
251272
* implementation as others may use a different implementation.
252273
*/
253274
static const struct soc_device_attribute gen3_soc_whitelist[] = {
254-
{ .soc_id = "r8a7795", .revision = "ES1.*" },
255-
{ .soc_id = "r8a7795", .revision = "ES2.0" },
256-
{ .soc_id = "r8a7796", .revision = "ES1.0" },
257-
{ .soc_id = "r8a77995", .revision = "ES1.0" },
258-
{ /* sentinel */ }
275+
{ .soc_id = "r8a7795", .revision = "ES1.*",
276+
.data = (void *)BIT(SDHI_INTERNAL_DMAC_ONE_RX_ONLY) },
277+
{ .soc_id = "r8a7795", .revision = "ES2.0" },
278+
{ .soc_id = "r8a7796", .revision = "ES1.0",
279+
.data = (void *)BIT(SDHI_INTERNAL_DMAC_ONE_RX_ONLY) },
280+
{ .soc_id = "r8a77995", .revision = "ES1.0" },
281+
{ /* sentinel */ }
259282
};
260283

261284
static int renesas_sdhi_internal_dmac_probe(struct platform_device *pdev)
262285
{
263-
if (!soc_device_match(gen3_soc_whitelist))
286+
const struct soc_device_attribute *soc = soc_device_match(gen3_soc_whitelist);
287+
288+
if (!soc)
264289
return -ENODEV;
265290

291+
global_flags |= (unsigned long)soc->data;
292+
266293
return renesas_sdhi_probe(pdev, &renesas_sdhi_internal_dmac_dma_ops);
267294
}
268295

drivers/mmc/host/sdhci-pci-core.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,7 +1312,7 @@ static void amd_enable_manual_tuning(struct pci_dev *pdev)
13121312
pci_write_config_dword(pdev, AMD_SD_MISC_CONTROL, val);
13131313
}
13141314

1315-
static int amd_execute_tuning(struct sdhci_host *host, u32 opcode)
1315+
static int amd_execute_tuning_hs200(struct sdhci_host *host, u32 opcode)
13161316
{
13171317
struct sdhci_pci_slot *slot = sdhci_priv(host);
13181318
struct pci_dev *pdev = slot->chip->pdev;
@@ -1351,6 +1351,27 @@ static int amd_execute_tuning(struct sdhci_host *host, u32 opcode)
13511351
return 0;
13521352
}
13531353

1354+
static int amd_execute_tuning(struct mmc_host *mmc, u32 opcode)
1355+
{
1356+
struct sdhci_host *host = mmc_priv(mmc);
1357+
1358+
/* AMD requires custom HS200 tuning */
1359+
if (host->timing == MMC_TIMING_MMC_HS200)
1360+
return amd_execute_tuning_hs200(host, opcode);
1361+
1362+
/* Otherwise perform standard SDHCI tuning */
1363+
return sdhci_execute_tuning(mmc, opcode);
1364+
}
1365+
1366+
static int amd_probe_slot(struct sdhci_pci_slot *slot)
1367+
{
1368+
struct mmc_host_ops *ops = &slot->host->mmc_host_ops;
1369+
1370+
ops->execute_tuning = amd_execute_tuning;
1371+
1372+
return 0;
1373+
}
1374+
13541375
static int amd_probe(struct sdhci_pci_chip *chip)
13551376
{
13561377
struct pci_dev *smbus_dev;
@@ -1385,12 +1406,12 @@ static const struct sdhci_ops amd_sdhci_pci_ops = {
13851406
.set_bus_width = sdhci_set_bus_width,
13861407
.reset = sdhci_reset,
13871408
.set_uhs_signaling = sdhci_set_uhs_signaling,
1388-
.platform_execute_tuning = amd_execute_tuning,
13891409
};
13901410

13911411
static const struct sdhci_pci_fixes sdhci_amd = {
13921412
.probe = amd_probe,
13931413
.ops = &amd_sdhci_pci_ops,
1414+
.probe_slot = amd_probe_slot,
13941415
};
13951416

13961417
static const struct pci_device_id pci_ids[] = {

0 commit comments

Comments
 (0)