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.

Linux/AM3358: U-boot crashes on LCD clock enable

Expert 2730 points

Part Number: AM3358

Tool/software: Linux

I'm using u-boot 2015.7 from SDK 2.00.00, because I can't get newer u-boots t launch with our custom board (which is based on am335x-evm). I'm trying to get the boot image to work and I have been following the guides from https://e2e.ti.com/support/arm/sitara_arm/f/791/p/217383/849350. I have copied the lcd drivers to my u-boot and I can compile everything, but when I try to initialize the LCD the processor/u-boot hangs on 

RasterClocksEnable(SOC_LCDC_0_REGS);

void RasterClocksEnable(unsigned int baseAddr)
{
    HWREG(baseAddr + LCDC_CLKC_ENABLE) =  (LCDC_CLKC_ENABLE_CORE |
                                           LCDC_CLKC_ENABLE_DMA  |
                                           LCDC_CLKC_ENABLE_LIDD);
}


data abort
pc : [<8ff25896>]          lr : [<8ff2576f>]
reloc pc : [<80818896>]    lr : [<8081876f>]
sp : 8eeecdf8  ip : 000009c0     fp : 00000001
r10: 00000000  r9 : 8eeeced8     r8 : 4030cdcc
r7 : 8ff43004  r6 : 8ff9ce0c     r5 : 00000000  r4 : 4830e000
r3 : 00000000  r2 : 44e108e8     r1 : 00000000  r0 : 4830e000
Flags: nzcv  IRQs off  FIQs on  Mode SVC_32

The LCD works when the kernel boots, but I need to get a logo to be shown as soon as possible. I'm initializing the display from board_late_init(void). I have also tried to initialize the display else where but always with the same result. What is causing the crash?

JHi

  • Hello JHi,

    Please, try this guide instead.

    Best regards,
    Kemal

  • The problem is that this is for SDK 03.02.00..05 and I have to use u-boot from SDK 2.0 which is completely different. As I said I can't get the u-boot from SDK3 or 4 to boot.
  • Ok I saw that the fb driver is also included in SDK 2. The next problem is that the guide is for mmc, how can I read the image from NAND or compiled in to u.boot?
  • Pelase, test this driver, which has some improvements implemented.

  • I have already tried it and that gave me the crash as explained on my first post.
  • I got the fb drivers to "work". It's showing something on the display but the timings are completely wrong and when it comes to Kernel it loses sync (tilcdc 4830e000.lcdc: tilcdc_crtc_irq(0x00000004): Sync lost).

    Could some one please help me to convert these dts values for the fb driver in u-boot?

    panel {
            	compatible = "ti,tilcdc,panel";
            	pinctrl-names = "default";
    	        pinctrl-0 = <&lcd_pins_default>;
            
            	status = "okay";
    		panel-info {
    		    ac-bias           = <255>;
    		    ac-bias-intrpt    = <0>;
    		    dma-burst-sz      = <16>;
    		    bpp               = <16>;
    		    fdd               = <0x80>;
    		    sync-edge         = <0>;
    		    sync-ctrl         = <1>;
    		    raster-order      = <0>;
    		    fifo-th           = <0>;
    		};
    		display-timings {
    		    	800x480 {
    				hactive         = <800>;
    				vactive         = <480>;
    				hback-porch     = <40>;
    				hfront-porch    = <40>;
    				hsync-len       = <48>;
    				vback-porch     = <30>;
    				vfront-porch    = <13>;
    				vsync-len       = <3>;
    				clock-frequency = <30000000>;
    				hsync-active    = <0>;
    				vsync-active    = <0>;
    		    	};
    		};
    	};

    What I have so far, which doesn't really work, are:

    struct am335x_lcdpanel pnltmp;
    
            pnltmp.hactive = 800;
            pnltmp.vactive = 480;
            pnltmp.bpp = 16;
            pnltmp.hfp = 40;
            pnltmp.hbp = 40;
            pnltmp.hsw = 48;
            pnltmp.vfp = 13;
            pnltmp.vbp = 30;
            pnltmp.vsw = 3;
            pnltmp.pxl_clk_div = 6;
            pnltmp.pol = HSYNC_INVERT | VSYNC_INVERT;
            pnltmp.pup_delay = 1;
            pnltmp.pon_delay = 1;
            panel_info.vl_rot = 0;

    Or do I have to change the fb driver also?

  • Please, see this link about FIFO underflow and sync lost issue.

  • Doesn't help at least as long as the timings are incorrect in u-boot.
  • I got the u-boot image working with fb driver I had to add the pll initialization for the display. The next problem is that tilcdc doesn't support display initialization bypass. Means when booting sequence comes to Kernel it will initialize the display again and the boot image will be lost. The kernel also supports boot image but it can only handle 224 colors which isn't much. The systemd scripts also doesn't start fast enough so there will be a long time before you get something on display. I just can't understand why TI doesn't properly support boot image because in every serious application where there is display, you need to show something to the customer when it's booting.

  • hi jhi, i am trying to display a logo in u-boot.
    i tried "processors.wiki.ti.com/.../Processor_SDK_Linux_U-Boot_Splash_Screen" patch wtih processor-sdk-04.01, i got 40% screen black colour remaining white.please let me know how can i get it work
    please check this post for more details (e2e.ti.com/.../2507496)

  • I'm using u-boot 2015.7 from SDK 2.00.00, so I don't know if the applies to the newer one.  So here is what I did:

    Added to arch/arm/cpu/armv7/am33xx/clock_am33xx.c 
    void enable_basic_clocks(void)
    ...
    &cmper->lcdclkctrl,
    &cmper->lcdcclkstctrl
    
    
    board.c
    
    #if defined(CONFIG_LCD) && defined(CONFIG_AM335X_LCD) && \
                    !defined(CONFIG_SPL_BUILD)
    void lcdbacklight(int on)
    {
            gpio_request(GPIO_BACKLIGHT_EN, "backlight_en");
    	gpio_request(GPIO_BACKLIGHT_ON, "backlight_on");
            if (on)
    	{
                    gpio_direction_output(GPIO_BACKLIGHT_EN, 1);
                    gpio_direction_output(GPIO_BACKLIGHT_ON, 1);
    	}
            else
    	{
                    gpio_direction_output(GPIO_BACKLIGHT_EN, 0);
    		gpio_direction_output(GPIO_BACKLIGHT_ON, 0);
    	}
    }
    
    int  load_lcdtiming(struct am335x_lcdpanel *panel)
    {
            struct am335x_lcdpanel pnltmp;
    
            pnltmp.hactive = 800;
            pnltmp.vactive = 480;
            pnltmp.bpp = 16;
            pnltmp.hfp = 40;
            pnltmp.hbp = 40;
            pnltmp.hsw = 48;
            pnltmp.vfp = 13;
            pnltmp.vbp = 30;
            pnltmp.vsw = 3;
            pnltmp.pxl_clk_div = 2;
            pnltmp.pol = HSYNC_INVERT | VSYNC_INVERT | HSVS_CONTROL;
            pnltmp.pup_delay = 0;
            pnltmp.pon_delay = 0;
            panel_info.vl_rot = 0;
    
            memcpy((void *)panel, (void *)&pnltmp, sizeof(struct am335x_lcdpanel));
    
            return 0;
    }
    
    void lcdpower(int on)
    {
            lcd_enable();
    }
    
    vidinfo_t       panel_info = {
                    .vl_col = 800,
                    .vl_row = 480,
                    .vl_bpix = 4,
                    .priv = 0
    };
    
    void lcd_ctrl_init(void *lcdbase)
    {
            struct am335x_lcdpanel lcd_panel;
    
            memset(&lcd_panel, 0, sizeof(struct am335x_lcdpanel));
            if (load_lcdtiming(&lcd_panel) != 0)
                    return;
    
            lcd_panel.panel_power_ctrl = &lcdpower;
    
            if (am335xfb_init(&lcd_panel) != 0)
                    printf("ERROR: failed to initialize video!");
    
            /* Modify panel into to real resolution */
            panel_info.vl_col = lcd_panel.hactive;
            panel_info.vl_row = lcd_panel.vactive;
    
    //      lcd_set_flush_dcache(1);
    }
    
    void lcd_enable(void)
    {
            lcdbacklight(1);
    }
    #endif
    mux.c
    
    static struct module_pin_mux led_pin_mux[] = {
            {OFFSET(gpmc_a10), MODE(7) | PULLUP_EN | RXACTIVE},         /* GPIO1_26 */
            {OFFSET(gpmc_a11), MODE(7) | PULLUP_EN | RXACTIVE},         /* GPIO1_27 */
            {-1},
    };
    
    ifdef CONFIG_AM335X_LCD
    static struct module_pin_mux lcd_pin_mux[] = {
            {OFFSET(lcd_data0), (MODE(0) | PULLUDDIS)},     /* LCD-Data(0) */
            {OFFSET(lcd_data1), (MODE(0) | PULLUDDIS)},     /* LCD-Data(1) */
            {OFFSET(lcd_data2), (MODE(0) | PULLUDDIS)},     /* LCD-Data(2) */
            {OFFSET(lcd_data3), (MODE(0) | PULLUDDIS)},     /* LCD-Data(3) */
            {OFFSET(lcd_data4), (MODE(0) | PULLUDDIS)},     /* LCD-Data(4) */
            {OFFSET(lcd_data5), (MODE(0) | PULLUDDIS)},     /* LCD-Data(5) */
            {OFFSET(lcd_data6), (MODE(0) | PULLUDDIS)},     /* LCD-Data(6) */
            {OFFSET(lcd_data7), (MODE(0) | PULLUDDIS)},     /* LCD-Data(7) */
            {OFFSET(lcd_data8), (MODE(0) | PULLUDDIS)},     /* LCD-Data(8) */
            {OFFSET(lcd_data9), (MODE(0) | PULLUDDIS)},     /* LCD-Data(9) */
            {OFFSET(lcd_data10), (MODE(0) | PULLUDDIS)},    /* LCD-Data(10) */
            {OFFSET(lcd_data11), (MODE(0) | PULLUDDIS)},    /* LCD-Data(11) */
            {OFFSET(lcd_data12), (MODE(0) | PULLUDDIS)},    /* LCD-Data(12) */
            {OFFSET(lcd_data13), (MODE(0) | PULLUDDIS)},    /* LCD-Data(13) */
            {OFFSET(lcd_data14), (MODE(0) | PULLUDDIS)},    /* LCD-Data(14) */
            {OFFSET(lcd_data15), (MODE(0) | PULLUDDIS)},    /* LCD-Data(15) */
            {OFFSET(lcd_vsync), (MODE(0) | PULLUDDIS)},     /* LCD-VSync */
            {OFFSET(lcd_hsync), (MODE(0) | PULLUDDIS)},     /* LCD-HSync */
            {OFFSET(lcd_ac_bias_en), (MODE(0) | PULLUDDIS)},/* LCD-DE */
            {OFFSET(lcd_pclk), (MODE(0) | PULLUDDIS)},      /* LCD-CLK */
    
            /* backlight */
            {OFFSET(xdma_event_intr0), (MODE(7) | PULLUDDIS)}, /* xdma_event_intr0_gpio0_19 */
    	{OFFSET(spi0_sclk), (MODE(7) | PULLUDDIS)}, 	   /* spi0_sclk_gpio0_2 */
    
            {-1},
    };
    #endif
    
    void enable_board_pin_mux(struct am335x_baseboard_id *header)
    {
    ....
            configure_module_pin_mux(led_pin_mux);
    #ifdef CONFIG_AM335X_LCD
            configure_module_pin_mux(lcd_pin_mux);
    #endif
    }
    configs/am335x_evm_defconfig
    
    CONFIG_SYS_EXTRA_OPTIONS="NAND" -> CONFIG_SYS_EXTRA_OPTIONS="NAND,SPLASH"
    drivers/video/am335x-fb.c
    
    static void disp_pll_clocks(void)
    {
        u32 clkmode, clksel, div_m2;
    
        clkmode = readl(CM_CLKMODE_DPLL_DISP);
        clksel = readl(CM_CLKSEL_DPLL_DISP);
       // div_m2 = readl(CM_DIV_M2_DPLL_DISP);
    
        /* Set the PLL to bypass Mode */
        clkmode = (clkmode & 0xfffffff8) | 0x00000004;
        writel(clkmode, CM_CLKMODE_DPLL_DISP);
        while ((readl(CM_IDLEST_DPLL_DISP) & 0x00000100) != 0x00000100);
    
        clksel = clksel & (~0x7ffff);
        clksel = clksel | ((0x5 << 0x8) | 0x1);
        writel(clksel, CM_CLKSEL_DPLL_DISP);
    
        /*div_m2 = div_m2 & 0xFFFFFFE0;
        div_m2 = div_m2 | DISPPLL_M2;
        writel(div_m2, CM_DIV_M2_DPLL_DISP);*/
    
        clkmode = (clkmode & 0xfffffff8) | 0x7;
        writel(clkmode, CM_CLKMODE_DPLL_DISP);
        while ((readl(CM_IDLEST_DPLL_DISP) & 0x00000001) != 0x1);
    }
    
    int am335xfb_init(struct am335x_lcdpanel *panel)
     {
    	disp_pll_clocks();
    ....
    }
    


    include/configs/am335x_evm.h

    /* Splash scrren support */ #ifdef CONFIG_SPLASH #define CONFIG_AM335X_LCD #define CONFIG_LCD #define CONFIG_LCD_NOSTDOUT #define CONFIG_SYS_WHITE_ON_BLACK #define LCD_BPP LCD_COLOR16

    You have to change the values in display_pll_clocks to fit your display timings. I just checked that the values in these registers were in userspace and put the same values. And of course lcd timings has to be changed accordingly.

    After that you can test the image, when you get to uboot and load the wanted image over tftp, with bmp display command.