summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIru Cai <mytbk920423@gmail.com>2020-06-07 21:40:21 +0800
committerIru Cai <mytbk920423@gmail.com>2020-06-25 20:44:10 +0800
commit52ffeb512ee07601f3a63961e6fd7c22ff978c25 (patch)
tree172a835f252c48c619da1f4f756080fcc146c475
parent28da35417bcde79edbf826fef7d02bbfe5c714cf (diff)
downloadcoreboot-52ffeb512ee07601f3a63961e6fd7c22ff978c25.tar.xz
[WIP] ec: Add support for MEC5055 for Dell laptops
This EC support code is required to boot Dell Latitude E6230 and E7240, otherwise the laptop will shut on in a minute after powered on. ACPI support doesn't work yet. Change-Id: Iee68ea52dcf0242315868a46b5e4768303e30dce Signed-off-by: Iru Cai <mytbk920423@gmail.com>
-rw-r--r--src/ec/dell/mec5055/Kconfig4
-rw-r--r--src/ec/dell/mec5055/Makefile.inc9
-rw-r--r--src/ec/dell/mec5055/acpi.c14
-rw-r--r--src/ec/dell/mec5055/early_init.c12
-rw-r--r--src/ec/dell/mec5055/mec5055.c110
-rw-r--r--src/ec/dell/mec5055/mec5055.h15
6 files changed, 164 insertions, 0 deletions
diff --git a/src/ec/dell/mec5055/Kconfig b/src/ec/dell/mec5055/Kconfig
new file mode 100644
index 0000000000..a7bf9a505d
--- /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 0000000000..b5438fc452
--- /dev/null
+++ b/src/ec/dell/mec5055/Makefile.inc
@@ -0,0 +1,9 @@
+## 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
+smm-y += mec5055.c acpi.c
+
+endif
diff --git a/src/ec/dell/mec5055/acpi.c b/src/ec/dell/mec5055/acpi.c
new file mode 100644
index 0000000000..ad4a34a466
--- /dev/null
+++ b/src/ec/dell/mec5055/acpi.c
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#include "mec5055.h"
+
+void mec5055_ec_acpi_enable(void)
+{
+ u8 buf1[32] = {0};
+ /* FIXME: only one arg? */
+ buf1[2] = 1;
+ mec5055_ec_command_0(buf1, 0x19, 3);
+ buf1[2] = 1;
+ mec5055_ec_command_0(buf1, 0x3a, 3);
+}
diff --git a/src/ec/dell/mec5055/early_init.c b/src/ec/dell/mec5055/early_init.c
new file mode 100644
index 0000000000..f69c1deabc
--- /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 buf1[32];
+ u8 c;
+ mec5055_ec_command_0(buf1, 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 0000000000..2deec7d49e
--- /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 0000000000..712057c26f
--- /dev/null
+++ b/src/ec/dell/mec5055/mec5055.h
@@ -0,0 +1,15 @@
+/* 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);
+void mec5055_ec_acpi_enable(void);
+
+#endif