📄 tmiic.c
字号:
req.direction = IIC_READ;
req.byteCount = 1;
req.address = address;
req.subaddress = subaddress;
req.numRetries = MAX_NUM_RETRIES;
req.waitBeforeRetry = TM1100_SLEEP_BEFORE_RETRY;
req.data = &data;
req.mode = IIC_Synchronous_By_Polling;
req.type = (subaddress < 0) ? IIC_SIMPLE : IIC_SUBADDRESS;
req.completion_function = Null;
err = iicDispatch(instance, &req);
*value = data;
err |= iicClose(instance);
return err;
}
/*
* Function : IIC dispatch function.
* Parameters : iic_request (I) description of required
* iic actions to be taken
* Function Result : True iff a synchronous iic request was
* suspended in order to wait for completion.
*/
tmLibdevErr_t
iicDispatch(Int instance, piicRequest_t iic_request)
{
UInt ien;
tmAssert(iic_request != Null, TMLIBDEV_ERR_NULL_PARAMETER);
tmAssert(capabilities.numCurrentInstances != 0, TMLIBDEV_ERR_NOT_OWNER);
/* since no checking is done on the instance, it is best to add this
safety check */
if (procCap->hostID == tmTmSimHost) {
return TMLIBDEV_ERR_NOT_OWNER;
}
if (iic_request->address > 0xFF)
return (IIC_ERR_BAD_ADDRESS);
if (iic_request->byteCount > LARGEST_TRANSFER)
return (IIC_ERR_BAD_COUNT);
/*
* Fill in some standard values in the request.
*/
iic_request->requester = AppModel_current_thread;
iic_request->done = False;
iic_request->index = 0;
iic_request->errorCode = 0;
if (iic_request->direction == IIC_READ) {
iic_request->address |= 1; /* only read at uneven addresses */
#if TM1000_COMPATIBLE
if (TM1000) {
if (iic_request->byteCount == 2)
return (IIC_ERR_BAD_COUNT);
if ((iic_request->byteCount > 1) && ((iic_request->byteCount % 4) == 1))
return (IIC_ERR_BAD_COUNT);
}
#endif
} else {
Int byteCount = iic_request->byteCount +
(iic_request->type == IIC_SUBADDRESS?1:0);
iic_request->address &= 0xFE; /* only write at even addresses */
#if TM1000_COMPATIBLE
if (TM1000) {
if (byteCount > 4)
return (IIC_ERR_BAD_COUNT);
}
#endif
if (TM1100_1_2) {
if ((byteCount > 1) && ((byteCount % 4) == 1))
return (IIC_ERR_BAD_COUNT);
}
}
/*
* Start the request if we're not working on something else,
* otherwise, insert the request in the queue.
*/
ien = intCLEAR_IEN();
if (iic_current_request == Null)
{
IIC_DP(("dispatch iic request %x to %x. ", iic_request, iic_request->address));
iic_queue_first = iic_queue_last = Null;
iic_current_request = iic_request;
start_next_transfer(False); /* starts iic_current_request, no retries */
} else
{ /* INSERT_REQUEST */
IIC_DP(("queue iic request %x to %x. ", iic_request, iic_request->address));
if (iic_queue_first == Null)
iic_queue_first = iic_request;
else
iic_queue_last->link = (iic_request);
iic_request->link = Null;
iic_queue_last = iic_request;
}
intRESTORE_IEN(ien);
/*
* Await completion, as specified:
*/
switch (iic_request->mode) {
case IIC_Asynchronous:
IIC_DP(("Async\n"));
return TMLIBDEV_OK;
case IIC_Synchronous_By_Polling:
if (!iic_request->done) {
/*
* Note that the MAX_WAIT_IN_US is the time we will wait
* for this transaction to finish. So, if other transactions
* are pending that take much time, we will time out.
*
*/
IIC_DP(("Poll- "));
for (LoopCount = 0; LoopCount < MAX_WAIT_IN_US / 5; LoopCount++)
{
if (iic_request->done) {
goto done;
}
IIC_DP(("."));
microsleep(10);
}
iic_request->errorCode |= IIC_ERR_TIMEOUT;
IIC_DP(("Timed Out! "));
}
done:
if (TM1000) {
/* this block of code seems redundant and causes problems
* when async transactions are used.
* It was deleted as duplicated at about 072p6.
* Then we found that it is required on TM1000,
* so it is added back conditionally.
*/
iic_current_request = iic_queue_first;
IIC_DP(("For TM1000, dispatch next in sync iic %x\n", iic_current_request));
if (iic_current_request != Null)
{
iic_queue_first = iic_queue_first->link;
if (iic_queue_first == Null) {
iic_queue_last = Null;
}
start_next_transfer(False); /* starts iic_current_request, no retries */
}
}
IIC_DP(("%x Complete.\n", iic_request));
return iic_request->errorCode;
case IIC_Synchronous:
IIC_DP(("Sync\n"));
if (!iic_request->done)
AppModel_suspend_self();
return iic_request->errorCode;
default:
return TMLIBDEV_OK; /* keep apcc happy */
}
}
/*
* Function : Fills in the capabilities structure.
* Parameters : cap (O) returned pointer to
* internal capabilities structure
* Function Result : resulting error condition
*/
tmLibdevErr_t
iicGetCapabilities(piicCapabilities_t * cap)
{
tmAssert(cap != Null, TMLIBDEV_ERR_NULL_PARAMETER);
*cap = &capabilities;
return TMLIBDEV_OK;
}
/*
* Function : Changes parameters of IIC interface,
* like speed and priority.
* Use is optional.
* Parameters : setup (O) pointer to buffer holding new capabilities
* Function Result : resulting error condition
*/
tmLibdevErr_t
iicSetup(piicSetup_t setup)
{
UInt ien;
tmAssert(setup != Null, TMLIBDEV_ERR_NULL_PARAMETER);
ien= intCLEAR_IEN();
IICSetup= *setup;
if (capabilities.numCurrentInstances != 0) {
intInstanceSetup_t int_setup;
intGetInstanceSetup(intIIC, &int_setup);
int_setup.priority = IICSetup.interruptPriority;
intInstanceSetup(intIIC, &int_setup);
}
intRESTORE_IEN(ien);
return TMLIBDEV_OK;
}
/*
* Function : Retrieve global parameters.
* Parameters : setup (O) pointer to buffer
* receiving returned parameters
* Function Result : resulting error condition
*/
extern tmLibdevErr_t
iicGetSetup(iicSetup_t * setup)
{
UInt ien;
tmAssert(setup != Null, TMLIBDEV_ERR_NULL_PARAMETER);
ien = intCLEAR_IEN();
*setup = IICSetup;
intRESTORE_IEN(ien);
return TMLIBDEV_OK;
}
/*
* Function : Assigns a unique instance for the caller.
* Parameters : instance (O) pointer to result variable
* Function Result : resulting error condition
*/
tmLibdevErr_t
iicOpen(Int * instance)
{
UInt ien;
tmLibdevErr_t err;
intInstanceSetup_t int_setup;
tmAssert(instance != Null, TMLIBDEV_ERR_NULL_PARAMETER);
/*
* Setup IIC handling:
*/
ien= intCLEAR_IEN();
if (capabilities.numCurrentInstances == 0) {
procGetCapabilities(&procCap);
if (procCap->hostID == tmTmSimHost) {
/* this could be running under tmsim. Let s try a PCI
* transaction. If the PCI transaction does not work, it might
* mean we are running under tmsim
*/
intRESTORE_IEN(ien);
return TMLIBDEV_ERR_NOT_AVAILABLE_IN_HW;
}
if (err = intOpen(intIIC)) {
intRESTORE_IEN(ien);
return err;
} else {
switch(procCap->deviceID) {
case PROC_DEVICE_TM1000:
case PROC_DEVICE_TM1100:
case PROC_DEVICE_TM1300:
/*
* Enable clock stretch
*/
MMIO(ARB_BW_CTL) |= 0x01000000;
break;
default:
break;
}
MMIO(BIU_CTL) |= (1 << 10);
MMIO(IIC_CTL) = IIC_CLR_ALL | IIC_ENABLE;
#if TM1000_COMPATIBLE
TM1000 = (procCap->deviceID == PROC_DEVICE_TM1000);
#endif
TM1100_1_2 = (procCap->deviceID == PROC_DEVICE_TM1100 &&
procCap->revisionID == PROC_REVISION_1_2);
}
}
/*
* Setup interrupt handler
*/
int_setup.handler = iic_handler;
int_setup.priority = IICSetup.interruptPriority;
int_setup.level_triggered = True;
int_setup.enabled = True;
intInstanceSetup(intIIC, &int_setup);
capabilities.numCurrentInstances++;
*instance = ++next_instance;
intRESTORE_IEN(ien);
return TMLIBDEV_OK;
}
/*
* Function : Deallocates the instance.
* Parameters : instance (O) instance to give up
* Function Result : resulting error condition
*/
tmLibdevErr_t
iicClose(Int instance)
{
UInt ien;
tmAssert(capabilities.numCurrentInstances != 0, TMLIBDEV_ERR_NOT_OWNER);
ien= intCLEAR_IEN();
if (--capabilities.numCurrentInstances == 0) {
intClose(intIIC);
}
intRESTORE_IEN(ien);
return TMLIBDEV_OK;
}
/**************************************************************************
* IIC Slave now part of IIC library
*************************************************************************/
static Int IicOpened = 0;
static Int IicInstance = 0;
static iicsSetup_t IICSSetup = {False, 184, 0, Null};
/*-----------------------------functions------------------------------------*/
tmLibdevErr_t iicsOpen(int* instance)
{
UInt ien, err;
err = procGetCapabilities(&procCap);
if (err) return err;
switch (procCap->deviceID)
{
case PROC_DEVICE_TM1000 :
case PROC_DEVICE_TM1100 :
case PROC_DEVICE_TM1300 :
return TMLIBDEV_ERR_NOT_AVAILABLE_IN_HW;
default:
case PROC_DEVICE_UNKNOWN:
case PROC_DEVICE_TM2500 : /* Classic TV */
case PROC_DEVICE_TM2600 : /* HD-SD */
case PROC_DEVICE_TM2700 : /* HD-HD */
case PROC_DEVICE_TM2800 : /* DVB TV / SD-SD */
break;
}
if (IicOpened++ > 0) return TMLIBDEV_OK;
ien= intCLEAR_IEN();
/* Make sure the shared ISR is installed */
iicOpen(&IicInstance);
/* Reset the IICS device */
iicsAckRESET();
intRESTORE_IEN(ien);
return TMLIBDEV_OK;
}
tmLibdevErr_t iicsSetup(piicsSetup_t pSetup)
{
UInt ien;
tmAssert(pSetup != Null, TMLIBDEV_ERR_NULL_PARAMETER);
ien= intCLEAR_IEN();
if (IicOpened > 0) {
IICSSetup = *pSetup;
IICSSetup.iicAddress &= ~0x1;
IICSSetup.iicsMask &= 0xF;
_iicsISR = IICSSetup.iicsISR;
_iicsMask = IICSSetup.iicsMask;
iicsSetSLAVE_ADR(IICSSetup.iicAddress);
iicsSetINTEN(IICSSetup.iicsMask);
}
intRESTORE_IEN(ien);
return TMLIBDEV_OK;
}
tmLibdevErr_t iicsGetSetup(piicsSetup_t pSetup)
{
tmAssert(pSetup != Null, TMLIBDEV_ERR_NULL_PARAMETER);
*pSetup = IICSSetup;
return TMLIBDEV_OK;
}
tmLibdevErr_t iicsClose(int instance)
{
UInt ien;
ien= intCLEAR_IEN();
if (--IicOpened == 0) {
iicClose(IicInstance);
IicInstance = 0;
_iicsISR = Null;
_iicsMask = 0;
iicsSetINTEN(0);
return TMLIBDEV_OK;
}
intRESTORE_IEN(ien);
return TMLIBDEV_OK;
}
/*--------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -