iMX6 boot configuration by GPIO differ from SBMR1 in reset

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

iMX6 boot configuration by GPIO differ from SBMR1 in reset

3,029 Views
juliocruz
Contributor III

Hi,

A custom board with a iMX6 DualLite have the BOOT_MODE equal to "10" (Internal Boot) and the boot flow is controlled by GPIO as below:

hardware config GPIO.png

The board have three SD sockets (SD1, SD2 and SD4). The following options are used to select the device:

board configuration.png

For testing purpose, I check the value of the register SBMR1 and SBMR2 in uBoot  as below:

  puts("Boot Configuration (SBMR1): \n");

  SBMR1 = readl(SRC_BASE_ADDR + 0x4);

  BOOT_CFG1 = ((SBMR1 & 0x000000FF) >> 0);

  BOOT_CFG2 = ((SBMR1 & 0x0000FF00) >> 4);

  BOOT_CFG3 = ((SBMR1 & 0x00FF0000) >> 8);

  BOOT_CFG4 = ((SBMR1 & 0xFF000000) >> 12);

  printf(" - BOOT_CFG1: "); print_register_bin(BOOT_CFG1);

  printf(" - BOOT_CFG2: "); print_register_bin(BOOT_CFG2);

  printf(" - BOOT_CFG3: "); print_register_bin(BOOT_CFG3);

  printf(" - BOOT_CFG4: "); print_register_bin(BOOT_CFG4)

  puts("Boot Configuration (SBMR2): \n");

  SBMR2 = readl(SRC_BASE_ADDR + 0x1C);

  SBMR2_8 = ((SBMR2 & 0x000000FF) >> 0);

  printf(" - SBMR2[7:0]: "); print_register_bin(SBMR2_8);

To print out the values I used the function below:

void print_register_bin(uint reg)

{

  if(reg & 0x80)

  printf("1");

  else

  printf("0");

  if(reg & 0x40)

  printf("1");

  else

  printf("0");

  if(reg & 0x20)

  printf("1");

  else

  printf("0");

  if(reg & 0x10)

  printf("1");

  else

  printf("0");

  if(reg & 0x08)

  printf("1");

  else

  printf("0");

  if(reg & 0x04)

  printf("1");

  else

  printf("0");

  if(reg & 0x02)

  printf("1");

  else

  printf("0");

  if(reg & 0x01)

  printf("1");

  else

  printf("0");

  printf("\n");

}

The testing shows unexpected results because the BOOT_CFG2 (in SBMR1) always have the bits [6 to 4] in zero and only recognize the bit [7] from the GPIO configuration (or dip switch).

To validate if the board and fuses are OK (following suggestions from others posts),

  1. The GPIO (dip-switch) was read using "gpio_get_value()" function
  2. The FUSES was read using "readl()" function

Both testing results was OK.

Below the functions used for reference:

  puts("Boot Configuration (FUSEMAP): \n");

  FUSE_MAP = readl(0x021BC000 + 0x450);

  BOOT_CFG1 = ((FUSE_MAP & 0x000000FF) >> 0);

  BOOT_CFG2 = ((FUSE_MAP & 0x0000FF00) >> 4);

  BOOT_CFG3 = ((FUSE_MAP & 0x00FF0000) >> 8);

  BOOT_CFG4 = ((FUSE_MAP & 0xFF000000) >> 12);

  printf(" - BOOT_CFG1: "); print_register_bin(BOOT_CFG1);

  printf(" - BOOT_CFG2: "); print_register_bin(BOOT_CFG2);

  printf(" - BOOT_CFG3: "); print_register_bin(BOOT_CFG3);

  printf(" - BOOT_CFG4: "); print_register_bin(BOOT_CFG4);

  puts("Boot Configuration (GPIO):");

  imx_iomux_v3_setup_multiple_pads(boot_cfg2_pads, ARRAY_SIZE(boot_cfg2_pads));

  gpio_direction_input(BOOT_CFG1_4_EIM_DA4);

  gpio_direction_input(BOOT_CFG1_5_EIM_DA5);

  gpio_direction_input(BOOT_CFG1_6_EIM_DA6);

  gpio_direction_input(BOOT_CFG1_7_EIM_DA7);

  gpio_direction_input(BOOT_CFG2_6_EIM_DA14);

  gpio_direction_input(BOOT_CFG2_5_EIM_DA13);

  gpio_direction_input(BOOT_CFG2_4_EIM_DA12);

  gpio_direction_input(BOOT_CFG2_3_EIM_DA11);

  printf("\n - BOOT_CFG1[7]: ");

  if(gpio_get_value(BOOT_CFG1_7_EIM_DA7))

  printf("1");

  else

  printf("0");

  printf("\n - BOOT_CFG1[6]: ");

  if(gpio_get_value(BOOT_CFG1_6_EIM_DA6))

  printf("1");

  else

  printf("0");

  printf("\n - BOOT_CFG1[5]: ");

  if(gpio_get_value(BOOT_CFG1_5_EIM_DA5))

  printf("1");

  else

  printf("0");

  printf("\n - BOOT_CFG1[4]: ");

  if(gpio_get_value(BOOT_CFG1_4_EIM_DA4))

  printf("1");

  else

  printf("0");

  printf("\n - BOOT_CFG2[6]: ");

  if(gpio_get_value(BOOT_CFG2_6_EIM_DA14))

  printf("1");

  else

  printf("0");

  printf("\n - BOOT_CFG2[5]: ");

  if(gpio_get_value(BOOT_CFG2_5_EIM_DA13))

  printf("1");

  else

  printf("0");

  printf("\n - BOOT_CFG2[4]: ");

  if(gpio_get_value(BOOT_CFG2_4_EIM_DA12))

  printf("1");

  else

  printf("0");

  printf("\n - BOOT_CFG2[3]: ");

  if(gpio_get_value(BOOT_CFG2_3_EIM_DA11))

  printf("1");

  else

  printf("0");

  printf("\n");

For example, the values of registers SBMR1, SBMR2, GPIO and FUSES, when all the dip-switch are set to use SD1 (BOOT_CFG1[7:4] = 0000, BOOT_CFG2[6:3] = 0100) are (please, refer to text in red color for unexpected results):

Boot Configuration (from SBMR1):

- BOOT_CFG1: 00000000

- BOOT_CFG2: 00000000

- BOOT_CFG3: 00000000

- BOOT_CFG4: 00000000

Boot Configuration (SBMR2):

- SBMR2[7:0]: 00000001

Boot Configuration (from FUSEMAP):

- BOOT_CFG1: 00000000

- BOOT_CFG2: 00000000

- BOOT_CFG3: 00000000

- BOOT_CFG4: 00000000

Boot Configuration (from GPIO):

- BOOT_CFG1[7]: 0

- BOOT_CFG1[6]: 0

- BOOT_CFG1[5]: 0

- BOOT_CFG1[4]: 0

- BOOT_CFG2[6]: 0

- BOOT_CFG2[5]: 1

- BOOT_CFG2[4]: 0

- BOOT_CFG2[3]: 0

I did another test to validate all the GPIO, when all the dip-switch are set to "1" (please, refer to text in red color for unexpected results):

Boot Configuration (from SBMR1):

- BOOT_CFG1: 11110000

- BOOT_CFG2: 10000000

- BOOT_CFG3: 00000000

- BOOT_CFG4: 00000000

Boot Configuration (SBMR2):

- SBMR2[7:0]: 00000001

Boot Configuration (from FUSEMAP):

- BOOT_CFG1: 00000000

- BOOT_CFG2: 00000000

- BOOT_CFG3: 00000000

- BOOT_CFG4: 00000000

Boot Configuration (from GPIO):

- BOOT_CFG1[7]: 1

- BOOT_CFG1[6]: 1

- BOOT_CFG1[5]: 1

- BOOT_CFG1[4]: 1

- BOOT_CFG2[6]: 1

- BOOT_CFG2[5]: 1

- BOOT_CFG2[4]: 1

- BOOT_CFG2[3]: 1

In conclusion, the bits BOOT_CFG1[6], BOOT_CFG1[5], BOOT_CFG1[4] are not changing according with the GPIO configuration or dip-switch.

Any suggestion?

Thanks

Labels (2)
Tags (4)
0 Kudos
Reply
8 Replies

1,708 Views
igorpadykov
NXP Employee
NXP Employee

HI Julio

suggest to check SBMR with jtag debugger, setting

BOOT_CFG4[7]=1, this is most accurate way.

Note, SBMR latches data on POR deassertion so

after booting, setting boot pins and reading them in Uboot

may lead to not correct results.

Boot_CFG.jpg

Best regards

igor

-----------------------------------------------------------------------------------------------------------------------

Note: If this post answers your question, please click the Correct Answer button. Thank you!

-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply

1,708 Views
juliocruz
Contributor III

Dear Igor,

Thanks for your suggestions.

Unfortunately, I don't have a JTAG tool right now. I will acquire one J-Link for this kind of issues as suggested on other post (Re: J-Link and iMX6​).

I have a couples of questions:

  • The SBMR latches the GPIO on POR deassertion. After that, the register could change the value?
  • If the SBMR latches the GPIO on POR deassertion, that's means that I can use it register to know which SD port is booting, right?

My final goal, is to boot from any of the available SD ports (SD1, SD2 and SD4) according with the GPIO settings. Right now, the board can boot from SD1, SD2 and cannot boot from SD4. Because that, I tried to read the SBMR1 and the GPIO to know if everything is OK (boot configuration and hardware).

If you consider this info need a new post (thread), please, let me know.

Thanks

0 Kudos
Reply

1,708 Views
igorpadykov
NXP Employee
NXP Employee

Hi Julio

yes, SBMR latches the GPIO on POR deassertion and after that,

the register should not change the value, provided that power-up

sequence is correct.

You can try to prolong POR up to 1 sec. to see if it helps.

Also it is recommended to check crystal clocks both 24MHz and 32.768 KHz.

Best regards

igor

0 Kudos
Reply

1,708 Views
juliocruz
Contributor III

Hi Igor,

I follow your suggestions.

  1. The POR is prolong for 1 sec. The results seems be the same. Only can change the bit BOOT_CFG2[7] and the others [6, 5, 4] don't change at all.
  2. The crystal clocks were  measured. The scope shows 32KHz and 24Mhz after POR.

crystal clock inspection.png

May I know if you have another suggestion?

Thanks

0 Kudos
Reply

1,708 Views
igorpadykov
NXP Employee
NXP Employee

Hi Julio

what is full processor part marking and

what design you followed, is it Freescale Sabre board ?

Also do you have permanent VDD_SNVS_IN to processor ?

If not, could you try with permanently applied VDD_SNVS_IN.

~igor

0 Kudos
Reply

1,708 Views
juliocruz
Contributor III

Hi Igor,

The problem was solved. I'm embarrassed because the problem was in the code as explain in the previous post.

The answer to your questions at the same order:

  1. Part marking: MCIMX6U5DVM10AC XAA1420   2N81E TAIW ATAAXC
  2. Freescale SABRE board? Custom board based on Freescale SABRE board
  3. VDD_SNVS_IN: permanent

Thanks again,

0 Kudos
Reply

1,708 Views
juliocruz
Contributor III

Please, may I know what I need to do? Correct answer? Other action?

0 Kudos
Reply

1,708 Views
juliocruz
Contributor III

Dear Igor, all,

I found where the problem was.

  1. When the SBMR is read, the "bit shift" operation was incorrect and the values on BOOT_CFG2 was shifted. Now, I fix the shift operation and everithing is as expected.
  2. Additionally, the BOOT_CFG2[7:6] must be in "01" for SD (1, 2, 3, or 4) and MMC/eMMC. Previously, this value was always in "00".

In conclusion, the SBMR1 is returning the correct values after reset and the SD is booting according with the GPIO config (SD1, SD2 and SD4).

Below, the code used to read the SBMR1 and configuration used on this board.

board configuration.png

void boot_registers(void)

{

  uint BOOT_CFG1, BOOT_CFG2, BOOT_CFG3, BOOT_CFG4;

  uint SBMR2_8;

  uint SBMR1;

  uint SBMR2;

  uint FUSE_MAP;

  puts("Boot Configuration (SBMR1): \n");

  SBMR1 = readl(SRC_BASE_ADDR + 0x4);

  BOOT_CFG1 = ((SBMR1 & 0x000000FF) >> 0);

  BOOT_CFG2 = ((SBMR1 & 0x0000FF00) >> 8);

  BOOT_CFG3 = ((SBMR1 & 0x00FF0000) >> 16);

  BOOT_CFG4 = ((SBMR1 & 0xFF000000) >> 24);

  printf(" - BOOT_CFG1: "); print_register_bin(BOOT_CFG1);

  printf(" - BOOT_CFG2: "); print_register_bin(BOOT_CFG2);

  printf(" - BOOT_CFG3: "); print_register_bin(BOOT_CFG3);

  printf(" - BOOT_CFG4: "); print_register_bin(BOOT_CFG4);

  puts("Boot Configuration (SBMR2): \n");

  SBMR2 = readl(SRC_BASE_ADDR + 0x1C);

  SBMR2_8 = ((SBMR2 & 0x000000FF) >> 0);

  printf(" - SBMR2[7:0]: "); print_register_bin(SBMR2_8);

  puts("Boot Configuration (FUSEMAP): \n");

  FUSE_MAP = readl(0x021BC000 + 0x450);

  BOOT_CFG1 = ((FUSE_MAP & 0x000000FF) >> 0);

  BOOT_CFG2 = ((FUSE_MAP & 0x0000FF00) >> 8);

  BOOT_CFG3 = ((FUSE_MAP & 0x00FF0000) >> 16);

  BOOT_CFG4 = ((FUSE_MAP & 0xFF000000) >> 24);

  printf(" - BOOT_CFG1: "); print_register_bin(BOOT_CFG1);

  printf(" - BOOT_CFG2: "); print_register_bin(BOOT_CFG2);

  printf(" - BOOT_CFG3: "); print_register_bin(BOOT_CFG3);

  printf(" - BOOT_CFG4: "); print_register_bin(BOOT_CFG4);

  puts("Boot Configuration (GPIO):");

  imx_iomux_v3_setup_multiple_pads(boot_cfg2_pads, ARRAY_SIZE(boot_cfg2_pads));

  gpio_direction_input(BOOT_CFG1_4_EIM_DA4);

  gpio_direction_input(BOOT_CFG1_5_EIM_DA5);

  gpio_direction_input(BOOT_CFG1_6_EIM_DA6);

  gpio_direction_input(BOOT_CFG1_7_EIM_DA7);

  gpio_direction_input(BOOT_CFG2_6_EIM_DA14);

  gpio_direction_input(BOOT_CFG2_5_EIM_DA13);

  gpio_direction_input(BOOT_CFG2_4_EIM_DA12);

  gpio_direction_input(BOOT_CFG2_3_EIM_DA11);

  printf("\n - BOOT_CFG1[7]: ");

  if(gpio_get_value(BOOT_CFG1_7_EIM_DA7))

  printf("1");

  else

  printf("0");

  printf("\n - BOOT_CFG1[6]: ");

  if(gpio_get_value(BOOT_CFG1_6_EIM_DA6))

  printf("1");

  else

  printf("0");

  printf("\n - BOOT_CFG1[5]: ");

  if(gpio_get_value(BOOT_CFG1_5_EIM_DA5))

  printf("1");

  else

  printf("0");

  printf("\n - BOOT_CFG1[4]: ");

  if(gpio_get_value(BOOT_CFG1_4_EIM_DA4))

  printf("1");

  else

  printf("0");

  printf("\n - BOOT_CFG2[6]: ");

  if(gpio_get_value(BOOT_CFG2_6_EIM_DA14))

  printf("1");

  else

  printf("0");

  printf("\n - BOOT_CFG2[5]: ");

  if(gpio_get_value(BOOT_CFG2_5_EIM_DA13))

  printf("1");

  else

  printf("0");

  printf("\n - BOOT_CFG2[4]: ");

  if(gpio_get_value(BOOT_CFG2_4_EIM_DA12))

  printf("1");

  else

  printf("0");

  printf("\n - BOOT_CFG2[3]: ");

  if(gpio_get_value(BOOT_CFG2_3_EIM_DA11))

  printf("1");

  else

  printf("0");

  printf("\n");

}

Thanks for your support

0 Kudos
Reply