* [PATCH v7 1/4] mmc: mediatek: add MT6779 MMC driver support
2020-07-20 0:42 [PATCH v7 0/4] mmc: mediatek: add mmc cqhci support Chun-Hung Wu
@ 2020-07-20 0:42 ` Chun-Hung Wu
2020-07-20 0:42 ` [PATCH v7 2/4] mmc: mediatek: refine msdc timeout api Chun-Hung Wu
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Chun-Hung Wu @ 2020-07-20 0:42 UTC (permalink / raw)
To: mirq-linux, Jonathan Hunter, Al Cooper, Adrian Hunter,
Florian Fainelli, bcm-kernel-feedback-list, Andy Gross,
Bjorn Andersson, Michal Simek, Thierry Reding, Chaotian Jing,
Ulf Hansson, Rob Herring, Mark Rutland, Matthias Brugger,
Linus Walleij, Pavel Machek, Kate Stewart, Greg Kroah-Hartman,
Martin Blumenstingl, Pan Bian, Thomas Gleixner, Allison Randal,
Mathieu Malaterre, Stanley Chu, Kuohong Wang
Cc: kernel-team, linux-kernel, linux-mmc, linux-mediatek, devicetree,
wsd_upstream, linux-arm-kernel, linux-arm-msm, linux-tegra,
Chun-Hung Wu
Add new code to support MT6779 mmc driver.
Signed-off-by: Chun-Hung Wu <chun-hung.wu@mediatek.com>
---
drivers/mmc/host/mtk-sd.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 39e7fc5..ed37a3c 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -538,6 +538,18 @@ struct msdc_host {
.use_internal_cd = true,
};
+static const struct mtk_mmc_compatible mt6779_compat = {
+ .clk_div_bits = 12,
+ .hs400_tune = false,
+ .pad_tune_reg = MSDC_PAD_TUNE0,
+ .async_fifo = true,
+ .data_tune = true,
+ .busy_check = true,
+ .stop_clk_fix = true,
+ .enhance_rx = true,
+ .support_64g = true,
+};
+
static const struct of_device_id msdc_of_ids[] = {
{ .compatible = "mediatek,mt8135-mmc", .data = &mt8135_compat},
{ .compatible = "mediatek,mt8173-mmc", .data = &mt8173_compat},
@@ -547,6 +559,7 @@ struct msdc_host {
{ .compatible = "mediatek,mt7622-mmc", .data = &mt7622_compat},
{ .compatible = "mediatek,mt8516-mmc", .data = &mt8516_compat},
{ .compatible = "mediatek,mt7620-mmc", .data = &mt7620_compat},
+ { .compatible = "mediatek,mt6779-mmc", .data = &mt6779_compat},
{}
};
MODULE_DEVICE_TABLE(of, msdc_of_ids);
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v7 2/4] mmc: mediatek: refine msdc timeout api
2020-07-20 0:42 [PATCH v7 0/4] mmc: mediatek: add mmc cqhci support Chun-Hung Wu
2020-07-20 0:42 ` [PATCH v7 1/4] mmc: mediatek: add MT6779 MMC driver support Chun-Hung Wu
@ 2020-07-20 0:42 ` Chun-Hung Wu
2020-07-20 15:43 ` Matthias Brugger
2020-07-20 0:42 ` [PATCH v7 3/4] mmc: mediatek: command queue support Chun-Hung Wu
` (2 subsequent siblings)
4 siblings, 1 reply; 9+ messages in thread
From: Chun-Hung Wu @ 2020-07-20 0:42 UTC (permalink / raw)
To: mirq-linux, Jonathan Hunter, Al Cooper, Adrian Hunter,
Florian Fainelli, bcm-kernel-feedback-list, Andy Gross,
Bjorn Andersson, Michal Simek, Thierry Reding, Chaotian Jing,
Ulf Hansson, Rob Herring, Mark Rutland, Matthias Brugger,
Linus Walleij, Pavel Machek, Kate Stewart, Greg Kroah-Hartman,
Martin Blumenstingl, Pan Bian, Thomas Gleixner, Allison Randal,
Mathieu Malaterre, Stanley Chu, Kuohong Wang
Cc: kernel-team, linux-kernel, linux-mmc, linux-mediatek, devicetree,
wsd_upstream, linux-arm-kernel, linux-arm-msm, linux-tegra,
Chun-Hung Wu
Extract msdc timeout api common part to have
better code architecture and avoid redundant code.
Signed-off-by: Chun-Hung Wu <chun-hung.wu@mediatek.com>
---
drivers/mmc/host/mtk-sd.c | 32 ++++++++++++++++++++++----------
1 file changed, 22 insertions(+), 10 deletions(-)
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index ed37a3c..347ed72 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -723,21 +723,21 @@ static void msdc_unprepare_data(struct msdc_host *host, struct mmc_request *mrq)
}
}
-/* clock control primitives */
-static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
+static u64 msdc_timeout_cal(struct msdc_host *host, u64 ns, u64 clks)
{
- u32 timeout, clk_ns;
+ u64 timeout, clk_ns;
u32 mode = 0;
- host->timeout_ns = ns;
- host->timeout_clks = clks;
if (host->mmc->actual_clock == 0) {
timeout = 0;
} else {
- clk_ns = 1000000000UL / host->mmc->actual_clock;
- timeout = (ns + clk_ns - 1) / clk_ns + clks;
+ clk_ns = 1000000000ULL;
+ do_div(clk_ns, host->mmc->actual_clock);
+ timeout = ns + clk_ns - 1;
+ do_div(timeout, clk_ns);
+ timeout += clks;
/* in 1048576 sclk cycle unit */
- timeout = (timeout + (0x1 << 20) - 1) >> 20;
+ timeout = DIV_ROUND_UP(timeout, (0x1 << 20));
if (host->dev_comp->clk_div_bits == 8)
sdr_get_field(host->base + MSDC_CFG,
MSDC_CFG_CKMOD, &mode);
@@ -747,9 +747,21 @@ static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
/*DDR mode will double the clk cycles for data timeout */
timeout = mode >= 2 ? timeout * 2 : timeout;
timeout = timeout > 1 ? timeout - 1 : 0;
- timeout = timeout > 255 ? 255 : timeout;
}
- sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, timeout);
+ return timeout;
+}
+
+/* clock control primitives */
+static void msdc_set_timeout(struct msdc_host *host, u64 ns, u64 clks)
+{
+ u64 timeout;
+
+ host->timeout_ns = ns;
+ host->timeout_clks = clks;
+
+ timeout = msdc_timeout_cal(host, ns, clks);
+ sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC,
+ (u32)(timeout > 255 ? 255 : timeout));
}
static void msdc_gate_clock(struct msdc_host *host)
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v7 2/4] mmc: mediatek: refine msdc timeout api
2020-07-20 0:42 ` [PATCH v7 2/4] mmc: mediatek: refine msdc timeout api Chun-Hung Wu
@ 2020-07-20 15:43 ` Matthias Brugger
0 siblings, 0 replies; 9+ messages in thread
From: Matthias Brugger @ 2020-07-20 15:43 UTC (permalink / raw)
To: Chun-Hung Wu, mirq-linux, Jonathan Hunter, Al Cooper,
Adrian Hunter, Florian Fainelli, bcm-kernel-feedback-list,
Andy Gross, Bjorn Andersson, Michal Simek, Thierry Reding,
Chaotian Jing, Ulf Hansson, Rob Herring, Mark Rutland,
Linus Walleij, Pavel Machek, Kate Stewart, Greg Kroah-Hartman,
Martin Blumenstingl, Pan Bian, Thomas Gleixner, Allison Randal,
Mathieu Malaterre, Stanley Chu, Kuohong Wang
Cc: kernel-team, linux-kernel, linux-mmc, linux-mediatek, devicetree,
wsd_upstream, linux-arm-kernel, linux-arm-msm, linux-tegra
On 20/07/2020 02:42, Chun-Hung Wu wrote:
> Extract msdc timeout api common part to have
> better code architecture and avoid redundant code.
>
> Signed-off-by: Chun-Hung Wu <chun-hung.wu@mediatek.com>
Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---
> drivers/mmc/host/mtk-sd.c | 32 ++++++++++++++++++++++----------
> 1 file changed, 22 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> index ed37a3c..347ed72 100644
> --- a/drivers/mmc/host/mtk-sd.c
> +++ b/drivers/mmc/host/mtk-sd.c
> @@ -723,21 +723,21 @@ static void msdc_unprepare_data(struct msdc_host *host, struct mmc_request *mrq)
> }
> }
>
> -/* clock control primitives */
> -static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
> +static u64 msdc_timeout_cal(struct msdc_host *host, u64 ns, u64 clks)
> {
> - u32 timeout, clk_ns;
> + u64 timeout, clk_ns;
> u32 mode = 0;
>
> - host->timeout_ns = ns;
> - host->timeout_clks = clks;
> if (host->mmc->actual_clock == 0) {
> timeout = 0;
> } else {
> - clk_ns = 1000000000UL / host->mmc->actual_clock;
> - timeout = (ns + clk_ns - 1) / clk_ns + clks;
> + clk_ns = 1000000000ULL;
> + do_div(clk_ns, host->mmc->actual_clock);
> + timeout = ns + clk_ns - 1;
> + do_div(timeout, clk_ns);
> + timeout += clks;
> /* in 1048576 sclk cycle unit */
> - timeout = (timeout + (0x1 << 20) - 1) >> 20;
> + timeout = DIV_ROUND_UP(timeout, (0x1 << 20));
> if (host->dev_comp->clk_div_bits == 8)
> sdr_get_field(host->base + MSDC_CFG,
> MSDC_CFG_CKMOD, &mode);
> @@ -747,9 +747,21 @@ static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
> /*DDR mode will double the clk cycles for data timeout */
> timeout = mode >= 2 ? timeout * 2 : timeout;
> timeout = timeout > 1 ? timeout - 1 : 0;
> - timeout = timeout > 255 ? 255 : timeout;
> }
> - sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, timeout);
> + return timeout;
> +}
> +
> +/* clock control primitives */
> +static void msdc_set_timeout(struct msdc_host *host, u64 ns, u64 clks)
> +{
> + u64 timeout;
> +
> + host->timeout_ns = ns;
> + host->timeout_clks = clks;
> +
> + timeout = msdc_timeout_cal(host, ns, clks);
> + sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC,
> + (u32)(timeout > 255 ? 255 : timeout));
> }
>
> static void msdc_gate_clock(struct msdc_host *host)
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v7 3/4] mmc: mediatek: command queue support
2020-07-20 0:42 [PATCH v7 0/4] mmc: mediatek: add mmc cqhci support Chun-Hung Wu
2020-07-20 0:42 ` [PATCH v7 1/4] mmc: mediatek: add MT6779 MMC driver support Chun-Hung Wu
2020-07-20 0:42 ` [PATCH v7 2/4] mmc: mediatek: refine msdc timeout api Chun-Hung Wu
@ 2020-07-20 0:42 ` Chun-Hung Wu
2020-07-21 6:38 ` yong.mao
2020-07-20 0:42 ` [PATCH v7 4/4] dt-bindings: mmc: mediatek: Add document for mt6779 Chun-Hung Wu
2020-08-05 6:34 ` [PATCH v7 0/4] mmc: mediatek: add mmc cqhci support Ulf Hansson
4 siblings, 1 reply; 9+ messages in thread
From: Chun-Hung Wu @ 2020-07-20 0:42 UTC (permalink / raw)
To: mirq-linux, Jonathan Hunter, Al Cooper, Adrian Hunter,
Florian Fainelli, bcm-kernel-feedback-list, Andy Gross,
Bjorn Andersson, Michal Simek, Thierry Reding, Chaotian Jing,
Ulf Hansson, Rob Herring, Mark Rutland, Matthias Brugger,
Linus Walleij, Pavel Machek, Kate Stewart, Greg Kroah-Hartman,
Martin Blumenstingl, Pan Bian, Thomas Gleixner, Allison Randal,
Mathieu Malaterre, Stanley Chu, Kuohong Wang
Cc: kernel-team, linux-kernel, linux-mmc, linux-mediatek, devicetree,
wsd_upstream, linux-arm-kernel, linux-arm-msm, linux-tegra,
Chun-Hung Wu
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 <chun-hung.wu@mediatek.com>
---
drivers/mmc/host/Kconfig | 1 +
drivers/mmc/host/mtk-sd.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 116 insertions(+)
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 3b706af..9c89a5b 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -1009,6 +1009,7 @@ config MMC_MTK
tristate "MediaTek SD/MMC Card Interface support"
depends on HAS_DMA
select REGULATOR
+ select MMC_CQHCI
help
This selects the MediaTek(R) Secure digital and Multimedia card Interface.
If you have a machine with a integrated SD/MMC card reader, say Y or M here.
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 347ed72..e560a06 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -31,6 +31,8 @@
#include <linux/mmc/sdio.h>
#include <linux/mmc/slot-gpio.h>
+#include "cqhci.h"
+
#define MAX_BD_NUM 1024
/*--------------------------------------------------------------------------*/
@@ -152,6 +154,7 @@
#define MSDC_INT_DMA_BDCSERR (0x1 << 17) /* W1C */
#define MSDC_INT_DMA_GPDCSERR (0x1 << 18) /* W1C */
#define MSDC_INT_DMA_PROTECT (0x1 << 19) /* W1C */
+#define MSDC_INT_CMDQ (0x1 << 28) /* W1C */
/* MSDC_INTEN mask */
#define MSDC_INTEN_MMCIRQ (0x1 << 0) /* RW */
@@ -182,6 +185,7 @@
/* SDC_CFG mask */
#define SDC_CFG_SDIOINTWKUP (0x1 << 0) /* RW */
#define SDC_CFG_INSWKUP (0x1 << 1) /* RW */
+#define SDC_CFG_WRDTOC (0x1fff << 2) /* RW */
#define SDC_CFG_BUSWIDTH (0x3 << 16) /* RW */
#define SDC_CFG_SDIO (0x1 << 19) /* RW */
#define SDC_CFG_SDIOIDE (0x1 << 20) /* RW */
@@ -230,6 +234,7 @@
#define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */
#define MSDC_PATCH_BIT1_CMDTA (0x7 << 3) /* RW */
+#define MSDC_PB1_BUSY_CHECK_SEL (0x1 << 7) /* RW */
#define MSDC_PATCH_BIT1_STOP_DLY (0xf << 8) /* RW */
#define MSDC_PATCH_BIT2_CFGRESP (0x1 << 15) /* RW */
@@ -431,9 +436,11 @@ struct msdc_host {
/* cmd response sample selection for HS400 */
bool hs400_mode; /* current eMMC will run at hs400 mode */
bool internal_cd; /* Use internal card-detect logic */
+ bool cqhci; /* support eMMC hw cmdq */
struct msdc_save_para save_para; /* used when gate HCLK */
struct msdc_tune_para def_tune_para; /* default tune setting */
struct msdc_tune_para saved_tune_para; /* tune result of CMD21/CMD19 */
+ struct cqhci_host *cq_host;
};
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)
(u32)(timeout > 255 ? 255 : timeout));
}
+static void msdc_set_busy_timeout(struct msdc_host *host, u64 ns, u64 clks)
+{
+ u64 timeout;
+
+ timeout = msdc_timeout_cal(host, ns, clks);
+ sdr_set_field(host->base + SDC_CFG, SDC_CFG_WRDTOC,
+ (u32)(timeout > 8191 ? 8191 : timeout));
+}
+
static void msdc_gate_clock(struct msdc_host *host)
{
clk_disable_unprepare(host->src_clk_cg);
@@ -1481,6 +1497,34 @@ static void msdc_enable_sdio_irq(struct mmc_host *mmc, int enb)
pm_runtime_put_noidle(host->dev);
}
+static irqreturn_t msdc_cmdq_irq(struct msdc_host *host, u32 intsts)
+{
+ int cmd_err = 0, dat_err = 0;
+
+ if (intsts & MSDC_INT_RSPCRCERR) {
+ cmd_err = -EILSEQ;
+ dev_err(host->dev, "%s: CMD CRC ERR", __func__);
+ } else if (intsts & MSDC_INT_CMDTMO) {
+ cmd_err = -ETIMEDOUT;
+ dev_err(host->dev, "%s: CMD TIMEOUT ERR", __func__);
+ }
+
+ if (intsts & MSDC_INT_DATCRCERR) {
+ dat_err = -EILSEQ;
+ dev_err(host->dev, "%s: DATA CRC ERR", __func__);
+ } else if (intsts & MSDC_INT_DATTMO) {
+ dat_err = -ETIMEDOUT;
+ dev_err(host->dev, "%s: DATA TIMEOUT ERR", __func__);
+ }
+
+ if (cmd_err || dat_err) {
+ dev_err(host->dev, "cmd_err = %d, dat_err =%d, intsts = 0x%x",
+ cmd_err, dat_err, intsts);
+ }
+
+ return cqhci_irq(host->mmc, 0, cmd_err, dat_err);
+}
+
static irqreturn_t msdc_irq(int irq, void *dev_id)
{
struct msdc_host *host = (struct msdc_host *) dev_id;
@@ -1517,6 +1561,14 @@ static irqreturn_t msdc_irq(int irq, void *dev_id)
if (!(events & (event_mask & ~MSDC_INT_SDIOIRQ)))
break;
+ if ((host->mmc->caps2 & MMC_CAP2_CQE) &&
+ (events & MSDC_INT_CMDQ)) {
+ msdc_cmdq_irq(host, events);
+ /* clear interrupts */
+ writel(events, host->base + MSDC_INT);
+ return IRQ_HANDLED;
+ }
+
if (!mrq) {
dev_err(host->dev,
"%s: MRQ=NULL; events=%08X; event_mask=%08X\n",
@@ -2201,6 +2253,36 @@ static int msdc_get_cd(struct mmc_host *mmc)
return !val;
}
+static void msdc_cqe_enable(struct mmc_host *mmc)
+{
+ struct msdc_host *host = mmc_priv(mmc);
+
+ /* enable cmdq irq */
+ writel(MSDC_INT_CMDQ, host->base + MSDC_INTEN);
+ /* enable busy check */
+ sdr_set_bits(host->base + MSDC_PATCH_BIT1, MSDC_PB1_BUSY_CHECK_SEL);
+ /* default write data / busy timeout 20s */
+ msdc_set_busy_timeout(host, 20 * 1000000000ULL, 0);
+ /* default read data timeout 1s */
+ msdc_set_timeout(host, 1000000000ULL, 0);
+}
+
+void msdc_cqe_disable(struct mmc_host *mmc, bool recovery)
+{
+ struct msdc_host *host = mmc_priv(mmc);
+
+ /* disable cmdq irq */
+ sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INT_CMDQ);
+ /* disable busy check */
+ sdr_clr_bits(host->base + MSDC_PATCH_BIT1, MSDC_PB1_BUSY_CHECK_SEL);
+
+ if (recovery) {
+ sdr_set_field(host->base + MSDC_DMA_CTRL,
+ MSDC_DMA_CTRL_STOP, 1);
+ msdc_reset_hw(host);
+ }
+}
+
static const struct mmc_host_ops mt_msdc_ops = {
.post_req = msdc_post_req,
.pre_req = msdc_pre_req,
@@ -2217,6 +2299,11 @@ static int msdc_get_cd(struct mmc_host *mmc)
.hw_reset = msdc_hw_reset,
};
+static const struct cqhci_host_ops msdc_cmdq_ops = {
+ .enable = msdc_cqe_enable,
+ .disable = msdc_cqe_disable,
+};
+
static void msdc_of_property_parse(struct platform_device *pdev,
struct msdc_host *host)
{
@@ -2237,6 +2324,12 @@ static void msdc_of_property_parse(struct platform_device *pdev,
host->hs400_cmd_resp_sel_rising = true;
else
host->hs400_cmd_resp_sel_rising = false;
+
+ if (of_property_read_bool(pdev->dev.of_node,
+ "supports-cqe"))
+ host->cqhci = true;
+ else
+ host->cqhci = false;
}
static int msdc_drv_probe(struct platform_device *pdev)
@@ -2352,6 +2445,8 @@ static int msdc_drv_probe(struct platform_device *pdev)
mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
mmc->caps |= MMC_CAP_CMD23;
+ if (host->cqhci)
+ mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD;
/* MMC core transfer sizes tunable parameters */
mmc->max_segs = MAX_BD_NUM;
if (host->dev_comp->support_64g)
@@ -2367,6 +2462,26 @@ static int msdc_drv_probe(struct platform_device *pdev)
host->dma_mask = DMA_BIT_MASK(32);
mmc_dev(mmc)->dma_mask = &host->dma_mask;
+ if (mmc->caps2 & MMC_CAP2_CQE) {
+ host->cq_host = devm_kzalloc(host->mmc->parent,
+ sizeof(*host->cq_host),
+ GFP_KERNEL);
+ if (!host->cq_host) {
+ ret = -ENOMEM;
+ goto host_free;
+ }
+ host->cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
+ host->cq_host->mmio = host->base + 0x800;
+ host->cq_host->ops = &msdc_cmdq_ops;
+ ret = cqhci_init(host->cq_host, mmc, true);
+ if (ret)
+ goto host_free;
+ mmc->max_segs = 128;
+ /* cqhci 16bit length */
+ /* 0 size, means 65536 so we don't have to -1 here */
+ mmc->max_seg_size = 64 * 1024;
+ }
+
host->timeout_clks = 3 * 1048576;
host->dma.gpd = dma_alloc_coherent(&pdev->dev,
2 * sizeof(struct mt_gpdma_desc),
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v7 3/4] mmc: mediatek: command queue support
2020-07-20 0:42 ` [PATCH v7 3/4] mmc: mediatek: command queue support Chun-Hung Wu
@ 2020-07-21 6:38 ` yong.mao
0 siblings, 0 replies; 9+ messages in thread
From: yong.mao @ 2020-07-21 6:38 UTC (permalink / raw)
To: Chun-Hung Wu
Cc: mirq-linux, Jonathan Hunter, Al Cooper, Adrian Hunter,
Florian Fainelli, bcm-kernel-feedback-list, Andy Gross,
Bjorn Andersson, Michal Simek, Thierry Reding, Chaotian Jing,
Ulf Hansson, Rob Herring, Mark Rutland, Matthias Brugger,
Linus Walleij, Pavel Machek, Kate Stewart, Greg Kroah-Hartman,
Martin Blumenstingl, Pan Bian, Thomas Gleixner, Allison Randal,
Mathieu Malaterre, Stanley Chu, Kuohong Wang, devicetree,
wsd_upstream, linux-arm-msm, linux-mmc, linux-kernel,
linux-mediatek, linux-tegra, kernel-team, linux-arm-kernel
On Mon, 2020-07-20 at 08:42 +0800, Chun-Hung Wu wrote:
> 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 <chun-hung.wu@mediatek.com>
> ---
> drivers/mmc/host/Kconfig | 1 +
> drivers/mmc/host/mtk-sd.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 116 insertions(+)
>
Acked-by: Yong Mao <yong.mao@mediatek.com>
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index 3b706af..9c89a5b 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -1009,6 +1009,7 @@ config MMC_MTK
> tristate "MediaTek SD/MMC Card Interface support"
> depends on HAS_DMA
> select REGULATOR
> + select MMC_CQHCI
> help
> This selects the MediaTek(R) Secure digital and Multimedia card Interface.
> If you have a machine with a integrated SD/MMC card reader, say Y or M here.
> diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> index 347ed72..e560a06 100644
> --- a/drivers/mmc/host/mtk-sd.c
> +++ b/drivers/mmc/host/mtk-sd.c
> @@ -31,6 +31,8 @@
> #include <linux/mmc/sdio.h>
> #include <linux/mmc/slot-gpio.h>
>
> +#include "cqhci.h"
> +
> #define MAX_BD_NUM 1024
>
> /*--------------------------------------------------------------------------*/
> @@ -152,6 +154,7 @@
> #define MSDC_INT_DMA_BDCSERR (0x1 << 17) /* W1C */
> #define MSDC_INT_DMA_GPDCSERR (0x1 << 18) /* W1C */
> #define MSDC_INT_DMA_PROTECT (0x1 << 19) /* W1C */
> +#define MSDC_INT_CMDQ (0x1 << 28) /* W1C */
>
> /* MSDC_INTEN mask */
> #define MSDC_INTEN_MMCIRQ (0x1 << 0) /* RW */
> @@ -182,6 +185,7 @@
> /* SDC_CFG mask */
> #define SDC_CFG_SDIOINTWKUP (0x1 << 0) /* RW */
> #define SDC_CFG_INSWKUP (0x1 << 1) /* RW */
> +#define SDC_CFG_WRDTOC (0x1fff << 2) /* RW */
> #define SDC_CFG_BUSWIDTH (0x3 << 16) /* RW */
> #define SDC_CFG_SDIO (0x1 << 19) /* RW */
> #define SDC_CFG_SDIOIDE (0x1 << 20) /* RW */
> @@ -230,6 +234,7 @@
> #define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */
>
> #define MSDC_PATCH_BIT1_CMDTA (0x7 << 3) /* RW */
> +#define MSDC_PB1_BUSY_CHECK_SEL (0x1 << 7) /* RW */
> #define MSDC_PATCH_BIT1_STOP_DLY (0xf << 8) /* RW */
>
> #define MSDC_PATCH_BIT2_CFGRESP (0x1 << 15) /* RW */
> @@ -431,9 +436,11 @@ struct msdc_host {
> /* cmd response sample selection for HS400 */
> bool hs400_mode; /* current eMMC will run at hs400 mode */
> bool internal_cd; /* Use internal card-detect logic */
> + bool cqhci; /* support eMMC hw cmdq */
> struct msdc_save_para save_para; /* used when gate HCLK */
> struct msdc_tune_para def_tune_para; /* default tune setting */
> struct msdc_tune_para saved_tune_para; /* tune result of CMD21/CMD19 */
> + struct cqhci_host *cq_host;
> };
>
> 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)
> (u32)(timeout > 255 ? 255 : timeout));
> }
>
> +static void msdc_set_busy_timeout(struct msdc_host *host, u64 ns, u64 clks)
> +{
> + u64 timeout;
> +
> + timeout = msdc_timeout_cal(host, ns, clks);
> + sdr_set_field(host->base + SDC_CFG, SDC_CFG_WRDTOC,
> + (u32)(timeout > 8191 ? 8191 : timeout));
> +}
> +
> static void msdc_gate_clock(struct msdc_host *host)
> {
> clk_disable_unprepare(host->src_clk_cg);
> @@ -1481,6 +1497,34 @@ static void msdc_enable_sdio_irq(struct mmc_host *mmc, int enb)
> pm_runtime_put_noidle(host->dev);
> }
>
> +static irqreturn_t msdc_cmdq_irq(struct msdc_host *host, u32 intsts)
> +{
> + int cmd_err = 0, dat_err = 0;
> +
> + if (intsts & MSDC_INT_RSPCRCERR) {
> + cmd_err = -EILSEQ;
> + dev_err(host->dev, "%s: CMD CRC ERR", __func__);
> + } else if (intsts & MSDC_INT_CMDTMO) {
> + cmd_err = -ETIMEDOUT;
> + dev_err(host->dev, "%s: CMD TIMEOUT ERR", __func__);
> + }
> +
> + if (intsts & MSDC_INT_DATCRCERR) {
> + dat_err = -EILSEQ;
> + dev_err(host->dev, "%s: DATA CRC ERR", __func__);
> + } else if (intsts & MSDC_INT_DATTMO) {
> + dat_err = -ETIMEDOUT;
> + dev_err(host->dev, "%s: DATA TIMEOUT ERR", __func__);
> + }
> +
> + if (cmd_err || dat_err) {
> + dev_err(host->dev, "cmd_err = %d, dat_err =%d, intsts = 0x%x",
> + cmd_err, dat_err, intsts);
> + }
> +
> + return cqhci_irq(host->mmc, 0, cmd_err, dat_err);
> +}
> +
> static irqreturn_t msdc_irq(int irq, void *dev_id)
> {
> struct msdc_host *host = (struct msdc_host *) dev_id;
> @@ -1517,6 +1561,14 @@ static irqreturn_t msdc_irq(int irq, void *dev_id)
> if (!(events & (event_mask & ~MSDC_INT_SDIOIRQ)))
> break;
>
> + if ((host->mmc->caps2 & MMC_CAP2_CQE) &&
> + (events & MSDC_INT_CMDQ)) {
> + msdc_cmdq_irq(host, events);
> + /* clear interrupts */
> + writel(events, host->base + MSDC_INT);
> + return IRQ_HANDLED;
> + }
> +
> if (!mrq) {
> dev_err(host->dev,
> "%s: MRQ=NULL; events=%08X; event_mask=%08X\n",
> @@ -2201,6 +2253,36 @@ static int msdc_get_cd(struct mmc_host *mmc)
> return !val;
> }
>
> +static void msdc_cqe_enable(struct mmc_host *mmc)
> +{
> + struct msdc_host *host = mmc_priv(mmc);
> +
> + /* enable cmdq irq */
> + writel(MSDC_INT_CMDQ, host->base + MSDC_INTEN);
> + /* enable busy check */
> + sdr_set_bits(host->base + MSDC_PATCH_BIT1, MSDC_PB1_BUSY_CHECK_SEL);
> + /* default write data / busy timeout 20s */
> + msdc_set_busy_timeout(host, 20 * 1000000000ULL, 0);
> + /* default read data timeout 1s */
> + msdc_set_timeout(host, 1000000000ULL, 0);
> +}
> +
> +void msdc_cqe_disable(struct mmc_host *mmc, bool recovery)
> +{
> + struct msdc_host *host = mmc_priv(mmc);
> +
> + /* disable cmdq irq */
> + sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INT_CMDQ);
> + /* disable busy check */
> + sdr_clr_bits(host->base + MSDC_PATCH_BIT1, MSDC_PB1_BUSY_CHECK_SEL);
> +
> + if (recovery) {
> + sdr_set_field(host->base + MSDC_DMA_CTRL,
> + MSDC_DMA_CTRL_STOP, 1);
> + msdc_reset_hw(host);
> + }
> +}
> +
> static const struct mmc_host_ops mt_msdc_ops = {
> .post_req = msdc_post_req,
> .pre_req = msdc_pre_req,
> @@ -2217,6 +2299,11 @@ static int msdc_get_cd(struct mmc_host *mmc)
> .hw_reset = msdc_hw_reset,
> };
>
> +static const struct cqhci_host_ops msdc_cmdq_ops = {
> + .enable = msdc_cqe_enable,
> + .disable = msdc_cqe_disable,
> +};
> +
> static void msdc_of_property_parse(struct platform_device *pdev,
> struct msdc_host *host)
> {
> @@ -2237,6 +2324,12 @@ static void msdc_of_property_parse(struct platform_device *pdev,
> host->hs400_cmd_resp_sel_rising = true;
> else
> host->hs400_cmd_resp_sel_rising = false;
> +
> + if (of_property_read_bool(pdev->dev.of_node,
> + "supports-cqe"))
> + host->cqhci = true;
> + else
> + host->cqhci = false;
> }
>
> static int msdc_drv_probe(struct platform_device *pdev)
> @@ -2352,6 +2445,8 @@ static int msdc_drv_probe(struct platform_device *pdev)
> mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
>
> mmc->caps |= MMC_CAP_CMD23;
> + if (host->cqhci)
> + mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD;
> /* MMC core transfer sizes tunable parameters */
> mmc->max_segs = MAX_BD_NUM;
> if (host->dev_comp->support_64g)
> @@ -2367,6 +2462,26 @@ static int msdc_drv_probe(struct platform_device *pdev)
> host->dma_mask = DMA_BIT_MASK(32);
> mmc_dev(mmc)->dma_mask = &host->dma_mask;
>
> + if (mmc->caps2 & MMC_CAP2_CQE) {
> + host->cq_host = devm_kzalloc(host->mmc->parent,
> + sizeof(*host->cq_host),
> + GFP_KERNEL);
> + if (!host->cq_host) {
> + ret = -ENOMEM;
> + goto host_free;
> + }
> + host->cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
> + host->cq_host->mmio = host->base + 0x800;
> + host->cq_host->ops = &msdc_cmdq_ops;
> + ret = cqhci_init(host->cq_host, mmc, true);
> + if (ret)
> + goto host_free;
> + mmc->max_segs = 128;
> + /* cqhci 16bit length */
> + /* 0 size, means 65536 so we don't have to -1 here */
> + mmc->max_seg_size = 64 * 1024;
> + }
> +
> host->timeout_clks = 3 * 1048576;
> host->dma.gpd = dma_alloc_coherent(&pdev->dev,
> 2 * sizeof(struct mt_gpdma_desc),
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v7 4/4] dt-bindings: mmc: mediatek: Add document for mt6779
2020-07-20 0:42 [PATCH v7 0/4] mmc: mediatek: add mmc cqhci support Chun-Hung Wu
` (2 preceding siblings ...)
2020-07-20 0:42 ` [PATCH v7 3/4] mmc: mediatek: command queue support Chun-Hung Wu
@ 2020-07-20 0:42 ` Chun-Hung Wu
2020-07-20 19:23 ` Rob Herring
2020-08-05 6:34 ` [PATCH v7 0/4] mmc: mediatek: add mmc cqhci support Ulf Hansson
4 siblings, 1 reply; 9+ messages in thread
From: Chun-Hung Wu @ 2020-07-20 0:42 UTC (permalink / raw)
To: mirq-linux, Jonathan Hunter, Al Cooper, Adrian Hunter,
Florian Fainelli, bcm-kernel-feedback-list, Andy Gross,
Bjorn Andersson, Michal Simek, Thierry Reding, Chaotian Jing,
Ulf Hansson, Rob Herring, Mark Rutland, Matthias Brugger,
Linus Walleij, Pavel Machek, Kate Stewart, Greg Kroah-Hartman,
Martin Blumenstingl, Pan Bian, Thomas Gleixner, Allison Randal,
Mathieu Malaterre, Stanley Chu, Kuohong Wang
Cc: kernel-team, linux-kernel, linux-mmc, linux-mediatek, devicetree,
wsd_upstream, linux-arm-kernel, linux-arm-msm, linux-tegra,
Chun-Hung Wu
Add compatible node for mt6779 mmc.
Signed-off-by: Chun-Hung Wu <chun-hung.wu@mediatek.com>
---
Documentation/devicetree/bindings/mmc/mtk-sd.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt
index 8a532f4..0c9cf6a 100644
--- a/Documentation/devicetree/bindings/mmc/mtk-sd.txt
+++ b/Documentation/devicetree/bindings/mmc/mtk-sd.txt
@@ -12,6 +12,7 @@ Required properties:
"mediatek,mt8173-mmc": for mmc host ip compatible with mt8173
"mediatek,mt8183-mmc": for mmc host ip compatible with mt8183
"mediatek,mt8516-mmc": for mmc host ip compatible with mt8516
+ "mediatek,mt6779-mmc": for mmc host ip compatible with mt6779
"mediatek,mt2701-mmc": for mmc host ip compatible with mt2701
"mediatek,mt2712-mmc": for mmc host ip compatible with mt2712
"mediatek,mt7622-mmc": for MT7622 SoC
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v7 4/4] dt-bindings: mmc: mediatek: Add document for mt6779
2020-07-20 0:42 ` [PATCH v7 4/4] dt-bindings: mmc: mediatek: Add document for mt6779 Chun-Hung Wu
@ 2020-07-20 19:23 ` Rob Herring
0 siblings, 0 replies; 9+ messages in thread
From: Rob Herring @ 2020-07-20 19:23 UTC (permalink / raw)
To: Chun-Hung Wu
Cc: Matthias Brugger, devicetree, Thomas Gleixner, Bjorn Andersson,
Ulf Hansson, linux-mmc, Thierry Reding, Chaotian Jing,
Florian Fainelli, linux-kernel, mirq-linux, Andy Gross,
Stanley Chu, Al Cooper, bcm-kernel-feedback-list, wsd_upstream,
linux-arm-msm, Mathieu Malaterre, Mark Rutland, Pavel Machek,
Kate Stewart, Greg Kroah-Hartman, linux-arm-kernel, Rob Herring,
linux-mediatek, Martin Blumenstingl, Adrian Hunter, Pan Bian,
Jonathan Hunter, Linus Walleij, linux-tegra, Michal Simek,
Kuohong Wang, kernel-team, Allison Randal
On Mon, 20 Jul 2020 08:42:39 +0800, Chun-Hung Wu wrote:
> Add compatible node for mt6779 mmc.
>
> Signed-off-by: Chun-Hung Wu <chun-hung.wu@mediatek.com>
> ---
> Documentation/devicetree/bindings/mmc/mtk-sd.txt | 1 +
> 1 file changed, 1 insertion(+)
>
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v7 0/4] mmc: mediatek: add mmc cqhci support
2020-07-20 0:42 [PATCH v7 0/4] mmc: mediatek: add mmc cqhci support Chun-Hung Wu
` (3 preceding siblings ...)
2020-07-20 0:42 ` [PATCH v7 4/4] dt-bindings: mmc: mediatek: Add document for mt6779 Chun-Hung Wu
@ 2020-08-05 6:34 ` Ulf Hansson
4 siblings, 0 replies; 9+ messages in thread
From: Ulf Hansson @ 2020-08-05 6:34 UTC (permalink / raw)
To: Chun-Hung Wu
Cc: Michał Mirosław, Jonathan Hunter, Al Cooper,
Adrian Hunter, Florian Fainelli, BCM Kernel Feedback, Andy Gross,
Bjorn Andersson, Michal Simek, Thierry Reding, Chaotian Jing,
Rob Herring, Mark Rutland, Matthias Brugger, Linus Walleij,
Pavel Machek, Kate Stewart, Greg Kroah-Hartman,
Martin Blumenstingl, Pan Bian, Thomas Gleixner, Allison Randal,
Mathieu Malaterre, Stanley Chu, Kuohong Wang,
Android Kernel Team, Linux Kernel Mailing List, linux-mmc,
moderated list:ARM/Mediatek SoC support, DTML, wsd_upstream,
Linux ARM, linux-arm-msm, linux-tegra
On Mon, 20 Jul 2020 at 02:42, Chun-Hung Wu <chun-hung.wu@mediatek.com> wrote:
>
> This series provides MediaTek cqhci implementations as below:
> - Refine msdc timeout api to reduce redundant code
> - MediaTek command queue support
> - dt-bindings for mt6779
>
> v1 -> v2:
> - Add more patch details in commit message
> - Separate msdc timeout api refine to individual patch
>
> v2 -> v3:
> - Remove CR-Id, Change-Id and Feature in patches
> - Add Signed-off-by in patches
>
> v3 -> v4:
> - Refine CQE bindings in mmc_of_parse (Ulf Hansson)
> - Remove redundant host CQE bindings (Linux Walleij)
>
> v4 -> v5:
> - Add Acked-by and more maintainers
>
> v5 -> v6:
> - Move CQE bindings back to vendor driver
> - Add mt6779 mmc support as an individual patch
> - Error handling for cq_host devm_kzallo()
>
> v6 -> v7:
> - Select MMC_CQHCI for MMC_MTK
> - Remove unnecessary option MMC_CQHCI in mtk-sd.c
> - Add error handling for cqhci_init()
> - Use native cqhci dt-bindings 'supports-cqe'
>
> Chun-Hung Wu (4):
> [1/4] mmc: mediatek: add MT6779 MMC driver support
> [2/4] mmc: mediatek: refine msdc timeout api
> [3/4] mmc: mediatek: command queue support
> [4/4] dt-bindings: mmc: mediatek: Add document for mt6779
>
> Documentation/devicetree/bindings/mmc/mtk-sd.txt | 1 +
> drivers/mmc/host/Kconfig | 1 +
> drivers/mmc/host/mtk-sd.c | 160 +++++++++++++++++++++--
> 3 files changed, 152 insertions(+), 10 deletions(-)
>
> --
> 1.9.1
Applied for next (a while ago), thanks!
Kind regards
Uffe
^ permalink raw reply [flat|nested] 9+ messages in thread