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.

OMAP-L138: uPP throws Channel Q underrun/overflow interrupt when DSP is clocked at 456 MHz

Part Number: OMAP-L138

Hi,

We have an OMAP-L138 processor, whose DSP has a uPP interface with an FPGA.

So far, we have been working at a clock rate of 300 MHz (which makes the uPP module and transmit clocks 150 MHz, according to the Technical Reference Guide and the Clock Calculator Excel sheet), and our interface with FPGA was working properly.

Recently, we have switched to a new board that supports the 456-MHz setting, so we changed the PLL controllers such that the DSP is now running at 456 MHz (which makes the module clock 228 MHz (fixed ratio, cannot be changed), but we maintain the transmit clock at 150 MHz). In this setting, when sending data from the DSP to FPGA, uPP occasionally throws a "Channel Q underrun/overflow interrupt", which would never occur at 300 MHz.

Our uPP clock divider value (in the UPICR register) is originally:

CLKDIVA = 3; // which should divide the transmit clock by (2 * (3 + 1))
CLKDIVB = 2; // likewise, by (2* (2 + 1))

But I don't know how to reduce the transmit clock back to 150 MHz in the 456-MHz setting. (I tried raising the clock dividers A and B up to 10, but that did not make a difference since, obviously, they do not affect the module clock).

What do you suggest?

Thanks in advance,

Silacko

  • Hi,

    I've notified the team. They will post their feedback directly here.

    Best Regards,
    Yordan
  • Silacko

    Can you check if SYSCFG.CFGCHIP3 bit 6 or 4 clocking scheme help back down the clock. (SPRUH77)

    You can also use the clocking tool to visualize the clocking scheme and options 

    Regards

    Mukul 

  • My PLL configuration is as follows:

    Chip configuration...
    CHGCHIP[0] -> 0x00000100
    CHGCHIP[1] -> 0x00000000
    CHGCHIP[2] -> 0x000349F2
    CHGCHIP[3] -> 0x0000FE10
    CHGCHIP[4] -> 0x0000FF00
    Pll controller 0...
    PLLCTL -> 0x00000049
    OCSEL -> 0x00000017
    PLLM -> 0x00000012
    PREDIV -> 0x00008000
    POSTDIV -> 0x00008000
    OSCDIV -> 0x00008000
    CKEN -> 0x00000003
    PLLDIV1 -> 0x00008000
    PLLDIV2 -> 0x00008001
    PLLDIV3 -> 0x00008003
    PLLDIV4 -> 0x00008003
    PLLDIV5 -> 0x00008002
    PLLDIV6 -> 0x00008000
    PLLDIV7 -> 0x00008009
    Pll controller 1...
    PLLCTL -> 0x00000049
    OCSEL -> 0x00000017
    PLLM -> 0x00000012
    POSTDIV -> 0x00008000
    PLLDIV1 -> 0x00008000
    PLLDIV2 -> 0x00008001
    PLLDIV3 -> 0x00008003

    This suggests ASYNC3_CLKSRC = 1 and UPP_TX_CLKSRC = 0.

    I already used the Excel datasheet. According to my configuration, the uPP clocks look like:

    My question is: how could raising the module clock to 228 MHz possibly lead to overflow/underrun errors? And how can I avoid this? I know I can't lower the PLL0_SYSCLK2 back to 150 MHz without reverting the DSP clock to 300 MHz.

    What would you suggest?
    Thanks again,
    Silacko

  • Hi Silacko

    Thanks for clarifying that you were already using PLL clocking spreadsheet ( I missed that).

    Have you tried

    CFGCHIP3.UPP_TX_CLKSRC = 1 and CFGCHIP3.ASYC3_CLKSRC= 0 instead?

    I think as long as the IO clocks for uPP are as per the datasheet timing requirements , it should be ok. 

    I do not know why you are choosing CFGCHIP3.ASYNC3 clock source to be PLL1_SYSCLK2 ? Was this the configuration for your previous 300 MHz setup too?

    ASYNC3 at 150 (instead of 228) will impact the following peripherals :ECAPs, UART1/2, Timer64P2/3, eHRPWMs, McBSPs, McASP0, SPI1

    (details in the clocking chapter in TRM)

    I do not know if these periphs are having any indirect impact on your system to cause overflow/underrun errors?

    I am assuming you have probed the IO clocks to ensure you are seeing the clock speeds to be as expected (in line with datsheet IO timings) and what you had in your 300 MHz setup?

    228 MHz internal module clock to UPP module should be ok , but IOs frequency (CH_CLKn) should be max as per datasheet timing. 

    Regards

    Mukul 

  • Clearing ASYNC_CLKSRC bit feeds the 228-MHz clock into the UART clock generator and blocks us from getting standard output from the serial port. That's why I set it so that it remains at 150MHz.

  • Hi Silacko
    Ok thanks for clarifying why you need PLL1 clock .
    Is it still possible for you as a test to see if changing ASYNC CLKSRC to 228 MHz makes your uPP underflow/overrun issue go away?

    Regards
    Mukul
  • Hi Mukul, thanks for your reply.

    I tried testing that, but there are two problems:

    • After clearing the ASYNC_CLKSRC bit, booting up Linux automatically forces the bit to set. I see the standard output gets corrupted for a moment (verifying the bit is cleared), but once the kernel starts booting up, the prints become normal and I see the value of the bit as 1.
    • I also tried testing this on DSP (baremetal) without booting ARM, but then, I can't confirm what happens because I can't print anything properly.

    Regards,
    Silacko

  • I managed to get UART working with the 228-MHz clock setting by adjusting UART2's DLL register and tested this on baremetal DSP. I can now confirm that uPP does not throw any underrun/overflow errors and works properly with both Tx and module clocks set to 228 MHz.

    The problem is, I can't use this setting on ARM because Linux overrides my changes in the PLL and UART registers once it boots up. I tried modifying the kernel configuration, more specifically, removing CONFIG_DAVINCI_RESET_CLOCKS  and CONFIG_CPU_FREQ; however, the registers returned to their original forms every time.

    What should I do stop the kernel from overriding my settings?

    Thanks again,
    Silacko

  • Hi Silacko
    Thanks for the update. Good to hear that the uPP issue seems to be under control.

    I am not a Linux expert - so may not be able to give you further guidance on the override issue.
    Do you mind opening another thread for that specific problem? I will point the this and the new thread to my Linux colleagues.

    Regards
    Mukul
  • Silacko
    I am reassigning this post to one of my software colleagues. Let us try to resolve the pending issues on linux/kernel side on this thread.

    Regards
    Mukul
  • Hi, Silacko,

    I am checking internally how it can be done. I'll post back as soon as I hear back.

    Rex
  • Thanks, looking forward to your answer.
    Should I still open a new thread?
    Regards,
    Silacko

  • Hi Rex,
    Is there any progress? Shall I create a new thread, or are we continue to use this one?
    Regards,
    Silacko
  • I haven't heard back yet. Let me ping again. Let's stay on this thread.

    Rex
  • Hi, Silacko,

    Sorry it takes a while to get the info, "Kernel switches async3 parent in da850_async3_set_parent() which affects the clock rate of number of modules including UART2."

    Rex
  • Hi, Rex,

    Thanks for your reply. I couldn't respond sooner because I was on holidays.

    Unfortunately, on my version of Linux kernel, there doesn't seem to be a "da850_async3_set_parent()" function. My kernel version is 3.2 in case it is needed.

    The closest piece of code I could get is in da850.c:

    /* clock.h */
    struct clk { struct list_head node; struct module *owner; const char *name; unsigned long rate; unsigned long maxrate; /* H/W supported max rate */ u8 usecount; u8 lpsc; u8 gpsc; u32 flags; struct clk *parent; struct list_head children; /* list of children */ struct list_head childnode; /* parent's child list node */ struct pll_data *pll_data; u32 div_reg; unsigned long (*recalc) (struct clk *); int (*set_rate) (struct clk *clk, unsigned long rate); int (*round_rate) (struct clk *clk, unsigned long rate); };
    /* da850.c */ static struct clk uart0_clk = { .name = "uart0", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC0_UART0, }; static struct clk uart1_clk = { .name = "uart1", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_UART1, .gpsc = 1, .flags = DA850_CLK_ASYNC3, }; static struct clk uart2_clk = { .name = "uart2", .parent = &pll0_sysclk2, .lpsc = DA8XX_LPSC1_UART2, .gpsc = 1, .flags = DA850_CLK_ASYNC3, };

    I suppose I need to change the uart2_clk variable somehow, but I'm not sure how. Could you please elaborate on that?

    Thanks in advance,

    Silacko

  • Hi, Silaco,

    Kernel version 3.2 is no longer supported. As the instruction I got is that this set_parent function switches async3 parent, hence affects the clock rate. It seems to me that you should check what does the set_parent function do and not to switch. With Kernel 3.2, you may want to find what was used before and stay with it.

    Rex