This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DSI PLL Not Locking - OMAP3530

Other Parts Discussed in Thread: SYSCONFIG

I'm trying to get the DSI PLL to lock in U-Boot.  I have tried to follow the steps in section 15.6.7.7.2 (including those leading into it in tables 15-96 and 15-97), but am unsuccessful.

My external oscillator is 26MHz.  Printing out a few pertinent clock registers gives:

PRM_CLKSRC_CTRL  = 0x00000080
PRM_CLKSEL       = 0x00000003
CM_CLKSEL2_PLL   = 0x0001b00c
CM_CLKEN_PLL     = 0x00370037
CM_CLKSEL_DSS    = 0x00001009
CM_AUTOIDLE_DSS  = 0x00000000
CM_SLEEPDEP_DSS  = 0x00000000
CM_CLKSTCTRL_DSS = 0x00000000
CM_FCLKEN_DSS    = 0x00000007
CM_ICLKEN_DSS    = 0x00000001
CM_IDLEST_DSS    = 0x00000001

I believe this confirms the following (correct me if I'm wrong, please):

  1. SYS_CLK is at 13MHz
  2. DSS2_ALWON_FCLK is also 13MHz.
  3. Clocks are on to DSS to configure it.

Following Table 15-96 I reset DSI (which according to 15.5.5.1 also resets the DSI PLL), then wait for DSI to finish resetting (DSI_SYSSTATUS bit 0 goes to 1), then although Tabl 15-96 doesn't specify it, I wait for the DSI PLL to finish resetting (DSI_PLL_STATUS bit 0 goes to 1).  By the way, after failing to get the DSI PLL to reset, I had to look at the Linux driver code to discover that in order for the DSI PLL to finish resetting, DISPC_CONTROL register bit 27 had to be set!

So now I think I should be ready to configure the DSI PLL, which I do as follows:

  1. DSI_CLK_CTRL = 0x80000000;
  2. Wait until DSI_CLK_CTRL[29:28] becomes 0x2.
  3. DSI_PLL_CONFIGURATION1 = 0x02a8ab0d        - RegM4 = 5, RegM3 = 5, RegM = 171, RegN = 6, StopMode selected
  4. DSI_PLL_CONFIGURATION2 = 0x5600e               - Exactly as from table 15-98
  5. DSI_PLL_CONTROL = 0x00000000                       - Manual Mode
  6. DSI_PLL_GO = 0x1     -- Kick of the lock attempt
  7. Wait until DSI_PLL_GO bit 0 becomes 0  -- Lock state machine has finished
  8. Wait until locked: DSI_PLL_STATUS bit 1 becomes 1 -- but it never becomes 1

Things I have tried to coax it to lock, or at least confirm that it should lock:

  1. The Linux driver sets DSI_PLL_CONFIGURATION2 differently for locking, then switches to the above.  I have tried their value, which would be 0x0010200e.
  2. The DSI_PLL_CONFIGURATION2[4:1].DSI_PLL_FREQSEL value of 0x7 is supposed to be valid for PLL reference clock between 1.75MHz and 2.1MHz.  Using DSS2_ALWON_FLCK as 13MHz and RegN as 6, we have 13MHz/(6+1) = 1.857MHz, which is within tolerances.
  3. I have tried ranging RegN from 3 to 14 to see if the input clock was out of range, but that didn't succeed in getting it to lock.
  4. In Linux the above values for the configuration are known to work (have read them from /debug/omapdss/dsi and /debug/omapdss/clk).

Any idea what I might be missing or what I might have done wrong?

Any suggestions as to what to look at next?

Thanks

Chris

  • Deleted as it was only a partial submission.

  • It's now working.  I didn't do anything that I thought was particularly different, though I did change the register writes from direct constant assignments to reading, modifying necessary bits, and then writing back the results to the registers--at least for a few of the registers.  That may have changed some timing of the writes to the registers.  If that was enough to make it work, I'll probably never find out exactly what fixed it.

  • I am currently trying to do the same thing. I followed that same steps from the TRM, but u-boot hangs when I start resetting the DSI modules. Any chance you could post the code you have that makes it work? 

  • Here is my brave attempt:

    void clock_init()
    {
    unsigned int tmp;

    printf("dss: enable free running pixel clock\n");
    tmp = readl(DISPC_CONTROL);
    writel(tmp | 0x08000000, DISPC_CONTROL);

    printf("dss: enable clocks\n");
    // Set the divided DPLL value for DSS1.
    tmp = readl(CM_CLKSEL_DSS);
    writel(tmp | 0x9, CM_CLKSEL_DSS);
    //Disable autoidle mode.
    writel(0x0, CM_AUTOIDLE_DSS);
    //Domain sleep is disabled.
    writel(0x0, CM_SLEEPDEP_DSS);
    //Automatic transition between active and inactive is disabled
    writel(0x0, CM_CLKSTCTRL_DSS);
    //Enable DSS1, DSS2 and TV clock (DSS1_ALWON_FCLK, DSS2_ALWON_FCLK
    //and TV_CLK). TV_CLK is only need for correct Reset.
    writel(0x7, CM_FCLKEN_DSS);
    //Enable the subsystem interface clock(DSS_L3_ICLK and DSS_L4_ICLK).
    writel(0x1, CM_ICLKEN_DSS);

    printf("dss: reset dsi modules\n");
    //Reset IRQ status.
    writel(0x0, DSI_IRQSTATUS);
    //OCP and functional clock are maintained during wakeup, smart idle, and reset DSI.
    writel(0x312, DSI_SYSCONFIG);
    //Wait until RESET_DONE ≠ 0.
    while (!(readl(DSI_SYSSTATUS) & 0x1))
    printf("dss: wait for dsi reset\n");

    printf("dss: setup dsi dpll\n");
    //Turn on PLL and HSDIVIDER.
    tmp = readl(DSI_CLK_CTRL);
    writel(tmp | 0xf0000000, DSI_CLK_CTRL);
    //Wait until PLL_PWR_STATUS = 0x2.
    while (!(readl(DSI_CLK_CTRL) & 0x20000000))
    printf("dss: wait for pwr status\n");

    //Set pll configurations and enable PLLStopMode
    writel(0x0061180d, DSI_PLL_CONFIGURATION1);
    writel(0x0005600e, DSI_PLL_CONFIGURATION2);
    //Manual mode
    writel(0x0, DSI_PLL_CONTROL);
    //Request PLL locking sequence.
    writel(0x1, DSI_PLL_GO);
    //Read until DSI_PLL_GO = 0
    while (!(~readl(DSI_PLL_GO) & 0x1))
    printf("dss: wait for pll go\n");
    //PLL is locked.
    while (!(readl(DSI_PLL_STATUS) & 0x1))
    printf("dss: wait for pll lock\n");
    //Turn on PLL and HSDIVIDER
    writel(0x80244008, DSI_CLK_CTRL);

    //Switch to DSI PLL Clock Source.
    writel(0x3, DSS_CONTROL);
    }

  • *Bump*

    If the OP doesn't respond, perhaps someone else can take a look at the code I posted? I tried to follow the TRM, but like I said stuff just locks up when I run the code.