ACPI: Add usb_charge_mode_from_gnvs()

Early Chromebook generations stored the information about
USB port power control for S3/S5 sleepstates in GNVS, although
the configuration is static.

Reduce code duplication and react to ACPI S4 as if it was ACPI
S5 request.

Change-Id: I7e6f37a023b0e9317dcf0355dfa70e28d51cdad9
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/74524
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
diff --git a/src/acpi/Kconfig b/src/acpi/Kconfig
index b3a87f9..b72d2c6 100644
--- a/src/acpi/Kconfig
+++ b/src/acpi/Kconfig
@@ -29,6 +29,13 @@
 	  Set to indicate <soc/nvs.h> exists for the platform with a definition
 	  for global_nvs.
 
+config ACPI_GNVS_USB_CHARGECTL
+	bool
+	depends on ACPI_SOC_NVS
+	help
+	  Set to indicate <soc/nvs.h> implements fields s3u0, s3u1, s5u0, s5u1
+	  to control USB port power rail for S3/S4/S5 sleep states.
+
 config ACPI_CUSTOM_MADT
 	bool
 	default n if ACPI_NO_CUSTOM_MADT
diff --git a/src/acpi/acpi_pm.c b/src/acpi/acpi_pm.c
index 40a3fbd..722d8f6 100644
--- a/src/acpi/acpi_pm.c
+++ b/src/acpi/acpi_pm.c
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
 #include <acpi/acpi.h>
+#include <acpi/acpi_gnvs.h>
 #include <acpi/acpi_pm.h>
 #include <assert.h>
 #include <cbmem.h>
@@ -59,3 +60,29 @@
 	}
 	return 0;
 }
+
+/* Not every <soc/nvs.h> exists and has required fields. */
+#if CONFIG(ACPI_GNVS_USB_CHARGECTL) && ENV_SMM
+
+#include <cpu/x86/smm.h>
+#include <soc/nvs.h>
+
+void usb_charge_mode_from_gnvs(uint8_t slp_typ, bool *usb0_disable, bool *usb1_disable)
+{
+	if (!gnvs)
+		return;
+
+	switch (slp_typ) {
+	case ACPI_S3:
+		*usb0_disable = (gnvs->s3u0 == 0);
+		*usb1_disable = (gnvs->s3u1 == 0);
+		break;
+	case ACPI_S4:
+	case ACPI_S5:
+		*usb0_disable = (gnvs->s5u0 == 0);
+		*usb1_disable = (gnvs->s5u1 == 0);
+		break;
+	}
+}
+
+#endif /* CONFIG(ACPI_GNVS_USB_CHARGECTL) */
diff --git a/src/ec/google/chromeec/smihandler.c b/src/ec/google/chromeec/smihandler.c
index b5ec3715..91b4231 100644
--- a/src/ec/google/chromeec/smihandler.c
+++ b/src/ec/google/chromeec/smihandler.c
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
 #include <acpi/acpi.h>
+#include <acpi/acpi_gnvs.h>
 #include <console/console.h>
 #include <cpu/x86/smm.h>
 #include <ec/google/chromeec/ec.h>
@@ -45,6 +46,19 @@
 		;
 }
 
+void chromeec_set_usb_charge_mode(int slp_type)
+{
+	bool usb0_disable = 0, usb1_disable = 0;
+
+	usb_charge_mode_from_gnvs(slp_type, &usb0_disable, &usb1_disable);
+
+	if (usb0_disable)
+		google_chromeec_set_usb_charge_mode(0, USB_CHARGE_MODE_DISABLED);
+
+	if (usb1_disable)
+		google_chromeec_set_usb_charge_mode(1, USB_CHARGE_MODE_DISABLED);
+}
+
 void chromeec_smi_sleep(int slp_type, uint64_t s3_mask, uint64_t s5_mask)
 {
 	if (!google_chromeec_is_uhepi_supported()) {
diff --git a/src/ec/google/chromeec/smm.h b/src/ec/google/chromeec/smm.h
index 6f209a7..895782d 100644
--- a/src/ec/google/chromeec/smm.h
+++ b/src/ec/google/chromeec/smm.h
@@ -8,6 +8,8 @@
 /* Process all events from the EC when EC triggered an SMI#. */
 void chromeec_smi_process_events(void);
 
+void chromeec_set_usb_charge_mode(int slp_type);
+
 /*
  * Set wake masks according to sleep type, clear SCI and SMI masks,
  * and clear any pending events.
diff --git a/src/include/acpi/acpi_gnvs.h b/src/include/acpi/acpi_gnvs.h
index ef6ec29..fe6924f 100644
--- a/src/include/acpi/acpi_gnvs.h
+++ b/src/include/acpi/acpi_gnvs.h
@@ -18,6 +18,9 @@
 static inline int acpi_reset_gnvs_for_wake(struct global_nvs **gnvs) { return -1; }
 #endif
 
+/* Return GNVS fields for USB0/1 disablement for S3/S4/S5 sleep states. */
+void usb_charge_mode_from_gnvs(uint8_t slp_typ, bool *usb0_disable, bool *usb1_disable);
+
 /*
  * These functions populate the gnvs structure in acpi table.
  * Defined as weak in common acpi as gnvs structure definition is
diff --git a/src/mainboard/google/auron/Kconfig b/src/mainboard/google/auron/Kconfig
index f503d46..e7ba578 100644
--- a/src/mainboard/google/auron/Kconfig
+++ b/src/mainboard/google/auron/Kconfig
@@ -1,5 +1,6 @@
 config BOARD_GOOGLE_BASEBOARD_AURON
 	def_bool n
+	select ACPI_GNVS_USB_CHARGECTL
 	select BOARD_ROMSIZE_KB_8192
 	select BROADWELL_LPDDR3 if BOARD_GOOGLE_SAMUS
 	select EC_GOOGLE_CHROMEEC
diff --git a/src/mainboard/google/auron/acpi_tables.c b/src/mainboard/google/auron/acpi_tables.c
index 501f54b..048de76 100644
--- a/src/mainboard/google/auron/acpi_tables.c
+++ b/src/mainboard/google/auron/acpi_tables.c
@@ -10,9 +10,7 @@
 {
 	/* Enable USB ports in S3 */
 	gnvs->s3u0 = 1;
-
-	/* Disable USB ports in S5 */
-	gnvs->s5u0 = 0;
+	gnvs->s3u1 = gnvs->s3u0;
 
 	gnvs->tmps = CTL_TDP_SENSOR_ID;
 	gnvs->tcrt = CRITICAL_TEMPERATURE;
diff --git a/src/mainboard/google/auron/smihandler.c b/src/mainboard/google/auron/smihandler.c
index 237a2b3..0fc3588 100644
--- a/src/mainboard/google/auron/smihandler.c
+++ b/src/mainboard/google/auron/smihandler.c
@@ -8,7 +8,6 @@
 #include <ec/google/chromeec/smm.h>
 #include <southbridge/intel/lynxpoint/lp_gpio.h>
 #include <soc/iomap.h>
-#include <soc/nvs.h>
 #include "ec.h"
 #include <variant/onboard.h>
 
@@ -36,28 +35,17 @@
 void mainboard_smi_sleep(u8 slp_typ)
 {
 	/* Disable USB charging if required */
+	/* NOTE: Setting of usb0 _may_ also control usb1 here. */
+	chromeec_set_usb_charge_mode(slp_typ);
+
 	switch (slp_typ) {
 	case ACPI_S3:
-		if (gnvs->s3u0 == 0) {
-			google_chromeec_set_usb_charge_mode(
-				0, USB_CHARGE_MODE_DISABLED);
-			google_chromeec_set_usb_charge_mode(
-				1, USB_CHARGE_MODE_DISABLED);
-		}
-
 		mainboard_disable_gpios();
 
 		/* Enable wake events */
 		google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS);
 		break;
 	case ACPI_S5:
-		if (gnvs->s5u0 == 0) {
-			google_chromeec_set_usb_charge_mode(
-				0, USB_CHARGE_MODE_DISABLED);
-			google_chromeec_set_usb_charge_mode(
-				1, USB_CHARGE_MODE_DISABLED);
-		}
-
 		mainboard_disable_gpios();
 
 		/* Enable wake events */
diff --git a/src/mainboard/google/butterfly/Kconfig b/src/mainboard/google/butterfly/Kconfig
index 49ac7d2..1eb81ee 100644
--- a/src/mainboard/google/butterfly/Kconfig
+++ b/src/mainboard/google/butterfly/Kconfig
@@ -2,6 +2,7 @@
 
 config BOARD_SPECIFIC_OPTIONS
 	def_bool y
+	select ACPI_GNVS_USB_CHARGECTL
 	select BOARD_ROMSIZE_KB_8192
 	select EC_QUANTA_ENE_KB3940Q
 	select GFX_GMA_PANEL_1_ON_LVDS
diff --git a/src/mainboard/google/butterfly/acpi_tables.c b/src/mainboard/google/butterfly/acpi_tables.c
index aa02f67..5973ffb 100644
--- a/src/mainboard/google/butterfly/acpi_tables.c
+++ b/src/mainboard/google/butterfly/acpi_tables.c
@@ -6,14 +6,6 @@
 
 void mainboard_fill_gnvs(struct global_nvs *gnvs)
 {
-	/* Disable USB ports in S3 by default */
-	gnvs->s3u0 = 0;
-	gnvs->s3u1 = 0;
-
-	/* Disable USB ports in S5 by default */
-	gnvs->s5u0 = 0;
-	gnvs->s5u1 = 0;
-
 	// the lid is open by default.
 	gnvs->lids = 1;
 
diff --git a/src/mainboard/google/butterfly/smihandler.c b/src/mainboard/google/butterfly/smihandler.c
index 23bd683..7963dac 100644
--- a/src/mainboard/google/butterfly/smihandler.c
+++ b/src/mainboard/google/butterfly/smihandler.c
@@ -1,8 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
+#include <acpi/acpi_gnvs.h>
 #include <console/console.h>
 #include <cpu/x86/smm.h>
-#include <soc/nvs.h>
 #include <southbridge/intel/bd82x6x/pch.h>
 #include <southbridge/intel/bd82x6x/me.h>
 #include <northbridge/intel/sandybridge/sandybridge.h>
@@ -13,8 +13,11 @@
 
 void mainboard_smi_sleep(u8 slp_typ)
 {
+	bool usb0_disable = 0, usb1_disable = 0;
+
 	/* Tell the EC to Enable USB power for S3 if requested */
-	if (gnvs->s3u0 != 0 || gnvs->s3u1 != 0)
+	usb_charge_mode_from_gnvs(3, &usb0_disable, &usb1_disable);
+	if (!usb0_disable || !usb1_disable)
 		ec_mem_write(EC_EC_PSW, ec_mem_read(EC_EC_PSW) | EC_PSW_USB);
 
 	/* Disable wake on USB, LAN & RTC */
diff --git a/src/mainboard/google/cyan/Kconfig b/src/mainboard/google/cyan/Kconfig
index 710ecc2..a162e3b 100644
--- a/src/mainboard/google/cyan/Kconfig
+++ b/src/mainboard/google/cyan/Kconfig
@@ -1,5 +1,6 @@
 config BOARD_GOOGLE_BASEBOARD_CYAN
 	def_bool n
+	select ACPI_GNVS_USB_CHARGECTL
 	select BOARD_ROMSIZE_KB_8192
 	select EC_GOOGLE_CHROMEEC
 	select EC_GOOGLE_CHROMEEC_ACPI_MEMMAP
diff --git a/src/mainboard/google/cyan/acpi_tables.c b/src/mainboard/google/cyan/acpi_tables.c
index a8e030a..96d5d34 100644
--- a/src/mainboard/google/cyan/acpi_tables.c
+++ b/src/mainboard/google/cyan/acpi_tables.c
@@ -11,10 +11,6 @@
 	gnvs->s3u0 = 1;
 	gnvs->s3u1 = 1;
 
-	/* Disable USB ports in S5 */
-	gnvs->s5u0 = 0;
-	gnvs->s5u1 = 0;
-
 	/* Disable PMIC I2C port for ACPI for all boards except cyan */
 	struct device_nvs *dev_nvs = acpi_get_device_nvs();
 	if (!CONFIG(BOARD_GOOGLE_CYAN))
diff --git a/src/mainboard/google/cyan/smihandler.c b/src/mainboard/google/cyan/smihandler.c
index 8f06cf4..efd6efe 100644
--- a/src/mainboard/google/cyan/smihandler.c
+++ b/src/mainboard/google/cyan/smihandler.c
@@ -7,7 +7,6 @@
 #include "ec.h"
 #include <ec/google/chromeec/ec.h>
 #include <ec/google/chromeec/smm.h>
-#include <soc/nvs.h>
 #include <soc/pm.h>
 #include <soc/gpio.h>
 
@@ -34,28 +33,16 @@
 	uint32_t	mask;
 
 	/* Disable USB charging if required */
+	chromeec_set_usb_charge_mode(slp_typ);
+
 	switch (slp_typ) {
 	case ACPI_S3:
-		if (gnvs->s3u0 == 0)
-			google_chromeec_set_usb_charge_mode(
-				0, USB_CHARGE_MODE_DISABLED);
-		if (gnvs->s3u1 == 0)
-			google_chromeec_set_usb_charge_mode(
-				1, USB_CHARGE_MODE_DISABLED);
-
 		/* Enable wake events */
 		google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS);
 		/* Enable wake pin in GPE block. */
 		enable_gpe(WAKE_GPIO_EN);
 		break;
 	case ACPI_S5:
-		if (gnvs->s5u0 == 0)
-			google_chromeec_set_usb_charge_mode(
-				0, USB_CHARGE_MODE_DISABLED);
-		if (gnvs->s5u1 == 0)
-			google_chromeec_set_usb_charge_mode(
-				1, USB_CHARGE_MODE_DISABLED);
-
 		/* Enable wake events */
 		google_chromeec_set_wake_mask(MAINBOARD_EC_S5_WAKE_EVENTS);
 
diff --git a/src/mainboard/google/link/Kconfig b/src/mainboard/google/link/Kconfig
index e6e4b0b..75a15b4 100644
--- a/src/mainboard/google/link/Kconfig
+++ b/src/mainboard/google/link/Kconfig
@@ -2,6 +2,7 @@
 
 config BOARD_SPECIFIC_OPTIONS
 	def_bool y
+	select ACPI_GNVS_USB_CHARGECTL
 	select BOARD_ROMSIZE_KB_8192
 	select EC_GOOGLE_CHROMEEC
 	select EC_GOOGLE_CHROMEEC_LPC
diff --git a/src/mainboard/google/link/acpi_tables.c b/src/mainboard/google/link/acpi_tables.c
index 9a23474..c232ade 100644
--- a/src/mainboard/google/link/acpi_tables.c
+++ b/src/mainboard/google/link/acpi_tables.c
@@ -6,14 +6,6 @@
 
 void mainboard_fill_gnvs(struct global_nvs *gnvs)
 {
-	/* Disable USB ports in S3 by default */
-	gnvs->s3u0 = 0;
-	gnvs->s3u1 = 0;
-
-	/* Disable USB ports in S5 by default */
-	gnvs->s5u0 = 0;
-	gnvs->s5u1 = 0;
-
 	gnvs->tmps = CTDP_SENSOR_ID;
 
 	gnvs->f1of = CTDP_NOMINAL_THRESHOLD_OFF;
diff --git a/src/mainboard/google/link/smihandler.c b/src/mainboard/google/link/smihandler.c
index 951cabc..81972ff 100644
--- a/src/mainboard/google/link/smihandler.c
+++ b/src/mainboard/google/link/smihandler.c
@@ -3,7 +3,6 @@
 #include <acpi/acpi.h>
 #include <console/console.h>
 #include <cpu/x86/smm.h>
-#include <soc/nvs.h>
 #include <southbridge/intel/bd82x6x/pch.h>
 #include <southbridge/intel/bd82x6x/me.h>
 #include <northbridge/intel/sandybridge/sandybridge.h>
@@ -22,24 +21,7 @@
 void mainboard_smi_sleep(u8 slp_typ)
 {
 	/* Disable USB charging if required */
-	switch (slp_typ) {
-	case ACPI_S3:
-		if (gnvs->s3u0 == 0)
-			google_chromeec_set_usb_charge_mode(
-				0, USB_CHARGE_MODE_DISABLED);
-		if (gnvs->s3u1 == 0)
-			google_chromeec_set_usb_charge_mode(
-				1, USB_CHARGE_MODE_DISABLED);
-		break;
-	case ACPI_S5:
-		if (gnvs->s5u0 == 0)
-			google_chromeec_set_usb_charge_mode(
-				0, USB_CHARGE_MODE_DISABLED);
-		if (gnvs->s5u1 == 0)
-			google_chromeec_set_usb_charge_mode(
-				1, USB_CHARGE_MODE_DISABLED);
-		break;
-	}
+	chromeec_set_usb_charge_mode(slp_typ);
 
 	/* Disable SCI and SMI events */
 	google_chromeec_set_smi_mask(0);
diff --git a/src/mainboard/google/parrot/Kconfig b/src/mainboard/google/parrot/Kconfig
index dd6df3e..4d8ce2b 100644
--- a/src/mainboard/google/parrot/Kconfig
+++ b/src/mainboard/google/parrot/Kconfig
@@ -2,6 +2,7 @@
 
 config BOARD_SPECIFIC_OPTIONS
 	def_bool y
+	select ACPI_GNVS_USB_CHARGECTL
 	select BOARD_ROMSIZE_KB_8192
 	select EC_COMPAL_ENE932
 	# This board also feature sandy-bridge CPU's so must have LVDS
diff --git a/src/mainboard/google/parrot/acpi_tables.c b/src/mainboard/google/parrot/acpi_tables.c
index 8f4396e..92a5553 100644
--- a/src/mainboard/google/parrot/acpi_tables.c
+++ b/src/mainboard/google/parrot/acpi_tables.c
@@ -11,14 +11,6 @@
 
 void mainboard_fill_gnvs(struct global_nvs *gnvs)
 {
-	/* Disable USB ports in S3 by default */
-	gnvs->s3u0 = 0;
-	gnvs->s3u1 = 0;
-
-	/* Disable USB ports in S5 by default */
-	gnvs->s5u0 = 0;
-	gnvs->s5u1 = 0;
-
 	/* EC handles all active thermal and fan control on Parrot. */
 	gnvs->tcrt = CRITICAL_TEMPERATURE;
 	gnvs->tpsv = PASSIVE_TEMPERATURE;
diff --git a/src/mainboard/google/parrot/smihandler.c b/src/mainboard/google/parrot/smihandler.c
index 7d519e3..10341fb 100644
--- a/src/mainboard/google/parrot/smihandler.c
+++ b/src/mainboard/google/parrot/smihandler.c
@@ -1,9 +1,9 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
+#include <acpi/acpi_gnvs.h>
 #include <console/console.h>
 #include <cpu/x86/smm.h>
 #include <halt.h>
-#include <soc/nvs.h>
 #include <southbridge/intel/bd82x6x/pch.h>
 #include <southbridge/intel/bd82x6x/me.h>
 #include <southbridge/intel/common/pmutil.h>
@@ -48,6 +48,8 @@
 
 void mainboard_smi_sleep(u8 slp_typ)
 {
+	bool usb0_disable = 0, usb1_disable = 0;
+
 	/* Disable SCI and SMI events */
 
 	/* Clear pending events that may trigger immediate wake */
@@ -55,7 +57,8 @@
 	/* Enable wake events */
 
 	/* Tell the EC to Disable USB power */
-	if (gnvs->s3u0 == 0 && gnvs->s3u1 == 0) {
+	usb_charge_mode_from_gnvs(3, &usb0_disable, &usb1_disable);
+	if (usb0_disable && usb1_disable) {
 		ec_kbc_write_cmd(0x45);
 		ec_kbc_write_ib(0xF2);
 	}
diff --git a/src/mainboard/google/rambi/Kconfig b/src/mainboard/google/rambi/Kconfig
index f74fef1..1c3c5cd 100644
--- a/src/mainboard/google/rambi/Kconfig
+++ b/src/mainboard/google/rambi/Kconfig
@@ -1,5 +1,6 @@
 config BOARD_GOOGLE_BASEBOARD_RAMBI
 	def_bool n
+	select ACPI_GNVS_USB_CHARGECTL
 	select BOARD_ROMSIZE_KB_8192
 	select EC_GOOGLE_CHROMEEC
 	select EC_GOOGLE_CHROMEEC_LPC
diff --git a/src/mainboard/google/rambi/acpi_tables.c b/src/mainboard/google/rambi/acpi_tables.c
index 161f68d..ec85efa 100644
--- a/src/mainboard/google/rambi/acpi_tables.c
+++ b/src/mainboard/google/rambi/acpi_tables.c
@@ -11,10 +11,6 @@
 	gnvs->s3u0 = 1;
 	gnvs->s3u1 = 1;
 
-	/* Disable USB ports in S5 */
-	gnvs->s5u0 = 0;
-	gnvs->s5u1 = 0;
-
 	/* TPM Present */
 	gnvs->tpmp = 1;
 
diff --git a/src/mainboard/google/rambi/smihandler.c b/src/mainboard/google/rambi/smihandler.c
index 3eb1d1d..5d3329f 100644
--- a/src/mainboard/google/rambi/smihandler.c
+++ b/src/mainboard/google/rambi/smihandler.c
@@ -8,7 +8,6 @@
 #include <ec/google/chromeec/smm.h>
 #include "ec.h"
 
-#include <soc/nvs.h>
 #include <soc/pm.h>
 
 /* The wake gpio is SUS_GPIO[0]. */
@@ -25,28 +24,16 @@
 void mainboard_smi_sleep(uint8_t slp_typ)
 {
 	/* Disable USB charging if required */
+	chromeec_set_usb_charge_mode(slp_typ);
+
 	switch (slp_typ) {
 	case ACPI_S3:
-		if (gnvs->s3u0 == 0)
-			google_chromeec_set_usb_charge_mode(
-				0, USB_CHARGE_MODE_DISABLED);
-		if (gnvs->s3u1 == 0)
-			google_chromeec_set_usb_charge_mode(
-				1, USB_CHARGE_MODE_DISABLED);
-
 		/* Enable wake events */
 		google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS);
 		/* Enable wake pin in GPE block. */
 		enable_gpe(WAKE_GPIO_EN);
 		break;
 	case ACPI_S5:
-		if (gnvs->s5u0 == 0)
-			google_chromeec_set_usb_charge_mode(
-				0, USB_CHARGE_MODE_DISABLED);
-		if (gnvs->s5u1 == 0)
-			google_chromeec_set_usb_charge_mode(
-				1, USB_CHARGE_MODE_DISABLED);
-
 		/* Enable wake events */
 		google_chromeec_set_wake_mask(MAINBOARD_EC_S5_WAKE_EVENTS);
 		break;
diff --git a/src/mainboard/google/slippy/Kconfig b/src/mainboard/google/slippy/Kconfig
index 437797c..8b4c67c 100644
--- a/src/mainboard/google/slippy/Kconfig
+++ b/src/mainboard/google/slippy/Kconfig
@@ -1,5 +1,6 @@
 config BOARD_GOOGLE_BASEBOARD_SLIPPY
 	def_bool n
+	select ACPI_GNVS_USB_CHARGECTL
 	select BOARD_ROMSIZE_KB_8192
 	select EC_GOOGLE_CHROMEEC
 	select EC_GOOGLE_CHROMEEC_LPC
diff --git a/src/mainboard/google/slippy/acpi_tables.c b/src/mainboard/google/slippy/acpi_tables.c
index 64bc09a..b7b77c2 100644
--- a/src/mainboard/google/slippy/acpi_tables.c
+++ b/src/mainboard/google/slippy/acpi_tables.c
@@ -13,10 +13,6 @@
 	gnvs->s3u0 = 1;
 	gnvs->s3u1 = 1;
 
-	/* Disable USB ports in S5 */
-	gnvs->s5u0 = 0;
-	gnvs->s5u1 = 0;
-
 	/* TPM Present */
 	gnvs->tpmp = 1;
 
diff --git a/src/mainboard/google/slippy/smihandler.c b/src/mainboard/google/slippy/smihandler.c
index 71e97af..7e4b271 100644
--- a/src/mainboard/google/slippy/smihandler.c
+++ b/src/mainboard/google/slippy/smihandler.c
@@ -3,7 +3,6 @@
 #include <acpi/acpi.h>
 #include <console/console.h>
 #include <cpu/x86/smm.h>
-#include <soc/nvs.h>
 #include <southbridge/intel/lynxpoint/pch.h>
 #include <southbridge/intel/common/gpio.h>
 #include <southbridge/intel/lynxpoint/me.h>
@@ -31,15 +30,10 @@
 void mainboard_smi_sleep(u8 slp_typ)
 {
 	/* Disable USB charging if required */
+	chromeec_set_usb_charge_mode(slp_typ);
+
 	switch (slp_typ) {
 	case ACPI_S3:
-		if (gnvs->s3u0 == 0)
-			google_chromeec_set_usb_charge_mode(
-				0, USB_CHARGE_MODE_DISABLED);
-		if (gnvs->s3u1 == 0)
-			google_chromeec_set_usb_charge_mode(
-				1, USB_CHARGE_MODE_DISABLED);
-
 		/* Prevent leak from standby rail to WLAN rail in S3. */
 		set_gpio(GPIO_WLAN_DISABLE_L, 0);
 		set_gpio(GPIO_PP3300_CODEC_EN, 0);
@@ -51,13 +45,6 @@
 		break;
 	case ACPI_S4:
 	case ACPI_S5:
-		if (gnvs->s5u0 == 0)
-			google_chromeec_set_usb_charge_mode(
-				0, USB_CHARGE_MODE_DISABLED);
-		if (gnvs->s5u1 == 0)
-			google_chromeec_set_usb_charge_mode(
-				1, USB_CHARGE_MODE_DISABLED);
-
 		/* Prevent leak from standby rail to WLAN rail in S5. */
 		set_gpio(GPIO_WLAN_DISABLE_L, 0);
 		set_gpio(GPIO_PP3300_CODEC_EN, 0);
diff --git a/src/mainboard/google/stout/Kconfig b/src/mainboard/google/stout/Kconfig
index 152c57f..d6ed754 100644
--- a/src/mainboard/google/stout/Kconfig
+++ b/src/mainboard/google/stout/Kconfig
@@ -2,6 +2,7 @@
 
 config BOARD_SPECIFIC_OPTIONS
 	def_bool y
+	select ACPI_GNVS_USB_CHARGECTL
 	select BOARD_ROMSIZE_KB_8192
 	select EC_QUANTA_IT8518
 	select GFX_GMA_PANEL_1_ON_LVDS
diff --git a/src/mainboard/google/stout/acpi_tables.c b/src/mainboard/google/stout/acpi_tables.c
index 0d5f06f..7e6d69c 100644
--- a/src/mainboard/google/stout/acpi_tables.c
+++ b/src/mainboard/google/stout/acpi_tables.c
@@ -9,14 +9,6 @@
 
 void mainboard_fill_gnvs(struct global_nvs *gnvs)
 {
-	/* Disable USB ports in S3 by default */
-	gnvs->s3u0 = 0;
-	gnvs->s3u1 = 0;
-
-	/* Disable USB ports in S5 by default */
-	gnvs->s5u0 = 0;
-	gnvs->s5u1 = 0;
-
 	/* EC handles all thermal and fan control on Stout. */
 	gnvs->tcrt = CRITICAL_TEMPERATURE;
 	gnvs->tpsv = PASSIVE_TEMPERATURE;
diff --git a/src/mainboard/google/stout/smihandler.c b/src/mainboard/google/stout/smihandler.c
index 30637ab..b77c73b 100644
--- a/src/mainboard/google/stout/smihandler.c
+++ b/src/mainboard/google/stout/smihandler.c
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
+#include <acpi/acpi_gnvs.h>
 #include <device/pci_ops.h>
 #include <console/console.h>
 #include <cpu/x86/smm.h>
@@ -38,6 +39,8 @@
 
 void mainboard_smi_sleep(u8 slp_typ)
 {
+	bool usb0_disable = 0, usb1_disable = 0;
+
 	/*
 	 * Tell the EC to Enable USB power for S3 if requested.
 	 * Bit0 of 0x0D/Bit0 of 0x26
@@ -47,7 +50,9 @@
 	 *             charge smart phone.
 	 * 1/1 USB on, yellow port in AUTO mode and didn't support wake up system.
 	 */
-	if (gnvs->s3u0 != 0 || gnvs->s3u1 != 0) {
+	usb_charge_mode_from_gnvs(3, &usb0_disable, &usb1_disable);
+
+	if (!usb0_disable || !usb1_disable) {
 		ec_write(EC_PERIPH_CNTL_3, ec_read(EC_PERIPH_CNTL_3) | 0x00);
 		ec_write(EC_USB_S3_EN, ec_read(EC_USB_S3_EN) | 0x01);
 		printk(BIOS_DEBUG, "USB wake from S3 enabled.\n");
diff --git a/src/mainboard/intel/strago/Kconfig b/src/mainboard/intel/strago/Kconfig
index b15984f..5cd7880 100644
--- a/src/mainboard/intel/strago/Kconfig
+++ b/src/mainboard/intel/strago/Kconfig
@@ -2,6 +2,7 @@
 
 config BOARD_SPECIFIC_OPTIONS
 	def_bool y
+	select ACPI_GNVS_USB_CHARGECTL
 	select BOARD_ROMSIZE_KB_8192
 	select EC_GOOGLE_CHROMEEC
 	select EC_GOOGLE_CHROMEEC_BOARDID
diff --git a/src/mainboard/intel/strago/acpi_tables.c b/src/mainboard/intel/strago/acpi_tables.c
index 279a5c1..5a705f4 100644
--- a/src/mainboard/intel/strago/acpi_tables.c
+++ b/src/mainboard/intel/strago/acpi_tables.c
@@ -11,10 +11,6 @@
 	gnvs->s3u0 = 1;
 	gnvs->s3u1 = 1;
 
-	/* Disable USB ports in S5 */
-	gnvs->s5u0 = 0;
-	gnvs->s5u1 = 0;
-
 	/* PMIC is configured in I2C1, hidden it from OS */
 	struct device_nvs *dev_nvs = acpi_get_device_nvs();
 	dev_nvs->lpss_en[LPSS_NVS_I2C2] = 0;
diff --git a/src/mainboard/intel/strago/smihandler.c b/src/mainboard/intel/strago/smihandler.c
index a625b62..6d29df8 100644
--- a/src/mainboard/intel/strago/smihandler.c
+++ b/src/mainboard/intel/strago/smihandler.c
@@ -8,7 +8,6 @@
 #include <ec/google/chromeec/ec.h>
 #include <ec/google/chromeec/smm.h>
 
-#include <soc/nvs.h>
 #include <soc/pm.h>
 #include <soc/gpio.h>
 
@@ -30,28 +29,16 @@
 void mainboard_smi_sleep(uint8_t slp_typ)
 {
 	/* Disable USB charging if required */
+	chromeec_set_usb_charge_mode(slp_typ);
+
 	switch (slp_typ) {
 	case ACPI_S3:
-		if (gnvs->s3u0 == 0)
-			google_chromeec_set_usb_charge_mode(
-				0, USB_CHARGE_MODE_DISABLED);
-		if (gnvs->s3u1 == 0)
-			google_chromeec_set_usb_charge_mode(
-				1, USB_CHARGE_MODE_DISABLED);
-
 		/* Enable wake events */
 		google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS);
 		/* Enable wake pin in GPE block. */
 		enable_gpe(WAKE_GPIO_EN);
 		break;
 	case ACPI_S5:
-		if (gnvs->s5u0 == 0)
-			google_chromeec_set_usb_charge_mode(
-				0, USB_CHARGE_MODE_DISABLED);
-		if (gnvs->s5u1 == 0)
-			google_chromeec_set_usb_charge_mode(
-				1, USB_CHARGE_MODE_DISABLED);
-
 		/* Enable wake events */
 		google_chromeec_set_wake_mask(MAINBOARD_EC_S5_WAKE_EVENTS);
 		break;
diff --git a/src/mainboard/samsung/lumpy/acpi_tables.c b/src/mainboard/samsung/lumpy/acpi_tables.c
index 4a96b5f..825ea7a 100644
--- a/src/mainboard/samsung/lumpy/acpi_tables.c
+++ b/src/mainboard/samsung/lumpy/acpi_tables.c
@@ -14,14 +14,6 @@
 	 */
 	gnvs->s33g = 0;
 
-	/* Disable USB ports in S3 by default */
-	gnvs->s3u0 = 0;
-	gnvs->s3u1 = 0;
-
-	/* Disable USB ports in S5 by default */
-	gnvs->s5u0 = 0;
-	gnvs->s5u1 = 0;
-
 	gnvs->f4of = FAN4_THRESHOLD_OFF;
 	gnvs->f4on = FAN4_THRESHOLD_ON;
 
diff --git a/src/soc/intel/broadwell/include/soc/nvs.h b/src/soc/intel/broadwell/include/soc/nvs.h
index f627c80..52fb711 100644
--- a/src/soc/intel/broadwell/include/soc/nvs.h
+++ b/src/soc/intel/broadwell/include/soc/nvs.h
@@ -30,7 +30,9 @@
 	u8	s33g; /* 0x15 - Enable 3G in S3 */
 	u8	lids; /* 0x16 - LID State */
 	u8	unused_was_pwrs; /* 0x17 - AC Power State */
-	u32	obsolete_cmem; /* 0x18 - 0x1b - CBMEM TOC */
+	u8	s5u1; /* 0x18 - compatibility only */
+	u8	s3u1; /* 0x19 - compatibility only */
+	u16	unused_incomplete_cmem; /* 0x1a - 0x1b - CBMEM TOC */
 	u32	unused_was_cbmc; /* 0x1c - 0x1f - coreboot Memory Console */
 	u64	pm1i; /* 0x20 - 0x27 - PM1 wake status bit */
 	u64	gpei; /* 0x28 - 0x2f - GPE wake status bit */