diff options
-rw-r--r-- | baseboard/intelrvp/README.md | 25 | ||||
-rw-r--r-- | baseboard/intelrvp/baseboard.c | 238 | ||||
-rw-r--r-- | baseboard/intelrvp/baseboard.h | 239 | ||||
-rw-r--r-- | baseboard/intelrvp/battery.c | 79 | ||||
-rw-r--r-- | baseboard/intelrvp/bc12.c | 28 | ||||
-rw-r--r-- | baseboard/intelrvp/build.mk | 28 | ||||
-rw-r--r-- | baseboard/intelrvp/chg_usb_pd.c | 167 | ||||
-rw-r--r-- | baseboard/intelrvp/ite_ec.c | 90 | ||||
-rw-r--r-- | baseboard/intelrvp/ite_ec.h | 24 | ||||
-rw-r--r-- | baseboard/intelrvp/led.c | 109 | ||||
-rw-r--r-- | baseboard/intelrvp/led_states.c | 188 | ||||
-rw-r--r-- | baseboard/intelrvp/led_states.h | 90 | ||||
-rw-r--r-- | baseboard/intelrvp/retimer.c | 32 | ||||
-rw-r--r-- | baseboard/intelrvp/usb_mux.c | 26 | ||||
-rw-r--r-- | baseboard/intelrvp/usb_pd_policy.c | 345 | ||||
-rw-r--r-- | baseboard/intelrvp/vbus.c | 30 |
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 */ |