System76 common board directory (#53)
* Move configuration for battery into board.mk * lemp9: remove tcpm code * Move touchpad to its own module * Add kbled_reset to all platforms, move items to run on CPU reset to a function * Add defines for battery and charger address * Add I2C_0 export to it5570e * Move common system76 board functions into src/board/system76/common
This commit is contained in:
4
Makefile
4
Makefile
@ -4,8 +4,8 @@
|
||||
ifeq ($(BOARD),)
|
||||
all:
|
||||
@echo "Please set BOARD to one of the following:"
|
||||
@cd src/board && for board in */*; do \
|
||||
echo " $$board"; \
|
||||
@cd src/board && for board in */*/board.mk; do \
|
||||
echo " $$(dirname "$$board")"; \
|
||||
done
|
||||
@exit 1
|
||||
else
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include <board/smbus.h>
|
||||
#include <common/debug.h>
|
||||
|
||||
#define BATTERY_ADDRESS 0x0B
|
||||
#define CHARGER_ADDRESS 0x09
|
||||
|
||||
// ChargeOption0 flags
|
||||
// Low Power Mode Enable
|
||||
@ -17,7 +19,7 @@ int battery_charger_disable(void) {
|
||||
|
||||
// Set charge option 0 with 175s watchdog
|
||||
res = smbus_write(
|
||||
0x09,
|
||||
CHARGER_ADDRESS,
|
||||
0x12,
|
||||
SBC_EN_LWPWR |
|
||||
SBC_WDTMR_ADJ_175S |
|
||||
@ -26,15 +28,15 @@ int battery_charger_disable(void) {
|
||||
);
|
||||
|
||||
// Disable charge current
|
||||
res = smbus_write(0x09, 0x14, 0);
|
||||
res = smbus_write(CHARGER_ADDRESS, 0x14, 0);
|
||||
if (res < 0) return res;
|
||||
|
||||
// Disable charge voltage
|
||||
res = smbus_write(0x09, 0x15, 0);
|
||||
res = smbus_write(CHARGER_ADDRESS, 0x15, 0);
|
||||
if (res < 0) return res;
|
||||
|
||||
// Disable input current
|
||||
res = smbus_write(0x09, 0x3F, 0);
|
||||
res = smbus_write(CHARGER_ADDRESS, 0x3F, 0);
|
||||
if (res < 0) return res;
|
||||
|
||||
return 0;
|
||||
@ -46,22 +48,21 @@ int battery_charger_enable(void) {
|
||||
res = battery_charger_disable();
|
||||
if (res < 0) return res;
|
||||
|
||||
// Set charge current to ~1.54 A
|
||||
res = smbus_write(0x09, 0x14, 0x061C);
|
||||
// Set charge current in mA
|
||||
res = smbus_write(CHARGER_ADDRESS, 0x14, CHARGER_CHARGE_CURRENT);
|
||||
if (res < 0) return res;
|
||||
|
||||
// Set charge voltage to 8.8 V
|
||||
res = smbus_write(0x09, 0x15, 0x2260);
|
||||
// Set charge voltage in mV
|
||||
res = smbus_write(CHARGER_ADDRESS, 0x15, CHARGER_CHARGE_VOLTAGE);
|
||||
if (res < 0) return res;
|
||||
|
||||
// Set input current to ~3.2 A
|
||||
// TODO: figure out why input current must be divided by 2
|
||||
res = smbus_write(0x09, 0x3F, 0x0C80 / 2);
|
||||
// Set input current in mA
|
||||
res = smbus_write(CHARGER_ADDRESS, 0x3F, CHARGER_INPUT_CURRENT);
|
||||
if (res < 0) return res;
|
||||
|
||||
// Set charge option 0 with watchdog disabled
|
||||
res = smbus_write(
|
||||
0x09,
|
||||
CHARGER_ADDRESS,
|
||||
0x12,
|
||||
SBC_EN_LWPWR |
|
||||
SBC_PWM_FREQ_800KHZ |
|
||||
@ -85,7 +86,7 @@ void battery_event(void) {
|
||||
int res = 0;
|
||||
|
||||
#define command(N, V) { \
|
||||
res = smbus_read(0x0B, V, &N); \
|
||||
res = smbus_read(BATTERY_ADDRESS, V, &N); \
|
||||
if (res < 0) { \
|
||||
N = 0; \
|
||||
} \
|
||||
@ -119,24 +120,24 @@ void battery_debug(void) {
|
||||
}
|
||||
|
||||
DEBUG("Battery:\n");
|
||||
command(Temperature, 0x0B, 0x08);
|
||||
command(Voltage, 0x0B, 0x09);
|
||||
command(Current, 0x0B, 0x0A);
|
||||
command(Charge, 0x0B, 0x0D);
|
||||
command(Status, 0x0B, 0x16);
|
||||
command(Temperature, BATTERY_ADDRESS, 0x08);
|
||||
command(Voltage, BATTERY_ADDRESS, 0x09);
|
||||
command(Current, BATTERY_ADDRESS, 0x0A);
|
||||
command(Charge, BATTERY_ADDRESS, 0x0D);
|
||||
command(Status, BATTERY_ADDRESS, 0x16);
|
||||
|
||||
DEBUG("Charger:\n");
|
||||
command(ChargeOption0, 0x09, 0x12);
|
||||
command(ChargeOption1, 0x09, 0x3B);
|
||||
command(ChargeOption2, 0x09, 0x38);
|
||||
command(ChargeOption3, 0x09, 0x37);
|
||||
command(ChargeCurrent, 0x09, 0x14);
|
||||
command(ChargeVoltage, 0x09, 0x15);
|
||||
command(DishargeCurrent, 0x09, 0x39);
|
||||
command(InputCurrent, 0x09, 0x3F);
|
||||
command(ProchotOption0, 0x09, 0x3C);
|
||||
command(ProchotOption1, 0x09, 0x3D);
|
||||
command(ProchotStatus, 0x09, 0x3A);
|
||||
command(ChargeOption0, CHARGER_ADDRESS, 0x12);
|
||||
command(ChargeOption1, CHARGER_ADDRESS, 0x3B);
|
||||
command(ChargeOption2, CHARGER_ADDRESS, 0x38);
|
||||
command(ChargeOption3, CHARGER_ADDRESS, 0x37);
|
||||
command(ChargeCurrent, CHARGER_ADDRESS, 0x14);
|
||||
command(ChargeVoltage, CHARGER_ADDRESS, 0x15);
|
||||
command(DishargeCurrent, CHARGER_ADDRESS, 0x39);
|
||||
command(InputCurrent, CHARGER_ADDRESS, 0x3F);
|
||||
command(ProchotOption0, CHARGER_ADDRESS, 0x3C);
|
||||
command(ProchotOption1, CHARGER_ADDRESS, 0x3D);
|
||||
command(ProchotStatus, CHARGER_ADDRESS, 0x3A);
|
||||
|
||||
#undef command
|
||||
}
|
24
src/board/system76/common/common.mk
Normal file
24
src/board/system76/common/common.mk
Normal file
@ -0,0 +1,24 @@
|
||||
# Include system76 common source
|
||||
SYSTEM76_COMMON_DIR=src/board/system76/common
|
||||
SRC+=$(wildcard $(SYSTEM76_COMMON_DIR)/*.c)
|
||||
INCLUDE+=$(wildcard $(SYSTEM76_COMMON_DIR)/include/common/*.h) $(SYSTEM76_COMMON_DIR)/common.mk
|
||||
CFLAGS+=-I$(SYSTEM76_COMMON_DIR)/include
|
||||
|
||||
# Add scratch ROM
|
||||
include $(SYSTEM76_COMMON_DIR)/scratch/scratch.mk
|
||||
|
||||
console_internal:
|
||||
cargo build --manifest-path tool/Cargo.toml --release
|
||||
sudo tool/target/release/system76_ectool console
|
||||
|
||||
console_external:
|
||||
sleep 1 && echo C | sudo tee /dev/ttyACM* &
|
||||
sudo tio -b 1000000 -m INLCRNL /dev/ttyACM*
|
||||
|
||||
flash_internal: $(BUILD)/ec.rom
|
||||
cargo build --manifest-path tool/Cargo.toml --release
|
||||
sudo tool/target/release/system76_ectool flash $<
|
||||
|
||||
flash_external: $(BUILD)/ec.rom
|
||||
cargo build --manifest-path ecflash/Cargo.toml --example isp --release
|
||||
sudo ecflash/target/release/examples/isp $<
|
@ -3,5 +3,4 @@
|
||||
void gctrl_init(void) {
|
||||
SPCTRL1 = 0x03;
|
||||
BADRSEL = 0;
|
||||
RSTS = 0x84;
|
||||
}
|
7
src/board/system76/common/include/board/board.h
Normal file
7
src/board/system76/common/include/board/board.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef _BOARD_BOARD_H
|
||||
#define _BOARD_BOARD_H
|
||||
|
||||
void board_init(void);
|
||||
void board_event(void);
|
||||
|
||||
#endif // _BOARD_BOARD_H
|
6
src/board/system76/common/include/board/touchpad.h
Normal file
6
src/board/system76/common/include/board/touchpad.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef _BOARD_TOUCHPAD_H
|
||||
#define _BOARD_TOUCHPAD_H
|
||||
|
||||
void touchpad_event(void);
|
||||
|
||||
#endif // _BOARD_TOUCHPAD_H
|
@ -37,16 +37,46 @@ static uint8_t kbscan_get_row(int i) {
|
||||
if (i < 8) {
|
||||
KSOLGOEN = 1 << i;
|
||||
KSOHGOEN = 0;
|
||||
#if KM_OUT >= 17
|
||||
GPCRC3 = GPIO_IN;
|
||||
#endif
|
||||
#if KM_OUT >= 18
|
||||
GPCRC5 = GPIO_IN;
|
||||
#endif
|
||||
} else if (i < 16) {
|
||||
KSOLGOEN = 0;
|
||||
KSOHGOEN = 1 << (i - 8);
|
||||
#if KM_OUT >= 17
|
||||
GPCRC3 = GPIO_IN;
|
||||
#endif
|
||||
#if KM_OUT >= 18
|
||||
GPCRC5 = GPIO_IN;
|
||||
#endif
|
||||
} else if (i == 16) {
|
||||
KSOLGOEN = 0;
|
||||
KSOHGOEN = 0;
|
||||
#if KM_OUT >= 17
|
||||
GPCRC3 = GPIO_OUT;
|
||||
#endif
|
||||
#if KM_OUT >= 18
|
||||
GPCRC5 = GPIO_IN;
|
||||
#endif
|
||||
} else if (i == 17) {
|
||||
KSOLGOEN = 0;
|
||||
KSOHGOEN = 0;
|
||||
#if KM_OUT >= 17
|
||||
GPCRC3 = GPIO_IN;
|
||||
#endif
|
||||
#if KM_OUT >= 18
|
||||
GPCRC5 = GPIO_OUT;
|
||||
#endif
|
||||
}
|
||||
#if KM_OUT >= 17
|
||||
GPDRC &= ~(1 << 3);
|
||||
#endif
|
||||
#if KM_OUT >= 18
|
||||
GPDRC &= ~(1 << 5);
|
||||
#endif
|
||||
|
||||
// TODO: figure out optimal delay
|
||||
delay_ticks(10);
|
||||
@ -341,6 +371,12 @@ void kbscan_event(void) {
|
||||
// Reset all lines to inputs
|
||||
KSOLGOEN = 0;
|
||||
KSOHGOEN = 0;
|
||||
#if KM_OUT >= 17
|
||||
GPCRC3 = GPIO_IN;
|
||||
#endif
|
||||
#if KM_OUT >= 18
|
||||
GPCRC5 = GPIO_IN;
|
||||
#endif
|
||||
|
||||
// TODO: figure out optimal delay
|
||||
delay_ticks(10);
|
@ -5,6 +5,7 @@
|
||||
#include <arch/delay.h>
|
||||
#include <arch/time.h>
|
||||
#include <board/battery.h>
|
||||
#include <board/board.h>
|
||||
#include <board/ecpm.h>
|
||||
#include <board/gpio.h>
|
||||
#include <board/gctrl.h>
|
||||
@ -19,6 +20,7 @@
|
||||
#include <board/pwm.h>
|
||||
#include <board/smbus.h>
|
||||
#include <board/smfi.h>
|
||||
#include <board/touchpad.h>
|
||||
#include <common/debug.h>
|
||||
#include <common/macro.h>
|
||||
#include <common/version.h>
|
||||
@ -40,6 +42,7 @@ uint8_t main_cycle = 0;
|
||||
void init(void) {
|
||||
// Must happen first
|
||||
arch_init();
|
||||
board_init();
|
||||
gctrl_init();
|
||||
gpio_init();
|
||||
|
||||
@ -61,22 +64,6 @@ void init(void) {
|
||||
//TODO: INTC
|
||||
}
|
||||
|
||||
void touchpad_event(struct Ps2 * ps2) {
|
||||
if (kbc_second) {
|
||||
*(ps2->control) = 0x07;
|
||||
} else {
|
||||
ps2_reset(ps2);
|
||||
}
|
||||
|
||||
uint8_t status = *(ps2->status);
|
||||
*(ps2->status) = status;
|
||||
if (status & (1 << 3)) {
|
||||
uint8_t data = *(ps2->data);
|
||||
TRACE("touchpad: %02X\n", data);
|
||||
kbc_mouse(&KBC, data, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
init();
|
||||
|
||||
@ -120,7 +107,7 @@ void main(void) {
|
||||
break;
|
||||
case 2:
|
||||
// Passes through touchpad packets
|
||||
touchpad_event(&PS2_3);
|
||||
touchpad_event();
|
||||
break;
|
||||
case 3:
|
||||
// Checks for keyboard/mouse packets from host
|
||||
@ -146,6 +133,9 @@ void main(void) {
|
||||
}
|
||||
}
|
||||
|
||||
// Board-specific events
|
||||
board_event();
|
||||
|
||||
// Handles ACPI communication
|
||||
pmc_event(&PMC_1);
|
||||
// AP/EC communication over SMFI
|
@ -252,6 +252,14 @@ void power_off_s5(void) {
|
||||
update_power_state();
|
||||
}
|
||||
|
||||
// This function is run when the CPU is reset
|
||||
static void power_cpu_reset(void) {
|
||||
// LPC was just reset, enable PNP devices
|
||||
pnp_enable();
|
||||
//TODO: reset KBC and touchpad states
|
||||
kbled_reset();
|
||||
}
|
||||
|
||||
void power_event(void) {
|
||||
// Always switch to ds5 if EC is running
|
||||
if (power_state == POWER_STATE_DEFAULT) {
|
||||
@ -362,12 +370,7 @@ void power_event(void) {
|
||||
#endif
|
||||
if(rst_new && !rst_last) {
|
||||
DEBUG("%02X: PLT_RST# de-asserted\n", main_cycle);
|
||||
|
||||
// LPC was just reset, enable PNP devices
|
||||
pnp_enable();
|
||||
//TODO: reset KBC and touchpad states
|
||||
|
||||
kbled_reset();
|
||||
power_cpu_reset();
|
||||
}
|
||||
rst_last = rst_new;
|
||||
|
@ -1,6 +1,22 @@
|
||||
# Set scratch ROM parameters
|
||||
SCRATCH_OFFSET=1024
|
||||
SCRATCH_SIZE=1024
|
||||
CFLAGS+=-DSCRATCH_OFFSET=$(SCRATCH_OFFSET) -DSCRATCH_SIZE=$(SCRATCH_SIZE)
|
||||
|
||||
# Copy parameters to use when compiling scratch ROM
|
||||
SCRATCH_INCLUDE=$(INCLUDE)
|
||||
SCRATCH_CFLAGS=$(CFLAGS)
|
||||
|
||||
#Include scratch source
|
||||
SCRATCH_DIR=$(SYSTEM76_COMMON_DIR)/scratch
|
||||
SCRATCH_SRC=$(wildcard $(SCRATCH_DIR)/*.c)
|
||||
SCRATCH_INCLUDE+=$(wildcard $(SCRATCH_DIR)/include/scratch/*.h) $(SCRATCH_DIR)/scratch.mk
|
||||
SCRATCH_CFLAGS+=-I$(SCRATCH_DIR)/include -D__SCRATCH__
|
||||
|
||||
# Add minimal source from other directories
|
||||
SCRATCH_SRC+=\
|
||||
$(COMMON_DIR)/version.c \
|
||||
$(BOARD_DIR)/smfi.c
|
||||
$(SYSTEM76_COMMON_DIR)/smfi.c
|
||||
|
||||
SCRATCH_BUILD=$(BUILD)/scratch
|
||||
SCRATCH_OBJ=$(patsubst src/%.c,$(SCRATCH_BUILD)/%.rel,$(SCRATCH_SRC))
|
||||
@ -31,3 +47,7 @@ $(SCRATCH_BUILD)/scratch.ihx: $(SCRATCH_OBJ)
|
||||
$(SCRATCH_OBJ): $(SCRATCH_BUILD)/%.rel: src/%.c $(SCRATCH_INCLUDE)
|
||||
@mkdir -p $(@D)
|
||||
$(SCRATCH_CC) $(SCRATCH_CFLAGS) -o $@ -c $<
|
||||
|
||||
# Include scratch header in main firmware
|
||||
CFLAGS+=-I$(BUILD)/include
|
||||
INCLUDE+=$(BUILD)/include/scratch.h
|
20
src/board/system76/common/touchpad.c
Normal file
20
src/board/system76/common/touchpad.c
Normal file
@ -0,0 +1,20 @@
|
||||
#include <board/kbc.h>
|
||||
#include <board/touchpad.h>
|
||||
#include <common/debug.h>
|
||||
#include <ec/ps2.h>
|
||||
|
||||
void touchpad_event(void) {
|
||||
if (kbc_second) {
|
||||
*(PS2_TOUCHPAD.control) = 0x07;
|
||||
} else {
|
||||
ps2_reset(&PS2_TOUCHPAD);
|
||||
}
|
||||
|
||||
uint8_t status = *(PS2_TOUCHPAD.status);
|
||||
*(PS2_TOUCHPAD.status) = status;
|
||||
if (status & (1 << 3)) {
|
||||
uint8_t data = *(PS2_TOUCHPAD.data);
|
||||
TRACE("touchpad: %02X\n", data);
|
||||
kbc_mouse(&KBC, data, 1000);
|
||||
}
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
#include <board/gpio.h>
|
||||
#include <board/smbus.h>
|
||||
#include <common/debug.h>
|
||||
|
||||
|
||||
// ChargeOption0 flags
|
||||
// Low Power Mode Enable
|
||||
#define SBC_EN_LWPWR ((uint16_t)(1 << 15))
|
||||
// Watchdog Timer Adjust
|
||||
#define SBC_WDTMR_ADJ_175S ((uint16_t)(0b11 << 13))
|
||||
// Switching Frequency
|
||||
#define SBC_PWM_FREQ_800KHZ ((uint16_t)(0b01 << 8))
|
||||
// IDCHG Amplifier Gain
|
||||
#define SBC_IDCHC_GAIN ((uint16_t)(1 << 3))
|
||||
|
||||
int battery_charger_disable(void) {
|
||||
int res = 0;
|
||||
|
||||
// Set charge option 0 with 175s watchdog
|
||||
res = smbus_write(
|
||||
0x09,
|
||||
0x12,
|
||||
SBC_EN_LWPWR |
|
||||
SBC_WDTMR_ADJ_175S |
|
||||
SBC_PWM_FREQ_800KHZ |
|
||||
SBC_IDCHC_GAIN
|
||||
);
|
||||
|
||||
// Disable charge current
|
||||
res = smbus_write(0x09, 0x14, 0);
|
||||
if (res < 0) return res;
|
||||
|
||||
// Disable charge voltage
|
||||
res = smbus_write(0x09, 0x15, 0);
|
||||
if (res < 0) return res;
|
||||
|
||||
// Disable input current
|
||||
res = smbus_write(0x09, 0x3F, 0);
|
||||
if (res < 0) return res;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int battery_charger_enable(void) {
|
||||
int res = 0;
|
||||
|
||||
res = battery_charger_disable();
|
||||
if (res < 0) return res;
|
||||
|
||||
// Set charge current to ~1.54 A
|
||||
res = smbus_write(0x09, 0x14, 0x061C);
|
||||
if (res < 0) return res;
|
||||
|
||||
// Set charge voltage to ~17.6 V
|
||||
res = smbus_write(0x09, 0x15, 0x44CB);
|
||||
if (res < 0) return res;
|
||||
|
||||
// Set input current to ~3.2 A
|
||||
res = smbus_write(0x09, 0x3F, 0x0C80);
|
||||
if (res < 0) return res;
|
||||
|
||||
// Set charge option 0 with watchdog disabled
|
||||
res = smbus_write(
|
||||
0x09,
|
||||
0x12,
|
||||
SBC_EN_LWPWR |
|
||||
SBC_PWM_FREQ_800KHZ |
|
||||
SBC_IDCHC_GAIN
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t battery_temp = 0;
|
||||
uint16_t battery_voltage = 0;
|
||||
uint16_t battery_current = 0;
|
||||
uint16_t battery_charge = 0;
|
||||
uint16_t battery_remaining_capacity = 0;
|
||||
uint16_t battery_full_capacity = 0;
|
||||
uint16_t battery_status = 0;
|
||||
uint16_t battery_design_capacity = 0;
|
||||
uint16_t battery_design_voltage = 0;
|
||||
|
||||
void battery_event(void) {
|
||||
int res = 0;
|
||||
|
||||
#define command(N, V) { \
|
||||
res = smbus_read(0x0B, V, &N); \
|
||||
if (res < 0) { \
|
||||
N = 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
command(battery_temp, 0x08);
|
||||
command(battery_voltage, 0x09);
|
||||
command(battery_current, 0x0A);
|
||||
command(battery_charge, 0x0D);
|
||||
command(battery_remaining_capacity, 0x0F);
|
||||
command(battery_full_capacity, 0x10);
|
||||
command(battery_status, 0x16);
|
||||
command(battery_design_capacity, 0x18);
|
||||
command(battery_design_voltage, 0x19);
|
||||
|
||||
#undef command
|
||||
|
||||
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 battery_debug(void) {
|
||||
uint16_t data = 0;
|
||||
int res = 0;
|
||||
|
||||
#define command(N, A, V) { \
|
||||
DEBUG(#N ": "); \
|
||||
res = smbus_read(A, V, &data); \
|
||||
if (res < 0) { \
|
||||
DEBUG("ERROR %04X\n", -res); \
|
||||
} else { \
|
||||
DEBUG("%04X\n", data); \
|
||||
} \
|
||||
}
|
||||
|
||||
DEBUG("Battery:\n");
|
||||
command(Temperature, 0x0B, 0x08);
|
||||
command(Voltage, 0x0B, 0x09);
|
||||
command(Current, 0x0B, 0x0A);
|
||||
command(Charge, 0x0B, 0x0D);
|
||||
command(Status, 0x0B, 0x16);
|
||||
|
||||
DEBUG("Charger:\n");
|
||||
command(ChargeOption0, 0x09, 0x12);
|
||||
command(ChargeOption1, 0x09, 0x3B);
|
||||
command(ChargeOption2, 0x09, 0x38);
|
||||
command(ChargeOption3, 0x09, 0x37);
|
||||
command(ChargeCurrent, 0x09, 0x14);
|
||||
command(ChargeVoltage, 0x09, 0x15);
|
||||
command(DishargeCurrent, 0x09, 0x39);
|
||||
command(InputCurrent, 0x09, 0x3F);
|
||||
command(ProchotOption0, 0x09, 0x3C);
|
||||
command(ProchotOption1, 0x09, 0x3D);
|
||||
command(ProchotStatus, 0x09, 0x3A);
|
||||
|
||||
#undef command
|
||||
}
|
30
src/board/system76/darp5/board.c
Normal file
30
src/board/system76/darp5/board.c
Normal file
@ -0,0 +1,30 @@
|
||||
#include <board/battery.h>
|
||||
#include <board/board.h>
|
||||
#include <board/gctrl.h>
|
||||
#include <board/gpio.h>
|
||||
|
||||
extern uint8_t main_cycle;
|
||||
|
||||
void board_init(void) {
|
||||
RSTS = 0x84;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -19,44 +19,20 @@ CFLAGS+=-DLEVEL=4
|
||||
# Set battery I2C bus
|
||||
CFLAGS+=-DI2C_SMBUS=I2C_0
|
||||
|
||||
# Set touchpad PS2 bus
|
||||
CFLAGS+=-DPS2_TOUCHPAD=PS2_3
|
||||
|
||||
# Set smart charger parameters
|
||||
CFLAGS+=\
|
||||
-DCHARGER_CHARGE_CURRENT=1536 \
|
||||
-DCHARGER_CHARGE_VOLTAGE=17600 \
|
||||
-DCHARGER_INPUT_CURRENT=3200
|
||||
|
||||
# Set keyboard LED I2C bus
|
||||
CFLAGS+=-DI2C_KBLED=I2C_1
|
||||
|
||||
# Enable debug logging over keyboard parallel port
|
||||
#CFLAGS+=-DPARPORT_DEBUG
|
||||
|
||||
# Set scratch ROM parameters
|
||||
SCRATCH_OFFSET=1024
|
||||
SCRATCH_SIZE=1024
|
||||
CFLAGS+=-DSCRATCH_OFFSET=$(SCRATCH_OFFSET) -DSCRATCH_SIZE=$(SCRATCH_SIZE)
|
||||
|
||||
# Copy parameters to use when compiling scratch ROM
|
||||
SCRATCH_INCLUDE=$(INCLUDE)
|
||||
SCRATCH_CFLAGS=$(CFLAGS)
|
||||
|
||||
# Add scratch ROM source
|
||||
SCRATCH_DIR=$(BOARD_DIR)/scratch
|
||||
SCRATCH_SRC=$(wildcard $(SCRATCH_DIR)/*.c)
|
||||
SCRATCH_INCLUDE+=$(wildcard $(SCRATCH_DIR)/include/scratch/*.h) $(SCRATCH_DIR)/scratch.mk
|
||||
SCRATCH_CFLAGS+=-I$(SCRATCH_DIR)/include -D__SCRATCH__
|
||||
include $(SCRATCH_DIR)/scratch.mk
|
||||
|
||||
# Include scratch header in main firmware
|
||||
CFLAGS+=-I$(BUILD)/include
|
||||
INCLUDE+=$(BUILD)/include/scratch.h
|
||||
|
||||
console_internal:
|
||||
cargo build --manifest-path tool/Cargo.toml --release
|
||||
sudo tool/target/release/system76_ectool console
|
||||
|
||||
console_external:
|
||||
sleep 1 && echo C | sudo tee /dev/ttyACM* &
|
||||
sudo tio -b 1000000 -m INLCRNL /dev/ttyACM*
|
||||
|
||||
flash_internal: $(BUILD)/ec.rom
|
||||
cargo build --manifest-path tool/Cargo.toml --release
|
||||
sudo tool/target/release/system76_ectool flash $<
|
||||
|
||||
flash_external: $(BUILD)/ec.rom
|
||||
cargo build --manifest-path ecflash/Cargo.toml --example isp --release
|
||||
sudo ecflash/target/release/examples/isp $<
|
||||
# Add system76 common code
|
||||
include src/board/system76/common/common.mk
|
||||
|
@ -1,7 +0,0 @@
|
||||
#include <board/gctrl.h>
|
||||
|
||||
void gctrl_init(void) {
|
||||
SPCTRL1 = 0x03;
|
||||
BADRSEL = 0;
|
||||
RSTS = 0x84;
|
||||
}
|
@ -1,350 +0,0 @@
|
||||
#include <arch/delay.h>
|
||||
#include <arch/time.h>
|
||||
#include <board/gpio.h>
|
||||
#include <board/kbc.h>
|
||||
#include <board/kbscan.h>
|
||||
#include <board/keymap.h>
|
||||
#include <board/pmc.h>
|
||||
#include <board/power.h>
|
||||
#include <common/debug.h>
|
||||
|
||||
bool kbscan_enabled = false;
|
||||
uint16_t kbscan_repeat_period = 91;
|
||||
uint16_t kbscan_repeat_delay = 500;
|
||||
|
||||
uint8_t sci_extra = 0;
|
||||
|
||||
void kbscan_init(void) {
|
||||
KSOCTRL = 0x05;
|
||||
KSICTRLR = 0x04;
|
||||
|
||||
// Set all outputs to GPIO mode, low, and inputs
|
||||
KSOL = 0;
|
||||
KSOLGCTRL = 0xFF;
|
||||
KSOLGOEN = 0;
|
||||
KSOH1 = 0;
|
||||
KSOHGCTRL = 0xFF;
|
||||
KSOHGOEN = 0;
|
||||
KSOH2 = 0;
|
||||
}
|
||||
|
||||
// Debounce time in milliseconds
|
||||
#define DEBOUNCE_DELAY 20
|
||||
|
||||
static uint8_t kbscan_get_row(int i) {
|
||||
// Set current line as output
|
||||
if (i < 8) {
|
||||
KSOLGOEN = 1 << i;
|
||||
KSOHGOEN = 0;
|
||||
GPCRC3 = GPIO_IN;
|
||||
GPCRC5 = GPIO_IN;
|
||||
} else if (i < 16) {
|
||||
KSOLGOEN = 0;
|
||||
KSOHGOEN = 1 << (i - 8);
|
||||
GPCRC3 = GPIO_IN;
|
||||
GPCRC5 = GPIO_IN;
|
||||
} else if (i == 16) {
|
||||
KSOLGOEN = 0;
|
||||
KSOHGOEN = 0;
|
||||
GPCRC3 = GPIO_OUT;
|
||||
GPCRC5 = GPIO_IN;
|
||||
} else if (i == 17) {
|
||||
KSOLGOEN = 0;
|
||||
KSOHGOEN = 0;
|
||||
GPCRC3 = GPIO_IN;
|
||||
GPCRC5 = GPIO_OUT;
|
||||
}
|
||||
GPDRC &= ~((1 << 3) | (1 << 5));
|
||||
|
||||
// TODO: figure out optimal delay
|
||||
delay_ticks(10);
|
||||
|
||||
return ~KSI;
|
||||
}
|
||||
|
||||
static inline bool popcount_more_than_one(uint8_t rowdata) {
|
||||
return rowdata & (rowdata - 1);
|
||||
}
|
||||
|
||||
static uint8_t kbscan_get_real_keys(int row, uint8_t rowdata) {
|
||||
// Remove any "active" blanks from the matrix.
|
||||
uint8_t realdata = 0;
|
||||
for (uint8_t col = 0; col < KM_IN; col++) {
|
||||
if (KEYMAP[0][row][col] && (rowdata & (1 << col))) {
|
||||
realdata |= 1 << col;
|
||||
}
|
||||
}
|
||||
|
||||
return realdata;
|
||||
}
|
||||
|
||||
static bool kbscan_has_ghost_in_row(int row, uint8_t rowdata) {
|
||||
rowdata = kbscan_get_real_keys(row, rowdata);
|
||||
|
||||
// No ghosts exist when less than 2 keys in the row are active.
|
||||
if (!popcount_more_than_one(rowdata)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check against other rows to see if more than one column matches.
|
||||
for (int i = 0; i < KM_OUT; i++) {
|
||||
uint8_t otherrow = kbscan_get_real_keys(i, kbscan_get_row(i));
|
||||
if (i != row && popcount_more_than_one(otherrow & rowdata)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool kbscan_press(uint16_t key, bool pressed, uint8_t * layer) {
|
||||
if (pressed &&
|
||||
(power_state == POWER_STATE_S3 || power_state == POWER_STATE_DS3)) {
|
||||
gpio_set(&SWI_N, false);
|
||||
delay_ticks(10); //TODO: find correct delay
|
||||
gpio_set(&SWI_N, true);
|
||||
}
|
||||
|
||||
switch (key & KT_MASK) {
|
||||
case (KT_NORMAL):
|
||||
if (kbscan_enabled) {
|
||||
kbc_scancode(&KBC, key, pressed);
|
||||
}
|
||||
break;
|
||||
case (KT_FN):
|
||||
if (layer != NULL) {
|
||||
if (pressed) *layer = 1;
|
||||
else *layer = 0;
|
||||
} else {
|
||||
// In the case no layer can be set, reset bit
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case (KT_COMBO):
|
||||
switch (key & 0xFF) {
|
||||
case COMBO_DISPLAY_MODE:
|
||||
if (kbscan_enabled) {
|
||||
if (pressed) {
|
||||
kbc_scancode(&KBC, K_LEFT_SUPER, true);
|
||||
kbc_scancode(&KBC, K_P, true);
|
||||
kbc_scancode(&KBC, K_P, false);
|
||||
} else {
|
||||
kbc_scancode(&KBC, K_LEFT_SUPER, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case COMBO_PRINT_SCREEN:
|
||||
if (kbscan_enabled) {
|
||||
if (pressed) {
|
||||
kbc_scancode(&KBC, K_E0 | 0x12, true);
|
||||
kbc_scancode(&KBC, K_E0 | 0x7C, true);
|
||||
} else {
|
||||
kbc_scancode(&KBC, K_E0 | 0x7C, false);
|
||||
kbc_scancode(&KBC, K_E0 | 0x12, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case (KT_SCI):
|
||||
if (pressed) {
|
||||
uint8_t sci = (uint8_t)(key & 0xFF);
|
||||
|
||||
// HACK FOR HARDWARE HOTKEYS
|
||||
switch (sci) {
|
||||
case SCI_DISPLAY_TOGGLE:
|
||||
gpio_set(&BKL_EN, !gpio_get(&BKL_EN));
|
||||
break;
|
||||
case SCI_CAMERA_TOGGLE:
|
||||
gpio_set(&CCD_EN, !gpio_get(&CCD_EN));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pmc_sci(&PMC_1, sci)) {
|
||||
// In the case of ignored SCI, reset bit
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case (KT_SCI_EXTRA):
|
||||
if (pressed) {
|
||||
uint8_t sci = SCI_EXTRA;
|
||||
sci_extra = (uint8_t)(key & 0xFF);
|
||||
|
||||
if (!pmc_sci(&PMC_1, sci)) {
|
||||
// In the case of ignored SCI, reset bit
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void kbscan_event(void) {
|
||||
static uint8_t kbscan_layer = 0;
|
||||
uint8_t layer = kbscan_layer;
|
||||
static uint8_t kbscan_last[KM_OUT] = { 0 };
|
||||
|
||||
static bool debounce = false;
|
||||
static uint32_t debounce_time = 0;
|
||||
|
||||
static bool repeat = false;
|
||||
static uint16_t repeat_key = 0;
|
||||
static uint32_t repeat_key_time = 0;
|
||||
|
||||
// If debounce complete
|
||||
if (debounce) {
|
||||
uint32_t time = time_get();
|
||||
//TODO: time test with overflow
|
||||
if (time < debounce_time) {
|
||||
// Overflow, reset debounce_time
|
||||
debounce_time = time;
|
||||
} else if (time >= (debounce_time + DEBOUNCE_DELAY)) {
|
||||
// Finish debounce
|
||||
debounce = false;
|
||||
}
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < KM_OUT; i++) {
|
||||
uint8_t new = kbscan_get_row(i);
|
||||
uint8_t last = kbscan_last[i];
|
||||
if (new != last) {
|
||||
if (kbscan_has_ghost_in_row(i, new)) {
|
||||
kbscan_last[i] = new;
|
||||
continue;
|
||||
}
|
||||
|
||||
// A key was pressed or released
|
||||
int j;
|
||||
for (j = 0; j < KM_IN; j++) {
|
||||
bool new_b = new & (1 << j);
|
||||
bool last_b = last & (1 << j);
|
||||
if (new_b != last_b) {
|
||||
bool reset = false;
|
||||
|
||||
// If debouncing
|
||||
if (debounce) {
|
||||
// Debounce presses and releases
|
||||
reset = true;
|
||||
} else {
|
||||
// Begin debounce
|
||||
debounce = true;
|
||||
debounce_time = time_get();
|
||||
|
||||
// Handle key press/release
|
||||
uint16_t key = keymap(i, j, kbscan_layer);
|
||||
if (key) {
|
||||
DEBUG("KB %d, %d, %d = 0x%04X, %d\n", i, j, kbscan_layer, key, new_b);
|
||||
if(!kbscan_press(key, new_b, &layer)){
|
||||
// In the case of ignored key press/release, reset bit
|
||||
reset = true;
|
||||
}
|
||||
|
||||
if (new_b) {
|
||||
// New key pressed, update last key
|
||||
repeat_key = key;
|
||||
repeat_key_time = time_get();
|
||||
repeat = false;
|
||||
} else if (key == repeat_key) {
|
||||
// Repeat key was released
|
||||
repeat_key = 0;
|
||||
repeat = false;
|
||||
}
|
||||
} else {
|
||||
WARN("KB %d, %d, %d missing\n", i, j, kbscan_layer);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset bit to last state
|
||||
if (reset) {
|
||||
if (last_b) {
|
||||
new |= (1 << j);
|
||||
} else {
|
||||
new &= ~(1 << j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kbscan_last[i] = new;
|
||||
} else if (new && repeat_key != 0) {
|
||||
// A key is being pressed
|
||||
uint32_t time = time_get();
|
||||
static uint32_t repeat_start = 0;
|
||||
|
||||
if (!repeat) {
|
||||
if (time < repeat_key_time) {
|
||||
// Overflow, reset repeat_key_time
|
||||
repeat_key_time = time;
|
||||
} else if ((time - repeat_key_time) >= kbscan_repeat_delay) {
|
||||
// Typematic repeat
|
||||
repeat = true;
|
||||
repeat_start = time;
|
||||
}
|
||||
}
|
||||
|
||||
if (repeat) {
|
||||
if ((time - repeat_start) > kbscan_repeat_period) {
|
||||
kbscan_press(repeat_key, true, &layer);
|
||||
repeat_start = time;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (layer != kbscan_layer) {
|
||||
//TODO: unpress keys before going to scratch rom
|
||||
|
||||
// Unpress all currently pressed keys
|
||||
for (i = 0; i < KM_OUT; i++) {
|
||||
uint8_t new = 0;
|
||||
uint8_t last = kbscan_last[i];
|
||||
if (last) {
|
||||
int j;
|
||||
for (j = 0; j < KM_IN; j++) {
|
||||
bool new_b = new & (1 << j);
|
||||
bool last_b = last & (1 << j);
|
||||
if (new_b != last_b) {
|
||||
bool reset = false;
|
||||
|
||||
// Handle key press/release
|
||||
uint16_t key = keymap(i, j, kbscan_layer);
|
||||
if (key) {
|
||||
DEBUG("KB %d, %d, %d = 0x%04X, %d\n", i, j, kbscan_layer, key, new_b);
|
||||
if(!kbscan_press(key, new_b, NULL)){
|
||||
// In the case of ignored key press/release, reset bit
|
||||
reset = true;
|
||||
}
|
||||
} else {
|
||||
WARN("KB %d, %d, %d missing\n", i, j, kbscan_layer);
|
||||
}
|
||||
|
||||
// Reset bit to last state
|
||||
if (reset) {
|
||||
if (last_b) {
|
||||
new |= (1 << j);
|
||||
} else {
|
||||
new &= ~(1 << j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kbscan_last[i] = new;
|
||||
}
|
||||
|
||||
kbscan_layer = layer;
|
||||
}
|
||||
|
||||
// Reset all lines to inputs
|
||||
KSOLGOEN = 0;
|
||||
KSOHGOEN = 0;
|
||||
GPCRC3 = GPIO_IN;
|
||||
GPCRC5 = GPIO_IN;
|
||||
|
||||
// TODO: figure out optimal delay
|
||||
delay_ticks(10);
|
||||
}
|
@ -1,156 +0,0 @@
|
||||
#include <8051.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <arch/arch.h>
|
||||
#include <arch/delay.h>
|
||||
#include <arch/time.h>
|
||||
#include <board/battery.h>
|
||||
#include <board/ecpm.h>
|
||||
#include <board/gpio.h>
|
||||
#include <board/gctrl.h>
|
||||
#include <board/kbc.h>
|
||||
#include <board/kbled.h>
|
||||
#include <board/kbscan.h>
|
||||
#include <board/lid.h>
|
||||
#include <board/peci.h>
|
||||
#include <board/pmc.h>
|
||||
#include <board/power.h>
|
||||
#include <board/ps2.h>
|
||||
#include <board/pwm.h>
|
||||
#include <board/smbus.h>
|
||||
#include <board/smfi.h>
|
||||
#include <common/debug.h>
|
||||
#include <common/macro.h>
|
||||
#include <common/version.h>
|
||||
|
||||
#ifdef PARPORT_DEBUG
|
||||
#include <ec/parallel.h>
|
||||
#endif
|
||||
|
||||
void external_0(void) __interrupt(0) {}
|
||||
// timer_0 is in time.c
|
||||
void timer_0(void) __interrupt(1);
|
||||
void external_1(void) __interrupt(2) {}
|
||||
void timer_1(void) __interrupt(3) {}
|
||||
void serial(void) __interrupt(4) {}
|
||||
void timer_2(void) __interrupt(5) {}
|
||||
|
||||
uint8_t main_cycle = 0;
|
||||
|
||||
void init(void) {
|
||||
// Must happen first
|
||||
arch_init();
|
||||
gctrl_init();
|
||||
gpio_init();
|
||||
|
||||
// Can happen in any order
|
||||
ecpm_init();
|
||||
kbc_init();
|
||||
kbled_init();
|
||||
#ifdef PARPORT_DEBUG
|
||||
parport_init();
|
||||
#else
|
||||
kbscan_init();
|
||||
#endif
|
||||
peci_init();
|
||||
pmc_init();
|
||||
pwm_init();
|
||||
smbus_init();
|
||||
smfi_init();
|
||||
|
||||
//TODO: INTC
|
||||
}
|
||||
|
||||
void touchpad_event(struct Ps2 * ps2) {
|
||||
if (kbc_second) {
|
||||
*(ps2->control) = 0x07;
|
||||
} else {
|
||||
ps2_reset(ps2);
|
||||
}
|
||||
|
||||
uint8_t status = *(ps2->status);
|
||||
*(ps2->status) = status;
|
||||
if (status & (1 << 3)) {
|
||||
uint8_t data = *(ps2->data);
|
||||
TRACE("touchpad: %02X\n", data);
|
||||
kbc_mouse(&KBC, data, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
init();
|
||||
|
||||
INFO("\n");
|
||||
|
||||
#if GPIO_DEBUG
|
||||
gpio_debug();
|
||||
#endif
|
||||
|
||||
// Allow CPU to boot
|
||||
gpio_set(&SB_KBCRST_N, true);
|
||||
// Allow backlight to be turned on
|
||||
gpio_set(&BKL_EN, true);
|
||||
// Enable camera
|
||||
gpio_set(&CCD_EN, true);
|
||||
// Enable wireless
|
||||
gpio_set(&BT_EN, true);
|
||||
gpio_set(&WLAN_EN, true);
|
||||
gpio_set(&WLAN_PWR_EN, true);
|
||||
// Enable right USB port
|
||||
gpio_set(&USB_PWR_EN_N, false);
|
||||
// Assert SMI#, SCI#, and SWI#
|
||||
gpio_set(&SCI_N, true);
|
||||
gpio_set(&SMI_N, true);
|
||||
gpio_set(&SWI_N, true);
|
||||
|
||||
INFO("System76 EC board '%s', version '%s'\n", board(), version());
|
||||
|
||||
uint32_t last_time = 0;
|
||||
for(main_cycle = 0; ; main_cycle++) {
|
||||
switch (main_cycle % 5) {
|
||||
case 0:
|
||||
// Handle power states
|
||||
power_event();
|
||||
break;
|
||||
case 1:
|
||||
#ifndef PARPORT_DEBUG
|
||||
// Scans keyboard and sends keyboard packets
|
||||
kbscan_event();
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
// Passes through touchpad packets
|
||||
touchpad_event(&PS2_3);
|
||||
break;
|
||||
case 3:
|
||||
// Checks for keyboard/mouse packets from host
|
||||
kbc_event(&KBC);
|
||||
break;
|
||||
case 4:
|
||||
// Handle lid close/open
|
||||
lid_event();
|
||||
break;
|
||||
}
|
||||
|
||||
if (main_cycle == 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 fan status and temps
|
||||
peci_event();
|
||||
|
||||
// Updates battery status
|
||||
battery_event();
|
||||
}
|
||||
}
|
||||
|
||||
// Handles ACPI communication
|
||||
pmc_event(&PMC_1);
|
||||
// AP/EC communication over SMFI
|
||||
smfi_event();
|
||||
// Idle until next timer interrupt
|
||||
//Disabled until interrupts used: PCON |= 1;
|
||||
}
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
#include <board/gpio.h>
|
||||
#include <board/smbus.h>
|
||||
#include <common/debug.h>
|
||||
|
||||
|
||||
// ChargeOption0 flags
|
||||
// Low Power Mode Enable
|
||||
#define SBC_EN_LWPWR ((uint16_t)(1 << 15))
|
||||
// Watchdog Timer Adjust
|
||||
#define SBC_WDTMR_ADJ_175S ((uint16_t)(0b11 << 13))
|
||||
// Switching Frequency
|
||||
#define SBC_PWM_FREQ_800KHZ ((uint16_t)(0b01 << 8))
|
||||
// IDCHG Amplifier Gain
|
||||
#define SBC_IDCHC_GAIN ((uint16_t)(1 << 3))
|
||||
|
||||
int battery_charger_disable(void) {
|
||||
int res = 0;
|
||||
|
||||
// Set charge option 0 with 175s watchdog
|
||||
res = smbus_write(
|
||||
0x09,
|
||||
0x12,
|
||||
SBC_EN_LWPWR |
|
||||
SBC_WDTMR_ADJ_175S |
|
||||
SBC_PWM_FREQ_800KHZ |
|
||||
SBC_IDCHC_GAIN
|
||||
);
|
||||
|
||||
// Disable charge current
|
||||
res = smbus_write(0x09, 0x14, 0);
|
||||
if (res < 0) return res;
|
||||
|
||||
// Disable charge voltage
|
||||
res = smbus_write(0x09, 0x15, 0);
|
||||
if (res < 0) return res;
|
||||
|
||||
// Disable input current
|
||||
res = smbus_write(0x09, 0x3F, 0);
|
||||
if (res < 0) return res;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int battery_charger_enable(void) {
|
||||
int res = 0;
|
||||
|
||||
res = battery_charger_disable();
|
||||
if (res < 0) return res;
|
||||
|
||||
// Set charge current to ~1.5 A
|
||||
res = smbus_write(0x09, 0x14, 0x0600);
|
||||
if (res < 0) return res;
|
||||
|
||||
// Set charge voltage to ~13 V
|
||||
res = smbus_write(0x09, 0x15, 0x3300);
|
||||
if (res < 0) return res;
|
||||
|
||||
// Set input current to ~1.92 A
|
||||
res = smbus_write(0x09, 0x3F, 0x0780);
|
||||
if (res < 0) return res;
|
||||
|
||||
// Set charge option 0 with watchdog disabled
|
||||
res = smbus_write(
|
||||
0x09,
|
||||
0x12,
|
||||
SBC_EN_LWPWR |
|
||||
SBC_PWM_FREQ_800KHZ |
|
||||
SBC_IDCHC_GAIN
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t battery_temp = 0;
|
||||
uint16_t battery_voltage = 0;
|
||||
uint16_t battery_current = 0;
|
||||
uint16_t battery_charge = 0;
|
||||
uint16_t battery_remaining_capacity = 0;
|
||||
uint16_t battery_full_capacity = 0;
|
||||
uint16_t battery_status = 0;
|
||||
uint16_t battery_design_capacity = 0;
|
||||
uint16_t battery_design_voltage = 0;
|
||||
|
||||
void battery_event(void) {
|
||||
int res = 0;
|
||||
|
||||
#define command(N, V) { \
|
||||
res = smbus_read(0x0B, V, &N); \
|
||||
if (res < 0) { \
|
||||
N = 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
command(battery_temp, 0x08);
|
||||
command(battery_voltage, 0x09);
|
||||
command(battery_current, 0x0A);
|
||||
command(battery_charge, 0x0D);
|
||||
command(battery_remaining_capacity, 0x0F);
|
||||
command(battery_full_capacity, 0x10);
|
||||
command(battery_status, 0x16);
|
||||
command(battery_design_capacity, 0x18);
|
||||
command(battery_design_voltage, 0x19);
|
||||
|
||||
#undef command
|
||||
|
||||
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 battery_debug(void) {
|
||||
uint16_t data = 0;
|
||||
int res = 0;
|
||||
|
||||
#define command(N, A, V) { \
|
||||
DEBUG(#N ": "); \
|
||||
res = smbus_read(A, V, &data); \
|
||||
if (res < 0) { \
|
||||
DEBUG("ERROR %04X\n", -res); \
|
||||
} else { \
|
||||
DEBUG("%04X\n", data); \
|
||||
} \
|
||||
}
|
||||
|
||||
DEBUG("Battery:\n");
|
||||
command(Temperature, 0x0B, 0x08);
|
||||
command(Voltage, 0x0B, 0x09);
|
||||
command(Current, 0x0B, 0x0A);
|
||||
command(Charge, 0x0B, 0x0D);
|
||||
command(Status, 0x0B, 0x16);
|
||||
|
||||
DEBUG("Charger:\n");
|
||||
command(ChargeOption0, 0x09, 0x12);
|
||||
command(ChargeOption1, 0x09, 0x3B);
|
||||
command(ChargeOption2, 0x09, 0x38);
|
||||
command(ChargeOption3, 0x09, 0x37);
|
||||
command(ChargeCurrent, 0x09, 0x14);
|
||||
command(ChargeVoltage, 0x09, 0x15);
|
||||
command(DishargeCurrent, 0x09, 0x39);
|
||||
command(InputCurrent, 0x09, 0x3F);
|
||||
command(ProchotOption0, 0x09, 0x3C);
|
||||
command(ProchotOption1, 0x09, 0x3D);
|
||||
command(ProchotStatus, 0x09, 0x3A);
|
||||
|
||||
#undef command
|
||||
}
|
30
src/board/system76/galp3-c/board.c
Normal file
30
src/board/system76/galp3-c/board.c
Normal file
@ -0,0 +1,30 @@
|
||||
#include <board/battery.h>
|
||||
#include <board/board.h>
|
||||
#include <board/gctrl.h>
|
||||
#include <board/gpio.h>
|
||||
|
||||
extern uint8_t main_cycle;
|
||||
|
||||
void board_init(void) {
|
||||
RSTS = 0x84;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -19,41 +19,17 @@ CFLAGS+=-DLEVEL=4
|
||||
# Set battery I2C bus
|
||||
CFLAGS+=-DI2C_SMBUS=I2C_0
|
||||
|
||||
# Set touchpad PS2 bus
|
||||
CFLAGS+=-DPS2_TOUCHPAD=PS2_3
|
||||
|
||||
# Set smart charger parameters
|
||||
CFLAGS+=\
|
||||
-DCHARGER_CHARGE_CURRENT=1536 \
|
||||
-DCHARGER_CHARGE_VOLTAGE=13056 \
|
||||
-DCHARGER_INPUT_CURRENT=1920
|
||||
|
||||
# Enable debug logging over keyboard parallel port
|
||||
#CFLAGS+=-DPARPORT_DEBUG
|
||||
|
||||
# Set scratch ROM parameters
|
||||
SCRATCH_OFFSET=1024
|
||||
SCRATCH_SIZE=1024
|
||||
CFLAGS+=-DSCRATCH_OFFSET=$(SCRATCH_OFFSET) -DSCRATCH_SIZE=$(SCRATCH_SIZE)
|
||||
|
||||
# Copy parameters to use when compiling scratch ROM
|
||||
SCRATCH_INCLUDE=$(INCLUDE)
|
||||
SCRATCH_CFLAGS=$(CFLAGS)
|
||||
|
||||
# Add scratch ROM source
|
||||
SCRATCH_DIR=$(BOARD_DIR)/scratch
|
||||
SCRATCH_SRC=$(wildcard $(SCRATCH_DIR)/*.c)
|
||||
SCRATCH_INCLUDE+=$(wildcard $(SCRATCH_DIR)/include/scratch/*.h) $(SCRATCH_DIR)/scratch.mk
|
||||
SCRATCH_CFLAGS+=-I$(SCRATCH_DIR)/include -D__SCRATCH__
|
||||
include $(SCRATCH_DIR)/scratch.mk
|
||||
|
||||
# Include scratch header in main firmware
|
||||
CFLAGS+=-I$(BUILD)/include
|
||||
INCLUDE+=$(BUILD)/include/scratch.h
|
||||
|
||||
console_internal:
|
||||
cargo build --manifest-path tool/Cargo.toml --release
|
||||
sudo tool/target/release/system76_ectool console
|
||||
|
||||
console_external:
|
||||
sleep 1 && echo C | sudo tee /dev/ttyACM* &
|
||||
sudo tio -b 1000000 -m INLCRNL /dev/ttyACM*
|
||||
|
||||
flash_internal: $(BUILD)/ec.rom
|
||||
cargo build --manifest-path tool/Cargo.toml --release
|
||||
sudo tool/target/release/system76_ectool flash $<
|
||||
|
||||
flash_external: $(BUILD)/ec.rom
|
||||
cargo build --manifest-path ecflash/Cargo.toml --example isp --release
|
||||
sudo ecflash/target/release/examples/isp $<
|
||||
# Add system76 common code
|
||||
include src/board/system76/common/common.mk
|
||||
|
@ -1,10 +0,0 @@
|
||||
#include <board/ecpm.h>
|
||||
|
||||
void ecpm_init(void) {
|
||||
// Clock gate EGPC, CIR, and SWUC
|
||||
CGCTRL2 |= (1 << 6) | (1 << 5) | (1 << 4);
|
||||
// Clock gate UART, SSPI, and DBGR
|
||||
CGCTRL3 |= (1 << 2) | (1 << 1) | (1 << 0);
|
||||
// Clock gate CEC
|
||||
CGCTRL4 |= (1 << 0);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#ifndef _BOARD_ACPI_H
|
||||
#define _BOARD_ACPI_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t acpi_read(uint8_t addr);
|
||||
void acpi_write(uint8_t addr, uint8_t data);
|
||||
|
||||
#endif // _BOARD_ACPI_H
|
@ -1,21 +0,0 @@
|
||||
#ifndef _BOARD_BATTERY_H
|
||||
#define _BOARD_BATTERY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint16_t battery_temp;
|
||||
extern uint16_t battery_voltage;
|
||||
extern uint16_t battery_current;
|
||||
extern uint16_t battery_charge;
|
||||
extern uint16_t battery_remaining_capacity;
|
||||
extern uint16_t battery_full_capacity;
|
||||
extern uint16_t battery_status;
|
||||
extern uint16_t battery_design_capacity;
|
||||
extern uint16_t battery_design_voltage;
|
||||
|
||||
int battery_charger_disable(void);
|
||||
int battery_charger_enable(void);
|
||||
void battery_event(void);
|
||||
void battery_debug(void);
|
||||
|
||||
#endif // _BOARD_BATTERY_H
|
@ -1,6 +0,0 @@
|
||||
#ifndef _BOARD_CPU_H
|
||||
#define _BOARD_CPU_H
|
||||
|
||||
#define F_CPU 9200000ULL
|
||||
|
||||
#endif // _BOARD_CPU_H
|
@ -1,8 +0,0 @@
|
||||
#ifndef _BOARD_ECPM_H
|
||||
#define _BOARD_ECPM_H
|
||||
|
||||
#include <ec/ecpm.h>
|
||||
|
||||
void ecpm_init(void);
|
||||
|
||||
#endif // _BOARD_ECPM_H
|
@ -1,8 +0,0 @@
|
||||
#ifndef _BOARD_GCTRL_H
|
||||
#define _BOARD_GCTRL_H
|
||||
|
||||
#include <ec/gctrl.h>
|
||||
|
||||
void gctrl_init(void);
|
||||
|
||||
#endif // _BOARD_GCTRL_H
|
@ -1,15 +0,0 @@
|
||||
#ifndef _BOARD_KBC_H
|
||||
#define _BOARD_KBC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <ec/kbc.h>
|
||||
|
||||
extern bool kbc_first;
|
||||
extern bool kbc_second;
|
||||
|
||||
void kbc_init(void);
|
||||
bool kbc_scancode(struct Kbc * kbc, uint16_t key, bool pressed);
|
||||
void kbc_event(struct Kbc * kbc);
|
||||
|
||||
#endif // _BOARD_KBC_H
|
@ -4,6 +4,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
void kbled_init(void);
|
||||
void kbled_reset(void);
|
||||
uint8_t kbled_get(void);
|
||||
void kbled_set(uint8_t level);
|
||||
|
||||
|
@ -1,18 +0,0 @@
|
||||
#ifndef _BOARD_KBSCAN_H
|
||||
#define _BOARD_KBSCAN_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <ec/kbscan.h>
|
||||
|
||||
extern bool kbscan_enabled;
|
||||
|
||||
// ms between repeating key
|
||||
extern uint16_t kbscan_repeat_period;
|
||||
// ms between pressing key and repeating
|
||||
extern uint16_t kbscan_repeat_delay;
|
||||
|
||||
void kbscan_init(void);
|
||||
void kbscan_event(void);
|
||||
|
||||
#endif // _BOARD_KBSCAN_H
|
@ -1,11 +0,0 @@
|
||||
#ifndef _BOARD_LID_H
|
||||
#define _BOARD_LID_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
extern bool lid_state;
|
||||
extern bool lid_wake;
|
||||
|
||||
void lid_event(void);
|
||||
|
||||
#endif // _BOARD_LID_H
|
@ -1,15 +0,0 @@
|
||||
#ifndef _BOARD_PECI_H
|
||||
#define _BOARD_PECI_H
|
||||
|
||||
#include <ec/peci.h>
|
||||
|
||||
extern int16_t peci_offset;
|
||||
extern int16_t peci_temp;
|
||||
extern uint8_t peci_duty;
|
||||
extern uint8_t peci_tcontrol;
|
||||
extern uint8_t peci_tjmax;
|
||||
|
||||
void peci_init(void);
|
||||
void peci_event(void);
|
||||
|
||||
#endif // _BOARD_PECI_H
|
@ -1,10 +0,0 @@
|
||||
#ifndef _BOARD_PMC_H
|
||||
#define _BOARD_PMC_H
|
||||
|
||||
#include <ec/pmc.h>
|
||||
|
||||
void pmc_init(void);
|
||||
bool pmc_sci(struct Pmc * pmc, uint8_t sci);
|
||||
void pmc_event(struct Pmc * pmc);
|
||||
|
||||
#endif // _BOARD_PMC_H
|
@ -1,6 +0,0 @@
|
||||
#ifndef _BOARD_PNP_H
|
||||
#define _BOARD_PNP_H
|
||||
|
||||
void pnp_enable(void);
|
||||
|
||||
#endif // _BOARD_PNP_H
|
@ -1,17 +0,0 @@
|
||||
#ifndef _BOARD_POWER_H
|
||||
#define _BOARD_POWER_H
|
||||
|
||||
enum PowerState {
|
||||
POWER_STATE_DEFAULT,
|
||||
POWER_STATE_DS5,
|
||||
POWER_STATE_S5,
|
||||
POWER_STATE_DS3,
|
||||
POWER_STATE_S3,
|
||||
POWER_STATE_S0,
|
||||
};
|
||||
|
||||
extern enum PowerState power_state;
|
||||
|
||||
void power_event(void);
|
||||
|
||||
#endif // _BOARD_POWER_H
|
@ -1,8 +0,0 @@
|
||||
#ifndef _BOARD_PS2_H
|
||||
#define _BOARD_PS2_H
|
||||
|
||||
#include <ec/ps2.h>
|
||||
|
||||
void ps2_init(void);
|
||||
|
||||
#endif // _BOARD_PS2_H
|
@ -1,8 +0,0 @@
|
||||
#ifndef _BOARD_PWM_H
|
||||
#define _BOARD_PWM_H
|
||||
|
||||
#include <ec/pwm.h>
|
||||
|
||||
void pwm_init(void);
|
||||
|
||||
#endif // _BOARD_PWM_H
|
@ -1,6 +0,0 @@
|
||||
#ifndef _BOARD_SCRATCH_H
|
||||
#define _BOARD_SCRATCH_H
|
||||
|
||||
void scratch_trampoline(void);
|
||||
|
||||
#endif // _BOARD_SCRATCH_H
|
@ -1,10 +0,0 @@
|
||||
#ifndef _BOARD_SMBUS_H
|
||||
#define _BOARD_SMBUS_H
|
||||
|
||||
#include <ec/smbus.h>
|
||||
|
||||
void smbus_init(void);
|
||||
int smbus_read(uint8_t address, uint8_t command, uint16_t * data);
|
||||
int smbus_write(uint8_t address, uint8_t command, uint16_t data);
|
||||
|
||||
#endif // _BOARD_SMBUS_H
|
@ -1,9 +0,0 @@
|
||||
#ifndef _BOARD_SMFI_H
|
||||
#define _BOARD_SMFI_H
|
||||
|
||||
void smfi_init(void);
|
||||
void smfi_watchdog(void);
|
||||
void smfi_event(void);
|
||||
void smfi_debug(unsigned char byte);
|
||||
|
||||
#endif // _BOARD_SMFI_H
|
@ -1,310 +0,0 @@
|
||||
#include <board/kbc.h>
|
||||
#include <board/kbscan.h>
|
||||
#include <board/keymap.h>
|
||||
#include <common/debug.h>
|
||||
#include <ec/ps2.h>
|
||||
|
||||
void kbc_init(void) {
|
||||
// Disable interrupts
|
||||
*(KBC.irq) = 0;
|
||||
*(KBC.control) = 0;
|
||||
}
|
||||
|
||||
#define KBC_TIMEOUT 10000
|
||||
|
||||
// System flag
|
||||
static bool kbc_system = false;
|
||||
// Enable first port - TODO
|
||||
bool kbc_first = false;
|
||||
// Enable second port - TODO
|
||||
bool kbc_second = false;
|
||||
// Translate from scancode set 2 to scancode set 1
|
||||
// for basically no good reason
|
||||
static bool kbc_translate = true;
|
||||
|
||||
// Values from linux/drivers/input/keyboard/atkbd.c
|
||||
static const uint16_t kbc_typematic_period[32] = {
|
||||
33, // 30.0 cps = ~33.33ms
|
||||
37, // 26.7 cps = ~37.45ms
|
||||
42, // 24.0 cps = ~41.67ms
|
||||
46, // 21.8 cps = ~45.87ms
|
||||
50, // 20.7 cps = ~48.30ms
|
||||
54, // 18.5 cps = ~54.05ms
|
||||
58, // 17.1 cps = ~58.48ms
|
||||
63, // 16.0 cps = ~62.50ms
|
||||
67, // 15.0 cps = ~66.67ms
|
||||
75, // 13.3 cps = ~75.19ms
|
||||
83, // 12.0 cps = ~83.33ms
|
||||
92, // 10.9 cps = ~91.74ms
|
||||
100, // 10.0 cps = 100ms
|
||||
109, // 9.2 cps = ~108.70ms
|
||||
116, // 8.6 cps = ~116.28ms
|
||||
125, // 8.0 cps = 125ms
|
||||
133, // 7.5 cps = ~133.33ms
|
||||
149, // 6.7 cps = ~149.25ms
|
||||
167, // 6.0 cps = ~166.67ms
|
||||
182, // 5.5 cps = ~181.82ms
|
||||
200, // 5.0 cps = 200ms
|
||||
217, // 4.6 cps = ~217.39ms
|
||||
232, // 4.3 cps = ~232.56ms
|
||||
250, // 4.0 cps = 250ms
|
||||
270, // 3.7 cps = ~270.27ms
|
||||
303, // 3.3 cps = ~303.03ms
|
||||
333, // 3.0 cps = ~333.33ms
|
||||
370, // 2.7 cps = ~370.37ms
|
||||
400, // 2.5 cps = 400ms
|
||||
435, // 2.3 cps = ~434.78ms
|
||||
470, // 2.1 cps = ~478.19ms
|
||||
500, // 2.0 cps = 500ms
|
||||
};
|
||||
|
||||
bool kbc_scancode(struct Kbc * kbc, uint16_t key, bool pressed) {
|
||||
if (!kbc_first) return true;
|
||||
if (kbc_translate) {
|
||||
key = keymap_translate(key);
|
||||
}
|
||||
if (!key) return true;
|
||||
switch (key & 0xFF00) {
|
||||
case K_E0:
|
||||
TRACE(" E0\n");
|
||||
if (!kbc_keyboard(kbc, 0xE0, KBC_TIMEOUT)) return false;
|
||||
key &= 0xFF;
|
||||
// Fall through
|
||||
case 0x00:
|
||||
if (!pressed) {
|
||||
if (kbc_translate) {
|
||||
key |= 0x80;
|
||||
} else {
|
||||
TRACE(" F0\n");
|
||||
if (!kbc_keyboard(kbc, 0xF0, KBC_TIMEOUT)) return false;
|
||||
}
|
||||
}
|
||||
TRACE(" %02X\n", key);
|
||||
if (!kbc_keyboard(kbc, (uint8_t)key, KBC_TIMEOUT)) return false;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
enum KbcState {
|
||||
KBC_STATE_NORMAL,
|
||||
KBC_STATE_WRITE_CONFIG,
|
||||
KBC_STATE_SET_LEDS,
|
||||
KBC_STATE_SCANCODE,
|
||||
KBC_STATE_TYPEMATIC,
|
||||
KBC_STATE_WRITE_PORT,
|
||||
KBC_STATE_FIRST_PORT_OUTPUT,
|
||||
KBC_STATE_SECOND_PORT_OUTPUT,
|
||||
KBC_STATE_SECOND_PORT_INPUT,
|
||||
};
|
||||
|
||||
void kbc_event(struct Kbc * kbc) {
|
||||
// TODO: state per KBC (we only have one KBC so low priority)
|
||||
static enum KbcState state = KBC_STATE_NORMAL;
|
||||
|
||||
uint8_t sts = kbc_status(kbc);
|
||||
if (sts & KBC_STS_IBF) {
|
||||
uint8_t data = kbc_read(kbc);
|
||||
if (sts & KBC_STS_CMD) {
|
||||
TRACE("kbc cmd: %02X\n", data);
|
||||
|
||||
state = KBC_STATE_NORMAL;
|
||||
switch (data) {
|
||||
case 0x20:
|
||||
TRACE(" read configuration byte\n");
|
||||
uint8_t config = *kbc->control & 0x03;
|
||||
if (kbc_system) {
|
||||
config |= (1 << 2);
|
||||
}
|
||||
if (!kbc_first) {
|
||||
config |= (1 << 4);
|
||||
}
|
||||
if (!kbc_second) {
|
||||
config |= (1 << 5);
|
||||
}
|
||||
if (kbc_translate) {
|
||||
config |= (1 << 6);
|
||||
}
|
||||
kbc_keyboard(kbc, config, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0x60:
|
||||
TRACE(" write configuration byte\n");
|
||||
state = KBC_STATE_WRITE_CONFIG;
|
||||
break;
|
||||
case 0xA7:
|
||||
TRACE(" disable second port\n");
|
||||
kbc_second = false;
|
||||
break;
|
||||
case 0xA8:
|
||||
TRACE(" enable second port\n");
|
||||
kbc_second = true;
|
||||
break;
|
||||
case 0xA9:
|
||||
TRACE(" test second port\n");
|
||||
// TODO: communicate with touchpad?
|
||||
kbc_keyboard(kbc, 0x00, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xAA:
|
||||
TRACE(" test controller\n");
|
||||
// Why not pass the test?
|
||||
kbc_keyboard(kbc, 0x55, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xAB:
|
||||
TRACE(" test first port\n");
|
||||
// We _ARE_ the keyboard, so everything is good.
|
||||
kbc_keyboard(kbc, 0x00, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xAD:
|
||||
TRACE(" disable first port\n");
|
||||
kbc_first = false;
|
||||
break;
|
||||
case 0xAE:
|
||||
TRACE(" enable first port\n");
|
||||
kbc_first = true;
|
||||
break;
|
||||
case 0xD1:
|
||||
TRACE(" write port byte\n");
|
||||
state = KBC_STATE_WRITE_PORT;
|
||||
break;
|
||||
case 0xD2:
|
||||
TRACE(" write first port output\n");
|
||||
state = KBC_STATE_FIRST_PORT_OUTPUT;
|
||||
break;
|
||||
case 0xD3:
|
||||
TRACE(" write second port output\n");
|
||||
state = KBC_STATE_SECOND_PORT_OUTPUT;
|
||||
break;
|
||||
case 0xD4:
|
||||
TRACE(" write second port input\n");
|
||||
state = KBC_STATE_SECOND_PORT_INPUT;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
TRACE("kbc data: %02X\n", data);
|
||||
|
||||
switch (state) {
|
||||
case KBC_STATE_NORMAL:
|
||||
TRACE(" keyboard command\n");
|
||||
switch (data) {
|
||||
case 0xED:
|
||||
TRACE(" set leds\n");
|
||||
state = KBC_STATE_SET_LEDS;
|
||||
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xEE:
|
||||
TRACE(" echo\n");
|
||||
// Hey, this is easy. I like easy commands
|
||||
kbc_keyboard(kbc, 0xEE, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xF0:
|
||||
TRACE(" get/set scancode\n");
|
||||
state = KBC_STATE_SCANCODE;
|
||||
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xF2:
|
||||
TRACE(" identify keyboard\n");
|
||||
if (kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT)) {
|
||||
if (kbc_keyboard(kbc, 0xAB, KBC_TIMEOUT)) {
|
||||
kbc_keyboard(kbc, 0x83, KBC_TIMEOUT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xF3:
|
||||
TRACE(" set typematic rate/delay\n");
|
||||
state = KBC_STATE_TYPEMATIC;
|
||||
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xF4:
|
||||
TRACE(" enable scanning\n");
|
||||
kbscan_enabled = true;
|
||||
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xF5:
|
||||
TRACE(" disable scanning\n");
|
||||
kbscan_enabled = false;
|
||||
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
|
||||
break;
|
||||
case 0xFF:
|
||||
TRACE(" self test\n");
|
||||
if (kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT)) {
|
||||
// Yep, everything is still good, I promise
|
||||
kbc_keyboard(kbc, 0xAA, KBC_TIMEOUT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case KBC_STATE_WRITE_CONFIG:
|
||||
TRACE(" write configuration byte\n");
|
||||
state = KBC_STATE_NORMAL;
|
||||
uint8_t control = *kbc->control;
|
||||
if (data & 1) {
|
||||
control |= 1;
|
||||
} else {
|
||||
control &= ~1;
|
||||
}
|
||||
if (data & (1 << 1)) {
|
||||
control |= (1 << 1);
|
||||
} else {
|
||||
control &= ~(1 << 1);
|
||||
}
|
||||
kbc_system = (bool)(data & (1 << 2));
|
||||
kbc_first = (bool)(!(data & (1 << 4)));
|
||||
kbc_second = (bool)(!(data & (1 << 5)));
|
||||
kbc_translate = (bool)(data & (1 << 6));
|
||||
*kbc->control = control;
|
||||
break;
|
||||
case KBC_STATE_SET_LEDS:
|
||||
TRACE(" set leds\n");
|
||||
state = KBC_STATE_NORMAL;
|
||||
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
|
||||
break;
|
||||
case KBC_STATE_SCANCODE:
|
||||
TRACE(" get/set scancode\n");
|
||||
state = KBC_STATE_NORMAL;
|
||||
#if LEVEL >= LEVEL_TRACE
|
||||
switch (data) {
|
||||
case 0x02:
|
||||
TRACE(" set scancode set 2\n");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
|
||||
break;
|
||||
case KBC_STATE_TYPEMATIC:
|
||||
TRACE(" set typematic rate/delay\n");
|
||||
state = KBC_STATE_NORMAL;
|
||||
{
|
||||
// Rate: bits 0-4
|
||||
uint16_t period = kbc_typematic_period[data & 0x1F];
|
||||
kbscan_repeat_period = period;
|
||||
|
||||
// Delay: bits 5-6
|
||||
static const uint16_t delay[4] = {250, 500, 750, 1000};
|
||||
uint8_t idx = (data & 0x60) >> 5;
|
||||
kbscan_repeat_delay = delay[idx];
|
||||
}
|
||||
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
|
||||
break;
|
||||
case KBC_STATE_WRITE_PORT:
|
||||
TRACE(" write port byte\n");
|
||||
state = KBC_STATE_NORMAL;
|
||||
break;
|
||||
case KBC_STATE_FIRST_PORT_OUTPUT:
|
||||
TRACE(" write first port output\n");
|
||||
state = KBC_STATE_NORMAL;
|
||||
kbc_keyboard(kbc, data, KBC_TIMEOUT);
|
||||
break;
|
||||
case KBC_STATE_SECOND_PORT_OUTPUT:
|
||||
TRACE(" write second port output\n");
|
||||
state = KBC_STATE_NORMAL;
|
||||
kbc_mouse(kbc, data, KBC_TIMEOUT);
|
||||
break;
|
||||
case KBC_STATE_SECOND_PORT_INPUT:
|
||||
TRACE(" write second port input\n");
|
||||
state = KBC_STATE_NORMAL;
|
||||
ps2_write(&PS2_3, &data, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -17,8 +17,11 @@ static uint8_t __code levels[] = {
|
||||
void kbled_init(void) {
|
||||
// Enable DAC used for KBLIGHT_ADJ
|
||||
DACPDREG &= ~(1 << KBLED_DAC);
|
||||
// Set DAC to 0V
|
||||
KBLED_DACDAT = 0;
|
||||
kbled_reset();
|
||||
}
|
||||
|
||||
void kbled_reset(void) {
|
||||
kbled_set(0);
|
||||
}
|
||||
|
||||
uint8_t kbled_get(void) {
|
||||
|
@ -1,347 +0,0 @@
|
||||
#include <arch/delay.h>
|
||||
#include <arch/time.h>
|
||||
#include <board/gpio.h>
|
||||
#include <board/kbc.h>
|
||||
#include <board/kbled.h>
|
||||
#include <board/kbscan.h>
|
||||
#include <board/keymap.h>
|
||||
#include <board/pmc.h>
|
||||
#include <board/power.h>
|
||||
#include <common/debug.h>
|
||||
|
||||
bool kbscan_enabled = false;
|
||||
uint16_t kbscan_repeat_period = 91;
|
||||
uint16_t kbscan_repeat_delay = 500;
|
||||
|
||||
uint8_t sci_extra = 0;
|
||||
|
||||
void kbscan_init(void) {
|
||||
KSOCTRL = 0x05;
|
||||
KSICTRLR = 0x04;
|
||||
|
||||
// Set all outputs to GPIO mode, low, and inputs
|
||||
KSOL = 0;
|
||||
KSOLGCTRL = 0xFF;
|
||||
KSOLGOEN = 0;
|
||||
KSOH1 = 0;
|
||||
KSOHGCTRL = 0xFF;
|
||||
KSOHGOEN = 0;
|
||||
KSOH2 = 0;
|
||||
}
|
||||
|
||||
// Debounce time in milliseconds
|
||||
#define DEBOUNCE_DELAY 20
|
||||
|
||||
static uint8_t kbscan_get_row(int i) {
|
||||
// Set current line as output
|
||||
if (i < 8) {
|
||||
KSOLGOEN = 1 << i;
|
||||
KSOHGOEN = 0;
|
||||
} else if (i < 16) {
|
||||
KSOLGOEN = 0;
|
||||
KSOHGOEN = 1 << (i - 8);
|
||||
} else if (i == 16) {
|
||||
KSOLGOEN = 0;
|
||||
KSOHGOEN = 0;
|
||||
} else if (i == 17) {
|
||||
KSOLGOEN = 0;
|
||||
KSOHGOEN = 0;
|
||||
}
|
||||
|
||||
// TODO: figure out optimal delay
|
||||
delay_ticks(10);
|
||||
|
||||
return ~KSI;
|
||||
}
|
||||
|
||||
static inline bool popcount_more_than_one(uint8_t rowdata) {
|
||||
return rowdata & (rowdata - 1);
|
||||
}
|
||||
|
||||
static uint8_t kbscan_get_real_keys(int row, uint8_t rowdata) {
|
||||
// Remove any "active" blanks from the matrix.
|
||||
uint8_t realdata = 0;
|
||||
for (uint8_t col = 0; col < KM_IN; col++) {
|
||||
if (KEYMAP[0][row][col] && (rowdata & (1 << col))) {
|
||||
realdata |= 1 << col;
|
||||
}
|
||||
}
|
||||
|
||||
return realdata;
|
||||
}
|
||||
|
||||
static bool kbscan_has_ghost_in_row(int row, uint8_t rowdata) {
|
||||
rowdata = kbscan_get_real_keys(row, rowdata);
|
||||
|
||||
// No ghosts exist when less than 2 keys in the row are active.
|
||||
if (!popcount_more_than_one(rowdata)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check against other rows to see if more than one column matches.
|
||||
for (int i = 0; i < KM_OUT; i++) {
|
||||
uint8_t otherrow = kbscan_get_real_keys(i, kbscan_get_row(i));
|
||||
if (i != row && popcount_more_than_one(otherrow & rowdata)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool kbscan_press(uint16_t key, bool pressed, uint8_t * layer) {
|
||||
if (pressed &&
|
||||
(power_state == POWER_STATE_S3 || power_state == POWER_STATE_DS3)) {
|
||||
gpio_set(&SWI_N, false);
|
||||
delay_ticks(10); //TODO: find correct delay
|
||||
gpio_set(&SWI_N, true);
|
||||
}
|
||||
|
||||
switch (key & KT_MASK) {
|
||||
case (KT_NORMAL):
|
||||
if (kbscan_enabled) {
|
||||
kbc_scancode(&KBC, key, pressed);
|
||||
}
|
||||
break;
|
||||
case (KT_FN):
|
||||
if (layer != NULL) {
|
||||
if (pressed) *layer = 1;
|
||||
else *layer = 0;
|
||||
} else {
|
||||
// In the case no layer can be set, reset bit
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case (KT_COMBO):
|
||||
switch (key & 0xFF) {
|
||||
case COMBO_DISPLAY_MODE:
|
||||
if (kbscan_enabled) {
|
||||
if (pressed) {
|
||||
kbc_scancode(&KBC, K_LEFT_SUPER, true);
|
||||
kbc_scancode(&KBC, K_P, true);
|
||||
kbc_scancode(&KBC, K_P, false);
|
||||
} else {
|
||||
kbc_scancode(&KBC, K_LEFT_SUPER, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case COMBO_PRINT_SCREEN:
|
||||
if (kbscan_enabled) {
|
||||
if (pressed) {
|
||||
kbc_scancode(&KBC, K_E0 | 0x12, true);
|
||||
kbc_scancode(&KBC, K_E0 | 0x7C, true);
|
||||
} else {
|
||||
kbc_scancode(&KBC, K_E0 | 0x7C, false);
|
||||
kbc_scancode(&KBC, K_E0 | 0x12, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case (KT_SCI):
|
||||
if (pressed) {
|
||||
uint8_t sci = (uint8_t)(key & 0xFF);
|
||||
|
||||
// HACK FOR HARDWARE HOTKEYS
|
||||
switch (sci) {
|
||||
case SCI_DISPLAY_TOGGLE:
|
||||
gpio_set(&BKL_EN, !gpio_get(&BKL_EN));
|
||||
break;
|
||||
case SCI_CAMERA_TOGGLE:
|
||||
gpio_set(&CCD_EN, !gpio_get(&CCD_EN));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pmc_sci(&PMC_1, sci)) {
|
||||
// In the case of ignored SCI, reset bit
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case (KT_SCI_EXTRA):
|
||||
if (pressed) {
|
||||
uint8_t sci = SCI_EXTRA;
|
||||
sci_extra = (uint8_t)(key & 0xFF);
|
||||
|
||||
// HACK FOR HARDWARE HOTKEYS
|
||||
switch (sci_extra) {
|
||||
case SCI_EXTRA_KBD_BKL:
|
||||
kbled_set(kbled_get() + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pmc_sci(&PMC_1, sci)) {
|
||||
// In the case of ignored SCI, reset bit
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void kbscan_event(void) {
|
||||
static uint8_t kbscan_layer = 0;
|
||||
uint8_t layer = kbscan_layer;
|
||||
static uint8_t kbscan_last[KM_OUT] = { 0 };
|
||||
|
||||
static bool debounce = false;
|
||||
static uint32_t debounce_time = 0;
|
||||
|
||||
static bool repeat = false;
|
||||
static uint16_t repeat_key = 0;
|
||||
static uint32_t repeat_key_time = 0;
|
||||
|
||||
// If debounce complete
|
||||
if (debounce) {
|
||||
uint32_t time = time_get();
|
||||
//TODO: time test with overflow
|
||||
if (time < debounce_time) {
|
||||
// Overflow, reset debounce_time
|
||||
debounce_time = time;
|
||||
} else if (time >= (debounce_time + DEBOUNCE_DELAY)) {
|
||||
// Finish debounce
|
||||
debounce = false;
|
||||
}
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < KM_OUT; i++) {
|
||||
uint8_t new = kbscan_get_row(i);
|
||||
uint8_t last = kbscan_last[i];
|
||||
if (new != last) {
|
||||
if (kbscan_has_ghost_in_row(i, new)) {
|
||||
kbscan_last[i] = new;
|
||||
continue;
|
||||
}
|
||||
|
||||
// A key was pressed or released
|
||||
int j;
|
||||
for (j = 0; j < KM_IN; j++) {
|
||||
bool new_b = new & (1 << j);
|
||||
bool last_b = last & (1 << j);
|
||||
if (new_b != last_b) {
|
||||
bool reset = false;
|
||||
|
||||
// If debouncing
|
||||
if (debounce) {
|
||||
// Debounce presses and releases
|
||||
reset = true;
|
||||
} else {
|
||||
// Begin debounce
|
||||
debounce = true;
|
||||
debounce_time = time_get();
|
||||
|
||||
// Handle key press/release
|
||||
uint16_t key = keymap(i, j, kbscan_layer);
|
||||
if (key) {
|
||||
DEBUG("KB %d, %d, %d = 0x%04X, %d\n", i, j, kbscan_layer, key, new_b);
|
||||
if(!kbscan_press(key, new_b, &layer)){
|
||||
// In the case of ignored key press/release, reset bit
|
||||
reset = true;
|
||||
}
|
||||
|
||||
if (new_b) {
|
||||
// New key pressed, update last key
|
||||
repeat_key = key;
|
||||
repeat_key_time = time_get();
|
||||
repeat = false;
|
||||
} else if (key == repeat_key) {
|
||||
// Repeat key was released
|
||||
repeat_key = 0;
|
||||
repeat = false;
|
||||
}
|
||||
} else {
|
||||
WARN("KB %d, %d, %d missing\n", i, j, kbscan_layer);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset bit to last state
|
||||
if (reset) {
|
||||
if (last_b) {
|
||||
new |= (1 << j);
|
||||
} else {
|
||||
new &= ~(1 << j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kbscan_last[i] = new;
|
||||
} else if (new && repeat_key != 0) {
|
||||
// A key is being pressed
|
||||
uint32_t time = time_get();
|
||||
static uint32_t repeat_start = 0;
|
||||
|
||||
if (!repeat) {
|
||||
if (time < repeat_key_time) {
|
||||
// Overflow, reset repeat_key_time
|
||||
repeat_key_time = time;
|
||||
} else if ((time - repeat_key_time) >= kbscan_repeat_delay) {
|
||||
// Typematic repeat
|
||||
repeat = true;
|
||||
repeat_start = time;
|
||||
}
|
||||
}
|
||||
|
||||
if (repeat) {
|
||||
if ((time - repeat_start) > kbscan_repeat_period) {
|
||||
kbscan_press(repeat_key, true, &layer);
|
||||
repeat_start = time;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (layer != kbscan_layer) {
|
||||
//TODO: unpress keys before going to scratch rom
|
||||
|
||||
// Unpress all currently pressed keys
|
||||
for (i = 0; i < KM_OUT; i++) {
|
||||
uint8_t new = 0;
|
||||
uint8_t last = kbscan_last[i];
|
||||
if (last) {
|
||||
int j;
|
||||
for (j = 0; j < KM_IN; j++) {
|
||||
bool new_b = new & (1 << j);
|
||||
bool last_b = last & (1 << j);
|
||||
if (new_b != last_b) {
|
||||
bool reset = false;
|
||||
|
||||
// Handle key press/release
|
||||
uint16_t key = keymap(i, j, kbscan_layer);
|
||||
if (key) {
|
||||
DEBUG("KB %d, %d, %d = 0x%04X, %d\n", i, j, kbscan_layer, key, new_b);
|
||||
if(!kbscan_press(key, new_b, NULL)){
|
||||
// In the case of ignored key press/release, reset bit
|
||||
reset = true;
|
||||
}
|
||||
} else {
|
||||
WARN("KB %d, %d, %d missing\n", i, j, kbscan_layer);
|
||||
}
|
||||
|
||||
// Reset bit to last state
|
||||
if (reset) {
|
||||
if (last_b) {
|
||||
new |= (1 << j);
|
||||
} else {
|
||||
new &= ~(1 << j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kbscan_last[i] = new;
|
||||
}
|
||||
|
||||
kbscan_layer = layer;
|
||||
}
|
||||
|
||||
// Reset all lines to inputs
|
||||
KSOLGOEN = 0;
|
||||
KSOHGOEN = 0;
|
||||
|
||||
// TODO: figure out optimal delay
|
||||
delay_ticks(10);
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
#include <board/keymap.h>
|
||||
#include <common/debug.h>
|
||||
|
||||
uint16_t keymap(int output, int input, int layer) {
|
||||
if (output < KM_OUT && input < KM_IN && layer < KM_LAY) {
|
||||
return KEYMAP[layer][output][input];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -1,45 +0,0 @@
|
||||
#include <arch/delay.h>
|
||||
#include <board/gpio.h>
|
||||
#include <board/lid.h>
|
||||
#include <board/pmc.h>
|
||||
#include <common/debug.h>
|
||||
|
||||
bool lid_state = true;
|
||||
bool lid_wake = false;
|
||||
|
||||
void lid_event(void) {
|
||||
static bool send_sci = true;
|
||||
|
||||
// Check if the lid switch has changed
|
||||
bool new = gpio_get(&LID_SW_N);
|
||||
if (new != lid_state) {
|
||||
DEBUG("Lid ");
|
||||
if (new) {
|
||||
DEBUG("open\n");
|
||||
|
||||
if (lid_wake) {
|
||||
gpio_set(&SWI_N, false);
|
||||
|
||||
//TODO: find correct delay
|
||||
delay_ticks(10);
|
||||
|
||||
gpio_set(&SWI_N, true);
|
||||
|
||||
lid_wake = false;
|
||||
}
|
||||
} else {
|
||||
DEBUG("closed\n");
|
||||
}
|
||||
|
||||
// Send SCI
|
||||
send_sci = true;
|
||||
}
|
||||
lid_state = new;
|
||||
|
||||
if (send_sci) {
|
||||
// Send SCI 0x1B for lid event
|
||||
if (pmc_sci(&PMC_1, 0x1B)) {
|
||||
send_sci = false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,178 +0,0 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <board/peci.h>
|
||||
#include <board/power.h>
|
||||
#include <common/debug.h>
|
||||
#include <common/macro.h>
|
||||
#include <ec/gpio.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
|
||||
|
||||
// Tjunction = 100C for i7-8565U (and probably the same for all WHL-U)
|
||||
#define T_JUNCTION 100
|
||||
|
||||
int16_t peci_offset = 0;
|
||||
int16_t peci_temp = 0;
|
||||
uint8_t peci_duty = 0;
|
||||
|
||||
#define PECI_TEMP(X) (((int16_t)(X)) << 6)
|
||||
#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 = PECI_TEMP(T), .duty = PWM_DUTY(D) }
|
||||
|
||||
// Fan curve with temperature in degrees C, duty cycle in percent
|
||||
struct FanPoint __code FAN_POINTS[] = {
|
||||
FAN_POINT(65, 40),
|
||||
FAN_POINT(70, 55),
|
||||
FAN_POINT(75, 75),
|
||||
FAN_POINT(80, 100)
|
||||
};
|
||||
|
||||
// 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) {
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 peci_init(void) {
|
||||
// Allow PECI pin to be used
|
||||
GCR2 |= (1 << 4);
|
||||
|
||||
// Set frequency to 1MHz
|
||||
HOCTL2R = 0x01;
|
||||
// Set VTT to 1V
|
||||
PADCTLR = 0x02;
|
||||
}
|
||||
|
||||
// PECI information can be found here: https://www.intel.com/content/dam/www/public/us/en/documents/design-guides/core-i7-lga-2011-guide.pdf
|
||||
void peci_event(void) {
|
||||
if (power_state == POWER_STATE_S0) {
|
||||
// Use PECI if in S0 state
|
||||
|
||||
// Wait for completion
|
||||
while (HOSTAR & 1) {}
|
||||
// Clear status
|
||||
HOSTAR = HOSTAR;
|
||||
|
||||
// Enable PECI, clearing data fifo's
|
||||
HOCTLR = (1 << 5) | (1 << 3);
|
||||
// Set address to default
|
||||
HOTRADDR = 0x30;
|
||||
// Set write length
|
||||
HOWRLR = 1;
|
||||
// Set read length
|
||||
HORDLR = 2;
|
||||
// Set command
|
||||
HOCMDR = 1;
|
||||
// Start transaction
|
||||
HOCTLR |= 1;
|
||||
|
||||
// Wait for completion
|
||||
while (HOSTAR & 1) {}
|
||||
|
||||
if (HOSTAR & (1 << 1)) {
|
||||
// Use result if finished successfully
|
||||
uint8_t low = HORDDR;
|
||||
uint8_t high = HORDDR;
|
||||
peci_offset = ((int16_t)high << 8) | (int16_t)low;
|
||||
|
||||
peci_temp = PECI_TEMP(T_JUNCTION) + peci_offset;
|
||||
peci_duty = fan_duty(peci_temp);
|
||||
} else {
|
||||
// Default to 50% if there is an error
|
||||
peci_offset = 0;
|
||||
peci_temp = 0;
|
||||
peci_duty = PWM_DUTY(50);
|
||||
}
|
||||
} else {
|
||||
// Turn fan off if not in S0 state
|
||||
peci_offset = 0;
|
||||
peci_temp = 0;
|
||||
peci_duty = PWM_DUTY(0);
|
||||
}
|
||||
|
||||
uint8_t heatup_duty = fan_heatup(peci_duty);
|
||||
uint8_t cooldown_duty = fan_cooldown(heatup_duty);
|
||||
if (cooldown_duty != DCR2) {
|
||||
DCR2 = cooldown_duty;
|
||||
DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, cooldown_duty);
|
||||
}
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
#include <arch/delay.h>
|
||||
#include <board/acpi.h>
|
||||
#include <board/gpio.h>
|
||||
#include <board/pmc.h>
|
||||
#include <common/debug.h>
|
||||
|
||||
void pmc_init(void) {
|
||||
*(PMC_1.control) = 0x41;
|
||||
*(PMC_2.control) = 0x41;
|
||||
}
|
||||
|
||||
enum PmcState {
|
||||
PMC_STATE_DEFAULT,
|
||||
PMC_STATE_WRITE,
|
||||
PMC_STATE_ACPI_READ,
|
||||
PMC_STATE_ACPI_WRITE,
|
||||
PMC_STATE_ACPI_WRITE_ADDR,
|
||||
};
|
||||
|
||||
static uint8_t pmc_sci_queue = 0;
|
||||
|
||||
void pmc_sci_interrupt(void) {
|
||||
// Start SCI interrupt
|
||||
gpio_set(&SCI_N, false);
|
||||
*(SCI_N.control) = GPIO_OUT;
|
||||
|
||||
// Delay T_HOLD (value assumed)
|
||||
delay_us(65);
|
||||
|
||||
// Stop SCI interrupt
|
||||
*(SCI_N.control) = GPIO_IN;
|
||||
gpio_set(&SCI_N, true);
|
||||
|
||||
// Delay T_HOLD (value assumed)
|
||||
delay_us(65);
|
||||
}
|
||||
|
||||
bool pmc_sci(struct Pmc * pmc, uint8_t sci) {
|
||||
// Set SCI queue if possible
|
||||
if (pmc_sci_queue == 0) {
|
||||
pmc_sci_queue = sci;
|
||||
|
||||
// Set SCI pending bit
|
||||
pmc_set_status(pmc, pmc_status(pmc) | (1 << 5));
|
||||
|
||||
// Send SCI
|
||||
pmc_sci_interrupt();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void pmc_event(struct Pmc * pmc) {
|
||||
static enum PmcState state = PMC_STATE_DEFAULT;
|
||||
static uint8_t state_data = 0;
|
||||
|
||||
uint8_t sts = pmc_status(pmc);
|
||||
|
||||
// Read command/data if available
|
||||
if (sts & PMC_STS_IBF) {
|
||||
uint8_t data = pmc_read(pmc);
|
||||
if (sts & PMC_STS_CMD) {
|
||||
TRACE("pmc cmd: %02X\n", data);
|
||||
|
||||
state = PMC_STATE_DEFAULT;
|
||||
switch (data) {
|
||||
case 0x80:
|
||||
state = PMC_STATE_ACPI_READ;
|
||||
// Send SCI for IBF=0
|
||||
pmc_sci_interrupt();
|
||||
break;
|
||||
case 0x81:
|
||||
state = PMC_STATE_ACPI_WRITE;
|
||||
// Send SCI for IBF=0
|
||||
pmc_sci_interrupt();
|
||||
break;
|
||||
case 0x82:
|
||||
TRACE(" burst enable\n");
|
||||
// Set burst bit
|
||||
pmc_set_status(pmc, sts | (1 << 4));
|
||||
// Send acknowledgement byte
|
||||
state = PMC_STATE_WRITE;
|
||||
state_data = 0x90;
|
||||
break;
|
||||
case 0x83:
|
||||
TRACE(" burst disable\n");
|
||||
// Clear burst bit
|
||||
pmc_set_status(pmc, sts & ~(1 << 4));
|
||||
// Send SCI for IBF=0
|
||||
pmc_sci_interrupt();
|
||||
break;
|
||||
case 0x84:
|
||||
TRACE(" SCI queue\n");
|
||||
// Clear SCI pending bit
|
||||
pmc_set_status(pmc, sts & ~(1 << 5));
|
||||
// Send SCI queue
|
||||
state = PMC_STATE_WRITE;
|
||||
state_data = pmc_sci_queue;
|
||||
// Clear SCI queue
|
||||
pmc_sci_queue = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
TRACE("pmc data: %02X\n", data);
|
||||
|
||||
switch (state) {
|
||||
case PMC_STATE_ACPI_READ:
|
||||
// Send byte from ACPI space
|
||||
state = PMC_STATE_WRITE;
|
||||
state_data = acpi_read(data);
|
||||
break;
|
||||
case PMC_STATE_ACPI_WRITE:
|
||||
state = PMC_STATE_ACPI_WRITE_ADDR;
|
||||
state_data = data;
|
||||
// Send SCI for IBF=0
|
||||
pmc_sci_interrupt();
|
||||
break;
|
||||
case PMC_STATE_ACPI_WRITE_ADDR:
|
||||
state = PMC_STATE_DEFAULT;
|
||||
acpi_write(state_data, data);
|
||||
// Send SCI for IBF=0
|
||||
pmc_sci_interrupt();
|
||||
break;
|
||||
default:
|
||||
state = PMC_STATE_DEFAULT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write data if possible
|
||||
if (!(sts & PMC_STS_OBF)) {
|
||||
switch (state) {
|
||||
case PMC_STATE_WRITE:
|
||||
TRACE("pmc write: %02X\n", state_data);
|
||||
state = PMC_STATE_DEFAULT;
|
||||
pmc_write(pmc, state_data);
|
||||
// Send SCI for OBF=1
|
||||
pmc_sci_interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
|
||||
volatile uint8_t __xdata __at(0x1200) IHIOA;
|
||||
volatile uint8_t __xdata __at(0x1201) IHD;
|
||||
volatile uint8_t __xdata __at(0x1204) IBMAE;
|
||||
volatile uint8_t __xdata __at(0x1205) IBCTL;
|
||||
void e2ci_write(uint8_t port, uint8_t data) {
|
||||
while (IBCTL & ((1 << 2) | (1 << 1))) {}
|
||||
IHIOA = port;
|
||||
IHD = data;
|
||||
IBMAE = 1;
|
||||
IBCTL = 1;
|
||||
while (IBCTL & (1 << 2)) {}
|
||||
IBMAE = 0;
|
||||
IBCTL = 0;
|
||||
}
|
||||
|
||||
void pnp_write(uint8_t reg, uint8_t data) {
|
||||
e2ci_write(0x2E, reg);
|
||||
e2ci_write(0x2F, data);
|
||||
}
|
||||
|
||||
void pnp_enable() {
|
||||
DEBUG("Enable PNP devices\n");
|
||||
|
||||
// Enable PMC1
|
||||
pnp_write(0x07, 0x11);
|
||||
pnp_write(0x30, 0x01);
|
||||
|
||||
// Enable KBC keyboard
|
||||
pnp_write(0x07, 0x06);
|
||||
pnp_write(0x30, 0x01);
|
||||
|
||||
// Enable KBC mouse
|
||||
pnp_write(0x07, 0x05);
|
||||
pnp_write(0x30, 0x01);
|
||||
|
||||
// Enable SMFI
|
||||
pnp_write(0x07, 0x0F);
|
||||
pnp_write(0xF5, 0x00);
|
||||
pnp_write(0xF6, 0x01);
|
||||
pnp_write(0x30, 0x01);
|
||||
|
||||
// Enable SWUC
|
||||
pnp_write(0x07, 0x04);
|
||||
pnp_write(0x30, 0x01);
|
||||
}
|
@ -1,436 +0,0 @@
|
||||
#include <arch/delay.h>
|
||||
#include <arch/time.h>
|
||||
#include <board/battery.h>
|
||||
#include <board/gpio.h>
|
||||
#include <board/lid.h>
|
||||
#include <board/power.h>
|
||||
#include <board/pmc.h>
|
||||
#include <board/pnp.h>
|
||||
#include <common/debug.h>
|
||||
|
||||
// Platform does not currently support Deep Sx
|
||||
#define DEEP_SX 0
|
||||
|
||||
extern uint8_t main_cycle;
|
||||
|
||||
// VccRTC stable (55%) to RTCRST# high
|
||||
#define tPCH01 delay_ms(9)
|
||||
// VccDSW stable (95%) to RSMRST# high
|
||||
#define tPCH02 delay_ms(10)
|
||||
// VccPrimary stable (95%) to RSMRST# high
|
||||
#define tPCH03 delay_ms(10)
|
||||
// VccRTC stable (90%) to start of VccDSW voltage ramp
|
||||
#define tPCH04 delay_ms(9)
|
||||
// RTCRST# high to DSW_PWROK
|
||||
#define tPCH05 delay_us(1)
|
||||
// VccDSW 3.3 stable to VccPrimary 1.05V
|
||||
#define tPCH06 delay_us(200)
|
||||
// DSW_PWROK high to RSMRST# high
|
||||
#define tPCH07 delay_ms(0)
|
||||
// SLP_S3# de-assertion to PCH_PWROK assertion
|
||||
#define tPCH08 delay_ms(1)
|
||||
// SLP_A# high when ASW rails are stable (95%)
|
||||
#define tPCH09 delay_ms(2, 4, 8, 16) //TODO
|
||||
// PCH_PWROK low to VCCIO dropping 5%
|
||||
#define tPCH10 delay_ns(400)
|
||||
// SLP_SUS# asserting to VccPRIM dropping 5%
|
||||
#define tPCH11 delay_ns(100)
|
||||
// RSMRST# asserting to VccPRIM dropping 5%
|
||||
#define tPCH12 delay_ns(400)
|
||||
// DSW_PWROK falling to any of VccDSW, VccPRIM dropping 5%
|
||||
#define tPCH14 delay_ns(400)
|
||||
// De-assertion of RSMRST# to de-assertion of ESPI_RESET#
|
||||
#if DEEP_SX
|
||||
#define tPCH18 delay_us(90)
|
||||
#else
|
||||
#define tPCH18 delay_ms(95)
|
||||
#endif
|
||||
// DSW_PWROK assertion to SLP_SUS# de-assertion
|
||||
#define tPCH32 delay_ms(95)
|
||||
// RSMRST# de-assertion to SUSPWRDNACK valid
|
||||
#define tPLT01 delay_ms(200)
|
||||
|
||||
enum PowerState power_state = POWER_STATE_DEFAULT;
|
||||
|
||||
enum PowerState calculate_power_state(void) {
|
||||
//TODO: Deep Sx states using SLP_SUS#
|
||||
|
||||
if (gpio_get(&SUSB_N_PCH)) {
|
||||
// S3, S4, and S5 planes powered
|
||||
return POWER_STATE_S0;
|
||||
}
|
||||
|
||||
if (gpio_get(&SUSC_N_PCH)) {
|
||||
// S4 and S5 planes powered
|
||||
return POWER_STATE_S3;
|
||||
}
|
||||
|
||||
if (gpio_get(&EC_RSMRST_N)) {
|
||||
// S5 plane powered
|
||||
return POWER_STATE_S5;
|
||||
}
|
||||
|
||||
#if DEEP_SX
|
||||
if (gpio_get(&PCH_DPWROK_EC)) {
|
||||
return POWER_STATE_DS5;
|
||||
}
|
||||
|
||||
return POWER_STATE_DEFAULT;
|
||||
#else
|
||||
return POWER_STATE_DS5;
|
||||
#endif
|
||||
}
|
||||
|
||||
void update_power_state(void) {
|
||||
enum PowerState new_power_state = calculate_power_state();
|
||||
if (power_state != new_power_state) {
|
||||
power_state = new_power_state;
|
||||
|
||||
#if LEVEL >= LEVEL_DEBUG
|
||||
switch (power_state) {
|
||||
case POWER_STATE_DEFAULT:
|
||||
DEBUG("POWER_STATE_DEFAULT\n");
|
||||
break;
|
||||
case POWER_STATE_DS5:
|
||||
DEBUG("POWER_STATE_DS5\n");
|
||||
break;
|
||||
case POWER_STATE_S5:
|
||||
DEBUG("POWER_STATE_S5\n");
|
||||
break;
|
||||
case POWER_STATE_DS3:
|
||||
DEBUG("POWER_STATE_DS3\n");
|
||||
break;
|
||||
case POWER_STATE_S3:
|
||||
DEBUG("POWER_STATE_S3\n");
|
||||
break;
|
||||
case POWER_STATE_S0:
|
||||
DEBUG("POWER_STATE_S0\n");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Enable deep sleep well power
|
||||
void power_on_ds5(void) {
|
||||
DEBUG("%02X: power_on_ds5\n", main_cycle);
|
||||
|
||||
#if DEEP_SX
|
||||
// See Figure 12-18 in Whiskey Lake Platform Design Guide
|
||||
// | VCCRTC | RTCRST# | VCCDSW_3P3 | DSW_PWROK |
|
||||
// | tPCH01---------- | | |
|
||||
// | tPCH04----------------------- | |
|
||||
// | | tPCH05-------------------------- |
|
||||
// | | | tPCH02---------------- |
|
||||
|
||||
// tPCH01 and tPCH02 combined make the longest delay
|
||||
tPCH01;
|
||||
tPCH02;
|
||||
|
||||
// Deep sleep well is a-ok
|
||||
gpio_set(&PCH_DPWROK_EC, true);
|
||||
// Wait for deep sleep well to propogate
|
||||
tPCH32;
|
||||
#else // DEEP_SX
|
||||
// See Figure 12-19 in Whiskey Lake Platform Design Guide
|
||||
// | VCCRTC | RTCRST# | VccPRIM |
|
||||
// | tPCH01---------- | |
|
||||
// | tPCH04-------------------- |
|
||||
|
||||
// tPCH04 is the ideal delay
|
||||
tPCH04;
|
||||
#endif // DEEP_SX
|
||||
|
||||
update_power_state();
|
||||
}
|
||||
|
||||
// Enable S5 power
|
||||
void power_on_s5(void) {
|
||||
DEBUG("%02X: power_on_s5\n", main_cycle);
|
||||
|
||||
#if DEEP_SX
|
||||
// See Figure 12-18 in Whiskey Lake Platform Design Guide
|
||||
// TODO - signal timing graph
|
||||
// See Figure 12-24 in Whiskey Lake Platform Design Guide
|
||||
// TODO - rail timing graph
|
||||
|
||||
// TODO: Must have SL_SUS# set high by PCH
|
||||
|
||||
// Enable VCCPRIM_* planes - must be enabled prior to USB power in order to
|
||||
// avoid leakage
|
||||
gpio_set(&VA_EC_EN, true);
|
||||
tPCH06;
|
||||
|
||||
// Enable VDD5
|
||||
gpio_set(&DD_ON, true);
|
||||
|
||||
//TODO: Should SUS_ACK# be de-asserted here?
|
||||
tPCH03;
|
||||
|
||||
// De-assert RSMRST#
|
||||
gpio_set(&EC_RSMRST_N, true);
|
||||
|
||||
// Wait for PCH stability
|
||||
tPCH18;
|
||||
|
||||
// Allow processor to control SUSB# and SUSC#
|
||||
gpio_set(&EC_EN, true);
|
||||
|
||||
// Extra wait - TODO remove
|
||||
delay_ms(200);
|
||||
#else // DEEP_SX
|
||||
// See Figure 12-19 in Whiskey Lake Platform Design Guide
|
||||
// TODO - signal timing graph
|
||||
// See Figure 12-25 in Whiskey Lake Platform Design Guide
|
||||
// TODO - rail timing graph
|
||||
|
||||
// Enable VCCPRIM_* planes - must be enabled prior to USB power in order to
|
||||
// avoid leakage
|
||||
gpio_set(&VA_EC_EN, true);
|
||||
tPCH06;
|
||||
|
||||
// Enable VDD5
|
||||
gpio_set(&DD_ON, true);
|
||||
|
||||
// De-assert SUS_ACK# - TODO is this needed on non-dsx?
|
||||
gpio_set(&SUS_PWR_ACK, true);
|
||||
tPCH03;
|
||||
|
||||
// Assert DSW_PWROK
|
||||
gpio_set(&PCH_DPWROK_EC, true);
|
||||
|
||||
// De-assert RSMRST#
|
||||
gpio_set(&EC_RSMRST_N, true);
|
||||
|
||||
// Wait for PCH stability
|
||||
tPCH18;
|
||||
|
||||
// Allow processor to control SUSB# and SUSC#
|
||||
gpio_set(&EC_EN, true);
|
||||
|
||||
// Wait for SUSPWRDNACK validity
|
||||
tPLT01;
|
||||
|
||||
// Extra wait - TODO remove
|
||||
delay_ms(200);
|
||||
#endif // DEEP_SX
|
||||
|
||||
update_power_state();
|
||||
}
|
||||
|
||||
void power_off_s5(void) {
|
||||
DEBUG("%02X: power_off_s5\n", main_cycle);
|
||||
|
||||
#if DEEP_SX
|
||||
// TODO
|
||||
#else // DEEP_SX
|
||||
// De-assert SYS_PWROK
|
||||
gpio_set(&PCH_PWROK_EC, false);
|
||||
|
||||
// De-assert PCH_PWROK
|
||||
gpio_set(&PM_PWROK, false);
|
||||
|
||||
// Block processor from controlling SUSB# and SUSC#
|
||||
gpio_set(&EC_EN, false);
|
||||
|
||||
// De-assert RSMRST#
|
||||
gpio_set(&EC_RSMRST_N, false);
|
||||
|
||||
// Disable VDD5
|
||||
gpio_set(&DD_ON, false);
|
||||
tPCH12;
|
||||
|
||||
// Disable VCCPRIM_* planes
|
||||
gpio_set(&VA_EC_EN, false);
|
||||
|
||||
// De-assert DSW_PWROK
|
||||
gpio_set(&PCH_DPWROK_EC, false);
|
||||
tPCH14;
|
||||
#endif // DEEP_SX
|
||||
|
||||
update_power_state();
|
||||
}
|
||||
|
||||
void power_event(void) {
|
||||
// Always switch to ds5 if EC is running
|
||||
if (power_state == POWER_STATE_DEFAULT) {
|
||||
power_on_ds5();
|
||||
}
|
||||
|
||||
// Check if the adapter line goes low
|
||||
static bool ac_send_sci = true;
|
||||
static bool ac_last = true;
|
||||
bool ac_new = gpio_get(&ACIN_N);
|
||||
if (ac_new != ac_last) {
|
||||
DEBUG("Power adapter ");
|
||||
if (ac_new) {
|
||||
DEBUG("unplugged\n");
|
||||
battery_charger_disable();
|
||||
} else {
|
||||
DEBUG("plugged in\n");
|
||||
battery_charger_enable();
|
||||
}
|
||||
battery_debug();
|
||||
|
||||
// Reset main loop cycle to force reading PECI and battery
|
||||
main_cycle = 0;
|
||||
|
||||
// Send SCI to update AC and battery information
|
||||
ac_send_sci = true;
|
||||
}
|
||||
if (ac_send_sci) {
|
||||
// Send SCI 0x16 for AC detect event
|
||||
if (pmc_sci(&PMC_1, 0x16)) {
|
||||
ac_send_sci = false;
|
||||
}
|
||||
}
|
||||
ac_last = ac_new;
|
||||
|
||||
// Read power switch state
|
||||
static bool ps_last = true;
|
||||
bool ps_new = gpio_get(&PWR_SW_N);
|
||||
// Disable power button if lid is closed and AC is disconnected
|
||||
if (!lid_state && ac_last) {
|
||||
ps_new = true;
|
||||
}
|
||||
if (!ps_new && ps_last) {
|
||||
// Ensure press is not spurious
|
||||
delay_ms(10);
|
||||
if (gpio_get(&PWR_SW_N) != ps_new) {
|
||||
DEBUG("%02X: Spurious press\n", main_cycle);
|
||||
ps_new = ps_last;
|
||||
} else {
|
||||
DEBUG("%02X: Power switch press\n", main_cycle);
|
||||
|
||||
// Enable S5 power if necessary, before sending PWR_BTN
|
||||
update_power_state();
|
||||
if (power_state == POWER_STATE_DS5) {
|
||||
power_on_s5();
|
||||
}
|
||||
}
|
||||
}
|
||||
#if LEVEL >= LEVEL_DEBUG
|
||||
else if (ps_new && !ps_last) {
|
||||
DEBUG("%02X: Power switch release\n", main_cycle);
|
||||
}
|
||||
#endif
|
||||
ps_last = ps_new;
|
||||
|
||||
// Send power signal to PCH
|
||||
gpio_set(&PWR_BTN_N, ps_new);
|
||||
|
||||
// Update power state before determining actions
|
||||
update_power_state();
|
||||
|
||||
#if DEEP_SX
|
||||
//TODO
|
||||
#else // DEEP_SX
|
||||
// If system power is good
|
||||
static bool pg_last = false;
|
||||
bool pg_new = gpio_get(&ALL_SYS_PWRGD);
|
||||
if (pg_new && !pg_last) {
|
||||
DEBUG("%02X: ALL_SYS_PWRGD asserted\n", main_cycle);
|
||||
|
||||
//TODO: tPLT04;
|
||||
|
||||
// Allow H_VR_READY to set PCH_PWROK
|
||||
gpio_set(&PM_PWROK, true);
|
||||
|
||||
// OEM defined delay from ALL_SYS_PWRGD to SYS_PWROK - TODO
|
||||
delay_ms(10);
|
||||
|
||||
// Assert SYS_PWROK, system can finally perform PLT_RST# and boot
|
||||
gpio_set(&PCH_PWROK_EC, true);
|
||||
} else if(!pg_new && pg_last) {
|
||||
DEBUG("%02X: ALL_SYS_PWRGD de-asserted\n", main_cycle);
|
||||
|
||||
// De-assert SYS_PWROK
|
||||
gpio_set(&PCH_PWROK_EC, false);
|
||||
|
||||
// De-assert PCH_PWROK
|
||||
gpio_set(&PM_PWROK, false);
|
||||
}
|
||||
pg_last = pg_new;
|
||||
|
||||
static bool rst_last = false;
|
||||
bool rst_new = gpio_get(&BUF_PLT_RST_N);
|
||||
#if LEVEL >= LEVEL_DEBUG
|
||||
if (!rst_new && rst_last) {
|
||||
DEBUG("%02X: PLT_RST# asserted\n", main_cycle);
|
||||
} else
|
||||
#endif
|
||||
if(rst_new && !rst_last) {
|
||||
DEBUG("%02X: PLT_RST# de-asserted\n", main_cycle);
|
||||
|
||||
// LPC was just reset, enable PNP devices
|
||||
pnp_enable();
|
||||
//TODO: reset KBC and touchpad states
|
||||
}
|
||||
rst_last = rst_new;
|
||||
|
||||
#if LEVEL >= LEVEL_DEBUG
|
||||
static bool sus_last = true;
|
||||
bool sus_new = gpio_get(&SLP_SUS_N);
|
||||
if (!sus_new && sus_last) {
|
||||
DEBUG("%02X: SLP_SUS# asserted\n", main_cycle);
|
||||
} else if (sus_new && !sus_last) {
|
||||
DEBUG("%02X: SLP_SUS# de-asserted\n", main_cycle);
|
||||
}
|
||||
sus_last = sus_new;
|
||||
#endif
|
||||
|
||||
// EC must keep VccPRIM powered if SUSPWRDNACK is de-asserted low or system
|
||||
// state is S3
|
||||
static bool ack_last = false;
|
||||
bool ack_new = gpio_get(&SUSWARN_N);
|
||||
#if LEVEL >= LEVEL_DEBUG
|
||||
if (ack_new && !ack_last) {
|
||||
DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle);
|
||||
} else if (!ack_new && ack_last) {
|
||||
DEBUG("%02X: SUSPWRDNACK de-asserted\n", main_cycle);
|
||||
}
|
||||
#endif
|
||||
ack_last = ack_new;
|
||||
|
||||
if (ack_new) {
|
||||
// Disable S5 power plane if not needed
|
||||
if (power_state == POWER_STATE_S5) {
|
||||
power_off_s5();
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t last_time = 0;
|
||||
uint32_t time = time_get();
|
||||
if (power_state == POWER_STATE_S0) {
|
||||
// CPU on, green light
|
||||
gpio_set(&LED_PWR, true);
|
||||
gpio_set(&LED_ACIN, false);
|
||||
} else if (power_state == POWER_STATE_S3 || power_state == POWER_STATE_DS3) {
|
||||
// Suspended, flashing green light
|
||||
if (
|
||||
(time < last_time) // overflow
|
||||
||
|
||||
(time >= (last_time + 1000)) // timeout
|
||||
) {
|
||||
gpio_set(&LED_PWR, !gpio_get(&LED_PWR));
|
||||
last_time = time;
|
||||
}
|
||||
gpio_set(&LED_ACIN, false);
|
||||
} else if (!ac_new) {
|
||||
// AC plugged in, orange light
|
||||
gpio_set(&LED_PWR, false);
|
||||
gpio_set(&LED_ACIN, true);
|
||||
} else {
|
||||
// CPU off and AC adapter unplugged, flashing orange light
|
||||
gpio_set(&LED_PWR, false);
|
||||
if (
|
||||
(time < last_time) // overflow
|
||||
||
|
||||
(time >= (last_time + 1000)) // timeout
|
||||
) {
|
||||
gpio_set(&LED_ACIN, !gpio_get(&LED_ACIN));
|
||||
last_time = time;
|
||||
}
|
||||
}
|
||||
#endif // DEEP_SX
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
#include <board/ps2.h>
|
||||
|
||||
void ps2_init(void) {
|
||||
ps2_reset(&PS2_1);
|
||||
ps2_reset(&PS2_2);
|
||||
ps2_reset(&PS2_3);
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
#include <board/pwm.h>
|
||||
|
||||
void pwm_init(void) {
|
||||
// Set T0CHSEL to TACH0A and T1CHSEL to TACH1A
|
||||
TSWCTLR = 0;
|
||||
|
||||
// Disable PWM
|
||||
ZTIER = 0;
|
||||
|
||||
// Set prescalar clock frequency to EC clock
|
||||
PCFSR = 0b01;
|
||||
|
||||
// Set clock prescaler to 0 + 1
|
||||
C0CPRS = 0;
|
||||
|
||||
// Set cycle time to 255 + 1
|
||||
CTR0 = 255;
|
||||
|
||||
// Turn off CPU fan (temperature control in peci_event)
|
||||
DCR2 = 0;
|
||||
|
||||
// Enable PWM
|
||||
ZTIER = (1 << 1);
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#include <board/smfi.h>
|
||||
|
||||
// Main program while running in scratch ROM
|
||||
void main(void) {
|
||||
for (;;) {
|
||||
smfi_event();
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
SCRATCH_SRC+=\
|
||||
$(COMMON_DIR)/version.c \
|
||||
$(BOARD_DIR)/smfi.c
|
||||
|
||||
SCRATCH_BUILD=$(BUILD)/scratch
|
||||
SCRATCH_OBJ=$(patsubst src/%.c,$(SCRATCH_BUILD)/%.rel,$(SCRATCH_SRC))
|
||||
SCRATCH_CC=\
|
||||
sdcc \
|
||||
-mmcs51 \
|
||||
--model-small \
|
||||
--code-loc $(SCRATCH_OFFSET) \
|
||||
--code-size $(SCRATCH_SIZE) \
|
||||
--Werror
|
||||
|
||||
# Convert from binary file to C header
|
||||
$(BUILD)/include/scratch.h: $(SCRATCH_BUILD)/scratch.rom
|
||||
@mkdir -p $(@D)
|
||||
xxd -s $(SCRATCH_OFFSET) --include < $< > $@
|
||||
|
||||
# Convert from Intel Hex file to binary file
|
||||
$(SCRATCH_BUILD)/scratch.rom: $(SCRATCH_BUILD)/scratch.ihx
|
||||
@mkdir -p $(@D)
|
||||
makebin -p < $< > $@
|
||||
|
||||
# Link object files into Intel Hex file
|
||||
$(SCRATCH_BUILD)/scratch.ihx: $(SCRATCH_OBJ)
|
||||
@mkdir -p $(@D)
|
||||
$(SCRATCH_CC) -o $@ $^
|
||||
|
||||
# Compile C files into object files
|
||||
$(SCRATCH_OBJ): $(SCRATCH_BUILD)/%.rel: src/%.c $(SCRATCH_INCLUDE)
|
||||
@mkdir -p $(@D)
|
||||
$(SCRATCH_CC) $(SCRATCH_CFLAGS) -o $@ -c $<
|
@ -1,9 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <board/smfi.h>
|
||||
|
||||
int putchar(int c) {
|
||||
unsigned char byte = (unsigned char)c;
|
||||
smfi_debug(byte);
|
||||
return (int)byte;
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
#include <board/smbus.h>
|
||||
#include <ec/i2c.h>
|
||||
|
||||
void smbus_init(void) {
|
||||
// 9.2 MHz * 4.7 us = 43.24
|
||||
SMB4P7USL = 43;
|
||||
// 9.2 MHz * 4.0 us = 36.8
|
||||
SMB4P0USL = 37;
|
||||
// 9.2 MHz * 300 ns = 2.76
|
||||
SMB300NS = 3;
|
||||
// 9.2 MHz * 250 ns = 2.3
|
||||
SMB250NS = 2;
|
||||
// 1.024 KHz * 25 ms = 25.6
|
||||
SMB25MS = 26;
|
||||
// 9.2 MHz * 45.3 us = 416.76 (0x01A1)
|
||||
SMB45P3USL = 0xA1;
|
||||
SMB45P3USH = 0x01;
|
||||
|
||||
// Set up for i2c usage
|
||||
i2c_reset(&I2C_SMBUS, true);
|
||||
}
|
||||
|
||||
int smbus_read(uint8_t address, uint8_t command, uint16_t * data) {
|
||||
return i2c_get(&I2C_SMBUS, address, command, (uint8_t *)data, 2);
|
||||
}
|
||||
|
||||
int smbus_write(uint8_t address, uint8_t command, uint16_t data) {
|
||||
return i2c_set(&I2C_SMBUS, address, command, (uint8_t *)&data, 2);
|
||||
}
|
@ -1,241 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef __SCRATCH__
|
||||
#include <board/scratch.h>
|
||||
#endif
|
||||
#include <board/smfi.h>
|
||||
#include <common/command.h>
|
||||
#include <common/macro.h>
|
||||
#include <common/version.h>
|
||||
#include <ec/etwd.h>
|
||||
#include <ec/pwm.h>
|
||||
|
||||
// Shared memory host semaphore
|
||||
volatile uint8_t __xdata __at(0x1022) SMHSR;
|
||||
// Host RAM window control
|
||||
volatile uint8_t __xdata __at(0x105A) HRAMWC;
|
||||
// Host RAM window 0 base address
|
||||
volatile uint8_t __xdata __at(0x105B) HRAMW0BA;
|
||||
// Host RAM window 1 base address
|
||||
volatile uint8_t __xdata __at(0x105C) HRAMW1BA;
|
||||
// Host RAM window 0 access allow size
|
||||
volatile uint8_t __xdata __at(0x105D) HRAMW0AAS;
|
||||
// Host RAM window 1 access allow size
|
||||
volatile uint8_t __xdata __at(0x105E) HRAMW1AAS;
|
||||
// Flash control register 3
|
||||
volatile uint8_t __xdata __at(0x1063) FLHCTRL3;
|
||||
|
||||
// EC indirect flash access
|
||||
volatile uint8_t __xdata __at(0x103B) ECINDAR0;
|
||||
volatile uint8_t __xdata __at(0x103C) ECINDAR1;
|
||||
volatile uint8_t __xdata __at(0x103D) ECINDAR2;
|
||||
volatile uint8_t __xdata __at(0x103E) ECINDAR3;
|
||||
volatile uint8_t __xdata __at(0x103F) ECINDDR;
|
||||
|
||||
static volatile uint8_t __xdata __at(0xE00) smfi_cmd[256];
|
||||
static volatile uint8_t __xdata __at(0xF00) smfi_dbg[256];
|
||||
|
||||
static enum Result cmd_spi_scratch(void) __critical {
|
||||
uint8_t flags = smfi_cmd[2];
|
||||
uint8_t len = smfi_cmd[3];
|
||||
|
||||
// Enable chip
|
||||
if (flags & CMD_SPI_FLAG_BACKUP) {
|
||||
ECINDAR3 = 0xFF;
|
||||
} else {
|
||||
ECINDAR3 = 0x7F;
|
||||
}
|
||||
ECINDAR2 = 0xFF;
|
||||
ECINDAR1 = 0xFD;
|
||||
ECINDAR0 = 0x00;
|
||||
|
||||
// Read or write len bytes
|
||||
uint8_t i;
|
||||
for (i = 0; (i < len) && ((i + 4) < ARRAY_SIZE(smfi_cmd)); i++) {
|
||||
if (flags & CMD_SPI_FLAG_READ) {
|
||||
smfi_cmd[i + 4] = ECINDDR;
|
||||
} else {
|
||||
ECINDDR = smfi_cmd[i + 4];
|
||||
}
|
||||
}
|
||||
|
||||
// Set actually read/written count
|
||||
smfi_cmd[3] = i;
|
||||
|
||||
if (flags & CMD_SPI_FLAG_DISABLE) {
|
||||
// Disable chip
|
||||
ECINDAR1 = 0xFE;
|
||||
ECINDDR = 0;
|
||||
}
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
void smfi_init(void) {
|
||||
int i;
|
||||
|
||||
// Clear command region
|
||||
for (i = 1; i < ARRAY_SIZE(smfi_cmd); i++) {
|
||||
smfi_cmd[i] = 0x00;
|
||||
}
|
||||
// Clear host command last
|
||||
smfi_cmd[0] = 0x00;
|
||||
|
||||
// Clear debug region
|
||||
for (i = 1; i < ARRAY_SIZE(smfi_dbg); i++) {
|
||||
smfi_dbg[i] = 0x00;
|
||||
}
|
||||
// Clear tail last
|
||||
smfi_dbg[0] = 0x00;
|
||||
|
||||
|
||||
// H2RAM window 0 address 0xE00 - 0xEFF, read/write
|
||||
HRAMW0BA = 0xE0;
|
||||
HRAMW0AAS = 0x04;
|
||||
|
||||
// H2RAM window 1 address 0xF00 - 0xFFF, read/write
|
||||
HRAMW1BA = 0xF0;
|
||||
HRAMW1AAS = 0x04;
|
||||
|
||||
// Enable H2RAM window 0 and 1 using LPC I/O
|
||||
HRAMWC |= 0x13;
|
||||
|
||||
// Enable backup ROM access
|
||||
FLHCTRL3 |= (1 << 3);
|
||||
}
|
||||
|
||||
static enum Result cmd_print(void) {
|
||||
uint8_t flags = smfi_cmd[2];
|
||||
uint8_t len = smfi_cmd[3];
|
||||
|
||||
uint8_t i;
|
||||
for (i = 0; (i < len) && ((i + 4) < ARRAY_SIZE(smfi_cmd)); i++) {
|
||||
putchar(smfi_cmd[i + 4]);
|
||||
}
|
||||
|
||||
smfi_cmd[3] = i;
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
static enum Result cmd_spi(void) {
|
||||
#ifdef __SCRATCH__
|
||||
return cmd_spi_scratch();
|
||||
#else
|
||||
if (smfi_cmd[2] & CMD_SPI_FLAG_SCRATCH) {
|
||||
scratch_trampoline();
|
||||
}
|
||||
|
||||
// Cannot use follow mode unless running from scratch rom
|
||||
return RES_ERR;
|
||||
#endif
|
||||
}
|
||||
|
||||
static enum Result cmd_reset(void) {
|
||||
// Attempt to trigger watchdog reset
|
||||
ETWCFG |= (1 << 5);
|
||||
EWDKEYR = 0;
|
||||
|
||||
// Failed if it got this far
|
||||
return RES_ERR;
|
||||
}
|
||||
|
||||
#ifndef __SCRATCH__
|
||||
static enum Result cmd_fan_get(void) {
|
||||
// If setting fan 0
|
||||
if (smfi_cmd[2] == 0) {
|
||||
// Get duty of fan 0
|
||||
smfi_cmd[3] = DCR2;
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
// Failed if fan not found
|
||||
return RES_ERR;
|
||||
}
|
||||
|
||||
static enum Result cmd_fan_set(void) {
|
||||
// If setting fan 0
|
||||
if (smfi_cmd[2] == 0) {
|
||||
// Set duty cycle of fan 0
|
||||
DCR2 = smfi_cmd[3];
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
// Failed if fan not found
|
||||
return RES_ERR;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set a watchdog timer of 10 seconds
|
||||
void smfi_watchdog(void) {
|
||||
ET1CNTLLR = 0xFF;
|
||||
EWDCNTLLR = 0xFF;
|
||||
EWDCNTLHR = 0x04;
|
||||
}
|
||||
|
||||
void smfi_event(void) {
|
||||
if (smfi_cmd[0]) {
|
||||
#ifdef __SCRATCH__
|
||||
// If in scratch ROM, restart watchdog timer when command received
|
||||
smfi_watchdog();
|
||||
#endif
|
||||
|
||||
switch (smfi_cmd[0]) {
|
||||
case CMD_PROBE:
|
||||
// Signature
|
||||
smfi_cmd[2] = 0x76;
|
||||
smfi_cmd[3] = 0xEC;
|
||||
// Version
|
||||
smfi_cmd[4] = 0x01;
|
||||
// Always successful
|
||||
smfi_cmd[1] = RES_OK;
|
||||
break;
|
||||
case CMD_BOARD:
|
||||
strncpy(&smfi_cmd[2], board(), ARRAY_SIZE(smfi_cmd) - 2);
|
||||
// Always successful
|
||||
smfi_cmd[1] = RES_OK;
|
||||
break;
|
||||
case CMD_VERSION:
|
||||
strncpy(&smfi_cmd[2], version(), ARRAY_SIZE(smfi_cmd) - 2);
|
||||
// Always successful
|
||||
smfi_cmd[1] = RES_OK;
|
||||
break;
|
||||
case CMD_PRINT:
|
||||
smfi_cmd[1] = cmd_print();
|
||||
break;
|
||||
case CMD_SPI:
|
||||
smfi_cmd[1] = cmd_spi();
|
||||
break;
|
||||
case CMD_RESET:
|
||||
smfi_cmd[1] = cmd_reset();
|
||||
break;
|
||||
#ifndef __SCRATCH__
|
||||
case CMD_FAN_GET:
|
||||
smfi_cmd[1] = cmd_fan_get();
|
||||
break;
|
||||
case CMD_FAN_SET:
|
||||
smfi_cmd[1] = cmd_fan_set();
|
||||
break;
|
||||
#endif // __SCRATCH__
|
||||
default:
|
||||
// Command not found
|
||||
smfi_cmd[1] = RES_ERR;
|
||||
break;
|
||||
}
|
||||
|
||||
// Mark command as finished
|
||||
smfi_cmd[0] = CMD_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void smfi_debug(unsigned char byte) {
|
||||
int tail = (int)smfi_dbg[0];
|
||||
tail++;
|
||||
if (tail >= ARRAY_SIZE(smfi_dbg)) {
|
||||
tail = 1;
|
||||
}
|
||||
smfi_dbg[tail] = byte;
|
||||
smfi_dbg[0] = (uint8_t)tail;
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <board/smfi.h>
|
||||
|
||||
#ifdef SERIAL_DEBUGGER
|
||||
#include <mcs51/8051.h>
|
||||
#endif
|
||||
|
||||
#ifdef I2C_DEBUGGER
|
||||
#include <ec/i2c.h>
|
||||
#endif
|
||||
|
||||
#ifdef PARPORT_DEBUG
|
||||
#include <ec/parallel.h>
|
||||
#endif
|
||||
|
||||
int putchar(int c) {
|
||||
unsigned char byte = (unsigned char)c;
|
||||
smfi_debug(byte);
|
||||
#ifdef SERIAL_DEBUGGER
|
||||
SBUF = byte;
|
||||
#endif
|
||||
#ifdef I2C_DEBUGGER
|
||||
i2c_send(&I2C_SMBUS, I2C_DEBUGGER, &byte, 1);
|
||||
#endif
|
||||
#ifdef PARPORT_DEBUG
|
||||
parport_write(&byte, 1);
|
||||
#endif
|
||||
return (int)byte;
|
||||
}
|
21
src/board/system76/lemp9/board.c
Normal file
21
src/board/system76/lemp9/board.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include <board/board.h>
|
||||
#include <board/gctrl.h>
|
||||
#include <board/gpio.h>
|
||||
#include <board/power.h>
|
||||
|
||||
extern uint8_t main_cycle;
|
||||
|
||||
void board_init(void) {
|
||||
RSTS = 0x44;
|
||||
}
|
||||
|
||||
void board_event(void) {
|
||||
if (main_cycle == 0) {
|
||||
if (power_state == POWER_STATE_S0 || power_state == POWER_STATE_S3 || power_state == POWER_STATE_DS3) {
|
||||
// System is on
|
||||
} else if (gpio_get(&ACIN_N)) {
|
||||
// Power off VDD3 if system should be off
|
||||
gpio_set(&XLP_OUT, 0);
|
||||
}
|
||||
}
|
||||
}
|
@ -19,44 +19,18 @@ CFLAGS+=-DLEVEL=4
|
||||
# Set battery I2C bus
|
||||
CFLAGS+=-DI2C_SMBUS=I2C_4
|
||||
|
||||
# Set type-c port manager I2C bus
|
||||
CFLAGS+=-DI2C_TCPM=I2C_1
|
||||
# Set touchpad PS2 bus
|
||||
CFLAGS+=-DPS2_TOUCHPAD=PS2_3
|
||||
|
||||
# Set smart charger parameters
|
||||
#TODO: Find out why input current must by divided by two
|
||||
CFLAGS+=\
|
||||
-DCHARGER_CHARGE_CURRENT=1536 \
|
||||
-DCHARGER_CHARGE_VOLTAGE=8800 \
|
||||
-DCHARGER_INPUT_CURRENT=1600
|
||||
|
||||
# Enable debug logging over keyboard parallel port
|
||||
#CFLAGS+=-DPARPORT_DEBUG
|
||||
|
||||
# Set scratch ROM parameters
|
||||
SCRATCH_OFFSET=1024
|
||||
SCRATCH_SIZE=1024
|
||||
CFLAGS+=-DSCRATCH_OFFSET=$(SCRATCH_OFFSET) -DSCRATCH_SIZE=$(SCRATCH_SIZE)
|
||||
|
||||
# Copy parameters to use when compiling scratch ROM
|
||||
SCRATCH_INCLUDE=$(INCLUDE)
|
||||
SCRATCH_CFLAGS=$(CFLAGS)
|
||||
|
||||
# Add scratch ROM source
|
||||
SCRATCH_DIR=$(BOARD_DIR)/scratch
|
||||
SCRATCH_SRC=$(wildcard $(SCRATCH_DIR)/*.c)
|
||||
SCRATCH_INCLUDE+=$(wildcard $(SCRATCH_DIR)/include/scratch/*.h) $(SCRATCH_DIR)/scratch.mk
|
||||
SCRATCH_CFLAGS+=-I$(SCRATCH_DIR)/include -D__SCRATCH__
|
||||
include $(SCRATCH_DIR)/scratch.mk
|
||||
|
||||
# Include scratch header in main firmware
|
||||
CFLAGS+=-I$(BUILD)/include
|
||||
INCLUDE+=$(BUILD)/include/scratch.h
|
||||
|
||||
console_internal:
|
||||
cargo build --manifest-path tool/Cargo.toml --release
|
||||
sudo tool/target/release/system76_ectool console
|
||||
|
||||
console_external:
|
||||
sleep 1 && echo C | sudo tee /dev/ttyACM* &
|
||||
sudo tio -b 1000000 -m INLCRNL /dev/ttyACM*
|
||||
|
||||
flash_internal: $(BUILD)/ec.rom
|
||||
cargo build --manifest-path tool/Cargo.toml --release
|
||||
sudo tool/target/release/system76_ectool flash $<
|
||||
|
||||
flash_external: $(BUILD)/ec.rom
|
||||
cargo build --manifest-path ecflash/Cargo.toml --example isp --release
|
||||
sudo ecflash/target/release/examples/isp $<
|
||||
# Add system76 common code
|
||||
include src/board/system76/common/common.mk
|
||||
|
@ -1,10 +0,0 @@
|
||||
#include <board/ecpm.h>
|
||||
|
||||
void ecpm_init(void) {
|
||||
// Clock gate EGPC, CIR, and SWUC
|
||||
CGCTRL2 |= (1 << 6) | (1 << 5) | (1 << 4);
|
||||
// Clock gate UART, SSPI, and DBGR
|
||||
CGCTRL3 |= (1 << 2) | (1 << 1) | (1 << 0);
|
||||
// Clock gate CEC
|
||||
CGCTRL4 |= (1 << 0);
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
#include <board/gctrl.h>
|
||||
|
||||
void gctrl_init(void) {
|
||||
SPCTRL1 = 0x03;
|
||||
BADRSEL = 0;
|
||||
RSTS = 0x44;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#ifndef _BOARD_ACPI_H
|
||||
#define _BOARD_ACPI_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t acpi_read(uint8_t addr);
|
||||
void acpi_write(uint8_t addr, uint8_t data);
|
||||
|
||||
#endif // _BOARD_ACPI_H
|
@ -1,21 +0,0 @@
|
||||
#ifndef _BOARD_BATTERY_H
|
||||
#define _BOARD_BATTERY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint16_t battery_temp;
|
||||
extern uint16_t battery_voltage;
|
||||
extern uint16_t battery_current;
|
||||
extern uint16_t battery_charge;
|
||||
extern uint16_t battery_remaining_capacity;
|
||||
extern uint16_t battery_full_capacity;
|
||||
extern uint16_t battery_status;
|
||||
extern uint16_t battery_design_capacity;
|
||||
extern uint16_t battery_design_voltage;
|
||||
|
||||
int battery_charger_disable(void);
|
||||
int battery_charger_enable(void);
|
||||
void battery_event(void);
|
||||
void battery_debug(void);
|
||||
|
||||
#endif // _BOARD_BATTERY_H
|
@ -1,6 +0,0 @@
|
||||
#ifndef _BOARD_CPU_H
|
||||
#define _BOARD_CPU_H
|
||||
|
||||
#define F_CPU 9200000ULL
|
||||
|
||||
#endif // _BOARD_CPU_H
|
@ -1,8 +0,0 @@
|
||||
#ifndef _BOARD_ECPM_H
|
||||
#define _BOARD_ECPM_H
|
||||
|
||||
#include <ec/ecpm.h>
|
||||
|
||||
void ecpm_init(void);
|
||||
|
||||
#endif // _BOARD_ECPM_H
|
@ -1,8 +0,0 @@
|
||||
#ifndef _BOARD_GCTRL_H
|
||||
#define _BOARD_GCTRL_H
|
||||
|
||||
#include <ec/gctrl.h>
|
||||
|
||||
void gctrl_init(void);
|
||||
|
||||
#endif // _BOARD_GCTRL_H
|
@ -1,15 +0,0 @@
|
||||
#ifndef _BOARD_KBC_H
|
||||
#define _BOARD_KBC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <ec/kbc.h>
|
||||
|
||||
extern bool kbc_first;
|
||||
extern bool kbc_second;
|
||||
|
||||
void kbc_init(void);
|
||||
bool kbc_scancode(struct Kbc * kbc, uint16_t key, bool pressed);
|
||||
void kbc_event(struct Kbc * kbc);
|
||||
|
||||
#endif // _BOARD_KBC_H
|
@ -4,6 +4,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
void kbled_init(void);
|
||||
void kbled_reset(void);
|
||||
uint8_t kbled_get(void);
|
||||
void kbled_set(uint8_t level);
|
||||
|
||||
|
@ -1,18 +0,0 @@
|
||||
#ifndef _BOARD_KBSCAN_H
|
||||
#define _BOARD_KBSCAN_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <ec/kbscan.h>
|
||||
|
||||
extern bool kbscan_enabled;
|
||||
|
||||
// ms between repeating key
|
||||
extern uint16_t kbscan_repeat_period;
|
||||
// ms between pressing key and repeating
|
||||
extern uint16_t kbscan_repeat_delay;
|
||||
|
||||
void kbscan_init(void);
|
||||
void kbscan_event(void);
|
||||
|
||||
#endif // _BOARD_KBSCAN_H
|
@ -1,11 +0,0 @@
|
||||
#ifndef _BOARD_LID_H
|
||||
#define _BOARD_LID_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
extern bool lid_state;
|
||||
extern bool lid_wake;
|
||||
|
||||
void lid_event(void);
|
||||
|
||||
#endif // _BOARD_LID_H
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user