/******************************************************************************* * mvTwsiStopBitSet - Set stop bit on the bus * * DESCRIPTION: * This routine set the stop bit on the TWSI bus. * The function then wait for the stop bit to be cleared by the HW. * Finally the function checks for status of 0xF8. * * INPUT: * chanNum - TWSI channel * * OUTPUT: * None. * * RETURN: * MV_TRUE is stop bit was set successfuly on the bus. * *******************************************************************************/ MV_STATUS mvTwsiStopBitSet(MV_U8 chanNum) { MV_U32 timeout, temp; /* Generate stop bit */ temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum)); MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), temp | TWSI_CONTROL_STOP_BIT); twsiIntFlgClr(chanNum); /* wait for stop bit to come down */ timeout = 0; while( ((MV_REG_READ(TWSI_CONTROL_REG(chanNum)) & TWSI_CONTROL_STOP_BIT) != 0) && (timeout++ < TWSI_TIMEOUT_VALUE)); /* check for timeout */ if(MV_TRUE == twsiTimeoutChk(timeout,"TWSI: mvTwsiStopBitSet ERROR - Stop bit TimeOut .\n")) return MV_TIMEOUT; /* check that the stop bit went down */ if((MV_REG_READ(TWSI_CONTROL_REG(chanNum)) & TWSI_CONTROL_STOP_BIT) != 0) { mvOsPrintf("TWSI: mvTwsiStopBitSet ERROR - stop bit didn't went down. \n"); return MV_FAIL; } /* check the status */ temp = twsiStsGet(chanNum); if( temp != TWSI_NO_REL_STS_INT_FLAG_IS_KEPT_0){ mvOsPrintf("TWSI: mvTwsiStopBitSet ERROR - status %x after Stop Bit. \n", temp); return MV_FAIL; } return MV_OK; }
/******************************************************************************* * mvTwsiStopBitSet - Set stop bit on the bus * * DESCRIPTION: * This routine set the stop bit on the TWSI bus. * The function then wait for the stop bit to be cleared by the HW. * Finally the function checks for status of 0xF8. * * INPUT: * chanNum - TWSI channel. * * OUTPUT: * None. * * RETURN: * MV_TRUE is stop bit was set successfuly on the bus. * *******************************************************************************/ MV_STATUS mvTwsiStopBitSet(MV_U8 chanNum) { MV_U32 timeout, temp; /* Generate stop bit */ temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum)); MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), temp | TWSI_CONTROL_STOP_BIT); twsiIntFlgClr(chanNum); /* wait for stop bit to come down */ timeout = 0; while (((MV_REG_READ(TWSI_CONTROL_REG(chanNum)) & TWSI_CONTROL_STOP_BIT) != 0) && (timeout++ < TWSI_TIMEOUT_VALUE)) ; /* check for timeout */ if (MV_TRUE == twsiTimeoutChk(timeout, "TWSI: mvTwsiStopBitSet ERROR - Stop bit TimeOut .\n")) return MV_TIMEOUT; /* check that the stop bit went down */ if ((MV_REG_READ(TWSI_CONTROL_REG(chanNum)) & TWSI_CONTROL_STOP_BIT) != 0) return MV_FAIL; /* check the status */ temp = twsiStsGet(chanNum); if ((TWSI_M_LOST_ARB_DUR_AD_OR_DATA_TRA == temp) || (TWSI_M_LOST_ARB_DUR_AD_TRA_GNL_CALL_AD_REC_ACK_TRA == temp)) return MV_TWSI_RETRY; else if (temp != TWSI_NO_REL_STS_INT_FLAG_IS_KEPT_0) return MV_FAIL; return MV_OK; }
/******************************************************************************* * twsiAckBitSet - Set acknowledge bit on the bus * * DESCRIPTION: * This routine set the acknowledge bit on the TWSI bus. * * INPUT: * None. * * OUTPUT: * None. * * RETURN: * None. * *******************************************************************************/ static MV_VOID twsiAckBitSet(MV_U8 chanNum) { MV_U32 temp; /*Set the Ack bit */ temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum)); MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), temp | TWSI_CONTROL_ACK); /* Add delay of 1ms */ mvOsDelay(1); return; }
/******************************************************************************* * twsiIntFlgClr - Clear Interrupt flag. * * DESCRIPTION: * This routine clears the interrupt flag. It does NOT poll the interrupt * to make sure the clear. After clearing the interrupt, it waits for at * least 1 miliseconds. * * INPUT: * chanNum - TWSI channel * * OUTPUT: * None. * * RETURN: * None. * *******************************************************************************/ static MV_VOID twsiIntFlgClr(MV_U8 chanNum) { MV_U32 temp; /* wait for 1 mili to prevent TWSI register write after write problems */ mvOsDelay(1); /* clear the int flag bit */ temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum)); MV_REG_WRITE(TWSI_CONTROL_REG(chanNum),temp & ~(TWSI_CONTROL_INT_FLAG_SET)); /* wait for 1 mili sec for the clear to take effect */ mvOsDelay(1); return; }
/******************************************************************************* * mvTwsiStartBitSet - Set start bit on the bus * * DESCRIPTION: * This routine sets the start bit on the TWSI bus. * The routine first checks for interrupt flag condition, then it sets * the start bit in the TWSI Control register. * If the interrupt flag condition check previously was set, the function * will clear it. * The function then wait for the start bit to be cleared by the HW. * Then it waits for the interrupt flag to be set and eventually, the * TWSI status is checked to be 0x8 or 0x10(repeated start bit). * * INPUT: * chanNum - TWSI channel. * * OUTPUT: * None. * * RETURN: * MV_OK is start bit was set successfuly on the bus. * MV_FAIL if interrupt flag was set before setting start bit. * *******************************************************************************/ MV_STATUS mvTwsiStartBitSet(MV_U8 chanNum) { MV_BOOL isIntFlag = MV_FALSE; MV_U32 timeout, temp; DB(mvOsPrintf("TWSI: mvTwsiStartBitSet \n")); /* check Int flag */ if (twsiMainIntGet(chanNum)) isIntFlag = MV_TRUE; /* set start Bit */ temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum)); MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), temp | TWSI_CONTROL_START_BIT); /* in case that the int flag was set before i.e. repeated start bit */ if (isIntFlag) { DB(mvOsPrintf("TWSI: mvTwsiStartBitSet repeated start Bit\n")); twsiIntFlgClr(chanNum); } /* wait for interrupt */ timeout = 0; while (!twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE)) ; /* check for timeout */ if (MV_TRUE == twsiTimeoutChk(timeout, (const MV_8 *)"TWSI: mvTwsiStartBitSet ERROR - Start Clear bit TimeOut .\n")) return MV_TIMEOUT; /* check that start bit went down */ if ((MV_REG_READ(TWSI_CONTROL_REG(chanNum)) & TWSI_CONTROL_START_BIT) != 0) { mvOsPrintf("TWSI: mvTwsiStartBitSet ERROR - start bit didn't went down\n"); return MV_FAIL; } /* check the status */ temp = twsiStsGet(chanNum); if ((TWSI_M_LOST_ARB_DUR_AD_OR_DATA_TRA == temp) || (TWSI_M_LOST_ARB_DUR_AD_TRA_GNL_CALL_AD_REC_ACK_TRA == temp)) { DB(mvOsPrintf("TWSI: Lost Arb, status %x \n", temp)); return MV_RETRY; } else if ((temp != TWSI_START_CON_TRA) && (temp != TWSI_REPEATED_START_CON_TRA)) { mvOsPrintf("TWSI: mvTwsiStartBitSet ERROR - status %x after Set Start Bit. \n", temp); return MV_FAIL; } return MV_OK; }
/******************************************************************************* * twsiInit - Initialize TWSI interface * * DESCRIPTION: * This routine: * -Reset the TWSI. * -Initialize the TWSI clock baud rate according to given frequancy * parameter based on Tclk frequancy and enables TWSI slave. * -Set the ack bit. * -Assign the TWSI slave address according to the TWSI address Type. * * * INPUT: * chanNum - TWSI channel * frequancy - TWSI frequancy in KHz. (up to 100KHZ) * * OUTPUT: * None. * * RETURN: * Actual frequancy. * *******************************************************************************/ MV_U32 mvTwsiInit(MV_U8 chanNum, MV_HZ frequancy, MV_U32 Tclk, MV_TWSI_ADDR *pTwsiAddr, MV_BOOL generalCallEnable) { MV_U32 n,m,freq,margin,minMargin = 0xffffffff; MV_U32 power; MV_U32 actualFreq = 0,actualN = 0,actualM = 0,val; if(frequancy > 100000) { mvOsPrintf("Warning TWSI frequancy is too high, please use up tp 100Khz. \n"); } DB(mvOsPrintf("TWSI: mvTwsiInit - Tclk = %d freq = %d\n",Tclk,frequancy)); /* Calucalte N and M for the TWSI clock baud rate */ for(n = 0 ; n < 8 ; n++) { for(m = 0 ; m < 16 ; m++) { power = 2 << n; /* power = 2^(n+1) */ freq = Tclk/(10*(m+1)*power); margin = MV_ABS(frequancy - freq); if(margin < minMargin) { minMargin = margin; actualFreq = freq; actualN = n; actualM = m; } } } DB(mvOsPrintf("TWSI: mvTwsiInit - actN %d actM %d actFreq %d\n",actualN , actualM, actualFreq)); /* Reset the TWSI logic */ twsiReset(chanNum); /* Set the baud rate */ val = ((actualM<< TWSI_BAUD_RATE_M_OFFS) | actualN << TWSI_BAUD_RATE_N_OFFS); MV_REG_WRITE(TWSI_STATUS_BAUDE_RATE_REG(chanNum),val); /* Enable the TWSI and slave */ MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), TWSI_CONTROL_ENA | TWSI_CONTROL_ACK); /* set the TWSI slave address */ if( pTwsiAddr->type == ADDR10_BIT )/* 10 Bit deviceAddress */ { /* writing the 2 most significant bits of the 10 bit address*/ val = ((pTwsiAddr->address & TWSI_SLAVE_ADDR_10BIT_MASK) >> TWSI_SLAVE_ADDR_10BIT_OFFS ); /* bits 7:3 must be 0x11110 */ val |= TWSI_SLAVE_ADDR_10BIT_CONST; /* set GCE bit */ if(generalCallEnable) val |= TWSI_SLAVE_ADDR_GCE_ENA; /* write slave address */ MV_REG_WRITE(TWSI_SLAVE_ADDR_REG(chanNum),val); /* writing the 8 least significant bits of the 10 bit address*/ val = (pTwsiAddr->address << TWSI_EXTENDED_SLAVE_OFFS) & TWSI_EXTENDED_SLAVE_MASK; MV_REG_WRITE(TWSI_EXTENDED_SLAVE_ADDR_REG(chanNum), val); }
/******************************************************************************* * twsiInit - Initialize TWSI interface * * DESCRIPTION: * This routine: * -Reset the TWSI. * -Initialize the TWSI clock baud rate according to given frequancy * parameter based on Tclk frequancy and enables TWSI slave. * -Set the ack bit. * -Assign the TWSI slave address according to the TWSI address Type. * * INPUT: * chanNum - TWSI channel * frequancy - TWSI frequancy in KHz. (up to 100KHZ) * * OUTPUT: * None. * * RETURN: * Actual frequancy. * *******************************************************************************/ MV_U32 mvTwsiInit(MV_U8 chanNum, MV_HZ frequancy, MV_U32 Tclk, MV_TWSI_ADDR *pTwsiAddr, MV_BOOL generalCallEnable) { MV_U32 n, m, freq, margin, minMargin = 0xffffffff; MV_U32 power; MV_U32 actualFreq = 0, actualN = 0, actualM = 0, val; #ifdef MV88F67XX /* set twsi MPPS */ val = (MV_REG_READ(REG_MPP_CONTROL_ADDR) | (REG_MPP_CONTROL_TWSI_VALUE << REG_MPP_CONTROL_TWSI_OFFS)); MV_REG_WRITE(REG_MPP_CONTROL_ADDR, val); #endif /* Calucalte N and M for the TWSI clock baud rate */ for (n = 0; n < 8; n++) { for (m = 0; m < 16; m++) { power = 2 << n; /* power = 2^(n+1) */ freq = Tclk / (10 * (m + 1) * power); margin = MV_ABS(frequancy - freq); if ((freq <= frequancy) && (margin < minMargin)) { minMargin = margin; actualFreq = freq; actualN = n; actualM = m; } } } /* Reset the TWSI logic */ twsiReset(chanNum); /* Set the baud rate */ val = ((actualM << TWSI_BAUD_RATE_M_OFFS) | actualN << TWSI_BAUD_RATE_N_OFFS); MV_REG_WRITE(TWSI_STATUS_BAUDE_RATE_REG(chanNum), val); /* Enable the TWSI and slave */ MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), TWSI_CONTROL_ENA | TWSI_CONTROL_ACK); /* set the TWSI slave address */ if (pTwsiAddr->type == ADDR10_BIT) { /* 10 Bit deviceAddress */ /* writing the 2 most significant bits of the 10 bit address */ val = ((pTwsiAddr->address & TWSI_SLAVE_ADDR_10BIT_MASK) >> TWSI_SLAVE_ADDR_10BIT_OFFS); /* bits 7:3 must be 0x11110 */ val |= TWSI_SLAVE_ADDR_10BIT_CONST; /* set GCE bit */ if (generalCallEnable) val |= TWSI_SLAVE_ADDR_GCE_ENA; /* write slave address */ MV_REG_WRITE(TWSI_SLAVE_ADDR_REG(chanNum), val); /* writing the 8 least significant bits of the 10 bit address */ val = (pTwsiAddr->address << TWSI_EXTENDED_SLAVE_OFFS) & TWSI_EXTENDED_SLAVE_MASK; MV_REG_WRITE(TWSI_EXTENDED_SLAVE_ADDR_REG(chanNum), val); } else { /*7 bit address */