AnsweredAssumed Answered

GPMI driver for i.mx6sl

Question asked by Vasily Yanikeev on Jun 13, 2018
Latest reply on Jun 14, 2018 by igorpadykov

Hello!

 

I am trying to run QNX6.5 etfs driver for parallel NAND memory on my i.MX6SL based board. I ported BSP for Freescale i.MX6Q Sabre Lite Board (http://community.qnx.com/sf/wiki/do/viewPage/projects.bsp/wiki/FreescaleImx6QSabreLite) and it successfully started on my board. After that I took driver from BSP for NXP MCIMX7 Sabre Board (http://community.qnx.com/sf/wiki/do/viewPage/projects.bsp/wiki/NxpMcimx7sabre) and ported it for my platform. I added driver initialization in  QNX startup (added “fs-etfs-imx-micron –e” to .script section in build-file). So drivers stops execution while initialization gpmi module on waiting IMX_APBH_IRQ interrupt (45 - Logical OR of APBH DMA channels 0-3 completion and error interrupts). What am I doing wrong?

 

So gpmi initialization sequence is follows.

 

1) Clock enable in DCD section:

 


DCD_ENTRY(1, 0x020c4068, 0xffffffff)
DCD_ENTRY(2, 0x020c406c, 0xffffffff)
DCD_ENTRY(3, 0x020c4070, 0xffffffff)
DCD_ENTRY(4, 0x020c4074, 0xffffffff)
DCD_ENTRY(5, 0x020c4078, 0xffffffff)
DCD_ENTRY(6, 0x020c407c, 0xffffffff)
DCD_ENTRY(7, 0x020c4080, 0xffffffff)

 

 

2) Setup pin muxing in startup:

 

            out32(MX6X_CCM_BASE + MX6X_CCM_CCGR4, 0xFFFFF300 );
 
            pinmux_set_swmux(SWMUX_NANDF_CLE, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_CLE, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_NANDF_ALE, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_ALE, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_NANDF_WP_B, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_WP_B, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_NANDF_RB0, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_RB0, PAD_CFG_1);
 
            pinmux_set_swmux(SWMUX_NANDF_CS0, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_CS0, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_NANDF_CS1, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_CS1, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_NANDF_CS2, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_CS2, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_NANDF_CS3, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_CS3, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_SD4_CMD, MUX_CTL_MUX_MODE_ALT1);
            pinmux_set_padcfg(SWPAD_SD4_CMD, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_SD4_CLK, MUX_CTL_MUX_MODE_ALT1);
            pinmux_set_padcfg(SWPAD_SD4_CLK, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_NANDF_D0, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_D0, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_NANDF_D1, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_D1, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_NANDF_D2, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_D2, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_NANDF_D3, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_D3, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_NANDF_D4, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_D4, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_NANDF_D5, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_D5, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_NANDF_D6, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_D6, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_NANDF_D7, MUX_CTL_MUX_MODE_ALT0);
            pinmux_set_padcfg(SWPAD_NANDF_D7, PAD_CFG_0);
 
            pinmux_set_swmux(SWMUX_SD4_DAT0, MUX_CTL_MUX_MODE_ALT2);
            pinmux_set_padcfg(SWPAD_SD4_DAT0, PAD_CFG_2);

 

 

3) GPMI initialization in driver. Briefly:

...
// APBH, BCH and GPMI init
if (nand_init(cio) != 0) {
        dev->log(_SLOG_CRITICAL, "nand_init failed : %s", strerror(errno));
        // We will not return
    }
 
    cio->apbhirq = IMX_APBH_IRQ;
    cio->bchirq = IMX_BCH_IRQ;
 
    // Start-up a thread that is dedicated to interrupt processing
    cio->apbhirq_expected = 0;
    pthread_mutex_init(&cio->apbhmutex, NULL);
    pthread_cond_init(&cio->apbhcond, NULL);
    pthread_create(NULL, NULL, apbhint_thread, cio);
    // Start-up a thread that is dedicated to interrupt processing
    cio->bchirq_expected = 0;
    pthread_mutex_init(&cio->bchmutex, NULL);
    pthread_cond_init(&cio->bchcond, NULL);
    pthread_create(NULL, NULL, bchint_thread, cio);
 
...
    if (nand_wait_busy(cio, MAX_RESET_USEC, 0) != 0) {
        dev->log(_SLOG_CRITICAL, "Timeout on RESET");
    }
 
    // Create reset device and reset the part - for some devices it must be first command
    create_reset_descriptor(reset_ptr);
    status = run_dma((apbh_dma_t*)reset_ptr, cio, NAND_DMA_GPMI_TRANS, (uint32_t)virtual_to_physical_addr(reset_ptr));
    if (status != NAND_EOK) {
        dev->log(_SLOG_CRITICAL, "DMA operation fail");
    }
    if (nand_wait_busy(cio, MAX_RESET_USEC, 0) != 0) {
        dev->log(_SLOG_CRITICAL, "Timeout on RESET");
    }
    delay(2);
    // Create read status chain and read status register from device
    create_readStatus2_descriptor(read_status_ptr, mem_stat_ptr, 1);
                status = run_dma((apbh_dma_t*)read_status_ptr, cio, NAND_DMA_GPMI_TRANS, (uint32_t)virtual_to_physical_addr(read_status_ptr));     //<<<<<<<<<<<<<<<<< Stops here <<<<<<<<<<<<<<<<<<<
...

 

 

Regards,

Vasily

Outcomes