From ed74dcd7f055e07f96562b0a866c185f251016ac Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Wed, 27 Aug 2014 23:22:50 +0200 Subject: [PATCH] lenovo: Read mainboard version from AT24RF08C. Tablets have different mainboard version than laptop variants. Change-Id: I77a1e2b50d30dcf3fa064e0c378ceca7ccf96e89 Signed-off-by: Vladimir Serbinenko Reviewed-on: http://review.coreboot.org/6785 Reviewed-by: Edward O'Callaghan Tested-by: build bot (Jenkins) --- src/drivers/i2c/at24rf08c/lenovo_serials.c | 93 +++++++++++++++++----- src/mainboard/lenovo/t520/mainboard.c | 5 -- src/mainboard/lenovo/t530/mainboard.c | 5 -- src/mainboard/lenovo/x200/mainboard.c | 5 -- src/mainboard/lenovo/x201/mainboard.c | 5 -- src/mainboard/lenovo/x220/mainboard.c | 5 -- src/mainboard/lenovo/x230/mainboard.c | 5 -- 7 files changed, 75 insertions(+), 48 deletions(-) diff --git a/src/drivers/i2c/at24rf08c/lenovo_serials.c b/src/drivers/i2c/at24rf08c/lenovo_serials.c index 7a5b259798..53e76da033 100644 --- a/src/drivers/i2c/at24rf08c/lenovo_serials.c +++ b/src/drivers/i2c/at24rf08c/lenovo_serials.c @@ -26,35 +26,62 @@ #include #include "lenovo.h" -static void at24rf08c_read_string(u8 bank, u8 start, u8 len, char *result) -{ - int i; - device_t dev; +#define ERROR_STRING "*INVALID*" +static device_t at24rf08c_find_bank(u8 bank) +{ + device_t dev; dev = dev_find_slot_on_smbus(1, 0x54 | bank); - if (dev == 0) { + if (!dev) printk(BIOS_WARNING, "EEPROM not found\n"); - memcpy(result, "*INVALID*", sizeof ("*INVALID*")); - return; + return dev; +} + +static int at24rf08c_read_byte(device_t dev, u8 addr) +{ + int t = -1; + int j; + + /* After a register write AT24RF08C (which we issued in init function) + sometimes stops responding. Retry several times in case of failure. + */ + for (j = 0; j < 100; j++) { + t = smbus_read_byte(dev, addr); + if (t >= 0) + return t; } + return t; +} + +static void at24rf08c_read_string_dev(device_t dev, u8 start, + u8 len, char *result) +{ + int i; for (i = 0; i < len; i++) { - int t; - int j; - /* After a register write AT24RF08C (which we issued in init function) sometimes stops responding. - Retry several times in case of failure. - */ - for (j = 0; j < 100; j++) { - t = smbus_read_byte(dev, start + i); - if (t >= 0) - break; - } + int t = at24rf08c_read_byte(dev, start + i); + if (t < 0x20 || t > 0x7f) { - memcpy(result, "*INVALID*", sizeof ("*INVALID*")); + memcpy(result, ERROR_STRING, sizeof (ERROR_STRING)); return; } result[i] = t; } + result[len] = '\0'; +} + +static void at24rf08c_read_string(u8 bank, u8 start, u8 len, char *result) +{ + device_t dev; + + dev = at24rf08c_find_bank(bank); + if (dev == 0) { + printk(BIOS_WARNING, "EEPROM not found\n"); + memcpy(result, ERROR_STRING, sizeof (ERROR_STRING)); + return; + } + + at24rf08c_read_string_dev(dev, start, len, result); } const char *smbios_mainboard_serial_number(void) @@ -141,3 +168,33 @@ void smbios_mainboard_set_uuid(u8 *uuid) memcpy (uuid, result, 16); } + +const char *smbios_mainboard_version(void) +{ + static char result[100]; + static int already_read; + device_t dev; + int len; + + if (already_read) + return result; + + memset (result, 0, sizeof (result)); + + dev = at24rf08c_find_bank(2); + if (dev == 0) { + memcpy(result, ERROR_STRING, sizeof (ERROR_STRING)); + return result; + } + + len = at24rf08c_read_byte(dev, 0x26) - 2; + if (len < 0 || len > sizeof(result) - 1) { + memcpy(result, ERROR_STRING, sizeof (ERROR_STRING)); + return result; + } + + at24rf08c_read_string_dev(dev, 0x27, len, result); + + already_read = 1; + return result; +} diff --git a/src/mainboard/lenovo/t520/mainboard.c b/src/mainboard/lenovo/t520/mainboard.c index 8b1aa0d02a..f89001aeea 100644 --- a/src/mainboard/lenovo/t520/mainboard.c +++ b/src/mainboard/lenovo/t520/mainboard.c @@ -133,11 +133,6 @@ static int int15_handler(void) } #endif -const char *smbios_mainboard_version(void) -{ - return "ThinkPad T520"; -} - /* Audio Setup */ static void verb_setup(void) diff --git a/src/mainboard/lenovo/t530/mainboard.c b/src/mainboard/lenovo/t530/mainboard.c index 5af6cec3da..feb1aa78f0 100644 --- a/src/mainboard/lenovo/t530/mainboard.c +++ b/src/mainboard/lenovo/t530/mainboard.c @@ -133,11 +133,6 @@ static int int15_handler(void) } #endif -const char *smbios_mainboard_version(void) -{ - return "ThinkPad T530"; -} - /* Audio Setup */ static void verb_setup(void) diff --git a/src/mainboard/lenovo/x200/mainboard.c b/src/mainboard/lenovo/x200/mainboard.c index a00f1851c9..9fe55db308 100644 --- a/src/mainboard/lenovo/x200/mainboard.c +++ b/src/mainboard/lenovo/x200/mainboard.c @@ -125,11 +125,6 @@ const char *smbios_mainboard_bios_version(void) return "CBET4000 " COREBOOT_VERSION; } -const char *smbios_mainboard_version(void) -{ - return "Lenovo X200"; -} - static int mainboard_smbios_data(device_t dev, int *handle, unsigned long *current) { int len; diff --git a/src/mainboard/lenovo/x201/mainboard.c b/src/mainboard/lenovo/x201/mainboard.c index b57d79065d..16d4bd9c7d 100644 --- a/src/mainboard/lenovo/x201/mainboard.c +++ b/src/mainboard/lenovo/x201/mainboard.c @@ -98,11 +98,6 @@ const char *smbios_mainboard_bios_version(void) return "CBET4000 " COREBOOT_VERSION; } -const char *smbios_mainboard_version(void) -{ - return "Lenovo X201"; -} - /* Audio Setup */ static void verb_setup(void) diff --git a/src/mainboard/lenovo/x220/mainboard.c b/src/mainboard/lenovo/x220/mainboard.c index 8d90c22170..7bc1edbe8d 100644 --- a/src/mainboard/lenovo/x220/mainboard.c +++ b/src/mainboard/lenovo/x220/mainboard.c @@ -143,11 +143,6 @@ const char *smbios_mainboard_bios_version(void) return "CBET4000 " COREBOOT_VERSION; } -const char *smbios_mainboard_version(void) -{ - return "ThinkPad X220"; -} - /* Audio Setup */ static void verb_setup(void) diff --git a/src/mainboard/lenovo/x230/mainboard.c b/src/mainboard/lenovo/x230/mainboard.c index 4e3151fef4..323f37faed 100644 --- a/src/mainboard/lenovo/x230/mainboard.c +++ b/src/mainboard/lenovo/x230/mainboard.c @@ -143,11 +143,6 @@ const char *smbios_mainboard_bios_version(void) return "CBET4000 " COREBOOT_VERSION; } -const char *smbios_mainboard_version(void) -{ - return "ThinkPad X230"; -} - /* Audio Setup */ static void verb_setup(void)