From patchwork Wed Jan 12 18:19:40 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Per Forlin X-Patchwork-Id: 474671 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p0CIKoqa019168 for ; Wed, 12 Jan 2011 18:20:50 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755493Ab1ALSUY (ORCPT ); Wed, 12 Jan 2011 13:20:24 -0500 Received: from mail-gw0-f46.google.com ([74.125.83.46]:39077 "EHLO mail-gw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755460Ab1ALSUX (ORCPT ); Wed, 12 Jan 2011 13:20:23 -0500 Received: by gwj20 with SMTP id 20so321585gwj.19 for ; Wed, 12 Jan 2011 10:20:23 -0800 (PST) Received: by 10.151.108.17 with SMTP id k17mr2387413ybm.246.1294856422906; Wed, 12 Jan 2011 10:20:22 -0800 (PST) Received: from localhost.localdomain ([63.133.153.66]) by mx.google.com with ESMTPS id u31sm668851yba.9.2011.01.12.10.20.21 (version=TLSv1/SSLv3 cipher=RC4-MD5); Wed, 12 Jan 2011 10:20:22 -0800 (PST) From: Per Forlin To: linux-mmc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linaro-dev@lists.linaro.org Cc: Chris Ball , Ulf Hansson Subject: [FYI 1/4] mmci: fixup broken_blockend variant patch Date: Wed, 12 Jan 2011 19:19:40 +0100 Message-Id: <1294856383-14187-2-git-send-email-per.forlin@linaro.org> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1294856383-14187-1-git-send-email-per.forlin@linaro.org> References: <1294856383-14187-1-git-send-email-per.forlin@linaro.org> Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Wed, 12 Jan 2011 18:20:50 +0000 (UTC) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 5630228..aafede4 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -48,8 +48,6 @@ static unsigned int fmax = 515633; * is asserted (likewise for RX) * @broken_blockend: the MCI_DATABLOCKEND is broken on the hardware * and will not work at all. - * @broken_blockend_dma: the MCI_DATABLOCKEND is broken on the hardware when - * using DMA. * @sdio: variant supports SDIO * @st_clkdiv: true if using a ST-specific clock divider algorithm */ @@ -60,7 +58,6 @@ struct variant_data { unsigned int fifosize; unsigned int fifohalfsize; bool broken_blockend; - bool broken_blockend_dma; bool sdio; bool st_clkdiv; }; @@ -76,7 +73,7 @@ static struct variant_data variant_u300 = { .fifohalfsize = 8 * 4, .clkreg_enable = 1 << 13, /* HWFCEN */ .datalength_bits = 16, - .broken_blockend_dma = true, + .broken_blockend = true, .sdio = true, }; @@ -199,7 +196,7 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) { struct variant_data *variant = host->variant; - unsigned int datactrl, timeout, irqmask; + unsigned int datactrl, timeout, irqmask0, irqmask1; unsigned long long clks; void __iomem *base; int blksz_bits; @@ -210,7 +207,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) host->data = data; host->size = data->blksz * data->blocks; host->data_xfered = 0; - host->blockend = false; + host->last_blockend = false; host->dataend = false; mmci_init_sg(host, data); @@ -230,20 +227,20 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) datactrl = MCI_DPSM_ENABLE | blksz_bits << 4; if (data->flags & MMC_DATA_READ) { datactrl |= MCI_DPSM_DIRECTION; - irqmask = MCI_RXFIFOHALFFULLMASK; + irqmask1 = MCI_RXFIFOHALFFULLMASK; /* * If we have less than a FIFOSIZE of bytes to transfer, * trigger a PIO interrupt as soon as any data is available. */ if (host->size < variant->fifosize) - irqmask |= MCI_RXDATAAVLBLMASK; + irqmask1 |= MCI_RXDATAAVLBLMASK; } else { /* * We don't actually need to include "FIFO empty" here * since its implicit in "FIFO half empty". */ - irqmask = MCI_TXFIFOHALFEMPTYMASK; + irqmask1 = MCI_TXFIFOHALFEMPTYMASK; } /* The ST Micro variants has a special bit to enable SDIO */ @@ -252,8 +249,14 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) datactrl |= MCI_ST_DPSM_SDIOEN; writel(datactrl, base + MMCIDATACTRL); - writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0); - mmci_set_mask1(host, irqmask); + irqmask0 = readl(base + MMCIMASK0); + if (variant->broken_blockend) + irqmask0 &= ~MCI_DATABLOCKENDMASK; + else + irqmask0 |= MCI_DATABLOCKENDMASK; + irqmask0 &= ~MCI_DATAENDMASK; + writel(irqmask0, base + MMCIMASK0); + mmci_set_mask1(host, irqmask1); } static void @@ -301,7 +304,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, data->error = -EIO; /* Force-complete the transaction */ - host->blockend = true; + host->last_blockend = true; host->dataend = true; /* @@ -337,7 +340,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, * * In the U300, the IRQs can arrive out-of-order, * e.g. MCI_DATABLOCKEND sometimes arrives after MCI_DATAEND, - * so for this case we use the flags "blockend" and + * so for this case we use the flags "last_blockend" and * "dataend" to make sure both IRQs have arrived before * concluding the transaction. (This does not apply * to the Ux500 which doesn't fire MCI_DATABLOCKEND @@ -353,7 +356,8 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, */ if (!variant->broken_blockend) host->data_xfered += data->blksz; - host->blockend = true; + if (host->data_xfered == data->blksz * data->blocks) + host->last_blockend = true; } if (status & MCI_DATAEND) @@ -364,11 +368,12 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, * on others we must sync with the blockend signal since they can * appear out-of-order. */ - if (host->dataend && (host->blockend || variant->broken_blockend)) { + if (host->dataend && + (host->last_blockend || variant->broken_blockend)) { mmci_stop_data(host); /* Reset these flags */ - host->blockend = false; + host->last_blockend = false; host->dataend = false; /* @@ -770,7 +775,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) struct variant_data *variant = id->data; struct mmci_host *host; struct mmc_host *mmc; - unsigned int mask; int ret; /* must have platform data */ @@ -951,12 +955,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) goto irq0_free; } - mask = MCI_IRQENABLE; - /* Don't use the datablockend flag if it's broken */ - if (variant->broken_blockend) - mask &= ~MCI_DATABLOCKEND; - - writel(mask, host->base + MMCIMASK0); + writel(MCI_IRQENABLE, host->base + MMCIMASK0); amba_set_drvdata(dev, mmc); diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index df06f01..7ac8c4d 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -137,7 +137,7 @@ #define MCI_IRQENABLE \ (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \ MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ - MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK) + MCI_CMDRESPENDMASK|MCI_CMDSENTMASK) /* These interrupts are directed to IRQ1 when two IRQ lines are available */ #define MCI_IRQ1MASK \ @@ -177,7 +177,7 @@ struct mmci_host { struct timer_list timer; unsigned int oldstat; - bool blockend; + bool last_blockend; bool dataend; /* pio stuff */