system76/common/pmc: Refactor to improve readability and support ESPI

This commit is contained in:
Jeremy Soller
2020-12-29 10:11:24 -07:00
committed by Jeremy Soller
parent 99a0d6861f
commit 3f41cd6ab3
2 changed files with 125 additions and 78 deletions

View File

@ -7,6 +7,7 @@
void pmc_init(void); void pmc_init(void);
bool pmc_sci(struct Pmc * pmc, uint8_t sci); bool pmc_sci(struct Pmc * pmc, uint8_t sci);
void pmc_swi(void);
void pmc_event(struct Pmc * pmc); void pmc_event(struct Pmc * pmc);
#endif // _BOARD_PMC_H #endif // _BOARD_PMC_H

View File

@ -5,6 +5,7 @@
#include <board/gpio.h> #include <board/gpio.h>
#include <board/pmc.h> #include <board/pmc.h>
#include <common/debug.h> #include <common/debug.h>
#include <ec/espi.h>
void pmc_init(void) { void pmc_init(void) {
*(PMC_1.control) = 0x41; *(PMC_1.control) = 0x41;
@ -21,7 +22,20 @@ enum PmcState {
static uint8_t pmc_sci_queue = 0; static uint8_t pmc_sci_queue = 0;
void pmc_sci_interrupt(void) { static void pmc_sci_interrupt(void) {
#if EC_ESPI
// Start SCI interrupt
vw_set(&VW_SCI_N, VWS_LOW);
// Delay T_HOLD (value assumed)
delay_us(65);
// Stop SCI interrupt
vw_set(&VW_SCI_N, VWS_HIGH);
// Delay T_HOLD (value assumed)
delay_us(65);
#else // EC_ESPI
// Start SCI interrupt // Start SCI interrupt
gpio_set(&SCI_N, false); gpio_set(&SCI_N, false);
*(SCI_N.control) = GPIO_OUT; *(SCI_N.control) = GPIO_OUT;
@ -35,6 +49,7 @@ void pmc_sci_interrupt(void) {
// Delay T_HOLD (value assumed) // Delay T_HOLD (value assumed)
delay_us(65); delay_us(65);
#endif // EC_ESPI
} }
bool pmc_sci(struct Pmc * pmc, uint8_t sci) { bool pmc_sci(struct Pmc * pmc, uint8_t sci) {
@ -54,18 +69,30 @@ bool pmc_sci(struct Pmc * pmc, uint8_t sci) {
} }
} }
void pmc_event(struct Pmc * pmc) { void pmc_swi(void) {
#if EC_ESPI
// Use SCI interrupt
pmc_sci_interrupt();
#else // EC_ESPI
// Start SWI interrupt
gpio_set(&SWI_N, false);
// Delay T_HOLD (value assumed)
delay_us(65);
// Stop SWI interrupt
gpio_set(&SWI_N, true);
// Delay T_HOLD (value assumed)
delay_us(65);
#endif // EC_ESPI
}
static enum PmcState state = PMC_STATE_DEFAULT; static enum PmcState state = PMC_STATE_DEFAULT;
static uint8_t state_data = 0; static uint8_t state_data = 0;
uint8_t sts = pmc_status(pmc); static void pmc_on_input_command(struct Pmc * pmc, uint8_t data) {
// 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); TRACE("pmc cmd: %02X\n", data);
state = PMC_STATE_DEFAULT; state = PMC_STATE_DEFAULT;
switch (data) { switch (data) {
case 0x80: case 0x80:
@ -81,7 +108,7 @@ void pmc_event(struct Pmc * pmc) {
case 0x82: case 0x82:
TRACE(" burst enable\n"); TRACE(" burst enable\n");
// Set burst bit // Set burst bit
pmc_set_status(pmc, sts | (1 << 4)); pmc_set_status(pmc, pmc_status(pmc) | (1 << 4));
// Send acknowledgement byte // Send acknowledgement byte
state = PMC_STATE_WRITE; state = PMC_STATE_WRITE;
state_data = 0x90; state_data = 0x90;
@ -89,14 +116,14 @@ void pmc_event(struct Pmc * pmc) {
case 0x83: case 0x83:
TRACE(" burst disable\n"); TRACE(" burst disable\n");
// Clear burst bit // Clear burst bit
pmc_set_status(pmc, sts & ~(1 << 4)); pmc_set_status(pmc, pmc_status(pmc) & ~(1 << 4));
// Send SCI for IBF=0 // Send SCI for IBF=0
pmc_sci_interrupt(); pmc_sci_interrupt();
break; break;
case 0x84: case 0x84:
TRACE(" SCI queue\n"); TRACE(" SCI queue\n");
// Clear SCI pending bit // Clear SCI pending bit
pmc_set_status(pmc, sts & ~(1 << 5)); pmc_set_status(pmc, pmc_status(pmc) & ~(1 << 5));
// Send SCI queue // Send SCI queue
state = PMC_STATE_WRITE; state = PMC_STATE_WRITE;
state_data = pmc_sci_queue; state_data = pmc_sci_queue;
@ -104,9 +131,10 @@ void pmc_event(struct Pmc * pmc) {
pmc_sci_queue = 0; pmc_sci_queue = 0;
break; break;
} }
} else { }
TRACE("pmc data: %02X\n", data);
static void pmc_on_input_data(uint8_t data) {
TRACE("pmc data: %02X\n", data);
switch (state) { switch (state) {
case PMC_STATE_ACPI_READ: case PMC_STATE_ACPI_READ:
// Send byte from ACPI space // Send byte from ACPI space
@ -130,10 +158,8 @@ void pmc_event(struct Pmc * pmc) {
break; break;
} }
} }
}
// Write data if possible static void pmc_on_output_empty(struct Pmc * pmc) {
if (!(sts & PMC_STS_OBF)) {
switch (state) { switch (state) {
case PMC_STATE_WRITE: case PMC_STATE_WRITE:
TRACE("pmc write: %02X\n", state_data); TRACE("pmc write: %02X\n", state_data);
@ -144,4 +170,24 @@ void pmc_event(struct Pmc * pmc) {
break; break;
} }
} }
void pmc_event(struct Pmc * pmc) {
uint8_t sts;
// Read command/data if available
sts = pmc_status(pmc);
if (sts & PMC_STS_IBF) {
uint8_t data = pmc_read(pmc);
if (sts & PMC_STS_CMD) {
pmc_on_input_command(pmc, data);
} else {
pmc_on_input_data(data);
}
}
// Write data if possible
sts = pmc_status(pmc);
if (!(sts & PMC_STS_OBF)) {
pmc_on_output_empty(pmc);
}
} }