//***************************************************************************** // // Function Name: chal_dsi_set_timing // // Description: Calculate Values Of DSI Timing Counters // // <in> escClk_MHz ESC CLK after divider // <in> hsBitRate_Mbps HS Bit Rate ( eq to DSI PLL/dsiPllDiv ) // <in> lpBitRate_Mbps LP Bit Rate, Max 10 Mbps // //***************************************************************************** cBool chal_dsi_set_timing ( CHAL_HANDLE handle, cUInt32 DPHY_SpecRev, float escClk_MHz, float hsBitRate_Mbps, float lpBitRate_Mbps ) { Boolean res = FALSE; float time_min; float time_min1; float time_min2; float time_max; float period; float ui_ns; float escClk_ns; cUInt32 i; DSI_COUNTER * pDsiC; CHAL_DSI_HANDLE pDev; chal_dprintf ( CDBG_INFO, "chal_dsi_set_timing() escClk_MHz:%f hsBitRate_Mbps:%f lpBitRate_Mbps:%f ", escClk_MHz, hsBitRate_Mbps, lpBitRate_Mbps); pDev = (CHAL_DSI_HANDLE) handle; ui_ns = 1 / hsBitRate_Mbps * 1000; escClk_ns = 1 / escClk_MHz * 1000; switch ( DPHY_SpecRev ) { case 1: pDsiC = &dsi_dphy_0_92[0]; break; default: return ( FALSE ); } // LP Symbol Data Rate = esc_clk / esc2lp_ratio if( ! chalDsiTimingDivAndRoundUp( pDsiC, DSI_C_ESC2LP_RATIO, (float)escClk_MHz, (float)lpBitRate_Mbps * 2) ) { return ( FALSE ); } for( i=1; i < DSI_C_MAX; i++ ) { // Period_min1 [ns] time_min1 = (float)pDsiC[i].time_min1_ns + (float)pDsiC[i].time_min1_ui * ui_ns; // Period_min2 [ns] if( pDsiC[i].mode & DSI_C_MIN_MAX_OF_2 ) time_min2 = (float)pDsiC[i].time_min2_ns + (float)pDsiC[i].time_min2_ui * ui_ns; else time_min2 = 0; // Period_min [ns] = max(min1, min2) if( time_min1 >= time_min2 ) time_min = time_min1; else time_min = time_min2; // Period_max [ns] if( pDsiC[i].mode & DSI_C_HAS_MAX ) time_max = (float)pDsiC[i].time_max_ns + (float)pDsiC[i].time_max_ui * ui_ns; else time_max = 0; // Period_units [ns] if ( pDsiC[i].timeBase & DSI_C_TIME_HS ) period = ui_ns; else if ( pDsiC[i].timeBase & DSI_C_TIME_ESC ) period = escClk_ns; else period = 0; pDsiC[i].period = period; if( period != 0 ) { res = chalDsiTimingDivAndRoundUp ( pDsiC, i, time_min, period ); if( !res ) return ( res ); if( pDsiC[i].mode & DSI_C_HAS_MAX ) { if( ((float)pDsiC[i].counter * period ) > time_max ) { chal_dprintf ( CDBG_ERRO, "[cHAL DSI] chal_dsi_set_timing: " "%s violates MAX D-PHY Spec allowed value\n\r", pDsiC[i].name ); return ( FALSE ); } } } } for( i=0; i < DSI_C_MAX; i++ ) { if ( pDsiC[i].timeBase == DSI_C_TIME_ESC2LPDT ) { chal_dprintf ( CDBG_INFO, "[cHAL DSI] chal_dsi_set_timing: " "%13s %7d\n\r", pDsiC[i].name, pDsiC[i].counter ); } else { chal_dprintf ( CDBG_INFO, "[cHAL DSI] chal_dsi_set_timing: " "%13s %7d %10.2f[ns]\n\r", pDsiC[i].name, pDsiC[i].counter, ((float)pDsiC[i].counter + pDsiC[i].counter_offs) * pDsiC[i].period ); } } chal_dprintf (CDBG_INFO, "\r\n[cHAL DSI] chal_dsi_set_timing: " "HS_DATA_RATE %6.2f[Mbps]\r\n", hsBitRate_Mbps ); chal_dprintf (CDBG_INFO, "[cHAL DSI] chal_dsi_set_timing: " "LP_DATA_RATE %6.2f[Mbps]\n\r", escClk_MHz / 2 / ( pDsiC [ DSI_C_ESC2LP_RATIO ].counter + pDsiC [ DSI_C_ESC2LP_RATIO ].counter_offs) ); // set ESC 2 LPDT ratio BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_PHYC , ESC_CLK_LPDT, pDsiC [ DSI_C_ESC2LP_RATIO ].counter ); // INIT BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_HS_INIT , HS_INIT , pDsiC [ DSI_C_HS_INIT ].counter ); // ULPS WakeUp BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_HS_WUP , HS_WUP , pDsiC [ DSI_C_HS_WAKEUP ].counter); BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_LP_WUP , LP_WUP , pDsiC [ DSI_C_LP_WAKEUP ].counter ); // HS CLK BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_HS_CPRE , HS_CPRE , pDsiC [ DSI_C_HS_CLK_PRE ].counter ); #if (CHIP_REVISION >= 20) BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_HS_CPREPARE , HS_CLK_PREP, pDsiC [ DSI_C_HS_CLK_PREPARE ].counter ); #endif BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_HS_CZERO , HS_CZERO , pDsiC [ DSI_C_HS_CLK_ZERO ].counter ); BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_HS_CPOST , HS_CPOST , pDsiC [ DSI_C_HS_CLK_POST ].counter ); BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_HS_CTRAIL, HS_CTRAIL , pDsiC [ DSI_C_HS_CLK_TRAIL ].counter ); // HS BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_HS_LPX , HS_LPX , pDsiC [ DSI_C_HS_LPX ].counter ); BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_HS_PRE , HS_PRE , pDsiC [ DSI_C_HS_PRE ].counter ); BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_HS_ZERO , HS_ZERO , pDsiC [ DSI_C_HS_ZERO ].counter ); BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_HS_TRAIL , HS_TRAIL , pDsiC [ DSI_C_HS_TRAIL ].counter ); BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_HS_EXIT , HS_EXIT , pDsiC [ DSI_C_HS_EXIT ].counter ); // ESC BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_LPX , LPX , pDsiC [ DSI_C_LPX ].counter ); // TURN_AROUND BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_TA_GO , TA_GO , pDsiC [ DSI_C_LP_TA_GO ].counter); BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_TA_SURE , TA_SURE , pDsiC [ DSI_C_LP_TA_SURE ].counter ); BRCM_WRITE_REG_FIELD ( pDev->baseAddr, DSI_TA_GET , TA_GET , pDsiC [ DSI_C_LP_TA_GET ].counter ); return ( TRUE ); }
/* * * Function Name: chal_dsi_set_timing * * Description: Calculate Values Of DSI Timing Counters * * <in> escClk_MHz ESC CLK after divider * <in> hsBitRate_Mbps HS Bit Rate ( eq to DSI PLL/dsiPllDiv ) * <in> lpBitRate_Mbps LP Bit Rate, Max 10 Mbps * */ cBool chal_dsi_set_timing(CHAL_HANDLE handle, cUInt32 DPHY_SpecRev, CHAL_DSI_CLK_SEL_t coreClkSel, cUInt32 escClk_MHz, cUInt32 hsBitRate_Mbps, cUInt32 lpBitRate_Mbps) { Boolean res = FALSE; cUInt32 scaled_time_min; cUInt32 scaled_time_min1; cUInt32 scaled_time_min2; cUInt32 scaled_time_max; cUInt32 scaled_period; cUInt32 scaled_ui_ns; cUInt32 scaled_escClk_ns; cUInt32 lp_clk_khz; cUInt32 i; struct DSI_COUNTER *pDsiC; struct CHAL_DSI *pDev; cUInt32 counter_offs; cUInt32 counter_step; cUInt32 lp_lpx_ns; pDev = (struct CHAL_DSI *)handle; scaled_ui_ns = (1000 * 1000) / hsBitRate_Mbps; scaled_escClk_ns = (1000 * 1000) / escClk_MHz; switch (DPHY_SpecRev) { case 1: pDsiC = &dsi_dphy_0_92[0]; break; default: return FALSE; } /* figure step & offset for HS counters */ if (coreClkSel == CHAL_DSI_BIT_CLK_DIV_BY_8) { counter_offs = 8; counter_step = 8; } else if (coreClkSel == CHAL_DSI_BIT_CLK_DIV_BY_4) { counter_offs = 4; counter_step = 4; } else { counter_offs = 2; counter_step = 2; } /* init offset & step for HS counters */ for (i = 1; i < DSI_C_MAX; i++) { /* Period_units [ns] */ if (pDsiC[i].timeBase & DSI_C_TIME_HS) { pDsiC[i].counter_offs = counter_offs; pDsiC[i].counter_step = counter_step; } } /* LP clk (LP Symbol Data Rate) = esc_clk / esc2lp_ratio */ /* calculate esc2lp_ratio */ if (!chalDsiTimingDivAndRoundUp(pDsiC, DSI_C_ESC2LP_RATIO, escClk_MHz, lpBitRate_Mbps * 2)) { return FALSE; } /* actual lp clock */ lp_clk_khz = 1000 * escClk_MHz / (pDsiC[DSI_C_ESC2LP_RATIO].counter + pDsiC[DSI_C_ESC2LP_RATIO].counter_offs); /* lp_esc_clk == lp_data_clock */ lp_lpx_ns = (1000 * 1000 / lp_clk_khz); /* set LP LPX to be equal to LP bit rate */ /* set time_min_ns for LP esc_clk counters */ pDsiC[DSI_C_LPX].time_min1_ns = pDsiC[DSI_C_LPX].time_lpx * lp_lpx_ns; pDsiC[DSI_C_LP_TA_GO].time_min1_ns = pDsiC[DSI_C_LP_TA_GO].time_lpx * lp_lpx_ns; pDsiC[DSI_C_LP_TA_SURE].time_min1_ns = pDsiC[DSI_C_LP_TA_SURE].time_lpx * lp_lpx_ns; pDsiC[DSI_C_LP_TA_GET].time_min1_ns = pDsiC[DSI_C_LP_TA_GET].time_lpx * lp_lpx_ns; /* start from 1, skip [0]=esc2lp_ratio */ for (i = 1; i < DSI_C_MAX; i++) { /* Period_min1 [ns] */ scaled_time_min1 = pDsiC[i].time_min1_ns * 1000 + pDsiC[i].time_min1_ui * scaled_ui_ns; /* Period_min2 [ns] */ if (pDsiC[i].mode & DSI_C_MIN_MAX_OF_2) scaled_time_min2 = pDsiC[i].time_min2_ns * 1000 + pDsiC[i].time_min2_ui * scaled_ui_ns; else scaled_time_min2 = 0; /* Period_min [ns] = max(min1, min2) */ if (scaled_time_min1 >= scaled_time_min2) scaled_time_min = scaled_time_min1; else scaled_time_min = scaled_time_min2; /* Period_max [ns] */ if (pDsiC[i].mode & DSI_C_HAS_MAX) scaled_time_max = pDsiC[i].time_max_ns * 1000 + pDsiC[i].time_max_ui * scaled_ui_ns; else scaled_time_max = 0; /* Period_units [ns] */ if (pDsiC[i].timeBase & DSI_C_TIME_HS) scaled_period = scaled_ui_ns; else if (pDsiC[i].timeBase & DSI_C_TIME_ESC) scaled_period = scaled_escClk_ns; else scaled_period = 0; pDsiC[i].period = scaled_period; if (scaled_period != 0) { res = chalDsiTimingDivAndRoundUp(pDsiC, i, scaled_time_min, scaled_period); if (!res) return res; if (pDsiC[i].mode & DSI_C_HAS_MAX) { if ((pDsiC[i].counter * scaled_period) > scaled_time_max) { chal_dprintf(CDBG_ERRO, "[cHAL DSI] chal_dsi_set_timing: " "%s violates MAX D-PHY Spec allowed value\n\r", pDsiC[i].name); return FALSE; } } } } for (i = 0; i < DSI_C_MAX; i++) { if (pDsiC[i].timeBase == DSI_C_TIME_ESC2LPDT) { chal_dprintf(CDBG_ERRO, "[cHAL DSI] chal_dsi_set_timing: " "%14s %7d => LP clk %u[Mhz]\n\r", pDsiC[i].name, pDsiC[i].counter, escClk_MHz / (pDsiC[i].counter + pDsiC[i].counter_offs)); } else { chal_dprintf(CDBG_ERRO, "[cHAL DSI] chal_dsi_set_timing: " "%14s %7d => %u[ns]\n\r", pDsiC[i].name, pDsiC[i].counter, (pDsiC[i].counter + pDsiC[i].counter_offs) * pDsiC[i].period / 1000); } } chal_dprintf(CDBG_ERRO, "\r\n[cHAL DSI] chal_dsi_set_timing: " "HS_DATA_RATE %u[Mbps]\r\n", hsBitRate_Mbps); chal_dprintf(CDBG_ERRO, "[cHAL DSI] chal_dsi_set_timing: " "LP_DATA_RATE %u[kbps]\n\r", lp_clk_khz / 2); /* set ESC 2 LPDT ratio */ BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_PHYC, ESC_CLK_LPDT, pDsiC[DSI_C_ESC2LP_RATIO].counter); /* HS_DLT5 INIT */ BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_HS_DLT5, HS_INIT, pDsiC[DSI_C_HS_INIT].counter); /* HS_CLT2 ULPS WakeUp */ BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_HS_CLT2, HS_WUP, pDsiC[DSI_C_HS_WAKEUP].counter); /* LP_DLT7 ULPS WakeUp */ BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_LP_DLT7, LP_WUP, pDsiC[DSI_C_LP_WAKEUP].counter); /* HS CLK - HS_CLT0 reg */ BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_HS_CLT0, HS_CZERO, pDsiC[DSI_C_HS_CLK_ZERO].counter); BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_HS_CLT0, HS_CPRE, pDsiC[DSI_C_HS_CLK_PRE].counter); BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_HS_CLT0, HS_CPREP, pDsiC[DSI_C_HS_CLK_PREPARE].counter); /* HS CLK - HS_CLT1 reg */ BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_HS_CLT1, HS_CTRAIL, pDsiC[DSI_C_HS_CLK_TRAIL].counter); BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_HS_CLT1, HS_CPOST, pDsiC[DSI_C_HS_CLK_POST].counter); /* HS DATA HS_DLT3 REG */ BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_HS_DLT3, HS_EXIT, pDsiC[DSI_C_HS_EXIT].counter); BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_HS_DLT3, HS_ZERO, pDsiC[DSI_C_HS_ZERO].counter); BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_HS_DLT3, HS_PRE, pDsiC[DSI_C_HS_PRE].counter); /* HS DATA HS_DLT4 REG */ /* !!! HS_ANLAT, new in HERA/RHEA, for now init to 0 (DEF) */ BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_HS_DLT4, HS_ANLAT, 0); BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_HS_DLT4, HS_TRAIL, pDsiC[DSI_C_HS_TRAIL].counter); BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_HS_DLT4, HS_LPX, pDsiC[DSI_C_HS_LPX].counter); /* LP_DLT6 REG */ BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_LP_DLT6, TA_GET, pDsiC[DSI_C_LP_TA_GET].counter); BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_LP_DLT6, TA_SURE, pDsiC[DSI_C_LP_TA_SURE].counter); BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_LP_DLT6, TA_GO, pDsiC[DSI_C_LP_TA_GO].counter); BRCM_WRITE_REG_FIELD(pDev->baseAddr, DSI1_LP_DLT6, LPX, pDsiC[DSI_C_LPX].counter); return TRUE; }