diff options
Diffstat (limited to 'src/ec')
-rw-r--r-- | src/ec/system76/ec/Makefile.inc | 6 | ||||
-rw-r--r-- | src/ec/system76/ec/system76_ec.c | 61 |
2 files changed, 67 insertions, 0 deletions
diff --git a/src/ec/system76/ec/Makefile.inc b/src/ec/system76/ec/Makefile.inc new file mode 100644 index 0000000000..382daa6581 --- /dev/null +++ b/src/ec/system76/ec/Makefile.inc @@ -0,0 +1,6 @@ +ifeq ($(CONFIG_EC_SYSTEM76_EC),y) + +all-y += system76_ec.c +smm-$(CONFIG_DEBUG_SMI) += system76_ec.c + +endif diff --git a/src/ec/system76/ec/system76_ec.c b/src/ec/system76/ec/system76_ec.c new file mode 100644 index 0000000000..ddcb602d4c --- /dev/null +++ b/src/ec/system76/ec/system76_ec.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <arch/io.h> +#include <console/system76_ec.h> +#include <timer.h> + +// This is the command region for System76 EC firmware. It must be +// enabled for LPC in the mainboard. +#define SYSTEM76_EC_BASE 0x0E00 +#define SYSTEM76_EC_SIZE 256 + +#define REG_CMD 0 +#define REG_RESULT 1 + +// When command register is 0, command is complete +#define CMD_FINISHED 0 + +// Print command. Registers are unique for each command +#define CMD_PRINT 4 +#define CMD_PRINT_REG_FLAGS 2 +#define CMD_PRINT_REG_LEN 3 +#define CMD_PRINT_REG_DATA 4 + +static inline uint8_t system76_ec_read(uint8_t addr) +{ + return inb(SYSTEM76_EC_BASE + (uint16_t)addr); +} + +static inline void system76_ec_write(uint8_t addr, uint8_t data) +{ + outb(data, SYSTEM76_EC_BASE + (uint16_t)addr); +} + +void system76_ec_init(void) +{ + // Clear entire command region + for (int i = 0; i < SYSTEM76_EC_SIZE; i++) + system76_ec_write((uint8_t)i, 0); +} + +void system76_ec_flush(void) +{ + system76_ec_write(REG_CMD, CMD_PRINT); + + // Wait for command completion, for up to 10 milliseconds, with a + // test period of 1 microsecond + wait_us(10000, system76_ec_read(REG_CMD) == CMD_FINISHED); + + system76_ec_write(CMD_PRINT_REG_LEN, 0); +} + +void system76_ec_print(uint8_t byte) +{ + uint8_t len = system76_ec_read(CMD_PRINT_REG_LEN); + system76_ec_write(CMD_PRINT_REG_DATA + len, byte); + system76_ec_write(CMD_PRINT_REG_LEN, len + 1); + + // If we hit the end of the buffer, or were given a newline, flush + if (byte == '\n' || len >= (SYSTEM76_EC_SIZE - CMD_PRINT_REG_DATA)) + system76_ec_flush(); +} |