Revert "kernel: remove long obsolete gpio spi controller driver patch"
This reverts commit 9e62a7668c.
			
			
This commit is contained in:
		| @@ -43,6 +43,22 @@ endef | |||||||
| $(eval $(call KernelPackage,spi-bitbang)) | $(eval $(call KernelPackage,spi-bitbang)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | define KernelPackage/spi-gpio-old | ||||||
|  |   SUBMENU:=$(SPI_MENU) | ||||||
|  |   TITLE:=Old GPIO based bitbanging SPI controller (DEPRECATED) | ||||||
|  |   DEPENDS:=@GPIO_SUPPORT +kmod-spi-bitbang | ||||||
|  |   KCONFIG:=CONFIG_SPI_GPIO_OLD | ||||||
|  |   FILES:=$(LINUX_DIR)/drivers/spi/spi_gpio_old.ko | ||||||
|  |   AUTOLOAD:=$(call AutoProbe,spi_gpio_old) | ||||||
|  | endef | ||||||
|  |  | ||||||
|  | define KernelPackage/spi-gpio-old/description | ||||||
|  |  This package contains the GPIO based bitbanging SPI controller driver | ||||||
|  | endef | ||||||
|  |  | ||||||
|  | $(eval $(call KernelPackage,spi-gpio-old)) | ||||||
|  |  | ||||||
|  |  | ||||||
| define KernelPackage/spi-gpio | define KernelPackage/spi-gpio | ||||||
|   SUBMENU:=$(SPI_MENU) |   SUBMENU:=$(SPI_MENU) | ||||||
|   TITLE:=GPIO-based bitbanging SPI Master |   TITLE:=GPIO-based bitbanging SPI Master | ||||||
|   | |||||||
| @@ -3784,6 +3784,7 @@ CONFIG_SND_VERBOSE_PROCFS=y | |||||||
| # CONFIG_SPI_FSL_ESPI is not set | # CONFIG_SPI_FSL_ESPI is not set | ||||||
| # CONFIG_SPI_FSL_SPI is not set | # CONFIG_SPI_FSL_SPI is not set | ||||||
| # CONFIG_SPI_GPIO is not set | # CONFIG_SPI_GPIO is not set | ||||||
|  | # CONFIG_SPI_GPIO_OLD is not set | ||||||
| # CONFIG_SPI_LM70_LLP is not set | # CONFIG_SPI_LM70_LLP is not set | ||||||
| # CONFIG_SPI_MASTER is not set | # CONFIG_SPI_MASTER is not set | ||||||
| # CONFIG_SPI_MPC52xx is not set | # CONFIG_SPI_MPC52xx is not set | ||||||
|   | |||||||
| @@ -3938,6 +3938,7 @@ CONFIG_SND_VERBOSE_PROCFS=y | |||||||
| # CONFIG_SPI_FSL_ESPI is not set | # CONFIG_SPI_FSL_ESPI is not set | ||||||
| # CONFIG_SPI_FSL_SPI is not set | # CONFIG_SPI_FSL_SPI is not set | ||||||
| # CONFIG_SPI_GPIO is not set | # CONFIG_SPI_GPIO is not set | ||||||
|  | # CONFIG_SPI_GPIO_OLD is not set | ||||||
| # CONFIG_SPI_IMG_SPFI is not set | # CONFIG_SPI_IMG_SPFI is not set | ||||||
| # CONFIG_SPI_LM70_LLP is not set | # CONFIG_SPI_LM70_LLP is not set | ||||||
| # CONFIG_SPI_MASTER is not set | # CONFIG_SPI_MASTER is not set | ||||||
|   | |||||||
| @@ -3942,6 +3942,7 @@ CONFIG_SND_VERBOSE_PROCFS=y | |||||||
| # CONFIG_SPI_FSL_ESPI is not set | # CONFIG_SPI_FSL_ESPI is not set | ||||||
| # CONFIG_SPI_FSL_SPI is not set | # CONFIG_SPI_FSL_SPI is not set | ||||||
| # CONFIG_SPI_GPIO is not set | # CONFIG_SPI_GPIO is not set | ||||||
|  | # CONFIG_SPI_GPIO_OLD is not set | ||||||
| # CONFIG_SPI_IMG_SPFI is not set | # CONFIG_SPI_IMG_SPFI is not set | ||||||
| # CONFIG_SPI_LM70_LLP is not set | # CONFIG_SPI_LM70_LLP is not set | ||||||
| # CONFIG_SPI_MASTER is not set | # CONFIG_SPI_MASTER is not set | ||||||
|   | |||||||
							
								
								
									
										373
									
								
								target/linux/generic/patches-3.18/862-gpio_spi_driver.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										373
									
								
								target/linux/generic/patches-3.18/862-gpio_spi_driver.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,373 @@ | |||||||
|  | THIS CODE IS DEPRECATED. | ||||||
|  |  | ||||||
|  | Please use the new mainline SPI-GPIO driver, as of 2.6.29. | ||||||
|  |  | ||||||
|  | --mb | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  drivers/spi/Kconfig              |    9 + | ||||||
|  |  drivers/spi/Makefile             |    1  | ||||||
|  |  drivers/spi/spi_gpio_old.c       |  251 +++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  include/linux/spi/spi_gpio_old.h |   73 +++++++++++ | ||||||
|  |  4 files changed, 334 insertions(+) | ||||||
|  |  | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/include/linux/spi/spi_gpio_old.h | ||||||
|  | @@ -0,0 +1,73 @@ | ||||||
|  | +/* | ||||||
|  | + * spi_gpio interface to platform code | ||||||
|  | + * | ||||||
|  | + * Copyright (c) 2008 Piotr Skamruk | ||||||
|  | + * Copyright (c) 2008 Michael Buesch | ||||||
|  | + * | ||||||
|  | + * 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; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * SPI_GPIO_PLATDEV_NAME - The platform device name string. | ||||||
|  | + * | ||||||
|  | + * The name string that has to be used for platform_device_alloc | ||||||
|  | + * when allocating a spi-gpio device. | ||||||
|  | + */ | ||||||
|  | +#define SPI_GPIO_PLATDEV_NAME	"spi-gpio" | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * spi_gpio_next_id - Get another platform device ID number. | ||||||
|  | + * | ||||||
|  | + * This returns the next platform device ID number that has to be used | ||||||
|  | + * for platform_device_alloc. The ID is opaque and should not be used for | ||||||
|  | + * anything else. | ||||||
|  | + */ | ||||||
|  | +int spi_gpio_next_id(void); | ||||||
|  | + | ||||||
|  | +#endif /* _LINUX_SPI_SPI_GPIO */ | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/spi/spi_gpio_old.c | ||||||
|  | @@ -0,0 +1,251 @@ | ||||||
|  | +/* | ||||||
|  | + * Bitbanging SPI bus driver using GPIO API | ||||||
|  | + * | ||||||
|  | + * Copyright (c) 2008 Piotr Skamruk | ||||||
|  | + * Copyright (c) 2008 Michael Buesch | ||||||
|  | + * | ||||||
|  | + * based on spi_s3c2410_gpio.c | ||||||
|  | + *   Copyright (c) 2006 Ben Dooks | ||||||
|  | + *   Copyright (c) 2006 Simtec Electronics | ||||||
|  | + * and on i2c-gpio.c | ||||||
|  | + *   Copyright (C) 2007 Atmel Corporation | ||||||
|  | + * | ||||||
|  | + * 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. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +#include <linux/kernel.h> | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/delay.h> | ||||||
|  | +#include <linux/spinlock.h> | ||||||
|  | +#include <linux/workqueue.h> | ||||||
|  | +#include <linux/module.h> | ||||||
|  | +#include <linux/platform_device.h> | ||||||
|  | +#include <linux/spi/spi.h> | ||||||
|  | +#include <linux/spi/spi_bitbang.h> | ||||||
|  | +#include <linux/spi/spi_gpio_old.h> | ||||||
|  | +#include <linux/gpio.h> | ||||||
|  | +#include <asm/atomic.h> | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +struct spi_gpio { | ||||||
|  | +	struct spi_bitbang bitbang; | ||||||
|  | +	struct spi_gpio_platform_data *info; | ||||||
|  | +	struct platform_device *pdev; | ||||||
|  | +	struct spi_board_info bi; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +static inline struct spi_gpio *spidev_to_sg(struct spi_device *dev) | ||||||
|  | +{ | ||||||
|  | +	return dev->controller_data; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static inline void setsck(struct spi_device *dev, int val) | ||||||
|  | +{ | ||||||
|  | +	struct spi_gpio *sp = spidev_to_sg(dev); | ||||||
|  | +	gpio_set_value(sp->info->pin_clk, val ? 1 : 0); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static inline void setmosi(struct spi_device *dev, int val) | ||||||
|  | +{ | ||||||
|  | +	struct spi_gpio *sp = spidev_to_sg(dev); | ||||||
|  | +	gpio_set_value(sp->info->pin_mosi, val ? 1 : 0); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static inline u32 getmiso(struct spi_device *dev) | ||||||
|  | +{ | ||||||
|  | +	struct spi_gpio *sp = spidev_to_sg(dev); | ||||||
|  | +	return gpio_get_value(sp->info->pin_miso) ? 1 : 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) | ||||||
|  | + | ||||||
|  | +#define EXPAND_BITBANG_TXRX | ||||||
|  | +#include "spi-bitbang-txrx.h" | ||||||
|  | + | ||||||
|  | +static u32 spi_gpio_txrx_mode0(struct spi_device *spi, | ||||||
|  | +			       unsigned nsecs, u32 word, u8 bits) | ||||||
|  | +{ | ||||||
|  | +	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static u32 spi_gpio_txrx_mode1(struct spi_device *spi, | ||||||
|  | +			       unsigned nsecs, u32 word, u8 bits) | ||||||
|  | +{ | ||||||
|  | +	return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static u32 spi_gpio_txrx_mode2(struct spi_device *spi, | ||||||
|  | +			       unsigned nsecs, u32 word, u8 bits) | ||||||
|  | +{ | ||||||
|  | +	return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static u32 spi_gpio_txrx_mode3(struct spi_device *spi, | ||||||
|  | +			       unsigned nsecs, u32 word, u8 bits) | ||||||
|  | +{ | ||||||
|  | +	return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void spi_gpio_chipselect(struct spi_device *dev, int on) | ||||||
|  | +{ | ||||||
|  | +	struct spi_gpio *sp = spidev_to_sg(dev); | ||||||
|  | + | ||||||
|  | +	if (sp->info->cs_activelow) | ||||||
|  | +		on = !on; | ||||||
|  | +	gpio_set_value(sp->info->pin_cs, on ? 1 : 0); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int spi_gpio_probe(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct spi_master *master; | ||||||
|  | +	struct spi_gpio_platform_data *pdata; | ||||||
|  | +	struct spi_gpio *sp; | ||||||
|  | +	struct spi_device *spidev; | ||||||
|  | +	int err; | ||||||
|  | + | ||||||
|  | +	pdata = pdev->dev.platform_data; | ||||||
|  | +	if (!pdata) | ||||||
|  | +		return -ENXIO; | ||||||
|  | + | ||||||
|  | +	err = -ENOMEM; | ||||||
|  | +	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_gpio)); | ||||||
|  | +	if (!master) | ||||||
|  | +		goto err_alloc_master; | ||||||
|  | + | ||||||
|  | +	sp = spi_master_get_devdata(master); | ||||||
|  | +	platform_set_drvdata(pdev, sp); | ||||||
|  | +	sp->info = pdata; | ||||||
|  | + | ||||||
|  | +	err = gpio_request(pdata->pin_clk, "spi_clock"); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_request_clk; | ||||||
|  | +	err = gpio_request(pdata->pin_mosi, "spi_mosi"); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_request_mosi; | ||||||
|  | +	err = gpio_request(pdata->pin_miso, "spi_miso"); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_request_miso; | ||||||
|  | +	err = gpio_request(pdata->pin_cs, "spi_cs"); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_request_cs; | ||||||
|  | + | ||||||
|  | +	sp->bitbang.master = spi_master_get(master); | ||||||
|  | +	sp->bitbang.master->bus_num = -1; | ||||||
|  | +	sp->bitbang.master->num_chipselect = 1; | ||||||
|  | +	sp->bitbang.chipselect = spi_gpio_chipselect; | ||||||
|  | +	sp->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_mode0; | ||||||
|  | +	sp->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_mode1; | ||||||
|  | +	sp->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_mode2; | ||||||
|  | +	sp->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_mode3; | ||||||
|  | + | ||||||
|  | +	gpio_direction_output(pdata->pin_clk, 0); | ||||||
|  | +	gpio_direction_output(pdata->pin_mosi, 0); | ||||||
|  | +	gpio_direction_output(pdata->pin_cs, | ||||||
|  | +			      pdata->cs_activelow ? 1 : 0); | ||||||
|  | +	gpio_direction_input(pdata->pin_miso); | ||||||
|  | + | ||||||
|  | +	err = spi_bitbang_start(&sp->bitbang); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_no_bitbang; | ||||||
|  | +	err = pdata->boardinfo_setup(&sp->bi, master, | ||||||
|  | +				     pdata->boardinfo_setup_data); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_bi_setup; | ||||||
|  | +	sp->bi.controller_data = sp; | ||||||
|  | +	spidev = spi_new_device(master, &sp->bi); | ||||||
|  | +	if (!spidev) | ||||||
|  | +		goto err_new_dev; | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | + | ||||||
|  | +err_new_dev: | ||||||
|  | +err_bi_setup: | ||||||
|  | +	spi_bitbang_stop(&sp->bitbang); | ||||||
|  | +err_no_bitbang: | ||||||
|  | +	spi_master_put(sp->bitbang.master); | ||||||
|  | +	gpio_free(pdata->pin_cs); | ||||||
|  | +err_request_cs: | ||||||
|  | +	gpio_free(pdata->pin_miso); | ||||||
|  | +err_request_miso: | ||||||
|  | +	gpio_free(pdata->pin_mosi); | ||||||
|  | +err_request_mosi: | ||||||
|  | +	gpio_free(pdata->pin_clk); | ||||||
|  | +err_request_clk: | ||||||
|  | +	kfree(master); | ||||||
|  | + | ||||||
|  | +err_alloc_master: | ||||||
|  | +	return err; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int spi_gpio_remove(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct spi_gpio *sp; | ||||||
|  | +	struct spi_gpio_platform_data *pdata; | ||||||
|  | + | ||||||
|  | +	pdata = pdev->dev.platform_data; | ||||||
|  | +	sp = platform_get_drvdata(pdev); | ||||||
|  | + | ||||||
|  | +	gpio_free(pdata->pin_clk); | ||||||
|  | +	gpio_free(pdata->pin_mosi); | ||||||
|  | +	gpio_free(pdata->pin_miso); | ||||||
|  | +	gpio_free(pdata->pin_cs); | ||||||
|  | +	spi_bitbang_stop(&sp->bitbang); | ||||||
|  | +	spi_master_put(sp->bitbang.master); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct platform_driver spi_gpio_driver = { | ||||||
|  | +	.driver		= { | ||||||
|  | +		.name	= SPI_GPIO_PLATDEV_NAME, | ||||||
|  | +		.owner	= THIS_MODULE, | ||||||
|  | +	}, | ||||||
|  | +	.probe		= spi_gpio_probe, | ||||||
|  | +	.remove		= spi_gpio_remove, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +int spi_gpio_next_id(void) | ||||||
|  | +{ | ||||||
|  | +	static atomic_t counter = ATOMIC_INIT(-1); | ||||||
|  | + | ||||||
|  | +	return atomic_inc_return(&counter); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(spi_gpio_next_id); | ||||||
|  | + | ||||||
|  | +static int __init spi_gpio_init(void) | ||||||
|  | +{ | ||||||
|  | +	int err; | ||||||
|  | + | ||||||
|  | +	err = platform_driver_register(&spi_gpio_driver); | ||||||
|  | +	if (err) | ||||||
|  | +		printk(KERN_ERR "spi-gpio: register failed: %d\n", err); | ||||||
|  | + | ||||||
|  | +	return err; | ||||||
|  | +} | ||||||
|  | +module_init(spi_gpio_init); | ||||||
|  | + | ||||||
|  | +static void __exit spi_gpio_exit(void) | ||||||
|  | +{ | ||||||
|  | +	platform_driver_unregister(&spi_gpio_driver); | ||||||
|  | +} | ||||||
|  | +module_exit(spi_gpio_exit); | ||||||
|  | + | ||||||
|  | +MODULE_AUTHOR("Piot Skamruk <piotr.skamruk at gmail.com>"); | ||||||
|  | +MODULE_AUTHOR("Michael Buesch"); | ||||||
|  | +MODULE_DESCRIPTION("Platform independent GPIO bitbanging SPI driver"); | ||||||
|  | +MODULE_LICENSE("GPL v2"); | ||||||
|  | --- a/drivers/spi/Kconfig | ||||||
|  | +++ b/drivers/spi/Kconfig | ||||||
|  | @@ -225,6 +225,15 @@ config SPI_GPIO | ||||||
|  |  	  GPIO operations, you should be able to leverage that for better | ||||||
|  |  	  speed with a custom version of this driver; see the source code. | ||||||
|  |   | ||||||
|  | +config SPI_GPIO_OLD | ||||||
|  | +	tristate "Old GPIO API based bitbanging SPI controller (DEPRECATED)" | ||||||
|  | +	depends on SPI_MASTER && GPIOLIB | ||||||
|  | +	select SPI_BITBANG | ||||||
|  | +	help | ||||||
|  | +	  This code is deprecated. Please use the new mainline SPI-GPIO driver. | ||||||
|  | + | ||||||
|  | +	  If unsure, say N. | ||||||
|  | + | ||||||
|  |  config SPI_IMX | ||||||
|  |  	tristate "Freescale i.MX SPI controllers" | ||||||
|  |  	depends on ARCH_MXC || COMPILE_TEST | ||||||
|  | --- a/drivers/spi/Makefile | ||||||
|  | +++ b/drivers/spi/Makefile | ||||||
|  | @@ -40,6 +40,7 @@ obj-$(CONFIG_SPI_FSL_LIB)		+= spi-fsl-li | ||||||
|  |  obj-$(CONFIG_SPI_FSL_ESPI)		+= spi-fsl-espi.o | ||||||
|  |  obj-$(CONFIG_SPI_FSL_SPI)		+= spi-fsl-spi.o | ||||||
|  |  obj-$(CONFIG_SPI_GPIO)			+= spi-gpio.o | ||||||
|  | +obj-$(CONFIG_SPI_GPIO_OLD)		+= spi_gpio_old.o | ||||||
|  |  obj-$(CONFIG_SPI_IMX)			+= spi-imx.o | ||||||
|  |  obj-$(CONFIG_SPI_LM70_LLP)		+= spi-lm70llp.o | ||||||
|  |  obj-$(CONFIG_SPI_MPC512x_PSC)		+= spi-mpc512x-psc.o | ||||||
							
								
								
									
										373
									
								
								target/linux/generic/patches-4.1/862-gpio_spi_driver.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										373
									
								
								target/linux/generic/patches-4.1/862-gpio_spi_driver.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,373 @@ | |||||||
|  | THIS CODE IS DEPRECATED. | ||||||
|  |  | ||||||
|  | Please use the new mainline SPI-GPIO driver, as of 2.6.29. | ||||||
|  |  | ||||||
|  | --mb | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  drivers/spi/Kconfig              |    9 + | ||||||
|  |  drivers/spi/Makefile             |    1  | ||||||
|  |  drivers/spi/spi_gpio_old.c       |  251 +++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  include/linux/spi/spi_gpio_old.h |   73 +++++++++++ | ||||||
|  |  4 files changed, 334 insertions(+) | ||||||
|  |  | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/include/linux/spi/spi_gpio_old.h | ||||||
|  | @@ -0,0 +1,73 @@ | ||||||
|  | +/* | ||||||
|  | + * spi_gpio interface to platform code | ||||||
|  | + * | ||||||
|  | + * Copyright (c) 2008 Piotr Skamruk | ||||||
|  | + * Copyright (c) 2008 Michael Buesch | ||||||
|  | + * | ||||||
|  | + * 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; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * SPI_GPIO_PLATDEV_NAME - The platform device name string. | ||||||
|  | + * | ||||||
|  | + * The name string that has to be used for platform_device_alloc | ||||||
|  | + * when allocating a spi-gpio device. | ||||||
|  | + */ | ||||||
|  | +#define SPI_GPIO_PLATDEV_NAME	"spi-gpio" | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * spi_gpio_next_id - Get another platform device ID number. | ||||||
|  | + * | ||||||
|  | + * This returns the next platform device ID number that has to be used | ||||||
|  | + * for platform_device_alloc. The ID is opaque and should not be used for | ||||||
|  | + * anything else. | ||||||
|  | + */ | ||||||
|  | +int spi_gpio_next_id(void); | ||||||
|  | + | ||||||
|  | +#endif /* _LINUX_SPI_SPI_GPIO */ | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/spi/spi_gpio_old.c | ||||||
|  | @@ -0,0 +1,251 @@ | ||||||
|  | +/* | ||||||
|  | + * Bitbanging SPI bus driver using GPIO API | ||||||
|  | + * | ||||||
|  | + * Copyright (c) 2008 Piotr Skamruk | ||||||
|  | + * Copyright (c) 2008 Michael Buesch | ||||||
|  | + * | ||||||
|  | + * based on spi_s3c2410_gpio.c | ||||||
|  | + *   Copyright (c) 2006 Ben Dooks | ||||||
|  | + *   Copyright (c) 2006 Simtec Electronics | ||||||
|  | + * and on i2c-gpio.c | ||||||
|  | + *   Copyright (C) 2007 Atmel Corporation | ||||||
|  | + * | ||||||
|  | + * 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. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +#include <linux/kernel.h> | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/delay.h> | ||||||
|  | +#include <linux/spinlock.h> | ||||||
|  | +#include <linux/workqueue.h> | ||||||
|  | +#include <linux/module.h> | ||||||
|  | +#include <linux/platform_device.h> | ||||||
|  | +#include <linux/spi/spi.h> | ||||||
|  | +#include <linux/spi/spi_bitbang.h> | ||||||
|  | +#include <linux/spi/spi_gpio_old.h> | ||||||
|  | +#include <linux/gpio.h> | ||||||
|  | +#include <asm/atomic.h> | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +struct spi_gpio { | ||||||
|  | +	struct spi_bitbang bitbang; | ||||||
|  | +	struct spi_gpio_platform_data *info; | ||||||
|  | +	struct platform_device *pdev; | ||||||
|  | +	struct spi_board_info bi; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +static inline struct spi_gpio *spidev_to_sg(struct spi_device *dev) | ||||||
|  | +{ | ||||||
|  | +	return dev->controller_data; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static inline void setsck(struct spi_device *dev, int val) | ||||||
|  | +{ | ||||||
|  | +	struct spi_gpio *sp = spidev_to_sg(dev); | ||||||
|  | +	gpio_set_value(sp->info->pin_clk, val ? 1 : 0); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static inline void setmosi(struct spi_device *dev, int val) | ||||||
|  | +{ | ||||||
|  | +	struct spi_gpio *sp = spidev_to_sg(dev); | ||||||
|  | +	gpio_set_value(sp->info->pin_mosi, val ? 1 : 0); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static inline u32 getmiso(struct spi_device *dev) | ||||||
|  | +{ | ||||||
|  | +	struct spi_gpio *sp = spidev_to_sg(dev); | ||||||
|  | +	return gpio_get_value(sp->info->pin_miso) ? 1 : 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) | ||||||
|  | + | ||||||
|  | +#define EXPAND_BITBANG_TXRX | ||||||
|  | +#include "spi-bitbang-txrx.h" | ||||||
|  | + | ||||||
|  | +static u32 spi_gpio_txrx_mode0(struct spi_device *spi, | ||||||
|  | +			       unsigned nsecs, u32 word, u8 bits) | ||||||
|  | +{ | ||||||
|  | +	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static u32 spi_gpio_txrx_mode1(struct spi_device *spi, | ||||||
|  | +			       unsigned nsecs, u32 word, u8 bits) | ||||||
|  | +{ | ||||||
|  | +	return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static u32 spi_gpio_txrx_mode2(struct spi_device *spi, | ||||||
|  | +			       unsigned nsecs, u32 word, u8 bits) | ||||||
|  | +{ | ||||||
|  | +	return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static u32 spi_gpio_txrx_mode3(struct spi_device *spi, | ||||||
|  | +			       unsigned nsecs, u32 word, u8 bits) | ||||||
|  | +{ | ||||||
|  | +	return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void spi_gpio_chipselect(struct spi_device *dev, int on) | ||||||
|  | +{ | ||||||
|  | +	struct spi_gpio *sp = spidev_to_sg(dev); | ||||||
|  | + | ||||||
|  | +	if (sp->info->cs_activelow) | ||||||
|  | +		on = !on; | ||||||
|  | +	gpio_set_value(sp->info->pin_cs, on ? 1 : 0); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int spi_gpio_probe(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct spi_master *master; | ||||||
|  | +	struct spi_gpio_platform_data *pdata; | ||||||
|  | +	struct spi_gpio *sp; | ||||||
|  | +	struct spi_device *spidev; | ||||||
|  | +	int err; | ||||||
|  | + | ||||||
|  | +	pdata = pdev->dev.platform_data; | ||||||
|  | +	if (!pdata) | ||||||
|  | +		return -ENXIO; | ||||||
|  | + | ||||||
|  | +	err = -ENOMEM; | ||||||
|  | +	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_gpio)); | ||||||
|  | +	if (!master) | ||||||
|  | +		goto err_alloc_master; | ||||||
|  | + | ||||||
|  | +	sp = spi_master_get_devdata(master); | ||||||
|  | +	platform_set_drvdata(pdev, sp); | ||||||
|  | +	sp->info = pdata; | ||||||
|  | + | ||||||
|  | +	err = gpio_request(pdata->pin_clk, "spi_clock"); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_request_clk; | ||||||
|  | +	err = gpio_request(pdata->pin_mosi, "spi_mosi"); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_request_mosi; | ||||||
|  | +	err = gpio_request(pdata->pin_miso, "spi_miso"); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_request_miso; | ||||||
|  | +	err = gpio_request(pdata->pin_cs, "spi_cs"); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_request_cs; | ||||||
|  | + | ||||||
|  | +	sp->bitbang.master = spi_master_get(master); | ||||||
|  | +	sp->bitbang.master->bus_num = -1; | ||||||
|  | +	sp->bitbang.master->num_chipselect = 1; | ||||||
|  | +	sp->bitbang.chipselect = spi_gpio_chipselect; | ||||||
|  | +	sp->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_mode0; | ||||||
|  | +	sp->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_mode1; | ||||||
|  | +	sp->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_mode2; | ||||||
|  | +	sp->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_mode3; | ||||||
|  | + | ||||||
|  | +	gpio_direction_output(pdata->pin_clk, 0); | ||||||
|  | +	gpio_direction_output(pdata->pin_mosi, 0); | ||||||
|  | +	gpio_direction_output(pdata->pin_cs, | ||||||
|  | +			      pdata->cs_activelow ? 1 : 0); | ||||||
|  | +	gpio_direction_input(pdata->pin_miso); | ||||||
|  | + | ||||||
|  | +	err = spi_bitbang_start(&sp->bitbang); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_no_bitbang; | ||||||
|  | +	err = pdata->boardinfo_setup(&sp->bi, master, | ||||||
|  | +				     pdata->boardinfo_setup_data); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_bi_setup; | ||||||
|  | +	sp->bi.controller_data = sp; | ||||||
|  | +	spidev = spi_new_device(master, &sp->bi); | ||||||
|  | +	if (!spidev) | ||||||
|  | +		goto err_new_dev; | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | + | ||||||
|  | +err_new_dev: | ||||||
|  | +err_bi_setup: | ||||||
|  | +	spi_bitbang_stop(&sp->bitbang); | ||||||
|  | +err_no_bitbang: | ||||||
|  | +	spi_master_put(sp->bitbang.master); | ||||||
|  | +	gpio_free(pdata->pin_cs); | ||||||
|  | +err_request_cs: | ||||||
|  | +	gpio_free(pdata->pin_miso); | ||||||
|  | +err_request_miso: | ||||||
|  | +	gpio_free(pdata->pin_mosi); | ||||||
|  | +err_request_mosi: | ||||||
|  | +	gpio_free(pdata->pin_clk); | ||||||
|  | +err_request_clk: | ||||||
|  | +	kfree(master); | ||||||
|  | + | ||||||
|  | +err_alloc_master: | ||||||
|  | +	return err; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int spi_gpio_remove(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct spi_gpio *sp; | ||||||
|  | +	struct spi_gpio_platform_data *pdata; | ||||||
|  | + | ||||||
|  | +	pdata = pdev->dev.platform_data; | ||||||
|  | +	sp = platform_get_drvdata(pdev); | ||||||
|  | + | ||||||
|  | +	gpio_free(pdata->pin_clk); | ||||||
|  | +	gpio_free(pdata->pin_mosi); | ||||||
|  | +	gpio_free(pdata->pin_miso); | ||||||
|  | +	gpio_free(pdata->pin_cs); | ||||||
|  | +	spi_bitbang_stop(&sp->bitbang); | ||||||
|  | +	spi_master_put(sp->bitbang.master); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct platform_driver spi_gpio_driver = { | ||||||
|  | +	.driver		= { | ||||||
|  | +		.name	= SPI_GPIO_PLATDEV_NAME, | ||||||
|  | +		.owner	= THIS_MODULE, | ||||||
|  | +	}, | ||||||
|  | +	.probe		= spi_gpio_probe, | ||||||
|  | +	.remove		= spi_gpio_remove, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +int spi_gpio_next_id(void) | ||||||
|  | +{ | ||||||
|  | +	static atomic_t counter = ATOMIC_INIT(-1); | ||||||
|  | + | ||||||
|  | +	return atomic_inc_return(&counter); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(spi_gpio_next_id); | ||||||
|  | + | ||||||
|  | +static int __init spi_gpio_init(void) | ||||||
|  | +{ | ||||||
|  | +	int err; | ||||||
|  | + | ||||||
|  | +	err = platform_driver_register(&spi_gpio_driver); | ||||||
|  | +	if (err) | ||||||
|  | +		printk(KERN_ERR "spi-gpio: register failed: %d\n", err); | ||||||
|  | + | ||||||
|  | +	return err; | ||||||
|  | +} | ||||||
|  | +module_init(spi_gpio_init); | ||||||
|  | + | ||||||
|  | +static void __exit spi_gpio_exit(void) | ||||||
|  | +{ | ||||||
|  | +	platform_driver_unregister(&spi_gpio_driver); | ||||||
|  | +} | ||||||
|  | +module_exit(spi_gpio_exit); | ||||||
|  | + | ||||||
|  | +MODULE_AUTHOR("Piot Skamruk <piotr.skamruk at gmail.com>"); | ||||||
|  | +MODULE_AUTHOR("Michael Buesch"); | ||||||
|  | +MODULE_DESCRIPTION("Platform independent GPIO bitbanging SPI driver"); | ||||||
|  | +MODULE_LICENSE("GPL v2"); | ||||||
|  | --- a/drivers/spi/Kconfig | ||||||
|  | +++ b/drivers/spi/Kconfig | ||||||
|  | @@ -242,6 +242,15 @@ config SPI_IMG_SPFI | ||||||
|  |  	  This enables support for the SPFI master controller found on | ||||||
|  |  	  IMG SoCs. | ||||||
|  |   | ||||||
|  | +config SPI_GPIO_OLD | ||||||
|  | +	tristate "Old GPIO API based bitbanging SPI controller (DEPRECATED)" | ||||||
|  | +	depends on SPI_MASTER && GPIOLIB | ||||||
|  | +	select SPI_BITBANG | ||||||
|  | +	help | ||||||
|  | +	  This code is deprecated. Please use the new mainline SPI-GPIO driver. | ||||||
|  | + | ||||||
|  | +	  If unsure, say N. | ||||||
|  | + | ||||||
|  |  config SPI_IMX | ||||||
|  |  	tristate "Freescale i.MX SPI controllers" | ||||||
|  |  	depends on ARCH_MXC || COMPILE_TEST | ||||||
|  | --- a/drivers/spi/Makefile | ||||||
|  | +++ b/drivers/spi/Makefile | ||||||
|  | @@ -41,6 +41,7 @@ obj-$(CONFIG_SPI_FSL_LIB)		+= spi-fsl-li | ||||||
|  |  obj-$(CONFIG_SPI_FSL_ESPI)		+= spi-fsl-espi.o | ||||||
|  |  obj-$(CONFIG_SPI_FSL_SPI)		+= spi-fsl-spi.o | ||||||
|  |  obj-$(CONFIG_SPI_GPIO)			+= spi-gpio.o | ||||||
|  | +obj-$(CONFIG_SPI_GPIO_OLD)		+= spi_gpio_old.o | ||||||
|  |  obj-$(CONFIG_SPI_IMG_SPFI)		+= spi-img-spfi.o | ||||||
|  |  obj-$(CONFIG_SPI_IMX)			+= spi-imx.o | ||||||
|  |  obj-$(CONFIG_SPI_LM70_LLP)		+= spi-lm70llp.o | ||||||
							
								
								
									
										373
									
								
								target/linux/generic/patches-4.4/862-gpio_spi_driver.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										373
									
								
								target/linux/generic/patches-4.4/862-gpio_spi_driver.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,373 @@ | |||||||
|  | THIS CODE IS DEPRECATED. | ||||||
|  |  | ||||||
|  | Please use the new mainline SPI-GPIO driver, as of 2.6.29. | ||||||
|  |  | ||||||
|  | --mb | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  drivers/spi/Kconfig              |    9 + | ||||||
|  |  drivers/spi/Makefile             |    1  | ||||||
|  |  drivers/spi/spi_gpio_old.c       |  251 +++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  include/linux/spi/spi_gpio_old.h |   73 +++++++++++ | ||||||
|  |  4 files changed, 334 insertions(+) | ||||||
|  |  | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/include/linux/spi/spi_gpio_old.h | ||||||
|  | @@ -0,0 +1,73 @@ | ||||||
|  | +/* | ||||||
|  | + * spi_gpio interface to platform code | ||||||
|  | + * | ||||||
|  | + * Copyright (c) 2008 Piotr Skamruk | ||||||
|  | + * Copyright (c) 2008 Michael Buesch | ||||||
|  | + * | ||||||
|  | + * 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; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * SPI_GPIO_PLATDEV_NAME - The platform device name string. | ||||||
|  | + * | ||||||
|  | + * The name string that has to be used for platform_device_alloc | ||||||
|  | + * when allocating a spi-gpio device. | ||||||
|  | + */ | ||||||
|  | +#define SPI_GPIO_PLATDEV_NAME	"spi-gpio" | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * spi_gpio_next_id - Get another platform device ID number. | ||||||
|  | + * | ||||||
|  | + * This returns the next platform device ID number that has to be used | ||||||
|  | + * for platform_device_alloc. The ID is opaque and should not be used for | ||||||
|  | + * anything else. | ||||||
|  | + */ | ||||||
|  | +int spi_gpio_next_id(void); | ||||||
|  | + | ||||||
|  | +#endif /* _LINUX_SPI_SPI_GPIO */ | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/spi/spi_gpio_old.c | ||||||
|  | @@ -0,0 +1,251 @@ | ||||||
|  | +/* | ||||||
|  | + * Bitbanging SPI bus driver using GPIO API | ||||||
|  | + * | ||||||
|  | + * Copyright (c) 2008 Piotr Skamruk | ||||||
|  | + * Copyright (c) 2008 Michael Buesch | ||||||
|  | + * | ||||||
|  | + * based on spi_s3c2410_gpio.c | ||||||
|  | + *   Copyright (c) 2006 Ben Dooks | ||||||
|  | + *   Copyright (c) 2006 Simtec Electronics | ||||||
|  | + * and on i2c-gpio.c | ||||||
|  | + *   Copyright (C) 2007 Atmel Corporation | ||||||
|  | + * | ||||||
|  | + * 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. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +#include <linux/kernel.h> | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/delay.h> | ||||||
|  | +#include <linux/spinlock.h> | ||||||
|  | +#include <linux/workqueue.h> | ||||||
|  | +#include <linux/module.h> | ||||||
|  | +#include <linux/platform_device.h> | ||||||
|  | +#include <linux/spi/spi.h> | ||||||
|  | +#include <linux/spi/spi_bitbang.h> | ||||||
|  | +#include <linux/spi/spi_gpio_old.h> | ||||||
|  | +#include <linux/gpio.h> | ||||||
|  | +#include <asm/atomic.h> | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +struct spi_gpio { | ||||||
|  | +	struct spi_bitbang bitbang; | ||||||
|  | +	struct spi_gpio_platform_data *info; | ||||||
|  | +	struct platform_device *pdev; | ||||||
|  | +	struct spi_board_info bi; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +static inline struct spi_gpio *spidev_to_sg(struct spi_device *dev) | ||||||
|  | +{ | ||||||
|  | +	return dev->controller_data; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static inline void setsck(struct spi_device *dev, int val) | ||||||
|  | +{ | ||||||
|  | +	struct spi_gpio *sp = spidev_to_sg(dev); | ||||||
|  | +	gpio_set_value(sp->info->pin_clk, val ? 1 : 0); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static inline void setmosi(struct spi_device *dev, int val) | ||||||
|  | +{ | ||||||
|  | +	struct spi_gpio *sp = spidev_to_sg(dev); | ||||||
|  | +	gpio_set_value(sp->info->pin_mosi, val ? 1 : 0); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static inline u32 getmiso(struct spi_device *dev) | ||||||
|  | +{ | ||||||
|  | +	struct spi_gpio *sp = spidev_to_sg(dev); | ||||||
|  | +	return gpio_get_value(sp->info->pin_miso) ? 1 : 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) | ||||||
|  | + | ||||||
|  | +#define EXPAND_BITBANG_TXRX | ||||||
|  | +#include "spi-bitbang-txrx.h" | ||||||
|  | + | ||||||
|  | +static u32 spi_gpio_txrx_mode0(struct spi_device *spi, | ||||||
|  | +			       unsigned nsecs, u32 word, u8 bits) | ||||||
|  | +{ | ||||||
|  | +	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static u32 spi_gpio_txrx_mode1(struct spi_device *spi, | ||||||
|  | +			       unsigned nsecs, u32 word, u8 bits) | ||||||
|  | +{ | ||||||
|  | +	return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static u32 spi_gpio_txrx_mode2(struct spi_device *spi, | ||||||
|  | +			       unsigned nsecs, u32 word, u8 bits) | ||||||
|  | +{ | ||||||
|  | +	return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static u32 spi_gpio_txrx_mode3(struct spi_device *spi, | ||||||
|  | +			       unsigned nsecs, u32 word, u8 bits) | ||||||
|  | +{ | ||||||
|  | +	return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void spi_gpio_chipselect(struct spi_device *dev, int on) | ||||||
|  | +{ | ||||||
|  | +	struct spi_gpio *sp = spidev_to_sg(dev); | ||||||
|  | + | ||||||
|  | +	if (sp->info->cs_activelow) | ||||||
|  | +		on = !on; | ||||||
|  | +	gpio_set_value(sp->info->pin_cs, on ? 1 : 0); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int spi_gpio_probe(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct spi_master *master; | ||||||
|  | +	struct spi_gpio_platform_data *pdata; | ||||||
|  | +	struct spi_gpio *sp; | ||||||
|  | +	struct spi_device *spidev; | ||||||
|  | +	int err; | ||||||
|  | + | ||||||
|  | +	pdata = pdev->dev.platform_data; | ||||||
|  | +	if (!pdata) | ||||||
|  | +		return -ENXIO; | ||||||
|  | + | ||||||
|  | +	err = -ENOMEM; | ||||||
|  | +	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_gpio)); | ||||||
|  | +	if (!master) | ||||||
|  | +		goto err_alloc_master; | ||||||
|  | + | ||||||
|  | +	sp = spi_master_get_devdata(master); | ||||||
|  | +	platform_set_drvdata(pdev, sp); | ||||||
|  | +	sp->info = pdata; | ||||||
|  | + | ||||||
|  | +	err = gpio_request(pdata->pin_clk, "spi_clock"); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_request_clk; | ||||||
|  | +	err = gpio_request(pdata->pin_mosi, "spi_mosi"); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_request_mosi; | ||||||
|  | +	err = gpio_request(pdata->pin_miso, "spi_miso"); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_request_miso; | ||||||
|  | +	err = gpio_request(pdata->pin_cs, "spi_cs"); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_request_cs; | ||||||
|  | + | ||||||
|  | +	sp->bitbang.master = spi_master_get(master); | ||||||
|  | +	sp->bitbang.master->bus_num = -1; | ||||||
|  | +	sp->bitbang.master->num_chipselect = 1; | ||||||
|  | +	sp->bitbang.chipselect = spi_gpio_chipselect; | ||||||
|  | +	sp->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_mode0; | ||||||
|  | +	sp->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_mode1; | ||||||
|  | +	sp->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_mode2; | ||||||
|  | +	sp->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_mode3; | ||||||
|  | + | ||||||
|  | +	gpio_direction_output(pdata->pin_clk, 0); | ||||||
|  | +	gpio_direction_output(pdata->pin_mosi, 0); | ||||||
|  | +	gpio_direction_output(pdata->pin_cs, | ||||||
|  | +			      pdata->cs_activelow ? 1 : 0); | ||||||
|  | +	gpio_direction_input(pdata->pin_miso); | ||||||
|  | + | ||||||
|  | +	err = spi_bitbang_start(&sp->bitbang); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_no_bitbang; | ||||||
|  | +	err = pdata->boardinfo_setup(&sp->bi, master, | ||||||
|  | +				     pdata->boardinfo_setup_data); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_bi_setup; | ||||||
|  | +	sp->bi.controller_data = sp; | ||||||
|  | +	spidev = spi_new_device(master, &sp->bi); | ||||||
|  | +	if (!spidev) | ||||||
|  | +		goto err_new_dev; | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | + | ||||||
|  | +err_new_dev: | ||||||
|  | +err_bi_setup: | ||||||
|  | +	spi_bitbang_stop(&sp->bitbang); | ||||||
|  | +err_no_bitbang: | ||||||
|  | +	spi_master_put(sp->bitbang.master); | ||||||
|  | +	gpio_free(pdata->pin_cs); | ||||||
|  | +err_request_cs: | ||||||
|  | +	gpio_free(pdata->pin_miso); | ||||||
|  | +err_request_miso: | ||||||
|  | +	gpio_free(pdata->pin_mosi); | ||||||
|  | +err_request_mosi: | ||||||
|  | +	gpio_free(pdata->pin_clk); | ||||||
|  | +err_request_clk: | ||||||
|  | +	kfree(master); | ||||||
|  | + | ||||||
|  | +err_alloc_master: | ||||||
|  | +	return err; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int spi_gpio_remove(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct spi_gpio *sp; | ||||||
|  | +	struct spi_gpio_platform_data *pdata; | ||||||
|  | + | ||||||
|  | +	pdata = pdev->dev.platform_data; | ||||||
|  | +	sp = platform_get_drvdata(pdev); | ||||||
|  | + | ||||||
|  | +	gpio_free(pdata->pin_clk); | ||||||
|  | +	gpio_free(pdata->pin_mosi); | ||||||
|  | +	gpio_free(pdata->pin_miso); | ||||||
|  | +	gpio_free(pdata->pin_cs); | ||||||
|  | +	spi_bitbang_stop(&sp->bitbang); | ||||||
|  | +	spi_master_put(sp->bitbang.master); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct platform_driver spi_gpio_driver = { | ||||||
|  | +	.driver		= { | ||||||
|  | +		.name	= SPI_GPIO_PLATDEV_NAME, | ||||||
|  | +		.owner	= THIS_MODULE, | ||||||
|  | +	}, | ||||||
|  | +	.probe		= spi_gpio_probe, | ||||||
|  | +	.remove		= spi_gpio_remove, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +int spi_gpio_next_id(void) | ||||||
|  | +{ | ||||||
|  | +	static atomic_t counter = ATOMIC_INIT(-1); | ||||||
|  | + | ||||||
|  | +	return atomic_inc_return(&counter); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(spi_gpio_next_id); | ||||||
|  | + | ||||||
|  | +static int __init spi_gpio_init(void) | ||||||
|  | +{ | ||||||
|  | +	int err; | ||||||
|  | + | ||||||
|  | +	err = platform_driver_register(&spi_gpio_driver); | ||||||
|  | +	if (err) | ||||||
|  | +		printk(KERN_ERR "spi-gpio: register failed: %d\n", err); | ||||||
|  | + | ||||||
|  | +	return err; | ||||||
|  | +} | ||||||
|  | +module_init(spi_gpio_init); | ||||||
|  | + | ||||||
|  | +static void __exit spi_gpio_exit(void) | ||||||
|  | +{ | ||||||
|  | +	platform_driver_unregister(&spi_gpio_driver); | ||||||
|  | +} | ||||||
|  | +module_exit(spi_gpio_exit); | ||||||
|  | + | ||||||
|  | +MODULE_AUTHOR("Piot Skamruk <piotr.skamruk at gmail.com>"); | ||||||
|  | +MODULE_AUTHOR("Michael Buesch"); | ||||||
|  | +MODULE_DESCRIPTION("Platform independent GPIO bitbanging SPI driver"); | ||||||
|  | +MODULE_LICENSE("GPL v2"); | ||||||
|  | --- a/drivers/spi/Kconfig | ||||||
|  | +++ b/drivers/spi/Kconfig | ||||||
|  | @@ -254,6 +254,15 @@ config SPI_IMG_SPFI | ||||||
|  |  	  This enables support for the SPFI master controller found on | ||||||
|  |  	  IMG SoCs. | ||||||
|  |   | ||||||
|  | +config SPI_GPIO_OLD | ||||||
|  | +	tristate "Old GPIO API based bitbanging SPI controller (DEPRECATED)" | ||||||
|  | +	depends on SPI_MASTER && GPIOLIB | ||||||
|  | +	select SPI_BITBANG | ||||||
|  | +	help | ||||||
|  | +	  This code is deprecated. Please use the new mainline SPI-GPIO driver. | ||||||
|  | + | ||||||
|  | +	  If unsure, say N. | ||||||
|  | + | ||||||
|  |  config SPI_IMX | ||||||
|  |  	tristate "Freescale i.MX SPI controllers" | ||||||
|  |  	depends on ARCH_MXC || COMPILE_TEST | ||||||
|  | --- a/drivers/spi/Makefile | ||||||
|  | +++ b/drivers/spi/Makefile | ||||||
|  | @@ -42,6 +42,7 @@ obj-$(CONFIG_SPI_FSL_LIB)		+= spi-fsl-li | ||||||
|  |  obj-$(CONFIG_SPI_FSL_ESPI)		+= spi-fsl-espi.o | ||||||
|  |  obj-$(CONFIG_SPI_FSL_SPI)		+= spi-fsl-spi.o | ||||||
|  |  obj-$(CONFIG_SPI_GPIO)			+= spi-gpio.o | ||||||
|  | +obj-$(CONFIG_SPI_GPIO_OLD)		+= spi_gpio_old.o | ||||||
|  |  obj-$(CONFIG_SPI_IMG_SPFI)		+= spi-img-spfi.o | ||||||
|  |  obj-$(CONFIG_SPI_IMX)			+= spi-imx.o | ||||||
|  |  obj-$(CONFIG_SPI_LM70_LLP)		+= spi-lm70llp.o | ||||||
| @@ -13,7 +13,7 @@ Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> | |||||||
|  |  | ||||||
| --- a/drivers/spi/Kconfig | --- a/drivers/spi/Kconfig | ||||||
| +++ b/drivers/spi/Kconfig | +++ b/drivers/spi/Kconfig | ||||||
| @@ -346,6 +346,13 @@ config SPI_MT65XX | @@ -355,6 +355,13 @@ config SPI_MT65XX | ||||||
|  	  say Y or M here.If you are not sure, say N. |  	  say Y or M here.If you are not sure, say N. | ||||||
|  	  SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs. |  	  SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs. | ||||||
|   |   | ||||||
| @@ -29,8 +29,8 @@ Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> | |||||||
|  	depends on GPIOLIB || COMPILE_TEST |  	depends on GPIOLIB || COMPILE_TEST | ||||||
| --- a/drivers/spi/Makefile | --- a/drivers/spi/Makefile | ||||||
| +++ b/drivers/spi/Makefile | +++ b/drivers/spi/Makefile | ||||||
| @@ -44,6 +44,7 @@ obj-$(CONFIG_SPI_FSL_SPI)		+= spi-fsl-sp | @@ -45,6 +45,7 @@ obj-$(CONFIG_SPI_GPIO)			+= spi-gpio.o | ||||||
|  obj-$(CONFIG_SPI_GPIO)			+= spi-gpio.o |  obj-$(CONFIG_SPI_GPIO_OLD)		+= spi_gpio_old.o | ||||||
|  obj-$(CONFIG_SPI_IMG_SPFI)		+= spi-img-spfi.o |  obj-$(CONFIG_SPI_IMG_SPFI)		+= spi-img-spfi.o | ||||||
|  obj-$(CONFIG_SPI_IMX)			+= spi-imx.o |  obj-$(CONFIG_SPI_IMX)			+= spi-imx.o | ||||||
| +obj-$(CONFIG_SPI_LANTIQ)		+= spi-lantiq.o | +obj-$(CONFIG_SPI_LANTIQ)		+= spi-lantiq.o | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Felix Fietkau
					Felix Fietkau