Files
OpenCellular/board/ryu/board.c
Vic Yang 5d4846ee52 plankton: Implement cable flip
When the cable flip button is pressed, instead of only flipping on
Plankton side, we should also signal the port partner to flip. This is
done by sending a custom VDM. Upon receiving the flip VDM, the port
partner is responsible of flipping the DP/USB polarity.

Note that the "flip" here only affects the superspeed lanes. The CC
lines polarity is not changed. We need this for factory test automation,
and this "flip" function should only be used for testing purpose as it
clearly violates the USB PD spec and it only works on devices that
accept the custom flip VDM.

BRANCH=Samus
BUG=chrome-os-partner:32163
TEST=COnnect Plankton and Ryu. Press the button on Plankton and make
sure the polarity GPIOs on Ryu are negated.

Change-Id: I7ee5ea70067de4f422a7478623fe7fe8d3724372
Signed-off-by: Vic Yang <victoryang@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/223325
Reviewed-by: Alec Berg <alecaberg@chromium.org>
2014-10-18 07:38:22 +00:00

206 lines
5.5 KiB
C

/* Copyright (c) 2014 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.
*/
/* ryu board configuration */
#include "adc.h"
#include "adc_chip.h"
#include "battery.h"
#include "charger.h"
#include "common.h"
#include "console.h"
#include "gpio.h"
#include "hooks.h"
#include "host_command.h"
#include "i2c.h"
#include "inductive_charging.h"
#include "power.h"
#include "power_button.h"
#include "registers.h"
#include "task.h"
#include "usb_pd.h"
#include "usb_pd_config.h"
#include "util.h"
void vbus_evt(enum gpio_signal signal)
{
ccprintf("VBUS %d, %d!\n", signal, gpio_get_level(signal));
task_wake(TASK_ID_PD);
}
void unhandled_evt(enum gpio_signal signal)
{
ccprintf("Unhandled INT %d,%d!\n", signal, gpio_get_level(signal));
}
#include "gpio_list.h"
/* Initialize board. */
static void board_init(void)
{
/*
* Determine recovery mode is requested by the power, volup, and
* voldown buttons being pressed.
*/
if (power_button_signal_asserted() &&
!gpio_get_level(GPIO_BTN_VOLD_L) &&
!gpio_get_level(GPIO_BTN_VOLU_L))
host_set_single_event(EC_HOST_EVENT_KEYBOARD_RECOVERY);
/*
* Enable CC lines after all GPIO have been initialized. Note, it is
* important that this is enabled after the CC_DEVICE_ODL lines are
* set low to specify device mode.
*/
gpio_set_level(GPIO_USBC_CC_EN, 1);
/* Enable interrupts on VBUS transitions. */
gpio_enable_interrupt(GPIO_CHGR_ACOK);
}
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
/* power signal list. Must match order of enum power_signal. */
const struct power_signal_info power_signal_list[] = {
{GPIO_AP_HOLD, 1, "AP_HOLD"},
{GPIO_AP_IN_SUSPEND, 1, "SUSPEND_ASSERTED"},
};
BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT);
/* ADC channels */
const struct adc_t adc_channels[] = {
/* Vbus sensing. Converted to mV, /10 voltage divider. */
[ADC_VBUS] = {"VBUS", 30000, 4096, 0, STM32_AIN(0)},
/* USB PD CC lines sensing. Converted to mV (3000mV/4096). */
[ADC_CC1_PD] = {"CC1_PD", 3000, 4096, 0, STM32_AIN(1)},
[ADC_CC2_PD] = {"CC1_PD", 3000, 4096, 0, STM32_AIN(3)},
/* Charger current sensing. Converted to mA. */
[ADC_IADP] = {"IADP", 7500, 4096, 0, STM32_AIN(8)},
[ADC_IBAT] = {"IBAT", 37500, 4096, 0, STM32_AIN(13)},
};
BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);
/* I2C ports */
const struct i2c_port_t i2c_ports[] = {
{"master", I2C_PORT_MASTER, 100,
GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA},
{"slave", I2C_PORT_SLAVE, 100,
GPIO_SLAVE_I2C_SCL, GPIO_SLAVE_I2C_SDA},
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
void board_set_usb_mux(int port, enum typec_mux mux, int polarity)
{
/* reset everything */
gpio_set_level(GPIO_USBC_SS_EN_L, 1);
gpio_set_level(GPIO_USBC_DP_MODE_L, 1);
gpio_set_level(GPIO_USBC_DP_POLARITY, 1);
gpio_set_level(GPIO_USBC_SS1_USB_MODE_L, 1);
gpio_set_level(GPIO_USBC_SS2_USB_MODE_L, 1);
if (mux == TYPEC_MUX_NONE)
/* everything is already disabled, we can return */
return;
if (mux == TYPEC_MUX_USB || mux == TYPEC_MUX_DOCK) {
/* USB 3.0 uses 2 superspeed lanes */
gpio_set_level(polarity ? GPIO_USBC_SS2_USB_MODE_L :
GPIO_USBC_SS1_USB_MODE_L, 0);
}
if (mux == TYPEC_MUX_DP || mux == TYPEC_MUX_DOCK) {
/* DP uses available superspeed lanes (x2 or x4) */
gpio_set_level(GPIO_USBC_DP_POLARITY, polarity);
gpio_set_level(GPIO_USBC_DP_MODE_L, 0);
}
/* switch on superspeed lanes */
gpio_set_level(GPIO_USBC_SS_EN_L, 0);
}
int board_get_usb_mux(int port, const char **dp_str, const char **usb_str)
{
int has_ss = !gpio_get_level(GPIO_USBC_SS_EN_L);
int has_usb = !gpio_get_level(GPIO_USBC_SS1_USB_MODE_L) ||
!gpio_get_level(GPIO_USBC_SS2_USB_MODE_L);
int has_dp = !gpio_get_level(GPIO_USBC_DP_MODE_L);
if (has_dp)
*dp_str = gpio_get_level(GPIO_USBC_DP_POLARITY) ? "DP2" : "DP1";
else
*dp_str = NULL;
if (has_usb)
*usb_str = gpio_get_level(GPIO_USBC_SS1_USB_MODE_L) ?
"USB2" : "USB1";
else
*usb_str = NULL;
return has_ss;
}
void board_flip_usb_mux(int port)
{
int usb_polarity;
/* Flip DP polarity */
gpio_set_level(GPIO_USBC_DP_POLARITY,
!gpio_get_level(GPIO_USBC_DP_POLARITY));
/* Flip USB polarity if enabled */
if (gpio_get_level(GPIO_USBC_SS1_USB_MODE_L) &&
gpio_get_level(GPIO_USBC_SS2_USB_MODE_L))
return;
usb_polarity = gpio_get_level(GPIO_USBC_SS1_USB_MODE_L);
/*
* Disable both sides first so that we don't enable both at the
* same time accidentally.
*/
gpio_set_level(GPIO_USBC_SS1_USB_MODE_L, 1);
gpio_set_level(GPIO_USBC_SS2_USB_MODE_L, 1);
gpio_set_level(GPIO_USBC_SS1_USB_MODE_L, !usb_polarity);
gpio_set_level(GPIO_USBC_SS2_USB_MODE_L, usb_polarity);
}
/**
* Discharge battery when on AC power for factory test.
*/
int board_discharge_on_ac(int enable)
{
return charger_discharge_on_ac(enable);
}
int extpower_is_present(void)
{
return gpio_get_level(GPIO_CHGR_ACOK);
}
/* Battery temperature ranges in degrees C */
static const struct battery_info info = {
/* Design voltage */
.voltage_max = 4350,
.voltage_normal = 3800,
.voltage_min = 2800,
/* Pre-charge current: I <= 0.01C */
.precharge_current = 64, /* mA */
/* Operational temperature range */
.start_charging_min_c = 0,
.start_charging_max_c = 45,
.charging_min_c = 0,
.charging_max_c = 50,
.discharging_min_c = -20,
.discharging_max_c = 60,
};
const struct battery_info *battery_get_info(void)
{
return &info;
}
/* Fake lid switch */
int lid_is_open(void)
{
return 1;
}