Received: by 2002:ac0:a582:0:0:0:0:0 with SMTP id m2-v6csp444363imm; Fri, 5 Oct 2018 06:25:46 -0700 (PDT) X-Google-Smtp-Source: ACcGV61MCaQZEw665QSaFatbqnU6+ha2Szou5Epd3IoapEyv3ubi+22EyHXTgoGaaGkx4fYUCxLm X-Received: by 2002:a63:194a:: with SMTP id 10-v6mr6040651pgz.192.1538745946242; Fri, 05 Oct 2018 06:25:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1538745946; cv=none; d=google.com; s=arc-20160816; b=drYMSSRNcAXfTpv2KL19SeA1fYkPVQmKM2yNMwvDkJ5hXgmSrRnkM4ygN+j0yGY/A5 q+EcPnaA0+2uPesV+kJ8gZA/ARjhip9xKsXMkvE4lHef3RKhm2IZG6HNyJ1rKHIUMfQg xvOqkjh1SHqB3pdYlGpHc6TVeJGB4ntj7Hb8ccWidhF/Qv0IBjmzvZdsSYGq5/hWVQog Ur0V2GZpmRD4edgd4EaLAJ1Ll7IsHNgNh7jsER2vE6rpgF23IYDQzusp3sp10NiXGZmN vLsABs3RkdMfH062Gy3RmegchxoJGobo3Tz4xqrCVVQ3G3PEpAuh5LoFO32KgshcjTNL DUSw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from; bh=sYXZpnu5plmNXkk8WjGh9/S2vV0oRhu+ii6mgmEHmao=; b=HPe50GWOmfN9sCzhSiCC3CLHN/bJuMridKhirkthVQXGMxfw5llO36HNnsDlDubTOn Z9R8wWr4kjzJvTUYAlEhXW87qEIVXlRgZC1mfQIenCH8SOrfTm86z3+5LSNk94szX05w QCmMQkPMjPj8UHajUxUD3wAvXqxWQp/398uv8+IYX91A/mqzmdjbXa5iVUHrjHH8aBM/ IXZjXyAYxNmB1A36hoBIF4th6iNnXOYix7+jKlYC82/sHxzPbZEsWOXuQMHa6jhj1k8n 6XRQFLWQxhRwd1+P8v8cPfeBMlGH83h9CVn9J+EoFlzMG23yqZiqgpmz4DZcOguffCpx A/CA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y190-v6si9415113pfy.147.2018.10.05.06.25.30; Fri, 05 Oct 2018 06:25:46 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728619AbeJEUWc (ORCPT + 99 others); Fri, 5 Oct 2018 16:22:32 -0400 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:17832 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728496AbeJEUWc (ORCPT ); Fri, 5 Oct 2018 16:22:32 -0400 Received: from pps.filterd (m0046660.ppops.net [127.0.0.1]) by mx08-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w95DJ2Qi015085; Fri, 5 Oct 2018 15:23:25 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-00178001.pphosted.com with ESMTP id 2msxh73acg-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Fri, 05 Oct 2018 15:23:25 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 359FD31; Fri, 5 Oct 2018 13:23:25 +0000 (GMT) Received: from Webmail-eu.st.com (Safex1hubcas21.st.com [10.75.90.44]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 0DFA22C92; Fri, 5 Oct 2018 13:23:25 +0000 (GMT) Received: from SAFEX1HUBCAS22.st.com (10.75.90.93) by SAFEX1HUBCAS21.st.com (10.75.90.44) with Microsoft SMTP Server (TLS) id 14.3.361.1; Fri, 5 Oct 2018 15:23:24 +0200 Received: from lmecxl0923.lme.st.com (10.48.0.237) by Webmail-ga.st.com (10.75.90.48) with Microsoft SMTP Server (TLS) id 14.3.361.1; Fri, 5 Oct 2018 15:23:24 +0200 From: Ludovic Barre To: Ulf Hansson , Rob Herring CC: , Maxime Coquelin , Alexandre Torgue , , , , , , Ludovic Barre Subject: [PATCH V5 02/24] mmc: mmci: create common mmci_dma_setup/release Date: Fri, 5 Oct 2018 15:22:40 +0200 Message-ID: <1538745782-27446-3-git-send-email-ludovic.Barre@st.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1538745782-27446-1-git-send-email-ludovic.Barre@st.com> References: <1538745782-27446-1-git-send-email-ludovic.Barre@st.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.48.0.237] X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-10-05_07:,, signatures=0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ludovic Barre This patch creates a common mmci_dma_setup/release which calls dma_setup/release callbacks of mmci_host_ops and manages common features like use_dma... If there is a fallbacks to pio mode, dma functions must check use_dma. error management: -mmci_dmae_setup fail if Tx and Rx dma channels are not defined -qcom_dma_setup fail if one of both dma channels is not defined, Qcom has no specific resource to release, just mmci dmae resource. Signed-off-by: Ludovic Barre --- drivers/mmc/host/mmci.c | 69 +++++++++++++++++++++++++++++++--------- drivers/mmc/host/mmci.h | 15 ++++++++- drivers/mmc/host/mmci_qcom_dml.c | 10 ++++-- 3 files changed, 76 insertions(+), 18 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index db8c085..07b799c 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -57,6 +57,7 @@ static struct variant_data variant_arm = { .mmcimask1 = true, .start_err = MCI_STARTBITERR, .opendrain = MCI_ROD, + .init = mmci_variant_init, }; static struct variant_data variant_arm_extended_fifo = { @@ -68,6 +69,7 @@ static struct variant_data variant_arm_extended_fifo = { .mmcimask1 = true, .start_err = MCI_STARTBITERR, .opendrain = MCI_ROD, + .init = mmci_variant_init, }; static struct variant_data variant_arm_extended_fifo_hwfc = { @@ -80,6 +82,7 @@ static struct variant_data variant_arm_extended_fifo_hwfc = { .mmcimask1 = true, .start_err = MCI_STARTBITERR, .opendrain = MCI_ROD, + .init = mmci_variant_init, }; static struct variant_data variant_u300 = { @@ -98,6 +101,7 @@ static struct variant_data variant_u300 = { .mmcimask1 = true, .start_err = MCI_STARTBITERR, .opendrain = MCI_OD, + .init = mmci_variant_init, }; static struct variant_data variant_nomadik = { @@ -117,6 +121,7 @@ static struct variant_data variant_nomadik = { .mmcimask1 = true, .start_err = MCI_STARTBITERR, .opendrain = MCI_OD, + .init = mmci_variant_init, }; static struct variant_data variant_ux500 = { @@ -142,6 +147,7 @@ static struct variant_data variant_ux500 = { .mmcimask1 = true, .start_err = MCI_STARTBITERR, .opendrain = MCI_OD, + .init = mmci_variant_init, }; static struct variant_data variant_ux500v2 = { @@ -169,6 +175,7 @@ static struct variant_data variant_ux500v2 = { .mmcimask1 = true, .start_err = MCI_STARTBITERR, .opendrain = MCI_OD, + .init = mmci_variant_init, }; static struct variant_data variant_stm32 = { @@ -186,6 +193,7 @@ static struct variant_data variant_stm32 = { .f_max = 48000000, .pwrreg_clkgate = true, .pwrreg_nopower = true, + .init = mmci_variant_init, }; static struct variant_data variant_qcom = { @@ -356,6 +364,27 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) mmci_write_clkreg(host, clk); } +void mmci_dma_release(struct mmci_host *host) +{ + if (host->ops && host->ops->dma_release) + host->ops->dma_release(host); + + host->use_dma = false; +} + +void mmci_dma_setup(struct mmci_host *host) +{ + if (!host->ops || !host->ops->dma_setup) + return; + + if (host->ops->dma_setup(host)) { + mmci_dma_release(host); + return; + } + + host->use_dma = true; +} + static void mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) { @@ -414,7 +443,7 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) * no custom DMA interfaces are supported. */ #ifdef CONFIG_DMA_ENGINE -static void mmci_dma_setup(struct mmci_host *host) +int mmci_dmae_setup(struct mmci_host *host) { const char *rxname, *txname; @@ -464,15 +493,17 @@ static void mmci_dma_setup(struct mmci_host *host) host->mmc->max_seg_size = max_seg_size; } - if (host->ops && host->ops->dma_setup) - host->ops->dma_setup(host); + if (!host->dma_tx_channel && !host->dma_rx_channel) + return -EINVAL; + + return 0; } /* * This is used in or so inline it * so it can be discarded. */ -static inline void mmci_dma_release(struct mmci_host *host) +void mmci_dmae_release(struct mmci_host *host) { if (host->dma_rx_channel) dma_release_channel(host->dma_rx_channel); @@ -496,7 +527,7 @@ static void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data) static void mmci_dma_data_error(struct mmci_host *host) { - if (!dma_inprogress(host)) + if (!host->use_dma || !dma_inprogress(host)) return; dev_err(mmc_dev(host->mmc), "error during DMA transfer!\n"); @@ -514,7 +545,7 @@ static void mmci_dma_finalize(struct mmci_host *host, struct mmc_data *data) u32 status; int i; - if (!dma_inprogress(host)) + if (!host->use_dma || !dma_inprogress(host)) return; /* Wait up to 1ms for the DMA to complete */ @@ -640,6 +671,9 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl) int ret; struct mmc_data *data = host->data; + if (!host->use_dma) + return -EINVAL; + ret = mmci_dma_prep_data(host, host->data); if (ret) return ret; @@ -674,6 +708,9 @@ static void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data) { struct mmci_host_next *next = &host->next_data; + if (!host->use_dma) + return; + WARN_ON(data->host_cookie && data->host_cookie != next->cookie); WARN_ON(!data->host_cookie && (next->dma_desc || next->dma_chan)); @@ -689,7 +726,7 @@ static void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq) struct mmc_data *data = mrq->data; struct mmci_host_next *nd = &host->next_data; - if (!data) + if (!host->use_dma || !data) return; BUG_ON(data->host_cookie); @@ -707,7 +744,7 @@ static void mmci_post_request(struct mmc_host *mmc, struct mmc_request *mrq, struct mmci_host *host = mmc_priv(mmc); struct mmc_data *data = mrq->data; - if (!data || !data->host_cookie) + if (!host->use_dma || !data || !data->host_cookie) return; mmci_dma_unmap(host, data); @@ -735,18 +772,20 @@ static void mmci_post_request(struct mmc_host *mmc, struct mmc_request *mrq, } } +static struct mmci_host_ops mmci_variant_ops = { + .dma_setup = mmci_dmae_setup, + .dma_release = mmci_dmae_release, +}; + +void mmci_variant_init(struct mmci_host *host) +{ + host->ops = &mmci_variant_ops; +} #else /* Blank functions if the DMA engine is not available */ static void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data) { } -static inline void mmci_dma_setup(struct mmci_host *host) -{ -} - -static inline void mmci_dma_release(struct mmci_host *host) -{ -} static inline void mmci_dma_finalize(struct mmci_host *host, struct mmc_data *data) diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 01e6c6b..9b0a960 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -273,7 +273,8 @@ struct variant_data { /* mmci variant callbacks */ struct mmci_host_ops { - void (*dma_setup)(struct mmci_host *host); + int (*dma_setup)(struct mmci_host *host); + void (*dma_release)(struct mmci_host *host); }; struct mmci_host_next { @@ -323,6 +324,7 @@ struct mmci_host { unsigned int size; int (*get_rx_fifocnt)(struct mmci_host *h, u32 status, int remain); + u8 use_dma:1; #ifdef CONFIG_DMA_ENGINE /* DMA stuff */ struct dma_chan *dma_current; @@ -336,3 +338,14 @@ struct mmci_host { #endif }; +#ifdef CONFIG_DMA_ENGINE +void mmci_variant_init(struct mmci_host *host); +#else +static inline void mmci_variant_init(struct mmci_host *host) +{ +} +#endif + +int mmci_dmae_setup(struct mmci_host *host); +void mmci_dmae_release(struct mmci_host *host); + diff --git a/drivers/mmc/host/mmci_qcom_dml.c b/drivers/mmc/host/mmci_qcom_dml.c index be3fab5..aa070a9 100644 --- a/drivers/mmc/host/mmci_qcom_dml.c +++ b/drivers/mmc/host/mmci_qcom_dml.c @@ -119,19 +119,22 @@ static int of_get_dml_pipe_index(struct device_node *np, const char *name) } /* Initialize the dml hardware connected to SD Card controller */ -static void qcom_dma_setup(struct mmci_host *host) +static int qcom_dma_setup(struct mmci_host *host) { u32 config; void __iomem *base; int consumer_id, producer_id; struct device_node *np = host->mmc->parent->of_node; + if (mmci_dmae_setup(host)) + return -EINVAL; + consumer_id = of_get_dml_pipe_index(np, "tx"); producer_id = of_get_dml_pipe_index(np, "rx"); if (producer_id < 0 || consumer_id < 0) { host->variant->qcom_dml = false; - return; + return -EINVAL; } base = host->base + DML_OFFSET; @@ -175,10 +178,13 @@ static void qcom_dma_setup(struct mmci_host *host) /* Make sure dml initialization is finished */ mb(); + + return 0; } static struct mmci_host_ops qcom_variant_ops = { .dma_setup = qcom_dma_setup, + .dma_release = mmci_dmae_release, }; void qcom_variant_init(struct mmci_host *host) -- 2.7.4