Refactor SMFI interface and ectool
This commit is contained in:
committed by
Jeremy Soller
parent
39e2586c50
commit
eff4caa752
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user