📄 mbxi2c.c
字号:
/* * setup local pointers and variables * initialize the base address to all buffers */ pI2cdrvBd = (I2C_DRV_BD *)DPRAM_I2C_BD; varBa = (UINT)((UCHAR *)DPRAM_I2C_BUFFER); /* mask processor interrupts */ localIntLock(&dontCare); /* disable i2c operation */ *I2MOD(immrVal) &= ~CPM_I2C_MODE_EN; IO_SYNC; /* initialize I2C specifics: * first, initialize the I2C clock (keep below 100khz) * * MAX_MPU_SPEED is the likely maximum MPU speed for an MPC * for the near future. We could call mpc8xx_clk_value() * here to determine the actual speed but to do so causes * very slow accesses to SROM contents. Using MAX_MPU_SPEED * instead here is ugly but since the I2C clock frequency is * legitimately variable, it works for all the supported * speeds and is much faster than calculating the clock speed * for every SROM access. */ varDiv = (MAX_MPU_SPEED) / 4; varDiv /= I2C_CLK_SPD; /* divide by I2C bus clock - 90khz */ varDiv /= 2; varDiv -= 3; *I2BRG(immrVal) = (UCHAR)varDiv; *I2MOD(immrVal) = (CPM_I2C_MODE_PDIV_BRGCLK4); IO_SYNC; /* enable the I2CSDA/I2CSCL pins */ *PBPAR(immrVal) |= PORT_B_PINS_I2C; IO_SYNC; *PBDIR(immrVal) |= PORT_B_PINS_I2C; IO_SYNC; *PBODR(immrVal) |= PORT_B_PINS_I2C; IO_SYNC; /* initialize receive buffers */ pBd = (SCC_BUF *)&pI2cdrvBd->rxbd[0]; for (varBdi = 0; varBdi < (I2C_DRV_NBDS-1); varBdi++, pBd++) { I2C_WRITE(pBd->dataLength,0x0000); I2C_WRITE(pBd->dataPointer,varBa); varWork = (CPM_I2C_R_CS_E|CPM_I2C_R_CS_I); I2C_WRITE(pBd->statusMode,varWork); varBa += I2C_RXBL_MAX; /* update buffer allocation variable */ } I2C_WRITE(pBd->dataLength,0x0000); I2C_WRITE(pBd->dataPointer,varBa); varWork = (CPM_I2C_R_CS_E|CPM_I2C_R_CS_I|CPM_I2C_R_CS_W); I2C_WRITE(pBd->statusMode,varWork); varBa += I2C_RXBL_MAX; /* update buffer allocation variable */ /* initialize transmit buffers */ pBd = (SCC_BUF *)&pI2cdrvBd->txbd[0]; for (varBdi = 0; varBdi < (I2C_DRV_NBDS-1); varBdi++, pBd++) { I2C_WRITE(pBd->dataLength,0x0000); I2C_WRITE(pBd->dataPointer,varBa); varWork = (CPM_I2C_T_CS_I|CPM_I2C_T_CS_L|CPM_I2C_T_CS_S); I2C_WRITE(pBd->statusMode,varWork); varBa += I2C_TXBL_MAX; /* update buffer allocation variable */ } I2C_WRITE(pBd->dataLength,0x0000); I2C_WRITE(pBd->dataPointer,varBa); varWork = (CPM_I2C_T_CS_I|CPM_I2C_T_CS_L|CPM_I2C_T_CS_S|CPM_I2C_T_CS_W); I2C_WRITE(pBd->statusMode,varWork); varBa += I2C_TXBL_MAX; /* update buffer allocation variable */ /* initialize parameter RAM specifics */ pI2cPram = (I2C_PARAM *)PPC860_DPR_I2C(dprbase); 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) mbxI2cdCcr (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 */ } /******************************************************************************** mbxI2cdIoctl - 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 mbxI2cdIoctl ( 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); }/******************************************************************************** mbxI2cdCcr - 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 mbxI2cdCcr ( 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) ; }/******************************************************************************* mbxI2cdAlarm - 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 mbxI2cdAlarm ( FAST UINT immrVal, /* Base address of Internal Memory Regs */ FAST UINT timeout /* timeout value in seconds */ ) { /* clear any possible pending alarm event */ /* SPR 65678, unlock/lock wrapper around RTCSC write */#ifdef USE_KEYED_REGS *RTCSCK(immrVal) = KEYED_REG_UNLOCK_VALUE; IO_ISYNC; *RTCSC(immrVal) |= RTCSC_ALR; *RTCSCK(immrVal) = ~KEYED_REG_UNLOCK_VALUE;#else *RTCSC(immrVal) |= RTCSC_ALR; #endif IO_SYNC; /* * add timeout to current RTC value and store into the * alarm seconds counter */ /* SPR 65678 */#ifdef USE_KEYED_REGS *RTCALK(immrVal) = KEYED_REG_UNLOCK_VALUE; IO_ISYNC; *RTCAL(immrVal) = *RTC(immrVal) + timeout; *RTCALK(immrVal) = ~KEYED_REG_UNLOCK_VALUE;#else *RTCAL(immrVal) = *RTC(immrVal) + timeout;#endif }/******************************************************************************** mbxI2cEepromRead - read EEPROM 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*/LOCAL UINT mbxI2cEepromRead ( FAST UINT i2cDevAdrs, /* I2C device address */ FAST UCHAR *pBuf, /* buffer pointer (>= 16 bytes) */ FAST UINT epromType /* EEPROM type: 0 = IBM, 1 = MOT */ ) { FAST UINT counter; /* counter variable */ FAST UINT value; /* data 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 = 0x00; /* call the MPC8xx I2C bus device driver, exit on error */ mbxI2cdMain(&i2cp); if (i2cp.csword & I2C_IO_S_ERROR) { return ((UINT)-1); } /* if the EEPROM type is an IBM, just read the first 16 bytes */ if (epromType == 0) { for (counter = 0; counter < 16; 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 */ mbxI2cdMain(&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 + 3) & 0x7F; /* rows */ if ((value < 8) || (value > 14)) counter++; value = *(pBuf + 4); /* columns */ if ((value < 8) || (value > 14)) counter++; value = *(pBuf + 5); /* banks */ if ((value < 1) || (value > 4)) counter++; value = *(pBuf + 6) / 32; /* width (lo) */ if ((value < 1) || (value > 2)) counter++; value = *(pBuf + 7); /* width (hi) */ if (value) counter++; value = *(pBuf + 9); /* RAS access */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -