rte_me2_cb.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. * arch/v850/kernel/rte_me2_cb.c -- Midas labs RTE-V850E/ME2-CB board
  3. *
  4. * Copyright (C) 2001,02,03 NEC Electronics Corporation
  5. * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
  6. *
  7. * This file is subject to the terms and conditions of the GNU General
  8. * Public License. See the file COPYING in the main directory of this
  9. * archive for more details.
  10. *
  11. * Written by Miles Bader <miles@gnu.org>
  12. */
  13. #include <linux/config.h>
  14. #include <linux/kernel.h>
  15. #include <linux/init.h>
  16. #include <linux/bootmem.h>
  17. #include <linux/irq.h>
  18. #include <linux/fs.h>
  19. #include <linux/major.h>
  20. #include <linux/sched.h>
  21. #include <linux/delay.h>
  22. #include <asm/atomic.h>
  23. #include <asm/page.h>
  24. #include <asm/me2.h>
  25. #include <asm/rte_me2_cb.h>
  26. #include <asm/machdep.h>
  27. #include <asm/v850e_intc.h>
  28. #include <asm/v850e_cache.h>
  29. #include <asm/irq.h>
  30. #include "mach.h"
  31. extern unsigned long *_intv_start;
  32. extern unsigned long *_intv_end;
  33. /* LED access routines. */
  34. extern unsigned read_leds (int pos, char *buf, int len);
  35. extern unsigned write_leds (int pos, const char *buf, int len);
  36. /* SDRAM are almost contiguous (with a small hole in between;
  37. see mach_reserve_bootmem for details), so just use both as one big area. */
  38. #define RAM_START SDRAM_ADDR
  39. #define RAM_END (SDRAM_ADDR + SDRAM_SIZE)
  40. void __init mach_get_physical_ram (unsigned long *ram_start,
  41. unsigned long *ram_len)
  42. {
  43. *ram_start = RAM_START;
  44. *ram_len = RAM_END - RAM_START;
  45. }
  46. void mach_gettimeofday (struct timespec *tv)
  47. {
  48. tv->tv_sec = 0;
  49. tv->tv_nsec = 0;
  50. }
  51. /* Called before configuring an on-chip UART. */
  52. void rte_me2_cb_uart_pre_configure (unsigned chan,
  53. unsigned cflags, unsigned baud)
  54. {
  55. /* The RTE-V850E/ME2-CB connects some general-purpose I/O
  56. pins on the CPU to the RTS/CTS lines of UARTB channel 0's
  57. serial connection.
  58. I/O pins P21 and P22 are RTS and CTS respectively. */
  59. if (chan == 0) {
  60. /* Put P21 & P22 in I/O port mode. */
  61. ME2_PORT2_PMC &= ~0x6;
  62. /* Make P21 and output, and P22 an input. */
  63. ME2_PORT2_PM = (ME2_PORT2_PM & ~0xC) | 0x4;
  64. }
  65. me2_uart_pre_configure (chan, cflags, baud);
  66. }
  67. void __init mach_init_irqs (void)
  68. {
  69. /* Initialize interrupts. */
  70. me2_init_irqs ();
  71. rte_me2_cb_init_irqs ();
  72. }
  73. #ifdef CONFIG_ROM_KERNEL
  74. /* Initialization for kernel in ROM. */
  75. static inline rom_kernel_init (void)
  76. {
  77. /* If the kernel is in ROM, we have to copy any initialized data
  78. from ROM into RAM. */
  79. extern unsigned long _data_load_start, _sdata, _edata;
  80. register unsigned long *src = &_data_load_start;
  81. register unsigned long *dst = &_sdata, *end = &_edata;
  82. while (dst != end)
  83. *dst++ = *src++;
  84. }
  85. #endif /* CONFIG_ROM_KERNEL */
  86. static void install_interrupt_vectors (void)
  87. {
  88. unsigned long *p1, *p2;
  89. ME2_IRAMM = 0x03; /* V850E/ME2 iRAM write mode */
  90. /* vector copy to iRAM */
  91. p1 = (unsigned long *)0; /* v85x vector start */
  92. p2 = (unsigned long *)&_intv_start;
  93. while (p2 < (unsigned long *)&_intv_end)
  94. *p1++ = *p2++;
  95. ME2_IRAMM = 0x00; /* V850E/ME2 iRAM read mode */
  96. }
  97. /* CompactFlash */
  98. static void cf_power_on (void)
  99. {
  100. /* CF card detected? */
  101. if (CB_CF_STS0 & 0x0030)
  102. return;
  103. CB_CF_REG0 = 0x0002; /* reest on */
  104. mdelay (10);
  105. CB_CF_REG0 = 0x0003; /* power on */
  106. mdelay (10);
  107. CB_CF_REG0 = 0x0001; /* reset off */
  108. mdelay (10);
  109. }
  110. static void cf_power_off (void)
  111. {
  112. CB_CF_REG0 = 0x0003; /* power on */
  113. mdelay (10);
  114. CB_CF_REG0 = 0x0002; /* reest on */
  115. mdelay (10);
  116. }
  117. void __init mach_early_init (void)
  118. {
  119. install_interrupt_vectors ();
  120. /* CS1 SDRAM instruction cache enable */
  121. v850e_cache_enable (0x04, 0x03, 0);
  122. rte_cb_early_init ();
  123. /* CompactFlash power on */
  124. cf_power_on ();
  125. #if defined (CONFIG_ROM_KERNEL)
  126. rom_kernel_init ();
  127. #endif
  128. }
  129. /* RTE-V850E/ME2-CB Programmable Interrupt Controller. */
  130. static struct cb_pic_irq_init cb_pic_irq_inits[] = {
  131. { "CB_EXTTM0", IRQ_CB_EXTTM0, 1, 1, 6 },
  132. { "CB_EXTSIO", IRQ_CB_EXTSIO, 1, 1, 6 },
  133. { "CB_TOVER", IRQ_CB_TOVER, 1, 1, 6 },
  134. { "CB_GINT0", IRQ_CB_GINT0, 1, 1, 6 },
  135. { "CB_USB", IRQ_CB_USB, 1, 1, 6 },
  136. { "CB_LANC", IRQ_CB_LANC, 1, 1, 6 },
  137. { "CB_USB_VBUS_ON", IRQ_CB_USB_VBUS_ON, 1, 1, 6 },
  138. { "CB_USB_VBUS_OFF", IRQ_CB_USB_VBUS_OFF, 1, 1, 6 },
  139. { "CB_EXTTM1", IRQ_CB_EXTTM1, 1, 1, 6 },
  140. { "CB_EXTTM2", IRQ_CB_EXTTM2, 1, 1, 6 },
  141. { 0 }
  142. };
  143. #define NUM_CB_PIC_IRQ_INITS \
  144. ((sizeof cb_pic_irq_inits / sizeof cb_pic_irq_inits[0]) - 1)
  145. static struct hw_interrupt_type cb_pic_hw_itypes[NUM_CB_PIC_IRQ_INITS];
  146. static unsigned char cb_pic_active_irqs = 0;
  147. void __init rte_me2_cb_init_irqs (void)
  148. {
  149. cb_pic_init_irq_types (cb_pic_irq_inits, cb_pic_hw_itypes);
  150. /* Initalize on board PIC1 (not PIC0) enable */
  151. CB_PIC_INT0M = 0x0000;
  152. CB_PIC_INT1M = 0x0000;
  153. CB_PIC_INTR = 0x0000;
  154. CB_PIC_INTEN |= CB_PIC_INT1EN;
  155. ME2_PORT2_PMC |= 0x08; /* INTP23/SCK1 mode */
  156. ME2_PORT2_PFC &= ~0x08; /* INTP23 mode */
  157. ME2_INTR(2) &= ~0x08; /* INTP23 falling-edge detect */
  158. ME2_INTF(2) &= ~0x08; /* " */
  159. rte_cb_init_irqs (); /* gbus &c */
  160. }
  161. /* Enable interrupt handling for interrupt IRQ. */
  162. void cb_pic_enable_irq (unsigned irq)
  163. {
  164. CB_PIC_INT1M |= 1 << (irq - CB_PIC_BASE_IRQ);
  165. }
  166. void cb_pic_disable_irq (unsigned irq)
  167. {
  168. CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ));
  169. }
  170. void cb_pic_shutdown_irq (unsigned irq)
  171. {
  172. cb_pic_disable_irq (irq);
  173. if (--cb_pic_active_irqs == 0)
  174. free_irq (IRQ_CB_PIC, 0);
  175. CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ));
  176. }
  177. static irqreturn_t cb_pic_handle_irq (int irq, void *dev_id,
  178. struct pt_regs *regs)
  179. {
  180. irqreturn_t rval = IRQ_NONE;
  181. unsigned status = CB_PIC_INTR;
  182. unsigned enable = CB_PIC_INT1M;
  183. /* Only pay attention to enabled interrupts. */
  184. status &= enable;
  185. CB_PIC_INTEN &= ~CB_PIC_INT1EN;
  186. if (status) {
  187. unsigned mask = 1;
  188. irq = CB_PIC_BASE_IRQ;
  189. do {
  190. /* There's an active interrupt, find out which one,
  191. and call its handler. */
  192. while (! (status & mask)) {
  193. irq++;
  194. mask <<= 1;
  195. }
  196. status &= ~mask;
  197. CB_PIC_INTR = mask;
  198. /* Recursively call handle_irq to handle it. */
  199. handle_irq (irq, regs);
  200. rval = IRQ_HANDLED;
  201. } while (status);
  202. }
  203. CB_PIC_INTEN |= CB_PIC_INT1EN;
  204. return rval;
  205. }
  206. static void irq_nop (unsigned irq) { }
  207. static unsigned cb_pic_startup_irq (unsigned irq)
  208. {
  209. int rval;
  210. if (cb_pic_active_irqs == 0) {
  211. rval = request_irq (IRQ_CB_PIC, cb_pic_handle_irq,
  212. SA_INTERRUPT, "cb_pic_handler", 0);
  213. if (rval != 0)
  214. return rval;
  215. }
  216. cb_pic_active_irqs++;
  217. cb_pic_enable_irq (irq);
  218. return 0;
  219. }
  220. /* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
  221. INITS (which is terminated by an entry with the name field == 0). */
  222. void __init cb_pic_init_irq_types (struct cb_pic_irq_init *inits,
  223. struct hw_interrupt_type *hw_irq_types)
  224. {
  225. struct cb_pic_irq_init *init;
  226. for (init = inits; init->name; init++) {
  227. struct hw_interrupt_type *hwit = hw_irq_types++;
  228. hwit->typename = init->name;
  229. hwit->startup = cb_pic_startup_irq;
  230. hwit->shutdown = cb_pic_shutdown_irq;
  231. hwit->enable = cb_pic_enable_irq;
  232. hwit->disable = cb_pic_disable_irq;
  233. hwit->ack = irq_nop;
  234. hwit->end = irq_nop;
  235. /* Initialize kernel IRQ infrastructure for this interrupt. */
  236. init_irq_handlers(init->base, init->num, init->interval, hwit);
  237. }
  238. }