From patchwork Thu Dec 4 15:03:39 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: DrEagle X-Patchwork-Id: 417824 X-Patchwork-Delegate: sr@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 6657A1400DD for ; Fri, 5 Dec 2014 02:04:44 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id D85984B666; Thu, 4 Dec 2014 16:04:13 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 6U7rnU9uP6qN; Thu, 4 Dec 2014 16:04:13 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 29BCA4B682; Thu, 4 Dec 2014 16:04:13 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 42DB04B666 for ; Thu, 4 Dec 2014 16:04:07 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id j7MaSqyrL50l for ; Thu, 4 Dec 2014 16:04:07 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from milenium.gk2.net (louche.gk2.net [88.178.80.34]) by theia.denx.de (Postfix) with ESMTPS id 89F6E4B68E for ; Thu, 4 Dec 2014 16:04:01 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by milenium.gk2.net (Postfix) with ESMTP id 3586C110C256; Thu, 4 Dec 2014 16:03:57 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at milenium.gk2.net Received: from milenium.gk2.net ([127.0.0.1]) by localhost (milenium.louche.gk2.net [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id kRt80Eozk6Se; Thu, 4 Dec 2014 16:03:48 +0100 (CET) Received: from BARATARIA.nation.gk2.net (village.gk2.net [109.190.23.135]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) (Authenticated sender: gege@milenium.gk2.net) by milenium.gk2.net (Postfix) with ESMTPSA id 6A2EB110C254; Thu, 4 Dec 2014 16:03:47 +0100 (CET) From: =?UTF-8?q?G=C3=A9rald=20Kerma?= To: u-boot@lists.denx.de Date: Thu, 4 Dec 2014 16:03:39 +0100 Message-Id: <1417705419-15652-1-git-send-email-drEagle@doukki.net> X-Mailer: git-send-email 2.1.3 MIME-Version: 1.0 Cc: mario.schuknecht@dresearch-fe.de, panto@antoniou-consulting.com, =?UTF-8?q?G=C3=A9rald=20Kerma?= Subject: [U-Boot] [PATCH v2 1/1] ARM: kirkwood: mvebu_mmc: Speed up access time X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.13 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Review delays and timeouts. Get around 20 x faster access on Sheevaplug tests. Changes in v2: - increase number of loops - remove initial delay Changes in v1: - review all loops, delays and timeouts Signed-off-by: GĂ©rald Kerma --- drivers/mmc/mvebu_mmc.c | 66 +++++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/drivers/mmc/mvebu_mmc.c b/drivers/mmc/mvebu_mmc.c index 9f98c3f..b636be6 100644 --- a/drivers/mmc/mvebu_mmc.c +++ b/drivers/mmc/mvebu_mmc.c @@ -23,6 +23,10 @@ DECLARE_GLOBAL_DATA_PTR; #define MVEBU_TARGET_DRAM 0 +#define TIMEOUT_LOOP 1000000000000000000 /* maximum loops */ +#define TIMEOUT_WAIT 100 /* wait 100 us */ +#define TIMEOUT_START 100 /* wait 100 us */ + static void mvebu_mmc_write(u32 offs, u32 val) { writel(val, CONFIG_SYS_MMC_BASE + (offs)); @@ -63,7 +67,7 @@ static int mvebu_mmc_setup_data(struct mmc_data *data) static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { - int timeout = 10; + u64 timeout = TIMEOUT_LOOP; ushort waittype = 0; ushort resptype = 0; ushort xfertype = 0; @@ -72,27 +76,32 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, debug("cmdidx [0x%x] resp_type[0x%x] cmdarg[0x%x]\n", cmd->cmdidx, cmd->resp_type, cmd->cmdarg); - udelay(10*1000); - debug("%s: cmd %d (hw state 0x%04x)\n", DRIVER_NAME, cmd->cmdidx, mvebu_mmc_read(SDIO_HW_STATE)); + /* Clear status */ + mvebu_mmc_write(SDIO_NOR_INTR_STATUS, SDIO_POLL_MASK); + mvebu_mmc_write(SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK); + /* Checking if card is busy */ while ((mvebu_mmc_read(SDIO_HW_STATE) & CARD_BUSY)) { + timeout--; + udelay(TIMEOUT_START); if (timeout == 0) { printf("%s: card busy!\n", DRIVER_NAME); return -1; } - timeout--; - udelay(1000); } /* Set up for a data transfer if we have one */ if (data) { int err = mvebu_mmc_setup_data(data); - if (err) + if (err){ + debug("%s: command DATA error :%x\n", + DRIVER_NAME, err); return err; + } } resptype = SDIO_CMD_INDEX(cmd->cmdidx); @@ -148,7 +157,7 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, mvebu_mmc_write(SDIO_ERR_INTR_EN, SDIO_POLL_MASK); /* Waiting for completion */ - timeout = 1000000; + timeout = TIMEOUT_LOOP; while (!((mvebu_mmc_read(SDIO_NOR_INTR_STATUS)) & waittype)) { if (mvebu_mmc_read(SDIO_NOR_INTR_STATUS) & SDIO_NOR_ERROR) { @@ -156,21 +165,22 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, DRIVER_NAME, cmd->cmdidx, mvebu_mmc_read(SDIO_ERR_INTR_STATUS)); if (mvebu_mmc_read(SDIO_ERR_INTR_STATUS) & - (SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT)) + (SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT)){ + debug("%s: command READ timed out\n", + DRIVER_NAME); return TIMEOUT; + } + debug("%s: command READ error\n", DRIVER_NAME); return COMM_ERR; } timeout--; - udelay(1); - if (timeout <= 0) { - printf("%s: command timed out\n", DRIVER_NAME); + udelay(TIMEOUT_WAIT); + if (timeout == 0) { + debug("%s: command timed out\n", DRIVER_NAME); return TIMEOUT; } } - if (mvebu_mmc_read(SDIO_ERR_INTR_STATUS) & - (SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT)) - return TIMEOUT; /* Handling response */ if (cmd->resp_type & MMC_RSP_136) { @@ -213,6 +223,11 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, debug("[0x%x] ", cmd->response[3]); debug("\n"); + if (mvebu_mmc_read(SDIO_ERR_INTR_STATUS) & SDIO_ERR_CMD_TIMEOUT){ + debug("%s: command STATUS timed out\n", DRIVER_NAME); + return TIMEOUT; + } + return 0; } @@ -236,33 +251,30 @@ static void mvebu_mmc_power_up(void) /* enable interrupts status */ mvebu_mmc_write(SDIO_NOR_INTR_STATUS, SDIO_POLL_MASK); mvebu_mmc_write(SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK); + + udelay(10*1000); } static void mvebu_mmc_set_clk(unsigned int clock) { - unsigned int m; - if (clock == 0) { debug("%s: clock off\n", DRIVER_NAME); mvebu_mmc_write(SDIO_XFER_MODE, SDIO_XFER_MODE_STOP_CLK); mvebu_mmc_write(SDIO_CLK_DIV, MVEBU_MMC_BASE_DIV_MAX); } else { - m = MVEBU_MMC_BASE_FAST_CLOCK/(2*clock) - 1; + u32 m = DIV_ROUND_UP(MVEBU_MMC_BASE_FAST_CLOCK, + (2 * clock)) - 1; if (m > MVEBU_MMC_BASE_DIV_MAX) m = MVEBU_MMC_BASE_DIV_MAX; - mvebu_mmc_write(SDIO_CLK_DIV, m & MVEBU_MMC_BASE_DIV_MAX); + mvebu_mmc_write(SDIO_CLK_DIV, m); + debug("%s: clock (%d) div : %d\n", DRIVER_NAME, clock, m); } - - udelay(10*1000); } static void mvebu_mmc_set_bus(unsigned int bus) { u32 ctrl_reg = 0; - ctrl_reg = mvebu_mmc_read(SDIO_HOST_CTRL); - ctrl_reg &= ~SDIO_HOST_CTRL_DATA_WIDTH_4_BITS; - switch (bus) { case 4: ctrl_reg |= SDIO_HOST_CTRL_DATA_WIDTH_4_BITS; @@ -277,7 +289,7 @@ static void mvebu_mmc_set_bus(unsigned int bus) ctrl_reg &= ~SDIO_HOST_CTRL_LSB_FIRST; /* default to maximum timeout */ - ctrl_reg |= SDIO_HOST_CTRL_TMOUT(SDIO_HOST_CTRL_TMOUT_MAX); + ctrl_reg |= SDIO_HOST_CTRL_TMOUT_MAX; ctrl_reg |= SDIO_HOST_CTRL_TMOUT_EN; ctrl_reg |= SDIO_HOST_CTRL_PUSH_PULL_EN; @@ -293,7 +305,6 @@ static void mvebu_mmc_set_bus(unsigned int bus) "high-speed" : ""); mvebu_mmc_write(SDIO_HOST_CTRL, ctrl_reg); - udelay(10*1000); } static void mvebu_mmc_set_ios(struct mmc *mmc) @@ -355,7 +366,7 @@ static void mvebu_window_setup(void) static int mvebu_mmc_initialize(struct mmc *mmc) { - debug("%s: mvebu_mmc_initialize", DRIVER_NAME); + debug("%s: mvebu_mmc_initialize\n", DRIVER_NAME); /* * Setting host parameters @@ -398,7 +409,8 @@ static const struct mmc_ops mvebu_mmc_ops = { static struct mmc_config mvebu_mmc_cfg = { .name = DRIVER_NAME, .ops = &mvebu_mmc_ops, - .f_min = MVEBU_MMC_BASE_FAST_CLOCK / MVEBU_MMC_BASE_DIV_MAX, + .f_min = DIV_ROUND_UP(MVEBU_MMC_BASE_FAST_CLOCK, + MVEBU_MMC_BASE_DIV_MAX), .f_max = MVEBU_MMC_CLOCKRATE_MAX, .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, .host_caps = MMC_MODE_4BIT | MMC_MODE_HS | MMC_MODE_HC |