//*****************************************************************************
//
// 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 );
}
Exemplo n.º 2
0
/*
 *
 * 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;
}