From 81b2654dc92b04750c2aa25e3ed9fed143c8d396 Mon Sep 17 00:00:00 2001 From: Nick Sanders Date: Mon, 15 May 2017 17:42:41 -0700 Subject: mn50: socket controls Add console and usb_spi commands to enable or disable IOs to the socket, so that it will not be powered if a chip is inserted, and control reset and boot_cfg. BUG=b:36910757 BRANCH=None TEST=Check no voltage when socket is disabled. Full spiflash compatibility. Change-Id: Ie4ce0613a868030833abfdccd827acce2753dc6f Reviewed-on: https://chromium-review.googlesource.com/509072 Commit-Ready: Nick Sanders Tested-by: Nick Sanders Reviewed-by: Mary Ruthven --- board/mn50/board.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++- board/mn50/board.h | 4 ++ board/mn50/gpio.inc | 18 ++++++--- board/mn50/usb_spi.c | 29 ++++++++------ chip/g/usb_spi.h | 3 ++ 5 files changed, 144 insertions(+), 20 deletions(-) diff --git a/board/mn50/board.c b/board/mn50/board.c index 9833b48e62..0981a516ce 100644 --- a/board/mn50/board.c +++ b/board/mn50/board.c @@ -54,9 +54,11 @@ const struct i2c_port_t i2c_ports[] = { }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); +/* Recall whether we have enable socket power. */ +static int socket_set_enabled; /*****************************************************************************/ -/* */ + #include "gpio.wrap" static void init_interrupts(void) @@ -119,6 +121,9 @@ static void board_init(void) /* Initialize the persistent storage. */ initvars(); + /* Disable all power to socket, for hot swapping. */ + disable_socket(); + /* Indication that firmware is running, for debug purposes. */ GREG32(PMU, PWRDN_SCRATCH16) = 0xCAFECAFE; @@ -199,6 +204,107 @@ int flash_regions_to_enable(struct g_flash_region *regions, return 3; } +/* Check if socket has been anabled and power is OK. */ +int is_socket_enabled(void) +{ + /* TODO: check voltage rails within approved bands. */ + return (gpio_get_level(GPIO_DUT_PWRGOOD) && socket_set_enabled); +} + +/* Determine whether the socket has no voltage. TODO: check GPIOS? */ +int is_socket_off(void) +{ + /* Check 3.3v = 0. */ + if (ina2xx_get_voltage(1) > 10) + return 0; + /* Check 2.6v = 0. */ + if (ina2xx_get_voltage(4) > 10) + return 0; + return 1; +} + +void enable_socket(void) +{ + /* Power up. */ + gpio_set_level(GPIO_DUT_PWR_EN, 1); + + /* Indicate socket powered with red LED. */ + gpio_set_level(GPIO_LED_L, 0); + + /* GPIOs as ioutputs. */ + gpio_set_flags(GPIO_DUT_RST_L, GPIO_OUT_LOW); + gpio_set_flags(GPIO_DUT_BOOT_CFG, GPIO_OUT_LOW); + gpio_set_flags(GPIO_SPI_CS_ALT_L, GPIO_OUT_HIGH); + + /* Connect DIO A4, A8 to the SPI peripheral */ + GWRITE(PINMUX, DIOA4_SEL, 0); /* SPI_MOSI */ + GWRITE(PINMUX, DIOA8_SEL, 0); /* SPI_CLK */ + GWRITE(PINMUX, DIOA5_SEL, GC_PINMUX_GPIO0_GPIO10_SEL); + + /* UART */ + GWRITE(PINMUX, DIOA7_SEL, GC_PINMUX_UART1_TX_SEL); + + /* Chip select. */ + GWRITE_FIELD(PINMUX, DIOA5_CTL, PU, 1); + + socket_set_enabled = 1; +} + +void disable_socket(void) +{ + /* Disable CS pin. */ + GWRITE_FIELD(PINMUX, DIOA5_CTL, PU, 0); + + /* TODO: Implement way to get the gpio */ + ASSERT(GREAD(PINMUX, GPIO0_GPIO7_SEL) == GC_PINMUX_DIOA4_SEL); + ASSERT(GREAD(PINMUX, GPIO0_GPIO8_SEL) == GC_PINMUX_DIOA8_SEL); + ASSERT(GREAD(PINMUX, GPIO0_GPIO10_SEL) == GC_PINMUX_DIOA5_SEL); + + /* Set SPI MOSI, CLK, and CS_L as inputs */ + GWRITE(PINMUX, DIOA4_SEL, GC_PINMUX_GPIO0_GPIO7_SEL); + GWRITE(PINMUX, DIOA8_SEL, GC_PINMUX_GPIO0_GPIO8_SEL); + GWRITE(PINMUX, DIOA5_SEL, GC_PINMUX_GPIO0_GPIO10_SEL); + + /* UART */ + GWRITE(PINMUX, DIOA7_SEL, 0); + + /* GPIOs as inputs. */ + gpio_set_flags(GPIO_DUT_BOOT_CFG, GPIO_INPUT); + gpio_set_flags(GPIO_DUT_RST_L, GPIO_INPUT); + gpio_set_flags(GPIO_SPI_CS_ALT_L, GPIO_INPUT); + + /* Turn off socket power. */ + gpio_set_level(GPIO_DUT_PWR_EN, 0); + + /* Indicate socket unpowered with no red LED. */ + gpio_set_level(GPIO_LED_L, 1); + socket_set_enabled = 0; +} + +static int command_socket(int argc, char **argv) +{ + if (argc > 1) { + if (!strcasecmp("enable", argv[1])) + enable_socket(); + else if (!strcasecmp("disable", argv[1])) + disable_socket(); + else + return EC_ERROR_PARAM1; + + /* Let power settle. */ + msleep(5); + } + + ccprintf("Socket enabled: %s, powered: %s\n", + is_socket_enabled() ? "yes" : "no", + is_socket_off() ? "off" : "on"); + return EC_SUCCESS; +} +DECLARE_SAFE_CONSOLE_COMMAND(socket, command_socket, + "[enable|disable]", + "Activate and deactivate socket"); + + /* Determine key type based on the key ID. */ static const char *key_type(uint32_t key_id) @@ -227,7 +333,7 @@ static int command_sysinfo(int argc, char **argv) system_print_reset_flags(); ccprintf(")\n"); - ccprintf("Chip: %s %s %s\n", system_get_chip_vendor(), + ccprintf("Chip: %s %s %s\n", system_get_chip_vendor(), system_get_chip_name(), system_get_chip_revision()); active = system_get_ro_image_copy(); diff --git a/board/mn50/board.h b/board/mn50/board.h index 92b92c877b..2037fd8e5b 100644 --- a/board/mn50/board.h +++ b/board/mn50/board.h @@ -127,6 +127,10 @@ enum usb_strings { void post_reboot_request(void); void ccd_force_enable(void); +void disable_socket(void); +void enable_socket(void); +int is_socket_enabled(void); +int is_socket_off(void); #endif /* !__ASSEMBLER__ */ diff --git a/board/mn50/gpio.inc b/board/mn50/gpio.inc index fd40d34026..069d57bcfb 100644 --- a/board/mn50/gpio.inc +++ b/board/mn50/gpio.inc @@ -46,10 +46,11 @@ /* Use these to reset/flash the DUT haven */ -GPIO(DUT_BOOT_CFG, PIN(0, 0), GPIO_OUT_LOW) /* DIOB2 */ -GPIO(DUT_RST_L, PIN(0, 1), GPIO_ODR_LOW) /* DIOB3 */ GPIO(DUT_PWR_EN, PIN(0, 2), GPIO_OUT_LOW) /* DIOB5 */ GPIO(DUT_PWRGOOD, PIN(0, 3), GPIO_INPUT) /* DIOB7 */ +/* These GPIOS are switched between input/output by socket enable. */ +GPIO(DUT_BOOT_CFG, PIN(0, 0), GPIO_OUT_LOW) /* DIOB2 */ +GPIO(DUT_RST_L, PIN(0, 1), GPIO_OUT_LOW) /* DIOB3 */ GPIO(LED_B_L, PIN(0, 4), GPIO_ODR_HIGH) /* DIOA9 */ GPIO(LED_R_L, PIN(0, 5), GPIO_ODR_HIGH) /* DIOA13 */ @@ -60,7 +61,7 @@ GPIO(LED_L, PIN(0, 11), GPIO_ODR_HIGH) /* DIOB6 */ GPIO(SPI_MOSI, PIN(0, 7), GPIO_INPUT) /* DIOA4 */ GPIO(SPI_CLK, PIN(0, 8), GPIO_INPUT) /* DIOA8 */ GPIO(SPI_CS_L, PIN(0, 9), GPIO_INPUT) /* DIOA14 */ -GPIO(SPI_CS_ALT_L, PIN(0, 10), GPIO_OUT_HIGH) /* DIOA5 */ +GPIO(SPI_CS_ALT_L, PIN(0, 10), GPIO_INPUT) /* DIOA5 */ /* Unimplemented signals which we need to emulate for now */ /* TODO(wfrichar): Half the boards don't use this signal. Take it out. */ @@ -90,7 +91,14 @@ PINMUX(GPIO(LED_L), B6, DIO_INPUT) PINMUX(FUNC(UART0_TX), A0, DIO_OUTPUT) /* Cr50 console */ PINMUX(FUNC(UART0_RX), A1, DIO_INPUT | DIO_WAKE_LOW) -PINMUX(FUNC(UART1_TX), A7, DIO_OUTPUT) /* DUT console */ +/* + * UART1_TX will be enabled when the socket power is enabled, + * to prevent backpowering. + * + * PINMUX(FUNC(UART1_TX), A7, DIO_OUTPUT) + */ + +/* DUT console */ PINMUX(FUNC(UART1_RX), A3, DIO_INPUT) /* I2C setup */ @@ -111,6 +119,6 @@ PINMUX(FUNC(I2C0_SDA), B1, DIO_INPUT | DIO_OUTPUT) */ PINMUX(GPIO(SPI_MOSI), A4, DIO_OUTPUT) PINMUX(GPIO(SPI_CLK), A8, DIO_OUTPUT) -PINMUX(GPIO(SPI_CS_ALT_L), A5, DIO_INPUT) +PINMUX(GPIO(SPI_CS_ALT_L), A5, DIO_OUTPUT) #undef PINMUX diff --git a/board/mn50/usb_spi.c b/board/mn50/usb_spi.c index 48f4728a34..9dffeeae99 100644 --- a/board/mn50/usb_spi.c +++ b/board/mn50/usb_spi.c @@ -16,10 +16,6 @@ int usb_spi_board_enable(struct usb_spi_config const *config) { - /* Connect DIO A4, A8, and A14 to the SPI peripheral */ - GWRITE(PINMUX, DIOA4_SEL, 0); /* SPI_MOSI */ - GWRITE(PINMUX, DIOA8_SEL, 0); /* SPI_CLK */ - spi_enable(CONFIG_SPI_FLASH_PORT, 1); /* Enable SPI framing for H1 bootloader */ @@ -34,14 +30,6 @@ void usb_spi_board_disable(struct usb_spi_config const *config) gpio_set_level(GPIO_SPI_CS_ALT_L, 1); spi_enable(CONFIG_SPI_FLASH_PORT, 0); - - /* Disconnect SPI peripheral to tri-state pads */ - ASSERT(GREAD(PINMUX, GPIO0_GPIO7_SEL) == GC_PINMUX_DIOA4_SEL); - ASSERT(GREAD(PINMUX, GPIO0_GPIO8_SEL) == GC_PINMUX_DIOA8_SEL); - - /* Set SPI MOSI, CLK as inputs */ - GWRITE(PINMUX, DIOA4_SEL, GC_PINMUX_GPIO0_GPIO7_SEL); - GWRITE(PINMUX, DIOA8_SEL, GC_PINMUX_GPIO0_GPIO8_SEL); } int usb_spi_interface(struct usb_spi_config const *config, @@ -52,7 +40,7 @@ int usb_spi_interface(struct usb_spi_config const *config, USB_RECIP_INTERFACE)) return 1; - if (req->wValue != 0 || + if ((req->wValue != 0 && req->wValue != 1) || req->wIndex != config->interface || req->wLength != 0) return 1; @@ -64,6 +52,21 @@ int usb_spi_interface(struct usb_spi_config const *config, case USB_SPI_REQ_ENABLE_H1: config->state->enabled_host = USB_SPI_H1; break; + + /* Set reset and DFU pins. Both active high. */ + case USB_SPI_REQ_RESET: + gpio_set_level(GPIO_DUT_RST_L, !req->wValue); + break; + case USB_SPI_REQ_BOOT_CFG: + gpio_set_level(GPIO_DUT_BOOT_CFG, req->wValue); + break; + /* Set socket power. */ + case USB_SPI_REQ_SOCKET: + if (req->wValue) + enable_socket(); + else + disable_socket(); + break; case USB_SPI_REQ_ENABLE_AP: case USB_SPI_REQ_ENABLE: CPRINTS("ERROR: Must specify target"); diff --git a/chip/g/usb_spi.h b/chip/g/usb_spi.h index bdd4fbcd24..2240999950 100644 --- a/chip/g/usb_spi.h +++ b/chip/g/usb_spi.h @@ -67,6 +67,9 @@ enum usb_spi_request { USB_SPI_REQ_ENABLE_AP = 0x0002, USB_SPI_REQ_ENABLE_EC = 0x0003, USB_SPI_REQ_ENABLE_H1 = 0x0004, + USB_SPI_REQ_RESET = 0x0005, + USB_SPI_REQ_BOOT_CFG = 0x0006, + USB_SPI_REQ_SOCKET = 0x0007, }; /* USB SPI device indexes */ -- cgit v1.2.1