Refactor SMFI interface and ectool

This commit is contained in:
Jeremy Soller
2020-09-25 19:41:38 -06:00
committed by Jeremy Soller
parent 39e2586c50
commit eff4caa752
19 changed files with 718 additions and 363 deletions

View File

@ -1,4 +1,17 @@
// SPDX-License-Identifier: GPL-3.0-only
//
// This defines a protocol for clients on the AP (application processor) to
// communicate with the EC. The protocol is polled, and uses semaphores to
// ensure correct sequencing.
//
// The client should check that the SMFI_CMD_CMD register is set to CMD_NONE,
// indicating that the EC is waiting for a command. The client should set the
// SMFI_CMD_DATA region as necessary for the command they wish to issue. They
// should then set the SMFI_CMD_CMD byte to indicate to the EC what command to
// execute. The EC will execute the command, and then set SMFI_CMD_RES to the
// correct result. It will finally set SMFI_CMD_CMD to CMD_NONE, to indicate
// the command is complete and the result is available. The client should only
// read the SMFI_CMD_RES value when SMFI_CMD_CMD is set to CMD_NONE.
#include <stdint.h>
#include <stdio.h>
@ -29,6 +42,14 @@ volatile uint8_t __xdata __at(0x105D) HRAMW0AAS;
volatile uint8_t __xdata __at(0x105E) HRAMW1AAS;
// Flash control register 3
volatile uint8_t __xdata __at(0x1063) FLHCTRL3;
// Host RAM window 2 base address
volatile uint8_t __xdata __at(0x1076) HRAMW2BA;
// Host RAM window 3 base address
volatile uint8_t __xdata __at(0x1077) HRAMW3BA;
// Host RAM window 2 access allow size
volatile uint8_t __xdata __at(0x1078) HRAMW2AAS;
// Host RAM window 3 access allow size
volatile uint8_t __xdata __at(0x1079) HRAMW3AAS;
// EC indirect flash access
volatile uint8_t __xdata __at(0x103B) ECINDAR0;
@ -37,12 +58,135 @@ volatile uint8_t __xdata __at(0x103D) ECINDAR2;
volatile uint8_t __xdata __at(0x103E) ECINDAR3;
volatile uint8_t __xdata __at(0x103F) ECINDDR;
// Command region - allows client to send commands to EC
#define SMFI_CMD_CMD 0x00
#define SMFI_CMD_RES 0x01
#define SMFI_CMD_DATA 0x02
static volatile uint8_t __xdata __at(0xE00) smfi_cmd[256];
// Debug region - ring buffer of EC firmware prints
#define SMFI_DBG_TAIL 0x00
static volatile uint8_t __xdata __at(0xF00) smfi_dbg[256];
#if !defined(__SCRATCH__)
void smfi_init(void) {
int i;
// Clear command region
for (i = (SMFI_CMD_CMD + 1); i < ARRAY_SIZE(smfi_cmd); i++) {
smfi_cmd[i] = 0x00;
}
// Clear host command last
smfi_cmd[SMFI_CMD_CMD] = 0x00;
// Clear debug region
for (i = (SMFI_DBG_TAIL + 1); i < ARRAY_SIZE(smfi_dbg); i++) {
smfi_dbg[i] = 0x00;
}
// Clear tail last
smfi_dbg[SMFI_DBG_TAIL] = 0x00;
// H2RAM window 0 address 0xE00 - 0xEFF, read/write
HRAMW0BA = 0xE0;
HRAMW0AAS = 0x04;
// H2RAM window 1 address 0xF00 - 0xFFF, read-only
HRAMW1BA = 0xF0;
HRAMW1AAS = 0x34;
// Enable H2RAM window 0 and 1 using LPC I/O
HRAMWC |= (1 << 4) | (1 << 1) | (1 << 0);
// Enable backup ROM access
FLHCTRL3 |= (1 << 3);
}
static enum Result cmd_print(void) {
uint8_t flags = smfi_cmd[SMFI_CMD_DATA];
uint8_t len = smfi_cmd[SMFI_CMD_DATA + 1];
uint8_t i;
for (i = 0; (i < len) && ((i + SMFI_CMD_DATA + 2) < ARRAY_SIZE(smfi_cmd)); i++) {
putchar(smfi_cmd[i + SMFI_CMD_DATA + 2]);
}
smfi_cmd[SMFI_CMD_DATA + 1] = i;
return RES_OK;
}
static enum Result cmd_fan_get(void) {
switch (smfi_cmd[SMFI_CMD_DATA]) {
case 0:
// Get duty of fan 0
smfi_cmd[SMFI_CMD_DATA + 1] = DCR2;
return RES_OK;
case 1:
// Get duty of fan 1
//TODO: only allow on platforms like addw2
smfi_cmd[SMFI_CMD_DATA + 1] = DCR4;
return RES_OK;
}
// Failed if fan not found
return RES_ERR;
}
static enum Result cmd_fan_set(void) {
switch (smfi_cmd[SMFI_CMD_DATA]) {
case 0:
// Set duty cycle of fan 0
DCR2 = smfi_cmd[SMFI_CMD_DATA + 1];
return RES_OK;
case 1:
// Set duty cycle of fan 1
//TODO: only allow on platforms like addw2
DCR4 = smfi_cmd[SMFI_CMD_DATA + 1];
return RES_OK;
}
// Failed if fan not found
return RES_ERR;
}
static enum Result cmd_keymap_get(void) {
int layer = smfi_cmd[SMFI_CMD_DATA];
int output = smfi_cmd[SMFI_CMD_DATA + 1];
int input = smfi_cmd[SMFI_CMD_DATA + 2];
if (layer < KM_LAY && output < KM_OUT && input < KM_IN) {
uint16_t key = KEYMAP[layer][output][input];
smfi_cmd[SMFI_CMD_DATA + 3] = (uint8_t)key;
smfi_cmd[SMFI_CMD_DATA + 4] = (uint8_t)(key >> 8);
return RES_OK;
}
// Failed if keyboard mapping not found
return RES_ERR;
}
static enum Result cmd_keymap_set(void) {
int layer = smfi_cmd[SMFI_CMD_DATA];
int output = smfi_cmd[SMFI_CMD_DATA + 1];
int input = smfi_cmd[SMFI_CMD_DATA + 2];
if (layer < KM_LAY && output < KM_OUT && input < KM_IN) {
uint16_t key =
((uint16_t)smfi_cmd[SMFI_CMD_DATA + 3]) |
(((uint16_t)smfi_cmd[SMFI_CMD_DATA + 4]) << 8);
KEYMAP[layer][output][input] = key;
return RES_OK;
}
// Failed if keyboard mapping not found
return RES_ERR;
}
#endif // !defined(__SCRATCH__)
#if defined(__SCRATCH__)
static enum Result cmd_spi_scratch(void) __critical {
uint8_t flags = smfi_cmd[2];
uint8_t len = smfi_cmd[3];
uint8_t flags = smfi_cmd[SMFI_CMD_DATA];
uint8_t len = smfi_cmd[SMFI_CMD_DATA + 1];
// Enable chip
if (flags & CMD_SPI_FLAG_BACKUP) {
@ -56,16 +200,16 @@ static enum Result cmd_spi_scratch(void) __critical {
// Read or write len bytes
uint8_t i;
for (i = 0; (i < len) && ((i + 4) < ARRAY_SIZE(smfi_cmd)); i++) {
for (i = 0; (i < len) && ((i + SMFI_CMD_DATA + 2) < ARRAY_SIZE(smfi_cmd)); i++) {
if (flags & CMD_SPI_FLAG_READ) {
smfi_cmd[i + 4] = ECINDDR;
smfi_cmd[i + SMFI_CMD_DATA + 2] = ECINDDR;
} else {
ECINDDR = smfi_cmd[i + 4];
ECINDDR = smfi_cmd[i + SMFI_CMD_DATA + 2];
}
}
// Set actually read/written count
smfi_cmd[3] = i;
smfi_cmd[SMFI_CMD_DATA + 1] = i;
if (flags & CMD_SPI_FLAG_DISABLE) {
// Disable chip
@ -75,65 +219,19 @@ static enum Result cmd_spi_scratch(void) __critical {
return RES_OK;
}
void smfi_init(void) {
int i;
// Clear command region
for (i = 1; i < ARRAY_SIZE(smfi_cmd); i++) {
smfi_cmd[i] = 0x00;
}
// Clear host command last
smfi_cmd[0] = 0x00;
// Clear debug region
for (i = 1; i < ARRAY_SIZE(smfi_dbg); i++) {
smfi_dbg[i] = 0x00;
}
// Clear tail last
smfi_dbg[0] = 0x00;
// H2RAM window 0 address 0xE00 - 0xEFF, read/write
HRAMW0BA = 0xE0;
HRAMW0AAS = 0x04;
// H2RAM window 1 address 0xF00 - 0xFFF, read/write
HRAMW1BA = 0xF0;
HRAMW1AAS = 0x04;
// Enable H2RAM window 0 and 1 using LPC I/O
HRAMWC |= 0x13;
// Enable backup ROM access
FLHCTRL3 |= (1 << 3);
}
static enum Result cmd_print(void) {
uint8_t flags = smfi_cmd[2];
uint8_t len = smfi_cmd[3];
uint8_t i;
for (i = 0; (i < len) && ((i + 4) < ARRAY_SIZE(smfi_cmd)); i++) {
putchar(smfi_cmd[i + 4]);
}
smfi_cmd[3] = i;
return RES_OK;
}
#endif // defined(__SCRATCH__)
static enum Result cmd_spi(void) {
#ifdef __SCRATCH__
#if defined(__SCRATCH__)
return cmd_spi_scratch();
#else
if (smfi_cmd[2] & CMD_SPI_FLAG_SCRATCH) {
#else // defined(__SCRATCH__)
if (smfi_cmd[SMFI_CMD_DATA] & CMD_SPI_FLAG_SCRATCH) {
scratch_trampoline();
}
// Cannot use follow mode unless running from scratch rom
return RES_ERR;
#endif
#endif // defined(__SCRATCH__)
}
static enum Result cmd_reset(void) {
@ -145,75 +243,6 @@ static enum Result cmd_reset(void) {
return RES_ERR;
}
#ifndef __SCRATCH__
static enum Result cmd_fan_get(void) {
switch (smfi_cmd[2]) {
case 0:
// Get duty of fan 0
smfi_cmd[3] = DCR2;
return RES_OK;
case 1:
// Get duty of fan 1
//TODO: only allow on platforms like addw2
smfi_cmd[3] = DCR4;
return RES_OK;
}
// Failed if fan not found
return RES_ERR;
}
static enum Result cmd_fan_set(void) {
switch (smfi_cmd[2]) {
case 0:
// Set duty cycle of fan 0
DCR2 = smfi_cmd[3];
return RES_OK;
case 1:
// Set duty cycle of fan 1
//TODO: only allow on platforms like addw2
DCR4 = smfi_cmd[3];
return RES_OK;
}
// Failed if fan not found
return RES_ERR;
}
static enum Result cmd_keymap_get(void) {
int layer = smfi_cmd[2];
int output = smfi_cmd[3];
int input = smfi_cmd[4];
if (layer < KM_LAY && output < KM_OUT && input < KM_IN) {
uint16_t key = KEYMAP[layer][output][input];
smfi_cmd[5] = (uint8_t)key;
smfi_cmd[6] = (uint8_t)(key >> 8);
return RES_OK;
}
// Failed if keyboard mapping not found
return RES_ERR;
}
static enum Result cmd_keymap_set(void) {
int layer = smfi_cmd[2];
int output = smfi_cmd[3];
int input = smfi_cmd[4];
if (layer < KM_LAY && output < KM_OUT && input < KM_IN) {
uint16_t key =
((uint16_t)smfi_cmd[5]) |
(((uint16_t)smfi_cmd[6]) << 8);
KEYMAP[layer][output][input] = key;
return RES_OK;
}
// Failed if keyboard mapping not found
return RES_ERR;
}
#endif
// Set a watchdog timer of 10 seconds
void smfi_watchdog(void) {
ET1CNTLLR = 0xFF;
@ -222,72 +251,73 @@ void smfi_watchdog(void) {
}
void smfi_event(void) {
if (smfi_cmd[0]) {
#ifdef __SCRATCH__
if (smfi_cmd[SMFI_CMD_CMD]) {
#if defined(__SCRATCH__)
// If in scratch ROM, restart watchdog timer when command received
smfi_watchdog();
#endif
switch (smfi_cmd[0]) {
switch (smfi_cmd[SMFI_CMD_CMD]) {
#if !defined(__SCRATCH__)
case CMD_PROBE:
// Signature
smfi_cmd[2] = 0x76;
smfi_cmd[3] = 0xEC;
smfi_cmd[SMFI_CMD_DATA + 0] = 0x76;
smfi_cmd[SMFI_CMD_DATA + 1] = 0xEC;
// Version
smfi_cmd[4] = 0x01;
smfi_cmd[SMFI_CMD_DATA + 2] = 0x01;
//TODO: bitmask of implemented commands?
// Always successful
smfi_cmd[1] = RES_OK;
smfi_cmd[SMFI_CMD_RES] = RES_OK;
break;
case CMD_BOARD:
strncpy(&smfi_cmd[2], board(), ARRAY_SIZE(smfi_cmd) - 2);
strncpy(&smfi_cmd[SMFI_CMD_DATA], board(), ARRAY_SIZE(smfi_cmd) - SMFI_CMD_DATA);
// Always successful
smfi_cmd[1] = RES_OK;
smfi_cmd[SMFI_CMD_RES] = RES_OK;
break;
case CMD_VERSION:
strncpy(&smfi_cmd[2], version(), ARRAY_SIZE(smfi_cmd) - 2);
strncpy(&smfi_cmd[SMFI_CMD_DATA], version(), ARRAY_SIZE(smfi_cmd) - SMFI_CMD_DATA);
// Always successful
smfi_cmd[1] = RES_OK;
smfi_cmd[SMFI_CMD_RES] = RES_OK;
break;
case CMD_PRINT:
smfi_cmd[1] = cmd_print();
smfi_cmd[SMFI_CMD_RES] = cmd_print();
break;
case CMD_SPI:
smfi_cmd[1] = cmd_spi();
break;
case CMD_RESET:
smfi_cmd[1] = cmd_reset();
break;
#ifndef __SCRATCH__
case CMD_FAN_GET:
smfi_cmd[1] = cmd_fan_get();
smfi_cmd[SMFI_CMD_RES] = cmd_fan_get();
break;
case CMD_FAN_SET:
smfi_cmd[1] = cmd_fan_set();
smfi_cmd[SMFI_CMD_RES] = cmd_fan_set();
break;
case CMD_KEYMAP_GET:
smfi_cmd[1] = cmd_keymap_get();
smfi_cmd[SMFI_CMD_RES] = cmd_keymap_get();
break;
case CMD_KEYMAP_SET:
smfi_cmd[1] = cmd_keymap_set();
smfi_cmd[SMFI_CMD_RES] = cmd_keymap_set();
break;
#endif // !defined(__SCRATCH__)
case CMD_SPI:
smfi_cmd[SMFI_CMD_RES] = cmd_spi();
break;
case CMD_RESET:
smfi_cmd[SMFI_CMD_RES] = cmd_reset();
break;
#endif // __SCRATCH__
default:
// Command not found
smfi_cmd[1] = RES_ERR;
smfi_cmd[SMFI_CMD_RES] = RES_ERR;
break;
}
// Mark command as finished
smfi_cmd[0] = CMD_NONE;
smfi_cmd[SMFI_CMD_CMD] = CMD_NONE;
}
}
void smfi_debug(unsigned char byte) {
int tail = (int)smfi_dbg[0];
int tail = (int)smfi_dbg[SMFI_DBG_TAIL];
tail++;
if (tail >= ARRAY_SIZE(smfi_dbg)) {
tail = 1;
tail = SMFI_DBG_TAIL + 1;
}
smfi_dbg[tail] = byte;
smfi_dbg[0] = (uint8_t)tail;
smfi_dbg[SMFI_DBG_TAIL] = (uint8_t)tail;
}