From patchwork Thu Mar 20 09:21:00 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lee Jones X-Patchwork-Id: 26661 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ve0-f199.google.com (mail-ve0-f199.google.com [209.85.128.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 9A14C202E0 for ; Thu, 20 Mar 2014 09:22:18 +0000 (UTC) Received: by mail-ve0-f199.google.com with SMTP id cz12sf1461861veb.6 for ; Thu, 20 Mar 2014 02:22:18 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=p7OvXgkkIZZPoL8Q9GguLqKgHPLOo/zEtIZNMZ2b0Bw=; b=Gi7elKH9nPP3x28OO+6PtzLC6xJ/17zDSmRn4czvYm1WhsLnvOBbI5g07fyuq7Aizz pkDbWA8sHUyfxvDn3AsmurfDjrb4fXq7xeZL1QUNR9qeoWl16xuPazcNoX2n7RZA05Nh fQ3QNbG5SVfsVfzgmTCzIPSSCRgowfjaC5FV4rrWZbYgqzqjOsHFPQf8WjBaD/qgidku HcTGI9A2s/JIcoL2GiiyZxW95ViJItfG4op26GSdAipdYVpJf+UJ3s+LqRGqWyc6Yhbo hurzZhK51Xk26ytyaaIRdKvO/OLskQwLNc3Vgq72xs/lgbHtUSpx1sOkqibACZHTF3yE eShA== X-Gm-Message-State: ALoCoQldCrbhY7dp9nVHWwPwGdrhNNWOs/iVYKQ9aElNoPofnSxH1hPuaCA8xGOyPv1v3dXOo6qZ X-Received: by 10.58.132.211 with SMTP id ow19mr5407199veb.8.1395307338239; Thu, 20 Mar 2014 02:22:18 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.93.194 with SMTP id d60ls154876qge.22.gmail; Thu, 20 Mar 2014 02:22:18 -0700 (PDT) X-Received: by 10.52.175.166 with SMTP id cb6mr27916914vdc.1.1395307338062; Thu, 20 Mar 2014 02:22:18 -0700 (PDT) Received: from mail-vc0-f177.google.com (mail-vc0-f177.google.com [209.85.220.177]) by mx.google.com with ESMTPS id tz5si298455vdc.133.2014.03.20.02.22.18 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 20 Mar 2014 02:22:18 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.220.177 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.177; Received: by mail-vc0-f177.google.com with SMTP id if17so598370vcb.36 for ; Thu, 20 Mar 2014 02:22:18 -0700 (PDT) X-Received: by 10.58.201.5 with SMTP id jw5mr32030174vec.6.1395307337968; Thu, 20 Mar 2014 02:22:17 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.78.9 with SMTP id i9csp372571vck; Thu, 20 Mar 2014 02:22:17 -0700 (PDT) X-Received: by 10.180.87.164 with SMTP id az4mr1819119wib.2.1395307336680; Thu, 20 Mar 2014 02:22:16 -0700 (PDT) Received: from mail-wi0-f169.google.com (mail-wi0-f169.google.com [209.85.212.169]) by mx.google.com with ESMTPS id l3si12099551wiz.32.2014.03.20.02.22.16 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 20 Mar 2014 02:22:16 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.212.169 is neither permitted nor denied by best guess record for domain of lee.jones@linaro.org) client-ip=209.85.212.169; Received: by mail-wi0-f169.google.com with SMTP id hm4so5790732wib.2 for ; Thu, 20 Mar 2014 02:22:16 -0700 (PDT) X-Received: by 10.194.57.38 with SMTP id f6mr6305059wjq.59.1395307336118; Thu, 20 Mar 2014 02:22:16 -0700 (PDT) Received: from lee--X1.home (host109-148-116-196.range109-148.btcentralplus.com. [109.148.116.196]) by mx.google.com with ESMTPSA id di9sm4735120wid.6.2014.03.20.02.22.14 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 20 Mar 2014 02:22:15 -0700 (PDT) From: Lee Jones To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, computersforpeace@gmail.com Cc: linux-mtd@lists.infradead.org, dwmw2@infradead.org, Angus.Clark@st.com, Lee Jones Subject: [PATCH v6 28/36] mtd: st_spi_fsm: Erase partly or as a whole a Serial Flash device Date: Thu, 20 Mar 2014 09:21:00 +0000 Message-Id: <1395307268-12721-29-git-send-email-lee.jones@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1395307268-12721-1-git-send-email-lee.jones@linaro.org> References: <1395307268-12721-1-git-send-email-lee.jones@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: lee.jones@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.177 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , When an erase is requested by userspace the MTD framework calls back into the driver to conduct the actual command issue. Here we provide the routines which do exactly that. We can choose to either do an entire chip erase or by sector. Acked-by Angus Clark Signed-off-by: Lee Jones --- drivers/mtd/devices/st_spi_fsm.c | 113 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c index 99e08b0..34aac3f 100644 --- a/drivers/mtd/devices/st_spi_fsm.c +++ b/drivers/mtd/devices/st_spi_fsm.c @@ -567,6 +567,27 @@ static struct stfsm_seq stfsm_seq_erase_sector = { SEQ_CFG_STARTSEQ), }; +static struct stfsm_seq stfsm_seq_erase_chip = { + .seq_opc = { + (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | + SEQ_OPC_OPCODE(FLASH_CMD_WREN) | SEQ_OPC_CSDEASSERT), + + (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | + SEQ_OPC_OPCODE(FLASH_CMD_CHIPERASE) | SEQ_OPC_CSDEASSERT), + }, + .seq = { + STFSM_INST_CMD1, + STFSM_INST_CMD2, + STFSM_INST_WAIT, + STFSM_INST_STOP, + }, + .seq_cfg = (SEQ_CFG_PADS_1 | + SEQ_CFG_ERASE | + SEQ_CFG_READNOTWRITE | + SEQ_CFG_CSDEASSERT | + SEQ_CFG_STARTSEQ), +}; + static struct stfsm_seq stfsm_seq_wrvcr = { .seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | SEQ_OPC_OPCODE(FLASH_CMD_WREN) | SEQ_OPC_CSDEASSERT), @@ -1217,6 +1238,47 @@ static int stfsm_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, return 0; } +static int stfsm_erase_sector(struct stfsm *fsm, const uint32_t offset) +{ + struct stfsm_seq *seq = &stfsm_seq_erase_sector; + int ret; + + dev_dbg(fsm->dev, "erasing sector at 0x%08x\n", offset); + + /* Enter 32-bit address mode, if required */ + if (fsm->configuration & CFG_ERASESEC_TOGGLE_32BIT_ADDR) + stfsm_enter_32bit_addr(fsm, 1); + + seq->addr1 = (offset >> 16) & 0xffff; + seq->addr2 = offset & 0xffff; + + stfsm_load_seq(fsm, seq); + + stfsm_wait_seq(fsm); + + /* Wait for completion */ + ret = stfsm_wait_busy(fsm); + + /* Exit 32-bit address mode, if required */ + if (fsm->configuration & CFG_ERASESEC_TOGGLE_32BIT_ADDR) + stfsm_enter_32bit_addr(fsm, 0); + + return ret; +} + +static int stfsm_erase_chip(struct stfsm *fsm) +{ + const struct stfsm_seq *seq = &stfsm_seq_erase_chip; + + dev_dbg(fsm->dev, "erasing chip\n"); + + stfsm_load_seq(fsm, seq); + + stfsm_wait_seq(fsm); + + return stfsm_wait_busy(fsm); +} + /* * Write an address range to the flash chip. Data must be written in * FLASH_PAGESIZE chunks. The address range may be any size provided @@ -1272,6 +1334,54 @@ out1: return ret; } +/* + * Erase an address range on the flash chip. The address range may extend + * one or more erase sectors. Return an error is there is a problem erasing. + */ +static int stfsm_mtd_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct stfsm *fsm = dev_get_drvdata(mtd->dev.parent); + u32 addr, len; + int ret; + + dev_dbg(fsm->dev, "%s at 0x%llx, len %lld\n", __func__, + (long long)instr->addr, (long long)instr->len); + + addr = instr->addr; + len = instr->len; + + mutex_lock(&fsm->lock); + + /* Whole-chip erase? */ + if (len == mtd->size) { + ret = stfsm_erase_chip(fsm); + if (ret) + goto out1; + } else { + while (len) { + ret = stfsm_erase_sector(fsm, addr); + if (ret) + goto out1; + + addr += mtd->erasesize; + len -= mtd->erasesize; + } + } + + mutex_unlock(&fsm->lock); + + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + + return 0; + +out1: + instr->state = MTD_ERASE_FAILED; + mutex_unlock(&fsm->lock); + + return ret; +} + static void stfsm_read_jedec(struct stfsm *fsm, uint8_t *const jedec) { const struct stfsm_seq *seq = &stfsm_seq_read_jedec; @@ -1529,8 +1639,9 @@ static int stfsm_probe(struct platform_device *pdev) fsm->mtd._read = stfsm_mtd_read; fsm->mtd._write = stfsm_mtd_write; + fsm->mtd._erase = stfsm_mtd_erase; - dev_err(&pdev->dev, + dev_info(&pdev->dev, "Found serial flash device: %s\n" " size = %llx (%lldMiB) erasesize = 0x%08x (%uKiB)\n", info->name,