wdenk | 7ebf744 | 2002-11-02 23:17:16 +0000 | [diff] [blame] | 1 | /* Memory.c - Memory mappings and remapping functions */ |
| 2 | |
| 3 | /* Copyright - Galileo technology. */ |
| 4 | |
| 5 | /* modified by Josh Huber to clean some things up, and |
| 6 | * fit it into the U-Boot framework */ |
| 7 | |
| 8 | #include <galileo/core.h> |
| 9 | #include <galileo/memory.h> |
| 10 | |
| 11 | /******************************************************************** |
| 12 | * memoryGetBankBaseAddress - Gets the base address of a memory bank |
| 13 | * - If the memory bank size is 0 then this base address has no meaning!!! |
| 14 | * |
| 15 | * |
| 16 | * INPUTS: MEMORY_BANK bank - The bank we ask for its base Address. |
| 17 | * OUTPUT: N/A |
| 18 | * RETURNS: Memory bank base address. |
| 19 | *********************************************************************/ |
| 20 | static unsigned long memoryGetBankRegOffset(MEMORY_BANK bank) |
| 21 | { |
| 22 | switch (bank) |
| 23 | { |
| 24 | case BANK0: |
| 25 | return SCS_0_LOW_DECODE_ADDRESS; |
| 26 | case BANK1: |
| 27 | return SCS_1_LOW_DECODE_ADDRESS; |
| 28 | case BANK2: |
| 29 | return SCS_2_LOW_DECODE_ADDRESS; |
| 30 | case BANK3: |
| 31 | return SCS_3_LOW_DECODE_ADDRESS; |
| 32 | } |
| 33 | return SCS_0_LOW_DECODE_ADDRESS; /* default value */ |
| 34 | } |
| 35 | |
| 36 | unsigned int memoryGetBankBaseAddress(MEMORY_BANK bank) |
| 37 | { |
| 38 | unsigned int base; |
| 39 | unsigned int regOffset=memoryGetBankRegOffset(bank); |
| 40 | |
| 41 | GT_REG_READ(regOffset,&base); |
| 42 | base = base << 20; |
| 43 | return base; |
| 44 | } |
| 45 | |
| 46 | /******************************************************************** |
| 47 | * memoryGetDeviceBaseAddress - Gets the base address of a device. |
| 48 | * - If the device size is 0 then this base address has no meaning!!! |
| 49 | * |
| 50 | * |
| 51 | * INPUT: DEVICE device - The device we ask for its base address. |
| 52 | * OUTPUT: N/A |
| 53 | * RETURNS: Device base address. |
| 54 | *********************************************************************/ |
| 55 | static unsigned int memoryGetDeviceRegOffset(DEVICE device) |
| 56 | { |
| 57 | switch (device) |
| 58 | { |
| 59 | case DEVICE0: |
| 60 | return CS_0_LOW_DECODE_ADDRESS; |
| 61 | case DEVICE1: |
| 62 | return CS_1_LOW_DECODE_ADDRESS; |
| 63 | case DEVICE2: |
| 64 | return CS_2_LOW_DECODE_ADDRESS; |
| 65 | case DEVICE3: |
| 66 | return CS_3_LOW_DECODE_ADDRESS; |
| 67 | case BOOT_DEVICE: |
| 68 | return BOOTCS_LOW_DECODE_ADDRESS; |
| 69 | } |
| 70 | return CS_0_LOW_DECODE_ADDRESS; /* default value */ |
| 71 | } |
| 72 | |
| 73 | unsigned int memoryGetDeviceBaseAddress(DEVICE device) |
| 74 | { |
| 75 | unsigned int regBase; |
| 76 | unsigned int regEnd; |
| 77 | unsigned int regOffset=memoryGetDeviceRegOffset(device); |
| 78 | |
| 79 | GT_REG_READ(regOffset, ®Base); |
| 80 | GT_REG_READ(regOffset+8, ®End); |
| 81 | |
| 82 | if(regEnd<=regBase) return 0xffffffff; /* ERROR !!! */ |
| 83 | |
| 84 | regBase = regBase << 20; |
| 85 | return regBase; |
| 86 | } |
| 87 | |
| 88 | /******************************************************************** |
| 89 | * memoryGetBankSize - Returns the size of a memory bank. |
| 90 | * |
| 91 | * |
| 92 | * INPUT: MEMORY_BANK bank - The bank we ask for its size. |
| 93 | * OUTPUT: N/A |
| 94 | * RETURNS: Memory bank size. |
| 95 | *********************************************************************/ |
| 96 | unsigned int memoryGetBankSize(MEMORY_BANK bank) |
| 97 | { |
| 98 | unsigned int size,base; |
| 99 | unsigned int highValue; |
| 100 | unsigned int highAddress=memoryGetBankRegOffset(bank)+8; |
| 101 | |
| 102 | base = memoryGetBankBaseAddress(bank); |
| 103 | GT_REG_READ(highAddress,&highValue); |
| 104 | highValue = (highValue + 1) << 20; |
| 105 | if(base > highValue) |
| 106 | size=0; |
| 107 | else |
| 108 | size = highValue - base; |
| 109 | return size; |
| 110 | } |
| 111 | |
| 112 | /******************************************************************** |
| 113 | * memoryGetDeviceSize - Returns the size of a device memory space |
| 114 | * |
| 115 | * |
| 116 | * INPUT: DEVICE device - The device we ask for its base address. |
| 117 | * OUTPUT: N/A |
| 118 | * RETURNS: Size of a device memory space. |
| 119 | *********************************************************************/ |
| 120 | unsigned int memoryGetDeviceSize(DEVICE device) |
| 121 | { |
| 122 | unsigned int size,base; |
| 123 | unsigned int highValue; |
| 124 | unsigned int highAddress=memoryGetDeviceRegOffset(device)+8; |
| 125 | |
| 126 | base = memoryGetDeviceBaseAddress(device); |
| 127 | GT_REG_READ(highAddress,&highValue); |
| 128 | if (highValue == 0xfff) |
| 129 | { |
| 130 | size = (~base) + 1; /* what the heck is this? */ |
| 131 | return size; |
| 132 | } |
| 133 | else |
| 134 | highValue = (highValue + 1) << 20; |
| 135 | |
| 136 | if(base > highValue) |
| 137 | size=0; |
| 138 | else |
| 139 | size = highValue - base; |
| 140 | return size; |
| 141 | } |
| 142 | |
| 143 | /******************************************************************** |
| 144 | * memoryGetDeviceWidth - A device can be with: 1,2,4 or 8 Bytes data width. |
| 145 | * The width is determine in registers: 'Device Parameters' |
| 146 | * registers (0x45c, 0x460, 0x464, 0x468, 0x46c - for each device. |
| 147 | * at bits: [21:20]. |
| 148 | * |
| 149 | * INPUT: DEVICE device - Device number |
| 150 | * OUTPUT: N/A |
| 151 | * RETURNS: Device width in Bytes (1,2,4 or 8), 0 if error had occurred. |
| 152 | *********************************************************************/ |
| 153 | unsigned int memoryGetDeviceWidth(DEVICE device) |
| 154 | { |
| 155 | unsigned int width; |
| 156 | unsigned int regValue; |
| 157 | |
| 158 | GT_REG_READ(DEVICE_BANK0PARAMETERS + device*4,®Value); |
| 159 | width = (regValue & 0x00300000) >> 20; |
| 160 | switch (width) |
| 161 | { |
| 162 | case 0: |
| 163 | return 1; |
| 164 | case 1: |
| 165 | return 2; |
| 166 | case 2: |
| 167 | return 4; |
| 168 | case 3: |
| 169 | return 8; |
| 170 | default: |
| 171 | return 0; |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | bool memoryMapBank(MEMORY_BANK bank, unsigned int bankBase,unsigned int bankLength) |
| 176 | { |
| 177 | unsigned int low=0xfff; |
| 178 | unsigned int high=0x0; |
| 179 | unsigned int regOffset=memoryGetBankRegOffset(bank); |
| 180 | |
| 181 | if(bankLength!=0) { |
| 182 | low = (bankBase >> 20) & 0xffff; |
| 183 | high=((bankBase+bankLength)>>20)-1; |
| 184 | } |
| 185 | |
| 186 | #ifdef DEBUG |
| 187 | { |
| 188 | unsigned int oldLow, oldHigh; |
| 189 | GT_REG_READ(regOffset,&oldLow); |
| 190 | GT_REG_READ(regOffset+8,&oldHigh); |
| 191 | |
| 192 | printf("b%d %x-%x->%x-%x\n", bank, oldLow, oldHigh, low, high); |
| 193 | } |
| 194 | #endif |
| 195 | |
| 196 | GT_REG_WRITE(regOffset,low); |
| 197 | GT_REG_WRITE(regOffset+8,high); |
| 198 | |
| 199 | return true; |
| 200 | } |
| 201 | bool memoryMapDeviceSpace(DEVICE device, unsigned int deviceBase,unsigned int deviceLength) |
| 202 | { |
| 203 | /* TODO: what are appropriate "unmapped" values? */ |
| 204 | unsigned int low=0xfff; |
| 205 | unsigned int high=0x0; |
| 206 | unsigned int regOffset=memoryGetDeviceRegOffset(device); |
| 207 | |
| 208 | if(deviceLength != 0) { |
| 209 | low=deviceBase>>20; |
| 210 | high=((deviceBase+deviceLength)>>20)-1; |
| 211 | } else { |
| 212 | /* big problems in here... */ |
| 213 | /* this will HANG */ |
| 214 | } |
| 215 | |
| 216 | GT_REG_WRITE(regOffset,low); |
| 217 | GT_REG_WRITE(regOffset+8,high); |
| 218 | |
| 219 | return true; |
| 220 | } |
| 221 | |
| 222 | |
| 223 | /******************************************************************** |
| 224 | * memoryMapInternalRegistersSpace - Sets new base address for the internals |
| 225 | * registers. |
| 226 | * |
| 227 | * INPUTS: unsigned int internalRegBase - The new base address. |
| 228 | * RETURNS: true on success, false on failure |
| 229 | *********************************************************************/ |
| 230 | bool memoryMapInternalRegistersSpace(unsigned int internalRegBase) |
| 231 | { |
| 232 | unsigned int currentValue; |
| 233 | unsigned int internalValue = internalRegBase; |
| 234 | |
| 235 | internalRegBase = (internalRegBase >> 20); |
| 236 | GT_REG_READ(INTERNAL_SPACE_DECODE,¤tValue); |
| 237 | internalRegBase = (currentValue & 0xffff0000) | internalRegBase; |
| 238 | GT_REG_WRITE(INTERNAL_SPACE_DECODE,internalRegBase); |
| 239 | INTERNAL_REG_BASE_ADDR = internalValue; |
| 240 | return true; |
| 241 | } |
| 242 | |
| 243 | /******************************************************************** |
| 244 | * memoryGetInternalRegistersSpace - Gets internal registers Base Address. |
| 245 | * |
| 246 | * INPUTS: unsigned int internalRegBase - The new base address. |
| 247 | * RETURNS: true on success, false on failure |
| 248 | *********************************************************************/ |
| 249 | unsigned int memoryGetInternalRegistersSpace(void) |
| 250 | { |
| 251 | return INTERNAL_REG_BASE_ADDR; |
| 252 | } |
| 253 | |
| 254 | /******************************************************************** |
| 255 | * memorySetProtectRegion - This function modifys one of the 8 regions with |
| 256 | * one of the three protection mode. |
| 257 | * - Be advised to check the spec before modifying them. |
| 258 | * |
| 259 | * |
| 260 | * Inputs: CPU_PROTECT_REGION - one of the eight regions. |
| 261 | * CPU_ACCESS - general access. |
| 262 | * CPU_WRITE - read only access. |
| 263 | * CPU_CACHE_PROTECT - chache access. |
| 264 | * we defining CPU because there is another protect from the pci SIDE. |
| 265 | * Returns: false if one of the parameters is wrong and true else |
| 266 | *********************************************************************/ |
| 267 | bool memorySetProtectRegion(MEMORY_PROTECT_REGION region, |
| 268 | MEMORY_ACCESS memAccess, |
| 269 | MEMORY_ACCESS_WRITE memWrite, |
| 270 | MEMORY_CACHE_PROTECT cacheProtection, |
| 271 | unsigned int baseAddress, |
| 272 | unsigned int regionLength) |
| 273 | { |
| 274 | unsigned int protectHigh = baseAddress + regionLength; |
| 275 | |
| 276 | if(regionLength == 0) /* closing the region */ |
| 277 | { |
| 278 | GT_REG_WRITE(CPU_LOW_PROTECT_ADDRESS_0 + 0x10*region,0x0000ffff); |
| 279 | GT_REG_WRITE(CPU_HIGH_PROTECT_ADDRESS_0 + 0x10*region,0); |
| 280 | return true; |
| 281 | } |
| 282 | baseAddress = (baseAddress & 0xfff00000) >> 20; |
| 283 | baseAddress = baseAddress | memAccess << 16 | memWrite << 17 |
| 284 | | cacheProtection << 18; |
| 285 | GT_REG_WRITE(CPU_LOW_PROTECT_ADDRESS_0 + 0x10*region,baseAddress); |
| 286 | protectHigh = (protectHigh & 0xfff00000) >> 20; |
| 287 | GT_REG_WRITE(CPU_HIGH_PROTECT_ADDRESS_0 + 0x10*region,protectHigh - 1); |
| 288 | return true; |
| 289 | } |
| 290 | |
| 291 | /******************************************************************** |
| 292 | * memorySetRegionSnoopMode - This function modifys one of the 4 regions which |
| 293 | * supports Cache Coherency. |
| 294 | * |
| 295 | * |
| 296 | * Inputs: SNOOP_REGION region - One of the four regions. |
| 297 | * SNOOP_TYPE snoopType - There is four optional Types: |
| 298 | * 1. No Snoop. |
| 299 | * 2. Snoop to WT region. |
| 300 | * 3. Snoop to WB region. |
| 301 | * 4. Snoop & Invalidate to WB region. |
| 302 | * unsigned int baseAddress - Base Address of this region. |
| 303 | * unsigned int topAddress - Top Address of this region. |
| 304 | * Returns: false if one of the parameters is wrong and true else |
| 305 | *********************************************************************/ |
| 306 | bool memorySetRegionSnoopMode(MEMORY_SNOOP_REGION region, |
| 307 | MEMORY_SNOOP_TYPE snoopType, |
| 308 | unsigned int baseAddress, |
| 309 | unsigned int regionLength) |
| 310 | { |
| 311 | unsigned int snoopXbaseAddress; |
| 312 | unsigned int snoopXtopAddress; |
| 313 | unsigned int data; |
| 314 | unsigned int snoopHigh = baseAddress + regionLength; |
| 315 | |
| 316 | if( (region > MEM_SNOOP_REGION3) || (snoopType > MEM_SNOOP_WB) ) |
| 317 | return false; |
| 318 | snoopXbaseAddress = SNOOP_BASE_ADDRESS_0 + 0x10 * region; |
| 319 | snoopXtopAddress = SNOOP_TOP_ADDRESS_0 + 0x10 * region; |
| 320 | if(regionLength == 0) /* closing the region */ |
| 321 | { |
| 322 | GT_REG_WRITE(snoopXbaseAddress,0x0000ffff); |
| 323 | GT_REG_WRITE(snoopXtopAddress,0); |
| 324 | return true; |
| 325 | } |
| 326 | baseAddress = baseAddress & 0xffff0000; |
| 327 | data = (baseAddress >> 16) | snoopType << 16; |
| 328 | GT_REG_WRITE(snoopXbaseAddress,data); |
| 329 | snoopHigh = (snoopHigh & 0xfff00000) >> 20; |
| 330 | GT_REG_WRITE(snoopXtopAddress,snoopHigh - 1); |
| 331 | return true; |
| 332 | } |
| 333 | |
| 334 | /******************************************************************** |
| 335 | * memoryRemapAddress - This fubction used for address remapping. |
| 336 | * |
| 337 | * |
| 338 | * Inputs: regOffset: remap register |
| 339 | * remapValue : |
| 340 | * Returns: false if one of the parameters is erroneous,true otherwise. |
| 341 | *********************************************************************/ |
| 342 | bool memoryRemapAddress(unsigned int remapReg, unsigned int remapValue) |
| 343 | { |
| 344 | unsigned int valueForReg; |
| 345 | valueForReg = (remapValue & 0xfff00000) >> 20; |
| 346 | GT_REG_WRITE(remapReg, valueForReg); |
| 347 | return true; |
| 348 | } |
| 349 | |
| 350 | /******************************************************************** |
| 351 | * memoryGetDeviceParam - This function used for getting device parameters from |
| 352 | * DEVICE BANK PARAMETERS REGISTER |
| 353 | * |
| 354 | * |
| 355 | * Inputs: - deviceParam: STRUCT with paramiters for DEVICE BANK |
| 356 | * PARAMETERS REGISTER |
| 357 | * - deviceNum : number of device |
| 358 | * Returns: false if one of the parameters is erroneous,true otherwise. |
| 359 | *********************************************************************/ |
| 360 | bool memoryGetDeviceParam(DEVICE_PARAM *deviceParam, DEVICE deviceNum) |
| 361 | { |
| 362 | unsigned int valueOfReg; |
| 363 | unsigned int calcData; |
| 364 | |
| 365 | GT_REG_READ(DEVICE_BANK0PARAMETERS + 4 * deviceNum, &valueOfReg); |
| 366 | calcData = (0x7 & valueOfReg) + ((0x400000 & valueOfReg) >> 19); |
| 367 | deviceParam -> turnOff = calcData; /* Turn Off */ |
| 368 | |
| 369 | calcData = ((0x78 & valueOfReg) >> 3) + ((0x800000 & valueOfReg) >> 19); |
| 370 | deviceParam -> acc2First = calcData; /* Access To First */ |
| 371 | |
| 372 | calcData = ((0x780 & valueOfReg) >> 7) + ((0x1000000 & valueOfReg) >> 20); |
| 373 | deviceParam -> acc2Next = calcData; /* Access To Next */ |
| 374 | |
| 375 | calcData = ((0x3800 & valueOfReg) >> 11) + ((0x2000000 & valueOfReg) >> 22); |
| 376 | deviceParam -> ale2Wr = calcData; /* Ale To Write */ |
| 377 | |
| 378 | calcData = ((0x1c000 & valueOfReg) >> 14) + ((0x4000000 & valueOfReg) >> 23); |
| 379 | deviceParam -> wrLow = calcData; /* Write Active */ |
| 380 | |
| 381 | calcData = ((0xe0000 & valueOfReg) >> 17) + ((0x8000000 & valueOfReg) >> 24); |
| 382 | deviceParam -> wrHigh = calcData; /* Write High */ |
| 383 | |
| 384 | calcData = ((0x300000 & valueOfReg) >> 20); |
| 385 | switch (calcData) |
| 386 | { |
| 387 | case 0: |
| 388 | deviceParam -> deviceWidth = 1; /* one Byte - 8-bit */ |
| 389 | break; |
| 390 | case 1: |
| 391 | deviceParam -> deviceWidth = 2; /* two Bytes - 16-bit */ |
| 392 | break; |
| 393 | case 2: |
| 394 | deviceParam -> deviceWidth = 4; /* four Bytes - 32-bit */ |
| 395 | break; |
| 396 | case 3: |
| 397 | deviceParam -> deviceWidth = 8; /* eight Bytes - 64-bit */ |
| 398 | break; |
| 399 | default: |
| 400 | deviceParam -> deviceWidth = 1; |
| 401 | break; |
| 402 | } |
| 403 | return true; |
| 404 | } |
| 405 | |
| 406 | /******************************************************************** |
| 407 | * memorySetDeviceParam - This function used for setting device parameters to |
| 408 | * DEVICE BANK PARAMETERS REGISTER |
| 409 | * |
| 410 | * |
| 411 | * Inputs: - deviceParam: STRUCT for store paramiters from DEVICE BANK |
| 412 | * PARAMETERS REGISTER |
| 413 | * - deviceNum : number of device |
| 414 | * Returns: false if one of the parameters is erroneous,true otherwise. |
| 415 | *********************************************************************/ |
| 416 | bool memorySetDeviceParam(DEVICE_PARAM *deviceParam, DEVICE deviceNum) |
| 417 | { |
| 418 | unsigned int valueForReg; |
| 419 | |
| 420 | if((deviceParam -> turnOff >= 0xf) || (deviceParam -> acc2First >= 0x1f) || |
| 421 | (deviceParam -> acc2Next >= 0x1f) || (deviceParam -> ale2Wr >= 0xf) || |
| 422 | (deviceParam -> wrLow >= 0xf) || (deviceParam -> wrHigh >= 0xf)) |
| 423 | return false; |
| 424 | valueForReg = (((deviceParam -> turnOff) & 0x7) | |
| 425 | (((deviceParam -> turnOff) & 0x8) << 19) | |
| 426 | (((deviceParam -> acc2First) & 0xf) << 3) | |
| 427 | (((deviceParam -> acc2First) & 0x10) << 19) | |
| 428 | (((deviceParam -> acc2Next) & 0xf) << 7) | |
| 429 | (((deviceParam -> acc2Next) & 0x10) << 20) | |
| 430 | (((deviceParam -> ale2Wr) & 0x7) << 11) | |
| 431 | (((deviceParam -> ale2Wr) & 0xf) << 22) | |
| 432 | (((deviceParam -> wrLow) & 0x7) << 14) | |
| 433 | (((deviceParam -> wrLow) & 0xf) << 23) | |
| 434 | (((deviceParam -> wrHigh) & 0x7) << 17) | |
| 435 | (((deviceParam -> wrHigh) & 0xf) << 24)); |
| 436 | /* insert the device width: */ |
| 437 | switch(deviceParam->deviceWidth) |
| 438 | { |
| 439 | case 1: |
| 440 | valueForReg = valueForReg | _8BIT; |
| 441 | break; |
| 442 | case 2: |
| 443 | valueForReg = valueForReg | _16BIT; |
| 444 | break; |
| 445 | case 4: |
| 446 | valueForReg = valueForReg | _32BIT; |
| 447 | break; |
| 448 | case 8: |
| 449 | valueForReg = valueForReg | _64BIT; |
| 450 | break; |
| 451 | default: |
| 452 | valueForReg = valueForReg | _8BIT; |
| 453 | break; |
| 454 | } |
| 455 | GT_REG_WRITE(DEVICE_BANK0PARAMETERS + 4 * deviceNum, valueForReg); |
| 456 | return true; |
| 457 | } |