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