1 Index: linux-2.6.23.16/drivers/char/gemini_gpio_dev.c
2 ===================================================================
3 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4 +++ linux-2.6.23.16/drivers/char/gemini_gpio_dev.c 2008-03-15 17:05:28.382258620 +0200
7 + * GPIO driver for Gemini board
11 +#include <linux/version.h>
12 +#include <linux/kernel.h>
13 +#include <linux/module.h>
14 +#include <linux/init.h>
15 +#include <linux/proc_fs.h>
16 +#include <linux/fcntl.h>
17 +#include <linux/miscdevice.h>
18 +#include <asm/uaccess.h> /* copy_to_user, copy_from_user */
20 +#include <asm/hardware.h>
22 +#include <asm/arch/sl2312.h>
23 +#include <asm/arch/irqs.h>
24 +#include <asm/arch/gemini_gpio.h>
26 +#define GEMINI_GPIO_BASE1 IO_ADDRESS(SL2312_GPIO_BASE)
27 +#define GEMINI_GPIO_BASE2 IO_ADDRESS(SL2312_GPIO_BASE1)
30 +#define MAX_GPIO_LINE 32*GPIO_SET
32 +wait_queue_head_t gemini_gpio_wait[MAX_GPIO_LINE];
36 + GPIO_DATA_OUT = 0x00,
37 + GPIO_DATA_IN = 0x04,
38 + GPIO_PIN_DIR = 0x08,
39 + GPIO_BY_PASS = 0x0C,
40 + GPIO_DATA_SET = 0x10,
41 + GPIO_DATA_CLEAR = 0x14,
42 + GPIO_PULL_ENABLE = 0x18,
43 + GPIO_PULL_TYPE = 0x1C,
44 + GPIO_INT_ENABLE = 0x20,
45 + GPIO_INT_RAW_STATUS = 0x24,
46 + GPIO_INT_MASK_STATUS = 0x28,
47 + GPIO_INT_MASK = 0x2C,
48 + GPIO_INT_CLEAR = 0x30,
49 + GPIO_INT_TRIG = 0x34,
50 + GPIO_INT_BOTH = 0x38,
51 + GPIO_INT_POLAR = 0x3C
54 +unsigned int regist_gpio_int0=0,regist_gpio_int1=0;
56 +/* defines a specific GPIO bit number and state */
59 + unsigned char state;
62 +#define GPIO_MAJOR 10
63 +#define GPIO_MINOR 127
66 + * ioctl calls that are permitted to the /dev/gpio interface
68 +#define GPIO_GET_BIT 0x0000001
69 +#define GPIO_SET_BIT 0x0000002
70 +#define GPIO_GET_CONFIG 0x0000003
71 +#define GPIO_SET_CONFIG 0x0000004
73 +//#define GPIO_CONFIG_OUT 1
74 +//#define GPIO_CONFIG_IN 2
78 +#define DEVICE_NAME "gpio"
87 +static int gpio_ioctl(struct inode *inode, struct file *file,
88 + unsigned int cmd, unsigned long arg);
90 +/* /proc/driver/gpio */
91 +static int gpio_read_proc(char *page, char **start, off_t off,
92 + int count, int *eof, void *data);
94 +static unsigned char gpio_status; /* bitmapped status byte. */
96 +/* functions for set/get gpio lines on storlink cpu */
98 +void gpio_line_get(unsigned char pin, u32 * data)
100 + unsigned int set = pin >>5; // each GPIO set has 32 pins
101 + unsigned int status,addr;
103 + addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1) + GPIO_DATA_IN;
104 + status = readl(addr);
106 + printk("status = %08X, pin = %d, set = %d\n", status, pin, set);
109 + *data = (status&(1<<(pin-32)))?1:0;
111 + *data = (status&(1<<pin))?1:0;
114 +void gpio_line_set(unsigned char pin, u32 high)
116 + unsigned char set = pin >>5; // each GPIO set has 32 pins
117 + unsigned int status=0,addr;
119 + addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+(high?GPIO_DATA_SET:GPIO_DATA_CLEAR);
121 + status &= ~(1 << (pin %32));
122 + status |= (1 << (pin % 32));
123 + writel(status,addr);
132 +void gpio_line_config(unsigned char pin, unsigned char mode)
134 + unsigned char set = pin >>5; // each GPIO set has 32 pins
135 + unsigned int status,addr;
137 + addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+GPIO_PIN_DIR;
138 + status = readl(addr);
140 + status &= ~(1 << (pin %32));
142 + status |= (1 << (pin % 32)); /* PinDir: 0 - input, 1 - output */
144 + writel(status,addr);
146 + /* enable pullup-high if mode is input */
148 + addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+GPIO_PULL_ENABLE;
149 + status = readl(addr);
151 + status &= ~(1 << (pin %32));
152 + if (mode == 2) /* input */
153 + status |= (1 << (pin % 32)); /* PullEnable: 0 - disable, 1 - enable */
155 + writel(status,addr);
157 + addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+GPIO_PULL_TYPE;
158 + status = readl(addr);
160 + status &= ~(1 << (pin %32));
161 + if (mode == 2) /* input */
162 + status |= (1 << (pin % 32)); /* PullType: 0 - low, 1 - high */
164 + writel(status,addr);
168 +#define GPIO_IS_OPEN 0x01 /* means /dev/gpio is in use */
171 + * Now all the various file operations that we export.
173 +static int gpio_ioctl(struct inode *inode, struct file *file,
174 + unsigned int cmd, unsigned long arg)
176 + struct gpio_bit bit;
179 + if (copy_from_user(&bit, (struct gpio_bit *)arg,
186 + gpio_line_get(bit.bit, &val);
188 + return copy_to_user((void *)arg, &bit, sizeof(bit)) ? -EFAULT : 0;
191 + gpio_line_set(bit.bit, val);
193 + case GPIO_GET_CONFIG:
194 + // gpio_line_config(bit.bit, bit.state);
195 + return copy_to_user((void *)arg, &bit, sizeof(bit)) ? -EFAULT : 0;
196 + case GPIO_SET_CONFIG:
198 + gpio_line_config(bit.bit, bit.state);
205 +static int gpio_open(struct inode *inode, struct file *file)
207 + if (gpio_status & GPIO_IS_OPEN)
210 + gpio_status |= GPIO_IS_OPEN;
215 +static int gpio_release(struct inode *inode, struct file *file)
218 + * Turn off all interrupts once the device is no longer
219 + * in use and clear the data.
222 + gpio_status &= ~GPIO_IS_OPEN;
228 + * The various file operations we support.
231 +static struct file_operations gpio_fops = {
232 + .owner = THIS_MODULE,
233 + .ioctl = gpio_ioctl,
235 + .release = gpio_release,
238 +static struct miscdevice gpio_dev =
240 + .minor = GPIO_MINOR,
242 + .fops = &gpio_fops,
248 +#ifdef CONFIG_PROC_FS
249 +static struct proc_dir_entry *dir;
252 + * Info exported via "/proc/driver/gpio".
254 +static int gpio_get_status(char *buf)
263 + for (i = 0; i < 0x20; i+=4 ) {
264 + addr = IO_ADDRESS(SL2312_GPIO_BASE) + i;
266 + p+=sprintf(p, "GPIO0: 0x%02X: %08X\n", i, val );
268 + for (i = 0; i < 0x20; i+=4 ) {
269 + addr = IO_ADDRESS(SL2312_GPIO_BASE1) + i;
271 + p+=sprintf(p, "GPIO1: 0x%02X: %08X\n", i, val );
275 + for (i = 0; i < 32; i++) {
276 + gpio_line_get(i, &bit);
280 + p += sprintf(p, "gpio0\t: 0x%08x\n", val);
283 + for (i = 32; i < 64; i++) {
284 + gpio_line_get(i, &bit);
288 + p += sprintf(p, "gpio1\t: 0x%08x\n", val);
294 +/* /proc/driver/gpio read op
296 +static int gpio_read_proc(char *page, char **start, off_t off,
297 + int count, int *eof, void *data)
299 + int len = gpio_get_status (page);
301 + if (len <= off+count)
303 + *start = page + off;
311 +#endif /* CONFIG_PROC_FS */
314 +static int __init gpio_init_module(void)
317 +#ifdef CONFIG_PROC_FS
318 + struct proc_dir_entry *res;
321 + /* register /dev/gpio file ops */
322 + //retval = register_chrdev(GPIO_MAJOR, DEVICE_NAME, &gpio_fops);
323 + retval = misc_register(&gpio_dev);
327 +#ifdef CONFIG_PROC_FS
328 + dir = proc_mkdir("driver/gpio", NULL);
330 + misc_deregister(&gpio_dev);
333 + /* register /proc/driver/gpio */
334 + res = create_proc_entry("info", 0644, dir);
336 + res->read_proc= gpio_read_proc;
338 + misc_deregister(&gpio_dev);
343 + printk("%s: GPIO driver loaded\n", __FILE__);
348 +static void __exit gpio_cleanup_module(void)
350 + remove_proc_entry ("info", dir);
351 + misc_deregister(&gpio_dev);
353 + printk("%s: GPIO driver unloaded\n", __FILE__);
356 +module_init(gpio_init_module);
357 +module_exit(gpio_cleanup_module);
359 +MODULE_AUTHOR("Jonas Majauskas");
360 +MODULE_LICENSE("GPL");
362 Index: linux-2.6.23.16/drivers/char/Kconfig
363 ===================================================================
364 --- linux-2.6.23.16.orig/drivers/char/Kconfig 2008-03-13 17:45:54.000221290 +0200
365 +++ linux-2.6.23.16/drivers/char/Kconfig 2008-03-15 17:05:09.381175866 +0200
366 @@ -1064,5 +1064,12 @@
368 source "drivers/s390/char/Kconfig"
370 +config GEMINI_GPIO_DEV
371 + tristate "GPIO driver for Gemini board (provides /dev/gpio)"
372 + depends on ARCH_SL2312
375 + GPIO driver for Gemini boards - SL3512, SL3516.
379 Index: linux-2.6.23.16/drivers/char/Makefile
380 ===================================================================
381 --- linux-2.6.23.16.orig/drivers/char/Makefile 2008-03-15 17:04:35.879266660 +0200
382 +++ linux-2.6.23.16/drivers/char/Makefile 2008-03-15 17:05:09.381175866 +0200
385 obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
386 obj-$(CONFIG_TCG_TPM) += tpm/
387 +obj-$(CONFIG_GEMINI_GPIO_DEV) += gemini_gpio_dev.o
389 obj-$(CONFIG_PS3_FLASH) += ps3flash.o