From f2711530bf8dfb764584cc1e35c35a428c90cbd0 Mon Sep 17 00:00:00 2001 From: Mary Ruthven Date: Thu, 16 Jul 2020 08:18:54 +1000 Subject: usb_spi: add support for custom SYS_RST and EC_RST setup Don't touch the SYS_RST_L or EC_RST_L signals when flashing the AP if flashrom is run with custom_rst=True. BUG=b:154885210 TEST=manual on bob ecrst on flashrom -p raiden_debug_spi:target=EC -r ec.bin ecrst on flashrom -p raiden_debug_spi:target=AP,custom_rst=True -r ap.bin check ecrst is still on flashrom -p raiden_debug_spi:target=AP -r ap.bin Change-Id: Ia1ab8c853c25ced994e053c9e19a18d0d0f1cb45 Signed-off-by: Mary Ruthven Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2301239 Reviewed-by: Vadim Bendebury --- board/cr50/usb_spi.c | 65 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 13 deletions(-) (limited to 'board') diff --git a/board/cr50/usb_spi.c b/board/cr50/usb_spi.c index 050ea63aac..a58e14789a 100644 --- a/board/cr50/usb_spi.c +++ b/board/cr50/usb_spi.c @@ -37,6 +37,12 @@ /* Timeout for auto-disabling SPI hash device, in microseconds */ #define SPI_HASH_TIMEOUT_US (60 * SECOND) +/* + * If True, don't touch the reset signals while setting up AP usb spi. This + * doesn't affect spi hash. + */ +static uint8_t usb_spi_custom_reset; + /* Current device for SPI hashing */ static uint8_t spi_hash_device = USB_SPI_DISABLE; @@ -146,7 +152,7 @@ static enum spi_bus_user_t get_spi_bus_user(void) /*****************************************************************************/ /* Methods to enable / disable the SPI bus and pin mux */ -static void disable_ec_ap_spi(void) +static void disable_ec_ap_spi(uint8_t custom_reset) { int was_ap_spi_en = gpio_get_level(GPIO_AP_FLASH_SELECT); @@ -160,8 +166,15 @@ static void disable_ec_ap_spi(void) * held in reset. Therefore, it needs to be released here. */ gpio_set_level(GPIO_AP_FLASH_SELECT, 0); - deassert_ec_rst(); - deassert_sys_rst(); + /* + * Some boards require special EC_RST_L SYS_RST_L behavior. + * Don't touch the signals if the user requested custom reset + * behavior. + */ + if (!custom_reset) { + deassert_ec_rst(); + deassert_sys_rst(); + } } } @@ -178,7 +191,7 @@ static void enable_ec_spi(void) */ } -static void enable_ap_spi(void) +static void enable_ap_spi(uint8_t custom_reset) { /* Select AP flash */ gpio_set_level(GPIO_AP_FLASH_SELECT, 1); @@ -187,8 +200,11 @@ static void enable_ap_spi(void) /* * On some systems SYS_RST_L is not level sensitive, so the only way to * be sure we're holding the AP in reset is to hold the EC in reset. + * Don't touch the reset signals if the user requested a custom reset + * setup. */ - assert_ec_rst(); + if (!custom_reset) + assert_ec_rst(); } /** @@ -245,9 +261,12 @@ static void disable_spi_pinmux(void) /*****************************************************************************/ /* USB SPI methods */ -int usb_spi_board_enable(int host) +/* + * Check that the CCD capability for the host is enabled and the SPI bus isn't + * active. + */ +static int usb_spi_check_host_accessible(int host) { - /* Make sure we're allowed to enable the requested device */ if (host == USB_SPI_EC) { if (!ccd_is_cap_enabled(CCD_CAP_EC_FLASH)) { CPRINTS("%s: EC access denied", __func__); @@ -267,8 +286,20 @@ int usb_spi_board_enable(int host) CPRINTS("%s: bus in use", __func__); return EC_ERROR_BUSY; } + return EC_SUCCESS; +} - disable_ec_ap_spi(); +int usb_spi_board_enable(int host) +{ + /* Make sure we're allowed to enable the requested device */ + int rv = usb_spi_check_host_accessible(host); + + if (rv != EC_SUCCESS) { + usb_spi_custom_reset = 0; + return rv; + } + + disable_ec_ap_spi(usb_spi_custom_reset); /* * Only need to check EC vs. AP, because other hosts were ruled out @@ -277,7 +308,7 @@ int usb_spi_board_enable(int host) if (host == USB_SPI_EC) enable_ec_spi(); else - enable_ap_spi(); + enable_ap_spi(usb_spi_custom_reset); enable_spi_pinmux(); return EC_SUCCESS; @@ -292,7 +323,8 @@ void usb_spi_board_disable(void) return; disable_spi_pinmux(); - disable_ec_ap_spi(); + disable_ec_ap_spi(usb_spi_custom_reset); + usb_spi_custom_reset = 0; set_spi_bus_user(SPI_BUS_USER_USB, 0); } @@ -313,13 +345,20 @@ int usb_spi_interface(struct usb_spi_config const *config, return 1; switch (req->bRequest) { + case USB_SPI_REQ_ENABLE_AP_CUSTOM: + usb_spi_custom_reset = 1; + config->state->enabled_host = USB_SPI_AP; + break; case USB_SPI_REQ_ENABLE_AP: + usb_spi_custom_reset = 0; config->state->enabled_host = USB_SPI_AP; break; case USB_SPI_REQ_ENABLE_EC: + usb_spi_custom_reset = 0; config->state->enabled_host = USB_SPI_EC; break; case USB_SPI_REQ_ENABLE: + usb_spi_custom_reset = 0; CPRINTS("%s: Must specify target", __func__); /* Fall through... */ case USB_SPI_REQ_DISABLE: @@ -409,7 +448,7 @@ static enum vendor_cmd_rc spi_hash_disable(void) /* Disable the SPI bus and chip select */ disable_spi_pinmux(); - disable_ec_ap_spi(); + disable_ec_ap_spi(0); /* Stop the EC device, if it was active */ spi_hash_stop_ec_device(); @@ -448,14 +487,14 @@ static void spi_hash_pp_done(void) /* Clear previous enable if needed */ if (spi_hash_device != USB_SPI_DISABLE) - disable_ec_ap_spi(); + disable_ec_ap_spi(0); /* Set up new device */ if (spi_hash_new_device == USB_SPI_AP) { /* Stop the EC device, if it was previously active */ spi_hash_stop_ec_device(); - enable_ap_spi(); + enable_ap_spi(0); } else { /* Force the EC into reset and enable EC SPI bus */ assert_ec_rst(); -- cgit v1.2.1