summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Short <keithshort@chromium.org>2018-12-19 16:17:28 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-01-08 01:59:12 -0800
commit90d177e3f0ae729bea7e24934a3c6ef9f2520d45 (patch)
treeda02f562f4d768beb09aaf198c252972347c232b
parent5079009d35d8900bb030cbc7d9ebc34cf3ad1696 (diff)
downloadchrome-ec-90d177e3f0ae729bea7e24934a3c6ef9f2520d45.tar.gz
cr50: Changes to support closed source EC factory mode
Drives OEM specific GPIOs to enable and disable factory mode to a closed source EC. BUG=b:118683718 BRANCH=none TEST=make buildall. Verified GPIO states with scope in both factory mode enable and disable conditions. Verified GPIO states are reapplied correctly after reboot, deep sleep, and power cycle. Change-Id: I9bc547504478fded5f95c515027e1da0f245d524 Signed-off-by: Keith Short <keithshort@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1358733 Reviewed-by: Mary Ruthven <mruthven@chromium.org>
-rw-r--r--board/cr50/board.c12
-rw-r--r--board/cr50/board.h26
-rw-r--r--board/cr50/build.mk1
-rw-r--r--board/cr50/closed_source_set1.c151
-rw-r--r--board/cr50/closed_source_set1.h25
-rw-r--r--board/cr50/gpio.inc12
-rw-r--r--board/cr50/usb_i2c.c12
-rw-r--r--common/ccd_config.c14
-rw-r--r--include/ccd_config.h12
9 files changed, 265 insertions, 0 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index 4477e1bfe8..ef8a91ec98 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -5,6 +5,7 @@
#include "board_id.h"
#include "ccd_config.h"
#include "clock.h"
+#include "closed_source_set1.h"
#include "common.h"
#include "console.h"
#include "dcrypto/dcrypto.h"
@@ -157,6 +158,11 @@ int board_tpm_uses_spi(void)
return !!(board_properties & BOARD_SLAVE_CONFIG_SPI);
}
+int board_uses_closed_source_set1(void)
+{
+ return !!(board_properties & BOARD_CLOSED_SOURCE_SET1);
+}
+
/* Get header address of the backup RW copy. */
const struct SignedHeader *get_other_rw_addr(void)
{
@@ -597,6 +603,9 @@ static void configure_board_specific_gpios(void)
/* Enable powerdown exit on DIOM0 */
GWRITE_FIELD(PINMUX, EXITEN0, DIOM0, 1);
}
+
+ if (board_uses_closed_source_set1())
+ closed_source_set1_configure_gpios();
}
void decrement_retry_counter(void)
@@ -769,6 +778,9 @@ static void board_ccd_config_changed(void)
& BOARD_CCD_STATE;
GWRITE_FIELD(PMU, LONG_LIFE_SCRATCH_WR_EN, REG1, 0);
+ if (board_uses_closed_source_set1())
+ closed_source_set1_update_factory_mode();
+
/* Update CCD state */
ccd_update_state();
}
diff --git a/board/cr50/board.h b/board/cr50/board.h
index e3c844c182..95a74e1af6 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -260,10 +260,36 @@ int is_ec_rst_asserted(void);
*/
void ccd_update_state(void);
+/**
+ * Return the state of the BOARD_USE_PLT_RST board strap option.
+ *
+ * @return 0 if option is not set, !=0 if option set.
+ */
int board_use_plt_rst(void);
+/**
+ * Return the state of the BOARD_NEEDS_SYS_RST_PULL_UP board strap option.
+ *
+ * @return 0 if option is not set, !=0 if option set.
+ */
int board_rst_pullup_needed(void);
+/**
+ * Return the state of the BOARD_SLAVE_CONFIG_I2C board strap option.
+ *
+ * @return 0 if option is not set, !=0 if option set.
+ */
int board_tpm_uses_i2c(void);
+/**
+ * Return the state of the BOARD_SLAVE_CONFIG_SPI board strap option.
+ *
+ * @return 0 if option is not set, !=0 if option set.
+ */
int board_tpm_uses_spi(void);
+/**
+ * Return the state of the BOARD_CLOSED_SOURCE_SET1 board strap option.
+ *
+ * @return 0 if option is not set, !=0 if option set.
+ */
+int board_uses_closed_source_set1(void);
int board_id_is_mismatched(void);
/* Allow for deep sleep to be enabled on AP shutdown */
int board_deep_sleep_allowed(void);
diff --git a/board/cr50/build.mk b/board/cr50/build.mk
index b65bdda1c6..b12bdc5f8b 100644
--- a/board/cr50/build.mk
+++ b/board/cr50/build.mk
@@ -31,6 +31,7 @@ dirs-y += $(BDIR)/tpm2
# Objects that we need to build
board-y = board.o
board-y += ap_state.o
+board-y += closed_source_set1.o
board-y += ec_state.o
board-y += power_button.o
board-y += servo_state.o
diff --git a/board/cr50/closed_source_set1.c b/board/cr50/closed_source_set1.c
new file mode 100644
index 0000000000..8c0a7f2829
--- /dev/null
+++ b/board/cr50/closed_source_set1.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2018 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.
+ *
+ * Board specific routines used only when BOARD_CLOSED_SOURCE_SET1 is
+ * enabled.
+ */
+#include "ccd_config.h"
+#include "closed_source_set1.h"
+#include "common.h"
+#include "console.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "registers.h"
+
+#define CPRINTF(format, args...) \
+ cprintf(CC_SYSTEM, "Closed Source Set1: " format, ## args)
+
+/*
+ * Map common gpio.inc pin names to descriptive names specific to the
+ * BOARD_CLOSED_SOURCE_SET1 option.
+ */
+#define GPIO_FACTORY_MODE GPIO_I2C_SCL_INA
+#define GPIO_CHROME_SEL GPIO_EN_PP3300_INA_L
+#define GPIO_EXIT_FACTORY_MODE GPIO_I2C_SDA_INA
+
+enum ec_trust_level {
+ EC_TL_FACTORY_MODE,
+ EC_TL_DIAGNOSTIC_MODE,
+ EC_TL_COREBOOT,
+};
+
+void closed_source_set1_configure_gpios(void)
+{
+ CPRINTF("configuring GPIOs\n");
+
+ /*
+ * Connect GPIO outputs to pads:
+ * GPIO0_12 (FACTORY_MODE) : B0
+ * GPIO0_13 (EXIT_FACTORY_MODE) : B1
+ * GPIO0_11 (CHROME_SEL) : B7
+ */
+ GWRITE(PINMUX, DIOB0_SEL, GC_PINMUX_GPIO0_GPIO12_SEL);
+ GWRITE(PINMUX, DIOB1_SEL, GC_PINMUX_GPIO0_GPIO13_SEL);
+ GWRITE(PINMUX, DIOB7_SEL, GC_PINMUX_GPIO0_GPIO11_SEL);
+
+ /*
+ * The PINMUX entries in gpio.inc already write to the GPIOn_GPOIn_SEL
+ * and DIOBn_CTL registers with values that work for GPIO output
+ * operation. If gpio.inc makes changes to the GPIO_I2C_SCL_INA,
+ * GPIO_I2C_SDA_INA, or GPIO_EN_PP3300_INA_L pinmux, then explicitly
+ * configure the corresponding GPIOn_GPIOn_SEL and DIOBn_CTL registers
+ * here.
+ */
+
+ /* Enable falling edge interrupt on I2C_SDA_SCL/EXIT_FACTORY_MODE */
+
+ /*
+ * TODO (keithshort): closed source EC documentation defines
+ * EXIT_FACTORY_MODE as an output from the EC that is driven low
+ * to indicate that factory mode must be terminated. However, the
+ * EC firmware has not yet (and may never) add this capability.
+ */
+// gpio_set_flags(GPIO_EXIT_FACTORY_MODE, GPIO_INPUT | GPIO_INT_F_FALLING);
+
+ closed_source_set1_update_factory_mode();
+}
+
+static void closed_source_set1_update_ec_trust_level(enum ec_trust_level tl)
+{
+ /*
+ * The EC state is partially controlled by the FACTORY_MODE and
+ * CHROME_SEL signals.
+ *
+ * State Description
+ * CHROME_SEL=0,FACTORY_MODE=1 TL0: EC factory mode
+ * CHROME_SEL=0,FACTORY_MODE=0 TL1: EC diagnostic mode
+ * CHROME_SEL=1,FACTORY_MODE=0 TL2: EC coreboot mode
+ * CHROME_SEL=1,FACTORY_MODE=1 Undefined
+ */
+ switch (tl) {
+ case EC_TL_FACTORY_MODE:
+ CPRINTF("enable factory mode\n");
+ /*
+ * Enable factory mode, CHROME_SEL must be set low first so
+ * that CHROME_SEL and FACTORY_MODE are not high
+ * simultaneously.
+ */
+ gpio_set_flags(GPIO_CHROME_SEL, GPIO_OUT_LOW);
+ gpio_set_flags(GPIO_FACTORY_MODE, GPIO_OUT_HIGH);
+ break;
+
+ case EC_TL_DIAGNOSTIC_MODE:
+ CPRINTF("enable diagnostic mode\n");
+
+ gpio_set_flags(GPIO_CHROME_SEL, GPIO_OUT_LOW);
+ gpio_set_flags(GPIO_FACTORY_MODE, GPIO_OUT_LOW);
+ break;
+
+ case EC_TL_COREBOOT:
+ CPRINTF("disable factory mode\n");
+ /*
+ * Disable factory mode, set FACTORY_MODE low first to avoid
+ * undefined state.
+ */
+ gpio_set_flags(GPIO_FACTORY_MODE, GPIO_OUT_LOW);
+ gpio_set_flags(GPIO_CHROME_SEL, GPIO_OUT_HIGH);
+ break;
+ default:
+ CPRINTF("unsupported EC trust level %d\n", tl);
+ }
+}
+
+void closed_source_set1_update_factory_mode(void)
+{
+ if (ccd_get_factory_mode())
+ closed_source_set1_update_ec_trust_level(EC_TL_FACTORY_MODE);
+ else
+ closed_source_set1_update_ec_trust_level(EC_TL_COREBOOT);
+}
+
+
+#ifdef CR50_DEV
+/* Debug command to manually set the EC trust level */
+static int ec_trust_level(int argc, char **argv)
+{
+ enum ec_trust_level tl;
+
+ if (argc > 1) {
+ tl = (enum ec_trust_level)atoi(argv[1]);
+
+ closed_source_set1_update_ec_trust_level(tl);
+ }
+
+ ccprintf("CCD factory mode = %d\n", ccd_get_factory_mode());
+
+ ccprintf("FACTORY_MODE = %d\n",
+ gpio_get_level(GPIO_FACTORY_MODE));
+ ccprintf("CHROME_SEL = %d\n",
+ gpio_get_level(GPIO_CHROME_SEL));
+ ccprintf("EXIT_FACTORY_MODE = %d\n",
+ gpio_get_level(GPIO_EXIT_FACTORY_MODE));
+
+ return 0;
+}
+DECLARE_SAFE_CONSOLE_COMMAND(ectrust, ec_trust_level,
+ "[0|1|2]",
+ "Get/set the EC trust level");
+#endif
+
diff --git a/board/cr50/closed_source_set1.h b/board/cr50/closed_source_set1.h
new file mode 100644
index 0000000000..44f7e39be0
--- /dev/null
+++ b/board/cr50/closed_source_set1.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#ifndef __EC_BOARD_CR50_CLOSED_SOURCE_SET1_H
+#define __EC_BOARD_CR50_CLOSED_SOURCE_SET1_H
+
+
+/**
+ * Configure the GPIOs specific to the BOARD_CLOSED_SOURCE_SET1 board strapping
+ * option. This includes the FACTORY_MODE, CHROME_SEL, and EXIT_FACTORY_MODE
+ * signals.
+ */
+void closed_source_set1_configure_gpios(void);
+
+/**
+ * Drive the GPIOs specific to BOARD_CLOSED_SOURCE_SET1 to match the current
+ * factory mode setting.
+ */
+void closed_source_set1_update_factory_mode(void);
+
+
+#endif /* ! __EC_BOARD_CR50_CLOSED_SOURCE_SET1_H */
diff --git a/board/cr50/gpio.inc b/board/cr50/gpio.inc
index 2943573b18..d9b0a8ff32 100644
--- a/board/cr50/gpio.inc
+++ b/board/cr50/gpio.inc
@@ -102,6 +102,10 @@ GPIO(STRAP_A1, PIN(1, 13), GPIO_INPUT)
GPIO(STRAP_B0, PIN(1, 14), GPIO_INPUT)
GPIO(STRAP_B1, PIN(1, 15), GPIO_INPUT)
+/*
+ * If you change the names of EN_PP3300_INA_L, I2C_SCL_INA, or I2C_SDA_INA,
+ * you also need to update the usage in closed_source_set1.c
+ */
/* Control the load switch powering the INA 3.3V rail */
GPIO(EN_PP3300_INA_L, PIN(0, 11), GPIO_ODR_HIGH)
/* GPIOs used for I2CM pins for INAs */
@@ -143,6 +147,10 @@ PINMUX(GPIO(INT_AP_L), A5, DIO_INPUT) /* DIOB7 is p_digitial_od */
/* We can't pull it up */
PINMUX(GPIO(EC_FLASH_SELECT), B2, DIO_INPUT)
PINMUX(GPIO(AP_FLASH_SELECT), B3, DIO_INPUT)
+/*
+ * Update closed_source_set1.c if pinmux for EN_PP3300_INA_L is changed or
+ * removed.
+ */
PINMUX(GPIO(EN_PP3300_INA_L), B7, DIO_INPUT)
/*
* To allow the EC to drive the signal we set sys_rst_l_out as an input here and
@@ -157,6 +165,10 @@ PINMUX(GPIO(SYS_RST_L_OUT), M0, DIO_INPUT)
*/
PINMUX(GPIO(CCD_MODE_L), M1, DIO_INPUT | DIO_OUTPUT)
PINMUX(GPIO(BATT_PRES_L), M2, 0)
+/*
+ * Update closed_source_set1.c if pinmux for I2C_SCL_INA or I2C_SDA_INA is
+ * changed or removed.
+ */
PINMUX(GPIO(I2C_SCL_INA), B0, DIO_INPUT)
PINMUX(GPIO(I2C_SDA_INA), B1, DIO_INPUT)
/* UARTs */
diff --git a/board/cr50/usb_i2c.c b/board/cr50/usb_i2c.c
index 1aa18012c3..b21c555858 100644
--- a/board/cr50/usb_i2c.c
+++ b/board/cr50/usb_i2c.c
@@ -20,6 +20,12 @@
int usb_i2c_board_is_enabled(void)
{
/*
+ * Closed source set1 board options use the INA pins as GPIOs
+ */
+ if (board_uses_closed_source_set1())
+ return 0;
+
+ /*
* Note that this signal requires an external pullup, because this is
* one of the real open drain pins; we cannot pull it up or drive it
* high. On test boards without the pullup, this will mis-detect as
@@ -79,6 +85,12 @@ void usb_i2c_board_disable(void)
int usb_i2c_board_enable(void)
{
+ /*
+ * Closed source set1 board options use the INA pins as GPIOs
+ */
+ if (board_uses_closed_source_set1())
+ return EC_SUCCESS;
+
if (servo_is_connected()) {
CPRINTS("Servo attached; cannot enable I2C");
usb_i2c_board_disable();
diff --git a/common/ccd_config.c b/common/ccd_config.c
index c6946522c5..8569ab6beb 100644
--- a/common/ccd_config.c
+++ b/common/ccd_config.c
@@ -474,6 +474,8 @@ int ccd_reset_config(unsigned int flags)
for (i = 0; i < CCD_CAP_COUNT; i++)
raw_set_cap(i, CCD_CAP_STATE_ALWAYS);
+ raw_set_flag(CCD_FLAG_FACTORY_MODE_ENABLED, 1);
+
/* Force WP disabled at boot */
raw_set_flag(CCD_FLAG_OVERRIDE_WP_AT_BOOT, 1);
raw_set_flag(CCD_FLAG_OVERRIDE_WP_STATE_ENABLED, 0);
@@ -679,6 +681,11 @@ void ccd_disable(void)
ccd_set_state(CCD_STATE_LOCKED);
}
+int ccd_get_factory_mode(void)
+{
+ return ccd_get_flag(CCD_FLAG_FACTORY_MODE_ENABLED);
+}
+
/******************************************************************************/
/* Console commands */
@@ -1511,6 +1518,13 @@ static enum vendor_cmd_rc ccd_disable_factory_mode(enum vendor_cmd_cc code,
*/
set_wp_follow_ccd_config();
+ /*
+ * Use raw_set_flag() because the factory mode flag is internal
+ */
+ mutex_lock(&ccd_config_mutex);
+ raw_set_flag(CCD_FLAG_FACTORY_MODE_ENABLED, 0);
+ mutex_unlock(&ccd_config_mutex);
+
*response_size = 0;
return VENDOR_RC_SUCCESS;
} while (0);
diff --git a/include/ccd_config.h b/include/ccd_config.h
index 5f21479cef..e670eb012a 100644
--- a/include/ccd_config.h
+++ b/include/ccd_config.h
@@ -39,6 +39,11 @@ enum ccd_flag {
*/
CCD_FLAG_PASSWORD_SET_WHEN_UNLOCKED = (1 << 1),
+ /*
+ * Factory mode state
+ */
+ CCD_FLAG_FACTORY_MODE_ENABLED = (1 << 2),
+
/* (flags in the middle are unused) */
/* Flags that can be set via ccd_set_flags(); fill from top down */
@@ -279,6 +284,13 @@ enum ccd_state ccd_get_state(void);
*/
void ccd_disable(void);
+/**
+ * Get the factory mode state.
+ *
+ * @return 0 if factory mode is disabled, !=0 if factory mode is enabled.
+ */
+int ccd_get_factory_mode(void);
+
/* Flags for ccd_reset_config() */
enum ccd_reset_config_flags {
/* Also reset test lab flag */