Update of /cvsroot/linux-vax/kernel-2.4/arch/mips/gt64120/momenco_ocelot
In directory usw-pr-cvs1:/tmp/cvs-serv20728/mips/gt64120/momenco_ocelot
Added Files:
Makefile dbg_io.c int-handler.S irq.c ocelot_pld.h pci.c
prom.c reset.c setup.c
Log Message:
synch 2.4.15 commit 39
--- NEW FILE ---
#
# Makefile for Momentum's Ocelot 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:= momenco_ocelot.o
obj-y += int-handler.o irq.o pci.o prom.o reset.o setup.o
obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o
include $(TOPDIR)/Rules.make
--- NEW FILE ---
#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 second serial port for kdb */
#define BASE 0xbd000020
#define MAX_BAUD 115200
/* === END OF CONFIG === */
#define REG_OFFSET 4
/* 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);
}
static int remoteDebugInitialized = 0;
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_9600,
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 ---
/*
* Copyright 2001 MontaVista Software Inc.
* Author: js...@mv... or js...@ju...
*
* First-level interrupt dispatcher for ocelot board.
*
* 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/config.h>
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
/*
* first level interrupt dispatcher for ocelot board -
* We check for the timer first, then check PCI ints A and D.
* Then check for serial IRQ and fall through.
*/
.align 5
NESTED(ocelot_handle_int, PT_SIZE, sp)
SAVE_ALL
CLI
.set at
mfc0 t0, CP0_CAUSE
mfc0 t2, CP0_STATUS
and t0, t2
andi t1, t0, STATUSF_IP2 /* int0 hardware line */
bnez t1, ll_pri_enet_irq
andi t1, t0, STATUSF_IP3 /* int1 hardware line */
bnez t1, ll_sec_enet_irq
andi t1, t0, STATUSF_IP4 /* int2 hardware line */
bnez t1, ll_uart1_irq
andi t1, t0, STATUSF_IP5 /* int3 hardware line */
bnez t1, ll_cpci_irq
andi t1, t0, STATUSF_IP6 /* int4 hardware line */
bnez t1, ll_galileo_irq
andi t1, t0, STATUSF_IP7 /* cpu timer */
bnez t1, ll_cputimer_irq
/* now look at the extended interrupts */
mfc0 t0, CP0_CAUSE
cfc0 t1, CP0_S1_INTCONTROL
/* shift the mask 8 bits left to line up the bits */
sll t2, t1, 8
and t0, t2
srl t0, t0, 16
andi t1, t0, STATUSF_IP8 /* int6 hardware line */
bnez t1, ll_pmc1_irq
andi t1, t0, STATUSF_IP9 /* int7 hardware line */
bnez t1, ll_pmc2_irq
andi t1, t0, STATUSF_IP10 /* int8 hardware line */
bnez t1, ll_cpci_abcd_irq
andi t1, t0, STATUSF_IP11 /* int9 hardware line */
bnez t1, ll_uart2_irq
.set reorder
/* wrong alarm or masked ... */
j spurious_interrupt
nop
END(ocelot_handle_int)
.align 5
ll_pri_enet_irq:
li a0, 2
move a1, sp
jal do_IRQ
j ret_from_irq
ll_sec_enet_irq:
li a0, 3
move a1, sp
jal do_IRQ
j ret_from_irq
ll_uart1_irq:
li a0, 4
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpci_irq:
li a0, 5
move a1, sp
jal do_IRQ
j ret_from_irq
ll_galileo_irq:
li a0, 6
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cputimer_irq:
li a0, 7
move a1, sp
jal do_IRQ
j ret_from_irq
ll_pmc1_irq:
li a0, 8
move a1, sp
jal do_IRQ
j ret_from_irq
ll_pmc2_irq:
li a0, 9
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpci_abcd_irq:
li a0, 10
move a1, sp
jal do_IRQ
j ret_from_irq
ll_uart2_irq:
li a0, 11
move a1, sp
jal do_IRQ
j ret_from_irq
--- NEW FILE ---
/*
* Copyright (C) 2000 RidgeRun, Inc.
* Author: RidgeRun, Inc.
* gl...@ri..., sk...@ri..., st...@ri...
*
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, js...@mv... or js...@ju...
* Copyright (C) 2000, 2001 Ralf Baechle (ra...@gn...)
*
* 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.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/timex.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/irq.h>
#include <asm/bitops.h>
#include <asm/bootinfo.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mipsregs.h>
#include <asm/system.h>
static spinlock_t rm7000_irq_lock = SPIN_LOCK_UNLOCKED;
/* Function for careful CP0 interrupt mask access */
static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in)
{
unsigned long status;
unsigned clr_mask;
unsigned set_mask;
/* do the low 8 bits first */
clr_mask = 0xff & clr_mask_in;
set_mask = 0xff & set_mask_in;
status = read_32bit_cp0_register(CP0_STATUS);
status &= ~((clr_mask & 0xFF) << 8);
status |= (set_mask & 0xFF) << 8;
write_32bit_cp0_register(CP0_STATUS, status);
/* do the high 8 bits */
clr_mask = 0xff & (clr_mask_in >> 8);
set_mask = 0xff & (set_mask_in >> 8);
status = read_32bit_cp0_set1_register(CP0_S1_INTCONTROL);
status &= ~((clr_mask & 0xFF) << 8);
status |= (set_mask & 0xFF) << 8;
write_32bit_cp0_set1_register(CP0_S1_INTCONTROL, status);
}
static inline void mask_irq(unsigned int irq)
{
modify_cp0_intmask(irq, 0);
}
static inline void unmask_irq(unsigned int irq)
{
modify_cp0_intmask(0, irq);
}
static void enable_cp7000_irq(unsigned int irq)
{
unsigned long flags;
spin_lock_irqsave(&rm7000_irq_lock, flags);
unmask_irq(1 << irq);
spin_unlock_irqrestore(&rm7000_irq_lock, flags);
}
static unsigned int startup_cp7000_irq(unsigned int irq)
{
enable_cp7000_irq(irq);
return 0; /* never anything pending */
}
static void disable_cp7000_irq(unsigned int irq)
{
unsigned long flags;
spin_lock_irqsave(&rm7000_irq_lock, flags);
mask_irq(1 << irq);
spin_unlock_irqrestore(&rm7000_irq_lock, flags);
}
#define shutdown_cp7000_irq disable_cp7000_irq
static void mask_and_ack_cp7000_irq(unsigned int irq)
{
mask_irq(1 << irq);
}
static void end_cp7000_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
unmask_irq(1 << irq);
}
static struct hw_interrupt_type cp7000_hpcdma_irq_type = {
"CP7000",
startup_cp7000_irq,
shutdown_cp7000_irq,
enable_cp7000_irq,
disable_cp7000_irq,
mask_and_ack_cp7000_irq,
end_cp7000_irq,
NULL
};
extern asmlinkage void ocelot_handle_int(void);
extern void gt64120_irq_init(void);
void __init init_IRQ(void)
{
int i;
/*
* Clear all of the interrupts while we change the able around a bit.
* int-handler is not on bootstrap
*/
clear_cp0_status(ST0_IM | ST0_BEV);
__cli();
/* Sets the first-level interrupt dispatcher. */
set_except_vector(0, ocelot_handle_int);
init_generic_irq();
for (i = 0; i <= 15; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = 0;
irq_desc[i].depth = 1;
irq_desc[i].handler = &cp7000_hpcdma_irq_type;
}
gt64120_irq_init();
#ifdef CONFIG_REMOTE_DEBUG
printk("start kgdb ...\n");
set_debug_traps();
breakpoint(); /* you may move this line to whereever you want :-) */
#endif
#ifdef CONFIG_GDB_CONSOLE
register_gdb_console();
#endif
}
--- NEW FILE ---
/*
* $Id: ocelot_pld.h,v 1.1 2002/04/10 14:47:29 atp Exp $
*
* Ocelot Board Register Definitions
*
* (C) 2001 Red Hat, Inc.
*
* GPL'd
*
*/
#ifndef __MOMENCO_OCELOT_PLD_H__
#define __MOMENCO_OCELOT_PLD_H__
#define OCELOT_CS0_ADDR (0xe0020000)
#define OCELOT_REG_BOARDREV (0)
#define OCELOT_REG_PLD1_ID (1)
#define OCELOT_REG_PLD2_ID (2)
#define OCELOT_REG_RESET_STATUS (3)
#define OCELOT_REG_BOARD_STATUS (4)
#define OCELOT_REG_CPCI_ID (5)
#define OCELOT_REG_I2C_CTRL (8)
#define OCELOT_REG_EEPROM_MODE (9)
#define OCELOT_REG_INTMASK (10)
#define OCELOT_REG_INTSTATUS (11)
#define OCELOT_REG_INTSET (12)
#define OCELOT_REG_INTCLR (13)
#define OCELOT_PLD_WRITE(x, y) writeb(x, OCELOT_CS0_ADDR + OCELOT_REG_##y)
#define OCELOT_PLD_READ(x) readb(OCELOT_CS0_ADDR + OCELOT_REG_##x)
#endif /* __MOMENCO_OCELOT_PLD_H__ */
--- NEW FILE ---
/*
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, js...@mv... or js...@ju...
*
* arch/mips/gt64120/momenco_ocelot/pci.c
* Board-specific PCI routines for gt64120 controller.
*
* 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/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/init.h>
#include <asm/pci.h>
void __init gt64120_board_pcibios_fixup_bus(struct pci_bus *bus)
{
struct pci_bus *current_bus = bus;
struct pci_dev *devices;
struct list_head *devices_link;
u16 cmd;
list_for_each(devices_link, &(current_bus->devices)) {
devices = pci_dev_b(devices_link);
if (devices == NULL)
continue;
if (PCI_SLOT(devices->devfn) == 1) {
/*
* Slot 1 is primary ether port, i82559
* we double-check against that assumption
*/
if ((devices->vendor != 0x8086) ||
(devices->device != 0x1209) ) {
panic("gt64120_board_pcibios_fixup_bus: found "
"unexpected PCI device in slot 1.");
}
devices->irq = 2; /* irq_nr is 2 for INT0 */
} else if (PCI_SLOT(devices->devfn) == 2) {
/*
* Slot 2 is secondary ether port, i21143
* we double-check against that assumption
*/
if ((devices->vendor != 0x1011) ||
(devices->device != 0x19) ) {
panic("galileo_pcibios_fixup_bus: "
"found unexpected PCI device in slot 2.");
}
devices->irq = 3; /* irq_nr is 3 for INT1 */
} else if (PCI_SLOT(devices->devfn) == 4) {
/* PMC Slot 1 */
devices->irq = 8; /* irq_nr is 8 for INT6 */
} else if (PCI_SLOT(devices->devfn) == 5) {
/* PMC Slot 1 */
devices->irq = 9; /* irq_nr is 9 for INT7 */
} else {
/* We don't have assign interrupts for other devices. */
devices->irq = 0xff;
}
/* Assign an interrupt number for the device */
bus->ops->write_byte(devices, PCI_INTERRUPT_LINE, devices->irq);
/* enable master */
bus->ops->read_word(devices, PCI_COMMAND, &cmd);
cmd |= PCI_COMMAND_MASTER;
bus->ops->write_word(devices, PCI_COMMAND, cmd);
}
}
--- NEW FILE ---
/*
* Copyright 2001 MontaVista Software Inc.
* Author: js...@mv... or js...@ju...
*
* 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/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#define PLD_BASE 0xbc000000
#define REV 0x0 /* Board Assembly Revision */
#define PLD1ID 0x1 /* PLD 1 ID */
#define PLD2ID 0x2 /* PLD 2 ID */
#define RESET_STAT 0x3 /* Reset Status Register */
#define BOARD_STAT 0x4 /* Board Status Register */
#define CPCI_ID 0x5 /* Compact PCI ID Register */
#define CONTROL 0x8 /* Control Register */
#define CPU_EEPROM 0x9 /* CPU Configuration EEPROM Register */
#define INTMASK 0xA /* Interrupt Mask Register */
#define INTSTAT 0xB /* Interrupt Status Register */
#define INTSET 0xC /* Interrupt Set Register */
#define INTCLR 0xD /* Interrupt Clear Register */
#define PLD_REG(x) ((uint8_t*)(PLD_BASE+(x)))
char arcs_cmdline[COMMAND_LINE_SIZE];
/* [js...@ju...] PMON passes arguments in C main() style */
void __init prom_init(int argc, const char **arg)
{
int i;
/* arg[0] is "g", the rest is boot parameters */
arcs_cmdline[0] = '\0';
for (i = 1; i < argc; i++) {
if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
>= sizeof(arcs_cmdline))
break;
strcat(arcs_cmdline, arg[i]);
strcat(arcs_cmdline, " ");
}
mips_machgroup = MACH_GROUP_MOMENCO;
mips_machtype = MACH_MOMENCO_OCELOT;
/* turn off the Bit Error LED, which comes on automatically
* at power-up reset */
*PLD_REG(INTCLR) = 0x80;
/* All the boards have at least 64MiB. If there's more, we
detect and register it later */
add_memory_region(0, 64 << 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 ---
/*
* 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 momenco_ocelot_restart(char *command)
{
*(volatile char *) 0xbc000000 = 0x0f;
/*
* Ouch, we're still alive ... This time we take the silver bullet ...
* ... and find that we leave the hardware in a state in which the
* kernel in the flush locks up somewhen during of after the PCI
* detection stuff.
*/
clear_cp0_status(ST0_BEV | ST0_ERL);
change_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 momenco_ocelot_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 momenco_ocelot_power_off(void)
{
momenco_ocelot_halt();
}
--- NEW FILE ---
/*
* setup.c
*
* BRIEF MODULE DESCRIPTION
* Galileo Evaluation Boards - board dependent boot routines
*
* Copyright (C) 1996, 1997, 2001 Ralf Baechle
* Copyright (C) 2000 RidgeRun, Inc.
* Copyright (C) 2001 Red Hat, Inc.
*
* Author: RidgeRun, Inc.
* gl...@ri..., sk...@ri..., st...@ri...
*
* Copyright 2001 MontaVista Software Inc.
* Author: js...@mv... or js...@ju...
*
* 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.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mc146818rtc.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/timex.h>
#include <linux/vmalloc.h>
#include <asm/time.h>
#include <asm/bootinfo.h>
#include <asm/page.h>
#include <asm/bootinfo.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/pci.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
#include <asm/reboot.h>
#include <asm/mc146818rtc.h>
#include <linux/version.h>
#include <linux/bootmem.h>
#include <linux/blk.h>
#include <asm/gt64120/gt64120.h>
#include "ocelot_pld.h"
extern struct rtc_ops no_rtc_ops;
unsigned long gt64120_base = KSEG1ADDR(GT_DEF_BASE);
/* These functions are used for rebooting or halting the machine*/
extern void momenco_ocelot_restart(char *command);
extern void momenco_ocelot_halt(void);
extern void momenco_ocelot_power_off(void);
extern void gt64120_time_init(void);
extern void momenco_ocelot_irq_setup(void);
static char reset_reason;
#define ENTRYLO(x) ((pte_val(mk_pte_phys((x), PAGE_KERNEL_UNCACHED)) >> 6)|1)
static void __init setup_l3cache(unsigned long size);
void __init momenco_ocelot_setup(void)
{
void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache);
unsigned int tmpword;
board_time_init = gt64120_time_init;
_machine_restart = momenco_ocelot_restart;
_machine_halt = momenco_ocelot_halt;
_machine_power_off = momenco_ocelot_power_off;
/*
* initrd_start = (ulong)ocelot_initrd_start;
* initrd_end = (ulong)ocelot_initrd_start + (ulong)ocelot_initrd_size;
* initrd_below_start_ok = 1;
*/
rtc_ops = &no_rtc_ops;
/* A wired TLB entry for the GT64120A and the serial port. The
GT64120A is going to be hit on every IRQ anyway - there's
absolutely no point in letting it be a random TLB entry, as
it'll just cause needless churning of the TLB. And we use
the other half for the serial port, which is just a PITA
otherwise :)
Device Physical Virtual
GT64120 Internal Regs 0x24000000 0xe0000000
UARTs (CS2) 0x2d000000 0xe0001000
*/
add_wired_entry(ENTRYLO(0x24000000), ENTRYLO(0x2D000000), 0xe0000000, PM_4K);
/* Also a temporary entry to let us talk to the Ocelot PLD and NVRAM
in the CS[012] region. We can't use ioremap() yet. The NVRAM
appears to be one of the variants of ST M48T35 - see
http://www.st.com/stonline/bin/sftab.exe?table=172&filter0=M48T35
Ocelot PLD (CS0) 0x2c000000 0xe0020000
NVRAM 0x2c800000 0xe0030000
*/
add_temporary_entry(ENTRYLO(0x2C000000), ENTRYLO(0x2d000000), 0xe0020000, PM_64K);
/* Relocate the CS3/BootCS region */
GT_WRITE( GT_CS3BOOTLD_OFS, 0x2f000000 >> 21);
/* Relocate CS[012] */
GT_WRITE(GT_CS20LD_OFS, 0x2c000000 >> 21);
/* Relocate the GT64120A itself... */
GT_WRITE(GT_ISD_OFS, 0x24000000 >> 21);
mb();
gt64120_base = 0xe0000000;
/* ...and the PCI0 view of it. */
GT_WRITE(GT_PCI0_CFGADDR_OFS, 0x80000020);
GT_WRITE(GT_PCI0_CFGDATA_OFS, 0x24000000);
GT_WRITE(GT_PCI0_CFGADDR_OFS, 0x80000024);
GT_WRITE(GT_PCI0_CFGDATA_OFS, 0x24000001);
/* Relocate PCI0 I/O and Mem0 */
GT_WRITE(GT_PCI0IOLD_OFS, 0x20000000 >> 21);
GT_WRITE(GT_PCI0M0LD_OFS, 0x22000000 >> 21);
/* Relocate PCI0 Mem1 */
GT_WRITE(GT_PCI0M1LD_OFS, 0x36000000 >> 21);
/* Relocate all the PCI1 stuff, not that we use it */
GT_WRITE(GT_PCI1IOLD_OFS, 0x30000000 >> 21);
GT_WRITE(GT_PCI1M0LD_OFS, 0x32000000 >> 21);
GT_WRITE(GT_PCI1M1LD_OFS, 0x34000000 >> 21);
/* Relocate the CPU's view of the RAM... */
GT_WRITE(GT_SCS10LD_OFS, 0);
GT_WRITE(GT_SCS10HD_OFS, 0x0fe00000 >> 21);
GT_WRITE(GT_SCS32LD_OFS, 0x10000000 >> 21);
GT_WRITE(GT_SCS32HD_OFS, 0x0fe00000 >> 21);
GT_WRITE(GT_SCS1LD_OFS, 0xff);
GT_WRITE(GT_SCS1HD_OFS, 0x00);
GT_WRITE(GT_SCS0LD_OFS, 0);
GT_WRITE(GT_SCS0HD_OFS, 0xff);
GT_WRITE(GT_SCS3LD_OFS, 0xff);
GT_WRITE(GT_SCS3HD_OFS, 0x00);
GT_WRITE(GT_SCS2LD_OFS, 0);
GT_WRITE(GT_SCS2HD_OFS, 0xff);
/* ...and the PCI0 view of it. */
GT_WRITE(GT_PCI0_CFGADDR_OFS, 0x80000010);
GT_WRITE(GT_PCI0_CFGDATA_OFS, 0x00000000);
GT_WRITE(GT_PCI0_CFGADDR_OFS, 0x80000014);
GT_WRITE(GT_PCI0_CFGDATA_OFS, 0x10000000);
GT_WRITE(GT_PCI0_BS_SCS10_OFS, 0x0ffff000);
GT_WRITE(GT_PCI0_BS_SCS32_OFS, 0x0ffff000);
tmpword = OCELOT_PLD_READ(BOARDREV);
if (tmpword < 26)
printk("Momenco Ocelot: Board Assembly Rev. %c\n", 'A'+tmpword);
else
printk("Momenco Ocelot: Board Assembly Revision #0x%x\n", tmpword);
tmpword = OCELOT_PLD_READ(PLD1_ID);
printk("PLD 1 ID: %d.%d\n", tmpword>>4, tmpword&15);
tmpword = OCELOT_PLD_READ(PLD2_ID);
printk("PLD 2 ID: %d.%d\n", tmpword>>4, tmpword&15);
tmpword = OCELOT_PLD_READ(RESET_STATUS);
printk("Reset reason: 0x%x\n", tmpword);
reset_reason = tmpword;
OCELOT_PLD_WRITE(0xff, RESET_STATUS);
tmpword = OCELOT_PLD_READ(BOARD_STATUS);
printk("Board Status register: 0x%02x\n", tmpword);
printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
printk(" - Tulip PHY %s connected\n", (tmpword&0x10)?"is":"not");
printk(" - L3 Cache size: %d MiB\n", (1<<((tmpword&12) >> 2))&~1);
printk(" - SDRAM size: %d MiB\n", 1<<(6+(tmpword&3)));
if (tmpword&12)
l3func((1<<(((tmpword&12) >> 2)+20)));
switch(tmpword &3) {
case 3:
/* 512MiB */
add_memory_region(256<<20, 256<<20, BOOT_MEM_RAM);
case 2:
/* 256MiB */
/* FIXME: Is it actually here, or at 0x10000000? */
add_memory_region(128<<20, 128<<20, BOOT_MEM_RAM);
case 1:
/* 128MiB */
add_memory_region(64<<20, 64<<20, BOOT_MEM_RAM);
case 0:
/* 64MiB */
;
}
/* Fix up the DiskOnChip mapping */
GT_WRITE(0x468, 0xfef73);
}
extern int rm7k_tcache_enabled;
/*
* This runs in KSEG1. See the verbiage in rm7k.c::probe_scache()
*/
#define Page_Invalidate_T 0x16
static void __init setup_l3cache(unsigned long size)
{
int register i;
unsigned long tmp;
printk("Enabling L3 cache...");
/* Enable the L3 cache in the GT64120A's CPU Configuration register */
GT_READ(0, &tmp);
GT_WRITE(0, tmp | (1<<14));
/* Enable the L3 cache in the CPU */
set_cp0_config(1<<12 /* CONF_TE */);
/* Clear the cache */
set_taglo(0);
set_taghi(0);
for (i=0; i < size; i+= 4096) {
__asm__ __volatile__ (
".set noreorder\n\t"
".set mips3\n\t"
"cache %1, (%0)\n\t"
".set mips0\n\t"
".set reorder"
:
: "r" (KSEG0ADDR(i)),
"i" (Page_Invalidate_T));
}
/* Let the RM7000 MM code know that the tertiary cache is enabled */
rm7k_tcache_enabled = 1;
printk("Done\n");
}
/* This needs to be one of the first initcalls, because no I/O port access
can work before this */
static int io_base_ioremap(void)
{
void *io_remap_range = ioremap(GT_PCI_IO_BASE, GT_PCI_IO_SIZE);
if (!io_remap_range) {
panic("Could not ioremap I/O port range\n");
}
mips_io_port_base = io_remap_range - GT_PCI_IO_BASE;
return 0;
}
module_init(io_base_ioremap);
|