From patchwork Tue Jan 11 16:19:07 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Frysinger X-Patchwork-Id: 471921 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 p0BGC8Hm024575 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 11 Jan 2011 16:12:34 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 1Pcgok-0001j1-0k; Tue, 11 Jan 2011 16:11:30 +0000 Received: from sog-mx-3.v43.ch3.sourceforge.com ([172.29.43.193] helo=mx.sourceforge.net) by sfs-ml-4.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1Pcgoi-0001iv-LP for spi-devel-general@lists.sourceforge.net; Tue, 11 Jan 2011 16:11:28 +0000 Received-SPF: pass (sog-mx-3.v43.ch3.sourceforge.com: domain of gentoo.org designates 140.211.166.183 as permitted sender) client-ip=140.211.166.183; envelope-from=vapier@gentoo.org; helo=smtp.gentoo.org; Received: from smtp.gentoo.org ([140.211.166.183]) by sog-mx-3.v43.ch3.sourceforge.com with esmtps (TLSv1:AES256-SHA:256) (Exim 4.72) id 1Pcgog-00079U-Ai for spi-devel-general@lists.sourceforge.net; Tue, 11 Jan 2011 16:11:28 +0000 Received: from localhost.localdomain (localhost [127.0.0.1]) by smtp.gentoo.org (Postfix) with ESMTP id ADC3F1B41E2; Tue, 11 Jan 2011 16:11:19 +0000 (UTC) From: Mike Frysinger To: spi-devel-general@lists.sourceforge.net, David Brownell , Grant Likely Subject: [PATCH 1/2] spi/bfin_spi: support for multiples of 8bits with hardware CS Date: Tue, 11 Jan 2011 11:19:07 -0500 Message-Id: <1294762748-25122-1-git-send-email-vapier@gentoo.org> X-Mailer: git-send-email 1.7.4.rc1 X-Spam-Score: -0.8 (/) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -1.5 SPF_CHECK_PASS SPF reports sender host as permitted sender for sender-domain -0.0 T_RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -0.0 SPF_PASS SPF: sender matches SPF record 0.7 AWL AWL: From: address is in the auto white-list X-Headers-End: 1Pcgog-00079U-Ai Cc: uclinux-dist-devel@blackfin.uclinux.org, Bob Liu 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.6 (demeter1.kernel.org [140.211.167.41]); Tue, 11 Jan 2011 16:12:34 +0000 (UTC) diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index 3f22351..e8d68b7 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c @@ -425,6 +425,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id) struct bfin_spi_slave_data *chip = drv_data->cur_chip; struct spi_message *msg = drv_data->cur_msg; int n_bytes = drv_data->n_bytes; + int loop = 0; /* wait until transfer finished. */ while (!(read_STAT(drv_data) & BIT_STAT_RXS)) @@ -435,10 +436,15 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id) /* last read */ if (drv_data->rx) { dev_dbg(&drv_data->pdev->dev, "last read\n"); - if (n_bytes == 2) - *(u16 *) (drv_data->rx) = read_RDBR(drv_data); - else if (n_bytes == 1) - *(u8 *) (drv_data->rx) = read_RDBR(drv_data); + if (n_bytes % 2) { + u16 *buf = (u16 *)drv_data->rx; + for (loop = 0; loop < n_bytes / 2; loop++) + *buf++ = read_RDBR(drv_data); + } else { + u8 *buf = (u8 *)drv_data->rx; + for (loop = 0; loop < n_bytes; loop++) + *buf++ = read_RDBR(drv_data); + } drv_data->rx += n_bytes; } @@ -458,29 +464,53 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id) if (drv_data->rx && drv_data->tx) { /* duplex */ dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n"); - if (drv_data->n_bytes == 2) { - *(u16 *) (drv_data->rx) = read_RDBR(drv_data); - write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); - } else if (drv_data->n_bytes == 1) { - *(u8 *) (drv_data->rx) = read_RDBR(drv_data); - write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); + if (n_bytes % 2) { + u16 *buf = (u16 *)drv_data->rx; + u16 *buf2 = (u16 *)drv_data->tx; + for (loop = 0; loop < n_bytes / 2; loop++) { + *buf++ = read_RDBR(drv_data); + write_TDBR(drv_data, *buf2++); + } + } else { + u8 *buf = (u8 *)drv_data->rx; + u8 *buf2 = (u8 *)drv_data->tx; + for (loop = 0; loop < n_bytes; loop++) { + *buf++ = read_RDBR(drv_data); + write_TDBR(drv_data, *buf2++); + } } } else if (drv_data->rx) { /* read */ dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n"); - if (drv_data->n_bytes == 2) - *(u16 *) (drv_data->rx) = read_RDBR(drv_data); - else if (drv_data->n_bytes == 1) - *(u8 *) (drv_data->rx) = read_RDBR(drv_data); - write_TDBR(drv_data, chip->idle_tx_val); + if (n_bytes % 2) { + u16 *buf = (u16 *)drv_data->rx; + for (loop = 0; loop < n_bytes / 2; loop++) { + *buf++ = read_RDBR(drv_data); + write_TDBR(drv_data, chip->idle_tx_val); + } + } else { + u8 *buf = (u8 *)drv_data->rx; + for (loop = 0; loop < n_bytes; loop++) { + *buf++ = read_RDBR(drv_data); + write_TDBR(drv_data, chip->idle_tx_val); + } + } } else if (drv_data->tx) { /* write */ dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n"); - bfin_spi_dummy_read(drv_data); - if (drv_data->n_bytes == 2) - write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); - else if (drv_data->n_bytes == 1) - write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); + if (n_bytes % 2) { + u16 *buf = (u16 *)drv_data->tx; + for (loop = 0; loop < n_bytes / 2; loop++) { + read_RDBR(drv_data); + write_TDBR(drv_data, *buf++); + } + } else { + u8 *buf = (u8 *)drv_data->tx; + for (loop = 0; loop < n_bytes; loop++) { + read_RDBR(drv_data); + write_TDBR(drv_data, *buf++); + } + } } if (drv_data->tx) @@ -651,16 +681,16 @@ static void bfin_spi_pump_transfers(unsigned long data) /* Bits per word setup */ bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word; - if (bits_per_word == 8) { - drv_data->n_bytes = 1; - drv_data->len = transfer->len; - cr_width = 0; - drv_data->ops = &bfin_bfin_spi_transfer_ops_u8; - } else if (bits_per_word == 16) { - drv_data->n_bytes = 2; + if ((bits_per_word > 0) && (bits_per_word % 16 == 0)) { + drv_data->n_bytes = bits_per_word/8; drv_data->len = (transfer->len) >> 1; cr_width = BIT_CTL_WORDSIZE; drv_data->ops = &bfin_bfin_spi_transfer_ops_u16; + } else if ((bits_per_word > 0) && (bits_per_word % 8 == 0)) { + drv_data->n_bytes = bits_per_word/8; + drv_data->len = transfer->len; + cr_width = 0; + drv_data->ops = &bfin_bfin_spi_transfer_ops_u8; } else { dev_err(&drv_data->pdev->dev, "transfer: unsupported bits_per_word\n"); message->status = -EINVAL; @@ -815,10 +845,19 @@ static void bfin_spi_pump_transfers(unsigned long data) if (drv_data->tx == NULL) write_TDBR(drv_data, chip->idle_tx_val); else { - if (bits_per_word == 8) - write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); - else - write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); + int loop; + if (bits_per_word % 16 == 0) { + u16 *buf = (u16 *)drv_data->tx; + for (loop = 0; loop < bits_per_word / 16; + loop++) { + write_TDBR(drv_data, *buf++); + } + } else if (bits_per_word % 8 == 0) { + u8 *buf = (u8 *)drv_data->tx; + for (loop = 0; loop < bits_per_word / 8; loop++) + write_TDBR(drv_data, *buf++); + } + drv_data->tx += drv_data->n_bytes; } @@ -1031,7 +1070,7 @@ static int bfin_spi_setup(struct spi_device *spi) chip->ctl_reg &= bfin_ctl_reg; } - if (spi->bits_per_word != 8 && spi->bits_per_word != 16) { + if (spi->bits_per_word % 8) { dev_err(&spi->dev, "%d bits_per_word is not supported\n", spi->bits_per_word); goto error;