/* 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; }