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.

AM4372: eMMC - SPL -> u-boot

Part Number: AM4372
Other Parts Discussed in Thread: TPS65218

Dear processors team,

I am trying to boot Linux from an AM4372-based custom board with eMMC memory.

I have no problems to start SPL from eMMC and also under Linux there are no issues. However, SPL will not use MLO and u-boot.bin to load u-boot from eMMC.

When trying to boot from eMMC, I will get the following error message:

U-Boot SPL 2019.01-g0757f3d81d-dirty (Jan 10 2021 - 11:06:56 +0100)
Trying to boot from MMC2
spl: could not find mmc device 1. error: -19
SPL: failed to boot from all boot devices
### ERROR ### Please RESET the board ###

The partition layout of the eMMC is as follows:

=> mmc part

Partition Map for MMC device 1  --   Partition Type: DOS

Part    Start Sector    Num Sectors     UUID            Type
  1     2048            81920           015884b5-01     06 Boot
  2     83968           3487744         015884b5-02     83
  3     3571712         163840          015884b5-03     83
  4     3735552         16384           015884b5-04     83

In theory, if I do not use mmcblk1boot0 and mmcblk1boot1 at all, he should just load MLO and u-boot.bin from the first partition (FAT) and be happy, right?

I have tried the follow to get it working:

  1. Write MLO to /dev/mmcblk1boot0 and u-boot.bin to /dev/mmcblk1boot1 under Linux.
  2. Use the command sequence indicated in software-dl.ti.com/.../Foundational_Components_U-Boot.html
    U-Boot # mmc dev 0
    U-Boot # mmc rescan
    U-Boot # mmc dev 1
    U-Boot # fatload mmc 0 0x82000000 MLO
    U-Boot # mmc write 0x82000000 0x100 0x100
    U-Boot # mmc write 0x82000000 0x200 0x100
    U-Boot # fatload mmc 0 0x82000000 u-boot.img
    U-Boot # mmc write 0x82000000 0x300 0x400

For your reference also the pinmux, but I suppose this is correct as the same settings work to access the eMMC from Linux or also from u-boot prompt (if doing the SPL via SD):

static struct module_pin_mux mmc1_pin_mux[] = {
	{OFFSET(gpmc_csn1), (MODE(2) | ((PIN_PULL_UD_DIS | PIN_PULL_UP_EN | PIN_RX_ACTIVE | PIN_DS_VALUE_OVERRIDE_EN | PIN_DS_OP_DIS | PIN_DS_PULL_UP_EN) & \
           (~PIN_DS_OP_VAL_1 & ~PIN_DS_PULL_UD_EN & ~PIN_WAKE_UP_EN)))},
	{OFFSET(gpmc_csn2), (MODE(2) | ((PIN_PULL_UD_DIS | PIN_PULL_UP_EN | PIN_RX_ACTIVE | PIN_DS_VALUE_OVERRIDE_EN | PIN_DS_OP_DIS | PIN_DS_PULL_UP_EN) & \
           (~PIN_DS_OP_VAL_1 & ~PIN_DS_PULL_UD_EN & ~PIN_WAKE_UP_EN)))},
	{OFFSET(gpmc_ad8), (MODE(2) | ((PIN_PULL_UD_DIS | PIN_PULL_UP_EN | PIN_RX_ACTIVE | PIN_DS_VALUE_OVERRIDE_EN | PIN_DS_OP_DIS | PIN_DS_PULL_UP_EN) & \
           (~PIN_DS_OP_VAL_1 & ~PIN_DS_PULL_UD_EN & ~PIN_WAKE_UP_EN)))},
	{OFFSET(gpmc_ad9), (MODE(2) | ((PIN_PULL_UD_DIS | PIN_PULL_UP_EN | PIN_RX_ACTIVE | PIN_DS_VALUE_OVERRIDE_EN | PIN_DS_OP_DIS | PIN_DS_PULL_UP_EN) & \
           (~PIN_DS_OP_VAL_1 & ~PIN_DS_PULL_UD_EN & ~PIN_WAKE_UP_EN)))},
	{OFFSET(gpmc_ad10), (MODE(2) | ((PIN_PULL_UD_DIS | PIN_PULL_UP_EN | PIN_RX_ACTIVE | PIN_DS_VALUE_OVERRIDE_EN | PIN_DS_OP_DIS | PIN_DS_PULL_UP_EN) & \
           (~PIN_DS_OP_VAL_1 & ~PIN_DS_PULL_UD_EN & ~PIN_WAKE_UP_EN)))},
	{OFFSET(gpmc_ad11), (MODE(2) | ((PIN_PULL_UD_DIS | PIN_PULL_UP_EN | PIN_RX_ACTIVE | PIN_DS_VALUE_OVERRIDE_EN | PIN_DS_OP_DIS | PIN_DS_PULL_UP_EN) & \
           (~PIN_DS_OP_VAL_1 & ~PIN_DS_PULL_UD_EN & ~PIN_WAKE_UP_EN)))},
	{OFFSET(gpmc_ad12), (MODE(2) | ((PIN_PULL_UD_DIS | PIN_PULL_UP_EN | PIN_RX_ACTIVE | PIN_DS_VALUE_OVERRIDE_EN | PIN_DS_OP_DIS | PIN_DS_PULL_UP_EN) & \
           (~PIN_DS_OP_VAL_1 & ~PIN_DS_PULL_UD_EN & ~PIN_WAKE_UP_EN)))},
	{OFFSET(gpmc_ad13), (MODE(2) | ((PIN_PULL_UD_DIS | PIN_PULL_UP_EN | PIN_RX_ACTIVE | PIN_DS_VALUE_OVERRIDE_EN | PIN_DS_OP_DIS | PIN_DS_PULL_UP_EN) & \
           (~PIN_DS_OP_VAL_1 & ~PIN_DS_PULL_UD_EN & ~PIN_WAKE_UP_EN)))},
	{OFFSET(gpmc_ad14), (MODE(2) | ((PIN_PULL_UD_DIS | PIN_PULL_UP_EN | PIN_RX_ACTIVE | PIN_DS_VALUE_OVERRIDE_EN | PIN_DS_OP_DIS | PIN_DS_PULL_UP_EN) & \
           (~PIN_DS_OP_VAL_1 & ~PIN_DS_PULL_UD_EN & ~PIN_WAKE_UP_EN)))},
	{OFFSET(gpmc_ad15), (MODE(2) | ((PIN_PULL_UD_DIS | PIN_PULL_UP_EN | PIN_RX_ACTIVE | PIN_DS_VALUE_OVERRIDE_EN | PIN_DS_OP_DIS | PIN_DS_PULL_UP_EN) & \
           (~PIN_DS_OP_VAL_1 & ~PIN_DS_PULL_UD_EN & ~PIN_WAKE_UP_EN)))},
	{OFFSET(mcasp0_fsx), (MODE(4) | ((PIN_PULL_UD_DIS | PIN_PULL_UP_EN | PIN_RX_ACTIVE | PIN_DS_VALUE_OVERRIDE_EN | PIN_DS_OP_DIS | PIN_DS_PULL_UP_EN) & \
           (~PIN_DS_OP_VAL_1 & ~PIN_DS_PULL_UD_EN & ~PIN_WAKE_UP_EN)))},
	{-1},
};

Regards
Peter

  • One thing which does not resolve the problem but which I noticed when checking voltages:

    The eMMC in our case is connected to dcdc4 of the TPS65218. However, your tps65218_voltage_update function in pmic_tps65218.c only supports updates on registers dcdc1 to dcdc3. Also, it checks at the beginning if one of these 3 registers is called which does not make much sense as all voltage registers are password protected but then it does not check for these registers for the GO command where it would actually make sense as this only applies up to dcdc3.

    May I suggest the following change to that function:

     int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel)
     {
    -       if ((dc_cntrl_reg != TPS65218_DCDC1) &&
    -           (dc_cntrl_reg != TPS65218_DCDC2) &&
    -           (dc_cntrl_reg != TPS65218_DCDC3))
    -               return 1;
    -
            /* set voltage level */
            if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, dc_cntrl_reg, volt_sel,
                                   TPS65218_DCDC_VSEL_MASK))
                    return 1;
    
    -       /* set GO bit to initiate voltage transition */
    -       if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, TPS65218_SLEW,
    -                              TPS65218_DCDC_GO, TPS65218_DCDC_GO))
    -               return 1;
    +               if ((dc_cntrl_reg == TPS65218_DCDC1) ||
    +               (dc_cntrl_reg == TPS65218_DCDC2) ||
    +               (dc_cntrl_reg == TPS65218_DCDC3))
    +       {
    +               /* set GO bit to initiate voltage transition */
    +               if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, TPS65218_SLEW,
    +                                       TPS65218_DCDC_GO, TPS65218_DCDC_GO))
    +                       return 1;
    +       }
    
            return 0;
     }

  • Hi Peter,
    >>>>
    spl: could not find mmc device 1. error: -19
    <<<<
    The above error (#define ENODEV 19 /* No such device */) is triggered in spl_mmc_find_device() in "/common/spl/spl_mmc.c" when SPL is trying to load u-boot.img. In newer SDK releases, Driver Model (DM) is used for mmc ports in SPL/u-boot. I'm listing u-boot "dm tree" log I captured on AM437x GP EVM (note that only MMC is enabled on AM437x GP EVM dtb file => mmc@48060000). You may need to add "CONFIG_CMD_DM=y" in your u-boot am43xx_xyz_defconfig if not set to enable "dm ..." cmd.

    => dm tree
     Class    index  Probed  Driver                Name
    -----------------------------------------------------------
     root        0  [ + ]   root_driver           root_driver
     simple_bus  0  [ + ]   generic_simple_bus    |-- ocp
     simple_bus  1  [   ]   generic_simple_bus    |   |-- l4_wkup@44c00000
     simple_bus  2  [   ]   generic_simple_bus    |   |   `-- scm@210000
     syscon      0  [   ]   syscon                |   |       `-- scm_conf@0
     serial      0  [ + ]   omap_serial           |   |-- serial@44e09000
     serial      1  [   ]   omap_serial           |   |-- serial@481a6000
     timer       0  [ + ]   omap_timer            |   |-- timer@48040000
     gpio        0  [ + ]   gpio_omap             |   |-- gpio@44e07000
     gpio        1  [   ]   gpio_omap             |   |-- gpio@4804c000
     gpio        2  [   ]   gpio_omap             |   |-- gpio@481ae000
     gpio        3  [   ]   gpio_omap             |   |-- gpio@48320000
     gpio        4  [   ]   gpio_omap             |   |-- gpio@48322000
     i2c         0  [ + ]   i2c_omap              |   |-- i2c@44e0b000
     i2c_generi  0  [ + ]   i2c_generic_chip_drv  |   |   `-- generic_24
     i2c         1  [   ]   i2c_omap              |   |-- i2c@4802a000
     mmc         0  [ + ]   omap_hsmmc            |   |-- mmc@48060000
     blk         0  [ + ]   mmc_blk               |   |   `-- mmc@48060000.blk
     eth         0  [ + ]   eth_cpsw              |   |-- ethernet@4a100000
     syscon      1  [   ]   syscon                |   |-- control-phy@44e10620
     syscon      2  [   ]   syscon                |   |-- control-phy@0x44e10628
     simple_bus  3  [   ]   generic_simple_bus    |   |-- ocp2scp@483a8000
     phy         0  [   ]   omap_usb2_phy         |   |   `-- phy@483a8000
     simple_bus  4  [   ]   generic_simple_bus    |   |-- ocp2scp@483e8000
     phy         1  [   ]   omap_usb2_phy         |   |   `-- phy@483e8000
     nop         0  [   ]   dwc3-generic-wrapper  |   |-- omap_dwc3@48380000
     usb         0  [   ]   dwc3-generic-periphe  |   |   `-- usb@48390000
     nop         1  [   ]   dwc3-generic-wrapper  |   `-- omap_dwc3@483c0000
     usb         0  [   ]   dwc3-generic-host     |       `-- usb@483d0000
     clk         0  [ + ]   fixed_rate_clock      `-- oscillator
    =>

  • Hi Hong,

    Below my dm tree output:

    => dm tree
     Class    index  Probed  Driver                Name
    -----------------------------------------------------------
     root        0  [ + ]   root_driver           root_driver
     simple_bus  0  [ + ]   generic_simple_bus    |-- ocp
     simple_bus  1  [   ]   generic_simple_bus    |   |-- l4_wkup@44c00000
     simple_bus  2  [   ]   generic_simple_bus    |   |   `-- scm@210000
     syscon      0  [   ]   syscon                |   |       `-- scm_conf@0
     serial      0  [ + ]   omap_serial           |   |-- serial@44e09000
     timer       0  [ + ]   omap_timer            |   |-- timer@48040000
     gpio        0  [ + ]   gpio_omap             |   |-- gpio@481ae000
     i2c         0  [ + ]   i2c_omap              |   |-- i2c@44e0b000
     i2c_generi  0  [ + ]   i2c_generic_chip_drv  |   |   `-- generic_24
     mmc         0  [ + ]   omap_hsmmc            |   |-- mmc@48060000
     blk         0  [ + ]   mmc_blk               |   |   `-- mmc@48060000.blk
     mmc         1  [ + ]   omap_hsmmc            |   |-- mmc@481d8000
     blk         1  [   ]   mmc_blk               |   |   `-- mmc@481d8000.blk
     syscon      1  [   ]   syscon                |   |-- control-phy@44e10620
     syscon      2  [   ]   syscon                |   |-- control-phy@0x44e10628
     simple_bus  3  [   ]   generic_simple_bus    |   |-- ocp2scp@483a8000
     simple_bus  4  [   ]   generic_simple_bus    |   |-- ocp2scp@483e8000
     phy         0  [   ]   omap_usb2_phy         |   |   `-- phy@483e8000
     nop         0  [   ]   dwc3-generic-wrapper  |   |-- omap_dwc3@48380000
     usb         0  [   ]   dwc3-generic-periphe  |   |   `-- usb@48390000
     nop         1  [   ]   dwc3-generic-wrapper  |   `-- omap_dwc3@483c0000
     usb         0  [   ]   dwc3-generic-host     |       `-- usb@483d0000
     clk         0  [ + ]   fixed_rate_clock      `-- oscillator

    => mmc dev 1
    switch to partitions #0, OK
    mmc1(part 0) is current device
    => mmc info
    Device: OMAP SD/MMC
    Manufacturer ID: fe
    OEM: 14e
    Name: MMC02
    Bus Speed: 48000000
    Mode : MMC High Speed (52MHz)
    Rd Block Len: 512
    MMC version 4.4.1
    High Capacity: No
    Capacity: 1.8 GiB
    Bus Width: 8-bit
    Erase Group Size: 512 KiB
    HC WP Group Size: 0 Bytes
    User Capacity: 1.8 GiB
    Boot Capacity: 1 MiB ENH
    RPMB Capacity: 128 KiB ENH

    From the u-boot command I can perfectly access the eMMC memory. I just have no clue to to convince SPL to do the same.

    Regards
    Peter

  • Hi Peter,
    Thanks for running "dm tree" cmd to confirm mmc2 node (mmc@481d8000) is available @u-boot prompt.
    I'd suspect mmc2 node is not active in your SPL FDT blob. One quick check is running "dtc -I dtb spl/u-boot-spl.dtb"

    Note that <u-boot-spl.dtb> is generated from <u-boot.dtb> with specific spl node property like <u-boot,dm-spl>, <u-boot,dm-pre-reloc>...
    For example, mmc1 node (MMC/SD) is defined in <am437x-gp-evm-u-boot.dtsi> which is, along with <am437x-gp-evm.dts>, implicitly compiled
    into <am437x-gp-evm.dtb> file.

    &mmc1 {
    	u-boot,dm-spl;
    };

    You may want to add mmc2 node in your u-boot board dts file:

    &mmc2 {
    	u-boot,dm-spl;
    };

    Best,

    -Hong

  • I had no idea that spl used parts of the dts. With u-boot,dm-spl; it is just working great, thank you so much.