diff options
| -rw-r--r-- | target/linux/at91-2.6/config/default | 1 | ||||
| -rw-r--r-- | target/linux/at91-2.6/patches/003-gpio-driver.patch | 357 | 
2 files changed, 358 insertions, 0 deletions
| diff --git a/target/linux/at91-2.6/config/default b/target/linux/at91-2.6/config/default index cfcfe54a7..05e6f7c38 100644 --- a/target/linux/at91-2.6/config/default +++ b/target/linux/at91-2.6/config/default @@ -42,6 +42,7 @@ CONFIG_ARM_THUMB=y  # CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set  CONFIG_AT91_SPI=y  CONFIG_AT91_SPIDEV=y +CONFIG_AT91_VLIO=y  # CONFIG_ATM_DUMMY is not set  # CONFIG_ATM_TCP is not set  CONFIG_BASE_SMALL=0 diff --git a/target/linux/at91-2.6/patches/003-gpio-driver.patch b/target/linux/at91-2.6/patches/003-gpio-driver.patch new file mode 100644 index 000000000..c14542acc --- /dev/null +++ b/target/linux/at91-2.6/patches/003-gpio-driver.patch @@ -0,0 +1,357 @@ +diff -urN linux-2.6.19.2.old/arch/arm/mach-at91rm9200/gpio.c linux-2.6.19.2/arch/arm/mach-at91rm9200/gpio.c +--- linux-2.6.19.2.old/arch/arm/mach-at91rm9200/gpio.c	2007-03-06 22:49:37.000000000 +0100 ++++ linux-2.6.19.2/arch/arm/mach-at91rm9200/gpio.c	2007-03-07 10:25:41.000000000 +0100 +@@ -28,7 +28,7 @@ +  + static struct at91_gpio_bank *gpio; + static int gpio_banks; +- ++static u32 pio_gpio_pin[4] = { 0, 0, 0, 0 }; +  + static inline void __iomem *pin_to_controller(unsigned pin) + { +@@ -113,10 +113,13 @@ + { + 	void __iomem	*pio = pin_to_controller(pin); + 	unsigned	mask = pin_to_mask(pin); ++	int bank = (pin - PIN_BASE) / 32; +  + 	if (!pio) + 		return -EINVAL; +  ++	pio_gpio_pin[bank] |= mask; ++ + 	__raw_writel(mask, pio + PIO_IDR); + 	__raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); + 	__raw_writel(mask, pio + PIO_ODR); +@@ -134,10 +137,13 @@ + { + 	void __iomem	*pio = pin_to_controller(pin); + 	unsigned	mask = pin_to_mask(pin); ++	int bank = (pin - PIN_BASE) / 32; +  + 	if (!pio) + 		return -EINVAL; +  ++	pio_gpio_pin[bank] |= mask; ++ + 	__raw_writel(mask, pio + PIO_IDR); + 	__raw_writel(mask, pio + PIO_PUDR); + 	__raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR)); +@@ -214,6 +220,18 @@ + } + EXPORT_SYMBOL(at91_get_gpio_value); +  ++int at91_is_pin_gpio(unsigned pin) ++{ ++  void __iomem  *pio = pin_to_controller(pin); ++  unsigned  mask = pin_to_mask(pin); ++  int     bank = (pin - PIN_BASE) / 32; ++ ++  if (!pio) ++    return -EINVAL; ++  return (pio_gpio_pin[bank] & mask) != 0; ++} ++EXPORT_SYMBOL(at91_is_pin_gpio); ++ + /*--------------------------------------------------------------------------*/ +  + #ifdef CONFIG_PM +diff -urN linux-2.6.19.2.old/drivers/char/Kconfig linux-2.6.19.2/drivers/char/Kconfig +--- linux-2.6.19.2.old/drivers/char/Kconfig	2007-03-06 22:49:37.000000000 +0100 ++++ linux-2.6.19.2/drivers/char/Kconfig	2007-03-07 01:08:57.000000000 +0100 +@@ -1064,5 +1064,12 @@ + 	  The SPI driver gives user mode access to this serial + 	  bus on the AT91RM9200 processor. +  ++config AT91_VLIO ++  tristate "Versalink LED and GPIO interface" ++  depends on ARCH_AT91RM9200 && MACH_VLINK ++  default n ++  help ++    Provides a handler for LED and GPIO in userspace ++ + endmenu +  +diff -urN linux-2.6.19.2.old/drivers/char/Makefile linux-2.6.19.2/drivers/char/Makefile +--- linux-2.6.19.2.old/drivers/char/Makefile	2007-03-06 22:49:37.000000000 +0100 ++++ linux-2.6.19.2/drivers/char/Makefile	2007-03-07 01:08:05.000000000 +0100 +@@ -92,6 +92,7 @@ + obj-$(CONFIG_TELCLOCK)		+= tlclk.o + obj-$(CONFIG_AT91_SPI)		+= at91_spi.o + obj-$(CONFIG_AT91_SPIDEV)	+= at91_spidev.o ++obj-$(CONFIG_AT91_VLIO)	+= vlink_giu.o +  + obj-$(CONFIG_WATCHDOG)		+= watchdog/ + obj-$(CONFIG_MWAVE)		+= mwave/ +diff -urN linux-2.6.19.2.old/drivers/char/vlink_giu.c linux-2.6.19.2/drivers/char/vlink_giu.c +--- linux-2.6.19.2.old/drivers/char/vlink_giu.c	1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.19.2/drivers/char/vlink_giu.c	2007-03-07 01:21:21.000000000 +0100 +@@ -0,0 +1,256 @@ ++/* ++ *  Driver for FDL Versalink GPIO ++ * ++ *  Copyright (C) 2005 Guthrie Consulting ++ *	Author: Hamish Guthrie <hamish@prodigi.ch> ++ * ++ *  This program is free software; you can redistribute it and/or modify ++ *  it under the terms of the GNU General Public License as published by ++ *  the Free Software Foundation; either version 2 of the License, or ++ *  (at your option) any later version. ++ * ++ *  This program is distributed in the hope that it will be useful, ++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of ++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the ++ *  GNU General Public License for more details. ++ * ++ *  You should have received a copy of the GNU General Public License ++ *  along with this program; if not, write to the Free Software ++ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA ++ */ ++ ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/init.h> ++#include <linux/platform_device.h> ++ ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/fs.h> ++#include <linux/errno.h> ++#include <linux/init.h> ++#include <linux/types.h> ++#include <linux/proc_fs.h> ++#include <linux/fcntl.h> ++#include <linux/seq_file.h> ++#include <linux/cdev.h> ++#include <asm/arch/gpio.h> ++#include <asm/uaccess.h> ++ ++static int major;	/* default is dynamic major device number */ ++module_param(major, int, 0); ++MODULE_PARM_DESC(major, "Major device number"); ++ ++#define VIO_NR_DEVS 96 ++ ++struct vio_dev { ++	struct cdev cdev; ++}; ++ ++struct vio_dev *vio_devices; ++static struct class *vio_class; ++ ++static ssize_t gpio_read(struct file *file, char __user *buf, size_t len, ++                         loff_t *ppos) ++{ ++	unsigned int pin; ++	int retval; ++	char value = '0'; ++ ++	pin = iminor(file->f_dentry->d_inode); ++ ++	retval = at91_get_gpio_value(PIN_BASE + pin); ++	if (retval < 0) ++		return -EFAULT; ++ ++	value = retval + 0x30; ++	if (put_user(value, buf)) ++		return -EFAULT; ++ ++	return 1; ++} ++ ++static ssize_t gpio_write(struct file *file, const char __user *data, ++                          size_t len, loff_t *ppos) ++{ ++	unsigned int pin; ++	size_t i; ++	char c; ++	int retval = 0; ++ ++	pin = iminor(file->f_dentry->d_inode); ++ ++	for (i = 0; i < len; i++) { ++		if (get_user(c, data + i)) ++			return -EFAULT; ++ ++		switch (c) { ++		case '0': ++		case '1': ++			retval = at91_set_gpio_value(PIN_BASE + pin, (int)c - 0x30); ++			if (retval < 0) ++				return -EFAULT; ++			break; ++		default: ++			break; ++		} ++ ++		if (retval < 0) ++			break; ++	} ++ ++	return i; ++} ++ ++static int gpio_open(struct inode *inode, struct file *file) ++{ ++	return nonseekable_open(inode, file); ++} ++ ++static int gpio_release(struct inode *inode, struct file *file) ++{ ++	return 0; ++} ++ ++static struct file_operations vio_fops = { ++	.owner		= THIS_MODULE, ++	.read		= gpio_read, ++	.write		= gpio_write, ++	.open		= gpio_open, ++	.release	= gpio_release, ++}; ++ ++static void vio_setup_cdev(struct vio_dev *dev, int index) ++{ ++	int err, devno = MKDEV(major, index); ++ ++	cdev_init(&dev->cdev, &vio_fops); ++	dev->cdev.owner = THIS_MODULE; ++	dev->cdev.ops = &vio_fops; ++	err = cdev_add (&dev->cdev, devno, 1); ++	if (err) ++		printk(KERN_NOTICE "vio: Error %d adding vio%d", err, index); ++} ++ ++static int vio_remove(struct platform_device *dev) ++{ ++	int i; ++	dev_t devno = MKDEV(major, 0); ++ ++	if (vio_devices) { ++		for(i=0; i<VIO_NR_DEVS; i++) { ++			int iodev = at91_is_pin_gpio(PIN_BASE + i); ++			if (iodev) { ++				cdev_del(&vio_devices[i].cdev); ++				class_device_destroy(vio_class, MKDEV(major, i)); ++			} ++		} ++		kfree(vio_devices); ++	} ++ ++	class_destroy(vio_class); ++	unregister_chrdev_region(devno, VIO_NR_DEVS); ++ ++	platform_set_drvdata(dev, NULL); ++ ++	return 0; ++} ++ ++static int vio_probe(struct platform_device *dev) ++{ ++	int retval, i, j; ++	dev_t vdev = 0; ++ ++	if (major) { ++		vdev = MKDEV(major, 0); ++		retval = register_chrdev_region(vdev, VIO_NR_DEVS, "vio"); ++	} else { ++		retval = alloc_chrdev_region(&vdev, 0, VIO_NR_DEVS, "vio"); ++		major = MAJOR(vdev); ++	} ++	if (retval < 0) { ++		printk(KERN_WARNING "vio: can't get major %d\n", major); ++		return retval; ++	} ++ ++	if (major == 0) { ++		major = retval; ++		printk(KERN_INFO "vio: major number %d\n", major); ++	} ++ ++	vio_class = class_create(THIS_MODULE, "vio"); ++ ++	if (IS_ERR(vio_class)) { ++		printk(KERN_ERR "vio: Error creating vio class\n"); ++		vio_remove(dev); ++		return PTR_ERR(vio_class); ++	} ++ ++	vio_devices = kmalloc(VIO_NR_DEVS * sizeof(struct vio_dev), GFP_KERNEL); ++	if (!vio_devices) { ++		retval = -ENOMEM; ++		goto fail; ++	} ++	memset(vio_devices, 0, VIO_NR_DEVS * sizeof(struct vio_dev)); ++ ++	for (i=0; i<VIO_NR_DEVS/32; i++) ++		for(j=0; j<32; j++) { ++			int iodev = at91_is_pin_gpio(PIN_BASE + i*32 + j); ++			if (iodev) { ++				vio_setup_cdev(&vio_devices[i*32 + j], i*32 + j); ++				class_device_create(vio_class, NULL, MKDEV(major, i*32 + j), NULL, ++					"vio%c%d", i + 'A', j); ++			} ++		} ++ ++	platform_set_drvdata(dev, vio_devices); ++ ++	return 0; ++ ++fail: ++	vio_remove(dev); ++	return retval; ++} ++ ++static struct platform_device *vio_platform_device; ++ ++static struct platform_driver vio_driver = { ++	.probe 		= vio_probe, ++	.remove		= vio_remove, ++	.driver		= { ++		.name	= "vio", ++		.owner	= THIS_MODULE, ++	}, ++}; ++ ++static int __init vio_init(void) ++{ ++	int retval; ++ ++	vio_platform_device = platform_device_register_simple("vio", -1, NULL, 0); ++	if (IS_ERR(vio_platform_device)) { ++		printk(KERN_WARNING "vio: device registration failed\n"); ++		return PTR_ERR(vio_platform_device); ++	} ++ ++	retval = platform_driver_register(&vio_driver); ++	if (retval < 0) { ++		printk(KERN_WARNING "vio: driver registration failed\n"); ++		platform_device_unregister(vio_platform_device); ++	} ++	 ++	return retval; ++} ++ ++static void __exit vio_exit(void) ++{ ++	platform_driver_unregister(&vio_driver); ++	platform_device_unregister(vio_platform_device); ++} ++ ++module_init(vio_init); ++module_exit(vio_exit); ++ ++MODULE_AUTHOR("Hamish Guthrie <hamish@prodigi.ch>"); ++MODULE_DESCRIPTION("FDL Versalink GPIO Driver"); ++MODULE_LICENSE("GPL"); +diff -urN linux-2.6.19.2.old/include/asm-arm/arch-at91rm9200/gpio.h linux-2.6.19.2/include/asm-arm/arch-at91rm9200/gpio.h +--- linux-2.6.19.2.old/include/asm-arm/arch-at91rm9200/gpio.h	2007-01-10 20:10:37.000000000 +0100 ++++ linux-2.6.19.2/include/asm-arm/arch-at91rm9200/gpio.h	2007-03-07 01:17:23.000000000 +0100 +@@ -189,6 +189,7 @@ + /* callable at any time */ + extern int at91_set_gpio_value(unsigned pin, int value); + extern int at91_get_gpio_value(unsigned pin); ++extern int at91_is_pin_gpio(unsigned pin); +  + /* callable only from core power-management code */ + extern void at91_gpio_suspend(void); | 
