Other Parts Discussed in Thread: SK-AM62-LP
Tool/software:
Dear TI team,
Kindly support on the following topic:
1) GPMC Nand speed configurations from U-Boot device tree:
Context:
We are trying to optimize DFU flashing time in U-Boot, and we are using SDKLA v8.6, and GPMC Nand write speed in U-Boot is not as excepted (very low).
Expected behavior:
We expected to achieve at least minimum 8 MB/s (Miga byte / second) for GPMC Nand chip write speed in U-Boot.
Actual behavior:
The Nand chip write speed in U-Boot during copying data from DDR RAM to GPMC Nand is 0.4MB/s (Miga byte / second).
Questions:
1.a) How to configure U-Boot device tree to set max Nand chip read/write speed?
1.b) How to apply our application NAND/GPMC configuration (shown below) in U-Boot device tree? Check footnote [1] for our failed trial to do so.
/* * Copyright (C) 2021 Texas Instruments Incorporated * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Auto generated file */ #include "ti_drivers_config.h" #include <drivers/device_manager/sciclient.h> /* * GPMC */ /* Regions restricted for DMA. We should use CPU memcpy in these cases */ static GPMC_AddrRegion gGpmcDmaRestrictRegions[] = { { .regionStartAddr = CSL_WKUP_R5FSS0_ATCM_BASE, .regionSize = CSL_WKUP_R5FSS0_ATCM_SIZE, }, { .regionStartAddr = CSL_WKUP_R5FSS0_BTCM_BASE, .regionSize = CSL_WKUP_R5FSS0_BTCM_SIZE, }, { .regionStartAddr = CSL_MCU_M4FSS0_IRAM_BASE, .regionSize = CSL_MCU_M4FSS0_IRAM_SIZE, }, { .regionStartAddr = CSL_MCU_M4FSS0_DRAM_BASE, .regionSize = CSL_MCU_M4FSS0_DRAM_SIZE, }, { .regionStartAddr = 0xFFFFFFFFU, .regionSize = 0U, } }; /* GPMC attributes */ static GPMC_HwAttrs gGpmcAttrs[CONFIG_GPMC_NUM_INSTANCES] = { { .gpmcBaseAddr = CSL_GPMC0_CFG_BASE, .dataBaseAddr = CSL_GPMC0_DATA_BASE, .elmBaseAddr = CSL_ELM0_BASE, .inputClkFreq = 133333333U, .intrNum = 103U, .intrPriority = 4U, .chipSelBaseAddr = 0x50000000U, .chipSelAddrSize = GPMC_CS_MASK_ADDR_SIZE_16MB, .clkDivider = CSL_GPMC_CONFIG1_GPMCFCLKDIVIDER_DIVBY1, .waitPinNum = CSL_GPMC_CONFIG1_WAITPINSELECT_W0, .addrDataMux = CSL_GPMC_CONFIG1_MUXADDDATA_NONMUX, .timeLatency = CSL_GPMC_CONFIG1_TIMEPARAGRANULARITY_X1, .waitPinPol = CSL_GPMC_CONFIG_WAIT0PINPOLARITY_W0ACTIVEL, .timingParams = { .csOnTime = 0U, .csRdOffTime = 5U, .csWrOffTime = 6U, .advOnTime = 0U, .advRdOffTime = 4U, .advWrOffTime = 4U, .advAadMuxOnTime = 0U, .advAadMuxRdOffTime = 0U, .advAadMuxWrOffTime = 0U, .weOnTtime = 0U, .weOffTime = 3U, .oeOnTime = 1U, .oeOffTime = 4U, .oeAadMuxOnTime = 0U, .oeAadMuxOffTime = 0U, .pageBurstAccess = 0U, .rdAccessTime = 5U, .wrAcessTime = 6U, .rdCycleTime = 5U, .wrCycleTime = 5U, .wrDataOnMuxBusTime = 0U, .cycle2CycleDelay = 0U, .busTurnAroundTime = 0U, .cycleDelaySameChipSel = CSL_GPMC_CONFIG6_CYCLE2CYCLESAMECSEN_NOC2CDELAY, .cycleDelayDiffChipSel = CSL_GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN_NOC2CDELAY, }, .eccAlgo = GPMC_NAND_ECC_ALGO_BCH_8BIT, .readType = CSL_GPMC_CONFIG1_READTYPE_RDASYNC, .csExDelay = CSL_GPMC_CONFIG2_CSEXTRADELAY_NOTDELAYED, .accessType = CSL_GPMC_CONFIG1_READMULTIPLE_RDSINGLE, .optimisedAccess = CSL_GPMC_PREFETCH_CONFIG1_ENABLEOPTIMIZEDACCESS_OPTDISABLED, .dmaRestrictedRegions = gGpmcDmaRestrictRegions, }, }; /* GPMC objects - initialized by the driver */ static GPMC_Object gGpmcObjects[CONFIG_GPMC_NUM_INSTANCES]; /* GPMC driver configuration */ GPMC_Config gGpmcConfig[CONFIG_GPMC_NUM_INSTANCES] = { { &gGpmcAttrs[CONFIG_GPMC0], &gGpmcObjects[CONFIG_GPMC0], }, }; uint32_t gGpmcConfigNum = CONFIG_GPMC_NUM_INSTANCES; #include <drivers/gpmc/v0/dma/gpmc_dma.h> #include <drivers/gpmc/v0/dma/udma/gpmc_dma_udma.h> #include <drivers/udma.h> /* * GPMC UDMA Blockcopy Parameters */ #define GPMC_UDMA_BLK_COPY_CH_RING_ELEM_CNT (1U) #define GPMC_UDMA_BLK_COPY_CH_RING_MEM_SIZE (((GPMC_UDMA_BLK_COPY_CH_RING_ELEM_CNT * 8U) + UDMA_CACHELINE_ALIGNMENT) & ~(UDMA_CACHELINE_ALIGNMENT - 1U)) #define GPMC_UDMA_BLK_COPY_CH_TRPD_MEM_SIZE (UDMA_GET_TRPD_TR15_SIZE(1U)) #define GPMC_UDMA_NUM_BLKCOPY_CH (1U) /* GPMC UDMA Blockcopy Channel Objects */ static Udma_ChObject gGpmcUdmaBlkCopyChObj[GPMC_UDMA_NUM_BLKCOPY_CH]; /* GPMC UDMA Blockcopy Channel Ring Mem */ static uint8_t gGpmcUdmaBlkCopyCh0RingMem[GPMC_UDMA_BLK_COPY_CH_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT))); /* GPMC UDMA Blockcopy Channel TRPD Mem */ static uint8_t gGpmcUdmaBlkCopyCh0TrpdMem[GPMC_UDMA_BLK_COPY_CH_TRPD_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT))); GpmcDma_UdmaArgs gGpmcUdma0Args = { .drvHandle = &gUdmaDrvObj[CONFIG_UDMA0], .chHandle = &gGpmcUdmaBlkCopyChObj[0], .trpdMem = &gGpmcUdmaBlkCopyCh0TrpdMem, .trpdMemSize = GPMC_UDMA_BLK_COPY_CH_TRPD_MEM_SIZE, .ringMem = &gGpmcUdmaBlkCopyCh0RingMem, .ringMemSize = GPMC_UDMA_BLK_COPY_CH_RING_MEM_SIZE, .ringElemCount = GPMC_UDMA_BLK_COPY_CH_RING_ELEM_CNT, .localEventID = 26, }; GPMC_DmaConfig gGpmcDmaConfig[CONFIG_GPMC_NUM_DMA_INSTANCES] = { { .fxns = &gGpmcDmaUdmaFxns, .gpmcDmaArgs = (void *)&gGpmcUdma0Args, } }; uint32_t gGpmcDmaConfigNum = CONFIG_GPMC_NUM_DMA_INSTANCES; /* * UDMA */ /* UDMA driver instance object */ Udma_DrvObject gUdmaDrvObj[CONFIG_UDMA_NUM_INSTANCES]; /* UDMA driver instance init params */ static Udma_InitPrms gUdmaInitPrms[CONFIG_UDMA_NUM_INSTANCES] = { { .instId = UDMA_INST_ID_BCDMA_0, .skipGlobalEventReg = TRUE, .virtToPhyFxn = Udma_defaultVirtToPhyFxn, .phyToVirtFxn = Udma_defaultPhyToVirtFxn, }, }; /* * I2C */ /* I2C atrributes */ static I2C_HwAttrs gI2cHwAttrs[CONFIG_I2C_NUM_INSTANCES] = { { .baseAddr = CSL_I2C0_CFG_BASE, .intNum = 193, .eventId = 0, .funcClk = 96000000U, .enableIntr = 0, .ownTargetAddr = { 0x1C, 0x1C, 0x1C, 0x1C, }, }, }; /* I2C objects - initialized by the driver */ static I2C_Object gI2cObjects[CONFIG_I2C_NUM_INSTANCES]; /* I2C driver configuration */ I2C_Config gI2cConfig[CONFIG_I2C_NUM_INSTANCES] = { { .object = &gI2cObjects[CONFIG_I2C0], .hwAttrs = &gI2cHwAttrs[CONFIG_I2C0] }, }; uint32_t gI2cConfigNum = CONFIG_I2C_NUM_INSTANCES; /* * UART */ /* UART atrributes */ static UART_Attrs gUartAttrs[CONFIG_UART_NUM_INSTANCES] = { { .baseAddr = CSL_WKUP_UART0_BASE, .inputClkFreq = 96000000U, }, }; /* UART objects - initialized by the driver */ static UART_Object gUartObjects[CONFIG_UART_NUM_INSTANCES]; /* UART driver configuration */ UART_Config gUartConfig[CONFIG_UART_NUM_INSTANCES] = { { &gUartAttrs[CONFIG_UART0], &gUartObjects[CONFIG_UART0], }, }; uint32_t gUartConfigNum = CONFIG_UART_NUM_INSTANCES; #include <drivers/uart/v0/dma/uart_dma.h> UART_DmaConfig gUartDmaConfig[CONFIG_UART_NUM_DMA_INSTANCES] = { }; uint32_t gUartDmaConfigNum = CONFIG_UART_NUM_DMA_INSTANCES; void Drivers_uartInit(void) { UART_init(); } void Pinmux_init(); void PowerClock_init(void); void PowerClock_deinit(void); /* * Common Functions */ void System_init(void) { /* DPL init sets up address transalation unit, on some CPUs this is needed * to access SCICLIENT services, hence this needs to happen first */ Dpl_init(); /* We should do sciclient init before we enable power and clock to the peripherals */ /* SCICLIENT init */ { int32_t retVal = SystemP_SUCCESS; retVal = Sciclient_direct_init(); DebugP_assertNoLog(SystemP_SUCCESS == retVal); } PowerClock_init(); /* Now we can do pinmux */ Pinmux_init(); /* finally we initialize all peripheral drivers */ GPMC_init(); /* UDMA */ { uint32_t instId; int32_t retVal = UDMA_SOK; for(instId = 0U; instId < CONFIG_UDMA_NUM_INSTANCES; instId++) { retVal += Udma_init(&gUdmaDrvObj[instId], &gUdmaInitPrms[instId]); DebugP_assert(UDMA_SOK == retVal); } } I2C_init(); Drivers_uartInit(); } void System_deinit(void) { GPMC_deinit(); /* UDMA */ { uint32_t instId; int32_t retVal = UDMA_SOK; for(instId = 0U; instId < CONFIG_UDMA_NUM_INSTANCES; instId++) { retVal += Udma_deinit(&gUdmaDrvObj[instId]); DebugP_assert(UDMA_SOK == retVal); } } I2C_deinit(); UART_deinit(); PowerClock_deinit(); /* SCICLIENT deinit */ { int32_t retVal = SystemP_SUCCESS; retVal = Sciclient_deinit(); DebugP_assertNoLog(SystemP_SUCCESS == retVal); } Dpl_deinit(); }
This is the uboot device tree code:
// SPDX-License-Identifier: GPL-2.0
/**
* DT overlay for HSE NAND expansion card on AM62X LP-SK
*
* Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
*/
#ifdef CONFIG_NAND_OMAP_GPMC
&elm0 {
u-boot,dm-spl;
status = "okay";
};
&main_pmx0 {
gpmc0_pins_default: gpmc0-pins-default {
pinctrl-single,pins = <
AM62X_IOPAD(0x003c, PIN_INPUT, 0) /* (M25) GPMC0_AD0 */
AM62X_IOPAD(0x0040, PIN_INPUT, 0) /* (N23) GPMC0_AD1 */
AM62X_IOPAD(0x0044, PIN_INPUT, 0) /* (N24) GPMC0_AD2 */
AM62X_IOPAD(0x0048, PIN_INPUT, 0) /* (N25) GPMC0_AD3 */
AM62X_IOPAD(0x004c, PIN_INPUT, 0) /* (P24) GPMC0_AD4 */
AM62X_IOPAD(0x0050, PIN_INPUT, 0) /* (P22) GPMC0_AD5 */
AM62X_IOPAD(0x0054, PIN_INPUT, 0) /* (P21) GPMC0_AD6 */
AM62X_IOPAD(0x0058, PIN_INPUT, 0) /* (R23) GPMC0_AD7 */
AM62X_IOPAD(0x0084, PIN_OUTPUT, 0) /* (L23) GPMC0_ADVn_ALE */
AM62X_IOPAD(0x0088, PIN_OUTPUT, 0) /* (L24) GPMC0_OEn_REn */
AM62X_IOPAD(0x008c, PIN_OUTPUT, 0) /* (L25) GPMC0_WEn */
AM62X_IOPAD(0x0090, PIN_OUTPUT, 0) /* (M24) GPMC0_BE0n_CLE */
AM62X_IOPAD(0x00a8, PIN_OUTPUT, 0) /* (M21) GPMC0_CSn0 */
AM62X_IOPAD(0x0098, PIN_INPUT, 0) /* (U23) GPMC0_WAIT0 */
>;
u-boot,dm-spl;
};
};
&gpmc0 {
pinctrl-names = "default";
status = "okay";
pinctrl-0 = <&gpmc0_pins_default>;
ranges = <0 0 0x00 0x51000000 0x01000000>; /* CS0 space. Min partition = 16MB */
#address-cells = <2>;
#size-cells = <1>;
u-boot,dm-spl;
nand0_0: nand@0,0 {
compatible = "ti,am64-nand";
reg = <0 0 64>; /* device IO registers */
interrupt-parent = <&gpmc0>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
rb-gpios = <&gpmc0 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
ti,nand-xfer-type = "prefetch-polled";
ti,nand-ecc-opt = "bch8"; /* BCH8: Bootrom limitation */
ti,elm-id = <&elm0>;
nand-bus-width = <8>;
gpmc,device-width = <1>;
gpmc,sync-clk-ps = <0>;
gpmc,cs-on-ns = <0>;
gpmc,cs-rd-off-ns = <40>;
gpmc,cs-wr-off-ns = <40>;
gpmc,adv-on-ns = <0>;
gpmc,adv-rd-off-ns = <25>;
gpmc,adv-wr-off-ns = <25>;
gpmc,we-on-ns = <0>;
gpmc,we-off-ns = <20>;
gpmc,oe-on-ns = <3>;
gpmc,oe-off-ns = <30>;
gpmc,access-ns = <30>;
gpmc,rd-cycle-ns = <40>;
gpmc,wr-cycle-ns = <40>;
gpmc,bus-turnaround-ns = <0>;
gpmc,cycle2cycle-delay-ns = <0>;
gpmc,clk-activation-ns = <0>;
gpmc,wr-access-ns = <40>;
gpmc,wr-data-mux-bus-ns = <0>;
u-boot,dm-spl;
};
};
#endif
Thanks in advance.
This thread is created upon request from TI team in this previous thread:
https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1456727/processor-sdk-am62x-dfu-u-boot-flashing-speed-optimization-questions/5593398#5593398
FYI: Islam NEGM
_________________________________________________________________________________________
Foot notes:
[1] I applied the nand chip configurations in uboot device tree as follow:
But I founded that I'm receiving wrong information from nand chip it seems that I'm reading wrong block size.
So, that I'm getting a bad block error because I'm reading the bad block marker from wrong location.
Attached Nand chip Datasheet:
2023_05_31-m79a_2gb_parallel_nand_auto (1).pdf