From patchwork Thu Apr 1 10:35:51 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 90112 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 o31AaGRk027821 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 1 Apr 2010 10:36:52 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 1NxHl1-0003xm-Qm; Thu, 01 Apr 2010 10:36:15 +0000 Received: from sfi-mx-1.v28.ch3.sourceforge.com ([172.29.28.121] helo=mx.sourceforge.net) by sfs-ml-4.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1NxHl0-0003xc-4r for spi-devel-general@lists.sourceforge.net; Thu, 01 Apr 2010 10:36:14 +0000 X-ACL-Warn: Received: from mailout3.w1.samsung.com ([210.118.77.13]) by sfi-mx-1.v28.ch3.sourceforge.com with esmtp (Exim 4.69) id 1NxHkv-0000MY-2q for spi-devel-general@lists.sourceforge.net; Thu, 01 Apr 2010 10:36:12 +0000 MIME-version: 1.0 Received: from eu_spt2 ([210.118.77.13]) by mailout3.w1.samsung.com (Sun Java(tm) System Messaging Server 6.3-8.04 (built Jul 29 2009; 32bit)) with ESMTP id <0L0700BKA1G1XT40@mailout3.w1.samsung.com> for spi-devel-general@lists.sourceforge.net; Thu, 01 Apr 2010 11:36:02 +0100 (BST) Received: from linux.samsung.com ([106.116.38.10]) by spt2.w1.samsung.com (iPlanet Messaging Server 5.2 Patch 2 (built Jul 14 2004)) with ESMTPA id <0L07003VO1G0AN@spt2.w1.samsung.com> for spi-devel-general@lists.sourceforge.net; Thu, 01 Apr 2010 11:36:01 +0100 (BST) Received: from localhost.localdomain (unknown [106.116.37.23]) by linux.samsung.com (Postfix) with ESMTP id D5F85270003; Thu, 01 Apr 2010 12:35:57 +0200 (CEST) Date: Thu, 01 Apr 2010 12:35:51 +0200 From: Marek Szyprowski To: spi-devel-general@lists.sourceforge.net, "'David Brownell'" Message-id: <1270118151-13286-1-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.7.0 X-Spam-Score: -0.0 (/) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 SPF_HELO_PASS SPF: HELO matches SPF record 0.0 AWL AWL: From: address is in the auto white-list X-Headers-End: 1NxHkv-0000MY-2q Cc: kyungmin.park@samsung.com, m.szyprowski@samsung.com Subject: [spi-devel-general] [PATCH] drivers: spi-gpio: add support for controllers without MISO or MOSI pin 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]); Thu, 01 Apr 2010 10:36:52 +0000 (UTC) diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c index 26bd03e..2db2f6f 100644 --- a/drivers/spi/spi_gpio.c +++ b/drivers/spi/spi_gpio.c @@ -109,12 +109,16 @@ static inline void setsck(const struct spi_device *spi, int is_on) static inline void setmosi(const struct spi_device *spi, int is_on) { - gpio_set_value(SPI_MOSI_GPIO, is_on); + if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) + gpio_set_value(SPI_MOSI_GPIO, is_on); } static inline int getmiso(const struct spi_device *spi) { - return !!gpio_get_value(SPI_MISO_GPIO); + if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) + return !!gpio_get_value(SPI_MISO_GPIO); + else + return 0; } #undef pdata @@ -233,19 +237,30 @@ static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in) } static int __init -spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label) +spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label, + u16 *res_flags) { int value; /* NOTE: SPI_*_GPIO symbols may reference "pdata" */ - value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false); - if (value) - goto done; + if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) { + value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false); + if (value) + goto done; + } else { + /* HW configuration without MOSI pin */ + *res_flags |= SPI_MASTER_NO_TX; + } - value = spi_gpio_alloc(SPI_MISO_GPIO, label, true); - if (value) - goto free_mosi; + if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) { + value = spi_gpio_alloc(SPI_MISO_GPIO, label, true); + if (value) + goto free_mosi; + } else { + /* HW configuration without MISO pin */ + *res_flags |= SPI_MASTER_NO_RX; + } value = spi_gpio_alloc(SPI_SCK_GPIO, label, false); if (value) @@ -254,9 +269,11 @@ spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label) goto done; free_miso: - gpio_free(SPI_MISO_GPIO); + if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) + gpio_free(SPI_MISO_GPIO); free_mosi: - gpio_free(SPI_MOSI_GPIO); + if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) + gpio_free(SPI_MOSI_GPIO); done: return value; } @@ -267,6 +284,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) struct spi_master *master; struct spi_gpio *spi_gpio; struct spi_gpio_platform_data *pdata; + u16 master_flags = 0; pdata = pdev->dev.platform_data; #ifdef GENERIC_BITBANG @@ -274,7 +292,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) return -ENODEV; #endif - status = spi_gpio_request(pdata, dev_name(&pdev->dev)); + status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags); if (status < 0) return status; @@ -290,6 +308,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) if (pdata) spi_gpio->pdata = *pdata; + master->flags = master_flags; master->bus_num = pdev->id; master->num_chipselect = SPI_N_CHIPSEL; master->setup = spi_gpio_setup; @@ -308,8 +327,10 @@ static int __init spi_gpio_probe(struct platform_device *pdev) if (status < 0) { spi_master_put(spi_gpio->bitbang.master); gpio_free: - gpio_free(SPI_MISO_GPIO); - gpio_free(SPI_MOSI_GPIO); + if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) + gpio_free(SPI_MISO_GPIO); + if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) + gpio_free(SPI_MOSI_GPIO); gpio_free(SPI_SCK_GPIO); spi_master_put(master); } @@ -332,8 +353,10 @@ static int __exit spi_gpio_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - gpio_free(SPI_MISO_GPIO); - gpio_free(SPI_MOSI_GPIO); + if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) + gpio_free(SPI_MISO_GPIO); + if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) + gpio_free(SPI_MOSI_GPIO); gpio_free(SPI_SCK_GPIO); return status; diff --git a/include/linux/spi/spi_gpio.h b/include/linux/spi/spi_gpio.h index ca6782e..369b3d7 100644 --- a/include/linux/spi/spi_gpio.h +++ b/include/linux/spi/spi_gpio.h @@ -29,11 +29,16 @@ * SPI_GPIO_NO_CHIPSELECT to the controller_data: * .controller_data = (void *) SPI_GPIO_NO_CHIPSELECT; * + * If the MISO or MOSI pin is not available then it should be set to + * SPI_GPIO_NO_MISO or SPI_GPIO_NO_MOSI. + * * If the bitbanged bus is later switched to a "native" controller, * that platform_device and controller_data should be removed. */ #define SPI_GPIO_NO_CHIPSELECT ((unsigned long)-1l) +#define SPI_GPIO_NO_MISO ((unsigned long)-1l) +#define SPI_GPIO_NO_MOSI ((unsigned long)-1l) /** * struct spi_gpio_platform_data - parameter for bitbanged SPI master