diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-12-04 04:04:09 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-12-04 04:04:09 +0000 |
commit | 074da8c3f230190b4a00177ff781f0a76d8b0dfe (patch) | |
tree | f62c562c8c324258f0c79cea9b99172783212827 /arch/mips/galileo-boards | |
parent | 1fbefa026d5a271ed014b1bb730de8de06ca89d5 (diff) |
EV64120 support. From Steve Johnson.
Diffstat (limited to 'arch/mips/galileo-boards')
40 files changed, 11814 insertions, 0 deletions
diff --git a/arch/mips/galileo-boards/ev64120/Makefile b/arch/mips/galileo-boards/ev64120/Makefile new file mode 100644 index 000000000..af08f9dcd --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/Makefile @@ -0,0 +1,27 @@ +# +# Copyright 2000 RidgeRun, Inc. +# Author: RidgeRun, Inc. +# glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com +# +# Makefile for the Galileo EV64120 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 + +all: ev64120.o +O_TARGET := ev64120.o +O_OBJS := serialGT.o int-handler.o promcon.o reset.o setup.o irq.o irq-handler.o i2o.o pci_bios.o + +int-handler.o: int-handler.S + +clean: + *.o + +include $(TOPDIR)/Rules.make diff --git a/arch/mips/galileo-boards/ev64120/cntmr.c b/arch/mips/galileo-boards/ev64120/cntmr.c new file mode 100644 index 000000000..568a88cb0 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/cntmr.c @@ -0,0 +1,207 @@ +/* cntmr.c - GT counters/timers functions */ + +/* Copyright - Galileo technology. 9/3/2000 */ + +/* +DESCRIPTION +This file contains function which serves the user with a complete interface +to the GT internal counters and timers, please advise: each counter/timer unit +can function only as a counter or a timer at current time. +Counter/timer 0 is 32 bit wide. +Counters/timers 1-3 are 24 bit wide. +*/ + +/* includes */ + +#ifdef __linux__ +#include <asm/galileo/evb64120A/cntmr.h> +#include <asm/galileo/evb64120A/core.h> +#else +#include "cntmr.h" +#include "core.h" +#endif + +/******************************************************************** +* cntTmrStart - Starts a counter/timer with given an initiate value. +* +* INPUTS: unsigned int countNum - Selects one of the 8 counters/timers. +* unsigned int countValue - Initial value for count down. +* CNT_TMR_OP_MODES opMode - Set Mode, Counter or Timer. +* +* RETURNS: false if one of the parameters is erroneous, true otherwise. +*********************************************************************/ + +bool cntTmrStart(CNTMR_NUM countNum, unsigned int countValue, + CNT_TMR_OP_MODES opMode) +{ + unsigned int command = 1; + unsigned int value; + + if (countNum > LAST_CNTMR) + return false; + else { + GT_REG_READ(TIMER_COUNTER_CONTROL, &value); + cntTmrDisable(countNum); + GT_REG_WRITE((TIMER_COUNTER0 + (4 * countNum)), + countValue); + command = command << countNum * 2; + value = value | command; + command = command << 1; + switch (opMode) { + case TIMER: /* The Timer/Counter bit set to logic '1' */ + value = value | command; + break; + case COUNTER: /* The Timer/Counter bit set to logic '0' */ + value = value & ~command; + break; + default: + return false; + } + GT_REG_WRITE(TIMER_COUNTER_CONTROL, value); + return true; + } +} + +/******************************************************************** +* cntTmrDisable - Disables the timer/counter operation and return its +* value. +* +* INPUTS: unsigned int countNum - Selects one of the 8 counters/timers. +* RETURNS: The counter/timer value (unsigned int), if any of the arguments are +* erroneous return 0. +*********************************************************************/ + +unsigned int cntTmrDisable(CNTMR_NUM countNum) +{ + unsigned int command = 1; + unsigned int regValue; + unsigned int value; + + GT_REG_READ(TIMER_COUNTER_CONTROL, &value); + if (countNum > LAST_CNTMR) + return 0; + GT_REG_READ(TIMER_COUNTER0 + 4 * countNum, ®Value); + command = command << countNum * 2; /* Disable the timer/counter */ + value = value & ~command; + GT_REG_WRITE(TIMER_COUNTER_CONTROL, value); + return regValue; +} + +/******************************************************************** +* cntTmrRead - Reads a timer or a counter value. (This operation can be +* perform while the counter/timer is active). +* +* RETURNS: The counter/timer value. If wrong input value, return 0. +*********************************************************************/ + +unsigned int cntTmrRead(CNTMR_NUM countNum) +{ + unsigned int value; + if (countNum > LAST_CNTMR) + return 0; + else + GT_REG_READ(TIMER_COUNTER0 + countNum * 4, &value); + return value; +} + +/******************************************************************** +* cntTmrEnable - Set enable-bit of timer/counter. +* Be aware: If the counter/timer is active, this function +* will terminate with an false. +* +* INPUTS: unsigned int countNum - Selects one of the 8 counters/timers. +* RETURNS: false if one of the parameters is erroneous, true otherwise. +*********************************************************************/ + +bool cntTmrEnable(CNTMR_NUM countNum) +{ + unsigned int command = 1; + unsigned int value; + GT_REG_READ(TIMER_COUNTER_CONTROL, &value); + if (countNum > LAST_CNTMR) + return false; + else { + command = command << countNum * 2; + if ((command & value) != 0) /* ==> The counter/timer is enabled */ + return false; /* doesn't make sense to Enable an "enabled" counter */ + value = value | command; + GT_REG_WRITE(TIMER_COUNTER_CONTROL, value); + return true; + } +} + +/******************************************************************** +* cntTmrLoad - loading value for timer number countNum. +* Be aware: If this function try to load value to an enabled +* counter/timer it terminate with false. +* +* INPUTS: unsigned int countNum - Selects one of the 8 counters/timers. +* unsigned int countValue - The value for load the register. +* RETURNS: false if one of the parameters is erroneous, true otherwise. +*********************************************************************/ + +bool cntTmrLoad(unsigned int countNum, unsigned int countValue) +{ + unsigned int command = 1; + unsigned int value; + GT_REG_READ(TIMER_COUNTER_CONTROL, &value); + if (countNum > LAST_CNTMR) + return false; + else { + command = command << countNum * 2; + value = value & command; + if (value != 0) { /* ==> The counter/timer is enabled */ + return false; /* can't reload value when counter/timer is enabled */ + } else { + GT_REG_WRITE((TIMER_COUNTER0 + (4 * countNum)), + countValue); + return true; + } + + } +} + +/******************************************************************** +* cntTmrSetMode - Configurate the Mode of the channel to work as a counter +* or as a timer. (for more details on the different between +* those two modes is written in the Data Sheet). +* NOTE: This function only set the counter/timer mode and +* don't enable it. +* Be aware: If this function try to load value to an enabled +* counter/timer it terminate with false. +* +* INPUTS: unsigned int countNum - Selects one of the 8 counters/timers. +* CNT_TMR_OP_MODES opMode - TIMER or COUNTER mode. +* RETURNS: false if one of the parameters is erroneous true otherwise . +*********************************************************************/ + +bool cntTmrSetMode(CNTMR_NUM countNum, CNT_TMR_OP_MODES opMode) +{ + unsigned int command = 1; + unsigned int value; + + GT_REG_READ(TIMER_COUNTER_CONTROL, &value); + if (countNum > LAST_CNTMR) + return false; + else { + command = command << countNum * 2; + value = value & command; + if (value != 0) { /* ==> The counter/timer is enabled */ + return false; /* can't set the Mode when counter/timer is enabled */ + } else { + command = command << 1; + switch (opMode) { + case TIMER: + value = value | command; /* The Timer/Counter bit set to logic '1' */ + break; + case COUNTER: + value = value & ~command; /*The Timer/Counter bit set to logic '0' */ + break; + default: + return false; + } + GT_REG_WRITE(TIMER_COUNTER_CONTROL, value); + return true; + } + } +} diff --git a/arch/mips/galileo-boards/ev64120/compressed/Makefile b/arch/mips/galileo-boards/ev64120/compressed/Makefile new file mode 100644 index 000000000..1390af515 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/Makefile @@ -0,0 +1,180 @@ +# ============================================================= +# +# linux/arch/mips/galileo/compressed/Makefile +# +# By RidgeRun Inc. +# +# Description: +# Create a system containing a copy of the compressed vmlinux kernel. +# The system knows how to decompress the contained kernel and then +# jump to it resulting in a linux kernel boot. +# +# The system comes in three forms: +# +# 1. - ramsys - +# to be loaded into ram then run. When run +# it decompresses the kernel housed in its internal +# data structures and then jumps to the image which +# results in a linux kernel boot. +# +# 2. - flashsys - +# to be loaded into ram so that it can be +# burned into the onboard flash. Then the board jumpers +# can be switched so that the next power cycle caused +# the system in flash to run which then proceeds as +# described by #1 above. +# Note: burner.srec is the utility that will allow +# the user to get this image into flash. +# +# 3. - flashsys2 - +# to be loaded into ram so that it can be +# burned into the onboard flash. Then on each power +# cycle when the standard PMON prompt is presented +# the user can type `call 0xbf000000` to invoke +# the system in flash which then proceeds as +# described by #1 above. +# Note: burner.srec is the utility that will allow +# the user to get this image into flash. +# +# 4. - burner.srec - +# related to #2 and #3 above. +# +# ============================================================= + +all: ramsys.srec \ + flashsys.srec \ + flashsys2.srec \ + burner.srec + +SYSTEM = $(TOPDIR)/vmlinux + +CFLAGS_2 = -DCONSOLE_SERIAL -DDELIMITERLINES -DGALILEO_PORT \ + -DANSIESC -DELF_IMAGE -DELF_IMAGE -DDOWNLOAD_PROTO_TFTP \ + -DEVB64120A -D__MIPSEB__ -DINCLUDE_EEPRO100 \ + -DINCLUDE_GETH0 -DNOPRINTK -DPROM -DCOMPRESSEDVMLINUX + +sbdreset_evb64120A.o: + $(CC) $(CFLAGS) $(CFLAGS_2) -c sbdreset_evb64120A.S -o $*.o +memory.o: + $(CC) $(CFLAGS) $(CFLAGS_2) -c memory.c -o $*.o +pci.o: + $(CC) $(CFLAGS) $(CFLAGS_2) -c pci.c -o $*.o +pci_etherboot.o: + $(CC) $(CFLAGS) $(CFLAGS_2) -c pci_etherboot.c -o $*.o +load.o: + $(CC) $(CFLAGS) $(CFLAGS_2) -c load.c -o $*.o +flashdrv.o: + $(CC) $(CFLAGS) $(CFLAGS_2) -c flashdrv.c -o $*.o + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +gz2asm: gz2asm.c + g++ -o gz2asm gz2asm.c + +doit: doit.c + gcc -o doit doit.c + +piggy.gz: $(SYSTEM) + rm -f piggy piggy.gz + $(OBJCOPY) -S -O binary $(SYSTEM) piggy + gzip -f -9 < piggy > piggy.gz + +piggy.S: doit fixit piggy.gz + ./doit < piggy.gz > piggy.S; . ./fixit piggy.S + +OBJECTS_ramsys = head.o misc.o piggy.o ../serialGT.o +OBJECTS_flashsys = sbdreset_evb64120A.o evb64120A_Setup.o pci_etherboot.o memory.o pci.o head.o misc.o piggy.o ../serialGT.o +OBJECTS_flashsys2 = xfer.o head.o misc.o piggy.o ../serialGT.o +OBJECTS_burner = burner.o load.o flashdrv.o + +ramsys.srec : $(OBJECTS_ramsys) ld.script.gal + @# Note: this image is intended to run out of ram. No flash involved. + $(LD) -T ld.script.gal -o ramsys $(OBJECTS_ramsys) + $(NM) ramsys | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System_ramsys.map + $(OBJCOPY) -O srec ramsys ramsys.srec + cp ramsys.srec $(TOPDIR)/. + +flashsys.srec : $(OBJECTS_flashsys) ld.sys.big.Flash + @# Note1: Use the burn utility to get this image into flash. + @# Note2: This image is intended to run out of flash as invoked + @# directly at powerup when EVB64120A jumpers are configured to + @# bypass the onboard eprom. + @# Assumes that 0xBFC00000 is the bootup run address (normal MIPS). + @# And assumes that EVB64120A jumber J11 is added to the board and jumber + @# J20 is moved from the 2&3 position to the 1&2 position instead. Without + @# the jumper settings the system will execute at address 0xBFC00000, + @# as normal, yet that address will map to the onboard eeprom instead + @# of the onboard flash. + @# + $(LD) -T ld.sys.big.Flash -o flashsys $(OBJECTS_flashsys) + $(NM) flashsys | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | sort > System_flashsys.map + @# + @# Next, Create the image that we want to place in the flash part. + $(OBJCOPY) -S -g --strip-unneeded \ + --adjust-section-vma=.text+0x3f820000 \ + --adjust-section-vma=.rodata+0x3f820000 \ + --adjust-section-vma=.reginfo+0x3f820000 \ + --adjust-section-vma=.data+0x3f820000 \ + --remove-section=.bss \ + --remove-section=.scommon \ + --remove-section=.note \ + --remove-section=.comment \ + flashsys flashsys.temp + @# + @# Next, change the addresses so that when we download to + @# to the board's ram it will land starting at address 0xA0300000 + @# because this is where we have choosen to have the image temporarily sit + @# while we subsequently burn it (using some method not revealed here) into + @# the board's flash. After the burn the system can be setup (via jumpers) + @# to boot this image directory from the flash part. + $(OBJCOPY) -O srec --adjust-vma=0xe0700000 flashsys.temp flashsys.srec + cp flashsys.srec $(TOPDIR)/. + +flashsys2.srec : $(OBJECTS_flashsys2) ld.sys.big.Flash2 + @# Note1: Use the burn utility to get this image into flash. + @# Note2: This image is intended to be run out of flash as invoked + @# manually from the standard PMON running in eprom. This means that + @# the image will be set to run from location 0xBF000000 which is the + @# location the flash is mapped to when the board jumpers are set to + @# the standard location such that the board boots out of onboard + @# eprom. From the PMON prompt the user can type `call 0xbf000000` + @# to transfer control to the image we are constructing here. + @# + $(LD) -T ld.sys.big.Flash2 -o flashsys2 $(OBJECTS_flashsys2) + $(NM) flashsys2 | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | sort > System_flashsys2.map + @# + @# Next, Create the image that we want to place in the flash part. + $(OBJCOPY) -S -g --strip-unneeded \ + --adjust-section-vma=.text+0x3ec20000 \ + --adjust-section-vma=.rodata+0x3ec20000 \ + --adjust-section-vma=.reginfo+0x3ec20000 \ + --adjust-section-vma=.data+0x3ec20000 \ + --remove-section=.bss \ + --remove-section=.scommon \ + --remove-section=.note \ + --remove-section=.comment \ + flashsys2 flashsys2.temp + @# + @# Next, change the addresses so that when we download to + @# to the board's ram it will land starting at address 0xA0300000 + @# because this is where we have choosen to have the image temporarily sit + @# while we subsequently burn it (using some method not revealed here) into + @# the board's flash. After the burn a user will then be able to type + @# `call 0xbf000000` at the PMON prompt (following a power cycle) to invoke + @# the linux kernel. + $(OBJCOPY) -O srec --adjust-vma=0xe1300000 flashsys2.temp flashsys2.srec + cp flashsys2.srec $(TOPDIR)/. + +burner.srec : $(OBJECTS_burner) ld.sys.big.burner + @# This utility can be used to burn the flashsys.srec or flashsys2.srec + @# into the EVB64120A's on board flash part (1Meg minimum). + $(LD) -T ld.sys.big.burner -o burner $(OBJECTS_burner) + $(NM) burner | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System_burner.map + $(OBJCOPY) -O srec burner burner.srec + cp burner.srec $(TOPDIR)/. + +clean: + rm -f doit piggy.S piggy.gz piggy burner *.o ramsys* flashsys* System*.map *.srec diff --git a/arch/mips/galileo-boards/ev64120/compressed/README b/arch/mips/galileo-boards/ev64120/compressed/README new file mode 100644 index 000000000..2edd146d1 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/README @@ -0,0 +1,131 @@ ++------------------------------------------------+ +| $TOPDIR/arch/mips/galileo/compressed/README | +| | +| By RidgeRun Inc, | +| Aug, 2000 | ++------------------------------------------------+ + +Description: +============ + It is intended that this makefile be wired in to run as + part of a top level linux build. For example, at the + time of this writing, if the user types "make gboot" at + the top level then in addition to building vmlinux the + build system's makefiles will descend into this + directory and build the "all:" target of this + Makefile. This will have the result of compressing the + vmlinux system and producing four separate systems. The + following snippet is pulled from this directory's + Makefile and describes each system. + + Four systems are availalbe for download to the EVB64120A + board. + + 1. - ramsys - + To be loaded into ram then run. When run + it decompresses the "vmlinux" kernel housed in its internal + data structures and then jumps to the image which + results in a linux kernel boot. + + 2. - flashsys - + To be loaded into ram so that it can be + burned into the onboard flash. Then the board jumpers + can be switched so that the next power cycle caused + the system in flash to run which then proceeds as + described by #1 above. + Note: burner.srec is the utility that will allow + the user to get this image into flash. + + 3. - flashsys2 - + To be loaded into ram so that it can be + burned into the onboard flash. Then on each power + cycle when the standard PMON prompt is presented + the user can type `call 0xbf000000` to invoke + the system in flash which then proceeds as + described by #1 above. + Note: burner.srec is the utility that will allow + the user to get this image into flash. + + 4. - burner.srec - + Related to #2 and #3 above. + +Example: Running from Ram +========================== + + In this scenario the compressed system is downloaded + into ram and run directly from there. No flash is involved + in this scenario. Naturally, the download must be repeated + on every power cycle. + + 1. At the PMON prompt type `load` + 2. Assuming you have your host connected to /dev/ttyS0 + type the following command in a host shell window. + `cat ramsys.srec > /dev/ttyS0` + 3. When the download completes type the following + at the PMON prompt: `g` + + +Example: Running from flash: Scenario #1 +======================================== + + In this scenario vmlinux runs out of flash code + automatically on every power up. This means that + standard PMON code (of eprom) never runs. + + 1. Place the boot jumpers in the Boot-from-eprom + state. This is the normal state and how the jumpers + are found when booting PMON. + + Jumper settings. J11 - Removed + J20 - Moved from the 1&2 position to + the 2&3 position instead + + 2. Use PMON to "load" the burner.srec image and then + run it. This utility will prompt you to download + the image that you want burned into the flash + part. + + 3. Send the flashsys.srec image to the running burner + utility. The utililty will indicate when the burn + process has completed. + + 4. Now switch off power and change the jumpers to + the boot-from-flash position. The next power cycle + will run the flash based system automatically. + + Jumper settings. J11 - Added. + J20 - Moved from the 2&3 position to + the 1&2 position instead + +Example: Running from flash: Scenario #2 +======================================== + + In this scenario vmlinux runs out of flash only if the + PMON user decides to jump there by issuing a command to + PMON. Every power cycle would continue to bring up PMON + and a user will have to reissue the jump command to + force control transfer to the flash system. + + 1. Insure that the boot jumpers are in the Boot-from-eprom + state. This is the normal state and how the jumpers + are found when booting PMON. + + Jumper settings. J11 - Removed + J20 - Moved from the 1&2 position to + the 2&3 position instead + + 2. Use PMON to "load" the burner.srec image and then + run it. This utility will prompt you to download + the image that you want burned into the flash + part. + + 3. Send the flashsys2.srec image to the running burner + utility. The utililty will indicate when the burn + process has completed. + + 4. Now that the image is in flash the user can invoke + the following PMON command whenever a vmlinux + boot is desired: + + call 0xbf000000 + diff --git a/arch/mips/galileo-boards/ev64120/compressed/burner.c b/arch/mips/galileo-boards/ev64120/compressed/burner.c new file mode 100644 index 000000000..0a2147c5c --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/burner.c @@ -0,0 +1,232 @@ +/* + * arch/mips/galileo/compressed/burner.c + * + * By RidgeRun Inc (Leveraged from Galileo's main.c, misc.c, etc). + * + * Burn image from ram to flash + * For use with Galileo EVB64120A MIPS eval board. + */ + +#include <linux/config.h> +#include <asm/types.h> +#include <asm/byteorder.h> +#include <asm/galileo-boards/evb64120A/eeprom_param.h> +#include <asm/galileo-boards/evb64120A/flashdrv.h> + +#define IMAGEOFFSET 0x00300000 + +static void burn_image_from_memory(void); +static char *sprintf(char *buf, const char *fmt, ...); +static void printf(const char *fmt, ...); + +unsigned int FlashSize; + +/****************************** + Routine: + Description: + ******************************/ +int main(void) +{ + printf("\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf(" +--------------------+\n"); + printf(" | |\n"); + printf(" | Flash Burn Utility |\n"); + printf(" | |\n"); + printf(" +--------------------+\n"); + printf("\n"); + printf("Please send your *.srec image to the parallel port\n"); + printf("\n"); + printf("Note: The *.srec image should be setup to\n"); + printf(" load into address 0xa0300000 where\n"); + printf(" it will then be transferred to flash\n"); + printf("\n"); + + SET_REG_BITS(0x468, BIT20); // Set Flash to be 16 bit wide + FlashSize = flashInit(0xbf000000, 2, X16); + + galileo_dl(); // read in the users *.srec image. + burn_image_from_memory(); // put it in flash. + + printf("\n"); + printf("\n"); + printf("+---------------+\n"); + printf("| Done |\n"); + printf("|(please reboot)|\n"); + printf("+---------------+\n"); + printf("\n"); + + while (1) { + } + return 0; +} + +/****************************** + Routine: + Description: + ******************************/ +static void burn_image_from_memory(void) +{ + unsigned int count, delta, temp, temp1; + unsigned int to_sector, last_sector; + + /* Find how many sectors needed to be erased */ + to_sector = flashInWhichSector(FlashSize - 4); // skranz, modified. + if (to_sector == 0xffffffff) { + printf + ("Flash Burning Error - Flash too small - Cannot burn image\n"); // skranz, modified. + return; + } + + /* Which is the last sector */ + last_sector = flashInWhichSector(FlashSize - 4); + delta = 0; + printf("\nErasing first %d sectors\n", to_sector); + for (count = 0; count < to_sector + 1; count++) { + printf("Erasing sector %d\n", count); + flashEraseSector(count); + } + printf("flash region size = %d\n", FlashSize); // skranz, added + printf("Sdram IMAGEOFFSET = %d\n", IMAGEOFFSET); // skranz, added + + printf("Burning from Sdram to %d mark; full burn.\n", FlashSize); + for (count = 0; count < (FlashSize - delta); count = count + 4) { + flashWriteWord(count, + *(unsigned int *) ((count | NONE_CACHEABLE) + + IMAGEOFFSET)); // skranz, modified. + temp = flashReadWord(count); + temp1 = *(unsigned int *) ((count | NONE_CACHEABLE) + IMAGEOFFSET); // skranz, modified. + if (((unsigned int) temp) != ((unsigned int) temp1)) { + printf + ("Burning error at address %X : flash(%X) sdram(%X)\n", + count, flashReadWord(count), + *(unsigned int *) ((count | NONE_CACHEABLE) + IMAGEOFFSET)); // skranz, modified. + printf("Aborting Prematurally.\n"); + break; + } + } + printf("Finished burning Image\n"); +} + +/****************************** + Routine: + Description: + Formats: + %X - 4 byte ASCII (8 hex digits) + %x - 2 byte ASCII (4 hex digits) + %b - 1 byte ASCII (2 hex digits) + %d - decimal (also %i) + %c - ASCII char + %s - ASCII string + %I - Internet address in x.x.x.x notation + ******************************/ +static char hex[] = "0123456789ABCDEF"; +static char *do_printf(char *buf, const char *fmt, const int *dp) +{ + register char *p; + char tmp[16]; + while (*fmt) { + if (*fmt == '%') { /* switch() uses more space */ + fmt++; + + if (*fmt == 'X') { + const long *lp = (const long *) dp; + register long h = *lp++; + dp = (const int *) lp; + *(buf++) = hex[(h >> 28) & 0x0F]; + *(buf++) = hex[(h >> 24) & 0x0F]; + *(buf++) = hex[(h >> 20) & 0x0F]; + *(buf++) = hex[(h >> 16) & 0x0F]; + *(buf++) = hex[(h >> 12) & 0x0F]; + *(buf++) = hex[(h >> 8) & 0x0F]; + *(buf++) = hex[(h >> 4) & 0x0F]; + *(buf++) = hex[h & 0x0F]; + } + if (*fmt == 'x') { + register int h = *(dp++); + *(buf++) = hex[(h >> 12) & 0x0F]; + *(buf++) = hex[(h >> 8) & 0x0F]; + *(buf++) = hex[(h >> 4) & 0x0F]; + *(buf++) = hex[h & 0x0F]; + } + if (*fmt == 'b') { + register int h = *(dp++); + *(buf++) = hex[(h >> 4) & 0x0F]; + *(buf++) = hex[h & 0x0F]; + } + if ((*fmt == 'd') || (*fmt == 'i')) { + register int dec = *(dp++); + p = tmp; + if (dec < 0) { + *(buf++) = '-'; + dec = -dec; + } + do { + *(p++) = '0' + (dec % 10); + dec = dec / 10; + } while (dec); + while ((--p) >= tmp) + *(buf++) = *p; + } + if (*fmt == 'I') { + union { + long l; + unsigned char c[4]; + } u; + const long *lp = (const long *) dp; + u.l = *lp++; + dp = (const int *) lp; + buf = sprintf(buf, "%d.%d.%d.%d", + u.c[0], u.c[1], u.c[2], + u.c[3]); + } + if (*fmt == 'c') + *(buf++) = *(dp++); + if (*fmt == 's') { + p = (char *) *dp++; + while (*p) + *(buf++) = *p++; + } + } else + *(buf++) = *fmt; + fmt++; + } + *buf = 0; + return (buf); +} + +/****************************** + Routine: + Description: + ******************************/ +static char *sprintf(char *buf, const char *fmt, ...) +{ + return do_printf(buf, fmt, ((const int *) &fmt) + 1); +} + +/****************************** + Routine: + Description: + ******************************/ +void putchar(int c) +{ + if (c == '\n') { + serial_putc('\r'); + } + serial_putc(c); +} + +/****************************** + Routine: + Description: + ******************************/ +static void printf(const char *fmt, ...) +{ + char buf[256], *p; + p = buf; + do_printf(buf, fmt, ((const int *) &fmt) + 1); + while (*p) + putchar(*p++); +} diff --git a/arch/mips/galileo-boards/ev64120/compressed/doit.c b/arch/mips/galileo-boards/ev64120/compressed/doit.c new file mode 100644 index 000000000..7986caae9 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/doit.c @@ -0,0 +1,75 @@ +/* + * By RidgeRun Inc. + * + * The input to this program is intended to be + * a compressed linux kernel. The output of this + * program is then a constructed *.S file which + * defines a large data structure -- the contents + * of which represent the compressed kernel which + * can subsequently be used in a program designed + * to access that struture for decompression at + * runtime and then subsequent kernel bootup. + * + * Example Usage: + * ./doit < piggy.gz > piggy.S + * + */ + +#include <stdio.h> + +void printval(int i) +{ + int tth, th, h, t, d; + + if (i > 99999) { + printf("Error - printval outofbounds\n"); + return; + } + + tth = 0; + th = 0; + //tth = (i) / 10000; + //th = (i - (tth * 10000)) / 1000; + h = (i - ((tth * 10000) + (th * 1000))) / 100; + t = (i - ((tth * 10000) + (th * 1000) + (h * 100))) / 10; + d = (i - ((tth * 10000) + (th * 1000) + (h * 100) + (t * 10))); + //putchar(tth + '0'); + //putchar(th + '0'); + putchar(h + '0'); + putchar(t + '0'); + putchar(d + '0'); +} + +main(int argc, char **argv) +{ + int val; + int size = 0; + unsigned char c; + + printf("gcc2_compiled.:\n"); + printf("__gnu_compiled_c:\n"); + printf("\t.globl linux_compressed_start\n"); + printf("\t.text\n"); + printf("\t.align 2\n"); + printf("\t.type linux_compressed_start,@object\n"); + printf("linux_compressed_start:\n"); + + + val = getchar(); + while (val != EOF) { + size++; + c = (unsigned char) (val & 0x00ff); + printf("\t.byte "); + printval((int) c); + printf("\n"); + val = getchar(); + } + printf("\t.size linux_compressed_start,%d\n", size); + printf("\t.globl linux_compressed_size\n"); + printf("\t.text\n"); + printf("\t.align 2\n"); + printf("\t.type linux_compressed_size,@object\n"); + printf("\t.size linux_compressed_size,4\n"); + printf("linux_compressed_size:\n"); + printf("\t.word %d\n", size); +} diff --git a/arch/mips/galileo-boards/ev64120/compressed/etherboot.h b/arch/mips/galileo-boards/ev64120/compressed/etherboot.h new file mode 100644 index 000000000..fd6eff847 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/etherboot.h @@ -0,0 +1,566 @@ +/************************************************************************** +ETHERBOOT - BOOTP/TFTP Bootstrap Program + +Author: Martin Renters + Date: Dec/93 + +**************************************************************************/ + +#include "osdep.h" + +/* These could be customised for different languages perhaps */ +#define ASK_PROMPT "Boot from (N)etwork or from (L)ocal? " +#define ANS_NETWORK 'N' +#define ANS_LOCAL 'L' +#ifndef ANS_DEFAULT /* in case left out in Makefile */ +#define ANS_DEFAULT ANS_NETWORK +#endif + +#define TAGGED_IMAGE /* eventually optional */ +#if !defined(TAGGED_IMAGE) && !defined(AOUT_IMAGE) && !defined(ELF_IMAGE) +#define TAGGED_IMAGE /* choose at least one */ +#endif + +#define ESC 0x1B + +#ifndef DEFAULT_BOOTFILE +#define DEFAULT_BOOTFILE "/tftpboot/kernel" +#endif + +/* Clean up console settings... mainly CONSOLE_CRT and CONSOLE_SERIAL are used + * in the sources (except start.S and serial.S which cannot include + * etherboot.h). At least one of the CONSOLE_xxx has to be set, and + * CONSOLE_DUAL sets both CONSOLE_CRT and CONSOLE_SERIAL. If none is set, + * CONSOLE_CRT is assumed. */ +#ifdef CONSOLE_DUAL +#undef CONSOLE_CRT +#define CONSOLE_CRT +#undef CONSOLE_SERIAL +#define CONSOLE_SERIAL +#endif +#if defined(CONSOLE_CRT) && defined(CONSOLE_SERIAL) +#undef CONSOLE_DUAL +#define CONSOLE_DUAL +#endif +#if !defined(CONSOLE_CRT) && !defined(CONSOLE_SERIAL) +#define CONSOLE_CRT +#endif + +#ifndef DOWNLOAD_PROTO_NFS +#undef DOWNLOAD_PROTO_TFTP +#define DOWNLOAD_PROTO_TFTP /* default booting protocol */ +#endif + +#ifdef DOWNLOAD_PROTO_TFTP +#define download(fname,loader) tftp((fname),(loader)) +#endif +#ifdef DOWNLOAD_PROTO_NFS +#define download(fname,loader) nfs((fname),(loader)) +#endif + +#ifndef MAX_TFTP_RETRIES +#define MAX_TFTP_RETRIES 20 +#endif + +#ifndef MAX_BOOTP_RETRIES +#define MAX_BOOTP_RETRIES 20 +#endif + +#ifndef MAX_BOOTP_EXTLEN +#if (RELOC < 0x94000) +/* Force internal buffer (if external buffer would overlap with our code...) */ +#undef INTERNAL_BOOTP_DATA +#define INTERNAL_BOOTP_DATA +#endif +/* sizeof(struct bootp_t) == 0x240 */ +#if defined(INTERNAL_BOOTP_DATA) || (RELOC >= 0x94240) +#define MAX_BOOTP_EXTLEN 1024 +#else +#define MAX_BOOTP_EXTLEN (1024-sizeof(struct bootp_t)) +#endif +#endif + +#ifndef MAX_ARP_RETRIES +#define MAX_ARP_RETRIES 20 +#endif + +#ifndef MAX_RPC_RETRIES +#define MAX_RPC_RETRIES 20 +#endif + +#define TICKS_PER_SEC 18 + +/* Inter-packet retry in ticks */ +#define TIMEOUT (10*TICKS_PER_SEC) + +/* These settings have sense only if compiled with -DCONGESTED */ +/* total retransmission timeout in ticks */ +#define TFTP_TIMEOUT (30*TICKS_PER_SEC) +/* packet retransmission timeout in ticks */ +#define TFTP_REXMT (3*TICKS_PER_SEC) + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#define TRUE 1 +#define FALSE 0 + +#define ETHER_ADDR_SIZE 6 /* Size of Ethernet address */ +#define ETHER_HDR_SIZE 14 /* Size of ethernet header */ +#define ETH_MIN_PACKET 64 +#define ETH_MAX_PACKET 1518 + +#define VENDOR_NONE 0 +#define VENDOR_WD 1 +#define VENDOR_NOVELL 2 +#define VENDOR_3COM 3 +#define VENDOR_3C509 4 +#define VENDOR_CS89x0 5 + +#define FLAG_PIO 0x01 +#define FLAG_16BIT 0x02 +#define FLAG_790 0x04 + +#define ARP_CLIENT 0 +#define ARP_SERVER 1 +#define ARP_GATEWAY 2 +#define ARP_ROOTSERVER 3 +#define ARP_SWAPSERVER 4 +#define MAX_ARP ARP_SWAPSERVER+1 + +#define RARP_REQUEST 3 +#define RARP_REPLY 4 + +#define IP 0x0800 +#define ARP 0x0806 +#define RARP 0x8035 + +#define BOOTP_SERVER 67 +#define BOOTP_CLIENT 68 +#define TFTP_PORT 69 +#define SUNRPC_PORT 111 + +#define IP_UDP 17 +/* Same after going through htonl */ +#define IP_BROADCAST 0xFFFFFFFF + +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +#define BOOTP_REQUEST 1 +#define BOOTP_REPLY 2 + +#define TAG_LEN(p) (*((p)+1)) +#define RFC1533_COOKIE 99, 130, 83, 99 +#define RFC1533_PAD 0 +#define RFC1533_NETMASK 1 +#define RFC1533_TIMEOFFSET 2 +#define RFC1533_GATEWAY 3 +#define RFC1533_TIMESERVER 4 +#define RFC1533_IEN116NS 5 +#define RFC1533_DNS 6 +#define RFC1533_LOGSERVER 7 +#define RFC1533_COOKIESERVER 8 +#define RFC1533_LPRSERVER 9 +#define RFC1533_IMPRESSSERVER 10 +#define RFC1533_RESOURCESERVER 11 +#define RFC1533_HOSTNAME 12 +#define RFC1533_BOOTFILESIZE 13 +#define RFC1533_MERITDUMPFILE 14 +#define RFC1533_DOMAINNAME 15 +#define RFC1533_SWAPSERVER 16 +#define RFC1533_ROOTPATH 17 +#define RFC1533_EXTENSIONPATH 18 +#define RFC1533_IPFORWARDING 19 +#define RFC1533_IPSOURCEROUTING 20 +#define RFC1533_IPPOLICYFILTER 21 +#define RFC1533_IPMAXREASSEMBLY 22 +#define RFC1533_IPTTL 23 +#define RFC1533_IPMTU 24 +#define RFC1533_IPMTUPLATEAU 25 +#define RFC1533_INTMTU 26 +#define RFC1533_INTLOCALSUBNETS 27 +#define RFC1533_INTBROADCAST 28 +#define RFC1533_INTICMPDISCOVER 29 +#define RFC1533_INTICMPRESPOND 30 +#define RFC1533_INTROUTEDISCOVER 31 +#define RFC1533_INTROUTESOLICIT 32 +#define RFC1533_INTSTATICROUTES 33 +#define RFC1533_LLTRAILERENCAP 34 +#define RFC1533_LLARPCACHETMO 35 +#define RFC1533_LLETHERNETENCAP 36 +#define RFC1533_TCPTTL 37 +#define RFC1533_TCPKEEPALIVETMO 38 +#define RFC1533_TCPKEEPALIVEGB 39 +#define RFC1533_NISDOMAIN 40 +#define RFC1533_NISSERVER 41 +#define RFC1533_NTPSERVER 42 +#define RFC1533_VENDOR 43 +#define RFC1533_NBNS 44 +#define RFC1533_NBDD 45 +#define RFC1533_NBNT 46 +#define RFC1533_NBSCOPE 47 +#define RFC1533_XFS 48 +#define RFC1533_XDM 49 +#ifndef NO_DHCP_SUPPORT +#define RFC2132_REQ_ADDR 50 +#define RFC2132_MSG_TYPE 53 +#define RFC2132_SRV_ID 54 +#define RFC2132_PARAM_LIST 55 +#define RFC2132_MAX_SIZE 57 + +#define DHCPDISCOVER 1 +#define DHCPOFFER 2 +#define DHCPREQUEST 3 +#define DHCPACK 5 +#endif /* NO_DHCP_SUPPORT */ + +#define RFC1533_VENDOR_MAJOR 0 +#define RFC1533_VENDOR_MINOR 0 + +#define RFC1533_VENDOR_MAGIC 128 +#define RFC1533_VENDOR_ADDPARM 129 +#ifdef IMAGE_FREEBSD +#define RFC1533_VENDOR_HOWTO 132 +#endif +#define RFC1533_VENDOR_MNUOPTS 160 +#define RFC1533_VENDOR_SELECTION 176 +#define RFC1533_VENDOR_MOTD 184 +#define RFC1533_VENDOR_NUMOFMOTD 8 +#define RFC1533_VENDOR_IMG 192 +#define RFC1533_VENDOR_NUMOFIMG 16 + +#define RFC1533_END 255 +#define BOOTP_VENDOR_LEN 64 +#ifndef NO_DHCP_SUPPORT +#define DHCP_OPT_LEN 312 +#endif /* NO_DHCP_SUPPORT */ + +#define TFTP_DEFAULTSIZE_PACKET 512 +#define TFTP_MAX_PACKET 1432 /* 512 */ + +#define TFTP_RRQ 1 +#define TFTP_WRQ 2 +#define TFTP_DATA 3 +#define TFTP_ACK 4 +#define TFTP_ERROR 5 +#define TFTP_OACK 6 + +#define TFTP_CODE_EOF 1 +#define TFTP_CODE_MORE 2 +#define TFTP_CODE_ERROR 3 +#define TFTP_CODE_BOOT 4 +#define TFTP_CODE_CFG 5 + +#define AWAIT_ARP 0 +#define AWAIT_BOOTP 1 +#define AWAIT_TFTP 2 +#define AWAIT_RARP 3 +#define AWAIT_RPC 4 +#define AWAIT_QDRAIN 5 /* drain queue, process ARP requests */ + +typedef struct { + unsigned long s_addr; +} in_addr; + +struct arptable_t { + in_addr ipaddr; + unsigned char node[6]; +}; + +/* + * A pity sipaddr and tipaddr are not longword aligned or we could use + * in_addr. No, I don't want to use #pragma packed. + */ +struct arprequest { + unsigned short hwtype; + unsigned short protocol; + char hwlen; + char protolen; + unsigned short opcode; + char shwaddr[6]; + char sipaddr[4]; + char thwaddr[6]; + char tipaddr[4]; +}; + +struct iphdr { + char verhdrlen; + char service; + unsigned short len; + unsigned short ident; + unsigned short frags; + char ttl; + char protocol; + unsigned short chksum; + in_addr src; + in_addr dest; +}; + +struct udphdr { + unsigned short src; + unsigned short dest; + unsigned short len; + unsigned short chksum; +}; + +struct bootp_t { + struct iphdr ip; + struct udphdr udp; + char bp_op; + char bp_htype; + char bp_hlen; + char bp_hops; + unsigned long bp_xid; + unsigned short bp_secs; + unsigned short unused; + in_addr bp_ciaddr; + in_addr bp_yiaddr; + in_addr bp_siaddr; + in_addr bp_giaddr; + char bp_hwaddr[16]; + char bp_sname[64]; + char bp_file[128]; +#ifdef NO_DHCP_SUPPORT + char bp_vend[BOOTP_VENDOR_LEN]; +#else + char bp_vend[DHCP_OPT_LEN]; +#endif /* NO_DHCP_SUPPORT */ +}; + +struct bootpd_t { + struct bootp_t bootp_reply; + unsigned char bootp_extension[MAX_BOOTP_EXTLEN]; +}; + +struct tftp_t { + struct iphdr ip; + struct udphdr udp; + unsigned short opcode; + union { + char rrq[TFTP_DEFAULTSIZE_PACKET]; + struct { + unsigned short block; + char download[TFTP_MAX_PACKET]; + } data; + struct { + unsigned short block; + } ack; + struct { + unsigned short errcode; + char errmsg[TFTP_DEFAULTSIZE_PACKET]; + } err; + struct { + char data[TFTP_DEFAULTSIZE_PACKET + 2]; + } oack; + } u; +}; + +#define TFTP_MIN_PACKET (sizeof(struct iphdr) + sizeof(struct udphdr) + 4) + +struct rpc_t { + struct iphdr ip; + struct udphdr udp; + union { + char data[300]; /* longest RPC call must fit!!!! */ + struct { + long id; + long type; + long rpcvers; + long prog; + long vers; + long proc; + long data[1]; + } call; + struct { + long id; + long type; + long rstatus; + long verifier; + long v2; + long astatus; + long data[1]; + } reply; + } u; +}; + +#define PROG_PORTMAP 100000 +#define PROG_NFS 100003 +#define PROG_MOUNT 100005 + +#define MSG_CALL 0 +#define MSG_REPLY 1 + +#define PORTMAP_GETPORT 3 + +#define MOUNT_ADDENTRY 1 +#define MOUNT_UMOUNTALL 4 + +#define NFS_LOOKUP 4 +#define NFS_READ 6 + +#define NFS_FHSIZE 32 + +#define NFSERR_PERM 1 +#define NFSERR_NOENT 2 +#define NFSERR_ACCES 13 + +/* Block size used for NFS read accesses. A RPC reply packet (including all + * headers) must fit within a single Ethernet frame to avoid fragmentation. + * Chosen to be a power of two, as most NFS servers are optimized for this. */ +#define NFS_READ_SIZE 1024 + +#define FLOPPY_BOOT_LOCATION 0x7c00 + +#define ROM_INFO_LOCATION 0x7dfa +/* at end of floppy boot block */ + +struct rom_info { + unsigned short rom_segment; + unsigned short rom_length; +}; + +/*************************************************************************** +External prototypes +***************************************************************************/ +/* main.c */ +extern void print_bytes P((unsigned char *bytes, int len)); +extern void load P((void)); +extern int load_linux P((int root_mount_port, int swap_mount_port, + int root_nfs_port, char *kernel_handle)); +extern int downloadkernel P((unsigned char *, int, int, int)); +extern int tftp +P((const char *name, int (*)(unsigned char *, int, int, int))); +extern void rpc_init(void); +extern int nfs +P((const char *name, int (*)(unsigned char *, int, int, int))); +extern void nfs_umountall P((int)); +extern int bootp P((void)); +extern int rarp P((void)); +extern int udp_transmit P((unsigned long destip, unsigned int srcsock, + unsigned int destsock, int len, + const void *buf)); + +extern int await_reply P((int type, int ival, void *ptr, int timeout)); +extern int decode_rfc1533 P((unsigned char *, int, int, int)); +extern unsigned short ipchksum P((unsigned short *, int len)); +extern void rfc951_sleep P((int)); +extern void cleanup_net P((void)); +extern void cleanup P((void)); + +/* config.c */ +extern void print_config(void); +extern void eth_reset(void); +extern int eth_probe(void); +extern int eth_poll(void); +extern void eth_transmit(const char *d, unsigned int t, unsigned int s, + const void *p); +extern void eth_disable(void); + +/* bootmenu.c */ +extern int execute P((char *string)); +extern void bootmenu P((int)); +extern void show_motd P((void)); +extern void parse_menuopts P((char *, int)); +extern int getoptvalue P((char **, int *, int *)); +extern void selectImage P((char **)); + +/* osloader.c */ +#if defined(AOUT_IMAGE) || defined(ELF_IMAGE) +extern int howto; +#endif +extern int os_download P((unsigned int, unsigned char *, unsigned int)); + +/* misc.c */ +extern void twiddle P((void)); +extern void sleep P((int secs)); +extern int strcasecmp P((char *a, char *b)); +extern char *substr P((char *a, char *b)); +extern int getdec P((char **)); +extern void printf P((const char *, ...)); +extern char *sprintf P((char *, const char *, ...)); +extern int inet_aton P((char *p, in_addr * i)); +extern void gateA20_set P((void)); +extern void gateA20_unset P((void)); +extern void putchar P((int)); +extern int getchar P((void)); +extern int iskey P((void)); + +/* start*.S */ +extern int getc P((void)); +extern void putc P((int)); +extern int ischar P((void)); +extern int getshift P((void)); +extern unsigned int memsize P((void)); +extern unsigned short basememsize P((void)); +extern void disk_init P((void)); +extern unsigned int disk_read P((int drv, int c, int h, int s, char *buf)); +extern void xstart P((unsigned long, unsigned long, char *)); +extern unsigned long currticks P((void)); +extern int setjmp P((void *jmpbuf)); +extern void longjmp P((void *jmpbuf, int where)); +extern void exit P((int status)); +extern void slowdownio P((void)); + +/* serial.S */ +extern int serial_getc P((void)); +extern void serial_putc P((int)); +extern int serial_ischar P((void)); +extern int serial_init P((void)); + +/* ansiesc.c */ +extern void ansi_reset P((void)); +extern void enable_cursor P((int)); +extern void handleansi P((unsigned char)); + +/* md5.c */ +extern void md5_put P((unsigned int ch)); +extern void md5_done P((unsigned char *buf)); + +/* floppy.c */ +extern int bootdisk P((int dev, int part)); + +/*************************************************************************** +External variables +***************************************************************************/ +/* main.c */ +extern const char *kernel; +extern char kernel_buf[128]; +extern struct rom_info rom; +extern int hostnamelen; +extern unsigned long netmask; +extern int jmp_bootmenu[10]; +extern struct arptable_t arptable[MAX_ARP]; +#ifdef IMAGE_MENU +extern char *motd[RFC1533_VENDOR_NUMOFMOTD]; +extern int menutmo, menudefault; +extern unsigned char *defparams; +extern int defparams_max; +#endif +#if defined(ETHERBOOT32) && !defined(INTERNAL_BOOTP_DATA) +#define BOOTP_DATA_ADDR ((struct bootpd_t *)0x93C00) +#else +extern struct bootpd_t bootp_data; +#define BOOTP_DATA_ADDR (&bootp_data) +#endif +extern unsigned char *end_of_rfc1533; +#ifdef IMAGE_FREEBSD +extern int freebsd_howto; +#endif + +/* config.c */ +extern struct nic nic; + +/* bootmenu.c */ + +/* osloader.c */ + +/* created by linker */ +extern char _start[], _edata[], _end[]; + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/arch/mips/galileo-boards/ev64120/compressed/evb64120A_Setup.c b/arch/mips/galileo-boards/ev64120/compressed/evb64120A_Setup.c new file mode 100644 index 000000000..41b89f1e8 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/evb64120A_Setup.c @@ -0,0 +1,199 @@ +/* + * arch/mips/galileo/compressed/evb64120A_memSetup.c + * + * By RidgeRun Inc, (Leveraged from Galileo's sbd.c) + * + * Xfer an image from flash to ram. + * For use with Galileo EVB64120A MIPS eval board. + */ + +#include <linux/config.h> +#include "ns16550.h" +#include <linux/serial_reg.h> +#include <asm/galileo-boards/evb64120A/pci.h> +#include <asm/galileo-boards/evb64120A/core.h> + +void XferToRam(void); +bool mapMemoryBanks0and1(unsigned int bank0Base, unsigned int bank0Length, + unsigned int bank1Base, unsigned int bank1Length); +bool mapMemoryBanks2and3(unsigned int bank2Base, unsigned int bank2Length, + unsigned int bank3Base, unsigned int bank3Length); +bool mapDevices0_1and2MemorySpace(unsigned int device0Base, + unsigned int device0Length, + unsigned int device1Base, + unsigned int device1Length, + unsigned int device2Base, + unsigned int device2Length); + +#define RUNNINGFROMFLASH +#include "./xfer.c" + +/****************************** + Routine: + Description: + ******************************/ +unsigned int readWord(unsigned int addr) +{ + unsigned int tmp; + tmp = *(unsigned int *) (addr | NONE_CACHEABLE); + return WORDSWAP(tmp); +} + +/****************************** + Routine: + Description: + ******************************/ +void writeWord(unsigned int addr, unsigned int data) +{ + *((unsigned int *) (addr | NONE_CACHEABLE)) = WORDSWAP(data); +} + +/****************************** + Routine: + Description: + ******************************/ +unsigned int GetExtendedMemorySize(void) +{ + unsigned int address, data = 0x11223344, type; + unsigned int bank1_ef = false, bank2_ef = false, bank3_ef = false; + unsigned int bank0_size, bank2_size, bank3_size, total_size = 0; + + mapMemoryBanks0and1(0, 0x800000, 0x800000, 0x800000); + mapMemoryBanks2and3(0x1000000, 0x800000, 0x1800000, 0x800000); + type = readWord(0x14000810); + switch (type) { + case 16: + bank0_size = 0x1000000; + break; + case 64: + bank0_size = 0x4000000; + break; + case 128: + bank0_size = 0x8000000; + break; + case 256: + bank0_size = 0x10000000; + break; + default: + bank0_size = 0x1000000; + break; + } + + type = readWord(0x14000814); + switch (type) { + case 16: + bank2_size = 0x1000000; + bank3_size = 0x1000000; + break; + case 64: + bank2_size = 0x4000000; + bank3_size = 0x4000000; + break; + case 128: + bank2_size = 0x8000000; + bank3_size = 0x8000000; + break; + case 256: + bank2_size = 0x10000000; + bank3_size = 0x10000000; + break; + default: + bank2_size = 0x1000000; + bank3_size = 0x1000000; + break; + } + + /* Check which banks exist */ + /* Bank 1 */ + for (address = 0xffff00; address < 0x1000000; address += 4) + writeWord(address, data); + for (address = 0xffff00; address < 0x1000000; address += 4) { + if (readWord(address) != data) + break; + } + if (address == 0x1000000) + bank1_ef = true; + // Bank 2 + for (address = 0x17fff00; address < 0x1800000; address += 4) + writeWord(address, data); + for (address = 0x17fff00; address < 0x1800000; address += 4) { + if (readWord(address) != data) + break; + } + if (address == 0x1800000) + bank2_ef = true; + else + bank2_size = 0x0; + // Bank 3 + for (address = 0x1ffff00; address < 0x2000000; address += 4) + writeWord(address, data); + for (address = 0x1ffff00; address < 0x2000000; address += 4) { + if (readWord(address) != data) + break; + } + if (address == 0x2000000) + bank3_ef = true; + + // Reconfig the system with the new bank0 (and maybe bank1) size. + if (bank0_size == 0x10000000) + bank1_ef = false; + if (bank1_ef == true) { + mapMemoryBanks0and1(0, bank0_size, bank0_size, bank0_size); + // Fix the PCI bars + pci0MapMemoryBanks0_1(0, bank0_size * 2); + pci1MapMemoryBanks0_1(0, bank0_size * 2); + total_size += bank0_size * 2; + } else { + mapMemoryBanks0and1(0, bank0_size, bank0_size, 0); + // Fix the PCI bars + pci0MapMemoryBanks0_1(0, bank0_size); + pci1MapMemoryBanks0_1(0, bank0_size); + total_size += bank0_size; + } + if (total_size == 0x10000000) { + bank2_ef = false; + bank3_ef = false; + } else { + if ((total_size + bank2_size) > 0x10000000) { + bank2_size = 0x10000000 - total_size; + bank3_ef = false; + } else { + if (bank3_size + total_size + bank2_size > + 0x10000000) { + bank3_size = + 0x10000000 - (total_size + bank2_size); + } + } + } + if (bank2_ef == true) { + if (bank3_ef == true) { + mapMemoryBanks2and3(total_size, bank2_size, + total_size + bank2_size, + bank3_size); + // Fix the PCI bars + pci0MapMemoryBanks2_3(total_size, + bank2_size + bank3_size); + pci1MapMemoryBanks2_3(total_size, + bank2_size + bank3_size); + total_size += (bank2_size + bank3_size); + } else { + mapMemoryBanks2and3(total_size, bank2_size, + total_size + bank2_size, 0); + // Fix the PCI bars + pci0MapMemoryBanks2_3(total_size, bank2_size); + pci1MapMemoryBanks2_3(total_size, bank2_size); + total_size += bank2_size; + } + } else { + mapMemoryBanks2and3(total_size, 0, total_size, 0); + pci0MapMemoryBanks2_3(total_size, 0); + pci1MapMemoryBanks2_3(total_size, 0); + } + /* Reorganize the devices memory map */ + mapDevices0_1and2MemorySpace(0x1c000000, 0x800000, 0x1a000000, + 0xc00000, 0x1d000000, 0x800000); + + XferToRam(); + return 0; // Not that we'll ever get to this line of code, but + // it does satisfy a compiler warning. +} diff --git a/arch/mips/galileo-boards/ev64120/compressed/fixit b/arch/mips/galileo-boards/ev64120/compressed/fixit new file mode 100644 index 000000000..5f4dcdc59 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/fixit @@ -0,0 +1,17 @@ +#!/bin/ksh + +# By RidgeRun Inc. +# +# The input to this script is +# intended to be a *.S file which +# was previously created by the doit +# program. That program constructs +# a *.S file which has a defined data +# table containing values with leading +# zeroes. To satisfy our assembler those +# leading zeroes need to be stripped off +# and that is the purpose of this script. + +echo "Removing leading zeros" +sed -e "s/ 0\(.\)/ \1/g" $1 | sed -e "s/ 0\(.\)/ \1/g" > $1.new +mv $1.new $1 diff --git a/arch/mips/galileo-boards/ev64120/compressed/flashdrv.c b/arch/mips/galileo-boards/ev64120/compressed/flashdrv.c new file mode 100644 index 000000000..8296fe83b --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/flashdrv.c @@ -0,0 +1,1560 @@ +/* flashdrv.c - FLASH memory functions and definitions*/ + +/* Copyright Galileo Technology. */ + +/* +DESCRIPTION +This flash driver gives the user a convenient interface to FLASH memory located +on the user`s board, it supports various layout configurations such as: +1. One pure 8 bit device (Such as AMD`s AM29LV040B). +2. 1,2,4 or 8 devices 16 bit wide configured to operate in 8 bit mode. +3. 1,2 or 4 devices each 16 bit wide. +Before using the driver you must call the initialization function at least once +or when ever you are changing the FLASH base address. +The list bellow contains the supported FLASH memory devices, new devices can be +added easily in the future. +*/ + +/*includes*/ +#ifdef __linux__ +#include <asm/galileo-boards/evb64120A/flashdrv.h> +#else +#include "flashdrv.h" +#endif +/* locals */ + +#ifdef __MIPSEB__ // skranz, add +#define BE // skranz, add +#endif // skranz, add + +/****************************************************************************** +* Those two tables contain the supported flash devices information needed by +* the driver: +* The first table "flashParametrs" starts with 10 shared fields +* (currently 6 are reserved): +* index 0 => Pointer to an entry in the second table list +* index 1 => baseAddress - Flash memory device base address. +* index 2 => width - 1, 2, 4 or 8 Bytes. +* index 3 => mode - PURE8, X8 or X16 flash configuration (for X16 devices only) +* The second table (flashTypes) contains: +* Entry`s structure: +* Manufacture ID,Device ID,number of sectors,list of sector`s sizes +* (in Kbytes starting with sector number 0). +* The end of the list is pointed with a zero. +******************************************************************************/ +unsigned int flashParametrs[10]; /* 0 Entry pointer */ + /* 0 Base address */ + /* 0 Width */ + /* 0 Mode */ + /* 0,0,0,0,0,0, spare entries. */ +unsigned int flashTypes[] = { + + /* 0 */ AMD_FLASH, AM29F400BB, 11, 16, 8, 8, 32, 64, 64, 64, 64, + 64, 64, 64, + /* 1 */ AMD_FLASH, AM29F400BT, 11, 64, 64, 64, 64, 64, 64, 64, 32, + 8, 8, 16, + /* 2 */ ST_FLASH, M29W040, 8, 64, 64, 64, 64, 64, 64, 64, 64, + /* 3 */ AMD_FLASH, AM29LV040B, 8, 64, 64, 64, 64, 64, 64, 64, 64, + /* 4 */ AMD_FLASH, AM29LV800BT, 19, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, + 64, 64, 64, 64, 64, 32, 8, 8, 16, + /* 5 */ INTEL_FLASH, I28F320J3A, 32, 128, 128, 128, 128, 128, 128, + 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, + /* 6 */ INTEL_FLASH, I28F640J3A, 64, 128, 128, 128, 128, 128, 128, + 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, + /* 7 */ INTEL_FLASH, I28F128J3A, 128, 128, 128, 128, 128, 128, 128, + 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + /* 8 */ AMD_FLASH, AM29LV400BB, 11, 16, 8, 8, 32, 64, 64, 64, 64, + 64, 64, 64, + /* 9 */ AMD_FLASH, AM29LV400BT, 11, 64, 64, 64, 64, 64, 64, 64, 32, + 8, 8, 16, + /* 10 */ INTEL_FLASH, I28F320B3_T, 71, 64, 64, 64, 64, 64, 64, 64, + 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 8, 8, 8, 8, 8, 8, 8, 8, + /* 11 */ INTEL_FLASH, I28F320B3_B, 71, 8, 8, 8, 8, 8, 8, 8, 8, 64, + 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + /* 12 */ INTEL_FLASH, I28F160B3_B, 39, 8, 8, 8, 8, 8, 8, 8, 8, 64, + 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + /* 13 */ INTEL_FLASH, I28F160B3_T, 39, 64, 64, 64, 64, 64, 64, 64, + 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 8, 8, 8, 8, 8, 8, 8, 8, + + 0 /* End of list indicator */ +}; + +/******************************************************************** +* flashInit - Initializes the FLASH memory driver`s parameters, this function +* must be called at least once before using the FLASH memory. +* If you are changing the FLASH base address call this function +* again. +* +* INPUTS: unsigned int flashBaseAddress - The flash base Address. +* unsigned int flashWidth - Flash bus width in Bytes: 1,2,4 or 8. +* flashMode - PURE8, X8 or X16. +* RETURNS: Flash Size, zero when operation (flashInit) failed. +*********************************************************************/ +unsigned int flashInit(unsigned int flashBaseAddress, + unsigned int flashWidth, FLASHmode flashMode) +{ + unsigned short mfrId = 0; + unsigned short devId = 0xffff; + unsigned int FirstAddr, SecondAddr, ThirdAddr; + unsigned int pArray = 0; + unsigned int counter; + unsigned int flashSize = 0; + + /* update the list with relevant parametrs */ + flashParametrs[0] = 0; /* Default initialization */ + flashParametrs[1] = flashBaseAddress; + flashParametrs[2] = flashWidth; + flashParametrs[3] = flashMode; + /* Get the FLASH`s ID */ + switch (FLASH_WIDTH) { + case 1: + /* AMD or ST ?? * */ + if (flashMode == PURE8) { /* Boot Flash */ + FirstAddr = 0x5555; + SecondAddr = 0x2aaa; + ThirdAddr = 0x5555; + } else { /* X16 device configured to 8bit Mode */ + + FirstAddr = 0xaaaa; + SecondAddr = 0x5555; + ThirdAddr = 0xaaaa; + } + flashReset(); + WRITE_CHAR(FLASH_BASE_ADDRESS + FirstAddr, 0xAA); + WRITE_CHAR(FLASH_BASE_ADDRESS + SecondAddr, 0x55); + WRITE_CHAR(FLASH_BASE_ADDRESS + ThirdAddr, 0x90); + READ_CHAR(FLASH_BASE_ADDRESS + 0x0, &mfrId); + if (mfrId == AMD_FLASH || mfrId == ST_FLASH) { + flashReset(); + WRITE_CHAR(FLASH_BASE_ADDRESS + FirstAddr, 0xAA); + WRITE_CHAR(FLASH_BASE_ADDRESS + SecondAddr, 0x55); + WRITE_CHAR(FLASH_BASE_ADDRESS + ThirdAddr, 0x90); + READ_CHAR(FLASH_BASE_ADDRESS + 0x1, &devId); + break; + } + /* Micron or Intel ?? * */ + WRITE_CHAR(FLASH_BASE_ADDRESS, 0xff); /* Read Array */ + /* Flash reset for Intel/Micron */ + WRITE_CHAR(FLASH_BASE_ADDRESS, 0x90); /* IDENTIFY Device */ + READ_CHAR(FLASH_BASE_ADDRESS + 0x0, &mfrId); /*Address for ManufactureID */ + if (mfrId == INTEL_FLASH || mfrId == MICRON_FLASH) { + WRITE_CHAR(FLASH_BASE_ADDRESS, 0xff); /* Read Array */ + /*Flash reset for Intel/Micron */ + WRITE_CHAR(FLASH_BASE_ADDRESS, 0x90); /* IDENTIFY Device */ + READ_CHAR(FLASH_BASE_ADDRESS + 0x1, &devId); /*Address for DeviceID */ + } + break; + case 2: + case 4: + case 8: + /* AMD or ST ??? */ + flashReset(); + WRITE_SHORT(FLASH_BASE_ADDRESS + 0x5555 * FLASH_WIDTH, + 0xaa); + WRITE_SHORT(FLASH_BASE_ADDRESS + 0x2aaa * FLASH_WIDTH, + 0x55); + WRITE_SHORT(FLASH_BASE_ADDRESS + 0x5555 * FLASH_WIDTH, + 0x90); + READ_SHORT(FLASH_BASE_ADDRESS, &mfrId); + flashReset(); + /* Read the device ID */ + if (mfrId == AMD_FLASH || mfrId == ST_FLASH) { + WRITE_SHORT(FLASH_BASE_ADDRESS + + 0x5555 * FLASH_WIDTH, 0xaa); + WRITE_SHORT(FLASH_BASE_ADDRESS + + 0x2aaa * FLASH_WIDTH, 0x55); + WRITE_SHORT(FLASH_BASE_ADDRESS + + 0x5555 * FLASH_WIDTH, 0x90); + READ_SHORT(FLASH_BASE_ADDRESS + 0x1 * FLASH_WIDTH, + &devId); + break; + } + /* Micron or Intel ?? * */ + WRITE_WORD(FLASH_BASE_ADDRESS, 0x00ff00ff); + WRITE_WORD(FLASH_BASE_ADDRESS, 0x00900090); + if ((FLASH_WIDTH == 4) || (FLASH_WIDTH == 8)) { /* 32 or 64 bit */ + READ_SHORT(FLASH_BASE_ADDRESS, &mfrId); + } else { /* FLASH_WIDTH = 2 */ + + READ_SHORT(FLASH_BASE_ADDRESS, &mfrId); + } + if ((mfrId == INTEL_FLASH) || (mfrId == MICRON_FLASH)) { + /* Flash reset for Intel/Micron */ + flashReset(); + WRITE_WORD(FLASH_BASE_ADDRESS, 0x00ff00ff); + WRITE_WORD(FLASH_BASE_ADDRESS, 0x00900090); + READ_SHORT(FLASH_BASE_ADDRESS + 0x1 * FLASH_WIDTH, + &devId); + } + break; + + } + /* Try to locate the device in the supported flashes list (FLASH_TYPE). + according to the keys: + 1) mfrId - manufactor ID. + 2) devId - device ID. + */ + + while (true) { + if (flashTypes[pArray] == 0) { + flashReset(); + return 0; /* Device not in the list */ + } + if ((flashTypes[pArray] == mfrId) && + (flashTypes[pArray + 1] == devId)) { + POINTER_TO_FLASH = pArray; + for (counter = 0; + counter < flashTypes[NUMBER_OF_SECTORS]; + counter++) { + flashSize = + flashSize + + flashTypes[FIRST_SECTOR_SIZE + + counter]; + } + if (FLASH_MODE != PURE8) { + flashReset(); + return (flashSize * _1K * + (FLASH_WIDTH / (FLASH_MODE / 8))); + } else { + flashReset(); + return (flashSize * _1K * FLASH_WIDTH); + } + } + pArray += (3 + flashTypes[pArray + 2]); /* Move to next entry */ + } +} + +/******************************************************************** +* flashReset - Resets the Flash memory (FLASH`s internal protocol reset). +* +* INTPUTS: N/A +* OUTPUT: N/A +*********************************************************************/ +void flashReset() +{ + unsigned char ucData; + unsigned short usData; + unsigned int uiData; + + if ((flashTypes[POINTER_TO_FLASH] == AMD_FLASH) || + (flashTypes[POINTER_TO_FLASH]) == ST_FLASH) { + if (FLASH_MODE == X16) { + ucData = 0xf0; + usData = 0xf0; + uiData = 0x00f000f0; + } else { /* case of PURE8 or X8 */ + + ucData = 0xf0; + usData = 0xf0f0; + uiData = 0xf0f0f0f0; + } + } else { + if (FLASH_MODE == X16) { + ucData = 0xff; + usData = 0xff; + uiData = 0x00ff00ff; + } else { /* case of PURE8 or X8 */ + + ucData = 0xff; + usData = 0xffff; + uiData = 0xffffffff; + } + } + switch (FLASH_WIDTH) { + case 1: + WRITE_CHAR(FLASH_BASE_ADDRESS, ucData); + break; + case 2: + WRITE_SHORT(FLASH_BASE_ADDRESS, usData); + break; + case 4: + WRITE_WORD(FLASH_BASE_ADDRESS, uiData); + break; + case 8: + WRITE_WORD(FLASH_BASE_ADDRESS, uiData); + WRITE_WORD(FLASH_BASE_ADDRESS + 0x4, uiData); + break; + } +} + +/******************************************************************** +* flashErase - The function erases the WHOLE flash memory. +* +* +* RETURNS: true on success,false on failure +*********************************************************************/ +bool flashErase() +{ + unsigned int totalFlashSize; + unsigned int address; + unsigned int readData; + unsigned int nextSector; + + flashReset(); + totalFlashSize = flashGetSize(); + /* scan all flash memory space. */ + address = 0; + while (address < totalFlashSize) { + readData = flashReadWord(address); + if (readData != 0xffffffff) { /* offset with dirty data. */ + flashEraseSector(flashInWhichSector(address)); + nextSector = flashInWhichSector(address) + 1; + if (nextSector < flashTypes[NUMBER_OF_SECTORS]) + /* jump to next sector. */ + address = flashGetSectorOffset(nextSector); + else + /* end of erasing. */ + address = totalFlashSize; + } else + address += 4; + } + return true; +} + +/******************************************************************** +* flashEraseSector - The function erases a specific sector in the flash memory. +* +* INPUTS: Sector number. +* RETURNS: true on success,false on failure. +*********************************************************************/ +bool flashEraseSector(unsigned int sectorNumber) +{ + volatile unsigned int spin; + unsigned int regValue; + unsigned int sectorBaseAddress = 0; + unsigned int i; + unsigned int data20, dataD0, data70; + unsigned int dataPoll; + unsigned int FirstAddr, SecondAddr, ThirdAddr, FourthAddr, + FifthAddr; + unsigned int FirstData, SecondData, ThirdData; + unsigned int FourthData, FifthData, SixthData; + + /* calculate the sector base Address according to the following parametrs: + 1: FLASH_WIDTH + 2: the size of each sector which it detailed in the table */ + + /* checking the if the sectorNumber is legal. */ + if (sectorNumber > flashTypes[NUMBER_OF_SECTORS] - 1) + return false; + /* now the calculation begining of the sector Address */ + for (i = 0; i < sectorNumber; i++) { + sectorBaseAddress = + sectorBaseAddress + flashTypes[FIRST_SECTOR_SIZE + i]; + } + /* In case of X8 wide the address should be */ + if (FLASH_MODE == PURE8) + sectorBaseAddress = _1K * sectorBaseAddress; + if (FLASH_MODE == X8) + sectorBaseAddress = _1K * sectorBaseAddress; + /* In case of X16 wide the address should be */ + if (FLASH_MODE == X16) + sectorBaseAddress = _1K * sectorBaseAddress / 2; + flashReset(); + if ((flashTypes[POINTER_TO_FLASH] == AMD_FLASH) || \ + (flashTypes[POINTER_TO_FLASH] == ST_FLASH)) { + switch (FLASH_WIDTH) { + case 1: + if (FLASH_MODE == PURE8) { /* Boot Flash PURE8 */ + FirstAddr = 0x5555; + SecondAddr = 0x2aaa; + ThirdAddr = 0x5555; + FourthAddr = 0x5555; + FifthAddr = 0x2aaa; + } else { + FirstAddr = 0xaaaa; + SecondAddr = 0x5555; + ThirdAddr = 0xaaaa; + FourthAddr = 0xaaaa; + FifthAddr = 0x5555; + } + WRITE_CHAR(FLASH_BASE_ADDRESS + FirstAddr, 0xAA); + WRITE_CHAR(FLASH_BASE_ADDRESS + SecondAddr, 0x55); + WRITE_CHAR(FLASH_BASE_ADDRESS + ThirdAddr, 0x80); + WRITE_CHAR(FLASH_BASE_ADDRESS + FourthAddr, 0xAA); + WRITE_CHAR(FLASH_BASE_ADDRESS + FifthAddr, 0x55); + WRITE_CHAR( + (FLASH_BASE_ADDRESS + + (sectorBaseAddress & 0xffffff00)), + 0x30); + /* Poll on the flash */ + do { + READ_CHAR(FLASH_BASE_ADDRESS + + sectorBaseAddress, ®Value); + } while ((regValue & 0x80) != 0x80); + + break; + case 2: + if (FLASH_MODE == X16) { + FirstData = 0xaa; /* Data for the First Cycle */ + SecondData = 0x55; /* Data for the Second Cycle */ + ThirdData = 0x80; /* Data for the Third Cycle */ + FourthData = 0xaa; /* Data for the Fourth Cycle */ + FifthData = 0x55; /* Data for the Fifth Cycle */ + SixthData = 0x30; /* Data for the Sixth Cycle */ + FirstAddr = 0x5555; /* Address for the First Cycle */ + SecondAddr = 0x2aaa; /* Address for the Second Cycle */ + ThirdAddr = 0x5555; /* Address for the Third Cycle */ + FourthAddr = 0x5555; /* Address for the Fourth Cycle */ + FifthAddr = 0x2aaa; /* Address for the Fifth Cycle */ + } else { /* (FLASH_MODE = 8) */ + + FirstData = 0xaaaa; /* Data for the First Cycle */ + SecondData = 0x5555; /* Data for the Second Cycle */ + ThirdData = 0x8080; /* Data for the Third Cycle */ + FourthData = 0xaaaa; /* Data for the Fourth Cycle */ + FifthData = 0x5555; /* Data for the Fifth Cycle */ + SixthData = 0x3030; /* Data for the Sixth Cycle */ + FirstAddr = 0xaaaa; /* Address for the First Cycle */ + SecondAddr = 0x5555; /* Address for the Second Cycle */ + ThirdAddr = 0xaaaa; /* Address for the Third Cycle */ + FourthAddr = 0xaaaa; /* Address for the Fourth Cycle */ + FifthAddr = 0x5555; /* Address for the Fifth Cycle */ + } + WRITE_SHORT(FLASH_BASE_ADDRESS + + FirstAddr * FLASH_WIDTH, FirstData); + WRITE_SHORT(FLASH_BASE_ADDRESS + + SecondAddr * FLASH_WIDTH, SecondData); + WRITE_SHORT(FLASH_BASE_ADDRESS + + ThirdAddr * FLASH_WIDTH, ThirdData); + WRITE_SHORT(FLASH_BASE_ADDRESS + + FourthAddr * FLASH_WIDTH, FourthData); + WRITE_SHORT(FLASH_BASE_ADDRESS + + FifthAddr * FLASH_WIDTH, FifthData); + WRITE_SHORT(FLASH_BASE_ADDRESS + + (sectorBaseAddress & 0xffffff00) * + FLASH_WIDTH, SixthData); + /* Poll on the flash */ + if (FLASH_MODE == X16) { /* 1 device of 16 bit */ + dataPoll = 0x0080; + } else { /* (FLASH_MODE = 8) ==> 2 devices , 8 bit each => 16bit */ + + dataPoll = 0x8080; + } + do { + READ_SHORT(FLASH_BASE_ADDRESS + + sectorBaseAddress * FLASH_WIDTH, + ®Value); + for (spin = 0; spin < 100; spin++) { + } // skranz, added spin loop. + } while ((regValue & dataPoll) != dataPoll); + break; + case 4: + if (FLASH_MODE == X16) { + FirstData = 0x00aa00aa; /* Data for the First Cycle */ + SecondData = 0x00550055; /* Data for the Second Cycle */ + ThirdData = 0x00800080; /* Data for the Third Cycle */ + FourthData = 0x00aa00aa; /* Data for the Fourth Cycle */ + FifthData = 0x00550055; /* Data for the Fifth Cycle */ + SixthData = 0x00300030; /* Data for the Sixth Cycle */ + FirstAddr = 0x5555; /* Address for the First Cycle */ + SecondAddr = 0x2aaa; /* Address for the Second Cycle */ + ThirdAddr = 0x5555; /* Address for the Third Cycle */ + FourthAddr = 0x5555; /* Address for the Fourth Cycle */ + FifthAddr = 0x2aaa; /* Address for the Fifth Cycle */ + } else { /* if (FLASH_MODE == 8) */ + + FirstData = 0xaaaaaaaa; /* Data for the First Cycle */ + SecondData = 0x55555555; /* Data for the Second Cycle */ + ThirdData = 0x80808080; /* Data for the Third Cycle */ + FourthData = 0xAAAAAAAA; /* Data for the Fourth Cycle */ + FifthData = 0x55555555; /* Data for the Fifth Cycle */ + SixthData = 0x30303030; /* Data for the Sixth Cycle */ + FirstAddr = 0xaaaa; /* Address for the First Cycle */ + SecondAddr = 0x5555; /* Address for the Second Cycle */ + ThirdAddr = 0xaaaa; /* Address for the Third Cycle */ + FourthAddr = 0xaaaa; /* Address for the Fourth Cycle */ + FifthAddr = 0x5555; /* Address for the Fifth Cycle */ + } + WRITE_WORD(FLASH_BASE_ADDRESS + + FirstAddr * FLASH_WIDTH, FirstData); + WRITE_WORD(FLASH_BASE_ADDRESS + + SecondAddr * FLASH_WIDTH, SecondData); + WRITE_WORD(FLASH_BASE_ADDRESS + + ThirdAddr * FLASH_WIDTH, ThirdData); + WRITE_WORD(FLASH_BASE_ADDRESS + + FourthAddr * FLASH_WIDTH, FourthData); + WRITE_WORD(FLASH_BASE_ADDRESS + + FifthAddr * FLASH_WIDTH, FifthData); + WRITE_WORD(FLASH_BASE_ADDRESS + + (sectorBaseAddress & 0xffffff00) * + FLASH_WIDTH, SixthData); + /* Poll on the flash */ + if (FLASH_MODE == X16) { /* 4 devices , 16 bit each => 64bit */ + dataPoll = 0x00800080; + } else { /* (FLASH_MODE = 8) ==> 8 devices , 8 bit each => 64bit */ + + dataPoll = 0x80808080; + } + do { + READ_WORD(FLASH_BASE_ADDRESS + + sectorBaseAddress * FLASH_WIDTH, + ®Value); + } while ((regValue & dataPoll) != dataPoll); + break; + case 8: /* In case of 64bit width the transformation is 1->8 */ + if (FLASH_MODE == X16) { + FirstData = 0x00aa00aa; /* Data for the First Cycle */ + SecondData = 0x00550055; /* Data for the Second Cycle */ + ThirdData = 0x00800080; /* Data for the Third Cycle */ + FourthData = 0x00aa00aa; /* Data for the Fourth Cycle */ + FifthData = 0x00550055; /* Data for the Fifth Cycle */ + SixthData = 0x00300030; /* Data for the Sixth Cycle */ + FirstAddr = 0x5555; /* Address for the First Cycle */ + SecondAddr = 0x2aaa; /* Address for the Second Cycle */ + ThirdAddr = 0x5555; /* Address for the Third Cycle */ + FourthAddr = 0x5555; /* Address for the Fourth Cycle */ + FifthAddr = 0x2aaa; /* Address for the Fifth Cycle */ + } else { /* (FLASH_MODE = 8 */ + + FirstData = 0xaaaaaaaa; /* Data for the First Cycle */ + SecondData = 0x55555555; /* Data for the Second Cycle */ + ThirdData = 0x80808080; /* Data for the Third Cycle */ + FourthData = 0xAAAAAAAA; /* Data for the Fourth Cycle */ + FifthData = 0x55555555; /* Data for the Fifth Cycle */ + SixthData = 0x30303030; /* Data for the Sixth Cycle */ + FirstAddr = 0xaaaa; /* Address for the First Cycle */ + SecondAddr = 0x5555; /* Address for the Second Cycle */ + ThirdAddr = 0xaaaa; /* Address for the Third Cycle */ + FourthAddr = 0xaaaa; /* Address for the Fourth Cycle */ + FifthAddr = 0x5555; /* Address for the Fifth Cycle */ + } + WRITE_WORD(FLASH_BASE_ADDRESS + + FirstAddr * FLASH_WIDTH, FirstData); + WRITE_WORD(FLASH_BASE_ADDRESS + + SecondAddr * FLASH_WIDTH, SecondData); + WRITE_WORD(FLASH_BASE_ADDRESS + + ThirdAddr * FLASH_WIDTH, ThirdData); + WRITE_WORD(FLASH_BASE_ADDRESS + + FourthAddr * FLASH_WIDTH, FourthData); + WRITE_WORD(FLASH_BASE_ADDRESS + + FifthAddr * FLASH_WIDTH, FifthData); + WRITE_WORD(FLASH_BASE_ADDRESS + + (sectorBaseAddress & 0xffffff00) * + FLASH_WIDTH, SixthData); + WRITE_WORD(FLASH_BASE_ADDRESS + + FirstAddr * FLASH_WIDTH + 4, FirstData); + WRITE_WORD(FLASH_BASE_ADDRESS + + SecondAddr * FLASH_WIDTH + 4, + SecondData); + WRITE_WORD(FLASH_BASE_ADDRESS + + ThirdAddr * FLASH_WIDTH + 4, ThirdData); + WRITE_WORD(FLASH_BASE_ADDRESS + + FourthAddr * FLASH_WIDTH + 4, + FourthData); + WRITE_WORD(FLASH_BASE_ADDRESS + + FifthAddr * FLASH_WIDTH + 4, FifthData); + WRITE_WORD(FLASH_BASE_ADDRESS + + (sectorBaseAddress & 0xffffff00) + * FLASH_WIDTH + 4, SixthData); + /* Poll on the flash */ + if (FLASH_MODE == X16) { /* 4 devices , 16 bit each => 64bit */ + dataPoll = 0x00800080; + } else { /* (FLASH_MODE = 8) ==> 8 devices , 8 bit each => 64bit */ + + dataPoll = 0x80808080; + } + do { + READ_WORD(FLASH_BASE_ADDRESS + + sectorBaseAddress * FLASH_WIDTH, + ®Value); + } while ((regValue & dataPoll) != dataPoll); + do { + READ_WORD(FLASH_BASE_ADDRESS + + sectorBaseAddress * FLASH_WIDTH + + 4, ®Value); + } while ((regValue & dataPoll) != dataPoll); + break; + default: + return false; + } + } /* End of 'flash erase sector' for AMD/ST */ + else { /* Intel/Micron */ + + switch (FLASH_WIDTH) { + case 1: + WRITE_CHAR(FLASH_BASE_ADDRESS, 0x20); + WRITE_CHAR( + (FLASH_BASE_ADDRESS + + (sectorBaseAddress & 0xffffff00)), + 0xd0); + /* Poll on the flash */ + while (true) { + WRITE_CHAR(FLASH_BASE_ADDRESS, 0x70); + READ_CHAR(FLASH_BASE_ADDRESS, ®Value); + if ((regValue & 0x80) == 0x80) + break; + } + break; + case 2: + if (FLASH_MODE == X16) { /* 1 device 16 bit. */ + data20 = 0x0020;; + dataD0 = 0x00d0;; + } else { /* (FLASH_MODE = 8) ==> 2 devices , 8 bit each => 16bit */ + + data20 = 0x2020; + dataD0 = 0xd0d0; + } + WRITE_SHORT(FLASH_BASE_ADDRESS, data20); + WRITE_SHORT( + (FLASH_BASE_ADDRESS + + ((sectorBaseAddress * 2) & + 0xffffff00)), dataD0); + /* Poll on the flash */ + if (FLASH_MODE == X16) { + dataPoll = 0x0080; + data70 = 0x0070; + } else { /* (FLASH_MODE = 8) */ + + dataPoll = 0x8080; + data70 = 0x7070; + } + while (true) { + WRITE_SHORT(FLASH_BASE_ADDRESS + + sectorBaseAddress * 2, data70); + READ_SHORT(FLASH_BASE_ADDRESS + + sectorBaseAddress * 2, + ®Value); + if ((regValue & 0x0080) == 0x0080) + break; + } + break; + case 4: + if (FLASH_MODE == X16) { /* 2 devices , 16 bit each => 32bit */ + data20 = 0x00200020; + dataD0 = 0x00d000d0; + } else { /* (FLASH_MODE = 8) ==> 4 devices , 8 bit each => 32bit */ + + data20 = 0x20202020; + dataD0 = 0xd0d0d0d0; + } + WRITE_WORD(FLASH_BASE_ADDRESS, data20); + WRITE_WORD( + (FLASH_BASE_ADDRESS + + ((sectorBaseAddress * 4) & + 0xffffff00)), dataD0); + /* Poll on the flash */ + if (FLASH_MODE == X16) { + dataPoll = 0x0080; + data70 = 0x0070; + } else { /* (FLASH_MODE = 8) */ + + dataPoll = 0x8080; + data70 = 0x7070; + } + while (true) { + WRITE_SHORT(FLASH_BASE_ADDRESS, data70); + READ_SHORT(FLASH_BASE_ADDRESS, ®Value); + if ((regValue & dataPoll) == dataPoll) + break; + } + while (true) { + WRITE_SHORT(FLASH_BASE_ADDRESS + 2, + data70); + READ_SHORT(FLASH_BASE_ADDRESS + 2, + ®Value); + if ((regValue & dataPoll) == dataPoll) + break; + } + break; + case 8: + if (FLASH_MODE == X16) { /* 4 devices , 16 bit each => 64bit */ + data20 = 0x00200020; + dataD0 = 0x00d000d0; + } else { /* (FLASH_MODE = 8) ==> 8 devices , 8 bit each => 64bit */ + + data20 = 0x20202020; + dataD0 = 0xd0d0d0d0; + } + WRITE_WORD(FLASH_BASE_ADDRESS, data20); + WRITE_WORD( + (FLASH_BASE_ADDRESS + + ((sectorBaseAddress * 8) & + 0xffffff00)), dataD0); + WRITE_WORD(FLASH_BASE_ADDRESS + 4, data20); + WRITE_WORD( + (FLASH_BASE_ADDRESS + + ((sectorBaseAddress * 8) & 0xffffff00 + + 4)), dataD0); + /* Poll on the flash */ + if (FLASH_MODE == X16) { + dataPoll = 0x0080; + data70 = 0x0070; + } else { /* (FLASH_MODE = 8) */ + + dataPoll = 0x8080; + data70 = 0x7070; + } + while (true) { + WRITE_SHORT(FLASH_BASE_ADDRESS + + sectorBaseAddress * 8, data70); + READ_SHORT(FLASH_BASE_ADDRESS + + sectorBaseAddress * 8, + ®Value); + if ((regValue & dataPoll) == dataPoll) + break; + } + while (true) { + WRITE_SHORT(FLASH_BASE_ADDRESS + 2, + data70); + READ_SHORT(FLASH_BASE_ADDRESS + 2, + ®Value); + if ((regValue & dataPoll) == dataPoll) + break; + } + while (true) { + WRITE_SHORT(FLASH_BASE_ADDRESS + 4, + data70); + READ_SHORT(FLASH_BASE_ADDRESS + 4, + ®Value); + if ((regValue & dataPoll) == dataPoll) + break; + } + while (true) { + WRITE_SHORT(FLASH_BASE_ADDRESS + 6, + data70); + READ_SHORT(FLASH_BASE_ADDRESS + 6, + ®Value); + if ((regValue & dataPoll) == dataPoll) + break; + } + break; + default: + return false; + } + } + flashReset(); + return true; +} + +/******************************************************************** +* flashWriteWord - Write 32Bit to the FLASH memory at the given offset from the +* FLASH base address. +* address 0 = 0x00000000 !! +* Attention!!! data "0" cannot be programed back to +* "1" (only by first performing an earase operation). +* The function takes care of Big/Little endian conversion +* +* INPUTS: offset - The offset from the flash`s base address. +* data - The data that should be written. +* RETURNS: true on success,false on failure +*********************************************************************/ +bool flashWriteWord(unsigned int offset, unsigned int data) +{ + unsigned char c, rc; + unsigned short s, rs; + register unsigned int rw; + register unsigned int regValue; + register unsigned int FirstAddr, SecondAddr, ThirdAddr; + register unsigned int FirstData, SecondData, ThirdData; + register unsigned int data10, data20, data70, data80; + + if ((flashTypes[POINTER_TO_FLASH] == AMD_FLASH) || \ + (flashTypes[POINTER_TO_FLASH] == ST_FLASH)) { + switch (FLASH_WIDTH) { + case 1: /* Split the 32 bit write into four 8bit Writings */ + if (FLASH_MODE == PURE8) { /* Boot Flash */ + FirstAddr = 0x5555; + SecondAddr = 0x2aaa; + ThirdAddr = 0x5555; + } else { + FirstAddr = 0xaaaa; + SecondAddr = 0x5555; + ThirdAddr = 0xaaaa; + } + WRITE_CHAR(FLASH_BASE_ADDRESS + FirstAddr, 0xaa); + WRITE_CHAR(FLASH_BASE_ADDRESS + SecondAddr, 0x55); + WRITE_CHAR(FLASH_BASE_ADDRESS + ThirdAddr, 0xa0); +#ifdef BE + c = (data >> 24); +#else + c = data; +#endif + WRITE_CHAR(FLASH_BASE_ADDRESS + offset, c); + /* Writing first Byte */ + while (true) { + READ_CHAR(FLASH_BASE_ADDRESS + offset, + &rc); + if ((rc & 0x80) == (c & 0x80)) /* DQ7 =? DATA */ + break; /* DQ7 = DATA */ + if ((rc & 0x20) == 0x20) { /* DQ5 =? '1' */ + READ_CHAR(FLASH_BASE_ADDRESS + + offset, &rc); + if ((rc & 0x80) == (c & 0x80)) + break; /* DQ7 = DATA */ + else + return false; /* DQ7 != DATA */ + } + } + WRITE_CHAR(FLASH_BASE_ADDRESS + FirstAddr, 0xaa); + WRITE_CHAR(FLASH_BASE_ADDRESS + SecondAddr, 0x55); + WRITE_CHAR(FLASH_BASE_ADDRESS + ThirdAddr, 0xa0); +#ifdef BE + c = (data >> 16); +#else + c = (data >> 8); +#endif + WRITE_CHAR(FLASH_BASE_ADDRESS + offset + 1, c); + /* Writing second Byte */ + while (true) { + READ_CHAR(FLASH_BASE_ADDRESS + offset + 1, + &rc); + if ((rc & 0x80) == (c & 0x80)) /* DQ7 =? DATA */ + break; /* DQ7 = DATA */ + if ((rc & 0x20) == 0x20) { /* DQ5 =? '1' */ + READ_CHAR(FLASH_BASE_ADDRESS + + offset + 1, &rc); + if ((rc & 0x80) == (c & 0x80)) + break; /* DQ7 = DATA */ + else + return false; /* DQ7 != DATA */ + } + } + WRITE_CHAR(FLASH_BASE_ADDRESS + FirstAddr, 0xaa); + WRITE_CHAR(FLASH_BASE_ADDRESS + SecondAddr, 0x55); + WRITE_CHAR(FLASH_BASE_ADDRESS + ThirdAddr, 0xa0); +#ifdef BE + c = (data >> 8); +#else + c = (data >> 16); +#endif + WRITE_CHAR(FLASH_BASE_ADDRESS + offset + 2, c); + /* Writing third Byte */ + while (true) { + READ_CHAR(FLASH_BASE_ADDRESS + offset + 2, + &rc); + if ((rc & 0x80) == (c & 0x80)) /* DQ7 =? DATA */ + break; /* DQ7 = DATA */ + if ((rc & 0x20) == 0x20) { /* DQ5 =? '1' */ + READ_CHAR(FLASH_BASE_ADDRESS + + offset + 2, &rc); + if ((rc & 0x80) == (c & 0x80)) + break; /* DQ7 = DATA */ + else + return false; /* DQ7 != DATA */ + } + } + WRITE_CHAR(FLASH_BASE_ADDRESS + FirstAddr, 0xaa); + WRITE_CHAR(FLASH_BASE_ADDRESS + SecondAddr, 0x55); + WRITE_CHAR(FLASH_BASE_ADDRESS + ThirdAddr, 0xa0); +#ifdef BE + c = data; +#else + c = (data >> 24); +#endif + WRITE_CHAR(FLASH_BASE_ADDRESS + offset + 3, c); + /* Writing fourth Byte */ + while (true) { + READ_CHAR(FLASH_BASE_ADDRESS + offset + 3, + &rc); + if ((rc & 0x80) == (c & 0x80)) /* DQ7 =? DATA */ + break; /* DQ7 = DATA */ + if ((rc & 0x20) == 0x20) { /* DQ5 =? '1' */ + READ_CHAR(FLASH_BASE_ADDRESS + + offset + 3, &rc); + if ((rc & 0x80) == (c & 0x80)) + break; /* DQ7 = DATA */ + else + return false; /* DQ7 != DATA */ + } + } + break; + case 2: /* Split the 32 bit write into two 8/16 bit Writings + (16bit width). */ + if (FLASH_MODE == X16) { + FirstData = 0xaa; /* Data for the First Cycle */ + SecondData = 0x55; /* Data for the Second Cycle */ + ThirdData = 0xa0; /* Data for the Third Cycle */ + FirstAddr = 0x5555; /* Address for the First Cycle */ + SecondAddr = 0x2aaa; /* Address for the Second Cycle */ + ThirdAddr = 0x5555; /* Address for the Third Cycle */ + } else { /* if (FLASH_MODE == 8) */ + + FirstData = 0xaaaa; /* Data for the First Cycle */ + SecondData = 0x5555; /* Data for the Second Cycle */ + ThirdData = 0xa0a0; /* Data for the Third Cycle */ + FirstAddr = 0xaaaa; /* Address for the First Cycle */ + SecondAddr = 0x5555; /* Address for the Second Cycle */ + ThirdAddr = 0xaaaa; /* Address for the Third Cycle */ + } + WRITE_SHORT(FLASH_BASE_ADDRESS + + FirstAddr * FLASH_WIDTH, FirstData); + WRITE_SHORT(FLASH_BASE_ADDRESS + + SecondAddr * FLASH_WIDTH, SecondData); + WRITE_SHORT(FLASH_BASE_ADDRESS + + ThirdAddr * FLASH_WIDTH, ThirdData); +#ifdef BE + s = (data >> 16); +#else + s = data; +#endif + WRITE_SHORT(FLASH_BASE_ADDRESS + offset, s); + /* Writing Two Bytes */ + if (FLASH_MODE == X16) { + data80 = 0x80;; + data20 = 0x20;; + } else { /* if (FLASH_MODE == 8) */ + + data80 = 0x8080; + data20 = 0x2020; + } + while (true) { + READ_SHORT(FLASH_BASE_ADDRESS + offset, + &rs); + if ((rs & data80) == (s & data80)) /* DQ7 =? DATA */ + break; /* DQ7 = DATA */ + if ((rs & data20) == data20) { /* DQ5 =? DATA */ + READ_SHORT(FLASH_BASE_ADDRESS + + offset, &rs); + if ((rs & data80) == (s & data80)) + break; /* DQ7 = DATA */ + else { + flashReset(); + return false; /* DQ7 != DATA */ + } + } + } + WRITE_SHORT(FLASH_BASE_ADDRESS + + FirstAddr * FLASH_WIDTH, FirstData); + WRITE_SHORT(FLASH_BASE_ADDRESS + + SecondAddr * FLASH_WIDTH, SecondData); + WRITE_SHORT(FLASH_BASE_ADDRESS + + ThirdAddr * FLASH_WIDTH, ThirdData); +#ifdef BE + s = data; +#else + s = (data >> 16); +#endif + WRITE_SHORT(FLASH_BASE_ADDRESS + offset + 2, s); + /* Writing Two Bytes */ + while (true) { + READ_SHORT(FLASH_BASE_ADDRESS + offset + 2, + &rs); + if ((rs & data80) == (s & data80)) /* DQ7 =? DATA */ + break; /* DQ7 = DATA */ + if ((rs & data20) == data20) { /* DQ5 =? '1' */ + READ_SHORT(FLASH_BASE_ADDRESS + + offset + 2, &rs); + if ((rs & data80) == (s & data80)) + break; /* DQ7 = DATA */ + else { + flashReset(); + return false; /* DQ7 != DATA */ + } + } + } + return true; + case 4: + case 8: + if (FLASH_MODE == X16) { + FirstData = 0x00aa00aa; + SecondData = 0x00550055; + ThirdData = 0x00a000a0; + FirstAddr = 0x5555; + SecondAddr = 0x2aaa; + ThirdAddr = 0x5555; + } else { /* (FLASH_MODE == 8) */ + + FirstData = 0xaaaaaaaa; /* Data for the First Cycle */ + SecondData = 0x55555555; /* Data for the Second Cycle */ + ThirdData = 0xa0a0a0a0; /* Data for the Third Cycle */ + FirstAddr = 0xaaaaaaaa; /* Address for the First Cycle */ + SecondAddr = 0x55555555; /* Address for the Second Cycle */ + ThirdAddr = 0xaaaaaaaa; /* Address for the Third Cycle */ + } + WRITE_WORD(FLASH_BASE_ADDRESS + FirstAddr * + FLASH_WIDTH + offset % FLASH_WIDTH, + FirstData); + WRITE_WORD(FLASH_BASE_ADDRESS + + SecondAddr * FLASH_WIDTH + + offset % FLASH_WIDTH, SecondData); + WRITE_WORD(FLASH_BASE_ADDRESS + + ThirdAddr * FLASH_WIDTH + + offset % FLASH_WIDTH, ThirdData); + /* writting the word. */ + WRITE_WORD(FLASH_BASE_ADDRESS + offset, data); + /* preparing the polling patterns. */ + if (FLASH_MODE == X16) { + data80 = 0x00800080; + data20 = 0x00200020; + } else { /* (FLASH_MODE == 8) */ + + data80 = 0x80808080; + data20 = 0x20202020; + } + while (true) { /* polling loop. */ + rw = READWORD(FLASH_BASE_ADDRESS + offset); + /* DQ7 =? DATA */ + if ((rw & data80) == (data & data80)) + break; /* DQ7 = DATA */ + if ((rw & data20) == data20) { /* DQ5 =? '1' */ + rw = + READWORD(FLASH_BASE_ADDRESS + + offset); + if ((rw & data80) == + (data & data80)) break; /* DQ7 = DATA */ + else + return false; /* DQ7 != DATA */ + } + } + return true; + default: + return false; /* case of invalid flash Width. */ + } + } else { /* Intel/Micron */ + + switch (FLASH_WIDTH) { + case 1: + /* Writing First Byte */ + WRITE_CHAR(FLASH_BASE_ADDRESS, 0x10); +#ifdef BE + c = (data >> 24); +#else + c = data; +#endif + WRITE_CHAR(FLASH_BASE_ADDRESS + offset, c); + while (true) { + /* Reading STATUS Register */ + WRITE_CHAR(FLASH_BASE_ADDRESS, 0x70); + regValue = READCHAR(FLASH_BASE_ADDRESS); + if ((regValue & 0x80) == 0x80) + break; /* Case of Write-Operation had Ended */ + } + /* Reading STATUS Register for Writing Verification */ + WRITE_CHAR(FLASH_BASE_ADDRESS, 0x70); + regValue = READCHAR(FLASH_BASE_ADDRESS); + if ((regValue & 0x10) == 0x10) + return false; /* Write failure */ + + /* Writing Second Byte */ + WRITE_CHAR(FLASH_BASE_ADDRESS + 1, 0x10); +#ifdef BE + c = (data >> 16); +#else + c = (data >> 8); +#endif + WRITE_CHAR(FLASH_BASE_ADDRESS + offset + 1, c); + while (true) { + /* Reading STATUS Register */ + WRITE_CHAR(FLASH_BASE_ADDRESS + 1, 0x70); + regValue = + READCHAR(FLASH_BASE_ADDRESS + 1); + if ((regValue & 0x80) == 0x80) + break; /* Write operation ended */ + } + /* Reading STATUS Register for Writing verification */ + WRITE_CHAR(FLASH_BASE_ADDRESS + 1, 0x70); + regValue = READCHAR(FLASH_BASE_ADDRESS + 1); + if ((regValue & 0x10) == 0x10) + return false; /* Write failure */ + + /* Writing Third Byte */ + WRITE_CHAR(FLASH_BASE_ADDRESS + 2, 0x10); +#ifdef BE + c = (data >> 8); +#else + c = (data >> 16); +#endif + WRITE_CHAR(FLASH_BASE_ADDRESS + offset + 2, c); + while (true) { + /* Reading STATUS Register */ + WRITE_CHAR(FLASH_BASE_ADDRESS + 2, 0x70); + regValue = + READCHAR(FLASH_BASE_ADDRESS + 2); + if ((regValue & 0x80) == 0x80) + break; /* Write operation ended */ + } + /* Reading STATUS Register for Writing Verification */ + WRITE_CHAR(FLASH_BASE_ADDRESS + 2, 0x70); + regValue = READCHAR(FLASH_BASE_ADDRESS + 2); + if ((regValue & 0x10) == 0x10) + return false; /* Write failure */ + + /* Writing Fourth Byte */ + WRITE_CHAR(FLASH_BASE_ADDRESS + 3, 0x10); +#ifdef BE + c = data; +#else + c = (data >> 24); +#endif + WRITE_CHAR(FLASH_BASE_ADDRESS + offset + 3, c); + while (true) { + /* Reading STATUS Register */ + WRITE_CHAR(FLASH_BASE_ADDRESS + 3, 0x70); + regValue = + READCHAR(FLASH_BASE_ADDRESS + 3); + if ((regValue & 0x80) == 0x80) + break; /* Write operation ended */ + } + /* Reading STATUS Register for Writing Verification */ + WRITE_CHAR(FLASH_BASE_ADDRESS + 3, 0x70); + regValue = READCHAR(FLASH_BASE_ADDRESS + 3); + if ((regValue & 0x10) == 0x10) + return false; /* Write failure */ + flashReset(); + return true; + case 2: + if (FLASH_MODE == X16) { /* Case of one X16 bit device */ + FirstData = 0x0010; /* Data for the First Cycle */ + } else { /* if (FLASH_MODE == 8) ==> Case of two X8 bit devices */ + + FirstData = 0x1010; /* Data for the First Cycle */ + } + /* Writing First two Bytes */ + WRITE_SHORT(FLASH_BASE_ADDRESS, FirstData); +#ifdef BE + s = (data >> 16); +#else + s = data; +#endif + WRITE_SHORT(FLASH_BASE_ADDRESS + offset, s); + if (FLASH_MODE == X16) { + data70 = 0x0070; + data80 = 0x0080; + data10 = 0x0010; + } else { /* case of (FLASH_MODE == X8) */ + + data70 = 0x7070; + data80 = 0x8080; + data10 = 0x1010; + } + /* polling on writing action => when done break. */ + while (true) { + WRITE_SHORT(FLASH_BASE_ADDRESS, data70); + regValue = READSHORT(FLASH_BASE_ADDRESS); + if ((regValue & data80) == data80) + break; + } + /* Reading STATUS Register for Writing Verification */ + WRITE_CHAR(FLASH_BASE_ADDRESS, data70); + regValue = READCHAR(FLASH_BASE_ADDRESS); + if ((regValue & data10) == data10) + return false; /* Write failure */ + /* Writing Last two Bytes */ + WRITE_SHORT(FLASH_BASE_ADDRESS + 2, FirstData); +#ifdef BE + s = data; +#else + s = (data >> 16); +#endif + WRITE_SHORT(FLASH_BASE_ADDRESS + offset + 2, s); + /* polling on writing action => when done break. */ + while (true) { + WRITE_SHORT(FLASH_BASE_ADDRESS + 2, + data70); + regValue = + READSHORT(FLASH_BASE_ADDRESS + 2); + if ((regValue & data80) == data80) + break; + } + /* Reading STATUS Register for Writing Verification */ + WRITE_CHAR(FLASH_BASE_ADDRESS, data70); + regValue = READCHAR(FLASH_BASE_ADDRESS); + if ((regValue & data10) == data10) + return false; /* Write failure */ + flashReset(); + return true; + case 4: + case 8: + if (FLASH_MODE == X16) { /* Case of one X16 bit device */ + FirstData = 0x00100010; /* Data for the First Cycle */ + } else { /* (FLASH_MODE == 8) ==> Case of two X8 bit devices */ + + FirstData = 0x10101010; /* Data for the First Cycle */ + } + /* Writing First two Bytes */ + WRITE_WORD(FLASH_BASE_ADDRESS + + offset % FLASH_WIDTH, FirstData); +#ifdef BE + s = (data >> 16); +#else + s = data; +#endif + /* writing the 32-bit data to flash. */ + WRITE_WORD(FLASH_BASE_ADDRESS + offset, data); + if (FLASH_MODE == X16) { + data70 = 0x0070; + data80 = 0x0080; + data10 = 0x0010; + } else { /* (FLASH_MODE == 8) */ + + data70 = 0x7070; + data80 = 0x8080; + data10 = 0x1010; + } + while (true) { + WRITE_SHORT(FLASH_BASE_ADDRESS + + offset % FLASH_WIDTH, data70); + regValue = READSHORT(FLASH_BASE_ADDRESS); + if ((regValue & data80) == data80) + break; + } + /* Reading STATUS Register for Writing Verification */ + WRITE_CHAR(FLASH_BASE_ADDRESS, data70); + regValue = READCHAR(FLASH_BASE_ADDRESS); + if ((regValue & data10) == data10) + return false; /* Write failure */ + + /* Writing Last two Bytes */ +#ifdef BE + s = data; +#else + s = (data >> 16); +#endif + while (true) { + WRITE_SHORT(FLASH_BASE_ADDRESS + + offset % FLASH_WIDTH + 2, + data70); + regValue = + READSHORT(FLASH_BASE_ADDRESS + + offset % FLASH_WIDTH + 2); + if ((regValue & data80) == data80) + break; + } + /* Reading STATUS Register for Writing Verification */ + WRITE_CHAR(FLASH_BASE_ADDRESS, data70); + regValue = READCHAR(FLASH_BASE_ADDRESS); + if ((regValue & data10) == data10) + return false; /* Write failure */ + + flashReset(); + return true; + default: + flashReset(); + return false; + } + } + flashReset(); + return true; +} + +/******************************************************************** +* flashReadWord - Read 32Bit from the FLASH memory at a given offset +* from the FLASH base address. +* address 0 = 0x00000000 !! +* The function takes care of Big/Little endian conversion +* INPUTS: offset,the offset from the flash`s base address +* RETURNS: data +*********************************************************************/ +unsigned int flashReadWord(unsigned int offset) +{ + unsigned int regValue; + flashReset(); + READ_WORD(FLASH_BASE_ADDRESS + offset, ®Value); + return regValue; +} + +/******************************************************************** +* flashInWhichSector - Returns the sector`s number at which offset is at. +* +* INPUTS: Offset +* RETURNS: Sector number,or 0xffffffff in case the address is out of range or +* flash wasn't initialize. +*********************************************************************/ +unsigned int flashInWhichSector(unsigned int offset) +{ + unsigned int sectorNumber, numberOfDevices; + unsigned int accMemory = 0; + + if ((FLASH_MODE == PURE8) || (FLASH_MODE == X8)) { + numberOfDevices = FLASH_WIDTH; + } else { /* X16 mode */ + + numberOfDevices = FLASH_WIDTH / 2; + } + for (sectorNumber = 0; + sectorNumber < flashTypes[NUMBER_OF_SECTORS]; sectorNumber++) { + accMemory = + accMemory + flashTypes[FIRST_SECTOR_SIZE + + sectorNumber]; + if (offset < accMemory * numberOfDevices * 1024) + return sectorNumber; + } + return 0xffffffff; +} + +/******************************************************************** +* flashGetSectorSize - When given a Valid sector Number returns its Size. +* +* INPUTS: unsigned int sectorNumber. +* RETURNS: Sector size. (if Sector number isn't valid or flash wasn't +* initialize return 0.) +*********************************************************************/ +unsigned int flashGetSectorSize(unsigned int sectorNumber) +{ + if (sectorNumber >= flashTypes[NUMBER_OF_SECTORS]) + return 0; + else { + if (FLASH_MODE != PURE8) + return (flashTypes + [FIRST_SECTOR_SIZE + + sectorNumber] * _1K * (FLASH_WIDTH * 8 / + FLASH_MODE)); + else /* in case of PUR8 */ + return (flashTypes + [FIRST_SECTOR_SIZE + + sectorNumber] * _1K * FLASH_WIDTH); + } +} + +/******************************************************************** +* getFlashSize - Return Total flash size. +* +* INPUTS: N/A. +* RETURNS: Flash size. (If flash wasn't initialize return 0) +*********************************************************************/ +unsigned int flashGetSize() +{ + unsigned int sectorNum; + unsigned int totalSize = 0; + + if (POINTER_TO_FLASH == 0) + return 0; /* case of flash not initialize */ + for (sectorNum = 0; sectorNum < flashTypes[NUMBER_OF_SECTORS]; + sectorNum++) { + totalSize += flashGetSectorSize(sectorNum); + } + return (totalSize); + +} + +/******************************************************************** +* flashGetSectorOffset - Returns sector base address. +* +* INPUTS: unsigned int sectorNum. +* RETURNS: Sector Base Address. +*********************************************************************/ +unsigned int flashGetSectorOffset(unsigned int sectorNum) +{ + unsigned int i; + unsigned int sectorBaseAddress = 0; + unsigned int numOfDevices; + + if (sectorNum > (flashParametrs[NUMBER_OF_SECTORS] - 1)) + return 0xffffffff; + for (i = 0; i < sectorNum; i++) { + sectorBaseAddress = + sectorBaseAddress + flashTypes[FIRST_SECTOR_SIZE + i]; + } + if (FLASH_MODE == X16) + numOfDevices = FLASH_WIDTH * 8 / FLASH_MODE; + else + numOfDevices = FLASH_WIDTH; + return (_1K * sectorBaseAddress * numOfDevices); + +} + +/******************************************************************** +* flashWriteBlock - Write block of chars to flash. +* +* INPUTS: unsigned int offset - flash destination address. +* unsigned int numOfByte - block size. +* unsigned char * blockAddress - block source address. +* RETURNS: Number of Bytes written. +*********************************************************************/ +unsigned int flashWriteBlock(unsigned int offset, unsigned int numOfByte, + unsigned char *blockAddress) +{ + register unsigned int flashWrite; + register unsigned int align; + register unsigned int num; + register unsigned int i; + + if ((offset + numOfByte) > flashGetSize()) + numOfByte = flashGetSize() - offset; /* getting to flash boundary. */ + num = numOfByte; + align = offset % 4; /* alignment toward flash. */ + /* writes chars until the offset toward flash will be align. */ + for (i = align; (i < 4) && (numOfByte > 0) && (align != 0); i++) { + flashWriteChar(offset, blockAddress[0]); + numOfByte--; + offset++; + blockAddress++; + } + while (numOfByte > 3) { +#ifdef LE + flashWrite = blockAddress[0] | (blockAddress[1] << 8) | + (blockAddress[2] << 16) | (blockAddress[3] << 24); +#else + flashWrite = blockAddress[3] | (blockAddress[2] << 8) | + (blockAddress[1] << 16) | (blockAddress[0] << 24); +#endif + if (flashWrite != 0xffffffff) /* for optimization. */ + flashWriteWord(offset, flashWrite); + numOfByte -= 4; + blockAddress += 4; + offset += 4; + } + while (numOfByte > 0) { + flashWriteChar(offset, blockAddress[0]); + numOfByte--; + blockAddress++; + offset++; + } + return num; +} + +/******************************************************************** +* flashReadBlock - Read block of chars from flash. +* +* INPUTS: unsigned int offset - flash source address. +* unsigned int numOfByte - block size. +* unsigned char * blockAddress - block destination address. +* RETURNS: Number of Bytes written. +*********************************************************************/ +unsigned int flashReadBlock(unsigned int offset, unsigned int numOfByte, + unsigned char *blockAddress) +{ + unsigned int i; + for (i = 0; i < numOfByte; i++) { + blockAddress[i] = flashReadChar(offset + i); + } + return numOfByte; +} + +/******************************************************************** +* flashReadChar - read one charecter form given flash offset. +* +* INPUTS: unsigned int offset - required offset to be read from. +* RETURNS: read charecter. +*********************************************************************/ +unsigned char flashReadChar(unsigned int offset) +{ + unsigned char regValue; + + flashReset(); + READ_CHAR(FLASH_BASE_ADDRESS + offset, ®Value); + return regValue; +} + +/******************************************************************** +* flashReadShort - read 16bit form given flash offset. +* +* INPUTS: unsigned int offset - required offset to be read from. +* RETURNS: 16bit data. +*********************************************************************/ +unsigned short flashReadShort(unsigned int offset) +{ + unsigned short regValue; + + flashReset(); + READ_SHORT(FLASH_BASE_ADDRESS + offset, ®Value); + return regValue; +} + +/******************************************************************** +* flashWriteShort - write 16bit data to a given flash offset. +* It reads the whole word 32bit wide, modify the short +* and write back the word. +* +* INPUTS: unsigned int offset - required offset to be write to. +* unsigned short sdata - data to be written. +* RETURNS: true if writting successesed false otherwise. +*********************************************************************/ +bool flashWriteShort(unsigned int offset, unsigned short sdata) +{ + unsigned int align; + unsigned int flashWrite; + unsigned int flashRead; + + align = offset % 4; + if ((align == 1) || (align == 3)) + return false; /* offset misaligned. */ + flashRead = flashReadWord(offset - align); + if (align == 0) +#ifdef BE + flashWrite = (flashRead & 0x0000ffff) | (sdata << 16); +#else + flashWrite = (flashRead & 0xffff0000) | sdata; +#endif + else /* (align == 2) */ +#ifdef BE + flashWrite = (flashRead & 0xffff0000) | sdata; +#else + flashWrite = (flashRead & 0x0000ffff) | (sdata << 16); +#endif + flashWriteWord(offset - align, flashWrite); + return true; + +} + +/******************************************************************** +* flashWriteChar - write one charecter (8 bit) to a given flash offset. +* It reads the whole word 32bit wide, modify the charecter +* and write back the word. +* +* INPUTS: unsigned int offset - required offset to be write to. +* unsigned short sdata - data to be written. +* RETURNS: true if writting successed. +*********************************************************************/ +bool flashWriteChar(unsigned int offset, unsigned char cdata) +{ + unsigned int align; + unsigned int flashWrite; + unsigned int flashRead; + + align = offset % 4; + flashRead = flashReadWord(offset - align); +#ifdef BE + flashWrite = (flashRead & ~(0xff000000 >> (8 * align))) | + (cdata << (8 * (3 - align))); +#else + flashWrite = (flashRead & ~(0xff000000 << (8 * align))) | + (cdata << (8 * align)); +#endif + flashWriteWord(offset - align, flashWrite); + return true; +} + +/******************************************************************** +* flashGetNumOfSectors - write one charecter (8 bit) to a given flash offset. +* It reads the whole word 32bit wide, modify the +* charecter and write back the word. +* +* INPUTS: N/A. +* RETURNS: Number of sectors. +*********************************************************************/ +unsigned int flashGetNumOfSectors(void) +{ + return (flashTypes[NUMBER_OF_SECTORS]); +} diff --git a/arch/mips/galileo-boards/ev64120/compressed/galileo_port.h b/arch/mips/galileo-boards/ev64120/compressed/galileo_port.h new file mode 100644 index 000000000..a565ce72a --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/galileo_port.h @@ -0,0 +1,8 @@ +#define GFP_KERNEL 0 +#define GFP_ATOMIC 1 +#define KERN_ERR "" + +void *kmalloc(unsigned int, int); +void *memset(void *, char, unsigned int); +int memcmp(char *, char *, unsigned int); +void *memcpy(void *to, const void *from, unsigned int); diff --git a/arch/mips/galileo-boards/ev64120/compressed/gt64011.h b/arch/mips/galileo-boards/ev64120/compressed/gt64011.h new file mode 100644 index 000000000..94e012c76 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/gt64011.h @@ -0,0 +1,279 @@ +/* + * gt64011.h: Galileo PCI system controller + * Copyright (c) 1998 Algorithmics Ltd + */ + +#ifdef __ASSEMBLER__ + +/* offsets from base register */ +#define GT64011(x) (x) + +/* device is littleendian, so data may need to be swapped */ +#ifdef GALILEO_PORT +#define htoll(x) ((((x) & 0x00ff) << 24) | \ + (((x) & 0xff00) << 8) | \ + (((x) >> 8) & 0xff00) | \ + (((x) >> 24) & 0x00ff)) +/*#define ltohl(x) htoll(x)*/ +#else +#define htoll(x) (x) +/* #define ltohl(x) (x) */ +#endif + +#else /* !__ASSEMBLER */ + +/* offsets from base pointer, this construct allows optimisation */ +static char *const _gt64011p = (char *) PA_TO_KVA1(GT64011_BASE); + +#define GT64011(x) *(volatile unsigned long *)(_gt64011p + (x)) + +/* device is littleendian, so data may need to be swapped */ +#ifdef GALILEO_PORT +#define htoll(x) ({ \ + unsigned int v = (unsigned int)(x); \ + v = (((v & 0x00ff) << 24) | \ + ((v & 0xff00) << 8) | \ + ((v >> 8) & 0xff00) | \ + ((v >> 24) & 0x00ff)); \ + v; \ + }) +#define ltohl(x) htoll(x) + +#else +asjdsajd +#define htoll(x) (x) +#define ltohl(x) (x) +#endif +#endif /* __ASSEMBLER__ */ +/* CPU configuration */ +#define GT_CPU_CFG GT64011(0x000) +#define GT_CPU_CFG_WriteMode (1<<11) +#define GT_CPU_CFG_Endianess (1<<12) +/* Processor Address Space */ +#define GT_PAS_RAS10LO GT64011(0x008) +#define GT_PAS_RAS10HI GT64011(0x010) +#define GT_PAS_RAS32LO GT64011(0x018) +#define GT_PAS_RAS32HI GT64011(0x020) +#define GT_PAS_CS20LO GT64011(0x028) +#define GT_PAS_CS20HI GT64011(0x030) +#define GT_PAS_CS3BOOTLO GT64011(0x038) +#define GT_PAS_CS3BOOTHI GT64011(0x040) +#define GT_PAS_PCIIOLO GT64011(0x048) +#define GT_PAS_PCIIOHI GT64011(0x050) +#define GT_PAS_PCIMEMLO GT64011(0x058) +#define GT_PAS_PCIMEMHI GT64011(0x060) +#define GT_PAS_INTDEC GT64011(0x068) +#define GT_PAS_BUSERRLO GT64011(0x070) +#define GT_PAS_PCIMEM1LO GT64011(0x080) +#define GT_PAS_PCIMEM1HI GT64011(0x088) +#define GT_PAS_LOMASK_Low 0x7ff +#define GT_PAS_LOSHIFT_Low 0 +#define GT_PAS_HIMASK_High 0x07f +#define GT_PAS_HISHIFT_High 0 +/* DRAM and Device Address Space */ +#define GT_DDAS_RAS0LO GT64011(0x400) +#define GT_DDAS_RAS0HI GT64011(0x404) +#define GT_DDAS_RAS1LO GT64011(0x408) +#define GT_DDAS_RAS1HI GT64011(0x40c) +#define GT_DDAS_RAS2LO GT64011(0x410) +#define GT_DDAS_RAS2HI GT64011(0x414) +#define GT_DDAS_RAS3LO GT64011(0x418) +#define GT_DDAS_RAS3HI GT64011(0x41c) +#define GT_DDAS_CS0LO GT64011(0x420) +#define GT_DDAS_CS0HI GT64011(0x424) +#define GT_DDAS_CS1LO GT64011(0x428) +#define GT_DDAS_CS1HI GT64011(0x42c) +#define GT_DDAS_CS2LO GT64011(0x430) +#define GT_DDAS_CS2HI GT64011(0x434) +#define GT_DDAS_CS3LO GT64011(0x438) +#define GT_DDAS_CS3HI GT64011(0x43c) +#define GT_DDAS_BOOTCSLO GT64011(0x440) +#define GT_DDAS_BOOTCSHI GT64011(0x444) +#define GT_DDAS_ERROR GT64011(0x470) +#define GT_DDAS_LOMASK_Low 0xff +#define GT_DDAS_LOSHIFT_Low 0 +#define GT_DDAS_HIMASK_High 0xff +#define GT_DDAS_HISHIFT_High 0 +/* DRAM Configuration */ +#define GT_DRAM_CFG GT64011(0x448) +#define GT_DRAM_CFG_RefIntCntMASK 0x00003fff +#define GT_DRAM_CFG_RefIntCntSHIFT 0 +#define GT_DRAM_CFG_RefIntCnt(x) (((x)<<GT_DRAM_CFG_RefIntCntSHIFT)&\ + GT_DRAM_CFG_RefIntCntMASK) +#define GT_DRAM_CFG_StagRef (1<<16) +#define GT_DRAM_CFG_StagRefOn 0 +#define GT_DRAM_CFG_StagRefAll GT_DRAM_CFG_StagRef +#define GT_DRAM_CFG_ADSFunct (1<<17) +#define GT_DRAM_CFG_ADSFunctDRAM 0 +#define GT_DRAM_CFG_ADSFunctOnly GT_DRAM_CFG_ADSFunct +#define GT_DRAM_CFG_DRAMLatch (1<<18) +#define GT_DRAM_CFG_DRAMLatchActive 0 +#define GT_DRAM_CFG_DRAMLatchTransparent GT_DRAM_CFG_DRAMLatch +/* DRAM Parameters */ +#define GT_DRAMPAR_BANK0 GT64011(0x44c) +#define GT_DRAMPAR_BANK1 GT64011(0x450) +#define GT_DRAMPAR_BANK2 GT64011(0x454) +#define GT_DRAMPAR_BANK3 GT64011(0x458) +#define GT_DRAMPAR_CASWr (1<<0) +#define GT_DRAMPAR_CASWr1 0 +#define GT_DRAMPAR_CASWr2 GT_DRAMPAR_CASWr +#define GT_DRAMPAR_RAStoCASWr (1<<1) +#define GT_DRAMPAR_RAStoCASWr2 0 +#define GT_DRAMPAR_RAStoCASWr3 GT_DRAMPAR_RAStoCASWr +#define GT_DRAMPAR_CASRd (1<<2) +#define GT_DRAMPAR_CASRd1 0 +#define GT_DRAMPAR_CASRd2 GT_DRAMPAR_CASRd +#define GT_DRAMPAR_RAStoCASRd (1<<3) +#define GT_DRAMPAR_RAStoCASRd2 0 +#define GT_DRAMPAR_RAStoCASRd3 GT_DRAMPAR_RAStoCASRd +#define GT_DRAMPAR_RefreshSHIFT 4 +#define GT_DRAMPAR_RefreshMASK (3<<4) +#define GT_DRAMPAR_Refresh512 (0<<4) +#define GT_DRAMPAR_Refresh1024 (1<<4) +#define GT_DRAMPAR_Refresh2048 (2<<4) +#define GT_DRAMPAR_Refresh4096 (3<<4) +#define GT_DRAMPAR_BankWidth (1<<6) +#define GT_DRAMPAR_BankWidth32 0 +#define GT_DRAMPAR_BankWidth64 GT_DRAMPAR_BankWidth +#define GT_DRAMPAR_BankLoc (1<<7) +#define GT_DRAMPAR_BankLocEven 0 +#define GT_DRAMPAR_BankLocOdd GT_DRAMPAR_BankLoc +#define GT_DRAMPAR_Parity (1<<8) +#define GT_DRAMPAR_ParityDisable 0 +#define GT_DRAMPAR_ParityEnable GT_DRAMPAR_Parity +#define GT_DRAMPAR_MBZ (1<<9) +/* Device Parameters */ +#define GT_DEVPAR_BANK0 GT64011(0x45c) +#define GT_DEVPAR_BANK1 GT64011(0x460) +#define GT_DEVPAR_BANK2 GT64011(0x464) +#define GT_DEVPAR_BANK3 GT64011(0x468) +#define GT_DEVPAR_BOOT GT64011(0x46c) +#define GT_DEVPAR_TurnOffMASK (7<<0) +#define GT_DEVPAR_TurnOffSHIFT 0 +#define GT_DEVPAR_TurnOff(x) ((x)<<0) +#define GT_DEVPAR_AccToFirstMASK (15<<3) +#define GT_DEVPAR_AccToFirstSHIFT 3 +#define GT_DEVPAR_AccToFirst(x) ((x)<<3) +#define GT_DEVPAR_AccToNextMASK (15<<7) +#define GT_DEVPAR_AccToNextSHIFT 7 +#define GT_DEVPAR_AccToNext(x) ((x)<<7) +#define GT_DEVPAR_ADStoWrMASK (7<<11) +#define GT_DEVPAR_ADStoWrSHIFT 11 +#define GT_DEVPAR_ADStoWr(x) ((x)<<11) +#define GT_DEVPAR_WrActiveMASK (7<<14) +#define GT_DEVPAR_WrActiveSHIFT 14 +#define GT_DEVPAR_WrActive(x) ((x)<<14) +#define GT_DEVPAR_WrHighMASK (7<<17) +#define GT_DEVPAR_WrHighSHIFT 17 +#define GT_DEVPAR_WrHigh(x) ((x)<<17) +#define GT_DEVPAR_DevWidthMASK (3<<20) +#define GT_DEVPAR_DevWidthSHIFT 20 +#define GT_DEVPAR_DevWidth8 (0<<20) +#define GT_DEVPAR_DevWidth16 (1<<20) +#define GT_DEVPAR_DevWidth32 (2<<20) +#define GT_DEVPAR_DevWidth64 (3<<20) +#define GT_DEVPAR_DevLoc (1<<23) +#define GT_DEVPAR_DevLocEven 0 +#define GT_DEVPAR_DevLocOdd GT_DEVPAR_DevLoc +#define GT_DEVPAR_LatchFunct (1<<25) +#define GT_DEVPAR_LatchFunctTransparent 0 +#define GT_DEVPAR_LatchFunctEnable GT_DEVPAR_LatchFunct +#define GT_DEVPAR_Parity (1<<30) +#define GT_DEVPAR_ParityDisable 0 +#define GT_DEVPAR_ParityEnable GT_DEVPAR_Parity +#define GT_DEVPAR_ReservedMASK 0x3d400000 +#define GT_DEVPAR_Reserved 0x14400000 +/* PCI Internal */ +#define GT_IPCI_CMD GT64011(0xc00) +#define GT_IPCI_CMD_ByteSwap (1<<0) +#define GT_IPCI_CMD_ByteSwapOn 0 +#define GT_IPCI_CMD_ByteSwapOff GT_INTPCI_CMD_ByteSwap +#define GT_IPCI_CMD_SyncModeMASK (3<<1) +#define GT_IPCI_CMD_SyncModeSHIFT 1 +#define GT_IPCI_CMD_SyncModeStd (0<<1) +#define GT_IPCI_CMD_SyncMode1 (1<<1) +#define GT_IPCI_CMD_SyncMode2 (2<<1) +#define GT_IPCI_TOR GT64011(0xc04) +#define GT_IPCI_TOR_Timeout0MASK (255<<0) +#define GT_IPCI_TOR_Timeout0SHIFT 0 +#define GT_IPCI_TOR_Timeout0(x) ((x)<<0) +#define GT_IPCI_TOR_Timeout1MASK (255<<8) +#define GT_IPCI_TOR_Timeout1SHIFT 8 +#define GT_IPCI_TOR_Timeout1(x) ((x)<<8) +#define GT_IPCI_TOR_RetryCtrMASK (255<<16) +#define GT_IPCI_TOR_RetryCtrSHIFT 16 +#define GT_IPCI_TOR_RetryCtr(x) ((x)<<16) +#define GT_IPCI_RAS10SIZE GT64011(0xc08) +#define GT_IPCI_RAS32SIZE GT64011(0xc0c) +#define GT_IPCI_CS20SIZE GT64011(0xc10) +#define GT_IPCI_CS3BOOTSIZE GT64011(0xc14) +#define GT_IPCI_SIZE_BankSizeMASK (0xfffff<<12) +#define GT_IPCI_SIZE_BankSizeSHIFT 12 +#define GT_IPCI_INTRCAUSE GT64011(0xc18) +#define GT_IPCI_INTRMASK GT64011(0xc1c) +#define GT_INTR_INTSUM 0x0000001 +#define GT_INTR_MEMOUT 0x0000002 +#define GT_INTR_DMAOUT 0x0000004 +#define GT_INTR_CPUOUT 0x0000008 +#define GT_INTR_DMA0COMP 0x0000010 +#define GT_INTR_DMA1COMP 0x0000020 +#define GT_INTR_DMA2COMP 0x0000040 +#define GT_INTR_DMA3COMP 0x0000080 +#define GT_INTR_T0EXP 0x0000100 +#define GT_INTR_T1EXP 0x0000200 +#define GT_INTR_T2EXP 0x0000400 +#define GT_INTR_T3EXP 0x0000800 +#define GT_INTR_MASRDERR 0x0001000 +#define GT_INTR_SLVWRERR 0x0002000 +#define GT_INTR_MASWRERR 0x0004000 +#define GT_INTR_SLVRDERR 0x0008000 +#define GT_INTR_ADDRERR 0x0010000 +#define GT_INTR_MEMERR 0x0020000 +#define GT_INTR_MASABORT 0x0040000 +#define GT_INTR_TARABORT 0x0080000 +#define GT_INTR_RETRYCTR 0x0010000 +#define GT_INTR_CPU2PCIA 0x0020000 +#define GT_INTR_CPU2PCIB 0x0040000 +#define GT_INTR_CPU2PCIC 0x0080000 +#define GT_INTR_CPU2PCID 0x0100000 +#define GT_INTR_CPU2PCIE 0x0200000 +#define GT_INTR_PCI2CPUA 0x0400000 +#define GT_INTR_PCI2CPUB 0x0800000 +#define GT_INTR_PCI2CPUC 0x1000000 +#define GT_INTR_PCI2CPUD 0x2000000 +#define GT_INTR_CPUINTSUM 0x4000000 +#define GT_INTR_PCIINTSUM 0x8000000 +#define GT_IPCI_PCIINTMASK GT64011(0xc24) +#define GT_IPCI_SERMASK GT64011(0xc28) +#define GT_IPCI_SERMASK_AddrErr (1<<0) +#define GT_IPCI_SERMASK_MasWrErr (1<<1) +#define GT_IPCI_SERMASK_MasRdErr (1<<2) +#define GT_IPCI_SERMASK_MemErr (1<<3) +#define GT_IPCI_SERMASK_MasAbort (1<<4) +#define GT_IPCI_SERMASK_TarAbort (1<<5) +#define GT_IPCI_INTACK GT64011(0xc34) +#define GT_IPCI_BAREN GT64011(0xc3c) +#define GT_IPCI_BAREN_SwCs3BootDis (1<<0) +#define GT_IPCI_BAREN_SwRas32Dis (1<<1) +#define GT_IPCI_BAREN_SwRas10Dis (1<<2) +#define GT_IPCI_BAREN_IntIODis (1<<3) +#define GT_IPCI_BAREN_IntMemDis (1<<4) +#define GT_IPCI_BAREN_Cs3BootDis (1<<5) +#define GT_IPCI_BAREN_Cs20Dis (1<<6) +#define GT_IPCI_BAREN_Ras32Dis (1<<7) +#define GT_IPCI_BAREN_Ras10Dis (1<<8) +#define GT_IPCI_CFGADDR GT64011(0xcf8) +#define GT_IPCI_CFGDATA GT64011(0xcfc) +#define GT_IPCI_CFGADDR_RegNumMASK (0x3f<<2) +#define GT_IPCI_CFGADDR_RegNumSHIFT 2 +#define GT_IPCI_CFGADDR_RegNum(x) ((x)<<2) +#define GT_IPCI_CFGADDR_FunctNumMASK (0x7<<8) +#define GT_IPCI_CFGADDR_FunctNumSHIFT 8 +#define GT_IPCI_CFGADDR_FunctNum(x) ((x)<<8) +#define GT_IPCI_CFGADDR_DevNumMASK (0x1f<<11) +#define GT_IPCI_CFGADDR_DevNumSHIFT 11 +#define GT_IPCI_CFGADDR_DevNum(x) ((x)<<11) +#define GT_IPCI_CFGADDR_BusNumMASK (0xff<<16) +#define GT_IPCI_CFGADDR_BusNumSHIFT 16 +#define GT_IPCI_CFGADDR_BusNum(x) ((x)<<16) +#define GT_IPCI_CFGADDR_ConfigEn (1<<31) diff --git a/arch/mips/galileo-boards/ev64120/compressed/head.S b/arch/mips/galileo-boards/ev64120/compressed/head.S new file mode 100644 index 000000000..fcbe250e7 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/head.S @@ -0,0 +1,19 @@ +/* + * arch/mips/galileo/compressed/head.S + * + */ + +#include <asm/asm.h> +#include <asm/regdef.h> + + .text +NESTED(startup, 16, sp) + .set noreorder + + jal decompress_kernel + nop + + jal kernel_location_start+0x584 + nop + + END(startup) diff --git a/arch/mips/galileo-boards/ev64120/compressed/ld.script.gal b/arch/mips/galileo-boards/ev64120/compressed/ld.script.gal new file mode 100644 index 000000000..68eda2a7c --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/ld.script.gal @@ -0,0 +1,19 @@ +OUTPUT_FORMAT("elf32-bigmips") +OUTPUT_ARCH(mips) +ENTRY(startup) +SECTIONS +{ + kernel_location_start = 0x80100000; + . = 0x80400000; + .text : { + *(.text) + } + .bss : { + *(.bss) + } + .data :{ + *(.data) + } + malloc_start = .; +} + diff --git a/arch/mips/galileo-boards/ev64120/compressed/ld.sys.big.Flash b/arch/mips/galileo-boards/ev64120/compressed/ld.sys.big.Flash new file mode 100644 index 000000000..1eef527b1 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/ld.sys.big.Flash @@ -0,0 +1,29 @@ +OUTPUT_FORMAT("elf32-bigmips") +OUTPUT_ARCH(mips) +ENTRY(sbdreset) + +SECTIONS +{ + . = 0xBFC00000; + .got : {*(.got)} + .reset : { + sbdreset = ABSOLUTE(.); + sbdreset_evb64120A.o + evb64120A_Setup.o /* <-- Note: contains xfer.c contents as well.. */ + pci_etherboot.o + memory.o + pci.o + } + kernel_location_start = 0x80100000; + . = 0x80400000; + .text : { + *(.text) + } + .bss : { + *(.bss) + } + .data :{ + *(.data) + } + malloc_start = .; +} diff --git a/arch/mips/galileo-boards/ev64120/compressed/ld.sys.big.Flash2 b/arch/mips/galileo-boards/ev64120/compressed/ld.sys.big.Flash2 new file mode 100644 index 000000000..d017e5f24 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/ld.sys.big.Flash2 @@ -0,0 +1,24 @@ +OUTPUT_FORMAT("elf32-bigmips") +OUTPUT_ARCH(mips) +ENTRY(XferToRam) + +SECTIONS +{ + . = 0xBF000000; + .got : {*(.got)} + .reset : { + xfer.o + } + kernel_location_start = 0x80100000; + . = 0x80400000; + .text : { + *(.text) + } + .bss : { + *(.bss) + } + .data :{ + *(.data) + } + malloc_start = .; +} diff --git a/arch/mips/galileo-boards/ev64120/compressed/ld.sys.big.burner b/arch/mips/galileo-boards/ev64120/compressed/ld.sys.big.burner new file mode 100644 index 000000000..77ebe571c --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/ld.sys.big.burner @@ -0,0 +1,11 @@ +OUTPUT_FORMAT("elf32-bigmips") +OUTPUT_ARCH(mips) +ENTRY(main) + +SECTIONS +{ + . = 0xA0400000; + .text : {*(.text)} + .data : {*(.data)} + .bss : {*(.bss)} +} diff --git a/arch/mips/galileo-boards/ev64120/compressed/load.c b/arch/mips/galileo-boards/ev64120/compressed/load.c new file mode 100644 index 000000000..e05dcb901 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/load.c @@ -0,0 +1,244 @@ + +/* control character used for download */ +#define ETX CNTRL('c') +#define ACK CNTRL('f') +#define NAK CNTRL('u') +#define XON CNTRL('q') +#define XOFF CNTRL('s') + +unsigned int csum; +unsigned int dl_entry; + +static const unsigned char hextab[256] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, + 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, + 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, +}; + + +unsigned char ascii_to_bin(unsigned char c) +{ + return hextab[c]; +} + +unsigned char read_char_direct(void) +{ + unsigned char c, *cp; + cp = (unsigned char *) 0xbd000020; + while (1) { + if (*(cp + 0x14) & 0x01) { + c = (volatile unsigned char) *cp; + return c; + } + cp++; + cp--; + } +} + +unsigned char get_pair(void) +{ + unsigned char byte; + + byte = ascii_to_bin(read_char_direct()) << 4; + byte |= ascii_to_bin(read_char_direct()); + csum += byte; + return (byte); +} + + +void serial_putc(int ch) +{ + unsigned long temp; + for (temp = 0; temp < 1000; temp++) { + } + *(char *) 0xbd000020 = (char) ch; +} + + +int inline serial_getc(void) +{ + return read_char_direct(); +} + +int serial_ischar(void) +{ + + unsigned char c, *cp; + unsigned count; + cp = (unsigned char *) 0xbd000020; + count = 0; + while (count != 100) { + if (*(cp + 0x14) & 0x01) { + c = (volatile unsigned char) *cp; + return c; + } + cp++; + cp--; + count++; + } + return 0; +} + +int serial_init(void) +{ + return 0; +} + + +int galileo_dl(void) +{ +#define display_char '.' +#define display_error 'E' +#define display_error_bad_7 '7' +#define display_error_unknown 'U' +#define display_error_length 'L' + + register int length, address, save_csum; + int i, first, done, eof, reccount, type, client_pc; + int src, dbl_length; + unsigned char *buffptr, databuff[258], tempo; + register int display_counter, chunks, leftovers, putter, + bytes_per_chunk; + display_counter = 0; + bytes_per_chunk = 16; + csum = 0; + + reccount = 1; + for (first = 1, done = 0; !done; first = 0, reccount++) { + while (read_char_direct() != 'S') + continue; + csum = 0; + type = read_char_direct(); + length = get_pair(); + if (length < 0 || length >= 256) { + *(char *) 0xbd000020 = display_error_length; + // *(char*)0xbd00000c = display_error_length; + return 0; + } + length--; + switch (type) { + case '0': + while (length-- > 0) + get_pair(); + break; + case '3': + address = 0; + for (i = 0; i < 4; i++) { + address <<= 8; + address |= get_pair(); + length--; + } + if (address == -1) { + eof = 1; + continue; + } + buffptr = &databuff[0]; + dbl_length = length << 1; + chunks = dbl_length / bytes_per_chunk; + leftovers = dbl_length % bytes_per_chunk; + putter = bytes_per_chunk >> 1; + while (chunks--) { + for (i = 0; i < bytes_per_chunk; i++) + databuff[i] = read_char_direct(); + src = i = 0; + while (i++ < putter) { + tempo = + (ascii_to_bin(databuff[src++]) + << 4) | + ascii_to_bin(databuff[src++]); + csum += tempo; + *(char *) address++ = tempo; + } + } + if (leftovers) { + putter = leftovers / 2; + for (i = 0; i < leftovers; i++) + databuff[i] = read_char_direct(); + src = i = 0; + while (i++ < putter) { + tempo = + (ascii_to_bin(databuff[src++]) + << 4) | + ascii_to_bin(databuff[src++]); + csum += tempo; + *(char *) address++ = tempo; + } + } + break; + + case '7': + address = 0; + for (i = 0; i < 4; i++) { + address <<= 8; + address |= get_pair(); + length--; + } + if (address == -1) { + eof = 1; + continue; + } + client_pc = address; + if (length) { + *(char *) 0xbd000020 = display_error_bad_7; + // *(char*)0xbd00000c = display_error_bad_7; + } + + done = 1; + break; + + default: + *(char *) 0xbd000020 = display_error_unknown; + // *(char*)0xbd00000c = display_error_unknown; + + break; + } + save_csum = (~csum) & 0xff; + if ((csum = get_pair()) < 0) { + eof = 1; + continue; + } + if (csum != save_csum) { + *(char *) 0xbd000020 = display_error; + // *(char*)0xbd00000c = display_error; + } else { + + if (display_counter % 50 == 0) { + *(char *) 0xbd000020 = display_char; + display_counter = 0; + } + display_counter++; + + } + } + --reccount; + dl_entry = client_pc; + return dl_entry; /* Success */ +} diff --git a/arch/mips/galileo-boards/ev64120/compressed/meminit.S b/arch/mips/galileo-boards/ev64120/compressed/meminit.S new file mode 100644 index 000000000..aa72b2cf5 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/meminit.S @@ -0,0 +1,187 @@ +/* + * Define BUSWIDTH to usually be real buswidth X 2 (i.e assuming + * 2-way interleaving). This is so that the test pattern and + * inverted pattern are written to the same bank of memory, which + * prevents us reading back data sitting in the dram buffers and + * getting a false match. + */ + +#ifndef BUSWIDTH +# if #cpu(r3000) || #cpu(r4300) || #cpu(r4650) +# define BUSWIDTH 8 /* 32 bit memory, bank interleaved */ +# elif #cpu(r4000) +# define BUSWIDTH 16 /* 64 bit memory, bank interleaved */ +# endif +#endif + +#ifndef RAM_BASE +#define RAM_BASE KSEG1_BASE +#endif + +#ifndef MEMSTART +#define MEMSTART 0x0 /* start of physical memory */ +#endif + +#ifndef MEMINCR +# define MEMINCR 0x10000 /* work up in 64Kb increments */ +#endif + +SLEAF(size_mem) + mfc0 t8,C0_STATUS +#if #cpu(r4000) + /* disable cache and memory parity checking */ + or t0,t8,SR_DE + mtc0 t0,C0_STATUS +#endif + + li t0,RAM_BASE+MEMSTART # start at bottom of phys mem + move t1,t0 # remember start address + li t2,0xaa55aa55 # pattern + not t3,t2 # ~pattern + + move t7,k0 + la t4,.fail # bus error exception catcher + addu k0,t4,s8 # RELOC + + /* fill first 64Kb with zero (for cache init) */ + move t4,t0 + li t5,0x10000 +1: sw zero,0(t4) + sw zero,4(t4) + sw zero,8(t4) + sw zero,12(t4) + subu t5,16 + addu t4,16 + bnez t5,1b + +.loop: + addu t0,MEMINCR + move t4,t0 + + /* store pattern in bank 0, line 0 */ + sw t2,0(t4) + addu t4,4 + +#if BUSWIDTH > 4 + /* fill remainder of line with zeros */ + li t5,BUSWIDTH-4 +1: sw zero,0(t4) + subu t5,4 + addu t4,4 + bnez t5,1b +#endif + + /* store inverse pattern in bank 0, line 1 */ + sw t3,0(t4) + addu t4,4 + +#if BUSWIDTH > 4 + /* fill remainder of line with zeros */ + li t5,BUSWIDTH-4 +1: sw zero,0(t4) + subu t5,4 + addu t4,4 + bnez t5,1b +#endif + + /* defeat write buffering */ +#if #cpu(r4000) + sync +#else + lw zero,-4(t4) +#endif + + lw t4,0(t0) # read first word of line + lw t5,0(t1) # read start of memory (should be zero) + bne t4,t2,.fail # this line wrong? + beq t5,zero,.loop # start of mem overwritten? + +.fail: + move k0,t7 # clear exception catcher + + /* restore Status register */ + mtc0 t8,C0_STATUS + + /* return top of memory offset (normally == size) */ + subu v0,t0,RAM_BASE + j ra +END(size_mem) + + +/* + * We must often initialise memory so that it has good parity/ecc, + * and this must be done before the caches are used. + */ + +/* + clear_mem (size) + - clear memory from RAM_BASE+MEMSTART to RAM_BASE+MEMSTART+size + clear_mem_range (size, start) + - clear memory from start to start+size +*/ + +SLEAF(clear_mem) + li a1,RAM_BASE+MEMSTART # start at bottom of phys mem +clear_mem_range: + beqz a0,9f + addu a0,a1 # end of memory + + /* XXX should run cached, but caches may not be initialised yet */ + .set noreorder +#if __mips >= 3 +1: sd zero,0(a1) + sd zero,8(a1) + sd zero,16(a1) + sd zero,24(a1) + sd zero,32(a1) + sd zero,40(a1) + sd zero,48(a1) + addu a1,64 + bne a1,a0,1b + sd zero,-8(a1) # BDSLOT +#else +1: sw zero,0(a1) + sw zero,4(a1) + sw zero,8(a1) + sw zero,12(a1) + sw zero,16(a1) + sw zero,20(a1) + sw zero,24(a1) + sw zero,28(a1) + sw zero,32(a1) + sw zero,36(a1) + sw zero,40(a1) + sw zero,44(a1) + sw zero,48(a1) + sw zero,52(a1) + sw zero,56(a1) + addu a1,64 + bne a1,a0,1b + sw zero,-4(a1) # BDSLOT +#endif + .set reorder + +9: j ra +END(clear_mem) + + +SLEAF(init_tlb) + /* initialise tlb */ + mtc0 zero,C0_TLBLO0 /* tlblo0 = invalid */ + mtc0 zero,C0_TLBLO1 /* tlblo1 = invalid */ + mtc0 zero,C0_PGMASK + li t8,K1BASE /* tlbhi = impossible vpn */ + li t9,(NTLBENTRIES-1) /* index */ + + .set noreorder + nop +1: mtc0 t8,C0_TLBHI + mtc0 t9,C0_INX + addu t8,0x2000 /* inc vpn */ + tlbwi + bnez t9,1b + subu t9,1 # BDSLOT + .set reorder + + j ra +END(init_tlb) diff --git a/arch/mips/galileo-boards/ev64120/compressed/memory.c b/arch/mips/galileo-boards/ev64120/compressed/memory.c new file mode 100644 index 000000000..e88985cb9 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/memory.c @@ -0,0 +1,593 @@ +/* Memory.c - Memory mappings and remapping functions */ + +/* Copyright - Galileo technology. */ + +/* +DESCRIPTION +This file contains function which gives the user the ability to remap the +SDRAM memory and devices windows, please pay attention to overlapping windows +since the function do not take care of that for you. +When remapping the SDRAM or devices memory space pay attention to the PCI +mappings and make sure to coordinate between the two interfaces!!! +*/ + +/* includes */ + +#ifdef __linux__ +#include <asm/galileo-boards/evb64120A/core.h> +#include <asm/galileo-boards/evb64120A/memory.h> +#else +#include "Core.h" +#include "Memory.h" +#endif + +/******************************************************************** +* getMemoryBankBaseAddress - Extract the base address of a memory bank +* - If the memory bank size is 0 then this base address has no meaning !!! +* +* INPUTS: MEMORY_BANK bank - SDRAM Bank number. +* OUTPUT: N/A +* RETURNS: Memory bank base address. +*********************************************************************/ +unsigned int getMemoryBankBaseAddress(MEMORY_BANK bank) +{ + unsigned int base, regBase; + GT_REG_READ((SCS_1_0_LOW_DECODE_ADDRESS + (bank / 2) * 0x10), + &base); + base = base << 21; + GT_REG_READ((SCS_0_LOW_DECODE_ADDRESS + bank * 8), ®Base); + base = base | (regBase << 20); + return base; +} + +/******************************************************************** +* getDeviceBaseAddress - Extract the base address of a device. +* - If the device size is 0 then this base address has no meaning!!! +* +* INPUT: DEVICE device - Bank number. +* OUTPUT: N/A +* RETURNS: Device base address. +*********************************************************************/ +unsigned int getDeviceBaseAddress(DEVICE device) +{ + unsigned int base, regBase; + GT_REG_READ((CS_2_0_LOW_DECODE_ADDRESS + (device / 3) * 0x10), + &base); + base = base << 21; + GT_REG_READ((CS_0_LOW_DECODE_ADDRESS + device * 0x8), ®Base); + base = base | (regBase << 20); + return base; +} + +/******************************************************************** +* getMemoryBankSize - Extract the size of a memory bank. +* +* INPUT: MEMORY_BANK bank - Bank number +* OUTPUT: N/A +* RETURNS: Memory bank size. +*********************************************************************/ +unsigned int getMemoryBankSize(MEMORY_BANK bank) +{ + unsigned int size, base, value; + base = getMemoryBankBaseAddress(bank); + GT_REG_READ((SCS_0_HIGH_DECODE_ADDRESS + bank * 8), &size); + size = ((size + 1) << 20) - (base & 0x0fffffff); + GT_REG_READ((SCS_0_HIGH_DECODE_ADDRESS + bank * 8), &value); + if (value == 0) + return 0; + else + return size; +} + +/******************************************************************** +* getDeviceSize - Extract the size of a device memory space +* +* INPUT: DEVICE device - Device number +* OUTPUT: N/A +* RETURNS: Size of a device memory space. +*********************************************************************/ +unsigned int getDeviceSize(DEVICE device) +{ + unsigned int size, base, value; + base = getDeviceBaseAddress(device); + GT_REG_READ((CS_0_HIGH_DECODE_ADDRESS + device * 8), &size); + size = ((size + 1) << 20) - (base & 0x0fffffff); + GT_REG_READ((CS_0_HIGH_DECODE_ADDRESS + device * 8), &value); + if ((value + 1) == 0) + return 0; + else + return size; +} + +/******************************************************************** +* getDeviceWidth - A device can be with: 1,2,4 or 8 Bytes data width. +* The width is determine in registers: 'Device Parameters' +* registers (0x45c, 0x460, 0x464, 0x468, 0x46c - for each device. +* at bits: [21:20]. +* +* INPUT: DEVICE device - Device number +* OUTPUT: N/A +* RETURNS: Device width in Bytes (1,2,4, or 8), 0 if error had occurred. +*********************************************************************/ +unsigned int getDeviceWidth(DEVICE device) +{ + unsigned int width; + unsigned int regValue; + + GT_REG_READ(DEVICE_BANK0PARAMETERS + device * 4, ®Value); + width = (regValue & 0x00300000) >> 20; + switch (width) { + case 0: + return 1; + case 1: + return 2; + case 2: + return 4; + case 3: + return 8; + default: + return 0; + } +} + +/******************************************************************** +* mapMemoryBanks0and1 - Sets new bases and boundaries for memory banks 0 and 1 +* - Pay attention to the PCI mappings and make sure to +* coordinate between the two interfaces!!! +* - It is the programmer`s responsibility to make sure +* there are no conflicts with other memory spaces!!! +* - If a bank needs to be closed , give it a 0 length +* +* +* INPUTS: unsigned int bank0Base - required bank 0 base address. +* unsigned int bank0Length - required bank 0 size. +* unsigned int bank1Base - required bank 1 base address. +* unsigned int bank1Length - required bank 1 size. +* RETURNS: true on success, false on failure or if one of the parameters is +* erroneous. +*********************************************************************/ +bool mapMemoryBanks0and1(unsigned int bank0Base, unsigned int bank0Length, + unsigned int bank1Base, unsigned int bank1Length) +{ + unsigned int mainBank0Top = bank0Base + bank0Length; + unsigned int mainBank1Top = bank1Base + bank1Length; + unsigned int memBank0Base, bank0Top; + unsigned int memBank1Base, bank1Top; + + if (bank0Base <= bank1Base) { + if ((bank0Base + bank0Length) > bank1Base) + return false; + } else { + if ((bank1Base + bank1Length) > bank0Base) + return false; + } + + if (bank0Length == 0) + mainBank0Top++; + if (bank1Length == 0) + mainBank1Top++; + + memBank0Base = ((unsigned int) (bank0Base & 0x0fffffff)) >> 20; + bank0Top = ((unsigned int) (mainBank0Top & 0x0fffffff)) >> 20; + memBank1Base = ((unsigned int) (bank1Base & 0x0fffffff)) >> 20; + bank1Top = ((unsigned int) (mainBank1Top & 0x0fffffff)) >> 20; + + if (mainBank1Top > mainBank0Top) { + bank0Base >>= 21; + mainBank0Top = + ((unsigned int) (mainBank1Top & 0x0fffffff)) >> 21; + } else { + bank0Base = bank1Base >> 21; + mainBank0Top = + ((unsigned int) (mainBank0Top & 0x0fffffff)) >> 21; + } + GT_REG_WRITE(SCS_1_0_LOW_DECODE_ADDRESS, bank0Base); + if ((bank0Length + bank1Length) != 0) { + GT_REG_WRITE(SCS_1_0_HIGH_DECODE_ADDRESS, + mainBank0Top - 1); + } else { + GT_REG_WRITE(SCS_1_0_HIGH_DECODE_ADDRESS, 0x0); + } + if (bank1Length != 0) { + GT_REG_WRITE(SCS_1_HIGH_DECODE_ADDRESS, bank1Top - 1); + } else { + GT_REG_WRITE(SCS_1_HIGH_DECODE_ADDRESS, 0x0); + } + GT_REG_WRITE(SCS_1_LOW_DECODE_ADDRESS, memBank1Base); + if (bank0Length != 0) { + GT_REG_WRITE(SCS_0_HIGH_DECODE_ADDRESS, bank0Top - 1); + } else { + GT_REG_WRITE(SCS_0_HIGH_DECODE_ADDRESS, 0x0); + } + GT_REG_WRITE(SCS_0_LOW_DECODE_ADDRESS, memBank0Base); + return true; +} + +/******************************************************************** +* mapMemoryBanks2and3 - Sets new bases and boundaries for memory banks 2 and 3 +* - Pay attention to the PCI mappings and make sure to +* coordinate between the two interfaces!!! +* - It`s the programmer`s responsibility to make sure there +* are no conflicts with other memory spaces!!! +* - If a bank needs to be closed , give it a 0 length. +* +* +* INPUTS: unsigned int bank2Base - required bank 2 base address. +* unsigned int bank2Length - required bank 2 size. +* unsigned int bank3Base - required bank 3 base address. +* unsigned int bank3Length - required bank 3 size. +* RETURNS: true on success, false on failure or if one of the parameters is +* erroneous. +*********************************************************************/ +bool mapMemoryBanks2and3(unsigned int bank2Base, unsigned int bank2Length, + unsigned int bank3Base, unsigned int bank3Length) +{ + unsigned int mainBank2Top = + (unsigned int) (bank2Base + bank2Length); + unsigned int mainBank3Top = + (unsigned int) (bank3Base + bank3Length); + unsigned int memBank2Base, bank2Top; + unsigned int memBank3Base, bank3Top; + + if (bank2Base <= bank3Base) { + if ((bank2Base + bank2Length) > bank3Base) + return false; + } else { + if ((bank3Base + bank3Length) > bank2Base) + return false; + } + if (bank2Length == 0) + mainBank2Top++; + if (bank3Length == 0) + mainBank3Top++; + + memBank2Base = ((unsigned int) (bank2Base & 0x0fffffff)) >> 20; + bank2Top = ((unsigned int) (mainBank2Top & 0x0fffffff)) >> 20; + memBank3Base = ((unsigned int) (bank3Base & 0x0fffffff)) >> 20; + bank3Top = ((unsigned int) (mainBank3Top & 0x0fffffff)) >> 20; + + if (mainBank3Top > mainBank2Top) { + bank2Base >>= 21; + mainBank2Top = + ((unsigned int) (mainBank3Top & 0x0fffffff)) >> 21; + } else { + bank2Base = bank3Base >> 21; + mainBank2Top = + ((unsigned int) (mainBank2Top & 0x0fffffff)) >> 21; + } + GT_REG_WRITE(SCS_3_2_LOW_DECODE_ADDRESS, bank2Base); + if ((bank2Length + bank3Length) != 0) { + GT_REG_WRITE(SCS_3_2_HIGH_DECODE_ADDRESS, + mainBank2Top - 1); + } else { + GT_REG_WRITE(SCS_3_2_HIGH_DECODE_ADDRESS, 0x0); + } + if (bank3Length != 0) { + GT_REG_WRITE(SCS_3_HIGH_DECODE_ADDRESS, bank3Top - 1); + } else { + GT_REG_WRITE(SCS_3_HIGH_DECODE_ADDRESS, 0x0); + } + GT_REG_WRITE(SCS_3_LOW_DECODE_ADDRESS, memBank3Base); + if (bank2Length != 0) { + GT_REG_WRITE(SCS_2_HIGH_DECODE_ADDRESS, bank2Top - 1); + } else { + GT_REG_WRITE(SCS_2_HIGH_DECODE_ADDRESS, 0x0); + } + GT_REG_WRITE(SCS_2_LOW_DECODE_ADDRESS, memBank2Base); + return true; +} + +/******************************************************************** +* mapDevices0_1and2MemorySpace - Sets new bases and boundaries for devices 0,1 +* and 2 +* - Pay attention to the PCI mappings and make sure to +* coordinate between the two interfaces!!! +* - It`s the programmer`s responsibility to make sure there +* are no conflicts with other memory spaces!!! +* - If a device needs to be closed , give it a 0 length +* +* +* INPUTS: unsigned int device0Base - required cs_0 base address. +* unsigned int device0Length - required cs_0 size. +* unsigned int device1Base - required cs_1 base address. +* unsigned int device1Length - required cs_0 size. +* unsigned int device2Base - required cs_2 base address. +* unsigned int device2Length - required cs_2 size. +* RETURNS: true on success, false on failure or if one of the parameters is +* erroneous. +*********************************************************************/ +bool mapDevices0_1and2MemorySpace(unsigned int device0Base, + unsigned int device0Length, + unsigned int device1Base, + unsigned int device1Length, + unsigned int device2Base, + unsigned int device2Length) +{ + unsigned int deviceBank0Top = + (unsigned int) (device0Base + device0Length); + unsigned int deviceBank1Top = + (unsigned int) (device1Base + device1Length); + unsigned int deviceBank2Top = + (unsigned int) (device2Base + device2Length); + unsigned int device0BaseTemp = 0, device0TopTemp = 0; + unsigned int bank0Base, bank0Top; + unsigned int bank1Base, bank1Top; + unsigned int bank2Base, bank2Top; + bank0Base = ((unsigned int) (device0Base & 0x0fffffff)) >> 20; + bank0Top = ((unsigned int) (deviceBank0Top & 0x0fffffff)) >> 20; + bank1Base = ((unsigned int) (device1Base & 0x0fffffff)) >> 20; + bank1Top = ((unsigned int) (deviceBank1Top & 0x0fffffff)) >> 20; + bank2Base = ((unsigned int) (device2Base & 0x0fffffff)) >> 20; + bank2Top = ((unsigned int) (deviceBank2Top & 0x0fffffff)) >> 20; + + if (device0Length == 0) + deviceBank0Top++; + if (device1Length == 0) + deviceBank1Top++; + if (device2Length == 0) + deviceBank2Top++; + + if (device0Base <= device1Base && device0Base <= device2Base) { + if ((device0Base + device0Length) > device1Base || \ + (device0Base + device0Length) > device2Base) + return false; + if (device1Base <= device2Base) { + if ((device1Base + device1Length) > device2Base) + return false; + } else { + if ((device2Base + device2Length) > device1Base) + return false; + } + } + + if (device1Base <= device0Base && device1Base <= device2Base) { + if ((device1Base + device1Length) > device0Base || + (device1Base + device1Length) > device2Base) + return false; + if (device0Base <= device2Base) { + if ((device0Base + device0Length) > device2Base) + return false; + } else { + if ((device2Base + device2Length) > device0Base) + return false; + } + } + + if (device2Base <= device1Base && device2Base <= device0Base) { + if ((device2Base + device2Length) > device1Base || + (device2Base + device2Length) > device0Base) + return false; + if (device0Base <= device1Base) { + if ((device0Base + device0Length) > device1Base) + return false; + } else { + if ((device1Base + device1Length) > device0Base) + return false; + } + } + + if ((deviceBank2Top > deviceBank1Top) && (deviceBank1Top > + deviceBank0Top)) { + device0BaseTemp = device0Base >> 21; + device0TopTemp = + ((unsigned int) (deviceBank2Top & 0x0fffffff)) >> 21; + } + if ((deviceBank2Top > deviceBank0Top) + && (deviceBank0Top > deviceBank1Top)) { + device0BaseTemp = device1Base >> 21; + device0TopTemp = + ((unsigned int) (deviceBank2Top & 0x0fffffff)) >> 21; + } + if ((deviceBank1Top > deviceBank2Top) + && (deviceBank2Top > deviceBank0Top)) { + device0BaseTemp = device0Base >> 21; + device0TopTemp = + ((unsigned int) (deviceBank1Top & 0x0fffffff)) >> 21; + } + if ((deviceBank1Top > deviceBank0Top) + && (deviceBank0Top > deviceBank2Top)) { + device0BaseTemp = device2Base >> 21; + device0TopTemp = + ((unsigned int) (deviceBank1Top & 0x0fffffff)) >> 21; + } + if ((deviceBank0Top > deviceBank2Top) + && (deviceBank2Top > deviceBank1Top)) { + device0BaseTemp = device1Base >> 21; + device0TopTemp = + ((unsigned int) (deviceBank0Top & 0x0fffffff)) >> 21; + } + if ((deviceBank0Top > deviceBank1Top) + && (deviceBank1Top > deviceBank2Top)) { + device0BaseTemp = device2Base >> 21; + device0TopTemp = + ((unsigned int) (deviceBank0Top & 0x0fffffff)) >> 21; + } + GT_REG_WRITE(CS_2_0_LOW_DECODE_ADDRESS, device0BaseTemp); + if ((device0Length + device1Length + device2Length) != 0) { + GT_REG_WRITE(CS_2_0_HIGH_DECODE_ADDRESS, + device0TopTemp - 1); + } else { + GT_REG_WRITE(CS_2_0_HIGH_DECODE_ADDRESS, 0x0); + } + GT_REG_WRITE(CS_0_LOW_DECODE_ADDRESS, bank0Base); + if (device0Length != 0) { + GT_REG_WRITE(CS_0_HIGH_DECODE_ADDRESS, bank0Top - 1); + } else { + GT_REG_WRITE(CS_0_HIGH_DECODE_ADDRESS, 0x0); + } + GT_REG_WRITE(CS_1_LOW_DECODE_ADDRESS, bank1Base); + if (device1Length != 0) { + GT_REG_WRITE(CS_1_HIGH_DECODE_ADDRESS, bank1Top - 1); + } else { + GT_REG_WRITE(CS_1_HIGH_DECODE_ADDRESS, 0x0); + } + GT_REG_WRITE(CS_2_LOW_DECODE_ADDRESS, bank2Base); + if (device2Length != 0) { + GT_REG_WRITE(CS_2_HIGH_DECODE_ADDRESS, bank2Top - 1); + } else { + GT_REG_WRITE(CS_2_HIGH_DECODE_ADDRESS, 0x0); + } + return true; +} + +/******************************************************************** +* mapDevices3andBootMemorySpace - Sets new bases and boundaries for devices: +* 3 and boot +* - Pay attention to the PCI mappings and make sure to +* coordinate between the two interfaces!!! +* - It is the programmer`s responsibility to make sure +* there are no conflicts with other memory spaces!!! +* - If a device needs to be closed , give it a 0 length. +* +* INPUTS: base and length of device 3and boot +* RETURNS: true on success, false on failure +*********************************************************************/ +bool mapDevices3andBootMemorySpace(unsigned int device3Base, + unsigned int device3Length, + unsigned int bootDeviceBase, + unsigned int bootDeviceLength) +{ + unsigned int deviceBank3Top = + (unsigned int) (device3Base + device3Length); + unsigned int deviceBankBootTop = + (unsigned int) (bootDeviceBase + bootDeviceLength); + unsigned int bank3Base, bank3Top; + unsigned int bank4Base, bank4Top; + unsigned int Device1Base, Device1Top; + + bank3Top = ((unsigned int) (deviceBank3Top & 0x0fffffff)) >> 20; + bank4Top = ((unsigned int) (deviceBankBootTop & 0x0fffffff)) >> 20; + bank3Base = ((unsigned int) (device3Base & 0x0fffffff)) >> 20; + bank4Base = ((unsigned int) (bootDeviceBase & 0x0fffffff)) >> 20; + + if (device3Base <= bootDeviceBase) { + if (deviceBank3Top > bootDeviceBase) + return false; + } else { + if (deviceBankBootTop > device3Base) + return false; + } + + if (deviceBankBootTop > deviceBank3Top) { + Device1Base = device3Base >> 21; + Device1Top = + ((unsigned int) (deviceBankBootTop & 0x0fffffff)) >> + 21; + } else { + Device1Base = bootDeviceBase >> 21; + Device1Top = + ((unsigned int) (deviceBank3Top & 0x0fffffff)) >> 21; + } + GT_REG_WRITE(CS_3_BOOTCS_LOW_DECODE_ADDRESS, Device1Base); + if ((device3Length + bootDeviceLength) != 0) { + GT_REG_WRITE(CS_3_BOOTCS_HIGH_DECODE_ADDRESS, + Device1Top - 1); + } else { + GT_REG_WRITE(CS_3_BOOTCS_HIGH_DECODE_ADDRESS, 0x0); + } + GT_REG_WRITE(CS_3_LOW_DECODE_ADDRESS, bank3Base); + if (device3Length != 0) { + GT_REG_WRITE(CS_3_HIGH_DECODE_ADDRESS, bank3Top - 1); + } else { + GT_REG_WRITE(CS_3_HIGH_DECODE_ADDRESS, 0x0); + } + GT_REG_WRITE(BOOTCS_LOW_DECODE_ADDRESS, bank4Base); + if (bootDeviceLength != 0) { + GT_REG_WRITE(BOOTCS_HIGH_DECODE_ADDRESS, bank4Top - 1); + } else { + GT_REG_WRITE(BOOTCS_HIGH_DECODE_ADDRESS, 0x0); + } + return true; +} + +/******************************************************************** +* modifyDeviceParameters - This function can be used to modify a device`s +* parameters. +* - Be advised to check the spec before modifying them. +* Inputs: +* Returns: false if one of the parameters is erroneous,true otherwise. +*********************************************************************/ +bool modifyDeviceParameters(DEVICE device, unsigned int turnOff, + unsigned int accToFirst, + unsigned int accToNext, unsigned int aleToWr, + unsigned int wrActive, unsigned int wrHigh, + unsigned int width, bool paritySupport) +{ + unsigned int data, oldValue; + + if ((turnOff > 0x7 && turnOff != DONT_MODIFY) + || (accToFirst > 0xf && accToFirst != DONT_MODIFY) + || (accToNext > 0xf && accToNext != DONT_MODIFY) + || (aleToWr > 0x7 && aleToWr != DONT_MODIFY) + || (wrActive > 0x7 && wrActive != DONT_MODIFY) + || (wrHigh > 0x7 && wrHigh != DONT_MODIFY)) { + return false; + } + + GT_REG_READ((DEVICE_BANK0PARAMETERS + device * 4), &oldValue); + if (turnOff == DONT_MODIFY) + turnOff = oldValue & 0x00000007; + else + turnOff = turnOff; + + if (accToFirst == DONT_MODIFY) + accToFirst = oldValue & 0x00000078; + else + accToFirst = accToFirst << 3; + + if (accToNext == DONT_MODIFY) + accToNext = oldValue & 0x00000780; + else + accToNext = accToNext << 7; + + if (aleToWr == DONT_MODIFY) + aleToWr = oldValue & 0x00003800; + else + aleToWr = aleToWr << 11; + + if (wrActive == DONT_MODIFY) + wrActive = oldValue & 0x0001c000; + else + wrActive = wrActive << 14; + + if (wrHigh == DONT_MODIFY) + wrHigh = oldValue & 0x000e0000; + else + wrHigh = wrHigh << 17; + + data = + turnOff | accToFirst | accToNext | aleToWr | wrActive | wrHigh; + switch (width) { + case _8BIT: + break; + case _16BIT: + data = data | _16BIT; + break; + case _32BIT: + data = data | _32BIT; + break; + case _64BIT: + data = data | _64BIT; + break; + default: + return false; + } + if (paritySupport == true) + data = data | PARITY_SUPPORT; + GT_REG_WRITE(DEVICE_BANK0PARAMETERS + device * 4, data); + return true; +} + +/******************************************************************** +* remapAddress - This fubction used for address remapping +* Inputs: - regOffset: remap register +* remapHeader : remapped address +* Returns: false if one of the parameters is erroneous,true otherwise. +*********************************************************************/ +bool remapAddress(unsigned int remapReg, unsigned int remapValue) +{ + unsigned int valueForReg; + valueForReg = (remapValue & 0xffe00000) >> 21; + GT_REG_WRITE(remapReg, valueForReg); + return true; +} diff --git a/arch/mips/galileo-boards/ev64120/compressed/misc.c b/arch/mips/galileo-boards/ev64120/compressed/misc.c new file mode 100644 index 000000000..b8f20a000 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/misc.c @@ -0,0 +1,313 @@ +/* + * arch/mips/galileo/misc.c + * + * This is a collection of several routines from gzip-1.0.3 + * adapted for Linux. + * + * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 + * puts by Nick Holloway 1993, better puts by Martin Mares 1995 + * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 + * + * Modified by RidgeRun Inc. + */ + +#include <linux/vmalloc.h> +#include <asm/io.h> +/* + * gzip declarations + */ + +#define OF(args) args +#define STATIC static + +#define channel 1 + +#undef memset +#undef memcpy +#define memzero(s, n) memset ((s), 0, (n)) + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +#define WSIZE 0x8000 /* Window size must be at least 32k, */ + /* and a power of two */ + +static uch *inbuf; /* input buffer */ +static uch window[WSIZE]; /* Sliding window buffer */ + +static unsigned insize = 0; /* valid bytes in inbuf */ +static unsigned inptr = 0; /* index of next byte to be processed in inbuf */ +static unsigned outcnt = 0; /* bytes in output buffer */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +#define RESERVED 0xC0 /* bit 6,7: reserved */ + +void variable_init(); +static void puts(const char *); + +void int2hex(int i) +{ + int tth, th, h, t, d; + + if (i > 99999) { + serial_putc(channel, "Error - int2hex outofbounds"); + return; + } + + tth = (i) / 10000; + th = (i - (tth * 10000)) / 1000; + h = (i - ((tth * 10000) + (th * 1000))) / 100; + t = (i - ((tth * 10000) + (th * 1000) + (h * 100))) / 10; + d = (i - ((tth * 10000) + (th * 1000) + (h * 100) + (t * 10))); + serial_putc(channel, tth + '0'); + serial_putc(channel, th + '0'); + serial_putc(channel, h + '0'); + serial_putc(channel, t + '0'); + serial_putc(channel, d + '0'); +} + +int checksum; +int byte_count; +static unsigned char *input_data; + +static int printCnt = 0; + +int get_byte() +{ + unsigned char c = (inptr < insize ? inbuf[inptr++] : fill_inbuf()); + byte_count++; + checksum += c; + + // if (printCnt++ < 150) + // { + // puts("\n"); + // puts("byte count = "); + // int2hex(byte_count & 0xff); + // puts(" byte val = "); + // int2hex(c); + // puts(" checksum = "); + // int2hex(checksum & 0xff); + // puts("\n"); + // } + return c; +} + +/* Diagnostic functions */ +#ifdef DEBUG +# define Assert(cond,msg) {if(!(cond)) error(msg);} +# define Trace(x) fprintf x +# define Tracev(x) {if (verbose) fprintf x ;} +# define Tracevv(x) {if (verbose>1) fprintf x ;} +# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} +# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +static int fill_inbuf(void); +static void flush_window(void); +static void error(char *m); +static void gzip_mark(void **); +static void gzip_release(void **); + +/* + * This is set up by the setup-routine at boot-time + */ + + +#define STACK_SIZE (4096) +long user_stack[STACK_SIZE]; +long *stack_start = &user_stack[STACK_SIZE]; + +extern int linux_compressed_start; +extern int linux_compressed_size; +extern int malloc_start; + +static int input_len; + +static long bytes_out = 0; +extern int kernel_location_start; +static uch *output_data; +static unsigned long output_ptr = 0; + + +static void *malloc(int size); +static void free(void *where); +static void error(char *m); +static void gzip_mark(void **); +static void gzip_release(void **); + +static unsigned long free_mem_ptr; +static unsigned long free_mem_end_ptr; + +#include "../../../../../lib/inflate.c" + +static void *malloc(int size) +{ + void *p; + + if (size < 0) + error("Malloc error\n"); + // if (free_mem_ptr <= 0) error("Memory error\n"); + + free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ + + p = (void *) free_mem_ptr; + free_mem_ptr += size; + + if (free_mem_ptr >= free_mem_end_ptr) + error("\nOut of memory\n"); + + return p; +} + +static void free(void *where) +{ /* Don't care */ +} + +static void gzip_mark(void **ptr) +{ + *ptr = (void *) free_mem_ptr; +} + +static void gzip_release(void **ptr) +{ + free_mem_ptr = (long) *ptr; +} + +static void puts(const char *s) +{ + while (*s) { + if (*s == 10) + serial_putc(channel, 13); + serial_putc(channel, *s++); + } +} + +void *memset(void *s, int c, size_t n) +{ + int i; + char *ss = (char *) s; + + for (i = 0; i < n; i++) + ss[i] = c; + return s; +} + +void *memcpy(void *__dest, __const void *__src, size_t __n) +{ + int i; + char *d = (char *) __dest, *s = (char *) __src; + + for (i = 0; i < __n; i++) + d[i] = s[i]; + return __dest; +} + +/* =========================================================================== + * Fill the input buffer. This is called only when the buffer is empty + * and at least one byte is really needed. + */ +static int fill_inbuf(void) +{ + if (insize != 0) { + error("ran out of input data\n"); + } + + inbuf = input_data; + insize = input_len; + inptr = 1; + return inbuf[0]; +} + +/* =========================================================================== + * Write the output window window[0..outcnt-1] and update crc and bytes_out. + * (Used for the decompressed data only.) + */ +static void flush_window(void) +{ + ulg c = crc; /* temporary variable */ + unsigned n; + uch *in, *out, ch; + + in = window; + out = &output_data[output_ptr]; + for (n = 0; n < outcnt; n++) { + ch = *out++ = *in++; + c = crc_32_tab[((int) c ^ ch) & 0xff] ^ (c >> 8); + } + crc = c; + bytes_out += (ulg) outcnt; + output_ptr += (ulg) outcnt; + outcnt = 0; +} + +check_mem() +{ + int i; + + puts("\ncplens = "); + for (i = 0; i < 10; i++) { + int2hex(cplens[i]); + puts(" "); + } + puts("\ncplext = "); + for (i = 0; i < 10; i++) { + int2hex(cplext[i]); + puts(" "); + } + puts("\nborder = "); + for (i = 0; i < 10; i++) { + int2hex(border[i]); + puts(" "); + } + puts("\n"); +} + +static void error(char *x) +{ + check_mem(); + puts("\n\n"); + puts(x); + puts("byte_count = "); + int2hex(byte_count); + puts("\n"); + puts("\n\n -- System halted"); + while (1); /* Halt */ +} + +void variable_init() +{ + byte_count = 0; + checksum = 0; + input_data = (unsigned char *) &linux_compressed_start; + input_len = linux_compressed_size; + output_data = &kernel_location_start; + free_mem_ptr = (long) &malloc_start; + free_mem_end_ptr = (long) ((char *) &malloc_start + 0x400000); +} + +int decompress_kernel() +{ + //check_mem(); + + variable_init(); + + makecrc(); + puts("Uncompressing Linux... \n"); + gunzip(); // ...see inflate.c + puts("Ok, booting the kernel.\n"); + return 0; +} diff --git a/arch/mips/galileo-boards/ev64120/compressed/ns16550.h b/arch/mips/galileo-boards/ev64120/compressed/ns16550.h new file mode 100644 index 000000000..c10d8f6e6 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/ns16550.h @@ -0,0 +1,126 @@ +/* NS16550 UART registers */ + +#ifndef NS16550H +#define NS16550H + +#define UART_BASE 0xbd000000 +#define NS16550_CHANA PHYS_TO_K1(UART_BASE + 0x20) +#define NS16550_CHANB PHYS_TO_K1(UART_BASE) + +#ifndef NS16550_HZ +#define NS16550_HZ 3686400 +#endif + +#ifdef __ASSEMBLER__ + +#ifndef NSREG +#define NSREG(x) ((x)*4) +#endif + +#define DATA NSREG(0) /* data register (R/W) */ +#define IER NSREG(1) /* interrupt enable (W) */ +#define IIR NSREG(2) /* interrupt identification (R) */ +#define FIFO IIR /* 16550 fifo control (W) */ +#define CFCR NSREG(3) /* line control register (R/W) */ +#define MCR NSREG(4) /* modem control register (R/W) */ +#define LSR NSREG(5) /* line status register (R/W) */ +#define MSR NSREG(6) /* modem status register (R/W) */ +#define SCR NSREG(7) /* scratch register (R/W) */ + +#else + +#ifndef nsreg +#if #endian(little) +#define nsreg(x) unsigned :24; unsigned char x; +#else +/*#define nsreg(x) unsigned char x; unsigned :24;*/ +#define nsreg(x) unsigned int x:8;unsigned int :24; +#endif +#endif + +typedef struct { + nsreg(data); /* data register (R/W) */ + nsreg(ier); /* interrupt enable (W) */ + nsreg(iir); /* interrupt identification (R) */ +#define fifo iir /* 16550 fifo control (W) */ + nsreg(cfcr); /* line control register (R/W) */ + nsreg(mcr); /* modem control register (R/W) */ + nsreg(lsr); /* line status register (R/W) */ + nsreg(msr); /* modem status register (R/W) */ + nsreg(scr); /* scratch register (R/W) */ +} ns16550dev; +#endif + + +/* 16 bit baud rate divisor (lower byte in dca_data, upper in dca_ier) */ +#define BRTC(x) (NS16550_HZ / (16*(x))) + +/* interrupt enable register */ +#define IER_ERXRDY 0x1 /* int on rx ready */ +#define IER_ETXRDY 0x2 /* int on tx ready */ +#define IER_ERLS 0x4 /* int on line status change */ +#define IER_EMSC 0x8 /* int on modem status change */ + +/* interrupt identification register */ +#define IIR_IMASK 0xf /* mask */ +#define IIR_RXTOUT 0xc /* receive timeout */ +#define IIR_RLS 0x6 /* receive line status */ +#define IIR_RXRDY 0x4 /* receive ready */ +#define IIR_TXRDY 0x2 /* transmit ready */ +#define IIR_NOPEND 0x1 /* nothing */ +#define IIR_MLSC 0x0 /* modem status */ +#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */ + +/* fifo control register */ +#define FIFO_ENABLE 0x01 /* enable fifo */ +#define FIFO_RCV_RST 0x02 /* reset receive fifo */ +#define FIFO_XMT_RST 0x04 /* reset transmit fifo */ +#define FIFO_DMA_MODE 0x08 /* enable dma mode */ +#define FIFO_TRIGGER_1 0x00 /* trigger at 1 char */ +#define FIFO_TRIGGER_4 0x40 /* trigger at 4 chars */ +#define FIFO_TRIGGER_8 0x80 /* trigger at 8 chars */ +#define FIFO_TRIGGER_14 0xc0 /* trigger at 14 chars */ + +/* character format control register */ +#define CFCR_DLAB 0x80 /* divisor latch */ +#define CFCR_SBREAK 0x40 /* send break */ +#define CFCR_PZERO 0x30 /* zero parity */ +#define CFCR_PONE 0x20 /* one parity */ +#define CFCR_PEVEN 0x10 /* even parity */ +#define CFCR_PODD 0x00 /* odd parity */ +#define CFCR_PENAB 0x08 /* parity enable */ +#define CFCR_STOPB 0x04 /* 2 stop bits */ +#define CFCR_8BITS 0x03 /* 8 data bits */ +#define CFCR_7BITS 0x02 /* 7 data bits */ +#define CFCR_6BITS 0x01 /* 6 data bits */ +#define CFCR_5BITS 0x00 /* 5 data bits */ + +/* modem control register */ +#define MCR_LOOPBACK 0x10 /* loopback */ +#define MCR_IENABLE 0x08 /* output 2 = int enable */ +#define MCR_DRS 0x04 /* output 1 = xxx */ +#define MCR_RTS 0x02 /* enable RTS */ +#define MCR_DTR 0x01 /* enable DTR */ + +/* line status register */ +#define LSR_RCV_FIFO 0x80 /* error in receive fifo */ +#define LSR_TSRE 0x40 /* transmitter empty */ +#define LSR_TXRDY 0x20 /* transmitter ready */ +#define LSR_BI 0x10 /* break detected */ +#define LSR_FE 0x08 /* framing error */ +#define LSR_PE 0x04 /* parity error */ +#define LSR_OE 0x02 /* overrun error */ +#define LSR_RXRDY 0x01 /* receiver ready */ +#define LSR_RCV_MASK 0x1f + +/* modem status register */ +#define MSR_DCD 0x80 /* DCD active */ +#define MSR_RI 0x40 /* RI active */ +#define MSR_DSR 0x20 /* DSR active */ +#define MSR_CTS 0x10 /* CTS active */ +#define MSR_DDCD 0x08 /* DCD changed */ +#define MSR_TERI 0x04 /* RI changed */ +#define MSR_DDSR 0x02 /* DSR changed */ +#define MSR_DCTS 0x01 /* CTS changed */ + +#endif diff --git a/arch/mips/galileo-boards/ev64120/compressed/osdep.h b/arch/mips/galileo-boards/ev64120/compressed/osdep.h new file mode 100644 index 000000000..933c8c1c7 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/osdep.h @@ -0,0 +1,36 @@ +#ifndef __OSDEP_H__ +#define __OSDEP_H__ + +/* + * 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, or (at + * your option) any later version. + */ + +#if defined(__linux__) || defined(__FreeBSD__) || defined (__MIPSEB__) +#define ETHERBOOT32 +#define ntohl(x) (x) +#define htonl(x) (x) +#define ntohs(x) (x) +#define htons(x) (x) + +#endif + + + + +/* ANSI prototyping macro */ +#ifdef __STDC__ +#define P(x) x +#else +#define P(x) () +#endif + +#endif + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/arch/mips/galileo-boards/ev64120/compressed/pci.c b/arch/mips/galileo-boards/ev64120/compressed/pci.c new file mode 100644 index 000000000..9d8add1eb --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/pci.c @@ -0,0 +1,1336 @@ +/* PCI.c - PCI functions */ + +/* Copyright - Galileo technology. */ + +#ifdef __linux__ +#include <asm/galileo-boards/evb64120A/core.h> +#include <asm/galileo-boards/evb64120A/pci.h> +#ifndef PROM +#include <linux/kernel.h> +#endif + +#undef PCI_DEBUG + +#ifdef PCI_DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +#else +#include "core.h" +#include "pci.h" +#include <string.h> +#endif + +/******************************************************************** +* pci0ScanDevices - This function scan PCI0 bus, if found any device on +* this bus it interrogate the Device for the information +* it can discover. +* The fields with all information are the following: +* char type[20]; +* unsigned int deviceNum; +* unsigned int venID; +* unsigned int deviceID; +* unsigned int bar0Base; +* unsigned int bar0Size; +* unsigned int bar1Base; +* unsigned int bar1Size; +* unsigned int bar2Base; +* unsigned int bar2Size; +* unsigned int bar3Base; +* unsigned int bar3Size; +* unsigned int bar4Base; +* unsigned int bar4Size; +* unsigned int bar5Base; +* unsigned int bar5Size; +* +* Inputs: PCI0_DEVICE* pci0Detect - Pointer to an array of STRUCT PCI0_DEVICE. +* unsigned int numberOfElment - The PCI0_DEVICE Array length. +* Output: None. +*********************************************************************/ + +void pci0ScanDevices(PCI_DEVICE * pci0Detect, unsigned int numberOfElment) +{ + PCI_DEVICE *pci0ArrayPointer = pci0Detect; + unsigned int id; /* PCI Configuration register 0x0. */ + unsigned int device; /* device`s Counter. */ + unsigned int classCode; /* PCI Configuration register 0x8 */ + unsigned int arrayCounter = 0; + unsigned int memBaseAddress; + unsigned int memSize; + unsigned int c18RegValue; + + PCI0_MASTER_ENABLE(SELF); + /* According to PCI REV 2.1 MAX agents on the bus are -21- */ + for (device = 6; device < 8; device++) { + id = pci0ReadConfigReg(PCI_0DEVICE_AND_VENDOR_ID, device); + GT_REG_READ(INTERRUPT_CAUSE_REGISTER, &c18RegValue); + /* Clearing bit 18 of in the Cause Register 0xc18 by writting 0. */ + GT_REG_WRITE(INTERRUPT_CAUSE_REGISTER, + c18RegValue & 0xfffbffff); + if ((id != 0xffffffff) && !(c18RegValue & 0x40000)) { + classCode = + pci0ReadConfigReg + (PCI_0CLASS_CODE_AND_REVISION_ID, device); + pci0ArrayPointer->deviceNum = device; + pci0ArrayPointer->venID = (id & 0xffff); + pci0ArrayPointer->deviceID = + ((id & 0xffff0000) >> 16); + DBG("\nrr: venID %x devID %x\n", + pci0ArrayPointer->venID, + pci0ArrayPointer->deviceID); + DBG("rr: device found %x\n", + pci0ArrayPointer->deviceNum); + /* BAR0 parameters */ + memBaseAddress = pci0ReadConfigReg(BAR0, device); + pci0ArrayPointer->bar0Type = memBaseAddress & 1; + pci0ArrayPointer->bar0Base = + memBaseAddress & 0xfffff000; + pci0WriteConfigReg(BAR0, device, 0xffffffff); + memSize = pci0ReadConfigReg(BAR0, device); + if (memSize == 0) { /* case of an empty BAR */ + pci0ArrayPointer->bar0Size = 0; + } else { + if (pci0ArrayPointer->bar0Type == 0) /* memory space */ + memSize = + ~(memSize & 0xfffffff0) + 1; + else /* IO space */ + memSize = + ~(memSize & 0xfffffffc) + 1; + pci0ArrayPointer->bar0Size = memSize; + } + DBG("rr: device BAR0 size %x\n", memSize); + DBG("rr: device BAR0 address %x\n", + memBaseAddress); + pci0WriteConfigReg(BAR0, device, memBaseAddress); + /* BAR1 parameters */ + memBaseAddress = pci0ReadConfigReg(BAR1, device); + pci0ArrayPointer->bar1Type = memBaseAddress & 1; + pci0ArrayPointer->bar1Base = + memBaseAddress & 0xfffff000; + pci0WriteConfigReg(BAR1, device, 0xffffffff); + memSize = pci0ReadConfigReg(BAR1, device); + if (memSize == 0) { /* case of an empty BAR */ + pci0ArrayPointer->bar1Size = 0; + } else { + if (pci0ArrayPointer->bar1Type == 0) /* memory space */ + memSize = + ~(memSize & 0xfffffff0) + 1; + else /* IO space */ + memSize = + ~(memSize & 0xfffffffc) + 1; + pci0ArrayPointer->bar1Size = memSize; + } + DBG("rr: device BAR1 size %x\n", memSize); + DBG("rr: device BAR1 address %x\n", + memBaseAddress); + pci0WriteConfigReg(BAR1, device, memBaseAddress); + /* BAR2 parameters */ + memBaseAddress = pci0ReadConfigReg(BAR2, device); + pci0ArrayPointer->bar2Type = memBaseAddress & 1; + pci0ArrayPointer->bar2Base = + memBaseAddress & 0xfffff000; + pci0WriteConfigReg(BAR2, device, 0xffffffff); + memSize = pci0ReadConfigReg(BAR2, device); + if (memSize == 0) { /* case of an empty BAR */ + pci0ArrayPointer->bar2Size = 0; + } else { + if (pci0ArrayPointer->bar2Type == 0) /* memory space */ + memSize = + ~(memSize & 0xfffffff0) + 1; + else /* IO space */ + memSize = + ~(memSize & 0xfffffffc) + 1; + pci0ArrayPointer->bar2Size = memSize; + } + DBG("rr: device BAR2 size %x\n", memSize); + DBG("rr: device BAR2 address %x\n", + memBaseAddress); + pci0WriteConfigReg(BAR2, device, memBaseAddress); + /* BAR3 parameters */ + memBaseAddress = pci0ReadConfigReg(BAR3, device); + pci0ArrayPointer->bar3Type = memBaseAddress & 1; + pci0ArrayPointer->bar3Base = + memBaseAddress & 0xfffff000; + pci0WriteConfigReg(BAR3, device, 0xffffffff); + memSize = pci0ReadConfigReg(BAR3, device); + if (memSize == 0) { /* case of an empty BAR */ + pci0ArrayPointer->bar3Size = 0; + } else { + if (pci0ArrayPointer->bar3Type == 0) /* memory space */ + memSize = + ~(memSize & 0xfffffff0) + 1; + else /* IO space */ + memSize = + ~(memSize & 0xfffffffc) + 1; + pci0ArrayPointer->bar3Size = memSize; + } + DBG("rr: device BAR3 size %x\n", memSize); + DBG("rr: device BAR3 address %x\n", + memBaseAddress); + pci0WriteConfigReg(BAR3, device, memBaseAddress); + /* BAR4 parameters */ + memBaseAddress = pci0ReadConfigReg(BAR4, device); + pci0ArrayPointer->bar4Type = memBaseAddress & 1; + pci0ArrayPointer->bar4Base = + memBaseAddress & 0xfffff000; + pci0WriteConfigReg(BAR4, device, 0xffffffff); + memSize = pci0ReadConfigReg(BAR4, device); + if (memSize == 0) { /* case of an empty BAR */ + pci0ArrayPointer->bar4Size = 0; + } else { + if (pci0ArrayPointer->bar4Type == 0) /* memory space */ + memSize = + ~(memSize & 0xfffffff0) + 1; + else /* IO space */ + memSize = + ~(memSize & 0xfffffffc) + 1; + pci0ArrayPointer->bar4Size = memSize; + } + DBG("rr: device BAR4 size %x\n", memSize); + DBG("rr: device BAR4 address %x\n", + memBaseAddress); + pci0WriteConfigReg(BAR4, device, memBaseAddress); + /* BAR5 parameters */ + memBaseAddress = pci0ReadConfigReg(BAR5, device); + pci0ArrayPointer->bar5Type = memBaseAddress & 1; + pci0ArrayPointer->bar5Base = + memBaseAddress & 0xfffff000; + pci0WriteConfigReg(BAR5, device, 0xffffffff); + memSize = pci0ReadConfigReg(BAR5, device); + if (memSize == 0) { /* case of an empty BAR */ + pci0ArrayPointer->bar5Size = 0; + } else { + if (pci0ArrayPointer->bar5Type == 1) /* memory space */ + memSize = + ~(memSize & 0xfffffff0) + 1; + else /* IO space */ + memSize = + ~(memSize & 0xfffffffc) + 1; + pci0ArrayPointer->bar5Size = memSize; + } + DBG("rr: device BAR5 size %x\n", memSize); + DBG("rr: device BAR5 address %x\n", + memBaseAddress); + pci0WriteConfigReg(BAR5, device, memBaseAddress); + /* End of BARs Detection. */ + + classCode = ((classCode & 0xff000000) >> 24); + switch (classCode) { + case 0x0: + strcpy(pci0ArrayPointer->type, + "Old generation device"); + break; + case 0x1: + strcpy(pci0ArrayPointer->type, + "Mass storage controller"); + break; + case 0x2: + strcpy(pci0ArrayPointer->type, + "Network controller"); + break; + case 0x3: + strcpy(pci0ArrayPointer->type, + "Display controller"); + break; + case 0x4: + strcpy(pci0ArrayPointer->type, + "Multimedia device"); + break; + case 0x5: + strcpy(pci0ArrayPointer->type, + "Memory controller"); + break; + case 0x6: + strcpy(pci0ArrayPointer->type, + "Bridge Device"); + break; + case 0x7: + strcpy(pci0ArrayPointer->type, + "Simple Communication controllers"); + break; + case 0x8: + strcpy(pci0ArrayPointer->type, + "Base system peripherals"); + break; + case 0x9: + strcpy(pci0ArrayPointer->type, + "Input Devices"); + break; + case 0xa: + strcpy(pci0ArrayPointer->type, + "Docking stations"); + break; + case 0xb: + strcpy(pci0ArrayPointer->type, + "Processors"); + break; + case 0xc: + strcpy(pci0ArrayPointer->type, + "Serial bus controllers"); + break; + case 0xd: + strcpy(pci0ArrayPointer->type, + "Wireless controllers"); + break; + case 0xe: + strcpy(pci0ArrayPointer->type, + "Intelligent I/O controllers"); + break; + case 0xf: + strcpy(pci0ArrayPointer->type, + "Satellite communication controllers"); + break; + case 0x10: + strcpy(pci0ArrayPointer->type, + "Encryption/Decryption controllers"); + break; + case 0x11: + strcpy(pci0ArrayPointer->type, + "Data acquisition and signal processing controllers"); + break; + default: + break; + + } + arrayCounter++; /* point to the next element in the Array. */ + if (arrayCounter == numberOfElment) + return; /* When the Array is fully used, return. */ + /* Else, points to next free Element. */ + pci0ArrayPointer = &pci0Detect[arrayCounter]; + } + } + pci0ArrayPointer->deviceNum = 0; /* 0 => End of List */ +} + + +/******************************************************************** +* pci1ScanDevices - This function scan PCI1 bus, if found any device on +* this bus it interrogate the Device for the information +* it can discover. +* The fields with all information are the following: +* char type[20]; +* unsigned int deviceNum; +* unsigned int venID; +* unsigned int deviceID; +* unsigned int bar0Base; +* unsigned int bar0Size; +* unsigned int bar1Base; +* unsigned int bar1Size; +* unsigned int bar2Base; +* unsigned int bar2Size; +* unsigned int bar3Base; +* unsigned int bar3Size; +* unsigned int bar4Base; +* unsigned int bar4Size; +* unsigned int bar5Base; +* unsigned int bar5Size; +* +* Inputs: Pointer to an array of STRUCT PCI1_DEVICE. +* Output: None. +*********************************************************************/ + +void pci1ScanDevices(PCI_DEVICE * pci1Detect, unsigned int numberOfElment) +{ + PCI_DEVICE *pci1ArrayPointer = pci1Detect; + unsigned int id; /* PCI Configuration register 0x0. */ + unsigned int device; /* device`s Counter. */ + unsigned int classCode; /* PCI Configuration register 0x8 */ + unsigned int arrayCounter = 0; + unsigned int memBaseAddress; + unsigned int memSize; + unsigned int c98RegValue; + + PCI1_MASTER_ENABLE(SELF); + /* According to PCI REV 2.1 MAX agents on the bus are -21- */ + for (device = 1; device < 22; device++) { + id = pci1ReadConfigReg(PCI_0DEVICE_AND_VENDOR_ID, device); + GT_REG_READ(HIGH_INTERRUPT_CAUSE_REGISTER, &c98RegValue); + /* Clearing bit 18 of in the High Cause Register 0xc98 */ + GT_REG_WRITE(HIGH_INTERRUPT_CAUSE_REGISTER, + c98RegValue & 0xfffbffff); + if ((id != 0xffffffff) && !(c98RegValue & 0x40000)) { + classCode = + pci1ReadConfigReg + (PCI_0CLASS_CODE_AND_REVISION_ID, device); + pci1ArrayPointer->deviceNum = device; + pci1ArrayPointer->venID = (id & 0xffff); + pci1ArrayPointer->deviceID = + ((id & 0xffff0000) >> 16); + + /* BAR0 parameters */ + memBaseAddress = pci1ReadConfigReg(BAR0, device); + pci1ArrayPointer->bar0Type = memBaseAddress & 1; + pci1ArrayPointer->bar0Base = + memBaseAddress & 0xfffff000; + pci1WriteConfigReg(BAR0, device, 0xffffffff); + memSize = pci1ReadConfigReg(BAR0, device); + if (memSize == 0) { /* case of an empty BAR */ + pci1ArrayPointer->bar0Size = 0; + } else { + if (pci1ArrayPointer->bar0Type == 0) /* memory space */ + memSize = + ~(memSize & 0xfffffff0) + 1; + else /* IO space */ + memSize = + ~(memSize & 0xfffffffc) + 1; + pci1ArrayPointer->bar0Size = memSize; + } + pci1WriteConfigReg(BAR0, device, memBaseAddress); + /* BAR1 parameters */ + memBaseAddress = pci1ReadConfigReg(BAR1, device); + pci1ArrayPointer->bar1Type = memBaseAddress & 1; + pci1ArrayPointer->bar1Base = + memBaseAddress & 0xfffff000; + pci1WriteConfigReg(BAR1, device, 0xffffffff); + memSize = pci1ReadConfigReg(BAR1, device); + if (memSize == 0) { /* case of an empty BAR */ + pci1ArrayPointer->bar1Size = 0; + } else { + if (pci1ArrayPointer->bar1Type == 0) /* memory space */ + memSize = + ~(memSize & 0xfffffff0) + 1; + else /* IO space */ + memSize = + ~(memSize & 0xfffffffc) + 1; + pci1ArrayPointer->bar1Size = memSize; + } + pci1WriteConfigReg(BAR1, device, memBaseAddress); + /* BAR2 parameters */ + memBaseAddress = pci1ReadConfigReg(BAR2, device); + pci1ArrayPointer->bar2Type = memBaseAddress & 1; + pci1ArrayPointer->bar2Base = + memBaseAddress & 0xfffff000; + pci1WriteConfigReg(BAR2, device, 0xffffffff); + memSize = pci1ReadConfigReg(BAR2, device); + if (memSize == 0) { /* case of an empty BAR */ + pci1ArrayPointer->bar2Size = 0; + } else { + if (pci1ArrayPointer->bar2Type == 0) /* memory space */ + memSize = + ~(memSize & 0xfffffff0) + 1; + else /* IO space */ + memSize = + ~(memSize & 0xfffffffc) + 1; + pci1ArrayPointer->bar2Size = memSize; + } + pci1WriteConfigReg(BAR2, device, memBaseAddress); + /* BAR3 parameters */ + memBaseAddress = pci1ReadConfigReg(BAR3, device); + pci1ArrayPointer->bar3Type = memBaseAddress & 1; + pci1ArrayPointer->bar3Base = + memBaseAddress & 0xfffff000; + pci1WriteConfigReg(BAR3, device, 0xffffffff); + memSize = pci1ReadConfigReg(BAR3, device); + if (memSize == 0) { /* case of an empty BAR */ + pci1ArrayPointer->bar3Size = 0; + } else { + if (pci1ArrayPointer->bar3Type == 0) /* memory space */ + memSize = + ~(memSize & 0xfffffff0) + 1; + else /* IO space */ + memSize = + ~(memSize & 0xfffffffc) + 1; + pci1ArrayPointer->bar3Size = memSize; + } + pci1WriteConfigReg(BAR3, device, memBaseAddress); + /* BAR4 parameters */ + memBaseAddress = pci1ReadConfigReg(BAR4, device); + pci1ArrayPointer->bar4Type = memBaseAddress & 1; + pci1ArrayPointer->bar4Base = + memBaseAddress & 0xfffff000; + pci1WriteConfigReg(BAR4, device, 0xffffffff); + memSize = pci1ReadConfigReg(BAR4, device); + if (memSize == 0) { /* case of an empty BAR */ + pci1ArrayPointer->bar4Size = 0; + } else { + if (pci1ArrayPointer->bar4Type == 0) /* memory space */ + memSize = + ~(memSize & 0xfffffff0) + 1; + else /* IO space */ + memSize = + ~(memSize & 0xfffffffc) + 1; + pci1ArrayPointer->bar4Size = memSize; + } + pci1WriteConfigReg(BAR4, device, memBaseAddress); + /* BAR5 parameters */ + memBaseAddress = pci1ReadConfigReg(BAR5, device); + pci1ArrayPointer->bar5Type = memBaseAddress & 1; + pci1ArrayPointer->bar5Base = + memBaseAddress & 0xfffff000; + pci1WriteConfigReg(BAR5, device, 0xffffffff); + memSize = pci1ReadConfigReg(BAR5, device); + if (memSize == 0) { /* case of an empty BAR */ + pci1ArrayPointer->bar5Size = 0; + } else { + if (pci1ArrayPointer->bar5Type == 0) /* memory space */ + memSize = + ~(memSize & 0xfffffff0) + 1; + else /* IO space */ + memSize = + ~(memSize & 0xfffffffc) + 1; + pci1ArrayPointer->bar5Size = memSize; + } + pci1WriteConfigReg(BAR5, device, memBaseAddress); + /* End of BARs Detection. */ + + classCode = ((classCode & 0xff000000) >> 24); + switch (classCode) { + case 0x0: + strcpy(pci1ArrayPointer->type, + "Old generation device"); + break; + case 0x1: + strcpy(pci1ArrayPointer->type, + "Mass storage controller"); + break; + case 0x2: + strcpy(pci1ArrayPointer->type, + "Network controller"); + break; + case 0x3: + strcpy(pci1ArrayPointer->type, + "Display controller"); + break; + case 0x4: + strcpy(pci1ArrayPointer->type, + "Multimedia device"); + break; + case 0x5: + strcpy(pci1ArrayPointer->type, + "Memory controller"); + break; + case 0x6: + strcpy(pci1ArrayPointer->type, + "Bridge Device"); + break; + case 0x7: + strcpy(pci1ArrayPointer->type, + "Simple Communication controllers"); + break; + case 0x8: + strcpy(pci1ArrayPointer->type, + "Base system peripherals"); + break; + case 0x9: + strcpy(pci1ArrayPointer->type, + "Input Devices"); + break; + case 0xa: + strcpy(pci1ArrayPointer->type, + "Docking stations"); + break; + case 0xb: + strcpy(pci1ArrayPointer->type, + "Processors"); + break; + case 0xc: + strcpy(pci1ArrayPointer->type, + "Serial bus controllers"); + break; + case 0xd: + strcpy(pci1ArrayPointer->type, + "Wireless controllers"); + break; + case 0xe: + strcpy(pci1ArrayPointer->type, + "Intelligent I/O controllers"); + break; + case 0xf: + strcpy(pci1ArrayPointer->type, + "Satellite communication controllers"); + break; + case 0x10: + strcpy(pci1ArrayPointer->type, + "Encryption/Decryption controllers"); + break; + case 0x11: + strcpy(pci1ArrayPointer->type, + "Data acquisition and signal processing controllers"); + break; + } + arrayCounter++; /* point to the next element in the Array. */ + if (arrayCounter == numberOfElment) + return; /* When the Array is fully used, return. */ + /* Else, points to next free Element. */ + pci1ArrayPointer = &pci1Detect[arrayCounter]; + } + } + pci1ArrayPointer->deviceNum = 0; /* 0 => End of List */ +} + +/******************************************************************** +* pci0WriteConfigReg - Write to a PCI configuration register +* - Make sure the GT is configured as a master before +* writingto another device on the PCI. +* - The function takes care of Big/Little endian conversion. +* Inputs: unsigned int regOffset: The register offset as it apears in the GT spec +* (or any other PCI device spec) +* pciDevNum: The device number needs to be addressed. +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|00| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +*********************************************************************/ + +void pci0WriteConfigReg(unsigned int regOffset, unsigned int pciDevNum, + unsigned int data) +{ + unsigned int DataForRegCf8; + unsigned int functionNum; + + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0x0fffffff; + DataForRegCf8 = (regOffset | pciDevNum | functionNum) | BIT31; + GT_REG_WRITE(PCI_0CONFIGURATION_ADDRESS, DataForRegCf8); + if (pciDevNum == SELF) { /* This board */ + GT_REG_WRITE(PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER, + data); + } else { /* configuration Transaction over the pci. */ + + /* The PCI is working in LE Mode So it swap the Data. */ + GT_REG_WRITE(PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER, + WORDSWAP(data)); + } +} + +/******************************************************************** +* pci1WriteConfigReg - Write to a PCI configuration register +* - Make sure the GT is configured as a master before writing +* to another device on the PCI. +* - The function takes care of Big/Little endian conversion. +* Inputs: unsigned int regOffset: The register offset as it apears in the +* GT spec (or any other PCI device spec) +* pciDevNum: The device number needs to be addressed. +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|00| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +*********************************************************************/ + +void pci1WriteConfigReg(unsigned int regOffset, unsigned int pciDevNum, + unsigned int data) +{ + unsigned int DataForRegCf8; + unsigned int functionNum; + + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0x0fffffff; + if (pciDevNum == SELF) { /* This board */ + /* when configurating our own PCI 1 L-unit the access is through + the PCI 0 interface with reg number = reg number + 0x80 */ + DataForRegCf8 = + (regOffset | pciDevNum | functionNum | 0x80) | BIT31; + GT_REG_WRITE(PCI_0CONFIGURATION_ADDRESS, DataForRegCf8); + } else { + DataForRegCf8 = + (regOffset | pciDevNum | functionNum) | BIT31; + GT_REG_WRITE(PCI_1CONFIGURATION_ADDRESS, DataForRegCf8); + } + if (pciDevNum == SELF) { /* This board */ + GT_REG_WRITE(PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER, + data); + } else { + GT_REG_WRITE(PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER, + WORDSWAP(data)); + } +} + +/******************************************************************** +* pci0ReadConfigReg - Read from a PCI0 configuration register +* - Make sure the GT is configured as a master before +* reading from another device on the PCI. +* - The function takes care of Big/Little endian conversion. +* INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI +* spec) +* pciDevNum: The device number needs to be addressed. +* RETURNS: data , if the data == 0xffffffff check the master abort bit in the +* cause register to make sure the data is valid +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|00| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +*********************************************************************/ + +unsigned int pci0ReadConfigReg(unsigned int regOffset, + unsigned int pciDevNum) +{ + unsigned int DataForRegCf8; + unsigned int data; + unsigned int functionNum; + + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0x0fffffff; + DataForRegCf8 = (regOffset | pciDevNum | functionNum) | BIT31; + GT_REG_WRITE(PCI_0CONFIGURATION_ADDRESS, DataForRegCf8); + if (pciDevNum == SELF) { /* This board */ + GT_REG_READ(PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER, + &data); + return data; + } else { /* The PCI is working in LE Mode So it swap the Data. */ + + GT_REG_READ(PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER, + &data); + return WORDSWAP(data); + } +} + +/******************************************************************** +* pci1ReadConfigReg - Read from a PCI1 configuration register +* - Make sure the GT is configured as a master before +* reading from another device on the PCI. +* - The function takes care of Big/Little endian conversion. +* INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI +* spec) +* pciDevNum: The device number needs to be addressed. +* RETURNS: data , if the data == 0xffffffff check the master abort bit in the +* cause register to make sure the data is valid +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|00| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +*********************************************************************/ + +unsigned int pci1ReadConfigReg(unsigned int regOffset, + unsigned int pciDevNum) +{ + unsigned int DataForRegCf8; + unsigned int data; + unsigned int functionNum; + + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0x0fffffff; + if (pciDevNum == SELF) { /* This board */ + /* when configurating our own PCI 1 L-unit the access is through + the PCI 0 interface with reg number = reg number + 0x80 */ + DataForRegCf8 = + (regOffset | pciDevNum | functionNum | 0x80) | BIT31; + GT_REG_WRITE(PCI_0CONFIGURATION_ADDRESS, DataForRegCf8); + } else { + DataForRegCf8 = + (regOffset | pciDevNum | functionNum) | BIT31; + GT_REG_WRITE(PCI_1CONFIGURATION_ADDRESS, DataForRegCf8); + } + if (pciDevNum == SELF) { /* This board */ + GT_REG_READ(PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER, + &data); + return data; + } else { + GT_REG_READ(PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER, + &data); + return WORDSWAP(data); + } +} + +/******************************************************************** +* pci0MapIOspace - Maps PCI0 IO space for the master. +* Inputs: base and length of pci0Io +*********************************************************************/ + +void pci0MapIOspace(unsigned int pci0IoBase, unsigned int pci0IoLength) +{ + unsigned int pci0IoTop = + (unsigned int) (pci0IoBase + pci0IoLength); + + if (pci0IoLength == 0) + pci0IoTop++; + + pci0IoBase = (unsigned int) (pci0IoBase >> 21); + pci0IoTop = (unsigned int) (((pci0IoTop - 1) & 0x0fffffff) >> 21); + GT_REG_WRITE(PCI_0I_O_LOW_DECODE_ADDRESS, pci0IoBase); + GT_REG_WRITE(PCI_0I_O_HIGH_DECODE_ADDRESS, pci0IoTop); +} + +/******************************************************************** +* pci1MapIOspace - Maps PCI1 IO space for the master. +* Inputs: base and length of pci1Io +*********************************************************************/ + +void pci1MapIOspace(unsigned int pci1IoBase, unsigned int pci1IoLength) +{ + unsigned int pci1IoTop = + (unsigned int) (pci1IoBase + pci1IoLength); + + if (pci1IoLength == 0) + pci1IoTop++; + + pci1IoBase = (unsigned int) (pci1IoBase >> 21); + pci1IoTop = (unsigned int) (((pci1IoTop - 1) & 0x0fffffff) >> 21); + GT_REG_WRITE(PCI_1I_O_LOW_DECODE_ADDRESS, pci1IoBase); + GT_REG_WRITE(PCI_1I_O_HIGH_DECODE_ADDRESS, pci1IoTop); +} + +/******************************************************************** +* pci0MapMemory0space - Maps PCI0 memory0 space for the master. +* Inputs: base and length of pci0Mem0 +*********************************************************************/ + + +void pci0MapMemory0space(unsigned int pci0Mem0Base, + unsigned int pci0Mem0Length) +{ + unsigned int pci0Mem0Top = pci0Mem0Base + pci0Mem0Length; + + if (pci0Mem0Length == 0) + pci0Mem0Top++; + + pci0Mem0Base = pci0Mem0Base >> 21; + pci0Mem0Top = ((pci0Mem0Top - 1) & 0x0fffffff) >> 21; + GT_REG_WRITE(PCI_0MEMORY0_LOW_DECODE_ADDRESS, pci0Mem0Base); + GT_REG_WRITE(PCI_0MEMORY0_HIGH_DECODE_ADDRESS, pci0Mem0Top); +} + +/******************************************************************** +* pci1MapMemory0space - Maps PCI1 memory0 space for the master. +* Inputs: base and length of pci1Mem0 +*********************************************************************/ + +void pci1MapMemory0space(unsigned int pci1Mem0Base, + unsigned int pci1Mem0Length) +{ + unsigned int pci1Mem0Top = pci1Mem0Base + pci1Mem0Length; + + if (pci1Mem0Length == 0) + pci1Mem0Top++; + + pci1Mem0Base = pci1Mem0Base >> 21; + pci1Mem0Top = ((pci1Mem0Top - 1) & 0x0fffffff) >> 21; + GT_REG_WRITE(PCI_1MEMORY0_LOW_DECODE_ADDRESS, pci1Mem0Base); + GT_REG_WRITE(PCI_1MEMORY0_HIGH_DECODE_ADDRESS, pci1Mem0Top); +} + +/******************************************************************** +* pci0MapMemory1space - Maps PCI0 memory1 space for the master. +* Inputs: base and length of pci0Mem1 +*********************************************************************/ + +void pci0MapMemory1space(unsigned int pci0Mem1Base, + unsigned int pci0Mem1Length) +{ + unsigned int pci0Mem1Top = pci0Mem1Base + pci0Mem1Length; + + if (pci0Mem1Length == 0) + pci0Mem1Top++; + + pci0Mem1Base = pci0Mem1Base >> 21; + pci0Mem1Top = ((pci0Mem1Top - 1) & 0x0fffffff) >> 21; + GT_REG_WRITE(PCI_0MEMORY1_LOW_DECODE_ADDRESS, pci0Mem1Base); + GT_REG_WRITE(PCI_0MEMORY1_HIGH_DECODE_ADDRESS, pci0Mem1Top); +#ifndef PROM + DBG(KERN_INFO "pci0Mem1Base %x\n", pci0Mem1Base); + DBG(KERN_INFO "pci0Mem1Top %x\n", pci0Mem1Top); + GT_REG_READ(PCI_0MEMORY0_ADDRESS_REMAP, &pci0Mem1Base); + DBG(KERN_INFO "Mem 0/0 remap %x\n", pci0Mem1Base); + GT_REG_READ(PCI_0MEMORY1_ADDRESS_REMAP, &pci0Mem1Base); + DBG(KERN_INFO "Mem 0/1 remap %x\n", pci0Mem1Base); + GT_REG_WRITE(PCI_0MEMORY1_ADDRESS_REMAP, 0x500); + GT_REG_READ(PCI_0MEMORY1_ADDRESS_REMAP, &pci0Mem1Base); + DBG(KERN_INFO "Mem 0/1 remapped %x\n", pci0Mem1Base); +#endif +} + +/******************************************************************** +* pci1MapMemory1space - Maps PCI1 memory1 space for the master. +* Inputs: base and length of pci1Mem1 +*********************************************************************/ + +void pci1MapMemory1space(unsigned int pci1Mem1Base, + unsigned int pci1Mem1Length) +{ + unsigned int pci1Mem1Top = pci1Mem1Base + pci1Mem1Length; + + if (pci1Mem1Length == 0) + pci1Mem1Top++; + + pci1Mem1Base = pci1Mem1Base >> 21; + pci1Mem1Top = ((pci1Mem1Top - 1) & 0x0fffffff) >> 21; + GT_REG_WRITE(PCI_1MEMORY1_LOW_DECODE_ADDRESS, pci1Mem1Base); + GT_REG_WRITE(PCI_1MEMORY1_HIGH_DECODE_ADDRESS, pci1Mem1Top); +} + +/******************************************************************** +* pci0GetIOspaceBase - Return PCI0 IO Base Address. +* Inputs: N/A +* Returns: PCI0 IO Base Address. +*********************************************************************/ + +unsigned int pci0GetIOspaceBase() +{ + unsigned int base; + GT_REG_READ(PCI_0I_O_LOW_DECODE_ADDRESS, &base); + base = base << 21; + return base; +} + +/******************************************************************** +* pci0GetIOspaceSize - Return PCI0 IO Bar Size. +* Inputs: N/A +* Returns: PCI0 IO Bar Size. +*********************************************************************/ + +unsigned int pci0GetIOspaceSize() +{ + unsigned int top, base, size; + GT_REG_READ(PCI_0I_O_LOW_DECODE_ADDRESS, &base); + base = base << 21; + GT_REG_READ(PCI_0I_O_HIGH_DECODE_ADDRESS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/******************************************************************** +* pci0GetMemory0Base - Return PCI0 Memory 0 Base Address. +* Inputs: N/A +* Returns: PCI0 Memory 0 Base Address. +*********************************************************************/ + +unsigned int pci0GetMemory0Base() +{ + unsigned int base; + GT_REG_READ(PCI_0MEMORY0_LOW_DECODE_ADDRESS, &base); + base = base << 21; + return base; +} + +/******************************************************************** +* pci0GetMemory0Size - Return PCI0 Memory 0 Bar Size. +* Inputs: N/A +* Returns: PCI0 Memory 0 Bar Size. +*********************************************************************/ + +unsigned int pci0GetMemory0Size() +{ + unsigned int top, base, size; + GT_REG_READ(PCI_0MEMORY0_LOW_DECODE_ADDRESS, &base); + base = base << 21; + GT_REG_READ(PCI_0MEMORY0_HIGH_DECODE_ADDRESS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/******************************************************************** +* pci0GetMemory1Base - Return PCI0 Memory 1 Base Address. +* Inputs: N/A +* Returns: PCI0 Memory 1 Base Address. +*********************************************************************/ + +unsigned int pci0GetMemory1Base() +{ + unsigned int base; + GT_REG_READ(PCI_0MEMORY1_LOW_DECODE_ADDRESS, &base); + base = base << 21; + return base; +} + +/******************************************************************** +* pci0GetMemory1Size - Return PCI0 Memory 1 Bar Size. +* Inputs: N/A +* Returns: PCI0 Memory 1 Bar Size. +*********************************************************************/ + +unsigned int pci0GetMemory1Size() +{ + unsigned int top, base, size; + GT_REG_READ(PCI_0MEMORY1_LOW_DECODE_ADDRESS, &base); + base = base << 21; + GT_REG_READ(PCI_0MEMORY1_HIGH_DECODE_ADDRESS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/******************************************************************** +* pci1GetIOspaceBase - Return PCI1 IO Base Address. +* Inputs: N/A +* Returns: PCI1 IO Base Address. +*********************************************************************/ + +unsigned int pci1GetIOspaceBase() +{ + unsigned int base; + GT_REG_READ(PCI_1I_O_LOW_DECODE_ADDRESS, &base); + base = base << 21; + return base; +} + +/******************************************************************** +* pci1GetIOspaceSize - Return PCI1 IO Bar Size. +* Inputs: N/A +* Returns: PCI1 IO Bar Size. +*********************************************************************/ + +unsigned int pci1GetIOspaceSize() +{ + unsigned int top, base, size; + GT_REG_READ(PCI_1I_O_LOW_DECODE_ADDRESS, &base); + base = base << 21; + GT_REG_READ(PCI_1I_O_HIGH_DECODE_ADDRESS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/******************************************************************** +* pci1GetMemory0Base - Return PCI1 Memory 0 Base Address. +* Inputs: N/A +* Returns: PCI1 Memory 0 Base Address. +*********************************************************************/ + +unsigned int pci1GetMemory0Base() +{ + unsigned int base; + GT_REG_READ(PCI_1MEMORY0_LOW_DECODE_ADDRESS, &base); + base = base << 21; + return base; +} + +/******************************************************************** +* pci1GetMemory0Size - Return PCI1 Memory 0 Bar Size. +* Inputs: N/A +* Returns: PCI1 Memory 0 Bar Size. +*********************************************************************/ + +unsigned int pci1GetMemory0Size() +{ + unsigned int top, base, size; + GT_REG_READ(PCI_1MEMORY1_LOW_DECODE_ADDRESS, &base); + base = base << 21; + GT_REG_READ(PCI_1MEMORY1_HIGH_DECODE_ADDRESS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/******************************************************************** +* pci1GetMemory1Base - Return PCI1 Memory 1 Base Address. +* Inputs: N/A +* Returns: PCI1 Memory 1 Base Address. +*********************************************************************/ + +unsigned int pci1GetMemory1Base() +{ + unsigned int base; + GT_REG_READ(PCI_1MEMORY1_LOW_DECODE_ADDRESS, &base); + base = base << 21; + return base; +} + +/******************************************************************** +* pci1GetMemory1Size - Return PCI1 Memory 1 Bar Size. +* Inputs: N/A +* Returns: PCI1 Memory 1 Bar Size. +*********************************************************************/ + +unsigned int pci1GetMemory1Size() +{ + unsigned int top, base, size; + GT_REG_READ(PCI_1MEMORY1_LOW_DECODE_ADDRESS, &base); + base = base << 21; + GT_REG_READ(PCI_1MEMORY1_HIGH_DECODE_ADDRESS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/******************************************************************** +* pci0MapInternalRegSpace - Maps the internal registers memory space for the +* slave. +* Stays the same for all GT devices Disco include +* Inputs: base of pci0 internal register +*********************************************************************/ + +void pci0MapInternalRegSpace(unsigned int pci0InternalBase) +{ + pci0InternalBase = pci0InternalBase & 0xfffff000; + pci0InternalBase = + pci0InternalBase | + (pci0ReadConfigReg + (PCI_0INTERNAL_REGISTERS_MEMORY_MAPPED_BASE_ADDRESS, + SELF) & 0x00000fff); + pci0WriteConfigReg + (PCI_0INTERNAL_REGISTERS_MEMORY_MAPPED_BASE_ADDRESS, SELF, + pci0InternalBase); +} + +/******************************************************************** +* pci1MapInternalRegSpace - Maps the internal registers memory space for the +* slave. +* Stays the same for all GT devices Disco include +* Inputs: base of pci1 internal register +*********************************************************************/ + +void pci1MapInternalRegSpace(unsigned int pci1InternalBase) +{ + pci1InternalBase = pci1InternalBase & 0xfffff000; + pci1InternalBase = + pci1InternalBase | + (pci1ReadConfigReg + (PCI_0INTERNAL_REGISTERS_MEMORY_MAPPED_BASE_ADDRESS, + SELF) & 0x00000fff); + pci1WriteConfigReg + (PCI_0INTERNAL_REGISTERS_MEMORY_MAPPED_BASE_ADDRESS, SELF, + pci1InternalBase); +} + +/******************************************************************** +* pci0MapInternalRegIOSpace - Maps the internal registers IO space for the +* slave. +* Stays the same for all GT devices Disco include +* Inputs: base of pci0 internal io register +*********************************************************************/ + +void pci0MapInternalRegIOSpace(unsigned int pci0InternalBase) +{ + pci0InternalBase = pci0InternalBase & 0xfffff000; + pci0InternalBase = + pci0InternalBase | + (pci0ReadConfigReg + (PCI_0INTERNAL_REGISTERS_I_OMAPPED_BASE_ADDRESS, + 0) & 0x00000fff); + pci0WriteConfigReg(PCI_0INTERNAL_REGISTERS_I_OMAPPED_BASE_ADDRESS, + SELF, pci0InternalBase); +} + +/******************************************************************** +* pci0MapInternalRegIOSpace - Maps the internal registers IO space for the +* slave. +* Stays the same for all GT devices Disco include +* Inputs: base of pci1 internal io register +*********************************************************************/ + +void pci1MapInternalRegIOSpace(unsigned int pci1InternalBase) +{ + pci1InternalBase = pci1InternalBase & 0xfffff000; + pci1InternalBase = + pci1InternalBase | + (pci1ReadConfigReg + (PCI_0INTERNAL_REGISTERS_I_OMAPPED_BASE_ADDRESS, + SELF) & 0x00000fff); + pci1WriteConfigReg(PCI_0INTERNAL_REGISTERS_I_OMAPPED_BASE_ADDRESS, + SELF, pci1InternalBase); +} + +/******************************************************************** +* pci0MapMemoryBanks0_1 - Maps PCI0 memory banks 0 and 1 for the slave. +* for Discovery we need two function: SCS0 & SCS1 +* (instead of SCS[1:0]) +* Inputs: base and size of pci0 dram +*********************************************************************/ + + +void pci0MapMemoryBanks0_1(unsigned int pci0Dram0_1Base, + unsigned int pci0Dram0_1Size) +{ + pci0Dram0_1Base = pci0Dram0_1Base & 0xfffff000; + pci0Dram0_1Base = + pci0Dram0_1Base | + (pci0ReadConfigReg(PCI_0SCS_1_0_BASE_ADDRESS, SELF) & + 0x00000fff); + pci0WriteConfigReg(PCI_0SCS_1_0_BASE_ADDRESS, SELF, + pci0Dram0_1Base); + /* swapped Bar */ + pci0WriteConfigReg(PCI_0SWAPPED_SCS_1_0_BASE_ADDRESS, SELF, + pci0Dram0_1Base); + if (pci0Dram0_1Size == 0) + pci0Dram0_1Size++; + GT_REG_WRITE(PCI_0SCS_1_0_BANK_SIZE, pci0Dram0_1Size - 1); +} + +/******************************************************************** +* pci1MapMemoryBanks0_1 - Maps PCI1 memory banks 0 and 1 for the slave. +* for Discovery we need two function: SCS0 & SCS1 +* (instead of SCS[1:0]) +* Inputs: base and size of pci1 dram +*********************************************************************/ + +void pci1MapMemoryBanks0_1(unsigned int pci1Dram0_1Base, + unsigned int pci1Dram0_1Size) +{ + pci1Dram0_1Base = pci1Dram0_1Base & 0xfffff000; + pci1Dram0_1Base = + pci1Dram0_1Base | + (pci1ReadConfigReg(PCI_0SCS_1_0_BASE_ADDRESS, SELF) & + 0x00000fff); + pci1WriteConfigReg(PCI_0SCS_1_0_BASE_ADDRESS, SELF, + pci1Dram0_1Base); + /* swapped Bar */ + pci1WriteConfigReg(PCI_0SWAPPED_SCS_1_0_BASE_ADDRESS, SELF, + pci1Dram0_1Base); + if (pci1Dram0_1Size == 0) + pci1Dram0_1Size++; + GT_REG_WRITE(PCI_1SCS_1_0_BANK_SIZE, pci1Dram0_1Size - 1); +} + +/******************************************************************** +* pci0MapMemoryBanks2_3 - Maps PCI0 memory banks 2 and 3 for the slave. +* for Discovery we need two function: SCS2 & SCS3 +* (instead of SCS[3:2]) +* Inputs: base and size of pci0 dram +*********************************************************************/ + +void pci0MapMemoryBanks2_3(unsigned int pci0Dram2_3Base, + unsigned int pci0Dram2_3Size) +{ + pci0Dram2_3Base = pci0Dram2_3Base & 0xfffff000; + pci0Dram2_3Base = + pci0Dram2_3Base | + (pci0ReadConfigReg(PCI_0SCS_3_2_BASE_ADDRESS, SELF) & + 0x00000fff); + pci0WriteConfigReg(PCI_0SCS_3_2_BASE_ADDRESS, SELF, + pci0Dram2_3Base); + /* swapped Bar */ + pci0WriteConfigReg(PCI_0SWAPPED_SCS_3_2_BASE_ADDRESS, SELF, + pci0Dram2_3Base); + if (pci0Dram2_3Size == 0) + pci0Dram2_3Size++; + GT_REG_WRITE(PCI_0SCS_3_2_BANK_SIZE, pci0Dram2_3Size - 1); +} + +/******************************************************************** +* pci1MapMemoryBanks2_3 - Maps PCI1 memory banks 2 and 3 for the slave. +* for Discovery we need two function: SCS2 & SCS3 +* (instead of SCS[3:2]) +* Inputs: base and size of pci1 dram +*********************************************************************/ + +void pci1MapMemoryBanks2_3(unsigned int pci1Dram2_3Base, + unsigned int pci1Dram2_3Size) +{ + pci1Dram2_3Base = pci1Dram2_3Base & 0xfffff000; + pci1Dram2_3Base = + pci1Dram2_3Base | + (pci1ReadConfigReg(PCI_0SCS_3_2_BASE_ADDRESS, SELF) & + 0x00000fff); + pci1WriteConfigReg(PCI_0SCS_3_2_BASE_ADDRESS, SELF, + pci1Dram2_3Base); + /* swapped Bar */ + pci1WriteConfigReg(PCI_0SWAPPED_SCS_3_2_BASE_ADDRESS, SELF, + pci1Dram2_3Base); + if (pci1Dram2_3Size == 0) + pci1Dram2_3Size++; + GT_REG_WRITE(PCI_1SCS_3_2_BANK_SIZE, pci1Dram2_3Size - 1); +} + +/******************************************************************** +* pci0MapDevices0_1and2MemorySpace - Maps PCI0 devices 0,1 and 2 memory spaces +* for the slave. +* For the Discovery there are 3 separate +* fucnction's +* Inputs: base and lengthof pci0 devises012 +*********************************************************************/ + + +void pci0MapDevices0_1and2MemorySpace(unsigned int pci0Dev012Base, + unsigned int pci0Dev012Length) +{ + pci0Dev012Base = pci0Dev012Base & 0xfffff000; + pci0Dev012Base = + pci0Dev012Base | + (pci0ReadConfigReg(PCI_0CS_2_0_BASE_ADDRESS, SELF) & + 0x00000fff); + pci0WriteConfigReg(PCI_0CS_2_0_BASE_ADDRESS, SELF, pci0Dev012Base); + if (pci0Dev012Length == 0) + pci0Dev012Length++; + GT_REG_WRITE(PCI_0CS_2_0_BANK_SIZE, pci0Dev012Length - 1); +} + +/******************************************************************** +* pci1MapDevices0_1and2MemorySpace - Maps PCI1 devices 0,1 and 2 memory spaces +* for the slave. +* For the Discovery there are 3 separate +* fucnction's +* Inputs: base and lengthof pci1 devises012 +*********************************************************************/ + +void pci1MapDevices0_1and2MemorySpace(unsigned int pci1Dev012Base, + unsigned int pci1Dev012Length) +{ + pci1Dev012Base = pci1Dev012Base & 0xfffff000; + pci1Dev012Base = + pci1Dev012Base | + (pci1ReadConfigReg(PCI_0CS_2_0_BASE_ADDRESS, SELF) & + 0x00000fff); + pci1WriteConfigReg(PCI_0CS_2_0_BASE_ADDRESS, SELF, pci1Dev012Base); + if (pci1Dev012Length == 0) + pci1Dev012Length++; + GT_REG_WRITE(PCI_1CS_2_0_BANK_SIZE, pci1Dev012Length - 1); +} + +/******************************************************************** +* pci0MapDevices3andBootMemorySpace - Maps PCI0 devices 3 and boot memory +* spaces for the slave. +* For the Discovery there are 2 separate +* fucnction's +* Inputs: base and length of pci0 device3/ boot +*********************************************************************/ + +void pci0MapDevices3andBootMemorySpace(unsigned int pci0Dev3andBootBase, + unsigned int pci0Dev3andBootLength) +{ + pci0Dev3andBootBase = pci0Dev3andBootBase & 0xfffff000; + pci0Dev3andBootBase = + pci0Dev3andBootBase | + (pci0ReadConfigReg(PCI_0CS_3_BOOTCS_BASE_ADDRESS, SELF) & + 0x00000fff); + pci0WriteConfigReg(PCI_0CS_3_BOOTCS_BASE_ADDRESS, SELF, + pci0Dev3andBootBase); + /* swapped Bar */ + pci0WriteConfigReg(PCI_0SWAPPED_CS_3_BOOTCS_BASE_ADDRESS, SELF, + pci0Dev3andBootBase); + if (pci0Dev3andBootLength == 0) + pci0Dev3andBootLength++; + GT_REG_WRITE(PCI_0CS_3_BOOTCS_BANK_SIZE, + pci0Dev3andBootLength - 1); +} + +/******************************************************************** +* pci1MapDevices3andBootMemorySpace - Maps PCI1 devices 3 and boot memory +* spaces for the slave. +* For the Discovery there are 2 separate +* fucnction's +* Inputs: base and length of pci1 device3/ boot +*********************************************************************/ + +void pci1MapDevices3andBootMemorySpace(unsigned int pci1Dev3andBootBase, + unsigned int pci1Dev3andBootLength) +{ + pci1Dev3andBootBase = pci1Dev3andBootBase & 0xfffff000; + pci1Dev3andBootBase = + pci1Dev3andBootBase | + (pci1ReadConfigReg(PCI_0CS_3_BOOTCS_BASE_ADDRESS, SELF) & + 0x00000fff); + pci1WriteConfigReg(PCI_0CS_3_BOOTCS_BASE_ADDRESS, SELF, + pci1Dev3andBootBase); + /* swapped Bar */ + pci1WriteConfigReg(PCI_0SWAPPED_CS_3_BOOTCS_BASE_ADDRESS, SELF, + pci1Dev3andBootBase); + if (pci1Dev3andBootLength == 0) + pci1Dev3andBootLength++; + GT_REG_WRITE(PCI_1CS_3_BOOTCS_BANK_SIZE, + pci1Dev3andBootLength - 1); +} diff --git a/arch/mips/galileo-boards/ev64120/compressed/pci_etherboot.c b/arch/mips/galileo-boards/ev64120/compressed/pci_etherboot.c new file mode 100644 index 000000000..0d6981094 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/pci_etherboot.c @@ -0,0 +1,318 @@ +/* + * 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, or (at + * your option) any later version. + */ + +#include "etherboot.h" +#include <asm/galileo-boards/evb64120A/pci.h> +#include <asm/byteorder.h> +#include "pci_etherboot.h" +//#include "gt64120ARegs.h" +#include "galileo_port.h" + +#define MAX_PCI_DEVS 10 +PCI_DEVICE pci0_devices[MAX_PCI_DEVS]; +PCI_DEVICE pci1_devices[MAX_PCI_DEVS]; + +static int pci_range_ck(unsigned char bus, unsigned char dev) +{ + if ((bus == 0) && (dev >= 0) && (dev < 30)) + return 0; // Bus/Device Number OK + + return -1; // Bus/Device Number not OK +} + +/******************************************************************** + * pcibios_(read/write)_config_(byte/word/dword) + * + *Inputs : + *bus - bus number + *dev - device number + *offset - register offset in the configuration space + *val - value to be written / read + * + *Outputs : + *Sucees/Failure + *********************************************************************/ +#define PCI_CFG_DATA ((volatile unsigned long *)0xb4000cfc) +#define PCI_CFG_CTRL ((volatile unsigned long *)0xb4000cf8) + +#define PCI_CFG_SET(dev,fun,off) \ + ((*PCI_CFG_CTRL) = cpu_to_le32((0x80000000 | ((dev)<<11) | ((fun)<<8) | (off)))) + +int pcibios_read_config_dword(unsigned char bus, unsigned char dev, + unsigned char offset, unsigned int *val) +{ + + if (offset & 0x3) { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + if (pci_range_ck(bus, dev)) { + *val = 0xFFFFFFFF; + return PCIBIOS_DEVICE_NOT_FOUND; + } + PCI_CFG_SET(dev, 0, offset); + if (dev != 0) { + *val = *PCI_CFG_DATA; + } else { + *val = cpu_to_le32(*PCI_CFG_DATA); + } + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_read_config_word(unsigned char bus, unsigned char dev, + unsigned char offset, unsigned short *val) +{ + if (offset & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (pci_range_ck(bus, dev)) { + *val = 0xffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + PCI_CFG_SET(dev, 0, (offset & ~0x3)); + if (dev != 0) { + *val = *PCI_CFG_DATA >> ((offset & 3) * 8); + } else { + *val = cpu_to_le32(*PCI_CFG_DATA) >> ((offset & 3) * 8); + } + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_read_config_byte(unsigned char bus, unsigned char dev, + unsigned char offset, unsigned char *val) +{ + if (pci_range_ck(bus, dev)) { + *val = 0xff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + PCI_CFG_SET(dev, 0, (offset & ~0x3)); + if (dev != 0) { + *val = *PCI_CFG_DATA >> ((offset & 3) * 8); + } else { + *val = cpu_to_le32(*PCI_CFG_DATA >> ((offset & 3) * 8)); + } + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_write_config_dword(unsigned char bus, unsigned char dev, + unsigned char offset, unsigned int val) +{ + if (offset & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + PCI_CFG_SET(dev, 0, offset); + if (dev != 0) { + *PCI_CFG_DATA = val; + } else { + *PCI_CFG_DATA = cpu_to_le32(val); + } + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_write_config_word(unsigned char bus, unsigned char dev, + unsigned char offset, unsigned short val) +{ + unsigned long tmp; + + if (offset & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + PCI_CFG_SET(dev, 0, (offset & ~0x3)); + if (dev != 0) { + tmp = *PCI_CFG_DATA; + } else { + tmp = cpu_to_le32(*PCI_CFG_DATA); + } + tmp &= ~(0xffff << ((offset & 0x3) * 8)); + tmp |= (val << ((offset & 0x3) * 8)); + if (dev != 0) { + *PCI_CFG_DATA = tmp; + } else { + *PCI_CFG_DATA = cpu_to_le32(tmp); + } + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_write_config_byte(unsigned char bus, unsigned char dev, + unsigned char offset, unsigned char val) +{ + unsigned long tmp; + + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + PCI_CFG_SET(dev, 0, (offset & ~0x3)); + if (dev != 0) { + tmp = *PCI_CFG_DATA; + } else { + tmp = cpu_to_le32(*PCI_CFG_DATA); + } + tmp &= ~(0xff << ((offset & 0x3) * 8)); + tmp |= (val << ((offset & 0x3) * 8)); + *PCI_CFG_DATA = cpu_to_le32(tmp); + return PCIBIOS_SUCCESSFUL; +} + + +/******************************************************************** + * eth_pci_init - Fill pci_devi + * + *Inputs : + *bus - bus number + *dev - device number + *offset - register offset in the configuration space + *val - value to be written / read + * + *Outputs : + *Sucees/Failure + *********************************************************************/ +void eth_pci_init(struct pci_device *pcidev) +{ + int i, count; + pcibios_write_config_word(0, 0, 4, 0x7); + pcibios_write_config_dword(0, 8, BAR0, 0x12000000); + pcibios_write_config_dword(0, 8, BAR1, 0x10000001); + pcibios_write_config_dword(0, 8, BAR2, 0x12100000); + strcpy(pci0_devices[0].type, "Network Controller"); + pci0_devices[0].deviceNum = 8; + pci0_devices[0].venID = 0x8086; + pci0_devices[0].deviceID = 0x1229; + + pci0_devices[0].bar0Base = 0x12000000; + pci0_devices[0].bar0Size = 0x00001000; + pci0_devices[0].bar0Type = 0; + pci0_devices[0].bar1Base = 0x10000000; + pci0_devices[0].bar1Size = 0x40; + pci0_devices[0].bar1Type = 1; + pci0_devices[0].bar2Base = 0x12100000; + pci0_devices[0].bar2Size = 0x00100000; + pci0_devices[0].bar2Type = 0; + for (i = 0; pcidev[i].vendor != 0; i++) { + /* Look for device in PCI0 first */ + for (count = 0; count < MAX_PCI_DEVS; count++) { + if ((pci0_devices[count].type[0] != 0) + && ((unsigned short) pci0_devices[count]. + venID == (unsigned short) pcidev[i].vendor) + && ((unsigned short) pci0_devices[count]. + deviceID == + (unsigned short) pcidev[i].dev_id)) { + if ((pci0_devices[count].bar0Type == 1) + && (pci0_devices[count].bar0Size != 0)) + pcidev[i].ioaddr = + pci0_devices[count].bar0Base; + if ((pci0_devices[count].bar1Type == 1) + && (pci0_devices[count].bar1Size != 0)) + pcidev[i].ioaddr = + pci0_devices[count].bar1Base; + if ((pci0_devices[count].bar2Type == 1) + && (pci0_devices[count].bar2Size != 0)) + pcidev[i].ioaddr = + pci0_devices[count].bar2Base; + if ((pci0_devices[count].bar3Type == 1) + && (pci0_devices[count].bar3Size != 0)) + pcidev[i].ioaddr = + pci0_devices[count].bar3Base; + if ((pci0_devices[count].bar4Type == 1) + && (pci0_devices[count].bar4Size != 0)) + pcidev[i].ioaddr = + pci0_devices[count].bar4Base; + if ((pci0_devices[count].bar5Type == 1) + && (pci0_devices[count].bar5Size != 0)) + pcidev[i].ioaddr = + pci0_devices[count].bar5Base; + + if ((pci0_devices[count].bar0Type == 0) + && (pci0_devices[count].bar0Size != 0)) + pcidev[i].membase = + pci0_devices[count].bar0Base; + if ((pci0_devices[count].bar1Type == 0) + && (pci0_devices[count].bar1Size != 0)) + pcidev[i].membase = + pci0_devices[count].bar1Base; + if ((pci0_devices[count].bar2Type == 0) + && (pci0_devices[count].bar2Size != 0)) + pcidev[i].membase = + pci0_devices[count].bar2Base; + if ((pci0_devices[count].bar3Type == 0) + && (pci0_devices[count].bar3Size != 0)) + pcidev[i].membase = + pci0_devices[count].bar3Base; + if ((pci0_devices[count].bar4Type == 0) + && (pci0_devices[count].bar4Size != 0)) + pcidev[i].membase = + pci0_devices[count].bar4Base; + if ((pci0_devices[count].bar5Type == 0) + && (pci0_devices[count].bar5Size != 0)) + pcidev[i].membase = + pci0_devices[count].bar5Base; + pcidev[i].bus = 0; + pcidev[i].devfn = + pci0_devices[count].deviceNum; + } +#ifdef CONFIG_EVB_PCI1 + if ((pci1_devices[count].type[0] != 0) + && (pci1_devices[count].venID == + pcidev[i].vendor) + && (pci1_devices[count].deviceID == + pcidev[i].dev_id)) { + if ((pci1_devices[count].bar0Type == 1) + && (pci1_devices[count].bar0Size != 0)) + pcidev[i].ioaddr = + pci1_devices[count].bar0Base; + if ((pci1_devices[count].bar1Type == 1) + && (pci1_devices[count].bar1Size != 0)) + pcidev[i].ioaddr = + pci1_devices[count].bar1Base; + if ((pci1_devices[count].bar2Type == 1) + && (pci1_devices[count].bar2Size != 0)) + pcidev[i].ioaddr = + pci1_devices[count].bar2Base; + if ((pci1_devices[count].bar3Type == 1) + && (pci1_devices[count].bar3Size != 0)) + pcidev[i].ioaddr = + pci1_devices[count].bar3Base; + if ((pci1_devices[count].bar4Type == 1) + && (pci1_devices[count].bar4Size != 0)) + pcidev[i].ioaddr = + pci1_devices[count].bar4Base; + if ((pci1_devices[count].bar5Type == 1) + && (pci1_devices[count].bar5Size != 0)) + pcidev[i].ioaddr = + pci1_devices[count].bar5Base; + + if ((pci1_devices[count].bar0Type == 0) + && (pci1_devices[count].bar0Size != 0)) + pcidev[i].membase = + pci1_devices[count].bar0Base; + if ((pci1_devices[count].bar1Type == 0) + && (pci1_devices[count].bar1Size != 0)) + pcidev[i].membase = + pci1_devices[count].bar1Base; + if ((pci1_devices[count].bar2Type == 0) + && (pci1_devices[count].bar2Size != 0)) + pcidev[i].membase = + pci1_devices[count].bar2Base; + if ((pci1_devices[count].bar3Type == 0) + && (pci1_devices[count].bar3Size != 0)) + pcidev[i].membase = + pci1_devices[count].bar3Base; + if ((pci1_devices[count].bar4Type == 0) + && (pci1_devices[count].bar4Size != 0)) + pcidev[i].membase = + pci1_devices[count].bar4Base; + if ((pci1_devices[count].bar5Type == 0) + && (pci1_devices[count].bar5Size != 0)) + pcidev[i].membase = + pci1_devices[count].bar5Base; + + pcidev[i].bus = 1; + pcidev[i].devfn = + pci1_devices[count].deviceNum; + } +#endif + } + } +} diff --git a/arch/mips/galileo-boards/ev64120/compressed/pci_etherboot.h b/arch/mips/galileo-boards/ev64120/compressed/pci_etherboot.h new file mode 100644 index 000000000..484062bd8 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/pci_etherboot.h @@ -0,0 +1,144 @@ +#ifndef PCI_H +#define PCI_H + +/* +** Support for NE2000 PCI clones added David Monro June 1997 +** Generalised for other PCI NICs by Ken Yap July 1997 +** +** Most of this is taken from: +** +** /usr/src/linux/drivers/pci/pci.c +** /usr/src/linux/include/linux/pci.h +** /usr/src/linux/arch/i386/bios32.c +** /usr/src/linux/include/linux/bios32.h +** /usr/src/linux/drivers/net/ne.c +*/ + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2, or (at + * your option) any later version. + */ + +#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ +#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */ +#define PCI_LATENCY_TIMER 0x0d /* 8 bits */ + + +#define PCI_VENDOR_ID 0x00 /* 16 bits */ +#define PCI_DEVICE_ID 0x02 /* 16 bits */ +#define PCI_COMMAND 0x04 /* 16 bits */ + +#define PCI_CLASS_CODE 0x0b /* 8 bits */ +#define PCI_SUBCLASS_CODE 0x0a /* 8 bits */ +#define PCI_HEADER_TYPE 0x0e /* 8 bits */ + +#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */ +#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits */ +#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits */ +#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */ +#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */ +#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */ + +#ifndef PCI_BASE_ADDRESS_IO_MASK +#define PCI_BASE_ADDRESS_IO_MASK (~0x03) +#endif +#define PCI_BASE_ADDRESS_SPACE_IO 0x01 +#define PCI_ROM_ADDRESS 0x30 /* 32 bits */ +#define PCI_ROM_ADDRESS_ENABLE 0x01 /* Write 1 to enable ROM, + bits 31..11 are address, + 10..2 are reserved */ + +#define PCI_FUNC(devfn) ((devfn) & 0x07) + +#define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24)) + +/* PCI signature: "PCI " */ +#define PCI_SIGNATURE (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24)) + +/* PCI service signature: "$PCI" */ +#define PCI_SERVICE (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24)) + +#define KERN_CODE_SEG 0x8 /* This _MUST_ match start.S */ + +#define PCI_VENDOR_ID_REALTEK 0x10ec +#define PCI_DEVICE_ID_REALTEK_8029 0x8029 +#define PCI_DEVICE_ID_REALTEK_8139 0x8139 +#define PCI_VENDOR_ID_WINBOND2 0x1050 +#define PCI_DEVICE_ID_WINBOND2_89C940 0x0940 +#define PCI_VENDOR_ID_COMPEX 0x11f6 +#define PCI_DEVICE_ID_COMPEX_RL2000 0x1401 +#define PCI_VENDOR_ID_KTI 0x8e2e +#define PCI_DEVICE_ID_KTI_ET32P2 0x3000 +#define PCI_VENDOR_ID_NETVIN 0x4a14 +#define PCI_DEVICE_ID_NETVIN_NV5000SC 0x5000 +#define PCI_VENDOR_ID_3COM 0x10b7 +#define PCI_DEVICE_ID_3COM_3C900TPO 0x9000 +#define PCI_DEVICE_ID_3COM_3C900COMBO 0x9001 +#define PCI_DEVICE_ID_3COM_3C905TX 0x9050 +#define PCI_DEVICE_ID_3COM_3C905T4 0x9051 +#define PCI_DEVICE_ID_3COM_3C905B_TX 0x9055 +#define PCI_DEVICE_ID_3COM_3C905C_TXM 0x9200 +#define PCI_VENDOR_ID_INTEL 0x8086 +#define PCI_DEVICE_ID_INTEL_82557 0x1229 +#define PCI_VENDOR_ID_AMD 0x1022 +#define PCI_DEVICE_ID_AMD_LANCE 0x2000 +#define PCI_VENDOR_ID_SMC_1211 0x1113 +#define PCI_DEVICE_ID_SMC_1211 0x1211 +#define PCI_VENDOR_ID_DEC 0x1011 +#define PCI_DEVICE_ID_DEC_TULIP 0x0002 +#define PCI_DEVICE_ID_DEC_TULIP_FAST 0x0009 +#define PCI_DEVICE_ID_DEC_TULIP_PLUS 0x0014 +#define PCI_DEVICE_ID_DEC_21142 0x0019 +#define PCI_VENDOR_ID_SMC 0x10B8 +#ifndef PCI_DEVICE_ID_SMC_EPIC100 +# define PCI_DEVICE_ID_SMC_EPIC100 0x0005 +#endif +#define PCI_VENDOR_ID_MACRONIX 0x10d9 +#define PCI_DEVICE_ID_MX987x5 0x0531 +#define PCI_VENDOR_ID_LINKSYS 0x11AD +#define PCI_DEVICE_ID_LC82C115 0xC115 +#define PCI_VENDOR_ID_VIATEC 0x1106 +#define PCI_DEVICE_ID_VIA_RHINE_I 0x3043 +#define PCI_DEVICE_ID_VIA_86C100A 0x6100 +#define PCI_VENDOR_ID_DAVICOM 0x1282 +#define PCI_DEVICE_ID_DM9102 0x9102 + +struct pci_device { + unsigned short vendor, dev_id; + const char *name; + unsigned int membase; + unsigned int ioaddr; + unsigned short devfn; + unsigned short bus; +}; + +extern void eth_pci_init(struct pci_device *); +int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned char *val); +int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned short *val); +int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned int *val); +int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned char val); +int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned short val); +int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned int val); + +/* + * Error values that may be returned by the PCI bios. + */ +#define PCIBIOS_SUCCESSFUL 0x00 +#define PCIBIOS_FUNC_NOT_SUPPORTED 0x81 +#define PCIBIOS_BAD_VENDOR_ID 0x83 +#define PCIBIOS_DEVICE_NOT_FOUND 0x86 +#define PCIBIOS_BAD_REGISTER_NUMBER 0x87 +#define PCIBIOS_SET_FAILED 0x88 +#define PCIBIOS_BUFFER_TOO_SMALL 0x89 + + + +#endif /* PCI_H */ diff --git a/arch/mips/galileo-boards/ev64120/compressed/sbd.h b/arch/mips/galileo-boards/ev64120/compressed/sbd.h new file mode 100644 index 000000000..a5849db1f --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/sbd.h @@ -0,0 +1,52 @@ +/* + * sbd.h: cpu board definitions for Galileo-9 + * Copyright (c) 1997 Algorithmics Ltd + */ + +#ifndef MHZ +/* fastest possible pipeline clock */ +#define MHZ 150 +#endif + +/* FIXME These timings are completely fictional */ +#define RAMCYCLE 60 /* 60ns dram cycle */ +#define ROMCYCLE 750 /* ~750ns rom cycle */ +#define CACHECYCLE (1000/MHZ) /* internal clock */ +#define CYCLETIME CACHECYCLE +#define CACHEMISS (CYCLETIME * 6) + +/* + * rough scaling factors for 2 instruction DELAY loop to get 1ms and 1us delays + */ +#define ASMDELAY(ns,icycle) \ + (((ns) + (icycle)) / ((icycle) * 2)) + +#define CACHEUS ASMDELAY(1000, CACHECYCLE) +#define RAMUS ASMDELAY(1000, CACHEMISS+RAMCYCLE) +#define ROMUS ASMDELAY(1000, CACHEMISS+ROMCYCLE) +#define CACHEMS ASMDELAY(1000000, CACHECYCLE) +#define RAMMS ASMDELAY(1000000, CACHEMISS+RAMCYCLE) +#define ROMMS ASMDELAY(1000000, CACHEMISS+ROMCYCLE) + +#ifndef __ASSEMBLER__ +#define nsdelay(ns) mips_cycle (ASMDELAY (ns, CACHECYCLE)) +#define usdelay(us) mips_cycle (ASMDELAY ((us)*1000, CACHECYCLE)) +#endif + +#define DRAM_BASE 0x00000000 +#define PCI_IO_BASE 0x10000000 +#define PCI_IO_SIZE 0x02000000 +#define PCI_MEM_BASE 0x12000000 +#define PCI_MEM_SIZE 0x02000000 +#define GT64011_BASE 0x14000000 +#define DUART_BASE 0x1d000000 +#define FLASH_BASE 0x1f000000 +#define PROM_BASE 0x1fc00000 + + +#define LOCAL_MEM DRAM_BASE +#define LOCAL_MEM_SIZE (128*1024*1024) /* SDRAM size (16MB) */ + +#define BOOTPROM_BASE PROM_BASE + +#define DUART_CLOCK 3686400 diff --git a/arch/mips/galileo-boards/ev64120/compressed/sbdreset_evb64120A.S b/arch/mips/galileo-boards/ev64120/compressed/sbdreset_evb64120A.S new file mode 100644 index 000000000..0f612aae5 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/sbdreset_evb64120A.S @@ -0,0 +1,1054 @@ +/* $Id: sbdreset_evb64120A.S,v 1.1 2000/11/21 00:48:25 stevej Exp $ */ +/* +** Copyright 1997 Algorithmics Ltd +** All Rights Reserved +** +** gal9/sbdreset.sx -- low level board dependent routines +*/ + +#ifdef EVB64120A +//#include <mips.h> +//#include <pmon.h> +#include <linux/config.h> + +#include <asm/asm.h> +#include <asm/regdef.h> +#include <asm/cacheops.h> +#include <asm/current.h> +#include <asm/offset.h> +#include <asm/processor.h> +#include <asm/regdef.h> +#include <asm/cachectl.h> +#include <asm/mipsregs.h> +#include <asm/stackframe.h> +#include <asm/bootinfo.h> +#include <asm/cpu.h> +#include "sbd.h" + + +#include "gt64011.h" +#include "ns16550.h" + +#ifdef GALILEO_PORT // miniBios crack +#define C0_CONFIG CP0_CONFIG +#define C0_STATUS CP0_STATUS +#define C0_TLBLO0 CP0_ENTRYLO0 +#define C0_TLBLO1 CP0_ENTRYLO1 +#define C0_PGMASK CP0_PAGEMASK +#define C0_TLBHI CP0_ENTRYHI +#define C0_INX CP0_INDEX +#define NTLBENTRIES 48 + + +#define CFG_IB CONF_IB +#define CFG_DB CONF_DB +#define CFG_C_NONCOHERENT CONF_CM_CACHABLE_NONCOHERENT +#define C0_SR CP0_STATUS +#define SR_DE ST0_DE + + + #define SLEAF(x) LEAF(x) + #define SEND(x) END(x) + #define XLEAF(x) LEAF(x) + #define SBD_DISPLAY(a,b,c,d,e) ; + +#define K0BASE 0x80000000 +#define K0SIZE 0x20000000 +#define K1BASE 0xa0000000 +#define K1SIZE 0x20000000 +#define K2BASE 0xc0000000 + +#define PHYS_TO_K0(pa) ((pa)|K0BASE) +#define PHYS_TO_K1(pa) ((pa)|K1BASE) +#define K0_TO_PHYS(va) ((va)&(K0SIZE-1)) +#define K1_TO_PHYS(va) ((va)&(K1SIZE-1)) +#define K0_TO_K1(va) ((va)|K1SIZE) +#define K1_TO_K0(va) ((va)&~K1SIZE) + +#define PA_TO_KVA0(pa) PHYS_TO_K0(pa) +#define PA_TO_KVA1(pa) PHYS_TO_K1(pa) +#define KVA_TO_PA(pa) K1_TO_PHYS(pa) +#define KSEG0_BASE K0BASE +#define KSEG1_BASE K1BASE + + +#endif + +#define MB 0x100000 + +#define MemTypeNone 0x8000 +#define MemRasMask 0x0f00 +#define MemRasShift 8 +#define MemCasMask 0x000f +#define MemCasShift 0 + +#define rasave s0 +#define p64011 s1 +#define bank0 s2 +#define bank1 s3 +#define bank2 s4 +#define bank3 s5 +#define memtop s6 +#define membase s7 + +/*#if #endian(big) */ +#ifdef __MIPSEB__ + +#define HTOLL(sr,tr) \ + .set noat ; \ + srl AT,sr,24 ; \ + srl tr,sr,8 ; \ + and tr,0xff00 ; \ + or AT,tr ; \ + and tr,sr,0xff00 ; \ + sll tr,8 ; \ + or AT,tr ; \ + sll tr,sr,24 ; \ + or sr,AT,tr ; \ + .set at +#else +#define HTOLL(sr,tr) +#endif + +#undef DBGSBD + +#ifdef DBGSBD +#define DBG(s) \ + .rdata ; \ +88: .asciiz s ; \ + .text ; \ + la a0, 88b ; \ + jal _dbgmsg + +LEAF(_dbgmsg) + .set noat + li AT,PHYS_TO_K1(NS16550_CHANB) +waitrdy: + lbu v1,LSR(AT) + .set noreorder; nop; nop; nop; nop; nop; nop; nop; nop; .set reorder + and v1,LSR_TXRDY + beqz v1,waitrdy + + lbu v1,(a0) + addu a0,1 + beqz v1,9f + sb v1,DATA(AT) + .set noreorder; nop; nop; nop; nop; nop; nop; nop; nop; .set reorder + b waitrdy +9: j ra + .set at +END(_dbgmsg) + +LEAF(_dbghex) + li a1,PHYS_TO_K1(NS16550_CHANB) + li t0,8 +1: + lbu t1,LSR(a1) + .set noreorder; nop; nop; nop; nop; nop; nop; nop; nop; .set reorder + and t1,LSR_TXRDY + beqz t1,1b + + srl t1,a0,28 + addu t1,'0' + ble t1,'9',2f + addu t1,'a'-'0'-10 +2: sb t1,DATA(a1) + .set noreorder; nop; nop; nop; nop; nop; nop; nop; nop; .set reorder + + sll a0,4 + sub t0,1 + bnez t0,1b + + j ra + .set at +END(_dbghex) + + .rdata +initb_str: + .byte 9,0x40 /* Reset CH B */ + .byte 1,0x00 /* Interrupt disabled */ + .byte 3,0xc1 /* 8 bits/char rx enable */ + .byte 4,0x44 /* x16 clk mode 1 stop bit */ + .byte 5,0x6a /* tx 8/bit RTS & tx enable */ + .byte 9,0x0a /* MIE Master int enab. and NV No Vector */ + .byte 11,0x50 /* Select BR gen. out for both rx and ts */ + .byte 0,0x10 + .byte 0,0x10 + .byte 14,0x01 /* enable baud rate gen. */ + .byte 15,0x00 /* known state for reg 15 */ + + .byte 14,0x00 /* disable baud rate gen. */ + .byte 12,0x0a /* 0x0a = 9600 baud time const. - lower 8 bits */ + .byte 13,0x00 /* 9600 buad time const. - upper 8 bits */ + .byte 14,0x01 /* enable baud rate gen. */ + .byte 0xff + + .text + +SLEAF(_dbginit) + /* + li v0,PHYS_TO_K1(NS16550_CHANB) + la a0,initb_str + or a0,K1BASE +1: lbu t0,0(a0) + beq t0,0xff,1f + sb t0,LSR(v0) + .set noreorder; nop; nop; nop; nop; nop; nop; nop; nop; .set reorder + addu a0,1 + b 1b + */ + jal init_ns16550_chan_b # Debug channel + j ra +SEND(_dbginit) +#else +#define DBG(s) +#endif + +LEAF(sbdreset) + move rasave,ra + + /* if launched by ITROM, leave Config alone */ +#ifndef ITBASE + /* set config register for 32b/32b cachelines, kseg0 cacheable */ + mfc0 t1,C0_CONFIG + and t1,~0x3f # set bits 5..0 only + or t1,CFG_IB | CFG_DB | CFG_C_NONCOHERENT + mtc0 t1,C0_CONFIG +#endif + + /* Initialize stack pointer to 6MB address */ + li sp,0xa0600000 + + + /* + * slight amount of kludgery here to stop RAM resident + * program from overwriting itself... + */ +// li v1,0x1fc00000 /* check return address is in ROM */ +// and v0,ra,v1 +// bne v0,v1,.noinit + + /* table driven hardware register initialization */ + la a0, reginittab + or a0, K1BASE /* force to kseg1 */ + +1: lw v0,0(a0) + lw v1,4(a0) + addu a0,8 + beqz v0,8f + + sw v1,0(v0) + b 1b +8: + +#ifdef DBGSBD + jal init_ns16550_chan_b # was - _dbginit + DBG("sbdreset\r\n") +#endif +#define DEVICE_BANK0PARAMETERS 0x45C +#define DEVICE_BANK1PARAMETERS 0x460 +#define DEVICE_BANK2PARAMETERS 0x464 +#define DEVICE_BANK3PARAMETERS 0x468 +#define DEVICE_BOOT_BANK_PARAMETERS 0x46C +#define GT_INTERNAL_REG_BASE 0xb4000000 + + li p64011, PA_TO_KVA1(GT64011_BASE) + + li v0,0xb400046c /* Boot Device */ + lw t0,0(v0) + and t0,0x00003000 /* Keep the correct boot size */ + or t0,htoll(0x3847de70) + sw t0,0(v0) + + li v0,0xb4000468 /* CS3 Device - 16 bit FLASH memory */ + li t0,htoll(0x3859e6e8) + sw t0,0(v0) + + + li v0,0xb4000c84 /* PCI 1 timeout register */ + li t0,htoll(0xffff) + sw t0,0(v0) + + + li v0,0xb4000c3c /* Enable I/O response on PCI0 */ + li t0,htoll(0x7) + sw t0,0(v0) + + li v0,0xb4000cbc /* Enable I/O response on PCI1 */ + li t0,htoll(0x7) + sw t0,0(v0) + + /* GT-64120 Initialization */ + + li p64011, PA_TO_KVA1(GT64011_BASE) + + /*********************************************************************/ + /************************* SDRAM initializing ************************/ + /******************************* START *******************************/ + + + /* SDRAM banks 0,1,2,3 parameters */ + li t0,htoll(0x01908200) /* - Standard Monitor: Interleave enabled */ + li v0,0xb4000448 /* - Registered SDRAM (Bit 23) */ + sw t0,0(v0) /* - Duplicate Dadr11,BankSel1 and Dadr12 */ + /* - Cas latency: 2 Cycles */ + /* - Flow Through enable: One sample */ + /* - SRAS - precharge time: 3 Cycles */ + /* - No ECC */ + /* - No ByPass */ + /* - Burst length: 8 */ + + /* Detect whether we have a 16,64,128 or 256 Mbit SDRAM on DIMM0 */ + /* Set bank0`s range to: 0 - 0x10000000 (256 MByte) */ +_DIMM0: + li v0,0xb4000008 + li t0,htoll(0x0) + sw t0,0(v0) + + li v0,0xb4000010 + li t0,htoll(0x7f) + sw t0,0(v0) + + /* Close banks 2 and 3 */ + li v0,0xb4000018 + li t0,htoll(0x7ff) + sw t0,0(v0) + li v0,0xb4000020 + li t0,htoll(0x00) + sw t0,0(v0) + + /* Extend bank0 to 0x10000000 and Close bank1,2 and 3 */ + DBG("Extend bank0 to 0x10000000 and Close bank1,2 and 3...\r\n") + li v0,0xb4000400 + li t0,htoll(0x0) + sw t0,0(v0) + li v0,0xb4000404 + li t0,htoll(0xff) + sw t0,0(v0) + li v0,0xb4000408 + li t0,htoll(0xff) + sw t0,0(v0) + li v0,0xb400040c + li t0,htoll(0x00) + sw t0,0(v0) + li v0,0xb4000410 + li t0,htoll(0xff) + sw t0,0(v0) + li v0,0xb4000414 + li t0,htoll(0x00) + sw t0,0(v0) + li v0,0xb4000418 + li t0,htoll(0xff) + sw t0,0(v0) + li v0,0xb400041c + li t0,htoll(0x00) + sw t0,0(v0) + + /* Configure bank0 to 256 Mbit */ + DBG("Configure bank0 to 256 Mbit...\r\n") + li v0,0xb400044c + li t0,htoll(0x00004c69) + sw t0,0(v0) + + /* Config the SDRAM banks decode system */ + li v0,0xb400047c + li t0,htoll(2) + sw t0,0(v0) + + li v0,0xb4000474 + li t0,htoll(0x3) + sw t0,0(v0) + + li v0,0xa0000000 + li t0,0 + sw t0,0(v0) + + li v0,0xb4000474 + li t0,htoll(0x0) + sw t0,0(v0) + + /* Write to address 0x2000000 and check if 0x00000000 is being written too */ + DBG("Write to address 0x2000000 and check if 0x00000000 is being written too...\r\n") + li v0,0xa0000000 + li t1,0xa0000010 + li t0,htoll(0x0) +1: sw t0,0(v0) + addu v0,4 + bne t1,v0,1b + + /* The address should activate Dadr12 */ + li v0,0xa2000000 + li t0,0x11111111 + sw t0,0(v0) + li v0,0xa0000010 + li t1,0xa0000100 + li t0,0x22222222 +2: sw t0,0(v0) + addu v0,4 + bne t1,v0,2b + + DBG("Check address 0x00000000 for duplications...\r\n") + li t0,0xa0000000 + li v0,0x11111111 + lw t0,(t0) + bne t0,v0,_256MBIT + + /* Write to address 0x1000 and check if 0x00000000 is being written too */ + DBG("Write to address 0x1000 and check if 0x00000000 is being written too...\r\n") + li v0,0xa0000000 + li t1,0xa0000010 + li t0,htoll(0x0) +1: sw t0,0(v0) + addu v0,4 + bne t1,v0,1b + + /* The address should activate bank select1*/ + li v0,0xa0001000 + li t0,0x11111111 + sw t0,0(v0) + li v0,0xa0000010 + li t1,0xa0000100 + li t0,0x22222222 +2: sw t0,0(v0) + addu v0,4 + bne t1,v0,2b + + DBG("Check address 0x00000000 for duplications...\r\n") + li t0,0xa0000000 + li v0,0x11111111 + lw t0,(t0) + beq t0,v0,_16MBIT + + /* Write to address 0x8000000 and check if 0x00000000 is being written too */ + DBG("Write to address 0x8000000 and check if 0x00000000 is being written too...\r\n") + li v0,0xa0000000 + li t1,0xa0000010 + li t0,htoll(0x0) +1: sw t0,0(v0) + addu v0,4 + bne t1,v0,1b + + /* The address should activate Dadr9 which on the column cycle is in active with 64 Mbit + device */ + li v0,0xa8000000 + li t0,0x11111111 + sw t0,0(v0) + li v0,0xa0000010 + li t1,0xa0000100 + li t0,0x22222222 +2: sw t0,0(v0) + addu v0,4 + bne t1,v0,2b + + DBG("Check address 0x00000000 for duplications...\r\n") + li t0,0xa0000000 + li v0,0x11111111 + lw t0,(t0) + beq t0,v0,_64MBIT + b _128MBIT + +_16MBIT: + DBG("16 Mbit SDRAM detected...\r\n") + /* In 16 Mbit SDRAM we must use 2 way bank interleaving!!! */ + li v0,0xb4000810 + li t0,htoll(16) + sw t0,0(v0) + li t1,htoll(0x00000449) + b _DIMM1 + +_64MBIT: + DBG("64 Mbit SDRAM detected...\r\n") + /* In 64 Mbit SDRAM we must use 4 way bank interleaving!!! */ + li v0,0xb4000810 + li t0,htoll(64) + sw t0,0(v0) + li t1,htoll(0x00000c69) + b _DIMM1 + +_128MBIT: + DBG("128 Mbit SDRAM detected...\r\n") + /* In 128 Mbit SDRAM we must use 4 way bank interleaving!!! */ + li v0,0xb4000810 + li t0,htoll(128) + sw t0,0(v0) + li t1,htoll(0x00000c69) + b _DIMM1 + +_256MBIT: + DBG("256 Mbit SDRAM detected...\r\n") + /* In 256 Mbit SDRAM we must use 4 way bank interleaving!!! */ + li v0,0xb4000810 + li t0,htoll(256) + sw t0,0(v0) + li t1,htoll(0x00004c69) + b _DIMM1 + +_DIMM1: + li v0,0xb400044c + sw t1,0(v0) # Bank0 + sw t1,4(v0) # Bank1 + + /* Detect whether we have a 16,64,128 or 256 Mbit SDRAM on DIMM1 */ + /* Close banks 0 and 1 */ + li v0,0xb4000008 + li t0,htoll(0xff) + sw t0,0(v0) + + li v0,0xb4000010 + li t0,htoll(0x0) + sw t0,0(v0) + + /* Set bank2`s range to: 0 - 0x10000000 (256 MByte) */ + li v0,0xb4000018 + li t0,htoll(0x0) + sw t0,0(v0) + li v0,0xb4000020 + li t0,htoll(0x7f) + sw t0,0(v0) + + /* Extend bank2 to 0x10000000 and Close bank0,1 and 3 */ + DBG("Extend bank2 to 0x10000000 and Close banks 0,1 and 3...\r\n") + li v0,0xb4000400 + li t0,htoll(0xff) + sw t0,0(v0) + li v0,0xb4000404 + li t0,htoll(0x00) + sw t0,0(v0) + li v0,0xb4000408 + li t0,htoll(0xff) + sw t0,0(v0) + li v0,0xb400040c + li t0,htoll(0x00) + sw t0,0(v0) + li v0,0xb4000410 + li t0,htoll(0x00) + sw t0,0(v0) + li v0,0xb4000414 + li t0,htoll(0xff) + sw t0,0(v0) + li v0,0xb4000418 + li t0,htoll(0xff) + sw t0,0(v0) + li v0,0xb400041c + li t0,htoll(0x00) + sw t0,0(v0) + + /* Configure bank2 to 256 Mbit */ + DBG("Configure bank2 to 256 Mbit...\r\n") + li v0,0xb4000454 + li t0,htoll(0x00004c69) + sw t0,0(v0) + + /* Config the SDRAM banks decode system */ + li v0,0xb400047c + li t0,htoll(2) + sw t0,0(v0) + + li v0,0xb4000474 + li t0,htoll(0x3) + sw t0,0(v0) + + li v0,0xa0000000 + li t0,0 + sw t0,0(v0) + + li v0,0xb4000474 + li t0,htoll(0x0) + sw t0,0(v0) + + /* Write to address 0x2000000 and check if 0x00000000 is being written too */ + DBG("Write to address 0x2000000 and check if 0x00000000 is being written too...\r\n") + li v0,0xa0000000 + li t1,0xa0000010 + li t0,htoll(0x0) +1: sw t0,0(v0) + addu v0,4 + bne t1,v0,1b + + /* The address should activate Dadr12 */ + li v0,0xa2000000 + li t0,0x11111111 + sw t0,0(v0) + li v0,0xa0000010 + li t1,0xa0000100 + li t0,0x22222222 +2: sw t0,0(v0) + addu v0,4 + bne t1,v0,2b + + DBG("Check address 0x00000000 for duplications...\r\n") + li t0,0xa0000000 + li v0,0x11111111 + lw t0,(t0) + bne t0,v0,_256MBIT2 + + /* Write to address 0x1000 and check if 0x00000000 is being written too */ + DBG("Write to address 0x1000 and check if 0x00000000 is being written too...\r\n") + li v0,0xa0000000 + li t1,0xa0000010 + li t0,htoll(0x0) +1: sw t0,0(v0) + addu v0,4 + bne t1,v0,1b + + /* The address should activate bank select1*/ + li v0,0xa0001000 + li t0,0x11111111 + sw t0,0(v0) + li v0,0xa0000010 + li t1,0xa0000100 + li t0,0x22222222 +2: sw t0,0(v0) + addu v0,4 + bne t1,v0,2b + + DBG("Check address 0x00000000 for duplications...\r\n") + li t0,0xa0000000 + li v0,0x11111111 + lw t0,(t0) + beq t0,v0,_16MBIT2 + + /* Write to address 0x8000000 and check if 0x00000000 is being written too */ + DBG("Write to address 0x8000000 and check if 0x00000000 is being written too...\r\n") + li v0,0xa0000000 + li t1,0xa0000010 + li t0,htoll(0x0) +1: sw t0,0(v0) + addu v0,4 + bne t1,v0,1b + + /* The address should activate Dadr9 which on the column cycle is in active with 64 Mbit + device */ + li v0,0xa8000000 + li t0,0x11111111 + sw t0,0(v0) + li v0,0xa0000010 + li t1,0xa0000100 + li t0,0x22222222 +2: sw t0,0(v0) + addu v0,4 + bne t1,v0,2b + + DBG("Check address 0x00000000 for duplications...\r\n") + li t0,0xa0000000 + li v0,0x11111111 + lw t0,(t0) + beq t0,v0,_64MBIT2 + b _128MBIT2 + +_16MBIT2: + DBG("16 Mbit SDRAM detected...\r\n") + /* In 16 Mbit SDRAM we must use 2 way bank interleaving!!! */ + li v0,0xb4000814 + li t0,htoll(16) + sw t0,0(v0) + li t1,htoll(0x00000449) + b _INIT_SDRAM + +_64MBIT2: + DBG("64 Mbit SDRAM detected...\r\n") + /* In 64 Mbit SDRAM we must use 4 way bank interleaving!!! */ + li v0,0xb4000814 + li t0,htoll(64) + sw t0,0(v0) + li t1,htoll(0x00000c69) + b _INIT_SDRAM + +_128MBIT2: + DBG("128 Mbit SDRAM detected...\r\n") + /* In 128 Mbit SDRAM we must use 4 way bank interleaving!!! */ + li v0,0xb4000814 + li t0,htoll(128) + sw t0,0(v0) + li t1,htoll(0x00000c69) + b _INIT_SDRAM + +_256MBIT2: + DBG("256 Mbit SDRAM detected...\r\n") + /* In 256 Mbit SDRAM we must use 4 way bank interleaving!!! */ + li v0,0xb4000814 + li t0,htoll(256) + sw t0,0(v0) + li t1,htoll(0x00004c69) + b _INIT_SDRAM + +_INIT_SDRAM: + /* Restore defaults */ + DBG("Restoring defaults...\r\n") + li v0,0xb4000404 + li t0,htoll(0x07) + sw t0,0(v0) + li v0,0xb4000408 + li t0,htoll(0x08) + sw t0,0(v0) + li v0,0xb400040c + li t0,htoll(0x0f) + sw t0,0(v0) + li v0,0xb4000410 + li t0,htoll(0x10) + sw t0,0(v0) + li v0,0xb4000414 + li t0,htoll(0x17) + sw t0,0(v0) + li v0,0xb4000418 + li t0,htoll(0x18) + sw t0,0(v0) + li v0,0xb400041c + li t0,htoll(0x1f) + sw t0,0(v0) + li v0,0xb4000010 + li t0,htoll(0x07) + sw t0,0(v0) + li v0,0xb4000018 + li t0,htoll(0x008) + sw t0,0(v0) + li v0,0xb4000020 + li t0,htoll(0x0f) + sw t0,0(v0) + + li v0,0xb400044c + sw t1,8(v0) # Bank2 + sw t1,12(v0) # Bank3 + + li v0,0xb4000474 + li t0,htoll(0x3) + sw t0,0(v0) + + li v0,0xa0000000 + li t0,0 + sw t0,0(v0) + + li v0,0xb4000474 + li t0,htoll(0x0) + sw t0,0(v0) + + li v0,0xb4000474 + li t0,htoll(0x3) + sw t0,0(v0) + + li v0,0xa0800000 + li t0,0 + sw t0,0(v0) + + li v0,0xb4000474 + li t0,htoll(0x0) + sw t0,0(v0) + + li v0,0xb4000474 + li t0,htoll(0x3) + sw t0,0(v0) + + li v0,0xa1000000 + li t0,0 + sw t0,0(v0) + + li v0,0xb4000474 + li t0,htoll(0x0) + sw t0,0(v0) + + li v0,0xb4000474 + li t0,htoll(0x3) + sw t0,0(v0) + + li v0,0xa1800000 + li t0,0 + sw t0,0(v0) + + li v0,0xb4000474 + li t0,htoll(0x0) + sw t0,0(v0) + + /*********************************************************************/ + /************************* SDRAM initializing ************************/ + /******************************* END *********************************/ + + li p64011, PA_TO_KVA1(GT64011_BASE) + + li t0,htoll(0x00000000) /* RAS[1:0] low decode address */ + sw t0,0x008(p64011) + + li t0,htoll(0x00000007) /* RAS[1:0] high decode address */ + sw t0,0x010(p64011) + + li t0,htoll(0x00000000) /* RAS[0] Low decode address */ + sw t0,0x400(p64011) + + li t0,htoll(0x0000000f) /* RAS[0] High decode address */ + sw t0,0x404(p64011) + + li t0,htoll(0x00000008) /* RAS[3:2] low decode address */ + sw t0,0x018(p64011) + + li t0,htoll(0x0000000f) /* RAS[3:2] high decode address */ + sw t0,0x020(p64011) + + li t0,htoll(0x0000000f) /* RAS[1] Low Decode Address */ + sw t0,0x408(p64011) + + li t0,htoll(0x00000008) /* RAS[1] High Decode Address */ + sw t0,0x40c(p64011) + + li t0,htoll(0x00000010) /* RAS[2] Low Decode Address */ + sw t0,0x410(p64011) + + li t0,htoll(0x00000017) /* RAS[2] High Decode Address */ + sw t0,0x414(p64011) + + li t0,htoll(0x00000018) /* RAS[3] Low Decode Address */ + sw t0,0x418(p64011) + + li t0,htoll(0x0000001f) /* RAS[3] High Decode Address <<<<<< 1*/ + sw t0,0x41c(p64011) + +#ifdef DBGSBD +#define DREG(str,rname) \ + DBG(str); \ + DBG(":\t") ; \ + lw a0,rname(p64011) ; \ + HTOLL(a0,t0) ; \ + jal _dbghex ; \ + DBG("\r\n") + + DBG("GT-64120 settings:\r\n") + DREG("DRAMPAR_BANK0 (44c)",GT_DRAMPAR_BANK0) + DREG("DRAMPAR_BANK1 (450)",GT_DRAMPAR_BANK1) + DREG("DRAMPAR_BANK2 (454)",GT_DRAMPAR_BANK2) + DREG("DRAMPAR_BANK3 (458)",GT_DRAMPAR_BANK3) + DREG("PAS_RAS10LO (008)",GT_PAS_RAS10LO) + DREG("PAS_RAS10HI (010)",GT_PAS_RAS10HI) + DREG("PAS_RAS32LO (018)",GT_PAS_RAS32LO) + DREG("PAS_RAS32HI (020)",GT_PAS_RAS32HI) + DREG("DDAS_RAS0LO (400)",GT_DDAS_RAS0LO) + DREG("DDAS_RAS0HI (404)",GT_DDAS_RAS0HI) + DREG("DDAS_RAS1LO (408)",GT_DDAS_RAS1LO) + DREG("DDAS_RAS1HI (40c)",GT_DDAS_RAS1HI) + DREG("DDAS_RAS2LO (410)",GT_DDAS_RAS2LO) + DREG("DDAS_RAS2HI (414)",GT_DDAS_RAS2HI) + DREG("DDAS_RAS3LO (418)",GT_DDAS_RAS3LO) + DREG("DDAS_RAS3HI (41c)",GT_DDAS_RAS3HI) + DREG("GT_DRAM_CFG (448)",GT_DRAM_CFG) + DREG("GT_DEVPAR_BANK0 (45c)",GT_DEVPAR_BANK0) + DREG("GT_DEVPAR_BANK1 (460)",GT_DEVPAR_BANK1) + DREG("GT_DEVPAR_BANK2 (464)",GT_DEVPAR_BANK2) + DREG("GT_DEVPAR_BANK3 (468)",GT_DEVPAR_BANK3) + DREG("GT_IPCI_TOR (c04)",GT_IPCI_TOR) +#endif + + /* we can now initialise the caches for a fast clear_mem */ + SBD_DISPLAY ('C','A','C','H',CHKPNT_CACH) + DBG("init_cache\r\n") +// jal mips_init_cache + +.noinit: + + /* initialise tlb */ + SBD_DISPLAY ('I','T','L','B', CHKPNT_ITLB) + DBG("init_tlb\r\n") +// bal init_tlb + +// DBG("sbdreset completed\r\n") +// move ra,rasave + j GetExtendedMemorySize + nop + +END(sbdreset) + +LEAF(_sbd_memfail) + SBD_DISPLAY ('!','M','E','M',CHKPNT_0MEM) +1: b 1b + j ra +END(_sbd_memfail) + + .rdata +RefreshBits: + .word htoll(GT_DRAMPAR_Refresh512) + .word htoll(GT_DRAMPAR_Refresh1024) + .word htoll(GT_DRAMPAR_Refresh2048) + .word htoll(GT_DRAMPAR_Refresh4096) + .text + +/* DRAM: */ +#define GT_DRAM_CFG_INIT \ + GT_DRAM_CFG_RefIntCnt(160) | \ + GT_DRAM_CFG_StagRefOn | \ + GT_DRAM_CFG_ADSFunctDRAM | \ + GT_DRAM_CFG_DRAMLatchActive + +/* serial port: widest timings even 8 bit bus, latch enabled no parity */ +#define GT_DEVPAR_SERIALINIT \ + GT_DEVPAR_TurnOff(7) | \ + GT_DEVPAR_AccToFirst(15) | \ + GT_DEVPAR_AccToNext(15) | \ + GT_DEVPAR_ADStoWr(7) | \ + GT_DEVPAR_WrActive(7) | \ + GT_DEVPAR_WrHigh(7) | \ + GT_DEVPAR_DevWidth8 | \ + GT_DEVPAR_DevLocEven | \ + GT_DEVPAR_LatchFunctTransparent | \ + GT_DEVPAR_ParityDisable | \ + GT_DEVPAR_Reserved + +/* PCI: */ +#define GT_IPCI_TOR_INIT \ + GT_IPCI_TOR_Timeout0(255) | \ + GT_IPCI_TOR_Timeout1(255) | \ + GT_IPCI_TOR_RetryCtr(0) + +#define INIT(addr,val) \ + .word addr, val +#define GTINIT(addr,val) \ + INIT(PHYS_TO_K1(GT64011_BASE+(addr)), htoll(val)) + + .rdata +reginittab: + + /* disable ras1:0 and ras3:2 decodes */ + GTINIT(GT_PAS_RAS10LO, GT_PAS_LOMASK_Low); + GTINIT(GT_PAS_RAS10HI, 0); + GTINIT(GT_PAS_RAS32LO, GT_PAS_LOMASK_Low); + GTINIT(GT_PAS_RAS32HI, 0); + + /* disable RAS[0123] */ + GTINIT(GT_DDAS_RAS0LO, GT_DDAS_LOMASK_Low) + GTINIT(GT_DDAS_RAS0HI, 0); + GTINIT(GT_DDAS_RAS1LO, GT_DDAS_LOMASK_Low) + GTINIT(GT_DDAS_RAS1HI, 0); + GTINIT(GT_DDAS_RAS2LO, GT_DDAS_LOMASK_Low) + GTINIT(GT_DDAS_RAS2HI, 0); + GTINIT(GT_DDAS_RAS3LO, GT_DDAS_LOMASK_Low) + GTINIT(GT_DDAS_RAS3HI, 0); + + /* 0x45c, 0x460, 0x464, 0x468 */ + /*GTINIT(GT_DEVPAR_BANK0, GT_DEVPAR_SERIALINIT)*/ + GTINIT(GT_DEVPAR_BANK0, 0x3847de60) + GTINIT(GT_DEVPAR_BANK1, 0x146fffff) + GTINIT(GT_DEVPAR_BANK2, 0x144fffff) + GTINIT(GT_DEVPAR_BANK3, 0x167fffff) + + GTINIT(GT_IPCI_TOR, GT_IPCI_TOR_INIT) + INIT(0,0) + .text + + .globl sbddelay + +LEAF(sbdberrenb) + mfc0 v0,C0_SR + li t0,SR_DE + bnez a0,1f + or t1,v0,t0 # disable cache/parity errors (SR_DE = 1) + b 2f +1: not t1,t0 # enable cache/parity errors (SR_DE = 0) + and t1,v0 +2: mtc0 t1,C0_SR + and v0,t0 # get old SR_DE bit + xor v0,t0 # and invert to make it an enable bit + j ra +END(sbdberrenb) + + +LEAF(sbdberrcnt) + move v0,zero + j ra +END(sbdberrcnt) + + .lcomm wbfltmp,4 + +LEAF(wbflush) +//XLEAF(mips_wbflush) + sync + la t0,wbfltmp + or t0,K1BASE + lw zero,0(t0) + j ra +END(wbflush) + + +LEAF(sbddelay) + li t1,CACHEUS + and t0,ra,0x20000000 + beqz t0,1f + li t1,ROMUS +1: mul a0,t1 + subu a0,15 # approx number of loops so far + + .set noreorder + .set nomacro + nop +2: bgtz a0,2b + subu a0,1 + .set macro + .set reorder + + j ra +END(sbddelay) + +#include "meminit.S" + + +LEAF(mips_cycle) + .set noreorder + .set nomacro +1: bgtz a0,1b + subu a0,1 + .set macro + .set reorder + j ra +END(mips_cycle) + +LEAF(init_ns16550_chan_b) + # enable 16550 fifo if it is there + li a0,NS16550_CHANB + li t0,FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_4 + sb t0,FIFO(a0) + + /* convert baud rate in a1 into register value */ + li t2,NS16550_HZ/(16*115200) # brtc = CLK/16/speed + + li t0,CFCR_DLAB # select brtc divisor + sb t0,CFCR(a0) + sb t2,DATA(a0) # store divisor lsb + srl t2,8 + sb t2,IER(a0) # store divisor msb + + li t0,CFCR_8BITS # set 8N1 mode + sb t0,CFCR(a0) + + li t0,MCR_DTR|MCR_RTS # Galileo |MCR_IENABLE # enable DTR & RTS + sb t0,MCR(a0) + li t0,0 # Galileo IER_ERXRDY # enable receive interrupt(!) + sb t0,IER(a0) + + move v0,zero # indicate success + j ra + +END(init_ns16550_chan_b) + +LEAF(init_ns16550_chan_a) + # enable 16550 fifo if it is there + li a0,NS16550_CHANA + li t0,FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_4 + sb t0,FIFO(a0) + + /* convert baud rate in a1 into register value */ + li t2,NS16550_HZ/(16*9600) # brtc = CLK/16/speed + + li t0,CFCR_DLAB # select brtc divisor + sb t0,CFCR(a0) + sb t2,DATA(a0) # store divisor lsb + srl t2,8 + sb t2,IER(a0) # store divisor msb + + li t0,CFCR_8BITS # set 8N1 mode + sb t0,CFCR(a0) + + li t0,MCR_DTR|MCR_RTS # Galileo |MCR_IENABLE # enable DTR & RTS + sb t0,MCR(a0) + li t0,0 # Galileo IER_ERXRDY # enable receive interrupt(!) + sb t0,IER(a0) + + move v0,zero # indicate success + j ra + +END(init_ns16550_chan_a) + +#endif /* EVB64120A */ diff --git a/arch/mips/galileo-boards/ev64120/compressed/xfer.c b/arch/mips/galileo-boards/ev64120/compressed/xfer.c new file mode 100644 index 000000000..15c6c49fd --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/compressed/xfer.c @@ -0,0 +1,114 @@ +/* + * arch/mips/galileo/compressed/xfer.c + * + * By RidgeRun Inc, + * + * Xfer an image from flash to ram. + * For use with Galileo EVB64120A MIPS eval board. + */ + +#include "linux/serial_reg.h" + +#define port 0xbd000000 +#define inb(addr) (*(volatile unsigned char *) ((unsigned long)(addr))) +#define outb(b,addr) (*(volatile unsigned char *) ((unsigned long)(addr)) = (b)) + +#ifdef RUNNINGFROMFLASH +// This is where our image of interest is mapped to +// when the jumbers are set for booting out of flash. +// (flash part starts at address 0xbfC00000) +#define srcAddr 0xbfC20000 +#else +// This is where our image of interest is mapped to +// when the jumbers are set for booting out of eprom. +// (flash part starts at address 0xbf000000) +#define srcAddr 0xbf020000 +#endif + +static int PortAddress(unsigned int channel, unsigned char reg); +static void inline cons_hook(void); +static void print_message(const char *string); + +/****************************** + Routine: + Description: + ******************************/ +void XferToRam(void) +{ + unsigned int temp; + void (*entry_point) (void); + + cons_hook(); + + print_message("Copying image from Flash to Ram.\n"); + for (temp = 0; temp < (0x100000 - 0x20000); temp = temp + 4) { + *(volatile unsigned int *) (temp + 0xa0400000) = + *(volatile unsigned int *) (temp + srcAddr); + if (*(volatile unsigned int *) (temp + 0xa0400000) != + *(volatile unsigned int *) (temp + srcAddr)) { + print_message + ("Error!: copy verification failed.\n"); + break; + } + } + + print_message("Now jumping to the code just xferred to ram.\n"); + entry_point = (void *) 0x80400000; + entry_point(); +} + +/****************************** + Routine: + Description: + ******************************/ +static int PortAddress(unsigned int channel, unsigned char reg) +{ + unsigned int channelOffset = 0x20; + unsigned int regDelta = 4; + return (port + (channel * channelOffset) + (reg * regDelta)); +} + +/****************************** + Routine: + Description: + ******************************/ +static void cons_hook(void) +{ + register int comstat; + unsigned temp; + unsigned int channel = 1; // Channel 1 is the main serial + // connector of the EVB64120A. Channel 0 + // is the secondary serial port (typically + // the unsoldered connector of the board). + + temp = *(unsigned int *) 0xb4000464; + *(unsigned int *) 0xb4000464 = 0xffff4f14; + + // Set Baud Rate, baud=115K + outb(0x83, PortAddress(channel, UART_LCR)); + outb(0x00, PortAddress(channel, UART_DLM)); + outb(0x02, PortAddress(channel, UART_DLL)); + outb(0x03, PortAddress(channel, UART_LCR)); + + comstat = inb(PortAddress(channel, UART_LSR)); + comstat = inb(PortAddress(channel, UART_RX)); + outb(0x00, PortAddress(channel, UART_IER)); +} + +/****************************** + Routine: + Description: + ******************************/ +static void print_message(const char *string) +{ + register int count, loop; + /* Display Opening Message */ + for (count = 0; string[count]; count++) { + if (string[count] == '\n') { + *(char *) 0xbd000020 = '\r'; + } + *(char *) 0xbd000020 = string[count]; + for (loop = 0; loop < 2000; loop++) { + } + } +} diff --git a/arch/mips/galileo-boards/ev64120/dma.c b/arch/mips/galileo-boards/ev64120/dma.c new file mode 100644 index 000000000..977a2d57c --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/dma.c @@ -0,0 +1,168 @@ +/* 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; +} diff --git a/arch/mips/galileo-boards/ev64120/i2o.c b/arch/mips/galileo-boards/ev64120/i2o.c new file mode 100644 index 000000000..bd2938bf9 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/i2o.c @@ -0,0 +1,689 @@ +/* i2o.c - Drivers for the I2O */ + +/* Copyright - Galileo technology. */ + +/*includes*/ + +#include <linux/module.h> + +#ifdef __linux__ +#include <asm/galileo-boards/evb64120A/core.h> +#include <asm/galileo-boards/evb64120A/i2o.h> +#else +#include "Core.h" +#include "i2o.h" +#endif + +/******************************************************************** +* getInBoundMessage - When the GT is configured for I2O support +* it can receive a message from an agent on the pci bus. +* This message is a 32 bit wide and can be read by +* the CPU. +* The messaging unit contains two sets of registers +* so, actually it can receive a 64 bit message. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* OUTPUT: N/A. +* RETURNS: Data received from the remote agent. +*********************************************************************/ +unsigned int getInBoundMessage(I2O_MESSAGE_REG messageRegNum) +{ + unsigned int regValue; + + GT_REG_READ(INBOUND_MESSAGE_REGISTER0_CPU_SIDE + 4 * messageRegNum, + ®Value); + return (regValue); +} + + +/******************************************************************** +* checkInboundIntAndClear - When a message is received an interrupt is +* generated, to enable polling instead the use of +* an interrupt handler the user can use this fuction. +* You will need to mask the incomming interrupt for +* proper use. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* OUTPUT: N/A. +* RETURNS: true if the corresponding bit in the cause register is set otherwise +* false. +*********************************************************************/ +bool checkInBoundIntAndClear(I2O_MESSAGE_REG messageRegNum) +{ + unsigned int regValue; + + GT_REG_READ(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Value); + /* clears bit 0 for message register 0 or bit 1 for message register 1 */ + GT_REG_WRITE(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, + BIT1 * messageRegNum); + switch (messageRegNum) { + case MESSAGE_REG_0: + if (regValue & BIT0) + return true; + break; + case MESSAGE_REG_1: + if (regValue & BIT1) + return true; + break; + } + return false; +} + +/******************************************************************** +* sendOutBoundMessage - When the GT is configured for I2O support +* it can send a message to an agent on the pci bus. +* This message is a 32 bit wide and can be read by +* the PCI agent. +* The messaging unit contains two sets of registers +* so, actually it can send a 64 bit message. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* unsigned int message - Message to be sent. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool sendOutBoundMessage(I2O_MESSAGE_REG messageRegNum, + unsigned int message) +{ + GT_REG_WRITE(OUTBOUND_MESSAGE_REGISTER0_CPU_SIDE + + 4 * messageRegNum, message); + return true; +} + +/******************************************************************** +* checkOutboundInt - When the CPU sends a message to the Outbound +* register it generates an interrupt which is refelcted on +* the Outbound Interrupt cause register, the interrupt can +* be cleard only by the PCI agent which read the message. +* After sending the message you can acknowledge it by +* monitoring the corresponding bit in the cause register. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* OUTPUT: N/A. +* RETURNS: true if the corresponding bit in the cause register is set otherwise +* false. +*********************************************************************/ +bool outBoundMessageAcknowledge(I2O_MESSAGE_REG messageRegNum) +{ + unsigned int regValue; + + GT_REG_READ(OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Value); + switch (messageRegNum) { + case MESSAGE_REG_0: + if (regValue & BIT0) + return true; + break; + case MESSAGE_REG_1: + if (regValue & BIT1) + return true; + break; + } + return false; +} + +/******************************************************************** +* maskInBoundMessageInterrupt - Mask the inbound interrupt, when masking +* the interrupt you can work in polling mode +* using the checkInboundIntAndClear function. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool maskInBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum) +{ + switch (messageRegNum) { + case MESSAGE_REG_0: + SET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT0); + break; + case MESSAGE_REG_1: + SET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT1); + break; + } + return true; +} + +/******************************************************************** +* enableInBoundMessageInterrupt - unMask the inbound interrupt. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool enableInBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum) +{ + switch (messageRegNum) { + case MESSAGE_REG_0: + RESET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT0); + break; + case MESSAGE_REG_1: + RESET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT1); + break; + } + return true; +} + +/******************************************************************** +* maskOutboundMessageInterrupt - Mask the out bound interrupt, when doing so +* the PCI agent needs to poll on the interrupt +* cause register to monitor an incoming message. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool maskOutBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum) +{ + switch (messageRegNum) { + case MESSAGE_REG_0: + SET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT0); + break; + case MESSAGE_REG_1: + SET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT1); + break; + } + return true; +} + +/******************************************************************** +* enableOutboundMessageInterrupt - Mask the out bound interrupt, when doing so +* the PCI agent needs to poll on the interrupt +* cause register to monitor an incoming message. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool enableOutBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum) +{ + switch (messageRegNum) { + case MESSAGE_REG_0: + RESET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT0); + break; + case MESSAGE_REG_1: + RESET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT1); + break; + } + return true; +} + +/******************************************************************** +* initiateOutBoundDoorBellInt - Setting a bit in this register to '1' by the +* CPU generates a PCI interrupt (if it is not masked by +* the Outbound interrupt Mask register) +* Only the PCI agent which recieved the interrupt can +* clear it, only after clearing all the bits the +* interrupt will be de-asserted. +* +* INPUTS: unsigned int data - Requested interrupt bits. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool initiateOutBoundDoorBellInt(unsigned int data) +{ + GT_REG_WRITE(OUTBOUND_DOORBELL_REGISTER_CPU_SIDE, data); + return true; +} + +/******************************************************************** +* readInBoundDoorBellInt - Read the in bound door bell interrupt cause +* register. +* +* OUTPUT: N/A. +* RETURNS: The 32 bit interrupt cause register. +*********************************************************************/ +unsigned int readInBoundDoorBellInt() +{ + unsigned int regData; + GT_REG_READ(INBOUND_DOORBELL_REGISTER_CPU_SIDE, ®Data); + return regData; +} + +/******************************************************************** +* clearInBoundDoorBellInt - An interrupt generated by a PCI agent through +* the in bound door bell mechanisem can be cleared +* only by the CPU. The interrupt will be de-asserted +* only if all the bits which where set by the PCI +* agent are cleared. +* +* INPUTS: unsigned int data - Bits to be cleared. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool clearInBoundDoorBellInt(unsigned int data) +{ + GT_REG_WRITE(INBOUND_DOORBELL_REGISTER_CPU_SIDE, data); + return true; +} + +/******************************************************************** +* isInBoundDoorBellInterruptSet - Check if Inbound Doorbell Interrupt is set, +* can be used for polling mode. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true if the corresponding bit in the cause register is set otherwise +* false. +*********************************************************************/ +bool isInBoundDoorBellInterruptSet() +{ + unsigned int regData; + + GT_REG_READ(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Data); + return (regData & BIT2); +} + +/******************************************************************** +* isOutBoundDoorBellInterruptSet - Check if out bound Doorbell Interrupt is +* set, can be used for acknowledging interrupt +* handling by the agent who recieived the +* interrupt. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true if the corresponding bit in the cause register is set otherwise +* false. +*********************************************************************/ +bool isOutBoundDoorBellInterruptSet() +{ + unsigned int regData; + + GT_REG_READ(OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Data); + return (regData & BIT2); +} + +/******************************************************************** +* maskInboundDoorBellInterrupt - Mask the Inbound Doorbell Interrupt. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool maskInBoundDoorBellInterrupt() +{ + SET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2); + return true; +} + +/******************************************************************** +* enableInboundDoorBellInterrupt - unMask the Inbound Doorbell Interrupt. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool enableInBoundDoorBellInterrupt() +{ + RESET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2); + return true; +} + +/******************************************************************** +* maskOutboundDoorBellInterrupt - Mask the Outbound Doorbell Interrupt. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool maskOutBoundDoorBellInterrupt() +{ + SET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2); + return true; +} + +/******************************************************************** +* enableOutboundDoorBellInterrupt - unMask the Outbound Doorbell Interrupt. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool enableOutBoundDoorBellInterrupt() +{ + RESET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2); + return true; +} + +/******************************************************************** +* circularQueueEnable - Initialize the I2O messaging mechanism. +* +* INPUTS: CIRCULE_QUEUE_SIZE cirQueSize - Bits 5:1 in the: +* Queue Control Register, Offset 0x50 (0x1c50). +* Defines the queues size (refer to the data sheet +* for more information) +* unsigned int queueBaseAddr - The base address for the first queue. +* The other queues base Address will be determined as follows: +* Inbound Free = queueBaseAddr +* Inbound Post = queueBaseAddr + cirQueSize +* Outbound Post = queueBaseAddr + cirQueSize +* +* OUTPUT: N/A. +* RETURNS: true. +* +* The Circular Queue Starting Addresses as written in the spec: +* ---------------------------------------- +* | Queue | Starting Address | +* |----------------|---------------------| +* | Inbound Free | QBAR | +* | Inbound Post | QBAR + Queue Size | +* | Outbound Post | QBAR + 2*Queue Size | +* | Outbound Free | QBAR + 3*Queue Size | +* ---------------------------------------- +*********************************************************************/ +bool circularQueueEnable(CIRCULAR_QUEUE_SIZE cirQueSize, + unsigned int queueBaseAddr) +{ + unsigned int regData; + + regData = BIT0 | (cirQueSize << 1); + /* Enable Queue Operation */ + GT_REG_WRITE(QUEUE_CONTROL_REGISTER_CPU_SIDE, regData); + /* Writing The base Address for the 4 Queues */ + GT_REG_WRITE(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, queueBaseAddr); + /* Update The Inbound Free Queue Base Address, offset=0 */ + GT_REG_WRITE(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, 0); + GT_REG_WRITE(INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, 0); + /* Update The Inbound Post Queue Base Address, offset=_16K*cirQueSize */ + GT_REG_WRITE(INBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE, + _16K * cirQueSize); + GT_REG_WRITE(INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE, + _16K * cirQueSize); + /* Update The Outbound Post Queue Base Address, offset=2*_16K*cirQueSize */ + GT_REG_WRITE(OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE, + 2 * _16K * cirQueSize); + GT_REG_WRITE(OUTBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE, + 2 * _16K * cirQueSize); + /* Update The Outbound Free Queue Base Address, offset=3*_16K*cirQueSize */ + GT_REG_WRITE(OUTBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, + 3 * _16K * cirQueSize); + GT_REG_WRITE(OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, + 3 * _16K * cirQueSize); + return true; +} + +/******************************************************************** +* inBoundPostQueuePop - Two actions are being taken upon pop: +* 1) Getting out the data from the Queue`s head. +* 2) Increment the tail pointer in a cyclic way (The HEAD is +* incremented automaticaly by the GT) +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: Data pointed by tail. +*********************************************************************/ +unsigned int inBoundPostQueuePop() +{ + unsigned int tailAddrPointer; + unsigned int data; + unsigned int cirQueSize; + unsigned int qBar; + unsigned int inBoundPostQbase; + + /* Gets the Inbound Post TAIL pointer */ + GT_REG_READ(INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE, + &tailAddrPointer); + /* Gets the Data From the pointer Address */ + READ_WORD(tailAddrPointer, &data); + /* incrementing head process: */ + /* Gets the fifo's base Address */ + GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar); + qBar = qBar & 0xfff00000; + /* Gets the fifo's size */ + GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize); + cirQueSize = 0x1f && (cirQueSize >> 1); + /* calculating The Inbound Post Queue Base Address */ + inBoundPostQbase = qBar + 1 * cirQueSize * _16K; + /* incrementing Inbound Post queue TAIL in a cyclic loop */ + tailAddrPointer = inBoundPostQbase + ((tailAddrPointer + 4) % + (_16K * cirQueSize)); + /* updating the pointer back to INBOUND_POST_TAIL_POINTER_REGISTER */ + GT_REG_WRITE(INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE, + tailAddrPointer); + return data; +} + +/******************************************************************** +* isInBoundPostQueueInterruptSet - Check if in bound interrupt is set. +* can be used for polling mode. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true if the corresponding bit in the cause register is set otherwise +* false. +*********************************************************************/ +bool isInBoundPostQueueInterruptSet() +{ + unsigned int regData; + + GT_REG_READ(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Data); + return (regData & BIT4); /* if set return '1' (true), else '0' (false) */ +} + +/******************************************************************** +* clearInBoundPostQueueInterrupt - Clears the Post queue interrupt. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool clearInBoundPostQueueInterrupt() +{ + GT_REG_WRITE(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, BIT4); + return true; +} + +/******************************************************************** +* maskInBoundPostQueueInterrupt - Mask the inbound interrupt, when masking +* the interrupt you can work in polling mode. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: +*********************************************************************/ +void maskInBoundPostQueueInterrupt() +{ + unsigned int regData; + + GT_REG_READ(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, ®Data); + GT_REG_WRITE(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + regData | BIT4); + +} + +/******************************************************************** +* enableInBoundPostQueueInterrupt - Enable interrupt when ever there is a new +* message from the PCI agent. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: +*********************************************************************/ +void enableInBoundPostQueueInterrupt() +{ + unsigned int regData; + + GT_REG_READ(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, ®Data); + GT_REG_WRITE(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + regData & 0xfffffffb); +} + +/******************************************************************** +* inBoundFreeQueuePush - Two actions are being taken upon push: +* 1) Place the user`s data on the Queue`s head. +* 2) Increment the haed pointer in a cyclic way (The tail is +* decremented automaticaly by the GT) +* +* INPUTS: unsigned int data - Data to be placed in the queue. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool inBoundFreeQueuePush(unsigned int data) +{ + unsigned int headPointer; + unsigned int cirQueSize; + unsigned int qBar; + unsigned int inBoundFreeQbase; + + GT_REG_READ(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, + &headPointer); + /* placing the data in the queue */ + WRITE_WORD(headPointer, data); + /* incrementing head process: */ + /* Gets the fifo's base Address */ + GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar); + qBar = qBar & 0xfff00000; + /* Gets the fifo's size */ + GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize); + cirQueSize = 0x1f && (cirQueSize >> 1); + /* calculating The Inbound Free Queue Base Address */ + inBoundFreeQbase = qBar; + /* incrementing Inbound Free queue HEAD in a cyclic loop */ + headPointer = + inBoundFreeQbase + ((headPointer + 4) % (_16K * cirQueSize)); + /* updating the pointer back to OUTBOUND_POST_HEAD_POINTER_REGISTER */ + GT_REG_WRITE(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, + headPointer); + return true; +} + +/******************************************************************** +* isInBoundFreeQueueEmpty - Check if Inbound Free Queue Empty. +* Can be used for acknowledging the messages +* being sent by us to the PCI agent. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true if the queue is empty , otherwise false. +*********************************************************************/ +bool isInBoundFreeQueueEmpty() +{ + unsigned int inBoundFreeQueHead; + unsigned int inBoundFreeQueTail; + + GT_REG_READ(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, + &inBoundFreeQueHead); + GT_REG_READ(INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, + &inBoundFreeQueTail); + if (inBoundFreeQueHead == inBoundFreeQueTail) { + return true; + } else + return false; +} + +/******************************************************************** +* outBoundPostQueuePush - Two actions are being taken upon push: +* 1) Place the user`s data on the Queue`s head. +* 2) Increment the haed pointer in a cyclic way (The tail is +* decremented automaticaly by the GT when the Agent on the +* PCI have read data from the Outbound Port). +* +* INPUTS: unsigned int data - Data to be placed in the queue`s head. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool outBoundPostQueuePush(unsigned int data) +{ + unsigned int headPointer; + unsigned int cirQueSize; + unsigned int qBar; + unsigned int outBoundPostQbase; + + GT_REG_READ(OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE, + &headPointer); + /* placing the data in the queue (where the head point to..) */ + WRITE_WORD(headPointer, data); + /* incrementing head process: */ + /* Gets the fifo's base Address */ + GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar); + qBar = qBar & 0xfff00000; + /* Gets the fifo's size */ + GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize); + cirQueSize = 0x1f && (cirQueSize >> 1); + /* calculating The Outbound Post Queue Base Address */ + outBoundPostQbase = qBar + 2 * cirQueSize * _16K; + /* incrementing Outbound Post queue in a cyclic loop */ + headPointer = + outBoundPostQbase + ((headPointer + 4) % (_16K * cirQueSize)); + /* updating the pointer back to OUTBOUND_POST_HEAD_POINTER_REGISTER */ + GT_REG_WRITE(OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE, + headPointer); + return true; +} + +/******************************************************************** +* isOutBoundPostQueueEmpty - Check if Outbound Post Queue Empty. +* Can be used for acknowledging the messages +* being sent by us to the PCI agent. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true if the queue is empty , otherwise false. +*********************************************************************/ +bool isOutBoundPostQueueEmpty() +{ + unsigned int outBoundPostQueHead; + unsigned int outBoundPostQueTail; + + GT_REG_READ(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, + &outBoundPostQueHead); + GT_REG_READ(INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, + &outBoundPostQueTail); + if (outBoundPostQueHead == outBoundPostQueTail) { + return true; + } else + return false; +} + +/******************************************************************** +* outBoundFreeQueuePop - Two actions are being taken upon pop: +* 1) Getting out the data from the Queue`s head. +* 2) Increment the tail pointer in a cyclic way (The HEAD is +* incremented automaticaly by the GT) +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: Data pointed by tail. +*********************************************************************/ +unsigned int outBoundFreeQueuePop() +{ + unsigned int tailAddrPointer; + unsigned int data; + unsigned int cirQueSize; + unsigned int qBar; + unsigned int outBoundFreeQbase; + + /* Gets the Inbound Post TAIL pointer */ + GT_REG_READ(OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, + &tailAddrPointer); + /* Gets the Data From the pointer Address */ + READ_WORD(tailAddrPointer, &data); + /* incrementing head process: */ + /* Gets the fifo's base Address */ + GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar); + qBar = qBar & 0xfff00000; + /* Gets the fifo's size */ + GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize); + cirQueSize = 0x1f && (cirQueSize >> 1); + /* calculating The Inbound Post Queue Base Address */ + outBoundFreeQbase = qBar + 3 * cirQueSize * _16K; + /* incrementing Outbound Free queue TAlL in a cyclic loop */ + tailAddrPointer = outBoundFreeQbase + ((tailAddrPointer + 4) % + (_16K * cirQueSize)); + /* updating the pointer back to OUTBOUND_FREE_TAIL_POINTER_REGISTER */ + GT_REG_WRITE(OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, + tailAddrPointer); + return data; +} + + +EXPORT_SYMBOL(isInBoundDoorBellInterruptSet); +EXPORT_SYMBOL(initiateOutBoundDoorBellInt); +EXPORT_SYMBOL(clearInBoundDoorBellInt); diff --git a/arch/mips/galileo-boards/ev64120/int-handler.S b/arch/mips/galileo-boards/ev64120/int-handler.S new file mode 100644 index 000000000..26e96c149 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/int-handler.S @@ -0,0 +1,117 @@ +/* + * int-handler.S + * + * $Id: int-handler.S,v 1.1 2000/11/21 00:48:25 stevej Exp $ + * Based on the cobalt handler. + * + */ + +#include <linux/config.h> +#include <asm/asm.h> +#include <asm/mipsregs.h> +#include <asm/addrspace.h> +#include <asm/regdef.h> +#include <asm/stackframe.h> + +/******************************************************************** + *galileo_handle_int - + 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 + + andi t1,t0,STATUSF_IP4 /* int2 hardware line (timer) */ + bnez t1,ll_galileo_irq + andi t1,t0,STATUSF_IP2 /* int0 hardware line */ + bnez t1,ll_pci_intA + andi t1,t0,STATUSF_IP5 /* int3 hardware line */ + bnez t1,ll_pci_intD + andi t1,t0,STATUSF_IP6 /* int4 hardware line */ + bnez t1,ll_serial_irq + andi t1,t0,STATUSF_IP7 /* compare int */ + bnez t1,ll_compare_irq + nop + + /* wrong alarm or masked ... */ + j spurious_interrupt + nop + END(galileo_handle_int) + + + .align 5 + .set reorder +ll_galileo_irq: + li a0,4 + move a1,sp + jal do_IRQ + nop + j ret_from_irq + nop + + .align 5 + .set reorder +ll_compare_irq: + li a0,7 + move a1,sp + jal do_IRQ + nop + j ret_from_irq + nop + + .align 5 + .set reorder +ll_pci_intA: + move a0,sp + jal pci_intA + nop + j ret_from_irq + nop + +#if 0 + .align 5 + .set reorder +ll_pci_intB: + move a0,sp + jal pci_intB + nop + j ret_from_irq + nop + + .align 5 + .set reorder +ll_pci_intC: + move a0,sp + jal pci_intC + nop + j ret_from_irq + nop +#endif + + .align 5 + .set reorder +ll_pci_intD: + move a0,sp + jal pci_intD + nop + j ret_from_irq + nop + + .align 5 + .set reorder +ll_serial_irq: + li a0,6 + move a1,sp + jal do_IRQ + nop + j ret_from_irq + nop diff --git a/arch/mips/galileo-boards/ev64120/irq-handler.c b/arch/mips/galileo-boards/ev64120/irq-handler.c new file mode 100644 index 000000000..a259ea7cd --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/irq-handler.c @@ -0,0 +1,274 @@ +/* + * 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/galileo-boards/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) +{ + int i, j; + +#if CURRENTLY_UNUSED + /* 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 + +} diff --git a/arch/mips/galileo-boards/ev64120/irq.c b/arch/mips/galileo-boards/ev64120/irq.c new file mode 100644 index 000000000..16aef239b --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/irq.c @@ -0,0 +1,488 @@ +/* + * irq.c + * + * 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/malloc.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> +#include <asm/galileo-boards/ev64120int.h> + + +#undef IRQ_DEBUG + +#ifdef IRQ_DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + + +asmlinkage void do_IRQ(int irq, struct pt_regs *regs); + +#define MAX_AGENTS_PER_INT 21 /* Random number */ +unsigned char pci_int_irq[MAX_AGENTS_PER_INT]; +static int max_interrupts = 0; + +/* Duplicate interrupt handlers. */ +/******************************************************************** + *pci_int(A/B/C/D) - + * + *Calls all the handlers connected to PCI interrupt A/B/C/D + * + *Inputs : + * + *Outpus : + * + *********************************************************************/ +asmlinkage __inline__ void pci_intA(struct pt_regs *regs) +{ + unsigned int count = 0; + DBG(KERN_INFO "pci_intA, max_interrupts %d\n", max_interrupts); + for (count = 0; count < max_interrupts; count++) { + do_IRQ(pci_int_irq[count], regs); + } +} + +asmlinkage __inline__ void pci_intD(struct pt_regs *regs) +{ + unsigned int count = 0; + DBG(KERN_INFO "pci_intD, max_interrupts %d\n", max_interrupts); + for (count = 0; count < max_interrupts; count++) { + do_IRQ(pci_int_irq[count], regs); + } +} + + +/* Function for careful CP0 interrupt mask access */ +static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask) +{ + unsigned long status = read_32bit_cp0_register(CP0_STATUS); + DBG(KERN_INFO "modify_cp0_intmask clr %x, set %x\n", clr_mask, + set_mask); + DBG(KERN_INFO "modify_cp0_intmask status %x\n", status); + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8; + DBG(KERN_INFO "modify_cp0_intmask status %x\n", status); + write_32bit_cp0_register(CP0_STATUS, status); +} + +static inline void mask_irq(unsigned int irq_nr) +{ + modify_cp0_intmask(irq_nr, 0); +} + +static inline void unmask_irq(unsigned int irq_nr) +{ + modify_cp0_intmask(0, irq_nr); +} + +void disable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + DBG(KERN_INFO "disable_irq, irq %d\n", irq_nr); + save_and_cli(flags); + if (irq_nr >= 8) { // All PCI interrupts are on line 5 or 2 + mask_irq(9 << 2); + } else { + mask_irq(1 << irq_nr); + } + restore_flags(flags); +} + +void enable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + DBG(KERN_INFO "enable_irq, irq %d\n", irq_nr); + save_and_cli(flags); + if (irq_nr >= 8) { // All PCI interrupts are on line 5 or 2 + DBG(KERN_INFO __FUNCTION__ " pci interrupt %d\n", irq_nr); + unmask_irq(9 << 2); + } else { + DBG(KERN_INFO __FUNCTION__ " interrupt set mask %d\n", + 1 << irq_nr); + unmask_irq(1 << irq_nr); + } + restore_flags(flags); +} + +/* + * Generic no controller code + */ + +static void no_irq_enable_disable(unsigned int irq) +{ +} +static unsigned int no_irq_startup(unsigned int irq) +{ + return 0; +} + +#if 0 +static void no_irq_ack(unsigned int irq) +{ + printk(KERN_CRIT "Unexpected IRQ trap at vector %u\n", irq); +} +#endif + +struct hw_interrupt_type no_irq_type = { + typename:"none", + startup:no_irq_startup, + shutdown:no_irq_enable_disable, + enable:no_irq_enable_disable, + disable:no_irq_enable_disable, + ack:NULL, + end:no_irq_enable_disable, +}; + +// ack: no_irq_ack, re-enable later -- SKJ + + +/* + * Controller mappings for all interrupt sources: + */ +irq_desc_t irq_desc[NR_IRQS]; + +unsigned long spurious_count = 0; + +int get_irq_list(char *buf) +{ + int i, len = 0, j; + struct irqaction *action; + + len += sprintf(buf + len, " "); + for (j = 0; j < smp_num_cpus; j++) + len += sprintf(buf + len, "CPU%d ", j); + *(char *) (buf + len++) = '\n'; + + for (i = 0; i < NR_IRQS; i++) { + action = irq_desc[i].action; + if (!action || !action->handler) + continue; + len += sprintf(buf + len, "%3d: ", i); + len += sprintf(buf + len, "%10u ", kstat_irqs(i)); + if (irq_desc[i].handler) + len += + sprintf(buf + len, " %s ", + irq_desc[i].handler->typename); + else + len += sprintf(buf + len, " None "); + len += sprintf(buf + len, " %s", action->name); + for (action = action->next; action; action = action->next) { + len += sprintf(buf + len, ", %s", action->name); + } + len += sprintf(buf + len, "\n"); + } + len += sprintf(buf + len, "BAD: %10lu\n", spurious_count); + return len; +} + +asmlinkage void do_IRQ(int irq, struct pt_regs *regs) +{ + struct irqaction *action; + int cpu; + +#ifdef IRQ_DEBUG + if (irq != TIMER) + DBG(KERN_INFO __FUNCTION__ " irq = %d\n", irq); + if (irq != TIMER) + DBG(KERN_INFO "cause register = %x\n", + read_32bit_cp0_register(CP0_CAUSE)); + if (irq != TIMER) + DBG(KERN_INFO "status register = %x\n", + read_32bit_cp0_register(CP0_STATUS)); +#endif + + cpu = smp_processor_id(); + irq_enter(cpu); + kstat.irqs[cpu][irq]++; + + if (irq_desc[irq].handler->ack) { + irq_desc[irq].handler->ack(irq); + } + + disable_irq(irq); + + action = irq_desc[irq].action; + if (action && action->handler) { +#ifdef IRQ_DEBUG + if (irq != TIMER) + DBG(KERN_INFO + "rr: irq %d action %p and handler %p\n", irq, + action, action->handler); +#endif + if (!(action->flags & SA_INTERRUPT)) + __sti(); + do { + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + __cli(); + if (irq_desc[irq].handler) { + if (irq_desc[irq].handler->end) + irq_desc[irq].handler->end(irq); + else if (irq_desc[irq].handler->enable) + irq_desc[irq].handler->enable(irq); + } + } + + enable_irq(irq); + irq_exit(cpu); + + if (softirq_active(cpu) & softirq_mask(cpu)) + do_softirq(); + + /* unmasking and bottom half handling is done magically for us. */ +} + +int request_irq(unsigned int irq, + void (*handler) (int, void *, struct pt_regs *), + unsigned long irqflags, const char *devname, void *dev_id) +{ + struct irqaction *old, **p, *action; + unsigned long flags; + + DBG(KERN_INFO "rr:dev %s irq %d handler %x\n", devname, irq, + handler); + if (irq >= NR_IRQS) + return -EINVAL; + + action = (struct irqaction *) + kmalloc(sizeof(struct irqaction), GFP_KERNEL); + if (!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->dev_id = dev_id; + action->next = NULL; + + save_flags(flags); + cli(); + + p = &irq_desc[irq].action; + + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & action->flags & SA_SHIRQ)) + return -EBUSY; + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + } + *p = action; + + restore_flags(flags); + if (irq >= 8) { + DBG(KERN_INFO "request_irq, max_interrupts %d\n", + max_interrupts); + pci_int_irq[max_interrupts++] = irq; // NOTE: Add error-handling if > max + } + enable_irq(irq); + return 0; +} + + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction *p, *old = NULL; + unsigned long flags; + int count, tmp, removed = 0; + + for (p = irq_desc[irq].action; p != NULL; old = p, p = p->next) { + /* Found the IRQ, is it the correct dev_id? */ + if (dev_id == p->dev_id) { + save_flags(flags); + cli(); + + // remove link from list + if (old) + old->next = p->next; + else + irq_desc[irq].action = p->next; + + restore_flags(flags); + kfree(p); + removed = 1; + break; + } + } + + /* + Remove PCI interrupts from the pci_int_irq list. Make sure + that some handler was removed before decrementing max_interrupts. + */ + if ((irq >= 8) && (removed)) { + 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--; + DBG(KERN_INFO "free_irq, max_interrupts %d\n", + max_interrupts); + } +} + +unsigned long probe_irq_on(void) +{ + printk(KERN_INFO "probe_irq_on\n"); + return 0; +} + +int probe_irq_off(unsigned long irqs) +{ + printk(KERN_INFO "probe_irq_off\n"); + return 0; +} + +int (*irq_cannonicalize) (int irq); + +int galileo_irq_cannonicalize(int i) +{ + return i; +} + +/******************************************************************** + *galileo_irq_setup - + * + *Initializes CPU interrupts + * + * + *Inputs : + * + *Outpus : + * + *********************************************************************/ +void galileo_irq_setup(void) +{ + extern asmlinkage void galileo_handle_int(void); + extern void galileo_irq_init(void); + + DBG(KERN_INFO "rr: galileo_irq_setup entry\n"); + + galileo_irq_init(); + + /* + * Clear all of the interrupts while we change the able around a bit. + */ + set_cp0_status(ST0_IM, 0); + set_cp0_status(ST0_BEV, 1); /* int-handler is not on bootstrap */ + + /* Sets the exception_handler array. */ + set_except_vector(0, galileo_handle_int); + + cli(); + +/* + Enable timer. Other interrupts will be enabled as they are registered. +*/ + set_cp0_status(ST0_IM, IE_IRQ2); + + +#ifdef CONFIG_REMOTE_DEBUG + { + extern int DEBUG_CHANNEL; + serial_init(DEBUG_CHANNEL); + serial_set(DEBUG_CHANNEL, 115200); + set_debug_traps(); + breakpoint(); /* you may move this line to whereever you want :-) */ + } +#endif + +} + + +void __init init_IRQ(void) +{ + int i; + + DBG(KERN_INFO "rr:init_IRQ\n"); + + /* Let's initialize our IRQ descriptors */ + for (i = 0; i < NR_IRQS; i++) { + irq_desc[i].status = 0; + irq_desc[i].handler = &no_irq_type; + irq_desc[i].action = NULL; + irq_desc[i].depth = 0; + irq_desc[i].lock = SPIN_LOCK_UNLOCKED; + } + + irq_cannonicalize = galileo_irq_cannonicalize; + galileo_irq_setup(); +} + +/* EXPORT_SYMBOL(irq_cannonicalize); */ + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 4 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -4 + * c-argdecl-indent: 4 + * c-label-offset: -4 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ diff --git a/arch/mips/galileo-boards/ev64120/ld.script.galileo b/arch/mips/galileo-boards/ev64120/ld.script.galileo new file mode 100644 index 000000000..1c9faa3f3 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/ld.script.galileo @@ -0,0 +1,113 @@ +OUTPUT_FORMAT("elf32-bigmips") +OUTPUT_ARCH(mips) +ENTRY(kernel_entry) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0x80100000; + /* app_header is needed for the Orion bootloader -- Cort */ + .app_header : { *(.app_header) } + .init : { *(.init) } =0 + .text : + { + _ftext = . ; + *(.text) + *(.rodata) + *(.rodata1) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0 + _etext = .; + PROVIDE (etext = .); + + . = ALIGN(8192); + .data.init_task : { *(.data.init_task) } + + /* Startup code */ + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(16); + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; + . = ALIGN(4096); /* Align double page for init_task_union */ + __init_end = .; + + . = ALIGN(4096); + .data.page_aligned : { *(.data.idt) } + + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + + .fini : { *(.fini) } =0 + .reginfo : { *(.reginfo) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. It would + be more correct to do this: + . = .; + The current expression does not correctly handle the case of a + text segment ending precisely at the end of a page; it causes the + data segment to skip a page. The above expression does not have + this problem, but it will currently (2/95) cause BFD to allocate + a single segment, combining both text and data, for this case. + This will prevent the text segment from being shared among + multiple executions of the program; I think that is more + important than losing a page of the virtual address space (note + that no actual memory is lost; the page which is skipped can not + be referenced). */ + . = .; + .data : + { + _fdata = . ; + *(.data) + CONSTRUCTORS + } + .data1 : { *(.data1) } + _gp = . + 0x8000; + .lit8 : { *(.lit8) } + .lit4 : { *(.lit4) } + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + .got : { *(.got.plt) *(.got) } + .dynamic : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : { *(.sdata) } + _edata = .; + PROVIDE (edata = .); + + __bss_start = .; + _fbss = .; + .sbss : { *(.sbss) *(.scommon) } + .bss : + { + *(.dynbss) + *(.bss) + *(COMMON) + _end = . ; + PROVIDE (end = .); + } + /* These are needed for ELF backends which have not yet been + converted to the new style linker. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + /* DWARF debug sections. + Symbols in the .debug DWARF section are relative to the beginning of the + section so we begin .debug at 0. It's not clear yet what needs to happen + for the others. */ + .debug 0 : { *(.debug) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .line 0 : { *(.line) } + /* These must appear regardless of . */ + .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } + .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } +} diff --git a/arch/mips/galileo-boards/ev64120/pci_bios.c b/arch/mips/galileo-boards/ev64120/pci_bios.c new file mode 100644 index 000000000..96a85a0e0 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/pci_bios.c @@ -0,0 +1,1266 @@ +/* + * pci_bios.c + * + * BRIEF MODULE DESCRIPTION + * Galileo Evaluation Boards PCI support. + * + * The general-purpose functions to read/write and configure the GT64120A's + * PCI registers (function names start with pci0 or pci1) are either direct + * copies of functions written by Galileo Technology, or are modifications + * of their functions to work with Linux 2.4 vs Linux 2.2. These functions + * are Copyright - Galileo Technology. + * + * Other functions are derived from other MIPS PCI implementations, or were + * written by RidgeRun, Inc, Copyright (C) 2000 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/types.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/malloc.h> +#include <linux/version.h> +#include <asm/pci.h> +#include <asm/io.h> +#include <asm/galileo-boards/ev64120.h> +#include <asm/galileo-boards/gt64120.h> + +#include <linux/init.h> + +#undef PCI_DEBUG + +#ifdef PCI_DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +#ifdef CONFIG_PCI + +#define SELF 0 + +/* + These functions and structures provide the BIOS scan and mapping of the PCI devices. +*/ + +#define MAX_PCI_DEVS 10 + +struct pci_device { + u32 slot; + u32 BARtype[6]; + u32 BARsize[6]; +}; + +static void __init scan_and_initialize_pci(void); +static u32 __init scan_pci_bus(struct pci_device *pci_devices); +static void __init allocate_pci_space(struct pci_device *pci_devices); + +static void __init galileo_pcibios_fixup_bus(struct pci_bus *bus); + +/* + The functions that actually read and write to the controller. + + Copied from or modified from Galileo Technology code. +*/ +static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device); +static void pci0WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data); +static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device); +static void pci1WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data); + +static void pci0MapIOspace(unsigned int pci0IoBase, + unsigned int pci0IoLength); +static void pci1MapIOspace(unsigned int pci1IoBase, + unsigned int pci1IoLength); +static void pci0MapMemory0space(unsigned int pci0Mem0Base, + unsigned int pci0Mem0Length); +static void pci1MapMemory0space(unsigned int pci1Mem0Base, + unsigned int pci1Mem0Length); +static void pci0MapMemory1space(unsigned int pci0Mem1Base, + unsigned int pci0Mem1Length); +static void pci1MapMemory1space(unsigned int pci1Mem1Base, + unsigned int pci1Mem1Length); +static unsigned int pci0GetIOspaceBase(void); +static unsigned int pci0GetIOspaceSize(void); +static unsigned int pci0GetMemory0Base(void); +static unsigned int pci0GetMemory0Size(void); +static unsigned int pci0GetMemory1Base(void); +static unsigned int pci0GetMemory1Size(void); +static unsigned int pci1GetIOspaceBase(void); +static unsigned int pci1GetIOspaceSize(void); +static unsigned int pci1GetMemory0Base(void); +static unsigned int pci1GetMemory0Size(void); +static unsigned int pci1GetMemory1Base(void); +static unsigned int pci1GetMemory1Size(void); + + +/* Functions to implement "pci ops" */ +static int galileo_pcibios_read_config_word(struct pci_dev *dev, + int offset, u16 * val); +static int galileo_pcibios_read_config_byte(struct pci_dev *dev, + int offset, u8 * val); +static int galileo_pcibios_read_config_dword(struct pci_dev *dev, + int offset, u32 * val); +static int galileo_pcibios_write_config_byte(struct pci_dev *dev, + int offset, u8 val); +static int galileo_pcibios_write_config_word(struct pci_dev *dev, + int offset, u16 val); +static int galileo_pcibios_write_config_dword(struct pci_dev *dev, + int offset, u32 val); +static void galileo_pcibios_set_master(struct pci_dev *dev); + +/* + General-purpose PCI functions. +*/ + +/******************************************************************** +* pci0MapIOspace - Maps PCI0 IO space for the master. +* Inputs: base and length of pci0Io +*********************************************************************/ + +static void pci0MapIOspace(unsigned int pci0IoBase, + unsigned int pci0IoLength) +{ + unsigned int pci0IoTop = + (unsigned int) (pci0IoBase + pci0IoLength); + + if (pci0IoLength == 0) + pci0IoTop++; + + pci0IoBase = (unsigned int) (pci0IoBase >> 21); + pci0IoTop = (unsigned int) (((pci0IoTop - 1) & 0x0fffffff) >> 21); + GT_WRITE(GT_PCI0IOLD_OFS, pci0IoBase); + GT_WRITE(GT_PCI0IOHD_OFS, pci0IoTop); +} + +/******************************************************************** +* pci1MapIOspace - Maps PCI1 IO space for the master. +* Inputs: base and length of pci1Io +*********************************************************************/ + +static void pci1MapIOspace(unsigned int pci1IoBase, + unsigned int pci1IoLength) +{ + unsigned int pci1IoTop = + (unsigned int) (pci1IoBase + pci1IoLength); + + if (pci1IoLength == 0) + pci1IoTop++; + + pci1IoBase = (unsigned int) (pci1IoBase >> 21); + pci1IoTop = (unsigned int) (((pci1IoTop - 1) & 0x0fffffff) >> 21); + GT_WRITE(GT_PCI1IOLD_OFS, pci1IoBase); + GT_WRITE(GT_PCI1IOHD_OFS, pci1IoTop); +} + +/******************************************************************** +* pci0MapMemory0space - Maps PCI0 memory0 space for the master. +* Inputs: base and length of pci0Mem0 +*********************************************************************/ + +static void pci0MapMemory0space(unsigned int pci0Mem0Base, + unsigned int pci0Mem0Length) +{ + unsigned int pci0Mem0Top = pci0Mem0Base + pci0Mem0Length; + + if (pci0Mem0Length == 0) + pci0Mem0Top++; + + pci0Mem0Base = pci0Mem0Base >> 21; + pci0Mem0Top = ((pci0Mem0Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI0M0LD_OFS, pci0Mem0Base); + GT_WRITE(GT_PCI0M0HD_OFS, pci0Mem0Top); +} + +/******************************************************************** +* pci1MapMemory0space - Maps PCI1 memory0 space for the master. +* Inputs: base and length of pci1Mem0 +*********************************************************************/ + +static void pci1MapMemory0space(unsigned int pci1Mem0Base, + unsigned int pci1Mem0Length) +{ + unsigned int pci1Mem0Top = pci1Mem0Base + pci1Mem0Length; + + if (pci1Mem0Length == 0) + pci1Mem0Top++; + + pci1Mem0Base = pci1Mem0Base >> 21; + pci1Mem0Top = ((pci1Mem0Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI1M0LD_OFS, pci1Mem0Base); + GT_WRITE(GT_PCI1M0HD_OFS, pci1Mem0Top); +} + +/******************************************************************** +* pci0MapMemory1space - Maps PCI0 memory1 space for the master. +* Inputs: base and length of pci0Mem1 +*********************************************************************/ + +static void pci0MapMemory1space(unsigned int pci0Mem1Base, + unsigned int pci0Mem1Length) +{ + unsigned int pci0Mem1Top = pci0Mem1Base + pci0Mem1Length; + + if (pci0Mem1Length == 0) + pci0Mem1Top++; + + pci0Mem1Base = pci0Mem1Base >> 21; + pci0Mem1Top = ((pci0Mem1Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI0M1LD_OFS, pci0Mem1Base); + GT_WRITE(GT_PCI0M1HD_OFS, pci0Mem1Top); + +} + +/******************************************************************** +* pci1MapMemory1space - Maps PCI1 memory1 space for the master. +* Inputs: base and length of pci1Mem1 +*********************************************************************/ + +static void pci1MapMemory1space(unsigned int pci1Mem1Base, + unsigned int pci1Mem1Length) +{ + unsigned int pci1Mem1Top = pci1Mem1Base + pci1Mem1Length; + + if (pci1Mem1Length == 0) + pci1Mem1Top++; + + pci1Mem1Base = pci1Mem1Base >> 21; + pci1Mem1Top = ((pci1Mem1Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI1M1LD_OFS, pci1Mem1Base); + GT_WRITE(GT_PCI1M1HD_OFS, pci1Mem1Top); +} + +/******************************************************************** +* pci0GetIOspaceBase - Return PCI0 IO Base Address. +* Inputs: N/A +* Returns: PCI0 IO Base Address. +*********************************************************************/ + +static unsigned int pci0GetIOspaceBase(void) +{ + unsigned int base; + GT_READ(GT_PCI0IOLD_OFS, &base); + base = base << 21; + return base; +} + +/******************************************************************** +* pci0GetIOspaceSize - Return PCI0 IO Bar Size. +* Inputs: N/A +* Returns: PCI0 IO Bar Size. +*********************************************************************/ + +static unsigned int pci0GetIOspaceSize(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI0IOLD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI0IOHD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/******************************************************************** +* pci0GetMemory0Base - Return PCI0 Memory 0 Base Address. +* Inputs: N/A +* Returns: PCI0 Memory 0 Base Address. +*********************************************************************/ + +static unsigned int pci0GetMemory0Base(void) +{ + unsigned int base; + GT_READ(GT_PCI0M0LD_OFS, &base); + base = base << 21; + return base; +} + +/******************************************************************** +* pci0GetMemory0Size - Return PCI0 Memory 0 Bar Size. +* Inputs: N/A +* Returns: PCI0 Memory 0 Bar Size. +*********************************************************************/ + +static unsigned int pci0GetMemory0Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI0M0LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI0M0HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/******************************************************************** +* pci0GetMemory1Base - Return PCI0 Memory 1 Base Address. +* Inputs: N/A +* Returns: PCI0 Memory 1 Base Address. +*********************************************************************/ + +static unsigned int pci0GetMemory1Base(void) +{ + unsigned int base; + GT_READ(GT_PCI0M1LD_OFS, &base); + base = base << 21; + return base; +} + +/******************************************************************** +* pci0GetMemory1Size - Return PCI0 Memory 1 Bar Size. +* Inputs: N/A +* Returns: PCI0 Memory 1 Bar Size. +*********************************************************************/ + +static unsigned int pci0GetMemory1Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI0M1LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI0M1HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/******************************************************************** +* pci1GetIOspaceBase - Return PCI1 IO Base Address. +* Inputs: N/A +* Returns: PCI1 IO Base Address. +*********************************************************************/ + +static unsigned int pci1GetIOspaceBase(void) +{ + unsigned int base; + GT_READ(GT_PCI1IOLD_OFS, &base); + base = base << 21; + return base; +} + +/******************************************************************** +* pci1GetIOspaceSize - Return PCI1 IO Bar Size. +* Inputs: N/A +* Returns: PCI1 IO Bar Size. +*********************************************************************/ + +static unsigned int pci1GetIOspaceSize(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI1IOLD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI1IOHD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/******************************************************************** +* pci1GetMemory0Base - Return PCI1 Memory 0 Base Address. +* Inputs: N/A +* Returns: PCI1 Memory 0 Base Address. +*********************************************************************/ + +static unsigned int pci1GetMemory0Base(void) +{ + unsigned int base; + GT_READ(GT_PCI1M0LD_OFS, &base); + base = base << 21; + return base; +} + +/******************************************************************** +* pci1GetMemory0Size - Return PCI1 Memory 0 Bar Size. +* Inputs: N/A +* Returns: PCI1 Memory 0 Bar Size. +*********************************************************************/ + +static unsigned int pci1GetMemory0Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI1M1LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI1M1HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/******************************************************************** +* pci1GetMemory1Base - Return PCI1 Memory 1 Base Address. +* Inputs: N/A +* Returns: PCI1 Memory 1 Base Address. +*********************************************************************/ + +static unsigned int pci1GetMemory1Base(void) +{ + unsigned int base; + GT_READ(GT_PCI1M1LD_OFS, &base); + base = base << 21; + return base; +} + +/******************************************************************** +* pci1GetMemory1Size - Return PCI1 Memory 1 Bar Size. +* Inputs: N/A +* Returns: PCI1 Memory 1 Bar Size. +*********************************************************************/ + +static unsigned int pci1GetMemory1Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI1M1LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI1M1HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + + + +/******************************************************************** + *pci_range_ck - + * + *Check if the pci device that are trying to access does really exists + *on the evaluation board. + * + *Inputs : + *bus - bus number (0 for PCI 0 ; 1 for PCI 1) + *dev - number of device on the specific pci bus + * + *Outpus : + *0 - if OK , 1 - if failure + *********************************************************************/ +static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev) +{ + //DBG(KERN_INFO "p_r_c %d %d\n",bus,dev); + if (((bus == 0) || (bus == 1)) && (dev >= 6) && (dev <= 8)) + return 0; // Bus/Device Number OK + return -1; // Bus/Device Number not OK +} + +/******************************************************************** +* pciXReadConfigReg - Read from a PCI configuration register +* - Make sure the GT is configured as a master before +* reading from another device on the PCI. +* - The function takes care of Big/Little endian conversion. +* INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI +* spec) +* pciDevNum: The device number needs to be addressed. +* RETURNS: data , if the data == 0xffffffff check the master abort bit in the +* cause register to make sure the data is valid +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|00| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +*********************************************************************/ +static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device) +{ + unsigned int DataForRegCf8; + unsigned int data; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + + /* The casual observer might wonder why the READ is duplicated here, + rather than immediately following the WRITE, and just have the + swap in the "if". That's because there is a latency problem + with trying to read immediately after setting up the address + register. The "if" check gives enough time for the address + to stabilize, so the READ can work. + */ + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_READ(GT_PCI0_CFGDATA_OFS, &data); + return data; + } else { /* The PCI is working in LE Mode so swap the Data. */ + GT_READ(GT_PCI0_CFGDATA_OFS, &data); + return cpu_to_le32(data); + } +} + +static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device) +{ + unsigned int DataForRegCf8; + unsigned int data; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + /* The casual observer might wonder why the READ is duplicated here, + rather than immediately following the WRITE, and just have the + swap in the "if". That's because there is a latency problem + with trying to read immediately after setting up the address + register. The "if" check gives enough time for the address + to stabilize, so the READ can work. + */ + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + /* when configurating our own PCI 1 L-unit the access is through + the PCI 0 interface with reg number = reg number + 0x80 */ + DataForRegCf8 |= 0x80; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + } else { /* The PCI is working in LE Mode so swap the Data. */ + GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8); + } + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_READ(GT_PCI0_CFGDATA_OFS, &data); + return data; + } else { + GT_READ(GT_PCI1_CFGDATA_OFS, &data); + return cpu_to_le32(data); + } +} + + + +/******************************************************************** +* pciXWriteConfigReg - Write to a PCI configuration register +* - Make sure the GT is configured as a master before +* writingto another device on the PCI. +* - The function takes care of Big/Little endian conversion. +* Inputs: unsigned int regOffset: The register offset as it apears in the GT spec +* (or any other PCI device spec) +* pciDevNum: The device number needs to be addressed. +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|00| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +*********************************************************************/ +static void pci0WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data) +{ + unsigned int DataForRegCf8; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, data); + } else { /* configuration Transaction over the pci. */ + /* The PCI is working in LE Mode so swap the Data. */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, le32_to_cpu(data)); + } +} + +static void pci1WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data) +{ + unsigned int DataForRegCf8; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + /* There is a latency problem + with trying to read immediately after setting up the address + register. The "if" check gives enough time for the address + to stabilize, so the WRITE can work. + */ + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + /* when configurating our own PCI 1 L-unit the access is through + the PCI 0 interface with reg number = reg number + 0x80 */ + DataForRegCf8 |= 0x80; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + } else { /* configuration Transaction over the pci. */ + /* The PCI is working in LE Mode so swap the Data. */ + GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8); + } + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, data); + } else { /* configuration Transaction over the pci. */ + GT_WRITE(GT_PCI1_CFGADDR_OFS, le32_to_cpu(data)); + } +} + + +/******************************************************************** + *galileo_pcibios_(read/write)_config_(dword/word/byte) - + * + *reads/write a dword/word/byte register from the configuration space + *of a device. + * + *Inputs : + *bus - bus number + *dev - device number + *offset - register offset in the configuration space + *val - value to be written / read + * + *Outputs : + *PCIBIOS_SUCCESSFUL when operation was succesfull + *PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous + *PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned + *********************************************************************/ + +static int galileo_pcibios_read_config_dword(struct pci_dev *device, + int offset, u32 * val) +{ + int dev, bus; + //DBG(KERN_INFO "rcd entry \n",offset,val); + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) { + *val = 0xffffffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + if (offset & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (bus == 0) + *val = pci0ReadConfigReg(offset, device); +// if (bus == 1) *val = pci1ReadConfigReg (offset,device); + DBG(KERN_INFO "rr: rcd dev %d offset %x %x\n", dev, offset, *val); + + /* This is so that the upper PCI layer will get the correct return value if + we're not attached to anything. */ + if ((offset == 0) && (*val == 0xffffffff)) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_read_config_word(struct pci_dev *device, + int offset, u16 * val) +{ + int dev, bus; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) { + *val = 0xffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + if (offset & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (bus == 0) + *val = + (unsigned short) (pci0ReadConfigReg(offset, device) >> + ((offset & ~0x3) * 8)); +// if (bus == 1) *val = (unsigned short) (pci1ReadConfigReg(offset,device) >> ((offset & ~0x3) * 8)); + + DBG(KERN_INFO "rr: rcw dev %d offset %x %x\n", dev, offset, *val); + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_read_config_byte(struct pci_dev *device, + int offset, u8 * val) +{ + int dev, bus; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) { + *val = 0xff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + + if (bus == 0) + *val = + (unsigned char) (pci0ReadConfigReg(offset, device) >> + ((offset & ~0x3) * 8)); +// if (bus == 1) *val = (unsigned char) (pci1ReadConfigReg(offset,device) >> ((offset & ~0x3) * 8)); + + DBG(KERN_INFO "rr: rcb dev %d offset %x %x\n", dev, offset, *val); + + /* This is so that the upper PCI layer will get the correct return value if + we're not attached to anything. */ + if ((offset == 0xe) && (*val == 0xff)) { + u32 MasterAbort; + GT_READ(GT_INTRCAUSE_OFS, &MasterAbort); + if (MasterAbort & 0x40000) { + DBG(KERN_INFO "PCI Master Abort, ICR %x\n", + MasterAbort); + GT_WRITE(GT_INTRCAUSE_OFS, + (MasterAbort & 0xfffbffff)); + return PCIBIOS_DEVICE_NOT_FOUND; + } + } + + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_write_config_dword(struct pci_dev *device, + int offset, u32 val) +{ + int dev, bus; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + if (offset & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (bus == 0) + pci0WriteConfigReg(offset, device, val); +// if (bus == 1) pci1WriteConfigReg (offset,device,val); + + DBG(KERN_INFO "rr: wcd dev %d, offset %x, val %x\n", dev, offset, + val); + return PCIBIOS_SUCCESSFUL; +} + + +static int galileo_pcibios_write_config_word(struct pci_dev *device, + int offset, u16 val) +{ + int dev, bus; + unsigned long tmp; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + if (offset & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (bus == 0) + tmp = pci0ReadConfigReg(offset, device); +// if (bus == 1) tmp = pci1ReadConfigReg (offset,device); + + if ((offset % 4) == 0) + tmp = (tmp & 0xffff0000) | (val & 0xffff); + if ((offset % 4) == 2) + tmp = (tmp & 0x0000ffff) | ((val & 0xffff) << 16); + + if (bus == 0) + pci0WriteConfigReg(offset, device, tmp); +// if (bus == 1) pci1WriteConfigReg (offset,device,tmp); + DBG(KERN_INFO "rr: wcw dev %d, offset %x, val %x\n", dev, offset, + val); + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_write_config_byte(struct pci_dev *device, + int offset, u8 val) +{ + int dev, bus; + unsigned long tmp; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + if (bus == 0) + tmp = pci0ReadConfigReg(offset, device); +// if (bus == 1) tmp = pci1ReadConfigReg (offset,device); + + if ((offset % 4) == 0) + tmp = (tmp & 0xffffff00) | (val & 0xff); + if ((offset % 4) == 1) + tmp = (tmp & 0xffff00ff) | ((val & 0xff) << 8); + if ((offset % 4) == 2) + tmp = (tmp & 0xff00ffff) | ((val & 0xff) << 16); + if ((offset % 4) == 3) + tmp = (tmp & 0x00ffffff) | ((val & 0xff) << 24); + + if (bus == 0) + pci0WriteConfigReg(offset, device, tmp); +// if (bus == 1) pci1WriteConfigReg (offset,device,tmp); + DBG(KERN_INFO "rr: wcb dev %d, offset %x, val %x\n", dev, offset, + val); + + return PCIBIOS_SUCCESSFUL; +} + +static void galileo_pcibios_set_master(struct pci_dev *dev) +{ + u16 cmd; + + DBG(KERN_INFO "rr: galileo_pcibios_set_master\n"); + + galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER; + galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd); + DBG("PCI: Enabling device %s (%04x)\n", dev->slot_name, cmd); +} + +/* Externally-expected functions. Do not change function names */ + +int pcibios_enable_resources(struct pci_dev *dev) +{ + u16 cmd, old_cmd; + u16 tmp; + u8 tmp1; + int idx; + struct resource *r; + + DBG(KERN_INFO "rr: pcibios_enable_resources\n"); + + galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for (idx = 0; idx < 6; idx++) { + r = &dev->resource[idx]; + DBG(KERN_INFO + "rr: BAR %d, start %lx, end %lx, flags %lx\n", idx, + r->start, r->end, r->flags); + if (!r->start && r->end) { + printk(KERN_ERR + "PCI: Device %s not available because of resource collisions\n", + dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (cmd != old_cmd) { + DBG(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n", + dev->slot_name, old_cmd, cmd); + galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd); + } + + /* + Let's fix up the latency timer and cache line size here. Cache line size = + 32 bytes / sizeof dword (4) = 8. + Latency timer must be > 8. 32 is random but appears to work. + */ + galileo_pcibios_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1); + if (tmp1 != 8) { + DBG(KERN_INFO + "rr: PCI setting cache line size to 8 from %d\n", + tmp1); + galileo_pcibios_write_config_byte(dev, PCI_CACHE_LINE_SIZE, + 8); + } + galileo_pcibios_read_config_byte(dev, PCI_LATENCY_TIMER, &tmp1); + if (tmp1 < 32) { + DBG(KERN_INFO + "rr: PCI setting latency timer to 32 from %d\n", tmp1); + galileo_pcibios_write_config_byte(dev, PCI_LATENCY_TIMER, + 32); + } + + return 0; +} + +int pcibios_enable_device(struct pci_dev *dev) +{ + DBG(KERN_INFO "rr: pcibios_enable_device\n"); + return pcibios_enable_resources(dev); +} + +void pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ + u32 new, check; + int reg; + + DBG(KERN_INFO "rr: pcibios_update_resource\n"); + return; + + new = res->start | (res->flags & PCI_REGION_FLAG_MASK); + if (resource < 6) { + reg = PCI_BASE_ADDRESS_0 + 4 * resource; + } else if (resource == PCI_ROM_RESOURCE) { + res->flags |= PCI_ROM_ADDRESS_ENABLE; + reg = dev->rom_base_reg; + } else { + /* Somebody might have asked allocation of a non-standard resource */ + return; + } + + pci_write_config_dword(dev, reg, new); + pci_read_config_dword(dev, reg, &check); + if ((new ^ check) & + ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : + PCI_BASE_ADDRESS_MEM_MASK)) { + DBG(KERN_ERR "PCI: Error while updating region " + "%s/%d (%08x != %08x)\n", dev->slot_name, resource, + new, check); + } +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size) +{ + struct pci_dev *dev = data; + + DBG(KERN_INFO "pcibios_align_resource\n"); + + if (res->flags & IORESOURCE_IO) { + unsigned long start = res->start; + + /* We need to avoid collisions with `mirrored' VGA ports + and other strange ISA hardware, so we always want the + addresses kilobyte aligned. */ + if (size > 0x100) { + DBG(KERN_ERR "PCI: I/O Region %s/%d too large" + " (%ld bytes)\n", dev->slot_name, + dev->resource - res, size); + } + + start = (start + 1024 - 1) & ~(1024 - 1); + res->start = start; + } +} + +/******************************************************************** + *structure galileo_pci_ops + * + *This structure holds the pointers for the PCI configuration space + *access, and the fixup for the interrupts. + *This structure is registered to the operating system in boot time + * + *********************************************************************/ + +struct pci_ops galileo_pci_ops = { + galileo_pcibios_read_config_byte, + galileo_pcibios_read_config_word, + galileo_pcibios_read_config_dword, + galileo_pcibios_write_config_byte, + galileo_pcibios_write_config_word, + galileo_pcibios_write_config_dword +}; + +/******************************************************************** + *galileo_pcibios_fixup_bus - + * + *After detecting all agents over the PCI , this function is called + *in order to give an interrupt number for each PCI device starting + *from IRQ 20. It does also enables master for each device. + * + *Inputs : + *mem_start , mem_end are not relevant in MIPS architecture. + * + *Outpus : + *return always mem_start + *********************************************************************/ +static void __init galileo_pcibios_fixup_bus(struct pci_bus *bus) +{ + unsigned int Current_IRQ = 20; + struct pci_bus *current_bus = bus; + struct pci_dev *devices; + struct list_head *devices_link; + + list_for_each(devices_link, &(current_bus->devices)) { + devices = pci_dev_b(devices_link); + if (devices != NULL) { + devices->irq = Current_IRQ++; + + /* Assign an interrupt number for the device */ + galileo_pcibios_write_config_byte(devices, + PCI_INTERRUPT_LINE, + Current_IRQ); + galileo_pcibios_set_master(devices); + + } + } + +} + +struct pci_fixup pcibios_fixups[] = { +// { PCI_FIXUP_HEADER, 0x4620, 0x11ab, galileo_pcibios_fixup }, + {0} +}; + +void __init pcibios_fixup_bus(struct pci_bus *c) +{ + DBG(KERN_INFO "rr: pcibios_fixup_bus\n"); + galileo_pcibios_fixup_bus(c); +} + +/* + This code was derived from Galileo Technology's example + and significantly reworked. + + This is very simple. It does not scan multiple function devices. It does not + scan behind bridges. Those would be simple to implement, but we don't currently + need this. +*/ + +static void __init scan_and_initialize_pci(void) +{ + struct pci_device pci_devices[MAX_PCI_DEVS]; + + if (scan_pci_bus(pci_devices)) { + allocate_pci_space(pci_devices); + } +} + +/* + This is your basic PCI scan. It goes through each slot and checks to + see if there's something that responds. If so, then get the size and + type of each of the responding BARs. Save them for later. +*/ + +static u32 __init scan_pci_bus(struct pci_device *pci_devices) +{ + u32 arrayCounter = 0; + u32 memType; + u32 memSize; + u32 pci_slot, bar; + u32 id; + u32 c18RegValue; + struct pci_dev device; + + DBG(KERN_INFO "rr: scan_pci_bus\n"); + + /* + According to PCI REV 2.1 MAX agents on the bus are 21. + We don't bother scanning ourselves (slot 0). + */ + for (pci_slot = 1; pci_slot < 22; pci_slot++) { + + device.devfn = PCI_DEVFN(pci_slot, 0); + id = pci0ReadConfigReg(PCI_VENDOR_ID, &device); + + /* Check for a PCI Master Abort (nothing responds in the slot) */ + GT_READ(GT_INTRCAUSE_OFS, &c18RegValue); + /* Clearing bit 18 of in the Cause Register 0xc18 by writting 0. */ + GT_WRITE(GT_INTRCAUSE_OFS, (c18RegValue & 0xfffbffff)); + if ((id != 0xffffffff) && !(c18RegValue & 0x40000)) { + DBG(KERN_INFO "rr: found device %x, slot %d\n", id, + pci_slot); + pci_devices[arrayCounter].slot = pci_slot; + for (bar = 0; bar < 6; bar++) { + memType = + pci0ReadConfigReg(PCI_BASE_ADDRESS_0 + + (bar * 4), &device); + pci_devices[arrayCounter].BARtype[bar] = + memType & 1; + pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + + (bar * 4), &device, + 0xffffffff); + memSize = + pci0ReadConfigReg(PCI_BASE_ADDRESS_0 + + (bar * 4), &device); + if (memType & 1) { /* IO space */ + pci_devices[arrayCounter]. + BARsize[bar] = + ~(memSize & 0xfffffffc) + 1; + } else { /* memory space */ + pci_devices[arrayCounter]. + BARsize[bar] = + ~(memSize & 0xfffffff0) + 1; + } + DBG(KERN_INFO + "rr: BAR %d, type %d, size %x\n", bar, + (memType & 1), + pci_devices[arrayCounter]. + BARsize[bar]); + } /* BAR counter */ + + arrayCounter++; + } + /* found a device */ + } /* slot counter */ + + DBG(KERN_INFO "rr: found %d devices\n", arrayCounter); + if (arrayCounter < MAX_PCI_DEVS) { + pci_devices[arrayCounter].slot = -1; + } + return (arrayCounter); +} + +#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1)) +#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2)) + +/* + This function goes through the list of devices and allocates the BARs in + either IO or MEM space. It does it in order of size, which will limit the + amount of fragmentation we have in the IO and MEM spaces. +*/ + +static void __init allocate_pci_space(struct pci_device *pci_devices) +{ + u32 count, maxcount, bar; + u32 maxSize, maxDevice, maxBAR; + u32 alignto; + u32 base; + u32 pci0_mem_base = pci0GetMemory0Base(); + u32 pci0_io_base = pci0GetIOspaceBase(); + struct pci_dev device; + + DBG(KERN_INFO "rr: allocate_pci_space\n"); + + DBG(KERN_INFO "pci0_io_base %x\n", pci0_io_base); + DBG(KERN_INFO "pci0_mem_base %x\n", pci0_mem_base); + + /* How many PCI devices do we have? */ + maxcount = MAX_PCI_DEVS; + for (count = 0; count < MAX_PCI_DEVS; count++) { + if (pci_devices[count].slot == -1) { + maxcount = count; + break; + } + } + +// DBG(KERN_INFO "Found %d devices\n", maxcount); + + do { + /* Find the largest size BAR we need to allocate */ + maxSize = 0; + for (count = 0; count < maxcount; count++) { + for (bar = 0; bar < 6; bar++) { + if (pci_devices[count].BARsize[bar] > + maxSize) { + maxSize = + pci_devices[count]. + BARsize[bar]; + maxDevice = count; + maxBAR = bar; + } + } + } + + /* + We've found the largest BAR. Allocate it into IO or + mem space. We don't idiot check the bases to make + sure they haven't overflowed the current size for that aperture. + + Don't bother to enable the device's IO or MEM space here. That will + be done in pci_enable_resources if the device is activated by a driver. + */ + if (maxSize) { + device.devfn = + PCI_DEVFN(pci_devices[maxDevice].slot, 0); + if (pci_devices[maxDevice].BARtype[maxBAR] == 1) { + alignto = MAX(0x1000, maxSize); + base = ALIGN(pci0_io_base, alignto); + pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + + (maxBAR * 4), &device, + base | 0x1); + pci0_io_base = base + alignto; + DBG(KERN_INFO + "Device %d BAR %d address %x\n", + pci_devices[maxDevice].slot, maxBAR, + base); + DBG(KERN_INFO "New IO base %x\n", + pci0_io_base); + } else { + alignto = MAX(0x1000, maxSize); + base = ALIGN(pci0_mem_base, alignto); + pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + + (maxBAR * 4), &device, + base); + pci0_mem_base = base + alignto; + DBG(KERN_INFO + "Device %d BAR %d address %x\n", + pci_devices[maxDevice].slot, maxBAR, + base); + DBG(KERN_INFO "New mem base %x\n", + pci0_mem_base); + } + /* + This entry is finished. Remove it from the list we'll scan. + */ + pci_devices[maxDevice].BARsize[maxBAR] = 0; + } + } while (maxSize); +} + +void __init pcibios_init(void) +{ + + u32 tmp; + struct pci_dev controller; + + controller.devfn = SELF; + + DBG(KERN_INFO "rr: pcibios_init\n"); + GT_READ(GT_PCI0_CMD_OFS, &tmp); + DBG(KERN_INFO "rr: PCI0 command - %x\n", tmp); + GT_READ(GT_PCI0_BARE_OFS, &tmp); + DBG(KERN_INFO "rr: BAR0 - %x\n", tmp); + +/* + You have to enable bus mastering to configure any other + card on the bus. +*/ + tmp = pci0ReadConfigReg(PCI_COMMAND, &controller); + DBG(KERN_INFO "rr: command/status - %x\n", tmp); + tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR; + DBG(KERN_INFO "rr: new command/status - %x\n", tmp); + pci0WriteConfigReg(PCI_COMMAND, &controller, tmp); + + /* This scans the PCI bus and sets up initial values. */ + scan_and_initialize_pci(); + + /* Reset PCI I/O and PCI MEM values to ones supported + by EVM. + */ + ioport_resource.start = 0x10000000; + ioport_resource.end = 0x11ffffff; /* 32 MB */ + iomem_resource.start = 0x12000000; + iomem_resource.end = 0x13ffffff; /* 32 MB */ + + pci_scan_bus(0, &galileo_pci_ops, NULL); + +} + +char *pcibios_setup(char *str) +{ + printk(KERN_INFO "rr: pcibios_setup\n"); + /* Nothing to do for now. */ + + return str; +} + +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t * dma_handle) +{ + void *ret; + int gfp = GFP_ATOMIC; + + if (hwdev == NULL || hwdev->dma_mask != 0xffffffff) + gfp |= GFP_DMA; + ret = (void *) __get_free_pages(gfp, get_order(size)); + + if (ret != NULL) { + memset(ret, 0, size); + *dma_handle = virt_to_bus(ret); + } + return ret; +} + +#if 1 +void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + free_pages((unsigned long) vaddr, get_order(size)); +} +#endif + +#endif /* CONFIG_PCI */ diff --git a/arch/mips/galileo-boards/ev64120/promcon.c b/arch/mips/galileo-boards/ev64120/promcon.c new file mode 100644 index 000000000..83d3006f9 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/promcon.c @@ -0,0 +1,80 @@ +/* + * 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 + */ + +#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 prom_console_wait_key(struct console *co) +{ + return prom_getchar(); +} + +static int __init prom_console_setup(struct console *co, char *options) +{ + + return 0; +} + +static kdev_t prom_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + +static struct console sercons = { + "ttyS", + prom_console_write, + NULL, + prom_console_device, + prom_console_wait_key, + NULL, + prom_console_setup, + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + + +/* + * Register console. + */ + +void gal_serial_console_init(void) +{ + // serial_init(); + //serial_set(115200); + + register_console(&sercons); +} diff --git a/arch/mips/galileo-boards/ev64120/reset.c b/arch/mips/galileo-boards/ev64120/reset.c new file mode 100644 index 000000000..b145a3446 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/reset.c @@ -0,0 +1,73 @@ +/* + * EVB96100 -Galileo reset subroutines + * + */ +#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> + +/******************************************************************** + *galileo_machine_restart - + * + *Restart the machine + * + * + *Inputs : + *command - not used + * + *Outpus : + * + *********************************************************************/ +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_cp0_status((ST0_BEV | ST0_ERL), (ST0_BEV | ST0_ERL)); + set_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_32bit_cp0_register(CP0_WIRED, 0); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +/******************************************************************** + *galileo_machine_halt - + * + *Halt the machine + * + * + *Inputs : + * + *Outpus : + * + *********************************************************************/ +void galileo_machine_halt(void) +{ + printk("\n** You can safely turn off the power\n"); + while (1) { + } +} + +/******************************************************************** + *galileo_machine_power_off - + * + *Halt the machine + * + * + *Inputs : + * + *Outpus : + * + *********************************************************************/ +void galileo_machine_power_off(void) +{ + galileo_machine_halt(); +} diff --git a/arch/mips/galileo-boards/ev64120/serialGT.c b/arch/mips/galileo-boards/ev64120/serialGT.c new file mode 100644 index 000000000..3d2d4452d --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/serialGT.c @@ -0,0 +1,212 @@ +/* + * 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); +} diff --git a/arch/mips/galileo-boards/ev64120/setup.c b/arch/mips/galileo-boards/ev64120/setup.c new file mode 100644 index 000000000..874245fa8 --- /dev/null +++ b/arch/mips/galileo-boards/ev64120/setup.c @@ -0,0 +1,234 @@ +/* + * setup.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/swap.h> +#include <linux/ioport.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/timex.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> + +extern struct rtc_ops no_rtc_ops; +struct rtc_ops *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; + +/* + * These two functions are added because arch/mips/mm/init.c needs them + * basically they do nothing + */ +void __init prom_fixup_mem_map(unsigned long start, unsigned long end) +{ +} + +void prom_free_prom_memory(void) +{ +} + +int /*__init*/ page_is_ram(unsigned long pagenr) +{ + return 1; +} + +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 ev64120_setup(void) +{ + unsigned int i, j; + + //printk(KERN_INFO "ev64120_setup\n"); + + _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; + mips_io_port_base = KSEG1; + mips_memory_upper = 32 * 1024 * 1024 | KSEG0; + set_cp0_status(ST0_FR, 0); + +#ifdef CONFIG_L2_L3_CACHE +#error "external cache not implemented yet" + config_register = read_32bit_cp0_register(CP0_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_32bit_cp0_register(CP0_CONFIG, config_register); + printk + ("\n\n\nchecking second level cache cp0_config = %08lx\n", + config_register); + } +#endif + +} + +/******************************************************************** + *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 + * + *Outpus : + * + *********************************************************************/ +void SetUpBootInfo(int argc, char **argv, char **envp) +{ + mips_machgroup = MACH_GROUP_GALILEO; + mips_machtype = MACH_EV64120A; +} + +#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) +#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) + +extern int _end; + +unsigned long mem_size; +int __init prom_init(int a, char **b, char **c, int *d) +{ + unsigned long free_start, free_end, start_pfn, bootmap_size; + + mips_machgroup = MACH_GROUP_GALILEO; + /* 32 MB */ + mem_size = 32 << 20; + mips_memory_upper = 0x81000000; + + free_start = PHYSADDR(PFN_ALIGN(&_end)); + free_end = mem_size; + start_pfn = PFN_UP((unsigned long) &_end); + + /* Register all the contiguous memory with the bootmem allocator + and free it. Be careful about the bootmem freemap. */ + bootmap_size = init_bootmem(start_pfn, mem_size >> PAGE_SHIFT); + + /* Free the entire available memory after the _end symbol. */ + free_start += bootmap_size; + free_bootmem(free_start, free_end - free_start); + return 0; +} + +#if 0 +void prom_free_prom_memory(void) +{ +} + +int page_is_ram(unsigned long pagenr) +{ + if (pagenr < (mem_size >> PAGE_SHIFT)) + return 1; + return 0; +} + +void turn_on_debug_led(); + +void turn_on_debug_led() +{ +#define DEBUG_LIGHT (*(char *)0xbc080000) + DEBUG_LIGHT = 1; +} +#endif |