| /* |
| * 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/config.h> |
| #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. */ |
| } |
| |
| EXPORT_SYMBOL(machine_restart); |
| |
| /* 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"); |
| } |
| |
| EXPORT_SYMBOL(machine_halt); |
| |
| void machine_power_off (void) |
| { |
| machine_halt (); |
| } |
| |
| EXPORT_SYMBOL(machine_power_off); |
| |
| |
| /* 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 */ |
| } |