> -Original Message-
> From: Adrian Hunter [mailto:adrian.hun...@intel.com]
> Sent: Friday, September 22, 2017 8:37 PM
> To: Ulf Hansson
> Cc: linux-mmc ; linux-block bl...@vger.kernel.org>; linux-kernel ; Bough
> Chen ; Alex Lemberg ;
> Mateusz Nowak ; Yuliy Izrailov
> ; Jaehoon Chung ;
> Dong Aisheng ; Das Asutosh
> ; Zhangfei Gao ;
> Sahitya Tummala ; Harjani Ritesh
> ; Venu Byravarasu ;
> Linus Walleij ; Shawn Lin chips.com>; Christoph Hellwig
> Subject: [PATCH V9 14/15] mmc: cqhci: support for command queue enabled
> host
>
> From: Venkat Gopalakrishnan
>
> This patch adds CMDQ support for command-queue compatible hosts.
>
> Command queue is added in eMMC-5.1 specification. This enables the
> controller to process upto 32 requests at a time.
>
> Adrian Hunter contributed renaming to cqhci, recovery, suspend and resume,
> cqhci_off, cqhci_wait_for_idle, and external timeout handling.
>
> Signed-off-by: Asutosh Das
> Signed-off-by: Sujit Reddy Thumma
> Signed-off-by: Konstantin Dorfman
> Signed-off-by: Venkat Gopalakrishnan
> Signed-off-by: Subhash Jadavani
> Signed-off-by: Ritesh Harjani
> Signed-off-by: Adrian Hunter
> ---
> 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
>
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index
> 17afe1ad3a03..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.
>
> +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 PCI
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index
> 2b5a8133948d..f01d9915304d 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -90,6 +90,7 @@ obj-$(CONFIG_MMC_SDHCI_ST) += sdhci-st.o
> obj-$(CONFIG_MMC_SDHCI_MICROCHIP_PIC32) += sdhci-pic32.o
> obj-$(CONFIG_MMC_SDHCI_BRCMSTB) += sdhci-brcmstb.o
> obj-$(CONFIG_MMC_SDHCI_OMAP) += sdhci-omap.o
> +obj-$(CONFIG_MMC_CQHCI) += cqhci.o
>
> ifeq ($(CONFIG_CB710_DEBUG),y)
> CFLAGS-cb710-mmc+= -DDEBUG
> diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c new file
> mode 100644 index ..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
> +#include
> +#include
> +#include
> +#include
> +#include
> +#include
> +#include
> +#include
> +
> +#include
> +#include
> +#include
> +
> +#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 = 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 +
> +