Move most code in system76 boards into system76/common
This commit is contained in:
		
				
					committed by
					
						
						Jeremy Soller
					
				
			
			
				
	
			
			
			
						parent
						
							185459b031
						
					
				
				
					commit
					42e88d03b3
				
			@@ -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,61 +33,35 @@ 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) {
 | 
			
		||||
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) {
 | 
			
		||||
                last_power_limit = power_limit;
 | 
			
		||||
            break;
 | 
			
		||||
        } 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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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) {
 | 
			
		||||
@@ -98,4 +70,6 @@ void board_event(void) {
 | 
			
		||||
            gpio_set(&LED_CAP_N, (kbc_leds & 4) == 0);
 | 
			
		||||
            last_kbc_leds = kbc_leds;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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 \
 | 
			
		||||
 
 | 
			
		||||
@@ -1,144 +0,0 @@
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <board/gpio.h>
 | 
			
		||||
#include <board/power.h>
 | 
			
		||||
#include <common/debug.h>
 | 
			
		||||
#include <common/macro.h>
 | 
			
		||||
#include <ec/i2c.h>
 | 
			
		||||
#include <ec/pwm.h>
 | 
			
		||||
 | 
			
		||||
// 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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
#ifndef _BOARD_DGPU_H
 | 
			
		||||
#define _BOARD_DGPU_H
 | 
			
		||||
 | 
			
		||||
void dgpu_init(void);
 | 
			
		||||
void dgpu_event(void);
 | 
			
		||||
 | 
			
		||||
#endif // _BOARD_DGPU_H
 | 
			
		||||
@@ -1,40 +0,0 @@
 | 
			
		||||
#include <8051.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <board/smfi.h>
 | 
			
		||||
#include <common/macro.h>
 | 
			
		||||
#include <ec/pwm.h>
 | 
			
		||||
 | 
			
		||||
// Include scratch ROM
 | 
			
		||||
uint8_t __code __at(SCRATCH_OFFSET) scratch_rom[] = {
 | 
			
		||||
    #include <scratch.h>
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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));
 | 
			
		||||
}
 | 
			
		||||
@@ -6,6 +6,10 @@
 | 
			
		||||
#include <board/peci.h>
 | 
			
		||||
#include <common/debug.h>
 | 
			
		||||
 | 
			
		||||
#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;
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
#include <board/dgpu.h>
 | 
			
		||||
 | 
			
		||||
#if HAVE_DGPU
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
@@ -9,10 +13,18 @@
 | 
			
		||||
#include <ec/pwm.h>
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
@@ -1,7 +1,10 @@
 | 
			
		||||
#ifndef _BOARD_BOARD_H
 | 
			
		||||
#define _BOARD_BOARD_H
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
void board_init(void);
 | 
			
		||||
void board_event(void);
 | 
			
		||||
void board_on_ac(bool ac);
 | 
			
		||||
 | 
			
		||||
#endif // _BOARD_BOARD_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);
 | 
			
		||||
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
#include <arch/time.h>
 | 
			
		||||
#include <board/battery.h>
 | 
			
		||||
#include <board/board.h>
 | 
			
		||||
#include <board/dgpu.h>
 | 
			
		||||
#include <board/ecpm.h>
 | 
			
		||||
#include <board/gpio.h>
 | 
			
		||||
#include <board/gctrl.h>
 | 
			
		||||
@@ -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();
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
#include <arch/delay.h>
 | 
			
		||||
#include <arch/time.h>
 | 
			
		||||
#include <board/battery.h>
 | 
			
		||||
#include <board/board.h>
 | 
			
		||||
#include <board/gpio.h>
 | 
			
		||||
#include <board/kbled.h>
 | 
			
		||||
#include <board/lid.h>
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										58
									
								
								src/board/system76/common/scratch.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/board/system76/common/scratch.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
#include <8051.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <board/dgpu.h>
 | 
			
		||||
#include <board/smfi.h>
 | 
			
		||||
#include <common/macro.h>
 | 
			
		||||
#include <ec/pwm.h>
 | 
			
		||||
 | 
			
		||||
// Include scratch ROM
 | 
			
		||||
uint8_t __code __at(SCRATCH_OFFSET) scratch_rom[] = {
 | 
			
		||||
    #include <scratch.h>
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#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));
 | 
			
		||||
}
 | 
			
		||||
@@ -1,161 +0,0 @@
 | 
			
		||||
#include <board/acpi.h>
 | 
			
		||||
#include <board/battery.h>
 | 
			
		||||
#include <board/gpio.h>
 | 
			
		||||
#include <board/kbled.h>
 | 
			
		||||
#include <board/lid.h>
 | 
			
		||||
#include <board/peci.h>
 | 
			
		||||
#include <common/debug.h>
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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) {}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +0,0 @@
 | 
			
		||||
#ifndef _BOARD_KBLED_H
 | 
			
		||||
#define _BOARD_KBLED_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
@@ -1,39 +0,0 @@
 | 
			
		||||
#include <8051.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <board/smfi.h>
 | 
			
		||||
#include <common/macro.h>
 | 
			
		||||
#include <ec/pwm.h>
 | 
			
		||||
 | 
			
		||||
// Include scratch ROM
 | 
			
		||||
uint8_t __code __at(SCRATCH_OFFSET) scratch_rom[] = {
 | 
			
		||||
    #include <scratch.h>
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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));
 | 
			
		||||
}
 | 
			
		||||
@@ -1,157 +0,0 @@
 | 
			
		||||
#include <board/acpi.h>
 | 
			
		||||
#include <board/battery.h>
 | 
			
		||||
#include <board/gpio.h>
 | 
			
		||||
#include <board/kbled.h>
 | 
			
		||||
#include <board/lid.h>
 | 
			
		||||
#include <board/peci.h>
 | 
			
		||||
#include <common/debug.h>
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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) {}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +0,0 @@
 | 
			
		||||
#ifndef _BOARD_KBLED_H
 | 
			
		||||
#define _BOARD_KBLED_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
void kbled_init(void);
 | 
			
		||||
void kbled_reset(void);
 | 
			
		||||
uint8_t kbled_get(void);
 | 
			
		||||
void kbled_set(uint8_t level);
 | 
			
		||||
 | 
			
		||||
#endif // _BOARD_KBLED_H
 | 
			
		||||
@@ -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; }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,39 +0,0 @@
 | 
			
		||||
#include <8051.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <board/smfi.h>
 | 
			
		||||
#include <common/macro.h>
 | 
			
		||||
#include <ec/pwm.h>
 | 
			
		||||
 | 
			
		||||
// Include scratch ROM
 | 
			
		||||
uint8_t __code __at(SCRATCH_OFFSET) scratch_rom[] = {
 | 
			
		||||
    #include <scratch.h>
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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));
 | 
			
		||||
}
 | 
			
		||||
@@ -1,161 +0,0 @@
 | 
			
		||||
#include <board/acpi.h>
 | 
			
		||||
#include <board/battery.h>
 | 
			
		||||
#include <board/gpio.h>
 | 
			
		||||
#include <board/kbled.h>
 | 
			
		||||
#include <board/lid.h>
 | 
			
		||||
#include <board/peci.h>
 | 
			
		||||
#include <common/debug.h>
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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) {
 | 
			
		||||
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) {
 | 
			
		||||
                last_power_limit = power_limit;
 | 
			
		||||
            break;
 | 
			
		||||
        } 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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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();
 | 
			
		||||
        }
 | 
			
		||||
        last_power_limit_ac = true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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 \
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
#ifndef _BOARD_DGPU_H
 | 
			
		||||
#define _BOARD_DGPU_H
 | 
			
		||||
 | 
			
		||||
void dgpu_init(void);
 | 
			
		||||
void dgpu_event(void);
 | 
			
		||||
 | 
			
		||||
#endif // _BOARD_DGPU_H
 | 
			
		||||
@@ -1,12 +0,0 @@
 | 
			
		||||
#ifndef _BOARD_KBLED_H
 | 
			
		||||
#define _BOARD_KBLED_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
@@ -1,40 +0,0 @@
 | 
			
		||||
#include <8051.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <board/smfi.h>
 | 
			
		||||
#include <common/macro.h>
 | 
			
		||||
#include <ec/pwm.h>
 | 
			
		||||
 | 
			
		||||
// Include scratch ROM
 | 
			
		||||
uint8_t __code __at(SCRATCH_OFFSET) scratch_rom[] = {
 | 
			
		||||
    #include <scratch.h>
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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));
 | 
			
		||||
}
 | 
			
		||||
@@ -1,145 +0,0 @@
 | 
			
		||||
#include <board/acpi.h>
 | 
			
		||||
#include <board/battery.h>
 | 
			
		||||
#include <board/gpio.h>
 | 
			
		||||
#include <board/kbled.h>
 | 
			
		||||
#include <board/lid.h>
 | 
			
		||||
#include <board/peci.h>
 | 
			
		||||
#include <common/debug.h>
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +0,0 @@
 | 
			
		||||
#ifndef _BOARD_KBLED_H
 | 
			
		||||
#define _BOARD_KBLED_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
void kbled_init(void);
 | 
			
		||||
void kbled_reset(void);
 | 
			
		||||
uint8_t kbled_get(void);
 | 
			
		||||
void kbled_set(uint8_t level);
 | 
			
		||||
 | 
			
		||||
#endif // _BOARD_KBLED_H
 | 
			
		||||
@@ -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; }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,39 +0,0 @@
 | 
			
		||||
#include <8051.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <board/smfi.h>
 | 
			
		||||
#include <common/macro.h>
 | 
			
		||||
#include <ec/pwm.h>
 | 
			
		||||
 | 
			
		||||
// Include scratch ROM
 | 
			
		||||
uint8_t __code __at(SCRATCH_OFFSET) scratch_rom[] = {
 | 
			
		||||
    #include <scratch.h>
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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));
 | 
			
		||||
}
 | 
			
		||||
@@ -1,149 +0,0 @@
 | 
			
		||||
#include <board/acpi.h>
 | 
			
		||||
#include <board/battery.h>
 | 
			
		||||
#include <board/gpio.h>
 | 
			
		||||
#include <board/kbled.h>
 | 
			
		||||
#include <board/lid.h>
 | 
			
		||||
#include <board/peci.h>
 | 
			
		||||
#include <common/debug.h>
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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) {
 | 
			
		||||
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) {
 | 
			
		||||
                    last_power_limit = power_limit;
 | 
			
		||||
            break;
 | 
			
		||||
        } 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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
        } 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();
 | 
			
		||||
        }
 | 
			
		||||
        last_power_limit_ac = true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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 \
 | 
			
		||||
 
 | 
			
		||||
@@ -1,144 +0,0 @@
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <board/gpio.h>
 | 
			
		||||
#include <board/power.h>
 | 
			
		||||
#include <common/debug.h>
 | 
			
		||||
#include <common/macro.h>
 | 
			
		||||
#include <ec/i2c.h>
 | 
			
		||||
#include <ec/pwm.h>
 | 
			
		||||
 | 
			
		||||
// 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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +0,0 @@
 | 
			
		||||
#ifndef _BOARD_KBLED_H
 | 
			
		||||
#define _BOARD_KBLED_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
@@ -1,40 +0,0 @@
 | 
			
		||||
#include <8051.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <board/smfi.h>
 | 
			
		||||
#include <common/macro.h>
 | 
			
		||||
#include <ec/pwm.h>
 | 
			
		||||
 | 
			
		||||
// Include scratch ROM
 | 
			
		||||
uint8_t __code __at(SCRATCH_OFFSET) scratch_rom[] = {
 | 
			
		||||
    #include <scratch.h>
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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));
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user