diff --git a/src/board/system76/addw2/board.c b/src/board/system76/addw2/board.c index a99e60a..b2661bf 100644 --- a/src/board/system76/addw2/board.c +++ b/src/board/system76/addw2/board.c @@ -22,8 +22,6 @@ void board_init(void) { gpio_set(&SCI_N, true); gpio_set(&SMI_N, true); gpio_set(&SWI_N, true); - - dgpu_init(); } // Set PL4 using PECI @@ -35,67 +33,43 @@ static int set_power_limit(uint8_t watts) { ); } -void board_event(void) { - bool acin = !gpio_get(&ACIN_N); - gpio_set(&AC_PRESENT, acin); +void board_on_ac(bool ac) { + uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC; + // Retry, timeout errors happen occasionally + for (int i = 0; i < 16; i++) { + int res = set_power_limit(power_limit); + DEBUG("set_power_limit %d = %d\n", power_limit, res); + if (res >= 0) { + break; + } else { + ERROR("set_power_limit failed: %X\n", -res); + } + } +} - static uint8_t last_power_limit = 0; - if (power_state == POWER_STATE_S0) { - uint8_t power_limit = acin ? POWER_LIMIT_AC : POWER_LIMIT_DC; - if (power_limit != last_power_limit) { - int res = set_power_limit(power_limit); - DEBUG("set_power_limit %d = %d\n", power_limit, res); - if (res >= 0) { - last_power_limit = power_limit; - } else { - ERROR("set_power_limit failed: %X\n", -res); - } +void board_event(void) { + bool ac = !gpio_get(&ACIN_N); + + static bool last_power_limit_ac = true; + // We don't use power_state because the latency needs to be low + if (gpio_get(&SUSB_N_PCH)) { + if (last_power_limit_ac != ac) { + board_on_ac(ac); + last_power_limit_ac = ac; } } else { - last_power_limit = 0; + last_power_limit_ac = true; } if (main_cycle == 0) { - if (acin) { - // Discharging (no AC adapter) - gpio_set(&LED_BAT_CHG, false); - gpio_set(&LED_BAT_FULL, false); - } else if (battery_status & 0x0020) { - // Fully charged - // TODO: turn off charger - gpio_set(&LED_BAT_CHG, false); - gpio_set(&LED_BAT_FULL, true); - } else { - // Charging - // TODO: detect no battery connected - gpio_set(&LED_BAT_CHG, true); - gpio_set(&LED_BAT_FULL, false); + // Set keyboard LEDs + static uint8_t last_kbc_leds = 0; + if (kbc_leds != last_kbc_leds) { + gpio_set(&LED_SCROLL_N, (kbc_leds & 1) == 0); + gpio_set(&LED_NUM_N, (kbc_leds & 2) == 0); + gpio_set(&LED_CAP_N, (kbc_leds & 4) == 0); + last_kbc_leds = kbc_leds; } - if (power_state == POWER_STATE_S0 || power_state == POWER_STATE_S3 || power_state == POWER_STATE_DS3) { - // System is on - } else if (!acin) { - // Power off VDD3 if system should be off - gpio_set(&XLP_OUT, 0); - } - - static uint32_t last_time = 0; - uint32_t time = time_get(); - // Only run the following once a second - if (last_time > time || (time - last_time) >= 1000) { - last_time = time; - - // Updates discrete GPU fan status and temps - dgpu_event(); - } - } - - // Set keyboard LEDs - static uint8_t last_kbc_leds = 0; - if (kbc_leds != last_kbc_leds) { - gpio_set(&LED_SCROLL_N, (kbc_leds & 1) == 0); - gpio_set(&LED_NUM_N, (kbc_leds & 2) == 0); - gpio_set(&LED_CAP_N, (kbc_leds & 4) == 0); - last_kbc_leds = kbc_leds; } } diff --git a/src/board/system76/addw2/board.mk b/src/board/system76/addw2/board.mk index fe9e61f..9613eab 100644 --- a/src/board/system76/addw2/board.mk +++ b/src/board/system76/addw2/board.mk @@ -25,12 +25,26 @@ CFLAGS+=-DI2C_SMBUS=I2C_4 # Set touchpad PS2 bus CFLAGS+=-DPS2_TOUCHPAD=PS2_3 +# Custom fan curve +CLFAGS+=-DBOARD_HEATUP=5 +CFLAGS+=-DBOARD_COOLDOWN=20 +CFLAGS+=-DBOARD_FAN_POINTS="\ + FAN_POINT(65, 40), \ + FAN_POINT(70, 60), \ + FAN_POINT(75, 75), \ + FAN_POINT(80, 90), \ + FAN_POINT(85, 100) \ +" + # Set smart charger parameters CFLAGS+=\ -DCHARGER_CHARGE_CURRENT=1536 \ -DCHARGER_CHARGE_VOLTAGE=12600 \ -DCHARGER_INPUT_CURRENT=11800 +# Enable DGPU support +CFLAGS+=-DHAVE_DGPU=1 + # Set CPU power limits in watts CFLAGS+=\ -DPOWER_LIMIT_AC=180 \ diff --git a/src/board/system76/addw2/dgpu.c b/src/board/system76/addw2/dgpu.c deleted file mode 100644 index 916c748..0000000 --- a/src/board/system76/addw2/dgpu.c +++ /dev/null @@ -1,144 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include -#include - -// Fan speed is the lowest requested over HEATUP seconds -#define HEATUP 10 - -// Fan speed is the highest HEATUP speed over COOLDOWN seconds -#define COOLDOWN 10 - -// Interpolate duty cycle -#define INTERPOLATE 0 - -int16_t dgpu_temp = 0; -uint8_t dgpu_duty = 0; - -#define DGPU_TEMP(X) ((int16_t)(X)) -#define PWM_DUTY(X) ((uint8_t)(((((uint16_t)(X)) * 255) + 99) / 100)) - -struct FanPoint { - int16_t temp; - uint8_t duty; -}; - -#define FAN_POINT(T, D) { .temp = DGPU_TEMP(T), .duty = PWM_DUTY(D) } - -// Fan curve with temperature in degrees C, duty cycle in percent -static struct FanPoint __code FAN_POINTS[] = { - FAN_POINT(70, 40), - FAN_POINT(75, 50), - FAN_POINT(80, 60), - FAN_POINT(85, 65), - FAN_POINT(90, 65) -}; - -// Get duty cycle based on temperature, adapted from -// https://github.com/pop-os/system76-power/blob/master/src/fan.rs -static uint8_t fan_duty(int16_t temp) { - for (int i = 0; i < ARRAY_SIZE(FAN_POINTS); i++) { - const struct FanPoint * cur = &FAN_POINTS[i]; - - // If exactly the current temp, return the current duty - if (temp == cur->temp) { - return cur->duty; - } else if (temp < cur->temp) { - // If lower than first temp, return 0% - if (i == 0) { - return PWM_DUTY(0); - } else { - const struct FanPoint * prev = &FAN_POINTS[i - 1]; - -#if INTERPOLATE - // If in between current temp and previous temp, interpolate - if (temp > prev->temp) { - int16_t dtemp = (cur->temp - prev->temp); - int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty); - return (uint8_t)( - ((int16_t)prev->duty) + - ((temp - prev->temp) * dduty) / dtemp - ); - } -#else // INTERPOLATE - return prev->duty; -#endif // INTERPOLATE - } - } - } - - // If no point is found, return 100% - return PWM_DUTY(100); -} - -static uint8_t fan_heatup(uint8_t duty) { - static uint8_t history[HEATUP] = { 0 }; - uint8_t lowest = duty; - - int i; - for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) { - uint8_t value = history[i + 1]; - if (value < lowest) { - lowest = value; - } - history[i] = value; - } - history[i] = duty; - - return lowest; -} - -static uint8_t fan_cooldown(uint8_t duty) { - static uint8_t history[COOLDOWN] = { 0 }; - uint8_t highest = duty; - - int i; - for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) { - uint8_t value = history[i + 1]; - if (value > highest) { - highest = value; - } - history[i] = value; - } - history[i] = duty; - - return highest; -} - -void dgpu_init(void) { - // Set up for i2c usage - i2c_reset(&I2C_DGPU, true); -} - -void dgpu_event(void) { - if (power_state == POWER_STATE_S0 && gpio_get(&DGPU_PWR_EN) && !gpio_get(&GC6_FB_EN)) { - // Use I2CS if in S0 state - int8_t rlts; - int res = i2c_get(&I2C_DGPU, 0x4F, 0x00, &rlts, 1); - if (res == 1) { - dgpu_temp = (int16_t)rlts; - dgpu_duty = fan_duty(dgpu_temp); - } else { - DEBUG("DGPU temp error: %d\n", res); - // Default to 50% if there is an error - dgpu_temp = 0; - dgpu_duty = PWM_DUTY(50); - } - } else { - // Turn fan off if not in S0 state or GPU power not on - dgpu_temp = 0; - dgpu_duty = PWM_DUTY(0); - } - - uint8_t heatup_duty = fan_heatup(dgpu_duty); - uint8_t cooldown_duty = fan_cooldown(heatup_duty); - if (cooldown_duty != DCR4) { - DCR4 = cooldown_duty; - DEBUG("DGPU temp=%d = %d\n", dgpu_temp, cooldown_duty); - } -} diff --git a/src/board/system76/addw2/include/board/dgpu.h b/src/board/system76/addw2/include/board/dgpu.h deleted file mode 100644 index ffe4f3a..0000000 --- a/src/board/system76/addw2/include/board/dgpu.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _BOARD_DGPU_H -#define _BOARD_DGPU_H - -void dgpu_init(void); -void dgpu_event(void); - -#endif // _BOARD_DGPU_H diff --git a/src/board/system76/addw2/scratch.c b/src/board/system76/addw2/scratch.c deleted file mode 100644 index 225d2ff..0000000 --- a/src/board/system76/addw2/scratch.c +++ /dev/null @@ -1,40 +0,0 @@ -#include <8051.h> -#include - -#include -#include -#include - -// Include scratch ROM -uint8_t __code __at(SCRATCH_OFFSET) scratch_rom[] = { - #include -}; - -// SCAR0 is stored in processor cache, not in xram -volatile uint8_t __xdata __at(0x1040) SCAR0L; -volatile uint8_t __xdata __at(0x1041) SCAR0M; -volatile uint8_t __xdata __at(0x1042) SCAR0H; - -// Enter or exit scratch ROM -void scratch_trampoline(void) { - // Set fans to 100% - DCR2 = 0xFF; - DCR4 = 0xFF; - - //TODO: Clear keyboard presses - - // Start watchdog timer - smfi_watchdog(); - - // Disable interrupts - EA = 0; - - // Use DMA mapping to copy flash data - SCAR0H = 0x80; - SCAR0L = (uint8_t)(SCRATCH_OFFSET); - SCAR0M = (uint8_t)(SCRATCH_OFFSET >> 8); - SCAR0H = 0; - - // Jump to scratch reset function - __asm__("ljmp " xstr(SCRATCH_OFFSET)); -} diff --git a/src/board/system76/addw2/acpi.c b/src/board/system76/common/acpi.c similarity index 89% rename from src/board/system76/addw2/acpi.c rename to src/board/system76/common/acpi.c index 06f5844..f7ff78a 100644 --- a/src/board/system76/addw2/acpi.c +++ b/src/board/system76/common/acpi.c @@ -6,6 +6,10 @@ #include #include +#ifndef HAVE_LED_AIRPLANE_N +#define HAVE_LED_AIRPLANE_N 1 +#endif // HAVE_LED_AIRPLANE_N + extern uint8_t sci_extra; uint8_t ecos = 0; @@ -19,6 +23,14 @@ void fcommand(void) { // Keyboard backlight case 0xCA: switch (fdat) { + // Set white LED brightness + case 0x00: + kbled_set(fbuf[0]); + break; + // Get white LED brightness + case 0x01: + fbuf[0] = kbled_get(); + break; // Set LED color case 0x03: kbled_set_color( @@ -97,12 +109,14 @@ uint8_t acpi_read(uint8_t addr) { ACPI_8(0xCC, sci_extra); +#if HAVE_LED_AIRPLANE_N // Airplane mode LED case 0xD9: if (!gpio_get(&LED_AIRPLANE_N)) { data |= (1 << 6); } break; +#endif // HAVE_LED_AIRPLANE_N // Set size of flash (from old firmware) ACPI_8 (0xE5, 0x80); @@ -133,10 +147,12 @@ void acpi_write(uint8_t addr, uint8_t data) { ecos = data; break; +#if HAVE_LED_AIRPLANE_N // Airplane mode LED case 0xD9: gpio_set(&LED_AIRPLANE_N, !(bool)(data & (1 << 6))); break; +#endif case 0xF8: fcmd = data; diff --git a/src/board/system76/gaze15/dgpu.c b/src/board/system76/common/dgpu.c similarity index 90% rename from src/board/system76/gaze15/dgpu.c rename to src/board/system76/common/dgpu.c index 916c748..6a2f032 100644 --- a/src/board/system76/gaze15/dgpu.c +++ b/src/board/system76/common/dgpu.c @@ -1,3 +1,7 @@ +#include + +#if HAVE_DGPU + #include #include @@ -9,10 +13,18 @@ #include // Fan speed is the lowest requested over HEATUP seconds -#define HEATUP 10 +#ifdef BOARD_DGPU_HEATUP + #define HEATUP BOARD_DGPU_HEATUP +#else + #define HEATUP 10 +#endif // Fan speed is the highest HEATUP speed over COOLDOWN seconds -#define COOLDOWN 10 +#ifdef BOARD_DGPU_COOLDOWN + #define COOLDOWN BOARD_DGPU_COOLDOWN +#else + #define COOLDOWN 10 +#endif // Interpolate duty cycle #define INTERPOLATE 0 @@ -32,11 +44,15 @@ struct FanPoint { // Fan curve with temperature in degrees C, duty cycle in percent static struct FanPoint __code FAN_POINTS[] = { +#ifdef BOARD_DGPU_FAN_POINTS + BOARD_DGPU_FAN_POINTS +#else FAN_POINT(70, 40), FAN_POINT(75, 50), FAN_POINT(80, 60), FAN_POINT(85, 65), FAN_POINT(90, 65) +#endif }; // Get duty cycle based on temperature, adapted from @@ -142,3 +158,11 @@ void dgpu_event(void) { DEBUG("DGPU temp=%d = %d\n", dgpu_temp, cooldown_duty); } } + +#else + +void dgpu_init(void) {} + +void dgpu_event(void) {} + +#endif // HAVE_DGPU diff --git a/src/board/system76/common/include/board/board.h b/src/board/system76/common/include/board/board.h index e139acf..f7c3dc6 100644 --- a/src/board/system76/common/include/board/board.h +++ b/src/board/system76/common/include/board/board.h @@ -1,7 +1,10 @@ #ifndef _BOARD_BOARD_H #define _BOARD_BOARD_H +#include + void board_init(void); void board_event(void); +void board_on_ac(bool ac); #endif // _BOARD_BOARD_H diff --git a/src/board/system76/oryp6/include/board/dgpu.h b/src/board/system76/common/include/board/dgpu.h similarity index 69% rename from src/board/system76/oryp6/include/board/dgpu.h rename to src/board/system76/common/include/board/dgpu.h index ffe4f3a..696e329 100644 --- a/src/board/system76/oryp6/include/board/dgpu.h +++ b/src/board/system76/common/include/board/dgpu.h @@ -1,6 +1,10 @@ #ifndef _BOARD_DGPU_H #define _BOARD_DGPU_H +#ifndef HAVE_DGPU + #define HAVE_DGPU 0 +#endif + void dgpu_init(void); void dgpu_event(void); diff --git a/src/board/system76/addw2/include/board/kbled.h b/src/board/system76/common/include/board/kbled.h similarity index 100% rename from src/board/system76/addw2/include/board/kbled.h rename to src/board/system76/common/include/board/kbled.h diff --git a/src/board/system76/common/main.c b/src/board/system76/common/main.c index e7ba92a..4b62578 100644 --- a/src/board/system76/common/main.c +++ b/src/board/system76/common/main.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,9 @@ void init(void) { gpio_init(); // Can happen in any order +#if HAVE_DGPU + dgpu_init(); +#endif ecpm_init(); kbc_init(); kbled_init(); @@ -115,6 +119,11 @@ void main(void) { // Updates fan status and temps peci_event(); +#if HAVE_DGPU + // Updates discrete GPU fan status and temps + dgpu_event(); +#endif + // Updates battery status battery_event(); } diff --git a/src/board/system76/common/peci.c b/src/board/system76/common/peci.c index 0c5bfa4..2f0f147 100644 --- a/src/board/system76/common/peci.c +++ b/src/board/system76/common/peci.c @@ -42,21 +42,21 @@ struct FanPoint { #define FAN_POINT(T, D) { .temp = PECI_TEMP(T), .duty = PWM_DUTY(D) } // Fan curve with temperature in degrees C, duty cycle in percent -struct FanPoint __code FAN_POINTS[] = { +static struct FanPoint __code FAN_POINTS[] = { #ifdef BOARD_FAN_POINTS BOARD_FAN_POINTS #else - FAN_POINT(65, 40), - FAN_POINT(70, 60), - FAN_POINT(75, 75), - FAN_POINT(80, 90), - FAN_POINT(85, 100) + FAN_POINT(70, 40), + FAN_POINT(75, 50), + FAN_POINT(80, 60), + FAN_POINT(85, 65), + FAN_POINT(90, 65) #endif }; // Get duty cycle based on temperature, adapted from // https://github.com/pop-os/system76-power/blob/master/src/fan.rs -uint8_t fan_duty(int16_t temp) { +static uint8_t fan_duty(int16_t temp) { for (int i = 0; i < ARRAY_SIZE(FAN_POINTS); i++) { const struct FanPoint * cur = &FAN_POINTS[i]; @@ -91,7 +91,7 @@ uint8_t fan_duty(int16_t temp) { return PWM_DUTY(100); } -uint8_t fan_heatup(uint8_t duty) { +static uint8_t fan_heatup(uint8_t duty) { static uint8_t history[HEATUP] = { 0 }; uint8_t lowest = duty; @@ -108,7 +108,7 @@ uint8_t fan_heatup(uint8_t duty) { return lowest; } -uint8_t fan_cooldown(uint8_t duty) { +static uint8_t fan_cooldown(uint8_t duty) { static uint8_t history[COOLDOWN] = { 0 }; uint8_t highest = duty; diff --git a/src/board/system76/common/power.c b/src/board/system76/common/power.c index 83d9861..6eb40fa 100644 --- a/src/board/system76/common/power.c +++ b/src/board/system76/common/power.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,14 @@ #define HAVE_EC_EN 1 #endif +#ifndef HAVE_LED_BAT_CHG + #define HAVE_LED_BAT_CHG 1 +#endif + +#ifndef HAVE_LED_BAT_FULL + #define HAVE_LED_BAT_FULL 1 +#endif + #ifndef HAVE_PCH_DPWROK_EC #define HAVE_PCH_DPWROK_EC 1 #endif @@ -35,6 +44,9 @@ #define HAVE_SLP_SUS_N 1 #endif +#ifndef HAVE_XLP_OUT + #define HAVE_XLP_OUT 1 +#endif #ifndef HAVE_SUSWARN_N #define HAVE_SUSWARN_N 1 #endif @@ -47,6 +59,10 @@ #define HAVE_VA_EC_EN 1 #endif +#ifndef HAVE_XLP_OUT + #define HAVE_XLP_OUT 1 +#endif + extern uint8_t main_cycle; // VccRTC stable (55%) to RTCRST# high @@ -326,6 +342,8 @@ void power_event(void) { static bool ac_last = true; bool ac_new = gpio_get(&ACIN_N); if (ac_new != ac_last) { + board_on_ac(!ac_new); + DEBUG("Power adapter "); if (ac_new) { DEBUG("unplugged\n"); @@ -350,6 +368,8 @@ void power_event(void) { } ac_last = ac_new; + gpio_set(&AC_PRESENT, !ac_new); + // Read power switch state static bool ps_last = true; bool ps_new = gpio_get(&PWR_SW_N); @@ -498,5 +518,29 @@ void power_event(void) { gpio_set(&LED_ACIN, !gpio_get(&LED_ACIN)); last_time = time; } + +#if HAVE_XLP_OUT + // Power off VDD3 if system should be off + gpio_set(&XLP_OUT, 0); +#endif // HAVE_XLP_OUT } + +//TODO: do not require both LEDs +#if HAVE_LED_BAT_CHG && HAVE_LED_BAT_FULL + if (ac_new) { + // Discharging (no AC adapter) + gpio_set(&LED_BAT_CHG, false); + gpio_set(&LED_BAT_FULL, false); + } else if (battery_status & 0x0020) { + // Fully charged + // TODO: turn off charger + gpio_set(&LED_BAT_CHG, false); + gpio_set(&LED_BAT_FULL, true); + } else { + // Charging + // TODO: detect no battery connected + gpio_set(&LED_BAT_CHG, true); + gpio_set(&LED_BAT_FULL, false); + } +#endif // HAVE_LED_BAT_CHG && HAVE_LED_BAT_FULL } diff --git a/src/board/system76/common/scratch.c b/src/board/system76/common/scratch.c new file mode 100644 index 0000000..a675e55 --- /dev/null +++ b/src/board/system76/common/scratch.c @@ -0,0 +1,58 @@ +#include <8051.h> +#include + +#include +#include +#include +#include + +// Include scratch ROM +uint8_t __code __at(SCRATCH_OFFSET) scratch_rom[] = { + #include +}; + +#if __EC__ == it5570e + // SCAR0 is stored in processor cache, not in xram + volatile uint8_t __xdata __at(0x1040) SCAR0L; + volatile uint8_t __xdata __at(0x1041) SCAR0M; + volatile uint8_t __xdata __at(0x1042) SCAR0H; + #define SCARL SCAR0L + #define SCARM SCAR0M + #define SCARH SCAR0H +#elif __EC__ == it8587e + // SCAR1 is in xram at 0x800-0xC00 + volatile uint8_t __xdata __at(0x1043) SCAR1L; + volatile uint8_t __xdata __at(0x1044) SCAR1M; + volatile uint8_t __xdata __at(0x1045) SCAR1H; + #define SCARL SCAR1L + #define SCARM SCAR1M + #define SCARH SCAR1H +#else + #error "scratch.c unknown EC" +#endif + +// Enter or exit scratch ROM +void scratch_trampoline(void) { + // Set fans to 100% + DCR2 = 0xFF; +#if HAVE_DGPU + DCR4 = 0xFF; +#endif + + //TODO: Clear keyboard presses + + // Start watchdog timer + smfi_watchdog(); + + // Disable interrupts + EA = 0; + + // Use DMA mapping to copy flash data + SCARH = 0x80; + SCARL = (uint8_t)(SCRATCH_OFFSET); + SCARM = (uint8_t)(SCRATCH_OFFSET >> 8); + SCARH = 0; + + // Jump to scratch reset function + __asm__("ljmp " xstr(SCRATCH_OFFSET)); +} diff --git a/src/board/system76/darp5/acpi.c b/src/board/system76/darp5/acpi.c deleted file mode 100644 index 06f5844..0000000 --- a/src/board/system76/darp5/acpi.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -extern uint8_t sci_extra; - -uint8_t ecos = 0; - -static uint8_t fcmd = 0; -static uint8_t fdat = 0; -static uint8_t fbuf[4] = { 0, 0, 0, 0 }; - -void fcommand(void) { - switch (fcmd) { - // Keyboard backlight - case 0xCA: - switch (fdat) { - // Set LED color - case 0x03: - kbled_set_color( - ((uint32_t)fbuf[0]) | - ((uint32_t)fbuf[1] << 16) | - ((uint32_t)fbuf[2] << 8) - ); - break; - // Set LED brightness - case 0x06: - kbled_set(fbuf[0]); - break; - } - break; - } -} - -uint8_t acpi_read(uint8_t addr) { - uint8_t data = 0; - - #define ACPI_8(K, V) \ - case (K): \ - data = (uint8_t)(V); \ - break - - #define ACPI_16(K, V) \ - ACPI_8(K, V); \ - ACPI_8((K) + 1, (V) >> 8) - - #define ACPI_32(K, V) \ - ACPI_16(K, V); \ - ACPI_16((K) + 2, (V) >> 16) - - switch (addr) { - // Lid state and other flags - case 0x03: - if (gpio_get(&LID_SW_N)) { - // Lid is open - data |= 1 << 0; - } - if (lid_wake) { - data |= 1 << 2; - } - break; - - // Handle AC adapter and battery present - case 0x10: - if (!gpio_get(&ACIN_N)) { - // AC adapter connected - data |= 1 << 0; - } - // BAT0 always connected - TODO - data |= 1 << 2; - break; - - ACPI_16(0x16, battery_design_capacity); - ACPI_16(0x1A, battery_full_capacity); - ACPI_16(0x22, battery_design_voltage); - - case 0x26: - // If AC adapter connected - if (!gpio_get(&ACIN_N)) { - // And battery is not fully charged - if (!(battery_status & 0x0020)) { - // Battery is charging - data |= 1 << 1; - } - } - break; - - ACPI_16(0x2A, battery_current); - ACPI_16(0x2E, battery_remaining_capacity); - ACPI_16(0x32, battery_voltage); - - ACPI_8(0x68, ecos); - - ACPI_8(0xCC, sci_extra); - - // Airplane mode LED - case 0xD9: - if (!gpio_get(&LED_AIRPLANE_N)) { - data |= (1 << 6); - } - break; - - // 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); - return data; -} - - -void acpi_write(uint8_t addr, uint8_t data) { - DEBUG("acpi_write %02X = %02X\n", addr, data); - - switch (addr) { - // Lid state and other flags - case 0x03: - lid_wake = (bool)(data & (1 << 2)); - break; - - case 0x68: - ecos = data; - break; - - // Airplane mode LED - 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/board.c b/src/board/system76/darp5/board.c index 6661e29..cb5a96f 100644 --- a/src/board/system76/darp5/board.c +++ b/src/board/system76/darp5/board.c @@ -23,22 +23,6 @@ void board_init(void) { gpio_set(&SWI_N, true); } -void board_event(void) { - if (main_cycle == 0) { - if (gpio_get(&ACIN_N)) { - // Discharging (no AC adapter) - gpio_set(&LED_BAT_CHG, false); - gpio_set(&LED_BAT_FULL, false); - } else if (battery_status & 0x0020) { - // Fully charged - // TODO: turn off charger - gpio_set(&LED_BAT_CHG, false); - gpio_set(&LED_BAT_FULL, true); - } else { - // Charging - // TODO: detect no battery connected - gpio_set(&LED_BAT_CHG, true); - gpio_set(&LED_BAT_FULL, false); - } - } -} +void board_on_ac(bool ac) { /* Fix unused variable */ ac = ac; } + +void board_event(void) {} diff --git a/src/board/system76/darp5/include/board/gpio.h b/src/board/system76/darp5/include/board/gpio.h index c08a40f..b6ac461 100644 --- a/src/board/system76/darp5/include/board/gpio.h +++ b/src/board/system76/darp5/include/board/gpio.h @@ -48,5 +48,6 @@ extern struct Gpio __code VA_EC_EN; extern struct Gpio __code VR_ON; extern struct Gpio __code WLAN_EN; extern struct Gpio __code WLAN_PWR_EN; +#define HAVE_XLP_OUT 0 #endif // _BOARD_GPIO_H diff --git a/src/board/system76/darp5/include/board/kbled.h b/src/board/system76/darp5/include/board/kbled.h deleted file mode 100644 index 895542c..0000000 --- a/src/board/system76/darp5/include/board/kbled.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _BOARD_KBLED_H -#define _BOARD_KBLED_H - -#include - -void kbled_init(void); -void kbled_reset(void); -uint8_t kbled_get(void); -void kbled_set(uint8_t level); -void kbled_set_color(uint32_t color); - -#endif // _BOARD_KBLED_H diff --git a/src/board/system76/darp5/scratch.c b/src/board/system76/darp5/scratch.c deleted file mode 100644 index e3c4029..0000000 --- a/src/board/system76/darp5/scratch.c +++ /dev/null @@ -1,39 +0,0 @@ -#include <8051.h> -#include - -#include -#include -#include - -// Include scratch ROM -uint8_t __code __at(SCRATCH_OFFSET) scratch_rom[] = { - #include -}; - -// SCAR1 is in xram at 0x800-0xC00 -volatile uint8_t __xdata __at(0x1043) SCAR1L; -volatile uint8_t __xdata __at(0x1044) SCAR1M; -volatile uint8_t __xdata __at(0x1045) SCAR1H; - -// Enter or exit scratch ROM -void scratch_trampoline(void) { - // Set fans to 100% - DCR2 = 0xFF; - - //TODO: Clear keyboard presses - - // Start watchdog timer - smfi_watchdog(); - - // Disable interrupts - EA = 0; - - // Use DMA mapping to copy flash data - SCAR1H = 0x80; - SCAR1L = (uint8_t)(SCRATCH_OFFSET); - SCAR1M = (uint8_t)(SCRATCH_OFFSET >> 8); - SCAR1H = 0; - - // Jump to scratch reset function - __asm__("ljmp " xstr(SCRATCH_OFFSET)); -} diff --git a/src/board/system76/galp3-c/acpi.c b/src/board/system76/galp3-c/acpi.c deleted file mode 100644 index 5df0af5..0000000 --- a/src/board/system76/galp3-c/acpi.c +++ /dev/null @@ -1,157 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -extern uint8_t sci_extra; - -uint8_t ecos = 0; - -static uint8_t fcmd = 0; -static uint8_t fdat = 0; -static 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: - kbled_set(fbuf[0]); - break; - // Get white LED brightness - case 0x01: - fbuf[0] = kbled_get(); - break; - } - break; - } -} - -uint8_t acpi_read(uint8_t addr) { - uint8_t data = 0; - - #define ACPI_8(K, V) \ - case (K): \ - data = (uint8_t)(V); \ - break - - #define ACPI_16(K, V) \ - ACPI_8(K, V); \ - ACPI_8((K) + 1, (V) >> 8) - - #define ACPI_32(K, V) \ - ACPI_16(K, V); \ - ACPI_16((K) + 2, (V) >> 16) - - switch (addr) { - // Lid state and other flags - case 0x03: - if (gpio_get(&LID_SW_N)) { - // Lid is open - data |= 1 << 0; - } - if (lid_wake) { - data |= 1 << 2; - } - break; - - // Handle AC adapter and battery present - case 0x10: - if (!gpio_get(&ACIN_N)) { - // AC adapter connected - data |= 1 << 0; - } - // BAT0 always connected - TODO - data |= 1 << 2; - break; - - ACPI_16(0x16, battery_design_capacity); - ACPI_16(0x1A, battery_full_capacity); - ACPI_16(0x22, battery_design_voltage); - - case 0x26: - // If AC adapter connected - if (!gpio_get(&ACIN_N)) { - // And battery is not fully charged - if (!(battery_status & 0x0020)) { - // Battery is charging - data |= 1 << 1; - } - } - break; - - ACPI_16(0x2A, battery_current); - ACPI_16(0x2E, battery_remaining_capacity); - ACPI_16(0x32, battery_voltage); - - ACPI_8(0x68, ecos); - - ACPI_8(0xCC, sci_extra); - - // Airplane mode LED - case 0xD9: - if (!gpio_get(&LED_AIRPLANE_N)) { - data |= (1 << 6); - } - break; - - // 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); - return data; -} - - -void acpi_write(uint8_t addr, uint8_t data) { - DEBUG("acpi_write %02X = %02X\n", addr, data); - - switch (addr) { - // Lid state and other flags - case 0x03: - lid_wake = (bool)(data & (1 << 2)); - break; - - case 0x68: - ecos = data; - break; - - // Airplane mode LED - 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/galp3-c/board.c b/src/board/system76/galp3-c/board.c index 6661e29..cb5a96f 100644 --- a/src/board/system76/galp3-c/board.c +++ b/src/board/system76/galp3-c/board.c @@ -23,22 +23,6 @@ void board_init(void) { gpio_set(&SWI_N, true); } -void board_event(void) { - if (main_cycle == 0) { - if (gpio_get(&ACIN_N)) { - // Discharging (no AC adapter) - gpio_set(&LED_BAT_CHG, false); - gpio_set(&LED_BAT_FULL, false); - } else if (battery_status & 0x0020) { - // Fully charged - // TODO: turn off charger - gpio_set(&LED_BAT_CHG, false); - gpio_set(&LED_BAT_FULL, true); - } else { - // Charging - // TODO: detect no battery connected - gpio_set(&LED_BAT_CHG, true); - gpio_set(&LED_BAT_FULL, false); - } - } -} +void board_on_ac(bool ac) { /* Fix unused variable */ ac = ac; } + +void board_event(void) {} diff --git a/src/board/system76/galp3-c/include/board/gpio.h b/src/board/system76/galp3-c/include/board/gpio.h index c08a40f..b6ac461 100644 --- a/src/board/system76/galp3-c/include/board/gpio.h +++ b/src/board/system76/galp3-c/include/board/gpio.h @@ -48,5 +48,6 @@ extern struct Gpio __code VA_EC_EN; extern struct Gpio __code VR_ON; extern struct Gpio __code WLAN_EN; extern struct Gpio __code WLAN_PWR_EN; +#define HAVE_XLP_OUT 0 #endif // _BOARD_GPIO_H diff --git a/src/board/system76/galp3-c/include/board/kbled.h b/src/board/system76/galp3-c/include/board/kbled.h deleted file mode 100644 index 0fb9cca..0000000 --- a/src/board/system76/galp3-c/include/board/kbled.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _BOARD_KBLED_H -#define _BOARD_KBLED_H - -#include - -void kbled_init(void); -void kbled_reset(void); -uint8_t kbled_get(void); -void kbled_set(uint8_t level); - -#endif // _BOARD_KBLED_H diff --git a/src/board/system76/galp3-c/kbled.c b/src/board/system76/galp3-c/kbled.c index 09fbd03..e0c53a1 100644 --- a/src/board/system76/galp3-c/kbled.c +++ b/src/board/system76/galp3-c/kbled.c @@ -42,3 +42,5 @@ void kbled_set(uint8_t level) { } KBLED_DACDAT = raw; } + +void kbled_set_color(uint32_t color) { /*Fix unused variable*/ color = color; } diff --git a/src/board/system76/galp3-c/scratch.c b/src/board/system76/galp3-c/scratch.c deleted file mode 100644 index e3c4029..0000000 --- a/src/board/system76/galp3-c/scratch.c +++ /dev/null @@ -1,39 +0,0 @@ -#include <8051.h> -#include - -#include -#include -#include - -// Include scratch ROM -uint8_t __code __at(SCRATCH_OFFSET) scratch_rom[] = { - #include -}; - -// SCAR1 is in xram at 0x800-0xC00 -volatile uint8_t __xdata __at(0x1043) SCAR1L; -volatile uint8_t __xdata __at(0x1044) SCAR1M; -volatile uint8_t __xdata __at(0x1045) SCAR1H; - -// Enter or exit scratch ROM -void scratch_trampoline(void) { - // Set fans to 100% - DCR2 = 0xFF; - - //TODO: Clear keyboard presses - - // Start watchdog timer - smfi_watchdog(); - - // Disable interrupts - EA = 0; - - // Use DMA mapping to copy flash data - SCAR1H = 0x80; - SCAR1L = (uint8_t)(SCRATCH_OFFSET); - SCAR1M = (uint8_t)(SCRATCH_OFFSET >> 8); - SCAR1H = 0; - - // Jump to scratch reset function - __asm__("ljmp " xstr(SCRATCH_OFFSET)); -} diff --git a/src/board/system76/gaze15/acpi.c b/src/board/system76/gaze15/acpi.c deleted file mode 100644 index 06f5844..0000000 --- a/src/board/system76/gaze15/acpi.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -extern uint8_t sci_extra; - -uint8_t ecos = 0; - -static uint8_t fcmd = 0; -static uint8_t fdat = 0; -static uint8_t fbuf[4] = { 0, 0, 0, 0 }; - -void fcommand(void) { - switch (fcmd) { - // Keyboard backlight - case 0xCA: - switch (fdat) { - // Set LED color - case 0x03: - kbled_set_color( - ((uint32_t)fbuf[0]) | - ((uint32_t)fbuf[1] << 16) | - ((uint32_t)fbuf[2] << 8) - ); - break; - // Set LED brightness - case 0x06: - kbled_set(fbuf[0]); - break; - } - break; - } -} - -uint8_t acpi_read(uint8_t addr) { - uint8_t data = 0; - - #define ACPI_8(K, V) \ - case (K): \ - data = (uint8_t)(V); \ - break - - #define ACPI_16(K, V) \ - ACPI_8(K, V); \ - ACPI_8((K) + 1, (V) >> 8) - - #define ACPI_32(K, V) \ - ACPI_16(K, V); \ - ACPI_16((K) + 2, (V) >> 16) - - switch (addr) { - // Lid state and other flags - case 0x03: - if (gpio_get(&LID_SW_N)) { - // Lid is open - data |= 1 << 0; - } - if (lid_wake) { - data |= 1 << 2; - } - break; - - // Handle AC adapter and battery present - case 0x10: - if (!gpio_get(&ACIN_N)) { - // AC adapter connected - data |= 1 << 0; - } - // BAT0 always connected - TODO - data |= 1 << 2; - break; - - ACPI_16(0x16, battery_design_capacity); - ACPI_16(0x1A, battery_full_capacity); - ACPI_16(0x22, battery_design_voltage); - - case 0x26: - // If AC adapter connected - if (!gpio_get(&ACIN_N)) { - // And battery is not fully charged - if (!(battery_status & 0x0020)) { - // Battery is charging - data |= 1 << 1; - } - } - break; - - ACPI_16(0x2A, battery_current); - ACPI_16(0x2E, battery_remaining_capacity); - ACPI_16(0x32, battery_voltage); - - ACPI_8(0x68, ecos); - - ACPI_8(0xCC, sci_extra); - - // Airplane mode LED - case 0xD9: - if (!gpio_get(&LED_AIRPLANE_N)) { - data |= (1 << 6); - } - break; - - // 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); - return data; -} - - -void acpi_write(uint8_t addr, uint8_t data) { - DEBUG("acpi_write %02X = %02X\n", addr, data); - - switch (addr) { - // Lid state and other flags - case 0x03: - lid_wake = (bool)(data & (1 << 2)); - break; - - case 0x68: - ecos = data; - break; - - // Airplane mode LED - 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/gaze15/board.c b/src/board/system76/gaze15/board.c index d0b4df5..9305502 100644 --- a/src/board/system76/gaze15/board.c +++ b/src/board/system76/gaze15/board.c @@ -23,8 +23,6 @@ void board_init(void) { gpio_set(&SCI_N, true); gpio_set(&SMI_N, true); gpio_set(&SWI_N, true); - - dgpu_init(); } // Set PL4 using PECI @@ -36,58 +34,31 @@ static int set_power_limit(uint8_t watts) { ); } -void board_event(void) { - bool acin = !gpio_get(&ACIN_N); - gpio_set(&AC_PRESENT, acin); - - static uint8_t last_power_limit = 0; - if (power_state == POWER_STATE_S0) { - uint8_t power_limit = acin ? POWER_LIMIT_AC : POWER_LIMIT_DC; - if (power_limit != last_power_limit) { - int res = set_power_limit(power_limit); - DEBUG("set_power_limit %d = %d\n", power_limit, res); - if (res >= 0) { - last_power_limit = power_limit; - } else { - ERROR("set_power_limit failed: %X\n", -res); - } - } - } else { - last_power_limit = 0; - } - - if (main_cycle == 0) { - if (acin) { - // Discharging (no AC adapter) - gpio_set(&LED_BAT_CHG, false); - gpio_set(&LED_BAT_FULL, false); - } else if (battery_status & 0x0020) { - // Fully charged - // TODO: turn off charger - gpio_set(&LED_BAT_CHG, false); - gpio_set(&LED_BAT_FULL, true); +void board_on_ac(bool ac) { + uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC; + // Retry, timeout errors happen occasionally + for (int i = 0; i < 16; i++) { + int res = set_power_limit(power_limit); + DEBUG("set_power_limit %d = %d\n", power_limit, res); + if (res >= 0) { + break; } else { - // Charging - // TODO: detect no battery connected - gpio_set(&LED_BAT_CHG, true); - gpio_set(&LED_BAT_FULL, false); - } - - if (power_state == POWER_STATE_S0 || power_state == POWER_STATE_S3 || power_state == POWER_STATE_DS3) { - // System is on - } else if (!acin) { - // Power off VDD3 if system should be off - gpio_set(&XLP_OUT, 0); - } - - static uint32_t last_time = 0; - uint32_t time = time_get(); - // Only run the following once a second - if (last_time > time || (time - last_time) >= 1000) { - last_time = time; - - // Updates discrete GPU fan status and temps - dgpu_event(); + ERROR("set_power_limit failed: %X\n", -res); } } } + +void board_event(void) { + bool ac = !gpio_get(&ACIN_N); + + static bool last_power_limit_ac = true; + // We don't use power_state because the latency needs to be low + if (gpio_get(&SUSB_N_PCH)) { + if (last_power_limit_ac != ac) { + board_on_ac(ac); + last_power_limit_ac = ac; + } + } else { + last_power_limit_ac = true; + } +} diff --git a/src/board/system76/gaze15/board.mk b/src/board/system76/gaze15/board.mk index b275aa2..2c5008a 100644 --- a/src/board/system76/gaze15/board.mk +++ b/src/board/system76/gaze15/board.mk @@ -25,12 +25,26 @@ CFLAGS+=-DI2C_SMBUS=I2C_4 # Set touchpad PS2 bus CFLAGS+=-DPS2_TOUCHPAD=PS2_3 +# Custom fan curve +CLFAGS+=-DBOARD_HEATUP=5 +CFLAGS+=-DBOARD_COOLDOWN=20 +CFLAGS+=-DBOARD_FAN_POINTS="\ + FAN_POINT(65, 40), \ + FAN_POINT(70, 60), \ + FAN_POINT(75, 75), \ + FAN_POINT(80, 90), \ + FAN_POINT(85, 100) \ +" + # Set smart charger parameters CFLAGS+=\ -DCHARGER_CHARGE_CURRENT=1536 \ -DCHARGER_CHARGE_VOLTAGE=16800 \ -DCHARGER_INPUT_CURRENT=9230 +# Enable DGPU support +CFLAGS+=-DHAVE_DGPU=1 + # Set CPU power limits in watts CFLAGS+=\ -DPOWER_LIMIT_AC=180 \ diff --git a/src/board/system76/gaze15/include/board/dgpu.h b/src/board/system76/gaze15/include/board/dgpu.h deleted file mode 100644 index ffe4f3a..0000000 --- a/src/board/system76/gaze15/include/board/dgpu.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _BOARD_DGPU_H -#define _BOARD_DGPU_H - -void dgpu_init(void); -void dgpu_event(void); - -#endif // _BOARD_DGPU_H diff --git a/src/board/system76/gaze15/include/board/kbled.h b/src/board/system76/gaze15/include/board/kbled.h deleted file mode 100644 index 895542c..0000000 --- a/src/board/system76/gaze15/include/board/kbled.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _BOARD_KBLED_H -#define _BOARD_KBLED_H - -#include - -void kbled_init(void); -void kbled_reset(void); -uint8_t kbled_get(void); -void kbled_set(uint8_t level); -void kbled_set_color(uint32_t color); - -#endif // _BOARD_KBLED_H diff --git a/src/board/system76/gaze15/scratch.c b/src/board/system76/gaze15/scratch.c deleted file mode 100644 index 225d2ff..0000000 --- a/src/board/system76/gaze15/scratch.c +++ /dev/null @@ -1,40 +0,0 @@ -#include <8051.h> -#include - -#include -#include -#include - -// Include scratch ROM -uint8_t __code __at(SCRATCH_OFFSET) scratch_rom[] = { - #include -}; - -// SCAR0 is stored in processor cache, not in xram -volatile uint8_t __xdata __at(0x1040) SCAR0L; -volatile uint8_t __xdata __at(0x1041) SCAR0M; -volatile uint8_t __xdata __at(0x1042) SCAR0H; - -// Enter or exit scratch ROM -void scratch_trampoline(void) { - // Set fans to 100% - DCR2 = 0xFF; - DCR4 = 0xFF; - - //TODO: Clear keyboard presses - - // Start watchdog timer - smfi_watchdog(); - - // Disable interrupts - EA = 0; - - // Use DMA mapping to copy flash data - SCAR0H = 0x80; - SCAR0L = (uint8_t)(SCRATCH_OFFSET); - SCAR0M = (uint8_t)(SCRATCH_OFFSET >> 8); - SCAR0H = 0; - - // Jump to scratch reset function - __asm__("ljmp " xstr(SCRATCH_OFFSET)); -} diff --git a/src/board/system76/lemp9/acpi.c b/src/board/system76/lemp9/acpi.c deleted file mode 100644 index ec0b79c..0000000 --- a/src/board/system76/lemp9/acpi.c +++ /dev/null @@ -1,145 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -extern uint8_t sci_extra; - -uint8_t ecos = 0; - -static uint8_t fcmd = 0; -static uint8_t fdat = 0; -static 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: - kbled_set(fbuf[0]); - break; - // Get white LED brightness - case 0x01: - fbuf[0] = kbled_get(); - break; - } - break; - } -} - -uint8_t acpi_read(uint8_t addr) { - uint8_t data = 0; - - #define ACPI_8(K, V) \ - case (K): \ - data = (uint8_t)(V); \ - break - - #define ACPI_16(K, V) \ - ACPI_8(K, V); \ - ACPI_8((K) + 1, (V) >> 8) - - #define ACPI_32(K, V) \ - ACPI_16(K, V); \ - ACPI_16((K) + 2, (V) >> 16) - - switch (addr) { - // Lid state and other flags - case 0x03: - if (gpio_get(&LID_SW_N)) { - // Lid is open - data |= 1 << 0; - } - if (lid_wake) { - data |= 1 << 2; - } - break; - - // Handle AC adapter and battery present - case 0x10: - if (!gpio_get(&ACIN_N)) { - // AC adapter connected - data |= 1 << 0; - } - // BAT0 always connected - TODO - data |= 1 << 2; - break; - - ACPI_16(0x16, battery_design_capacity); - ACPI_16(0x1A, battery_full_capacity); - ACPI_16(0x22, battery_design_voltage); - - case 0x26: - // If AC adapter connected - if (!gpio_get(&ACIN_N)) { - // And battery is not fully charged - if (!(battery_status & 0x0020)) { - // Battery is charging - data |= 1 << 1; - } - } - break; - - ACPI_16(0x2A, battery_current); - ACPI_16(0x2E, battery_remaining_capacity); - ACPI_16(0x32, battery_voltage); - - ACPI_8(0x68, ecos); - - 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); - return data; -} - - -void acpi_write(uint8_t addr, uint8_t data) { - DEBUG("acpi_write %02X = %02X\n", addr, data); - - switch (addr) { - // Lid state and other flags - case 0x03: - lid_wake = (bool)(data & (1 << 2)); - break; - - case 0x68: - ecos = data; - 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/board.c b/src/board/system76/lemp9/board.c index 09a4a4a..7fe84bd 100644 --- a/src/board/system76/lemp9/board.c +++ b/src/board/system76/lemp9/board.c @@ -23,6 +23,8 @@ void board_init(void) { gpio_set(&SWI_N, true); } +void board_on_ac(bool ac) { /* Fix unused variable */ ac = ac; } + void board_event(void) { if (main_cycle == 0) { if (power_state == POWER_STATE_S0 || power_state == POWER_STATE_S3 || power_state == POWER_STATE_DS3) { diff --git a/src/board/system76/lemp9/include/board/gpio.h b/src/board/system76/lemp9/include/board/gpio.h index 34e38d7..a54f45b 100644 --- a/src/board/system76/lemp9/include/board/gpio.h +++ b/src/board/system76/lemp9/include/board/gpio.h @@ -24,6 +24,9 @@ extern struct Gpio __code EC_EN; extern struct Gpio __code EC_RSMRST_N; extern struct Gpio __code EC_SMD_EN_N; extern struct Gpio __code LED_ACIN; +#define HAVE_LED_AIRPLANE_N 0 +#define HAVE_LED_BAT_CHG 0 +#define HAVE_LED_BAT_FULL 0 extern struct Gpio __code LED_PWR; extern struct Gpio __code LID_SW_N; extern struct Gpio __code PCH_DPWROK_EC; diff --git a/src/board/system76/lemp9/include/board/kbled.h b/src/board/system76/lemp9/include/board/kbled.h deleted file mode 100644 index 0fb9cca..0000000 --- a/src/board/system76/lemp9/include/board/kbled.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _BOARD_KBLED_H -#define _BOARD_KBLED_H - -#include - -void kbled_init(void); -void kbled_reset(void); -uint8_t kbled_get(void); -void kbled_set(uint8_t level); - -#endif // _BOARD_KBLED_H diff --git a/src/board/system76/lemp9/kbled.c b/src/board/system76/lemp9/kbled.c index bbe343b..77f20f8 100644 --- a/src/board/system76/lemp9/kbled.c +++ b/src/board/system76/lemp9/kbled.c @@ -42,3 +42,5 @@ void kbled_set(uint8_t level) { } KBLED_DACDAT = raw; } + +void kbled_set_color(uint32_t color) { /*Fix unused variable*/ color = color; } diff --git a/src/board/system76/lemp9/scratch.c b/src/board/system76/lemp9/scratch.c deleted file mode 100644 index e14654d..0000000 --- a/src/board/system76/lemp9/scratch.c +++ /dev/null @@ -1,39 +0,0 @@ -#include <8051.h> -#include - -#include -#include -#include - -// Include scratch ROM -uint8_t __code __at(SCRATCH_OFFSET) scratch_rom[] = { - #include -}; - -// SCAR0 is stored in processor cache, not in xram -volatile uint8_t __xdata __at(0x1040) SCAR0L; -volatile uint8_t __xdata __at(0x1041) SCAR0M; -volatile uint8_t __xdata __at(0x1042) SCAR0H; - -// Enter or exit scratch ROM -void scratch_trampoline(void) { - // Set fans to 100% - DCR2 = 0xFF; - - //TODO: Clear keyboard presses - - // Start watchdog timer - smfi_watchdog(); - - // Disable interrupts - EA = 0; - - // Use DMA mapping to copy flash data - SCAR0H = 0x80; - SCAR0L = (uint8_t)(SCRATCH_OFFSET); - SCAR0M = (uint8_t)(SCRATCH_OFFSET >> 8); - SCAR0H = 0; - - // Jump to scratch reset function - __asm__("ljmp " xstr(SCRATCH_OFFSET)); -} diff --git a/src/board/system76/oryp6/acpi.c b/src/board/system76/oryp6/acpi.c deleted file mode 100644 index 51c3f64..0000000 --- a/src/board/system76/oryp6/acpi.c +++ /dev/null @@ -1,149 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -extern uint8_t sci_extra; - -uint8_t ecos = 0; - -static uint8_t fcmd = 0; -static uint8_t fdat = 0; -static uint8_t fbuf[4] = { 0, 0, 0, 0 }; - -void fcommand(void) { - switch (fcmd) { - // Keyboard backlight - case 0xCA: - switch (fdat) { - // Set LED color - case 0x03: - kbled_set_color( - ((uint32_t)fbuf[0]) | - ((uint32_t)fbuf[1] << 16) | - ((uint32_t)fbuf[2] << 8) - ); - break; - // Set LED brightness - case 0x06: - kbled_set(fbuf[0]); - break; - } - break; - } -} - -uint8_t acpi_read(uint8_t addr) { - uint8_t data = 0; - - #define ACPI_8(K, V) \ - case (K): \ - data = (uint8_t)(V); \ - break - - #define ACPI_16(K, V) \ - ACPI_8(K, V); \ - ACPI_8((K) + 1, (V) >> 8) - - #define ACPI_32(K, V) \ - ACPI_16(K, V); \ - ACPI_16((K) + 2, (V) >> 16) - - switch (addr) { - // Lid state and other flags - case 0x03: - if (gpio_get(&LID_SW_N)) { - // Lid is open - data |= 1 << 0; - } - if (lid_wake) { - data |= 1 << 2; - } - break; - - // Handle AC adapter and battery present - case 0x10: - if (!gpio_get(&ACIN_N)) { - // AC adapter connected - data |= 1 << 0; - } - // BAT0 always connected - TODO - data |= 1 << 2; - break; - - ACPI_16(0x16, battery_design_capacity); - ACPI_16(0x1A, battery_full_capacity); - ACPI_16(0x22, battery_design_voltage); - - case 0x26: - // If AC adapter connected - if (!gpio_get(&ACIN_N)) { - // And battery is using current - if (battery_current != 0) { - // Battery is charging - data |= 1 << 1; - } - } - break; - - ACPI_16(0x2A, battery_current); - ACPI_16(0x2E, battery_remaining_capacity); - ACPI_16(0x32, battery_voltage); - - ACPI_8(0x68, ecos); - - 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); - return data; -} - - -void acpi_write(uint8_t addr, uint8_t data) { - DEBUG("acpi_write %02X = %02X\n", addr, data); - - switch (addr) { - // Lid state and other flags - case 0x03: - lid_wake = (bool)(data & (1 << 2)); - break; - - case 0x68: - ecos = data; - 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/oryp6/board.c b/src/board/system76/oryp6/board.c index f749286..441d85b 100644 --- a/src/board/system76/oryp6/board.c +++ b/src/board/system76/oryp6/board.c @@ -27,8 +27,6 @@ void board_init(void) { gpio_set(&SCI_N, true); gpio_set(&SMI_N, true); gpio_set(&SWI_N, true); - - dgpu_init(); } // Set PL4 using PECI @@ -40,62 +38,31 @@ static int set_power_limit(uint8_t watts) { ); } -void board_event(void) { - bool acin = !gpio_get(&ACIN_N); - gpio_set(&AC_PRESENT, acin); - - static uint8_t last_power_limit = 0; - if (power_state == POWER_STATE_S0) { - uint8_t power_limit = acin ? POWER_LIMIT_AC : POWER_LIMIT_DC; - if (power_limit != last_power_limit) { - // Retry, timeout errors happen occasionally - for (int i = 0; i < 16; i++) { - int res = set_power_limit(power_limit); - DEBUG("set_power_limit %d = %d\n", power_limit, res); - if (res >= 0) { - last_power_limit = power_limit; - break; - } else { - ERROR("set_power_limit failed: %X\n", -res); - } - } - } - } else { - last_power_limit = 0; - } - - if (main_cycle == 0) { - if (!acin) { - // Discharging (no AC adapter) - gpio_set(&LED_BAT_CHG, false); - gpio_set(&LED_BAT_FULL, false); - } else if (battery_current == 0) { - // Fully charged - // TODO: turn off charger - gpio_set(&LED_BAT_CHG, false); - gpio_set(&LED_BAT_FULL, true); +void board_on_ac(bool ac) { + uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC; + // Retry, timeout errors happen occasionally + for (int i = 0; i < 16; i++) { + int res = set_power_limit(power_limit); + DEBUG("set_power_limit %d = %d\n", power_limit, res); + if (res >= 0) { + break; } else { - // Charging - // TODO: detect no battery connected - gpio_set(&LED_BAT_CHG, true); - gpio_set(&LED_BAT_FULL, false); - } - - if (power_state == POWER_STATE_S0 || power_state == POWER_STATE_S3 || power_state == POWER_STATE_DS3) { - // System is on - } else if (!acin) { - // Power off VDD3 if system should be off - gpio_set(&XLP_OUT, 0); - } - - static uint32_t last_time = 0; - uint32_t time = time_get(); - // Only run the following once a second - if (last_time > time || (time - last_time) >= 1000) { - last_time = time; - - // Updates discrete GPU fan status and temps - dgpu_event(); + ERROR("set_power_limit failed: %X\n", -res); } } } + +void board_event(void) { + bool ac = !gpio_get(&ACIN_N); + + static bool last_power_limit_ac = true; + // We don't use power_state because the latency needs to be low + if (gpio_get(&SUSB_N_PCH)) { + if (last_power_limit_ac != ac) { + board_on_ac(ac); + last_power_limit_ac = ac; + } + } else { + last_power_limit_ac = true; + } +} diff --git a/src/board/system76/oryp6/board.mk b/src/board/system76/oryp6/board.mk index 320c1f3..566dc9a 100644 --- a/src/board/system76/oryp6/board.mk +++ b/src/board/system76/oryp6/board.mk @@ -42,6 +42,9 @@ CFLAGS+=\ -DCHARGER_CHARGE_VOLTAGE=16800 \ -DCHARGER_INPUT_CURRENT=13050 +# Enable DGPU support +CFLAGS+=-DHAVE_DGPU=1 + # Set CPU power limits in watts CFLAGS+=\ -DPOWER_LIMIT_AC=180 \ diff --git a/src/board/system76/oryp6/dgpu.c b/src/board/system76/oryp6/dgpu.c deleted file mode 100644 index 1dcf324..0000000 --- a/src/board/system76/oryp6/dgpu.c +++ /dev/null @@ -1,144 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include -#include - -// Fan speed is the lowest requested over HEATUP seconds -#define HEATUP 5 - -// Fan speed is the highest HEATUP speed over COOLDOWN seconds -#define COOLDOWN 20 - -// Interpolate duty cycle -#define INTERPOLATE 0 - -int16_t dgpu_temp = 0; -uint8_t dgpu_duty = 0; - -#define DGPU_TEMP(X) ((int16_t)(X)) -#define PWM_DUTY(X) ((uint8_t)(((((uint16_t)(X)) * 255) + 99) / 100)) - -struct FanPoint { - int16_t temp; - uint8_t duty; -}; - -#define FAN_POINT(T, D) { .temp = DGPU_TEMP(T), .duty = PWM_DUTY(D) } - -// Fan curve with temperature in degrees C, duty cycle in percent -static struct FanPoint __code FAN_POINTS[] = { - FAN_POINT(65, 40), - FAN_POINT(70, 60), - FAN_POINT(75, 75), - FAN_POINT(80, 90), - FAN_POINT(85, 100) -}; - -// Get duty cycle based on temperature, adapted from -// https://github.com/pop-os/system76-power/blob/master/src/fan.rs -static uint8_t fan_duty(int16_t temp) { - for (int i = 0; i < ARRAY_SIZE(FAN_POINTS); i++) { - const struct FanPoint * cur = &FAN_POINTS[i]; - - // If exactly the current temp, return the current duty - if (temp == cur->temp) { - return cur->duty; - } else if (temp < cur->temp) { - // If lower than first temp, return 0% - if (i == 0) { - return PWM_DUTY(0); - } else { - const struct FanPoint * prev = &FAN_POINTS[i - 1]; - -#if INTERPOLATE - // If in between current temp and previous temp, interpolate - if (temp > prev->temp) { - int16_t dtemp = (cur->temp - prev->temp); - int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty); - return (uint8_t)( - ((int16_t)prev->duty) + - ((temp - prev->temp) * dduty) / dtemp - ); - } -#else // INTERPOLATE - return prev->duty; -#endif // INTERPOLATE - } - } - } - - // If no point is found, return 100% - return PWM_DUTY(100); -} - -static uint8_t fan_heatup(uint8_t duty) { - static uint8_t history[HEATUP] = { 0 }; - uint8_t lowest = duty; - - int i; - for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) { - uint8_t value = history[i + 1]; - if (value < lowest) { - lowest = value; - } - history[i] = value; - } - history[i] = duty; - - return lowest; -} - -static uint8_t fan_cooldown(uint8_t duty) { - static uint8_t history[COOLDOWN] = { 0 }; - uint8_t highest = duty; - - int i; - for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) { - uint8_t value = history[i + 1]; - if (value > highest) { - highest = value; - } - history[i] = value; - } - history[i] = duty; - - return highest; -} - -void dgpu_init(void) { - // Set up for i2c usage - i2c_reset(&I2C_DGPU, true); -} - -void dgpu_event(void) { - if (power_state == POWER_STATE_S0 && gpio_get(&DGPU_PWR_EN) && !gpio_get(&GC6_FB_EN)) { - // Use I2CS if in S0 state - int8_t rlts; - int res = i2c_get(&I2C_DGPU, 0x4F, 0x00, &rlts, 1); - if (res == 1) { - dgpu_temp = (int16_t)rlts; - dgpu_duty = fan_duty(dgpu_temp); - } else { - DEBUG("DGPU temp error: %d\n", res); - // Default to 50% if there is an error - dgpu_temp = 0; - dgpu_duty = PWM_DUTY(50); - } - } else { - // Turn fan off if not in S0 state or GPU power not on - dgpu_temp = 0; - dgpu_duty = PWM_DUTY(0); - } - - uint8_t heatup_duty = fan_heatup(dgpu_duty); - uint8_t cooldown_duty = fan_cooldown(heatup_duty); - if (cooldown_duty != DCR4) { - DCR4 = cooldown_duty; - DEBUG("DGPU temp=%d = %d\n", dgpu_temp, cooldown_duty); - } -} diff --git a/src/board/system76/oryp6/include/board/gpio.h b/src/board/system76/oryp6/include/board/gpio.h index 76c43e0..21b8f10 100644 --- a/src/board/system76/oryp6/include/board/gpio.h +++ b/src/board/system76/oryp6/include/board/gpio.h @@ -25,7 +25,7 @@ extern struct Gpio __code EC_EN; extern struct Gpio __code EC_RSMRST_N; extern struct Gpio __code GC6_FB_EN; extern struct Gpio __code LED_ACIN; -extern struct Gpio __code LED_AIRPLANE_N; +#define HAVE_LED_AIRPLANE_N 0 extern struct Gpio __code LED_BAT_CHG; extern struct Gpio __code LED_BAT_FULL; extern struct Gpio __code LED_PWR; diff --git a/src/board/system76/oryp6/include/board/kbled.h b/src/board/system76/oryp6/include/board/kbled.h deleted file mode 100644 index 895542c..0000000 --- a/src/board/system76/oryp6/include/board/kbled.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _BOARD_KBLED_H -#define _BOARD_KBLED_H - -#include - -void kbled_init(void); -void kbled_reset(void); -uint8_t kbled_get(void); -void kbled_set(uint8_t level); -void kbled_set_color(uint32_t color); - -#endif // _BOARD_KBLED_H diff --git a/src/board/system76/oryp6/scratch.c b/src/board/system76/oryp6/scratch.c deleted file mode 100644 index 225d2ff..0000000 --- a/src/board/system76/oryp6/scratch.c +++ /dev/null @@ -1,40 +0,0 @@ -#include <8051.h> -#include - -#include -#include -#include - -// Include scratch ROM -uint8_t __code __at(SCRATCH_OFFSET) scratch_rom[] = { - #include -}; - -// SCAR0 is stored in processor cache, not in xram -volatile uint8_t __xdata __at(0x1040) SCAR0L; -volatile uint8_t __xdata __at(0x1041) SCAR0M; -volatile uint8_t __xdata __at(0x1042) SCAR0H; - -// Enter or exit scratch ROM -void scratch_trampoline(void) { - // Set fans to 100% - DCR2 = 0xFF; - DCR4 = 0xFF; - - //TODO: Clear keyboard presses - - // Start watchdog timer - smfi_watchdog(); - - // Disable interrupts - EA = 0; - - // Use DMA mapping to copy flash data - SCAR0H = 0x80; - SCAR0L = (uint8_t)(SCRATCH_OFFSET); - SCAR0M = (uint8_t)(SCRATCH_OFFSET >> 8); - SCAR0H = 0; - - // Jump to scratch reset function - __asm__("ljmp " xstr(SCRATCH_OFFSET)); -}