Hi all,
I will try tomorrow with IMC activated in coreboot. Current patch attached
UNTESTED COMPLETELY! It should deactivate the IMC and find all base addresses
automagically.
For IMC details check http://coreboot.org/AMD_IMC
Is it possible to call some function when flashrom exits?
Signed-off-by: Rudolf Marek <[email protected]>
Thanks
Rudolf
Index: imc.c
===================================================================
--- imc.c (revision 0)
+++ imc.c (revision 0)
@@ -0,0 +1,167 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2013 Rudolf Marek <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if defined(__i386__) || defined(__x86_64__)
+
+#include "flash.h"
+#include "programmer.h"
+#include "hwaccess.h"
+#include "spi.h"
+
+/* same as serverengines */
+static void enter_conf_mode_ec(uint16_t port)
+{
+ outb(0x5a, port);
+}
+
+static void exit_conf_mode_ec(uint16_t port)
+{
+ outb(0xa5, port);
+}
+
+static uint16_t get_sio_port(struct pci_dev *dev)
+{
+ uint16_t ec_port;
+
+ if (!dev) {
+ return 0;
+ }
+
+ if (!(pci_read_byte(dev, 0x40) & (1 << 7)))
+ return 0;
+
+ ec_port = pci_read_word(dev, 0xa4);
+
+ if (!(ec_port & 0x1))
+ return 0;
+
+ ec_port &= ~0x1;
+
+ return ec_port;
+}
+
+
+static void write_data(uint16_t port, uint8_t off, uint8_t data)
+{
+ outb(off, port);
+ outb(data, port + 1);
+}
+
+static uint8_t read_data(uint16_t port, uint8_t off)
+{
+ outb(off, port);
+ return inb(port + 1);
+}
+
+
+static uint16_t get_mbox_port(uint16_t sio_port)
+{
+ uint16_t mbox_port;
+
+ enter_conf_mode_ec(sio_port);
+
+ /* go to LDN 9, mailbox */
+ write_data(sio_port, 7, 9);
+
+ /* MBOX not active ? */
+ if (!(read_data(sio_port, 0x30) & 1)) {
+ exit_conf_mode_ec(sio_port);
+ return 0;
+ }
+
+ mbox_port = read_data(sio_port, 0x60) << 8;
+ mbox_port |= read_data(sio_port, 0x61);
+
+ exit_conf_mode_ec(sio_port);
+ return mbox_port;
+}
+
+static int mbox_wait_ack(uint16_t mbox_port)
+{
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ /* sleep 1ms */
+ programmer_delay(1000);
+ if (read_data(mbox_port, 0x82) == 0xfa) {
+ return 0;
+ }
+ }
+ msg_pwarn("IMC MBOX: Timeout!\n");
+ return 1;
+
+}
+
+static int send_cmd(uint16_t mbox_port, uint8_t cmd)
+{
+ write_data(mbox_port, 0x82, 0x0);
+ write_data(mbox_port, 0x83, cmd);
+ /* trigger transfer 0x96 with subcommand cmd */
+ write_data(mbox_port, 0x80, 0x96);
+
+ return mbox_wait_ack(mbox_port);
+}
+
+static int imc_cmd(struct pci_dev *dev, uint8_t cmd)
+{
+ uint16_t sio_port;
+ uint16_t mbox_port;
+ sio_port = get_sio_port(dev);
+
+ if (!sio_port)
+ return -1;
+
+ msg_pdbg("EC SIO is at 0x%x\n", sio_port);
+
+ mbox_port = get_mbox_port(sio_port);
+
+ if (!mbox_port)
+ return -1;
+
+ msg_pdbg("EC MBOX is at 0x%x\n", mbox_port);
+
+ /* put IMC to sleep */
+ return send_cmd(mbox_port, cmd);
+}
+
+int imc_try_shutdown(struct pci_dev *dev)
+{
+ int ret = imc_cmd(dev, 0xb4);
+
+ /* No IMC active, fake OK */
+ if (ret < 0)
+ return 0;
+
+ msg_pinfo("IMC firmware handoff %s\n", ret ? "failed" : "OK");
+ return ret;
+}
+
+int imc_try_resume(struct pci_dev *dev)
+{
+ int ret = imc_cmd(dev, 0xb5);
+
+ /* No IMC active, fake OK */
+ if (ret < 0)
+ return 0;
+
+ msg_pinfo("IMC firmware resume %s\n", ret ? "failed" : "OK");
+ return ret;
+}
+#endif
\ No newline at end of file
Index: chipset_enable.c
===================================================================
--- chipset_enable.c (revision 1657)
+++ chipset_enable.c (working copy)
@@ -922,6 +922,11 @@
uint8_t reg;
int ret;
+ if (imc_try_shutdown(dev)) {
+ msg_perr("IMC firmware handoff failed!\n");
+ return ERROR_FATAL;
+ }
+
/* Clear ROM protect 0-3. */
for (reg = 0x50; reg < 0x60; reg += 4) {
prot = pci_read_long(dev, reg);
Index: programmer.h
===================================================================
--- programmer.h (revision 1657)
+++ programmer.h (working copy)
@@ -559,6 +559,10 @@
enum ich_chipset ich_generation);
int via_init_spi(struct pci_dev *dev, uint32_t mmio_base);
+/* imc.c */
+int imc_try_shutdown(struct pci_dev *dev);
+int imc_try_resume(struct pci_dev *dev);
+
/* it85spi.c */
int it85xx_spi_init(struct superio s);
Index: Makefile
===================================================================
--- Makefile (revision 1657)
+++ Makefile (working copy)
@@ -417,7 +417,7 @@
FEATURE_CFLAGS += -D'CONFIG_INTERNAL=1'
PROGRAMMER_OBJS += processor_enable.o chipset_enable.o board_enable.o cbtable.o dmi.o internal.o
ifeq ($(ARCH), x86)
-PROGRAMMER_OBJS += it87spi.o it85spi.o sb600spi.o wbsio_spi.o mcp6x_spi.o
+PROGRAMMER_OBJS += it87spi.o it85spi.o sb600spi.o imc.o wbsio_spi.o mcp6x_spi.o
PROGRAMMER_OBJS += ichspi.o ich_descriptors.o
else
endif
_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom