📄 hawki2c.c
字号:
/* hawkI2c.c - Low-Level Falcon/Hawk I2C Routines *//* Copyright 1984-2001 Wind River Systems, Inc. *//* Copyright 1998 Motorola, Inc., All Rights Reserved *//*modification history--------------------01f,02nov01,mil Cleaned up compiler warnings.01e,15oct01,mil Fixed boot hanging in sysHawkMsDelay(), needed besides removing asm bclr (SPR 27046).01d,16sep01,dat removed in-line assembly, using vxDecGet()01c,23oct98,rhv Added LOCAL to forward declarations.01b,23oct98,rhv Made local copies of sysMsDelay and sysGetDec for use in compressed images.01a,14sep98,rhv Created by Motorola using code written by rl/jd*//*DESCRIPTIONThis file contains the following falcon/hawk i2c utility routines:.CS sysHawkI2cWait - Waits for a given value in the I2C status register sysHawkI2CByteWrite - Write a single byte to a serial eeprom sysHawkI2cByteRead - Reads a single byte from a serial eeprom sysHawkI2cRangeRead - Reads a range of bytes from a serial eeprom.CECAVEATSThese routines are needed before the kernel is un-compressed. For properoperation, this file must be added to the BOOT_EXTRA list in the Makefile toprevent it from being compressed during kernel generation.These routines were primarily intended for use during system start-up, beforemulti-tasking is started, and are not multi-tasking safe. They are safe forcommand-line use during debug, but were not intended to be run-timeuser-callable.*/#include "vxWorks.h"#include "config.h"#include "stdlib.h"#include "hawkI2c.h" /* i2c defines *//* forwards */LOCAL void sysHawkMsDelay(UINT32);LOCAL int sysHawkGetDec();/* externals */IMPORT int sysGetBusSpd (void);IMPORT int vxDecGet (void);/********************************************************************************* sysHawkI2cWait - wait for a given value in the i2c status register** This function waits for a given value in the i2c status register.* If the specified value is never detected, the routine times out* and returns an error. the routine also returns an error if the error bit* in the status register is found set.** RETURNS: OK, or ERROR if the expected value does not appear.**/STATUS sysHawkI2cWait ( UINT32 value /* expected status value */ ) { UINT32 count; volatile UINT32 status; EIEIO_SYNC; /* eieio, sync */ for (count=0;;) { status = *(UINT32 *)I2C_HAWK_STATUS_REG; if ( (status & value) == value ) return (OK); else { /* check for timeout or error bit */ if ( (++count > I2C_TIMEOUT_COUNT) || (status & I2C_HAWK_ERR) ) { /* * generate stop condition and return error */ *(UINT32 *)I2C_HAWK_CONTROL_REG = I2C_HAWK_STOP|I2C_HAWK_ENBL; *(UINT32 *)I2C_HAWK_TXD_REG = 0; return (ERROR); } sysHawkMsDelay(1); /* delay 1 ms */ } } }/********************************************************************************* sysHawkI2cByteWrite - write a single byte to an i2c device via the falcon/hawk** This function writes one 8-bit word to an I2C device specified by the passed* in parameters. The access is specifically tailored for the Hawk/Falcon3 I2C * controller.** RETURNS: OK, or ERROR if transfer failed.**/STATUS sysHawkI2cByteWrite ( UCHAR devAddr, /* i2c address of target device */ UCHAR devOffset, /* offset within target device to write */ UCHAR * pBfr /* pointer to data byte */ ) { /* don't start unless status reg shows complete bit set */ if ( sysHawkI2cWait (I2C_HAWK_CMPLT) != OK ) return (ERROR); /* initiate start sequence */ *(UINT32 *)I2C_HAWK_CONTROL_REG = I2C_HAWK_START|I2C_HAWK_ENBL; /* write addr to transmit data register, bit 0 = 0 = write */ *(UINT32 *)I2C_HAWK_TXD_REG = (UINT32)(devAddr & BYTE_WRITE_MASK); /* await complete + acknowledge in status register */ if ( sysHawkI2cWait (I2C_HAWK_ACKIN|I2C_HAWK_CMPLT) != OK ) return (ERROR); /* end of start sequence */ /* devOffset to transmit data register */ *(UINT32 *)I2C_HAWK_TXD_REG = (UINT32)devOffset; /* await complete + acknowledge in status register */ if ( sysHawkI2cWait (I2C_HAWK_ACKIN|I2C_HAWK_CMPLT) != OK ) return (ERROR); /* Send data byte to transmit data register */ *(UINT32 *)I2C_HAWK_TXD_REG = (UINT32)*pBfr; /* await complete + acknowledge in status register */ if ( sysHawkI2cWait (I2C_HAWK_ACKIN|I2C_HAWK_CMPLT) != OK ) return (ERROR); /* stop sequence */ *(UINT32 *)I2C_HAWK_CONTROL_REG = I2C_HAWK_STOP|I2C_HAWK_ENBL; *(UINT32 *)I2C_HAWK_TXD_REG = 0; /* dummy write */ sysHawkMsDelay(1); /* delay for ASIC errata. */ /* await complete in status register */ if ( sysHawkI2cWait (I2C_HAWK_CMPLT) != OK ) return (ERROR); /* allow time for EEPROM write to occur */ sysHawkMsDelay(1); return (OK); }/********************************************************************************* sysHawkI2cByteRead - read a single byte to an i2c device via the falcon/hawk** This function reads one 8-bit word from an I2C device specified by the passed* in parameters. The access is specifically tailored for the Hawk/Falcon3 I2C * controller.** RETURNS: OK, or ERROR if transfer failed.**/STATUS sysHawkI2cByteRead ( UCHAR devAddr, /* i2c address of target device */ UCHAR devOffset, /* offset within target device to read */ UCHAR * pBfr /* pointer to data byte */ ) { /* await complete in status register */ if ( sysHawkI2cWait (I2C_HAWK_CMPLT) != OK ) return (ERROR); /* initiate start sequence in write mode */ *(UINT32 *)I2C_HAWK_CONTROL_REG = I2C_HAWK_START|I2C_HAWK_ENBL; *(UINT32 *)I2C_HAWK_TXD_REG = (UINT32)(devAddr & BYTE_WRITE_MASK); /* await complete + acknowledge in status register */ if ( sysHawkI2cWait (I2C_HAWK_ACKIN|I2C_HAWK_CMPLT) != OK ) return (ERROR); /* devOffset to transmit data register */ *(UINT32 *)I2C_HAWK_TXD_REG = (UINT32)devOffset; /* await complete + acknowledge in status register */ if ( sysHawkI2cWait (I2C_HAWK_ACKIN|I2C_HAWK_CMPLT) != OK ) return (ERROR); /* initiate start sequence in read mode */ *(UINT32 *)I2C_HAWK_CONTROL_REG = I2C_HAWK_START|I2C_HAWK_ENBL; *(UINT32 *)I2C_HAWK_TXD_REG = (UINT32)(devAddr | BYTE_READ_MASK); /* await complete + acknowledge in status register */ if ( sysHawkI2cWait (I2C_HAWK_ACKIN|I2C_HAWK_CMPLT) != OK ) return (ERROR); /* read the byte */ *(UINT32 *)I2C_HAWK_TXD_REG = 0; /* dummy write to initiate read */ sysHawkMsDelay(1); /* delay for ASIC errata. */ /* await complete and datain in status register */ if ( sysHawkI2cWait (I2C_HAWK_CMPLT | I2C_HAWK_DATIN) != OK ) return (ERROR); /* the actual read */ *pBfr = (UCHAR) (*(UINT32 *)I2C_HAWK_RXD_REG); /* There is no ack after a single byte read */ /* stop sequence */ *(UINT32 *)I2C_HAWK_CONTROL_REG = I2C_HAWK_STOP|I2C_HAWK_ENBL; *(UINT32 *)I2C_HAWK_TXD_REG = 0; /* dummy write */ sysHawkMsDelay(1); /* delay for ASIC errata. */ /* await complete in status register */ if ( sysHawkI2cWait (I2C_HAWK_CMPLT) != OK ) return (ERROR); return (OK); }/********************************************************************************* sysHawkI2cRangeRead - reads a range of bytes from an I2C serial eeprom (SROM)** This routine simply calls the I2C byte read routine for each requested byte.* The I2C byte read call is written using a macro to accommodate alternate* read routines.** RETURNS: OK, or ERROR if the I2C byte read fails.** SEE ALSO: sysI2cSromRangeWrite**/STATUS sysHawkI2cRangeRead ( UCHAR devAddr, /* i2c address of the serial eeprom */ UCHAR devOffset, /* starting offset within the serial eeprom to read */ UINT16 byteCount, /* number of bytes to read (one-based) */ UCHAR * pBfr /* destination buffer */ ) { /* await complete in status register */ if ( sysHawkI2cWait (I2C_HAWK_CMPLT) != OK ) return (ERROR); /* initiate start sequence in write mode */ *(UINT32 *)I2C_HAWK_CONTROL_REG = I2C_HAWK_START|I2C_HAWK_ENBL; *(UINT32 *)I2C_HAWK_TXD_REG = (UINT32)(devAddr & BYTE_WRITE_MASK); /* await complete + acknowledge in status register */ if ( sysHawkI2cWait (I2C_HAWK_ACKIN|I2C_HAWK_CMPLT) != OK ) return (ERROR); /* devOffset to transmit data register */ *(UINT32 *)I2C_HAWK_TXD_REG = (UINT32)devOffset; /* await complete + acknowledge in status register */ if ( sysHawkI2cWait (I2C_HAWK_ACKIN|I2C_HAWK_CMPLT) != OK ) return (ERROR); /* initiate start sequence in read mode */ *(UINT32 *)I2C_HAWK_CONTROL_REG = I2C_HAWK_START|I2C_HAWK_ENBL; *(UINT32 *)I2C_HAWK_TXD_REG = (UINT32)(devAddr | BYTE_READ_MASK); /* await complete + acknowledge in status register */ if ( sysHawkI2cWait (I2C_HAWK_ACKIN|I2C_HAWK_CMPLT) != OK ) return (ERROR); for ( ; byteCount != 0; --byteCount) { if (byteCount != 1) *(UINT32 *)I2C_HAWK_CONTROL_REG = I2C_HAWK_ACKOUT|I2C_HAWK_ENBL; else *(UINT32 *)I2C_HAWK_CONTROL_REG = I2C_HAWK_ENBL; /* read the byte */ *(UINT32 *)I2C_HAWK_TXD_REG = 0; /* dummy write to initiate read */ sysHawkMsDelay(1); /* delay for ASIC errata. */ /* await complete and datain in status register */ if ( sysHawkI2cWait (I2C_HAWK_CMPLT | I2C_HAWK_DATIN) != OK ) return (ERROR); /* the actual read */ *pBfr++ = (UCHAR) (*(UINT32 *)I2C_HAWK_RXD_REG); } /* stop sequence */ *(UINT32 *)I2C_HAWK_CONTROL_REG = I2C_HAWK_STOP|I2C_HAWK_ENBL; *(UINT32 *)I2C_HAWK_TXD_REG = 0; /* dummy write */ sysHawkMsDelay(1); /* delay for ASIC errata. */ /* await complete in status register */ if ( sysHawkI2cWait (I2C_HAWK_CMPLT) != OK ) return (ERROR); return (OK); }/******************************************************************************** sysHawkMsDelay - delay for the specified amount of time (MS)** This routine will delay for the specified amount of time by counting* decrementer ticks.** This routine is not dependent on a particular rollover value for* the decrementer, it should work no matter what the rollover* value is.** A small amount of count may be lost at the rollover point resulting in* the sysHawkMsDelay() causing a slightly longer delay than requested.** This routine will produce incorrect results if the delay time requested* requires a count larger than 0xffffffff to hold the decrementer* elapsed tick count. For a System Bus Speed of 67 MHZ this amounts to* about 258 seconds.** RETURNS: N/A**/LOCAL void sysHawkMsDelay ( UINT delay /* length of time in MS to delay */ ) { register UINT oldval; /* decrementer value */ register UINT newval; /* decrementer value */ register UINT totalDelta; /* Dec. delta for entire delay period */ register UINT decElapsed; /* cumulative decrementer ticks */ /* * Calculate delta of decrementer ticks for desired elapsed time. */ totalDelta = ((DEC_CLOCK_FREQ / 4) / 1000) * delay; /* * Now keep grabbing decrementer value and incrementing "decElapsed" until * we hit the desired delay value. Compensate for the fact that we may * read the decrementer at 0xffffffff before the interrupt service * routine has a chance to set in the rollover value. */ decElapsed = 0; oldval = sysHawkGetDec(); while (decElapsed < totalDelta) { newval = sysHawkGetDec(); if (newval > oldval) decElapsed += oldval; /* rollover */ else decElapsed += (oldval - newval); /* no rollover */ oldval = newval; } }/******************************************************************************** sysHawkGetDec - read from the Decrementer register SPR22.** This routine will read the contents the decrementer (SPR22)** RETURNS: value of SPR22 (in r3)**/LOCAL int sysHawkGetDec(void) { return vxDecGet(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -