diff options
-rw-r--r-- | board/fizz/board.c | 5 | ||||
-rw-r--r-- | board/fizz/board.h | 4 | ||||
-rw-r--r-- | common/build.mk | 1 | ||||
-rw-r--r-- | common/cbi.c | 127 | ||||
-rw-r--r-- | include/config.h | 6 | ||||
-rw-r--r-- | include/cros_board_info.h | 60 |
6 files changed, 203 insertions, 0 deletions
diff --git a/board/fizz/board.c b/board/fizz/board.c index 2089777a01..9756aa05c0 100644 --- a/board/fizz/board.c +++ b/board/fizz/board.c @@ -17,6 +17,7 @@ #include "charger.h" #include "chipset.h" #include "console.h" +#include "cros_board_info.h" #include "driver/pmic_tps650x30.h" #include "driver/temp_sensor/tmp432.h" #include "driver/tcpm/ps8xxx.h" @@ -449,6 +450,10 @@ DECLARE_HOOK(HOOK_AC_CHANGE, board_extpower, HOOK_PRIO_DEFAULT); /* Initialize board. */ static void board_init(void) { + uint32_t version; + if (cbi_get_board_version(&version) == EC_SUCCESS) + CPRINTS("Board Version: 0x%04x", version); + /* Provide AC status to the PCH */ board_extpower(); diff --git a/board/fizz/board.h b/board/fizz/board.h index 9409cfffb3..67b7d20aad 100644 --- a/board/fizz/board.h +++ b/board/fizz/board.h @@ -18,6 +18,9 @@ /* EC */ #define CONFIG_ADC #define CONFIG_BOARD_VERSION +#define CONFIG_BOARD_SPECIFIC_VERSION +#define CONFIG_CRC8 +#define CONFIG_CROS_BOARD_INFO #define CONFIG_DEDICATED_RECOVERY_BUTTON #define CONFIG_EMULATED_SYSRQ #define CONFIG_LED_COMMON @@ -130,6 +133,7 @@ /* I2C addresses */ #define I2C_ADDR_TCPC0 0x16 +#define I2C_ADDR_EEPROM 0xa0 /* Verify and jump to RW image on boot */ #define CONFIG_VBOOT_EFS diff --git a/common/build.mk b/common/build.mk index 589c71bf3c..7b70378541 100644 --- a/common/build.mk +++ b/common/build.mk @@ -26,6 +26,7 @@ common-$(CONFIG_BLUETOOTH_LE)+=bluetooth_le.o common-$(CONFIG_BLUETOOTH_LE_STACK)+=btle_hci_controller.o btle_ll.o common-$(CONFIG_CAPSENSE)+=capsense.o common-$(CONFIG_CASE_CLOSED_DEBUG_V1)+=ccd_config.o +common-$(CONFIG_CROS_BOARD_INFO)+=cbi.o common-$(CONFIG_CHARGE_MANAGER)+=charge_manager.o common-$(CONFIG_CHARGE_RAMP_HW)+=charge_ramp.o common-$(CONFIG_CHARGE_RAMP_SW)+=charge_ramp.o charge_ramp_sw.o diff --git a/common/cbi.c b/common/cbi.c new file mode 100644 index 0000000000..dce8475d81 --- /dev/null +++ b/common/cbi.c @@ -0,0 +1,127 @@ +/* Copyright 2018 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Cros Board Info + */ + +#include "common.h" +#include "console.h" +#include "crc8.h" +#include "cros_board_info.h" +#include "i2c.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_SYSTEM, "CBI " format, ## args) + +static struct board_info bi; +/* TODO: Init it to -1. On error (I2C or bad contents), retry a read and set it + * to enum ec_error_list if it still fails. The successive calls can be + * immediately returned with the cached error code. This will avoid attempting + * reads doomed to fail. */ +static int initialized; + +static uint8_t cbi_crc8(const struct board_info *bi) +{ + return crc8((uint8_t *)&bi->head.crc + 1, bi->head.total_size - 4); +} + +/* + * Get board information from EEPROM + */ +static int read_board_info(void) +{ + uint8_t buf[256]; + uint8_t offset; + + if (initialized) + return EC_SUCCESS; + + CPRINTS("Reading board info"); + + /* Read header */ + offset = 0; + if (i2c_xfer(I2C_PORT_EEPROM, I2C_ADDR_EEPROM, + &offset, 1, buf, sizeof(bi.head), I2C_XFER_SINGLE)) { + CPRINTS("Failed to read header"); + return EC_ERROR_INVAL; + } + memcpy(&bi.head, buf, sizeof(bi.head)); + + /* Check magic */ + if (memcmp(bi.head.magic, cbi_magic, sizeof(bi.head.magic))) { + CPRINTS("Bad magic"); + return EC_ERROR_INVAL; + } + + /* check version */ + if (bi.head.major_version > CBI_VERSION_MAJOR) { + CPRINTS("Version mismatch"); + return EC_ERROR_INVAL; + } + + /* Check the data size. It's expected to support up to 64k but our + * buffer has practical limitation. */ + if (bi.head.total_size < sizeof(bi) || + bi.head.total_size > sizeof(buf)) { + CPRINTS("Bad size: %d", bi.head.total_size); + return EC_ERROR_OVERFLOW; + } + + /* Read the rest */ + offset = sizeof(bi.head); + if (i2c_xfer(I2C_PORT_EEPROM, I2C_ADDR_EEPROM, &offset, 1, + buf + sizeof(bi.head), + bi.head.total_size - sizeof(bi.head), + I2C_XFER_SINGLE)) { + CPRINTS("Failed to read body"); + return EC_ERROR_INVAL; + } + + /* Check CRC. This supports new fields unknown to this parser. */ + if (cbi_crc8((struct board_info *)&buf) != bi.head.crc) { + CPRINTS("Bad CRC"); + return EC_ERROR_INVAL; + } + + /* Save only the data we understand. */ + memcpy(&bi.head + 1, &buf[sizeof(bi.head)], + sizeof(bi) - sizeof(bi.head)); + /* If we're handling previous version, clear all new fields */ + + initialized = 1; + + return EC_SUCCESS; +} + +int cbi_get_board_version(uint32_t *version) +{ + if (read_board_info()) + return EC_ERROR_UNKNOWN; + *version = bi.version; + return EC_SUCCESS; +} + +int cbi_get_sku_id(uint32_t *sku_id) +{ + if (read_board_info()) + return EC_ERROR_UNKNOWN; + *sku_id = bi.sku_id; + return EC_SUCCESS; +} + +int cbi_get_oem_id(uint32_t *oem_id) +{ + if (read_board_info()) + return EC_ERROR_UNKNOWN; + *oem_id = bi.oem_id; + return EC_SUCCESS; +} + +int board_get_version(void) +{ + uint32_t version; + if (cbi_get_board_version(&version)) + return -1; + return version; +} diff --git a/include/config.h b/include/config.h index 5126164767..cb2dc59f81 100644 --- a/include/config.h +++ b/include/config.h @@ -3118,6 +3118,12 @@ */ #undef CONFIG_BOARD_ID_SUPPORT +/* + * Define this to enable Cros Board Info support. I2C_EEPROM_PORT and + * I2C_EEPROM_ADDR must be defined as well. + */ +#undef CONFIG_CROS_BOARD_INFO + /*****************************************************************************/ /* * Include board and core configs, since those hold the CONFIG_ constants for a diff --git a/include/cros_board_info.h b/include/cros_board_info.h new file mode 100644 index 0000000000..8d140f1d25 --- /dev/null +++ b/include/cros_board_info.h @@ -0,0 +1,60 @@ +/* Copyright 2018 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Cros Board Info + */ +#ifndef __CROS_EC_CROS_BOARD_INFO_H +#define __CROS_EC_CROS_BOARD_INFO_H + +#include "common.h" + +#define CBI_VERSION_MAJOR 0 +#define CBI_VERSION_MINOR 0 +static const uint8_t cbi_magic[] = { 0x43, 0x42, 0x49 }; /* 'C' 'B' 'I' */ + +struct cbi_header { + uint8_t magic[3]; + /* CRC of 'struct board_info' excluding magic and crc */ + uint8_t crc; + /* Data format version. Parsers are expected to process data as long + * as major version is equal or younger. */ + union { + struct { + uint8_t minor_version; + uint8_t major_version; + }; + uint16_t version; + }; + /* Total size of data. It can be larger than sizeof(struct board_info) + * if future versions add additional fields. */ + uint16_t total_size; +} __attribute__((packed)); + +struct board_info { + struct cbi_header head; + /* Board version */ + union { + struct { + uint8_t minor_version; + uint8_t major_version; + }; + uint16_t version; + }; + /* OEM ID */ + uint8_t oem_id; + /* SKU ID */ + uint8_t sku_id; +} __attribute__((packed)); + +/** + * Board info accessors + * + * @param version/sku_id/oem_id [OUT] Data read from EEPROM + * @return EC_SUCCESS on success or EC_ERROR_* otherwise. + */ +int cbi_get_board_version(uint32_t *version); +int cbi_get_sku_id(uint32_t *sku_id); +int cbi_get_oem_id(uint32_t *oem_id); + +#endif /* __CROS_EC_CROS_BOARD_INFO_H */ |