~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/cris/arch-v10/drivers/gpio.c

Version: ~ [ linux-5.8 ] ~ [ linux-5.7.12 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.55 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.136 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.191 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.232 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.232 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* $Id: gpio.c,v 1.8 2003/07/04 08:27:37 starvik Exp $
  2  *
  3  * Etrax general port I/O device
  4  *
  5  * Copyright (c) 1999, 2000, 2001, 2002 Axis Communications AB
  6  *
  7  * Authors:    Bjorn Wesen      (initial version)
  8  *             Ola Knutsson     (LED handling)
  9  *             Johan Adolfsson  (read/set directions, write, port G)
 10  *
 11  * $Log: gpio.c,v $
 12  * Revision 1.8  2003/07/04 08:27:37  starvik
 13  * Merge of Linux 2.5.74
 14  *
 15  * Revision 1.7  2003/01/10 07:44:07  starvik
 16  * init_ioremap is now called by kernel before drivers are initialized
 17  *
 18  * Revision 1.6  2002/12/11 13:13:57  starvik
 19  * Added arch/ to v10 specific includes
 20  * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
 21  *
 22  * Revision 1.5  2002/11/20 11:56:11  starvik
 23  * Merge of Linux 2.5.48
 24  *
 25  * Revision 1.4  2002/11/18 10:10:05  starvik
 26  * Linux 2.5 port of latest gpio.c from Linux 2.4
 27  *
 28  * Revision 1.20  2002/10/16 21:16:24  johana
 29  * Added support for PA high level interrupt.
 30  * That gives 2ms response time with iodtest for high levels and 2-12 ms
 31  * response time on low levels if the check is not made in
 32  * process.c:cpu_idle() as well.
 33  *
 34  * Revision 1.19  2002/10/14 18:27:33  johana
 35  * Implemented alarm handling so select() now works.
 36  * Latency is around 6-9 ms with a etrax_gpio_wake_up_check() in
 37  * cpu_idle().
 38  * Otherwise I get 15-18 ms (same as doing the poll in userspace -
 39  * but less overhead).
 40  * TODO? Perhaps we should add the check in IMMEDIATE_BH (or whatever it
 41  * is in 2.4) as well?
 42  * TODO? Perhaps call request_irq()/free_irq() only when needed?
 43  * Increased version to 2.5
 44  *
 45  * Revision 1.18  2002/10/11 15:02:00  johana
 46  * Mask inverted 8 bit value in setget_input().
 47  *
 48  * Revision 1.17  2002/06/17 15:53:01  johana
 49  * Added IO_READ_INBITS, IO_READ_OUTBITS, IO_SETGET_INPUT and IO_SETGET_OUTPUT
 50  * that take a pointer as argument and thus can handle 32 bit ports (G)
 51  * correctly.
 52  * These should be used instead of IO_READBITS, IO_SETINPUT and IO_SETOUTPUT.
 53  * (especially if Port G bit 31 is used)
 54  *
 55  * Revision 1.16  2002/06/17 09:59:51  johana
 56  * Returning 32 bit values in the ioctl return value doesn't work if bit
 57  * 31 is set (could happen for port G), so mask it of with 0x7FFFFFFF.
 58  * A new set of ioctl's will be added.
 59  *
 60  * Revision 1.15  2002/05/06 13:19:13  johana
 61  * IO_SETINPUT returns mask with bit set = inputs for PA and PB as well.
 62  *
 63  * Revision 1.14  2002/04/12 12:01:53  johana
 64  * Use global r_port_g_data_shadow.
 65  * Moved gpio_init_port_g() closer to gpio_init() and marked it __init.
 66  *
 67  * Revision 1.13  2002/04/10 12:03:55  johana
 68  * Added support for port G /dev/gpiog (minor 3).
 69  * Changed indentation on switch cases.
 70  * Fixed other spaces to tabs.
 71  *
 72  * Revision 1.12  2001/11/12 19:42:15  pkj
 73  * * Corrected return values from gpio_leds_ioctl().
 74  * * Fixed compiler warnings.
 75  *
 76  * Revision 1.11  2001/10/30 14:39:12  johana
 77  * Added D() around gpio_write printk.
 78  *
 79  * Revision 1.10  2001/10/25 10:24:42  johana
 80  * Added IO_CFG_WRITE_MODE ioctl and write method that can do fast
 81  * bittoggling in the kernel. (This speeds up programming an FPGA with 450kB
 82  * from ~60 seconds to 4 seconds).
 83  * Added save_flags/cli/restore_flags in ioctl.
 84  *
 85  * Revision 1.9  2001/05/04 14:16:07  matsfg
 86  * Corrected spelling error
 87  *
 88  * Revision 1.8  2001/04/27 13:55:26  matsfg
 89  * Moved initioremap.
 90  * Turns off all LEDS on init.
 91  * Added support for shutdown and powerbutton.
 92  *
 93  * Revision 1.7  2001/04/04 13:30:08  matsfg
 94  * Added bitset and bitclear for leds. Calls init_ioremap to set up memmapping
 95  *
 96  * Revision 1.6  2001/03/26 16:03:06  bjornw
 97  * Needs linux/config.h
 98  *
 99  * Revision 1.5  2001/03/26 14:22:03  bjornw
100  * Namechange of some config options
101  *
102  * Revision 1.4  2001/02/27 13:52:48  bjornw
103  * malloc.h -> slab.h
104  *
105  * Revision 1.3  2001/01/24 15:06:48  bjornw
106  * gpio_wq correct type
107  *
108  * Revision 1.2  2001/01/18 16:07:30  bjornw
109  * 2.4 port
110  *
111  * Revision 1.1  2001/01/18 15:55:16  bjornw
112  * Verbatim copy of etraxgpio.c from elinux 2.0 added
113  *
114  *
115  */
116 
117 #include <linux/config.h>
118 
119 #include <linux/module.h>
120 #include <linux/sched.h>
121 #include <linux/slab.h>
122 #include <linux/ioport.h>
123 #include <linux/errno.h>
124 #include <linux/kernel.h>
125 #include <linux/fs.h>
126 #include <linux/string.h>
127 #include <linux/poll.h>
128 #include <linux/init.h>
129 #include <linux/interrupt.h>
130 
131 #include <asm/etraxgpio.h>
132 #include <asm/arch/svinto.h>
133 #include <asm/io.h>
134 #include <asm/system.h>
135 #include <asm/irq.h>
136 
137 #define GPIO_MAJOR 120  /* experimental MAJOR number */
138 
139 #define D(x)
140 
141 #if 0
142 static int dp_cnt;
143 #define DP(x) do { dp_cnt++; if (dp_cnt % 1000 == 0) x; }while(0)
144 #else
145 #define DP(x)
146 #endif
147         
148 static char gpio_name[] = "etrax gpio";
149 
150 #if 0
151 static wait_queue_head_t *gpio_wq;
152 #endif
153 
154 static int gpio_ioctl(struct inode *inode, struct file *file,
155                       unsigned int cmd, unsigned long arg);
156 static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
157                           loff_t *off);
158 static int gpio_open(struct inode *inode, struct file *filp);
159 static int gpio_release(struct inode *inode, struct file *filp);
160 static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait);
161 
162 /* private data per open() of this driver */
163 
164 struct gpio_private {
165         struct gpio_private *next;
166         /* These fields are for PA and PB only */
167         volatile unsigned char *port, *shadow;
168         volatile unsigned char *dir, *dir_shadow;
169         unsigned char changeable_dir;
170         unsigned char changeable_bits;
171         unsigned char clk_mask;
172         unsigned char data_mask;
173         unsigned char write_msb;
174         unsigned char pad1, pad2, pad3;
175         /* These fields are generic */
176         unsigned long highalarm, lowalarm;
177         wait_queue_head_t alarm_wq;
178         int minor;
179 };
180 
181 /* linked list of alarms to check for */
182 
183 static struct gpio_private *alarmlist = 0;
184 
185 static int gpio_some_alarms = 0; /* Set if someone uses alarm */
186 
187 /* Port A and B use 8 bit access, but Port G is 32 bit */
188 #define NUM_PORTS (GPIO_MINOR_B+1)
189 
190 static volatile unsigned char *ports[NUM_PORTS] = { 
191         R_PORT_PA_DATA, 
192         R_PORT_PB_DATA,
193 };
194 static volatile unsigned char *shads[NUM_PORTS] = {
195         &port_pa_data_shadow, 
196         &port_pb_data_shadow
197 };
198 
199 /* What direction bits that are user changeable 1=changeable*/
200 #ifndef CONFIG_ETRAX_PA_CHANGEABLE_DIR
201 #define CONFIG_ETRAX_PA_CHANGEABLE_DIR 0x00
202 #endif
203 #ifndef CONFIG_ETRAX_PB_CHANGEABLE_DIR
204 #define CONFIG_ETRAX_PB_CHANGEABLE_DIR 0x00
205 #endif
206 
207 #ifndef CONFIG_ETRAX_PA_CHANGEABLE_BITS
208 #define CONFIG_ETRAX_PA_CHANGEABLE_BITS 0xFF
209 #endif
210 #ifndef CONFIG_ETRAX_PB_CHANGEABLE_BITS
211 #define CONFIG_ETRAX_PB_CHANGEABLE_BITS 0xFF
212 #endif
213 
214 
215 static unsigned char changeable_dir[NUM_PORTS] = { 
216         CONFIG_ETRAX_PA_CHANGEABLE_DIR,
217         CONFIG_ETRAX_PB_CHANGEABLE_DIR 
218 };
219 static unsigned char changeable_bits[NUM_PORTS] = { 
220         CONFIG_ETRAX_PA_CHANGEABLE_BITS,
221         CONFIG_ETRAX_PB_CHANGEABLE_BITS 
222 };
223 
224 static volatile unsigned char *dir[NUM_PORTS] = { 
225         R_PORT_PA_DIR, 
226         R_PORT_PB_DIR 
227 };
228 
229 static volatile unsigned char *dir_shadow[NUM_PORTS] = {
230         &port_pa_dir_shadow, 
231         &port_pb_dir_shadow 
232 };
233 
234 /* Port G is 32 bit, handle it special, some bits are both inputs 
235    and outputs at the same time, only some of the bits can change direction
236    and some of them in groups of 8 bit. */
237 static unsigned long changeable_dir_g;
238 static unsigned long dir_g_in_bits;
239 static unsigned long dir_g_out_bits;
240 static unsigned long dir_g_shadow; /* 1=output */
241 
242 #define USE_PORTS(priv) ((priv)->minor <= GPIO_MINOR_B)
243 
244 
245 
246 static unsigned int 
247 gpio_poll(struct file *file,
248           poll_table *wait)
249 {
250         unsigned int mask = 0;
251         struct gpio_private *priv = (struct gpio_private *)file->private_data;
252         unsigned long data;
253         poll_wait(file, &priv->alarm_wq, wait);
254         if (priv->minor == GPIO_MINOR_A) {
255                 unsigned long tmp;
256                 data = *R_PORT_PA_DATA;
257                 /* PA has support for high level interrupt -
258                  * lets activate for those low and with highalarm set
259                  */
260                 tmp = ~data & priv->highalarm & 0xFF;
261                 *R_IRQ_MASK1_SET = (tmp << R_IRQ_MASK1_SET__pa0__BITNR);
262         } else if (priv->minor == GPIO_MINOR_B)
263                 data = *R_PORT_PB_DATA;
264         else if (priv->minor == GPIO_MINOR_G)
265                 data = *R_PORT_G_DATA;
266         else
267                 return 0;
268         
269         if ((data & priv->highalarm) ||
270             (~data & priv->lowalarm)) {
271                 mask = POLLIN|POLLRDNORM;
272         }
273         
274         DP(printk("gpio_poll ready: mask 0x%08X\n", mask));
275         return mask;
276 }
277 
278 int etrax_gpio_wake_up_check(void)
279 {
280         struct gpio_private *priv = alarmlist;
281         unsigned long data = 0;
282         int ret = 0;
283         while (priv) {
284                 if (USE_PORTS(priv)) {
285                         data = *priv->port;
286                 } else if (priv->minor == GPIO_MINOR_G) {
287                         data = *R_PORT_G_DATA;
288                 }
289                 if ((data & priv->highalarm) ||
290                     (~data & priv->lowalarm)) {
291                         DP(printk("etrax_gpio_wake_up_check %i\n",priv->minor));
292                         wake_up_interruptible(&priv->alarm_wq);
293                         ret = 1;
294                 }
295                 priv = priv->next;
296         }
297         return ret;
298 }
299 
300 static irqreturn_t
301 gpio_poll_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
302 {
303         if (gpio_some_alarms) {
304                 etrax_gpio_wake_up_check();
305                 return IRQ_HANDLED;
306         }
307         return IRQ_NONE;
308 }
309 
310 static irqreturn_t
311 gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
312 {
313         unsigned long tmp;
314         /* Find what PA interrupts are active */
315         tmp = (*R_IRQ_READ1 >> R_IRQ_READ1__pa0__BITNR) & 0xFF;
316         /* Clear them.. */
317         /* NOTE: Maybe we need to be more careful here if some other
318          * driver uses PA interrupt as well?
319          */
320         *R_IRQ_MASK1_CLR = (tmp << R_IRQ_MASK1_CLR__pa0__BITNR);
321         if (gpio_some_alarms) {
322                 return IRQ_RETVAL(etrax_gpio_wake_up_check());
323         }
324         return IRQ_NONE;
325 }
326 
327 
328 static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
329                           loff_t *off)
330 {
331         struct gpio_private *priv = (struct gpio_private *)file->private_data;
332         unsigned char data, clk_mask, data_mask, write_msb;
333         unsigned long flags;
334         ssize_t retval = count;
335         if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) {
336                 return -EFAULT;
337         }
338     
339         if (verify_area(VERIFY_READ, buf, count)) {
340                 return -EFAULT;
341         }
342         clk_mask = priv->clk_mask;
343         data_mask = priv->data_mask;
344         /* It must have been configured using the IO_CFG_WRITE_MODE */
345         /* Perhaps a better error code? */
346         if (clk_mask == 0 || data_mask == 0) {
347                 return -EPERM;
348         }
349         write_msb = priv->write_msb;
350         D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb));
351         while (count--) {
352                 int i;
353                 data = *buf++;
354                 if (priv->write_msb) {
355                         for (i = 7; i >= 0;i--) {
356                                 local_irq_save(flags); local_irq_disable();
357                                 *priv->port = *priv->shadow &= ~clk_mask;
358                                 if (data & 1<<i)
359                                         *priv->port = *priv->shadow |= data_mask;
360                                 else
361                                         *priv->port = *priv->shadow &= ~data_mask;
362                         /* For FPGA: min 5.0ns (DCC) before CCLK high */
363                                 *priv->port = *priv->shadow |= clk_mask;
364                                 local_irq_restore(flags);
365                         }
366                 } else {
367                         for (i = 0; i <= 7;i++) {
368                                 local_irq_save(flags); local_irq_disable();
369                                 *priv->port = *priv->shadow &= ~clk_mask;
370                                 if (data & 1<<i)
371                                         *priv->port = *priv->shadow |= data_mask;
372                                 else
373                                         *priv->port = *priv->shadow &= ~data_mask;
374                         /* For FPGA: min 5.0ns (DCC) before CCLK high */
375                                 *priv->port = *priv->shadow |= clk_mask;
376                                 local_irq_restore(flags);
377                         }
378                 }
379         }
380         return retval;
381 }
382 
383 
384 
385 static int
386 gpio_open(struct inode *inode, struct file *filp)
387 {
388         struct gpio_private *priv;
389         int p = iminor(inode);
390 
391         if (p > GPIO_MINOR_LAST)
392                 return -EINVAL;
393 
394         priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private), 
395                                               GFP_KERNEL);
396 
397         if (!priv)
398                 return -ENOMEM;
399 
400         priv->minor = p;
401 
402         /* initialize the io/alarm struct and link it into our alarmlist */
403 
404         priv->next = alarmlist;
405         alarmlist = priv;
406         if (USE_PORTS(priv)) { /* A and B */
407                 priv->port = ports[p];
408                 priv->shadow = shads[p];
409                 priv->dir = dir[p];
410                 priv->dir_shadow = dir_shadow[p];
411                 priv->changeable_dir = changeable_dir[p];
412                 priv->changeable_bits = changeable_bits[p];
413         } else {
414                 priv->port = NULL;
415                 priv->shadow = NULL;
416                 priv->dir = NULL;
417                 priv->dir_shadow = NULL;
418                 priv->changeable_dir = 0;
419                 priv->changeable_bits = 0;
420         }
421 
422         priv->highalarm = 0;
423         priv->lowalarm = 0;
424         priv->clk_mask = 0;
425         priv->data_mask = 0;
426         init_waitqueue_head(&priv->alarm_wq);
427 
428         filp->private_data = (void *)priv;
429 
430         return 0;
431 }
432 
433 static int
434 gpio_release(struct inode *inode, struct file *filp)
435 {
436         struct gpio_private *p = alarmlist;
437         struct gpio_private *todel = (struct gpio_private *)filp->private_data;
438         
439         /* unlink from alarmlist and free the private structure */
440 
441         if (p == todel) {
442                 alarmlist = todel->next;
443         } else {
444                 while (p->next != todel)
445                         p = p->next;
446                 p->next = todel->next;
447         }
448 
449         kfree(todel);
450         /* Check if there are still any alarms set */
451         p = alarmlist;
452         while (p) {
453                 if (p->highalarm | p->lowalarm) {
454                         gpio_some_alarms = 1;
455                         return 0;
456                 }
457                 p = p->next;
458         }
459         gpio_some_alarms = 0;
460                 
461         return 0;
462 }
463 
464 /* Main device API. ioctl's to read/set/clear bits, as well as to 
465  * set alarms to wait for using a subsequent select().
466  */
467 
468 unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
469 {
470         /* Set direction 0=unchanged 1=input, 
471          * return mask with 1=input 
472          */
473         unsigned long flags;
474         if (USE_PORTS(priv)) {
475                 local_irq_save(flags); local_irq_disable();
476                 *priv->dir = *priv->dir_shadow &= 
477                 ~((unsigned char)arg & priv->changeable_dir);
478                 local_irq_restore(flags);
479                 return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */
480         } else if (priv->minor == GPIO_MINOR_G) {
481                 /* We must fiddle with R_GEN_CONFIG to change dir */
482                 if (((arg & dir_g_in_bits) != arg) && 
483                     (arg & changeable_dir_g)) {
484                         arg &= changeable_dir_g;
485                         /* Clear bits in genconfig to set to input */
486                         if (arg & (1<<0)) {
487                                 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g0dir);
488                                 dir_g_in_bits |= (1<<0);
489                                 dir_g_out_bits &= ~(1<<0);
490                         }
491                         if ((arg & 0x0000FF00) == 0x0000FF00) {
492                                 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g8_15dir);
493                                 dir_g_in_bits |= 0x0000FF00;
494                                 dir_g_out_bits &= ~0x0000FF00;
495                         }
496                         if ((arg & 0x00FF0000) == 0x00FF0000) {
497                                 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g16_23dir);
498                                 dir_g_in_bits |= 0x00FF0000;
499                                 dir_g_out_bits &= ~0x00FF0000;
500                         }
501                         if (arg & (1<<24)) {
502                                 genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g24dir);
503                                 dir_g_in_bits |= (1<<24);
504                                 dir_g_out_bits &= ~(1<<24);
505                         }
506                         printk("gpio: SETINPUT on port G set "
507                                 "genconfig to 0x%08lX "
508                                 "in_bits: 0x%08lX "
509                                 "out_bits: 0x%08lX\n", 
510                                (unsigned long)genconfig_shadow, 
511                                dir_g_in_bits, dir_g_out_bits);
512                         *R_GEN_CONFIG = genconfig_shadow;
513                         /* Must be a >120 ns delay before writing this again */
514                                 
515                 }
516                 return dir_g_in_bits;
517         }
518         return 0;
519 } /* setget_input */
520 
521 unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
522 {
523         unsigned long flags;
524         if (USE_PORTS(priv)) {
525                 local_irq_save(flags); local_irq_disable();
526                 *priv->dir = *priv->dir_shadow |= 
527                   ((unsigned char)arg & priv->changeable_dir);
528                 local_irq_restore(flags);
529                 return *priv->dir_shadow;
530         } else if (priv->minor == GPIO_MINOR_G) {
531                 /* We must fiddle with R_GEN_CONFIG to change dir */                    
532                 if (((arg & dir_g_out_bits) != arg) &&
533                     (arg & changeable_dir_g)) {
534                         /* Set bits in genconfig to set to output */
535                         if (arg & (1<<0)) {
536                                 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g0dir);
537                                 dir_g_out_bits |= (1<<0);
538                                 dir_g_in_bits &= ~(1<<0);
539                         }
540                         if ((arg & 0x0000FF00) == 0x0000FF00) {
541                                 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g8_15dir);
542                                 dir_g_out_bits |= 0x0000FF00;
543                                 dir_g_in_bits &= ~0x0000FF00;
544                         }
545                         if ((arg & 0x00FF0000) == 0x00FF0000) {
546                                 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g16_23dir);
547                                 dir_g_out_bits |= 0x00FF0000;
548                                 dir_g_in_bits &= ~0x00FF0000;
549                         }
550                         if (arg & (1<<24)) {
551                                 genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g24dir);
552                                 dir_g_out_bits |= (1<<24);
553                                 dir_g_in_bits &= ~(1<<24);
554                         }
555                         printk("gpio: SETOUTPUT on port G set "
556                                 "genconfig to 0x%08lX "
557                                 "in_bits: 0x%08lX "
558                                 "out_bits: 0x%08lX\n", 
559                                (unsigned long)genconfig_shadow, 
560                                dir_g_in_bits, dir_g_out_bits);
561                         *R_GEN_CONFIG = genconfig_shadow;
562                         /* Must be a >120 ns delay before writing this again */
563                 }
564                 return dir_g_out_bits & 0x7FFFFFFF;
565         }
566         return 0;
567 } /* setget_output */
568 
569 static int
570 gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
571 
572 static int
573 gpio_ioctl(struct inode *inode, struct file *file,
574            unsigned int cmd, unsigned long arg)
575 {
576         unsigned long flags;
577         unsigned long val;
578         struct gpio_private *priv = (struct gpio_private *)file->private_data;
579         if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
580                 return -EINVAL;
581         }
582 
583         switch (_IOC_NR(cmd)) {
584         case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
585                 // read the port
586                 if (USE_PORTS(priv)) {
587                         return *priv->port;
588                 } else if (priv->minor == GPIO_MINOR_G) {
589                         return (*R_PORT_G_DATA) & 0x7FFFFFFF;
590                 }
591                 break;
592         case IO_SETBITS:
593                 local_irq_save(flags); local_irq_disable();
594                 // set changeable bits with a 1 in arg
595                 if (USE_PORTS(priv)) {
596                         *priv->port = *priv->shadow |= 
597                           ((unsigned char)arg & priv->changeable_bits);
598                 } else if (priv->minor == GPIO_MINOR_G) {
599                         *R_PORT_G_DATA = port_g_data_shadow |= (arg & dir_g_out_bits);
600                 }
601                 local_irq_restore(flags);
602                 break;
603         case IO_CLRBITS:
604                 local_irq_save(flags); local_irq_disable();
605                 // clear changeable bits with a 1 in arg
606                 if (USE_PORTS(priv)) {
607                         *priv->port = *priv->shadow &= 
608                          ~((unsigned char)arg & priv->changeable_bits);
609                 } else if (priv->minor == GPIO_MINOR_G) {
610                         *R_PORT_G_DATA = port_g_data_shadow &= ~((unsigned long)arg & dir_g_out_bits);
611                 }
612                 local_irq_restore(flags);
613                 break;
614         case IO_HIGHALARM:
615                 // set alarm when bits with 1 in arg go high
616                 priv->highalarm |= arg;
617                 gpio_some_alarms = 1;
618                 break;
619         case IO_LOWALARM:
620                 // set alarm when bits with 1 in arg go low
621                 priv->lowalarm |= arg;
622                 gpio_some_alarms = 1;
623                 break;
624         case IO_CLRALARM:
625                 // clear alarm for bits with 1 in arg
626                 priv->highalarm &= ~arg;
627                 priv->lowalarm  &= ~arg;
628                 break;
629         case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
630                 /* Read direction 0=input 1=output */
631                 if (USE_PORTS(priv)) {
632                         return *priv->dir_shadow;
633                 } else if (priv->minor == GPIO_MINOR_G) {
634                         /* Note: Some bits are both in and out,
635                          * Those that are dual is set here as well.
636                          */
637                         return (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF;
638                 }
639         case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
640                 /* Set direction 0=unchanged 1=input, 
641                  * return mask with 1=input 
642                  */
643                 return setget_input(priv, arg) & 0x7FFFFFFF;
644                 break;
645         case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
646                 /* Set direction 0=unchanged 1=output, 
647                  * return mask with 1=output 
648                  */
649                 return setget_output(priv, arg) & 0x7FFFFFFF;
650 
651         case IO_SHUTDOWN:
652                 SOFT_SHUTDOWN();
653                 break;
654         case IO_GET_PWR_BT:
655 #if defined (CONFIG_ETRAX_SOFT_SHUTDOWN)
656                 return (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));
657 #else
658                 return 0;
659 #endif
660                 break;
661         case IO_CFG_WRITE_MODE:
662                 priv->clk_mask = arg & 0xFF;
663                 priv->data_mask = (arg >> 8) & 0xFF;
664                 priv->write_msb = (arg >> 16) & 0x01;
665                 /* Check if we're allowed to change the bits and
666                  * the direction is correct
667                  */
668                 if (!((priv->clk_mask & priv->changeable_bits) &&
669                       (priv->data_mask & priv->changeable_bits) &&
670                       (priv->clk_mask & *priv->dir_shadow) &&
671                       (priv->data_mask & *priv->dir_shadow)))
672                 {
673                         priv->clk_mask = 0;
674                         priv->data_mask = 0;
675                         return -EPERM;
676                 }
677                 break;
678         case IO_READ_INBITS: 
679                 /* *arg is result of reading the input pins */
680                 if (USE_PORTS(priv)) {
681                         val = *priv->port;
682                 } else if (priv->minor == GPIO_MINOR_G) {
683                         val = *R_PORT_G_DATA;
684                 }
685                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
686                         return -EFAULT;
687                 return 0;
688                 break;
689         case IO_READ_OUTBITS:
690                  /* *arg is result of reading the output shadow */
691                 if (USE_PORTS(priv)) {
692                         val = *priv->shadow;
693                 } else if (priv->minor == GPIO_MINOR_G) {
694                         val = port_g_data_shadow;
695                 }
696                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
697                         return -EFAULT;
698                 break;
699         case IO_SETGET_INPUT: 
700                 /* bits set in *arg is set to input,
701                  * *arg updated with current input pins.
702                  */
703                 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
704                         return -EFAULT;
705                 val = setget_input(priv, val);
706                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
707                         return -EFAULT;
708                 break;
709         case IO_SETGET_OUTPUT:
710                 /* bits set in *arg is set to output,
711                  * *arg updated with current output pins.
712                  */
713                 if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
714                         return -EFAULT;
715                 val = setget_output(priv, val);
716                 if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
717                         return -EFAULT;
718                 break;
719         default:
720                 if (priv->minor == GPIO_MINOR_LEDS)
721                         return gpio_leds_ioctl(cmd, arg);
722                 else
723                         return -EINVAL;
724         } /* switch */
725         
726         return 0;
727 }
728 
729 static int
730 gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
731 {
732         unsigned char green;
733         unsigned char red;
734 
735         switch (_IOC_NR(cmd)) {
736         case IO_LEDACTIVE_SET:
737                 green = ((unsigned char) arg) & 1;
738                 red   = (((unsigned char) arg) >> 1) & 1;
739                 LED_ACTIVE_SET_G(green);
740                 LED_ACTIVE_SET_R(red);
741                 break;
742 
743         case IO_LED_SETBIT:
744                 LED_BIT_SET(arg);
745                 break;
746 
747         case IO_LED_CLRBIT:
748                 LED_BIT_CLR(arg);
749                 break;
750 
751         default:
752                 return -EINVAL;
753         } /* switch */
754 
755         return 0;
756 }
757 
758 struct file_operations gpio_fops = {
759         .owner       = THIS_MODULE,
760         .poll        = gpio_poll,
761         .ioctl       = gpio_ioctl,
762         .write       = gpio_write,
763         .open        = gpio_open,
764         .release     = gpio_release,
765 };
766 
767 
768 static void __init gpio_init_port_g(void)
769 {
770 #define GROUPA (0x0000FF3F)
771 #define GROUPB (1<<6 | 1<<7)
772 #define GROUPC (1<<30 | 1<<31)
773 #define GROUPD (0x3FFF0000)
774 #define GROUPD_LOW (0x00FF0000)
775         unsigned long used_in_bits = 0;
776         unsigned long used_out_bits = 0;
777         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0, select)){
778                 used_in_bits  |= GROUPA | GROUPB | 0 | 0;
779                 used_out_bits |= GROUPA | GROUPB | 0 | 0;
780         }
781         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ata, select)) {
782                 used_in_bits  |= GROUPA | GROUPB | GROUPC | (GROUPD & ~(1<<25|1<<26));
783                 used_out_bits |= GROUPA | GROUPB | GROUPC | GROUPD;
784         }
785 
786         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par0, select)) {
787                 used_in_bits  |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;
788                 used_out_bits |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;
789         }
790         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser2, select)) {
791                 used_in_bits  |= 0 | GROUPB | 0 | 0;
792                 used_out_bits |= 0 | GROUPB | 0 | 0;
793         }
794         /* mio same as shared RAM ? */
795         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio, select)) {
796                 used_in_bits  |= (GROUPA & ~(1<<0)) | 0 |0 |GROUPD_LOW;
797                 used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 |0 |GROUPD_LOW;
798         }
799         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi1, select)) {
800                 used_in_bits  |= 0 | 0 | GROUPC | GROUPD;
801                 used_out_bits |= 0 | 0 | GROUPC | GROUPD;
802         }
803         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0w, select)) {
804                 used_in_bits  |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24);
805                 used_out_bits |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24 | 1<<25|1<<26);
806         }
807 
808         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par1, select)) {
809                 used_in_bits  |= 0 | 0 | 0 | (GROUPD & ~(1<<24));
810                 used_out_bits |= 0 | 0 | 0 | (GROUPD & ~(1<<24));
811         }
812         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser3, select)) {
813                 used_in_bits  |= 0 | 0 | GROUPC | 0;
814                 used_out_bits |= 0 | 0 | GROUPC | 0;
815         }
816         /* mio same as shared RAM-W? */
817         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio_w, select)) {
818                 used_in_bits  |= (GROUPA & ~(1<<0)) | 0 | 0 |GROUPD_LOW;
819                 used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 | 0 |GROUPD_LOW;
820         }
821         /* TODO: USB p2, parw, sync ser3? */
822 
823         /* Initialise the dir_g_shadow etc. depending on genconfig */
824         /* 0=input 1=output */
825         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g0dir, out)) 
826                 dir_g_shadow |= (1 << 0);
827         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g8_15dir, out))
828                 dir_g_shadow |= 0x0000FF00;
829         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g16_23dir, out))
830                 dir_g_shadow |= 0x00FF0000;
831         if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g24dir, out))
832                 dir_g_shadow |= (1 << 24);
833 
834         dir_g_in_bits = ~used_in_bits;
835         dir_g_out_bits = ~used_out_bits;
836 
837         changeable_dir_g = 0x01FFFF01; /* all that can change dir */
838         changeable_dir_g &= dir_g_out_bits;
839         changeable_dir_g &= dir_g_in_bits;
840         /* Correct the bits that can change direction */ 
841         dir_g_out_bits &= ~changeable_dir_g;
842         dir_g_out_bits |= dir_g_shadow;
843         dir_g_in_bits &= ~changeable_dir_g;
844         dir_g_in_bits |= (~dir_g_shadow & changeable_dir_g);
845 
846 
847         printk("GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n",
848                dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA);
849         printk("GPIO port G: dir: %08lX changeable: %08lX\n", 
850                dir_g_shadow, changeable_dir_g);
851 }
852 
853 /* main driver initialization routine, called from mem.c */
854 
855 static __init int
856 gpio_init(void)
857 {
858         int res;
859 #if defined (CONFIG_ETRAX_CSP0_LEDS)
860         int i;
861 #endif
862 
863         /* do the formalities */
864 
865         res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
866         if (res < 0) {
867                 printk(KERN_ERR "gpio: couldn't get a major number.\n");
868                 return res;
869         }
870 
871         /* Clear all leds */
872 #if defined (CONFIG_ETRAX_CSP0_LEDS) ||  defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS)
873         LED_NETWORK_SET(0);
874         LED_ACTIVE_SET(0);
875         LED_DISK_READ(0);
876         LED_DISK_WRITE(0);
877 
878 #if defined (CONFIG_ETRAX_CSP0_LEDS)
879         for (i = 0; i < 32; i++) {
880                 LED_BIT_SET(i);
881         }
882 #endif
883 
884 #endif
885         gpio_init_port_g();
886         printk("ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002 Axis Communications AB\n");
887         /* We call etrax_gpio_wake_up_check() from timer interrupt and
888          * from cpu_idle() in kernel/process.c
889          * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
890          * in some tests.
891          */  
892         if (request_irq(TIMER0_IRQ_NBR, gpio_poll_timer_interrupt,
893                         SA_SHIRQ | SA_INTERRUPT,"gpio poll", NULL)) {
894                 printk("err: timer0 irq for gpio\n");
895         }
896         if (request_irq(PA_IRQ_NBR, gpio_pa_interrupt,
897                         SA_SHIRQ | SA_INTERRUPT,"gpio PA", NULL)) {
898                 printk("err: PA irq for gpio\n");
899         }
900         
901 
902         return res;
903 }
904 
905 /* this makes sure that gpio_init is called during kernel boot */
906 
907 module_init(gpio_init);
908 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp