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

Reply via email to