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