RE: [PATCH V9 14/15] mmc: cqhci: support for command queue enabled host
From: Bough Chen <haibo.chen@nxp.com>
Date: 2017-09-25 02:39:39
Also in:
linux-mmc, lkml
-----Original Message----- From: Adrian Hunter [mailto:adrian.hunter@intel.com] Sent: Friday, September 22, 2017 8:37 PM To: Ulf Hansson <redacted> Cc: linux-mmc <redacted>; linux-block <linux- block@vger.kernel.org>; linux-kernel [off-list ref]; Boug=
h
Chen [off-list ref]; Alex Lemberg [off-list ref]; Mateusz Nowak [off-list ref]; Yuliy Izrailov [off-list ref]; Jaehoon Chung [off-list ref]; Dong Aisheng [off-list ref]; Das Asutosh [off-list ref]; Zhangfei Gao [off-list ref]; Sahitya Tummala [off-list ref]; Harjani Ritesh [off-list ref]; Venu Byravarasu [off-list ref]; Linus Walleij [off-list ref]; Shawn Lin <shawn.lin@rock- chips.com>; Christoph Hellwig [off-list ref] Subject: [PATCH V9 14/15] mmc: cqhci: support for command queue enabled host =20 From: Venkat Gopalakrishnan <redacted> =20 This patch adds CMDQ support for command-queue compatible hosts. =20 Command queue is added in eMMC-5.1 specification. This enables the controller to process upto 32 requests at a time. =20 Adrian Hunter contributed renaming to cqhci, recovery, suspend and resume=
,
quoted hunk ↗ jump to hunk
cqhci_off, cqhci_wait_for_idle, and external timeout handling. =20 Signed-off-by: Asutosh Das <redacted> Signed-off-by: Sujit Reddy Thumma <redacted> Signed-off-by: Konstantin Dorfman <redacted> Signed-off-by: Venkat Gopalakrishnan <redacted> Signed-off-by: Subhash Jadavani <redacted> Signed-off-by: Ritesh Harjani <redacted> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> --- drivers/mmc/host/Kconfig | 13 + drivers/mmc/host/Makefile | 1 + drivers/mmc/host/cqhci.c | 1154 +++++++++++++++++++++++++++++++++++++++++++++ drivers/mmc/host/cqhci.h | 240 ++++++++++ 4 files changed, 1408 insertions(+) create mode 100644 drivers/mmc/host/cqhci.c create mode 100644 drivers/mmc/host/cqhci.h =20diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index17afe1ad3a03..f2751465bc54 100644--- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig@@ -843,6 +843,19 @@ config MMC_SUNXI This selects support for the SD/MMC Host Controller on Allwinner sunxi SoCs.=20 +config MMC_CQHCI + tristate "Command Queue Host Controller Interface support" + depends on HAS_DMA + help + This selects the Command Queue Host Controller Interface (CQHCI) + support present in host controllers of Qualcomm Technologies, Inc + amongst others. + This controller supports eMMC devices with command queue support. + + If you have a controller with this interface, say Y or M here. + + If unsure, say N. + config MMC_TOSHIBA_PCI tristate "Toshiba Type A SD/MMC Card Interface Driver" depends on PCIdiff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index2b5a8133948d..f01d9915304d 100644--- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile@@ -90,6 +90,7 @@ obj-$(CONFIG_MMC_SDHCI_ST) +=3D sdhci-st.o obj-$(CONFIG_MMC_SDHCI_MICROCHIP_PIC32) +=3D sdhci-pic32.o obj-$(CONFIG_MMC_SDHCI_BRCMSTB) +=3D sdhci-brcmstb.o obj-$(CONFIG_MMC_SDHCI_OMAP) +=3D sdhci-omap.o +obj-$(CONFIG_MMC_CQHCI) +=3D cqhci.o=20 ifeq ($(CONFIG_CB710_DEBUG),y) CFLAGS-cb710-mmc +=3D -DDEBUGdiff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c new filemode 100644 index 000000000000..eb3c1695b0c7--- /dev/null +++ b/drivers/mmc/host/cqhci.c@@ -0,0 +1,1154 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/delay.h> +#include <linux/highmem.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/dma-mapping.h> +#include <linux/slab.h> +#include <linux/scatterlist.h> +#include <linux/platform_device.h> +#include <linux/ktime.h> + +#include <linux/mmc/mmc.h> +#include <linux/mmc/host.h> +#include <linux/mmc/card.h> + +#include "cqhci.h" + +#define DCMD_SLOT 31 +#define NUM_SLOTS 32 + +struct cqhci_slot { + struct mmc_request *mrq; + unsigned int flags; +#define CQHCI_EXTERNAL_TIMEOUT BIT(0) +#define CQHCI_COMPLETED BIT(1) +#define CQHCI_HOST_CRC BIT(2) +#define CQHCI_HOST_TIMEOUT BIT(3) +#define CQHCI_HOST_OTHER BIT(4) +}; + +static inline u8 *get_desc(struct cqhci_host *cq_host, u8 tag) { + return cq_host->desc_base + (tag * cq_host->slot_sz); } + +static inline u8 *get_link_desc(struct cqhci_host *cq_host, u8 tag) { + u8 *desc =3D get_desc(cq_host, tag); + + return desc + cq_host->task_desc_len; +} + +static inline dma_addr_t get_trans_desc_dma(struct cqhci_host *cq_host, +u8 tag) { + return cq_host->trans_desc_dma_base + + (cq_host->mmc->max_segs * tag * + cq_host->trans_desc_len); +} + +static inline u8 *get_trans_desc(struct cqhci_host *cq_host, u8 tag) { + return cq_host->trans_desc_base + + (cq_host->trans_desc_len * cq_host->mmc->max_segs * tag); } + +static void setup_trans_desc(struct cqhci_host *cq_host, u8 tag) { + u8 *link_temp; + dma_addr_t trans_temp; + + link_temp =3D get_link_desc(cq_host, tag); + trans_temp =3D get_trans_desc_dma(cq_host, tag); + + memset(link_temp, 0, cq_host->link_desc_len); + if (cq_host->link_desc_len > 8) + *(link_temp + 8) =3D 0; + + if (tag =3D=3D DCMD_SLOT && (cq_host->mmc->caps2 &MMC_CAP2_CQE_DCMD)) { + *link_temp =3D CQHCI_VALID(0) | CQHCI_ACT(0) | CQHCI_END(1); + return; + } + + *link_temp =3D CQHCI_VALID(1) | CQHCI_ACT(0x6) | CQHCI_END(0); + + if (cq_host->dma64) { + __le64 *data_addr =3D (__le64 __force *)(link_temp + 4); + + data_addr[0] =3D cpu_to_le64(trans_temp); + } else { + __le32 *data_addr =3D (__le32 __force *)(link_temp + 4); + + data_addr[0] =3D cpu_to_le32(trans_temp); + } +} + +static void cqhci_set_irqs(struct cqhci_host *cq_host, u32 set) { + u32 ier; + + ier =3D cqhci_readl(cq_host, CQHCI_ISTE); + ier |=3D set;
Hi Adrian, I think operation ' |=3D ' is not correct, since we will also call cqhci_se= t_irqs(cq_host, 0), Which means to mask all cmdq irq, so I think better to directly write the = parameter 'set' to ISTE and ISGE. Best Regards, Haibo Chen
+ cqhci_writel(cq_host, ier, CQHCI_ISTE); + cqhci_writel(cq_host, ier, CQHCI_ISGE); } + +#define DRV_NAME "cqhci" +