From patchwork Wed Aug 21 13:50:39 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Seungwon Jeon X-Patchwork-Id: 2847750 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 95113BF546 for ; Wed, 21 Aug 2013 13:50:48 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 18EB220490 for ; Wed, 21 Aug 2013 13:50:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 24B68203D9 for ; Wed, 21 Aug 2013 13:50:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751909Ab3HUNul (ORCPT ); Wed, 21 Aug 2013 09:50:41 -0400 Received: from mailout3.samsung.com ([203.254.224.33]:44167 "EHLO mailout3.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751719Ab3HUNuk (ORCPT ); Wed, 21 Aug 2013 09:50:40 -0400 Received: from epcpsbgr3.samsung.com (u143.gpu120.samsung.co.kr [203.254.230.143]) by mailout3.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MRV00DBBVSF6MB0@mailout3.samsung.com> for linux-mmc@vger.kernel.org; Wed, 21 Aug 2013 22:50:39 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [203.254.230.50]) by epcpsbgr3.samsung.com (EPCPMTA) with SMTP id 03.DD.03969.FA5C4125; Wed, 21 Aug 2013 22:50:39 +0900 (KST) X-AuditID: cbfee68f-b7f436d000000f81-6e-5214c5af48ef Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 7A.B1.31505.FA5C4125; Wed, 21 Aug 2013 22:50:39 +0900 (KST) Received: from DOTGIHJUN01 ([12.23.118.161]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MRV00FUSVSFZ240@mmp1.samsung.com>; Wed, 21 Aug 2013 22:50:39 +0900 (KST) From: Seungwon Jeon To: linux-mmc@vger.kernel.org Cc: 'Chris Ball' , 'Jaehoon Chung' , 'Alim Akhtar' References: In-reply-to: Subject: [PATCH 07/14] mmc: dw_mmc: adjust the fifoth with block size Date: Wed, 21 Aug 2013 22:50:39 +0900 Message-id: <002c01ce9e75$6bbeed40$433cc7c0$%jun@samsung.com> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-transfer-encoding: 7bit X-Mailer: Microsoft Office Outlook 12.0 Thread-index: Ac03z3aCvVFr8FaITt2vKVQKst76fw3OcIrwS9fJ1BA= Content-language: ko X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrKIsWRmVeSWpSXmKPExsVy+t8zI931R0WCDP6uNbB4MG8bm8X21xvZ LG78amO1OPK/n9GBxePQlbWMHn1bVjF6fN4kF8AcxWWTkpqTWZZapG+XwJXRumo3c8EhtYp9 X/6zNjBeketi5OSQEDCR2LrqKROELSZx4d56ti5GLg4hgWWMEv+enmOCKZp44iMLRGIRo8SB cxeZQRJCAn8YJZ4uLgKx2QS0JP6+eQMWFxGQlfj55wIbiM0sUCbx9s59oDgHUD23xOrmIJAw pwCPxLo/nWDlwgKuEt8mXWEEsVkEVCUa1rwG28srYCuxe8FaZghbUOLH5HssIGOYBdQlpkzJ hZguL7F5zVuw6RJA4Ud/dSEOsJI4vPwIK0SJiMS+F+8YQa6XEDjGLjF7/R12iFUCEt8mH2KB 6JWV2HSAGeJbSYmDK26wTGCUmIVk8SyExbOQLJ6FZMMCRpZVjKKpBckFxUnpRcZ6xYm5xaV5 6XrJ+bmbGCFR2L+D8e4B60OMyUDbJzJLiSbnA6M4ryTe0NjMyMLUxNTYyNzSjDRhJXFetRbr QCGB9MSS1OzU1ILUovii0pzU4kOMTBycUg2MHIFrHnakFf7SL1RftXG1ak6l509/8atHEhy0 ss2zv+j9jBCL+lLwYJvJVu4P5xeuu3p8WorSXdfVb/s2Xm7bd/jg4sdJf86nffksfkits2f9 nruMz09MaLhdu3fzNqtP5byrTAV3NoUVLq4UNlnb2DXLS728femdgisMz3Ys2rSP9dF2ucJC eyWW4oxEQy3mouJEAOkYIiTYAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrEKsWRmVeSWpSXmKPExsVy+t9jAd31R0WCDK5261g8mLeNzWL7641s Fjd+tbFaHPnfz+jA4nHoylpGj74tqxg9Pm+SC2COamC0yUhNTEktUkjNS85PycxLt1XyDo53 jjc1MzDUNbS0MFdSyEvMTbVVcvEJ0HXLzAFap6RQlphTChQKSCwuVtK3wzQhNMRN1wKmMULX NyQIrsfIAA0krGPMaF21m7ngkFrFvi//WRsYr8h1MXJySAiYSEw88ZEFwhaTuHBvPVsXIxeH kMAiRokD5y4ygySEBP4wSjxdXARiswloSfx98wYsLiIgK/HzzwU2EJtZoEzi7Z37QHEOoHpu idXNQSBhTgEeiXV/OsHKhQVcJb5NusIIYrMIqEo0rHnNBGLzCthK7F6wlhnCFpT4MfkeC8gY ZgF1iSlTciGmy0tsXvMWbLoEUPjRX12IA6wkDi8/wgpRIiKx78U7xgmMQrOQDJqFMGgWkkGz kHQsYGRZxSiaWpBcUJyUnmukV5yYW1yal66XnJ+7iREc48+kdzCuarA4xCjAwajEw3thp0iQ EGtiWXFl7iFGCQ5mJRHez/uBQrwpiZVVqUX58UWlOanFhxiTgd6cyCwlmpwPTD95JfGGxiZm RpZGZhZGJubmpAkrifMebLUOFBJITyxJzU5NLUgtgtnCxMEp1cBY1/EpUTal9d2FlvlRX8M/ 5/cuTl+ra1Vgvt26jSlx1o0qr6++X5ZcvTnTNELpcZ7RnJmrNnCvzysozb/G2bj/zOmYqcGP TQvsPMpjWytXNzF4b3BuWWNjmm92JfOMDpvoL8f/nuf/HthXvjLzjLhoftvHVS8rbScczy9h zr7o+ei9p9SpN+VKLMUZiYZazEXFiQBu9bwPNQMAAA== DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Spam-Status: No, score=-9.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This change helps to choose msize, rx_watermark and tx_watermak depending on block size for IDMAC mode. For SDIO block size can be variable, so if these values are set incorrectly, card clock may stop. Signed-off-by: Seungwon Jeon --- drivers/mmc/host/dw_mmc.c | 74 ++++++++++++++++++++++++++++++++++++++++++-- drivers/mmc/host/dw_mmc.h | 4 ++ include/linux/mmc/dw_mmc.h | 1 + 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 296d4a4..b8ba707 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -529,6 +529,47 @@ static void dw_mci_post_req(struct mmc_host *mmc, data->host_cookie = 0; } +static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data) +{ +#ifdef CONFIG_MMC_DW_IDMAC + unsigned int blksz = data->blksz; + const u32 mszs[] = {1, 4, 8, 16, 32, 64, 128, 256}; + u32 fifo_width = 1 << host->data_shift; + u32 blksz_depth = blksz / fifo_width, fifoth_val; + u32 msize = 0, rx_wmark = 1, tx_wmark, tx_wmark_invers; + int idx = (sizeof(mszs) / sizeof(mszs[0])) - 1; + + tx_wmark = (host->fifo_depth) / 2; + tx_wmark_invers = host->fifo_depth - tx_wmark; + + /* + * MSIZE is '1', + * if blksz is not a multiple of the FIFO width + */ + if (blksz % fifo_width) { + msize = 0; + rx_wmark = 1; + goto done; + } + + do { + if (!((blksz_depth % mszs[idx]) || + (tx_wmark_invers % mszs[idx]))) { + msize = idx; + rx_wmark = mszs[idx] - 1; + break; + } + } while (--idx > 0); + /* + * If idx is '0', it won't be tried + * Thus, initial values are uesed + */ +done: + fifoth_val = SDMMC_SET_FIFOTH(msize, rx_wmark, tx_wmark); + mci_writel(host, FIFOTH, fifoth_val); +#endif +} + static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) { int sg_len; @@ -553,6 +594,14 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma, sg_len); + /* + * Decide the MSIZE and RX/TX Watermark. + * If current block size is same with previous size, + * no need to update fifoth. + */ + if (host->prev_blksz != data->blksz) + dw_mci_adjust_fifoth(host, data); + /* Enable the DMA interface */ temp = mci_readl(host, CTRL); temp |= SDMMC_CTRL_DMA_ENABLE; @@ -603,6 +652,21 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) temp = mci_readl(host, CTRL); temp &= ~SDMMC_CTRL_DMA_ENABLE; mci_writel(host, CTRL, temp); + + /* + * Use the initial fifoth_val for PIO mode. + * If next issued data may be transfered by DMA mode, + * prev_blksz should be invalidated. + */ + mci_writel(host, FIFOTH, host->fifoth_val); + host->prev_blksz = 0; + } else { + /* + * Keep the current block size. + * It will be used to decide whether to update + * fifoth register next time. + */ + host->prev_blksz = data->blksz; } } @@ -2358,8 +2422,8 @@ int dw_mci_probe(struct dw_mci *host) fifo_size = host->pdata->fifo_depth; } host->fifo_depth = fifo_size; - host->fifoth_val = ((0x2 << 28) | ((fifo_size/2 - 1) << 16) | - ((fifo_size/2) << 0)); + host->fifoth_val = + SDMMC_SET_FIFOTH(0x2, fifo_size / 2 - 1, fifo_size / 2); mci_writel(host, FIFOTH, host->fifoth_val); /* disable clock to CIU */ @@ -2542,8 +2606,12 @@ int dw_mci_resume(struct dw_mci *host) if (host->use_dma && host->dma_ops->init) host->dma_ops->init(host); - /* Restore the old value at FIFOTH register */ + /* + * Restore the initial value at FIFOTH register + * And Invalidate the prev_blksz with zero + */ mci_writel(host, FIFOTH, host->fifoth_val); + host->prev_blksz = 0; mci_writel(host, RINTSTS, 0xFFFFFFFF); mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 661c6f9..4002c84 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -128,6 +128,10 @@ #define SDMMC_CMD_INDX(n) ((n) & 0x1F) /* Status register defines */ #define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FFF) +/* FIFOTH register defines */ +#define SDMMC_SET_FIFOTH(m, r, t) (((m) & 0x7) << 28 | \ + ((r) & 0xFFF) << 16 | \ + ((t) & 0xFFF)) /* Internal DMAC interrupt defines */ #define SDMMC_IDMAC_INT_AI BIT(9) #define SDMMC_IDMAC_INT_NI BIT(8) diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 198f0fa..4ec9dcc 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -129,6 +129,7 @@ struct dw_mci { struct mmc_request *mrq; struct mmc_command *cmd; struct mmc_data *data; + unsigned int prev_blksz; struct workqueue_struct *card_workqueue; /* DMA interface members*/