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
Hi Vasily
if you are trying to boot from nand one can try mfg tool
or other procedures
i.MX7: Flashing Images to NAND - Develop.phytec - PHYTEC Wiki
Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Igor!
Actually I am trying to access to NAND from QNX OS. So I want to run NAND driver after booting.
Hi Vasily
qnx is not supported by nxp, may be helpful to look at baremetal gpmi
examples in sdk (check zip on below link)
https://community.nxp.com/thread/432859
Best regards
igor