hd64465_gpio.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: hd64465_gpio.c,v 1.2 2001/05/24 00:13:47 gniibe Exp $
  3.  * by Greg Banks <gbanks@pocketpenguins.com>
  4.  * (c) 2000 PocketPenguins Inc
  5.  *
  6.  * GPIO pin support for HD64465 companion chip.
  7.  */
  8. #include <linux/kernel.h>
  9. #include <linux/init.h>
  10. #include <linux/module.h>
  11. #include <linux/sched.h>
  12. #include <linux/ioport.h>
  13. #include <asm/io.h>
  14. #include <asm/hd64465_gpio.h>
  15. #define _PORTOF(portpin)    (((portpin)>>3)&0x7)
  16. #define _PINOF(portpin)     ((portpin)&0x7)
  17. /* Register addresses parametrised on port */
  18. #define GPIO_CR(port)     (HD64465_REG_GPACR+((port)<<1))
  19. #define GPIO_DR(port)     (HD64465_REG_GPADR+((port)<<1))
  20. #define GPIO_ICR(port)     (HD64465_REG_GPAICR+((port)<<1))
  21. #define GPIO_ISR(port)     (HD64465_REG_GPAISR+((port)<<1))
  22. #define GPIO_NPORTS 5
  23. #define MODNAME "hd64465_gpio"
  24. EXPORT_SYMBOL(hd64465_gpio_configure);
  25. EXPORT_SYMBOL(hd64465_gpio_get_pin);
  26. EXPORT_SYMBOL(hd64465_gpio_get_port);
  27. EXPORT_SYMBOL(hd64465_gpio_register_irq);
  28. EXPORT_SYMBOL(hd64465_gpio_set_pin);
  29. EXPORT_SYMBOL(hd64465_gpio_set_port);
  30. EXPORT_SYMBOL(hd64465_gpio_unregister_irq);
  31. /* TODO: each port should be protected with a spinlock */
  32. void hd64465_gpio_configure(int portpin, int direction)
  33. {
  34.      unsigned short cr;
  35. unsigned int shift = (_PINOF(portpin)<<1);
  36. cr = inw(GPIO_CR(_PORTOF(portpin)));
  37. cr &= ~(3<<shift);
  38. cr |= direction<<shift;
  39. outw(cr, GPIO_CR(_PORTOF(portpin)));
  40. }
  41. void hd64465_gpio_set_pin(int portpin, unsigned int value)
  42. {
  43.      unsigned short d;
  44. unsigned short mask = 1<<(_PINOF(portpin));
  45. d = inw(GPIO_DR(_PORTOF(portpin)));
  46. if (value)
  47.     d |= mask;
  48. else
  49.     d &= ~mask;
  50. outw(d, GPIO_DR(_PORTOF(portpin)));
  51. }
  52. unsigned int hd64465_gpio_get_pin(int portpin)
  53. {
  54. return inw(GPIO_DR(_PORTOF(portpin))) & (1<<(_PINOF(portpin)));
  55. }
  56. /* TODO: for cleaner atomicity semantics, add a mask to this routine */
  57. void hd64465_gpio_set_port(int port, unsigned int value)
  58. {
  59. outw(value, GPIO_DR(port));
  60. }
  61. unsigned int hd64465_gpio_get_port(int port)
  62. {
  63. return inw(GPIO_DR(port));
  64. }
  65. static struct {
  66.     void (*func)(int portpin, void *dev);
  67.     void *dev;
  68. } handlers[GPIO_NPORTS * 8];
  69. static void hd64465_gpio_interrupt(int irq, void *dev, struct pt_regs *regs)
  70. {
  71.      unsigned short port, pin, isr, mask, portpin;
  72. for (port=0 ; port<GPIO_NPORTS ; port++) {
  73.     isr = inw(GPIO_ISR(port));
  74.     
  75.     for (pin=0 ; pin<8 ; pin++) {
  76.      mask = 1<<pin;
  77.      if (isr & mask) {
  78.     portpin = (port<<3)|pin;
  79.     if (handlers[portpin].func != 0)
  80.      handlers[portpin].func(portpin, handlers[portpin].dev);
  81.               else
  82.      printk(KERN_NOTICE "unexpected GPIO interrupt, pin %c%dn",
  83.     port+'A', (int)pin);
  84. }
  85.     }
  86.     
  87.     /* Write 1s back to ISR to clear it?  That's what the manual says.. */
  88.     outw(isr, GPIO_ISR(port));
  89. }
  90. }
  91. void hd64465_gpio_register_irq(int portpin, int mode,
  92. void (*handler)(int portpin, void *dev), void *dev)
  93. {
  94.      unsigned long flags;
  95. unsigned short icr, mask;
  96. if (handler == 0)
  97.     return;
  98.     
  99. save_and_cli(flags);
  100. handlers[portpin].func = handler;
  101. handlers[portpin].dev = dev;
  102.      /*
  103.  * Configure Interrupt Control Register
  104.  */
  105. icr = inw(GPIO_ICR(_PORTOF(portpin)));
  106. mask = (1<<_PINOF(portpin));
  107. /* unmask interrupt */
  108. icr &= ~mask;
  109. /* set TS bit */
  110. mask <<= 8;
  111. icr &= ~mask;
  112. if (mode == HD64465_GPIO_RISING)
  113.     icr |= mask;
  114.     
  115. outw(icr, GPIO_ICR(_PORTOF(portpin)));
  116. restore_flags(flags);
  117. }
  118. void hd64465_gpio_unregister_irq(int portpin)
  119. {
  120.      unsigned long flags;
  121. unsigned short icr;
  122. save_and_cli(flags);
  123.      /*
  124.  * Configure Interrupt Control Register
  125.  */
  126. icr = inw(GPIO_ICR(_PORTOF(portpin)));
  127. icr |= (1<<_PINOF(portpin)); /* mask interrupt */
  128. outw(icr, GPIO_ICR(_PORTOF(portpin)));
  129. handlers[portpin].func = 0;
  130. handlers[portpin].dev = 0;
  131. restore_flags(flags);
  132. }
  133. static int __init hd64465_gpio_init(void)
  134. {
  135.      /* TODO: check return values */
  136.      request_region(HD64465_REG_GPACR, 0x1000, MODNAME);
  137. request_irq(HD64465_IRQ_GPIO, hd64465_gpio_interrupt,
  138.     SA_INTERRUPT, MODNAME, 0);
  139.      printk("HD64465 GPIO layer on irq %dn", HD64465_IRQ_GPIO);
  140. return 0;
  141. }
  142. static void __exit hd64465_gpio_exit(void)
  143. {
  144.      release_region(HD64465_REG_GPACR, 0x1000);
  145. free_irq(HD64465_IRQ_GPIO, 0);
  146. }
  147. module_init(hd64465_gpio_init);
  148. module_exit(hd64465_gpio_exit);