From patchwork Thu Apr 29 18:34:24 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hartley Sweeten X-Patchwork-Id: 51304 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 83831B7D30 for ; Fri, 30 Apr 2010 04:39:09 +1000 (EST) Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) id 1O7YbH-00039Y-7B; Thu, 29 Apr 2010 18:36:39 +0000 Received: from p01c12o148.mxlogic.net ([208.65.145.71]) by bombadil.infradead.org with esmtps (Exim 4.69 #1 (Red Hat Linux)) id 1O7YbA-00037c-F2 for linux-mtd@lists.infradead.org; Thu, 29 Apr 2010 18:36:35 +0000 Received: from unknown [216.166.12.72] (EHLO p01c12o148.mxlogic.net) by p01c12o148.mxlogic.net(mxl_mta-6.5.0-2) with ESMTP id 0b1d9db4.7314d940.5951.00-405.14261.p01c12o148.mxlogic.net (envelope-from ); Thu, 29 Apr 2010 12:36:32 -0600 (MDT) X-MXL-Hash: 4bd9d1b016903d9c-2c47face00998779e0c22b768fcb9b3c76c193d7 Received: from unknown [216.166.12.72] by p01c12o148.mxlogic.net(mxl_mta-6.5.0-2) with SMTP id 251d9db4.0.2287.00-001.12734.p01c12o148.mxlogic.net (envelope-from ); Thu, 29 Apr 2010 12:36:14 -0600 (MDT) X-MXL-Hash: 4bd9d19e217b8539-377f8aca4ad5779c50c82beba01c76395749fc80 Received: from AUSP01VMBX24.collaborationhost.net ([10.2.12.1]) by AUSP01MHUB50.collaborationhost.net ([10.2.10.3]) with mapi; Thu, 29 Apr 2010 13:34:24 -0500 From: H Hartley Sweeten To: Linux Kernel , "linux-mtd@lists.infradead.org" Date: Thu, 29 Apr 2010 13:34:24 -0500 Subject: [PATCH] sst25l.c: fix multi-part messages with broken spi masters Thread-Topic: [PATCH] sst25l.c: fix multi-part messages with broken spi masters Thread-Index: AcrnypfJPeCwvyWvRyqcxSV64zmhaw== Message-ID: <0D753D10438DA54287A00B0270842697636E305D4A@AUSP01VMBX24.collaborationhost.net> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: acceptlanguage: en-US MIME-Version: 1.0 X-Spam: [F=0.2000000000; CM=0.500; S=0.200(2010042902)] X-MAIL-FROM: X-SOURCE-IP: [216.166.12.72] X-AnalysisOut: [v=1.0 c=1 a=borFIQzli1YA:10 a=VphdPIyG4kEA:10 a=IkcTkHD0fZ] X-AnalysisOut: [MA:10 a=jM3uHZP82BWpxjlUuN2t4A==:17 a=i00gxMtYAAAA:8 a=Jfr] X-AnalysisOut: [nYn6hAAAA:8 a=pGLkceISAAAA:8 a=rggnVFrEAAAA:8 a=nowIHpIveu] X-AnalysisOut: [VuGbkFGBMA:9 a=Hj9QbegMjyGHuiDSf8cA:7 a=vP3aldeonwbFo30t8E] X-AnalysisOut: [bzZHiF4tIA:4 a=QEXdDO2ut3YA:10 a=x1WnkoZAwusA:10 a=3Rfx1nU] X-AnalysisOut: [Sh_UA:10 a=MSl-tDqOz04A:10 a=ct-hs6iedJYA:10] X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20100429_143632_761524_8F74362E X-CRM114-Status: GOOD ( 17.27 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.3.1 on bombadil.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, medium trust [208.65.145.71 listed in list.dnswl.org] Cc: "ryan@bluewatersys.com" , "andre@bluewatersys.com" , David Woodhouse , "dedekind1@gmail.com" 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 Some SPI masters (ep93xx) have limitations when using the SFRMOUT signal for the spi device chip select. The SFRMOUT signal is only asserted as long as the spi transmit fifo contains data. As soon as the last bit is clocked into the receive fifo it gets deasserted. The functions sst25l_status and sst25l_match_device use the API function spi_write_then_read to write a command to the flash then read the response back. This API function creates a two part spi message for the write then read. When this message is transferred the SFRMOUT signal ends up getting deasserted after the command phase. This causes the command to get aborted by the device so the read phase returns invalid data. By changing sst25l_status and sst25l_match_device to use a single transfer synchronous message, the SFRMOUT signal stays asserted during the entire message so the correct data always gets returned. This change will have no effect on SPI masters which use a chip select mechanism (GPIO's, etc.) which does stay asserted correctly. As a bonus, the single transfer synchronous messages complete faster than multi-part messages. Signed-off-by: H Hartley Sweeten Cc: David Woodhouse Cc: Artem Bityutskiy Cc: Andre Renaud Cc: Ryan Mallon --- This driver is needed on the ep93xx based EDB93xx dev boards to access the SPI flash. This patch replaces "sst25l.c: simplify reading the device ManID/DevID" which was previously posted. diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c index fe17054..7de3bee 100644 --- a/drivers/mtd/devices/sst25l.c +++ b/drivers/mtd/devices/sst25l.c @@ -73,15 +73,25 @@ static struct flash_info __initdata sst25l_flash_info[] = { static int sst25l_status(struct sst25l_flash *flash, int *status) { - unsigned char command, response; + struct spi_message m; + struct spi_transfer t; + unsigned char cmd_resp[2]; int err; - command = SST25L_CMD_RDSR; - err = spi_write_then_read(flash->spi, &command, 1, &response, 1); + spi_message_init(&m); + memset(&t, 0, sizeof(struct spi_transfer)); + + cmd_resp[0] = SST25L_CMD_RDSR; + cmd_resp[1] = 0xff; + t.tx_buf = cmd_resp; + t.rx_buf = cmd_resp; + t.len = sizeof(cmd_resp); + spi_message_add_tail(&t, &m); + err = spi_sync(flash->spi, &m); if (err < 0) return err; - *status = response; + *status = cmd_resp[1]; return 0; } @@ -328,33 +338,32 @@ out: static struct flash_info *__init sst25l_match_device(struct spi_device *spi) { struct flash_info *flash_info = NULL; - unsigned char command[4], response; + struct spi_message m; + struct spi_transfer t; + unsigned char cmd_resp[6]; int i, err; uint16_t id; - command[0] = SST25L_CMD_READ_ID; - command[1] = 0; - command[2] = 0; - command[3] = 0; - err = spi_write_then_read(spi, command, sizeof(command), &response, 1); - if (err < 0) { - dev_err(&spi->dev, "error reading device id msb\n"); - return NULL; - } - - id = response << 8; - - command[0] = SST25L_CMD_READ_ID; - command[1] = 0; - command[2] = 0; - command[3] = 1; - err = spi_write_then_read(spi, command, sizeof(command), &response, 1); + spi_message_init(&m); + memset(&t, 0, sizeof(struct spi_transfer)); + + cmd_resp[0] = SST25L_CMD_READ_ID; + cmd_resp[1] = 0; + cmd_resp[2] = 0; + cmd_resp[3] = 0; + cmd_resp[4] = 0xff; + cmd_resp[5] = 0xff; + t.tx_buf = cmd_resp; + t.rx_buf = cmd_resp; + t.len = sizeof(cmd_resp); + spi_message_add_tail(&t, &m); + err = spi_sync(spi, &m); if (err < 0) { - dev_err(&spi->dev, "error reading device id lsb\n"); + dev_err(&spi->dev, "error reading device id\n"); return NULL; } - id |= response; + id = (cmd_resp[4] << 8) | cmd_resp[5]; for (i = 0; i < ARRAY_SIZE(sst25l_flash_info); i++) if (sst25l_flash_info[i].device_id == id)