Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+56 -8
+33 -6
drivers/mmc/host/renesas_sdhi_internal_dmac.c
··· 9 9 * published by the Free Software Foundation. 10 10 */ 11 11 12 + #include <linux/bitops.h> 12 13 #include <linux/device.h> 13 14 #include <linux/dma-mapping.h> 14 15 #include <linux/io-64-nonatomic-hi-lo.h> ··· 62 61 * - Since this SDHI DMAC register set has 16 but 32-bit width, we 63 62 * need a custom accessor. 64 63 */ 64 + 65 + static unsigned long global_flags; 66 + /* 67 + * Workaround for avoiding to use RX DMAC by multiple channels. 68 + * On R-Car H3 ES1.* and M3-W ES1.0, when multiple SDHI channels use 69 + * RX DMAC simultaneously, sometimes hundreds of bytes data are not 70 + * stored into the system memory even if the DMAC interrupt happened. 71 + * So, this driver then uses one RX DMAC channel only. 72 + */ 73 + #define SDHI_INTERNAL_DMAC_ONE_RX_ONLY 0 74 + #define SDHI_INTERNAL_DMAC_RX_IN_USE 1 65 75 66 76 /* Definitions for sampling clocks */ 67 77 static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = { ··· 138 126 renesas_sdhi_internal_dmac_dm_write(host, DM_CM_RST, 139 127 RST_RESERVED_BITS | val); 140 128 129 + if (host->data && host->data->flags & MMC_DATA_READ) 130 + clear_bit(SDHI_INTERNAL_DMAC_RX_IN_USE, &global_flags); 131 + 141 132 renesas_sdhi_internal_dmac_enable_dma(host, true); 142 133 } 143 134 ··· 170 155 if (data->flags & MMC_DATA_READ) { 171 156 dtran_mode |= DTRAN_MODE_CH_NUM_CH1; 172 157 dir = DMA_FROM_DEVICE; 158 + if (test_bit(SDHI_INTERNAL_DMAC_ONE_RX_ONLY, &global_flags) && 159 + test_and_set_bit(SDHI_INTERNAL_DMAC_RX_IN_USE, &global_flags)) 160 + goto force_pio; 173 161 } else { 174 162 dtran_mode |= DTRAN_MODE_CH_NUM_CH0; 175 163 dir = DMA_TO_DEVICE; ··· 226 208 renesas_sdhi_internal_dmac_enable_dma(host, false); 227 209 dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->sg_len, dir); 228 210 211 + if (dir == DMA_FROM_DEVICE) 212 + clear_bit(SDHI_INTERNAL_DMAC_RX_IN_USE, &global_flags); 213 + 229 214 tmio_mmc_do_data_irq(host); 230 215 out: 231 216 spin_unlock_irq(&host->lock); ··· 272 251 * implementation as others may use a different implementation. 273 252 */ 274 253 static const struct soc_device_attribute gen3_soc_whitelist[] = { 275 - { .soc_id = "r8a7795", .revision = "ES1.*" }, 276 - { .soc_id = "r8a7795", .revision = "ES2.0" }, 277 - { .soc_id = "r8a7796", .revision = "ES1.0" }, 278 - { .soc_id = "r8a77995", .revision = "ES1.0" }, 279 - { /* sentinel */ } 254 + { .soc_id = "r8a7795", .revision = "ES1.*", 255 + .data = (void *)BIT(SDHI_INTERNAL_DMAC_ONE_RX_ONLY) }, 256 + { .soc_id = "r8a7795", .revision = "ES2.0" }, 257 + { .soc_id = "r8a7796", .revision = "ES1.0", 258 + .data = (void *)BIT(SDHI_INTERNAL_DMAC_ONE_RX_ONLY) }, 259 + { .soc_id = "r8a77995", .revision = "ES1.0" }, 260 + { /* sentinel */ } 280 261 }; 281 262 282 263 static int renesas_sdhi_internal_dmac_probe(struct platform_device *pdev) 283 264 { 284 - if (!soc_device_match(gen3_soc_whitelist)) 265 + const struct soc_device_attribute *soc = soc_device_match(gen3_soc_whitelist); 266 + 267 + if (!soc) 285 268 return -ENODEV; 269 + 270 + global_flags |= (unsigned long)soc->data; 286 271 287 272 return renesas_sdhi_probe(pdev, &renesas_sdhi_internal_dmac_dma_ops); 288 273 }
+23 -2
drivers/mmc/host/sdhci-pci-core.c
··· 1312 1312 pci_write_config_dword(pdev, AMD_SD_MISC_CONTROL, val); 1313 1313 } 1314 1314 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) 1316 1316 { 1317 1317 struct sdhci_pci_slot *slot = sdhci_priv(host); 1318 1318 struct pci_dev *pdev = slot->chip->pdev; ··· 1351 1351 return 0; 1352 1352 } 1353 1353 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 + 1354 1375 static int amd_probe(struct sdhci_pci_chip *chip) 1355 1376 { 1356 1377 struct pci_dev *smbus_dev; ··· 1406 1385 .set_bus_width = sdhci_set_bus_width, 1407 1386 .reset = sdhci_reset, 1408 1387 .set_uhs_signaling = sdhci_set_uhs_signaling, 1409 - .platform_execute_tuning = amd_execute_tuning, 1410 1388 }; 1411 1389 1412 1390 static const struct sdhci_pci_fixes sdhci_amd = { 1413 1391 .probe = amd_probe, 1414 1392 .ops = &amd_sdhci_pci_ops, 1393 + .probe_slot = amd_probe_slot, 1415 1394 }; 1416 1395 1417 1396 static const struct pci_device_id pci_ids[] = {