From patchwork Fri Sep 3 01:36:54 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jassi Brar X-Patchwork-Id: 151931 Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o832DZff006013 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 3 Sep 2010 02:14:11 GMT Received: from localhost ([127.0.0.1] helo=sfs-ml-4.v29.ch3.sourceforge.com) by sfs-ml-4.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1OrLmZ-0004XD-OV; Fri, 03 Sep 2010 02:13:35 +0000 Received: from sog-mx-2.v43.ch3.sourceforge.com ([172.29.43.192] helo=mx.sourceforge.net) by sfs-ml-4.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1OrLmY-0004X7-LX for spi-devel-general@lists.sourceforge.net; Fri, 03 Sep 2010 02:13:34 +0000 X-ACL-Warn: Received: from ganesha.gnumonks.org ([213.95.27.120]) by sog-mx-2.v43.ch3.sourceforge.com with esmtps (TLSv1:AES256-SHA:256) (Exim 4.69) id 1OrLmX-0003jL-Ij; Fri, 03 Sep 2010 02:13:34 +0000 Received: from uucp by ganesha.gnumonks.org with local-bsmtp (Exim 4.69) (envelope-from ) id 1OrLQU-0004Rm-Rg; Fri, 03 Sep 2010 03:50:46 +0200 Received: from [12.23.102.184] (helo=localhost.localdomain) by jackpot.kr.gnumonks.org with esmtp (Exim 4.69) (envelope-from ) id 1OrKXs-0007ci-2X; Fri, 03 Sep 2010 09:54:20 +0900 From: Jassi Brar To: spi-devel-general@lists.sourceforge.net Subject: [PATCH 4/6] SPI: S3C64XX: Correction for 16,32 bits bus width Date: Fri, 3 Sep 2010 10:36:54 +0900 Message-Id: <1283477814-31228-1-git-send-email-jassi.brar@samsung.com> X-Mailer: git-send-email 1.6.2.5 In-Reply-To: <1OrKX4-0007cO-1K> References: <1OrKX4-0007cO-1K> X-Spam-Score: 0.0 (/) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. X-Headers-End: 1OrLmX-0003jL-Ij Cc: dbrownell@users.sourceforge.net X-BeenThere: spi-devel-general@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: Linux SPI core/device drivers discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: spi-devel-general-bounces@lists.sourceforge.net X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Fri, 03 Sep 2010 02:14:12 +0000 (UTC) diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c index 39816bb..8aa9f85 100644 --- a/drivers/spi/spi_s3c64xx.c +++ b/drivers/spi/spi_s3c64xx.c @@ -174,12 +174,59 @@ struct s3c64xx_spi_driver_data { unsigned state; unsigned cur_mode, cur_bpw; unsigned cur_speed; + void (*do_xfer)(void *ptr, void *fifo, unsigned sz, bool rd); }; static struct s3c2410_dma_client s3c64xx_spi_dma_client = { .name = "samsung-spi-dma", }; +static void s3c64xx_spi_xfer8(void *ptr, void __iomem *fifo, + unsigned len, bool read) +{ + u8 *buf = (u8 *)ptr; + int i = 0; + + if (read) + while (i < len) + buf[i++] = readb(fifo); + else + while (i < len) + writeb(buf[i++], fifo); +} + +static void s3c64xx_spi_xfer16(void *ptr, void __iomem *fifo, + unsigned len, bool read) +{ + u16 *buf = (u16 *)ptr; + int i = 0; + + len /= 2; + + if (read) + while (i < len) + buf[i++] = readw(fifo); + else + while (i < len) + writew(buf[i++], fifo); +} + +static void s3c64xx_spi_xfer32(void *ptr, void __iomem *fifo, + unsigned len, bool read) +{ + u32 *buf = (u32 *)ptr; + int i = 0; + + len /= 4; + + if (read) + while (i < len) + buf[i++] = readl(fifo); + else + while (i < len) + writel(buf[i++], fifo); +} + static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) { struct s3c64xx_spi_info *sci = sdd->cntrlr_info; @@ -260,10 +307,8 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, xfer->tx_dma, xfer->len); s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START); } else { - unsigned char *buf = (unsigned char *) xfer->tx_buf; - int i = 0; - while (i < xfer->len) - writeb(buf[i++], regs + S3C64XX_SPI_TX_DATA); + sdd->do_xfer((void *)xfer->tx_buf, + regs + S3C64XX_SPI_TX_DATA, xfer->len, false); } } @@ -360,20 +405,14 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, return -EIO; } } else { - unsigned char *buf; - int i; - /* If it was only Tx */ if (xfer->rx_buf == NULL) { sdd->state &= ~TXBUSY; return 0; } - i = 0; - buf = xfer->rx_buf; - while (i < xfer->len) - buf[i++] = readb(regs + S3C64XX_SPI_RX_DATA); - + sdd->do_xfer(xfer->rx_buf, + regs + S3C64XX_SPI_RX_DATA, xfer->len, true); sdd->state &= ~RXBUSY; } @@ -423,15 +462,20 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) switch (sdd->cur_bpw) { case 32: val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD; + val |= S3C64XX_SPI_MODE_CH_TSZ_WORD; + sdd->do_xfer = s3c64xx_spi_xfer32; break; case 16: val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD; + val |= S3C64XX_SPI_MODE_CH_TSZ_HALFWORD; + sdd->do_xfer = s3c64xx_spi_xfer16; break; default: val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE; + val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE; + sdd->do_xfer = s3c64xx_spi_xfer8; break; } - val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE; /* Always 8bits wide */ writel(val, regs + S3C64XX_SPI_MODE_CFG); @@ -610,6 +654,14 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd, bpw = xfer->bits_per_word ? : spi->bits_per_word; speed = xfer->speed_hz ? : spi->max_speed_hz; + if (bpw != 8 && xfer->len % (bpw / 8)) { + dev_err(&spi->dev, + "Xfer length(%u) not a multiple of word size(%u)\n", + xfer->len, bpw / 8); + status = -EIO; + goto out; + } + if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) { sdd->cur_bpw = bpw; sdd->cur_speed = speed;