add preliminary support for Storm SL3512 based devices, not ready yet
[librecmc/librecmc.git] / target / linux / storm / patches / 1100-gpio.patch
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
5 @@ -0,0 +1,356 @@
6 +/*
7 + *     GPIO driver for Gemini board
8 + *     Provides /dev/gpio
9 + */
10 +
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 */
19 +
20 +#include <asm/hardware.h>
21 +#include <asm/io.h>
22 +#include <asm/arch/sl2312.h>
23 +#include <asm/arch/irqs.h>
24 +#include <asm/arch/gemini_gpio.h>
25 +
26 +#define GEMINI_GPIO_BASE1              IO_ADDRESS(SL2312_GPIO_BASE)
27 +#define GEMINI_GPIO_BASE2              IO_ADDRESS(SL2312_GPIO_BASE1)
28 +
29 +#define GPIO_SET       2
30 +#define MAX_GPIO_LINE  32*GPIO_SET
31 +
32 +wait_queue_head_t gemini_gpio_wait[MAX_GPIO_LINE];
33 +
34 +enum GPIO_REG
35 +{
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
52 +};
53 +
54 +unsigned int regist_gpio_int0=0,regist_gpio_int1=0;
55 +
56 +/* defines a specific GPIO bit number and state */
57 +struct gpio_bit {
58 +       unsigned char bit;
59 +       unsigned char state;
60 +};
61 +
62 +#define GPIO_MAJOR    10
63 +#define GPIO_MINOR    127
64 +
65 +/*
66 + * ioctl calls that are permitted to the /dev/gpio interface
67 + */
68 +#define GPIO_GET_BIT   0x0000001
69 +#define GPIO_SET_BIT   0x0000002
70 +#define GPIO_GET_CONFIG        0x0000003
71 +#define GPIO_SET_CONFIG 0x0000004
72 +
73 +//#define GPIO_CONFIG_OUT  1
74 +//#define GPIO_CONFIG_IN   2
75 +
76 +
77 +
78 +#define DEVICE_NAME "gpio"
79 +
80 +//#define DEBUG
81 +
82 +/*
83 + * GPIO interface
84 + */
85 +
86 +/* /dev/gpio */
87 +static int gpio_ioctl(struct inode *inode, struct file *file,
88 +                     unsigned int cmd, unsigned long arg);
89 +
90 +/* /proc/driver/gpio */
91 +static int gpio_read_proc(char *page, char **start, off_t off,
92 +                         int count, int *eof, void *data);
93 +
94 +static unsigned char gpio_status;        /* bitmapped status byte.       */
95 +
96 +/* functions for set/get gpio lines on storlink cpu */
97 +
98 +void gpio_line_get(unsigned char pin, u32 * data)
99 +{
100 +       unsigned int set = pin >>5;             // each GPIO set has 32 pins
101 +       unsigned int status,addr;
102 +
103 +       addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1) + GPIO_DATA_IN;
104 +       status = readl(addr);
105 +#ifdef DEBUG
106 +       printk("status = %08X, pin = %d, set = %d\n", status, pin, set);
107 +#endif
108 +       if (set)
109 +                       *data = (status&(1<<(pin-32)))?1:0;
110 +       else
111 +                       *data = (status&(1<<pin))?1:0;
112 +}
113 +
114 +void gpio_line_set(unsigned char pin, u32 high)
115 +{
116 +       unsigned char set = pin >>5;            // each GPIO set has 32 pins
117 +       unsigned int status=0,addr;
118 +
119 +       addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+(high?GPIO_DATA_SET:GPIO_DATA_CLEAR);
120 +
121 +       status &= ~(1 << (pin %32));
122 +       status |= (1 << (pin % 32));
123 +       writel(status,addr);
124 +}
125 +
126 +/*
127 + * pin = [0..63]
128 + * mode =
129 + *                     1 -- OUT
130 + *                     2 -- IN
131 + */
132 +void gpio_line_config(unsigned char pin, unsigned char mode)
133 +{
134 +       unsigned char set = pin >>5;            // each GPIO set has 32 pins
135 +       unsigned int status,addr;
136 +
137 +       addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+GPIO_PIN_DIR;
138 +       status = readl(addr);
139 +
140 +       status &= ~(1 << (pin %32));
141 +       if (mode == 1)
142 +                       status |= (1 << (pin % 32)); /* PinDir: 0 - input, 1 - output */
143 +
144 +       writel(status,addr);
145 +#if 0
146 +       /* enable pullup-high if mode is input */
147 +
148 +       addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+GPIO_PULL_ENABLE;
149 +       status = readl(addr);
150 +
151 +       status &= ~(1 << (pin %32));
152 +       if (mode == 2) /* input */
153 +                       status |= (1 << (pin % 32)); /* PullEnable: 0 - disable, 1 - enable */
154 +
155 +       writel(status,addr);
156 +
157 +       addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+GPIO_PULL_TYPE;
158 +       status = readl(addr);
159 +
160 +       status &= ~(1 << (pin %32));
161 +       if (mode == 2) /* input */
162 +                       status |= (1 << (pin % 32)); /* PullType: 0 - low, 1 - high */
163 +
164 +       writel(status,addr);
165 +#endif
166 +}
167 +
168 +#define GPIO_IS_OPEN             0x01    /* means /dev/gpio is in use     */
169 +
170 +/*
171 + *      Now all the various file operations that we export.
172 + */
173 +static int gpio_ioctl(struct inode *inode, struct file *file,
174 +                         unsigned int cmd, unsigned long arg)
175 +{
176 +               struct gpio_bit bit;
177 +               u32 val;
178 +
179 +               if (copy_from_user(&bit, (struct gpio_bit *)arg,
180 +                                                               sizeof(bit)))
181 +                               return -EFAULT;
182 +
183 +               switch (cmd) {
184 +
185 +                               case GPIO_GET_BIT:
186 +                                               gpio_line_get(bit.bit, &val);
187 +                                               bit.state = val;
188 +                                               return copy_to_user((void *)arg, &bit, sizeof(bit)) ? -EFAULT : 0;
189 +                               case GPIO_SET_BIT:
190 +                                               val = bit.state;
191 +                                               gpio_line_set(bit.bit, val);
192 +                                               return 0;
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:
197 +                                               val = bit.state;
198 +                                               gpio_line_config(bit.bit, bit.state);
199 +                                               return 0;
200 +               }
201 +               return -EINVAL;
202 +}
203 +
204 +
205 +static int gpio_open(struct inode *inode, struct file *file)
206 +{
207 +        if (gpio_status & GPIO_IS_OPEN)
208 +                return -EBUSY;
209 +
210 +        gpio_status |= GPIO_IS_OPEN;
211 +        return 0;
212 +}
213 +
214 +
215 +static int gpio_release(struct inode *inode, struct file *file)
216 +{
217 +        /*
218 +         * Turn off all interrupts once the device is no longer
219 +         * in use and clear the data.
220 +         */
221 +
222 +        gpio_status &= ~GPIO_IS_OPEN;
223 +        return 0;
224 +}
225 +
226 +
227 +/*
228 + *      The various file operations we support.
229 + */
230 +
231 +static struct file_operations gpio_fops = {
232 +        .owner          = THIS_MODULE,
233 +        .ioctl          = gpio_ioctl,
234 +        .open           = gpio_open,
235 +        .release        = gpio_release,
236 +};
237 +
238 +static struct miscdevice gpio_dev =
239 +{
240 +        .minor          = GPIO_MINOR,
241 +        .name           = "gpio",
242 +        .fops           = &gpio_fops,
243 +};
244 +
245 +
246 +
247 +
248 +#ifdef CONFIG_PROC_FS
249 +static struct proc_dir_entry *dir;
250 +
251 +/*
252 + *      Info exported via "/proc/driver/gpio".
253 + */
254 +static int gpio_get_status(char *buf)
255 +{
256 +    char *p = buf;
257 +       u32 val = 0;
258 +       int i;
259 +       int bit;
260 +#ifdef DEBUG
261 +       u32 addr;
262 +
263 +       for (i = 0; i < 0x20; i+=4 ) {
264 +                       addr = IO_ADDRESS(SL2312_GPIO_BASE) + i;
265 +                       val = readl(addr);
266 +                       p+=sprintf(p, "GPIO0: 0x%02X: %08X\n", i, val );
267 +       }
268 +       for (i = 0; i < 0x20; i+=4 ) {
269 +                       addr = IO_ADDRESS(SL2312_GPIO_BASE1) + i;
270 +                       val = readl(addr);
271 +                       p+=sprintf(p, "GPIO1: 0x%02X: %08X\n", i, val );
272 +       }
273 +#endif
274 +
275 +       for (i = 0; i < 32; i++) {
276 +                       gpio_line_get(i, &bit);
277 +                       if (bit)
278 +                                       val |= (1 << i);
279 +       }
280 +       p += sprintf(p, "gpio0\t: 0x%08x\n", val);
281 +
282 +       val = 0;
283 +       for (i = 32; i < 64; i++) {
284 +                       gpio_line_get(i, &bit);
285 +                       if (bit)
286 +                                       val |= (1 << i);
287 +       }
288 +       p += sprintf(p, "gpio1\t: 0x%08x\n", val);
289 +
290 +       return p - buf;
291 +}
292 +
293 +
294 +/* /proc/driver/gpio read op
295 + */
296 +static int gpio_read_proc(char *page, char **start, off_t off,
297 +                             int count, int *eof, void *data)
298 +{
299 +        int len = gpio_get_status (page);
300 +
301 +        if (len <= off+count)
302 +                       *eof = 1;
303 +        *start = page + off;
304 +        len -= off;
305 +        if ( len > count )
306 +                       len = count;
307 +        if ( len < 0 )
308 +                       len = 0;
309 +        return len;
310 +}
311 +#endif /* CONFIG_PROC_FS */
312 +
313 +
314 +static int __init gpio_init_module(void)
315 +{
316 +        int retval;
317 +#ifdef CONFIG_PROC_FS
318 +       struct proc_dir_entry *res;
319 +#endif
320 +
321 +        /* register /dev/gpio file ops */
322 +       //retval = register_chrdev(GPIO_MAJOR, DEVICE_NAME, &gpio_fops);
323 +       retval = misc_register(&gpio_dev);
324 +        if(retval < 0)
325 +                return retval;
326 +
327 +#ifdef CONFIG_PROC_FS
328 +       dir = proc_mkdir("driver/gpio", NULL);
329 +       if (!dir) {
330 +               misc_deregister(&gpio_dev);
331 +               return -ENOMEM;
332 +       }
333 +        /* register /proc/driver/gpio */
334 +       res = create_proc_entry("info", 0644, dir);
335 +       if (res) {
336 +               res->read_proc= gpio_read_proc;
337 +       } else {
338 +               misc_deregister(&gpio_dev);
339 +               return -ENOMEM;
340 +       }
341 +#endif
342 +
343 +       printk("%s: GPIO driver loaded\n", __FILE__);
344 +
345 +       return 0;
346 +}
347 +
348 +static void __exit gpio_cleanup_module(void)
349 +{
350 +       remove_proc_entry ("info", dir);
351 +        misc_deregister(&gpio_dev);
352 +
353 +       printk("%s: GPIO driver unloaded\n", __FILE__);
354 +}
355 +
356 +module_init(gpio_init_module);
357 +module_exit(gpio_cleanup_module);
358 +
359 +MODULE_AUTHOR("Jonas Majauskas");
360 +MODULE_LICENSE("GPL");
361 +
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 @@
367  
368  source "drivers/s390/char/Kconfig"
369  
370 +config GEMINI_GPIO_DEV
371 +       tristate "GPIO driver for Gemini board (provides /dev/gpio)"
372 +       depends on ARCH_SL2312
373 +       default n
374 +       help
375 +         GPIO driver for Gemini boards - SL3512, SL3516.
376 +
377  endmenu
378  
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
383 @@ -115,6 +115,7 @@
384  
385  obj-$(CONFIG_HANGCHECK_TIMER)  += hangcheck-timer.o
386  obj-$(CONFIG_TCG_TPM)          += tpm/
387 +obj-$(CONFIG_GEMINI_GPIO_DEV)          += gemini_gpio_dev.o
388  
389  obj-$(CONFIG_PS3_FLASH)                += ps3flash.o
390