Linux-2.6.12-rc2
[linux-2.6/kvm.git] / arch / v850 / kernel / as85ep1.c
blob4059b1df11b57431c99d6e7b3f1ec0d273f7bb94
1 /*
2 * arch/v850/kernel/as85ep1.c -- AS85EP1 V850E evaluation chip/board
4 * Copyright (C) 2002,03 NEC Electronics Corporation
5 * Copyright (C) 2002,03 Miles Bader <miles@gnu.org>
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.
11 * Written by Miles Bader <miles@gnu.org>
14 #include <linux/config.h>
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/init.h>
18 #include <linux/bootmem.h>
19 #include <linux/major.h>
20 #include <linux/irq.h>
22 #include <asm/machdep.h>
23 #include <asm/atomic.h>
24 #include <asm/page.h>
25 #include <asm/v850e_timer_d.h>
26 #include <asm/v850e_uart.h>
28 #include "mach.h"
31 /* SRAM and SDRAM are vaguely contiguous (with a big hole in between; see
32 mach_reserve_bootmem for details); use both as one big area. */
33 #define RAM_START SRAM_ADDR
34 #define RAM_END (SDRAM_ADDR + SDRAM_SIZE)
36 /* The bits of this port are connected to an 8-LED bar-graph. */
37 #define LEDS_PORT 4
40 static void as85ep1_led_tick (void);
42 extern char _intv_copy_src_start, _intv_copy_src_end;
43 extern char _intv_copy_dst_start;
46 void __init mach_early_init (void)
48 #ifndef CONFIG_ROM_KERNEL
49 const u32 *src;
50 register u32 *dst asm ("ep");
51 #endif
53 AS85EP1_CSC(0) = 0x0403;
54 AS85EP1_BCT(0) = 0xB8B8;
55 AS85EP1_DWC(0) = 0x0104;
56 AS85EP1_BCC = 0x0012;
57 AS85EP1_ASC = 0;
58 AS85EP1_LBS = 0x00A9;
60 AS85EP1_PORT_PMC(6) = 0xFF; /* valid A0,A1,A20-A25 */
61 AS85EP1_PORT_PMC(7) = 0x0E; /* valid CS1-CS3 */
62 AS85EP1_PORT_PMC(9) = 0xFF; /* valid D16-D23 */
63 AS85EP1_PORT_PMC(10) = 0xFF; /* valid D24-D31 */
65 AS85EP1_RFS(1) = 0x800c;
66 AS85EP1_RFS(3) = 0x800c;
67 AS85EP1_SCR(1) = 0x20A9;
68 AS85EP1_SCR(3) = 0x20A9;
70 #ifndef CONFIG_ROM_KERNEL
71 /* The early chip we have is buggy, and writing the interrupt
72 vectors into low RAM may screw up, so for non-ROM kernels, we
73 only rely on the reset vector being downloaded, and copy the
74 rest of the interrupt vectors into place here. The specific bug
75 is that writing address N, where (N & 0x10) == 0x10, will _also_
76 write to address (N - 0x10). We avoid this (effectively) by
77 writing in 16-byte chunks backwards from the end. */
79 AS85EP1_IRAMM = 0x3; /* "write-mode" for the internal instruction memory */
81 src = (u32 *)(((u32)&_intv_copy_src_end - 1) & ~0xF);
82 dst = (u32 *)&_intv_copy_dst_start
83 + (src - (u32 *)&_intv_copy_src_start);
84 do {
85 u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3];
86 dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3;
87 dst -= 4;
88 src -= 4;
89 } while (src > (u32 *)&_intv_copy_src_start);
91 AS85EP1_IRAMM = 0x0; /* "read-mode" for the internal instruction memory */
92 #endif /* !CONFIG_ROM_KERNEL */
94 v850e_intc_disable_irqs ();
97 void __init mach_setup (char **cmdline)
99 AS85EP1_PORT_PMC (LEDS_PORT) = 0; /* Make the LEDs port an I/O port. */
100 AS85EP1_PORT_PM (LEDS_PORT) = 0; /* Make all the bits output pins. */
101 mach_tick = as85ep1_led_tick;
104 void __init mach_get_physical_ram (unsigned long *ram_start,
105 unsigned long *ram_len)
107 *ram_start = RAM_START;
108 *ram_len = RAM_END - RAM_START;
111 /* Convenience macros. */
112 #define SRAM_END (SRAM_ADDR + SRAM_SIZE)
113 #define SDRAM_END (SDRAM_ADDR + SDRAM_SIZE)
115 void __init mach_reserve_bootmem ()
117 if (SDRAM_ADDR < RAM_END && SDRAM_ADDR > RAM_START)
118 /* We can't use the space between SRAM and SDRAM, so
119 prevent the kernel from trying. */
120 reserve_bootmem (SRAM_END, SDRAM_ADDR - SRAM_END);
123 void mach_gettimeofday (struct timespec *tv)
125 tv->tv_sec = 0;
126 tv->tv_nsec = 0;
129 void __init mach_sched_init (struct irqaction *timer_action)
131 /* Start hardware timer. */
132 v850e_timer_d_configure (0, HZ);
133 /* Install timer interrupt handler. */
134 setup_irq (IRQ_INTCMD(0), timer_action);
137 static struct v850e_intc_irq_init irq_inits[] = {
138 { "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
139 { "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 },
140 { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 },
141 { "SRE", IRQ_INTSRE(0), IRQ_INTSRE_NUM, 3, 3 },
142 { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 3, 4 },
143 { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 3, 5 },
144 { 0 }
146 #define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
148 static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
150 void __init mach_init_irqs (void)
152 v850e_intc_init_irq_types (irq_inits, hw_itypes);
155 void machine_restart (char *__unused)
157 #ifdef CONFIG_RESET_GUARD
158 disable_reset_guard ();
159 #endif
160 asm ("jmp r0"); /* Jump to the reset vector. */
163 EXPORT_SYMBOL(machine_restart);
165 void machine_halt (void)
167 #ifdef CONFIG_RESET_GUARD
168 disable_reset_guard ();
169 #endif
170 local_irq_disable (); /* Ignore all interrupts. */
171 AS85EP1_PORT_IO (LEDS_PORT) = 0xAA; /* Note that we halted. */
172 for (;;)
173 asm ("halt; nop; nop; nop; nop; nop");
176 EXPORT_SYMBOL(machine_halt);
178 void machine_power_off (void)
180 machine_halt ();
183 EXPORT_SYMBOL(machine_power_off);
185 /* Called before configuring an on-chip UART. */
186 void as85ep1_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
188 /* Make the shared uart/port pins be uart pins. */
189 AS85EP1_PORT_PMC(3) |= (0x5 << chan);
191 /* The AS85EP1 connects some general-purpose I/O pins on the CPU to
192 the RTS/CTS lines of UART 1's serial connection. I/O pins P53
193 and P54 are RTS and CTS respectively. */
194 if (chan == 1) {
195 /* Put P53 & P54 in I/O port mode. */
196 AS85EP1_PORT_PMC(5) &= ~0x18;
197 /* Make P53 an output, and P54 an input. */
198 AS85EP1_PORT_PM(5) |= 0x10;
202 /* Minimum and maximum bounds for the moving upper LED boundary in the
203 clock tick display. */
204 #define MIN_MAX_POS 0
205 #define MAX_MAX_POS 7
207 /* There are MAX_MAX_POS^2 - MIN_MAX_POS^2 cycles in the animation, so if
208 we pick 6 and 0 as above, we get 49 cycles, which is when divided into
209 the standard 100 value for HZ, gives us an almost 1s total time. */
210 #define TICKS_PER_FRAME \
211 (HZ / (MAX_MAX_POS * MAX_MAX_POS - MIN_MAX_POS * MIN_MAX_POS))
213 static void as85ep1_led_tick ()
215 static unsigned counter = 0;
217 if (++counter == TICKS_PER_FRAME) {
218 static int pos = 0, max_pos = MAX_MAX_POS, dir = 1;
220 if (dir > 0 && pos == max_pos) {
221 dir = -1;
222 if (max_pos == MIN_MAX_POS)
223 max_pos = MAX_MAX_POS;
224 else
225 max_pos--;
226 } else {
227 if (dir < 0 && pos == 0)
228 dir = 1;
230 if (pos + dir <= max_pos) {
231 /* Each bit of port 0 has a LED. */
232 set_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT));
233 pos += dir;
234 clear_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT));
238 counter = 0;