|
|
/*
|
|
|
* include/asm-v850/rte_cb.c -- Midas lab RTE-CB series of evaluation boards
|
|
|
*
|
|
|
* Copyright (C) 2001,02,03 NEC Electronics Corporation
|
|
|
* Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
|
|
|
*
|
|
|
* This file is subject to the terms and conditions of the GNU General
|
|
|
* Public License. See the file COPYING in the main directory of this
|
|
|
* archive for more details.
|
|
|
*
|
|
|
* Written by Miles Bader <miles@gnu.org>
|
|
|
*/
|
|
|
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/irq.h>
|
|
|
#include <linux/fs.h>
|
|
|
#include <linux/module.h>
|
|
|
|
|
|
#include <asm/machdep.h>
|
|
|
#include <asm/v850e_uart.h>
|
|
|
|
|
|
#include "mach.h"
|
|
|
|
|
|
static void led_tick (void);
|
|
|
|
|
|
/* LED access routines. */
|
|
|
extern unsigned read_leds (int pos, char *buf, int len);
|
|
|
extern unsigned write_leds (int pos, const char *buf, int len);
|
|
|
|
|
|
#ifdef CONFIG_RTE_CB_MULTI
|
|
|
extern void multi_init (void);
|
|
|
#endif
|
|
|
|
|
|
|
|
|
void __init rte_cb_early_init (void)
|
|
|
{
|
|
|
v850e_intc_disable_irqs ();
|
|
|
|
|
|
#ifdef CONFIG_RTE_CB_MULTI
|
|
|
multi_init ();
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
void __init mach_setup (char **cmdline)
|
|
|
{
|
|
|
#ifdef CONFIG_RTE_MB_A_PCI
|
|
|
/* Probe for Mother-A, and print a message if we find it. */
|
|
|
*(volatile unsigned long *)MB_A_SRAM_ADDR = 0xDEADBEEF;
|
|
|
if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0xDEADBEEF) {
|
|
|
*(volatile unsigned long *)MB_A_SRAM_ADDR = 0x12345678;
|
|
|
if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0x12345678)
|
|
|
printk (KERN_INFO
|
|
|
" NEC SolutionGear/Midas lab"
|
|
|
" RTE-MOTHER-A motherboard\n");
|
|
|
}
|
|
|
#endif /* CONFIG_RTE_MB_A_PCI */
|
|
|
|
|
|
mach_tick = led_tick;
|
|
|
}
|
|
|
|
|
|
void machine_restart (char *__unused)
|
|
|
{
|
|
|
#ifdef CONFIG_RESET_GUARD
|
|
|
disable_reset_guard ();
|
|
|
#endif
|
|
|
asm ("jmp r0"); /* Jump to the reset vector. */
|
|
|
}
|
|
|
|
|
|
/* This says `HALt.' in LEDese. */
|
|
|
static unsigned char halt_leds_msg[] = { 0x76, 0x77, 0x38, 0xF8 };
|
|
|
|
|
|
void machine_halt (void)
|
|
|
{
|
|
|
#ifdef CONFIG_RESET_GUARD
|
|
|
disable_reset_guard ();
|
|
|
#endif
|
|
|
|
|
|
/* Ignore all interrupts. */
|
|
|
local_irq_disable ();
|
|
|
|
|
|
/* Write a little message. */
|
|
|
write_leds (0, halt_leds_msg, sizeof halt_leds_msg);
|
|
|
|
|
|
/* Really halt. */
|
|
|
for (;;)
|
|
|
asm ("halt; nop; nop; nop; nop; nop");
|
|
|
}
|
|
|
|
|
|
void machine_power_off (void)
|
|
|
{
|
|
|
machine_halt ();
|
|
|
}
|
|
|
|
|
|
|
|
|
/* Animated LED display for timer tick. */
|
|
|
|
|
|
#define TICK_UPD_FREQ 6
|
|
|
static int tick_frames[][10] = {
|
|
|
{ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, -1 },
|
|
|
{ 0x63, 0x5c, -1 },
|
|
|
{ 0x5c, 0x00, -1 },
|
|
|
{ 0x63, 0x00, -1 },
|
|
|
{ -1 }
|
|
|
};
|
|
|
|
|
|
static void led_tick ()
|
|
|
{
|
|
|
static unsigned counter = 0;
|
|
|
|
|
|
if (++counter == (HZ / TICK_UPD_FREQ)) {
|
|
|
/* Which frame we're currently displaying for each digit. */
|
|
|
static unsigned frame_nums[LED_NUM_DIGITS] = { 0 };
|
|
|
/* Display image. */
|
|
|
static unsigned char image[LED_NUM_DIGITS] = { 0 };
|
|
|
unsigned char prev_image[LED_NUM_DIGITS];
|
|
|
int write_to_leds = 1; /* true if we should actually display */
|
|
|
int digit;
|
|
|
|
|
|
/* We check to see if the physical LEDs contains what we last
|
|
|
wrote to them; if not, we suppress display (this is so that
|
|
|
users can write to the LEDs, and not have their output
|
|
|
overwritten). As a special case, we start writing again if
|
|
|
all the LEDs are blank, or our display image is all zeros
|
|
|
(indicating that this is the initial update, when the actual
|
|
|
LEDs might contain random data). */
|
|
|
read_leds (0, prev_image, LED_NUM_DIGITS);
|
|
|
for (digit = 0; digit < LED_NUM_DIGITS; digit++)
|
|
|
if (image[digit] != prev_image[digit]
|
|
|
&& image[digit] && prev_image[digit])
|
|
|
{
|
|
|
write_to_leds = 0;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
/* Update display image. */
|
|
|
for (digit = 0;
|
|
|
digit < LED_NUM_DIGITS && tick_frames[digit][0] >= 0;
|
|
|
digit++)
|
|
|
{
|
|
|
int frame = tick_frames[digit][frame_nums[digit]];
|
|
|
if (frame < 0) {
|
|
|
image[digit] = tick_frames[digit][0];
|
|
|
frame_nums[digit] = 1;
|
|
|
} else {
|
|
|
image[digit] = frame;
|
|
|
frame_nums[digit]++;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (write_to_leds)
|
|
|
/* Write the display image to the physical LEDs. */
|
|
|
write_leds (0, image, LED_NUM_DIGITS);
|
|
|
|
|
|
counter = 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/* Mother-A interrupts. */
|
|
|
|
|
|
#ifdef CONFIG_RTE_GBUS_INT
|
|
|
|
|
|
#define L GBUS_INT_PRIORITY_LOW
|
|
|
#define M GBUS_INT_PRIORITY_MEDIUM
|
|
|
#define H GBUS_INT_PRIORITY_HIGH
|
|
|
|
|
|
static struct gbus_int_irq_init gbus_irq_inits[] = {
|
|
|
#ifdef CONFIG_RTE_MB_A_PCI
|
|
|
{ "MB_A_LAN", IRQ_MB_A_LAN, 1, 1, L },
|
|
|
{ "MB_A_PCI1", IRQ_MB_A_PCI1(0), IRQ_MB_A_PCI1_NUM, 1, L },
|
|
|
{ "MB_A_PCI2", IRQ_MB_A_PCI2(0), IRQ_MB_A_PCI2_NUM, 1, L },
|
|
|
{ "MB_A_EXT", IRQ_MB_A_EXT(0), IRQ_MB_A_EXT_NUM, 1, L },
|
|
|
{ "MB_A_USB_OC",IRQ_MB_A_USB_OC(0), IRQ_MB_A_USB_OC_NUM, 1, L },
|
|
|
{ "MB_A_PCMCIA_OC",IRQ_MB_A_PCMCIA_OC, 1, 1, L },
|
|
|
#endif
|
|
|
{ 0 }
|
|
|
};
|
|
|
#define NUM_GBUS_IRQ_INITS \
|
|
|
((sizeof gbus_irq_inits / sizeof gbus_irq_inits[0]) - 1)
|
|
|
|
|
|
static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS];
|
|
|
|
|
|
#endif /* CONFIG_RTE_GBUS_INT */
|
|
|
|
|
|
|
|
|
void __init rte_cb_init_irqs (void)
|
|
|
{
|
|
|
#ifdef CONFIG_RTE_GBUS_INT
|
|
|
gbus_int_init_irqs ();
|
|
|
gbus_int_init_irq_types (gbus_irq_inits, gbus_hw_itypes);
|
|
|
#endif /* CONFIG_RTE_GBUS_INT */
|
|
|
}
|
|
|
|