From patchwork Thu Sep 30 08:00:45 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mingkai Hu X-Patchwork-Id: 66131 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [18.85.46.34]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 0025CB70DA for ; Thu, 30 Sep 2010 18:28:08 +1000 (EST) Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.72 #1 (Red Hat Linux)) id 1P1ESt-0004wP-EO; Thu, 30 Sep 2010 08:26:07 +0000 Received: from tx2ehsobe001.messaging.microsoft.com ([65.55.88.11] helo=TX2EHSOBE002.bigfish.com) by bombadil.infradead.org with esmtps (Exim 4.72 #1 (Red Hat Linux)) id 1P1ESp-0004v4-HK for linux-mtd@lists.infradead.org; Thu, 30 Sep 2010 08:26:05 +0000 Received: from mail33-tx2-R.bigfish.com (10.9.14.241) by TX2EHSOBE002.bigfish.com (10.9.40.22) with Microsoft SMTP Server id 14.1.225.8; Thu, 30 Sep 2010 08:26:02 +0000 Received: from mail33-tx2 (localhost.localdomain [127.0.0.1]) by mail33-tx2-R.bigfish.com (Postfix) with ESMTP id 1BEA811F0052 for ; Thu, 30 Sep 2010 08:26:02 +0000 (UTC) X-SpamScore: 12 X-BigFish: VS12(zzbb2cK6aa9wzz1202hzz8275bhz2dh2a8h) Received: from mail33-tx2 (localhost.localdomain [127.0.0.1]) by mail33-tx2 (MessageSwitch) id 1285835161633853_26530; Thu, 30 Sep 2010 08:26:01 +0000 (UTC) Received: from TX2EHSMHS015.bigfish.com (unknown [10.9.14.249]) by mail33-tx2.bigfish.com (Postfix) with ESMTP id 87A5C1890050 for ; Thu, 30 Sep 2010 08:26:01 +0000 (UTC) Received: from de01egw02.freescale.net (192.88.165.103) by TX2EHSMHS015.bigfish.com (10.9.99.115) with Microsoft SMTP Server (TLS) id 14.0.482.44; Thu, 30 Sep 2010 08:26:01 +0000 Received: from de01smr01.freescale.net (de01smr01.freescale.net [10.208.0.31]) by de01egw02.freescale.net (8.14.3/8.14.3) with ESMTP id o8U8Q0Fk021234 for ; Thu, 30 Sep 2010 01:26:00 -0700 (MST) Received: from zch01exm21.fsl.freescale.net (zch01exm21.ap.freescale.net [10.192.129.205]) by de01smr01.freescale.net (8.13.1/8.13.0) with ESMTP id o8U8eU0o025764 for ; Thu, 30 Sep 2010 03:40:41 -0500 (CDT) Received: from localhost ([10.193.20.106]) by zch01exm21.fsl.freescale.net with Microsoft SMTPSVC(6.0.3790.4675); Thu, 30 Sep 2010 16:25:49 +0800 From: Mingkai Hu To: , , Subject: [PATCH v3 6/7] mtd: m25p80: add a read function to read page by page Date: Thu, 30 Sep 2010 16:00:45 +0800 Message-ID: <1285833646-12006-7-git-send-email-Mingkai.hu@freescale.com> X-Mailer: git-send-email 1.6.4 In-Reply-To: <1285833646-12006-6-git-send-email-Mingkai.hu@freescale.com> References: <1285833646-12006-1-git-send-email-Mingkai.hu@freescale.com> <1285833646-12006-2-git-send-email-Mingkai.hu@freescale.com> <1285833646-12006-3-git-send-email-Mingkai.hu@freescale.com> <1285833646-12006-4-git-send-email-Mingkai.hu@freescale.com> <1285833646-12006-5-git-send-email-Mingkai.hu@freescale.com> <1285833646-12006-6-git-send-email-Mingkai.hu@freescale.com> X-OriginalArrivalTime: 30 Sep 2010 08:25:49.0725 (UTC) FILETIME=[16A284D0:01CB6079] MIME-Version: 1.0 X-Reverse-DNS: de01egw02.freescale.net X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20100930_042603_819375_F36C6032 X-CRM114-Status: GOOD ( 25.01 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.3.1 on bombadil.infradead.org summary: Content analysis details: (-0.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [65.55.88.11 listed in list.dnswl.org] Cc: grant.likely@secretlab.ca, kumar.gala@freescale.com, tie-fei.zang@freescale.com, Mingkai Hu X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-mtd-bounces@lists.infradead.org Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org For Freescale's eSPI controller, the max transaction length one time is limitted by the SPCOM[TRANSLEN] field which is 0xFFFF. When used mkfs.ext2 command to create ext2 filesystem on the flash, the read length will exceed the max value of the SPCOM[TRANSLEN] field, so change the read function to read page by page. For other SPI flash driver, also needed to supply the read function if used the eSPI controller. Signed-off-by: Mingkai Hu --- v3: - Add a quirks member for the SPI master to handle the contrains of the SPI controller. I can't think of other method. :-( drivers/mtd/devices/m25p80.c | 78 ++++++++++++++++++++++++++++++++++++++++++ drivers/spi/spi_fsl_lib.c | 4 ++ include/linux/spi/spi.h | 5 +++ 3 files changed, 87 insertions(+), 0 deletions(-) diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 47d53c7..f65cca8 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -377,6 +377,81 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, } /* + * Read an address range from the flash chip page by page. + * Some controller has transaction length limitation such as the + * Freescale's eSPI controller can only trasmit 0xFFFF bytes one + * time, so we have to read page by page if the len is more than + * the limitation. + */ +static int m25p80_page_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct m25p *flash = mtd_to_m25p(mtd); + struct spi_transfer t[2]; + struct spi_message m; + u32 i, page_size = 0; + + DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", + dev_name(&flash->spi->dev), __func__, "from", + (u32)from, len); + + /* sanity checks */ + if (!len) + return 0; + + if (from + len > flash->mtd.size) + return -EINVAL; + + spi_message_init(&m); + memset(t, 0, (sizeof t)); + + /* NOTE: + * OPCODE_FAST_READ (if available) is faster. + * Should add 1 byte DUMMY_BYTE. + */ + t[0].tx_buf = flash->command; + t[0].len = m25p_cmdsz(flash) + FAST_READ_DUMMY_BYTE; + spi_message_add_tail(&t[0], &m); + + t[1].rx_buf = buf; + spi_message_add_tail(&t[1], &m); + + /* Byte count starts at zero. */ + if (retlen) + *retlen = 0; + + mutex_lock(&flash->lock); + + /* Wait till previous write/erase is done. */ + if (wait_till_ready(flash)) { + /* REVISIT status return?? */ + mutex_unlock(&flash->lock); + return 1; + } + + /* Set up the write data buffer. */ + flash->command[0] = OPCODE_READ; + + for (i = page_size; i < len; i += page_size) { + page_size = len - i; + if (page_size > flash->page_size) + page_size = flash->page_size; + m25p_addr2cmd(flash, from + i, flash->command); + t[1].len = page_size; + t[1].rx_buf = buf + i; + + spi_sync(flash->spi, &m); + + *retlen += m.actual_length - m25p_cmdsz(flash) + - FAST_READ_DUMMY_BYTE; + } + + mutex_unlock(&flash->lock); + + return 0; +} + +/* * Write an address range to the flash chip. Data must be written in * FLASH_PAGESIZE chunks. The address range may be any size provided * it is within the physical boundaries. @@ -874,6 +949,9 @@ static int __devinit m25p_probe(struct spi_device *spi) flash->mtd.erase = m25p80_erase; flash->mtd.read = m25p80_read; + if (spi->master->quirks & SPI_QUIRK_TRANS_LEN_LIMIT) + flash->mtd.read = m25p80_page_read; + /* sst flash chips use AAI word program */ if (info->jedec_id >> 16 == 0xbf) flash->mtd.write = sst_write; diff --git a/drivers/spi/spi_fsl_lib.c b/drivers/spi/spi_fsl_lib.c index 5cd741f..c8d8c2d 100644 --- a/drivers/spi/spi_fsl_lib.c +++ b/drivers/spi/spi_fsl_lib.c @@ -135,6 +135,10 @@ int mpc8xxx_spi_probe(struct device *dev, struct resource *mem, master->cleanup = mpc8xxx_spi_cleanup; master->dev.of_node = dev->of_node; + if (of_get_property(dev->of_node, + "fsl,spi-quirk-trans-len-limit", NULL)) + master->quirks |= SPI_QUIRK_TRANS_LEN_LIMIT; + mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi->dev = dev; mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 92e52a1..4234dfd 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -304,6 +304,11 @@ struct spi_master { /* called on release() to free memory provided by spi_master */ void (*cleanup)(struct spi_device *spi); + + /* some constraints of the controller */ + u16 quirks; +#define SPI_QUIRK_TRANS_LEN_LIMIT BIT(0) /* have trans length limit */ + }; static inline void *spi_master_get_devdata(struct spi_master *master)