diff --git a/src/board/system76/darp5/acpi.c b/src/board/system76/darp5/acpi.c index e42f6ae..33229f1 100644 --- a/src/board/system76/darp5/acpi.c +++ b/src/board/system76/darp5/acpi.c @@ -1,11 +1,26 @@ #include #include +#include #include #include -#include extern bool lid_wake; +extern uint8_t sci_extra; + +uint8_t fcmd = 0; +uint8_t fdat = 0; +uint8_t fbuf[4] = { 0, 0, 0, 0 }; + +void fcommand(void) { + switch (fcmd) { + // Keyboard backlight + case 0xCA: + // TODO + break; + } +} + uint8_t acpi_read(uint8_t addr) { uint8_t data = 0; @@ -57,6 +72,8 @@ uint8_t acpi_read(uint8_t addr) { ACPI_16(0x2E, battery_remaining_capacity); ACPI_16(0x32, battery_voltage); + ACPI_8(0xCC, sci_extra); + // Airplane mode LED case 0xD9: if (!gpio_get(&LED_AIRPLANE_N)) { @@ -66,6 +83,13 @@ uint8_t acpi_read(uint8_t addr) { // Set size of flash (from old firmware) ACPI_8 (0xE5, 0x80); + + ACPI_8 (0xF8, fcmd); + ACPI_8 (0xF9, fdat); + ACPI_8 (0xFA, fbuf[0]); + ACPI_8 (0xFB, fbuf[1]); + ACPI_8 (0xFC, fbuf[2]); + ACPI_8 (0xFD, fbuf[3]); } DEBUG("acpi_read %02X = %02X\n", addr, data); @@ -86,5 +110,25 @@ void acpi_write(uint8_t addr, uint8_t data) { case 0xD9: gpio_set(&LED_AIRPLANE_N, !(bool)(data & (1 << 6))); break; + + case 0xF8: + fcmd = data; + fcommand(); + break; + case 0xF9: + fdat = data; + break; + case 0xFA: + fbuf[0] = data; + break; + case 0xFB: + fbuf[1] = data; + break; + case 0xFC: + fbuf[2] = data; + break; + case 0xFD: + fbuf[3] = data; + break; } } diff --git a/src/board/system76/darp5/include/board/keymap.h b/src/board/system76/darp5/include/board/keymap.h index eacd404..b671426 100644 --- a/src/board/system76/darp5/include/board/keymap.h +++ b/src/board/system76/darp5/include/board/keymap.h @@ -3,6 +3,11 @@ #include +// Extra SCI layer for keyboard backlight control +#define KT_SCI_EXTRA (0x4000) + +#define SCI_EXTRA (0x50) + #define ___ 0 // Conversion of physical layout to keyboard matrix diff --git a/src/board/system76/darp5/kbscan.c b/src/board/system76/darp5/kbscan.c index 12af49e..617fafc 100644 --- a/src/board/system76/darp5/kbscan.c +++ b/src/board/system76/darp5/kbscan.c @@ -10,6 +10,8 @@ bool kbscan_enabled = false; +uint8_t sci_extra = 0; + void kbscan_init(void) { KSOCTRL = 0x05; KSICTRLR = 0x04; @@ -107,9 +109,27 @@ void kbscan_event(void) { if (new_b) layer = 1; else layer = 0; break; + case (KT_SCI_EXTRA): + if (new_b) { + uint8_t sci = SCI_EXTRA; + sci_extra = (uint8_t)(key & 0xFF); + if (!pmc_sci(&PMC_1, sci)) { + // In the case of ignored SCI, reset bit + new &= ~(1 << j); + } + } + break; case (KT_SCI): if (new_b) { uint8_t sci = (uint8_t)(key & 0xFF); + + // HACK FOR HARDWARE HOTKEYS + switch (sci) { + case SCI_CAMERA_TOGGLE: + gpio_set(&CCD_EN, !gpio_get(&CCD_EN)); + break; + } + if (!pmc_sci(&PMC_1, sci)) { // In the case of ignored SCI, reset bit new &= ~(1 << j); diff --git a/src/board/system76/darp5/keymap/default.c b/src/board/system76/darp5/keymap/default.c index a41bc46..a1b2b51 100644 --- a/src/board/system76/darp5/keymap/default.c +++ b/src/board/system76/darp5/keymap/default.c @@ -12,7 +12,7 @@ LAYOUT( K_LEFT_CTRL, KT_FN, K_LEFT_SUPER, K_LEFT_ALT, K_SPACE, K_RIGHT_ALT, K_APP, K_RIGHT_CTRL, K_LEFT, K_DOWN, K_RIGHT, K_NUM_0, K_NUM_PERIOD ), LAYOUT( - K_ESC, K_TOUCHPAD, K_F2, K_MUTE, K_F4, K_VOLUME_DOWN, K_VOLUME_UP, K_F7, KT_SCI | SCI_BRIGHTNESS_DOWN, KT_SCI | SCI_BRIGHTNESS_UP, K_F10, KT_SCI | SCI_AIRPLANE_MODE, KT_SCI | SCI_SUSPEND, 0 /*prtsc*/, K_INSERT, K_DEL, K_HOME, K_END, K_PGUP, K_PGDN, + K_ESC, K_TOUCHPAD, K_F2, K_MUTE, K_F4, K_VOLUME_DOWN, K_VOLUME_UP, K_F7, KT_SCI | SCI_BRIGHTNESS_DOWN, KT_SCI | SCI_BRIGHTNESS_UP, KT_SCI | SCI_CAMERA_TOGGLE, KT_SCI | SCI_AIRPLANE_MODE, KT_SCI | SCI_SUSPEND, 0 /*prtsc*/, K_INSERT, K_DEL, K_HOME, K_END, K_PGUP, K_PGDN, K_PLAY_PAUSE, K_1, K_2, K_3, K_4, K_5, K_6, K_7, K_8, K_9, K_0, K_MINUS, K_EQUALS, K_BKSP, K_NUM_LOCK, K_NUM_SLASH, K_NUM_ASTERISK, K_NUM_MINUS, K_TAB, K_Q, K_W, K_E, K_R, K_T, K_Y, K_U, K_I, K_O, K_P, K_BRACE_OPEN, K_BRACE_CLOSE, K_BACKSLASH, K_NUM_7, K_NUM_8, K_NUM_9, K_NUM_PLUS, K_CAPS, K_A, K_S, K_D, K_F, K_G, K_H, K_J, K_K, K_L, K_SEMICOLON, K_QUOTE, K_ENTER, K_NUM_4, K_NUM_5, K_NUM_6, diff --git a/src/board/system76/darp5/main.c b/src/board/system76/darp5/main.c index 996092f..18322d4 100644 --- a/src/board/system76/darp5/main.c +++ b/src/board/system76/darp5/main.c @@ -46,12 +46,13 @@ void timer_2(void) __interrupt(5) { void init(void) { gpio_init(); gctrl_init(); - kbc_init(); - pmc_init(); - kbscan_init(); pwm_init(); - smbus_init(); + + kbc_init(); + kbscan_init(); + pmc_init(); peci_init(); + smbus_init(); //TODO: INTC } diff --git a/src/board/system76/darp5/peci.c b/src/board/system76/darp5/peci.c index 93802aa..145d8f6 100644 --- a/src/board/system76/darp5/peci.c +++ b/src/board/system76/darp5/peci.c @@ -12,9 +12,6 @@ int16_t peci_offset = 0; int16_t peci_temp = 0; uint8_t peci_duty = 0; -uint8_t peci_tcontrol = 0; -uint8_t peci_tjmax = T_JUNCTION; -static bool peci_config_loaded = false; #define PECI_TEMP(X) (((int16_t)(X)) << 6) #define PWM_DUTY(X) ((uint8_t)(((((uint16_t)(X)) * 255) + 99) / 100)) @@ -78,55 +75,6 @@ void peci_init(void) { PADCTLR = 0x02; } -// Read tjmax using index 16 of RdPkgConfig -static void peci_config(void) { - // Wait for completion - while (HOSTAR & 1) {} - // Clear status - HOSTAR = HOSTAR; - - // Enable PECI, clearing data fifo's - HOCTLR = (1 << 5) | (1 << 3); - // Set address to default - HOTRADDR = 0x30; - // Set write length - HOWRLR = 5; - // Set read length - HORDLR = 5; - // Set command - HOCMDR = 0xA1; - // Set Host ID ? - HOWRDR = 0x00; - // Set index - HOWRDR = 16; - // Set parameter - HOWRDR = 0; - HOWRDR = 0; - // Start transaction - HOCTLR |= 1; - - // Wait for completion - while (HOSTAR & 1) {} - - if (HOSTAR & (1 << 1)) { - // Use result if finished successfully - - //TODO: check completion code - uint8_t data = HOWRDR; - - // Throw away reserved byte - data = HOWRDR; - // Tead tcontrol for now - peci_tcontrol = HOWRDR; - // Read tjmax - peci_tjmax = HOWRDR; - // Throw away reserved byte - data = HOWRDR; - - peci_config_loaded = true; - } -} - // PECI information can be found here: https://www.intel.com/content/dam/www/public/us/en/documents/design-guides/core-i7-lga-2011-guide.pdf void peci_event(void) { // Wait for completion @@ -156,12 +104,6 @@ void peci_event(void) { uint8_t high = HORDDR; peci_offset = ((int16_t)high << 8) | (int16_t)low; - // TODO: Update max value if possible - // if (!peci_config_loaded) { - // peci_config(); - // } - - // TODO: tjmax peci_temp = PECI_TEMP(T_JUNCTION) + peci_offset; peci_duty = fan_duty(peci_temp); } else { diff --git a/src/board/system76/darp5/pmc.c b/src/board/system76/darp5/pmc.c index 8710fda..1af0a33 100644 --- a/src/board/system76/darp5/pmc.c +++ b/src/board/system76/darp5/pmc.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -20,88 +21,125 @@ enum PmcState { static uint8_t pmc_sci_queue = 0; -bool pmc_sci(struct Pmc * pmc, uint8_t sci) { - bool update = pmc_sci_queue == 0; - // Set SCI queue if possible - if (update) pmc_sci_queue = sci; - // Set SCI pending bit - uint8_t sts = pmc_status(pmc); - pmc_set_status(pmc, sts | (1 << 5)); +void pmc_sci_interrupt(void) { // Start SCI interrupt gpio_set(&SCI_N, false); - *(SCI_N.control) = 0x40; - return update; + *(SCI_N.control) = GPIO_OUT; + + // Delay T_HOLD (value assumed) + delay_us(1); + + // Stop SCI interrupt + *(SCI_N.control) = GPIO_IN; + gpio_set(&SCI_N, true); +} + +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[2] = {0, 0}; + static uint8_t state_data = 0; - uint8_t sts = pmc_status(pmc); - if (sts & PMC_STS_IBF) { - uint8_t data = pmc_read(pmc); - if (sts & PMC_STS_CMD) { - DEBUG("pmc cmd: %02X\n", data); + uint8_t burst_timeout; + for (burst_timeout = 1; burst_timeout > 0; burst_timeout--) { + uint8_t sts = pmc_status(pmc); + if (sts & PMC_STS_IBF) { + uint8_t data = pmc_read(pmc); + if (sts & PMC_STS_CMD) { + DEBUG("pmc cmd: %02X\n", data); - state = PMC_STATE_DEFAULT; - switch (data) { - case 0x80: - state = PMC_STATE_ACPI_READ; - break; - case 0x81: - state = PMC_STATE_ACPI_WRITE; - break; - case 0x82: - DEBUG(" burst enable\n"); - // Set burst bit - pmc_set_status(pmc, sts | (1 << 4)); - // Send acknowledgement byte - pmc_write(pmc, 0x90, PMC_TIMEOUT); - break; - case 0x83: - DEBUG(" burst disable\n"); - // Clear burst bit - pmc_set_status(pmc, sts & ~(1 << 4)); - break; - case 0x84: - DEBUG(" SCI queue\n"); - // Clear SCI pending bit - pmc_set_status(pmc, sts & ~(1 << 5)); - // Send SCI queue - pmc_write(pmc, pmc_sci_queue, PMC_TIMEOUT); - // Stop SCI interrupt - *(SCI_N.control) = 0x80; - gpio_set(&SCI_N, true); - // Clear SCI queue - pmc_sci_queue = 0; - break; - - case 0xEC: - DEBUG(" scratch rom\n"); - pmc_write(pmc, 0x76, PMC_TIMEOUT); - scratch_trampoline(); - break; - } - } else { - DEBUG("pmc data: %02X\n", data); - - switch (state) { - case PMC_STATE_ACPI_READ: state = PMC_STATE_DEFAULT; - uint8_t value = acpi_read(data); - pmc_write(pmc, value, PMC_TIMEOUT); - break; - case PMC_STATE_ACPI_WRITE: - state = PMC_STATE_ACPI_WRITE_ADDR; - state_data[0] = data; - break; - case PMC_STATE_ACPI_WRITE_ADDR: - state = PMC_STATE_DEFAULT; - acpi_write(state_data[0], data); - break; - default: - state = PMC_STATE_DEFAULT; - break; + 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: + DEBUG(" burst enable\n"); + // Run pmc_event in a tight loop for more iterations + burst_timeout = 100; + // Set burst bit + pmc_set_status(pmc, sts | (1 << 4)); + // Send acknowledgement byte + pmc_write(pmc, 0x90, PMC_TIMEOUT); + // Send SCI for OBF=1 + pmc_sci_interrupt(); + break; + case 0x83: + DEBUG(" burst disable\n"); + // Exit pmc_event tight loop + burst_timeout = 0; + // Clear burst bit + pmc_set_status(pmc, sts & ~(1 << 4)); + // Send SCI for IBF=0 + pmc_sci_interrupt(); + break; + case 0x84: + DEBUG(" SCI queue\n"); + // Clear SCI pending bit + pmc_set_status(pmc, sts & ~(1 << 5)); + // Send SCI queue + pmc_write(pmc, pmc_sci_queue, PMC_TIMEOUT); + // Clear SCI queue + pmc_sci_queue = 0; + // Send SCI for OBF=1 + pmc_sci_interrupt(); + break; + + case 0xEC: + DEBUG(" scratch rom\n"); + pmc_write(pmc, 0x76, PMC_TIMEOUT); + scratch_trampoline(); + break; + } + } else { + DEBUG("pmc data: %02X\n", data); + + switch (state) { + case PMC_STATE_ACPI_READ: + state = PMC_STATE_DEFAULT; + state_data = acpi_read(data); + pmc_write(pmc, state_data, PMC_TIMEOUT); + // Send SCI for OBF=1 + pmc_sci_interrupt(); + 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; + } } } } diff --git a/src/board/system76/lemp9/acpi.c b/src/board/system76/lemp9/acpi.c index 85d5fda..a8968cd 100644 --- a/src/board/system76/lemp9/acpi.c +++ b/src/board/system76/lemp9/acpi.c @@ -1,11 +1,36 @@ #include #include +#include +#include #include #include -#include extern bool lid_wake; +extern uint8_t sci_extra; + +uint8_t fcmd = 0; +uint8_t fdat = 0; +uint8_t fbuf[4] = { 0, 0, 0, 0 }; + +void fcommand(void) { + switch (fcmd) { + // Keyboard backlight + case 0xCA: + switch (fdat) { + // Set white LED brightness + case 0x00: + DACDAT2 = fbuf[0]; + break; + // Get white LED brightness + case 0x01: + fbuf[0] = DACDAT2; + break; + } + break; + } +} + uint8_t acpi_read(uint8_t addr) { uint8_t data = 0; @@ -57,8 +82,17 @@ uint8_t acpi_read(uint8_t addr) { ACPI_16(0x2E, battery_remaining_capacity); ACPI_16(0x32, battery_voltage); + ACPI_8(0xCC, sci_extra); + // Set size of flash (from old firmware) ACPI_8 (0xE5, 0x80); + + ACPI_8 (0xF8, fcmd); + ACPI_8 (0xF9, fdat); + ACPI_8 (0xFA, fbuf[0]); + ACPI_8 (0xFB, fbuf[1]); + ACPI_8 (0xFC, fbuf[2]); + ACPI_8 (0xFD, fbuf[3]); } DEBUG("acpi_read %02X = %02X\n", addr, data); @@ -74,5 +108,25 @@ void acpi_write(uint8_t addr, uint8_t data) { case 0x03: lid_wake = (bool)(data & (1 << 2)); break; + + case 0xF8: + fcmd = data; + fcommand(); + break; + case 0xF9: + fdat = data; + break; + case 0xFA: + fbuf[0] = data; + break; + case 0xFB: + fbuf[1] = data; + break; + case 0xFC: + fbuf[2] = data; + break; + case 0xFD: + fbuf[3] = data; + break; } } diff --git a/src/board/system76/lemp9/dac.c b/src/board/system76/lemp9/dac.c new file mode 100644 index 0000000..b410a00 --- /dev/null +++ b/src/board/system76/lemp9/dac.c @@ -0,0 +1,8 @@ +#include + +void dac_init(void) { + // Enable DAC2, used for KBLIGHT_ADJ + DACPDREG &= ~(1 << 2); + // Set DAC2 to 0V + DACDAT2 = 0; +} diff --git a/src/board/system76/lemp9/gpio.c b/src/board/system76/lemp9/gpio.c index 6daad26..f69a62c 100644 --- a/src/board/system76/lemp9/gpio.c +++ b/src/board/system76/lemp9/gpio.c @@ -205,7 +205,7 @@ void gpio_init() { // KBC_MUTE# GPCRJ1 = GPIO_IN; // KBLIGHT_ADJ - GPCRJ2 = GPIO_OUT; + GPCRJ2 = GPIO_ALT; // SLP_SUS# GPCRJ3 = GPIO_IN; // VA_EC_EN diff --git a/src/board/system76/lemp9/include/board/dac.h b/src/board/system76/lemp9/include/board/dac.h new file mode 100644 index 0000000..fedf609 --- /dev/null +++ b/src/board/system76/lemp9/include/board/dac.h @@ -0,0 +1,8 @@ +#ifndef _BOARD_DAC_H +#define _BOARD_DAC_H + +#include + +void dac_init(void); + +#endif // _BOARD_DAC_H diff --git a/src/board/system76/lemp9/include/board/keymap.h b/src/board/system76/lemp9/include/board/keymap.h index cf81558..b18468d 100644 --- a/src/board/system76/lemp9/include/board/keymap.h +++ b/src/board/system76/lemp9/include/board/keymap.h @@ -3,6 +3,12 @@ #include +// Extra SCI layer for keyboard backlight control +#define KT_SCI_EXTRA (0x4000) + +#define SCI_EXTRA (0x50) +#define SCI_EXTRA_KBD_BKL (0x8A) + #define ___ 0 // Conversion of physical layout to keyboard matrix diff --git a/src/board/system76/lemp9/kbscan.c b/src/board/system76/lemp9/kbscan.c index 48892fc..6df78d4 100644 --- a/src/board/system76/lemp9/kbscan.c +++ b/src/board/system76/lemp9/kbscan.c @@ -10,6 +10,8 @@ bool kbscan_enabled = false; +uint8_t sci_extra = 0; + void kbscan_init(void) { KSOCTRL = 0x05; KSICTRLR = 0x04; @@ -98,9 +100,27 @@ void kbscan_event(void) { if (new_b) layer = 1; else layer = 0; break; + case (KT_SCI_EXTRA): + if (new_b) { + uint8_t sci = SCI_EXTRA; + sci_extra = (uint8_t)(key & 0xFF); + if (!pmc_sci(&PMC_1, sci)) { + // In the case of ignored SCI, reset bit + new &= ~(1 << j); + } + } + break; case (KT_SCI): if (new_b) { uint8_t sci = (uint8_t)(key & 0xFF); + + // HACK FOR HARDWARE HOTKEYS + switch (sci) { + case SCI_CAMERA_TOGGLE: + gpio_set(&CCD_EN, !gpio_get(&CCD_EN)); + break; + } + if (!pmc_sci(&PMC_1, sci)) { // In the case of ignored SCI, reset bit new &= ~(1 << j); diff --git a/src/board/system76/lemp9/keymap/default.c b/src/board/system76/lemp9/keymap/default.c index c61afea..f12c68b 100644 --- a/src/board/system76/lemp9/keymap/default.c +++ b/src/board/system76/lemp9/keymap/default.c @@ -13,7 +13,7 @@ LAYOUT( K_LEFT, K_DOWN, K_RIGHT ), LAYOUT( - K_ESC, K_TOUCHPAD, K_F2, K_MUTE, K_F4, K_VOLUME_DOWN, K_VOLUME_UP, K_F7, KT_SCI | SCI_BRIGHTNESS_DOWN, KT_SCI | SCI_BRIGHTNESS_UP, K_F10, KT_SCI | SCI_AIRPLANE_MODE, KT_SCI | SCI_SUSPEND, K_HOME, K_END, 0 /*prtsc*/, K_DEL, + K_ESC, K_TOUCHPAD, K_F2, K_MUTE, KT_SCI_EXTRA | SCI_EXTRA_KBD_BKL, K_VOLUME_DOWN, K_VOLUME_UP, K_F7, KT_SCI | SCI_BRIGHTNESS_DOWN, KT_SCI | SCI_BRIGHTNESS_UP, KT_SCI | SCI_CAMERA_TOGGLE, KT_SCI | SCI_AIRPLANE_MODE, KT_SCI | SCI_SUSPEND, K_HOME, K_END, 0 /*prtsc*/, K_DEL, K_PLAY_PAUSE, K_1, K_2, K_3, K_4, K_5, K_6, K_7, K_8, K_9, K_0, K_MINUS, K_EQUALS, K_BKSP, K_TAB, K_Q, K_W, K_E, K_R, K_T, K_Y, K_U, K_I, K_O, K_P, K_BRACE_OPEN, K_BRACE_CLOSE, K_BACKSLASH, K_CAPS, K_A, K_S, K_D, K_F, K_G, K_H, K_J, K_K, K_L, K_SEMICOLON, K_QUOTE, K_ENTER, diff --git a/src/board/system76/lemp9/keymap/jeremy.c b/src/board/system76/lemp9/keymap/jeremy.c index c66fb4f..a1fd874 100644 --- a/src/board/system76/lemp9/keymap/jeremy.c +++ b/src/board/system76/lemp9/keymap/jeremy.c @@ -13,7 +13,7 @@ LAYOUT( K_LEFT, K_DOWN, K_RIGHT ), LAYOUT( - K_ESC, K_TOUCHPAD, K_F2, K_MUTE, K_F4, K_VOLUME_DOWN, K_VOLUME_UP, K_F7, KT_SCI | SCI_BRIGHTNESS_DOWN, KT_SCI | SCI_BRIGHTNESS_UP, K_F10, KT_SCI | SCI_AIRPLANE_MODE, KT_SCI | SCI_SUSPEND, K_HOME, K_END, 0 /*prtsc*/, K_DEL, + K_ESC, K_TOUCHPAD, K_F2, K_MUTE, KT_SCI_EXTRA | SCI_EXTRA_KBD_BKL, K_VOLUME_DOWN, K_VOLUME_UP, K_F7, KT_SCI | SCI_BRIGHTNESS_DOWN, KT_SCI | SCI_BRIGHTNESS_UP, KT_SCI | SCI_CAMERA_TOGGLE, KT_SCI | SCI_AIRPLANE_MODE, KT_SCI | SCI_SUSPEND, K_HOME, K_END, 0 /*prtsc*/, K_DEL, K_PLAY_PAUSE, K_1, K_2, K_3, K_4, K_5, K_6, K_7, K_8, K_9, K_0, K_MINUS, K_EQUALS, K_BKSP, K_TAB, K_Q, K_W, K_E, K_R, K_T, K_Y, K_PGUP, K_HOME, K_PGDN, K_P, K_BRACE_OPEN, K_BRACE_CLOSE, K_BACKSLASH, KT_FN, K_A, K_S, K_D, K_F, K_G, K_LEFT, K_DOWN, K_UP, K_RIGHT, K_BKSP, K_DEL, K_ENTER, diff --git a/src/board/system76/lemp9/main.c b/src/board/system76/lemp9/main.c index 996092f..6266062 100644 --- a/src/board/system76/lemp9/main.c +++ b/src/board/system76/lemp9/main.c @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -46,12 +47,14 @@ void timer_2(void) __interrupt(5) { void init(void) { gpio_init(); gctrl_init(); - kbc_init(); - pmc_init(); - kbscan_init(); + dac_init(); pwm_init(); - smbus_init(); + + kbc_init(); + kbscan_init(); + pmc_init(); peci_init(); + smbus_init(); //TODO: INTC } diff --git a/src/board/system76/lemp9/peci.c b/src/board/system76/lemp9/peci.c index 93802aa..145d8f6 100644 --- a/src/board/system76/lemp9/peci.c +++ b/src/board/system76/lemp9/peci.c @@ -12,9 +12,6 @@ int16_t peci_offset = 0; int16_t peci_temp = 0; uint8_t peci_duty = 0; -uint8_t peci_tcontrol = 0; -uint8_t peci_tjmax = T_JUNCTION; -static bool peci_config_loaded = false; #define PECI_TEMP(X) (((int16_t)(X)) << 6) #define PWM_DUTY(X) ((uint8_t)(((((uint16_t)(X)) * 255) + 99) / 100)) @@ -78,55 +75,6 @@ void peci_init(void) { PADCTLR = 0x02; } -// Read tjmax using index 16 of RdPkgConfig -static void peci_config(void) { - // Wait for completion - while (HOSTAR & 1) {} - // Clear status - HOSTAR = HOSTAR; - - // Enable PECI, clearing data fifo's - HOCTLR = (1 << 5) | (1 << 3); - // Set address to default - HOTRADDR = 0x30; - // Set write length - HOWRLR = 5; - // Set read length - HORDLR = 5; - // Set command - HOCMDR = 0xA1; - // Set Host ID ? - HOWRDR = 0x00; - // Set index - HOWRDR = 16; - // Set parameter - HOWRDR = 0; - HOWRDR = 0; - // Start transaction - HOCTLR |= 1; - - // Wait for completion - while (HOSTAR & 1) {} - - if (HOSTAR & (1 << 1)) { - // Use result if finished successfully - - //TODO: check completion code - uint8_t data = HOWRDR; - - // Throw away reserved byte - data = HOWRDR; - // Tead tcontrol for now - peci_tcontrol = HOWRDR; - // Read tjmax - peci_tjmax = HOWRDR; - // Throw away reserved byte - data = HOWRDR; - - peci_config_loaded = true; - } -} - // PECI information can be found here: https://www.intel.com/content/dam/www/public/us/en/documents/design-guides/core-i7-lga-2011-guide.pdf void peci_event(void) { // Wait for completion @@ -156,12 +104,6 @@ void peci_event(void) { uint8_t high = HORDDR; peci_offset = ((int16_t)high << 8) | (int16_t)low; - // TODO: Update max value if possible - // if (!peci_config_loaded) { - // peci_config(); - // } - - // TODO: tjmax peci_temp = PECI_TEMP(T_JUNCTION) + peci_offset; peci_duty = fan_duty(peci_temp); } else { diff --git a/src/board/system76/lemp9/pmc.c b/src/board/system76/lemp9/pmc.c index 8710fda..1af0a33 100644 --- a/src/board/system76/lemp9/pmc.c +++ b/src/board/system76/lemp9/pmc.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -20,88 +21,125 @@ enum PmcState { static uint8_t pmc_sci_queue = 0; -bool pmc_sci(struct Pmc * pmc, uint8_t sci) { - bool update = pmc_sci_queue == 0; - // Set SCI queue if possible - if (update) pmc_sci_queue = sci; - // Set SCI pending bit - uint8_t sts = pmc_status(pmc); - pmc_set_status(pmc, sts | (1 << 5)); +void pmc_sci_interrupt(void) { // Start SCI interrupt gpio_set(&SCI_N, false); - *(SCI_N.control) = 0x40; - return update; + *(SCI_N.control) = GPIO_OUT; + + // Delay T_HOLD (value assumed) + delay_us(1); + + // Stop SCI interrupt + *(SCI_N.control) = GPIO_IN; + gpio_set(&SCI_N, true); +} + +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[2] = {0, 0}; + static uint8_t state_data = 0; - uint8_t sts = pmc_status(pmc); - if (sts & PMC_STS_IBF) { - uint8_t data = pmc_read(pmc); - if (sts & PMC_STS_CMD) { - DEBUG("pmc cmd: %02X\n", data); + uint8_t burst_timeout; + for (burst_timeout = 1; burst_timeout > 0; burst_timeout--) { + uint8_t sts = pmc_status(pmc); + if (sts & PMC_STS_IBF) { + uint8_t data = pmc_read(pmc); + if (sts & PMC_STS_CMD) { + DEBUG("pmc cmd: %02X\n", data); - state = PMC_STATE_DEFAULT; - switch (data) { - case 0x80: - state = PMC_STATE_ACPI_READ; - break; - case 0x81: - state = PMC_STATE_ACPI_WRITE; - break; - case 0x82: - DEBUG(" burst enable\n"); - // Set burst bit - pmc_set_status(pmc, sts | (1 << 4)); - // Send acknowledgement byte - pmc_write(pmc, 0x90, PMC_TIMEOUT); - break; - case 0x83: - DEBUG(" burst disable\n"); - // Clear burst bit - pmc_set_status(pmc, sts & ~(1 << 4)); - break; - case 0x84: - DEBUG(" SCI queue\n"); - // Clear SCI pending bit - pmc_set_status(pmc, sts & ~(1 << 5)); - // Send SCI queue - pmc_write(pmc, pmc_sci_queue, PMC_TIMEOUT); - // Stop SCI interrupt - *(SCI_N.control) = 0x80; - gpio_set(&SCI_N, true); - // Clear SCI queue - pmc_sci_queue = 0; - break; - - case 0xEC: - DEBUG(" scratch rom\n"); - pmc_write(pmc, 0x76, PMC_TIMEOUT); - scratch_trampoline(); - break; - } - } else { - DEBUG("pmc data: %02X\n", data); - - switch (state) { - case PMC_STATE_ACPI_READ: state = PMC_STATE_DEFAULT; - uint8_t value = acpi_read(data); - pmc_write(pmc, value, PMC_TIMEOUT); - break; - case PMC_STATE_ACPI_WRITE: - state = PMC_STATE_ACPI_WRITE_ADDR; - state_data[0] = data; - break; - case PMC_STATE_ACPI_WRITE_ADDR: - state = PMC_STATE_DEFAULT; - acpi_write(state_data[0], data); - break; - default: - state = PMC_STATE_DEFAULT; - break; + 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: + DEBUG(" burst enable\n"); + // Run pmc_event in a tight loop for more iterations + burst_timeout = 100; + // Set burst bit + pmc_set_status(pmc, sts | (1 << 4)); + // Send acknowledgement byte + pmc_write(pmc, 0x90, PMC_TIMEOUT); + // Send SCI for OBF=1 + pmc_sci_interrupt(); + break; + case 0x83: + DEBUG(" burst disable\n"); + // Exit pmc_event tight loop + burst_timeout = 0; + // Clear burst bit + pmc_set_status(pmc, sts & ~(1 << 4)); + // Send SCI for IBF=0 + pmc_sci_interrupt(); + break; + case 0x84: + DEBUG(" SCI queue\n"); + // Clear SCI pending bit + pmc_set_status(pmc, sts & ~(1 << 5)); + // Send SCI queue + pmc_write(pmc, pmc_sci_queue, PMC_TIMEOUT); + // Clear SCI queue + pmc_sci_queue = 0; + // Send SCI for OBF=1 + pmc_sci_interrupt(); + break; + + case 0xEC: + DEBUG(" scratch rom\n"); + pmc_write(pmc, 0x76, PMC_TIMEOUT); + scratch_trampoline(); + break; + } + } else { + DEBUG("pmc data: %02X\n", data); + + switch (state) { + case PMC_STATE_ACPI_READ: + state = PMC_STATE_DEFAULT; + state_data = acpi_read(data); + pmc_write(pmc, state_data, PMC_TIMEOUT); + // Send SCI for OBF=1 + pmc_sci_interrupt(); + 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; + } } } }