diff options
| author | mirko <mirko@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-08-22 12:46:12 +0000 | 
|---|---|---|
| committer | mirko <mirko@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-08-22 12:46:12 +0000 | 
| commit | c3fd35e7800ae1f2dd3fa42ade850c948e4b18ea (patch) | |
| tree | f2e9f1150816b597adc38a4ca8a7a5f14a0909e5 /target/linux/generic-2.6/patches-2.6.31/921-gpio_spi_driver.patch | |
| parent | f48e79cafe9d99bc741c905cb8328cc54cb75f6d (diff) | |
add generic patchset levelled up to 2.6.31-rc6
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@17351 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/generic-2.6/patches-2.6.31/921-gpio_spi_driver.patch')
| -rw-r--r-- | target/linux/generic-2.6/patches-2.6.31/921-gpio_spi_driver.patch | 366 | 
1 files changed, 366 insertions, 0 deletions
diff --git a/target/linux/generic-2.6/patches-2.6.31/921-gpio_spi_driver.patch b/target/linux/generic-2.6/patches-2.6.31/921-gpio_spi_driver.patch new file mode 100644 index 000000000..90e40e705 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.31/921-gpio_spi_driver.patch @@ -0,0 +1,366 @@ +THIS CODE IS DEPRECATED. + +Please use the new mainline SPI-GPIO driver, as of 2.6.29. + +--mb + + + +--- /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 <linux/spi/spi_bitbang.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, 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, 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, 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, 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 __devexit 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		= __devexit_p(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 +@@ -116,6 +116,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 && GENERIC_GPIO ++	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 iMX SPI controller" + 	depends on ARCH_MX1 && EXPERIMENTAL +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_BITBANG)		+= spi_bitban + obj-$(CONFIG_SPI_AU1550)		+= au1550_spi.o + obj-$(CONFIG_SPI_BUTTERFLY)		+= spi_butterfly.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_PXA2XX)		+= pxa2xx_spi.o  | 
