Files
system76-embedded-controller/src/board/system76/galp3-c/pmc.c
Jeremy Soller 657437e1ce Faster flashing with SMFI (#32)
* WIP: support for new flashing API

* Add SPI flashing support to tool

* Add timeouts when flashing with ectool

* Test SPI reading

* Use chunks for SPI commands

* Sanity test of flash size

* Read rom in sectors

* Relocate memmap region, remove PMC3

* Use ectool to flash

* Remove debugging of spi command

* Fix flashing over smfi
2020-02-26 09:04:40 -07:00

146 lines
3.9 KiB
C

#include <arch/delay.h>
#include <board/acpi.h>
#include <board/gpio.h>
#include <board/pmc.h>
#include <common/debug.h>
void pmc_init(void) {
*(PMC_1.control) = 0x41;
*(PMC_2.control) = 0x41;
}
enum PmcState {
PMC_STATE_DEFAULT,
PMC_STATE_WRITE,
PMC_STATE_ACPI_READ,
PMC_STATE_ACPI_WRITE,
PMC_STATE_ACPI_WRITE_ADDR,
};
static uint8_t pmc_sci_queue = 0;
void pmc_sci_interrupt(void) {
// Start SCI interrupt
gpio_set(&SCI_N, false);
*(SCI_N.control) = GPIO_OUT;
// Delay T_HOLD (value assumed)
delay_us(65);
// Stop SCI interrupt
*(SCI_N.control) = GPIO_IN;
gpio_set(&SCI_N, true);
// Delay T_HOLD (value assumed)
delay_us(65);
}
bool pmc_sci(struct Pmc * pmc, uint8_t sci) {
// Set SCI queue if possible
if (pmc_sci_queue == 0) {
pmc_sci_queue = sci;
// Set SCI pending bit
pmc_set_status(pmc, pmc_status(pmc) | (1 << 5));
// Send SCI
pmc_sci_interrupt();
return true;
} else {
return false;
}
}
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) {
TRACE("pmc cmd: %02X\n", data);
state = PMC_STATE_DEFAULT;
switch (data) {
case 0x80:
state = PMC_STATE_ACPI_READ;
// Send SCI for IBF=0
pmc_sci_interrupt();
break;
case 0x81:
state = PMC_STATE_ACPI_WRITE;
// Send SCI for IBF=0
pmc_sci_interrupt();
break;
case 0x82:
TRACE(" burst enable\n");
// Set burst bit
pmc_set_status(pmc, sts | (1 << 4));
// Send acknowledgement byte
state = PMC_STATE_WRITE;
state_data = 0x90;
break;
case 0x83:
TRACE(" burst disable\n");
// Clear burst bit
pmc_set_status(pmc, sts & ~(1 << 4));
// Send SCI for IBF=0
pmc_sci_interrupt();
break;
case 0x84:
TRACE(" SCI queue\n");
// Clear SCI pending bit
pmc_set_status(pmc, sts & ~(1 << 5));
// Send SCI queue
state = PMC_STATE_WRITE;
state_data = pmc_sci_queue;
// Clear SCI queue
pmc_sci_queue = 0;
break;
}
} else {
TRACE("pmc data: %02X\n", data);
switch (state) {
case PMC_STATE_ACPI_READ:
// Send byte from ACPI space
state = PMC_STATE_WRITE;
state_data = acpi_read(data);
break;
case PMC_STATE_ACPI_WRITE:
state = PMC_STATE_ACPI_WRITE_ADDR;
state_data = data;
// Send SCI for IBF=0
pmc_sci_interrupt();
break;
case PMC_STATE_ACPI_WRITE_ADDR:
state = PMC_STATE_DEFAULT;
acpi_write(state_data, data);
// Send SCI for IBF=0
pmc_sci_interrupt();
break;
default:
state = PMC_STATE_DEFAULT;
break;
}
}
}
// Write data if possible
if (!(sts & PMC_STS_OBF)) {
switch (state) {
case PMC_STATE_WRITE:
TRACE("pmc write: %02X\n", state_data);
state = PMC_STATE_DEFAULT;
pmc_write(pmc, state_data);
// Send SCI for OBF=1
pmc_sci_interrupt();
break;
}
}
}