diff options
-rw-r--r-- | src/ec/dell/mec5035/Kconfig | 4 | ||||
-rw-r--r-- | src/ec/dell/mec5035/Makefile.inc | 9 | ||||
-rw-r--r-- | src/ec/dell/mec5035/mec5035.c | 122 | ||||
-rw-r--r-- | src/ec/dell/mec5035/mec5035.h | 23 |
4 files changed, 158 insertions, 0 deletions
diff --git a/src/ec/dell/mec5035/Kconfig b/src/ec/dell/mec5035/Kconfig new file mode 100644 index 0000000000..220714371d --- /dev/null +++ b/src/ec/dell/mec5035/Kconfig @@ -0,0 +1,4 @@ +## SPDX-License-Identifier: GPL-2.0-only + +config EC_DELL_MEC5035 + bool diff --git a/src/ec/dell/mec5035/Makefile.inc b/src/ec/dell/mec5035/Makefile.inc new file mode 100644 index 0000000000..4ebdd811f9 --- /dev/null +++ b/src/ec/dell/mec5035/Makefile.inc @@ -0,0 +1,9 @@ +## SPDX-License-Identifier: GPL-2.0-only + +ifeq ($(CONFIG_EC_DELL_MEC5035),y) + +bootblock-y += mec5035.c +romstage-y += mec5035.c +ramstage-y += mec5035.c + +endif diff --git a/src/ec/dell/mec5035/mec5035.c b/src/ec/dell/mec5035/mec5035.c new file mode 100644 index 0000000000..8da11e5b1c --- /dev/null +++ b/src/ec/dell/mec5035/mec5035.c @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <arch/io.h> +#include <console/console.h> +#include <device/device.h> +#include <device/pnp.h> +#include <pc80/keyboard.h> +#include <stdint.h> +#include "mec5035.h" + +static const u16 MAILBOX_INDEX = 0x910; +static const u16 MAILBOX_DATA = MAILBOX_INDEX + 1; + +static inline u8 __get_mailbox_register(u8 index) +{ + outb(index + 0x10, MAILBOX_INDEX); + return inb(MAILBOX_DATA); +} + +static inline void __set_mailbox_register(u8 index, u8 data) +{ + outb(index + 0x10, MAILBOX_INDEX); + outb(data, MAILBOX_DATA); +} + +static void wait_ec(void) +{ + u8 busy; + do { + outb(0, MAILBOX_INDEX); + busy = inb(MAILBOX_DATA); + } while (busy); +} + + +static enum cb_err read_mailbox_regs(u8 *data, u8 start, u8 count) +{ + if (start + count >= NUM_REGISTERS) { + printk(BIOS_ERR, "%s: Invalid start or count argument.\n", __func__); + return CB_ERR_ARG; + } + + while (count--) { + *data = __get_mailbox_register(start); + data++; + start++; + } + + return CB_SUCCESS; +} + +static enum cb_err write_mailbox_regs(const u8 *data, u8 start, u8 count) +{ + if (start + count >= NUM_REGISTERS) { + printk(BIOS_ERR, "%s: Invalid start or count argument.\n", __func__); + return CB_ERR_ARG; + } + + while (count--) { + __set_mailbox_register(start, *data); + data++; + start++; + } + + return CB_SUCCESS; +} + +static void ec_command(u8 cmd) +{ + outb(0, MAILBOX_INDEX); + outb(cmd, MAILBOX_DATA); + wait_ec(); +} + +u8 mec5035_mouse_touchpad(u8 setting) +{ + u8 buf[15] = {0}; + write_mailbox_regs(&setting, 2, 1); + ec_command(CMD_MOUSE_TP); + /* The vendor firmware reads 15 bytes starting at index 1, presumably + to get some sort of return code. Though I don't know for sure if + this is the case. Assume the first byte is the return code. */ + read_mailbox_regs(buf, 1, 15); + return buf[0]; +} + +void mec5035_early_init(void) +{ + /* If this isn't sent the EC shuts down the system after about 15 + seconds, flashing a pattern on the keyboard LEDs corresponding + to "processor failure" according to Dell service manuals. */ + ec_command(CMD_CPU_OK); +} + +static void mec5035_init(struct device *dev) +{ + /* Unconditionally use this argument for now as this setting + is probably the most sensible default out of the 3 choices. */ + mec5035_mouse_touchpad(TP_PS2_MOUSE); + + pc_keyboard_init(NO_AUX_DEVICE); +} + +static struct device_operations ops = { + .init = mec5035_init, + .read_resources = noop_read_resources, + .set_resources = noop_set_resources +}; + +static struct pnp_info pnp_dev_info[] = { + { NULL, 0, 0, 0, } +}; + +static void mec5035_enable(struct device *dev) +{ + pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info); +} + +struct chip_operations ec_dell_mec5035_ops = { + CHIP_NAME("MEC5035 EC") + .enable_dev = mec5035_enable, +}; diff --git a/src/ec/dell/mec5035/mec5035.h b/src/ec/dell/mec5035/mec5035.h new file mode 100644 index 0000000000..e7a05b64d4 --- /dev/null +++ b/src/ec/dell/mec5035/mec5035.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _EC_DELL_MEC5035_H_ +#define _EC_DELL_MEC5035_H_ + +#include <stdint.h> + +#define NUM_REGISTERS 32 + +/* Touchpad (TP) and mouse related. The EC seems to + default to 0 which results in the TP not working. */ +#define CMD_MOUSE_TP 0x1a +#define SERIAL_MOUSE 0 /* Disable TP, force use of a serial mouse */ +#define PS2_MOUSE 1 /* Disable TP when using a PS/2 mouse */ +#define TP_PS2_MOUSE 2 /* Leave TP enabled when using a PS/2 mouse */ + +#define CMD_CPU_OK 0xc2 + +u8 mec5035_mouse_touchpad(u8 setting); +void mec5035_cpu_ok(void); +void mec5035_early_init(void); + +#endif /* _EC_DELL_MEC5035_H_ */ |