|
18 | 18 | #include <linux/of.h>
|
19 | 19 | #include <linux/pm.h>
|
20 | 20 | #include <linux/pm_runtime.h>
|
| 21 | +#include <linux/mm.h> |
| 22 | +#include <linux/dma-mapping.h> |
21 | 23 |
|
22 | 24 | #include "sdhci-pltfm.h"
|
23 | 25 | #include "sdhci-xenon.h"
|
@@ -422,6 +424,7 @@ static int xenon_probe_params(struct platform_device *pdev)
|
422 | 424 | struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
|
423 | 425 | u32 sdhc_id, nr_sdhc;
|
424 | 426 | u32 tuning_count;
|
| 427 | + struct sysinfo si; |
425 | 428 |
|
426 | 429 | /* Disable HS200 on Armada AP806 */
|
427 | 430 | if (priv->hw_version == XENON_AP806)
|
@@ -450,6 +453,23 @@ static int xenon_probe_params(struct platform_device *pdev)
|
450 | 453 | }
|
451 | 454 | priv->tuning_count = tuning_count;
|
452 | 455 |
|
| 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 | + |
453 | 473 | return xenon_phy_parse_params(dev, host);
|
454 | 474 | }
|
455 | 475 |
|
@@ -562,6 +582,16 @@ static int xenon_probe(struct platform_device *pdev)
|
562 | 582 | goto remove_sdhc;
|
563 | 583 |
|
564 | 584 | 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)); |
565 | 595 |
|
566 | 596 | return 0;
|
567 | 597 |
|
@@ -680,6 +710,7 @@ static const struct of_device_id sdhci_xenon_dt_ids[] = {
|
680 | 710 | { .compatible = "marvell,armada-ap807-sdhci", .data = (void *)XENON_AP807},
|
681 | 711 | { .compatible = "marvell,armada-cp110-sdhci", .data = (void *)XENON_CP110},
|
682 | 712 | { .compatible = "marvell,armada-3700-sdhci", .data = (void *)XENON_A3700},
|
| 713 | + { .compatible = "marvell,ac5-sdhci", .data = (void *)XENON_AC5}, |
683 | 714 | {}
|
684 | 715 | };
|
685 | 716 | MODULE_DEVICE_TABLE(of, sdhci_xenon_dt_ids);
|
|
0 commit comments