summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--baseboard/intelrvp/README.md25
-rw-r--r--baseboard/intelrvp/baseboard.c238
-rw-r--r--baseboard/intelrvp/baseboard.h239
-rw-r--r--baseboard/intelrvp/battery.c79
-rw-r--r--baseboard/intelrvp/bc12.c28
-rw-r--r--baseboard/intelrvp/build.mk28
-rw-r--r--baseboard/intelrvp/chg_usb_pd.c167
-rw-r--r--baseboard/intelrvp/ite_ec.c90
-rw-r--r--baseboard/intelrvp/ite_ec.h24
-rw-r--r--baseboard/intelrvp/led.c109
-rw-r--r--baseboard/intelrvp/led_states.c188
-rw-r--r--baseboard/intelrvp/led_states.h90
-rw-r--r--baseboard/intelrvp/retimer.c32
-rw-r--r--baseboard/intelrvp/usb_mux.c26
-rw-r--r--baseboard/intelrvp/usb_pd_policy.c345
-rw-r--r--baseboard/intelrvp/vbus.c30
16 files changed, 1738 insertions, 0 deletions
diff --git a/baseboard/intelrvp/README.md b/baseboard/intelrvp/README.md
new file mode 100644
index 0000000000..b72d653d33
--- /dev/null
+++ b/baseboard/intelrvp/README.md
@@ -0,0 +1,25 @@
+/* Copyright 2019 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.
+ */
+
+This folder is for the baseboard for the board specific files which use Intel
+Reference Validation Platform (RVP) for developing the EC and other peripherals
+which can be hooked on EC or RVP.
+
+This baseboard follows the Intel Modular Embedded Controller Card (MECC)
+specification for pinout and these pin definitions remain same on all the
+RVPs. Chrome MECC spec is standardized for Icelake and successor RVPs hence
+this baseboard code is applicable to Icelake and its successors only.
+
+Following hardware features are supported on MECC header by RVP and can be
+validated by software by MECC.
+1. Power to MECC is provide by RVP (battery + DC Jack + Type C)
+2. Power control pins for Intel SOC are added
+3. Servo V2 header need to be added by MECC
+4. Google H1 chip need to be added by MECC (optional for EC vendors)
+4. 2 Type-C port support (SRC/SNK/BC1.2/MUX/Rerimer)
+5. 6 Temperature sensors
+6. 4 ADC
+7. 4 I2C Channels
+8. 1 Fan control
diff --git a/baseboard/intelrvp/baseboard.c b/baseboard/intelrvp/baseboard.c
new file mode 100644
index 0000000000..b48bda035f
--- /dev/null
+++ b/baseboard/intelrvp/baseboard.c
@@ -0,0 +1,238 @@
+/* Copyright 2019 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.
+ */
+
+/* Intel-RVP family-specific configuration */
+
+#include "adc_chip.h"
+#include "charge_state.h"
+#include "espi.h"
+#include "fan.h"
+#include "hooks.h"
+#include "ioexpander_pca9555.h"
+#include "peci.h"
+#include "power.h"
+#include "temp_sensor.h"
+#include "thermistor.h"
+
+/* GPIO for power signal */
+#ifdef CONFIG_HOSTCMD_ESPI_VW_SLP_SIGNALS
+#define SLP_S3_SIGNAL_L VW_SLP_S3_L
+#define SLP_S4_SIGNAL_L VW_SLP_S4_L
+#else
+#define SLP_S3_SIGNAL_L GPIO_PCH_SLP_S3_L
+#define SLP_S4_SIGNAL_L GPIO_PCH_SLP_S4_L
+#endif
+
+/* power signal list. Must match order of enum power_signal. */
+const struct power_signal_info power_signal_list[] = {
+ [X86_SLP_S0_DEASSERTED] = {
+ GPIO_PCH_SLP_S0_L,
+ POWER_SIGNAL_ACTIVE_HIGH | POWER_SIGNAL_DISABLE_AT_BOOT,
+ "SLP_S0_DEASSERTED",
+ },
+ [X86_SLP_S3_DEASSERTED] = {
+ SLP_S3_SIGNAL_L,
+ POWER_SIGNAL_ACTIVE_HIGH,
+ "SLP_S3_DEASSERTED",
+ },
+ [X86_SLP_S4_DEASSERTED] = {
+ SLP_S4_SIGNAL_L,
+ POWER_SIGNAL_ACTIVE_HIGH,
+ "SLP_S4_DEASSERTED",
+ },
+ [X86_RSMRST_L_PGOOD] = {
+ GPIO_RSMRST_L_PGOOD,
+ POWER_SIGNAL_ACTIVE_HIGH,
+ "RSMRST_L_PGOOD",
+ },
+ [X86_ALL_SYS_PWRGD] = {
+ GPIO_ALL_SYS_PWRGD,
+ POWER_SIGNAL_ACTIVE_HIGH,
+ "ALL_SYS_PWRGD",
+ },
+#if defined(CONFIG_CHIPSET_ICELAKE)
+ [X86_SLP_SUS_DEASSERTED] = {
+ GPIO_PCH_SLP_SUS_L,
+ POWER_SIGNAL_ACTIVE_HIGH,
+ "SLP_SUS_DEASSERTED",
+ },
+ [X86_DSW_DPWROK] = {
+ GPIO_DSW_DPWROK,
+ POWER_SIGNAL_ACTIVE_HIGH,
+ "DSW_DPWROK",
+ },
+#elif defined(CONFIG_CHIPSET_COMETLAKE)
+ [PP5000_A_PGOOD] = {
+ GPIO_PP5000_A_PG_OD,
+ POWER_SIGNAL_ACTIVE_HIGH,
+ "PP5000_A_PGOOD",
+ },
+#endif
+};
+BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT);
+
+/* Wake-up pins for hibernate */
+const enum gpio_signal hibernate_wake_pins[] = {
+ GPIO_AC_PRESENT,
+ GPIO_LID_OPEN,
+ GPIO_POWER_BUTTON_L,
+};
+const int hibernate_wake_pins_used = ARRAY_SIZE(hibernate_wake_pins);
+
+/* ADC channels */
+const struct adc_t adc_channels[] = {
+ [ADC_TEMP_SNS_AMBIENT] = {
+ .name = "ADC_TEMP_SNS_AMBIENT",
+ .factor_mul = ADC_MAX_MVOLT,
+ .factor_div = ADC_READ_MAX + 1,
+ .shift = 0,
+ .channel = ADC_TEMP_SNS_AMBIENT_CHANNEL,
+ },
+ [ADC_TEMP_SNS_DDR] = {
+ .name = "ADC_TEMP_SNS_DDR",
+ .factor_mul = ADC_MAX_MVOLT,
+ .factor_div = ADC_READ_MAX + 1,
+ .shift = 0,
+ .channel = ADC_TEMP_SNS_DDR_CHANNEL,
+ },
+ [ADC_TEMP_SNS_SKIN] = {
+ .name = "ADC_TEMP_SNS_SKIN",
+ .factor_mul = ADC_MAX_MVOLT,
+ .factor_div = ADC_READ_MAX + 1,
+ .shift = 0,
+ .channel = ADC_TEMP_SNS_SKIN_CHANNEL,
+ },
+ [ADC_TEMP_SNS_VR] = {
+ .name = "ADC_TEMP_SNS_VR",
+ .factor_mul = ADC_MAX_MVOLT,
+ .factor_div = ADC_READ_MAX + 1,
+ .shift = 0,
+ .channel = ADC_TEMP_SNS_VR_CHANNEL,
+ },
+};
+BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);
+
+#ifdef CONFIG_TEMP_SENSOR
+/* Temperature sensors */
+const struct temp_sensor_t temp_sensors[] = {
+ [TEMP_SNS_AMBIENT] = {
+ .name = "Ambient",
+ .type = TEMP_SENSOR_TYPE_BOARD,
+ .read = get_temp_3v0_22k6_47k_4050b,
+ .idx = ADC_TEMP_SNS_AMBIENT,
+ .action_delay_sec = 5,
+ },
+ [TEMP_SNS_BATTERY] = {
+ .name = "Battery",
+ .type = TEMP_SENSOR_TYPE_BATTERY,
+ .read = charge_get_battery_temp,
+ .idx = 0,
+ .action_delay_sec = 1,
+ },
+ [TEMP_SNS_DDR] = {
+ .name = "DDR",
+ .type = TEMP_SENSOR_TYPE_BOARD,
+ .read = get_temp_3v0_22k6_47k_4050b,
+ .idx = ADC_TEMP_SNS_DDR,
+ .action_delay_sec = 1,
+ },
+#ifdef CONFIG_PECI
+ [TEMP_SNS_PECI] = {
+ .name = "PECI",
+ .type = TEMP_SENSOR_TYPE_CPU,
+ .read = peci_temp_sensor_get_val,
+ .idx = 0,
+ .action_delay_sec = 1,
+ },
+#endif /* CONFIG_PECI */
+ [TEMP_SNS_SKIN] = {
+ .name = "Skin",
+ .type = TEMP_SENSOR_TYPE_BOARD,
+ .read = get_temp_3v0_22k6_47k_4050b,
+ .idx = ADC_TEMP_SNS_SKIN,
+ .action_delay_sec = 1,
+ },
+ [TEMP_SNS_VR] = {
+ .name = "VR",
+ .type = TEMP_SENSOR_TYPE_BOARD,
+ .read = get_temp_3v0_22k6_47k_4050b,
+ .idx = ADC_TEMP_SNS_VR,
+ .action_delay_sec = 1,
+ },
+};
+BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT);
+#endif /* CONFIG_TEMP_SENSOR */
+
+#ifdef CONFIG_FANS
+/* Physical fan config */
+const struct fan_conf fan_conf_0 = {
+ .flags = FAN_USE_RPM_MODE,
+ .ch = 0,
+ .pgood_gpio = GPIO_ALL_SYS_PWRGD,
+ .enable_gpio = GPIO_FAN_POWER_EN,
+};
+
+/* Physical fan rpm config */
+const struct fan_rpm fan_rpm_0 = {
+ .rpm_min = 3100,
+ .rpm_start = 3100,
+ .rpm_max = 6900,
+};
+
+/* FAN channels */
+struct fan_t fans[] = {
+ [FAN_CH_0] = {
+ .conf = &fan_conf_0,
+ .rpm = &fan_rpm_0,
+ },
+};
+BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT);
+
+const static struct ec_thermal_config thermal_a = {
+ .temp_host = {
+ [EC_TEMP_THRESH_WARN] = 0,
+ [EC_TEMP_THRESH_HIGH] = C_TO_K(75),
+ [EC_TEMP_THRESH_HALT] = C_TO_K(80),
+ },
+ .temp_host_release = {
+ [EC_TEMP_THRESH_WARN] = 0,
+ [EC_TEMP_THRESH_HIGH] = C_TO_K(65),
+ [EC_TEMP_THRESH_HALT] = 0,
+ },
+ .temp_fan_off = C_TO_K(25),
+ .temp_fan_max = C_TO_K(50),
+};
+
+struct ec_thermal_config thermal_params[] = {
+ [TEMP_SNS_AMBIENT] = thermal_a,
+ [TEMP_SNS_BATTERY] = thermal_a,
+ [TEMP_SNS_DDR] = thermal_a,
+#ifdef CONFIG_PECI
+ [TEMP_SNS_PECI] = thermal_a,
+#endif
+ [TEMP_SNS_SKIN] = thermal_a,
+ [TEMP_SNS_VR] = thermal_a,
+};
+BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT);
+#endif /* CONFIG_FANS */
+
+static void board_init(void)
+{
+ /* Enable SOC SPI */
+ gpio_set_level(GPIO_EC_SPI_OE_N, 1);
+}
+DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_LAST);
+
+int ioexpander_read_intelrvp_version(int *port0, int *port1)
+{
+ if (pca9555_read(I2C_PORT_PCA9555_BOARD_ID_GPIO,
+ I2C_ADDR_PCA9555_BOARD_ID_GPIO,
+ PCA9555_CMD_INPUT_PORT_0, port0))
+ return -1;
+
+ return pca9555_read(I2C_PORT_PCA9555_BOARD_ID_GPIO,
+ I2C_ADDR_PCA9555_BOARD_ID_GPIO,
+ PCA9555_CMD_INPUT_PORT_1, port1);
+}
diff --git a/baseboard/intelrvp/baseboard.h b/baseboard/intelrvp/baseboard.h
new file mode 100644
index 0000000000..c8a083c4ed
--- /dev/null
+++ b/baseboard/intelrvp/baseboard.h
@@ -0,0 +1,239 @@
+/* Copyright 2019 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.
+ */
+
+/* Intel BASEBOARD-RVP board-specific configuration */
+
+#ifndef __CROS_EC_BASEBOARD_H
+#define __CROS_EC_BASEBOARD_H
+
+#ifdef CHIP_FAMILY_IT83XX
+#include "ite_ec.h"
+#endif /* CHIP_FAMILY_IT83XX */
+
+/*
+ * Allow dangerous commands.
+ * TODO: Remove this config before production.
+ */
+#define CONFIG_SYSTEM_UNLOCKED
+
+#define CC_DEFAULT (CC_ALL & ~(CC_MASK(CC_EVENTS) | CC_MASK(CC_LPC)))
+#undef CONFIG_HOSTCMD_DEBUG_MODE
+
+/*
+ * By default, enable all console messages excepted HC, ACPI and event:
+ * The sensor stack is generating a lot of activity.
+ */
+#define CONFIG_HOSTCMD_DEBUG_MODE HCDEBUG_OFF
+
+/* EC console commands */
+#define CONFIG_CMD_CHARGER_DUMP
+
+/* Port80 display */
+#define CONFIG_MAX695X_SEVEN_SEGMENT_DISPLAY
+
+/* Battery */
+#define CONFIG_BATTERY_CUT_OFF
+#define CONFIG_BATTERY_FUEL_GAUGE
+#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_L
+#define CONFIG_BATTERY_REVIVE_DISCONNECT
+#define CONFIG_BATTERY_SMART
+
+/* Charger */
+#define CONFIG_CHARGE_MANAGER
+#define CONFIG_CHARGER
+#define CONFIG_CHARGER_DISCHARGE_ON_AC
+#define CONFIG_CHARGER_INPUT_CURRENT 512
+#define CONFIG_CHARGER_SENSE_RESISTOR 5
+#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10
+#define CONFIG_CHARGER_V2
+#undef CONFIG_EXTPOWER_DEBOUNCE_MS
+#define CONFIG_EXTPOWER_DEBOUNCE_MS 200
+#define CONFIG_EXTPOWER_GPIO
+#define CONFIG_TRICKLE_CHARGING
+
+/* Keyboard */
+#define CONFIG_KEYBOARD_BOARD_CONFIG
+#define CONFIG_KEYBOARD_PROTOCOL_8042
+
+/* UART */
+#define CONFIG_LOW_POWER_IDLE
+
+/* USB-A config */
+
+/* BC1.2 config */
+#ifdef HAS_TASK_USB_CHG_P0
+#define CONFIG_CHARGE_RAMP_HW
+#endif
+
+/* USB PD config */
+#define CONFIG_USB_PD_ALT_MODE
+#define CONFIG_USB_PD_ALT_MODE_DFP
+#define CONFIG_USB_PD_DUAL_ROLE
+#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0
+#define CONFIG_USB_PD_TCPM_TCPCI
+#define CONFIG_USB_PD_TRY_SRC
+#define CONFIG_USB_PD_VBUS_MEASURE_NOT_PRESENT
+#define CONFIG_USB_POWER_DELIVERY
+
+/* USB MUX */
+#define CONFIG_USBC_SS_MUX
+
+/* SoC / PCH */
+#define CONFIG_HOSTCMD_ESPI
+#define CONFIG_HOSTCMD_ESPI_VW_SLP_SIGNALS
+#define CONFIG_MKBP_EVENT
+#define CONFIG_MKBP_USE_HOST_EVENT
+#define CONFIG_CHIPSET_RESET_HOOK
+#define CONFIG_POWER_BUTTON
+#define CONFIG_POWER_BUTTON_X86
+#define CONFIG_POWER_COMMON
+#define CONFIG_POWER_S0IX
+#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE
+
+/* EC */
+#define CONFIG_BOARD_VERSION_CUSTOM
+#define CONFIG_LED_COMMON
+#define CONFIG_LID_SWITCH
+#define CONFIG_VOLUME_BUTTONS
+#define CONFIG_WP_ALWAYS
+
+/* Tablet mode */
+#define CONFIG_TABLET_MODE
+#define CONFIG_HALL_SENSOR
+#define HALL_SENSOR_GPIO_L GPIO_TABLET_MODE_L
+
+/* Verified boot */
+#define CONFIG_SHA256_UNROLLED
+#define CONFIG_VBOOT_HASH
+/*
+ * Enable 1 slot of secure temporary storage to support
+ * suspend/resume with read/write memory training.
+ */
+#define CONFIG_VSTORE
+#define CONFIG_VSTORE_SLOT_COUNT 1
+
+/* Temperature sensor */
+#ifdef CONFIG_TEMP_SENSOR
+#define CONFIG_STEINHART_HART_3V0_22K6_47K_4050B
+#define CONFIG_THERMISTOR
+#define CONFIG_THROTTLE_AP
+#ifdef CONFIG_PECI
+#define CONFIG_PECI_COMMON
+#endif
+#endif
+
+/* Fan features */
+#ifdef CONFIG_FANS
+#undef CONFIG_FAN_INIT_SPEED
+#define CONFIG_FAN_INIT_SPEED 50
+#endif
+
+/* I2C ports */
+#define CONFIG_I2C
+#define CONFIG_I2C_MASTER
+
+/* EC exclude modules */
+#undef CONFIG_WATCHDOG
+
+#ifndef __ASSEMBLER__
+
+#include "gpio_signal.h"
+#include "registers.h"
+#include "usb_pd_tcpm.h"
+
+enum power_signal {
+ X86_SLP_S0_DEASSERTED,
+ X86_SLP_S3_DEASSERTED,
+ X86_SLP_S4_DEASSERTED,
+ X86_RSMRST_L_PGOOD,
+ X86_ALL_SYS_PWRGD,
+#if defined(CONFIG_CHIPSET_ICELAKE)
+ X86_SLP_SUS_DEASSERTED,
+ X86_DSW_DPWROK,
+#elif defined(CONFIG_CHIPSET_COMETLAKE)
+ PP5000_A_PGOOD,
+#else
+ #error "define Intel AP chipset variant"
+#endif
+ /* Number of X86 signals */
+ POWER_SIGNAL_COUNT
+};
+
+/* PWM channels */
+enum pwm_channel {
+ PWM_CH_FAN,
+ PWM_CH_COUNT
+};
+
+/* FAN channels */
+enum fan_channel {
+ FAN_CH_0,
+ FAN_CH_COUNT,
+};
+
+/* ADC channels */
+enum adc_channel {
+ ADC_TEMP_SNS_AMBIENT,
+ ADC_TEMP_SNS_DDR,
+ ADC_TEMP_SNS_SKIN,
+ ADC_TEMP_SNS_VR,
+ ADC_CH_COUNT,
+};
+
+/* Temperature sensors */
+enum temp_sensor_id {
+ TEMP_SNS_AMBIENT,
+ TEMP_SNS_BATTERY,
+ TEMP_SNS_DDR,
+ TEMP_SNS_PECI,
+ TEMP_SNS_SKIN,
+ TEMP_SNS_VR,
+ TEMP_SENSOR_COUNT,
+};
+
+/* List of supported batteries */
+enum battery_type {
+ BATTERY_SIMPLO_SMP_HHP_408,
+ BATTERY_SIMPLO_SMP_CA_445,
+ BATTERY_TYPE_COUNT,
+};
+
+/* TODO(b:132652892): Verify the below numbers. */
+#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */
+#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */
+
+/* Define typical operating power */
+#define PD_OPERATING_POWER_MW 15000
+#define PD_MAX_CURRENT_MA 3000
+#define PD_MAX_VOLTAGE_MV 20000
+#define DC_JACK_MAX_VOLTAGE_MV 19000
+
+/* TCPC gpios */
+struct tcpc_gpio_t {
+ enum gpio_signal pin;
+ uint8_t pin_pol;
+};
+
+struct tcpc_gpio_config_t {
+ /* VBUS interrput */
+ struct tcpc_gpio_t vbus;
+ /* Source enable */
+ struct tcpc_gpio_t src;
+ /* Sink enable */
+ struct tcpc_gpio_t snk;
+};
+extern const struct tcpc_gpio_config_t tcpc_gpios[];
+
+/* Reset PD MCU */
+void board_reset_pd_mcu(void);
+void vbus0_evt(enum gpio_signal signal);
+void vbus1_evt(enum gpio_signal signal);
+void board_charging_enable(int port, int enable);
+void board_vbus_enable(int port, int enable);
+int ioexpander_read_intelrvp_version(int *port0, int *port1);
+
+#endif /* !__ASSEMBLER__ */
+
+#endif /* __CROS_EC_BASEBOARD_H */
diff --git a/baseboard/intelrvp/battery.c b/baseboard/intelrvp/battery.c
new file mode 100644
index 0000000000..cf4464ce55
--- /dev/null
+++ b/baseboard/intelrvp/battery.c
@@ -0,0 +1,79 @@
+/* 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.
+ *
+ * Battery pack vendor provided charging profile
+ */
+
+#include "battery_fuel_gauge.h"
+#include "battery_smart.h"
+#include "common.h"
+#include "util.h"
+
+const struct board_batt_params board_battery_info[] = {
+ /*
+ * Simplo Battery (SMP-HHP-408) Information
+ * Fuel gauge: BQ40Z50
+ */
+ [BATTERY_SIMPLO_SMP_HHP_408] = {
+ .fuel_gauge = {
+ .manuf_name = "SMP-HHP-408",
+ .ship_mode = {
+ .reg_addr = 0x00,
+ .reg_data = { 0x0010, 0x0010 },
+ },
+ .fet = {
+ .reg_addr = SB_BATTERY_STATUS,
+ .reg_mask = STATUS_INITIALIZED,
+ .disconnect_val = 0x0,
+ }
+ },
+ .batt_info = {
+ .voltage_max = 8700, /* mV */
+ .voltage_normal = 7600,
+ .voltage_min = 6100,
+ .precharge_current = 204, /* mA */
+ .start_charging_min_c = 0,
+ .start_charging_max_c = 45,
+ .charging_min_c = 0,
+ .charging_max_c = 45,
+ .discharging_min_c = 0,
+ .discharging_max_c = 60,
+ },
+ },
+
+ /*
+ * Simplo Battery (SMP-CA-445) Information
+ * Fuel gauge: BQ30Z554
+ * TODO: SYSCROS-25972
+ */
+ [BATTERY_SIMPLO_SMP_CA_445] = {
+ .fuel_gauge = {
+ .manuf_name = "SMP-CA-445",
+ .ship_mode = {
+ .reg_addr = 0x00,
+ .reg_data = { 0x0010, 0x0010 },
+ },
+ .fet = {
+ .reg_addr = SB_BATTERY_STATUS,
+ .reg_mask = STATUS_INITIALIZED,
+ .disconnect_val = 0x0,
+ }
+ },
+ .batt_info = {
+ .voltage_max = 8700, /* mV */
+ .voltage_normal = 7600,
+ .voltage_min = 6100,
+ .precharge_current = 150, /* mA */
+ .start_charging_min_c = 0,
+ .start_charging_max_c = 45,
+ .charging_min_c = 0,
+ .charging_max_c = 45,
+ .discharging_min_c = -20,
+ .discharging_max_c = 60,
+ },
+ },
+};
+BUILD_ASSERT(ARRAY_SIZE(board_battery_info) == BATTERY_TYPE_COUNT);
+
+const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_SIMPLO_SMP_HHP_408;
diff --git a/baseboard/intelrvp/bc12.c b/baseboard/intelrvp/bc12.c
new file mode 100644
index 0000000000..4f1d1808cc
--- /dev/null
+++ b/baseboard/intelrvp/bc12.c
@@ -0,0 +1,28 @@
+/* Copyright 2019 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.
+ */
+
+/* Intel BASEBOARD-RVP BC1.2 specific configuration */
+
+#include "common.h"
+#include "max14637.h"
+
+/* BC1.2 chip Configuration */
+#ifdef CONFIG_BC12_DETECT_MAX14637
+const struct max14637_config_t max14637_config[CONFIG_USB_PD_PORT_COUNT] = {
+ [TYPE_C_PORT_0] = {
+ .chip_enable_pin = GPIO_USB_C0_BC12_VBUS_ON_ODL,
+ .chg_det_pin = GPIO_USB_C0_BC12_CHG_DET_L,
+ .flags = MAX14637_FLAGS_CHG_DET_ACTIVE_LOW,
+ },
+#ifdef HAS_TASK_PD_C1
+ [TYPE_C_PORT_1] = {
+ .chip_enable_pin = GPIO_USB_C1_BC12_VBUS_ON_ODL,
+ .chg_det_pin = GPIO_USB_C1_BC12_CHG_DET_L,
+ .flags = MAX14637_FLAGS_CHG_DET_ACTIVE_LOW,
+ },
+#endif /* HAS_TASK_PD_C1 */
+};
+BUILD_ASSERT(ARRAY_SIZE(max14637_config) == CONFIG_USB_PD_PORT_COUNT);
+#endif /* CONFIG_BC12_DETECT_MAX14637 */
diff --git a/baseboard/intelrvp/build.mk b/baseboard/intelrvp/build.mk
new file mode 100644
index 0000000000..bfbd86abce
--- /dev/null
+++ b/baseboard/intelrvp/build.mk
@@ -0,0 +1,28 @@
+# -*- makefile -*-
+# 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.
+#
+# Baseboard specific files build
+#
+
+#Intel RVP common files
+baseboard-y=baseboard.o
+baseboard-$(CONFIG_LED_COMMON)+=led.o led_states.o
+baseboard-$(CONFIG_BATTERY_SMART)+=battery.o
+baseboard-$(CONFIG_USB_POWER_DELIVERY)+=chg_usb_pd.o usb_pd_policy.o
+
+#EC specific files
+baseboard-$(CONFIG_USB_PD_TCPM_ITE83XX)+=ite_ec.o
+
+#BC1.2 specific files
+baseboard-$(CONFIG_BC12_DETECT_MAX14637)+=bc12.o
+
+#USB MUX specific files
+baseboard-$(CONFIG_USB_MUX_VIRTUAL)+=usb_mux.o
+
+#USB Retimer specific files
+baseboard-$(CONFIG_USB_PD_RETIMER_INTEL_BB)+=retimer.o
+
+#VBUS detection specific files
+baseboard-$(CONFIG_USB_PD_VBUS_DETECT_GPIO)+=vbus.o
diff --git a/baseboard/intelrvp/chg_usb_pd.c b/baseboard/intelrvp/chg_usb_pd.c
new file mode 100644
index 0000000000..052fe1caca
--- /dev/null
+++ b/baseboard/intelrvp/chg_usb_pd.c
@@ -0,0 +1,167 @@
+/* Copyright 2019 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.
+ */
+
+/* Intel-RVP family-specific configuration */
+
+#include "charge_manager.h"
+#include "charge_state_v2.h"
+#include "console.h"
+#include "hooks.h"
+#include "tcpci.h"
+#include "system.h"
+
+#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
+
+static int board_charger_port_is_sourcing_vbus(int port)
+{
+ int src_en;
+
+ /* DC Jack can't source VBUS */
+ if (port == DC_JACK_PORT_0 || port == CHARGE_PORT_NONE)
+ return 0;
+
+ src_en = gpio_get_level(tcpc_gpios[port].src.pin);
+
+ return tcpc_gpios[port].src.pin_pol ? src_en : !src_en;
+}
+
+void board_charging_enable(int port, int enable)
+{
+ gpio_set_level(tcpc_gpios[port].snk.pin,
+ tcpc_gpios[port].snk.pin_pol ? enable : !enable);
+
+}
+
+void board_vbus_enable(int port, int enable)
+{
+ gpio_set_level(tcpc_gpios[port].src.pin,
+ tcpc_gpios[port].src.pin_pol ? enable : !enable);
+}
+
+int pd_snk_is_vbus_provided(int port)
+{
+ int vbus_intr;
+
+ if (port == DC_JACK_PORT_0)
+ return 1;
+
+ vbus_intr = gpio_get_level(tcpc_gpios[port].vbus.pin);
+
+ return tcpc_gpios[port].vbus.pin_pol ? vbus_intr : !vbus_intr;
+}
+
+void tcpc_alert_event(enum gpio_signal signal)
+{
+#ifdef HAS_TASK_PDCMD
+ /* Exchange status with TCPCs */
+ host_command_pd_send_status(PD_CHARGE_NO_CHANGE);
+#endif
+}
+
+void board_tcpc_init(void)
+{
+ int i;
+
+ /* Only reset TCPC if not sysjump */
+ if (!system_jumped_to_this_image())
+ board_reset_pd_mcu();
+
+ /* Enable TCPCx interrupt */
+ for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++)
+ gpio_enable_interrupt(tcpc_gpios[i].vbus.pin);
+}
+DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1);
+
+static inline int board_dc_jack_present(void)
+{
+ return gpio_get_level(GPIO_DC_JACK_PRESENT);
+}
+
+static void board_dc_jack_handle(void)
+{
+ struct charge_port_info charge_dc_jack;
+
+ /* System is booted from DC Jack */
+ if (board_dc_jack_present()) {
+ charge_dc_jack.current = (PD_MAX_POWER_MW * 1000) /
+ DC_JACK_MAX_VOLTAGE_MV;
+ charge_dc_jack.voltage = DC_JACK_MAX_VOLTAGE_MV;
+ } else {
+ charge_dc_jack.current = 0;
+ charge_dc_jack.voltage = USB_CHARGER_VOLTAGE_MV;
+ }
+
+ charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED,
+ DC_JACK_PORT_0, &charge_dc_jack);
+}
+DECLARE_HOOK(HOOK_AC_CHANGE, board_dc_jack_handle, HOOK_PRIO_FIRST);
+
+static void board_charge_init(void)
+{
+ int port, supplier;
+ struct charge_port_info charge_init = {
+ .current = 0,
+ .voltage = USB_CHARGER_VOLTAGE_MV,
+ };
+
+ /* Initialize all charge suppliers to seed the charge manager */
+ for (port = 0; port < CHARGE_PORT_COUNT; port++) {
+ for (supplier = 0; supplier < CHARGE_SUPPLIER_COUNT; supplier++)
+ charge_manager_update_charge(supplier, port,
+ &charge_init);
+ }
+
+ board_dc_jack_handle();
+}
+DECLARE_HOOK(HOOK_INIT, board_charge_init, HOOK_PRIO_DEFAULT);
+
+int board_set_active_charge_port(int port)
+{
+ int i;
+ /* charge port is a realy physical port */
+ int is_real_port = (port >= 0 &&
+ port < CHARGE_PORT_COUNT);
+ /* check if we are source vbus on that port */
+ int source = board_charger_port_is_sourcing_vbus(port);
+
+ if (is_real_port && source) {
+ CPRINTS("Skip enable p%d", port);
+ return EC_ERROR_INVAL;
+ }
+
+ /*
+ * Do not enable Type-C port if the DC Jack is present.
+ * When the Type-C is active port, hardware circuit will
+ * block DC jack from enabling +VADP_OUT.
+ */
+ if (port != DC_JACK_PORT_0 && board_dc_jack_present()) {
+ CPRINTS("DC Jack present, Skip enable p%d", port);
+ return EC_ERROR_INVAL;
+ }
+
+ /* Make sure non-charging ports are disabled */
+ for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) {
+ if (i == port)
+ continue;
+
+ board_charging_enable(i, 0);
+ }
+
+ /* Enable charging port */
+ if (port != DC_JACK_PORT_0 && port != CHARGE_PORT_NONE)
+ board_charging_enable(port, 1);
+
+ CPRINTS("New chg p%d", port);
+
+ return EC_SUCCESS;
+}
+
+void board_set_charge_limit(int port, int supplier, int charge_ma,
+ int max_ma, int charge_mv)
+{
+ charge_set_input_current_limit(MAX(charge_ma,
+ CONFIG_CHARGER_INPUT_CURRENT), charge_mv);
+}
diff --git a/baseboard/intelrvp/ite_ec.c b/baseboard/intelrvp/ite_ec.c
new file mode 100644
index 0000000000..d6640bf10f
--- /dev/null
+++ b/baseboard/intelrvp/ite_ec.c
@@ -0,0 +1,90 @@
+/* Copyright 2019 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.
+ */
+
+/* Intel BASEBOARD-RVP ITE EC specific configuration */
+
+#include "common.h"
+#include "it83xx_pd.h"
+#include "keyboard_scan.h"
+#include "pwm.h"
+#include "pwm_chip.h"
+#include "timer.h"
+#include "usb_pd_tcpm.h"
+
+/* USB-C TPCP Configuration */
+const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_COUNT] = {
+ [TYPE_C_PORT_0] = {
+ /* TCPC is embedded within EC so no i2c config needed */
+ .drv = &it83xx_tcpm_drv,
+ },
+#ifdef HAS_TASK_PD_C1
+ [TYPE_C_PORT_1] = {
+ /* TCPC is embedded within EC so no i2c config needed */
+ .drv = &it83xx_tcpm_drv,
+ },
+#endif /* HAS_TASK_PD_C1 */
+};
+BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == CONFIG_USB_PD_PORT_COUNT);
+
+/* Reset PD MCU */
+void board_reset_pd_mcu(void)
+{
+ /* Not applicable for ITE TCPC */
+}
+
+uint16_t tcpc_get_alert_status(void)
+{
+ /*
+ * Since C0/C1 TCPC are embedded within EC, we don't need the
+ * PDCMD tasks. The (embedded) TCPC status since chip driver
+ * code handles its own interrupts and forward the correct
+ * events to the PD_C0 task. See it83xx/intc.c
+ */
+
+ return 0;
+}
+
+/* Keyboard scan setting */
+struct keyboard_scan_config keyscan_config = {
+ .output_settle_us = 35,
+ .debounce_down_us = 5 * MSEC,
+ .debounce_up_us = 40 * MSEC,
+ .scan_period_us = 3 * MSEC,
+ .min_post_scan_delay_us = 1000,
+ .poll_timeout_us = 100 * MSEC,
+ .actual_key_mask = {
+ 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff,
+ 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */
+ },
+};
+
+/*
+ * PWM HW channelx binding tachometer channelx for fan control.
+ * Four tachometer input pins but two tachometer modules only,
+ * so always binding [TACH_CH_TACH0A | TACH_CH_TACH0B] and/or
+ * [TACH_CH_TACH1A | TACH_CH_TACH1B]
+ */
+const struct fan_tach_t fan_tach[] = {
+ {TACH_CH_NULL, -1, -1, -1},
+ {TACH_CH_NULL, -1, -1, -1},
+ {TACH_CH_NULL, -1, -1, -1},
+ {TACH_CH_NULL, -1, -1, -1},
+ {TACH_CH_NULL, -1, -1, -1},
+ {TACH_CH_NULL, -1, -1, -1},
+ {TACH_CH_NULL, -1, -1, -1},
+ {TACH_CH_TACH1A, 2, 50, 30},
+};
+BUILD_ASSERT(ARRAY_SIZE(fan_tach) == PWM_HW_CH_TOTAL);
+
+/* PWM channels */
+const struct pwm_t pwm_channels[] = {
+ [PWM_CH_FAN] = {
+ .channel = PWM_HW_CH_DCR2,
+ .flags = PWM_CONFIG_ACTIVE_LOW,
+ .freq_hz = 30000,
+ .pcfsr_sel = PWM_PRESCALER_C4,
+ },
+};
+BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT);
diff --git a/baseboard/intelrvp/ite_ec.h b/baseboard/intelrvp/ite_ec.h
new file mode 100644
index 0000000000..c233f1ef89
--- /dev/null
+++ b/baseboard/intelrvp/ite_ec.h
@@ -0,0 +1,24 @@
+/* Copyright 2019 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.
+ */
+
+/* Intel BASEBOARD-RVP ITE EC specific configuration */
+
+#ifndef __CROS_EC_ITE_EC_H
+#define __CROS_EC_ITE_EC_H
+
+/* USB PD config */
+#define CONFIG_USB_PD_TCPM_ITE83XX
+#define CONFIG_USB_PD_VBUS_DETECT_GPIO
+
+/* Optional feature - used by ITE */
+#define CONFIG_IT83XX_FLASH_CLOCK_48MHZ
+
+/* ADC channels */
+#define ADC_TEMP_SNS_AMBIENT_CHANNEL CHIP_ADC_CH13
+#define ADC_TEMP_SNS_DDR_CHANNEL CHIP_ADC_CH15
+#define ADC_TEMP_SNS_SKIN_CHANNEL CHIP_ADC_CH6
+#define ADC_TEMP_SNS_VR_CHANNEL CHIP_ADC_CH1
+
+#endif /* __CROS_EC_ITE_EC_H */
diff --git a/baseboard/intelrvp/led.c b/baseboard/intelrvp/led.c
new file mode 100644
index 0000000000..8e98f8e10f
--- /dev/null
+++ b/baseboard/intelrvp/led.c
@@ -0,0 +1,109 @@
+/* Copyright 2019 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.
+ *
+ * Power and battery LED control for Phaser
+ */
+
+#include "chipset.h"
+#include "ec_commands.h"
+#include "gpio.h"
+#include "led_common.h"
+#include "led_states.h"
+
+#define LED_ON_LVL 0
+#define LED_OFF_LVL 1
+
+#define GPIO_BAT_LED_RED_L GPIO_BAT_LED_GREEN_L
+#define GPIO_PWR_LED_WHITE_L GPIO_AC_LED_GREEN_L
+
+const int led_charge_lvl_1 = 5;
+
+const int led_charge_lvl_2 = 97;
+
+struct led_descriptor led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = {
+ [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} },
+ [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} },
+ [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} },
+ [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} },
+ [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} },
+ [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} },
+ [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC},
+ {LED_OFF, 1 * LED_ONE_SEC} },
+ [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC},
+ {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} },
+};
+
+const struct led_descriptor
+ led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = {
+ [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} },
+ [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC},
+ {LED_OFF, 1 * LED_ONE_SEC} },
+ [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} },
+};
+
+const enum ec_led_id supported_led_ids[] = {
+ EC_LED_ID_POWER_LED,
+ EC_LED_ID_BATTERY_LED
+};
+
+const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids);
+
+void led_set_color_power(enum ec_led_colors color)
+{
+ if (color == EC_LED_COLOR_WHITE)
+ gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_ON_LVL);
+ else
+ /* LED_OFF and unsupported colors */
+ gpio_set_level(GPIO_PWR_LED_WHITE_L, LED_OFF_LVL);
+}
+
+void led_set_color_battery(enum ec_led_colors color)
+{
+ switch (color) {
+ case EC_LED_COLOR_RED:
+ gpio_set_level(GPIO_BAT_LED_RED_L, LED_ON_LVL);
+ break;
+ case EC_LED_COLOR_AMBER:
+ gpio_set_level(GPIO_BAT_LED_RED_L, LED_ON_LVL);
+ break;
+ case EC_LED_COLOR_GREEN:
+ gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL);
+ break;
+ default: /* LED_OFF and other unsupported colors */
+ gpio_set_level(GPIO_BAT_LED_RED_L, LED_OFF_LVL);
+ break;
+ }
+}
+
+void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range)
+{
+ if (led_id == EC_LED_ID_BATTERY_LED) {
+ brightness_range[EC_LED_COLOR_RED] = 1;
+ brightness_range[EC_LED_COLOR_AMBER] = 1;
+ brightness_range[EC_LED_COLOR_GREEN] = 1;
+ } else if (led_id == EC_LED_ID_POWER_LED) {
+ brightness_range[EC_LED_COLOR_WHITE] = 1;
+ }
+}
+
+int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness)
+{
+ if (led_id == EC_LED_ID_BATTERY_LED) {
+ if (brightness[EC_LED_COLOR_RED] != 0)
+ led_set_color_battery(EC_LED_COLOR_RED);
+ else if (brightness[EC_LED_COLOR_AMBER] != 0)
+ led_set_color_battery(EC_LED_COLOR_AMBER);
+ else if (brightness[EC_LED_COLOR_GREEN] != 0)
+ led_set_color_battery(EC_LED_COLOR_GREEN);
+ else
+ led_set_color_battery(LED_OFF);
+ } else if (led_id == EC_LED_ID_POWER_LED) {
+ if (brightness[EC_LED_COLOR_WHITE] != 0)
+ led_set_color_power(EC_LED_COLOR_WHITE);
+ else
+ led_set_color_power(LED_OFF);
+ }
+
+ return EC_SUCCESS;
+}
diff --git a/baseboard/intelrvp/led_states.c b/baseboard/intelrvp/led_states.c
new file mode 100644
index 0000000000..5f8768bdd9
--- /dev/null
+++ b/baseboard/intelrvp/led_states.c
@@ -0,0 +1,188 @@
+/* Copyright 2019 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.
+ *
+ * Power and battery LED state control for octopus boards
+ */
+
+#include "battery.h"
+#include "charge_state.h"
+#include "chipset.h"
+#include "console.h"
+#include "ec_commands.h"
+#include "extpower.h"
+#include "hooks.h"
+#include "led_common.h"
+#include "led_states.h"
+
+#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args)
+
+static enum led_states led_get_state(void)
+{
+ int charge_lvl;
+ enum led_states new_state = LED_NUM_STATES;
+
+ switch (charge_get_state()) {
+ case PWR_STATE_CHARGE:
+ /* Get percent charge */
+ charge_lvl = charge_get_percent();
+ /* Determine which charge state to use */
+ if (charge_lvl < led_charge_lvl_1)
+ new_state = STATE_CHARGING_LVL_1;
+ else if (charge_lvl < led_charge_lvl_2)
+ new_state = STATE_CHARGING_LVL_2;
+ else
+ new_state = STATE_CHARGING_FULL_CHARGE;
+ break;
+ case PWR_STATE_DISCHARGE_FULL:
+ if (extpower_is_present()) {
+ new_state = STATE_CHARGING_FULL_CHARGE;
+ break;
+ }
+ /* Intentional fall-through */
+ case PWR_STATE_DISCHARGE /* and PWR_STATE_DISCHARGE_FULL */:
+ if (chipset_in_state(CHIPSET_STATE_ON))
+ new_state = STATE_DISCHARGE_S0;
+ else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND))
+ new_state = STATE_DISCHARGE_S3;
+ else
+ new_state = STATE_DISCHARGE_S5;
+ break;
+ case PWR_STATE_ERROR:
+ new_state = STATE_BATTERY_ERROR;
+ break;
+ case PWR_STATE_CHARGE_NEAR_FULL:
+ new_state = STATE_CHARGING_FULL_CHARGE;
+ break;
+ case PWR_STATE_IDLE: /* External power connected in IDLE */
+ if (charge_get_flags() & CHARGE_FLAG_FORCE_IDLE)
+ new_state = STATE_FACTORY_TEST;
+ else
+ new_state = STATE_DISCHARGE_S0;
+ break;
+ default:
+ /* Other states don't alter LED behavior */
+ break;
+ }
+
+ return new_state;
+}
+
+static void led_update_battery(void)
+{
+ static uint8_t ticks, period;
+ static int led_state = LED_NUM_STATES;
+ int phase;
+ enum led_states desired_state = led_get_state();
+
+ /*
+ * We always need to check the current state since the value could
+ * have been manually overwritten. If we're in a new valid state,
+ * update our ticks and period info. If our new state isn't defined,
+ * continue using the previous one.
+ */
+ if (desired_state != led_state && desired_state < LED_NUM_STATES) {
+ /* State is changing */
+ led_state = desired_state;
+ /* Reset ticks and period when state changes */
+ ticks = 0;
+
+ period = led_bat_state_table[led_state][LED_PHASE_0].time +
+ led_bat_state_table[led_state][LED_PHASE_1].time;
+
+ }
+
+ /* If this state is undefined, turn the LED off */
+ if (period == 0) {
+ CPRINTS("Undefined LED behavior for battery state %d,"
+ "turning off LED", led_state);
+ led_set_color_battery(LED_OFF);
+ return;
+ }
+
+ /*
+ * Determine which phase of the state table to use. The phase is
+ * determined if it falls within first phase time duration.
+ */
+ phase = ticks < led_bat_state_table[led_state][LED_PHASE_0].time ?
+ 0 : 1;
+ ticks = (ticks + 1) % period;
+
+ /* Set the color for the given state and phase */
+ led_set_color_battery(led_bat_state_table[led_state][phase].color);
+}
+
+static enum pwr_led_states pwr_led_get_state(void)
+{
+ if (extpower_is_present()) {
+ if (charge_get_state() == PWR_STATE_CHARGE_NEAR_FULL)
+ return PWR_LED_STATE_OFF;
+ else
+ return PWR_LED_STATE_ON;
+ } else
+ return PWR_LED_STATE_SUSPEND_AC;
+}
+
+static void led_update_power(void)
+{
+ static uint8_t ticks, period;
+ static enum pwr_led_states led_state = PWR_LED_NUM_STATES;
+ int phase;
+ enum pwr_led_states desired_state = pwr_led_get_state();
+
+ /*
+ * If we're in a new valid state, update our ticks and period info.
+ * Otherwise, continue to use old state
+ */
+ if (desired_state != led_state && desired_state < PWR_LED_NUM_STATES) {
+ /* State is changing */
+ led_state = desired_state;
+ /* Reset ticks and period when state changes */
+ ticks = 0;
+
+ period = led_pwr_state_table[led_state][LED_PHASE_0].time +
+ led_pwr_state_table[led_state][LED_PHASE_1].time;
+
+ }
+
+ /* If this state is undefined, turn the LED off */
+ if (period == 0) {
+ CPRINTS("Undefined LED behavior for power state %d,"
+ "turning off LED", led_state);
+ led_set_color_power(LED_OFF);
+ return;
+ }
+
+ /*
+ * Determine which phase of the state table to use. The phase is
+ * determined if it falls within first phase time duration.
+ */
+ phase = ticks < led_pwr_state_table[led_state][LED_PHASE_0].time ?
+ 0 : 1;
+ ticks = (ticks + 1) % period;
+
+ /* Set the color for the given state and phase */
+ led_set_color_power(led_pwr_state_table[led_state][phase].color);
+}
+
+static void led_init(void)
+{
+ /* If battery LED is enabled, set it to "off" to start with */
+ if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED))
+ led_set_color_battery(LED_OFF);
+}
+DECLARE_HOOK(HOOK_INIT, led_init, HOOK_PRIO_DEFAULT);
+
+/* Called by hook task every hook tick (200 msec) */
+static void led_update(void)
+{
+ /*
+ * If battery LED is enabled, set its state based on our power and
+ * charge
+ */
+ if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED))
+ led_update_battery();
+ if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED))
+ led_update_power();
+}
+DECLARE_HOOK(HOOK_TICK, led_update, HOOK_PRIO_DEFAULT);
diff --git a/baseboard/intelrvp/led_states.h b/baseboard/intelrvp/led_states.h
new file mode 100644
index 0000000000..907ff5c8b8
--- /dev/null
+++ b/baseboard/intelrvp/led_states.h
@@ -0,0 +1,90 @@
+/* Copyright 2019 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.
+ *
+ * Common functions for stateful LEDs (charger and power)
+ */
+
+#ifndef __CROS_EC_BASEBOARD_LED_H
+#define __CROS_EC_BASEBOARD_LED_H
+
+#include "ec_commands.h"
+
+#define LED_INDEFINITE UINT8_MAX
+#define LED_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS)
+#define LED_OFF EC_LED_COLOR_COUNT
+
+/*
+ * All LED states should have one phase defined,
+ * and an additional phase can be defined for blinking
+ */
+enum led_phase {
+ LED_PHASE_0,
+ LED_PHASE_1,
+ LED_NUM_PHASES
+};
+
+/*
+ * STATE_CHARGING_LVL_1 is when 0 <= charge_percentage < led_charge_level_1
+ *
+ * STATE_CHARGING_LVL_2 is when led_charge_level_1 <=
+ * charge_percentage < led_charge_level_2
+ *
+ * STATE_CHARGING_FULL_CHARGE is when led_charge_level_2 <=
+ * charge_percentage < 100
+ */
+enum led_states {
+ STATE_CHARGING_LVL_1,
+ STATE_CHARGING_LVL_2,
+ STATE_CHARGING_FULL_CHARGE,
+ STATE_DISCHARGE_S0,
+ STATE_DISCHARGE_S0_BAT_LOW,
+ STATE_DISCHARGE_S3,
+ STATE_DISCHARGE_S5,
+ STATE_BATTERY_ERROR,
+ STATE_FACTORY_TEST,
+ LED_NUM_STATES
+};
+
+struct led_descriptor {
+ enum ec_led_colors color;
+ uint8_t time;
+};
+
+
+/* Charging LED state table - defined in board's led.c */
+extern struct led_descriptor
+ led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES];
+
+/* Charging LED state level 1 - defined in board's led.c */
+extern const int led_charge_lvl_1;
+
+/* Charging LED state level 2 - defined in board's led.c */
+extern const int led_charge_lvl_2;
+
+enum pwr_led_states {
+ PWR_LED_STATE_ON,
+ PWR_LED_STATE_SUSPEND_AC,
+ PWR_LED_STATE_SUSPEND_NO_AC,
+ PWR_LED_STATE_OFF,
+ PWR_LED_NUM_STATES
+};
+
+/* Power LED state table - defined in board's led.c */
+extern const struct led_descriptor
+ led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES];
+
+/**
+ * Set battery LED color - defined in board's led.c
+ *
+ * @param color Color to set on battery LED
+ *
+ */
+void led_set_color_battery(enum ec_led_colors color);
+
+/**
+ * Set power LED color - defined in board's led.c
+ */
+void led_set_color_power(enum ec_led_colors color);
+
+#endif /* __CROS_EC_BASEBOARD_LED_H */
diff --git a/baseboard/intelrvp/retimer.c b/baseboard/intelrvp/retimer.c
new file mode 100644
index 0000000000..4317924d41
--- /dev/null
+++ b/baseboard/intelrvp/retimer.c
@@ -0,0 +1,32 @@
+/* Copyright 2019 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.
+ */
+
+/* Intel BASEBOARD-RVP Retimer specific configuration */
+
+#include "bb_retimer.h"
+#include "common.h"
+
+/* USB Retimers configuration */
+#ifdef CONFIG_USB_PD_RETIMER_INTEL_BB
+struct bb_retimer bb_retimers[CONFIG_USB_PD_PORT_COUNT] = {
+ [TYPE_C_PORT_0] = {
+ .i2c_port = I2C_PORT0_BB_RETIMER,
+ .i2c_addr = I2C_PORT0_BB_RETIMER_ADDR,
+ .usb_ls_en_gpio = GPIO_USB_C0_LS_EN,
+ .retimer_rst_gpio = GPIO_USB_C0_RETIMER_RST,
+ .force_power_gpio = GPIO_USB_C0_RETIMER_FORCE_PWR,
+ },
+#ifdef HAS_TASK_PD_C1
+ [TYPE_C_PORT_1] = {
+ .i2c_port = I2C_PORT1_BB_RETIMER,
+ .i2c_addr = I2C_PORT1_BB_RETIMER_ADDR,
+ .usb_ls_en_gpio = GPIO_USB_C1_LS_EN,
+ .retimer_rst_gpio = GPIO_USB_C1_RETIMER_RST,
+ .force_power_gpio = GPIO_USB_C1_RETIMER_FORCE_PWR,
+ },
+#endif /* HAS_TASK_PD_C1 */
+};
+BUILD_ASSERT(ARRAY_SIZE(bb_retimers) == CONFIG_USB_PD_PORT_COUNT);
+#endif /* CONFIG_USB_PD_RETIMER_INTEL_BB */
diff --git a/baseboard/intelrvp/usb_mux.c b/baseboard/intelrvp/usb_mux.c
new file mode 100644
index 0000000000..e4e45de188
--- /dev/null
+++ b/baseboard/intelrvp/usb_mux.c
@@ -0,0 +1,26 @@
+/* Copyright 2019 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.
+ */
+
+/* Intel BASEBOARD-RVP USB MUX specific configuration */
+
+#include "common.h"
+#include "usb_mux.h"
+
+/* USB muxes Configuration */
+#ifdef CONFIG_USB_MUX_VIRTUAL
+struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_COUNT] = {
+ [TYPE_C_PORT_0] = {
+ .driver = &virtual_usb_mux_driver,
+ .hpd_update = &virtual_hpd_update,
+ },
+#ifdef HAS_TASK_PD_C1
+ [TYPE_C_PORT_1] = {
+ .driver = &virtual_usb_mux_driver,
+ .hpd_update = &virtual_hpd_update,
+ },
+#endif /* HAS_TASK_PD_C1 */
+};
+BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == CONFIG_USB_PD_PORT_COUNT);
+#endif /* CONFIG_USB_MUX_VIRTUAL */
diff --git a/baseboard/intelrvp/usb_pd_policy.c b/baseboard/intelrvp/usb_pd_policy.c
new file mode 100644
index 0000000000..b0e3ede29b
--- /dev/null
+++ b/baseboard/intelrvp/usb_pd_policy.c
@@ -0,0 +1,345 @@
+/* Copyright 2019 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.
+ */
+
+#include "console.h"
+#include "gpio.h"
+#include "system.h"
+#include "usb_mux.h"
+
+#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
+
+#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\
+ PDO_FIXED_COMM_CAP)
+
+/* TODO: fill in correct source and sink capabilities */
+const uint32_t pd_src_pdo[] = {
+ PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS),
+};
+const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo);
+const uint32_t pd_src_pdo_max[] = {
+ PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS),
+};
+const int pd_src_pdo_max_cnt = ARRAY_SIZE(pd_src_pdo_max);
+
+const uint32_t pd_snk_pdo[] = {
+ PDO_FIXED(5000, 500, PDO_FIXED_FLAGS),
+ PDO_BATT(4750, 21000, 15000),
+ PDO_VAR(4750, 21000, 3000),
+};
+const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
+
+int pd_is_valid_input_voltage(int mv)
+{
+ return 1;
+}
+
+void pd_transition_voltage(int idx)
+{
+ /* No-operation: we are always 5V */
+}
+
+int pd_set_power_supply_ready(int port)
+{
+ /* Disable charging */
+ board_charging_enable(port, 0);
+
+ /* Provide VBUS */
+ board_vbus_enable(port, 1);
+
+ /* notify host of power info change */
+ pd_send_host_event(PD_EVENT_POWER_CHANGE);
+
+ return EC_SUCCESS; /* we are ready */
+}
+
+void pd_power_supply_reset(int port)
+{
+ /* Disable VBUS */
+ board_vbus_enable(port, 0);
+
+ /* notify host of power info change */
+ pd_send_host_event(PD_EVENT_POWER_CHANGE);
+}
+
+int pd_board_checks(void)
+{
+ return EC_SUCCESS;
+}
+
+int pd_check_power_swap(int port)
+{
+ /*
+ * Allow power swap as long as we are acting as a dual role device,
+ * otherwise assume our role is fixed (not in S0 or console command
+ * to fix our role).
+ */
+ return pd_get_dual_role(port) == PD_DRP_TOGGLE_ON;
+}
+
+int pd_check_data_swap(int port, int data_role)
+{
+ /* Allow data swap if we are a UFP, otherwise don't allow */
+ return (data_role == PD_ROLE_UFP);
+}
+
+int pd_check_vconn_swap(int port)
+{
+ return 1;
+}
+
+void pd_execute_data_swap(int port, int data_role)
+{
+ /* Do nothing */
+}
+
+void pd_check_pr_role(int port, int pr_role, int flags)
+{
+ /*
+ * If partner is dual-role power and dualrole toggling is on, consider
+ * if a power swap is necessary.
+ */
+ if ((flags & PD_FLAGS_PARTNER_DR_POWER) &&
+ pd_get_dual_role(port) == PD_DRP_TOGGLE_ON) {
+ /*
+ * If we are a sink and partner is not externally powered, then
+ * swap to become a source. If we are source and partner is
+ * externally powered, swap to become a sink.
+ */
+ int partner_extpower = flags & PD_FLAGS_PARTNER_EXTPOWER;
+
+ if ((!partner_extpower && pr_role == PD_ROLE_SINK) ||
+ (partner_extpower && pr_role == PD_ROLE_SOURCE))
+ pd_request_power_swap(port);
+ }
+}
+
+void pd_check_dr_role(int port, int dr_role, int flags)
+{
+ /* If UFP, try to switch to DFP */
+ if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP)
+ pd_request_data_swap(port);
+}
+
+/* ----------------- Vendor Defined Messages ------------------ */
+const struct svdm_response svdm_rsp = {
+ .identity = NULL,
+ .svids = NULL,
+ .modes = NULL,
+};
+
+int pd_custom_vdm(int port, int cnt, uint32_t *payload,
+ uint32_t **rpayload)
+{
+ int cmd = PD_VDO_CMD(payload[0]);
+ uint16_t dev_id = 0;
+ int is_rw, is_latest;
+
+ /* make sure we have some payload */
+ if (cnt == 0)
+ return 0;
+
+ switch (cmd) {
+ case VDO_CMD_VERSION:
+ /* guarantee last byte of payload is null character */
+ *(payload + cnt - 1) = 0;
+ CPRINTF("version: %s\n", (char *)(payload+1));
+ break;
+ case VDO_CMD_READ_INFO:
+ case VDO_CMD_SEND_INFO:
+ /* copy hash */
+ if (cnt == 7) {
+ dev_id = VDO_INFO_HW_DEV_ID(payload[6]);
+ is_rw = VDO_INFO_IS_RW(payload[6]);
+
+ is_latest = pd_dev_store_rw_hash(port,
+ dev_id,
+ payload + 1,
+ is_rw ?
+ SYSTEM_IMAGE_RW :
+ SYSTEM_IMAGE_RO);
+
+ /*
+ * Send update host event unless our RW hash is
+ * already known to be the latest update RW.
+ */
+ if (!is_rw || !is_latest)
+ pd_send_host_event(PD_EVENT_UPDATE_DEVICE);
+
+ CPRINTF("DevId:%d.%d SW:%d RW:%d\n",
+ HW_DEV_ID_MAJ(dev_id),
+ HW_DEV_ID_MIN(dev_id),
+ VDO_INFO_SW_DBG_VER(payload[6]),
+ is_rw);
+ } else if (cnt == 6) {
+ /* really old devices don't have last byte */
+ pd_dev_store_rw_hash(port, dev_id, payload + 1,
+ SYSTEM_IMAGE_UNKNOWN);
+ }
+ break;
+ case VDO_CMD_CURRENT:
+ CPRINTF("Current: %dmA\n", payload[1]);
+ break;
+ case VDO_CMD_FLIP:
+ usb_mux_flip(port);
+ break;
+#ifdef CONFIG_USB_PD_LOGGING
+ case VDO_CMD_GET_LOG:
+ pd_log_recv_vdm(port, cnt, payload);
+ break;
+#endif /* CONFIG_USB_PD_LOGGING */
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+static int dp_flags[CONFIG_USB_PD_PORT_COUNT];
+static uint32_t dp_status[CONFIG_USB_PD_PORT_COUNT];
+
+static void svdm_safe_dp_mode(int port)
+{
+ /* make DP interface safe until configure */
+ dp_flags[port] = 0;
+ dp_status[port] = 0;
+ usb_mux_set(port, TYPEC_MUX_NONE,
+ USB_SWITCH_CONNECT, pd_get_polarity(port));
+}
+
+static int svdm_enter_dp_mode(int port, uint32_t mode_caps)
+{
+ /* Only enter mode if device is DFP_D capable */
+ if (mode_caps & MODE_DP_SNK) {
+ svdm_safe_dp_mode(port);
+ return 0;
+ }
+
+ return -1;
+}
+
+static int svdm_dp_status(int port, uint32_t *payload)
+{
+ int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+
+ payload[0] = VDO(USB_SID_DISPLAYPORT, 1,
+ CMD_DP_STATUS | VDO_OPOS(opos));
+ payload[1] = VDO_DP_STATUS(0, /* HPD IRQ ... not applicable */
+ 0, /* HPD level ... not applicable */
+ 0, /* exit DP? ... no */
+ 0, /* usb mode? ... no */
+ 0, /* multi-function ... no */
+ (!!(dp_flags[port] & DP_FLAGS_DP_ON)),
+ 0, /* power low? ... no */
+ (!!(dp_flags[port] & DP_FLAGS_DP_ON)));
+ return 2;
+};
+
+static int svdm_dp_config(int port, uint32_t *payload)
+{
+ int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+ int mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]);
+ int pin_mode = pd_dfp_dp_get_pin_mode(port, dp_status[port]);
+
+ if (!pin_mode)
+ return 0;
+
+ usb_mux_set(port, mf_pref ? TYPEC_MUX_DOCK : TYPEC_MUX_DP,
+ USB_SWITCH_CONNECT, pd_get_polarity(port));
+
+ payload[0] = VDO(USB_SID_DISPLAYPORT, 1,
+ CMD_DP_CONFIG | VDO_OPOS(opos));
+ payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */
+ 1, /* DPv1.3 signaling */
+ 2); /* UFP connected */
+ return 2;
+};
+
+static void svdm_dp_post_config(int port)
+{
+ const struct usb_mux *mux = &usb_muxes[port];
+
+ dp_flags[port] |= DP_FLAGS_DP_ON;
+ if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING))
+ return;
+ mux->hpd_update(port, 1, 0);
+}
+
+static int svdm_dp_attention(int port, uint32_t *payload)
+{
+ int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]);
+ int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]);
+ const struct usb_mux *mux = &usb_muxes[port];
+
+ dp_status[port] = payload[1];
+ if (!(dp_flags[port] & DP_FLAGS_DP_ON)) {
+ if (lvl)
+ dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING;
+ return 1;
+ }
+ mux->hpd_update(port, lvl, irq);
+
+ /* ack */
+ return 1;
+}
+
+static void svdm_exit_dp_mode(int port)
+{
+ const struct usb_mux *mux = &usb_muxes[port];
+
+ svdm_safe_dp_mode(port);
+ mux->hpd_update(port, 0, 0);
+}
+
+static int svdm_enter_gfu_mode(int port, uint32_t mode_caps)
+{
+ /* Always enter GFU mode */
+ return 0;
+}
+
+static void svdm_exit_gfu_mode(int port)
+{
+}
+
+static int svdm_gfu_status(int port, uint32_t *payload)
+{
+ /*
+ * This is called after enter mode is successful, send unstructured
+ * VDM to read info.
+ */
+ pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_READ_INFO, NULL, 0);
+ return 0;
+}
+
+static int svdm_gfu_config(int port, uint32_t *payload)
+{
+ return 0;
+}
+
+static int svdm_gfu_attention(int port, uint32_t *payload)
+{
+ return 0;
+}
+
+const struct svdm_amode_fx supported_modes[] = {
+ {
+ .svid = USB_SID_DISPLAYPORT,
+ .enter = &svdm_enter_dp_mode,
+ .status = &svdm_dp_status,
+ .config = &svdm_dp_config,
+ .post_config = &svdm_dp_post_config,
+ .attention = &svdm_dp_attention,
+ .exit = &svdm_exit_dp_mode,
+ },
+ {
+ .svid = USB_VID_GOOGLE,
+ .enter = &svdm_enter_gfu_mode,
+ .status = &svdm_gfu_status,
+ .config = &svdm_gfu_config,
+ .attention = &svdm_gfu_attention,
+ .exit = &svdm_exit_gfu_mode,
+ }
+};
+const int supported_modes_cnt = ARRAY_SIZE(supported_modes);
+#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
diff --git a/baseboard/intelrvp/vbus.c b/baseboard/intelrvp/vbus.c
new file mode 100644
index 0000000000..45ea3409cd
--- /dev/null
+++ b/baseboard/intelrvp/vbus.c
@@ -0,0 +1,30 @@
+/* Copyright 2019 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.
+ */
+
+/* Intel BASEBOARD-RVP VBUS detection specific configuration */
+
+#include "task.h"
+#include "usb_charge.h"
+
+/* USB VBUS detection configuration */
+#ifdef CONFIG_USB_PD_VBUS_DETECT_GPIO
+void vbus0_evt(enum gpio_signal signal)
+{
+#ifdef HAS_TASK_USB_CHG_P0
+ task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_VBUS, 0);
+#endif
+ task_wake(TASK_ID_PD_C0);
+}
+
+#ifdef HAS_TASK_PD_C1
+void vbus1_evt(enum gpio_signal signal)
+{
+#ifdef HAS_TASK_USB_CHG_P1
+ task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_VBUS, 0);
+#endif
+ task_wake(TASK_ID_PD_C1);
+}
+#endif /* HAS_TASK_PD_C1 */
+#endif /* CONFIG_USB_PD_VBUS_DETECT_GPIO */