From patchwork Wed Jan 8 13:47:13 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lee Jones X-Patchwork-Id: 22966 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oa0-f70.google.com (mail-oa0-f70.google.com [209.85.219.70]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id AEEBB202E2 for ; Wed, 8 Jan 2014 13:49:15 +0000 (UTC) Received: by mail-oa0-f70.google.com with SMTP id h16sf6410484oag.5 for ; Wed, 08 Jan 2014 05:49:14 -0800 (PST) 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=60pfvcwOtTEU6BgTQkUwYj2CU2I9ddJNyeGQA4bLZQU=; b=T294c4jhsFIeth+g0Nk1IsE0mQPnGZ3olijzttNX8gEGG9onpFZ+LlZzoZsFbxlMxG /VGnmmb4G7lsAQ3PReu4dAnzXnfF7ALp/jjYqRosRTZXLvzdsLYI214GV+cUBMLTSWmf PMQJsIHEsQC8vARFmSR0KRiJp+dekvJaPeRhwvc/EJaF3nUNifxyPkfu9zYYIbGkJj4T nKXSH8NV130VFzd2te0SlUZ8uK1ykgxuHoLv6/A9Rxz0jRvU33OcC19CrTlMdr7Oqp+I kF8r0kR0GEfjv3dNpz8zBDchBzeReD/yeBMDIDbQH4D6wnVUVxK3cOrC3ec9/oF0vDRb Gk7w== X-Gm-Message-State: ALoCoQndwlbP5b8N6m+FciGLe87O3WTVPxsvhH4pL7S+HvLuhmvF8WculQTnuzziZrOw/P1YachR X-Received: by 10.42.81.84 with SMTP id y20mr46671183ick.10.1389188954831; Wed, 08 Jan 2014 05:49:14 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.131.4 with SMTP id oi4ls586490qeb.76.gmail; Wed, 08 Jan 2014 05:49:14 -0800 (PST) X-Received: by 10.52.227.233 with SMTP id sd9mr2730042vdc.53.1389188954713; Wed, 08 Jan 2014 05:49:14 -0800 (PST) Received: from mail-vb0-f42.google.com (mail-vb0-f42.google.com [209.85.212.42]) by mx.google.com with ESMTPS id gs2si592595vdc.122.2014.01.08.05.49.14 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 08 Jan 2014 05:49:14 -0800 (PST) Received-SPF: neutral (google.com: 209.85.212.42 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.212.42; Received: by mail-vb0-f42.google.com with SMTP id w5so1156184vbf.29 for ; Wed, 08 Jan 2014 05:49:14 -0800 (PST) X-Received: by 10.58.243.37 with SMTP id wv5mr3205254vec.41.1389188954593; Wed, 08 Jan 2014 05:49:14 -0800 (PST) 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.59.13.131 with SMTP id ey3csp226651ved; Wed, 8 Jan 2014 05:49:13 -0800 (PST) X-Received: by 10.180.36.40 with SMTP id n8mr21347195wij.54.1389188951322; Wed, 08 Jan 2014 05:49:11 -0800 (PST) Received: from mail-wi0-f176.google.com (mail-wi0-f176.google.com [209.85.212.176]) by mx.google.com with ESMTPS id k8si29292145wje.69.2014.01.08.05.49.10 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 08 Jan 2014 05:49:11 -0800 (PST) Received-SPF: neutral (google.com: 209.85.212.176 is neither permitted nor denied by best guess record for domain of lee.jones@linaro.org) client-ip=209.85.212.176; Received: by mail-wi0-f176.google.com with SMTP id hq4so5527346wib.9 for ; Wed, 08 Jan 2014 05:49:10 -0800 (PST) X-Received: by 10.194.48.74 with SMTP id j10mr56989097wjn.41.1389188950802; Wed, 08 Jan 2014 05:49:10 -0800 (PST) Received: from localhost.localdomain (cpc15-aztw25-2-0-cust493.aztw.cable.virginm.net. [92.233.57.238]) by mx.google.com with ESMTPSA id j9sm48125217wjx.18.2014.01.08.05.49.09 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 08 Jan 2014 05:49:10 -0800 (PST) From: Lee Jones To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: computersforpeace@gmail.com, angus.clark@st.com, Lee Jones Subject: [PATCH v4 30/37] mtd: st_spi_fsm: Erase partly or as a whole a Serial Flash device Date: Wed, 8 Jan 2014 13:47:13 +0000 Message-Id: <1389188840-14306-31-git-send-email-lee.jones@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1389188840-14306-1-git-send-email-lee.jones@linaro.org> References: <1389188840-14306-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.212.42 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. 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 0b80d74..eac23df 100644 --- a/drivers/mtd/devices/st_spi_fsm.c +++ b/drivers/mtd/devices/st_spi_fsm.c @@ -565,6 +565,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), @@ -1203,6 +1224,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 @@ -1260,6 +1322,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; @@ -1530,8 +1640,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,