rm200.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * RM200 specific code
  3. *
  4. * This file is subject to the terms and conditions of the GNU General Public
  5. * License. See the file "COPYING" in the main directory of this archive
  6. * for more details.
  7. *
  8. * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
  9. */
  10. #include <linux/init.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/serial_8250.h>
  14. #include <asm/sni.h>
  15. #include <asm/time.h>
  16. #include <asm/irq_cpu.h>
  17. #define PORT(_base,_irq) \
  18. { \
  19. .iobase = _base, \
  20. .irq = _irq, \
  21. .uartclk = 1843200, \
  22. .iotype = UPIO_PORT, \
  23. .flags = UPF_BOOT_AUTOCONF, \
  24. }
  25. static struct plat_serial8250_port rm200_data[] = {
  26. PORT(0x3f8, 4),
  27. PORT(0x2f8, 3),
  28. { },
  29. };
  30. static struct platform_device rm200_serial8250_device = {
  31. .name = "serial8250",
  32. .id = PLAT8250_DEV_PLATFORM,
  33. .dev = {
  34. .platform_data = rm200_data,
  35. },
  36. };
  37. static struct resource rm200_ds1216_rsrc[] = {
  38. {
  39. .start = 0x1cd41ffc,
  40. .end = 0x1cd41fff,
  41. .flags = IORESOURCE_MEM
  42. }
  43. };
  44. static struct platform_device rm200_ds1216_device = {
  45. .name = "rtc-ds1216",
  46. .num_resources = ARRAY_SIZE(rm200_ds1216_rsrc),
  47. .resource = rm200_ds1216_rsrc
  48. };
  49. static struct resource snirm_82596_rm200_rsrc[] = {
  50. {
  51. .start = 0x18000000,
  52. .end = 0x180fffff,
  53. .flags = IORESOURCE_MEM
  54. },
  55. {
  56. .start = 0x1b000000,
  57. .end = 0x1b000004,
  58. .flags = IORESOURCE_MEM
  59. },
  60. {
  61. .start = 0x1ff00000,
  62. .end = 0x1ff00020,
  63. .flags = IORESOURCE_MEM
  64. },
  65. {
  66. .start = 27,
  67. .end = 27,
  68. .flags = IORESOURCE_IRQ
  69. },
  70. {
  71. .flags = 0x00
  72. }
  73. };
  74. static struct platform_device snirm_82596_rm200_pdev = {
  75. .name = "snirm_82596",
  76. .num_resources = ARRAY_SIZE(snirm_82596_rm200_rsrc),
  77. .resource = snirm_82596_rm200_rsrc
  78. };
  79. static struct resource snirm_53c710_rm200_rsrc[] = {
  80. {
  81. .start = 0x19000000,
  82. .end = 0x190fffff,
  83. .flags = IORESOURCE_MEM
  84. },
  85. {
  86. .start = 26,
  87. .end = 26,
  88. .flags = IORESOURCE_IRQ
  89. }
  90. };
  91. static struct platform_device snirm_53c710_rm200_pdev = {
  92. .name = "snirm_53c710",
  93. .num_resources = ARRAY_SIZE(snirm_53c710_rm200_rsrc),
  94. .resource = snirm_53c710_rm200_rsrc
  95. };
  96. static int __init snirm_setup_devinit(void)
  97. {
  98. if (sni_brd_type == SNI_BRD_RM200) {
  99. platform_device_register(&rm200_serial8250_device);
  100. platform_device_register(&rm200_ds1216_device);
  101. platform_device_register(&snirm_82596_rm200_pdev);
  102. platform_device_register(&snirm_53c710_rm200_pdev);
  103. }
  104. return 0;
  105. }
  106. device_initcall(snirm_setup_devinit);
  107. #define SNI_RM200_INT_STAT_REG 0xbc000000
  108. #define SNI_RM200_INT_ENA_REG 0xbc080000
  109. #define SNI_RM200_INT_START 24
  110. #define SNI_RM200_INT_END 28
  111. static void enable_rm200_irq(unsigned int irq)
  112. {
  113. unsigned int mask = 1 << (irq - SNI_RM200_INT_START);
  114. *(volatile u8 *)SNI_RM200_INT_ENA_REG &= ~mask;
  115. }
  116. void disable_rm200_irq(unsigned int irq)
  117. {
  118. unsigned int mask = 1 << (irq - SNI_RM200_INT_START);
  119. *(volatile u8 *)SNI_RM200_INT_ENA_REG |= mask;
  120. }
  121. void end_rm200_irq(unsigned int irq)
  122. {
  123. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  124. enable_rm200_irq(irq);
  125. }
  126. static struct irq_chip rm200_irq_type = {
  127. .typename = "RM200",
  128. .ack = disable_rm200_irq,
  129. .mask = disable_rm200_irq,
  130. .mask_ack = disable_rm200_irq,
  131. .unmask = enable_rm200_irq,
  132. .end = end_rm200_irq,
  133. };
  134. static void sni_rm200_hwint(void)
  135. {
  136. u32 pending = read_c0_cause() & read_c0_status();
  137. u8 mask;
  138. u8 stat;
  139. int irq;
  140. if (pending & C_IRQ5)
  141. do_IRQ(MIPS_CPU_IRQ_BASE + 7);
  142. else if (pending & C_IRQ0) {
  143. clear_c0_status(IE_IRQ0);
  144. mask = *(volatile u8 *)SNI_RM200_INT_ENA_REG ^ 0x1f;
  145. stat = *(volatile u8 *)SNI_RM200_INT_STAT_REG ^ 0x14;
  146. irq = ffs(stat & mask & 0x1f);
  147. if (likely(irq > 0))
  148. do_IRQ(irq + SNI_RM200_INT_START - 1);
  149. set_c0_status(IE_IRQ0);
  150. }
  151. }
  152. void __init sni_rm200_irq_init(void)
  153. {
  154. int i;
  155. * (volatile u8 *)SNI_RM200_INT_ENA_REG = 0x1f;
  156. mips_cpu_irq_init();
  157. /* Actually we've got more interrupts to handle ... */
  158. for (i = SNI_RM200_INT_START; i <= SNI_RM200_INT_END; i++)
  159. set_irq_chip(i, &rm200_irq_type);
  160. sni_hwint = sni_rm200_hwint;
  161. change_c0_status(ST0_IM, IE_IRQ0);
  162. setup_irq(SNI_RM200_INT_START + 0, &sni_isa_irq);
  163. }
  164. void __init sni_rm200_init(void)
  165. {
  166. set_io_port_base(SNI_PORT_BASE + 0x02000000);
  167. ioport_resource.end += 0x02000000;
  168. }