rm200.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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/ds1216.h>
  17. #include <asm/irq_cpu.h>
  18. #define PORT(_base,_irq) \
  19. { \
  20. .iobase = _base, \
  21. .irq = _irq, \
  22. .uartclk = 1843200, \
  23. .iotype = UPIO_PORT, \
  24. .flags = UPF_BOOT_AUTOCONF, \
  25. }
  26. static struct plat_serial8250_port rm200_data[] = {
  27. PORT(0x3f8, 4),
  28. PORT(0x2f8, 3),
  29. { },
  30. };
  31. static struct platform_device rm200_serial8250_device = {
  32. .name = "serial8250",
  33. .id = PLAT8250_DEV_PLATFORM,
  34. .dev = {
  35. .platform_data = rm200_data,
  36. },
  37. };
  38. static struct resource snirm_82596_rm200_rsrc[] = {
  39. {
  40. .start = 0xb8000000,
  41. .end = 0xb80fffff,
  42. .flags = IORESOURCE_MEM
  43. },
  44. {
  45. .start = 0xbb000000,
  46. .end = 0xbb000004,
  47. .flags = IORESOURCE_MEM
  48. },
  49. {
  50. .start = 0xbff00000,
  51. .end = 0xbff00020,
  52. .flags = IORESOURCE_MEM
  53. },
  54. {
  55. .start = 27,
  56. .end = 27,
  57. .flags = IORESOURCE_IRQ
  58. },
  59. {
  60. .flags = 0x00
  61. }
  62. };
  63. static struct platform_device snirm_82596_rm200_pdev = {
  64. .name = "snirm_82596",
  65. .num_resources = ARRAY_SIZE(snirm_82596_rm200_rsrc),
  66. .resource = snirm_82596_rm200_rsrc
  67. };
  68. static struct resource snirm_53c710_rm200_rsrc[] = {
  69. {
  70. .start = 0xb9000000,
  71. .end = 0xb90fffff,
  72. .flags = IORESOURCE_MEM
  73. },
  74. {
  75. .start = 26,
  76. .end = 26,
  77. .flags = IORESOURCE_IRQ
  78. }
  79. };
  80. static struct platform_device snirm_53c710_rm200_pdev = {
  81. .name = "snirm_53c710",
  82. .num_resources = ARRAY_SIZE(snirm_53c710_rm200_rsrc),
  83. .resource = snirm_53c710_rm200_rsrc
  84. };
  85. static int __init snirm_setup_devinit(void)
  86. {
  87. if (sni_brd_type == SNI_BRD_RM200) {
  88. platform_device_register(&rm200_serial8250_device);
  89. platform_device_register(&snirm_82596_rm200_pdev);
  90. platform_device_register(&snirm_53c710_rm200_pdev);
  91. }
  92. return 0;
  93. }
  94. device_initcall(snirm_setup_devinit);
  95. #define SNI_RM200_INT_STAT_REG 0xbc000000
  96. #define SNI_RM200_INT_ENA_REG 0xbc080000
  97. #define SNI_RM200_INT_START 24
  98. #define SNI_RM200_INT_END 28
  99. static void enable_rm200_irq(unsigned int irq)
  100. {
  101. unsigned int mask = 1 << (irq - SNI_RM200_INT_START);
  102. *(volatile u8 *)SNI_RM200_INT_ENA_REG &= ~mask;
  103. }
  104. void disable_rm200_irq(unsigned int irq)
  105. {
  106. unsigned int mask = 1 << (irq - SNI_RM200_INT_START);
  107. *(volatile u8 *)SNI_RM200_INT_ENA_REG |= mask;
  108. }
  109. void end_rm200_irq(unsigned int irq)
  110. {
  111. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  112. enable_rm200_irq(irq);
  113. }
  114. static struct irq_chip rm200_irq_type = {
  115. .typename = "RM200",
  116. .ack = disable_rm200_irq,
  117. .mask = disable_rm200_irq,
  118. .mask_ack = disable_rm200_irq,
  119. .unmask = enable_rm200_irq,
  120. .end = end_rm200_irq,
  121. };
  122. static void sni_rm200_hwint(void)
  123. {
  124. u32 pending = read_c0_cause() & read_c0_status();
  125. u8 mask;
  126. u8 stat;
  127. int irq;
  128. if (pending & C_IRQ5)
  129. do_IRQ (MIPS_CPU_IRQ_BASE + 7);
  130. else if (pending & C_IRQ0) {
  131. clear_c0_status (IE_IRQ0);
  132. mask = *(volatile u8 *)SNI_RM200_INT_ENA_REG ^ 0x1f;
  133. stat = *(volatile u8 *)SNI_RM200_INT_STAT_REG ^ 0x14;
  134. irq = ffs(stat & mask & 0x1f);
  135. if (likely(irq > 0))
  136. do_IRQ (irq + SNI_RM200_INT_START - 1);
  137. set_c0_status (IE_IRQ0);
  138. }
  139. }
  140. void __init sni_rm200_irq_init(void)
  141. {
  142. int i;
  143. * (volatile u8 *)SNI_RM200_INT_ENA_REG = 0x1f;
  144. mips_cpu_irq_init();
  145. /* Actually we've got more interrupts to handle ... */
  146. for (i = SNI_RM200_INT_START; i <= SNI_RM200_INT_END; i++)
  147. set_irq_chip(i, &rm200_irq_type);
  148. sni_hwint = sni_rm200_hwint;
  149. change_c0_status(ST0_IM, IE_IRQ0);
  150. setup_irq (SNI_RM200_INT_START + 0, &sni_isa_irq);
  151. }
  152. void sni_rm200_init(void)
  153. {
  154. set_io_port_base(SNI_PORT_BASE + 0x02000000);
  155. ioport_resource.end += 0x02000000;
  156. ds1216_base = (volatile unsigned char *) SNI_DS1216_RM200_BASE;
  157. rtc_mips_get_time = ds1216_get_cmos_time;
  158. board_time_init = sni_cpu_time_init;
  159. }