📄 cpvi2c.c
字号:
pI2cPram->rbase = (USHORT)((UINT)&pI2cdrvBd->rxbd[0] - (UINT)DPRAM(immrVal)); pI2cPram->tbase = (USHORT)((UINT)&pI2cdrvBd->txbd[0] - (UINT)DPRAM(immrVal)); pI2cPram->rfcr = 0x15; pI2cPram->tfcr = 0x15; pI2cPram->mrblr = I2C_RXBL_MAX; pI2cPram->ris = 0x00000000; pI2cPram->rbptr = pI2cPram->rbase; pI2cPram->tis = 0x00000000; pI2cPram->tbptr = pI2cPram->tbase; /* issue initialize Rx and Tx parameters command */ if (!PPC860_I2C_PATCH_INSTALLED) cpvI2cdCcr (immrVal, CPM_CR_OPCODE_INIT_RT); /* * clear any previous interrupt status * disable all interrupts (polled mode) */ I2C_WRITE(*I2CER(immrVal),I2C_INT_CLR); I2C_WRITE(*I2CMR(immrVal),I2C_INT_DSBL); /* * configure to master mode * enable i2c operation */ *I2COM(immrVal) = CPM_I2C_COMMAND_MS; IO_SYNC; *I2MOD(immrVal) |= CPM_I2C_MODE_EN; IO_SYNC; /* unmask processor interrupts */ localIntUnlock(dontCare); return (pI2cdrvBd); /* return buffer descriptor pointer */ } /******************************************************************************** cpvI2cdIoctl - I/O control* * This component's purpose is to perform the specified action* as requested by the passed arguments:* * argument #1 = input/output control flag* I2C_IOCTL_W = write* I2C_IOCTL_R = read* I2C_IOCTL_O = read/or/write* I2C_IOCTL_A = read/and/write* I2C_IOCTL_AO = read/and/or/write* argument #2 = address of register* argument #3 = register size in bytes (1/2/4)* argument #4 = data to write #1 (na for read)* argument #5 = data to write #2 (na for read)** RETURNS: readdata, if read operation*/LOCAL UINT cpvI2cdIoctl ( FAST UINT ioctlflg, /* io control flag */ FAST UINT pReg, /* register pointer */ FAST UINT size, /* register size (1/2/4 bytes) */ FAST UINT wdata1, /* write data #1 */ FAST UINT wdata2 /* write data #2 */ ) { FAST UINT rdata; FAST UCHAR *pReg1; FAST USHORT *pReg2; FAST UINT *pReg4; rdata = 0; /* make the compiler happy */ switch (size) { case 1: pReg1 = (UCHAR *)pReg; if(ioctlflg == I2C_IOCTL_W) /* write */ *pReg1 = wdata1; else if(ioctlflg == I2C_IOCTL_R) /* read */ rdata = *pReg1; else if(ioctlflg == I2C_IOCTL_O) /* read/or/write */ *pReg1 |= wdata1; else if(ioctlflg == I2C_IOCTL_A) /* read/and/write */ *pReg1 &= wdata1; else if(ioctlflg == I2C_IOCTL_AO) /* read/and/or/write */ *pReg1 = (*pReg1 & wdata1) | wdata2; break; case 2: pReg2 = (USHORT *)pReg; if(ioctlflg == I2C_IOCTL_W) /* write */ *pReg2 = wdata1; else if(ioctlflg == I2C_IOCTL_R) /* read */ rdata = *pReg2; else if(ioctlflg == I2C_IOCTL_O) /* read/or/write */ *pReg2 |= wdata1; else if(ioctlflg == I2C_IOCTL_A) /* read/and/write */ *pReg2 &= wdata1; else if(ioctlflg == I2C_IOCTL_AO) /* read/and/or/write */ *pReg2 = (*pReg2 & wdata1) | wdata2; break; case 4: pReg4 = (UINT *)pReg; if(ioctlflg == I2C_IOCTL_W) /* write */ *pReg4 = wdata1; else if(ioctlflg == I2C_IOCTL_R) /* read */ rdata = *pReg4; else if(ioctlflg == I2C_IOCTL_O) /* read/or/write */ *pReg4 |= wdata1; else if(ioctlflg == I2C_IOCTL_A) /* read/and/write */ *pReg4 &= wdata1; else if(ioctlflg == I2C_IOCTL_AO) /* read/and/or/write */ *pReg4 = (*pReg4 & wdata1) | wdata2; break; } /* synchronize all data */ IO_SYNC; return (rdata); }/******************************************************************************** cpvI2cdCcr - execute channel command* * This component's purpose is to execute the command* passed. The channel command register is read prior* to execution to verify that there are no outstanding* commands, this is done by waiting for a zero status.* The channel command register is also read after the command* execution to insure command completion prior to returning.** RETURNS: N/A*/LOCAL void cpvI2cdCcr ( FAST UINT immrVal, /* Base address of Internal Memory Regs */ FAST UINT cmd /* command to execute */ ) { /* wait for any pending commands to complete */ while (*CPCR(immrVal) & CPM_CR_FLG) ; /* issue command */ *CPCR(immrVal) = (cmd | CPM_CR_CHANNEL_I2C | CPM_CR_FLG); IO_SYNC; /* wait for issued command to complete */ while (*CPCR(immrVal) & CPM_CR_FLG) ; }/******************************************************************************** cpvI2cdAlarm - enable alarm* * This component's purpose is to initialize the alarm feature* of the RTC. It's the caller's responsibility to the handle* the event (i.e., if the interrupt is enabled).** RETURNS: N/A*/LOCAL void cpvI2cdAlarm ( FAST UINT immrVal, /* Base address of Internal Memory Regs */ FAST UINT timeout /* timeout value in seconds */ ) { /* clear any possible pending alarm event */ *RTCSC(immrVal) |= RTCSC_ALR; IO_SYNC; /* * add timeout to current RTC value and store into the * alarm seconds counter */ *RTCAL(immrVal) = *RTC(immrVal) + timeout; }/******************************************************************************** cpvI2cEepromRead - read EEPROM for DRAM information** This function's purpose is to retrieve the serial presence* detect data (need the first 32 bytes) from the specified EEPROM.* These EEPROMs are located on the I2C bus.* * This routine is responsible for determining the size of the on-board* SDRAM. It uses values read from the serial presence detect data to* perform the sizing. The following fields are used in the sizing * algorithm:* rows - number of row address lines per bank (byte 3)* cols - number of column address lines per bank (byte 4)* pBanks - number of physical banks (byte 5)* dBanks - number of logical banks per device (byte 17)* dWidth - data width, in bits of memory (byte 6)** The algorithm for determining the size of the SDRAM is:** total size in bytes = * (2**rows * 2**cols) * (dWidth / 4) * (pBanks * dBanks)** RETURNS: size of DRAM array in bytes if OK or* -1 if I2C device access error, -2 if data failed sanity check*/UINT cpvI2cEepromRead ( FAST UINT i2cDevAdrs, /* I2C device address */ FAST UCHAR *pBuf, /* buffer pointer (>= 32 bytes) */ FAST UINT epromType /* EEPROM type: 0 = IBM, 1 = MOT */ ) { FAST UINT value; /* data variable */ FAST UINT counter; /* counter variable */ FAST UINT bankSize; /* used for calculating the size of memory */ FAST UINT bankAddrLines; /* set to total number of rows and columns */ FAST UINT dataWidth; /* data width size (in bits) */ FAST UINT memBanks; /* total number of mem. banks on the board */ FAST UINT devBanks; /* number of banks per device */ FAST UINT memSize; /* size of SDRAM */ I2C_CMD_PKT i2cp; /* command packet */ /* reset eeprom internal address index */ i2cp.csword = (I2C_IO_C_WDATA); i2cp.devAdrs = i2cDevAdrs; i2cp.dataAdrs = (UINT)pBuf; i2cp.dataSize = 1; *pBuf = 0x00; /* call the MPC8xx I2C bus device driver, exit on error */ cpvI2cdMain(&i2cp); if (i2cp.csword & I2C_IO_S_ERROR) { return ((UINT)-1); } /* if the EEPROM type is an IBM, just read the first 32 bytes */ if (epromType == 0) { for (counter = 0; counter < 32; counter += 4) { /* read 4 bytes from the device */ i2cp.csword = (I2C_IO_C_RDATA); i2cp.devAdrs = i2cDevAdrs; i2cp.dataAdrs = (UINT)(pBuf + counter); i2cp.dataSize = 4; /* call the MPC8xx I2C bus device driver, exit on error */ cpvI2cdMain(&i2cp); if (i2cp.csword & I2C_IO_S_ERROR) { return ((UINT)-1); } } } /* * make some sense of the information read, basically perform * a sanity check on the data which is used to determine the * size and speed of the DRAM array */ counter = 0; value = *(pBuf + SPD_ROW_ADDR_INDEX) & 0x7F; /* rows */ if ((value < 8) || (value > 14)) counter++; bankAddrLines = value; value = *(pBuf + SPD_COL_ADDR_INDEX); /* columns */ if ((value < 8) || (value > 14)) counter++; bankAddrLines += value; value = *(pBuf + SPD_NUM_PHYSBANKS_INDEX); /* physical banks */ if ((value < 1) || (value > 4)) counter++; memBanks = value; /* save data width in bytes */ dataWidth = *(pBuf + SPD_DATA_WIDTH_INDEX) / 8; /* width (lo) */ if ((dataWidth != 4) && (dataWidth != 8)) counter++; value = *(pBuf + SPD_DATA_WIDTH_HI_INDEX); /* width (hi) */ if (value) counter++; value = *(pBuf + SPD_TCYC_INDEX); /* CAS access */ if ((value & 0x0f) > 9) counter++; devBanks = *(pBuf + SPD_DEV_BANKS_INDEX); /* banks per device */ if (devBanks == 0) counter++; /* if an bounds error has occurred, return error code */ if (counter) return ((UINT)-2); /* calculate the total SDRAM size */ bankSize = (1 << bankAddrLines); /* size of 1 bank = 2**rows * 2**columns */ /* total banks = num physical banks * num of banks per device */ memBanks = (memBanks * devBanks); /* * multiply it all together to get the total size * (in bytes) of the onboard memory */ memSize = (bankSize * memBanks * dataWidth); return (memSize); }/******************************************************************************** cpvI2cSromRead - read SROM for DRAM information* * This function's purpose is to retrieve the serial presence* detect data (the first 16 bytes) from the specified EEPROM.* These EEPROMs are located on the I2C bus.** RETURNS: size of DRAM array in bytes if OK or* -1 if I2C device access error, -2 if data failed sanity check*/UINT cpvI2cSromRead ( FAST UINT i2cDevAdrs, /* I2C device address */ FAST UCHAR *pBuf, /* buffer pointer (>= 16 bytes) */ FAST UINT devOffset, /* I2C address offset */ FAST UINT byteCount /* I2C bytes to read */ ) { FAST UINT counter; /* counter variable */ FAST UINT inc; /* increment size variable */ I2C_CMD_PKT i2cp; /* command packet */ /* reset eeprom internal address index */ i2cp.csword = (I2C_IO_C_WDATA); i2cp.devAdrs = i2cDevAdrs; i2cp.dataAdrs = (UINT)pBuf; i2cp.dataSize = 1; *pBuf = devOffset; /* start from desired offset */ /* call the MPC8xx I2C bus device driver, exit on error */ cpvI2cdMain(&i2cp); if (i2cp.csword & I2C_IO_S_ERROR) return ((UINT)-1); if (byteCount % 4) inc = 1; /* not evenly divisible by 4. */ else inc = 4; /* evenly divisible by 4. */ for (counter = 0; counter < byteCount; counter += inc) { /* read "inc" bytes from the device */ i2cp.csword = (I2C_IO_C_RDATA); i2cp.devAdrs = i2cDevAdrs; i2cp.dataAdrs = (UINT)(pBuf + counter); i2cp.dataSize = inc; /* call the MPC8xx I2C bus device driver, exit on error */ cpvI2cdMain(&i2cp); if (i2cp.csword & I2C_IO_S_ERROR) return ((UINT)-1); } return (0); }/******************************************************************************** localIntLock - Disable interrupts* * This function saves the current interrupt state and disables* interrupts. localIntLock() and localIntUnlock() support ONLY* functions within this file. It is necessary for this file* to be totally self contained (not access any routines not* defined in this file) in order to avoid build errors when* building the compressed boot ROMs.** See also: localIntUnlock()** RETURNS: N/A*/LOCAL void localIntLock ( UINT *key /* save the current interrupt state */ ) { WRS_ASM(" mfmsr 4"); WRS_ASM(" stw 4, 0(3)"); WRS_ASM(" rlwinm 3, 4, 0, 17, 15"); WRS_ASM(" mtmsr 3"); WRS_ASM(" isync"); }/******************************************************************************** localIntUnlock - Restore original interrupt state* * This function restores the interrupt state which was in effect* when localIntLock() was last called with the "key" input* parameter. localIntLock() and localIntUnlock() support ONLY* functions within this file. It is necessary for this file to* be totally self contained (not access any routines outside of* this file) in order to avoid build errors when building the* compressed boot ROMs.** See also: localIntLock()** RETURNS: N/A*/LOCAL void localIntUnlock ( UINT key /* input requires value returned from lock call */ ) { WRS_ASM(" rlwinm 3, 3, 0, 16, 16"); WRS_ASM(" mfmsr 4"); WRS_ASM(" or 3, 4, 3"); WRS_ASM(" mtmsr 3"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -