PageRenderTime 26ms CodeModel.GetById 12ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/v850/kernel/rte_me2_cb.c

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