From patchwork Tue Apr 25 18:30:14 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Moritz Fischer X-Patchwork-Id: 9699257 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2F729601D3 for ; Tue, 25 Apr 2017 18:33:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1F6012846C for ; Tue, 25 Apr 2017 18:33:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 13D7A284DA; Tue, 25 Apr 2017 18:33:14 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A4BAC2846C for ; Tue, 25 Apr 2017 18:33:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1953215AbdDYSbw (ORCPT ); Tue, 25 Apr 2017 14:31:52 -0400 Received: from mail.kernel.org ([198.145.29.136]:47250 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1949572AbdDYSak (ORCPT ); Tue, 25 Apr 2017 14:30:40 -0400 Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9F5F5201B9; Tue, 25 Apr 2017 18:30:38 +0000 (UTC) Received: from tyrael.amer.corp.natinst.com (207-114-172-147.static.twtelecom.net [207.114.172.147]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 83C3320145; Tue, 25 Apr 2017 18:30:37 +0000 (UTC) From: Moritz Fischer To: linux-kernel@vger.kernel.org Cc: linux-spi@vger.kernel.org, broonie@kernel.org, moritz.fischer@ettus.com, alex.williams@ni.com, Moritz Fischer Subject: [PATCH] spi: cadence: Allow for GPIO pins to be used as chipselects Date: Tue, 25 Apr 2017 11:30:14 -0700 Message-Id: <1493145014-3163-1-git-send-email-mdf@kernel.org> X-Mailer: git-send-email 2.7.4 X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This adds support for using GPIOs for chipselects as described by the default dt-bindings. Signed-off-by: Moritz Fischer --- Hi Mark, I've tested this on my Zynq-7000 based system with GPIO and non-gpio based chipselects mixed. Thanks for your time, Moritz --- drivers/spi/spi-cadence.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 1c57ce6..f0b5c7b 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -127,6 +128,10 @@ struct cdns_spi { u32 is_decoded_cs; }; +struct cdns_spi_device_data { + bool gpio_requested; +}; + /* Macros for the SPI controller read/write */ static inline u32 cdns_spi_read(struct cdns_spi *xspi, u32 offset) { @@ -456,6 +461,64 @@ static int cdns_unprepare_transfer_hardware(struct spi_master *master) return 0; } +static int cdns_spi_setup(struct spi_device *spi) +{ + + int ret = -EINVAL; + struct cdns_spi_device_data *cdns_spi_data = spi_get_ctldata(spi); + + /* this is a pin managed by the controller, leave it alone */ + if (spi->cs_gpio == -ENOENT) + return 0; + + /* this seems to be the first time we're here */ + if (!cdns_spi_data) { + cdns_spi_data = kzalloc(sizeof(*cdns_spi_data), GFP_KERNEL); + if (!cdns_spi_data) + return -ENOMEM; + cdns_spi_data->gpio_requested = false; + spi_set_ctldata(spi, cdns_spi_data); + } + + /* if we haven't done so, grab the gpio */ + if (!cdns_spi_data->gpio_requested && gpio_is_valid(spi->cs_gpio)) { + ret = gpio_request_one(spi->cs_gpio, + (spi->mode & SPI_CS_HIGH) ? + GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, + dev_name(&spi->dev)); + if (ret) + dev_err(&spi->dev, "can't request chipselect gpio %d\n", + spi->cs_gpio); + else + cdns_spi_data->gpio_requested = true; + } else { + if (gpio_is_valid(spi->cs_gpio)) { + int mode = ((spi->mode & SPI_CS_HIGH) ? + GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH); + + ret = gpio_direction_output(spi->cs_gpio, mode); + if (ret) + dev_err(&spi->dev, "chipselect gpio %d setup failed (%d)\n", + spi->cs_gpio, ret); + } + } + + return ret; +} + +static void cdns_spi_cleanup(struct spi_device *spi) +{ + struct cdns_spi_device_data *cdns_spi_data = spi_get_ctldata(spi); + + if (cdns_spi_data) { + if (cdns_spi_data->gpio_requested) + gpio_free(spi->cs_gpio); + kfree(cdns_spi_data); + spi_set_ctldata(spi, NULL); + } + +} + /** * cdns_spi_probe - Probe method for the SPI driver * @pdev: Pointer to the platform_device structure @@ -555,6 +618,8 @@ static int cdns_spi_probe(struct platform_device *pdev) master->transfer_one = cdns_transfer_one; master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware; master->set_cs = cdns_spi_chipselect; + master->setup = cdns_spi_setup; + master->cleanup = cdns_spi_cleanup; master->auto_runtime_pm = true; master->mode_bits = SPI_CPOL | SPI_CPHA;