BPI-R4: u-boot: i2c

Hi,

has anyone tried i2c on bpi-r4 yet?

i try to access the i2c-mux and further the eeprom on its channel 0, but i do not see the mux on the i2c bus…am i missing something (just used the linux device tree nodes for pinctrl and i2cmux - i2c controller itself was already in u-boot)?

BPI-R4> fatload usb 0:1 $loadaddr u-boot-r4-2025.04-i2c.bin
903816 bytes read in 80 ms (10.8 MiB/s)
BPI-R4> go $loadaddr
## Starting application at 0x46000000 ...


U-Boot 2025.04-bpi-i2cmux-00032-g935c239f9e94-dirty (May 29 2025 - 13:05:36 +0200)

CPU:   MediaTek MT7988
Model: mt7988-rfb
DRAM:  8 GiB
Core:  54 devices, 21 uclasses, devicetree: separate
MMC:   mmc@11230000: 0
Loading Environment from nowhere... OK
In:    serial@11000000
Out:   serial@11000000
Err:   serial@11000000
=> board_late_init...
bootmedia:sd
Net:   MediaTek MT7988 built-in switch

Warning: ethernet@15110100 (eth0) using random MAC address - f2:f2:2c:2a:fe:8c
eth0: ethernet@15110100
Hit any key to stop autoboot:  0 
BPI-R4> i2c
i2c - I2C sub-system

Usage:
i2c bus [muxtype:muxaddr:muxchannel] - show I2C bus info
i2c crc32 chip address[.0, .1, .2] count - compute CRC32 checksum
i2c dev [dev] - show or set current I2C bus
i2c loop chip address[.0, .1, .2] [# of objects] - looping read of device
i2c md chip address[.0, .1, .2] [# of objects] - read from I2C device
i2c mm chip address[.0, .1, .2] - write to I2C device (auto-incrementing)
i2c mw chip address[.0, .1, .2] value [count] - write to I2C device (fill)
i2c nm chip address[.0, .1, .2] - write to I2C device (constant address)
i2c probe [address] - test for and show device(s) on the I2C bus
i2c read chip address[.0, .1, .2] length memaddress - read to memory
i2c write memaddress chip address[.0, .1, .2] length [-s] - write memory
          to I2C; the -s option selects bulk write in a single transaction
i2c flags chip [flags] - set or get chip flags
i2c olen chip [offset_length] - set or get chip offset length
i2c reset - re-init the I2C Controller
i2c speed [speed] - show or set I2C bus speed
BPI-R4> eeprom 
eeprom - EEPROM sub-system

Usage:
eeprom list
eeprom read  [device_specifier] addr off cnt
eeprom write [device_specifier] addr off cnt
       - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'

DEVICE SPECIFIER - the eeprom device can be specified
  [dev_name] - by device name (devices can listed with the eeprom list command)
  [[bus] devaddr] - or by I2C bus and I2C device address
If no device specifier is given, the first driver-model found device is used.
BPI-R4> eeprom list
BPI-R4> i2c bus 0  
Bus 0:  i2c@11004000  (active 0)
BPI-R4> i2c bus 1
Bus 1:  i2c@11005000  (active 1)
BPI-R4> i2c dev 1
Setting bus to 1
BPI-R4> i2c probe
Valid chip addresses:

i2c bus 1 seems to be the i2c2 (i2c2: i2c@11005000), so basicly i2c seems to be probed correctly, but does not show any devices

source:

@hackpascal have you an idea?

edit: got a bit further…noticed that the pca954x driver misses the compatible for pca9545 after adding this and its config i see the eeprom

BPI-R4> i2c bus
Bus 0:  i2c@11004000
Bus 1:  i2c@11005000
   70: i2c-mux@70, offset len 1, flags 0
Bus 2:  i2c@11005000->i2c-mux@70->i2c@0
   57: eeprom@57, offset len 1, flags 0
BPI-R4> eeprom list
eeprom@57 (i2c_eeprom)
BPI-R4> eeprom read eeprom@57 0x0 100

EEPROM @0x0 read: addr 0xffffffffffffffff  off 0x0000  count 256 ... done
exit not allowed from main input shell.

not sure if i do it right, but it seems read was working (my eeprom is currentl empty)

also tried using i2c read, but this seems not working (maybe because device is bound to driver)

BPI-R4> i2c dev 2
Setting bus to 2
BPI-R4> i2c read 0x57 0 100 $loadaddr
Error reading the chip: -19
BPI-R4> i2c md 0x57 0 100            
Error reading the chip: -19

it looks like it does read on main i2c bus not on bus 2 because when i probe the current bus i see the i2c-mux

BPI-R4> i2c probe
Valid chip addresses: 70

but after this i see this strange device below bus 2 and not the rtc i expected on 0x51

BPI-R4> i2c bus
Bus 0:  i2c@11004000
Bus 1:  i2c@11005000  (active 1)
   70: i2c-mux@70, offset len 1, flags 0
Bus 2:  i2c@11005000->i2c-mux@70->i2c@0  (active 2)
   57: eeprom@57, offset len 1, flags 0
   70: generic_70, offset len 1, flags 0

verified from linux that my 8g-phy board still has the rtc…ans yes it has

root@bpi-r4-phy-8G:~# dmesg | grep at24
[    1.148263] at24 2-0057: supply vcc not found, using dummy regulator
[    1.155171] at24 2-0057: 256 byte 24c02 EEPROM, writable, 1 bytes/write
root@bpi-r4-phy-8G:~# dmesg | grep rtc
[    1.119439] rtc-pcf8563 2-0051: low voltage detected, date/time is not reliable.
[    1.126919] rtc-pcf8563 2-0051: registered as rtc0
[    1.132914] rtc-pcf8563 2-0051: low voltage detected, date/time is not reliable.
[    1.140304] rtc-pcf8563 2-0051: hctosys: unable to read the hardware clock
root@bpi-r4-phy-8G:~# i2cdetect -y 2
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- UU -- -- -- -- -- UU -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: UU -- -- -- -- -- -- --
root@bpi-r4-phy-8G:~# dmesg | grep pca
[    1.110017] pca954x 1-0070: supply vdd not found, using dummy regulator
[    1.181250] pca954x 1-0070: registered 4 multiplexed busses for I2C switch pca9545

and seems adress 70 is also there (i guess its the mux itself as it is also bound to driver)

maybe there is any trick to see i2c devices in uboot without driver too

1 Like

EEPROM Available for programming ?

What is tlv_eeprom? I’m not eperienced in eeprom access,but if read works write should too

Not sure this helps?:

We try uboot here… I have already copied dts nodes from linux added/modified drivers and see the eeprom.

But i cannot access via i2c command (where the most examples base on),read vie eeprom command seems to work (my eeprom is empty).

Btw parts of the txt are from me using my oled display on r3.

so did a small test:

# echo "TEST" | dd of=/sys/bus/i2c/devices/2-0057/eeprom bs=1                                                           
5+0 records in
5+0 records out
5 bytes copied, 0.00206577 s, 2.4 kB/s
root@bpi-r4-v11:~
# dd if=/sys/bus/i2c/devices/2-0057/eeprom bs=1 count=5                                                                 
test
5+0 records in
5+0 records out
5 bytes copied, 0.00272846 s, 1.8 kB/s

wonder why text is lowercase on reading, but basicly it seems working in linux so far.

in uboot i have not yet fuigured out how to read as i always get a -19 error with i2c command

and with eeprom-command i get this:

BPI-R4> i2c dev 2
Setting bus to 2
BPI-R4> eeprom read 57 $loadaddr 0 5  

EEPROM @0x57 read: addr 0x46000000  off 0x0000  count 5 ... eeprom_rw_block: Cannot find udev for a bus -1
done
BPI-R4> md $loadaddr
46000000: 1400000a d503201f 41e00000 00000000  ..... .....A....

Pipe the output to hexdump?

Edit:

| hexdump -C

# dd if=/sys/bus/i2c/devices/2-0057/eeprom bs=1 count=5|hexdump -C
5+0 records in
5+0 records out
5 bytes copied, 0.00266515 s, 1.9 kB/s
00000000  74 65 73 74 0a                                    |test.|
00000005
root@bpi-r4-v11:~
# echo "TEST" |hexdump -C
00000000  54 45 53 54 0a                                    |TEST.|
00000005

btw. i tried

echo "BLAH" > /sys/bus/i2c/devices/2-0057/eeprom

but this does not work, and noticed, that i cannot repeat this with another write from linux (i guess i have to erase the blocks first, but have not found out how yet)

root@bpi-r4-v11:~
# echo "BLAH" | dd of=/sys/bus/i2c/devices/2-0057/eeprom bs=1                                                           
5+0 records in
5+0 records out
5 bytes copied, 0.00221038 s, 2.3 kB/s
root@bpi-r4-v11:~
# dd if=/sys/bus/i2c/devices/2-0057/eeprom bs=1 count=5|hexdump -C
00000000  74 65 73 74 0a                                    |test.|
5+0 records in
5+0 records out
00000005
5 bytes copied, 0.0027213 s, 1.8 kB/s

added some debugs in uboot and this is the result:

BPI-R4> i2c dev 2
Setting bus to 2
mtk_i2c_probe:791 i2c@11005000 probe start
mtk_i2c_probe:801 i2c@11005000 probe finish
pca954x_select:126 i2c-mux@70 select start bus i2c@11005000->i2c-mux@70->i2c@0 channel:#0
pca954x_select:132 i2c-mux@70 select end
mtk_i2c_transfer:700 i2c@11005000 transfer start
mtk_i2c_transfer:758 i2c@11005000 transfer end
mtk_i2c_transfer:700 i2c@11005000 transfer start
mtk_i2c_transfer:758 i2c@11005000 transfer end
BPI-R4> eeprom read 57 $loadaddr 0 5

EEPROM @0x57 read: addr 0x46000000  off 0x0000  count 5 ... eeprom_rw_block: Cannot find udev for a bus -1
done

so it looks right till the i2c-mux, but it seems the eeprom itself is not probed, but compatible is there

when i do a i2c probe then it looks like the eeprom-probe is called

i2c_eeprom_std_probe:158 eeprom@57 probe start
i2c_eeprom_read:28 eeprom@57 start
i2c_eeprom_read:31 eeprom@57 read end
pca954x_select:126 i2c-mux@70 select start bus i2c@11005000->i2c-mux@70->i2c@0 channel:#0
pca954x_select:132 i2c-mux@70 select end
mtk_i2c_transfer:700 i2c@11005000 transfer start
mtk_i2c_transfer:758 i2c@11005000 transfer end
mtk_i2c_transfer:700 i2c@11005000 transfer start
mtk_i2c_transfer:758 i2c@11005000 transfer end
mtk_i2c_transfer:700 i2c@11005000 transfer start
mtk_i2c_transfer:758 i2c@11005000 transfer end
i2c_eeprom_std_probe:174 eeprom@57 probe end
 57pca954x_select:126 i2c-mux@70 select start bus i2c@11005000->i2c-mux@70->i2c@0 channel:#0
pca954x_select:132 i2c-mux@70 select end

https://docs.phytec.com/projects/yocto-phycore-am65x/en/latest/interfaceguides/eeprom.html

dd if=/dev/zero

got the eeprom read this way…so i2c layer works and it is a uboot eeprom driver issue

edit: added previous commands without debug

BPI-R4> i2c bus
Bus 0:  i2c@11004000
Bus 1:  i2c@11005000
   70: i2c-mux@70, offset len 1, flags 0
Bus 2:  i2c@11005000->i2c-mux@70->i2c@0
   57: eeprom@57, offset len 1, flags 0
BPI-R4> i2c dev 2
Setting bus to 2
BPI-R4> i2c probe
BPI-R4> i2c md 0x57 0 5
pca954x_select:126 i2c-mux@70 select start bus i2c@11005000->i2c-mux@70->i2c@0 channel:#0
pca954x_select:132 i2c-mux@70 select end
mtk_i2c_transfer:700 i2c@11005000 transfer start
mtk_i2c_transfer:758 i2c@11005000 transfer end
mtk_i2c_transfer:700 i2c@11005000 transfer start
mtk_i2c_transfer:758 i2c@11005000 transfer end
mtk_i2c_transfer:700 i2c@11005000 transfer start
mtk_i2c_transfer:758 i2c@11005000 transfer end
0000: 74 65 73 74 0a    test.

also loading to mem address works so far

BPI-R4> i2c read 0x57 0 5 $loadaddr
BPI-R4> md.b $loadaddr 5
46000000: 74 65 73 74 0a                                   test.

also looks like the “i2c probe” command is optional and is done on i2c md/read

but the eeprom-command seems not accessing the i2c bus. but got u-boot crashing with the eeprom-command

BPI-R4> eeprom read 2 0x57 $loadaddr 0 5

EEPROM @0x57 read: addr 0x46000000  off 0x0000  count 5 ... i2c_eeprom_read:28 0
"Synchronous Abort" handler, esr 0x96000021, far 0x31

seems not working

root@bpi-r4-v11:~
# dd if=/dev/zero of=/sys/bus/i2c/devices/2-0057/eeprom bs=16 count=1                                                                        
1+0 records in
1+0 records out
16 bytes copied, 0.00567577 s, 2.8 kB/s
root@bpi-r4-v11:~
# cat /sys/bus/i2c/devices/2-0057/eeprom | hexdump -C                                                                       
00000000  74 65 73 74 0a ff ff ff  ff ff ff ff ff ff ff ff  |test............|
00000010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*                                                                                                                                            
00000100

tried with 512 blocksize first, but got “dd: error writing ‘/sys/bus/i2c/devices/2-0057/eeprom’: File too large”

possibly the case-issue was because i wrote first small case “test” and afterwards with big letters, which was not written like the “BLAH” above

also tried erasing with 0xFF, but same as normal write it gets ignored

# echo -en "\xff\xff\xff\xff\xff" | dd of=/sys/bus/i2c/devices/2-0057/eeprom
0+1 records in
0+1 records out
5 bytes copied, 0.00197715 s, 2.5 kB/s
root@bpi-r4-v11:~
# cat /sys/bus/i2c/devices/2-0057/eeprom | hexdump -C
00000000  74 65 73 74 0a ff ff ff  ff ff ff ff ff ff ff ff  |test............|
00000010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
00000100

does eeprom only support full page write (so maybe i need to write x bytes to allow overwriting it) or remember last write position (but then i had the TEST after my lowercase test)?

i tried also writing from uboot

i2c mw 0x57 0 0xff 6
BPI-R4> i2c md 0x57 0 10                                                                                                                     
0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................

Maybe try to find the largest possible?

Would it be better to use the command eeprog instead of sysfs?

eeprog - reads and writes 24Cxx EEPROMs connected to I2C serial bus

seems 256 is the largest blocksize to be written.

eeprog seems having no package on debian and needs to be compiled

The 24c02 is only 256 bytes :wink:

Yes you are right,i thought it was a bit bigger (at least kbytes),but linux kernel confirms

at24 2-0057: 256 byte 24c02 EEPROM, writable, 1 bytes/write

It is set in the devicetree,size = 256, but for this eeprom, it is the actual size.

AT24C02A/04A : PAGE WRITE: The 2K EEPROM is capable of an 8-byte page write, and the 4K device is capable of 16-byte page writes.

So should be able to add:

pagesize = <8>;

To the devicetree, but leaving it out <1> is the safer option, get it functional without first.

The WP pin is connected to the same gpio pin as the green led :wink: So you would need to switch this led on or off to enable writing to the eeprom.

1 Like

tlv_eeprom

For Board Information (Type Code and Value) https://opencomputeproject.github.io/onie/design-spec/hw_requirements.html

This information can now be used to pre-configure the device. For example, assigning mac address

How to use

Add this line to .config

CONFIG_CMD_TLV_EEPROM=y

Read and erase eeprom data

tlv_eeprom read
tlv_eeprom erase

Programming data to eeprom

tlv_eeprom set 0x21 'BananaPI BPI-R4'
tlv_eeprom set 0x22 '<Serial Number>'
tlv_eeprom set 0x25 'DD/MM/YYYY HH:MM:SS'
tlv_eeprom set 0x26 '0x01'
tlv_eeprom set 0x24 '<Base Mac Address>'
tlv_eeprom set 0x2A '<Number of mac address (3 GMAC == 3 mac Address)>'
tlv_eeprom set 0x28 '(aarch|arm)64-bananapi_bpi_r4-r0'
tlv_eeprom set 0x2B 'Mediatek'
tlv_eeprom set 0x2D 'Sinovoip'
tlv_eeprom write

Enjoy

Ah,this is a command in mainline uboot?

Does it generate 3 mac addresses based on the base mac? Does it update devicetree for linux?