Re: [BISECTED] BeagleBone Black doesn't boot after a58147c2dbbf

I cannot understand what is going on. As far as I understand, read consists of i2c write of address and subsequent i2c read of data. During the i2c write process, EEPROM handles ACK/NOACK and - since there is no error code - the EEPROM handles i2c write correctly. And then it looks like no EEPROM device during the i2c read stage.
вт, 16 авг. 2022 г. в 04:27, Nishanth Menon nm@ti.com:
On 23:32-20220815, Matwey V. Kornilov wrote:
Only the first one dm_i2c_read is successful, whenever the size value.
I wonder if we need to add complete ep read... this is what I see on my element 14 board:
<debug_uart> ti_i2c_eeprom_get: 98: rc=0 header=0xee3355aa ti_i2c_eeprom_get: 102: rc=0 ti_i2c_eeprom_get: 110: rc=0 ti_i2c_eeprom_get: 121: header=0xffffffff rc=0 ti_i2c_eeprom_get: 130: rc=0 ti_i2c_eeprom_get: 135: rc=0 ti_i2c_eeprom_get: 139: header=0xee3355aa ti_i2c_eeprom_get: 144: rc=0 ep[0]=0xaa ep[1]=0x55 ep[2]=0x33 ep[3]=0xee ep[4]=0x41 ep[5]=0x33 ep[6]=0x33 ep[7]=0x35 ep[8]=0x42 ep[9]=0x4e ep[10]=0x4c ep[11]=0x54 ep[12]=0x30 ep[13]=0x30 ep[14]=0x43 ep[15]=0x30 ep[16]=0x34 ep[17]=0x31 ep[18]=0x34 ep[19]=0x42 ep[20]=0x42 ep[21]=0x42 ep[22]=0x4b ep[23]=0x30 ep[24]=0x31 ep[25]=0x36 ep[26]=0x37 ep[27]=0xff ep[28]=0xff ep[29]=0xff ep[30]=0xff ep[31]=0xff ep[32]=0xff ep[33]=0xff ep[34]=0xff ep[35]=0xff ep[36]=0xff ep[37]=0xff ep[38]=0xff ep[39]=0xff ep[40]=0xff ep[41]=0xff ep[42]=0xff ep[43]=0xff ep[44]=0xff ep[45]=0xff ep[46]=0xff ep[47]=0xff ep[48]=0xff ep[49]=0xff ep[50]=0xff ep[51]=0xff ep[52]=0xff ep[53]=0xff ep[54]=0xff ep[55]=0xff ep[56]=0xff ep[57]=0xff ep[58]=0xff ep[59]=0xff ep[60]=0xff ep[61]=0xff ep[62]=0xff ep[63]=0xff ep[64]=0xff ep[65]=0xff ep[66]=0xff ep[67]=0xff ep[68]=0xff ep[69]=0xff ep[70]=0xff ep[71]=0xff ep[72]=0xff ep[73]=0xff ep[74]=0xff ep[75]=0xff ep[76]=0xff ep[77]=0xff ti_i2c_eeprom_get: 195: Out OK
U-Boot SPL 2022.10-rc2-00030-g29d075bc05ca-dirty (Aug 15 2022 - 14:50:17 -0500) Trying to boot from MMC1
U-Boot 2022.10-rc2-00030-g29d075bc05ca-dirty (Aug 15 2022 - 14:50:17 -0500)
CPU : AM335X-GP rev 2.1 Model: TI AM335x BeagleBone Black DRAM: 512 MiB Core: 160 devices, 18 uclasses, devicetree: separate WDT: Started wdt@44e35000 with servicing (60s timeout) NAND: 0 MiB MMC: OMAP SD/MMC: 0, OMAP SD/MMC: 1 Loading Environment from FAT... Unable to read "uboot.env" from mmc0:1... <ethaddr> not set. Validating first E-fuse MAC Net: eth2: ethernet@4a100000, eth3: usb_ether Hit any key to stop autoboot: 0 =>
пн, 15 авг. 2022 г. в 23:21, Matwey V. Kornilov matwey.kornilov@gmail.com:
I have one idea. I'll try dm_i2c_read() with different `size' argument values tomorrow.
пн, 15 авг. 2022 г. в 23:13, Matwey V. Kornilov matwey.kornilov@gmail.com:
пн, 15 авг. 2022 г. в 22:56, Nishanth Menon nm@ti.com:
On 21:12-20220815, Matwey V. Kornilov wrote: [....]
Trying offline for now (I am also on libera.chat #linux-ti and #u-boot)..
<debug_uart> ti_i2c_eeprom_get: 98: rc=0 header=0xee3355aa ti_i2c_eeprom_get: 102: rc=0 ti_i2c_eeprom_get: 110: rc=0 ti_i2c_eeprom_get: 121: header=0xee3355aa ti_i2c_eeprom_get: 139: header=0xee3355aa ti_i2c_eeprom_get: 144: rc=0 ep[0]=0xff
gaah... data seems stuck... with one more potential fixup... Dont know how this might behave..
ti_i2c_eeprom_get: 121: header=0xee3355aa rc=0
main change is this: @@ -113,33 +117,42 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, * We must allow for fall through to check the data if 2 byte * addressing works */
(void)dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
printf("%s: %d: header=0x%08x rc=%d\n", __func__, __LINE__, hdr_read, rc); /* Corrupted data??? */
if (hdr_read != header) {
if (rc || hdr_read != header) {
8<--- diff --git a/board/ti/common/board_detect.c b/board/ti/common/board_detect.c index ed34991377ee..f4e5da34b70a 100644 --- a/board/ti/common/board_detect.c +++ b/board/ti/common/board_detect.c @@ -90,13 +90,16 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, int rc;
#if CONFIG_IS_ENABLED(DM_I2C)
int i; struct udevice *dev; struct udevice *bus; rc = uclass_get_device_by_seq(UCLASS_I2C, bus_addr, &bus);
printf("%s: %d: rc=%d header=0x%08x\n", __func__, __LINE__, rc, header); if (rc) return rc; rc = dm_i2c_probe(bus, dev_addr, 0, &dev);
printf("%s: %d: rc=%d\n", __func__, __LINE__, rc); if (rc) return rc;
@@ -104,6 +107,7 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, * Read the header first then only read the other contents. */ rc = i2c_set_chip_offset_len(dev, 1);
printf("%s: %d: rc=%d\n", __func__, __LINE__, rc); if (rc) return rc;
@@ -113,33 +117,42 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, * We must allow for fall through to check the data if 2 byte * addressing works */
(void)dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
printf("%s: %d: header=0x%08x rc=%d\n", __func__, __LINE__, hdr_read, rc); /* Corrupted data??? */
if (hdr_read != header) {
if (rc || hdr_read != header) { /* * read the eeprom header using i2c again, but use only a * 2 byte address (some newer boards need this..) */ rc = i2c_set_chip_offset_len(dev, 2);
printf("%s: %d: rc=%d\n", __func__, __LINE__, rc); if (rc) return rc; rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
printf("%s: %d: rc=%d\n", __func__, __LINE__, rc); if (rc) return rc; }
printf("%s: %d: header=0x%08x\n", __func__, __LINE__, hdr_read); if (hdr_read != header) return -1; rc = dm_i2c_read(dev, 0, ep, size);
printf("%s: %d: rc=%d\n", __func__, __LINE__, rc); if (rc) return rc;
for (i = 0; i< size; i++)
printf("ep[%d]=0x%02x\n",i, ep[i]);
#else u32 byte;
gpi2c_init(); rc = ti_i2c_eeprom_init(bus_addr, dev_addr);
printf("%s: %d: rc=%d header=0x%08x\n", __func__, __LINE__, rc, header); if (rc) return rc;
@@ -157,6 +170,7 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, (void)i2c_read(dev_addr, 0x0, byte, (uint8_t *)&hdr_read, 4);
/* Corrupted data??? */
printf("%s: %d: header=0x%08x\n", __func__, __LINE__, hdr_read); if (hdr_read != header) { /* * read the eeprom header using i2c again, but use only a
@@ -165,16 +179,20 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, byte = 2; rc = i2c_read(dev_addr, 0x0, byte, (uint8_t *)&hdr_read, 4);
printf("%s: %d: rc=%d\n", __func__, __LINE__, rc); if (rc) return rc; }
printf("%s: %d: header=0x%08x\n", __func__, __LINE__, hdr_read); if (hdr_read != header) return -1; rc = i2c_read(dev_addr, 0x0, byte, ep, size);
printf("%s: %d: rc=%d\n", __func__, __LINE__, rc); if (rc) return rc;
#endif
printf("%s: %d: Out OK\n", __func__, __LINE__); return 0;
}
diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig index b500ed0fdd8d..b4039018793b 100644 --- a/configs/am335x_evm_defconfig +++ b/configs/am335x_evm_defconfig @@ -9,6 +9,9 @@ CONFIG_AM335X_USB0=y CONFIG_AM335X_USB0_PERIPHERAL=y CONFIG_AM335X_USB1=y CONFIG_SPL=y +CONFIG_DEBUG_UART_BASE=0x44e09000 +CONFIG_DEBUG_UART_CLOCK=48000000 +CONFIG_DEBUG_UART=y CONFIG_DISTRO_DEFAULTS=y CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x4030ff00 @@ -102,6 +105,9 @@ CONFIG_DRIVER_TI_CPSW=y CONFIG_DM_PMIC=y # CONFIG_SPL_DM_PMIC is not set CONFIG_PMIC_TPS65217=y +CONFIG_DEBUG_UART_OMAP=y +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_DEBUG_UART_ANNOUNCE=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_OMAP3_SPI=y -- Regards, Nishanth Menon Key (0xDDB5849D1736249D) / Fingerprint: F8A2 8693 54EB 8232 17A3 1A34 DDB5 849D 1736 249D
-- With best regards, Matwey V. Kornilov
-- With best regards, Matwey V. Kornilov
-- With best regards, Matwey V. Kornilov
-- Regards, Nishanth Menon Key (0xDDB5849D1736249D) / Fingerprint: F8A2 8693 54EB 8232 17A3 1A34 DDB5 849D 1736 249D

I've played a little and now I believe that the issue is that EEPROM read addr pointer is somehow corrupted due to 1-byte address write. The EEPROM is definitely have two-byte read address accoring the datasheet. I've failed to unravel exact rule what is happening when only one address byte is set, but was able to read random places of EEPROM.
However, the following diff makes the board bootable.
diff --git a/board/ti/common/board_detect.c b/board/ti/common/board_detect.c index ed34991377..26edddccc6 100644 --- a/board/ti/common/board_detect.c +++ b/board/ti/common/board_detect.c @@ -86,7 +86,6 @@ __weak void gpi2c_init(void) static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, u32 header, u32 size, uint8_t *ep) { - u32 hdr_read = 0xdeadbeef; int rc;
#if CONFIG_IS_ENABLED(DM_I2C) @@ -113,10 +112,10 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, * We must allow for fall through to check the data if 2 byte * addressing works */ - (void)dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4); + rc = dm_i2c_read(dev, 0, ep, size);
/* Corrupted data??? */ - if (hdr_read != header) { + if (rc || (*((u32*)ep) != header)) { /* * read the eeprom header using i2c again, but use only a * 2 byte address (some newer boards need this..) @@ -125,16 +124,13 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, if (rc) return rc;
- rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4); + rc = dm_i2c_read(dev, 0, ep, size); if (rc) return rc; } - if (hdr_read != header) + if (*((u32*)ep) != header) return -1;
- rc = dm_i2c_read(dev, 0, ep, size); - if (rc) - return rc; #else u32 byte;

On 11:28-20220818, Matwey V. Kornilov wrote:
I've played a little and now I believe that the issue is that EEPROM read addr pointer is somehow corrupted due to 1-byte address write. The EEPROM is definitely have two-byte read address accoring the datasheet. I've failed to unravel exact rule what is happening when only one address byte is set, but was able to read random places of EEPROM.
However, the following diff makes the board bootable.
diff --git a/board/ti/common/board_detect.c b/board/ti/common/board_detect.c index ed34991377..26edddccc6 100644 --- a/board/ti/common/board_detect.c +++ b/board/ti/common/board_detect.c @@ -86,7 +86,6 @@ __weak void gpi2c_init(void) static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, u32 header, u32 size, uint8_t *ep) {
u32 hdr_read = 0xdeadbeef; int rc;
#if CONFIG_IS_ENABLED(DM_I2C) @@ -113,10 +112,10 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, * We must allow for fall through to check the data if 2 byte * addressing works */
(void)dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
rc = dm_i2c_read(dev, 0, ep, size); /* Corrupted data??? */
if (hdr_read != header) {
if (rc || (*((u32*)ep) != header)) { /* * read the eeprom header using i2c again, but use only a * 2 byte address (some newer boards need this..)
@@ -125,16 +124,13 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, if (rc) return rc;
rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
rc = dm_i2c_read(dev, 0, ep, size); if (rc) return rc; }
if (hdr_read != header)
if (*((u32*)ep) != header) return -1;
rc = dm_i2c_read(dev, 0, ep, size);
if (rc)
return rc;
#else u32 byte;
This does work. I tested a few variations of boards to check this concept out.. but anyways.. on beaglebone black (element 14 boards):
NOTE: This will improve detection times for 1 byte eeprom based boot, since there is no retry..
However for boards with 2 byte addressing eeproms:
master branch: https://pasteboard.co/n3P8yhSq6pem.png Time from first attempt to read eeprom to actual trigger of final eeprom read attempt: ~4ms
With this patch: https://pasteboard.co/IVQzHwMuhc4p.png Time from first attempt to read eeprom to actual trigger of final eeprom read attempt: ~18ms
IMHO, 14ms penalty is'nt a bad deal for dealing with variations of eeproms we are seeing in the wild.
You can find the data (analog+digital capture) here: https://github.com/nmenon/data-captures/tree/main/i2c-eeprom-1byte-captures Tool used to capture (and view): https://www.saleae.com/downloads/
Tom, Robert, folks: what do you folks think?

On Fri, Aug 19, 2022 at 4:30 AM Nishanth Menon nm@ti.com wrote:
On 11:28-20220818, Matwey V. Kornilov wrote:
I've played a little and now I believe that the issue is that EEPROM read addr pointer is somehow corrupted due to 1-byte address write. The EEPROM is definitely have two-byte read address accoring the datasheet. I've failed to unravel exact rule what is happening when only one address byte is set, but was able to read random places of EEPROM.
However, the following diff makes the board bootable.
diff --git a/board/ti/common/board_detect.c b/board/ti/common/board_detect.c index ed34991377..26edddccc6 100644 --- a/board/ti/common/board_detect.c +++ b/board/ti/common/board_detect.c @@ -86,7 +86,6 @@ __weak void gpi2c_init(void) static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, u32 header, u32 size, uint8_t *ep) {
u32 hdr_read = 0xdeadbeef; int rc;
#if CONFIG_IS_ENABLED(DM_I2C) @@ -113,10 +112,10 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, * We must allow for fall through to check the data if 2 byte * addressing works */
(void)dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
rc = dm_i2c_read(dev, 0, ep, size); /* Corrupted data??? */
if (hdr_read != header) {
if (rc || (*((u32*)ep) != header)) { /* * read the eeprom header using i2c again, but use only a * 2 byte address (some newer boards need this..)
@@ -125,16 +124,13 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, if (rc) return rc;
rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
rc = dm_i2c_read(dev, 0, ep, size); if (rc) return rc; }
if (hdr_read != header)
if (*((u32*)ep) != header) return -1;
rc = dm_i2c_read(dev, 0, ep, size);
if (rc)
return rc;
#else u32 byte;
This does work. I tested a few variations of boards to check this concept out.. but anyways.. on beaglebone black (element 14 boards):
NOTE: This will improve detection times for 1 byte eeprom based boot, since there is no retry..
However for boards with 2 byte addressing eeproms:
master branch: https://pasteboard.co/n3P8yhSq6pem.png Time from first attempt to read eeprom to actual trigger of final eeprom read attempt: ~4ms
With this patch: https://pasteboard.co/IVQzHwMuhc4p.png Time from first attempt to read eeprom to actual trigger of final eeprom read attempt: ~18ms
IMHO, 14ms penalty is'nt a bad deal for dealing with variations of eeproms we are seeing in the wild.
You can find the data (analog+digital capture) here: https://github.com/nmenon/data-captures/tree/main/i2c-eeprom-1byte-captures Tool used to capture (and view): https://www.saleae.com/downloads/
Tom, Robert, folks: what do you folks think?
I'm okay with the delay. if we only had 'one' production run it would be a different story.. But with 10 years of manufacturing, parts will EOL and vary. Let's go with the safe slower route..
Regards,

On 08:56-20220819, Robert Nelson wrote:
On Fri, Aug 19, 2022 at 4:30 AM Nishanth Menon nm@ti.com wrote:
On 11:28-20220818, Matwey V. Kornilov wrote:
[..]
Tom, Robert, folks: what do you folks think?
I'm okay with the delay. if we only had 'one' production run it would be a different story.. But with 10 years of manufacturing, parts will EOL and vary. Let's go with the safe slower route..
Matwey, would you post your fix formally?

вт, 23 авг. 2022 г., 06:54 Nishanth Menon nm@ti.com:
On 08:56-20220819, Robert Nelson wrote:
On Fri, Aug 19, 2022 at 4:30 AM Nishanth Menon nm@ti.com wrote:
On 11:28-20220818, Matwey V. Kornilov wrote:
[..]
Tom, Robert, folks: what do you folks think?
I'm okay with the delay. if we only had 'one' production run it would be a different story.. But with 10 years of manufacturing, parts will EOL and vary. Let's go with the safe slower route..
Matwey, would you post your fix formally?
Ok. I'll do.
participants (3)
-
Matwey V. Kornilov
-
Nishanth Menon
-
Robert Nelson