Skip to content

Commit 84362d7

Browse files
shawn1221storulf
authored andcommitted
mmc: sdhci-of-arasan: Add CQHCI support for arasan,sdhci-5.1
Add CQHCI initialization and implement CQHCI operations for Arasan SDHCI variant host, namely arasan,sdhci-5.1, which is used by Rockchip RK3399 platform. Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> Acked-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
1 parent 7ad43a1 commit 84362d7

File tree

2 files changed

+132
-6
lines changed

2 files changed

+132
-6
lines changed

drivers/mmc/host/Kconfig

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ config MMC_SDHCI_OF_ARASAN
133133
depends on MMC_SDHCI_PLTFM
134134
depends on OF
135135
depends on COMMON_CLK
136+
select MMC_CQHCI
136137
help
137138
This selects the Arasan Secure Digital Host Controller Interface
138139
(SDHCI). This hardware is found e.g. in Xilinx' Zynq SoC.

drivers/mmc/host/sdhci-of-arasan.c

+131-6
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@
2525
#include <linux/of_device.h>
2626
#include <linux/phy/phy.h>
2727
#include <linux/regmap.h>
28-
#include "sdhci-pltfm.h"
2928
#include <linux/of.h>
3029

31-
#define SDHCI_ARASAN_VENDOR_REGISTER 0x78
30+
#include "cqhci.h"
31+
#include "sdhci-pltfm.h"
3232

33+
#define SDHCI_ARASAN_VENDOR_REGISTER 0x78
34+
#define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
3335
#define VENDOR_ENHANCED_STROBE BIT(0)
3436

3537
#define PHY_CLK_TOO_SLOW_HZ 400000
@@ -90,6 +92,7 @@ struct sdhci_arasan_data {
9092
struct phy *phy;
9193
bool is_phy_on;
9294

95+
bool has_cqe;
9396
struct clk_hw sdcardclk_hw;
9497
struct clk *sdcardclk;
9598

@@ -290,6 +293,62 @@ static const struct sdhci_pltfm_data sdhci_arasan_pdata = {
290293
SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
291294
};
292295

296+
static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32 intmask)
297+
{
298+
int cmd_error = 0;
299+
int data_error = 0;
300+
301+
if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error))
302+
return intmask;
303+
304+
cqhci_irq(host->mmc, intmask, cmd_error, data_error);
305+
306+
return 0;
307+
}
308+
309+
static void sdhci_arasan_dumpregs(struct mmc_host *mmc)
310+
{
311+
sdhci_dumpregs(mmc_priv(mmc));
312+
}
313+
314+
static void sdhci_arasan_cqe_enable(struct mmc_host *mmc)
315+
{
316+
struct sdhci_host *host = mmc_priv(mmc);
317+
u32 reg;
318+
319+
reg = sdhci_readl(host, SDHCI_PRESENT_STATE);
320+
while (reg & SDHCI_DATA_AVAILABLE) {
321+
sdhci_readl(host, SDHCI_BUFFER);
322+
reg = sdhci_readl(host, SDHCI_PRESENT_STATE);
323+
}
324+
325+
sdhci_cqe_enable(mmc);
326+
}
327+
328+
static const struct cqhci_host_ops sdhci_arasan_cqhci_ops = {
329+
.enable = sdhci_arasan_cqe_enable,
330+
.disable = sdhci_cqe_disable,
331+
.dumpregs = sdhci_arasan_dumpregs,
332+
};
333+
334+
static const struct sdhci_ops sdhci_arasan_cqe_ops = {
335+
.set_clock = sdhci_arasan_set_clock,
336+
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
337+
.get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
338+
.set_bus_width = sdhci_set_bus_width,
339+
.reset = sdhci_arasan_reset,
340+
.set_uhs_signaling = sdhci_set_uhs_signaling,
341+
.set_power = sdhci_arasan_set_power,
342+
.irq = sdhci_arasan_cqhci_irq,
343+
};
344+
345+
static const struct sdhci_pltfm_data sdhci_arasan_cqe_pdata = {
346+
.ops = &sdhci_arasan_cqe_ops,
347+
.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
348+
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
349+
SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
350+
};
351+
293352
#ifdef CONFIG_PM_SLEEP
294353
/**
295354
* sdhci_arasan_suspend - Suspend method for the driver
@@ -309,6 +368,12 @@ static int sdhci_arasan_suspend(struct device *dev)
309368
if (host->tuning_mode != SDHCI_TUNING_MODE_3)
310369
mmc_retune_needed(host->mmc);
311370

371+
if (sdhci_arasan->has_cqe) {
372+
ret = cqhci_suspend(host->mmc);
373+
if (ret)
374+
return ret;
375+
}
376+
312377
ret = sdhci_suspend_host(host);
313378
if (ret)
314379
return ret;
@@ -365,7 +430,16 @@ static int sdhci_arasan_resume(struct device *dev)
365430
sdhci_arasan->is_phy_on = true;
366431
}
367432

368-
return sdhci_resume_host(host);
433+
ret = sdhci_resume_host(host);
434+
if (ret) {
435+
dev_err(dev, "Cannot resume host.\n");
436+
return ret;
437+
}
438+
439+
if (sdhci_arasan->has_cqe)
440+
return cqhci_resume(host->mmc);
441+
442+
return 0;
369443
}
370444
#endif /* ! CONFIG_PM_SLEEP */
371445

@@ -568,6 +642,49 @@ static void sdhci_arasan_unregister_sdclk(struct device *dev)
568642
of_clk_del_provider(dev->of_node);
569643
}
570644

645+
static int sdhci_arasan_add_host(struct sdhci_arasan_data *sdhci_arasan)
646+
{
647+
struct sdhci_host *host = sdhci_arasan->host;
648+
struct cqhci_host *cq_host;
649+
bool dma64;
650+
int ret;
651+
652+
if (!sdhci_arasan->has_cqe)
653+
return sdhci_add_host(host);
654+
655+
ret = sdhci_setup_host(host);
656+
if (ret)
657+
return ret;
658+
659+
cq_host = devm_kzalloc(host->mmc->parent,
660+
sizeof(*cq_host), GFP_KERNEL);
661+
if (!cq_host) {
662+
ret = -ENOMEM;
663+
goto cleanup;
664+
}
665+
666+
cq_host->mmio = host->ioaddr + SDHCI_ARASAN_CQE_BASE_ADDR;
667+
cq_host->ops = &sdhci_arasan_cqhci_ops;
668+
669+
dma64 = host->flags & SDHCI_USE_64_BIT_DMA;
670+
if (dma64)
671+
cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
672+
673+
ret = cqhci_init(cq_host, host->mmc, dma64);
674+
if (ret)
675+
goto cleanup;
676+
677+
ret = __sdhci_add_host(host);
678+
if (ret)
679+
goto cleanup;
680+
681+
return 0;
682+
683+
cleanup:
684+
sdhci_cleanup_host(host);
685+
return ret;
686+
}
687+
571688
static int sdhci_arasan_probe(struct platform_device *pdev)
572689
{
573690
int ret;
@@ -578,9 +695,15 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
578695
struct sdhci_pltfm_host *pltfm_host;
579696
struct sdhci_arasan_data *sdhci_arasan;
580697
struct device_node *np = pdev->dev.of_node;
698+
const struct sdhci_pltfm_data *pdata;
699+
700+
if (of_device_is_compatible(pdev->dev.of_node, "arasan,sdhci-5.1"))
701+
pdata = &sdhci_arasan_cqe_pdata;
702+
else
703+
pdata = &sdhci_arasan_pdata;
704+
705+
host = sdhci_pltfm_init(pdev, pdata, sizeof(*sdhci_arasan));
581706

582-
host = sdhci_pltfm_init(pdev, &sdhci_arasan_pdata,
583-
sizeof(*sdhci_arasan));
584707
if (IS_ERR(host))
585708
return PTR_ERR(host);
586709

@@ -675,9 +798,11 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
675798
sdhci_arasan_hs400_enhanced_strobe;
676799
host->mmc_host_ops.start_signal_voltage_switch =
677800
sdhci_arasan_voltage_switch;
801+
sdhci_arasan->has_cqe = true;
802+
host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD;
678803
}
679804

680-
ret = sdhci_add_host(host);
805+
ret = sdhci_arasan_add_host(sdhci_arasan);
681806
if (ret)
682807
goto err_add_host;
683808

0 commit comments

Comments
 (0)