diff --git a/src/board/system76/common/include/board/pmc.h b/src/board/system76/common/include/board/pmc.h index 02f7fdf..73032d6 100644 --- a/src/board/system76/common/include/board/pmc.h +++ b/src/board/system76/common/include/board/pmc.h @@ -7,6 +7,7 @@ void pmc_init(void); bool pmc_sci(struct Pmc * pmc, uint8_t sci); +void pmc_swi(void); void pmc_event(struct Pmc * pmc); #endif // _BOARD_PMC_H diff --git a/src/board/system76/common/pmc.c b/src/board/system76/common/pmc.c index 87b88a6..68bbc2c 100644 --- a/src/board/system76/common/pmc.c +++ b/src/board/system76/common/pmc.c @@ -5,6 +5,7 @@ #include #include #include +#include void pmc_init(void) { *(PMC_1.control) = 0x41; @@ -21,7 +22,20 @@ enum PmcState { 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 gpio_set(&SCI_N, false); *(SCI_N.control) = GPIO_OUT; @@ -35,6 +49,7 @@ void pmc_sci_interrupt(void) { // Delay T_HOLD (value assumed) delay_us(65); +#endif // EC_ESPI } bool pmc_sci(struct Pmc * pmc, uint8_t sci) { @@ -54,94 +69,125 @@ bool pmc_sci(struct Pmc * pmc, uint8_t sci) { } } -void pmc_event(struct Pmc * pmc) { - static enum PmcState state = PMC_STATE_DEFAULT; - static uint8_t state_data = 0; +void pmc_swi(void) { +#if EC_ESPI + // Use SCI interrupt + pmc_sci_interrupt(); +#else // EC_ESPI + // Start SWI interrupt + gpio_set(&SWI_N, false); - uint8_t sts = pmc_status(pmc); + // 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 uint8_t state_data = 0; + +static void pmc_on_input_command(struct Pmc * pmc, uint8_t data) { + 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, pmc_status(pmc) | (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, pmc_status(pmc) & ~(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, pmc_status(pmc) & ~(1 << 5)); + // Send SCI queue + state = PMC_STATE_WRITE; + state_data = pmc_sci_queue; + // Clear SCI queue + pmc_sci_queue = 0; + break; + } +} + +static void pmc_on_input_data(uint8_t data) { + 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; + } +} + +static void pmc_on_output_empty(struct Pmc * pmc) { + 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; + } +} + +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) { - 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; - } + pmc_on_input_command(pmc, data); } 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; - } + pmc_on_input_data(data); } } // Write data if possible + sts = pmc_status(pmc); 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; - } + pmc_on_output_empty(pmc); } }