wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 1 | /************************************************** |
| 2 | * |
| 3 | * copyright @ motorola, 1999 |
| 4 | * |
| 5 | *************************************************/ |
| 6 | #include <mpc824x.h> |
| 7 | #include <common.h> |
| 8 | #include "epic.h" |
| 9 | |
| 10 | |
| 11 | #define PRINT(format, args...) printf(format , ## args) |
| 12 | |
| 13 | typedef void (*VOIDFUNCPTR) (void); /* ptr to function returning void */ |
| 14 | struct SrcVecTable SrcVecTable[MAXVEC] = /* Addr/Vector cross-reference tbl */ |
| 15 | { |
| 16 | { EPIC_EX_INT0_VEC_REG, "External Direct/Serial Source 0"}, |
| 17 | { EPIC_EX_INT1_VEC_REG, "External Direct/Serial Source 1"}, |
| 18 | { EPIC_EX_INT2_VEC_REG, "External Direct/Serial Source 2"}, |
| 19 | { EPIC_EX_INT3_VEC_REG, "External Direct/Serial Source 3"}, |
| 20 | { EPIC_EX_INT4_VEC_REG, "External Direct/Serial Source 4"}, |
| 21 | |
| 22 | { EPIC_SR_INT5_VEC_REG, "External Serial Source 5"}, |
| 23 | { EPIC_SR_INT6_VEC_REG, "External Serial Source 6"}, |
| 24 | { EPIC_SR_INT7_VEC_REG, "External Serial Source 7"}, |
| 25 | { EPIC_SR_INT8_VEC_REG, "External Serial Source 8"}, |
| 26 | { EPIC_SR_INT9_VEC_REG, "External Serial Source 9"}, |
| 27 | { EPIC_SR_INT10_VEC_REG, "External Serial Source 10"}, |
| 28 | { EPIC_SR_INT11_VEC_REG, "External Serial Source 11"}, |
| 29 | { EPIC_SR_INT12_VEC_REG, "External Serial Source 12"}, |
| 30 | { EPIC_SR_INT13_VEC_REG, "External Serial Source 13"}, |
| 31 | { EPIC_SR_INT14_VEC_REG, "External Serial Source 14"}, |
| 32 | { EPIC_SR_INT15_VEC_REG, "External Serial Source 15"}, |
| 33 | |
| 34 | { EPIC_I2C_INT_VEC_REG, "Internal I2C Source"}, |
| 35 | { EPIC_DMA0_INT_VEC_REG, "Internal DMA0 Source"}, |
| 36 | { EPIC_DMA1_INT_VEC_REG, "Internal DMA1 Source"}, |
| 37 | { EPIC_MSG_INT_VEC_REG, "Internal Message Source"}, |
| 38 | }; |
| 39 | |
| 40 | VOIDFUNCPTR intVecTbl[MAXVEC]; /* Interrupt vector table */ |
| 41 | |
| 42 | |
| 43 | /**************************************************************************** |
| 44 | * epicInit - Initialize the EPIC registers |
| 45 | * |
| 46 | * This routine resets the Global Configuration Register, thus it: |
| 47 | * - Disables all interrupts |
| 48 | * - Sets epic registers to reset values |
| 49 | * - Sets the value of the Processor Current Task Priority to the |
| 50 | * highest priority (0xF). |
| 51 | * epicInit then sets the EPIC operation mode to Mixed Mode (vs. Pass |
| 52 | * Through or 8259 compatible mode). |
| 53 | * |
| 54 | * If IRQType (input) is Direct IRQs: |
| 55 | * - IRQType is written to the SIE bit of the EPIC Interrupt |
| 56 | * Configuration register (ICR). |
| 57 | * - clkRatio is ignored. |
| 58 | * If IRQType is Serial IRQs: |
| 59 | * - both IRQType and clkRatio will be written to the ICR register |
| 60 | */ |
| 61 | |
| 62 | void epicInit |
| 63 | ( |
| 64 | unsigned int IRQType, /* Direct or Serial */ |
| 65 | unsigned int clkRatio /* Clk Ratio for Serial IRQs */ |
| 66 | ) |
| 67 | { |
| 68 | ULONG tmp; |
| 69 | |
| 70 | tmp = sysEUMBBARRead(EPIC_GLOBAL_REG); |
| 71 | tmp |= 0xa0000000; /* Set the Global Conf. register */ |
| 72 | sysEUMBBARWrite(EPIC_GLOBAL_REG, tmp); |
wdenk | 7c7a23b | 2002-12-07 00:20:59 +0000 | [diff] [blame] | 73 | /* |
| 74 | * Wait for EPIC to reset - CLH |
| 75 | */ |
| 76 | while( (sysEUMBBARRead(EPIC_GLOBAL_REG) & 0x80000000) == 1); |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 77 | sysEUMBBARWrite(EPIC_GLOBAL_REG, 0x20000000); |
| 78 | tmp = sysEUMBBARRead(EPIC_INT_CONF_REG); /* Read interrupt conf. reg */ |
| 79 | |
| 80 | if (IRQType == EPIC_DIRECT_IRQ) /* direct mode */ |
wdenk | 8bde7f7 | 2003-06-27 21:31:46 +0000 | [diff] [blame] | 81 | sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp & 0xf7ffffff); |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 82 | else /* Serial mode */ |
wdenk | 8bde7f7 | 2003-06-27 21:31:46 +0000 | [diff] [blame] | 83 | { |
| 84 | tmp = (clkRatio << 28) | 0x08000000; /* Set clock ratio */ |
| 85 | sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp); |
| 86 | } |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 87 | |
wdenk | 7c7a23b | 2002-12-07 00:20:59 +0000 | [diff] [blame] | 88 | while (epicIntAck() != 0xff) /* Clear all pending interrupts */ |
| 89 | epicEOI(); |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 90 | } |
| 91 | |
| 92 | /**************************************************************************** |
| 93 | * epicIntEnable - Enable an interrupt source |
| 94 | * |
| 95 | * This routine clears the mask bit of an external, an internal or |
| 96 | * a Timer register to enable the interrupt. |
| 97 | * |
| 98 | * RETURNS: None |
| 99 | */ |
wdenk | 7c7a23b | 2002-12-07 00:20:59 +0000 | [diff] [blame] | 100 | void epicIntEnable(int intVec) |
| 101 | { |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 102 | ULONG tmp; |
| 103 | ULONG srAddr; |
| 104 | |
| 105 | srAddr = SrcVecTable[intVec].srcAddr; /* Retrieve src Vec/Prio register */ |
| 106 | tmp = sysEUMBBARRead(srAddr); |
wdenk | 7c7a23b | 2002-12-07 00:20:59 +0000 | [diff] [blame] | 107 | tmp &= ~EPIC_VEC_PRI_MASK; /* Clear the mask bit */ |
| 108 | tmp |= (EPIC_VEC_PRI_DFLT_PRI << 16); /* Set priority to Default - CLH */ |
| 109 | tmp |= intVec; /* Set Vector number */ |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 110 | sysEUMBBARWrite(srAddr, tmp); |
wdenk | 7c7a23b | 2002-12-07 00:20:59 +0000 | [diff] [blame] | 111 | |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 112 | return; |
| 113 | } |
| 114 | |
| 115 | /**************************************************************************** |
| 116 | * epicIntDisable - Disable an interrupt source |
| 117 | * |
| 118 | * This routine sets the mask bit of an external, an internal or |
| 119 | * a Timer register to disable the interrupt. |
| 120 | * |
| 121 | * RETURNS: OK or ERROR |
| 122 | * |
| 123 | */ |
| 124 | |
| 125 | void epicIntDisable |
| 126 | ( |
| 127 | int intVec /* Interrupt vector number */ |
| 128 | ) |
| 129 | { |
| 130 | |
| 131 | ULONG tmp, srAddr; |
| 132 | |
| 133 | srAddr = SrcVecTable[intVec].srcAddr; |
| 134 | tmp = sysEUMBBARRead(srAddr); |
| 135 | tmp |= 0x80000000; /* Set the mask bit */ |
| 136 | sysEUMBBARWrite(srAddr, tmp); |
| 137 | return; |
| 138 | } |
| 139 | |
| 140 | /**************************************************************************** |
| 141 | * epicIntSourceConfig - Set properties of an interrupt source |
| 142 | * |
| 143 | * This function sets interrupt properites (Polarity, Sense, Interrupt |
| 144 | * Prority, and Interrupt Vector) of an Interrupt Source. The properties |
| 145 | * can be set when the current source is not in-request or in-service, |
| 146 | * which is determined by the Activity bit. This routine return ERROR |
| 147 | * if the the Activity bit is 1 (in-request or in-service). |
| 148 | * |
| 149 | * This function assumes that the Source Vector/Priority register (input) |
| 150 | * is a valid address. |
| 151 | * |
| 152 | * RETURNS: OK or ERROR |
| 153 | */ |
| 154 | |
| 155 | int epicIntSourceConfig |
| 156 | ( |
| 157 | int Vect, /* interrupt source vector number */ |
| 158 | int Polarity, /* interrupt source polarity */ |
| 159 | int Sense, /* interrupt source Sense */ |
| 160 | int Prio /* interrupt source priority */ |
| 161 | ) |
| 162 | |
| 163 | { |
| 164 | ULONG tmp, newVal; |
| 165 | ULONG actBit, srAddr; |
| 166 | |
| 167 | srAddr = SrcVecTable[Vect].srcAddr; |
| 168 | tmp = sysEUMBBARRead(srAddr); |
| 169 | actBit = (tmp & 40000000) >> 30; /* retrieve activity bit - bit 30 */ |
| 170 | if (actBit == 1) |
wdenk | 8bde7f7 | 2003-06-27 21:31:46 +0000 | [diff] [blame] | 171 | return ERROR; |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 172 | |
| 173 | tmp &= 0xff30ff00; /* Erase previously set P,S,Prio,Vector bits */ |
| 174 | newVal = (Polarity << 23) | (Sense << 22) | (Prio << 16) | Vect; |
| 175 | sysEUMBBARWrite(srAddr, tmp | newVal ); |
| 176 | return (OK); |
| 177 | } |
| 178 | |
| 179 | /**************************************************************************** |
| 180 | * epicIntAck - acknowledge an interrupt |
| 181 | * |
| 182 | * This function reads the Interrupt acknowldge register and return |
| 183 | * the vector number of the highest pending interrupt. |
| 184 | * |
| 185 | * RETURNS: Interrupt Vector number. |
| 186 | */ |
| 187 | |
| 188 | unsigned int epicIntAck(void) |
| 189 | { |
| 190 | return(sysEUMBBARRead( EPIC_PROC_INT_ACK_REG )); |
| 191 | } |
| 192 | |
| 193 | /**************************************************************************** |
| 194 | * epicEOI - signal an end of interrupt |
| 195 | * |
| 196 | * This function writes 0x0 to the EOI register to signal end of interrupt. |
| 197 | * It is usually called after an interrupt routine is served. |
| 198 | * |
| 199 | * RETURNS: None |
| 200 | */ |
| 201 | |
| 202 | void epicEOI(void) |
| 203 | { |
| 204 | sysEUMBBARWrite(EPIC_PROC_EOI_REG, 0x0); |
| 205 | } |
| 206 | |
| 207 | /**************************************************************************** |
| 208 | * epicCurTaskPrioSet - sets the priority of the Processor Current Task |
| 209 | * |
| 210 | * This function should be called after epicInit() to lower the priority |
| 211 | * of the processor current task. |
| 212 | * |
| 213 | * RETURNS: OK or ERROR |
| 214 | */ |
| 215 | |
| 216 | int epicCurTaskPrioSet |
| 217 | ( |
| 218 | int prioNum /* New priority value */ |
| 219 | ) |
| 220 | { |
| 221 | |
| 222 | if ( (prioNum < 0) || (prioNum > 0xF)) |
wdenk | 8bde7f7 | 2003-06-27 21:31:46 +0000 | [diff] [blame] | 223 | return ERROR; |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 224 | sysEUMBBARWrite(EPIC_PROC_CTASK_PRI_REG, prioNum); |
| 225 | return OK; |
| 226 | } |
| 227 | |
| 228 | |
| 229 | /************************************************************************ |
| 230 | * function: epicIntTaskGet |
| 231 | * |
| 232 | * description: Get value of processor current interrupt task priority register |
| 233 | * |
| 234 | * note: |
| 235 | ***********************************************************************/ |
| 236 | unsigned char epicIntTaskGet() |
| 237 | { |
| 238 | /* get the interrupt task priority register */ |
| 239 | ULONG reg; |
| 240 | unsigned char rec; |
| 241 | |
| 242 | reg = sysEUMBBARRead( EPIC_PROC_CTASK_PRI_REG ); |
| 243 | rec = ( reg & 0x0F ); |
| 244 | return rec; |
| 245 | } |
| 246 | |
| 247 | |
| 248 | /************************************************************** |
| 249 | * function: epicISR |
| 250 | * |
| 251 | * description: EPIC service routine called by the core exception |
| 252 | * at 0x500 |
| 253 | * |
| 254 | * note: |
| 255 | **************************************************************/ |
| 256 | unsigned int epicISR(void) |
| 257 | { |
| 258 | return 0; |
| 259 | } |
| 260 | |
| 261 | |
| 262 | /************************************************************ |
| 263 | * function: epicModeGet |
| 264 | * |
| 265 | * description: query EPIC mode, return 0 if pass through mode |
| 266 | * return 1 if mixed mode |
| 267 | * |
| 268 | * note: |
| 269 | *************************************************************/ |
| 270 | unsigned int epicModeGet(void) |
| 271 | { |
| 272 | ULONG val; |
| 273 | |
| 274 | val = sysEUMBBARRead( EPIC_GLOBAL_REG ); |
| 275 | return (( val & 0x20000000 ) >> 29); |
| 276 | } |
| 277 | |
| 278 | |
| 279 | /********************************************* |
| 280 | * function: epicConfigGet |
| 281 | * |
| 282 | * description: Get the EPIC interrupt Configuration |
| 283 | * return 0 if not error, otherwise return 1 |
| 284 | * |
| 285 | * note: |
| 286 | ********************************************/ |
| 287 | void epicConfigGet( unsigned int *clkRatio, unsigned int *serEnable) |
| 288 | { |
| 289 | ULONG val; |
| 290 | |
| 291 | val = sysEUMBBARRead( EPIC_INT_CONF_REG ); |
| 292 | *clkRatio = ( val & 0x70000000 ) >> 28; |
| 293 | *serEnable = ( val & 0x8000000 ) >> 27; |
| 294 | } |
| 295 | |
| 296 | |
| 297 | /******************************************************************* |
| 298 | * sysEUMBBARRead - Read a 32-bit EUMBBAR register |
| 299 | * |
| 300 | * This routine reads the content of a register in the Embedded |
| 301 | * Utilities Memory Block, and swaps to big endian before returning |
| 302 | * the value. |
| 303 | * |
| 304 | * RETURNS: The content of the specified EUMBBAR register. |
| 305 | */ |
| 306 | |
| 307 | ULONG sysEUMBBARRead |
| 308 | ( |
| 309 | ULONG regNum |
| 310 | ) |
| 311 | { |
| 312 | ULONG temp; |
| 313 | |
| 314 | temp = *(ULONG *) (CFG_EUMB_ADDR + regNum); |
| 315 | return ( LONGSWAP(temp)); |
| 316 | } |
| 317 | |
| 318 | /******************************************************************* |
| 319 | * sysEUMBBARWrite - Write a 32-bit EUMBBAR register |
| 320 | * |
| 321 | * This routine swaps the value to little endian then writes it to |
| 322 | * a register in the Embedded Utilities Memory Block address space. |
| 323 | * |
| 324 | * RETURNS: N/A |
| 325 | */ |
| 326 | |
| 327 | void sysEUMBBARWrite |
| 328 | ( |
| 329 | ULONG regNum, /* EUMBBAR register address */ |
| 330 | ULONG regVal /* Value to be written */ |
| 331 | ) |
| 332 | { |
| 333 | |
| 334 | *(ULONG *) (CFG_EUMB_ADDR + regNum) = LONGSWAP(regVal); |
| 335 | return ; |
| 336 | } |
| 337 | |
| 338 | |
| 339 | /******************************************************** |
| 340 | * function: epicVendorId |
| 341 | * |
| 342 | * description: return the EPIC Vendor Identification |
| 343 | * register: |
| 344 | * |
| 345 | * siliccon version, device id, and vendor id |
| 346 | * |
| 347 | * note: |
| 348 | ********************************************************/ |
| 349 | void epicVendorId |
| 350 | ( |
| 351 | unsigned int *step, |
| 352 | unsigned int *devId, |
| 353 | unsigned int *venId |
| 354 | ) |
| 355 | { |
| 356 | ULONG val; |
| 357 | val = sysEUMBBARRead( EPIC_VENDOR_ID_REG ); |
| 358 | *step = ( val & 0x00FF0000 ) >> 16; |
| 359 | *devId = ( val & 0x0000FF00 ) >> 8; |
| 360 | *venId = ( val & 0x000000FF ); |
| 361 | } |
| 362 | |
| 363 | /************************************************** |
| 364 | * function: epicFeatures |
| 365 | * |
| 366 | * description: return the number of IRQ supported, |
| 367 | * number of CPU, and the version of the |
| 368 | * OpenEPIC |
| 369 | * |
| 370 | * note: |
| 371 | *************************************************/ |
| 372 | void epicFeatures |
| 373 | ( |
| 374 | unsigned int *noIRQs, |
| 375 | unsigned int *noCPUs, |
| 376 | unsigned int *verId |
| 377 | ) |
| 378 | { |
| 379 | ULONG val; |
| 380 | |
| 381 | val = sysEUMBBARRead( EPIC_FEATURES_REG ); |
| 382 | *noIRQs = ( val & 0x07FF0000 ) >> 16; |
| 383 | *noCPUs = ( val & 0x00001F00 ) >> 8; |
| 384 | *verId = ( val & 0x000000FF ); |
| 385 | } |
| 386 | |
| 387 | |
| 388 | /********************************************************* |
| 389 | * function: epciTmFrequncySet |
| 390 | * |
| 391 | * description: Set the timer frequency reporting register |
| 392 | ********************************************************/ |
| 393 | void epicTmFrequencySet( unsigned int frq ) |
| 394 | { |
| 395 | sysEUMBBARWrite(EPIC_TM_FREQ_REG, frq); |
| 396 | } |
| 397 | |
| 398 | /******************************************************* |
| 399 | * function: epicTmFrequncyGet |
| 400 | * |
| 401 | * description: Get the current value of the Timer Frequency |
| 402 | * Reporting register |
| 403 | * |
| 404 | ******************************************************/ |
| 405 | unsigned int epicTmFrequencyGet(void) |
| 406 | { |
| 407 | return( sysEUMBBARRead(EPIC_TM_FREQ_REG)) ; |
| 408 | } |
| 409 | |
| 410 | |
| 411 | /**************************************************** |
| 412 | * function: epicTmBaseSet |
| 413 | * |
| 414 | * description: Set the #n global timer base count register |
| 415 | * return 0 if no error, otherwise return 1. |
| 416 | * |
| 417 | * note: |
| 418 | ****************************************************/ |
| 419 | unsigned int epicTmBaseSet |
| 420 | ( |
| 421 | ULONG srcAddr, /* Address of the Timer Base register */ |
| 422 | unsigned int cnt, /* Base count */ |
| 423 | unsigned int inhibit /* 1 - count inhibit */ |
| 424 | ) |
| 425 | { |
| 426 | |
| 427 | unsigned int val = 0x80000000; |
| 428 | /* First inhibit counting the timer */ |
| 429 | sysEUMBBARWrite(srcAddr, val) ; |
| 430 | |
| 431 | /* set the new value */ |
| 432 | val = (cnt & 0x7fffffff) | ((inhibit & 0x1) << 31); |
| 433 | sysEUMBBARWrite(srcAddr, val) ; |
| 434 | return 0; |
| 435 | } |
| 436 | |
| 437 | /*********************************************************************** |
| 438 | * function: epicTmBaseGet |
| 439 | * |
| 440 | * description: Get the current value of the global timer base count register |
| 441 | * return 0 if no error, otherwise return 1. |
| 442 | * |
| 443 | * note: |
| 444 | ***********************************************************************/ |
| 445 | unsigned int epicTmBaseGet( ULONG srcAddr, unsigned int *val ) |
| 446 | { |
| 447 | *val = sysEUMBBARRead( srcAddr ); |
| 448 | *val = *val & 0x7fffffff; |
| 449 | return 0; |
| 450 | } |
| 451 | |
| 452 | /*********************************************************** |
| 453 | * function: epicTmCountGet |
| 454 | * |
| 455 | * description: Get the value of a given global timer |
| 456 | * current count register |
| 457 | * return 0 if no error, otherwise return 1 |
| 458 | * note: |
| 459 | **********************************************************/ |
| 460 | unsigned int epicTmCountGet( ULONG srcAddr, unsigned int *val ) |
| 461 | { |
| 462 | *val = sysEUMBBARRead( srcAddr ); |
| 463 | *val = *val & 0x7fffffff; |
| 464 | return 0; |
| 465 | } |
| 466 | |
| 467 | |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 468 | /*********************************************************** |
| 469 | * function: epicTmInhibit |
| 470 | * |
| 471 | * description: Stop counting of a given global timer |
| 472 | * return 0 if no error, otherwise return 1 |
| 473 | * |
| 474 | * note: |
| 475 | ***********************************************************/ |
| 476 | unsigned int epicTmInhibit( unsigned int srcAddr ) |
| 477 | { |
| 478 | ULONG val; |
| 479 | |
| 480 | val = sysEUMBBARRead( srcAddr ); |
| 481 | val |= 0x80000000; |
| 482 | sysEUMBBARWrite( srcAddr, val ); |
| 483 | return 0; |
| 484 | } |
| 485 | |
| 486 | /****************************************************************** |
| 487 | * function: epicTmEnable |
| 488 | * |
| 489 | * description: Enable counting of a given global timer |
| 490 | * return 0 if no error, otherwise return 1 |
| 491 | * |
| 492 | * note: |
| 493 | *****************************************************************/ |
| 494 | unsigned int epicTmEnable( ULONG srcAddr ) |
| 495 | { |
| 496 | ULONG val; |
| 497 | |
| 498 | val = sysEUMBBARRead( srcAddr ); |
| 499 | val &= 0x7fffffff; |
| 500 | sysEUMBBARWrite( srcAddr, val ); |
| 501 | return 0; |
| 502 | } |
| 503 | |
| 504 | void epicSourcePrint(int Vect) |
| 505 | { |
| 506 | ULONG srcVal; |
| 507 | |
| 508 | srcVal = sysEUMBBARRead(SrcVecTable[Vect].srcAddr); |
| 509 | PRINT("%s\n", SrcVecTable[Vect].srcName); |
| 510 | PRINT("Address = 0x%lx\n", SrcVecTable[Vect].srcAddr); |
| 511 | PRINT("Vector = %ld\n", (srcVal & 0x000000FF) ); |
| 512 | PRINT("Mask = %ld\n", srcVal >> 31); |
| 513 | PRINT("Activitiy = %ld\n", (srcVal & 40000000) >> 30); |
| 514 | PRINT("Polarity = %ld\n", (srcVal & 0x00800000) >> 23); |
| 515 | PRINT("Sense = %ld\n", (srcVal & 0x00400000) >> 22); |
| 516 | PRINT("Priority = %ld\n", (srcVal & 0x000F0000) >> 16); |
| 517 | } |