/*! \fn int DbridgeEsafe_AddNetDev(struct net_device* ptr_net_dev, * unsigned int esafe_type,int (*push)(struct sk_buff* skb)) ************************************************************************** * \brief Connect target device interface to esafe (EMTA,EPS,ESTB_IP,ESTB_DSG,ETEA) * \param[in] ptr_net_dev - pointer to target device interface. * \param[in] esafe_type - EMTA -1, EPS -2, ESTB_IP-3, ESTB_DSG-4 ,ETEA-5. * \param[in] push - push function to send packet from esafe to target device interface. * \return OK=0 or error status. **************************************************************************/ int DbridgeEsafe_AddNetDev(struct net_device* ptr_net_dev,unsigned int esafe_type,int (*push)(struct sk_buff* skb)) { Uint32 lockKey; int res = -1; PAL_osProtectEntry(PAL_OSPROTECT_INTERRUPT, &lockKey); if (esafe_table_insert < DBR_MAX_ESAFE_INTERFACES) { if (ptr_net_dev) { /* create and register esafe interface */ struct net_device *esafe_net_device; esafe_net_device = DbridgeEsafe_CreateDev(esafe_table_insert); if (esafe_net_device) { DbridgeDb_DevAdd(esafe_net_device,DbridgeEsafe_NetifReceive,DBR_ESAFE_NET_DEV_TYPE); DbridgeEsafeDeviceTable[esafe_table_insert].ptr_esafeInterface = esafe_net_device; DbridgeEsafeDeviceTable[esafe_table_insert].ptr_targetInterface = ptr_net_dev; DbridgeEsafeDeviceTable[esafe_table_insert].dbridgeDevice = DbridgeDb_DevGetByInterface(esafe_net_device); DbridgeEsafeDeviceTable[esafe_table_insert].eSafeType = esafe_type; DbridgeEsafeDeviceTable[esafe_table_insert].push = push; esafe_table_insert++; rtnl_lock(); res = dev_open(esafe_net_device); rtnl_unlock(); if (res == 0) { PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, lockKey); return res; } else printk(KERN_WARNING "DUnable to open device %s\n",esafe_net_device->name); } else { printk(KERN_WARNING "DbridgeEsafe_CreateDev Fail\n"); } } else { printk(KERN_WARNING "input ptr_net_dev is NULL\n"); } } else { printk(KERN_WARNING "Device table is full\n"); } PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, lockKey); return res; }
/** * \brief Close Instance of the I2C device * * This function closes the device for data transfers and usage by the * upper layer driver software. The hardware is programmed to stop/abort data * transfer (depending upon the type of device and its specifics) and the * device ISR is "disabled" by the upper layer driver software after the * completion of this call. After the successful completion of this call, the * device cannot perform any data IO. * * \param handle [IN] I2C Driver Instance Handle * \return PSP_SOK or PSP Error code */ PSP_Result PSP_i2cClose(PSP_Handle handle) { DDC_I2cDriverObject *pi2cHandle; DDC_I2cObject *i2cObj; Uint32 cookie; Int retVal; Int retCode; retVal = PSP_SOK; retCode = 0; /* Check state of handle */ if (handle == NULL) { retVal = (PSP_E_INVAL_PARAM); } else { pi2cHandle = (DDC_I2cDriverObject *)handle; if (pi2cHandle == ((DDC_I2cDriverObject *) NULL)) { retVal = (PSP_E_INVAL_PARAM); } else { i2cObj = pi2cHandle->pi2cInstHandle; if (i2cObj == ((DDC_I2cObject *) NULL)) { retVal = (PSP_E_INVAL_PARAM); } else { /* Check for the validity of the I2C STATE */ if ( i2cObj->state != I2C_OPENED ) { retVal = (PSP_E_INVAL_STATE); } } } } if (retVal == PSP_SOK) { /* Check for any IO is pending, if yes then cancel io */ if ( i2cObj->pendingState == TRUE ){ retCode = PSP_i2cIoctl(handle,PSP_I2C_IOCTL_CANCEL_PENDING_IO, NULL, NULL); if(retCode != PSP_SOK){ retVal = retCode; } } /* Start of Critical Section */ PAL_osProtectEntry(PAL_OSPROTECT_INTERRUPT, &cookie); /* Decrease the Number of Opens */ i2cObj->numOpens = i2cObj->numOpens - 1u; pi2cHandle->pi2cInstHandle = NULL; pi2cHandle = NULL; PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, cookie); if (i2cObj->numOpens == 0) { /* Put the device in reset and quit */ i2cObj->i2cRegs->ICMDR = 0; i2cObj->state = I2C_CLOSED; } }/* retVal */ return (retVal); }
/** I2C driver Transfer [internal to DDC where actual transfer happens] * * This is the function in which a tuall data transfer happens. * In this function it validates input parameters set the parameter values in * to the registers and starts transmission * * \param handle [IN] I2C Driver Instance Handle * \param slaveAddr [IN] Slave address (only valid in Master mode) * \param buffer [IN] Buffer (to read into or write from) * \param bufLen [IN] Buffer length - number of bytes to transact * \param flags [IN] Flags to specify mode of operation * \param timeout [IN] Timeout for i2c transaction * \param param [IN] Extra paramter for future usage * \param xferActual [IN] Gives number of bytes actually transferred * * \return Interger Value > 0 - Number of bytes transferred. * */ static Int DDC_i2cTransfer (PSP_Handle handle, Uint32 slaveAddr, Uint16 *buffer, Uint32 bufLen, Uint32 flags, Int32 timeout, Ptr param, Ptr xferActual) { DDC_I2cObject *i2cObj; Uint32 cnt; Uint32 icmdr; Uint32 status; PSP_Result retCode; Uint32 cookie; Int retVal; volatile Uint16 looper; #ifdef BIOS_BUILD Uint32 timeCnt; #endif cnt = 0; icmdr = 0; retCode = 0; retVal = 0; /* Check the state of handle */ if (((handle == NULL) || (buffer == NULL)) || (xferActual == NULL)) { retVal = (PSP_E_INVAL_PARAM); } else { i2cObj = (DDC_I2cObject *) handle; if (i2cObj == ((DDC_I2cObject *) NULL)) { retVal = (PSP_E_INVAL_PARAM); } /* Check user has not set both read and write flag at same time*/ else if (((flags & PSP_I2C_READ) != 0) && ((flags & PSP_I2C_WRITE) != 0)) { retVal = (PSP_E_INVAL_PARAM); } else if ( ( (buffer == NULL) || (bufLen == 0) ) || (bufLen > DDC_I2C_BUFFER_MAXLENGTH) ) { retVal = (PSP_E_INVAL_PARAM); } else if (i2cObj->repeatMode == TRUE) { if ( (bufLen > 0) && ((flags & PSP_I2C_STOP) != 0)) { retVal = (PSP_E_INVAL_PARAM); } } else { /* Check for Bus Busy if not restarting */ if (((flags & PSP_I2C_RESTART) == 0) && ((flags & PSP_I2C_IGNORE_BUS_BUSY) == 0)) { /* Loop on busy condition */ if (i2cObj->mode == PSP_OPMODE_POLLED) { retCode = i2cWaitForBB(i2cObj, PSP_I2C_BUS_BUSY_TIMEOUT_CNT, 0); if ( retCode != 0 ) { retVal = (PSP_I2C_BUS_BUSY_ERR); } } else { retCode = i2cWaitForBB(i2cObj, PSP_I2C_BUS_BUSY_TIMEOUT_MSECS, 1u); if ( retCode != 0 ) { retVal = (PSP_I2C_BUS_BUSY_ERR); } } /* Enters this condition if i2c bus is busy */ } } /* else */ } /* retVal */ if (retVal == 0) { /* Set count for data transfer and init mode control register */ i2cObj->i2cRegs->ICCNT = (bufLen & DDC_I2C_BUFFER_MAXLENGTH); /* Check flags and set accordingly */ if ((flags & PSP_I2C_MASTER) != 0) { i2cObj->i2cRegs->ICMDR |= CSL_I2C_ICMDR_MST_MASK; } if ((flags & PSP_I2C_START) != 0) { icmdr |= CSL_I2C_ICMDR_STT_MASK; } if ((flags & PSP_I2C_STOP) != 0) { icmdr |= CSL_I2C_ICMDR_STP_MASK; } if ((flags & PSP_I2C_WRITE) != 0) { i2cObj->i2cRegs->ICMDR |= CSL_I2C_ICMDR_TRX_MASK; } if ((flags & PSP_I2C_READ) != 0) { i2cObj->i2cRegs->ICMDR &= ~CSL_I2C_ICMDR_TRX_MASK; } /* Write slave address - restrict to 10 bits */ i2cObj->i2cRegs->ICSAR = (((Uint)slaveAddr) & DDC_I2C_SLAVEADRR_10BIT); /* Check if restart required to set the bus busy */ if ((flags & PSP_I2C_RESTART) != 0) { i2cObj->i2cRegs->ICSTR |= CSL_I2C_ICSTR_BB_MASK; icmdr |= CSL_I2C_ICMDR_STT_MASK; } /* To make transaction is in progress */ i2cObj->pendingState = TRUE; /* If polled mode, wait for data transfer and completion, * else wait (on a semaphore) for transaction to complete */ if (i2cObj->mode == PSP_OPMODE_POLLED) { i2cObj->i2cRegs->ICIMR = 0; /* Mask all interrupts - :) * just to make sure */ i2cObj->i2cRegs->ICMDR |= icmdr; /* Start bit set here to * start transaction */ #ifdef BIOS_BUILD timeCnt = PAL_osGetCurrentTick(); #endif while (cnt < bufLen) { if ( retCode == 0 ) { if ((flags & PSP_I2C_WRITE) != 0) { /* Transmit */ if ((i2cObj->i2cRegs->ICSTR & CSL_I2C_ICSTR_ICXRDY_MASK) != 0) { i2cObj->i2cRegs->ICDXR = (*buffer & 0x00FF); /* Transmit 8-bit data */ buffer = buffer + 1u; cnt = cnt + 1u; } } else { /* Receive */ if ((i2cObj->i2cRegs->ICSTR & CSL_I2C_ICIMR_ICRRDY_MASK) != 0) { *buffer = (Uint8) i2cObj->i2cRegs->ICDRR; buffer = buffer + 1u; cnt = cnt + 1u; } } /* Check for Arbitration loss, transmit underflow and * receive overflow errors */ status = i2cObj->i2cRegs->ICSTR; if ((status & CSL_I2C_ICSTR_AL_MASK) != 0) { retCode = PSP_I2C_ARBITRATION_LOSS_ERR; } else if ((status & CSL_I2C_ICSTR_RSFULL_MASK) != 0) { retCode = PSP_I2C_RECEIVE_OVERFLOW_ERR; } /* Check for NACK error */ else{ if ((status & CSL_I2C_ICSTR_NACK_MASK) != 0){ retCode = PSP_I2C_NACK_ERR; } } } else { if (retCode == PSP_SOK) { retCode = PSP_E_TIMEOUT; } break; } // PAL_osWaitMsecs(1u); for(looper = 0;looper < 2000;looper++) { asm("\tNOP;"); } } /* While number of byte to be transmitted/received loop */ } /* if polled mode */ else { /* Set the current buffer params correctly */ i2cObj->currError = 0; i2cObj->currFlags = flags; i2cObj->currBuffer = (buffer+cnt); i2cObj->currBufferLen = (bufLen-cnt); if (i2cObj->currBufferLen > 0) { /* Enable interrupts */ i2cObj->i2cRegs->ICIMR = ( CSL_I2C_ICIMR_AL_MASK | /* Arbitration lost */ CSL_I2C_ICIMR_NACK_MASK | /* NACK received/not received */ CSL_I2C_ICIMR_AAS_MASK); /* Addressed as Slave */ if ((flags & PSP_I2C_WRITE) != 0){ i2cObj->i2cRegs->ICIMR |= CSL_I2C_ICIMR_ICXRDY_MASK ; /* Transmit ready */ }else if((flags & PSP_I2C_READ) != 0){ i2cObj->i2cRegs->ICIMR |= CSL_I2C_ICIMR_ICRRDY_MASK ; } /* Receive ready */ /* Start I2C transaction */ i2cObj->i2cRegs->ICIVR = 0; /* Clear IVR before doing a start */ i2cObj->i2cRegs->ICMDR |= icmdr; /* Start bit set here to start * transaction */ /* Take completion semaphore */ retCode = PAL_osSemTake(i2cObj->completionSem, _DDA_i2cOsGetTicks( timeout) ); if (retCode != PAL_SOK) { /* Entry of Critical Section */ PAL_osProtectEntry(PAL_OSPROTECT_INTERRUPT, &cookie); cnt = bufLen - i2cObj->currBufferLen; i2cObj->currBufferLen = 0 ; i2cObj->currBuffer = NULL; i2cObj->currError = PSP_E_TIMEOUT; i2cObj->i2cRegs->ICIMR &= ~CSL_I2C_ICIMR_ICXRDY_MASK; /* Disable Transmit interrupt */ i2cObj->i2cRegs->ICIMR &= ~CSL_I2C_ICIMR_ICRRDY_MASK; /* Disable Receive interrupt */ /*wait till data is shifted out of shift register*/ if ((flags & PSP_I2C_WRITE) != 0) { while (( (i2cObj->i2cRegs->ICSTR) & (CSL_I2C_ICSTR_ICXRDY_MASK) ) == 0) { } } /*Put the module in reset mode*/ i2cObj->i2cRegs->ICMDR &= ~( DDC_I2C_RESET); /*Bring the module out of reset*/ i2cObj->i2cRegs->ICMDR |= DDC_I2C_RESET; /* Exit of Critical Section */ PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, cookie); } else { /* Return error code (if error) or number of bytes transmitted */ retCode = i2cObj->currError; /* Disable the interrupts once it comes out of ISR */ i2cObj->i2cRegs->ICIMR = 0; } } /* Return error code (if error) or number of bytes transmitted */ cnt = bufLen - i2cObj->currBufferLen; } #ifdef BIOS_BUILD if (1u == bufLen) { timeCnt = PAL_osGetCurrentTick(); /* This Delay is given to ensure whether there is check for any errors */ while(FALSE == PAL_osCheckTimeOut(timeCnt,1)){ } } #endif /* Check for Arbitration loss, transmit underflow and * receive overflow errors( this checking is for the reason that updating * ICSTR depends on the clock frequency and speed of slave */ if ((i2cObj->i2cRegs->ICSTR & CSL_I2C_ICSTR_AL_MASK) != 0) { retCode = PSP_I2C_ARBITRATION_LOSS_ERR; } else if ((i2cObj->i2cRegs->ICSTR & CSL_I2C_ICSTR_RSFULL_MASK) != 0) { retCode = PSP_I2C_RECEIVE_OVERFLOW_ERR; } /* Check for NACK error */ else { if ((i2cObj->i2cRegs->ICSTR & CSL_I2C_ICSTR_NACK_MASK) != 0) { retCode = PSP_I2C_NACK_ERR; } } if ( retCode != 0) { i2c_cancelIO(i2cObj); retVal = retCode; } *(Uint32 *)xferActual = cnt; i2cObj->pendingState=FALSE; } /* retVal */ return retVal; }
/** * \brief Open Instance of the I2C device * * This function prepares the device hardware for data transfers and * usage by the upper layer driver software. The DDA layer is expected * to install the ISR and enable it only after the completion of this * call. The function prepares the driver instance for data transfers * and returns an handle to the driver instance. * * Note: The driver can be opened multiple times * \param instanceId [IN] I2C instance number * \param callback [IN] Callback function for events notification * \param appHandle [IN] This appHandle will be provided by user and * will be returned along with call back * \return PSP_Handle [OUT] If successful positive Driver Instance Handle * else return the NULL pointer. */ PSP_Handle PSP_i2cOpen(Uint32 instanceId, PSP_I2cAppCallback callback, Ptr appHandle) { DDC_I2cObject *i2cObj; DDC_I2cDriverObject *i2cHandle; Uint32 psc, clk, cnt; Uint32 cookie; i2cHandle = NULL; /* Validate instance ID */ if (instanceId < PSP_I2C_NUM_INSTANCES) { i2cObj = &ddcI2CObj[instanceId]; if ( ((i2cObj != NULL) && (i2cObj->state != I2C_DELETED)) && (i2cObj->numOpens < PSP_I2C_NUM_OPENS) ) { /* Create i2c driver object */ for (cnt=0; cnt < PSP_I2C_NUM_OPENS; cnt++) { ddcI2CDriver[i2cObj->instanceId][cnt].callBack = callback; ddcI2CDriver[i2cObj->instanceId][cnt].appHandle = appHandle; ddcI2CDriver[i2cObj->instanceId][cnt].pi2cInstHandle = i2cObj; i2cHandle = &ddcI2CDriver[i2cObj->instanceId][cnt]; break; } } } if (i2cHandle != NULL) { /* Start of critical section */ PAL_osProtectEntry(PAL_OSPROTECT_INTERRUPT, &cookie); /* Init hardware if first open */ if (i2cObj->numOpens == 0) { i2cObj->instanceId = instanceId; switch (instanceId) { case 0: i2cObj->i2cRegs = (CSL_I2cDrvRegs *) CSL_I2C_REGS; break; default: i2cHandle = NULL; break; } if (i2cHandle != NULL) { /* Put the module in reset */ i2cObj->i2cRegs->ICMDR = 0; if(i2cCalculateClockSettings(i2cObj , &psc, &clk) != 0 ) { i2cHandle = NULL; } else { i2cObj->i2cRegs->ICPSC = psc; i2cObj->i2cRegs->ICCLKH = clk; i2cObj->i2cRegs->ICCLKL = clk; /* Set own address and bits/byte */ i2cObj->i2cRegs->ICOAR = i2cObj->i2cOwnAddr; i2cObj->i2cRegs->ICMDR = (i2cObj->numBits & 0x7u) | CSL_I2C_ICMDR_MST_MASK; /* Enable/Disable Repeat,DLB and 7/10 bit addressing modes */ if ((Bool)TRUE == i2cObj->dlb) { i2cObj->i2cRegs->ICMDR |= CSL_I2C_ICMDR_DLB_MASK; } else { i2cObj->i2cRegs->ICMDR &= ~(CSL_I2C_ICMDR_DLB_MASK); } if ( ((Bool)TRUE == i2cObj->repeatMode) ) { i2cObj->i2cRegs->ICMDR |= CSL_I2C_ICMDR_RM_MASK; } else { i2cObj->i2cRegs->ICMDR &= (~(CSL_I2C_ICMDR_RM_MASK)); } if ((Bool)TRUE == i2cObj->addressing) { i2cObj->i2cRegs->ICMDR |= CSL_I2C_ICMDR_XA_MASK; } else { i2cObj->i2cRegs->ICMDR &= (~(CSL_I2C_ICMDR_XA_MASK)); } /* Bring module out of reset */ i2cObj->i2cRegs->ICMDR |= CSL_I2C_ICMDR_IRS_MASK; /* Set the backward compatibility mode off - this is critical to get * interrupts correctly */ i2cObj->i2cRegs->ICEMDR = 0; } /* else retCode */ } /* retVal = NULL in side if first oprn */ } /* First open initialization */ /* End of critical section */ PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, cookie); } /* retVal = NULL before firstt open */ if (i2cHandle != NULL) { /* Increment open count and return driver handle */ i2cObj->numOpens = i2cObj->numOpens + 1u; /* Updated the driver state */ i2cObj->state = I2C_OPENED; } return (PSP_Handle)i2cHandle; }