Files
system76-embedded-controller/src/board/system76/darp5/scratch/main.c
2020-02-24 14:08:16 -07:00

131 lines
3.0 KiB
C

#include <stdbool.h>
#include <stdint.h>
#include <scratch/pmc.h>
volatile uint8_t __xdata __at(0x103B) ECINDAR0;
volatile uint8_t __xdata __at(0x103C) ECINDAR1;
volatile uint8_t __xdata __at(0x103D) ECINDAR2;
volatile uint8_t __xdata __at(0x103E) ECINDAR3;
volatile uint8_t __xdata __at(0x103F) ECINDDR;
volatile uint8_t __xdata __at(0x1F01) ETWCFG;
volatile uint8_t __xdata __at(0x1F07) EWDKEYR;
uint8_t acpi_read(uint8_t addr) {
uint8_t data = 0;
switch (addr) {
case 4:
data = ECINDAR0;
break;
case 5:
data = ECINDAR1;
break;
case 6:
data = ECINDAR2;
break;
case 7:
data = ECINDAR3;
break;
case 8:
data = ECINDDR;
break;
}
return data;
}
void acpi_write(uint8_t addr, uint8_t data) {
switch (addr) {
case 4:
ECINDAR0 = data;
break;
case 5:
ECINDAR1 = data;
break;
case 6:
ECINDAR2 = data;
break;
case 7:
ECINDAR3 = data;
break;
case 8:
ECINDDR = data;
break;
}
}
enum PmcState {
PMC_STATE_DEFAULT,
PMC_STATE_WRITE,
PMC_STATE_ACPI_READ,
PMC_STATE_ACPI_WRITE,
PMC_STATE_ACPI_WRITE_ADDR,
};
void pmc_event(struct Pmc * pmc) {
static enum PmcState state = PMC_STATE_DEFAULT;
static uint8_t state_data = 0;
uint8_t sts = pmc_status(pmc);
// Read command/data if available
if (sts & PMC_STS_IBF) {
uint8_t data = pmc_read(pmc);
if (sts & PMC_STS_CMD) {
state = PMC_STATE_DEFAULT;
switch (data) {
case 0x80:
state = PMC_STATE_ACPI_READ;
break;
case 0x81:
state = PMC_STATE_ACPI_WRITE;
break;
case 0xEC:
for (;;) {
// Attempt to trigger watchdog reset
ETWCFG |= (1 << 5);
EWDKEYR = 0;
}
break;
}
} else {
switch (state) {
case PMC_STATE_ACPI_READ:
state = PMC_STATE_WRITE;
state_data = acpi_read(data);
break;
case PMC_STATE_ACPI_WRITE:
state = PMC_STATE_ACPI_WRITE_ADDR;
state_data = data;
break;
case PMC_STATE_ACPI_WRITE_ADDR:
state = PMC_STATE_DEFAULT;
acpi_write(state_data, data);
break;
default:
state = PMC_STATE_DEFAULT;
break;
}
}
}
// Write data if possible
if (!(sts & PMC_STS_OBF)) {
switch (state) {
case PMC_STATE_WRITE:
state = PMC_STATE_DEFAULT;
pmc_write(pmc, state_data);
break;
}
}
}
// Main program while running in scratch ROM
void main(void) {
for (;;) {
pmc_event(&PMC_3);
}
}