summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott <scollyer@chromium.org>2016-07-21 11:08:11 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-08-03 19:40:55 -0700
commitd67f3aa1f60ff9abd4f03c58a103ab4eecf99e7f (patch)
tree3269a2071be1819469005dacd61a96bf19b7c276
parent96e05799536c264b63d11604429ed760a4e019d2 (diff)
downloadchrome-ec-d67f3aa1f60ff9abd4f03c58a103ab4eecf99e7f.tar.gz
Cr50: Sample slave configuration pins at POR
There is just one version of Cr50 firmware for all boards that it's used on. However, on some boards the AP communicates to the TPM via a SPI interface (i.e. Kevin) and on others, the AP communicates via an I2C interface (i.e. Reef). In order to dynamically discover which interface to configure, there are strapping resistors added to the board which enables the Cr50 to detect which configuration to implement. This CL is a first pass and is only looking at DIOA1 which is pulled high for SPI and pulled low for I2C configurations. The strapping resistor should be read when the AP is in reset prior to it attempting to drive any of the lines used for strapping. To ensure this condition is met, Cr50 will only check the strapping options following a POR (power on reset). Once the configuration type is discovered, a 'long_life' register is used to hold the result so that the result can always be available. The long_life register contents remain unchanged until a subsequent power down event. BRANCH=none BUG=chrome-os-partner:50728 TEST=manual Tested on Kevin and Reef. Verfifed by reading the stored value that the SPI configuraiton is detected for Kevin and the I2C interface is detected on Reef. In addition, verified on Kevin that the Cr50 FW version is correctly reported to the AP which means that TPM register reads via the slave SPI are functioning. Change-Id: Ibd7624ad8e3b4126f6346dce0bc72f62a3cc6d18 Signed-off-by: Scott <scollyer@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/363014 Commit-Ready: Scott Collyer <scollyer@chromium.org> Tested-by: Scott Collyer <scollyer@chromium.org> Reviewed-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r--board/cr50/board.c37
-rw-r--r--board/cr50/gpio.inc4
-rw-r--r--chip/g/sps.c8
-rw-r--r--chip/g/system.c9
-rw-r--r--include/system.h20
5 files changed, 78 insertions, 0 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index ba8862119b..bcb5c6dae7 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -48,6 +48,9 @@ uint32_t nvmem_user_sizes[NVMEM_NUM_USERS] = {
NVMEM_CR50_SIZE
};
+/* Board specific configuration settings */
+static uint32_t board_properties;
+
/*
* There's no way to trigger on both rising and falling edges, so force a
* compiler error if we try. The workaround is to use the pinmux to connect
@@ -499,3 +502,37 @@ void board_update_device_state(enum device_type device)
hook_call_deferred(device_states[device].deferred, 50);
}
}
+
+static void detect_slave_config(void)
+{
+ uint32_t properties = 0;
+
+ /* Check for power on reset */
+ if (system_get_reset_flags() & RESET_FLAG_POWER_ON) {
+ /* Read DIOA1 strap pin */
+ if (gpio_get_level(GPIO_STRAP0))
+ /* Strap is pulled high -> Kevin SPI TPM option */
+ properties |= BOARD_SLAVE_CONFIG_SPI;
+ else
+ /* Strap is low -> Reef I2C TPM option */
+ properties |= BOARD_SLAVE_CONFIG_I2C;
+ /* Write enable bit for LONG_LIFE_SCRATCH1 register */
+ GWRITE_FIELD(PMU, LONG_LIFE_SCRATCH_WR_EN, REG1, 1);
+ /* Save type in LONG_LIFE register */
+ GREG32(PMU, LONG_LIFE_SCRATCH1) = properties;
+ /* Clear enable bit of LONG_LIFE_SCRATCH1 register */
+ GWRITE_FIELD(PMU, LONG_LIFE_SCRATCH_WR_EN, REG1, 0);
+ } else {
+ /* Not a power on reset, so can read what was discovered */
+ properties = GREG32(PMU, LONG_LIFE_SCRATCH1);
+ }
+ /* Save this configuration setting */
+ board_properties = properties;
+}
+/* Need this hook to run before the default hook level */
+DECLARE_HOOK(HOOK_INIT, detect_slave_config, HOOK_PRIO_DEFAULT - 1);
+
+uint32_t system_board_properties_callback(void)
+{
+ return board_properties;
+}
diff --git a/board/cr50/gpio.inc b/board/cr50/gpio.inc
index a6dafa8e94..8234e80017 100644
--- a/board/cr50/gpio.inc
+++ b/board/cr50/gpio.inc
@@ -58,6 +58,9 @@ GPIO(SPI_CS_L, PIN(0, 9), GPIO_INPUT)
/* Control the load switch powering the INA 3.3V rail */
GPIO(EN_PP3300_INA_L, PIN(1, 9), GPIO_ODR_HIGH)
+/* GPIOs used for Cr50 strapping options */
+GPIO(STRAP0, PIN(0, 10), GPIO_INPUT)
+
/* Unimplemented signals which we need to emulate for now */
/* TODO(wfrichar): Half the boards don't use this signal. Take it out. */
UNIMPLEMENTED(ENTERING_RW)
@@ -82,6 +85,7 @@ PINMUX(GPIO(SYS_RST_L_IN), M0, DIO_WAKE_FALLING)
PINMUX(GPIO(SYS_RST_L_OUT), M0, DIO_INPUT)
PINMUX(GPIO(CCD_MODE_L), M1, DIO_INPUT)
PINMUX(GPIO(BATT_PRES), M2, 0)
+PINMUX(GPIO(STRAP0), A1, DIO_INPUT)
/* UARTs */
PINMUX(FUNC(UART0_TX), A0, DIO_OUTPUT) /* Cr50 console */
diff --git a/chip/g/sps.c b/chip/g/sps.c
index 6d21b06358..0ce1d6be41 100644
--- a/chip/g/sps.c
+++ b/chip/g/sps.c
@@ -9,6 +9,7 @@
#include "pmu.h"
#include "registers.h"
#include "sps.h"
+#include "system.h"
#include "task.h"
#include "timer.h"
#include "watchdog.h"
@@ -238,6 +239,13 @@ int sps_unregister_rx_handler(void)
static void sps_init(void)
{
+ /*
+ * Check to see if slave SPI interface is required by the board before
+ * initializing it. If SPI option is not set, then just return.
+ */
+ if (!(system_get_board_properties() & BOARD_SLAVE_CONFIG_SPI))
+ return;
+
pmu_clock_en(PERIPH_SPS);
/* The pinmux connections are preset, but we have to set IN/OUT */
diff --git a/chip/g/system.c b/chip/g/system.c
index 80b55601d9..7071e2680b 100644
--- a/chip/g/system.c
+++ b/chip/g/system.c
@@ -352,3 +352,12 @@ int system_process_retry_counter(void)
}
#endif
+uint32_t system_get_board_properties(void)
+{
+ uint32_t properties = 0;
+
+#ifdef BOARD_CR50
+ properties = system_board_properties_callback();
+#endif
+ return properties;
+}
diff --git a/include/system.h b/include/system.h
index 8d792123ff..60ec6b1072 100644
--- a/include/system.h
+++ b/include/system.h
@@ -466,4 +466,24 @@ int system_is_reboot_warm(void);
*/
int system_process_retry_counter(void);
+/* Board properties options */
+#define BOARD_SLAVE_CONFIG_SPI (1 << 0) /* Slave SPI interface */
+#define BOARD_SLAVE_CONFIG_I2C (1 << 1) /* Slave I2C interface */
+/**
+ * Get board properites
+ *
+ *
+ * @return uint32_t bit field where a set bit indicates option exists
+ */
+uint32_t system_get_board_properties(void);
+
+/**
+ * API for board specific version of system_get_board_properties
+ *
+ * This function must be in the board's board.c file
+ *
+ * @return uint32_t bit field where a set bit indicates option exists
+ */
+uint32_t system_board_properties_callback(void);
+
#endif /* __CROS_EC_SYSTEM_H */