Victor Ding has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Add MEC1308 EC programmer
Initial support of Microchip MEC1308 Embedded Controller.
Signed-off-by: Victor Ding victording@google.com Change-Id: I2d51b4bdc0b38b6e488e71b9e774eb6232a2069e --- M Makefile M flashrom.c A mec1308.c M meson.build M meson_options.txt M programmer.h 6 files changed, 569 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/41/44541/1
diff --git a/Makefile b/Makefile index 803529f..2acd656 100644 --- a/Makefile +++ b/Makefile @@ -175,6 +175,11 @@ else override CONFIG_FT2232_SPI = no endif +ifeq ($(CONFIG_MEC1308), yes) +UNSUPPORTED_FEATURES += CONFIG_MEC1308=yes +else +override CONFIG_MEC1308 = no +endif ifeq ($(CONFIG_USBBLASTER_SPI), yes) UNSUPPORTED_FEATURES += CONFIG_USBBLASTER_SPI=yes else @@ -281,6 +286,11 @@ else override CONFIG_DRKAISER = no endif +ifeq ($(CONFIG_MEC1308), yes) +UNSUPPORTED_FEATURES += CONFIG_MEC1308=yes +else +override CONFIG_MEC1308 = no +endif ifeq ($(CONFIG_NICREALTEK), yes) UNSUPPORTED_FEATURES += CONFIG_NICREALTEK=yes else @@ -386,6 +396,11 @@ else override CONFIG_FT2232_SPI = no endif +ifeq ($(CONFIG_MEC1308), yes) +UNSUPPORTED_FEATURES += CONFIG_MEC1308=yes +else +override CONFIG_MEC1308 = no +endif ifeq ($(CONFIG_USBBLASTER_SPI), yes) UNSUPPORTED_FEATURES += CONFIG_USBBLASTER_SPI=yes else @@ -674,6 +689,9 @@ # Always enable FT2232 SPI dongles for now. CONFIG_FT2232_SPI ?= yes
+# Microchip MEC1308 Embedded Controller +CONFIG_MEC1308 ?= yes + # Always enable Altera USB-Blaster dongles for now. CONFIG_USBBLASTER_SPI ?= yes
@@ -855,6 +873,11 @@ NEED_LIBPCI += CONFIG_INTERNAL endif
+ifeq ($(CONFIG_MEC1308), yes) +FEATURE_CFLAGS += -D'CONFIG_MEC1308=1' +PROGRAMMER_OBJS += mec1308.o +endif + ifeq ($(CONFIG_SERPROG), yes) FEATURE_CFLAGS += -D'CONFIG_SERPROG=1' PROGRAMMER_OBJS += serprog.o diff --git a/flashrom.c b/flashrom.c index 4a30986..5a8e37a 100644 --- a/flashrom.c +++ b/flashrom.c @@ -84,6 +84,18 @@ }, #endif
+#if CONFIG_MEC1308 == 1 + { + .name = "mec1308", + .type = OTHER, + .devs.note = "Microchip MEC1308 Embedded Controller.\n", + .init = mec1308_init, + .map_flash_region = fallback_map, + .unmap_flash_region = fallback_unmap, + .delay = internal_delay, + }, +#endif + #if CONFIG_NIC3COM == 1 { .name = "nic3com", diff --git a/mec1308.c b/mec1308.c new file mode 100644 index 0000000..43bd2db --- /dev/null +++ b/mec1308.c @@ -0,0 +1,520 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2010 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Google or the names of contributors or + * licensors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. + * GOOGLE INC AND ITS LICENSORS SHALL NOT BE LIABLE + * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING + * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL + * GOOGLE OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, + * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR + * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF + * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, + * EVEN IF GOOGLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#if defined(__i386__) || defined(__x86_64__) +#include <inttypes.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "flash.h" +#include "hwaccess.h" +#include "chipdrivers.h" +#include "programmer.h" +#include "spi.h" + +#define MEC1308_SIO_PORT1 0x2e +#define MEC1308_SIO_PORT2 0x4e +#define MEC1308_SIO_ENTRY_KEY 0x55 +#define MEC1308_SIO_EXIT_KEY 0xaa + +#define MEC1308_SIOCFG_LDN 0x07 /* LDN Bank Selector */ +#define MEC1308_DEVICE_ID_REG 0x20 /* Device ID Register */ +#define MEC1308_DEVICE_ID_VAL 0x4d /* Device ID Value for MEC1308 */ +#define MEC1310_DEVICE_ID_VAL 0x04 /* Device ID Value for MEC1310 */ +#define MEC1308_DEVICE_REV 0x21 /* Device Revision ID Register */ + +#define MEC1308_MBX_CMD 0x82 /* mailbox command register offset */ +#define MEC1308_MBX_EXT_CMD 0x83 /* mailbox ext. command reg offset */ +#define MEC1308_MBX_DATA_START 0x84 /* first mailbox data register offset */ +#define MEC1308_MBX_DATA_END 0x91 /* last mailbox data register offset */ + +static unsigned int mbx_data; /* Mailbox register interface data address*/ + +/* + * These command codes depend on EC firmware. The ones listed below are input + * using the mailbox interface, though others may be input using the ACPI + * interface. Some commands also have an output value (ie pass/failure code) + * which EC writes to the mailbox command register after completion. + */ +#define MEC1308_CMD_SMI_ENABLE 0x84 +#define MEC1308_CMD_SMI_DISABLE 0x85 +#define MEC1308_CMD_ACPI_ENABLE 0x86 +#define MEC1308_CMD_ACPI_DISABLE 0x87 + +/* + * Passthru commands are also input using the mailbox interface. Passthru mode + * enter/start/end commands are special since they require a command word to + * be written to the data registers. Other passthru commands are performed + * after passthru mode has been started. + * + * Multiple passthru mode commands may be issued before ending passthru mode. + * You do not need to enter, start, and end passthru mode for each SPI + * command. However, other mailbox commands might not work when passthru mode + * is enabled. For example, you may read all SPI chip content while in passthru + * mode, but you should exit passthru mode before performing other EC commands + * such as reading fan speed. + */ +#define MEC1308_CMD_PASSTHRU 0x55 /* force EC to process word */ +#define MEC1308_CMD_PASSTHRU_SUCCESS 0xaa /* success code for passthru */ +#define MEC1308_CMD_PASSTHRU_FAIL 0xfe /* failure code for passthru */ +#define MEC1308_CMD_PASSTHRU_ENTER "PathThruMode" /* not a typo... */ +#define MEC1308_CMD_PASSTHRU_START "Start" +#define MEC1308_CMD_PASSTHRU_EXIT "End_Mode" +#define MEC1308_CMD_PASSTHRU_CS_EN 0xf0 /* chip-select enable */ +#define MEC1308_CMD_PASSTHRU_CS_DIS 0xf1 /* chip-select disable */ +#define MEC1308_CMD_PASSTHRU_SEND 0xf2 /* send byte from data0 */ +#define MEC1308_CMD_PASSTHRU_READ 0xf3 /* read byte, place in data0 */ + +typedef struct +{ + unsigned int in_sio_cfgmode; + unsigned int mbx_idx; /* Mailbox register interface index address */ + unsigned int mbx_data; /* Mailbox register interface data address*/ +} mec1308_data_t; + +static void mec1308_sio_enter(mec1308_data_t *ctx_data, uint16_t port) +{ + if (ctx_data->in_sio_cfgmode) + return; + + OUTB(MEC1308_SIO_ENTRY_KEY, port); + ctx_data->in_sio_cfgmode = 1; +} + +static void mec1308_sio_exit(mec1308_data_t *ctx_data, uint16_t port) +{ + if (!ctx_data->in_sio_cfgmode) + return; + + OUTB(MEC1308_SIO_EXIT_KEY, port); + ctx_data->in_sio_cfgmode = 0; +} + +/** probe for super i/o index + * @port: allocated buffer to store port + * + * returns 0 to indicate success, <0 to indicate error + */ +static int mec1308_get_sio_index(mec1308_data_t *ctx_data, uint16_t *port) +{ + uint16_t ports[] = { MEC1308_SIO_PORT1, + MEC1308_SIO_PORT2, + }; + size_t i; + static uint16_t port_internal, port_found = 0; + + if (port_found) { + *port = port_internal; + return 0; + } + + if (rget_io_perms()) + return -1; + + for (i = 0; i < ARRAY_SIZE(ports); i++) { + uint8_t tmp8; + + /* + * Only after config mode has been successfully entered will the + * index port will read back the last value written to it. + * So we will attempt to enter config mode, set the index + * register, and see if the index register retains the value. + * + * Note: It seems to work "best" when using a device ID register + * as the index and reading from the data port before reading + * the index port. + */ + mec1308_sio_enter(ctx_data, ports[i]); + OUTB(MEC1308_DEVICE_ID_REG, ports[i]); + tmp8 = INB(ports[i] + 1); + tmp8 = INB(ports[i]); + if ((tmp8 != MEC1308_DEVICE_ID_REG)) { + ctx_data->in_sio_cfgmode = 0; + continue; + } + + port_internal = ports[i]; + port_found = 1; + break; + } + + if (!port_found) { + msg_cdbg("\nfailed to obtain super i/o index\n"); + return -1; + } + + msg_cdbg("\nsuper i/o index = 0x%04x\n", port_internal); + *port = port_internal; + return 0; +} + +static uint8_t mbx_read(mec1308_data_t *ctx_data, uint8_t idx) +{ + OUTB(idx, ctx_data->mbx_idx); + return INB(mbx_data); +} + +static int mbx_wait(mec1308_data_t *ctx_data) +{ + int i; + int max_attempts = 10000; + int rc = 0; + + for (i = 0; mbx_read(ctx_data, MEC1308_MBX_CMD); i++) { + if (i == max_attempts) { + rc = 1; + break; + } + /* FIXME: This delay adds determinism to the delay period. It + was chosen arbitrarily thru some experiments. */ + programmer_delay(2); + } + + return rc; +} + +static int mbx_write(mec1308_data_t *ctx_data, uint8_t idx, uint8_t data) +{ + int rc = 0; + + if (idx == MEC1308_MBX_CMD && mbx_wait(ctx_data)) { + msg_perr("%s: command register not clear\n", __func__); + return 1; + } + + OUTB(idx, ctx_data->mbx_idx); + OUTB(data, mbx_data); + + if (idx == MEC1308_MBX_CMD) + rc = mbx_wait(ctx_data); + + return rc; +} + +static void mbx_clear(mec1308_data_t *ctx_data) +{ + int reg; + + for (reg = MEC1308_MBX_DATA_START; reg < MEC1308_MBX_DATA_END; reg++) + mbx_write(ctx_data, reg, 0x00); + mbx_write(ctx_data, MEC1308_MBX_CMD, 0x00); +} + +static int mec1308_exit_passthru_mode(mec1308_data_t *ctx_data) +{ + uint8_t tmp8; + size_t i; + + /* exit passthru mode */ + for (i = 0; i < strlen(MEC1308_CMD_PASSTHRU_EXIT); i++) { + mbx_write(ctx_data, MEC1308_MBX_DATA_START + i, + MEC1308_CMD_PASSTHRU_EXIT[i]); + } + + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_PASSTHRU)) { + msg_pdbg("%s(): exit passthru command timed out\n", __func__); + return 1; + } + + tmp8 = mbx_read(ctx_data, MEC1308_MBX_DATA_START); + msg_pdbg("%s: result: 0x%02x ", __func__, tmp8); + if (tmp8 == MEC1308_CMD_PASSTHRU_SUCCESS) { + msg_pdbg("(exited passthru mode)\n"); + } else if (tmp8 == MEC1308_CMD_PASSTHRU_FAIL) { + msg_pdbg("(failed to exit passthru mode)\n"); + } + + return 0; +} + +static int enter_passthru_mode(mec1308_data_t *ctx_data) +{ + uint8_t tmp8; + size_t i; + + /* + * Enter passthru mode. If the EC does not successfully enter passthru + * mode the first time, we'll clear the mailbox and issue the "exit + * passthru mode" command sequence up to 3 times or until it arrives in + * a known state. + * + * Note: This workaround was developed experimentally. + */ + for (i = 0; i < 3; i++) { + size_t j; + + msg_pdbg("%s(): entering passthru mode, attempt %d out of 3\n", + __func__, (int)(i + 1)); + for (j = 0; j < strlen(MEC1308_CMD_PASSTHRU_ENTER); j++) { + mbx_write(ctx_data, MEC1308_MBX_DATA_START + j, + MEC1308_CMD_PASSTHRU_ENTER[j]); + } + + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_PASSTHRU)) + msg_pdbg("%s(): enter passthru command timed out\n", + __func__); + + tmp8 = mbx_read(ctx_data, MEC1308_MBX_DATA_START); + if (tmp8 == MEC1308_CMD_PASSTHRU_SUCCESS) + break; + + msg_pdbg("%s(): command failed, clearing data registers and " + "issuing full exit passthru command...\n", __func__); + mbx_clear(ctx_data); + mec1308_exit_passthru_mode(ctx_data); + } + + if (tmp8 != MEC1308_CMD_PASSTHRU_SUCCESS) { + msg_perr("%s(): failed to enter passthru mode, result=0x%02x\n", + __func__, tmp8); + return 1; + } + + msg_pdbg("%s(): enter passthru mode return code: 0x%02x\n", + __func__, tmp8); + + /* start passthru mode */ + for (i = 0; i < strlen(MEC1308_CMD_PASSTHRU_START); i++) + mbx_write(ctx_data, MEC1308_MBX_DATA_START + i, + MEC1308_CMD_PASSTHRU_START[i]); + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_PASSTHRU)) { + msg_pdbg("%s(): start passthru command timed out\n", __func__); + return 1; + } + tmp8 = mbx_read(ctx_data, MEC1308_MBX_DATA_START); + if (tmp8 != MEC1308_CMD_PASSTHRU_SUCCESS) { + msg_perr("%s(): failed to enter passthru mode, result=%02x\n", + __func__, tmp8); + return 1; + } + msg_pdbg("%s(): start passthru mode return code: 0x%02x\n", + __func__, tmp8); + + return 0; +} + +static int mec1308_shutdown(void *data) +{ + mec1308_data_t *ctx_data = (mec1308_data_t *)data; + + /* Exit passthru mode before performing commands which do not affect + the SPI ROM */ + mec1308_exit_passthru_mode(ctx_data); + + /* Re-enable SMI and ACPI. + FIXME: is there an ordering dependency? */ + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_SMI_ENABLE)) + msg_pdbg("%s: unable to re-enable SMI\n", __func__); + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_ACPI_ENABLE)) + msg_pdbg("%s: unable to re-enable ACPI\n", __func__); + + free(data); + return 0; +} + +static int mec1308_chip_select(mec1308_data_t *ctx_data) +{ + return mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_PASSTHRU_CS_EN); +} + +static int mec1308_chip_deselect(mec1308_data_t *ctx_data) +{ + return mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_PASSTHRU_CS_DIS); +} + +/* + * MEC1308 will not allow direct access to SPI chip from host if EC is + * connected to LPC bus. This function will forward commands issued thru + * mailbox interface to the SPI flash chip. + */ +static int mec1308_spi_send_command(const struct flashctx *flash, unsigned int writecnt, + unsigned int readcnt, + const unsigned char *writearr, + unsigned char *readarr) +{ + int rc = 0; + size_t i; + mec1308_data_t *ctx_data = (mec1308_data_t *)flash->mst->spi.data; + + if (mec1308_chip_select(ctx_data)) + return 1; + + for (i = 0; i < writecnt; i++) { + if (mbx_write(ctx_data, MEC1308_MBX_DATA_START, writearr[i]) || + mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_PASSTHRU_SEND)) { + msg_pdbg("%s: failed to issue send command\n",__func__); + rc = 1; + goto mec1308_spi_send_command_exit; + } + } + + for (i = 0; i < readcnt; i++) { + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_PASSTHRU_READ)) { + msg_pdbg("%s: failed to issue read command\n",__func__); + rc = 1; + goto mec1308_spi_send_command_exit; + } + readarr[i] = mbx_read(ctx_data, MEC1308_MBX_DATA_START); + } + +mec1308_spi_send_command_exit: + rc |= mec1308_chip_deselect(ctx_data); + return rc; +} + +static struct spi_master spi_master_mec1308 = { + .max_data_read = 256, /* FIXME: should be MAX_DATA_READ_UNLIMITED? */ + .max_data_write = 256, /* FIXME: should be MAX_DATA_WRITE_UNLIMITED? */ + .command = mec1308_spi_send_command, + .multicommand = default_spi_send_multicommand, + .read = default_spi_read, + .write_256 = default_spi_write_256, +}; + +int mec1308_init(void) +{ + uint16_t sio_port; + uint8_t device_id; + uint8_t tmp8; + int ret = 0; + char *p = NULL; + mec1308_data_t *ctx_data = NULL; + + msg_pdbg("%s(): entered\n", __func__); + + ctx_data = calloc(1, sizeof(mec1308_data_t)); + if (!ctx_data) { + msg_perr("Unable to allocate space for extra context data.\n"); + return 1; + } + + p = extract_programmer_param("type"); + if (p && strcmp(p, "ec")) { + msg_pdbg("mec1308 only supports "ec" type devices\n"); + ret = 1; + goto mec1308_init_exit; + } + + if (mec1308_get_sio_index(ctx_data, &sio_port) < 0) { + msg_pdbg("MEC1308 not found (probe failed).\n"); + ret = 1; + goto mec1308_init_exit; + } + device_id = sio_read(sio_port, MEC1308_DEVICE_ID_REG); + switch(device_id) { + case MEC1308_DEVICE_ID_VAL: + msg_pdbg("Found EC: MEC1308 (ID:0x%02x,Rev:0x%02x) on " + "sio_port:0x%x.\n", device_id, + sio_read(sio_port, MEC1308_DEVICE_REV), sio_port); + break; + case MEC1310_DEVICE_ID_VAL: + msg_pdbg("Found EC: MEC1310 (ID:0x%02x,Rev:0x%02x) on " + "sio_port:0x%x.\n", device_id, + sio_read(sio_port, MEC1308_DEVICE_REV), sio_port); + break; + default: + msg_pdbg("MEC1308 not found\n"); + ret = 1; + goto mec1308_init_exit; + } + + /* + * setup mailbox interface at LDN 9 + */ + sio_write(sio_port, MEC1308_SIOCFG_LDN, 0x09); + tmp8 = sio_read(sio_port, 0x30); + tmp8 |= 1; + sio_write(sio_port, 0x30, tmp8); /* activate logical device */ + + ctx_data->mbx_idx = (unsigned int)sio_read(sio_port, 0x60) << 8 | + sio_read(sio_port, 0x61); + mbx_data = ctx_data->mbx_idx + 1; + msg_pdbg("%s: mbx_idx: 0x%04x, mbx_data: 0x%04x\n", + __func__, ctx_data->mbx_idx, mbx_data); + + /* Exit Super I/O config mode */ + mec1308_sio_exit(ctx_data, sio_port); + + /* Now that we can read the mailbox, we will wait for any remaining + * command to finish.*/ + if (mbx_wait(ctx_data) != 0) { + msg_perr("%s: mailbox is not available\n", __func__); + ret = 1; + goto mec1308_init_exit; + } + + /* Further setup -- disable SMI and ACPI. + FIXME: is there an ordering dependency? */ + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_ACPI_DISABLE)) { + msg_pdbg("%s: unable to disable ACPI\n", __func__); + ret = 1; + goto mec1308_init_exit; + } + + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_SMI_DISABLE)) { + msg_pdbg("%s: unable to disable SMI\n", __func__); + ret = 1; + goto mec1308_init_exit; + } + + if (register_shutdown(mec1308_shutdown, ctx_data)) { + ret = 1; + goto mec1308_init_exit; + } + + /* + * Enter SPI Pass-Thru Mode after commands which do not require access + * to SPI ROM are complete. We'll start by doing the exit_passthru_mode + * sequence, which is benign if the EC is already in passthru mode. + */ + mec1308_exit_passthru_mode(ctx_data); + + if (enter_passthru_mode(ctx_data)) { + ret = 1; + goto mec1308_init_exit; + } + + internal_buses_supported |= BUS_LPC; /* for LPC <--> SPI bridging */ + spi_master_mec1308.data = ctx_data; + register_spi_master(&spi_master_mec1308); + msg_pdbg("%s(): successfully initialized mec1308\n", __func__); + +mec1308_init_exit: + free(p); + if (ret) + free(ctx_data); + return ret; +} +#endif diff --git a/meson.build b/meson.build index 04176f3..fc79c60 100644 --- a/meson.build +++ b/meson.build @@ -47,6 +47,7 @@ config_it8212 = get_option('config_it8212') config_linux_mtd = get_option('config_linux_mtd') config_linux_spi = get_option('config_linux_spi') +config_mec1308 = get_option('config_mec1308') config_mstarddc_spi = get_option('config_mstarddc_spi') config_nic3com = get_option('config_nic3com') config_nicintel_eeprom = get_option('config_nicintel_eeprom') @@ -214,6 +215,10 @@ srcs += 'linux_spi.c' cargs += '-DCONFIG_LINUX_SPI=1' endif +if config_mec1308 + srcs += 'mec1308.c' + cargs += '-DCONFIG_MEC1308=1' +endif if config_mstarddc_spi srcs += 'mstarddc_spi.c' cargs += '-DCONFIG_MSTARDDC_SPI=1' diff --git a/meson_options.txt b/meson_options.txt index ac48e4e..24a1911 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -19,6 +19,7 @@ option('config_it8212', type : 'boolean', value : true, description : 'ITE IT8212F PATA') option('config_linux_mtd', type : 'boolean', value : true, description : 'Linux MTD interfaces') option('config_linux_spi', type : 'boolean', value : true, description : 'Linux spidev interfaces') +option('config_mec1308', type : 'boolean', value : false, description : 'Microchip MEC1308 Embedded Controller') option('config_mstarddc_spi', type : 'boolean', value : false, description : 'MSTAR DDC support') option('config_nic3com', type : 'boolean', value : true, description : '3Com NICs') option('config_nicintel_eeprom', type : 'boolean', value : true, description : 'EEPROM on Intel NICs') diff --git a/programmer.h b/programmer.h index c5cab18..6422541 100644 --- a/programmer.h +++ b/programmer.h @@ -109,6 +109,9 @@ #if CONFIG_USBBLASTER_SPI == 1 PROGRAMMER_USBBLASTER_SPI, #endif +#if CONFIG_MEC1308 == 1 + PROGRAMMER_MEC1308, +#endif #if CONFIG_MSTARDDC_SPI == 1 PROGRAMMER_MSTARDDC_SPI, #endif @@ -689,6 +692,11 @@ /* mcp6x_spi.c */ int mcp6x_spi_init(int want_spi);
+/* mec1308.c */ +#if CONFIG_MEC1308 == 1 +int mec1308_init(void); +#endif + /* sb600spi.c */ int sb600_probe_spi(struct pci_dev *dev);
Edward O'Callaghan has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Patch Set 1: Code-Review+2
Hello build bot (Jenkins), Edward O'Callaghan, Angel Pons,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/flashrom/+/44541
to look at the new patch set (#2).
Change subject: Add MEC1308 EC programmer ......................................................................
Add MEC1308 EC programmer
Initial support of Microchip MEC1308 Embedded Controller.
BUG=b:156144893 BRANCH=none
Signed-off-by: Victor Ding victording@google.com Change-Id: I2d51b4bdc0b38b6e488e71b9e774eb6232a2069e --- M Makefile M flashrom.c A mec1308.c M meson.build M meson_options.txt M programmer.h 6 files changed, 569 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/41/44541/2
David Hendricks has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Patch Set 2: Code-Review+1
Hello build bot (Jenkins), David Hendricks, Edward O'Callaghan, Angel Pons,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/flashrom/+/44541
to look at the new patch set (#3).
Change subject: Add MEC1308 EC programmer ......................................................................
Add MEC1308 EC programmer
Initial support of Microchip MEC1308 Embedded Controller.
BUG=b:156144893 BRANCH=none
Signed-off-by: Victor Ding victording@google.com Change-Id: I2d51b4bdc0b38b6e488e71b9e774eb6232a2069e --- M Makefile M flashrom.c A mec1308.c M meson.build M meson_options.txt M programmer.h 6 files changed, 569 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/41/44541/3
Edward O'Callaghan has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Patch Set 3: Code-Review+2
Angel Pons has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Patch Set 3:
(1 comment)
https://review.coreboot.org/c/flashrom/+/44541/3/mec1308.c File mec1308.c:
PS3: Is this license compatible with the rest of flashrom? If possible, it would be nice to have dual licensing (like on raiden_debug_spi.c)
Edward O'Callaghan has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Patch Set 3: -Code-Review
(1 comment)
https://review.coreboot.org/c/flashrom/+/44541/3/mec1308.c File mec1308.c:
PS3:
Is this license compatible with the rest of flashrom? If possible, it would be nice to have dual lic […]
We can just change the license since we are the orginal authors. Do you wish for us to just copy-paste the same header as raiden_debug Angel?
Angel Pons has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Patch Set 3:
(1 comment)
https://review.coreboot.org/c/flashrom/+/44541/3/mec1308.c File mec1308.c:
PS3:
We can just change the license since we are the orginal authors. […]
Yes, that would work. Thanks
Edward O'Callaghan has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Patch Set 3:
(1 comment)
https://review.coreboot.org/c/flashrom/+/44541/3/mec1308.c File mec1308.c:
PS3:
Yes, that would work. […]
Absolutely, np. Please let us know if there is anything else so we can handle it all in one go.
Hello build bot (Jenkins), David Hendricks, Edward O'Callaghan, Angel Pons,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/flashrom/+/44541
to look at the new patch set (#4).
Change subject: Add MEC1308 EC programmer ......................................................................
Add MEC1308 EC programmer
Initial support of Microchip MEC1308 Embedded Controller.
BUG=b:156144893 BRANCH=none
Signed-off-by: Victor Ding victording@google.com Change-Id: I2d51b4bdc0b38b6e488e71b9e774eb6232a2069e --- M Makefile M flashrom.c A mec1308.c M meson.build M meson_options.txt M programmer.h 6 files changed, 572 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/41/44541/4
Victor Ding has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Patch Set 4:
(1 comment)
https://review.coreboot.org/c/flashrom/+/44541/3/mec1308.c File mec1308.c:
PS3:
Absolutely, np. Please let us know if there is anything else so we can handle it all in one go.
The license has been updated to the same one as `raiden_debug_spi.c`.
Angel Pons has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Patch Set 4: Code-Review+2
Hello build bot (Jenkins), David Hendricks, Edward O'Callaghan, Angel Pons,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/flashrom/+/44541
to look at the new patch set (#5).
Change subject: Add MEC1308 EC programmer ......................................................................
Add MEC1308 EC programmer
Initial support of Microchip MEC1308 Embedded Controller.
BUG=b:156144893 BRANCH=none
Signed-off-by: Victor Ding victording@google.com Change-Id: I2d51b4bdc0b38b6e488e71b9e774eb6232a2069e --- M Makefile M flashrom.c A mec1308.c M meson.build M meson_options.txt M programmer.h 6 files changed, 572 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/41/44541/5
Edward O'Callaghan has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Patch Set 5: Code-Review+2
Edward O'Callaghan has submitted this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Add MEC1308 EC programmer
Initial support of Microchip MEC1308 Embedded Controller.
BUG=b:156144893 BRANCH=none
Signed-off-by: Victor Ding victording@google.com Change-Id: I2d51b4bdc0b38b6e488e71b9e774eb6232a2069e Reviewed-on: https://review.coreboot.org/c/flashrom/+/44541 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Edward O'Callaghan quasisec@chromium.org --- M Makefile M flashrom.c A mec1308.c M meson.build M meson_options.txt M programmer.h 6 files changed, 572 insertions(+), 0 deletions(-)
Approvals: build bot (Jenkins): Verified Edward O'Callaghan: Looks good to me, approved
diff --git a/Makefile b/Makefile index 85b4850..f3f7717 100644 --- a/Makefile +++ b/Makefile @@ -180,6 +180,11 @@ else override CONFIG_FT2232_SPI = no endif +ifeq ($(CONFIG_MEC1308), yes) +UNSUPPORTED_FEATURES += CONFIG_MEC1308=yes +else +override CONFIG_MEC1308 = no +endif ifeq ($(CONFIG_USBBLASTER_SPI), yes) UNSUPPORTED_FEATURES += CONFIG_USBBLASTER_SPI=yes else @@ -291,6 +296,11 @@ else override CONFIG_DRKAISER = no endif +ifeq ($(CONFIG_MEC1308), yes) +UNSUPPORTED_FEATURES += CONFIG_MEC1308=yes +else +override CONFIG_MEC1308 = no +endif ifeq ($(CONFIG_NICREALTEK), yes) UNSUPPORTED_FEATURES += CONFIG_NICREALTEK=yes else @@ -401,6 +411,11 @@ else override CONFIG_FT2232_SPI = no endif +ifeq ($(CONFIG_MEC1308), yes) +UNSUPPORTED_FEATURES += CONFIG_MEC1308=yes +else +override CONFIG_MEC1308 = no +endif ifeq ($(CONFIG_USBBLASTER_SPI), yes) UNSUPPORTED_FEATURES += CONFIG_USBBLASTER_SPI=yes else @@ -692,6 +707,9 @@ # Always enable FT2232 SPI dongles for now. CONFIG_FT2232_SPI ?= yes
+# Microchip MEC1308 Embedded Controller +CONFIG_MEC1308 ?= yes + # Always enable Altera USB-Blaster dongles for now. CONFIG_USBBLASTER_SPI ?= yes
@@ -878,6 +896,11 @@ PROGRAMMER_OBJS += ene_lpc.o endif
+ifeq ($(CONFIG_MEC1308), yes) +FEATURE_CFLAGS += -D'CONFIG_MEC1308=1' +PROGRAMMER_OBJS += mec1308.o +endif + ifeq ($(CONFIG_SERPROG), yes) FEATURE_CFLAGS += -D'CONFIG_SERPROG=1' PROGRAMMER_OBJS += serprog.o diff --git a/flashrom.c b/flashrom.c index 35ac6f5..c18a04f 100644 --- a/flashrom.c +++ b/flashrom.c @@ -84,6 +84,18 @@ }, #endif
+#if CONFIG_MEC1308 == 1 + { + .name = "mec1308", + .type = OTHER, + .devs.note = "Microchip MEC1308 Embedded Controller.\n", + .init = mec1308_init, + .map_flash_region = fallback_map, + .unmap_flash_region = fallback_unmap, + .delay = internal_delay, + }, +#endif + #if CONFIG_NIC3COM == 1 { .name = "nic3com", diff --git a/mec1308.c b/mec1308.c new file mode 100644 index 0000000..c4b34f5 --- /dev/null +++ b/mec1308.c @@ -0,0 +1,523 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2010-2020, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + */ + +#if defined(__i386__) || defined(__x86_64__) +#include <inttypes.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "flash.h" +#include "hwaccess.h" +#include "chipdrivers.h" +#include "programmer.h" +#include "spi.h" + +#define MEC1308_SIO_PORT1 0x2e +#define MEC1308_SIO_PORT2 0x4e +#define MEC1308_SIO_ENTRY_KEY 0x55 +#define MEC1308_SIO_EXIT_KEY 0xaa + +#define MEC1308_SIOCFG_LDN 0x07 /* LDN Bank Selector */ +#define MEC1308_DEVICE_ID_REG 0x20 /* Device ID Register */ +#define MEC1308_DEVICE_ID_VAL 0x4d /* Device ID Value for MEC1308 */ +#define MEC1310_DEVICE_ID_VAL 0x04 /* Device ID Value for MEC1310 */ +#define MEC1308_DEVICE_REV 0x21 /* Device Revision ID Register */ + +#define MEC1308_MBX_CMD 0x82 /* mailbox command register offset */ +#define MEC1308_MBX_EXT_CMD 0x83 /* mailbox ext. command reg offset */ +#define MEC1308_MBX_DATA_START 0x84 /* first mailbox data register offset */ +#define MEC1308_MBX_DATA_END 0x91 /* last mailbox data register offset */ + +static unsigned int mbx_data; /* Mailbox register interface data address*/ + +/* + * These command codes depend on EC firmware. The ones listed below are input + * using the mailbox interface, though others may be input using the ACPI + * interface. Some commands also have an output value (ie pass/failure code) + * which EC writes to the mailbox command register after completion. + */ +#define MEC1308_CMD_SMI_ENABLE 0x84 +#define MEC1308_CMD_SMI_DISABLE 0x85 +#define MEC1308_CMD_ACPI_ENABLE 0x86 +#define MEC1308_CMD_ACPI_DISABLE 0x87 + +/* + * Passthru commands are also input using the mailbox interface. Passthru mode + * enter/start/end commands are special since they require a command word to + * be written to the data registers. Other passthru commands are performed + * after passthru mode has been started. + * + * Multiple passthru mode commands may be issued before ending passthru mode. + * You do not need to enter, start, and end passthru mode for each SPI + * command. However, other mailbox commands might not work when passthru mode + * is enabled. For example, you may read all SPI chip content while in passthru + * mode, but you should exit passthru mode before performing other EC commands + * such as reading fan speed. + */ +#define MEC1308_CMD_PASSTHRU 0x55 /* force EC to process word */ +#define MEC1308_CMD_PASSTHRU_SUCCESS 0xaa /* success code for passthru */ +#define MEC1308_CMD_PASSTHRU_FAIL 0xfe /* failure code for passthru */ +#define MEC1308_CMD_PASSTHRU_ENTER "PathThruMode" /* not a typo... */ +#define MEC1308_CMD_PASSTHRU_START "Start" +#define MEC1308_CMD_PASSTHRU_EXIT "End_Mode" +#define MEC1308_CMD_PASSTHRU_CS_EN 0xf0 /* chip-select enable */ +#define MEC1308_CMD_PASSTHRU_CS_DIS 0xf1 /* chip-select disable */ +#define MEC1308_CMD_PASSTHRU_SEND 0xf2 /* send byte from data0 */ +#define MEC1308_CMD_PASSTHRU_READ 0xf3 /* read byte, place in data0 */ + +typedef struct +{ + unsigned int in_sio_cfgmode; + unsigned int mbx_idx; /* Mailbox register interface index address */ + unsigned int mbx_data; /* Mailbox register interface data address*/ +} mec1308_data_t; + +static void mec1308_sio_enter(mec1308_data_t *ctx_data, uint16_t port) +{ + if (ctx_data->in_sio_cfgmode) + return; + + OUTB(MEC1308_SIO_ENTRY_KEY, port); + ctx_data->in_sio_cfgmode = 1; +} + +static void mec1308_sio_exit(mec1308_data_t *ctx_data, uint16_t port) +{ + if (!ctx_data->in_sio_cfgmode) + return; + + OUTB(MEC1308_SIO_EXIT_KEY, port); + ctx_data->in_sio_cfgmode = 0; +} + +/** probe for super i/o index + * @port: allocated buffer to store port + * + * returns 0 to indicate success, <0 to indicate error + */ +static int mec1308_get_sio_index(mec1308_data_t *ctx_data, uint16_t *port) +{ + uint16_t ports[] = { MEC1308_SIO_PORT1, + MEC1308_SIO_PORT2, + }; + size_t i; + static uint16_t port_internal, port_found = 0; + + if (port_found) { + *port = port_internal; + return 0; + } + + if (rget_io_perms()) + return -1; + + for (i = 0; i < ARRAY_SIZE(ports); i++) { + uint8_t tmp8; + + /* + * Only after config mode has been successfully entered will the + * index port will read back the last value written to it. + * So we will attempt to enter config mode, set the index + * register, and see if the index register retains the value. + * + * Note: It seems to work "best" when using a device ID register + * as the index and reading from the data port before reading + * the index port. + */ + mec1308_sio_enter(ctx_data, ports[i]); + OUTB(MEC1308_DEVICE_ID_REG, ports[i]); + tmp8 = INB(ports[i] + 1); + tmp8 = INB(ports[i]); + if ((tmp8 != MEC1308_DEVICE_ID_REG)) { + ctx_data->in_sio_cfgmode = 0; + continue; + } + + port_internal = ports[i]; + port_found = 1; + break; + } + + if (!port_found) { + msg_cdbg("\nfailed to obtain super i/o index\n"); + return -1; + } + + msg_cdbg("\nsuper i/o index = 0x%04x\n", port_internal); + *port = port_internal; + return 0; +} + +static uint8_t mbx_read(mec1308_data_t *ctx_data, uint8_t idx) +{ + OUTB(idx, ctx_data->mbx_idx); + return INB(mbx_data); +} + +static int mbx_wait(mec1308_data_t *ctx_data) +{ + int i; + int max_attempts = 10000; + int rc = 0; + + for (i = 0; mbx_read(ctx_data, MEC1308_MBX_CMD); i++) { + if (i == max_attempts) { + rc = 1; + break; + } + /* FIXME: This delay adds determinism to the delay period. It + was chosen arbitrarily thru some experiments. */ + programmer_delay(2); + } + + return rc; +} + +static int mbx_write(mec1308_data_t *ctx_data, uint8_t idx, uint8_t data) +{ + int rc = 0; + + if (idx == MEC1308_MBX_CMD && mbx_wait(ctx_data)) { + msg_perr("%s: command register not clear\n", __func__); + return 1; + } + + OUTB(idx, ctx_data->mbx_idx); + OUTB(data, mbx_data); + + if (idx == MEC1308_MBX_CMD) + rc = mbx_wait(ctx_data); + + return rc; +} + +static void mbx_clear(mec1308_data_t *ctx_data) +{ + int reg; + + for (reg = MEC1308_MBX_DATA_START; reg < MEC1308_MBX_DATA_END; reg++) + mbx_write(ctx_data, reg, 0x00); + mbx_write(ctx_data, MEC1308_MBX_CMD, 0x00); +} + +static int mec1308_exit_passthru_mode(mec1308_data_t *ctx_data) +{ + uint8_t tmp8; + size_t i; + + /* exit passthru mode */ + for (i = 0; i < strlen(MEC1308_CMD_PASSTHRU_EXIT); i++) { + mbx_write(ctx_data, MEC1308_MBX_DATA_START + i, + MEC1308_CMD_PASSTHRU_EXIT[i]); + } + + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_PASSTHRU)) { + msg_pdbg("%s(): exit passthru command timed out\n", __func__); + return 1; + } + + tmp8 = mbx_read(ctx_data, MEC1308_MBX_DATA_START); + msg_pdbg("%s: result: 0x%02x ", __func__, tmp8); + if (tmp8 == MEC1308_CMD_PASSTHRU_SUCCESS) { + msg_pdbg("(exited passthru mode)\n"); + } else if (tmp8 == MEC1308_CMD_PASSTHRU_FAIL) { + msg_pdbg("(failed to exit passthru mode)\n"); + } + + return 0; +} + +static int enter_passthru_mode(mec1308_data_t *ctx_data) +{ + uint8_t tmp8; + size_t i; + + /* + * Enter passthru mode. If the EC does not successfully enter passthru + * mode the first time, we'll clear the mailbox and issue the "exit + * passthru mode" command sequence up to 3 times or until it arrives in + * a known state. + * + * Note: This workaround was developed experimentally. + */ + for (i = 0; i < 3; i++) { + size_t j; + + msg_pdbg("%s(): entering passthru mode, attempt %d out of 3\n", + __func__, (int)(i + 1)); + for (j = 0; j < strlen(MEC1308_CMD_PASSTHRU_ENTER); j++) { + mbx_write(ctx_data, MEC1308_MBX_DATA_START + j, + MEC1308_CMD_PASSTHRU_ENTER[j]); + } + + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_PASSTHRU)) + msg_pdbg("%s(): enter passthru command timed out\n", + __func__); + + tmp8 = mbx_read(ctx_data, MEC1308_MBX_DATA_START); + if (tmp8 == MEC1308_CMD_PASSTHRU_SUCCESS) + break; + + msg_pdbg("%s(): command failed, clearing data registers and " + "issuing full exit passthru command...\n", __func__); + mbx_clear(ctx_data); + mec1308_exit_passthru_mode(ctx_data); + } + + if (tmp8 != MEC1308_CMD_PASSTHRU_SUCCESS) { + msg_perr("%s(): failed to enter passthru mode, result=0x%02x\n", + __func__, tmp8); + return 1; + } + + msg_pdbg("%s(): enter passthru mode return code: 0x%02x\n", + __func__, tmp8); + + /* start passthru mode */ + for (i = 0; i < strlen(MEC1308_CMD_PASSTHRU_START); i++) + mbx_write(ctx_data, MEC1308_MBX_DATA_START + i, + MEC1308_CMD_PASSTHRU_START[i]); + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_PASSTHRU)) { + msg_pdbg("%s(): start passthru command timed out\n", __func__); + return 1; + } + tmp8 = mbx_read(ctx_data, MEC1308_MBX_DATA_START); + if (tmp8 != MEC1308_CMD_PASSTHRU_SUCCESS) { + msg_perr("%s(): failed to enter passthru mode, result=%02x\n", + __func__, tmp8); + return 1; + } + msg_pdbg("%s(): start passthru mode return code: 0x%02x\n", + __func__, tmp8); + + return 0; +} + +static int mec1308_shutdown(void *data) +{ + mec1308_data_t *ctx_data = (mec1308_data_t *)data; + + /* Exit passthru mode before performing commands which do not affect + the SPI ROM */ + mec1308_exit_passthru_mode(ctx_data); + + /* Re-enable SMI and ACPI. + FIXME: is there an ordering dependency? */ + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_SMI_ENABLE)) + msg_pdbg("%s: unable to re-enable SMI\n", __func__); + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_ACPI_ENABLE)) + msg_pdbg("%s: unable to re-enable ACPI\n", __func__); + + free(data); + return 0; +} + +static int mec1308_chip_select(mec1308_data_t *ctx_data) +{ + return mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_PASSTHRU_CS_EN); +} + +static int mec1308_chip_deselect(mec1308_data_t *ctx_data) +{ + return mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_PASSTHRU_CS_DIS); +} + +/* + * MEC1308 will not allow direct access to SPI chip from host if EC is + * connected to LPC bus. This function will forward commands issued thru + * mailbox interface to the SPI flash chip. + */ +static int mec1308_spi_send_command(const struct flashctx *flash, unsigned int writecnt, + unsigned int readcnt, + const unsigned char *writearr, + unsigned char *readarr) +{ + int rc = 0; + size_t i; + mec1308_data_t *ctx_data = (mec1308_data_t *)flash->mst->spi.data; + + if (mec1308_chip_select(ctx_data)) + return 1; + + for (i = 0; i < writecnt; i++) { + if (mbx_write(ctx_data, MEC1308_MBX_DATA_START, writearr[i]) || + mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_PASSTHRU_SEND)) { + msg_pdbg("%s: failed to issue send command\n",__func__); + rc = 1; + goto mec1308_spi_send_command_exit; + } + } + + for (i = 0; i < readcnt; i++) { + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_PASSTHRU_READ)) { + msg_pdbg("%s: failed to issue read command\n",__func__); + rc = 1; + goto mec1308_spi_send_command_exit; + } + readarr[i] = mbx_read(ctx_data, MEC1308_MBX_DATA_START); + } + +mec1308_spi_send_command_exit: + rc |= mec1308_chip_deselect(ctx_data); + return rc; +} + +static struct spi_master spi_master_mec1308 = { + .max_data_read = 256, /* FIXME: should be MAX_DATA_READ_UNLIMITED? */ + .max_data_write = 256, /* FIXME: should be MAX_DATA_WRITE_UNLIMITED? */ + .command = mec1308_spi_send_command, + .multicommand = default_spi_send_multicommand, + .read = default_spi_read, + .write_256 = default_spi_write_256, +}; + +int mec1308_init(void) +{ + uint16_t sio_port; + uint8_t device_id; + uint8_t tmp8; + int ret = 0; + char *p = NULL; + mec1308_data_t *ctx_data = NULL; + + msg_pdbg("%s(): entered\n", __func__); + + ctx_data = calloc(1, sizeof(mec1308_data_t)); + if (!ctx_data) { + msg_perr("Unable to allocate space for extra context data.\n"); + return 1; + } + + p = extract_programmer_param("type"); + if (p && strcmp(p, "ec")) { + msg_pdbg("mec1308 only supports "ec" type devices\n"); + ret = 1; + goto mec1308_init_exit; + } + + if (mec1308_get_sio_index(ctx_data, &sio_port) < 0) { + msg_pdbg("MEC1308 not found (probe failed).\n"); + ret = 1; + goto mec1308_init_exit; + } + device_id = sio_read(sio_port, MEC1308_DEVICE_ID_REG); + switch(device_id) { + case MEC1308_DEVICE_ID_VAL: + msg_pdbg("Found EC: MEC1308 (ID:0x%02x,Rev:0x%02x) on " + "sio_port:0x%x.\n", device_id, + sio_read(sio_port, MEC1308_DEVICE_REV), sio_port); + break; + case MEC1310_DEVICE_ID_VAL: + msg_pdbg("Found EC: MEC1310 (ID:0x%02x,Rev:0x%02x) on " + "sio_port:0x%x.\n", device_id, + sio_read(sio_port, MEC1308_DEVICE_REV), sio_port); + break; + default: + msg_pdbg("MEC1308 not found\n"); + ret = 1; + goto mec1308_init_exit; + } + + /* + * setup mailbox interface at LDN 9 + */ + sio_write(sio_port, MEC1308_SIOCFG_LDN, 0x09); + tmp8 = sio_read(sio_port, 0x30); + tmp8 |= 1; + sio_write(sio_port, 0x30, tmp8); /* activate logical device */ + + ctx_data->mbx_idx = (unsigned int)sio_read(sio_port, 0x60) << 8 | + sio_read(sio_port, 0x61); + mbx_data = ctx_data->mbx_idx + 1; + msg_pdbg("%s: mbx_idx: 0x%04x, mbx_data: 0x%04x\n", + __func__, ctx_data->mbx_idx, mbx_data); + + /* Exit Super I/O config mode */ + mec1308_sio_exit(ctx_data, sio_port); + + /* Now that we can read the mailbox, we will wait for any remaining + * command to finish.*/ + if (mbx_wait(ctx_data) != 0) { + msg_perr("%s: mailbox is not available\n", __func__); + ret = 1; + goto mec1308_init_exit; + } + + /* Further setup -- disable SMI and ACPI. + FIXME: is there an ordering dependency? */ + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_ACPI_DISABLE)) { + msg_pdbg("%s: unable to disable ACPI\n", __func__); + ret = 1; + goto mec1308_init_exit; + } + + if (mbx_write(ctx_data, MEC1308_MBX_CMD, MEC1308_CMD_SMI_DISABLE)) { + msg_pdbg("%s: unable to disable SMI\n", __func__); + ret = 1; + goto mec1308_init_exit; + } + + if (register_shutdown(mec1308_shutdown, ctx_data)) { + ret = 1; + goto mec1308_init_exit; + } + + /* + * Enter SPI Pass-Thru Mode after commands which do not require access + * to SPI ROM are complete. We'll start by doing the exit_passthru_mode + * sequence, which is benign if the EC is already in passthru mode. + */ + mec1308_exit_passthru_mode(ctx_data); + + if (enter_passthru_mode(ctx_data)) { + ret = 1; + goto mec1308_init_exit; + } + + internal_buses_supported |= BUS_LPC; /* for LPC <--> SPI bridging */ + spi_master_mec1308.data = ctx_data; + register_spi_master(&spi_master_mec1308); + msg_pdbg("%s(): successfully initialized mec1308\n", __func__); + +mec1308_init_exit: + free(p); + if (ret) + free(ctx_data); + return ret; +} +#endif diff --git a/meson.build b/meson.build index 180b5dd..9836194 100644 --- a/meson.build +++ b/meson.build @@ -48,6 +48,7 @@ config_it8212 = get_option('config_it8212') config_linux_mtd = get_option('config_linux_mtd') config_linux_spi = get_option('config_linux_spi') +config_mec1308 = get_option('config_mec1308') config_mstarddc_spi = get_option('config_mstarddc_spi') config_nic3com = get_option('config_nic3com') config_nicintel_eeprom = get_option('config_nicintel_eeprom') @@ -219,6 +220,10 @@ srcs += 'linux_spi.c' cargs += '-DCONFIG_LINUX_SPI=1' endif +if config_mec1308 + srcs += 'mec1308.c' + cargs += '-DCONFIG_MEC1308=1' +endif if config_mstarddc_spi srcs += 'mstarddc_spi.c' cargs += '-DCONFIG_MSTARDDC_SPI=1' diff --git a/meson_options.txt b/meson_options.txt index ba5130b..9c0a798 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -20,6 +20,7 @@ option('config_it8212', type : 'boolean', value : true, description : 'ITE IT8212F PATA') option('config_linux_mtd', type : 'boolean', value : true, description : 'Linux MTD interfaces') option('config_linux_spi', type : 'boolean', value : true, description : 'Linux spidev interfaces') +option('config_mec1308', type : 'boolean', value : true, description : 'Microchip MEC1308 Embedded Controller') option('config_mstarddc_spi', type : 'boolean', value : false, description : 'MSTAR DDC support') option('config_nic3com', type : 'boolean', value : true, description : '3Com NICs') option('config_nicintel_eeprom', type : 'boolean', value : true, description : 'EEPROM on Intel NICs') diff --git a/programmer.h b/programmer.h index b3bc700..73d37f8 100644 --- a/programmer.h +++ b/programmer.h @@ -112,6 +112,9 @@ #if CONFIG_USBBLASTER_SPI == 1 PROGRAMMER_USBBLASTER_SPI, #endif +#if CONFIG_MEC1308 == 1 + PROGRAMMER_MEC1308, +#endif #if CONFIG_MSTARDDC_SPI == 1 PROGRAMMER_MSTARDDC_SPI, #endif @@ -697,6 +700,11 @@ /* mcp6x_spi.c */ int mcp6x_spi_init(int want_spi);
+/* mec1308.c */ +#if CONFIG_MEC1308 == 1 +int mec1308_init(void); +#endif + /* sb600spi.c */ int sb600_probe_spi(struct pci_dev *dev);
Attention is currently required from: Victor Ding. Nico Huber has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Patch Set 6:
(1 comment)
File Makefile:
https://review.coreboot.org/c/flashrom/+/44541/comment/4f41b8ad_84896c93 PS6, Line 187: endif Why?
Attention is currently required from: Victor Ding. Nico Huber has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Patch Set 6:
(1 comment)
File Makefile:
https://review.coreboot.org/c/flashrom/+/44541/comment/3f5f92ac_6f7cf27e PS6, Line 418: endif Why?
Victor Ding has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Patch Set 6:
(2 comments)
File Makefile:
https://review.coreboot.org/c/flashrom/+/44541/comment/8774010b_bb9d2238 PS6, Line 187: endif
Why?
The code was ported from Chromium's flashrom fork, I don't think it has ever been verified on DOS; therefore, I decided this configuration shouldn't be allowed until tested when submitting this patch. WDYT?
https://review.coreboot.org/c/flashrom/+/44541/comment/7dde53ce_3677cf76 PS6, Line 418: endif
Why?
The code was ported from Chromium's flashrom fork, I don't think it has ever been verified on libpayload; therefore, I decided this configuration shouldn't be allowed until tested when submitting this patch. WDYT?
Attention is currently required from: Victor Ding. Angel Pons has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Patch Set 6:
(1 comment)
File Makefile:
https://review.coreboot.org/c/flashrom/+/44541/comment/9bf138de_e296b645 PS6, Line 187: endif
The code was ported from Chromium's flashrom fork, I don't think it has ever been verified on DOS; t […]
It doesn't make sense to artificially limit support. Plus, the programmer lacks any sort of compatibility list to ensure it isn't used on an unknown system by accident. Yes, other programmers also have this issue.
Victor Ding has posted comments on this change. ( https://review.coreboot.org/c/flashrom/+/44541 )
Change subject: Add MEC1308 EC programmer ......................................................................
Patch Set 6:
(2 comments)
File Makefile:
https://review.coreboot.org/c/flashrom/+/44541/comment/8a456dc6_e1ddf706 PS6, Line 187: endif
It doesn't make sense to artificially limit support. […]
The programmer has been deleted by CB:56476.
https://review.coreboot.org/c/flashrom/+/44541/comment/2f0c44ac_d08744fc PS6, Line 418: endif
The code was ported from Chromium's flashrom fork, I don't think it has ever been verified on libpay […]
The programmer has been deleted by CB:56476.