Move most code in system76 boards into system76/common
This commit is contained in:
parent
185459b031
commit
42e88d03b3
@ -22,8 +22,6 @@ void board_init(void) {
|
|||||||
gpio_set(&SCI_N, true);
|
gpio_set(&SCI_N, true);
|
||||||
gpio_set(&SMI_N, true);
|
gpio_set(&SMI_N, true);
|
||||||
gpio_set(&SWI_N, true);
|
gpio_set(&SWI_N, true);
|
||||||
|
|
||||||
dgpu_init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set PL4 using PECI
|
// Set PL4 using PECI
|
||||||
@ -35,61 +33,35 @@ static int set_power_limit(uint8_t watts) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void board_event(void) {
|
void board_on_ac(bool ac) {
|
||||||
bool acin = !gpio_get(&ACIN_N);
|
uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC;
|
||||||
gpio_set(&AC_PRESENT, acin);
|
// Retry, timeout errors happen occasionally
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
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);
|
int res = set_power_limit(power_limit);
|
||||||
DEBUG("set_power_limit %d = %d\n", power_limit, res);
|
DEBUG("set_power_limit %d = %d\n", power_limit, res);
|
||||||
if (res >= 0) {
|
if (res >= 0) {
|
||||||
last_power_limit = power_limit;
|
break;
|
||||||
} else {
|
} else {
|
||||||
ERROR("set_power_limit failed: %X\n", -res);
|
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 {
|
} else {
|
||||||
last_power_limit = 0;
|
last_power_limit_ac = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (main_cycle == 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set keyboard LEDs
|
// Set keyboard LEDs
|
||||||
static uint8_t last_kbc_leds = 0;
|
static uint8_t last_kbc_leds = 0;
|
||||||
if (kbc_leds != last_kbc_leds) {
|
if (kbc_leds != last_kbc_leds) {
|
||||||
@ -98,4 +70,6 @@ void board_event(void) {
|
|||||||
gpio_set(&LED_CAP_N, (kbc_leds & 4) == 0);
|
gpio_set(&LED_CAP_N, (kbc_leds & 4) == 0);
|
||||||
last_kbc_leds = kbc_leds;
|
last_kbc_leds = kbc_leds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,26 @@ CFLAGS+=-DI2C_SMBUS=I2C_4
|
|||||||
# Set touchpad PS2 bus
|
# Set touchpad PS2 bus
|
||||||
CFLAGS+=-DPS2_TOUCHPAD=PS2_3
|
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
|
# Set smart charger parameters
|
||||||
CFLAGS+=\
|
CFLAGS+=\
|
||||||
-DCHARGER_CHARGE_CURRENT=1536 \
|
-DCHARGER_CHARGE_CURRENT=1536 \
|
||||||
-DCHARGER_CHARGE_VOLTAGE=12600 \
|
-DCHARGER_CHARGE_VOLTAGE=12600 \
|
||||||
-DCHARGER_INPUT_CURRENT=11800
|
-DCHARGER_INPUT_CURRENT=11800
|
||||||
|
|
||||||
|
# Enable DGPU support
|
||||||
|
CFLAGS+=-DHAVE_DGPU=1
|
||||||
|
|
||||||
# Set CPU power limits in watts
|
# Set CPU power limits in watts
|
||||||
CFLAGS+=\
|
CFLAGS+=\
|
||||||
-DPOWER_LIMIT_AC=180 \
|
-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 <board/peci.h>
|
||||||
#include <common/debug.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;
|
extern uint8_t sci_extra;
|
||||||
|
|
||||||
uint8_t ecos = 0;
|
uint8_t ecos = 0;
|
||||||
@ -19,6 +23,14 @@ void fcommand(void) {
|
|||||||
// Keyboard backlight
|
// Keyboard backlight
|
||||||
case 0xCA:
|
case 0xCA:
|
||||||
switch (fdat) {
|
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
|
// Set LED color
|
||||||
case 0x03:
|
case 0x03:
|
||||||
kbled_set_color(
|
kbled_set_color(
|
||||||
@ -97,12 +109,14 @@ uint8_t acpi_read(uint8_t addr) {
|
|||||||
|
|
||||||
ACPI_8(0xCC, sci_extra);
|
ACPI_8(0xCC, sci_extra);
|
||||||
|
|
||||||
|
#if HAVE_LED_AIRPLANE_N
|
||||||
// Airplane mode LED
|
// Airplane mode LED
|
||||||
case 0xD9:
|
case 0xD9:
|
||||||
if (!gpio_get(&LED_AIRPLANE_N)) {
|
if (!gpio_get(&LED_AIRPLANE_N)) {
|
||||||
data |= (1 << 6);
|
data |= (1 << 6);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#endif // HAVE_LED_AIRPLANE_N
|
||||||
|
|
||||||
// Set size of flash (from old firmware)
|
// Set size of flash (from old firmware)
|
||||||
ACPI_8 (0xE5, 0x80);
|
ACPI_8 (0xE5, 0x80);
|
||||||
@ -133,10 +147,12 @@ void acpi_write(uint8_t addr, uint8_t data) {
|
|||||||
ecos = data;
|
ecos = data;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if HAVE_LED_AIRPLANE_N
|
||||||
// Airplane mode LED
|
// Airplane mode LED
|
||||||
case 0xD9:
|
case 0xD9:
|
||||||
gpio_set(&LED_AIRPLANE_N, !(bool)(data & (1 << 6)));
|
gpio_set(&LED_AIRPLANE_N, !(bool)(data & (1 << 6)));
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case 0xF8:
|
case 0xF8:
|
||||||
fcmd = data;
|
fcmd = data;
|
@ -1,3 +1,7 @@
|
|||||||
|
#include <board/dgpu.h>
|
||||||
|
|
||||||
|
#if HAVE_DGPU
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -9,10 +13,18 @@
|
|||||||
#include <ec/pwm.h>
|
#include <ec/pwm.h>
|
||||||
|
|
||||||
// Fan speed is the lowest requested over HEATUP seconds
|
// 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
|
// 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
|
// Interpolate duty cycle
|
||||||
#define INTERPOLATE 0
|
#define INTERPOLATE 0
|
||||||
@ -32,11 +44,15 @@ struct FanPoint {
|
|||||||
|
|
||||||
// Fan curve with temperature in degrees C, duty cycle in percent
|
// Fan curve with temperature in degrees C, duty cycle in percent
|
||||||
static struct FanPoint __code FAN_POINTS[] = {
|
static struct FanPoint __code FAN_POINTS[] = {
|
||||||
|
#ifdef BOARD_DGPU_FAN_POINTS
|
||||||
|
BOARD_DGPU_FAN_POINTS
|
||||||
|
#else
|
||||||
FAN_POINT(70, 40),
|
FAN_POINT(70, 40),
|
||||||
FAN_POINT(75, 50),
|
FAN_POINT(75, 50),
|
||||||
FAN_POINT(80, 60),
|
FAN_POINT(80, 60),
|
||||||
FAN_POINT(85, 65),
|
FAN_POINT(85, 65),
|
||||||
FAN_POINT(90, 65)
|
FAN_POINT(90, 65)
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get duty cycle based on temperature, adapted from
|
// 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);
|
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
|
#ifndef _BOARD_BOARD_H
|
||||||
#define _BOARD_BOARD_H
|
#define _BOARD_BOARD_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
void board_init(void);
|
void board_init(void);
|
||||||
void board_event(void);
|
void board_event(void);
|
||||||
|
void board_on_ac(bool ac);
|
||||||
|
|
||||||
#endif // _BOARD_BOARD_H
|
#endif // _BOARD_BOARD_H
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
#ifndef _BOARD_DGPU_H
|
#ifndef _BOARD_DGPU_H
|
||||||
#define _BOARD_DGPU_H
|
#define _BOARD_DGPU_H
|
||||||
|
|
||||||
|
#ifndef HAVE_DGPU
|
||||||
|
#define HAVE_DGPU 0
|
||||||
|
#endif
|
||||||
|
|
||||||
void dgpu_init(void);
|
void dgpu_init(void);
|
||||||
void dgpu_event(void);
|
void dgpu_event(void);
|
||||||
|
|
@ -6,6 +6,7 @@
|
|||||||
#include <arch/time.h>
|
#include <arch/time.h>
|
||||||
#include <board/battery.h>
|
#include <board/battery.h>
|
||||||
#include <board/board.h>
|
#include <board/board.h>
|
||||||
|
#include <board/dgpu.h>
|
||||||
#include <board/ecpm.h>
|
#include <board/ecpm.h>
|
||||||
#include <board/gpio.h>
|
#include <board/gpio.h>
|
||||||
#include <board/gctrl.h>
|
#include <board/gctrl.h>
|
||||||
@ -48,6 +49,9 @@ void init(void) {
|
|||||||
gpio_init();
|
gpio_init();
|
||||||
|
|
||||||
// Can happen in any order
|
// Can happen in any order
|
||||||
|
#if HAVE_DGPU
|
||||||
|
dgpu_init();
|
||||||
|
#endif
|
||||||
ecpm_init();
|
ecpm_init();
|
||||||
kbc_init();
|
kbc_init();
|
||||||
kbled_init();
|
kbled_init();
|
||||||
@ -115,6 +119,11 @@ void main(void) {
|
|||||||
// Updates fan status and temps
|
// Updates fan status and temps
|
||||||
peci_event();
|
peci_event();
|
||||||
|
|
||||||
|
#if HAVE_DGPU
|
||||||
|
// Updates discrete GPU fan status and temps
|
||||||
|
dgpu_event();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Updates battery status
|
// Updates battery status
|
||||||
battery_event();
|
battery_event();
|
||||||
}
|
}
|
||||||
|
@ -42,21 +42,21 @@ struct FanPoint {
|
|||||||
#define FAN_POINT(T, D) { .temp = PECI_TEMP(T), .duty = PWM_DUTY(D) }
|
#define FAN_POINT(T, D) { .temp = PECI_TEMP(T), .duty = PWM_DUTY(D) }
|
||||||
|
|
||||||
// Fan curve with temperature in degrees C, duty cycle in percent
|
// 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
|
#ifdef BOARD_FAN_POINTS
|
||||||
BOARD_FAN_POINTS
|
BOARD_FAN_POINTS
|
||||||
#else
|
#else
|
||||||
FAN_POINT(65, 40),
|
FAN_POINT(70, 40),
|
||||||
FAN_POINT(70, 60),
|
FAN_POINT(75, 50),
|
||||||
FAN_POINT(75, 75),
|
FAN_POINT(80, 60),
|
||||||
FAN_POINT(80, 90),
|
FAN_POINT(85, 65),
|
||||||
FAN_POINT(85, 100)
|
FAN_POINT(90, 65)
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get duty cycle based on temperature, adapted from
|
// Get duty cycle based on temperature, adapted from
|
||||||
// https://github.com/pop-os/system76-power/blob/master/src/fan.rs
|
// 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++) {
|
for (int i = 0; i < ARRAY_SIZE(FAN_POINTS); i++) {
|
||||||
const struct FanPoint * cur = &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);
|
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 };
|
static uint8_t history[HEATUP] = { 0 };
|
||||||
uint8_t lowest = duty;
|
uint8_t lowest = duty;
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ uint8_t fan_heatup(uint8_t duty) {
|
|||||||
return lowest;
|
return lowest;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t fan_cooldown(uint8_t duty) {
|
static uint8_t fan_cooldown(uint8_t duty) {
|
||||||
static uint8_t history[COOLDOWN] = { 0 };
|
static uint8_t history[COOLDOWN] = { 0 };
|
||||||
uint8_t highest = duty;
|
uint8_t highest = duty;
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <arch/delay.h>
|
#include <arch/delay.h>
|
||||||
#include <arch/time.h>
|
#include <arch/time.h>
|
||||||
#include <board/battery.h>
|
#include <board/battery.h>
|
||||||
|
#include <board/board.h>
|
||||||
#include <board/gpio.h>
|
#include <board/gpio.h>
|
||||||
#include <board/kbled.h>
|
#include <board/kbled.h>
|
||||||
#include <board/lid.h>
|
#include <board/lid.h>
|
||||||
@ -23,6 +24,14 @@
|
|||||||
#define HAVE_EC_EN 1
|
#define HAVE_EC_EN 1
|
||||||
#endif
|
#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
|
#ifndef HAVE_PCH_DPWROK_EC
|
||||||
#define HAVE_PCH_DPWROK_EC 1
|
#define HAVE_PCH_DPWROK_EC 1
|
||||||
#endif
|
#endif
|
||||||
@ -35,6 +44,9 @@
|
|||||||
#define HAVE_SLP_SUS_N 1
|
#define HAVE_SLP_SUS_N 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_XLP_OUT
|
||||||
|
#define HAVE_XLP_OUT 1
|
||||||
|
#endif
|
||||||
#ifndef HAVE_SUSWARN_N
|
#ifndef HAVE_SUSWARN_N
|
||||||
#define HAVE_SUSWARN_N 1
|
#define HAVE_SUSWARN_N 1
|
||||||
#endif
|
#endif
|
||||||
@ -47,6 +59,10 @@
|
|||||||
#define HAVE_VA_EC_EN 1
|
#define HAVE_VA_EC_EN 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_XLP_OUT
|
||||||
|
#define HAVE_XLP_OUT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
extern uint8_t main_cycle;
|
extern uint8_t main_cycle;
|
||||||
|
|
||||||
// VccRTC stable (55%) to RTCRST# high
|
// VccRTC stable (55%) to RTCRST# high
|
||||||
@ -326,6 +342,8 @@ void power_event(void) {
|
|||||||
static bool ac_last = true;
|
static bool ac_last = true;
|
||||||
bool ac_new = gpio_get(&ACIN_N);
|
bool ac_new = gpio_get(&ACIN_N);
|
||||||
if (ac_new != ac_last) {
|
if (ac_new != ac_last) {
|
||||||
|
board_on_ac(!ac_new);
|
||||||
|
|
||||||
DEBUG("Power adapter ");
|
DEBUG("Power adapter ");
|
||||||
if (ac_new) {
|
if (ac_new) {
|
||||||
DEBUG("unplugged\n");
|
DEBUG("unplugged\n");
|
||||||
@ -350,6 +368,8 @@ void power_event(void) {
|
|||||||
}
|
}
|
||||||
ac_last = ac_new;
|
ac_last = ac_new;
|
||||||
|
|
||||||
|
gpio_set(&AC_PRESENT, !ac_new);
|
||||||
|
|
||||||
// Read power switch state
|
// Read power switch state
|
||||||
static bool ps_last = true;
|
static bool ps_last = true;
|
||||||
bool ps_new = gpio_get(&PWR_SW_N);
|
bool ps_new = gpio_get(&PWR_SW_N);
|
||||||
@ -498,5 +518,29 @@ void power_event(void) {
|
|||||||
gpio_set(&LED_ACIN, !gpio_get(&LED_ACIN));
|
gpio_set(&LED_ACIN, !gpio_get(&LED_ACIN));
|
||||||
last_time = time;
|
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);
|
gpio_set(&SWI_N, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void board_event(void) {
|
void board_on_ac(bool ac) { /* Fix unused variable */ ac = ac; }
|
||||||
if (main_cycle == 0) {
|
|
||||||
if (gpio_get(&ACIN_N)) {
|
void board_event(void) {}
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -48,5 +48,6 @@ extern struct Gpio __code VA_EC_EN;
|
|||||||
extern struct Gpio __code VR_ON;
|
extern struct Gpio __code VR_ON;
|
||||||
extern struct Gpio __code WLAN_EN;
|
extern struct Gpio __code WLAN_EN;
|
||||||
extern struct Gpio __code WLAN_PWR_EN;
|
extern struct Gpio __code WLAN_PWR_EN;
|
||||||
|
#define HAVE_XLP_OUT 0
|
||||||
|
|
||||||
#endif // _BOARD_GPIO_H
|
#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);
|
gpio_set(&SWI_N, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void board_event(void) {
|
void board_on_ac(bool ac) { /* Fix unused variable */ ac = ac; }
|
||||||
if (main_cycle == 0) {
|
|
||||||
if (gpio_get(&ACIN_N)) {
|
void board_event(void) {}
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -48,5 +48,6 @@ extern struct Gpio __code VA_EC_EN;
|
|||||||
extern struct Gpio __code VR_ON;
|
extern struct Gpio __code VR_ON;
|
||||||
extern struct Gpio __code WLAN_EN;
|
extern struct Gpio __code WLAN_EN;
|
||||||
extern struct Gpio __code WLAN_PWR_EN;
|
extern struct Gpio __code WLAN_PWR_EN;
|
||||||
|
#define HAVE_XLP_OUT 0
|
||||||
|
|
||||||
#endif // _BOARD_GPIO_H
|
#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;
|
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(&SCI_N, true);
|
||||||
gpio_set(&SMI_N, true);
|
gpio_set(&SMI_N, true);
|
||||||
gpio_set(&SWI_N, true);
|
gpio_set(&SWI_N, true);
|
||||||
|
|
||||||
dgpu_init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set PL4 using PECI
|
// Set PL4 using PECI
|
||||||
@ -36,58 +34,31 @@ static int set_power_limit(uint8_t watts) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void board_event(void) {
|
void board_on_ac(bool ac) {
|
||||||
bool acin = !gpio_get(&ACIN_N);
|
uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC;
|
||||||
gpio_set(&AC_PRESENT, acin);
|
// Retry, timeout errors happen occasionally
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
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);
|
int res = set_power_limit(power_limit);
|
||||||
DEBUG("set_power_limit %d = %d\n", power_limit, res);
|
DEBUG("set_power_limit %d = %d\n", power_limit, res);
|
||||||
if (res >= 0) {
|
if (res >= 0) {
|
||||||
last_power_limit = power_limit;
|
break;
|
||||||
} else {
|
} else {
|
||||||
ERROR("set_power_limit failed: %X\n", -res);
|
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 {
|
} 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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,26 @@ CFLAGS+=-DI2C_SMBUS=I2C_4
|
|||||||
# Set touchpad PS2 bus
|
# Set touchpad PS2 bus
|
||||||
CFLAGS+=-DPS2_TOUCHPAD=PS2_3
|
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
|
# Set smart charger parameters
|
||||||
CFLAGS+=\
|
CFLAGS+=\
|
||||||
-DCHARGER_CHARGE_CURRENT=1536 \
|
-DCHARGER_CHARGE_CURRENT=1536 \
|
||||||
-DCHARGER_CHARGE_VOLTAGE=16800 \
|
-DCHARGER_CHARGE_VOLTAGE=16800 \
|
||||||
-DCHARGER_INPUT_CURRENT=9230
|
-DCHARGER_INPUT_CURRENT=9230
|
||||||
|
|
||||||
|
# Enable DGPU support
|
||||||
|
CFLAGS+=-DHAVE_DGPU=1
|
||||||
|
|
||||||
# Set CPU power limits in watts
|
# Set CPU power limits in watts
|
||||||
CFLAGS+=\
|
CFLAGS+=\
|
||||||
-DPOWER_LIMIT_AC=180 \
|
-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);
|
gpio_set(&SWI_N, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void board_on_ac(bool ac) { /* Fix unused variable */ ac = ac; }
|
||||||
|
|
||||||
void board_event(void) {
|
void board_event(void) {
|
||||||
if (main_cycle == 0) {
|
if (main_cycle == 0) {
|
||||||
if (power_state == POWER_STATE_S0 || power_state == POWER_STATE_S3 || power_state == POWER_STATE_DS3) {
|
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_RSMRST_N;
|
||||||
extern struct Gpio __code EC_SMD_EN_N;
|
extern struct Gpio __code EC_SMD_EN_N;
|
||||||
extern struct Gpio __code LED_ACIN;
|
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 LED_PWR;
|
||||||
extern struct Gpio __code LID_SW_N;
|
extern struct Gpio __code LID_SW_N;
|
||||||
extern struct Gpio __code PCH_DPWROK_EC;
|
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;
|
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(&SCI_N, true);
|
||||||
gpio_set(&SMI_N, true);
|
gpio_set(&SMI_N, true);
|
||||||
gpio_set(&SWI_N, true);
|
gpio_set(&SWI_N, true);
|
||||||
|
|
||||||
dgpu_init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set PL4 using PECI
|
// Set PL4 using PECI
|
||||||
@ -40,62 +38,31 @@ static int set_power_limit(uint8_t watts) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void board_event(void) {
|
void board_on_ac(bool ac) {
|
||||||
bool acin = !gpio_get(&ACIN_N);
|
uint8_t power_limit = ac ? POWER_LIMIT_AC : POWER_LIMIT_DC;
|
||||||
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
|
// Retry, timeout errors happen occasionally
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
int res = set_power_limit(power_limit);
|
int res = set_power_limit(power_limit);
|
||||||
DEBUG("set_power_limit %d = %d\n", power_limit, res);
|
DEBUG("set_power_limit %d = %d\n", power_limit, res);
|
||||||
if (res >= 0) {
|
if (res >= 0) {
|
||||||
last_power_limit = power_limit;
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
ERROR("set_power_limit failed: %X\n", -res);
|
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 {
|
} 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_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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,9 @@ CFLAGS+=\
|
|||||||
-DCHARGER_CHARGE_VOLTAGE=16800 \
|
-DCHARGER_CHARGE_VOLTAGE=16800 \
|
||||||
-DCHARGER_INPUT_CURRENT=13050
|
-DCHARGER_INPUT_CURRENT=13050
|
||||||
|
|
||||||
|
# Enable DGPU support
|
||||||
|
CFLAGS+=-DHAVE_DGPU=1
|
||||||
|
|
||||||
# Set CPU power limits in watts
|
# Set CPU power limits in watts
|
||||||
CFLAGS+=\
|
CFLAGS+=\
|
||||||
-DPOWER_LIMIT_AC=180 \
|
-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 EC_RSMRST_N;
|
||||||
extern struct Gpio __code GC6_FB_EN;
|
extern struct Gpio __code GC6_FB_EN;
|
||||||
extern struct Gpio __code LED_ACIN;
|
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_CHG;
|
||||||
extern struct Gpio __code LED_BAT_FULL;
|
extern struct Gpio __code LED_BAT_FULL;
|
||||||
extern struct Gpio __code LED_PWR;
|
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));
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user