Skip to content

Commit 88bd652

Browse files
bnw3000storulf
authored andcommitted
mmc: mediatek: command queue support
Support command queue for mt6779 platform. a. Add msdc_set_busy_timeout() to calculate emmc write timeout. b. Connect mtk msdc driver to cqhci driver through host->cq_host->ops = &msdc_cmdq_ops; c. msdc_cmdq_irq() will link up with cqchi_irq(). Besides, it provides more irq error messages like RSPCRCERR/CMDTO/DATACRCERR/DATTMO. d. Select kernel config MMC_CQHCI for MMC_MTK Signed-off-by: Chun-Hung Wu <[email protected]> Acked-by: Yong Mao <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ulf Hansson <[email protected]>
1 parent 557011b commit 88bd652

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

drivers/mmc/host/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,7 @@ config MMC_MTK
10091009
tristate "MediaTek SD/MMC Card Interface support"
10101010
depends on HAS_DMA
10111011
select REGULATOR
1012+
select MMC_CQHCI
10121013
help
10131014
This selects the MediaTek(R) Secure digital and Multimedia card Interface.
10141015
If you have a machine with a integrated SD/MMC card reader, say Y or M here.

drivers/mmc/host/mtk-sd.c

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include <linux/mmc/sdio.h>
3232
#include <linux/mmc/slot-gpio.h>
3333

34+
#include "cqhci.h"
35+
3436
#define MAX_BD_NUM 1024
3537

3638
/*--------------------------------------------------------------------------*/
@@ -152,6 +154,7 @@
152154
#define MSDC_INT_DMA_BDCSERR (0x1 << 17) /* W1C */
153155
#define MSDC_INT_DMA_GPDCSERR (0x1 << 18) /* W1C */
154156
#define MSDC_INT_DMA_PROTECT (0x1 << 19) /* W1C */
157+
#define MSDC_INT_CMDQ (0x1 << 28) /* W1C */
155158

156159
/* MSDC_INTEN mask */
157160
#define MSDC_INTEN_MMCIRQ (0x1 << 0) /* RW */
@@ -182,6 +185,7 @@
182185
/* SDC_CFG mask */
183186
#define SDC_CFG_SDIOINTWKUP (0x1 << 0) /* RW */
184187
#define SDC_CFG_INSWKUP (0x1 << 1) /* RW */
188+
#define SDC_CFG_WRDTOC (0x1fff << 2) /* RW */
185189
#define SDC_CFG_BUSWIDTH (0x3 << 16) /* RW */
186190
#define SDC_CFG_SDIO (0x1 << 19) /* RW */
187191
#define SDC_CFG_SDIOIDE (0x1 << 20) /* RW */
@@ -230,6 +234,7 @@
230234
#define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */
231235

232236
#define MSDC_PATCH_BIT1_CMDTA (0x7 << 3) /* RW */
237+
#define MSDC_PB1_BUSY_CHECK_SEL (0x1 << 7) /* RW */
233238
#define MSDC_PATCH_BIT1_STOP_DLY (0xf << 8) /* RW */
234239

235240
#define MSDC_PATCH_BIT2_CFGRESP (0x1 << 15) /* RW */
@@ -431,9 +436,11 @@ struct msdc_host {
431436
/* cmd response sample selection for HS400 */
432437
bool hs400_mode; /* current eMMC will run at hs400 mode */
433438
bool internal_cd; /* Use internal card-detect logic */
439+
bool cqhci; /* support eMMC hw cmdq */
434440
struct msdc_save_para save_para; /* used when gate HCLK */
435441
struct msdc_tune_para def_tune_para; /* default tune setting */
436442
struct msdc_tune_para saved_tune_para; /* tune result of CMD21/CMD19 */
443+
struct cqhci_host *cq_host;
437444
};
438445

439446
static const struct mtk_mmc_compatible mt8135_compat = {
@@ -764,6 +771,15 @@ static void msdc_set_timeout(struct msdc_host *host, u64 ns, u64 clks)
764771
(u32)(timeout > 255 ? 255 : timeout));
765772
}
766773

774+
static void msdc_set_busy_timeout(struct msdc_host *host, u64 ns, u64 clks)
775+
{
776+
u64 timeout;
777+
778+
timeout = msdc_timeout_cal(host, ns, clks);
779+
sdr_set_field(host->base + SDC_CFG, SDC_CFG_WRDTOC,
780+
(u32)(timeout > 8191 ? 8191 : timeout));
781+
}
782+
767783
static void msdc_gate_clock(struct msdc_host *host)
768784
{
769785
clk_disable_unprepare(host->src_clk_cg);
@@ -1480,6 +1496,34 @@ static void msdc_enable_sdio_irq(struct mmc_host *mmc, int enb)
14801496
pm_runtime_put_noidle(host->dev);
14811497
}
14821498

1499+
static irqreturn_t msdc_cmdq_irq(struct msdc_host *host, u32 intsts)
1500+
{
1501+
int cmd_err = 0, dat_err = 0;
1502+
1503+
if (intsts & MSDC_INT_RSPCRCERR) {
1504+
cmd_err = -EILSEQ;
1505+
dev_err(host->dev, "%s: CMD CRC ERR", __func__);
1506+
} else if (intsts & MSDC_INT_CMDTMO) {
1507+
cmd_err = -ETIMEDOUT;
1508+
dev_err(host->dev, "%s: CMD TIMEOUT ERR", __func__);
1509+
}
1510+
1511+
if (intsts & MSDC_INT_DATCRCERR) {
1512+
dat_err = -EILSEQ;
1513+
dev_err(host->dev, "%s: DATA CRC ERR", __func__);
1514+
} else if (intsts & MSDC_INT_DATTMO) {
1515+
dat_err = -ETIMEDOUT;
1516+
dev_err(host->dev, "%s: DATA TIMEOUT ERR", __func__);
1517+
}
1518+
1519+
if (cmd_err || dat_err) {
1520+
dev_err(host->dev, "cmd_err = %d, dat_err =%d, intsts = 0x%x",
1521+
cmd_err, dat_err, intsts);
1522+
}
1523+
1524+
return cqhci_irq(host->mmc, 0, cmd_err, dat_err);
1525+
}
1526+
14831527
static irqreturn_t msdc_irq(int irq, void *dev_id)
14841528
{
14851529
struct msdc_host *host = (struct msdc_host *) dev_id;
@@ -1516,6 +1560,14 @@ static irqreturn_t msdc_irq(int irq, void *dev_id)
15161560
if (!(events & (event_mask & ~MSDC_INT_SDIOIRQ)))
15171561
break;
15181562

1563+
if ((host->mmc->caps2 & MMC_CAP2_CQE) &&
1564+
(events & MSDC_INT_CMDQ)) {
1565+
msdc_cmdq_irq(host, events);
1566+
/* clear interrupts */
1567+
writel(events, host->base + MSDC_INT);
1568+
return IRQ_HANDLED;
1569+
}
1570+
15191571
if (!mrq) {
15201572
dev_err(host->dev,
15211573
"%s: MRQ=NULL; events=%08X; event_mask=%08X\n",
@@ -2200,6 +2252,36 @@ static int msdc_get_cd(struct mmc_host *mmc)
22002252
return !val;
22012253
}
22022254

2255+
static void msdc_cqe_enable(struct mmc_host *mmc)
2256+
{
2257+
struct msdc_host *host = mmc_priv(mmc);
2258+
2259+
/* enable cmdq irq */
2260+
writel(MSDC_INT_CMDQ, host->base + MSDC_INTEN);
2261+
/* enable busy check */
2262+
sdr_set_bits(host->base + MSDC_PATCH_BIT1, MSDC_PB1_BUSY_CHECK_SEL);
2263+
/* default write data / busy timeout 20s */
2264+
msdc_set_busy_timeout(host, 20 * 1000000000ULL, 0);
2265+
/* default read data timeout 1s */
2266+
msdc_set_timeout(host, 1000000000ULL, 0);
2267+
}
2268+
2269+
void msdc_cqe_disable(struct mmc_host *mmc, bool recovery)
2270+
{
2271+
struct msdc_host *host = mmc_priv(mmc);
2272+
2273+
/* disable cmdq irq */
2274+
sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INT_CMDQ);
2275+
/* disable busy check */
2276+
sdr_clr_bits(host->base + MSDC_PATCH_BIT1, MSDC_PB1_BUSY_CHECK_SEL);
2277+
2278+
if (recovery) {
2279+
sdr_set_field(host->base + MSDC_DMA_CTRL,
2280+
MSDC_DMA_CTRL_STOP, 1);
2281+
msdc_reset_hw(host);
2282+
}
2283+
}
2284+
22032285
static const struct mmc_host_ops mt_msdc_ops = {
22042286
.post_req = msdc_post_req,
22052287
.pre_req = msdc_pre_req,
@@ -2216,6 +2298,11 @@ static const struct mmc_host_ops mt_msdc_ops = {
22162298
.hw_reset = msdc_hw_reset,
22172299
};
22182300

2301+
static const struct cqhci_host_ops msdc_cmdq_ops = {
2302+
.enable = msdc_cqe_enable,
2303+
.disable = msdc_cqe_disable,
2304+
};
2305+
22192306
static void msdc_of_property_parse(struct platform_device *pdev,
22202307
struct msdc_host *host)
22212308
{
@@ -2236,6 +2323,12 @@ static void msdc_of_property_parse(struct platform_device *pdev,
22362323
host->hs400_cmd_resp_sel_rising = true;
22372324
else
22382325
host->hs400_cmd_resp_sel_rising = false;
2326+
2327+
if (of_property_read_bool(pdev->dev.of_node,
2328+
"supports-cqe"))
2329+
host->cqhci = true;
2330+
else
2331+
host->cqhci = false;
22392332
}
22402333

22412334
static int msdc_drv_probe(struct platform_device *pdev)
@@ -2351,6 +2444,8 @@ static int msdc_drv_probe(struct platform_device *pdev)
23512444
mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
23522445

23532446
mmc->caps |= MMC_CAP_CMD23;
2447+
if (host->cqhci)
2448+
mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD;
23542449
/* MMC core transfer sizes tunable parameters */
23552450
mmc->max_segs = MAX_BD_NUM;
23562451
if (host->dev_comp->support_64g)
@@ -2366,6 +2461,26 @@ static int msdc_drv_probe(struct platform_device *pdev)
23662461
host->dma_mask = DMA_BIT_MASK(32);
23672462
mmc_dev(mmc)->dma_mask = &host->dma_mask;
23682463

2464+
if (mmc->caps2 & MMC_CAP2_CQE) {
2465+
host->cq_host = devm_kzalloc(host->mmc->parent,
2466+
sizeof(*host->cq_host),
2467+
GFP_KERNEL);
2468+
if (!host->cq_host) {
2469+
ret = -ENOMEM;
2470+
goto host_free;
2471+
}
2472+
host->cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
2473+
host->cq_host->mmio = host->base + 0x800;
2474+
host->cq_host->ops = &msdc_cmdq_ops;
2475+
ret = cqhci_init(host->cq_host, mmc, true);
2476+
if (ret)
2477+
goto host_free;
2478+
mmc->max_segs = 128;
2479+
/* cqhci 16bit length */
2480+
/* 0 size, means 65536 so we don't have to -1 here */
2481+
mmc->max_seg_size = 64 * 1024;
2482+
}
2483+
23692484
host->timeout_clks = 3 * 1048576;
23702485
host->dma.gpd = dma_alloc_coherent(&pdev->dev,
23712486
2 * sizeof(struct mt_gpdma_desc),

0 commit comments

Comments
 (0)