From 52ffeb512ee07601f3a63961e6fd7c22ff978c25 Mon Sep 17 00:00:00 2001 From: Iru Cai Date: Sun, 7 Jun 2020 21:40:21 +0800 Subject: [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 --- src/ec/dell/mec5055/Kconfig | 4 ++ src/ec/dell/mec5055/Makefile.inc | 9 ++++ src/ec/dell/mec5055/acpi.c | 14 +++++ src/ec/dell/mec5055/early_init.c | 12 +++++ src/ec/dell/mec5055/mec5055.c | 110 +++++++++++++++++++++++++++++++++++++++ src/ec/dell/mec5055/mec5055.h | 15 ++++++ 6 files changed, 164 insertions(+) create mode 100644 src/ec/dell/mec5055/Kconfig create mode 100644 src/ec/dell/mec5055/Makefile.inc create mode 100644 src/ec/dell/mec5055/acpi.c create mode 100644 src/ec/dell/mec5055/early_init.c create mode 100644 src/ec/dell/mec5055/mec5055.c create mode 100644 src/ec/dell/mec5055/mec5055.h 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 +#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 +#include + +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 -- cgit v1.2.3