Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src/board/system76: Add USB port power options #64

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/board/novacustom/v540tnx/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ void gpio_init(void) {
GPDRC = 0;
// PWR_BTN#
GPDRD = BIT(5);
// USB_PWR_EN
GPDRE = BIT(3);
// H_PECI
GPDRF = BIT(6);
// H_PROCHOT_EC
Expand Down Expand Up @@ -159,7 +157,7 @@ void gpio_init(void) {
// TBT_I2C_IRQ2Z
GPCRE2 = GPIO_IN;
// USB_PWR_EN
GPCRE3 = GPIO_OUT | GPIO_UP;
GPCRE3 = GPIO_OUT;
// DD_ON
GPCRE4 = GPIO_OUT;
// EC_RSMRST#
Expand Down
3 changes: 3 additions & 0 deletions src/board/novacustom/v540tnx/include/board/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,8 @@ extern struct Gpio __code VA_EC_EN;
#define HAVE_WLAN_EN 0
extern struct Gpio __code WLAN_PWR_EN;
extern struct Gpio __code XLP_OUT;
#define HAVE_USB_CHARGE_EN 1
extern struct Gpio __code USB_CHARGE_EN;
extern struct Gpio __code USB_PWR_EN_N;

#endif // _BOARD_GPIO_H
2 changes: 0 additions & 2 deletions src/board/novacustom/v540tu/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ void gpio_init(void) {
GPDRC = 0;
// PWR_BTN#
GPDRD = BIT(5);
// USB_PWR_EN
GPDRE = BIT(3);
// H_PECI
GPDRF = BIT(6);
// H_PROCHOT_EC
Expand Down
3 changes: 3 additions & 0 deletions src/board/novacustom/v540tu/include/board/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,8 @@ extern struct Gpio __code VA_EC_EN;
#define HAVE_WLAN_EN 0
extern struct Gpio __code WLAN_PWR_EN;
extern struct Gpio __code XLP_OUT;
#define HAVE_USB_CHARGE_EN 1
extern struct Gpio __code USB_CHARGE_EN;
extern struct Gpio __code USB_PWR_EN_N;

#endif // _BOARD_GPIO_H
4 changes: 1 addition & 3 deletions src/board/novacustom/v560tnx/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ void gpio_init(void) {
GPDRC = 0;
// PWR_BTN#
GPDRD = BIT(5);
// USB_PWR_EN
GPDRE = BIT(3);
// H_PECI
GPDRF = BIT(6);
// H_PROCHOT_EC
Expand Down Expand Up @@ -159,7 +157,7 @@ void gpio_init(void) {
// TBT_I2C_IRQ2Z
GPCRE2 = GPIO_IN;
// USB_PWR_EN
GPCRE3 = GPIO_OUT | GPIO_UP;
GPCRE3 = GPIO_OUT;
// DD_ON
GPCRE4 = GPIO_OUT;
// EC_RSMRST#
Expand Down
3 changes: 3 additions & 0 deletions src/board/novacustom/v560tnx/include/board/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,8 @@ extern struct Gpio __code VA_EC_EN;
#define HAVE_WLAN_EN 0
extern struct Gpio __code WLAN_PWR_EN;
extern struct Gpio __code XLP_OUT;
#define HAVE_USB_CHARGE_EN 1
extern struct Gpio __code USB_CHARGE_EN;
extern struct Gpio __code USB_PWR_EN_N;

#endif // _BOARD_GPIO_H
2 changes: 0 additions & 2 deletions src/board/novacustom/v560tu/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ void gpio_init(void) {
GPDRC = 0;
// PWR_BTN#
GPDRD = BIT(5);
// USB_PWR_EN
GPDRE = BIT(3);
// H_PECI
GPDRF = BIT(6);
// H_PROCHOT_EC
Expand Down
3 changes: 3 additions & 0 deletions src/board/novacustom/v560tu/include/board/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,8 @@ extern struct Gpio __code VA_EC_EN;
#define HAVE_WLAN_EN 0
extern struct Gpio __code WLAN_PWR_EN;
extern struct Gpio __code XLP_OUT;
#define HAVE_USB_CHARGE_EN 1
extern struct Gpio __code USB_CHARGE_EN;
extern struct Gpio __code USB_PWR_EN_N;

#endif // _BOARD_GPIO_H
6 changes: 3 additions & 3 deletions src/board/system76/common/common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ board-common-y += wireless.c
# 3 - INFO
# 4 - DEBUG
# 5 - TRACE
CFLAGS+=-DLEVEL=2
CFLAGS+=-DLEVEL=4

# Uncomment to enable debug logging over keyboard parallel port
#CFLAGS+=-DPARALLEL_DEBUG
CFLAGS+=-DPARALLEL_DEBUG

# Uncomment to enable I2C debug on 0x76
CFLAGS+=-DI2C_DEBUGGER=0x76
#CFLAGS+=-DI2C_DEBUGGER=0x76

ifeq ($(CONFIG_SECURITY),y)
CFLAGS+=-DCONFIG_SECURITY=1
Expand Down
7 changes: 7 additions & 0 deletions src/board/system76/common/include/board/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,14 @@ enum {
OPT_BAT_THRESHOLD_START,
OPT_BAT_THRESHOLD_STOP,
OPT_ALLOW_BAT_BOOST,
OPT_USB_POWER,
NUM_OPTIONS
};

enum {
USB_POWER_ON_IN_S0,
USB_POWER_ALWAYS_ON,
USB_POWER_ON_AC
};

#endif // _BOARD_OPTIONS_H
3 changes: 2 additions & 1 deletion src/board/system76/common/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ uint8_t DEFAULT_OPTIONS[NUM_OPTIONS] = {
[OPT_BAT_THRESHOLD_START] = 95,
[OPT_BAT_THRESHOLD_STOP] = 98,
[OPT_ALLOW_BAT_BOOST] = 0,
[OPT_USB_POWER] = 0,
};
// clang-format on

#define SAVE_IMMEDIATELY BIT(OPT_POWER_ON_AC)
#define SAVE_IMMEDIATELY (BIT(OPT_POWER_ON_AC) || BIT(OPT_USB_POWER))

// Config is in the second to last sector of flash
const uint32_t OPTIONS_ADDR = 0x1F800;
Expand Down
122 changes: 110 additions & 12 deletions src/board/system76/common/power.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,19 @@
#define HAVE_PD_EN 0
#endif

// Disable by default
#ifndef HAVE_USB_CHARGE_EN
#define HAVE_USB_CHARGE_EN 0
#endif

#ifndef HAVE_USB_PWR_EN_N
#define HAVE_USB_PWR_EN_N 1
#endif

#ifndef HAVE_CC_EN
#define HAVE_CC_EN 0
#endif

#ifndef HAVE_XLP_OUT
#define HAVE_XLP_OUT 1
#endif
Expand Down Expand Up @@ -201,6 +214,70 @@ void update_power_state(void) {
}
}

static void usb_power_control(bool enable) {
#if HAVE_USB_PWR_EN_N
GPIO_SET_DEBUG(USB_PWR_EN_N, enable);
delay_ms(20);
#endif
#if HAVE_PD_EN
GPIO_SET_DEBUG(PD_EN, enable);
delay_ms(20);
#endif
#if HAVE_CC_EN
// CC_EN controls USB Type-C port power
GPIO_SET_DEBUG(CC_EN, enable);
delay_ms(20);
#endif
}

static void configure_usb_port_power(bool powering_on, bool ac_change) {
bool usb_port_power;
static bool usb_port_power_last = false;
uint8_t usb_power_opt = options_get(OPT_USB_POWER);

if (usb_power_opt > USB_POWER_ON_AC)
usb_power_opt = USB_POWER_ON_IN_S0;

usb_port_power = (usb_power_opt == USB_POWER_ALWAYS_ON);

DEBUG("Configure USB port power, option %u, state %u\n", usb_power_opt, usb_port_power);

update_power_state();

if (powering_on) {
usb_port_power = true;
#if HAVE_USB_CHARGE_EN
GPIO_SET_DEBUG(USB_CHARGE_EN, false);
delay_ms(20);
#endif
} else if (ac_change) {
// If we change AC state, only change USB port power in the powered
// off/S5 state
if (power_state == POWER_STATE_OFF || power_state == POWER_STATE_S5) {
if (usb_power_opt == USB_POWER_ON_AC)
usb_port_power = !gpio_get(&ACIN_N);
} else {
usb_port_power = usb_port_power_last;
}
} else {
if (usb_power_opt == USB_POWER_ON_AC)
usb_port_power = !gpio_get(&ACIN_N);
}

if (usb_port_power_last != usb_port_power) {
usb_port_power_last = usb_port_power;

DEBUG("USB ports power change to %sabled\n", usb_port_power ? "en" : "dis");

usb_power_control(usb_port_power);
#if HAVE_USB_CHARGE_EN
if (!powering_on)
// Enables VDD5 (like DD_ON), but does not enable 3.3V
GPIO_SET_DEBUG(USB_CHARGE_EN, usb_port_power);
#endif
}
}

void power_init(void) {
// See Figure 12-19 in Whiskey Lake Platform Design Guide
// | VCCRTC | RTCRST# | VccPRIM |
Expand All @@ -211,6 +288,11 @@ void power_init(void) {
tPCH04;

update_power_state();

// Set USB power according to option. Must be called when AC is being
// plugged while powered off, otherwise one would have to press a power
// button to make effect.
// configure_usb_port_power(false, false);
}

void power_on(void) {
Expand All @@ -229,14 +311,15 @@ void power_on(void) {
// avoid leakage
GPIO_SET_DEBUG(VA_EC_EN, true);
#endif // HAVE_VA_EC_EN
#if HAVE_PD_EN
GPIO_SET_DEBUG(PD_EN, true);
#endif

tPCH06;

// Enable VDD5
GPIO_SET_DEBUG(DD_ON, true);

// Configure USB port power before powering on
configure_usb_port_power(true, false);

#if HAVE_SUS_PWR_ACK
// De-assert SUS_ACK# - TODO is this needed on non-dsx?
GPIO_SET_DEBUG(SUS_PWR_ACK, true);
Expand Down Expand Up @@ -318,13 +401,12 @@ void power_off(void) {
// De-assert RSMRST#
GPIO_SET_DEBUG(EC_RSMRST_N, false);

configure_usb_port_power(false, false);

// Disable VDD5
GPIO_SET_DEBUG(DD_ON, false);
tPCH12;

#if HAVE_PD_EN
GPIO_SET_DEBUG(PD_EN, false);
#endif
#if HAVE_VA_EC_EN
// Disable VCCPRIM_* planes
GPIO_SET_DEBUG(VA_EC_EN, false);
Expand Down Expand Up @@ -429,6 +511,7 @@ void power_event(void) {
GPIO_SET_DEBUG(H_PROCHOT_EC, false);
ac_unplug_time = time_get();
battery_charger_disable();
configure_usb_port_power(false, true);
} else {
DEBUG("plugged in\n");
battery_charger_configure();
Expand All @@ -438,13 +521,16 @@ void power_event(void) {
power_on();
break;
case POWER_STATE_S5:
configure_usb_port_power(true, true);
GPIO_SET_DEBUG(PWR_BTN_N, false);
delay_ms(32); // PWRBTN# must assert for at least 16 ms, we do twice that
GPIO_SET_DEBUG(PWR_BTN_N, true);
break;
default:
break;
}
} else {
configure_usb_port_power(false, true);
}
}
power_apply_limit(!ac_new);
Expand Down Expand Up @@ -542,6 +628,9 @@ void power_event(void) {
// Assert SYS_PWROK, system can finally perform PLT_RST# and boot
GPIO_SET_DEBUG(PCH_PWROK_EC, true);
#endif // HAVE_PCH_PWROK_EC

configure_usb_port_power(true, false);

} else if (!pg_new && pg_last) {
DEBUG("%02X: ALL_SYS_PWRGD de-asserted\n", main_cycle);

Expand All @@ -554,6 +643,8 @@ void power_event(void) {
// De-assert PCH_PWROK
GPIO_SET_DEBUG(PM_PWROK, false);
#endif // HAVE_PM_PWROK

configure_usb_port_power(false, false);
}
pg_last = pg_new;

Expand Down Expand Up @@ -682,15 +773,22 @@ void power_event(void) {
} else {
// CPU off and AC adapter unplugged, flashing orange light
gpio_set(&LED_PWR, false);
if ((time - last_time) >= 1000) {
gpio_set(&LED_ACIN, !gpio_get(&LED_ACIN));
last_time = time;
}

// Don't blink if we have USB power enabled, because we can't
// unset XLP_OUT to keep USB powered
if (options_get(OPT_USB_POWER) == USB_POWER_ON_IN_S0) {
if ((time - last_time) >= 1000) {
gpio_set(&LED_ACIN, !gpio_get(&LED_ACIN));
last_time = time;
}
#if HAVE_XLP_OUT
// Power off VDD3 if system should be off
gpio_set(&XLP_OUT, 0);
DEBUG("Powering off VDD3\n");
// Power off VDD3 if system should be off
gpio_set(&XLP_OUT, 0);
#endif // HAVE_XLP_OUT
} else {
gpio_set(&LED_ACIN, false);
}
}

//TODO: do not require both LEDs
Expand Down
12 changes: 6 additions & 6 deletions src/board/system76/darp7/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ struct Gpio __code VA_EC_EN = GPIO(J, 4);
struct Gpio __code WLAN_EN = GPIO(G, 1);
struct Gpio __code WLAN_PWR_EN = GPIO(A, 3);
struct Gpio __code XLP_OUT = GPIO(B, 4);
struct Gpio __code USB_CHARGE_EN = GPIO(F, 1);
struct Gpio __code CC_EN = GPIO(F, 7);
// clang-format on

void gpio_init() {
Expand All @@ -68,8 +70,6 @@ void gpio_init() {
GPDRC = 0;
// PWR_BTN#, SMI#
GPDRD = BIT(5) | BIT(4);
// USB_PWR_EN#
GPDRE = BIT(3);
// H_PECI
GPDRF = BIT(6);
// H_PROCHOT_EC#
Expand Down Expand Up @@ -152,7 +152,7 @@ void gpio_init() {
// RGBKB-DET#
GPCRE2 = GPIO_IN | GPIO_UP;
// USB_PWR_EN#
GPCRE3 = GPIO_OUT | GPIO_UP;
GPCRE3 = GPIO_OUT;
// DD_ON
GPCRE4 = GPIO_OUT | GPIO_DOWN;
// EC_RSMRST#
Expand All @@ -164,7 +164,7 @@ void gpio_init() {
// 80CLK
GPCRF0 = GPIO_IN;
// USB_CHARGE_EN
GPCRF1 = GPIO_OUT | GPIO_UP;
GPCRF1 = GPIO_OUT;
// 3IN1
GPCRF2 = GPIO_IN | GPIO_UP;
// NC
Expand All @@ -175,8 +175,8 @@ void gpio_init() {
GPCRF5 = GPIO_ALT;
// H_PECI
GPCRF6 = GPIO_ALT;
//TODO: CC_EN
GPCRF7 = GPIO_IN | GPIO_UP;
// CC_EN
GPCRF7 = GPIO_OUT;
// VCCIN_AUX_PG
GPCRG0 = GPIO_IN;
// WLAN_EN
Expand Down
Loading
Loading