From: Jun S. <ju...@us...> - 2001-09-22 04:27:18
|
Update of /cvsroot/linux-mips/linux/arch/mips/vr4181/osprey In directory usw-pr-cvs1:/tmp/cvs-serv27047/arch/mips/vr4181/osprey Added Files: Makefile dbg_io.c int_handler.S prom.c reset.c setup.c Log Message: Initial re-structuring of vr41xx directory. More are coming to actually get Osprey/Eagle building and running. --- NEW FILE: Makefile --- # # Makefile for common code of NEC Osprey board # # Note! Dependencies are done automagically by 'make dep', which also # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # .S.s: $(CPP) $(CFLAGS) $< -o $*.s .S.o: $(CC) $(CFLAGS) -c $< -o $*.o O_TARGET:= osprey.o obj-y := setup.o prom.o reset.o int_handler.o dbg_io.o include $(TOPDIR)/Rules.make --- NEW FILE: dbg_io.c --- #include <linux/config.h> #if defined(CONFIG_REMOTE_DEBUG) /* --- CONFIG --- */ typedef unsigned char uint8; typedef unsigned int uint32; /* --- END OF CONFIG --- */ #define UART16550_BAUD_2400 2400 #define UART16550_BAUD_4800 4800 #define UART16550_BAUD_9600 9600 #define UART16550_BAUD_19200 19200 #define UART16550_BAUD_38400 38400 #define UART16550_BAUD_57600 57600 #define UART16550_BAUD_115200 115200 #define UART16550_PARITY_NONE 0 #define UART16550_PARITY_ODD 0x08 #define UART16550_PARITY_EVEN 0x18 #define UART16550_PARITY_MARK 0x28 #define UART16550_PARITY_SPACE 0x38 #define UART16550_DATA_5BIT 0x0 #define UART16550_DATA_6BIT 0x1 #define UART16550_DATA_7BIT 0x2 #define UART16550_DATA_8BIT 0x3 #define UART16550_STOP_1BIT 0x0 #define UART16550_STOP_2BIT 0x4 /* ----------------------------------------------------- */ /* === CONFIG === */ /* [jsun] we use the debug board serial port for kdb */ #define BASE 0xb7fffff0 #define MAX_BAUD 115200 #define REG_OFFSET 1 static int remoteDebugInitialized = 1; /* === END OF CONFIG === */ /* register offset */ #define OFS_RCV_BUFFER 0 #define OFS_TRANS_HOLD 0 #define OFS_SEND_BUFFER 0 #define OFS_INTR_ENABLE (1*REG_OFFSET) #define OFS_INTR_ID (2*REG_OFFSET) #define OFS_DATA_FORMAT (3*REG_OFFSET) #define OFS_LINE_CONTROL (3*REG_OFFSET) #define OFS_MODEM_CONTROL (4*REG_OFFSET) #define OFS_RS232_OUTPUT (4*REG_OFFSET) #define OFS_LINE_STATUS (5*REG_OFFSET) #define OFS_MODEM_STATUS (6*REG_OFFSET) #define OFS_RS232_INPUT (6*REG_OFFSET) #define OFS_SCRATCH_PAD (7*REG_OFFSET) #define OFS_DIVISOR_LSB (0*REG_OFFSET) #define OFS_DIVISOR_MSB (1*REG_OFFSET) /* memory-mapped read/write of the port */ #define UART16550_READ(y) (*((volatile uint8*)(BASE + y))) #define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z) void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) { /* disable interrupts */ UART16550_WRITE(OFS_INTR_ENABLE, 0); /* set up buad rate */ { uint32 divisor; /* set DIAB bit */ UART16550_WRITE(OFS_LINE_CONTROL, 0x80); /* set divisor */ divisor = MAX_BAUD / baud; UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); /* clear DIAB bit */ UART16550_WRITE(OFS_LINE_CONTROL, 0x0); } /* set data format */ UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); } uint8 getDebugChar(void) { if (!remoteDebugInitialized) { remoteDebugInitialized = 1; debugInit(UART16550_BAUD_38400, UART16550_DATA_8BIT, UART16550_PARITY_NONE, UART16550_STOP_1BIT); } while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); return UART16550_READ(OFS_RCV_BUFFER); } int putDebugChar(uint8 byte) { if (!remoteDebugInitialized) { remoteDebugInitialized = 1; debugInit(UART16550_BAUD_38400, UART16550_DATA_8BIT, UART16550_PARITY_NONE, UART16550_STOP_1BIT); } while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); UART16550_WRITE(OFS_SEND_BUFFER, byte); return 1; } #endif --- NEW FILE: int_handler.S --- /* * linux/arch/mips/vr41xx/int-handler.S * * Copyright (C) 1995, 1996, 1997 Paul M. Antoine and Harald Koerfgen * * Written by Ralf Baechle and Andreas Busse, modified for DECStation * support by Paul Antoine and Harald Koerfgen. * * completly rewritten: * Copyright (C) 1998 Harald Koerfgen * * Adapted to the VR4181 and almost entirely rewritten: * Copyright (C) 1999 Bradley D. LaRonde and Michael Klar * * 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. * */ #include <asm/asm.h> #include <asm/regdef.h> #include <asm/mipsregs.h> #include <asm/stackframe.h> #include <asm/vr4181/vr4181.h> /* jsun HACK */ #define CONFIG_CPU_VR4181 y .text .set noreorder /* * Interrupt handler for VR41xx based devices * * In a zealous attempt to save CPU cycles, we don't worry about making the code * readable and instead optimize for the most frequently occurring ints (the * timer int IRQ 3 and the ICU ints that cascade off IRQ 2), while keeping a * priority scheme that actually makes some sense: * * Highest ---- CPU IP3 - Int1: RTClong1 IRQ 3 * CPU IP4 - Int2: RTClong2 IRQ 4 * CPU IP5 - Int3: HSP IRQ 5 * CPU IP6 - Int4: unused IRQ 6 * CPU IP7 - counter IRQ 7 * ICU SYSINT1REG bit 0 IRQ 8 * ... * ICU SYSINT1REG bit 7 IRQ 15 * GPIO 0 IRQ 40 * ... * GPIO 31 IRQ 71 * ICU SYSINT1REG bit 9 IRQ 17 * ... * ICU SYSINT1REG bit 15 IRQ 23 * ICU SYSINT2REG bit 0 IRQ 24 * ... * ICU SYSINT2REG bit 15 IRQ 39 * CPU IP0 - software 1 IRQ 0 * Lowest --- CPU IP1 - software 2 IRQ 1 * * IRQ 2 is the cascade to the ICU (CPU IP2, Int0) * * then we just return, if multiple IRQs are pending then we will just take * another exception immediately. * */ .align 5 NESTED(vr41xx_handle_irq, PT_SIZE, ra) .set noat SAVE_ALL CLI .set at .set noreorder // Get the pending interrupts mfc0 t0,CP0_CAUSE // Isolate the allowed ones by anding with irq mask mfc0 t2,CP0_STATUS andi t0,0xff00 and t0,t2 andi t1,t0,0x0800 // check for IRQ 3 bnez t1,handle_it li a0,3 andi t1,t0,0xf000 // check for IRQ 4-7 bnez t1,1f andi t1,t0,0x0400 // check for IRQ 2 bnez t1,icu_int lui t3,%hi(VR4181_SYSINT1REG) beqz t0,go_spurious // check for IRQ 0-1 li a0,-1 sll t0,4 1: andi t1,t0,0x1000 srl t0,1 beqz t1,1b addiu a0,1 b handle_it nop /* * In the interest of speed, we implement a 3 tier check for which bit * in the ICU level 1 interrupt registers is active. First, we determine * which 16-bit register (1 or 2). Second, we narrow it down to which * group of 4 bits, then we get the exact bit. a0 holds the IRQ number. * Since we always add both 4 and 1 to a0, we initalize it to 5 less than * the lowest IRQ number for each ICU level 1 register */ icu_int: // see delay slot instruction from branch that got us here lhu t0,%lo(VR4181_SYSINT1REG)(t3) lhu t2,%lo(VR4181_MSYSINT1REG)(t3) /* * OK, this next instruction deserves some explanation. The timer interrupt * (a few others are similar, but the timer interrupt happens... well... all * the time) comes in on both CPU int1 (IRQ 3) and ICU SYSINT1 bit 2 (IRQ 10), * and since we check IRQ 3 before even loading the value of SYSINT1, it is * possible for a timer interrupt to occur between the time we load CP0_STATUS to * check IRQ 3 and the time we load SYSINT1REG to check IRQ 10. This will only * happen when we're in the middle of servicing another interrupt, so we just * ignore IRQ 10 (and a few others that behave similarly) and keep looking for * the interrupt that actually caused the exception. When we re-enable * interrupts, the timer int will immediately re-trigger and be detected as IRQ 3. */ and t0,0xfffb and t0,t2 beqz t0,2f andi t1,t0,0x01ff // check for GIU int xori t1,0x0100 // (and no higher priority SYSINT1 int) bnez t1,1f li a0,3 // if it is, break out further #ifdef CONFIG_CPU_VR4181 lui t3,%hi(VR4181_GPINTMSK) lhu t0,%lo(VR4181_GPINTMSK)(t3) lhu t2,%lo(VR4181_GPINTSTAT)(t3) xori t0, 0xffff and t0,t2 bnez t0,1f li a0,35 #else lhu t0,%lo(VR4181_GIUINTLREG)(t3) lhu t2,%lo(VR4181_MGIUINTLREG)(t3) li a0,35 and t0,t2 bnez t0,1f lhu t2,%lo(VR4181_MGIUINTHREG)(t3) lhu t0,%lo(VR4181_GIUINTHREG)(t3) // load delay stall and t0,t2 bnez t0,1f li a0,51 #endif go_spurious: j spurious_interrupt nop 2: lhu t0,%lo(VR4181_SYSINT2REG)(t3) lhu t2,%lo(VR4181_MSYSINT2REG)(t3) #ifdef CONFIG_CPU_VR4181 and t0,0xfffe // see above comment #else and t0,0xfffa // see above comment #endif and t0,t2 beqz t0,go_spurious li a0,19 1: andi t1,t0,0x000f addi a0,4 beqzl t1,1b // the beqzl will cancel the last srl t0,4 // shift so we don't lose the bits 1: andi t1,t0,0x0001 addi a0,1 beqz t1,1b srl t0,1 handle_it: jal do_IRQ move a1,sp j ret_from_irq nop END(vr41xx_handle_irq) --- NEW FILE: prom.c --- /*********************************************************************** * * Copyright 2001 MontaVista Software Inc. * Author: js...@mv... or js...@ju... * * arch/mips/vr4181/osprey/prom.c * prom code for osprey. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * *********************************************************************** */ #include <linux/init.h> #include <linux/config.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/mm.h> #include <linux/bootmem.h> #include <asm/bootinfo.h> #include <asm/addrspace.h> char arcs_cmdline[COMMAND_LINE_SIZE]; /* * [jsun] right now we assume it is the nec debug monitor, which does * not pass any arguments. */ void __init prom_init() { strcpy(arcs_cmdline, "ether=0,0x03fe0300,eth0 " // strcpy(arcs_cmdline, "ether=0,0x0300,eth0 " "video=vr4181fb:xres:240,yres:320,bpp:8"); mips_machgroup = MACH_GROUP_NEC_VR41XX; mips_machtype = MACH_NEC_OSPREY; /* 16MB fixed */ add_memory_region(0, 16 << 20, BOOT_MEM_RAM); } void __init prom_free_prom_memory(void) { } void __init prom_fixup_mem_map(unsigned long start, unsigned long end) { } --- NEW FILE: reset.c --- /* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * Copyright (C) 1997, 2001 Ralf Baechle * Copyright 2001 MontaVista Software Inc. * Author: js...@mv... or js...@ju... */ #include <linux/sched.h> #include <linux/mm.h> #include <asm/io.h> #include <asm/pgtable.h> #include <asm/processor.h> #include <asm/reboot.h> #include <asm/system.h> void nec_osprey_restart(char *command) { set_cp0_status((ST0_BEV | ST0_ERL), (ST0_BEV | ST0_ERL)); set_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); flush_cache_all(); write_32bit_cp0_register(CP0_WIRED, 0); __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); } void nec_osprey_halt(void) { printk(KERN_NOTICE "\n** You can safely turn off the power\n"); while (1) __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0"); } void nec_osprey_power_off(void) { nec_osprey_halt(); } --- NEW FILE: setup.c --- /* * linux/arch/mips/vr4181/setup.c * * VR41xx setup routines * * Copyright (C) 1999 Bradley D. LaRonde * Copyright (C) 1999, 2000 Michael Klar * * 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. * */ #include <linux/config.h> #include <linux/console.h> #include <linux/ide.h> #include <linux/init.h> #include <linux/delay.h> #include <asm/reboot.h> #include <asm/vr4181/vr4181.h> #include <asm/io.h> #include <linux/pc_keyb.h> extern struct kbd_ope no_kbd_ops; struct semaphore vr4181_dma_sem; // This enables the CF hacks below, to be replaced with real CF driver eventually #if defined(CONFIG_EVEREX_FREESTYLE) #define CF_HACK #else // If CF doesn't work on your device, try changing this to #define: #undef CF_HACK #endif #ifdef CONFIG_TCIC #define TCIC_BASE 0x240 #define TCIC_MODE 0x08 #define TCIC_AUX 0x0E #define TCIC_MODE_PGMMASK 0x1f #define TCIC_AUX_ILOCK (6<<5) #define TCIC_ILOCK_CRESET 0x04 #endif extern void nec_osprey_restart(char* c); extern void nec_osprey_halt(void); extern void nec_osprey_power_off(void); #if defined(CF_HACK) || defined(CONFIG_I82365) void __init put_cf_reg(unsigned char reg, unsigned char val) { #ifdef CONFIG_CPU_VR4181 *VR4181_PCCARDINDEX = reg; barrier(); *VR4181_PCCARDDATA = val; #else outb(reg, 0x3e0); outb(val, 0x3e1); #endif } #endif #if defined(CONFIG_NEC_OSPREY) || defined(CONFIG_IBM_WORKPAD) || \ defined(CONFIG_NEC_MOBILEGEAR2_R300) || \ defined(CONFIG_NEC_MOBILEGEAR2_R310) || \ defined(CONFIG_NEC_MOBILEGEAR2_R430) || \ defined(CONFIG_NEC_MOBILEGEAR2_R530) || \ defined(CONFIG_NEC_MOBILEGEAR2_R700) || \ defined(CONFIG_NEC_MOBILEGEAR2_R730) || \ defined(CONFIG_DOCOMO_SIGMARION) || \ defined(CONFIG_AGENDA_VR3) // extern void platdep_setup(void); void platdep_setup(void) {} #else void platdep_setup(void) {} #endif void __init nec_osprey_setup(void) { mips_io_port_base = VR4181_PORT_BASE; isa_slot_offset = VR4181_ISAMEM_BASE; #ifdef CONFIG_BLK_DEV_IDE ide_ops = &vr4181_ide_ops; #endif #ifdef CONFIG_FB conswitchp = &dummy_con; #endif // reset the PC card, and power off #ifdef CONFIG_I82365 put_cf_reg(0x03, 0x20); // socket 0 put_cf_reg(0x43, 0x20); // socket 1 put_cf_reg(0x02, 0x00); // socket 0 put_cf_reg(0x42, 0x00); // socket 1 #endif #ifdef CONFIG_TCIC { u_char mode; mode = (inb(TCIC_BASE+TCIC_MODE) & TCIC_MODE_PGMMASK) | TCIC_AUX_ILOCK; outb(mode, TCIC_BASE+TCIC_MODE); outb(TCIC_ILOCK_CRESET, TCIC_BASE+TCIC_AUX); } #endif #ifdef CF_HACK // this is a nasty hack to initialize the CF registers, eventually this // is to be replaced with a real CF controller driver { unsigned char i; unsigned char cfinitdata[] = { 0x90, 0x63, 0x00, 0x35, 0x00, 0x55, 0x76, 0x03, 0x77, 0x03, 0x70, 0x01, 0x78, 0x01, 0x10, 0x00, 0x1f, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0x20, 0x00, 0xe4, 0x00, 0xe0, 0x3f, 0x00, 0x02, 0xe5, 0x00, 0xed, 0x00, 0x1b, 0x3f, 0x00, 0x00, 0xee, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00 }; #ifdef CONFIG_CPU_VR4181 // Enable CF, not key scan. *VR4181_KEYEN = 0; // Unmask all CF IRQs for now except for IRQ 3 (which makes it fail) // I think the bit sense in reversed from what User Manual states *VR4181_INTMSKREG = 0xdeb0; // Set CF wait states. *VR4181_CFG_REG_1 = 1; #else #warning "Generic CF hack in use, assuming non-i82365 registers set up prior to boot" #endif put_cf_reg(0x02, 0x10); udelay(1); for (i = 0x02; i < 0x36; i++) put_cf_reg(i, cfinitdata[i-2]); // enable the IO and mem windows, now that start and stop values set up put_cf_reg(0x06, 0xdf); // reset the card put_cf_reg(0x03, 0x23); udelay(1); put_cf_reg(0x03, 0x63); mdelay(30); // now set up CF config register (this assumes it is a CF card...) writeb(0x43, ioremap(0x10200, 1)); } #endif _machine_restart = nec_osprey_restart; _machine_halt = nec_osprey_halt; _machine_power_off = nec_osprey_power_off; /* setup resource limit */ ioport_resource.end = 0xffffffff; iomem_resource.end = 0xffffffff; // Insure that vr4181_dma_sem is initialized as unlocked, even // in the case of a failed hibernate/wakeup: init_MUTEX(&vr4181_dma_sem); // Do platform-dependent setup. // This is mostly stuff that doesn't fit well anywhere else. platdep_setup(); /* [jsun] hack */ /* printk("[jsun] hack to change external ISA control register, %x -> %x\n", (*VR4181_XISACTL), (*VR4181_XISACTL) | 0x2); *VR4181_XISACTL |= 0x2; */ // *VR4181_GPHIBSTH = 0x2000; // *VR4181_GPMD0REG = 0x00c0; // *VR4181_GPINTEN = 1<<6; /* [jsun] I believe this will get the interrupt type right * for the ether port. */ *VR4181_GPINTTYPL = 0x3000; } |