Commit 56e4f65c authored by Ralf Bächle's avatar Ralf Bächle Committed by Linus Torvalds

[PATCH] Code for Galileo boards

The support code for two more Galileo evaluation boards.

(Evil stuff, just to get your tree in sync again.  I've got a cleanup in
my work tree).
parent d3791f47
This diff is collapsed.
#
# Automatically generated make config: don't edit
#
CONFIG_MIPS=y
CONFIG_MIPS32=y
# CONFIG_MIPS64 is not set
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
#
# General setup
#
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_EMBEDDED is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
#
# Loadable module support
#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
# CONFIG_KMOD is not set
#
# Machine selection
#
# CONFIG_ACER_PICA_61 is not set
# CONFIG_BAGET_MIPS is not set
# CONFIG_CASIO_E55 is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_DECSTATION is not set
# CONFIG_MIPS_EV64120 is not set
CONFIG_MIPS_EV96100=y
# CONFIG_MIPS_IVR is not set
# CONFIG_LASAT is not set
# CONFIG_HP_LASERJET is not set
# CONFIG_IBM_WORKPAD is not set
# CONFIG_MIPS_ITE8172 is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MAGNUM_4000 is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
# CONFIG_MOMENCO_OCELOT is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_DDB5074 is not set
# CONFIG_DDB5476 is not set
# CONFIG_DDB5477 is not set
# CONFIG_NEC_OSPREY is not set
# CONFIG_NEC_EAGLE is not set
# CONFIG_OLIVETTI_M700 is not set
# CONFIG_SGI_IP22 is not set
# CONFIG_SGI_IP32 is not set
# CONFIG_SOC_AU1X00 is not set
# CONFIG_SIBYTE_SB1xxx_SOC is not set
# CONFIG_SNI_RM200_PCI is not set
# CONFIG_TANBAC_TB0226 is not set
# CONFIG_TANBAC_TB0229 is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_VICTOR_MPC30X is not set
# CONFIG_ZAO_CAPCELLA is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_NONCOHERENT_IO=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_NEW_PCI=y
CONFIG_SWAP_IO_SPACE=y
CONFIG_MIPS_GT96100=y
# CONFIG_FB is not set
CONFIG_BOARD_SCACHE=y
#
# CPU selection
#
# CONFIG_CPU_MIPS32 is not set
# CONFIG_CPU_MIPS64 is not set
# CONFIG_CPU_R3000 is not set
# CONFIG_CPU_TX39XX is not set
# CONFIG_CPU_VR41XX is not set
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_TX49XX is not set
# CONFIG_CPU_R5000 is not set
# CONFIG_CPU_R5432 is not set
# CONFIG_CPU_R6000 is not set
# CONFIG_CPU_NEVADA is not set
# CONFIG_CPU_R8000 is not set
# CONFIG_CPU_R10000 is not set
CONFIG_CPU_RM7000=y
# CONFIG_CPU_SB1 is not set
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_64BIT_PHYS_ADDR is not set
# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_LLDSCD=y
CONFIG_CPU_HAS_SYNC=y
# CONFIG_PREEMPT is not set
CONFIG_KALLSYMS=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
#
# Bus options (PCI, PCMCIA, EISA, ISA, TC)
#
# CONFIG_PCI is not set
CONFIG_MMU=y
# CONFIG_HOTPLUG is not set
#
# Executable file formats
#
CONFIG_KCORE_ELF=y
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_BINFMT_IRIX is not set
#
# Memory Technology Devices (MTD)
#
# CONFIG_MTD is not set
#
# Parallel port support
#
# CONFIG_PARPORT is not set
#
# Plug and Play support
#
# CONFIG_PNP is not set
#
# Generic Driver Options
#
# CONFIG_FW_LOADER is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
#
# ATA/ATAPI/MFM/RLL support
#
# CONFIG_IDE is not set
#
# SCSI device support
#
# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
#
# Fusion MPT device support
#
#
# I2O device support
#
#
# Networking support
#
CONFIG_NET=y
#
# Networking options
#
# CONFIG_PACKET is not set
CONFIG_NETLINK_DEV=y
# CONFIG_NETFILTER is not set
CONFIG_UNIX=y
CONFIG_NET_KEY=y
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_PNP=y
# CONFIG_IP_PNP_DHCP is not set
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_IPV6 is not set
# CONFIG_XFRM_USER is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
CONFIG_IPV6_SCTP__=y
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_LLC is not set
# CONFIG_DECNET is not set
# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_FASTROUTE is not set
# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_ETHERTAP is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
CONFIG_MIPS_GT96100ETH=y
#
# Ethernet (1000 Mbit)
#
#
# Ethernet (10000 Mbit)
#
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
#
# Wireless LAN (non-hamradio)
#
# CONFIG_NET_RADIO is not set
#
# Token Ring devices (depends on LLC=y)
#
# CONFIG_SHAPER is not set
#
# Wan interfaces
#
# CONFIG_WAN is not set
#
# Amateur Radio support
#
# CONFIG_HAMRADIO is not set
#
# IrDA (infrared) support
#
# CONFIG_IRDA is not set
#
# ISDN subsystem
#
# CONFIG_ISDN_BOOL is not set
#
# Telephony Support
#
# CONFIG_PHONE is not set
#
# Input device support
#
CONFIG_INPUT=y
#
# Userland interfaces
#
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
#
# Input I/O drivers
#
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
CONFIG_SERIO=y
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_CT82C710 is not set
#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
#
# Character devices
#
# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
# Serial drivers
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
# CONFIG_SERIAL_8250_EXTENDED is not set
#
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=256
#
# I2C support
#
# CONFIG_I2C is not set
#
# I2C Hardware Sensors Mainboard support
#
#
# I2C Hardware Sensors Chip support
#
# CONFIG_I2C_SENSOR is not set
#
# Mice
#
# CONFIG_BUSMOUSE is not set
# CONFIG_QIC02_TAPE is not set
#
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_HANGCHECK_TIMER is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
#
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
#
# File systems
#
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT3_FS is not set
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
# CONFIG_UDF_FS is not set
#
# DOS/FAT/NT Filesystems
#
# CONFIG_FAT_FS is not set
# CONFIG_NTFS_FS is not set
#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
CONFIG_DEVPTS_FS=y
CONFIG_DEVPTS_FS_XATTR=y
CONFIG_DEVPTS_FS_SECURITY=y
# CONFIG_TMPFS is not set
CONFIG_RAMFS=y
#
# Miscellaneous filesystems
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
#
# Network File Systems
#
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_SUNRPC_GSS is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
#
# Graphics support
#
#
# Sound
#
# CONFIG_SOUND is not set
#
# USB support
#
# CONFIG_USB_GADGET is not set
#
# Bluetooth support
#
# CONFIG_BT is not set
#
# Kernel hacking
#
CONFIG_CROSSCOMPILE=y
# CONFIG_DEBUG_KERNEL is not set
#
# Security options
#
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
# CONFIG_CRYPTO is not set
#
# Library routines
#
# CONFIG_CRC32 is not set
#
# Copyright 2000 RidgeRun, Inc.
# Author: RidgeRun, Inc.
# glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
#
# Makefile for the Galileo EV64120 board.
#
obj-y := serialGT.o int-handler.o promcon.o reset.o setup.o irq.o \
irq-handler.o
EXTRA_AFLAGS := $(CFLAGS)
The compressed boot code was such a mess I deleted it. Feel free to
reimplement it -- Ralf
/* DMA.C - DMA functions and definitions */
/* Copyright Galileo Technology. */
/*
DESCRIPTION
This file gives the user a complete interface to the powerful DMA engines,
including functions for controling the priority mechanism.
To fully understand the capabilities of the DMA engines please spare some
time to go trough the spec.
*/
/* includes */
#ifdef __linux__
#include <asm/galileo/evb64120A/core.h>
#include <asm/galileo/evb64120A/dma.h>
#else
#include "Core.h"
#include "DMA.h"
#endif
/********************************************************************
* dmaCommand - Write a command to a DMA channel
*
* Inputs: DMA_ENGINE channel - choosing one of the four engine.
* unsigned int command - The command to be written to the control register.
* Returns: false if one of the parameters is erroneous else returns true.
*********************************************************************/
bool dmaCommand(DMA_ENGINE channel, unsigned int command)
{
if (channel > LAST_DMA_ENGINE)
return false;
GT_REG_WRITE(CHANNEL0CONTROL + channel * 4, command);
return true;
}
/********************************************************************
* dmaTransfer - transfer data from sourceAddr to destAddr on DMA channel
* Inputs:
* DMA_RECORED *nextRecoredPointer: If we are using chain mode DMA transfer,
* then this pointer should point to the next recored,otherwise it should be
* NULL.
* VERY IMPORTANT !!! When using chain mode, the records must be 16 Bytes
* aligned, the function will take care of that for you, but you need to
* allocate one more record for that, meaning: if you are having 3 records ,
* declare 4 (see the example bellow) and start using the second one.
* Example:
* Performing a chain mode DMA transfer(Copy a 1/4 mega of data using
* chain mode DMA):
* DMA_RECORED dmaRecoredArray[4];
* dmaRecoredArray[1].ByteCnt = _64KB;
* dmaRecoredArray[1].DestAdd = destAddress + _64KB;
* dmaRecoredArray[1].SrcAdd = sourceAddress + _64KB;
* dmaRecoredArray[1].NextRecPtr = &dmaRecoredArray[2];
* dmaRecoredArray[2].ByteCnt = _64KB;
* dmaRecoredArray[2].DestAdd = destAddress + 2*_64KB;
* dmaRecoredArray[2].SrcAdd = sourceAddress + 2*_64KB;
* dmaRecoredArray[2].NextRecPtr = &dmaRecoredArray[3];
* dmaRecoredArray[3].ByteCnt = _64KB;
* dmaRecoredArray[3].DestAdd = destAddress + 3*_64KB;
* dmaRecoredArray[3].SrcAdd = sourceAddress + 3*_64KB;
* dmaRecoredArray[3].NextRecPtr = NULL;
* performCmDma(0,sourceAddress,destAddress,_64KB,PLAIN,WAIT_TO_END,
* &dmaRecoredArray[1]);
* Returns: NO_SUCH_CHANNEL if channel does not exist, CHANNEL_BUSY if channel
* is active and true if the transfer ended successfully
*********************************************************************/
DMA_STATUS dmaTransfer(DMA_ENGINE channel, unsigned int sourceAddr,
unsigned int destAddr, unsigned int numOfBytes,
unsigned int command,
DMA_RECORED * nextRecoredPointer)
{
unsigned int tempData, checkBits, alignmentOffset = 0;
DMA_RECORED *next = nextRecoredPointer;
if (channel > LAST_DMA_ENGINE)
return NO_SUCH_CHANNEL;
if (numOfBytes > 0xffff)
return GENERAL_ERROR;
if (isDmaChannelActive(channel))
return CHANNEL_BUSY;
if (next != NULL) { /* case of chain Mode */
alignmentOffset = ((unsigned int) next % 16);
}
checkBits = command & 0x6000000;
if (checkBits == 0) {
while (next != NULL) {
WRITE_WORD((unsigned int) next - alignmentOffset,
next->ByteCnt);
tempData = (unsigned int) next->SrcAdd;
WRITE_WORD((unsigned int) next + 4 -
alignmentOffset, tempData & 0x5fffffff);
tempData = (unsigned int) next->DestAdd;
WRITE_WORD((unsigned int) next + 8 -
alignmentOffset, tempData & 0x5fffffff);
tempData = (unsigned int) next->NextRecPtr;
WRITE_WORD((unsigned int) next + 12 -
alignmentOffset,
tempData & 0x5fffffff -
alignmentOffset);
next = (DMA_RECORED *) tempData;
if (next == nextRecoredPointer)
next = NULL;
}
}
GT_REG_WRITE(CHANNEL0_DMA_BYTE_COUNT + channel * 4, numOfBytes);
tempData = sourceAddr;
GT_REG_WRITE(CHANNEL0_DMA_SOURCE_ADDRESS + channel * 4,
tempData & 0x5fffffff);
tempData = destAddr;
GT_REG_WRITE(CHANNEL0_DMA_DESTINATION_ADDRESS + channel * 4,
tempData & 0x5fffffff);
if (nextRecoredPointer != NULL) {
tempData =
(unsigned int) nextRecoredPointer - alignmentOffset;
GT_REG_WRITE(CHANNEL0NEXT_RECORD_POINTER + 4 * channel,
tempData & 0x5fffffff);
command = command | CHANNEL_ENABLE;
} else {
command = command | CHANNEL_ENABLE | NON_CHAIN_MOD;
}
/* Activate DMA engine By writting to dmaControlRegister */
GT_REG_WRITE(CHANNEL0CONTROL + channel * 4, command);
return DMA_OK;
}
/********************************************************************
* isDmaChannelActive - check if channel is busy
*
* Inputs: channel number
* RETURNS: True if the channel is busy, false otherwise.
*********************************************************************/
bool isDmaChannelActive(DMA_ENGINE channel)
{
unsigned int data;
if (channel > LAST_DMA_ENGINE)
return false;
GT_REG_READ(CHANNEL0CONTROL + 4 * channel, &data);
if (data & DMA_ACTIVITY_STATUS)
return true;
else
return false;
}
/********************************************************************
* changeDmaPriority - update the arbiter`s priority for channels 0-3
*
* Inputs: priority for channels 0-1, priority for channels 2-3,
priority for groups and other priority options
* RETURNS: false if one of the parameters is erroneous and true else
*********************************************************************/
bool changeDmaPriority(PRIO_CHAN_0_1 prio_01, PRIO_CHAN_2_3 prio_23,
PRIO_GROUP prioGrp, PRIO_OPT prioOpt)
{
unsigned int prioReg = 0;
prioReg = (prio_01 & 0x3) + ((prio_23 & 0x3) << 2) +
((prioGrp & 0x3) << 4) + (prioOpt << 6);
GT_REG_WRITE(ARBITER_CONTROL, prioReg);
return true;
}
This diff is collapsed.
/*
* int-handler.S
*
* Based on the cobalt handler.
*/
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
/*
* We check for the timer first, then check PCI ints A and D.
* Then check for serial IRQ and fall through.
*/
.align 5
.set reorder
.set noat
NESTED(galileo_handle_int, PT_SIZE, sp)
SAVE_ALL
CLI
.set at
mfc0 t0, CP0_CAUSE
mfc0 t2, CP0_STATUS
and t0, t2
.set noreorder
andi t1, t0, STATUSF_IP4 /* int2 hardware line (timer) */
andi t2, t0, STATUSF_IP2 /* int0 hardware line */
bnez t1, ll_galileo_irq
andi t1, t0, STATUSF_IP5 /* int3 hardware line */
bnez t2, ll_pci_intA
andi t2, t0, STATUSF_IP6 /* int4 hardware line */
bnez t1, ll_pci_intD
andi t1, t0, STATUSF_IP7 /* compare int */
bnez t2, ll_serial_irq
nop
bnez t1, ll_compare_irq
nop
.set reorder
j spurious_interrupt
END(galileo_handle_int)
.align 5
ll_galileo_irq: li a0, 4
move a1, sp
jal do_IRQ
j ret_from_irq
.align 5
ll_compare_irq: li a0, 7
move a1, sp
jal do_IRQ
j ret_from_irq
.align 5
ll_pci_intA: move a0, sp
jal pci_intA
j ret_from_irq
#if 0
.align 5
ll_pci_intB: move a0, sp
jal pci_intB
j ret_from_irq
.align 5
ll_pci_intC: move a0, sp
jal pci_intC
j ret_from_irq
#endif
.align 5
ll_pci_intD: move a0, sp
jal pci_intD
j ret_from_irq
.align 5
ll_serial_irq: li a0, 6
move a1, sp
jal do_IRQ
j ret_from_irq
/*
* Galileo Technology chip interrupt handler
*
* Modified by RidgeRun, Inc.
*/
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <asm/ptrace.h>
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel_stat.h>
#include <asm/io.h>
#include <asm/gt64120.h>
#include <asm/galileo-boards/ev64120.h>
#include <asm/galileo-boards/ev64120int.h>
/*
* These are interrupt handlers for the GT on-chip interrupts. They all come
* in to the MIPS on a single interrupt line, and have to be handled and ack'ed
* differently than other MIPS interrupts.
*/
#if CURRENTLY_UNUSED
struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH];
void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr);
/*
* hook_irq_handler
*
* Hooks IRQ handler to the system. When the system is interrupted
* the interrupt service routine is called.
*
* Inputs :
* int_cause - The interrupt cause number. In EVB64120 two parameters
* are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
* bit_num - Indicates which bit number in the cause register
* isr_ptr - Pointer to the interrupt service routine
*
* Outputs :
*/
void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr)
{
irq_handlers[int_cause][bit_num].routine = isr_ptr;
}
/*
* enable_galileo_irq
*
* Enables the IRQ on Galileo Chip
*
* Inputs :
* int_cause - The interrupt cause number. In EVB64120 two parameters
* are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
* bit_num - Indicates which bit number in the cause register
*
* Outputs :
* 1 if succesful, 0 if failure
*/
int enable_galileo_irq(int int_cause, int bit_num)
{
if (int_cause == INT_CAUSE_MAIN)
SET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, (1 << bit_num));
else if (int_cause == INT_CAUSE_HIGH)
SET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER,
(1 << bit_num));
else
return 0;
return 1;
}
/*
* disable_galileo_irq
*
* Disables the IRQ on Galileo Chip
*
* Inputs :
* int_cause - The interrupt cause number. In EVB64120 two parameters
* are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
* bit_num - Indicates which bit number in the cause register
*
* Outputs :
* 1 if succesful, 0 if failure
*/
int disable_galileo_irq(int int_cause, int bit_num)
{
if (int_cause == INT_CAUSE_MAIN)
RESET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER,
(1 << bit_num));
else if (int_cause == INT_CAUSE_HIGH)
RESET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER,
(1 << bit_num));
else
return 0;
return 1;
}
#endif /* UNUSED */
/*
* galileo_irq -
*
* Interrupt handler for interrupts coming from the Galileo chip.
* It could be timer interrupt, built in ethernet ports etc...
*
* Inputs :
*
* Outputs :
*
*/
static void galileo_irq(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned int irq_src, int_high_src, irq_src_mask,
int_high_src_mask;
int handled;
unsigned int count;
static int counter = 0;
GT_READ(GT_INTRCAUSE_OFS, &irq_src);
GT_READ(GT_INTRMASK_OFS, &irq_src_mask);
GT_READ(GT_HINTRCAUSE_OFS, &int_high_src);
GT_READ(GT_HINTRMASK_OFS, &int_high_src_mask);
irq_src = irq_src & irq_src_mask;
int_high_src = int_high_src & int_high_src_mask;
handled = 0;
/* Execute all interrupt handlers */
/* Check for timer interrupt */
if (irq_src & 0x00000800) {
handled = 1;
irq_src &= ~0x00000800;
// RESET_REG_BITS (INTERRUPT_CAUSE_REGISTER,BIT8);
do_timer(regs);
}
if (irq_src) {
printk(KERN_INFO
"Other Galileo interrupt received irq_src %x\n",
irq_src);
#if CURRENTLY_UNUSED
for (count = 0; count < MAX_CAUSE_REG_WIDTH; count++) {
if (irq_src & (1 << count)) {
if (irq_handlers[INT_CAUSE_MAIN][count].
routine) {
queue_task(&irq_handlers
[INT_CAUSE_MAIN][count],
&tq_immediate);
mark_bh(IMMEDIATE_BH);
handled = 1;
}
}
}
#endif /* UNUSED */
}
GT_WRITE(GT_INTRCAUSE_OFS, 0);
GT_WRITE(GT_HINTRCAUSE_OFS, 0);
#undef GALILEO_I2O
#ifdef GALILEO_I2O
/*
Future I2O support. We currently attach I2O interrupt handlers to the
Galileo interrupt (int 4) and handle them in do_IRQ.
*/
if (isInBoundDoorBellInterruptSet()) {
printk(KERN_INFO "I2O doorbell interrupt received.\n");
handled = 1;
}
if (isInBoundPostQueueInterruptSet()) {
printk(KERN_INFO "I2O Queue interrupt received.\n");
handled = 1;
}
/*
This normally would be outside of the ifdef, but since
we're handling I2O outside of this handler, this
printk shows up every time we get a valid I2O
interrupt. So turn this off for now.
*/
if (handled == 0) {
if (counter < 50) {
printk("Spurious Galileo interrupt...\n");
counter++;
}
}
#endif
}
/*
* galileo_time_init -
*
* Initializes timer using galileo's built in timer.
*
*
* Inputs :
* irq - number of irq to be used by the timer
*
* Outpus :
*
*/
#ifdef CONFIG_SYSCLK_100
#define Sys_clock (100 * 1000000) // 100 MHz
#endif
#ifdef CONFIG_SYSCLK_83
#define Sys_clock (83.333 * 1000000) // 83.333 MHz
#endif
#ifdef CONFIG_SYSCLK_75
#define Sys_clock (75 * 1000000) // 75 MHz
#endif
/*
* This will ignore the standard MIPS timer interrupt handler that is passed
* in as *irq (=irq0 in ../kernel/time.c). We will do our own timer interrupt
* handling.
*/
void galileo_time_init(struct irqaction *irq)
{
extern irq_desc_t irq_desc[NR_IRQS];
static struct irqaction timer;
/* Disable timer first */
GT_WRITE(GT_TC_CONTROL_OFS, 0);
/* Load timer value for 100 Hz */
GT_WRITE(GT_TC3_OFS, Sys_clock / 100);
/*
* Create the IRQ structure entry for the timer. Since we're too early
* in the boot process to use the "request_irq()" call, we'll hard-code
* the values to the correct interrupt line.
*/
timer.handler = &galileo_irq;
timer.flags = SA_SHIRQ;
timer.name = "timer";
timer.dev_id = NULL;
timer.next = NULL;
timer.mask = 0;
irq_desc[TIMER].action = &timer;
/* Enable timer ints */
GT_WRITE(GT_TC_CONTROL_OFS, 0xc0);
/* clear Cause register first */
GT_WRITE(GT_INTRCAUSE_OFS, 0x0);
/* Unmask timer int */
GT_WRITE(GT_INTRMASK_OFS, 0x800);
/* Clear High int register */
GT_WRITE(GT_HINTRCAUSE_OFS, 0x0);
/* Mask All interrupts at High cause interrupt */
GT_WRITE(GT_HINTRMASK_OFS, 0x0);
}
void galileo_irq_init(void)
{
#if CURRENTLY_UNUSED
int i, j;
/* Reset irq handlers pointers to NULL */
for (i = 0; i < MAX_CAUSE_REGS; i++) {
for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) {
irq_handlers[i][j].next = NULL;
irq_handlers[i][j].sync = 0;
irq_handlers[i][j].routine = NULL;
irq_handlers[i][j].data = NULL;
}
}
#endif
}
/*
* BRIEF MODULE DESCRIPTION
* Code to handle irqs on GT64120A boards
* Derived from mips/orion and Cort <cort@fsmlabs.com>
*
* Copyright (C) 2000 RidgeRun, Inc.
* Author: RidgeRun, Inc.
* glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
*
* 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 <asm/bitops.h>
#include <asm/bootinfo.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mipsregs.h>
#include <asm/system.h>
#include <asm/galileo-boards/ev64120int.h>
#define MAX_AGENTS_PER_INT 21 /* Random number */
unsigned char pci_int_irq[MAX_AGENTS_PER_INT];
static int max_interrupts = 0;
asmlinkage void pci_intA(struct pt_regs *regs)
{
unsigned int count = 0;
/* This must be a joke - Ralf */
for (count = 0; count < max_interrupts; count++)
do_IRQ(pci_int_irq[count], regs);
}
asmlinkage void pci_intD(struct pt_regs *regs)
{
unsigned int count = 0;
/* Encore une fois - This must be a joke - Ralf */
for (count = 0; count < max_interrupts; count++)
do_IRQ(pci_int_irq[count], regs);
}
/*
* Now this is scarry. A disable_irq(2) or disable_irq(5) would just
* accidently disable a pci irq. It shouldn't happen but may just leaving
* these always enabled or use some reference counting wouldn't be such a
* bad thing.
*/
static void disable_ev64120_irq(unsigned int irq_nr)
{
unsigned long flags;
local_irq_save(flags);
if (irq_nr >= 8) {
/* All PCI interrupts are on line 5 or 2 */
clear_c0_status(IE_IRQ0 | IE_IRQ3);
} else {
clear_c0_status(0x100 << irq_nr);
}
local_irq_restore(flags);
}
#define mask_and_ack_ev64120_irq disable_ev64120_irq
static inline void enable_ev64120_irq(unsigned int irq_nr)
{
unsigned long flags;
local_irq_save(flags);
if (irq_nr >= 8) {
/* All PCI interrupts are on line 5 or 2 */
set_c0_status(IE_IRQ0 | IE_IRQ3);
} else {
set_c0_status(IE_SW0 << irq_nr);
}
local_irq_restore(flags);
}
static unsigned int startup_ev64120_irq(unsigned int irq)
{
if (irq >= 8) {
// NOTE: Add error-handling if > max
pci_int_irq[max_interrupts++] = irq;
}
enable_ev64120_irq(irq);
return 0;
}
static void shutdown_ev64120_irq(unsigned int irq)
{
int count, tmp;
/*
* Remove PCI interrupts from the pci_int_irq list. Make sure
* that some handler was removed before decrementing max_interrupts.
*/
if (irq >= 8) {
for (count = 0; count < max_interrupts; count++) {
if (pci_int_irq[count] == irq) {
for (tmp = count; tmp < max_interrupts; tmp++) {
pci_int_irq[tmp] =
pci_int_irq[tmp + 1];
}
}
}
max_interrupts--;
}
}
static void end_ev64120_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
enable_ev64120_irq(irq);
}
static struct hw_interrupt_type ev64120_irq_type = {
"EV64120",
startup_ev64120_irq,
shutdown_ev64120_irq,
enable_ev64120_irq,
disable_ev64120_irq,
mask_and_ack_ev64120_irq,
end_ev64120_irq
};
/*
* galileo_irq_setup - Initializes CPU interrupts
*/
void __init init_IRQ(void)
{
extern asmlinkage void galileo_handle_int(void);
int i;
init_generic_irq();
/* Yes, how many interrupts does this beast actually have? -- Ralf */
for (i = 0; i < NR_IRQS; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = 0;
irq_desc[i].depth = 1;
irq_desc[i].handler = &ev64120_irq_type;
}
/*
* Clear all of the interrupts while we change the able around a bit.
* Enable timer. Other interrupts will be enabled as they are
* registered.
*/
change_c0_status(ST0_IM | IE_IRQ2, IE_IRQ2);
/* Sets the exception_handler array. */
set_except_vector(0, galileo_handle_int);
}
/*
* Wrap-around code for a console using the
* SGI PROM io-routines.
*
* Copyright (c) 1999 Ulf Carlsson
*
* Derived from DECstation promcon.c
* Copyright (c) 1998 Harald Koerfgen
* Copyright (c) 2002 Ralf Baechle
*/
#include <linux/tty.h>
#include <linux/major.h>
#include <linux/ptrace.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/fs.h>
/*
#include <asm/sgialib.h>
*/
static void prom_console_write(struct console *co, const char *s,
unsigned count)
{
extern int CONSOLE_CHANNEL; // The default serial port
unsigned i;
/*
* Now, do each character
*/
for (i = 0; i < count; i++) {
if (*s == 10)
serial_putc(CONSOLE_CHANNEL, 13);
serial_putc(CONSOLE_CHANNEL, *s++);
}
}
int prom_getchar(void)
{
return 0;
}
static int __init prom_console_setup(struct console *co, char *options)
{
return 0;
}
static kdev_t prom_console_device(struct console *c)
{
return mk_kdev(TTY_MAJOR, 64 + c->index);
}
static struct console sercons = {
.name = "ttyS",
.write = prom_console_write,
.device = prom_console_device,
.setup = prom_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
};
/*
* Register console.
*/
void gal_serial_console_init(void)
{
// serial_init();
//serial_set(115200);
register_console(&sercons);
}
/*
* 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.
*
* Copyright (C) 1997, 2002 Ralf Baechle
*/
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/io.h>
#include <asm/cacheflush.h>
#include <asm/processor.h>
#include <asm/reboot.h>
#include <asm/system.h>
void galileo_machine_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.
*/
set_c0_status(ST0_BEV | ST0_ERL);
change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
flush_cache_all();
write_c0_wired(0);
__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
}
void galileo_machine_halt(void)
{
printk(KERN_NOTICE "You can safely turn off the power\n");
while (1)
__asm__(".set\tmips3\n\t"
"wait\n\t"
".set\tmips0");
}
void galileo_machine_power_off(void)
{
galileo_machine_halt();
}
/*
* serialGT.c
*
* BRIEF MODULE DESCRIPTION
* Low Level Serial Port control for use
* with the Galileo EVB64120A MIPS eval board and
* its on board two channel 16552 Uart.
*
* Copyright (C) 2000 RidgeRun, Inc.
* Author: RidgeRun, Inc.
* glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
*
* 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.
*
*/
// Note:
// Serial CHANNELS - 0 is the bottom connector of evb64120A.
// (The one that maps to the "B" channel of the
// board's uart)
// 1 is the top connector of evb64120A.
// (The one that maps to the "A" channel of the
// board's uart)
int DEBUG_CHANNEL = 0; // See Note Above
int CONSOLE_CHANNEL = 1; // See Note Above
#define DUART 0xBD000000 /* Base address of Uart. */
#define CHANNELOFFSET 0x20 /* DUART+CHANNELOFFSET gets you to the ChanA
register set of the 16552 Uart device.
DUART+0 gets you to the ChanB register set.
*/
#define DUART_DELTA 0x4
#define FIFO_ENABLE 0x07
#define INT_ENABLE 0x04 /* default interrupt mask */
#define RBR 0x00
#define THR 0x00
#define DLL 0x00
#define IER 0x01
#define DLM 0x01
#define IIR 0x02
#define FCR 0x02
#define LCR 0x03
#define MCR 0x04
#define LSR 0x05
#define MSR 0x06
#define SCR 0x07
#define LCR_DLAB 0x80
#define XTAL 1843200
#define LSR_THRE 0x20
#define LSR_BI 0x10
#define LSR_DR 0x01
#define MCR_LOOP 0x10
#define ACCESS_DELAY 0x10000
/******************************
Routine:
Description:
******************************/
int inreg(int channel, int reg)
{
int val;
val =
*((volatile unsigned char *) DUART +
(channel * CHANNELOFFSET) + (reg * DUART_DELTA));
return val;
}
/******************************
Routine:
Description:
******************************/
void outreg(int channel, int reg, unsigned char val)
{
*((volatile unsigned char *) DUART + (channel * CHANNELOFFSET)
+ (reg * DUART_DELTA)) = val;
}
/******************************
Routine:
Description:
Initialize the device driver.
******************************/
void serial_init(int channel)
{
/*
* Configure active port, (CHANNELOFFSET already set.)
*
* Set 8 bits, 1 stop bit, no parity.
*
* LCR<7> 0 divisor latch access bit
* LCR<6> 0 break control (1=send break)
* LCR<5> 0 stick parity (0=space, 1=mark)
* LCR<4> 0 parity even (0=odd, 1=even)
* LCR<3> 0 parity enable (1=enabled)
* LCR<2> 0 # stop bits (0=1, 1=1.5)
* LCR<1:0> 11 bits per character(00=5, 01=6, 10=7, 11=8)
*/
outreg(channel, LCR, 0x3);
outreg(channel, FCR, FIFO_ENABLE); /* Enable the FIFO */
outreg(channel, IER, INT_ENABLE); /* Enable appropriate interrupts */
}
/******************************
Routine:
Description:
Set the baud rate.
******************************/
void serial_set(int channel, unsigned long baud)
{
unsigned char sav_lcr;
/*
* Enable access to the divisor latches by setting DLAB in LCR.
*
*/
sav_lcr = inreg(channel, LCR);
#if 0
/*
* Set baud rate
*/
outreg(channel, LCR, LCR_DLAB | sav_lcr);
// outreg(DLL,(XTAL/(16*2*(baud))-2));
outreg(channel, DLL, XTAL / (16 * baud));
// outreg(DLM,(XTAL/(16*2*(baud))-2)>>8);
outreg(channel, DLM, (XTAL / (16 * baud)) >> 8);
#else
/*
* Note: Set baud rate, hardcoded here for rate of 115200
* since became unsure of above "buad rate" algorithm (??).
*/
outreg(channel, LCR, 0x83);
outreg(channel, DLM, 0x00); // See note above
outreg(channel, DLL, 0x02); // See note above.
outreg(channel, LCR, 0x03);
#endif
/*
* Restore line control register
*/
outreg(channel, LCR, sav_lcr);
}
/******************************
Routine:
Description:
Transmit a character.
******************************/
void serial_putc(int channel, int c)
{
while ((inreg(channel, LSR) & LSR_THRE) == 0);
outreg(channel, THR, c);
}
/******************************
Routine:
Description:
Read a received character if one is
available. Return -1 otherwise.
******************************/
int serial_getc(int channel)
{
if (inreg(channel, LSR) & LSR_DR) {
return inreg(channel, RBR);
}
return -1;
}
/******************************
Routine:
Description:
Used by embedded gdb client. (example; gdb-stub.c)
******************************/
char getDebugChar()
{
int val;
while ((val = serial_getc(DEBUG_CHANNEL)) == -1); // loop until we get a character in.
return (char) val;
}
/******************************
Routine:
Description:
Used by embedded gdb target. (example; gdb-stub.c)
******************************/
void putDebugChar(char c)
{
serial_putc(DEBUG_CHANNEL, (int) c);
}
/*
* BRIEF MODULE DESCRIPTION
* Galileo Evaluation Boards - board dependent boot routines
*
* Copyright (C) 2000 RidgeRun, Inc.
* Author: RidgeRun, Inc.
* glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
*
* 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/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/bootmem.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/version.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 <asm/traps.h>
extern struct rtc_ops no_rtc_ops;
/* These functions are used for rebooting or halting the machine*/
extern void galileo_machine_restart(char *command);
extern void galileo_machine_halt(void);
extern void galileo_machine_power_off(void);
/*
*This structure holds pointers to the pci configuration space accesses
*and interrupts allocating routine for device over the PCI
*/
extern struct pci_ops galileo_pci_ops;
extern unsigned long mips_machgroup;
char arcs_cmdline[CL_SIZE] = { "console=ttyS0,115200 "
"root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal "
"ip=192.168.1.211:192.168.1.1:::gt::"
};
//struct eeprom_parameters eeprom_param;
/*
* This function is added because arch/mips/mm/init.c needs it
* basically it does nothing
*/
void prom_free_prom_memory(void)
{
}
extern void (*board_time_init) (struct irqaction * irq);
static unsigned char galileo_rtc_read_data(unsigned long addr)
{
return 0;
}
static void galileo_rtc_write_data(unsigned char data, unsigned long addr)
{
}
static int galileo_rtc_bcd_mode(void)
{
return 0;
}
struct rtc_ops galileo_rtc_ops = {
&galileo_rtc_read_data,
&galileo_rtc_write_data,
&galileo_rtc_bcd_mode
};
/********************************************************************
*ev64120_setup -
*
*Initializes basic routines and structures pointers, memory size (as
*given by the bios and saves the command line.
*
*
*Inputs :
*
*Outpus :
*
*********************************************************************/
extern void galileo_time_init();
void __init ev64120_setup(void)
{
_machine_restart = galileo_machine_restart;
_machine_halt = galileo_machine_halt;
_machine_power_off = galileo_machine_power_off;
rtc_ops = &galileo_rtc_ops;
board_time_init = galileo_time_init;
set_io_port_base(KSEG1);
#ifdef CONFIG_L2_L3_CACHE
#error "external cache not implemented yet"
config_register = read_c0_config();
printk("\n\n\nchecking second level cache cp0_config = %08lx\n",
config_register);
if (config_register & CONF_SC) { // second/third level cache available
config_register = config_register & (1 << 12);
write_c0_config(config_register);
printk
("\n\n\nchecking second level cache c0_config = %08lx\n",
config_register);
}
#endif
}
const char *get_system_type(void)
{
return "Galileo EV64120A";
}
/*
* SetUpBootInfo -
*
* This function is called at very first stages of kernel startup.
* It specifies for the kernel the evaluation board that the linux
* is running on. Then it saves the eprom parameters that holds the
* command line, memory size etc...
*
* Inputs :
* argc - nothing
* argv - holds a pointer to the eprom parameters
* envp - nothing
*/
void SetUpBootInfo(int argc, char **argv, char **envp)
{
mips_machgroup = MACH_GROUP_GALILEO;
mips_machtype = MACH_EV64120A;
}
void __init prom_init(int a, char **b, char **c, int *d)
{
mips_machgroup = MACH_GROUP_GALILEO;
add_memory_region(0, 32 << 20, BOOT_MEM_RAM);
}
#
# Copyright 2000 MontaVista Software Inc.
# Author: MontaVista Software, Inc.
# ppopov@mvista.com or source@mvista.com
#
# Makefile for the Galileo EV96100 board.
#
obj-y += init.o time.o irq.o int-handler.o setup.o puts.o
EXTRA_AFLAGS := $(CFLAGS)
/*
* Copyright 2000 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* This file was derived from Carsten Langgaard's
* arch/mips/mips-boards/generic/generic.c
*
* Carsten Langgaard, carstenl@mips.com
* Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
*
* 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/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/galileo-boards/ev96100.h>
/* Environment variable */
typedef struct {
char *name;
char *val;
} t_env_var;
int prom_argc;
char **prom_argv, **prom_envp;
char arcs_cmdline[CL_SIZE];
int init_debug = 0;
char * __init prom_getcmdline(void)
{
return &(arcs_cmdline[0]);
}
void prom_free_prom_memory (void)
{
}
void __init prom_init_cmdline(void)
{
char *cp;
int actr;
actr = 1; /* Always ignore argv[0] */
cp = &(arcs_cmdline[0]);
while(actr < prom_argc) {
strcpy(cp, prom_argv[actr]);
cp += strlen(prom_argv[actr]);
*cp++ = ' ';
actr++;
}
if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
--cp;
*cp = '\0';
}
char *prom_getenv(char *envname)
{
/*
* Return a pointer to the given environment variable.
*/
t_env_var *env = (t_env_var *) prom_envp;
int i;
i = strlen(envname);
while (env->name) {
if (strncmp(envname, env->name, i) == 0) {
return (env->val);
}
env++;
}
return (NULL);
}
static inline unsigned char str2hexnum(unsigned char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
return 0; /* foo */
}
static inline void str2eaddr(unsigned char *ea, unsigned char *str)
{
int i;
for (i = 0; i < 6; i++) {
unsigned char num;
if ((*str == '.') || (*str == ':'))
str++;
num = str2hexnum(*str++) << 4;
num |= (str2hexnum(*str++));
ea[i] = num;
}
}
int get_ethernet_addr(char *ethernet_addr)
{
char *ethaddr_str;
ethaddr_str = prom_getenv("ethaddr");
if (!ethaddr_str) {
printk("ethaddr not set in boot prom\n");
return -1;
}
str2eaddr(ethernet_addr, ethaddr_str);
if (init_debug > 1) {
int i;
printk("get_ethernet_addr: ");
for (i = 0; i < 5; i++)
printk("%02x:",
(unsigned char) *(ethernet_addr + i));
printk("%02x\n", *(ethernet_addr + i));
}
return 0;
}
const char *get_system_type(void)
{
return "Galileo EV96100";
}
void __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
{
volatile unsigned char *uart;
char ppbuf[8];
prom_argc = argc;
prom_argv = argv;
prom_envp = envp;
mips_machgroup = MACH_GROUP_GALILEO;
mips_machtype = MACH_EV96100;
prom_init_cmdline();
/* 32 MB upgradable */
add_memory_region(0, 32 << 20, BOOT_MEM_RAM);
}
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
.set noat
.align 5
NESTED(ev96100IRQ, PT_SIZE, sp)
SAVE_ALL
CLI # Important: mark KERNEL mode !
mfc0 t0, CP0_CAUSE # get pending interrupts
mfc0 t1, CP0_STATUS # get enabled interrupts
and t0, t1 # isolate allowed ones
# FIX ME add R7000 extensions
andi t0,0xff00 # isolate pending bits
andi a0, t0, CAUSEF_IP7
beq a0, zero, 1f
move a0, sp
jal mips_timer_interrupt
j ret_from_irq
1: beqz t0, 3f # spurious interrupt
move a0, t0
move a1, sp # delay slot
jal ev96100_cpu_irq
j ret_from_irq
3: j spurious_interrupt
END(ev96100IRQ)
/*
* Copyright 2000 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* This file was derived from Carsten Langgaard's
* arch/mips/mips-boards/atlas/atlas_int.c.
*
* Carsten Langgaard, carstenl@mips.com
* Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
*
* 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/irq.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 <asm/bitops.h>
#include <asm/bootinfo.h>
#include <asm/io.h>
#include <asm/mipsregs.h>
#include <asm/system.h>
#include <asm/galileo-boards/ev96100int.h>
extern void mips_timer_interrupt(int irq, struct pt_regs *regs);
extern asmlinkage void ev96100IRQ(void);
static void disable_ev96100_irq(unsigned int irq_nr)
{
unsigned long flags;
local_irq_save(flags);
clear_c0_status(0x100 << irq_nr);
local_irq_restore(flags);
}
static inline void enable_ev96100_irq(unsigned int irq_nr)
{
unsigned long flags;
local_irq_save(flags);
set_c0_status(0x100 << irq_nr);
local_irq_restore(flags);
}
static unsigned int startup_ev96100_irq(unsigned int irq)
{
enable_ev96100_irq(irq);
return 0; /* never anything pending */
}
#define shutdown_ev96100_irq disable_ev96100_irq
#define mask_and_ack_ev96100_irq disable_ev96100_irq
static void end_ev96100_irq (unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
enable_ev96100_irq(irq);
}
static inline unsigned int ffz8(unsigned int word)
{
unsigned long k;
k = 7;
if (word & 0x0fUL) { k -= 4; word <<= 4; }
if (word & 0x30UL) { k -= 2; word <<= 2; }
if (word & 0x40UL) { k -= 1; }
return k;
}
asmlinkage void ev96100_cpu_irq(unsigned long cause, struct pt_regs * regs)
{
if (!(cause & 0xff00))
return;
do_IRQ(ffz8((cause >> 8) & 0xff), regs);
}
static struct hw_interrupt_type ev96100_irq_type = {
"EV96100",
startup_ev96100_irq,
shutdown_ev96100_irq,
enable_ev96100_irq,
disable_ev96100_irq,
mask_and_ack_ev96100_irq,
end_ev96100_irq
};
void __init init_IRQ(void)
{
int i;
set_except_vector(0, ev96100IRQ);
init_generic_irq();
for (i = 0; i < 8; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = 0;
irq_desc[i].depth = 1;
irq_desc[i].handler = &ev96100_irq_type;
}
}
/*
* Debug routines which directly access the uart.
*/
#include <linux/types.h>
#include <asm/galileo-boards/ev96100.h>
//#define SERIAL_BASE EV96100_UART0_REGS_BASE
#define SERIAL_BASE 0xBD000020
#define NS16550_BASE SERIAL_BASE
#define SERA_CMD 0x0D
#define SERA_DATA 0x08
//#define SERB_CMD 0x05
#define SERB_CMD 20
#define SERB_DATA 0x00
#define TX_BUSY 0x20
#define TIMEOUT 0xffff
#undef SLOW_DOWN
static const char digits[16] = "0123456789abcdef";
static volatile unsigned char * const com1 = (unsigned char *)SERIAL_BASE;
#ifdef SLOW_DOWN
static inline void slow_down()
{
int k;
for (k=0; k<10000; k++);
}
#else
#define slow_down()
#endif
void
putch(const unsigned char c)
{
unsigned char ch;
int i = 0;
do {
ch = com1[SERB_CMD];
slow_down();
i++;
if (i>TIMEOUT) {
break;
}
} while (0 == (ch & TX_BUSY));
com1[SERB_DATA] = c;
}
void
putchar(const unsigned char c)
{
unsigned char ch;
int i = 0;
do {
ch = com1[SERB_CMD];
slow_down();
i++;
if (i>TIMEOUT) {
break;
}
} while (0 == (ch & TX_BUSY));
com1[SERB_DATA] = c;
}
void
puts(unsigned char *cp)
{
unsigned char ch;
int i = 0;
while (*cp) {
do {
ch = com1[SERB_CMD];
slow_down();
i++;
if (i>TIMEOUT) {
break;
}
} while (0 == (ch & TX_BUSY));
com1[SERB_DATA] = *cp++;
}
putch('\r');
putch('\n');
}
void
fputs(unsigned char *cp)
{
unsigned char ch;
int i = 0;
while (*cp) {
do {
ch = com1[SERB_CMD];
slow_down();
i++;
if (i>TIMEOUT) {
break;
}
} while (0 == (ch & TX_BUSY));
com1[SERB_DATA] = *cp++;
}
}
void
put64(uint64_t ul)
{
int cnt;
unsigned ch;
cnt = 16; /* 16 nibbles in a 64 bit long */
putch('0');
putch('x');
do {
cnt--;
ch = (unsigned char)(ul >> cnt * 4) & 0x0F;
putch(digits[ch]);
} while (cnt > 0);
}
void
put32(unsigned u)
{
int cnt;
unsigned ch;
cnt = 8; /* 8 nibbles in a 32 bit long */
putch('0');
putch('x');
do {
cnt--;
ch = (unsigned char)(u >> cnt * 4) & 0x0F;
putch(digits[ch]);
} while (cnt > 0);
}
/*
* BRIEF MODULE DESCRIPTION
* Galileo EV96100 setup.
*
* Copyright 2000 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* This file was derived from Carsten Langgaard's
* arch/mips/mips-boards/atlas/atlas_setup.c.
*
* Carsten Langgaard, carstenl@mips.com
* Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
*
* 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/config.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/ioport.h>
#include <linux/mc146818rtc.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/pci.h>
#include <linux/major.h>
#include <linux/kdev_t.h>
#include <linux/root_dev.h>
#include <asm/cpu.h>
#include <asm/bootinfo.h>
#include <asm/mipsregs.h>
#include <asm/irq.h>
#include <asm/delay.h>
#include <asm/gt64120.h>
#include <asm/galileo-boards/ev96100.h>
#include <asm/galileo-boards/ev96100int.h>
#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE)
extern void console_setup(char *, int *);
char serial_console[20];
#endif
extern char * __init prom_getcmdline(void);
extern void mips_reboot_setup(void);
extern struct rtc_ops no_rtc_ops;
extern struct resource ioport_resource;
unsigned char mac_0_1[12];
void __init ev96100_setup(void)
{
unsigned long config = read_c0_config();
unsigned long status = read_c0_status();
unsigned long info = read_c0_info();
u32 tmp;
char *argptr;
clear_c0_status(ST0_FR);
if (config & 0x8) {
printk("Secondary cache is enabled\n");
}
else {
printk("Secondary cache is disabled\n");
}
if (status & (1<<27)) {
printk("User-mode cache ops enabled\n");
}
else {
printk("User-mode cache ops disabled\n");
}
printk("CP0 info reg: %x\n", (unsigned)info);
if (info & (1<<28)) {
printk("burst mode Scache RAMS\n");
}
else {
printk("pipelined Scache RAMS\n");
}
if ((info & (0x3<<26)) >> 26 == 0) {
printk("67 percent drive strength\n");
}
else if ((info & (0x3<<26)) >> 26 == 1) {
printk("50 percent drive strength\n");
}
else if ((info & (0x3<<26)) >> 26 == 2) {
printk("100 percent drive strength\n");
}
else if ((info & (0x3<<26)) >> 26 == 3) {
printk("83 percent drive strength\n");
}
if ((info & (0x3<<23)) >> 23 == 0) {
printk("Write Protocol: R4000 compatible\n");
}
else if ((info & (0x3<<23)) >> 23 == 1) {
printk("Write Protocol: Reserved\n");
}
else if ((info & (0x3<<23)) >> 23 == 2) {
printk("Write Protocol: Pipelined\n");
}
else if ((info & (0x3<<23)) >> 23 == 3) {
printk("Write Protocol: Write re-issue\n");
}
if (info & 0x1) {
printk("Atomic Enable is set\n");
}
argptr = prom_getcmdline();
#ifdef CONFIG_SERIAL_CONSOLE
if (strstr(argptr, "console=") == NULL) {
argptr = prom_getcmdline();
strcat(argptr, " console=ttyS0,115200");
}
#endif
rtc_ops = &no_rtc_ops;
mips_reboot_setup();
set_io_port_base(KSEG1);
ioport_resource.start = GT_PCI_IO_BASE;
ioport_resource.end = GT_PCI_IO_BASE + 0x01ffffff;
#ifdef CONFIG_BLK_DEV_INITRD
ROOT_DEV = Root_RAM0;
#endif
/*
* setup gt controller master bit so we can do config cycles
*/
/* Clear cause register bits */
GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
GT_INTRCAUSE_TARABORT0_BIT));
/* Setup address */
GT_WRITE(GT_PCI0_CFGADDR_OFS,
(0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
(0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
GT_PCI0_CFGADDR_CONFIGEN_BIT);
udelay(2);
tmp = le32_to_cpu(*(volatile u32 *)(MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS));
tmp |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
GT_WRITE(GT_PCI0_CFGADDR_OFS,
(0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
(0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
GT_PCI0_CFGADDR_CONFIGEN_BIT);
udelay(2);
*(volatile u32 *)(MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS) = cpu_to_le32(tmp);
/* Setup address */
GT_WRITE(GT_PCI0_CFGADDR_OFS,
(0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
(0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
GT_PCI0_CFGADDR_CONFIGEN_BIT);
udelay(2);
tmp = le32_to_cpu(*(volatile u32 *)(MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS));
}
unsigned short get_gt_devid(void)
{
u32 gt_devid;
/* Figure out if this is a gt96100 or gt96100A */
GT_WRITE(GT_PCI0_CFGADDR_OFS,
(0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
(0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
((PCI_VENDOR_ID / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
GT_PCI0_CFGADDR_CONFIGEN_BIT);
udelay(4);
gt_devid = le32_to_cpu(*(volatile u32 *)
(MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS));
return (unsigned short)(gt_devid>>16);
}
/*
* BRIEF MODULE DESCRIPTION
* Galileo EV96100 rtc routines.
*
* Copyright 2000 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* This file was derived from Carsten Langgaard's
* arch/mips/mips-boards/atlas/atlas_rtc.c.
*
* Carsten Langgaard, carstenl@mips.com
* Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
*
* 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_stat.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <asm/mipsregs.h>
#include <asm/ptrace.h>
#include <linux/timex.h>
#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
extern volatile unsigned long wall_jiffies;
unsigned long missed_heart_beats = 0;
static unsigned long r4k_offset; /* Amount to increment compare reg each time */
static unsigned long r4k_cur; /* What counter should be at next timer irq */
static inline void ack_r4ktimer(unsigned long newval)
{
write_c0_compare(newval);
}
static int set_rtc_mmss(unsigned long nowtime)
{
/* EV96100 does not have a real time clock */
int retval = 0;
return retval;
}
/*
* Figure out the r4k offset, the amount to increment the compare
* register for each time tick.
* Use the RTC to calculate offset.
*/
static unsigned long __init cal_r4koff(void)
{
unsigned long count;
count = 300000000/2;
return (count / HZ);
}
static unsigned long __init get_mips_time(void)
{
unsigned int year, mon, day, hour, min, sec;
year = 2000;
mon = 10;
day = 31;
hour = 0;
min = 0;
sec = 0;
return mktime(year, mon, day, hour, min, sec);
}
/*
* called from start_kernel()
*/
void __init time_init(void)
{
unsigned int est_freq;
r4k_offset = cal_r4koff();
est_freq = 2*r4k_offset*HZ;
est_freq += 5000; /* round */
est_freq -= est_freq%10000;
printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
(est_freq%1000000)*100/1000000);
r4k_cur = (read_c0_count() + r4k_offset);
write_c0_compare(r4k_cur);
change_c0_status(ST0_IM, IE_IRQ5); /* FIX ME */
}
/* This is for machines which generate the exact clock. */
#define USECS_PER_JIFFY (1000000/HZ)
/* Cycle counter value at the previous timer interrupt.. */
static unsigned int timerhi = 0, timerlo = 0;
/*
* FIXME: Does playing with the RP bit in c0_status interfere with this code?
*/
static unsigned long do_fast_gettimeoffset(void)
{
u32 count;
unsigned long res, tmp;
/* Last jiffy when do_fast_gettimeoffset() was called. */
static unsigned long last_jiffies=0;
unsigned long quotient;
/*
* Cached "1/(clocks per usec)*2^32" value.
* It has to be recalculated once each jiffy.
*/
static unsigned long cached_quotient=0;
tmp = jiffies;
quotient = cached_quotient;
if (tmp && last_jiffies != tmp) {
last_jiffies = tmp;
__asm__(".set\tnoreorder\n\t"
".set\tnoat\n\t"
".set\tmips3\n\t"
"lwu\t%0,%2\n\t"
"dsll32\t$1,%1,0\n\t"
"or\t$1,$1,%0\n\t"
"ddivu\t$0,$1,%3\n\t"
"mflo\t$1\n\t"
"dsll32\t%0,%4,0\n\t"
"nop\n\t"
"ddivu\t$0,%0,$1\n\t"
"mflo\t%0\n\t"
".set\tmips0\n\t"
".set\tat\n\t"
".set\treorder"
:"=&r" (quotient)
:"r" (timerhi),
"m" (timerlo),
"r" (tmp),
"r" (USECS_PER_JIFFY));
cached_quotient = quotient;
}
/* Get last timer tick in absolute kernel time */
count = read_c0_count();
/* .. relative to previous jiffy (32 bits is enough) */
count -= timerlo;
__asm__("multu\t%1,%2\n\t"
"mfhi\t%0"
:"=r" (res)
:"r" (count),
"r" (quotient));
/*
* Due to possible jiffies inconsistencies, we need to check
* the result so that we'll get a timer that is monotonic.
*/
if (res >= USECS_PER_JIFFY)
res = USECS_PER_JIFFY-1;
return res;
}
/*
* This version of gettimeofday has microsecond resolution
* and better than microsecond precision on fast x86 machines with TSC.
*/
void do_gettimeofday(struct timeval *tv)
{
unsigned long seq;
unsigned long usec, sec;
do {
seq = read_seqbegin(&xtime_lock);
usec = do_gettimeoffset();
{
unsigned long lost = jiffies - wall_jiffies;
if (lost)
usec += lost * (1000000 / HZ);
}
sec = xtime.tv_sec;
usec += (xtime.tv_nsec / 1000);
} while (read_seqretry(&xtime_lock, seq));
while (usec >= 1000000) {
usec -= 1000000;
sec++;
}
tv->tv_sec = sec;
tv->tv_usec = usec;
}
void do_settimeofday(struct timeval *tv)
{
write_seqlock_irq(&xtime_lock);
/*
* This is revolting. We need to set "xtime" correctly. However, the
* value in this location is the value at the most recent update of
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
tv->tv_usec -= do_gettimeoffset();
tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ);
while (tv->tv_usec < 0) {
tv->tv_usec += 1000000;
tv->tv_sec--;
}
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = (tv->tv_usec * 1000);
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
write_sequnlock_irq(&xtime_lock);
}
/*
* There are a lot of conceptually broken versions of the MIPS timer interrupt
* handler floating around. This one is rather different, but the algorithm
* is probably more robust.
*/
void mips_timer_interrupt(struct pt_regs *regs)
{
int irq = 7; /* FIX ME */
if (r4k_offset == 0) {
goto null;
}
do {
kstat_cpu(0).irqs[irq]++;
do_timer(regs);
r4k_cur += r4k_offset;
ack_r4ktimer(r4k_cur);
} while (((unsigned long)read_c0_count()
- r4k_cur) < 0x7fffffff);
return;
null:
ack_r4ktimer(0);
}
#
# Carsten Langgaard, carstenl@mips.com
# Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
#
# ########################################################################
#
# This program is free software; you can distribute it and/or modify it
# under the terms of the GNU General Public License (Version 2) as
# published by the Free Software Foundation.
#
# This program is distributed in the hope it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# 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.,
# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
#
# #######################################################################
#
# Makefile for the MIPS boards generic routines under Linux.
#
obj-y := reset.o
/*
* BRIEF MODULE DESCRIPTION
* Galileo EV96100 reset routines.
*
* Copyright 2000 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* This file was derived from Carsten Langgaard's
* arch/mips/mips-boards/generic/reset.c
*
* Carsten Langgaard, carstenl@mips.com
* Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
*
* 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/sched.h>
#include <linux/mm.h>
#include <asm/cacheflush.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/reboot.h>
#include <asm/system.h>
#include <asm/reboot.h>
#include <asm/galileo-boards/ev96100.h>
static void mips_machine_restart(char *command);
static void mips_machine_halt(void);
static void mips_machine_restart(char *command)
{
set_c0_status(ST0_BEV | ST0_ERL);
change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
flush_cache_all();
write_c0_wired(0);
__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
while (1);
}
static void mips_machine_halt(void)
{
printk(KERN_NOTICE "You can safely turn off the power\n");
while (1)
__asm__(".set\tmips3\n\t"
"wait\n\t"
".set\tmips0");
}
void mips_reboot_setup(void)
{
_machine_restart = mips_machine_restart;
_machine_halt = mips_machine_halt;
}
/*
* This is a direct copy of the ev96100.h file, with a global
* search and replace. The numbers are the same.
*
* The reason I'm duplicating this is so that the 64120/96100
* defines won't be confusing in the source code.
*/
#ifndef _MIPS_EV64120_H
#define _MIPS_EV64120_H
#include <asm/addrspace.h>
/*
* GT64120 config space base address
*/
#define GT64120_BASE (KSEG1ADDR(0x14000000))
#define MIPS_GT_BASE GT64120_BASE
/*
* PCI Bus allocation
*/
#define GT_PCI_MEM_BASE 0x12000000
#define GT_PCI_MEM_SIZE 0x02000000
#define GT_PCI_IO_BASE 0x10000000
#define GT_PCI_IO_SIZE 0x02000000
#define GT_ISA_IO_BASE PCI_IO_BASE
/*
* Duart I/O ports.
*/
#define EV64120_COM1_BASE_ADDR (0x1d000000 + 0x20)
#define EV64120_COM2_BASE_ADDR (0x1d000000 + 0x00)
/*
* EV64120 interrupt controller register base.
*/
#define EV64120_ICTRL_REGS_BASE (KSEG1ADDR(0x1f000000))
/*
* EV64120 UART register base.
*/
#define EV64120_UART0_REGS_BASE (KSEG1ADDR(EV64120_COM1_BASE_ADDR))
#define EV64120_UART1_REGS_BASE (KSEG1ADDR(EV64120_COM2_BASE_ADDR))
#define EV64120_BASE_BAUD ( 3686400 / 16 )
/*
* Because of an error/peculiarity in the Galileo chip, we need to swap the
* bytes when running bigendian.
*/
#define GT_WRITE(ofs, data) \
*(volatile u32 *)(MIPS_GT_BASE+ofs) = cpu_to_le32(data)
#define GT_READ(ofs, data) \
*data = le32_to_cpu(*(volatile u32 *)(MIPS_GT_BASE+ofs))
#endif /* !(_MIPS_EV64120_H) */
#ifndef IRQ_HANDLER_
#define IRQ_HANDLER_
#define INT_CAUSE_MAIN 0
#define INT_CAUSE_HIGH 1
#define MAX_CAUSE_REGS 4
#define MAX_CAUSE_REG_WIDTH 32
void hook_irq_handler (int int_cause , int bit_num , void *isr_ptr);
int disable_galileo_irq (int int_cause , int bit_num);
int enable_galileo_irq (int int_cause , int bit_num);
extern struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH];
/*
PCI interrupts will come in on either the INTA or
INTD interrups lines, which are mapped to the #2 and
#5 interrupt pins of the MIPS. On our boards, they
all either come in on IntD or they all come in on
IntA, they aren't mixed. There can be numerous PCI
interrupts, so we keep a list of the "requested"
interrupt numbers and go through the list whenever
we get an IntA/D.
All PCI interrupts have numbers >= 20 by arbitrary convention. Any
interrupt < 8 is an interrupt that is maskable on the
MIPS.
*/
#define TIMER 4
#define INTA 2
#define INTD 5
#endif /* IRQ_HANDLER_ */
/*
*
*/
#ifndef _MIPS_EV96100_H
#define _MIPS_EV96100_H
#include <asm/addrspace.h>
/*
* GT64120 config space base address
*/
#define GT64120_BASE (KSEG1ADDR(0x14000000))
#define MIPS_GT_BASE GT64120_BASE
/*
* PCI Bus allocation
*/
#define GT_PCI_MEM_BASE 0x12000000
#define GT_PCI_MEM_SIZE 0x02000000
#define GT_PCI_IO_BASE 0x10000000
#define GT_PCI_IO_SIZE 0x02000000
#define GT_ISA_IO_BASE PCI_IO_BASE
/*
* Duart I/O ports.
*/
#define EV96100_COM1_BASE_ADDR (0xBD000000 + 0x20)
#define EV96100_COM2_BASE_ADDR (0xBD000000 + 0x00)
/*
* EV96100 interrupt controller register base.
*/
#define EV96100_ICTRL_REGS_BASE (KSEG1ADDR(0x1f000000))
/*
* EV96100 UART register base.
*/
#define EV96100_UART0_REGS_BASE EV96100_COM1_BASE_ADDR
#define EV96100_UART1_REGS_BASE EV96100_COM2_BASE_ADDR
#define EV96100_BASE_BAUD ( 3686400 / 16 )
/*
* Because of an error/peculiarity in the Galileo chip, we need to swap the
* bytes when running bigendian.
*/
#define GT_WRITE(ofs, data) \
*(volatile u32 *)(MIPS_GT_BASE+ofs) = cpu_to_le32(data)
#define GT_READ(ofs, data) \
data = le32_to_cpu(*(volatile u32 *)(MIPS_GT_BASE+ofs))
#endif /* !(_MIPS_EV96100_H) */
/*
*
*/
#ifndef _MIPS_EV96100INT_H
#define _MIPS_EV96100INT_H
#define EV96100INT_UART_0 6 /* IP 6 */
#define EV96100INT_TIMER 7 /* IP 7 */
extern void ev96100int_init(void);
#endif /* !(_MIPS_EV96100_H) */
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment