269 lines
6.0 KiB
C
269 lines
6.0 KiB
C
/* 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 "charge_manager.h"
|
|
#include "charge_state_v2.h"
|
|
#include "console.h"
|
|
#include "hooks.h"
|
|
#include "task.h"
|
|
#include "tcpci.h"
|
|
#include "system.h"
|
|
#include "usb_mux.h"
|
|
#include "util.h"
|
|
|
|
#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
|
|
#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
|
|
|
|
#define PTN5110_EXT_GPIO_CONFIG 0x92
|
|
#define PTN5110_EXT_GPIO_CONTROL 0x93
|
|
|
|
#define PTN5110_EXT_GPIO_FRS_EN BIT(6)
|
|
#define PTN5110_EXT_GPIO_EN_SRC BIT(5)
|
|
#define PTN5110_EXT_GPIO_EN_SNK1 BIT(4)
|
|
#define PTN5110_EXT_GPIO_IILIM_5V_VBUS_L BIT(3)
|
|
|
|
enum glkrvp_charge_ports {
|
|
TYPE_C_PORT_0,
|
|
TYPE_C_PORT_1,
|
|
DC_JACK_PORT_0 = DEDICATED_CHARGE_PORT,
|
|
};
|
|
|
|
const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_COUNT] = {
|
|
{
|
|
.bus_type = EC_BUS_TYPE_I2C,
|
|
.i2c_info = {
|
|
.port = NPCX_I2C_PORT7_0,
|
|
.addr_flags = 0x50,
|
|
},
|
|
.drv = &tcpci_tcpm_drv,
|
|
},
|
|
{
|
|
.bus_type = EC_BUS_TYPE_I2C,
|
|
.i2c_info = {
|
|
.port = NPCX_I2C_PORT7_0,
|
|
.addr_flags = 0x52,
|
|
},
|
|
.drv = &tcpci_tcpm_drv,
|
|
},
|
|
};
|
|
BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == CONFIG_USB_PD_PORT_COUNT);
|
|
|
|
struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_COUNT] = {
|
|
{
|
|
.port_addr = 0x10,
|
|
.driver = &ps874x_usb_mux_driver,
|
|
},
|
|
{
|
|
.port_addr = 0x11,
|
|
.driver = &ps874x_usb_mux_driver,
|
|
},
|
|
};
|
|
|
|
/* TODO: Implement this function and move to appropriate file */
|
|
void usb_charger_set_switches(int port, enum usb_switch setting)
|
|
{
|
|
}
|
|
|
|
static int board_charger_port_is_sourcing_vbus(int port)
|
|
{
|
|
int reg;
|
|
|
|
if (tcpc_read(port, PTN5110_EXT_GPIO_CONTROL, ®))
|
|
return 0;
|
|
|
|
return !!(reg & PTN5110_EXT_GPIO_EN_SRC);
|
|
}
|
|
|
|
static int ptn5110_ext_gpio_enable(int port, int enable, int gpio)
|
|
{
|
|
int reg;
|
|
int rv;
|
|
|
|
rv = tcpc_read(port, PTN5110_EXT_GPIO_CONTROL, ®);
|
|
if (rv)
|
|
return rv;
|
|
|
|
if (enable)
|
|
reg |= gpio;
|
|
else
|
|
reg &= ~gpio;
|
|
|
|
return tcpc_write(port, PTN5110_EXT_GPIO_CONTROL, reg);
|
|
}
|
|
|
|
void board_charging_enable(int port, int enable)
|
|
{
|
|
ptn5110_ext_gpio_enable(port, enable, PTN5110_EXT_GPIO_EN_SNK1);
|
|
}
|
|
|
|
void board_vbus_enable(int port, int enable)
|
|
{
|
|
ptn5110_ext_gpio_enable(port, enable, PTN5110_EXT_GPIO_EN_SRC);
|
|
}
|
|
|
|
void tcpc_alert_event(enum gpio_signal signal)
|
|
{
|
|
int port = -1;
|
|
|
|
switch (signal) {
|
|
case GPIO_USB_C0_PD_INT_ODL:
|
|
port = 0;
|
|
break;
|
|
case GPIO_USB_C1_PD_INT_ODL:
|
|
port = 1;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
schedule_deferred_pd_interrupt(port);
|
|
}
|
|
|
|
void board_tcpc_init(void)
|
|
{
|
|
/* Only reset TCPC if not sysjump */
|
|
if (!system_jumped_to_this_image())
|
|
board_reset_pd_mcu();
|
|
|
|
/* Enable TCPC0/1 interrupt */
|
|
gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL);
|
|
gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL);
|
|
}
|
|
DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1);
|
|
|
|
int board_tcpc_post_init(int port)
|
|
{
|
|
int reg;
|
|
int rv;
|
|
|
|
rv = tcpc_read(port, PTN5110_EXT_GPIO_CONFIG, ®);
|
|
if (rv)
|
|
return rv;
|
|
|
|
/* Configure PTN5110 External GPIOs as output */
|
|
reg |= PTN5110_EXT_GPIO_EN_SRC | PTN5110_EXT_GPIO_EN_SNK1 |
|
|
PTN5110_EXT_GPIO_IILIM_5V_VBUS_L;
|
|
rv = tcpc_write(port, PTN5110_EXT_GPIO_CONFIG, reg);
|
|
if (rv)
|
|
return rv;
|
|
|
|
return ptn5110_ext_gpio_enable(port, 1,
|
|
PTN5110_EXT_GPIO_IILIM_5V_VBUS_L);
|
|
}
|
|
|
|
/* Reset PD MCU */
|
|
void board_reset_pd_mcu(void)
|
|
{
|
|
/* TODO: Add reset logic */
|
|
}
|
|
|
|
static inline int board_dc_jack_present(void)
|
|
{
|
|
return !gpio_get_level(GPIO_DC_JACK_PRESENT_L);
|
|
}
|
|
|
|
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;
|
|
|
|
/* 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, NULL);
|
|
}
|
|
|
|
board_dc_jack_handle();
|
|
}
|
|
DECLARE_HOOK(HOOK_INIT, board_charge_init, HOOK_PRIO_DEFAULT);
|
|
|
|
int board_set_active_charge_port(int port)
|
|
{
|
|
/* 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 port is disabled */
|
|
switch (port) {
|
|
case TYPE_C_PORT_0:
|
|
board_charging_enable(TYPE_C_PORT_1, 0);
|
|
board_charging_enable(TYPE_C_PORT_0, 1);
|
|
break;
|
|
case TYPE_C_PORT_1:
|
|
board_charging_enable(TYPE_C_PORT_0, 0);
|
|
board_charging_enable(TYPE_C_PORT_1, 1);
|
|
break;
|
|
case DC_JACK_PORT_0:
|
|
case CHARGE_PORT_NONE:
|
|
default:
|
|
/* Disable both Type-C ports */
|
|
board_charging_enable(TYPE_C_PORT_0, 0);
|
|
board_charging_enable(TYPE_C_PORT_1, 0);
|
|
break;
|
|
}
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
uint16_t tcpc_get_alert_status(void)
|
|
{
|
|
uint16_t status = 0;
|
|
|
|
if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL))
|
|
status |= PD_STATUS_TCPC_ALERT_0;
|
|
|
|
if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL))
|
|
status |= PD_STATUS_TCPC_ALERT_1;
|
|
|
|
return status;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
int adc_read_channel(enum adc_channel ch)
|
|
{
|
|
return 0;
|
|
}
|