/* Copyright 2017 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 "atomic.h" #include "extpower.h" #include "charge_manager.h" #include "common.h" #include "console.h" #include "driver/tcpm/anx74xx.h" #include "driver/tcpm/ps8xxx.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" #include "registers.h" #include "system.h" #include "task.h" #include "timer.h" #include "util.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.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) const uint32_t pd_src_pdo[] = { PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), }; const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); const uint32_t pd_snk_pdo[] = { PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), PDO_BATT(4750, 21000, 50000), PDO_VAR(4750, 21000, 3000), }; const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); int board_vbus_source_enabled(int port) { if (port != 0) return 0; return gpio_get_level(GPIO_USB_C0_5V_EN); } int pd_set_power_supply_ready(int port) { /* Disable charging */ gpio_set_level(GPIO_USB_C0_CHARGE_L, 1); /* Enable VBUS source */ gpio_set_level(GPIO_USB_C0_5V_EN, 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 source */ gpio_set_level(GPIO_USB_C0_5V_EN, 0); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } int pd_snk_is_vbus_provided(int port) { return !gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L); } __override int pd_check_power_swap(int port) { /* If type-c port is supplying power, we never swap PR (to source) */ if (port == charge_manager_get_active_charge_port()) return 0; /* * 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 ? 1 : 0; } int pd_check_vconn_swap(int port) { /* in G3, do not allow vconn swap since pp5000_A rail is off */ return gpio_get_level(GPIO_PMIC_SLP_SUS_L); } int board_set_active_charge_port(int port) { const int active_port = charge_manager_get_active_charge_port(); if (port < 0 || CHARGE_PORT_COUNT <= port) return EC_ERROR_INVAL; if (port == active_port) return EC_SUCCESS; /* Don't charge from a source port */ if (board_vbus_source_enabled(port)) return EC_ERROR_INVAL; CPRINTS("New charger p%d", port); switch (port) { case CHARGE_PORT_TYPEC0: /* This is connected to TP on board version 2.2+ thus no-op */ gpio_set_level(GPIO_USB_C0_CHARGE_L, 0); gpio_set_level(GPIO_AC_JACK_CHARGE_L, 1); gpio_enable_interrupt(GPIO_ADP_IN_L); break; case CHARGE_PORT_BARRELJACK: /* Make sure BJ adapter is sourcing power */ if (gpio_get_level(GPIO_ADP_IN_L)) return EC_ERROR_INVAL; /* This will cause brown out when switching from type-c on * board version 2.2+ thus the rest of the code is no-op. */ gpio_set_level(GPIO_AC_JACK_CHARGE_L, 0); /* If type-c voltage > BJ voltage, we'll brown out due to the * reverse current protection of PU3 but it's intended. */ gpio_set_level(GPIO_USB_C0_CHARGE_L, 1); gpio_disable_interrupt(GPIO_ADP_IN_L); break; default: return EC_ERROR_INVAL; } return EC_SUCCESS; } int board_get_battery_soc(void) { return 100; }