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 <nsanders@chromium.org>
Tested-by: Nick Sanders <nsanders@chromium.org>
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
This commit is contained in:
Nick Sanders
2017-05-15 17:42:41 -07:00
committed by chrome-bot
parent c78562ff60
commit 81b2654dc9
5 changed files with 144 additions and 20 deletions

View File

@@ -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();

View File

@@ -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__ */

View File

@@ -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

View File

@@ -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");

View File

@@ -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 */