Iru Cai (vimacs) would like Iru Cai to review this change.

View Change

ec: Add support for MEC5055 for Dell laptops

This EC support code is required to boot various Dell Latitude laptops,
otherwise the laptop will shut down in a minute after powered on.

Tested on Dell Latitude E7240.

Change-Id: Iee68ea52dcf0242315868a46b5e4768303e30dce
Signed-off-by: Iru Cai <mytbk920423@gmail.com>
---
A src/ec/dell/mec5055/Kconfig
A src/ec/dell/mec5055/Makefile.inc
A src/ec/dell/mec5055/early_init.c
A src/ec/dell/mec5055/mec5055.c
A src/ec/dell/mec5055/mec5055.h
5 files changed, 148 insertions(+), 0 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/75/44975/1
diff --git a/src/ec/dell/mec5055/Kconfig b/src/ec/dell/mec5055/Kconfig
new file mode 100644
index 0000000..a7bf9a5
--- /dev/null
+++ b/src/ec/dell/mec5055/Kconfig
@@ -0,0 +1,4 @@
+## SPDX-License-Identifier: GPL-2.0-only
+
+config EC_DELL_MEC5055
+ bool
diff --git a/src/ec/dell/mec5055/Makefile.inc b/src/ec/dell/mec5055/Makefile.inc
new file mode 100644
index 0000000..9cdfbb3
--- /dev/null
+++ b/src/ec/dell/mec5055/Makefile.inc
@@ -0,0 +1,8 @@
+## SPDX-License-Identifier: GPL-2.0-only
+
+ifeq ($(CONFIG_EC_DELL_MEC5055),y)
+
+bootblock-y += mec5055.c early_init.c
+romstage-y += mec5055.c early_init.c
+
+endif
diff --git a/src/ec/dell/mec5055/early_init.c b/src/ec/dell/mec5055/early_init.c
new file mode 100644
index 0000000..6aec48b
--- /dev/null
+++ b/src/ec/dell/mec5055/early_init.c
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#include "mec5055.h"
+
+void mec5055_early_init(void)
+{
+ u8 buf[32], c;
+
+ mec5055_ec_command_0(buf, 0xc2, 0);
+ mec5055_ec_command_1(0xab, NULL, 0, &c, 1);
+}
diff --git a/src/ec/dell/mec5055/mec5055.c b/src/ec/dell/mec5055/mec5055.c
new file mode 100644
index 0000000..2deec7d
--- /dev/null
+++ b/src/ec/dell/mec5055/mec5055.c
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#include <arch/io.h>
+#include "mec5055.h"
+
+static const u16 EC_CTRL = 0x910;
+static const u16 EC_DATA = 0x911;
+
+static void wait_ec(void)
+{
+ u8 v;
+ do {
+ outb(0, EC_CTRL);
+ v = inb(EC_DATA);
+ } while (v != 0);
+}
+
+static int read_ec_regs(u8 start, u8 *sdata, u8 count)
+{
+ if (start >= 0x20 || start + count > 0x20)
+ return -1;
+
+ if (count <= 0)
+ return 0;
+
+ while (count--) {
+ outb(start + 0x10, EC_CTRL);
+ *sdata = inb(EC_DATA);
+ sdata++;
+ start++;
+ }
+
+ return 0;
+}
+
+static int write_ec_regs(u8 start, const u8 *sdata, u8 count)
+{
+ if (start >= 0x20 || start + count > 0x20)
+ return -1;
+
+ if (count <= 0)
+ return 0;
+
+ while (count--) {
+ outb(start + 0x10, EC_CTRL);
+ outb(*sdata, EC_DATA);
+ sdata++;
+ start++;
+ }
+
+ return 0;
+}
+
+/* Steps to communicate with the EC:
+ * 1. send command:
+ * - write arguments to EC[2:]
+ * - send 0 to CTRL then cmd to DATA
+ * 2. wait EC
+ * 3. receive result: result may starts at EC[0] or EC[1]
+ */
+
+/* send command to EC and wait, command at cmd[0], args in cmd[2:] */
+static int ec_send_command(const u8 *cmd, int argc)
+{
+ int result = 0;
+
+ if (argc > 0) {
+ if (argc > 0x1e)
+ result = -1;
+ else
+ result = write_ec_regs(2, cmd + 2, argc);
+ }
+
+ outb(0, EC_CTRL);
+ outb(cmd[0], EC_DATA);
+ wait_ec();
+ return result;
+}
+
+/* receive result from EC[0:] */
+int mec5055_ec_command_0(u8 *buf, u8 cmd, int argc)
+{
+ buf[0] = cmd;
+ int res = ec_send_command(buf, argc);
+ if (res < 0)
+ return res;
+
+ return read_ec_regs(0, buf, 0x10);
+}
+
+/* receive result from EC[1:] */
+int mec5055_ec_command_1(u8 cmd, const u8 *cmd_buf, int argc, u8 *res_buf, int res_size)
+{
+ if (argc >= 0x1e)
+ argc = 0x1e;
+
+ if (res_size >= 0x1f)
+ res_size = 0x1f;
+
+ int t = write_ec_regs(2, cmd_buf, argc);
+ if (t < 0)
+ return t;
+
+ outb(0, EC_CTRL);
+ outb(cmd, EC_DATA);
+ wait_ec();
+
+ return read_ec_regs(1, res_buf, res_size);
+}
diff --git a/src/ec/dell/mec5055/mec5055.h b/src/ec/dell/mec5055/mec5055.h
new file mode 100644
index 0000000..33c6a1d
--- /dev/null
+++ b/src/ec/dell/mec5055/mec5055.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#ifndef _EC_DELL_MEC5055_H_
+#define _EC_DELL_MEC5055_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+int mec5055_ec_command_0(u8 *buf, u8 cmd, int argc);
+int mec5055_ec_command_1(u8 cmd, const u8 *cmd_buf, int argc, u8 *res_buf, int res_size);
+void mec5055_early_init(void);
+
+#endif

To view, visit change 44975. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: Iee68ea52dcf0242315868a46b5e4768303e30dce
Gerrit-Change-Number: 44975
Gerrit-PatchSet: 1
Gerrit-Owner: Iru Cai (vimacs) <mytbk920423@gmail.com>
Gerrit-Reviewer: Iru Cai <mytbk920423@gmail.com>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-MessageType: newchange