blob: ed981776fc61c4b0d90245411470ad55df685c65 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <console/console.h>
#include <inttypes.h>
#include <baseboard/variants.h>
#include <ec/google/chromeec/ec.h>
/* Global definitions for FW_CONFIG values */
enum {
/* Daughterboard index for attributes. */
FW_CONFIG_MASK_DB_INDEX = 0xf,
FW_CONFIG_DB_INDEX_SHIFT = 0,
/* Mainboard USB index for attributes. */
FW_CONFIG_MASK_MB_USB_INDEX = 0xf,
FW_CONFIG_MB_USB_INDEX_SHIFT = 4,
/* Lid accelerometer properties. */
FW_CONFIG_MASK_LID_ACCEL = 0x7,
FW_CONFIG_LID_ACCEL_SHIFT = 8,
/* Base gyro sensor properties. */
FW_CONFIG_MASK_BASE_GYRO = 0x7,
FW_CONFIG_BASE_GYRO_SHIFT = 11,
/* Keyboard backlight presence */
FW_CONFIG_MASK_KEYB_BL = 0x1,
FW_CONFIG_KEYB_BL_SHIFT = 14,
/* Tablet mode supported through lid angle */
FW_CONFIG_MASK_LID_ANGLE_TABLET_MODE = 0x1,
FW_CONFIG_LID_ANGLE_TABLET_MODE_SHIFT = 15,
/* Stylus presence */
FW_CONFIG_MASK_STYLUS = 0x1,
FW_CONFIG_STYLUS_SHIFT = 16,
/* Fingerprint sensor presence */
FW_CONFIG_MASK_FP = 0x1,
FW_CONFIG_SHIFT_FP = 17,
/* NVME presence */
FW_CONFIG_MASK_NVME = 0x1,
FW_CONFIG_SHIFT_NVME = 18,
/* EMMC presence */
FW_CONFIG_MASK_EMMC = 0x1,
FW_CONFIG_SHIFT_EMMC = 19,
/* SD controller type */
FW_CONFIG_MASK_SD_CTRLR = 0x7,
FW_CONFIG_SHIFT_SD_CTRLR = 20,
/* SAR presence */
FW_CONFIG_MASK_SAR = 0x7,
FW_CONFIG_SHIFT_SAR = 23,
/* Mainboard Type for VCORE IC */
FW_CONFIG_MASK_MB_TYPE = 0x1,
FW_CONFIG_SHIFT_MB_TYPE = 26,
/* Fan information */
FW_CONFIG_MASK_FAN = 0x3,
FW_CONFIG_SHIFT_FAN = 27,
/* WWAN presence */
FW_CONFIG_MASK_WWAN = 0x1,
FW_CONFIG_SHIFT_WWAN = 29,
/* Audio AMP type */
FW_CONFIG_MASK_AUDIO_AMP = 0x1,
FW_CONFIG_SHIFT_AUDIO_AMP = 35,
/* Audio codec type */
FW_CONFIG_MASK_AUDIO_CODEC_SOURCE = 0x3,
FW_CONFIG_SHIFT_AUDIO_CODEC_SOURCE = 36,
};
static int get_fw_config(uint64_t *val)
{
static uint64_t known_value;
if (known_value) {
*val = known_value;
return 0;
}
if (google_chromeec_cbi_get_fw_config(&known_value) != 0) {
printk(BIOS_ERR, "FW_CONFIG not set in CBI\n");
return -1;
}
*val = known_value;
return 0;
}
static unsigned int extract_field(uint64_t mask, int shift)
{
uint64_t fw_config;
/* On errors nothing is assumed to be set. */
if (get_fw_config(&fw_config))
return 0;
return (fw_config >> shift) & mask;
}
int variant_gets_sar_config(void)
{
return extract_field(FW_CONFIG_MASK_SAR, FW_CONFIG_SHIFT_SAR);
}
int variant_gets_mb_type_config(void)
{
return extract_field(FW_CONFIG_MASK_MB_TYPE, FW_CONFIG_SHIFT_MB_TYPE);
}
int variant_has_emmc(void)
{
return !!extract_field(FW_CONFIG_MASK_EMMC, FW_CONFIG_SHIFT_EMMC);
}
int variant_has_nvme(void)
{
return !!extract_field(FW_CONFIG_MASK_NVME, FW_CONFIG_SHIFT_NVME);
}
int variant_has_wwan(void)
{
return !!extract_field(FW_CONFIG_MASK_WWAN, FW_CONFIG_SHIFT_WWAN);
}
int variant_is_convertible(void)
{
return !!extract_field(FW_CONFIG_MASK_LID_ANGLE_TABLET_MODE,
FW_CONFIG_LID_ANGLE_TABLET_MODE_SHIFT);
}
bool variant_uses_v3_schematics(void)
{
uint32_t board_version;
if (!CONFIG(VARIANT_SUPPORTS_PRE_V3_SCHEMATICS))
return true;
if (google_chromeec_cbi_get_board_version(&board_version) != 0)
return false;
if ((int)board_version < CONFIG_VARIANT_MIN_BOARD_ID_V3_SCHEMATICS)
return false;
return true;
}
bool variant_uses_v3_6_schematics(void)
{
uint32_t board_version;
if (!CONFIG(VARIANT_SUPPORTS_PRE_V3_6_SCHEMATICS))
return true;
if (google_chromeec_cbi_get_board_version(&board_version) != 0)
return false;
if ((int)board_version < CONFIG_VARIANT_MIN_BOARD_ID_V3_6_SCHEMATICS)
return false;
return true;
}
/*
* pre-v3.6, CODEC_GPI was used as headphone jack interrupt.
* Starting v3.6 this was changed to a separate GPIO.
*/
bool variant_uses_codec_gpi(void)
{
return !variant_uses_v3_6_schematics();
}
bool variant_has_active_low_wifi_power(void)
{
uint32_t board_version;
if (!CONFIG(VARIANT_SUPPORTS_WIFI_POWER_ACTIVE_HIGH))
return true;
if (google_chromeec_cbi_get_board_version(&board_version) != 0)
return false;
if ((int)board_version < CONFIG_VARIANT_MIN_BOARD_ID_WIFI_POWER_ACTIVE_LOW)
return false;
return true;
}
int variant_get_daughterboard_id(void)
{
return extract_field(FW_CONFIG_MASK_DB_INDEX, FW_CONFIG_DB_INDEX_SHIFT);
}
__weak bool variant_has_fingerprint(void)
{
if (CONFIG(VARIANT_HAS_FPMCU))
return true;
return false;
}
bool fpmcu_needs_delay(void)
{
/*
* Older board versions need an extra delay here to finish resetting
* the FPMCU. The resistor value in the glitch prevention circuit was
* sized so that the FPMCU doesn't turn of for ~1 second. On newer
* boards, that's been updated to ~30ms, which allows the FPMCU's
* reset to be completed in the time between bootblock and finalize.
*/
uint32_t board_version;
if (google_chromeec_cbi_get_board_version(&board_version))
board_version = 1;
if (board_version <= CONFIG_VARIANT_MAX_BOARD_ID_BROKEN_FMPCU_POWER)
return true;
return false;
}