/******************************************************************************* * sdramTimeCtrlLowRegCalc - Calculate sdram timing control low register * * DESCRIPTION: * This function calculates sdram timing control low register * optimized value based on the bank info parameters and the minCas. * * INPUT: * pBankInfo - sdram bank parameters * busClk - Bus clock * * OUTPUT: * None * * RETURN: * sdram timinf control low reg value. * *******************************************************************************/ static MV_U32 sdramTimeCtrlLowRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 minCas, MV_U32 busClk) { MV_U32 tRp = 0; MV_U32 tRrd = 0; MV_U32 tRcd = 0; MV_U32 tRas = 0; MV_U32 tWr = 0; MV_U32 tWtr = 0; MV_U32 tRtp = 0; MV_U32 bankNum; busClk = busClk / 1000000; /* In MHz */ /* Scan all DRAM banks to find maximum timing values */ for (bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) { tRp = MV_MAX(tRp, pBankInfo[bankNum].minRowPrechargeTime); tRrd = MV_MAX(tRrd, pBankInfo[bankNum].minRowActiveToRowActive); tRcd = MV_MAX(tRcd, pBankInfo[bankNum].minRasToCasDelay); tRas = MV_MAX(tRas, pBankInfo[bankNum].minRasPulseWidth); } /* Extract timing (in ns) from SPD value. We ignore the tenth ns part. */ /* by shifting the data two bits right. */ tRp = tRp >> 2; /* For example 0x50 -> 20ns */ tRrd = tRrd >> 2; tRcd = tRcd >> 2; /* Extract clock cycles from time parameter. We need to round up */ tRp = ((busClk * tRp) / 1000) + (((busClk * tRp) % 1000) ? 1 : 0); DB(mvOsPrintf("Dram Timing Low: tRp = %d ", tRp)); tRrd = ((busClk * tRrd) / 1000) + (((busClk * tRrd) % 1000) ? 1 : 0); DB(mvOsPrintf("tRrd = %d ", tRrd)); tRcd = ((busClk * tRcd) / 1000) + (((busClk * tRcd) % 1000) ? 1 : 0); DB(mvOsPrintf("tRcd = %d ", tRcd)); tRas = ((busClk * tRas) / 1000) + (((busClk * tRas) % 1000) ? 1 : 0); DB(mvOsPrintf("tRas = %d ", tRas)); /* tWr and tWtr is different for DDR1 and DDR2. tRtp is only for DDR2 */ if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) { /* Scan all DRAM banks to find maximum timing values */ for (bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) { tWr = MV_MAX(tWr, pBankInfo[bankNum].minWriteRecoveryTime); tWtr = MV_MAX(tWtr, pBankInfo[bankNum].minWriteToReadCmdDelay); tRtp = MV_MAX(tWtr, pBankInfo[bankNum].minReadToPrechCmdDelay); } /* Extract timing (in ns) from SPD value. We ignore the tenth ns */ /* part by shifting the data two bits right. */ tWr = tWr >> 2; /* For example 0x50 -> 20ns */ tWtr = tWtr >> 2; tRtp = tRtp >> 2; /* Extract clock cycles from time parameter. We need to round up */ tWr = ((busClk * tWr) / 1000) + (((busClk * tWr) % 1000) ? 1 : 0); DB(mvOsPrintf("tWr = %d ", tWr)); tWtr = ((busClk * tWtr) / 1000) + (((busClk * tWtr) % 1000) ? 1 : 0); DB(mvOsPrintf("tWtr = %d ", tWtr)); tRtp = ((busClk * tRtp) / 1000) + (((busClk * tRtp) % 1000) ? 1 : 0); DB(mvOsPrintf("tRtp = %d ", tRtp)); } else {
int mvtsu_open (struct inode *inode, struct file *filp) { struct mvtsu_dev *dev; MV_TSU_PORT_CONFIG port_cfg; MV_TSU_BUFF_INFO *binfo = NULL; MV_STATUS status; int result = 0; int stat_size = 0; int data_size = 0; int data_buff_offs; TSU_ENTER(TSU_DBG_OPEN, "mvtsu_open"); if(MV_FALSE == mvCtrlPwrClckGet(TS_UNIT_ID, 0)) { printk("Transport Stream interface is powered off.\n"); return 0; } /* Find the device structure. */ dev = container_of(inode->i_cdev, struct mvtsu_dev, cdev); /* Determine the port direction according to the read / write flag.*/ if ((filp->f_mode & (FMODE_WRITE | FMODE_READ)) == FMODE_WRITE) { port_cfg.portDir = TSU_PORT_OUTPUT; } else if ((filp->f_mode & (FMODE_WRITE | FMODE_READ)) == FMODE_READ) { port_cfg.portDir = TSU_PORT_INPUT; } else { result = -EINVAL; goto fail_init; } /* Reset the port. */ mvTsuPortReset(dev->port); /* Initialize the port. */ port_cfg.pktSize = cfg_pkt_size; status = mvTsuPortInit(dev->port,&port_cfg); if(status != MV_OK) { result = -EINVAL; goto fail_init; } TSU_DPRINT(TSU_DBG_OPEN, ("\tTSU unit initialized successfully.\n")); /* Initialize the port buffers. */ binfo = &dev->buff_info; switch(binfo->aggrMode) { case (MV_TSU_AGGR_MODE_DISABLED): binfo->dataBlockSize = port_cfg.pktSize; dev->valid_data_size = port_cfg.pktSize; dev->rd_rw_data_size = binfo->dataBlockSize + TSU_DONE_STATUS_ENTRY_SIZE; binfo->aggrNumPackets = 1; break; case (MV_TSU_AGGR_MODE_1): binfo->dataBlockSize = port_cfg.pktSize * binfo->aggrNumPackets; if(port_cfg.portDir == TSU_PORT_OUTPUT) { binfo->dataBlockSize += MV_MAX(TSU_DMA_ALIGN,TSU_MODE1_OUT_TMS_SIZE); dev->rd_rw_data_size = binfo->dataBlockSize; } else { dev->rd_rw_data_size = binfo->dataBlockSize + (binfo->aggrNumPackets * TSU_DONE_STATUS_ENTRY_SIZE); } dev->valid_data_size = port_cfg.pktSize * binfo->aggrNumPackets; break; case (MV_TSU_AGGR_MODE_2): binfo->aggrMode2TmstmpOff = TSU_DMA_ALIGN - (port_cfg.pktSize & (TSU_DMA_ALIGN - 1)); binfo->dataBlockSize = (binfo->aggrNumPackets * (port_cfg.pktSize + binfo->aggrMode2TmstmpOff) + TSU_DMA_ALIGN); dev->valid_data_size = (binfo->aggrNumPackets * (port_cfg.pktSize + binfo->aggrMode2TmstmpOff)); dev->rd_rw_data_size = dev->valid_data_size; default: break; } dev->port_dir = port_cfg.portDir; /* Align the data block size to a cache line. */ binfo->dataBlockSize = MV_ALIGN_UP(binfo->dataBlockSize,32); data_size = binfo->dataBlockSize * binfo->numTsDesc; #ifdef TSU_UNCACHED_DATA_BUFFERS binfo->tsDataBuff = mvOsIoUncachedMalloc(NULL,data_size,(MV_ULONG*)(&binfo->tsDataBuffPhys), NULL); #else binfo->tsDataBuff = mvOsIoCachedMalloc(NULL,data_size,(MV_ULONG*)(&binfo->tsDataBuffPhys), NULL); #endif /* TSU_UNCACHED_DATA_BUFFERS */ if(binfo->tsDataBuff == NULL) { result = -ENOMEM; goto fail_init; } // memset(binfo->tsDataBuff,0x88,data_size); #ifndef TSU_UNCACHED_DATA_BUFFERS mvOsCacheClear(NULL,(MV_U32*)TSU_DATA_BUFF_HW_2_SW(binfo->tsDataBuff), data_size); #endif /* TSU_UNCACHED_DATA_BUFFERS */ /* Align tsDataBuff according to the HW limitation. */ if(binfo->aggrMode == MV_TSU_AGGR_MODE_2) { data_buff_offs = port_cfg.pktSize & (TSU_DMA_ALIGN - 1); } else if((binfo->aggrMode == MV_TSU_AGGR_MODE_1) && (port_cfg.portDir == TSU_PORT_OUTPUT)) { data_buff_offs = TSU_DMA_ALIGN - TSU_MODE1_OUT_TMS_SIZE; } else { data_buff_offs = 0; } binfo->tsDataBuff = (MV_U32*)((MV_U32)binfo->tsDataBuff + data_buff_offs); binfo->tsDataBuffPhys += data_buff_offs; TSU_DPRINT(TSU_DBG_OPEN, ("\tTSU Data buffer allocated successfully " "(%p, %d).\n",binfo->tsDataBuff, data_size)); /* Allocate memory for done queue. */ stat_size = TSU_DONE_STATUS_ENTRY_SIZE * binfo->numDoneQEntry; dev->stat_buff_size = stat_size; binfo->tsDoneBuff = mvOsIoUncachedMalloc(NULL,stat_size, (MV_ULONG*)(&binfo->tsDoneBuffPhys),NULL); if(binfo->tsDoneBuff == NULL) { result = -ENOMEM; goto fail_init; } TSU_DPRINT(TSU_DBG_OPEN, ("\tTSU Done buffer allocated successfully" "(%p, %d).\n",binfo->tsDoneBuff, stat_size)); status = mvTsuBuffersInit(dev->port,&dev->buff_info); if(status != MV_OK) { TSU_DPRINT(TSU_DBG_OPEN, ("\tmvTsuBuffersInit() Failed (%d).", status)); result = -EINVAL; goto fail_init; } TSU_DPRINT(TSU_DBG_OPEN, ("\tHAL Buffers initialized successfully.\n")); status = mvTsuPortSignalCfgSet(dev->port,&(dev->signal_cfg),dev->serial_sig_flags); if(status != MV_OK) { TSU_DPRINT(TSU_DBG_OPEN, ("\tmvTsuPortSignalCfgSet() Failed (%d).", status)); result = -EINVAL; goto fail_init; } TSU_DPRINT(TSU_DBG_OPEN, ("\tPort signal parameters set successfully.\n")); status = mvTsuRxSyncDetectionSet(dev->port,dev->sync_detect,dev->sync_loss); if(status != MV_OK) { TSU_DPRINT(TSU_DBG_OPEN, ("\tmvTsuRxSyncDetectionSet() Failed (%d).", status)); result = -EINVAL; goto fail_init; } TSU_DPRINT(TSU_DBG_OPEN, ("\tRx sync parameters set successfully.\n")); mvtsu_rd_wr_timeout_calc(dev); if(dev->port_dir == TSU_PORT_OUTPUT) { mvtsu_tx_timestamp_calc(dev); } /* Register IRQ. */ MV_REG_WRITE(MV_TSU_INTERRUPT_MASK_REG(dev->port),TSU_DFLT_INT_MASK); if(request_irq(IRQ_TS_INT(dev->port),mvtsu_interrupt_handler, IRQF_DISABLED | IRQF_SAMPLE_RANDOM,"tsu",dev)) { printk(KERN_ERR "Cannot assign irq%d to TSU port%d\n", IRQ_TS_INT(dev->port), dev->port); goto fail_init; } TSU_DPRINT(TSU_DBG_OPEN, ("\tTSU interrupt registered at IRQ %d.\n", IRQ_TS_INT(dev->port))); if(port_cfg.portDir == TSU_PORT_INPUT) { /* Enable Rx timestamp. */ mvTsuRxTimestampCntEn(dev->port,MV_TRUE); mvTsuDmaWatermarkSet(dev->port,0x8); } /* Make the private_data hold the pointer to the device data. */ filp->private_data = dev; TSU_LEAVE(TSU_DBG_OPEN, "mvtsu_open"); return 0; fail_init: if(binfo != NULL) { if(binfo->tsDataBuff != NULL) #ifdef TSU_UNCACHED_DATA_BUFFERS mvOsIoUncachedFree( NULL,data_size, TSU_DATA_BUFF_HW_2_SW(binfo->tsDataBuffPhys), (MV_U32*)TSU_DATA_BUFF_HW_2_SW(binfo->tsDataBuff),0); #else mvOsIoCachedFree( NULL,data_size, TSU_DATA_BUFF_HW_2_SW(binfo->tsDataBuffPhys), (MV_U32*)TSU_DATA_BUFF_HW_2_SW(binfo->tsDataBuff),0); #endif /* TSU_UNCACHED_DATA_BUFFERS */ if(binfo->tsDoneBuff != NULL) mvOsIoUncachedFree(NULL,stat_size,binfo->tsDoneBuffPhys, binfo->tsDoneBuff,0); binfo->tsDataBuff = NULL; binfo->tsDoneBuff = NULL; } TSU_LEAVE(TSU_DBG_OPEN, "mvtsu_open"); return result; }