Skip to contentSkip to conversation

Add SPI over GPIO driver

PATCH Superseded Michael Buesch 3 participants 5 messages Jul 14, 2008 – Jul 15, 2008 SPI

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Add SPI over GPIO driver

This adds a driver that lets you drive an SPI bus over generic GPIO pins.

---

This driver is used in OpenWrt since quite some time, so please consider for inclusion in mainline.

include/linux/spi/spi_gpio.h new file +53 -0
Index: linux-next/include/linux/spi/spi_gpio.h
===================================================================
@@ -0,0 +1,53 @@
+/*
+ * spi_gpio interface to platform code
+ *
+ * Copyright (c) 2008 Piotr Skamruk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _LINUX_SPI_SPI_GPIO
+#define _LINUX_SPI_SPI_GPIO
+
+#include <linux/types.h>
+#include <linux/spi/spi.h>
+
+
+/** struct spi_gpio_platform_data - Data definitions for a SPI-GPIO device.
+ * This structure holds information about a GPIO-based SPI device.
+ *
+ * @pin_clk: The GPIO pin number of the CLOCK pin.
+ *
+ * @pin_miso: The GPIO pin number of the MISO pin.
+ *
+ * @pin_mosi: The GPIO pin number of the MOSI pin.
+ *
+ * @pin_cs: The GPIO pin number of the CHIPSELECT pin.
+ *
+ * @cs_activelow: If true, the chip is selected when the CS line is low.
+ *
+ * @no_spi_delay: If true, no delay is done in the lowlevel bitbanging.
+ *                Note that doing no delay is not standards compliant,
+ *                but it might be needed to speed up transfers on some
+ *                slow embedded machines.
+ *
+ * @boardinfo_setup: This callback is called after the
+ *                   SPI master device was registered, but before the
+ *                   device is registered.
+ * @boardinfo_setup_data: Data argument passed to boardinfo_setup().
+ */
+struct spi_gpio_platform_data {
+	unsigned int pin_clk;
+	unsigned int pin_miso;
+	unsigned int pin_mosi;
+	unsigned int pin_cs;
+	bool cs_activelow;
+	bool no_spi_delay;
+	int (*boardinfo_setup)(struct spi_board_info *bi,
+			       struct spi_master *master,
+			       void *data);
+	void *boardinfo_setup_data;
+};
+
+#endif /* _LINUX_SPI_SPI_GPIO */
drivers/spi/spi_gpio.c new file +242 -0

242 lines not on this page · raw message

drivers/spi/Kconfig +13 -0
Index: linux-next/drivers/spi/Kconfig
===================================================================
@@ -100,6 +100,19 @@ config SPI_BUTTERFLY
 	  inexpensive battery powered microcontroller evaluation board.
 	  This same cable can be used to flash new firmware.
 
+config SPI_GPIO
+	tristate "GPIO API based bitbanging SPI controller"
+	depends on SPI_MASTER && GENERIC_GPIO
+	select SPI_BITBANG
+	help
+	  This is a platform driver that can be used for bitbanging
+	  an SPI bus over GPIO pins.
+	  Select this, if you have any SPI device that is connected via
+	  GPIO pins.
+	  The module will be called spi_gpio.
+
+	  If unsure, say N.
+
 config SPI_IMX
 	tristate "Freescale iMX SPI controller"
 	depends on SPI_MASTER && ARCH_IMX && EXPERIMENTAL
drivers/spi/Makefile +1 -0
Index: linux-next/drivers/spi/Makefile
===================================================================
@@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_BFIN)			+= spi_bfin5xx.
 obj-$(CONFIG_SPI_BITBANG)		+= spi_bitbang.o
 obj-$(CONFIG_SPI_AU1550)		+= au1550_spi.o
 obj-$(CONFIG_SPI_BUTTERFLY)		+= spi_butterfly.o
+obj-$(CONFIG_SPI_GPIO)			+= spi_gpio.o
 obj-$(CONFIG_SPI_IMX)			+= spi_imx.o
 obj-$(CONFIG_SPI_LM70_LLP)		+= spi_lm70llp.o
 obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
Signature · 1 line
Greetings Michael.
#1 lore raw

drivers/spi/spi_gpio.c line 74

Quoted 13 lines · On Mon, 14 Jul 2008 21:09:12 +0200 Michael Buesch <[email protected]> wrote:
drivers/spi/spi_gpio.c new file +13 -0
+static inline void do_spidelay(struct spi_device *dev, unsigned nsecs)
+{
+	struct spi_gpio *sp = spidev_to_sg(dev);
+
+	if (!sp->info->no_spi_delay)
+		ndelay(nsecs);
+}
+
+#define spidelay(nsecs) do {					\
+	/* Steal the spi_device pointer from our caller.	\
+	 * The bitbang-API should probably get fixed here... */	\
+	do_spidelay(spi, nsecs);				\
+  } while (0)

A macro which requires that its caller have a particular local variable is a bit nasty. Could we plan to add the spi_device* to spidelay() please?

#2 lore raw
Quoted 12 lines · On Monday 14 July 2008 22:43:45 Andrew Morton wrote:
Quoted 9 lines · On Mon, 14 Jul 2008 21:09:12 +0200 Michael Buesch <[email protected]> wrote:
drivers/spi/spi_gpio.c new file +9 -0
+static inline void do_spidelay(struct spi_device *dev, unsigned nsecs)
+{
+	struct spi_gpio *sp = spidev_to_sg(dev);
+
+	if (!sp->info->no_spi_delay)
+		ndelay(nsecs);
+}
+
+#define spidelay(nsecs) do {					\
Quoted 8 lines

drivers/spi/spi_gpio.c line 74

Quoted 4 lines
drivers/spi/spi_gpio.c new file +4 -0
+	/* Steal the spi_device pointer from our caller.	\
+	 * The bitbang-API should probably get fixed here... */	\
+	do_spidelay(spi, nsecs);				\
+  } while (0)

A macro which requires that its caller have a particular local variable is a bit nasty. Could we plan to add the spi_device* to spidelay() please?

Yeah right. I was planning to fix this later on _after_ this was merged. This makes the merge easier with less patch cross-dependencies.

Signature · 1 line
Greetings Michael.
#3 lore raw
In reply to Michael Buesch
Quoted 2 lines · Michael Buesch

This adds a driver that lets you drive an SPI bus over generic GPIO pins.

Right, this is where spi-gpio is, please disregard my question in the mmc-spi-gpio thing thread, it was domestic blindness after all :-)

Looks good overall. I'm not sure that it need pretend to be hotpluggable though (i.e. the board info can be hardwired so there's no need for the board setup callback). I guess this is to integrate with your "dynamically create an mmc over spi over gpio" thinggy in the other thread. As I said there, I'd prefer that this platform device is treated like other platform devices and any dynamicness be introduced at in a more generic way.

What problem are you solving (or whole in board support are you plugging) in this dynamic plugging of MMCs?

Thanks,

	--Ben.
#4 lore raw
Quoted 2 lines · On Tuesday 15 July 2008 07:30:51 Ben Nizette wrote:

Looks good overall. I'm not sure that it need pretend to be hotpluggable though

Because the hardware _is_ hotpluggable.

Quoted 2 lines

(i.e. the board info can be hardwired so there's no need for the board setup callback).

I'm not sure why we should limit ourselves so much by compiling dynamic and completely individual information, like the bus wireing into the kernel.
This _has_ to be dynamic, as the wireing is _completely_ random and different for every machine. This is selfmade hardware. ;)

Quoted 2 lines

What problem are you solving (or whole in board support are you plugging) in this dynamic plugging of MMCs?

This is to support running MMCs/SDs on GPIO pins.
Which board or card provides the GPIO pins doesn't matter. It doesn't matter, as it's completely abstracted. You can even run 10 or more of the cards at the same time, if you have enough GPIO pins.

Of course, this is mostly useful for embedded systems only. But it is not bound to any specific type of hardware. The hardware just has to implement generic GPIO for its GPIO pins.

Signature · 1 line
Greetings Michael.