summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiana Z <dzigterman@chromium.org>2020-03-19 12:04:13 -0600
committerCommit Bot <commit-bot@chromium.org>2020-03-24 23:19:25 +0000
commitbb4aee8eaf39ef68da363786771439d3c330c912 (patch)
treea978b2726892686295492a33db9fee3a1d99e21f
parentdc71caed2ee356da20d308f720dd281fc5826c4b (diff)
downloadchrome-ec-bb4aee8eaf39ef68da363786771439d3c330c912.tar.gz
Waddledee: Complete basic EC tasks
This commit adds tasks to cover PD functionality, charging, and LED behavior. The charger and TCPC functionality are a part of the ITE variant code for now, but may be moved out as OEM boards are determined. BUG=b:146557556 BRANCH=None TEST=make -j buldall Signed-off-by: Diana Z <dzigterman@chromium.org> Change-Id: I50df3caabfae5e3981d7a8b76c0a76332f7d00a1 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2110532 Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
-rw-r--r--baseboard/dedede/baseboard.h27
-rw-r--r--baseboard/dedede/variant_ec_it8320.c248
-rw-r--r--board/waddledee/board.c85
-rw-r--r--board/waddledee/board.h52
-rw-r--r--board/waddledee/build.mk2
-rw-r--r--board/waddledee/ec.tasklist8
-rw-r--r--board/waddledee/gpio.inc6
-rw-r--r--board/waddledee/led.c73
8 files changed, 449 insertions, 52 deletions
diff --git a/baseboard/dedede/baseboard.h b/baseboard/dedede/baseboard.h
index 0c2c82f90b..0b18483ccc 100644
--- a/baseboard/dedede/baseboard.h
+++ b/baseboard/dedede/baseboard.h
@@ -32,6 +32,16 @@
#define CONFIG_FLASH_SIZE (512 * 1024)
#define CONFIG_SPI_FLASH_REGS
#define CONFIG_SPI_FLASH_W25Q80 /* Internal SPI flash type. */
+
+ /* USB defines specific to external TCPCs */
+ #define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
+ #define CONFIG_USB_PD_VBUS_DETECT_TCPC
+ #define CONFIG_USB_PD_DISCHARGE_TCPC
+ /* #define CONFIG_USB_PD_TCPC_LOW_POWER */
+
+ /* Variant references the TCPCs to determine Vbus sourcing */
+ #define CONFIG_USB_PD_5V_EN_CUSTOM
+
#elif defined(VARIANT_DEDEDE_EC_IT8320)
/* Flash clock must be > (50Mhz / 2) */
#define CONFIG_IT83XX_FLASH_CLOCK_48MHZ
@@ -43,6 +53,18 @@
#define I2C_PORT_USB_C0 IT83XX_I2C_CH_F
#define I2C_ADDR_EEPROM_FLAGS 0x50
+
+ #define CONFIG_CHARGER_SM5803 /* C0 and C1: Charger */
+ #define CONFIG_FPU /* For charger calculations */
+
+ #define CONFIG_USB_PD_TCPM_ITE_ON_CHIP /* C0: ITE EC TCPC */
+ #define CONFIG_USB_PD_TCPM_ANX7447 /* C1: ANX TCPC + Mux */
+ #define CONFIG_BC12_DETECT_PI3USB9201 /* BC 1.2 */
+
+ /* Vbus is controlled by the charger */
+ #define CONFIG_USB_PD_VBUS_DETECT_CHARGER
+ #define CONFIG_USB_PD_5V_CHARGER_CTRL
+ #define CONFIG_CHARGER_OTG
#else
#error "Must define a VARIANT_DEDEDE_EC!"
#endif
@@ -113,7 +135,6 @@
#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1
#define CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON 15001
#define CONFIG_USB_CHARGER
-#define CONFIG_USB_PD_5V_EN_CUSTOM
#define CONFIG_TRICKLE_CHARGING
#undef CONFIG_CHARGER_SINGLE_CHIP
@@ -149,13 +170,10 @@
/* USB PD */
#define CONFIG_USB_PD_ALT_MODE
#define CONFIG_USB_PD_ALT_MODE_DFP
-#define CONFIG_USB_PD_DISCHARGE_TCPC
#define CONFIG_USB_PD_DP_HPD_GPIO
#define CONFIG_USB_PD_DUAL_ROLE
-#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
#define CONFIG_USB_PD_LOGGING
#define CONFIG_USB_PD_PORT_MAX_COUNT 2
-/* #define CONFIG_USB_PD_TCPC_LOW_POWER */
#define CONFIG_USB_PD_TCPM_MUX
#define CONFIG_USB_PD_TCPM_TCPCI
#define CONFIG_USB_PD_TRY_SRC
@@ -168,7 +186,6 @@
#undef CONFIG_USB_PD_TRY_SRC_MIN_BATT_SOC
#define CONFIG_USB_PD_TRY_SRC_MIN_BATT_SOC 5
/* #define CONFIG_USB_PD_VBUS_DETECT_CHARGER */
-#define CONFIG_USB_PD_VBUS_DETECT_TCPC
#define CONFIG_USB_PD_VBUS_MEASURE_CHARGER
#define CONFIG_USB_PD_DECODE_SOP
#define CONFIG_USB_PID 0x5042
diff --git a/baseboard/dedede/variant_ec_it8320.c b/baseboard/dedede/variant_ec_it8320.c
index 8106b6c7ab..8fa134ab1b 100644
--- a/baseboard/dedede/variant_ec_it8320.c
+++ b/baseboard/dedede/variant_ec_it8320.c
@@ -6,9 +6,17 @@
/* Common code for VARIANT_DEDEDE_IT8320 configuration */
#include "adc_chip.h"
+#include "charge_manager.h"
+#include "charge_state_v2.h"
+#include "charger.h"
+#include "chipset.h"
#include "common.h"
#include "compile_time_macros.h"
#include "console.h"
+#include "driver/bc12/pi3usb9201.h"
+#include "driver/charger/sm5803.h"
+#include "driver/tcpm/anx7447.h"
+#include "driver/tcpm/it83xx_pd.h"
#include "gpio.h"
#include "hooks.h"
#include "i2c.h"
@@ -16,6 +24,10 @@
#include "pwm.h"
#include "pwm_chip.h"
#include "registers.h"
+#include "tcpci.h"
+#include "usb_pd_tcpm.h"
+
+#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ## args)
/* ADC channels */
const struct adc_t adc_channels[] = {
@@ -35,6 +47,33 @@ BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);
/* TODO(b/149094481): Set up ADC comparator interrupts for ITE */
+/* BC12 chips */
+const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = {
+ {
+ .i2c_port = I2C_PORT_USB_C0,
+ .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS,
+ },
+ {
+ .i2c_port = I2C_PORT_SUB_USB_C1,
+ .i2c_addr_flags = PI3USB9201_I2C_ADDR_3_FLAGS,
+ },
+};
+
+/* Charger chips */
+const struct charger_config_t chg_chips[] = {
+ [CHARGER_PRIMARY] = {
+ .i2c_port = I2C_PORT_USB_C0,
+ .i2c_addr_flags = SM5803_ADDR_CHARGER_FLAGS,
+ .drv = &sm5803_drv,
+ },
+ [CHARGER_SECONDARY] = {
+ .i2c_port = I2C_PORT_SUB_USB_C1,
+ .i2c_addr_flags = SM5803_ADDR_CHARGER_FLAGS,
+ .drv = &sm5803_drv,
+ },
+};
+const unsigned int chg_cnt = ARRAY_SIZE(chg_chips);
+
/* I2C Ports */
const struct i2c_port_t i2c_ports[] = {
{
@@ -63,3 +102,212 @@ const struct i2c_port_t i2c_ports[] = {
},
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+
+/* TCPCs */
+const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = {
+ {
+ .bus_type = EC_BUS_TYPE_EMBEDDED,
+ .drv = &it83xx_tcpm_drv,
+ },
+ {
+ .bus_type = EC_BUS_TYPE_I2C,
+ .i2c_info = {
+ .port = I2C_PORT_SUB_USB_C1,
+ .addr_flags = AN7447_TCPC0_I2C_ADDR_FLAGS,
+ },
+ .drv = &anx7447_tcpm_drv,
+ .flags = TCPC_FLAGS_TCPCI_REV2_0,
+ },
+};
+
+uint16_t tcpc_get_alert_status(void)
+{
+ /*
+ * TCPC 0 is embedded in the EC and processes interrupts in the chip
+ * code (it83xx/intc.c)
+ */
+
+ uint16_t status = 0;
+ int regval;
+
+ /* Check whether TCPC 1 pulled the shared interrupt line */
+ if (!gpio_get_level(GPIO_USB_C1_INT_ODL)) {
+ if (!tcpc_read16(1, TCPC_REG_ALERT, &regval)) {
+ if (regval)
+ status = PD_STATUS_TCPC_ALERT_1;
+ }
+ }
+
+ return status;
+}
+
+int extpower_is_present(void)
+{
+ int chg0 = 0;
+ int chg1 = 0;
+
+ sm5803_get_chg_det(0, &chg0);
+ sm5803_get_chg_det(1, &chg1);
+
+ return chg0 || chg1;
+}
+
+void board_set_charge_limit(int port, int supplier, int charge_ma, int max_ma,
+ int charge_mv)
+{
+ int icl = MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT);
+
+ /*
+ * TODO(b/151955431): Characterize the input current limit in case a
+ * scaling needs to be applied here
+ */
+ charge_set_input_current_limit(icl, charge_mv);
+}
+
+int board_set_active_charge_port(int port)
+{
+ int is_valid_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT);
+ int p0_otg, p1_otg;
+
+ if (!is_valid_port && port != CHARGE_PORT_NONE)
+ return EC_ERROR_INVAL;
+
+ /* TODO(b/147440290): charger functions should take chgnum */
+ p0_otg = chg_chips[0].drv->is_sourcing_otg_power(0, 0);
+ p1_otg = chg_chips[1].drv->is_sourcing_otg_power(1, 1);
+
+ if (port == CHARGE_PORT_NONE) {
+ CPRINTUSB("Disabling all charge ports");
+
+ if (!p0_otg)
+ chg_chips[0].drv->set_mode(0,
+ CHARGE_FLAG_INHIBIT_CHARGE);
+ if (!p1_otg)
+ chg_chips[1].drv->set_mode(1,
+ CHARGE_FLAG_INHIBIT_CHARGE);
+
+ return EC_SUCCESS;
+ }
+
+ CPRINTUSB("New chg p%d", port);
+
+ /*
+ * Charger task will take care of enabling charging on the new charge
+ * port. Here, we ensure the other port is not charging by changing
+ * CHG_EN
+ */
+ if (port == 0) {
+ if (p0_otg) {
+ CPRINTUSB("Skip enable p%d", port);
+ return EC_ERROR_INVAL;
+ }
+ if (!p1_otg) {
+ chg_chips[1].drv->set_mode(1,
+ CHARGE_FLAG_INHIBIT_CHARGE);
+ }
+ } else {
+ if (p1_otg) {
+ CPRINTUSB("Skip enable p%d", port);
+ return EC_ERROR_INVAL;
+ }
+ if (!p0_otg) {
+ chg_chips[0].drv->set_mode(0,
+ CHARGE_FLAG_INHIBIT_CHARGE);
+ }
+ }
+
+ return EC_SUCCESS;
+}
+
+/* Vconn control for integrated ITE TCPC */
+void board_pd_vconn_ctrl(int port, enum usbpd_cc_pin cc_pin, int enabled)
+{
+ /* Vconn control is only for port 0 */
+ if (port)
+ return;
+
+ if (cc_pin == USBPD_CC_PIN_1)
+ gpio_set_level(GPIO_EN_USB_C0_CC1_VCONN, !!enabled);
+ else
+ gpio_set_level(GPIO_EN_USB_C0_CC2_VCONN, !!enabled);
+}
+
+__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp)
+{
+ int current;
+
+ if (port < 0 || port > CONFIG_USB_PD_PORT_MAX_COUNT)
+ return;
+
+ current = (rp == TYPEC_RP_3A0) ? 3000 : 1500;
+
+ chg_chips[port].drv->set_otg_current_voltage(port, current, 5000);
+}
+
+
+int pd_check_vconn_swap(int port)
+{
+ /* Allow VCONN swaps if the AP is on */
+ return chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON);
+}
+
+void pd_power_supply_reset(int port)
+{
+ int prev_en;
+
+ if (port < 0 || port >= CONFIG_USB_PD_PORT_MAX_COUNT)
+ return;
+
+ /* TODO(b/147440290): charger functions should take chgnum */
+ prev_en = chg_chips[port].drv->is_sourcing_otg_power(port, port);
+
+ /* Disable Vbus */
+ chg_chips[port].drv->enable_otg_power(port, 0);
+
+ /* Discharge Vbus if previously enabled */
+ if (prev_en)
+ sm5803_set_vbus_disch(port, 1);
+
+#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT
+ /* Give back the current quota we are no longer using */
+ charge_manager_source_port(port, 0);
+#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */
+
+ /* Notify host of power info change. */
+ pd_send_host_event(PD_EVENT_POWER_CHANGE);
+}
+
+int pd_set_power_supply_ready(int port)
+{
+ enum ec_error_list rv;
+
+ /* Disable charging */
+ rv = chg_chips[port].drv->set_mode(port, CHARGE_FLAG_INHIBIT_CHARGE);
+ if (rv)
+ return rv;
+
+ /* Disable Vbus discharge */
+ sm5803_set_vbus_disch(port, 0);
+
+ /* Provide Vbus */
+ chg_chips[port].drv->enable_otg_power(port, 1);
+
+#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT
+ /* Ensure we advertise the proper available current quota */
+ charge_manager_source_port(port, 1);
+#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */
+
+ /* Notify host of power info change. */
+ pd_send_host_event(PD_EVENT_POWER_CHANGE);
+
+ return EC_SUCCESS;
+}
+
+int pd_snk_is_vbus_provided(int port)
+{
+ int chg_det = 0;
+
+ sm5803_get_chg_det(port, &chg_det);
+
+ return chg_det;
+}
diff --git a/board/waddledee/board.c b/board/waddledee/board.c
index ce9d4a8a6d..d25858c30c 100644
--- a/board/waddledee/board.c
+++ b/board/waddledee/board.c
@@ -8,8 +8,12 @@
#include "button.h"
#include "driver/accel_lis2dh.h"
#include "driver/accelgyro_lsm6dsm.h"
+#include "driver/charger/sm5803.h"
#include "driver/sync.h"
+#include "driver/retimer/tusb544.h"
#include "driver/temp_sensor/thermistor.h"
+#include "driver/tcpm/anx7447.h"
+#include "driver/usb_mux/it5205.h"
#include "gpio.h"
#include "intc.h"
#include "keyboard_scan.h"
@@ -23,19 +27,79 @@
#include "task.h"
#include "temp_sensor.h"
#include "uart.h"
+#include "usb_charge.h"
+#include "usb_mux.h"
+#include "usb_pd.h"
-static void filler_interrupt_handler(enum gpio_signal s)
+#define CPRINTUSB(format, args...) cprints(CC_USBCHARGE, format, ## args)
+
+/* C0 interrupt line shared by BC 1.2 and charger */
+static void usb_c0_interrupt(enum gpio_signal s)
+{
+ task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0);
+ sm5803_interrupt(0);
+}
+
+/* C1 interrupt line shared by BC 1.2, TCPC, and charger */
+static void usb_c1_interrupt(enum gpio_signal s)
{
- /* TODO(b/146557556): placeholder for TCPC, charger, fault protector */
+ schedule_deferred_pd_interrupt(1);
+ task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0);
+ sm5803_interrupt(1);
+}
+
+static void c0_ccsbu_ovp_interrupt(enum gpio_signal s)
+{
+ cprints(CC_USBPD, "C0: CC OVP, SBU OVP, or thermal event");
+ /*pd_handle_cc_overvoltage(0);*/
}
/* Must come after other header files and interrupt handler declarations */
#include "gpio_list.h"
-int extpower_is_present(void)
+/* USB Retimer */
+const struct usb_mux usbc1_retimer = {
+ .usb_port = 1,
+ .i2c_port = I2C_PORT_SUB_USB_C1,
+ .i2c_addr_flags = TUSB544_I2C_ADDR_FLAGS0,
+ .driver = &tusb544_drv,
+};
+
+/* USB Muxes */
+const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = {
+ {
+ .usb_port = 0,
+ .i2c_port = I2C_PORT_USB_C0,
+ .i2c_addr_flags = IT5205_I2C_ADDR1_FLAGS,
+ .driver = &it5205_usb_mux_driver,
+ },
+ {
+ .usb_port = 1,
+ .i2c_port = I2C_PORT_SUB_USB_C1,
+ .i2c_addr_flags = AN7447_TCPC0_I2C_ADDR_FLAGS,
+ .driver = &anx7447_usb_mux_driver,
+ .next_mux = &usbc1_retimer,
+ },
+};
+
+void board_init(void)
{
- /* TODO(b/146651778): retrieve from chargers */
- return 0;
+ int on;
+
+ gpio_enable_interrupt(GPIO_USB_C0_INT_ODL);
+ gpio_enable_interrupt(GPIO_USB_C1_INT_ODL);
+ gpio_enable_interrupt(GPIO_USB_C0_CCSBU_OVP_ODL);
+
+ /* Charger on the MB will be outputting PROCHOT and OD CHG_DET */
+ sm5803_configure_gpio0(CHARGER_PRIMARY, GPIO0_MODE_PROCHOT);
+ sm5803_configure_chg_det_od(CHARGER_PRIMARY, 1);
+
+ /* Charger on the sub-board will be a GPIO */
+ sm5803_configure_gpio0(CHARGER_SECONDARY, GPIO0_MODE_OUTPUT);
+
+ /* Turn on 5V if the system is on, otherwise turn it off */
+ on = chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_ANY_SUSPEND);
+ board_power_5v_enable(on);
}
void board_reset_pd_mcu(void)
@@ -46,6 +110,17 @@ void board_reset_pd_mcu(void)
*/
}
+__override void board_power_5v_enable(int enable)
+{
+ /*
+ * Motherboard has a GPIO to turn on the 5V regulator, but the sub-board
+ * sets it through the charger GPIO.
+ */
+ gpio_set_level(GPIO_EN_PP5000, !!enable);
+ if (sm5803_set_gpio0_level(1, !!enable))
+ CPRINTUSB("Failed to %sable sub rails!", enable ? "en" : "dis");
+}
+
/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */
const struct pwm_t pwm_channels[] = {
[PWM_CH_KBLIGHT] = {
diff --git a/board/waddledee/board.h b/board/waddledee/board.h
index a2fe3ead84..13eb9b64d3 100644
--- a/board/waddledee/board.h
+++ b/board/waddledee/board.h
@@ -12,46 +12,15 @@
#define VARIANT_DEDEDE_EC_IT8320
#include "baseboard.h"
-/* Undef battery, charger, LED, PD functions until charger is in */
-#undef CONFIG_BATTERY_CUT_OFF
-#undef CONFIG_BATTERY_PRESENT_GPIO
-#undef CONFIG_BATTERY_REVIVE_DISCONNECT
-#undef CONFIG_BATTERY_SMART
-#undef CONFIG_CHARGE_MANAGER
-#undef CONFIG_CHARGER
-#undef CONFIG_CHARGER_INPUT_CURRENT
-#undef CONFIG_LED_COMMON
-#undef CONFIG_LED_PWM
-#undef CONFIG_USB_MUX_PI3USB31532
-#undef CONFIG_USBC_SS_MUX
-#undef CONFIG_USBC_SS_MUX_DFP_ONLY
-#undef CONFIG_USBC_VCONN
-#undef CONFIG_USBC_VCONN_SWAP
-#undef CONFIG_USB_CHARGER
-#undef CONFIG_USB_PD_5V_EN_CUSTOM
-#undef CONFIG_TRICKLE_CHARGING
-#undef CONFIG_USB_PD_ALT_MODE
-#undef CONFIG_USB_PD_ALT_MODE_DFP
-#undef CONFIG_USB_PD_DISCHARGE_TCPC
-#undef CONFIG_USB_PD_DP_HPD_GPIO
-#undef CONFIG_USB_PD_DUAL_ROLE
-#undef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
-#undef CONFIG_USB_PD_LOGGING
-#undef CONFIG_USB_PD_PORT_MAX_COUNT
-#undef CONFIG_USB_PD_TCPM_MUX
-#undef CONFIG_USB_PD_TCPM_TCPCI
-#undef CONFIG_USB_PD_TRY_SRC
-#undef CONFIG_USB_PD_VBUS_DETECT_TCPC
-#undef CONFIG_USB_PD_VBUS_MEASURE_CHARGER
-#undef CONFIG_USB_PD_DECODE_SOP
-#undef CONFIG_USB_PID
-#undef CONFIG_USB_POWER_DELIVERY
-#undef CONFIG_USB_PD_TCPMV2
-#undef CONFIG_USB_TYPEC_DRP_ACC_TRYSRC
-
/* System unlocked in early development */
#define CONFIG_SYSTEM_UNLOCKED
+/* Battery */
+#define CONFIG_BATTERY_FUEL_GAUGE
+
+/* LED */
+#define CONFIG_LED_PWM_COUNT 1
+
/* Sensors */
#define CONFIG_ACCEL_LIS2DE /* Lid accel */
#define CONFIG_ACCELGYRO_LSM6DSM /* Base accel */
@@ -78,6 +47,13 @@
#define CONFIG_TABLET_MODE_SWITCH
#define CONFIG_GMR_TABLET_MODE
+/* USB Mux and Retimer */
+#define CONFIG_USB_MUX_IT5205 /* C1: ITE Mux */
+#define I2C_PORT_USB_MUX I2C_PORT_USB_C0 /* Required for ITE Mux */
+
+#define CONFIG_USBC_RETIMER_TUSB544 /* C1 Redriver: TUSB544 */
+
+
/* Thermistors */
#define CONFIG_TEMP_SENSOR
#define CONFIG_THERMISTOR
@@ -118,6 +94,8 @@ enum battery_type {
BATTERY_TYPE_COUNT,
};
+int board_is_sourcing_vbus(int port);
+
#endif /* !__ASSEMBLER__ */
#endif /* __CROS_EC_BOARD_H */
diff --git a/board/waddledee/build.mk b/board/waddledee/build.mk
index 382ec57971..0450a2d57f 100644
--- a/board/waddledee/build.mk
+++ b/board/waddledee/build.mk
@@ -11,5 +11,5 @@ CHIP_FAMILY:=it8320
CHIP_VARIANT:=it8320dx
BASEBOARD:=dedede
-board-y=board.o
+board-y=board.o led.o
board-$(CONFIG_BATTERY_SMART)+=battery.o
diff --git a/board/waddledee/ec.tasklist b/board/waddledee/ec.tasklist
index bf1b5b19c3..307c7a82a1 100644
--- a/board/waddledee/ec.tasklist
+++ b/board/waddledee/ec.tasklist
@@ -10,10 +10,16 @@
#define CONFIG_TASK_LIST \
TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \
TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \
+ TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, LARGER_TASK_STACK_SIZE) \
+ TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, LARGER_TASK_STACK_SIZE) \
+ TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \
TASK_NOTEST(CHIPSET, chipset_task, NULL, VENTI_TASK_STACK_SIZE) \
TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \
TASK_NOTEST(PDCMD, pd_command_task, NULL, TASK_STACK_SIZE) \
TASK_ALWAYS(HOSTCMD, host_command_task, NULL, VENTI_TASK_STACK_SIZE) \
TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \
TASK_ALWAYS(POWERBTN, power_button_task, NULL, VENTI_TASK_STACK_SIZE) \
- TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE)
+ TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \
+ TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \
+ TASK_ALWAYS(PD_C1, pd_task, NULL, VENTI_TASK_STACK_SIZE) \
+ TASK_ALWAYS(PD_INT_C1, pd_interrupt_handler_task, 1, VENTI_TASK_STACK_SIZE)
diff --git a/board/waddledee/gpio.inc b/board/waddledee/gpio.inc
index 6d86813bf9..c1ed840f37 100644
--- a/board/waddledee/gpio.inc
+++ b/board/waddledee/gpio.inc
@@ -29,9 +29,9 @@ GPIO_INT(UART1_RX, PIN(B, 0), GPIO_INT_BOTH, uart_deepsleep_interrupt) /* UART_
#endif
/* USB-C interrupts */
-GPIO_INT(USB_C0_INT_ODL, PIN(K, 0), GPIO_INT_FALLING, filler_interrupt_handler) /* BC12 and charger */
-GPIO_INT(USB_C1_INT_ODL, PIN(B, 5), GPIO_INT_FALLING, filler_interrupt_handler) /* TCPC, charger, BC12 */
-GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING, filler_interrupt_handler) /* Fault protection */
+GPIO_INT(USB_C0_INT_ODL, PIN(K, 0), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c0_interrupt) /* BC12 and charger */
+GPIO_INT(USB_C1_INT_ODL, PIN(B, 5), GPIO_INT_FALLING | GPIO_PULL_UP, usb_c1_interrupt) /* TCPC, charger, BC12 */
+GPIO_INT(USB_C0_CCSBU_OVP_ODL, PIN(K, 6), GPIO_INT_FALLING | GPIO_PULL_UP, c0_ccsbu_ovp_interrupt) /* Fault protection */
/* Other interrupts */
GPIO_INT(LID_OPEN, PIN(F, 3), GPIO_INT_BOTH, lid_interrupt)
diff --git a/board/waddledee/led.c b/board/waddledee/led.c
new file mode 100644
index 0000000000..f8c34eb078
--- /dev/null
+++ b/board/waddledee/led.c
@@ -0,0 +1,73 @@
+/* Copyright 2020 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.
+ */
+
+/* Waddledee specific PWM LED settings. */
+
+#include "common.h"
+#include "ec_commands.h"
+#include "led_pwm.h"
+#include "pwm.h"
+#include "util.h"
+
+const enum ec_led_id supported_led_ids[] = {
+ EC_LED_ID_POWER_LED,
+};
+const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids);
+
+/*
+ * Board has one physical LED with red, green, and blue
+ */
+struct pwm_led led_color_map[EC_LED_COLOR_COUNT] = {
+ /* Red, Green, Blue */
+ [EC_LED_COLOR_RED] = { 100, 0, 0 },
+ [EC_LED_COLOR_GREEN] = { 0, 100, 0 },
+ [EC_LED_COLOR_BLUE] = { 0, 0, 100 },
+ [EC_LED_COLOR_YELLOW] = { 0, 0, 0 },
+ [EC_LED_COLOR_WHITE] = { 0, 0, 0 },
+ [EC_LED_COLOR_AMBER] = { 0, 0, 0 },
+};
+
+/* One logical LED with red, green, and blue channels. */
+struct pwm_led pwm_leds[CONFIG_LED_PWM_COUNT] = {
+ {
+ .ch0 = PWM_CH_LED_RED,
+ .ch1 = PWM_CH_LED_GREEN,
+ .ch2 = PWM_CH_LED_BLUE,
+ .enable = &pwm_enable,
+ .set_duty = &pwm_set_duty,
+ },
+};
+
+void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range)
+{
+ memset(brightness_range, '\0',
+ sizeof(*brightness_range) * EC_LED_COLOR_COUNT);
+ brightness_range[EC_LED_COLOR_RED] = 100;
+ brightness_range[EC_LED_COLOR_GREEN] = 100;
+ brightness_range[EC_LED_COLOR_BLUE] = 100;
+}
+
+int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness)
+{
+ enum pwm_led_id pwm_id;
+
+ /* Convert ec_led_id to pwm_led_id. */
+ if (led_id == EC_LED_ID_POWER_LED)
+ pwm_id = PWM_LED0;
+ else
+ return EC_ERROR_UNKNOWN;
+
+ if (brightness[EC_LED_COLOR_RED])
+ set_pwm_led_color(pwm_id, EC_LED_COLOR_RED);
+ else if (brightness[EC_LED_COLOR_GREEN])
+ set_pwm_led_color(pwm_id, EC_LED_COLOR_GREEN);
+ else if (brightness[EC_LED_COLOR_BLUE])
+ set_pwm_led_color(pwm_id, EC_LED_COLOR_BLUE);
+ else
+ /* Otherwise, the "color" is "off". */
+ set_pwm_led_color(pwm_id, -1);
+
+ return EC_SUCCESS;
+}