neponset.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * linux/arch/arm/mach-sa1100/neponset.c
  3.  *
  4.  */
  5. #include <linux/init.h>
  6. #include <linux/sched.h>
  7. #include <linux/interrupt.h>
  8. #include <linux/ptrace.h>
  9. #include <linux/tty.h>
  10. #include <linux/ioport.h>
  11. #include <linux/serial_core.h>
  12. #include <asm/hardware.h>
  13. #include <asm/irq.h>
  14. #include <asm/mach/map.h>
  15. #include <asm/mach/irq.h>
  16. #include <asm/arch/irq.h>
  17. #include <asm/mach/serial_sa1100.h>
  18. #include <asm/arch/assabet.h>
  19. #include <asm/hardware/sa1111.h>
  20. #include "sa1111.h"
  21. /*
  22.  * Install handler for Neponset IRQ.  Yes, yes... we are way down the IRQ
  23.  * cascade which is not good for IRQ latency, but the hardware has been
  24.  * designed that way...
  25.  */
  26. static void neponset_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
  27. {
  28. int irr;
  29. for(;;){
  30. irr = IRR & (IRR_ETHERNET | IRR_USAR | IRR_SA1111);
  31. /* Let's have all active IRQ bits high.
  32.  * Note: there is a typo in the Neponset user's guide
  33.  * for the SA1111 IRR level.
  34.  */
  35. irr ^= (IRR_ETHERNET | IRR_USAR);
  36. if (!irr) break;
  37. if( irr & IRR_ETHERNET )
  38. do_IRQ(IRQ_NEPONSET_SMC9196, regs);
  39. if( irr & IRR_USAR )
  40. do_IRQ(IRQ_NEPONSET_USAR, regs);
  41. if( irr & IRR_SA1111 )
  42. sa1111_IRQ_demux(irq, dev_id, regs);
  43. }
  44. }
  45. static struct irqaction neponset_irq = {
  46. name: "Neponset",
  47. handler: neponset_IRQ_demux,
  48. flags: SA_INTERRUPT
  49. };
  50. static void __init neponset_init_irq(void)
  51. {
  52. sa1111_init_irq(-1); /* SA1111 IRQ not routed to a GPIO */
  53. /* setup extra Neponset IRQs */
  54. irq_desc[IRQ_NEPONSET_SMC9196].valid = 1;
  55. irq_desc[IRQ_NEPONSET_SMC9196].probe_ok = 1;
  56. irq_desc[IRQ_NEPONSET_USAR].valid = 1;
  57. irq_desc[IRQ_NEPONSET_USAR].probe_ok = 1;
  58. set_GPIO_IRQ_edge(GPIO_GPIO25, GPIO_RISING_EDGE);
  59. setup_arm_irq(IRQ_GPIO25, &neponset_irq);
  60. }
  61. static int __init neponset_init(void)
  62. {
  63. int ret;
  64. /*
  65.  * The Neponset is only present on the Assabet machine type.
  66.  */
  67. if (!machine_is_assabet())
  68. return -ENODEV;
  69. /*
  70.  * Ensure that the memory bus request/grant signals are setup,
  71.  * and the grant is held in its inactive state, whether or not
  72.  * we actually have a Neponset attached.
  73.  */
  74. sa1110_mb_disable();
  75. if (!machine_has_neponset()) {
  76. printk(KERN_DEBUG "Neponset expansion board not presentn");
  77. return -ENODEV;
  78. }
  79. if (WHOAMI != 0x11) {
  80. printk(KERN_WARNING "Neponset board detected, but "
  81. "wrong ID: %02xn", WHOAMI);
  82. return -ENODEV;
  83. }
  84. /*
  85.  * Disable GPIO 0/1 drivers so the buttons work on the module.
  86.  */
  87. NCR_0 |= NCR_GP01_OFF;
  88. /*
  89.  * Neponset has SA1111 connected to CS4.  We know that after
  90.  * reset the chip will be configured for variable latency IO.
  91.  */
  92. /* FIXME: setup MSC2 */
  93. /*
  94.  * Probe for a SA1111.
  95.  */
  96. ret = sa1111_probe(NEPONSET_SA1111_BASE);
  97. if (ret < 0)
  98. return ret;
  99. /*
  100.  * We found it.  Wake the chip up.
  101.  */
  102. sa1111_wake();
  103. /*
  104.  * The SDRAM configuration of the SA1110 and the SA1111 must
  105.  * match.  This is very important to ensure that SA1111 accesses
  106.  * don't corrupt the SDRAM.  Note that this ungates the SA1111's
  107.  * MBGNT signal, so we must have called sa1110_mb_disable()
  108.  * beforehand.
  109.  */
  110. sa1111_configure_smc(1,
  111.      FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
  112.      FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
  113. /*
  114.  * We only need to turn on DCLK whenever we want to use the
  115.  * DMA.  It can otherwise be held firmly in the off position.
  116.  */
  117. SKPCR |= SKPCR_DCLKEN;
  118. /*
  119.  * Enable the SA1110 memory bus request and grant signals.
  120.  */
  121. sa1110_mb_enable();
  122. neponset_init_irq();
  123. return 0;
  124. }
  125. __initcall(neponset_init);
  126. static struct map_desc neponset_io_desc[] __initdata = {
  127.  /* virtual     physical    length      domain     r  w  c  b */
  128.   { 0xf3000000, 0x10000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* System Registers */
  129.   { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
  130.   LAST_DESC
  131. };
  132. static void neponset_set_mctrl(struct uart_port *port, u_int mctrl)
  133. {
  134. u_int mdm_ctl0 = MDM_CTL_0;
  135. if (port->mapbase == _Ser1UTCR0) {
  136. if (mctrl & TIOCM_RTS)
  137. mdm_ctl0 &= ~MDM_CTL0_RTS2;
  138. else
  139. mdm_ctl0 |= MDM_CTL0_RTS2;
  140. if (mctrl & TIOCM_DTR)
  141. mdm_ctl0 &= ~MDM_CTL0_DTR2;
  142. else
  143. mdm_ctl0 |= MDM_CTL0_DTR2;
  144. } else if (port->mapbase == _Ser3UTCR0) {
  145. if (mctrl & TIOCM_RTS)
  146. mdm_ctl0 &= ~MDM_CTL0_RTS1;
  147. else
  148. mdm_ctl0 |= MDM_CTL0_RTS1;
  149. if (mctrl & TIOCM_DTR)
  150. mdm_ctl0 &= ~MDM_CTL0_DTR1;
  151. else
  152. mdm_ctl0 |= MDM_CTL0_DTR1;
  153. }
  154. MDM_CTL_0 = mdm_ctl0;
  155. }
  156. static u_int neponset_get_mctrl(struct uart_port *port)
  157. {
  158. u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
  159. u_int mdm_ctl1 = MDM_CTL_1;
  160. if (port->mapbase == _Ser1UTCR0) {
  161. if (mdm_ctl1 & MDM_CTL1_DCD2)
  162. ret &= ~TIOCM_CD;
  163. if (mdm_ctl1 & MDM_CTL1_CTS2)
  164. ret &= ~TIOCM_CTS;
  165. if (mdm_ctl1 & MDM_CTL1_DSR2)
  166. ret &= ~TIOCM_DSR;
  167. } else if (port->mapbase == _Ser3UTCR0) {
  168. if (mdm_ctl1 & MDM_CTL1_DCD1)
  169. ret &= ~TIOCM_CD;
  170. if (mdm_ctl1 & MDM_CTL1_CTS1)
  171. ret &= ~TIOCM_CTS;
  172. if (mdm_ctl1 & MDM_CTL1_DSR1)
  173. ret &= ~TIOCM_DSR;
  174. }
  175. return ret;
  176. }
  177. static struct sa1100_port_fns neponset_port_fns __initdata = {
  178. set_mctrl: neponset_set_mctrl,
  179. get_mctrl: neponset_get_mctrl,
  180. };
  181. void __init neponset_map_io(void)
  182. {
  183. iotable_init(neponset_io_desc);
  184. if (machine_has_neponset())
  185. sa1100_register_uart_fns(&neponset_port_fns);
  186. }