From patchwork Wed Apr 21 10:46:51 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 93847 Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o3LAlJiI022983 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 21 Apr 2010 10:47:55 GMT Received: from localhost ([127.0.0.1] helo=sfs-ml-3.v29.ch3.sourceforge.com) by sfs-ml-3.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1O4XSc-0003gv-Di; Wed, 21 Apr 2010 10:47:14 +0000 Received: from sfi-mx-1.v28.ch3.sourceforge.com ([172.29.28.121] helo=mx.sourceforge.net) by sfs-ml-3.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1O4XSb-0003gl-Ld for spi-devel-general@lists.sourceforge.net; Wed, 21 Apr 2010 10:47:13 +0000 Received-SPF: pass (sfi-mx-1.v28.ch3.sourceforge.com: domain of gmail.com designates 72.14.220.155 as permitted sender) client-ip=72.14.220.155; envelope-from=mika.westerberg@gmail.com; helo=fg-out-1718.google.com; Received: from fg-out-1718.google.com ([72.14.220.155]) by sfi-mx-1.v28.ch3.sourceforge.com with esmtp (Exim 4.69) id 1O4XSa-0006Ma-GE for spi-devel-general@lists.sourceforge.net; Wed, 21 Apr 2010 10:47:13 +0000 Received: by fg-out-1718.google.com with SMTP id 19so1517393fgg.10 for ; Wed, 21 Apr 2010 03:47:06 -0700 (PDT) Received: by 10.223.7.78 with SMTP id c14mr474812fac.64.1271846815716; Wed, 21 Apr 2010 03:46:55 -0700 (PDT) Received: from gw.healthdatacare.com (a88-112-70-218.elisa-laajakaista.fi [88.112.70.218]) by mx.google.com with ESMTPS id 9sm4973890fks.26.2010.04.21.03.46.53 (version=SSLv3 cipher=RC4-MD5); Wed, 21 Apr 2010 03:46:54 -0700 (PDT) Date: Wed, 21 Apr 2010 13:46:51 +0300 From: Mika Westerberg To: H Hartley Sweeten Message-ID: <20100421104651.GO19534@gw.healthdatacare.com> References: <0D753D10438DA54287A00B0270842697636D85BCCC@AUSP01VMBX24.collaborationhost.net> <0D753D10438DA54287A00B0270842697636D85BDD8@AUSP01VMBX24.collaborationhost.net> <0D753D10438DA54287A00B0270842697636D85BE26@AUSP01VMBX24.collaborationhost.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <0D753D10438DA54287A00B0270842697636D85BE26@AUSP01VMBX24.collaborationhost.net> User-Agent: Mutt/1.5.18 (2008-05-17) X-Spam-Score: -1.1 (-) 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 SPF_PASS SPF: sender matches SPF record -0.0 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.0 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.4 AWL AWL: From: address is in the auto white-list X-Headers-End: 1O4XSa-0006Ma-GE Cc: "spi-devel-general@lists.sourceforge.net" , Martin Guy , "ryan@bluewatersys.com" , "linux-arm-kernel@lists.infradead.org" Subject: Re: [spi-devel-general] [PATCH v4 1/2] spi: implemented driver for Cirrus EP93xx SPI controller 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: , 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 (demeter.kernel.org [140.211.167.41]); Wed, 21 Apr 2010 10:47:56 +0000 (UTC) diff --git a/drivers/spi/ep93xx_spi.c b/drivers/spi/ep93xx_spi.c index 310032d..11dcdd1 100644 --- a/drivers/spi/ep93xx_spi.c +++ b/drivers/spi/ep93xx_spi.c @@ -106,6 +106,8 @@ struct ep93xx_spi { unsigned long min_rate; unsigned long max_rate; bool running; + bool can_continue; + struct spi_transfer *last_transfer; struct workqueue_struct *wq; struct work_struct msg_work; struct completion wait; @@ -380,6 +382,7 @@ static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *msg) struct ep93xx_spi *espi = spi_master_get_devdata(spi->master); struct spi_transfer *t; unsigned long flags; + bool can_continue = true; if (!msg || !msg->complete) return -EINVAL; @@ -387,11 +390,21 @@ static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *msg) /* first validate each transfer */ list_for_each_entry(t, &msg->transfers, transfer_list) { if (t->bits_per_word) { + can_continue = false; if (t->bits_per_word < 4 || t->bits_per_word > 16) return -EINVAL; } - if (t->speed_hz && t->speed_hz < espi->min_rate) + if (t->speed_hz) { + can_continue = false; + if (t->speed_hz < espi->min_rate) return -EINVAL; + } + if (t->cs_change && + !list_is_last(&t->transfer_list, &msg->transfers)) { + can_continue = false; + } + if (t->delay_usecs) + can_continue = false; } /* @@ -400,7 +413,7 @@ static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *msg) * error in transfer and @msg->state is used to hold pointer to the * current transfer (or %NULL if no active current transfer). */ - msg->state = NULL; + msg->state = (void *)can_continue; msg->status = 0; msg->actual_length = 0; @@ -606,10 +619,33 @@ static void ep93xx_spi_process_message(struct ep93xx_spi *espi, ep93xx_spi_chip_setup(espi, spi_get_ctldata(msg->spi)); ep93xx_spi_select_device(espi, msg->spi); - list_for_each_entry(t, &msg->transfers, transfer_list) { - ep93xx_spi_process_transfer(espi, msg, t); - if (msg->status) - break; + if (msg->state) { + espi->can_continue = true; + espi->last_transfer = list_entry(msg->transfers.prev, struct spi_transfer, + transfer_list); + } else { + espi->can_continue = false; + espi->last_transfer = NULL; + } + + /* + * In case there is no transfer specific settings in this message we + * can transfer the whole message with interrupts. Otherwise we need + * to perform transfer specific stuff in thread context. + */ + if (espi->can_continue) { + msg->state = list_first_entry(&msg->transfers, struct spi_transfer, + transfer_list); + espi->rx = 0; + espi->tx = 0; + ep93xx_spi_enable_interrupts(espi); + wait_for_completion(&espi->wait); + } else { + list_for_each_entry(t, &msg->transfers, transfer_list) { + ep93xx_spi_process_transfer(espi, msg, t); + if (msg->status) + break; + } } /* @@ -792,6 +828,24 @@ static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id) * interrupt then. */ return IRQ_HANDLED; + } else { + /* + * If we can continue directly to the next transfer, do + * that now. + */ + if (espi->can_continue) { + struct spi_message *msg = espi->current_msg; + struct spi_transfer *t = msg->state; + + if (t != espi->last_transfer) { + msg->state = list_entry(t->transfer_list.next, struct spi_transfer, + transfer_list); + espi->rx = 0; + espi->tx = 0; + return IRQ_HANDLED; + } + } + /* otherwise we are ready */ } }