summaryrefslogtreecommitdiff
path: root/target/linux/storm/patches/1100-gpio.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/storm/patches/1100-gpio.patch')
-rw-r--r--target/linux/storm/patches/1100-gpio.patch390
1 files changed, 390 insertions, 0 deletions
diff --git a/target/linux/storm/patches/1100-gpio.patch b/target/linux/storm/patches/1100-gpio.patch
new file mode 100644
index 0000000000..d2ea7279b0
--- /dev/null
+++ b/target/linux/storm/patches/1100-gpio.patch
@@ -0,0 +1,390 @@
+Index: linux-2.6.23.16/drivers/char/gemini_gpio_dev.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.23.16/drivers/char/gemini_gpio_dev.c 2008-03-15 17:05:28.382258620 +0200
+@@ -0,0 +1,356 @@
++/*
++ * GPIO driver for Gemini board
++ * Provides /dev/gpio
++ */
++
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/proc_fs.h>
++#include <linux/fcntl.h>
++#include <linux/miscdevice.h>
++#include <asm/uaccess.h> /* copy_to_user, copy_from_user */
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/arch/sl2312.h>
++#include <asm/arch/irqs.h>
++#include <asm/arch/gemini_gpio.h>
++
++#define GEMINI_GPIO_BASE1 IO_ADDRESS(SL2312_GPIO_BASE)
++#define GEMINI_GPIO_BASE2 IO_ADDRESS(SL2312_GPIO_BASE1)
++
++#define GPIO_SET 2
++#define MAX_GPIO_LINE 32*GPIO_SET
++
++wait_queue_head_t gemini_gpio_wait[MAX_GPIO_LINE];
++
++enum GPIO_REG
++{
++ GPIO_DATA_OUT = 0x00,
++ GPIO_DATA_IN = 0x04,
++ GPIO_PIN_DIR = 0x08,
++ GPIO_BY_PASS = 0x0C,
++ GPIO_DATA_SET = 0x10,
++ GPIO_DATA_CLEAR = 0x14,
++ GPIO_PULL_ENABLE = 0x18,
++ GPIO_PULL_TYPE = 0x1C,
++ GPIO_INT_ENABLE = 0x20,
++ GPIO_INT_RAW_STATUS = 0x24,
++ GPIO_INT_MASK_STATUS = 0x28,
++ GPIO_INT_MASK = 0x2C,
++ GPIO_INT_CLEAR = 0x30,
++ GPIO_INT_TRIG = 0x34,
++ GPIO_INT_BOTH = 0x38,
++ GPIO_INT_POLAR = 0x3C
++};
++
++unsigned int regist_gpio_int0=0,regist_gpio_int1=0;
++
++/* defines a specific GPIO bit number and state */
++struct gpio_bit {
++ unsigned char bit;
++ unsigned char state;
++};
++
++#define GPIO_MAJOR 10
++#define GPIO_MINOR 127
++
++/*
++ * ioctl calls that are permitted to the /dev/gpio interface
++ */
++#define GPIO_GET_BIT 0x0000001
++#define GPIO_SET_BIT 0x0000002
++#define GPIO_GET_CONFIG 0x0000003
++#define GPIO_SET_CONFIG 0x0000004
++
++//#define GPIO_CONFIG_OUT 1
++//#define GPIO_CONFIG_IN 2
++
++
++
++#define DEVICE_NAME "gpio"
++
++//#define DEBUG
++
++/*
++ * GPIO interface
++ */
++
++/* /dev/gpio */
++static int gpio_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg);
++
++/* /proc/driver/gpio */
++static int gpio_read_proc(char *page, char **start, off_t off,
++ int count, int *eof, void *data);
++
++static unsigned char gpio_status; /* bitmapped status byte. */
++
++/* functions for set/get gpio lines on storlink cpu */
++
++void gpio_line_get(unsigned char pin, u32 * data)
++{
++ unsigned int set = pin >>5; // each GPIO set has 32 pins
++ unsigned int status,addr;
++
++ addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1) + GPIO_DATA_IN;
++ status = readl(addr);
++#ifdef DEBUG
++ printk("status = %08X, pin = %d, set = %d\n", status, pin, set);
++#endif
++ if (set)
++ *data = (status&(1<<(pin-32)))?1:0;
++ else
++ *data = (status&(1<<pin))?1:0;
++}
++
++void gpio_line_set(unsigned char pin, u32 high)
++{
++ unsigned char set = pin >>5; // each GPIO set has 32 pins
++ unsigned int status=0,addr;
++
++ addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+(high?GPIO_DATA_SET:GPIO_DATA_CLEAR);
++
++ status &= ~(1 << (pin %32));
++ status |= (1 << (pin % 32));
++ writel(status,addr);
++}
++
++/*
++ * pin = [0..63]
++ * mode =
++ * 1 -- OUT
++ * 2 -- IN
++ */
++void gpio_line_config(unsigned char pin, unsigned char mode)
++{
++ unsigned char set = pin >>5; // each GPIO set has 32 pins
++ unsigned int status,addr;
++
++ addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+GPIO_PIN_DIR;
++ status = readl(addr);
++
++ status &= ~(1 << (pin %32));
++ if (mode == 1)
++ status |= (1 << (pin % 32)); /* PinDir: 0 - input, 1 - output */
++
++ writel(status,addr);
++#if 0
++ /* enable pullup-high if mode is input */
++
++ addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+GPIO_PULL_ENABLE;
++ status = readl(addr);
++
++ status &= ~(1 << (pin %32));
++ if (mode == 2) /* input */
++ status |= (1 << (pin % 32)); /* PullEnable: 0 - disable, 1 - enable */
++
++ writel(status,addr);
++
++ addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+GPIO_PULL_TYPE;
++ status = readl(addr);
++
++ status &= ~(1 << (pin %32));
++ if (mode == 2) /* input */
++ status |= (1 << (pin % 32)); /* PullType: 0 - low, 1 - high */
++
++ writel(status,addr);
++#endif
++}
++
++#define GPIO_IS_OPEN 0x01 /* means /dev/gpio is in use */
++
++/*
++ * Now all the various file operations that we export.
++ */
++static int gpio_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ struct gpio_bit bit;
++ u32 val;
++
++ if (copy_from_user(&bit, (struct gpio_bit *)arg,
++ sizeof(bit)))
++ return -EFAULT;
++
++ switch (cmd) {
++
++ case GPIO_GET_BIT:
++ gpio_line_get(bit.bit, &val);
++ bit.state = val;
++ return copy_to_user((void *)arg, &bit, sizeof(bit)) ? -EFAULT : 0;
++ case GPIO_SET_BIT:
++ val = bit.state;
++ gpio_line_set(bit.bit, val);
++ return 0;
++ case GPIO_GET_CONFIG:
++ // gpio_line_config(bit.bit, bit.state);
++ return copy_to_user((void *)arg, &bit, sizeof(bit)) ? -EFAULT : 0;
++ case GPIO_SET_CONFIG:
++ val = bit.state;
++ gpio_line_config(bit.bit, bit.state);
++ return 0;
++ }
++ return -EINVAL;
++}
++
++
++static int gpio_open(struct inode *inode, struct file *file)
++{
++ if (gpio_status & GPIO_IS_OPEN)
++ return -EBUSY;
++
++ gpio_status |= GPIO_IS_OPEN;
++ return 0;
++}
++
++
++static int gpio_release(struct inode *inode, struct file *file)
++{
++ /*
++ * Turn off all interrupts once the device is no longer
++ * in use and clear the data.
++ */
++
++ gpio_status &= ~GPIO_IS_OPEN;
++ return 0;
++}
++
++
++/*
++ * The various file operations we support.
++ */
++
++static struct file_operations gpio_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = gpio_ioctl,
++ .open = gpio_open,
++ .release = gpio_release,
++};
++
++static struct miscdevice gpio_dev =
++{
++ .minor = GPIO_MINOR,
++ .name = "gpio",
++ .fops = &gpio_fops,
++};
++
++
++
++
++#ifdef CONFIG_PROC_FS
++static struct proc_dir_entry *dir;
++
++/*
++ * Info exported via "/proc/driver/gpio".
++ */
++static int gpio_get_status(char *buf)
++{
++ char *p = buf;
++ u32 val = 0;
++ int i;
++ int bit;
++#ifdef DEBUG
++ u32 addr;
++
++ for (i = 0; i < 0x20; i+=4 ) {
++ addr = IO_ADDRESS(SL2312_GPIO_BASE) + i;
++ val = readl(addr);
++ p+=sprintf(p, "GPIO0: 0x%02X: %08X\n", i, val );
++ }
++ for (i = 0; i < 0x20; i+=4 ) {
++ addr = IO_ADDRESS(SL2312_GPIO_BASE1) + i;
++ val = readl(addr);
++ p+=sprintf(p, "GPIO1: 0x%02X: %08X\n", i, val );
++ }
++#endif
++
++ for (i = 0; i < 32; i++) {
++ gpio_line_get(i, &bit);
++ if (bit)
++ val |= (1 << i);
++ }
++ p += sprintf(p, "gpio0\t: 0x%08x\n", val);
++
++ val = 0;
++ for (i = 32; i < 64; i++) {
++ gpio_line_get(i, &bit);
++ if (bit)
++ val |= (1 << i);
++ }
++ p += sprintf(p, "gpio1\t: 0x%08x\n", val);
++
++ return p - buf;
++}
++
++
++/* /proc/driver/gpio read op
++ */
++static int gpio_read_proc(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ int len = gpio_get_status (page);
++
++ if (len <= off+count)
++ *eof = 1;
++ *start = page + off;
++ len -= off;
++ if ( len > count )
++ len = count;
++ if ( len < 0 )
++ len = 0;
++ return len;
++}
++#endif /* CONFIG_PROC_FS */
++
++
++static int __init gpio_init_module(void)
++{
++ int retval;
++#ifdef CONFIG_PROC_FS
++ struct proc_dir_entry *res;
++#endif
++
++ /* register /dev/gpio file ops */
++ //retval = register_chrdev(GPIO_MAJOR, DEVICE_NAME, &gpio_fops);
++ retval = misc_register(&gpio_dev);
++ if(retval < 0)
++ return retval;
++
++#ifdef CONFIG_PROC_FS
++ dir = proc_mkdir("driver/gpio", NULL);
++ if (!dir) {
++ misc_deregister(&gpio_dev);
++ return -ENOMEM;
++ }
++ /* register /proc/driver/gpio */
++ res = create_proc_entry("info", 0644, dir);
++ if (res) {
++ res->read_proc= gpio_read_proc;
++ } else {
++ misc_deregister(&gpio_dev);
++ return -ENOMEM;
++ }
++#endif
++
++ printk("%s: GPIO driver loaded\n", __FILE__);
++
++ return 0;
++}
++
++static void __exit gpio_cleanup_module(void)
++{
++ remove_proc_entry ("info", dir);
++ misc_deregister(&gpio_dev);
++
++ printk("%s: GPIO driver unloaded\n", __FILE__);
++}
++
++module_init(gpio_init_module);
++module_exit(gpio_cleanup_module);
++
++MODULE_AUTHOR("Jonas Majauskas");
++MODULE_LICENSE("GPL");
++
+Index: linux-2.6.23.16/drivers/char/Kconfig
+===================================================================
+--- linux-2.6.23.16.orig/drivers/char/Kconfig 2008-03-13 17:45:54.000221290 +0200
++++ linux-2.6.23.16/drivers/char/Kconfig 2008-03-15 17:05:09.381175866 +0200
+@@ -1064,5 +1064,12 @@
+
+ source "drivers/s390/char/Kconfig"
+
++config GEMINI_GPIO_DEV
++ tristate "GPIO driver for Gemini board (provides /dev/gpio)"
++ depends on ARCH_SL2312
++ default n
++ help
++ GPIO driver for Gemini boards - SL3512, SL3516.
++
+ endmenu
+
+Index: linux-2.6.23.16/drivers/char/Makefile
+===================================================================
+--- linux-2.6.23.16.orig/drivers/char/Makefile 2008-03-15 17:04:35.879266660 +0200
++++ linux-2.6.23.16/drivers/char/Makefile 2008-03-15 17:05:09.381175866 +0200
+@@ -115,6 +115,7 @@
+
+ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
+ obj-$(CONFIG_TCG_TPM) += tpm/
++obj-$(CONFIG_GEMINI_GPIO_DEV) += gemini_gpio_dev.o
+
+ obj-$(CONFIG_PS3_FLASH) += ps3flash.o
+