diff options
-rw-r--r-- | src/console/Kconfig | 7 | ||||
-rw-r--r-- | src/console/console.c | 4 | ||||
-rw-r--r-- | src/ec/system76/ec/Makefile.inc | 6 | ||||
-rw-r--r-- | src/ec/system76/ec/system76_ec.c | 61 | ||||
-rw-r--r-- | src/include/console/system76_ec.h | 35 |
5 files changed, 113 insertions, 0 deletions
diff --git a/src/console/Kconfig b/src/console/Kconfig index 7c6e9bc5e0..bad6c564fc 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -302,6 +302,13 @@ config SPI_CONSOLE This is currently working only in ramstage due to how the spi drivers are written. +config CONSOLE_SYSTEM76_EC + bool "System76 EC console output" + default n + depends on EC_SYSTEM76_EC + help + Send coreboot debug output to a System76 embedded controller. + config CONSOLE_OVERRIDE_LOGLEVEL bool help diff --git a/src/console/console.c b/src/console/console.c index bc9d9183a0..2f544a80f2 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -9,6 +9,7 @@ #include <console/usb.h> #include <console/spi.h> #include <console/flash.h> +#include <console/system76_ec.h> void console_hw_init(void) { @@ -21,6 +22,7 @@ void console_hw_init(void) __usbdebug_init(); __spiconsole_init(); __flashconsole_init(); + __system76_ec_init(); } void console_tx_byte(unsigned char byte) @@ -42,6 +44,7 @@ void console_tx_byte(unsigned char byte) __usb_tx_byte(byte); __spiconsole_tx_byte(byte); __flashconsole_tx_byte(byte); + __system76_ec_tx_byte(byte); } void console_tx_flush(void) @@ -50,6 +53,7 @@ void console_tx_flush(void) __ne2k_tx_flush(); __usb_tx_flush(); __flashconsole_tx_flush(); + __system76_ec_tx_flush(); } void console_write_line(uint8_t *buffer, size_t number_of_bytes) 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(); +} diff --git a/src/include/console/system76_ec.h b/src/include/console/system76_ec.h new file mode 100644 index 0000000000..616e46f4a2 --- /dev/null +++ b/src/include/console/system76_ec.h @@ -0,0 +1,35 @@ +#ifndef CONSOLE_SYSTEM76_EC_H +#define CONSOLE_SYSTEM76_EC_H 1 + +#include <stddef.h> +#include <stdint.h> + +void system76_ec_init(void); +void system76_ec_flush(void); +void system76_ec_print(uint8_t byte); + +#define __CONSOLE_SYSTEM76_EC_ENABLE__ (CONFIG(CONSOLE_SYSTEM76_EC) && \ + (ENV_BOOTBLOCK || ENV_ROMSTAGE || ENV_RAMSTAGE \ + || ENV_SEPARATE_VERSTAGE || ENV_POSTCAR \ + || (ENV_SMM && CONFIG(DEBUG_SMI)))) + +#if __CONSOLE_SYSTEM76_EC_ENABLE__ +static inline void __system76_ec_init(void) +{ + system76_ec_init(); +} +static inline void __system76_ec_tx_flush(void) +{ + system76_ec_flush(); +} +static inline void __system76_ec_tx_byte(unsigned char byte) +{ + system76_ec_print(byte); +} +#else +static inline void __system76_ec_init(void) {} +static inline void __system76_ec_tx_flush(void) {} +static inline void __system76_ec_tx_byte(unsigned char byte) {} +#endif + +#endif |