From patchwork Fri Oct 12 14:02:02 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 12188 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 51275293F83 for ; Fri, 12 Oct 2012 14:03:03 +0000 (UTC) Received: from mail-ie0-f180.google.com (mail-ie0-f180.google.com [209.85.223.180]) by fiordland.canonical.com (Postfix) with ESMTP id BF143A186B5 for ; Fri, 12 Oct 2012 14:03:02 +0000 (UTC) Received: by mail-ie0-f180.google.com with SMTP id e10so4687966iej.11 for ; Fri, 12 Oct 2012 07:03:02 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to:cc :subject:date:message-id:x-mailer:mime-version:content-type :x-gm-message-state; bh=MnuVkT+UWFrgn6+T/FzCOLEKuqIk/DW6KmK4nbXo+Qs=; b=Zi4wP//x9L4PmjueQKDThW0zwTqU/vvNcju6+HuTO9ICrdWMUZZaoS1rtql529uJOO aVtC5P9XhcafjYfq0pPlZGVHr3Jgqi41EqVJAchSyPml6nliUKCcPXn9mZ64cPCWqXWM I9WAC/p2NrRpH0zDWCY1wM1OrI9vHTI+i2nAMg1Pkgy6COeyjdwqDdyM4US6q0rg4Tqx QqsiwNl2I/QjoTdJuzC+tUJejX++MOJnEDkpIBTlr4RtlV8tt9SuWAcTGySPPI2cBjhK YXvnLTnLJOJ/oa6/kTvlQHtkj9NaaGzEH18wLgLI/+gIAK2Li4fnRXJfwrt1B/FvR46I qg2A== Received: by 10.43.7.132 with SMTP id oo4mr3544342icb.6.1350050582157; Fri, 12 Oct 2012 07:03:02 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.50.67.148 with SMTP id n20csp200760igt; Fri, 12 Oct 2012 07:03:01 -0700 (PDT) Received: by 10.14.213.65 with SMTP id z41mr6837055eeo.29.1350050580416; Fri, 12 Oct 2012 07:03:00 -0700 (PDT) Received: from eu1sys200aog114.obsmtp.com (eu1sys200aog114.obsmtp.com [207.126.144.137]) by mx.google.com with SMTP id z46si6606034eeo.28.2012.10.12.07.02.55 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 12 Oct 2012 07:03:00 -0700 (PDT) Received-SPF: neutral (google.com: 207.126.144.137 is neither permitted nor denied by best guess record for domain of ulf.hansson@stericsson.com) client-ip=207.126.144.137; Authentication-Results: mx.google.com; spf=neutral (google.com: 207.126.144.137 is neither permitted nor denied by best guess record for domain of ulf.hansson@stericsson.com) smtp.mail=ulf.hansson@stericsson.com Received: from beta.dmz-eu.st.com ([164.129.1.35]) (using TLSv1) by eu1sys200aob114.postini.com ([207.126.147.11]) with SMTP ID DSNKUHgjCK3n8psXL7tUnesyKU8oxkoX3aM+@postini.com; Fri, 12 Oct 2012 14:03:00 UTC 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 87B0789; Fri, 12 Oct 2012 14:02:26 +0000 (GMT) Received: from relay2.stm.gmessaging.net (unknown [10.230.100.18]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 28DFD45B8; Fri, 12 Oct 2012 14:02:24 +0000 (GMT) Received: from exdcvycastm022.EQ1STM.local (alteon-source-exch [10.230.100.61]) (using TLSv1 with cipher RC4-MD5 (128/128 bits)) (Client CN "exdcvycastm022", Issuer "exdcvycastm022" (not verified)) by relay2.stm.gmessaging.net (Postfix) with ESMTPS id 12583A807E; Fri, 12 Oct 2012 16:02:18 +0200 (CEST) Received: from steludxu1397.stericsson.com (10.230.100.153) by smtp.stericsson.com (10.230.100.30) with Microsoft SMTP Server (TLS) id 8.3.83.0; Fri, 12 Oct 2012 16:02:23 +0200 From: Ulf Hansson To: , Chris Ball Cc: , Russell King , Linus Walleij , Ulf Hansson , Per Forlin Subject: [PATCH] mmc: mmci: Support non-power-of-two block sizes for ux500v2 variant Date: Fri, 12 Oct 2012 16:02:02 +0200 Message-ID: <1350050522-8852-1-git-send-email-ulf.hansson@stericsson.com> X-Mailer: git-send-email 1.7.10 MIME-Version: 1.0 X-Gm-Message-State: ALoCoQkzbEBqcsFtdAzibuJFGiIwcuvRlyN7vJ1ikOy77NPsqLAyyztwZfCL+Fq/GdkL64nj4cad From: Ulf Hansson For the ux500v2 variant non power of two block sizes are supported. This will make it possible to decrease data overhead for SDIO transfers. Although we need to put some constraints to the alignment of the buffers when enabling this feature. Buffers must be 4 bytes aligned due to restrictions that the PL18x FIFO accesses must be done in a 4 byte aligned manner. Moreover we need to enable DMA_REQCTL for SDIO to support write of non 32 bytes aligned sg element lengths. In PIO mode any buffer length can be handled as long as the buffer address is 4 byte aligned. Signed-off-by: Ulf Hansson Signed-off-by: Per Forlin --- drivers/mmc/host/mmci.c | 56 +++++++++++++++++++++++++++++++++++++++++------ drivers/mmc/host/mmci.h | 7 ++++++ 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index edc3e9b..ca6d128 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -48,6 +48,7 @@ static unsigned int fmax = 515633; * struct variant_data - MMCI variant-specific quirks * @clkreg: default value for MCICLOCK register * @clkreg_enable: enable value for MMCICLOCK register + * @dma_sdio_req_ctrl: enable value for DMAREQCTL register for SDIO write * @datalength_bits: number of bits in the MMCIDATALENGTH register * @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY * is asserted (likewise for RX) @@ -58,10 +59,12 @@ static unsigned int fmax = 515633; * @blksz_datactrl16: true if Block size is at b16..b30 position in datactrl register * @pwrreg_powerup: power up value for MMCIPOWER register * @signal_direction: input/out direction of bus signals can be indicated + * @non_power_of_2_blksize: true if block sizes can be other than power of two */ struct variant_data { unsigned int clkreg; unsigned int clkreg_enable; + unsigned int dma_sdio_req_ctrl; unsigned int datalength_bits; unsigned int fifosize; unsigned int fifohalfsize; @@ -70,6 +73,7 @@ struct variant_data { bool blksz_datactrl16; u32 pwrreg_powerup; bool signal_direction; + bool non_power_of_2_blksize; }; static struct variant_data variant_arm = { @@ -112,6 +116,7 @@ static struct variant_data variant_ux500 = { .fifohalfsize = 8 * 4, .clkreg = MCI_CLK_ENABLE, .clkreg_enable = MCI_ST_UX500_HWFCEN, + .dma_sdio_req_ctrl = MCI_ST_DPSM_DMAREQCTL, .datalength_bits = 24, .sdio = true, .st_clkdiv = true, @@ -124,15 +129,42 @@ static struct variant_data variant_ux500v2 = { .fifohalfsize = 8 * 4, .clkreg = MCI_CLK_ENABLE, .clkreg_enable = MCI_ST_UX500_HWFCEN, + .dma_sdio_req_ctrl = MCI_ST_DPSM_DMAREQCTL, .datalength_bits = 24, .sdio = true, .st_clkdiv = true, .blksz_datactrl16 = true, .pwrreg_powerup = MCI_PWR_ON, .signal_direction = true, + .non_power_of_2_blksize = true, }; /* + * Validate mmc prerequisites + */ +static int mmci_validate_data(struct mmci_host *host, + struct mmc_data *data) +{ + if (!data) + return 0; + + if (!host->variant->non_power_of_2_blksize && + !is_power_of_2(data->blksz)) { + dev_err(mmc_dev(host->mmc), + "unsupported block size (%d bytes)\n", data->blksz); + return -EINVAL; + } + + if (data->sg->offset & 3) { + dev_err(mmc_dev(host->mmc), + "unsupported alginment (0x%x)\n", data->sg->offset); + return -EINVAL; + } + + return 0; +} + +/* * This must be called with host->lock held */ static void mmci_write_clkreg(struct mmci_host *host, u32 clk) @@ -446,8 +478,12 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data, if (!chan) return -EINVAL; - /* If less than or equal to the fifo size, don't bother with DMA */ - if (data->blksz * data->blocks <= variant->fifosize) + /* + * If less than or equal to the fifo size, don't bother with DMA + * SDIO transfers may not be 4 bytes aligned, fall back to PIO + */ + if (data->blksz * data->blocks <= variant->fifosize || + (data->blksz * data->blocks) & 3) return -EINVAL; device = chan->device; @@ -482,6 +518,7 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl) { int ret; struct mmc_data *data = host->data; + struct variant_data *variant = host->variant; ret = mmci_dma_prep_data(host, host->data, NULL); if (ret) @@ -496,6 +533,11 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl) datactrl |= MCI_DPSM_DMAENABLE; + /* Some hardware versions need special flags for SDIO DMA write */ + if (variant->sdio && host->mmc->card && mmc_card_sdio(host->mmc->card) + && (data->flags & MMC_DATA_WRITE)) + datactrl |= variant->dma_sdio_req_ctrl; + /* Trigger the DMA transfer */ writel(datactrl, host->base + MMCIDATACTRL); @@ -540,6 +582,9 @@ static void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq, if (!data) return; + if (mmci_validate_data(host, mrq->data)) + return; + if (data->host_cookie) { data->host_cookie = 0; return; @@ -642,7 +687,6 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) writel(host->size, base + MMCIDATALENGTH); blksz_bits = ffs(data->blksz) - 1; - BUG_ON(1 << blksz_bits != data->blksz); if (variant->blksz_datactrl16) datactrl = MCI_DPSM_ENABLE | (data->blksz << 16); @@ -1048,10 +1092,8 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) WARN_ON(host->mrq != NULL); - if (mrq->data && !is_power_of_2(mrq->data->blksz)) { - dev_err(mmc_dev(mmc), "unsupported block size (%d bytes)\n", - mrq->data->blksz); - mrq->cmd->error = -EINVAL; + mrq->cmd->error = mmci_validate_data(host, mrq->data); + if (mrq->cmd->error) { mmc_request_done(mmc, mrq); return; } diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index d437ccf..c2b3332 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -60,6 +60,13 @@ #define MCI_ST_DPSM_RWMOD (1 << 10) #define MCI_ST_DPSM_SDIOEN (1 << 11) /* Control register extensions in the ST Micro Ux500 versions */ +/* + * DMA request control is required for write + * if transfer size is not 32 byte aligned. + * DMA request control is also needed if the total + * transfer size is 32 byte aligned but any of the + * sg element lengths are not aligned with 32 byte. + */ #define MCI_ST_DPSM_DMAREQCTL (1 << 12) #define MCI_ST_DPSM_DBOOTMODEEN (1 << 13) #define MCI_ST_DPSM_BUSYMODE (1 << 14)