aboutsummaryrefslogtreecommitdiff
path: root/src/mainboard/lippert/frontrunner-af/sema.c
diff options
context:
space:
mode:
authorKyösti Mälkki <kyosti.malkki@gmail.com>2017-08-30 12:01:08 +0300
committerKyösti Mälkki <kyosti.malkki@gmail.com>2017-09-06 22:18:10 +0000
commit081b66951f04bb67ad2d04750212a45fc0c24e90 (patch)
treeb4f9342a0bf2c58b44a9b1b413b980e498dbc446 /src/mainboard/lippert/frontrunner-af/sema.c
parent8a8386eeb9356b73fc7bc706298706656ceca385 (diff)
mainboard/lippert: Refactor SEMA watchdog message
It's too critical to ignore when sending the message on SMBus fails, so allow for a fair amount of retries. Failure here causes watchdog to do hard reset later. Move it out of mainboard.c as we need to call this early in romstage while we are debugging. Change-Id: I1006b079269d6dd44de630db7a5694124af2f974 Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-on: https://review.coreboot.org/21316 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/mainboard/lippert/frontrunner-af/sema.c')
-rw-r--r--src/mainboard/lippert/frontrunner-af/sema.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/src/mainboard/lippert/frontrunner-af/sema.c b/src/mainboard/lippert/frontrunner-af/sema.c
new file mode 100644
index 0000000000..3a4994de1d
--- /dev/null
+++ b/src/mainboard/lippert/frontrunner-af/sema.c
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <delay.h>
+#include "OEM.h" /* SMBUS0_BASE_ADDRESS */
+
+#include "Porting.h"
+#include "AGESA.h"
+#include <northbridge/amd/agesa/dimmSpd.h>
+#include "sema.h"
+
+/* Write data block to slave on SMBUS0. */
+#define SMB0_STATUS ((SMBUS0_BASE_ADDRESS) + 0)
+#define SMB0_CONTROL ((SMBUS0_BASE_ADDRESS) + 2)
+#define SMB0_HOSTCMD ((SMBUS0_BASE_ADDRESS) + 3)
+#define SMB0_ADDRESS ((SMBUS0_BASE_ADDRESS) + 4)
+#define SMB0_DATA0 ((SMBUS0_BASE_ADDRESS) + 5)
+#define SMB0_BLOCKDATA ((SMBUS0_BASE_ADDRESS) + 7)
+
+static int smb_write_blk(u8 slave, u8 command, u8 length, const u8 *data)
+{
+ __outbyte(SMB0_STATUS, 0x1E); // clear error status
+ __outbyte(SMB0_ADDRESS, slave & ~1); // slave addr + direction = out
+ __outbyte(SMB0_HOSTCMD, command); // or destination offset
+ __outbyte(SMB0_DATA0, length); // sent before data
+ __inbyte(SMB0_CONTROL); // reset block data array
+ while (length--)
+ __outbyte(SMB0_BLOCKDATA, *(data++));
+ __outbyte(SMB0_CONTROL, 0x54); // execute block write, no IRQ
+
+ while (__inbyte(SMB0_STATUS) == 0x01); // busy, no errors
+ return __inbyte(SMB0_STATUS) ^ 0x02; // 0x02 = completed, no errors
+}
+
+#define RETRY_COUNT 100
+
+/* Use of mdelay() here would fail in romstage. */
+static void early_mdelay(int msecs)
+{
+ while (msecs--) {
+ int i;
+ for (i = 0; i < 1000; i++)
+ inb(0x80);
+ }
+}
+
+int sema_send_alive(void)
+{
+ const u8 i_am_alive[] = { 0x03 };
+ int i, j = 0;
+ char one_spd_byte;
+
+ /* Fake read just to setup SMBUS controller. */
+ if (ENV_ROMSTAGE)
+ smbus_readSpd(0xa0, &one_spd_byte, 1);
+
+ /* Notify the SMC we're alive and kicking, or after a while it will
+ * effect a power cycle and switch to the alternate BIOS chip.
+ * Should be done as late as possible. */
+
+ printk(BIOS_CRIT, "Sending BIOS alive message... ");
+
+ do {
+ i = smb_write_blk(0x50, 0x25, sizeof(i_am_alive), i_am_alive);
+ early_mdelay(25);
+ } while ((++j < RETRY_COUNT) && i);
+
+ if (j == RETRY_COUNT) {
+ printk(BIOS_INFO, "failed\n");
+ return -1;
+ }
+ printk(BIOS_CRIT, "took %d tries\n", j);
+
+ return 0;
+}