From patchwork Wed Mar 2 12:26:44 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sperl X-Patchwork-Id: 8480541 Return-Path: X-Original-To: patchwork-linux-spi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 2D64BC0553 for ; Wed, 2 Mar 2016 12:26:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 940152038F for ; Wed, 2 Mar 2016 12:26:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 82F652022A for ; Wed, 2 Mar 2016 12:26:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755168AbcCBM0q (ORCPT ); Wed, 2 Mar 2016 07:26:46 -0500 Received: from 212-186-180-163.dynamic.surfer.at ([212.186.180.163]:45740 "EHLO cgate.sperl.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752980AbcCBM0q (ORCPT ); Wed, 2 Mar 2016 07:26:46 -0500 Received: from [213.185.161.134] (account martin@sperl.org HELO [212.186.180.163]) by sperl.org (CommuniGate Pro SMTP 6.1.2) with ESMTPSA id 6397423; Wed, 02 Mar 2016 12:26:42 +0000 Subject: Re: [PATCH 1/6] spi: add flow controll support To: Oleksij Rempel , fixed-term.Oleksij.Rempel@de.bosch.com, geert@linux-m68k.org, dirk.behme@de.bosch.com, broonie@kernel.org, linux-spi@vger.kernel.org, devicetree@vger.kernel.org, robh+dt@kernel.org References: <56D448E1.6090006@de.bosch.com> <1456843400-20696-1-git-send-email-linux@rempel-privat.de> From: Martin Sperl Message-ID: <56D6DC04.30803@martin.sperl.org> Date: Wed, 2 Mar 2016 13:26:44 +0100 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.6.0 MIME-Version: 1.0 In-Reply-To: <1456843400-20696-1-git-send-email-linux@rempel-privat.de> Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On 01.03.2016 15:43, Oleksij Rempel wrote: > Different HW implement different variants of SPI based flow control (FC). > To flexible FC implementation a spited it to fallowing common parts: > Flow control: Request Sequence > Master CS |-------2\_____________________| > Slave FC |-----1\_______________________| > DATA |-----------3\_________________| > > Flow control: Ready Sequence > Master CS |-----1\_______________________| > Slave FC |--------2\____________________| > DATA |-----------3\_________________| > > Flow control: ACK End of Data > Master CS |______________________/2------| > Slave FC |________________________/3----| > DATA |__________________/1----------| > > Flow control: Pause > Master CS |_______________________/------| > Slave FC |_______1/-----\3______/-------| > DATA |________2/------\4___/--------| > > Flow control: Ready signal on MISO > Master CS |-----1\_______________________| > MISO/DATA |------2\____3/----------------| > CONV START | ^ | > DATA READY | ^ | One alternative idea: I guess all of the above could also get implemented without a single framework change like this only in the spi_device driver that requires this: * spi_bus_lock * spi_sync_lock (but with cs_change = 1 on the last transfer, so that cs does not get de-asserted - maybe a 0 byte transfer) * check for your gpio to be of the "expected" level (maybe via interrupt or polling) * spi_sync_lock (continue your transfer) * spi_bus_unlock This could also get wrapped in a generic spi_* method. Maybe another alternative to this approach could be a generic callback after having finished the processing a specific spi_transfer. (not the specific version that you propose) E.g: Then all that is left is implementing that gpio logic as this callback. The complete_code could be just waiting for an GPIO-interrupt to wake up the thread - so it could be as simple as: void spi_transfer_complete_wait_for_completion(void *context) { /* possibly enable interrupt */ /* wait for interrupt to wake us up*/ wait_for_completion(context); /* possibly disable interrupt */ reinit_completion(context); } The creation of the GPIO interrupt and such could also be spi_* helper methods which then could take some of the required info from the device tree. This way the whole thing would be orthogonal to the SPI_READY, for which there is no spi_device driver besides spidev. So there would be also no impact to out of tree/userland drivers. Such an interface actually would allow for other (ab)uses - e.g: read len, then read len bytes becomes easy: void spi_transfer_complete_read_length_then_read(void *context) { struct spi_transfer *xfer = context; struct spi_transfer *next = list_first_entry(list, typeof(*next), transfer_list); /* saturate on length given in original transfer */ if (xfer->rx_buf && (xfer->len>0)) /* this may require unmapping the dma-buffer */ next->len = min_t(unsigned, len, ((char*)xfer->rx_buf)[0]); /* note that if we wanted the ability to abort a transfer, * then the complete method would need to return a status */ } All that is required is that a spi_message is created with 2 transfers, where the first has: * len = 1 * complete = spi_transfer_complete_read_length_then_read; * context = xfer[0] and the second contains: * len = 16; Just some ideas of how it could be implemented in a more generic way that would also allow other uses. Martin --- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1001,6 +1001,9 @@ static int spi_transfer_one_message(struct spi_master *master, if (msg->status != -EINPROGRESS) goto out; + if (xfer->complete) + xfer->complete(xfer->context); + if (xfer->delay_usecs) udelay(xfer->delay_usecs); diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 520a23d..d2b53c4 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -753,6 +753,9 @@ struct spi_transfer { u16 delay_usecs; u32 speed_hz; + void (*complete)(void *context); + void *context; + struct list_head transfer_list; };