Skip to content

Commit 5d40213

Browse files
eladnachmanstorulf
authored andcommitted
mmc: xenon: Add ac5 support via bounce buffer
AC5/X/IM SOCs has a variant of the Xenon eMMC controller, in which only 31-bit of addressing pass from the controller on the AXI bus. Since we cannot guarantee that only buffers from the first 2GB of memory will reach the driver, the driver is configured for SDMA mode, without 64-bit mode, overriding the DMA mask to 34-bit to support the DDR memory mapping, which starts at offset 8GB. Signed-off-by: Elad Nachman <[email protected]> Acked-by: Adrian Hunter <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ulf Hansson <[email protected]>
1 parent d586272 commit 5d40213

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

drivers/mmc/host/sdhci-xenon.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include <linux/of.h>
1919
#include <linux/pm.h>
2020
#include <linux/pm_runtime.h>
21+
#include <linux/mm.h>
22+
#include <linux/dma-mapping.h>
2123

2224
#include "sdhci-pltfm.h"
2325
#include "sdhci-xenon.h"
@@ -422,6 +424,7 @@ static int xenon_probe_params(struct platform_device *pdev)
422424
struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
423425
u32 sdhc_id, nr_sdhc;
424426
u32 tuning_count;
427+
struct sysinfo si;
425428

426429
/* Disable HS200 on Armada AP806 */
427430
if (priv->hw_version == XENON_AP806)
@@ -450,6 +453,23 @@ static int xenon_probe_params(struct platform_device *pdev)
450453
}
451454
priv->tuning_count = tuning_count;
452455

456+
/*
457+
* AC5/X/IM HW has only 31-bits passed in the crossbar switch.
458+
* If we have more than 2GB of memory, this means we might pass
459+
* memory pointers which are above 2GB and which cannot be properly
460+
* represented. In this case, disable ADMA, 64-bit DMA and allow only SDMA.
461+
* This effectively will enable bounce buffer quirk in the
462+
* generic SDHCI driver, which will make sure DMA is only done
463+
* from supported memory regions:
464+
*/
465+
if (priv->hw_version == XENON_AC5) {
466+
si_meminfo(&si);
467+
if (si.totalram * si.mem_unit > SZ_2G) {
468+
host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
469+
host->quirks2 |= SDHCI_QUIRK2_BROKEN_64_BIT_DMA;
470+
}
471+
}
472+
453473
return xenon_phy_parse_params(dev, host);
454474
}
455475

@@ -562,6 +582,16 @@ static int xenon_probe(struct platform_device *pdev)
562582
goto remove_sdhc;
563583

564584
pm_runtime_put_autosuspend(&pdev->dev);
585+
/*
586+
* If we previously detected AC5 with over 2GB of memory,
587+
* then we disable ADMA and 64-bit DMA.
588+
* This means generic SDHCI driver has set the DMA mask to
589+
* 32-bit. Since DDR starts at 0x2_0000_0000, we must use
590+
* 34-bit DMA mask to access this DDR memory:
591+
*/
592+
if (priv->hw_version == XENON_AC5 &&
593+
host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA)
594+
dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34));
565595

566596
return 0;
567597

@@ -680,6 +710,7 @@ static const struct of_device_id sdhci_xenon_dt_ids[] = {
680710
{ .compatible = "marvell,armada-ap807-sdhci", .data = (void *)XENON_AP807},
681711
{ .compatible = "marvell,armada-cp110-sdhci", .data = (void *)XENON_CP110},
682712
{ .compatible = "marvell,armada-3700-sdhci", .data = (void *)XENON_A3700},
713+
{ .compatible = "marvell,ac5-sdhci", .data = (void *)XENON_AC5},
683714
{}
684715
};
685716
MODULE_DEVICE_TABLE(of, sdhci_xenon_dt_ids);

drivers/mmc/host/sdhci-xenon.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ enum xenon_variant {
5757
XENON_A3700,
5858
XENON_AP806,
5959
XENON_AP807,
60-
XENON_CP110
60+
XENON_CP110,
61+
XENON_AC5
6162
};
6263

6364
struct xenon_priv {

0 commit comments

Comments
 (0)