From patchwork Tue Feb 18 14:55:55 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lee Jones X-Patchwork-Id: 24878 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pd0-f200.google.com (mail-pd0-f200.google.com [209.85.192.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id EA74C202B2 for ; Tue, 18 Feb 2014 15:00:37 +0000 (UTC) Received: by mail-pd0-f200.google.com with SMTP id y10sf37494841pdj.7 for ; Tue, 18 Feb 2014 07:00:37 -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:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=WHtHpuIRB9ICMqQOwQ4ii84d0hmusypRNnr5DYeOMIo=; b=GHBz3dbHErkf5LOzJ3RofbzBvLQrkObA86vrAIlu/rWKFcciI5a17yHmg8dhV13ZbT Vhdc0itulidM33AS/W/uypc+xWSHK1lF14chUFBH7qDe1RD3Fuw+5uOmIttuy1/QbYF/ CrnObB33xASY98L0yTsqDHgF6BR8a++0jBZX8Ds0QzUreewK1dJHGE8iKZ1R8yAzMnmi bFWhapsvrFT/DSVHNL26IIDpYh7z2WDmm8zvJBncBHRIJb0Bqm+NtV7rn4l4DbTF4SlH uiKrqMeKHEOsmdBnMhCBYUf/By9KKdVPhvVYRXZJIF5myMIyJiiJx5EwsTeqZNjzEhMM H0ig== X-Gm-Message-State: ALoCoQlM+fRuMfK5IWfVobWsHTcua4M+3NCxyjdqOMWfPDFxGHc2Nisydmc+G1U69m2Y2tBVvqrd X-Received: by 10.67.21.145 with SMTP id hk17mr12703520pad.35.1392735636309; Tue, 18 Feb 2014 07:00:36 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.20.166 with SMTP id 35ls1322715qgj.20.gmail; Tue, 18 Feb 2014 07:00:36 -0800 (PST) X-Received: by 10.220.67.18 with SMTP id p18mr21589305vci.14.1392735636206; Tue, 18 Feb 2014 07:00:36 -0800 (PST) Received: from mail-ve0-f171.google.com (mail-ve0-f171.google.com [209.85.128.171]) by mx.google.com with ESMTPS id tr5si5555988vdc.104.2014.02.18.07.00.36 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 18 Feb 2014 07:00:36 -0800 (PST) Received-SPF: neutral (google.com: 209.85.128.171 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.171; Received: by mail-ve0-f171.google.com with SMTP id pa12so13439676veb.2 for ; Tue, 18 Feb 2014 07:00:36 -0800 (PST) X-Received: by 10.220.133.80 with SMTP id e16mr21550281vct.13.1392735636042; Tue, 18 Feb 2014 07:00:36 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.174.196 with SMTP id u4csp222799vcz; Tue, 18 Feb 2014 07:00:35 -0800 (PST) X-Received: by 10.68.230.137 with SMTP id sy9mr33384068pbc.126.1392735634985; Tue, 18 Feb 2014 07:00:34 -0800 (PST) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id zk9si18597518pac.173.2014.02.18.07.00.34; Tue, 18 Feb 2014 07:00:34 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756270AbaBRPA0 (ORCPT + 27 others); Tue, 18 Feb 2014 10:00:26 -0500 Received: from mail-wg0-f52.google.com ([74.125.82.52]:43323 "EHLO mail-wg0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932345AbaBRO5m (ORCPT ); Tue, 18 Feb 2014 09:57:42 -0500 Received: by mail-wg0-f52.google.com with SMTP id b13so3404140wgh.7 for ; Tue, 18 Feb 2014 06:57:41 -0800 (PST) X-Received: by 10.180.24.227 with SMTP id x3mr18610793wif.41.1392735461223; Tue, 18 Feb 2014 06:57:41 -0800 (PST) Received: from localhost.localdomain ([80.76.198.141]) by mx.google.com with ESMTPSA id h13sm46039687wjr.22.2014.02.18.06.57.38 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 18 Feb 2014 06:57:40 -0800 (PST) From: Lee Jones To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: lee.jones@linaro.org, DCG_UPD_stlinux_kernel@list.st.com, dwmw2@infradead.org, linux-mtd@lists.infradead.org, computersforpeace@gmail.com, Angus.Clark@st.com Subject: [PATCH 28/35] mtd: st_spi_fsm: Erase partly or as a whole a Serial Flash device Date: Tue, 18 Feb 2014 14:55:55 +0000 Message-Id: <1392735362-1245-29-git-send-email-lee.jones@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1392735362-1245-1-git-send-email-lee.jones@linaro.org> References: <1392735362-1245-1-git-send-email-lee.jones@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.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.128.171 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 Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org 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 0eacfbf..a5e2c5a 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), @@ -1218,6 +1239,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 @@ -1275,6 +1337,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; @@ -1533,8 +1643,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,