drivers/i2c/rv3028c7: Use byte ops for i801 SMBus compatibility
The RV3028-C7 driver currently uses i2c_dev_read_at() and
i2c_dev_write_at() for block transfers when accessing RTC registers.
These block transfer functions are not universally supported across all
I2C/SMBus controller implementations in coreboot.
Specifically, the Intel i801 SMBus controller does not implement block
read/write operations, causing the RV3028-C7 driver to fail on platforms
using this controller due to missing transfer ops.
Replace block transfers with byte-by-byte operations
i2c_dev_readb_at() and i2c_dev_writeb_at(). These functions are
supported by i801.
TEST=Verified new SMBus functionality on mc_ehl8 (i801 controller).
Verified I2C functionality still works on mc_ehl2.
Used i2ctools from OS to read out registers 0x00-0x06 and confirmed
values match date/time set in coreboot.
Change-Id: I8a40ae14e62e3acf7c3904a8654c1d58fe4eb813
Signed-off-by: Kilian Krause <kilian.krause@siemens.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/91199
Reviewed-by: Mario Scheithauer <mario.scheithauer@siemens.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
90d9411271
commit
ca601f7df6
1 changed files with 23 additions and 15 deletions
|
|
@ -86,29 +86,37 @@ static void rtc_set_time_date(struct device *dev)
|
|||
buf[6] = coreboot_build_date.year;
|
||||
printk(BIOS_DEBUG, "%s: Set to coreboot build date\n", dev->chip_ops->name);
|
||||
}
|
||||
/* According to the datasheet, date and time should be transferred in "one go"
|
||||
in order to avoid value corruption. */
|
||||
if (i2c_dev_write_at(dev, buf, sizeof(buf), 0) != sizeof(buf)) {
|
||||
printk(BIOS_ERR, "%s: Not able to set date and time!\n", dev->chip_ops->name);
|
||||
for (size_t i = 0; i < ARRAY_SIZE(buf); i++) {
|
||||
if (i2c_dev_writeb_at(dev, i, buf[i]) < 0) {
|
||||
printk(BIOS_ERR, "%s: Failed to write register 0x%02zx!\n",
|
||||
dev->chip_ops->name, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rtc_final(struct device *dev)
|
||||
{
|
||||
uint8_t buf[7];
|
||||
int val;
|
||||
/* Read back current RTC date and time byte by byte */
|
||||
printk(BIOS_DEBUG, "%s: Reading current date and time...\n", dev->chip_ops->name);
|
||||
|
||||
/* Read back current RTC date and time and print it to the console.
|
||||
Date and time are read in "one go", the buffer contains seconds (byte 0)
|
||||
through years (byte 6) after this read. */
|
||||
if (i2c_dev_read_at(dev, buf, sizeof(buf), 0) != sizeof(buf)) {
|
||||
printk(BIOS_ERR, "%s: Not able to read current date and time!\n",
|
||||
dev->chip_ops->name);
|
||||
} else {
|
||||
printk(BIOS_INFO, "%s: Current date %02d.%02d.%02d %02d:%02d:%02d\n",
|
||||
dev->chip_ops->name, bcd2bin(buf[5]), bcd2bin(buf[4]),
|
||||
bcd2bin(buf[6]), bcd2bin(buf[2]), bcd2bin(buf[1]),
|
||||
bcd2bin(buf[0]));
|
||||
for (size_t i = 0; i < ARRAY_SIZE(buf); i++) {
|
||||
val = i2c_dev_readb_at(dev, i);
|
||||
if (val < 0) {
|
||||
printk(BIOS_ERR, "%s: Failed to read register 0x%02zx!\n",
|
||||
dev->chip_ops->name, i);
|
||||
return;
|
||||
}
|
||||
buf[i] = (uint8_t)val;
|
||||
}
|
||||
|
||||
printk(BIOS_INFO, "%s: Current date %02d.%02d.%02d %02d:%02d:%02d\n",
|
||||
dev->chip_ops->name, bcd2bin(buf[5]), bcd2bin(buf[4]),
|
||||
bcd2bin(buf[6]), bcd2bin(buf[2]), bcd2bin(buf[1]),
|
||||
bcd2bin(buf[0]));
|
||||
|
||||
/* Make sure the EEPROM automatic refresh is enabled. */
|
||||
if (rtc_eep_auto_refresh(dev, EEP_REFRESH_EN) != CB_SUCCESS) {
|
||||
printk(BIOS_ERR, "%s: Not able to enable EEPROM auto refresh!\n",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue