| /* Memory.c - Memory mappings and remapping functions */ | |
| /* Copyright - Galileo technology. */ | |
| /* modified by Josh Huber to clean some things up, and | |
| * fit it into the U-Boot framework */ | |
| #include <galileo/core.h> | |
| #include <galileo/memory.h> | |
| /******************************************************************** | |
| * memoryGetBankBaseAddress - Gets 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 - The bank we ask for its base Address. | |
| * OUTPUT: N/A | |
| * RETURNS: Memory bank base address. | |
| *********************************************************************/ | |
| static unsigned long memoryGetBankRegOffset(MEMORY_BANK bank) | |
| { | |
| switch (bank) | |
| { | |
| case BANK0: | |
| return SCS_0_LOW_DECODE_ADDRESS; | |
| case BANK1: | |
| return SCS_1_LOW_DECODE_ADDRESS; | |
| case BANK2: | |
| return SCS_2_LOW_DECODE_ADDRESS; | |
| case BANK3: | |
| return SCS_3_LOW_DECODE_ADDRESS; | |
| } | |
| return SCS_0_LOW_DECODE_ADDRESS; /* default value */ | |
| } | |
| unsigned int memoryGetBankBaseAddress(MEMORY_BANK bank) | |
| { | |
| unsigned int base; | |
| unsigned int regOffset=memoryGetBankRegOffset(bank); | |
| GT_REG_READ(regOffset,&base); | |
| base = base << 20; | |
| return base; | |
| } | |
| /******************************************************************** | |
| * memoryGetDeviceBaseAddress - Gets the base address of a device. | |
| * - If the device size is 0 then this base address has no meaning!!! | |
| * | |
| * | |
| * INPUT: DEVICE device - The device we ask for its base address. | |
| * OUTPUT: N/A | |
| * RETURNS: Device base address. | |
| *********************************************************************/ | |
| static unsigned int memoryGetDeviceRegOffset(DEVICE device) | |
| { | |
| switch (device) | |
| { | |
| case DEVICE0: | |
| return CS_0_LOW_DECODE_ADDRESS; | |
| case DEVICE1: | |
| return CS_1_LOW_DECODE_ADDRESS; | |
| case DEVICE2: | |
| return CS_2_LOW_DECODE_ADDRESS; | |
| case DEVICE3: | |
| return CS_3_LOW_DECODE_ADDRESS; | |
| case BOOT_DEVICE: | |
| return BOOTCS_LOW_DECODE_ADDRESS; | |
| } | |
| return CS_0_LOW_DECODE_ADDRESS; /* default value */ | |
| } | |
| unsigned int memoryGetDeviceBaseAddress(DEVICE device) | |
| { | |
| unsigned int regBase; | |
| unsigned int regEnd; | |
| unsigned int regOffset=memoryGetDeviceRegOffset(device); | |
| GT_REG_READ(regOffset, ®Base); | |
| GT_REG_READ(regOffset+8, ®End); | |
| if(regEnd<=regBase) return 0xffffffff; /* ERROR !!! */ | |
| regBase = regBase << 20; | |
| return regBase; | |
| } | |
| /******************************************************************** | |
| * memoryGetBankSize - Returns the size of a memory bank. | |
| * | |
| * | |
| * INPUT: MEMORY_BANK bank - The bank we ask for its size. | |
| * OUTPUT: N/A | |
| * RETURNS: Memory bank size. | |
| *********************************************************************/ | |
| unsigned int memoryGetBankSize(MEMORY_BANK bank) | |
| { | |
| unsigned int size,base; | |
| unsigned int highValue; | |
| unsigned int highAddress=memoryGetBankRegOffset(bank)+8; | |
| base = memoryGetBankBaseAddress(bank); | |
| GT_REG_READ(highAddress,&highValue); | |
| highValue = (highValue + 1) << 20; | |
| if(base > highValue) | |
| size=0; | |
| else | |
| size = highValue - base; | |
| return size; | |
| } | |
| /******************************************************************** | |
| * memoryGetDeviceSize - Returns the size of a device memory space | |
| * | |
| * | |
| * INPUT: DEVICE device - The device we ask for its base address. | |
| * OUTPUT: N/A | |
| * RETURNS: Size of a device memory space. | |
| *********************************************************************/ | |
| unsigned int memoryGetDeviceSize(DEVICE device) | |
| { | |
| unsigned int size,base; | |
| unsigned int highValue; | |
| unsigned int highAddress=memoryGetDeviceRegOffset(device)+8; | |
| base = memoryGetDeviceBaseAddress(device); | |
| GT_REG_READ(highAddress,&highValue); | |
| if (highValue == 0xfff) | |
| { | |
| size = (~base) + 1; /* what the heck is this? */ | |
| return size; | |
| } | |
| else | |
| highValue = (highValue + 1) << 20; | |
| if(base > highValue) | |
| size=0; | |
| else | |
| size = highValue - base; | |
| return size; | |
| } | |
| /******************************************************************** | |
| * memoryGetDeviceWidth - 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 memoryGetDeviceWidth(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; | |
| } | |
| } | |
| bool memoryMapBank(MEMORY_BANK bank, unsigned int bankBase,unsigned int bankLength) | |
| { | |
| unsigned int low=0xfff; | |
| unsigned int high=0x0; | |
| unsigned int regOffset=memoryGetBankRegOffset(bank); | |
| if(bankLength!=0) { | |
| low = (bankBase >> 20) & 0xffff; | |
| high=((bankBase+bankLength)>>20)-1; | |
| } | |
| #ifdef DEBUG | |
| { | |
| unsigned int oldLow, oldHigh; | |
| GT_REG_READ(regOffset,&oldLow); | |
| GT_REG_READ(regOffset+8,&oldHigh); | |
| printf("b%d %x-%x->%x-%x\n", bank, oldLow, oldHigh, low, high); | |
| } | |
| #endif | |
| GT_REG_WRITE(regOffset,low); | |
| GT_REG_WRITE(regOffset+8,high); | |
| return true; | |
| } | |
| bool memoryMapDeviceSpace(DEVICE device, unsigned int deviceBase,unsigned int deviceLength) | |
| { | |
| /* TODO: what are appropriate "unmapped" values? */ | |
| unsigned int low=0xfff; | |
| unsigned int high=0x0; | |
| unsigned int regOffset=memoryGetDeviceRegOffset(device); | |
| if(deviceLength != 0) { | |
| low=deviceBase>>20; | |
| high=((deviceBase+deviceLength)>>20)-1; | |
| } else { | |
| /* big problems in here... */ | |
| /* this will HANG */ | |
| } | |
| GT_REG_WRITE(regOffset,low); | |
| GT_REG_WRITE(regOffset+8,high); | |
| return true; | |
| } | |
| /******************************************************************** | |
| * memoryMapInternalRegistersSpace - Sets new base address for the internals | |
| * registers. | |
| * | |
| * INPUTS: unsigned int internalRegBase - The new base address. | |
| * RETURNS: true on success, false on failure | |
| *********************************************************************/ | |
| bool memoryMapInternalRegistersSpace(unsigned int internalRegBase) | |
| { | |
| unsigned int currentValue; | |
| unsigned int internalValue = internalRegBase; | |
| internalRegBase = (internalRegBase >> 20); | |
| GT_REG_READ(INTERNAL_SPACE_DECODE,¤tValue); | |
| internalRegBase = (currentValue & 0xffff0000) | internalRegBase; | |
| GT_REG_WRITE(INTERNAL_SPACE_DECODE,internalRegBase); | |
| INTERNAL_REG_BASE_ADDR = internalValue; | |
| return true; | |
| } | |
| /******************************************************************** | |
| * memoryGetInternalRegistersSpace - Gets internal registers Base Address. | |
| * | |
| * INPUTS: unsigned int internalRegBase - The new base address. | |
| * RETURNS: true on success, false on failure | |
| *********************************************************************/ | |
| unsigned int memoryGetInternalRegistersSpace(void) | |
| { | |
| return INTERNAL_REG_BASE_ADDR; | |
| } | |
| /******************************************************************** | |
| * memorySetProtectRegion - This function modifys one of the 8 regions with | |
| * one of the three protection mode. | |
| * - Be advised to check the spec before modifying them. | |
| * | |
| * | |
| * Inputs: CPU_PROTECT_REGION - one of the eight regions. | |
| * CPU_ACCESS - general access. | |
| * CPU_WRITE - read only access. | |
| * CPU_CACHE_PROTECT - chache access. | |
| * we defining CPU because there is another protect from the pci SIDE. | |
| * Returns: false if one of the parameters is wrong and true else | |
| *********************************************************************/ | |
| bool memorySetProtectRegion(MEMORY_PROTECT_REGION region, | |
| MEMORY_ACCESS memAccess, | |
| MEMORY_ACCESS_WRITE memWrite, | |
| MEMORY_CACHE_PROTECT cacheProtection, | |
| unsigned int baseAddress, | |
| unsigned int regionLength) | |
| { | |
| unsigned int protectHigh = baseAddress + regionLength; | |
| if(regionLength == 0) /* closing the region */ | |
| { | |
| GT_REG_WRITE(CPU_LOW_PROTECT_ADDRESS_0 + 0x10*region,0x0000ffff); | |
| GT_REG_WRITE(CPU_HIGH_PROTECT_ADDRESS_0 + 0x10*region,0); | |
| return true; | |
| } | |
| baseAddress = (baseAddress & 0xfff00000) >> 20; | |
| baseAddress = baseAddress | memAccess << 16 | memWrite << 17 | |
| | cacheProtection << 18; | |
| GT_REG_WRITE(CPU_LOW_PROTECT_ADDRESS_0 + 0x10*region,baseAddress); | |
| protectHigh = (protectHigh & 0xfff00000) >> 20; | |
| GT_REG_WRITE(CPU_HIGH_PROTECT_ADDRESS_0 + 0x10*region,protectHigh - 1); | |
| return true; | |
| } | |
| /******************************************************************** | |
| * memorySetRegionSnoopMode - This function modifys one of the 4 regions which | |
| * supports Cache Coherency. | |
| * | |
| * | |
| * Inputs: SNOOP_REGION region - One of the four regions. | |
| * SNOOP_TYPE snoopType - There is four optional Types: | |
| * 1. No Snoop. | |
| * 2. Snoop to WT region. | |
| * 3. Snoop to WB region. | |
| * 4. Snoop & Invalidate to WB region. | |
| * unsigned int baseAddress - Base Address of this region. | |
| * unsigned int topAddress - Top Address of this region. | |
| * Returns: false if one of the parameters is wrong and true else | |
| *********************************************************************/ | |
| bool memorySetRegionSnoopMode(MEMORY_SNOOP_REGION region, | |
| MEMORY_SNOOP_TYPE snoopType, | |
| unsigned int baseAddress, | |
| unsigned int regionLength) | |
| { | |
| unsigned int snoopXbaseAddress; | |
| unsigned int snoopXtopAddress; | |
| unsigned int data; | |
| unsigned int snoopHigh = baseAddress + regionLength; | |
| if( (region > MEM_SNOOP_REGION3) || (snoopType > MEM_SNOOP_WB) ) | |
| return false; | |
| snoopXbaseAddress = SNOOP_BASE_ADDRESS_0 + 0x10 * region; | |
| snoopXtopAddress = SNOOP_TOP_ADDRESS_0 + 0x10 * region; | |
| if(regionLength == 0) /* closing the region */ | |
| { | |
| GT_REG_WRITE(snoopXbaseAddress,0x0000ffff); | |
| GT_REG_WRITE(snoopXtopAddress,0); | |
| return true; | |
| } | |
| baseAddress = baseAddress & 0xffff0000; | |
| data = (baseAddress >> 16) | snoopType << 16; | |
| GT_REG_WRITE(snoopXbaseAddress,data); | |
| snoopHigh = (snoopHigh & 0xfff00000) >> 20; | |
| GT_REG_WRITE(snoopXtopAddress,snoopHigh - 1); | |
| return true; | |
| } | |
| /******************************************************************** | |
| * memoryRemapAddress - This fubction used for address remapping. | |
| * | |
| * | |
| * Inputs: regOffset: remap register | |
| * remapValue : | |
| * Returns: false if one of the parameters is erroneous,true otherwise. | |
| *********************************************************************/ | |
| bool memoryRemapAddress(unsigned int remapReg, unsigned int remapValue) | |
| { | |
| unsigned int valueForReg; | |
| valueForReg = (remapValue & 0xfff00000) >> 20; | |
| GT_REG_WRITE(remapReg, valueForReg); | |
| return true; | |
| } | |
| /******************************************************************** | |
| * memoryGetDeviceParam - This function used for getting device parameters from | |
| * DEVICE BANK PARAMETERS REGISTER | |
| * | |
| * | |
| * Inputs: - deviceParam: STRUCT with paramiters for DEVICE BANK | |
| * PARAMETERS REGISTER | |
| * - deviceNum : number of device | |
| * Returns: false if one of the parameters is erroneous,true otherwise. | |
| *********************************************************************/ | |
| bool memoryGetDeviceParam(DEVICE_PARAM *deviceParam, DEVICE deviceNum) | |
| { | |
| unsigned int valueOfReg; | |
| unsigned int calcData; | |
| GT_REG_READ(DEVICE_BANK0PARAMETERS + 4 * deviceNum, &valueOfReg); | |
| calcData = (0x7 & valueOfReg) + ((0x400000 & valueOfReg) >> 19); | |
| deviceParam -> turnOff = calcData; /* Turn Off */ | |
| calcData = ((0x78 & valueOfReg) >> 3) + ((0x800000 & valueOfReg) >> 19); | |
| deviceParam -> acc2First = calcData; /* Access To First */ | |
| calcData = ((0x780 & valueOfReg) >> 7) + ((0x1000000 & valueOfReg) >> 20); | |
| deviceParam -> acc2Next = calcData; /* Access To Next */ | |
| calcData = ((0x3800 & valueOfReg) >> 11) + ((0x2000000 & valueOfReg) >> 22); | |
| deviceParam -> ale2Wr = calcData; /* Ale To Write */ | |
| calcData = ((0x1c000 & valueOfReg) >> 14) + ((0x4000000 & valueOfReg) >> 23); | |
| deviceParam -> wrLow = calcData; /* Write Active */ | |
| calcData = ((0xe0000 & valueOfReg) >> 17) + ((0x8000000 & valueOfReg) >> 24); | |
| deviceParam -> wrHigh = calcData; /* Write High */ | |
| calcData = ((0x300000 & valueOfReg) >> 20); | |
| switch (calcData) | |
| { | |
| case 0: | |
| deviceParam -> deviceWidth = 1; /* one Byte - 8-bit */ | |
| break; | |
| case 1: | |
| deviceParam -> deviceWidth = 2; /* two Bytes - 16-bit */ | |
| break; | |
| case 2: | |
| deviceParam -> deviceWidth = 4; /* four Bytes - 32-bit */ | |
| break; | |
| case 3: | |
| deviceParam -> deviceWidth = 8; /* eight Bytes - 64-bit */ | |
| break; | |
| default: | |
| deviceParam -> deviceWidth = 1; | |
| break; | |
| } | |
| return true; | |
| } | |
| /******************************************************************** | |
| * memorySetDeviceParam - This function used for setting device parameters to | |
| * DEVICE BANK PARAMETERS REGISTER | |
| * | |
| * | |
| * Inputs: - deviceParam: STRUCT for store paramiters from DEVICE BANK | |
| * PARAMETERS REGISTER | |
| * - deviceNum : number of device | |
| * Returns: false if one of the parameters is erroneous,true otherwise. | |
| *********************************************************************/ | |
| bool memorySetDeviceParam(DEVICE_PARAM *deviceParam, DEVICE deviceNum) | |
| { | |
| unsigned int valueForReg; | |
| if((deviceParam -> turnOff >= 0xf) || (deviceParam -> acc2First >= 0x1f) || | |
| (deviceParam -> acc2Next >= 0x1f) || (deviceParam -> ale2Wr >= 0xf) || | |
| (deviceParam -> wrLow >= 0xf) || (deviceParam -> wrHigh >= 0xf)) | |
| return false; | |
| valueForReg = (((deviceParam -> turnOff) & 0x7) | | |
| (((deviceParam -> turnOff) & 0x8) << 19) | | |
| (((deviceParam -> acc2First) & 0xf) << 3) | | |
| (((deviceParam -> acc2First) & 0x10) << 19) | | |
| (((deviceParam -> acc2Next) & 0xf) << 7) | | |
| (((deviceParam -> acc2Next) & 0x10) << 20) | | |
| (((deviceParam -> ale2Wr) & 0x7) << 11) | | |
| (((deviceParam -> ale2Wr) & 0xf) << 22) | | |
| (((deviceParam -> wrLow) & 0x7) << 14) | | |
| (((deviceParam -> wrLow) & 0xf) << 23) | | |
| (((deviceParam -> wrHigh) & 0x7) << 17) | | |
| (((deviceParam -> wrHigh) & 0xf) << 24)); | |
| /* insert the device width: */ | |
| switch(deviceParam->deviceWidth) | |
| { | |
| case 1: | |
| valueForReg = valueForReg | _8BIT; | |
| break; | |
| case 2: | |
| valueForReg = valueForReg | _16BIT; | |
| break; | |
| case 4: | |
| valueForReg = valueForReg | _32BIT; | |
| break; | |
| case 8: | |
| valueForReg = valueForReg | _64BIT; | |
| break; | |
| default: | |
| valueForReg = valueForReg | _8BIT; | |
| break; | |
| } | |
| GT_REG_WRITE(DEVICE_BANK0PARAMETERS + 4 * deviceNum, valueForReg); | |
| return true; | |
| } |