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),)
|
ifeq ($(BOARD),)
|
||||||
all:
|
all:
|
||||||
@echo "Please set BOARD to one of the following:"
|
@echo "Please set BOARD to one of the following:"
|
||||||
@cd src/board && for board in */*; do \
|
@cd src/board && for board in */*/board.mk; do \
|
||||||
echo " $$board"; \
|
echo " $$(dirname "$$board")"; \
|
||||||
done
|
done
|
||||||
@exit 1
|
@exit 1
|
||||||
else
|
else
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include <board/smbus.h>
|
#include <board/smbus.h>
|
||||||
#include <common/debug.h>
|
#include <common/debug.h>
|
||||||
|
|
||||||
|
#define BATTERY_ADDRESS 0x0B
|
||||||
|
#define CHARGER_ADDRESS 0x09
|
||||||
|
|
||||||
// ChargeOption0 flags
|
// ChargeOption0 flags
|
||||||
// Low Power Mode Enable
|
// Low Power Mode Enable
|
||||||
@ -17,7 +19,7 @@ int battery_charger_disable(void) {
|
|||||||
|
|
||||||
// Set charge option 0 with 175s watchdog
|
// Set charge option 0 with 175s watchdog
|
||||||
res = smbus_write(
|
res = smbus_write(
|
||||||
0x09,
|
CHARGER_ADDRESS,
|
||||||
0x12,
|
0x12,
|
||||||
SBC_EN_LWPWR |
|
SBC_EN_LWPWR |
|
||||||
SBC_WDTMR_ADJ_175S |
|
SBC_WDTMR_ADJ_175S |
|
||||||
@ -26,15 +28,15 @@ int battery_charger_disable(void) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Disable charge current
|
// Disable charge current
|
||||||
res = smbus_write(0x09, 0x14, 0);
|
res = smbus_write(CHARGER_ADDRESS, 0x14, 0);
|
||||||
if (res < 0) return res;
|
if (res < 0) return res;
|
||||||
|
|
||||||
// Disable charge voltage
|
// Disable charge voltage
|
||||||
res = smbus_write(0x09, 0x15, 0);
|
res = smbus_write(CHARGER_ADDRESS, 0x15, 0);
|
||||||
if (res < 0) return res;
|
if (res < 0) return res;
|
||||||
|
|
||||||
// Disable input current
|
// Disable input current
|
||||||
res = smbus_write(0x09, 0x3F, 0);
|
res = smbus_write(CHARGER_ADDRESS, 0x3F, 0);
|
||||||
if (res < 0) return res;
|
if (res < 0) return res;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -46,22 +48,21 @@ int battery_charger_enable(void) {
|
|||||||
res = battery_charger_disable();
|
res = battery_charger_disable();
|
||||||
if (res < 0) return res;
|
if (res < 0) return res;
|
||||||
|
|
||||||
// Set charge current to ~1.54 A
|
// Set charge current in mA
|
||||||
res = smbus_write(0x09, 0x14, 0x061C);
|
res = smbus_write(CHARGER_ADDRESS, 0x14, CHARGER_CHARGE_CURRENT);
|
||||||
if (res < 0) return res;
|
if (res < 0) return res;
|
||||||
|
|
||||||
// Set charge voltage to 8.8 V
|
// Set charge voltage in mV
|
||||||
res = smbus_write(0x09, 0x15, 0x2260);
|
res = smbus_write(CHARGER_ADDRESS, 0x15, CHARGER_CHARGE_VOLTAGE);
|
||||||
if (res < 0) return res;
|
if (res < 0) return res;
|
||||||
|
|
||||||
// Set input current to ~3.2 A
|
// Set input current in mA
|
||||||
// TODO: figure out why input current must be divided by 2
|
res = smbus_write(CHARGER_ADDRESS, 0x3F, CHARGER_INPUT_CURRENT);
|
||||||
res = smbus_write(0x09, 0x3F, 0x0C80 / 2);
|
|
||||||
if (res < 0) return res;
|
if (res < 0) return res;
|
||||||
|
|
||||||
// Set charge option 0 with watchdog disabled
|
// Set charge option 0 with watchdog disabled
|
||||||
res = smbus_write(
|
res = smbus_write(
|
||||||
0x09,
|
CHARGER_ADDRESS,
|
||||||
0x12,
|
0x12,
|
||||||
SBC_EN_LWPWR |
|
SBC_EN_LWPWR |
|
||||||
SBC_PWM_FREQ_800KHZ |
|
SBC_PWM_FREQ_800KHZ |
|
||||||
@ -85,7 +86,7 @@ void battery_event(void) {
|
|||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
#define command(N, V) { \
|
#define command(N, V) { \
|
||||||
res = smbus_read(0x0B, V, &N); \
|
res = smbus_read(BATTERY_ADDRESS, V, &N); \
|
||||||
if (res < 0) { \
|
if (res < 0) { \
|
||||||
N = 0; \
|
N = 0; \
|
||||||
} \
|
} \
|
||||||
@ -119,24 +120,24 @@ void battery_debug(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEBUG("Battery:\n");
|
DEBUG("Battery:\n");
|
||||||
command(Temperature, 0x0B, 0x08);
|
command(Temperature, BATTERY_ADDRESS, 0x08);
|
||||||
command(Voltage, 0x0B, 0x09);
|
command(Voltage, BATTERY_ADDRESS, 0x09);
|
||||||
command(Current, 0x0B, 0x0A);
|
command(Current, BATTERY_ADDRESS, 0x0A);
|
||||||
command(Charge, 0x0B, 0x0D);
|
command(Charge, BATTERY_ADDRESS, 0x0D);
|
||||||
command(Status, 0x0B, 0x16);
|
command(Status, BATTERY_ADDRESS, 0x16);
|
||||||
|
|
||||||
DEBUG("Charger:\n");
|
DEBUG("Charger:\n");
|
||||||
command(ChargeOption0, 0x09, 0x12);
|
command(ChargeOption0, CHARGER_ADDRESS, 0x12);
|
||||||
command(ChargeOption1, 0x09, 0x3B);
|
command(ChargeOption1, CHARGER_ADDRESS, 0x3B);
|
||||||
command(ChargeOption2, 0x09, 0x38);
|
command(ChargeOption2, CHARGER_ADDRESS, 0x38);
|
||||||
command(ChargeOption3, 0x09, 0x37);
|
command(ChargeOption3, CHARGER_ADDRESS, 0x37);
|
||||||
command(ChargeCurrent, 0x09, 0x14);
|
command(ChargeCurrent, CHARGER_ADDRESS, 0x14);
|
||||||
command(ChargeVoltage, 0x09, 0x15);
|
command(ChargeVoltage, CHARGER_ADDRESS, 0x15);
|
||||||
command(DishargeCurrent, 0x09, 0x39);
|
command(DishargeCurrent, CHARGER_ADDRESS, 0x39);
|
||||||
command(InputCurrent, 0x09, 0x3F);
|
command(InputCurrent, CHARGER_ADDRESS, 0x3F);
|
||||||
command(ProchotOption0, 0x09, 0x3C);
|
command(ProchotOption0, CHARGER_ADDRESS, 0x3C);
|
||||||
command(ProchotOption1, 0x09, 0x3D);
|
command(ProchotOption1, CHARGER_ADDRESS, 0x3D);
|
||||||
command(ProchotStatus, 0x09, 0x3A);
|
command(ProchotStatus, CHARGER_ADDRESS, 0x3A);
|
||||||
|
|
||||||
#undef command
|
#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) {
|
void gctrl_init(void) {
|
||||||
SPCTRL1 = 0x03;
|
SPCTRL1 = 0x03;
|
||||||
BADRSEL = 0;
|
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) {
|
if (i < 8) {
|
||||||
KSOLGOEN = 1 << i;
|
KSOLGOEN = 1 << i;
|
||||||
KSOHGOEN = 0;
|
KSOHGOEN = 0;
|
||||||
|
#if KM_OUT >= 17
|
||||||
|
GPCRC3 = GPIO_IN;
|
||||||
|
#endif
|
||||||
|
#if KM_OUT >= 18
|
||||||
|
GPCRC5 = GPIO_IN;
|
||||||
|
#endif
|
||||||
} else if (i < 16) {
|
} else if (i < 16) {
|
||||||
KSOLGOEN = 0;
|
KSOLGOEN = 0;
|
||||||
KSOHGOEN = 1 << (i - 8);
|
KSOHGOEN = 1 << (i - 8);
|
||||||
|
#if KM_OUT >= 17
|
||||||
|
GPCRC3 = GPIO_IN;
|
||||||
|
#endif
|
||||||
|
#if KM_OUT >= 18
|
||||||
|
GPCRC5 = GPIO_IN;
|
||||||
|
#endif
|
||||||
} else if (i == 16) {
|
} else if (i == 16) {
|
||||||
KSOLGOEN = 0;
|
KSOLGOEN = 0;
|
||||||
KSOHGOEN = 0;
|
KSOHGOEN = 0;
|
||||||
|
#if KM_OUT >= 17
|
||||||
|
GPCRC3 = GPIO_OUT;
|
||||||
|
#endif
|
||||||
|
#if KM_OUT >= 18
|
||||||
|
GPCRC5 = GPIO_IN;
|
||||||
|
#endif
|
||||||
} else if (i == 17) {
|
} else if (i == 17) {
|
||||||
KSOLGOEN = 0;
|
KSOLGOEN = 0;
|
||||||
KSOHGOEN = 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
|
// TODO: figure out optimal delay
|
||||||
delay_ticks(10);
|
delay_ticks(10);
|
||||||
@ -341,6 +371,12 @@ void kbscan_event(void) {
|
|||||||
// Reset all lines to inputs
|
// Reset all lines to inputs
|
||||||
KSOLGOEN = 0;
|
KSOLGOEN = 0;
|
||||||
KSOHGOEN = 0;
|
KSOHGOEN = 0;
|
||||||
|
#if KM_OUT >= 17
|
||||||
|
GPCRC3 = GPIO_IN;
|
||||||
|
#endif
|
||||||
|
#if KM_OUT >= 18
|
||||||
|
GPCRC5 = GPIO_IN;
|
||||||
|
#endif
|
||||||
|
|
||||||
// TODO: figure out optimal delay
|
// TODO: figure out optimal delay
|
||||||
delay_ticks(10);
|
delay_ticks(10);
|
@ -5,6 +5,7 @@
|
|||||||
#include <arch/delay.h>
|
#include <arch/delay.h>
|
||||||
#include <arch/time.h>
|
#include <arch/time.h>
|
||||||
#include <board/battery.h>
|
#include <board/battery.h>
|
||||||
|
#include <board/board.h>
|
||||||
#include <board/ecpm.h>
|
#include <board/ecpm.h>
|
||||||
#include <board/gpio.h>
|
#include <board/gpio.h>
|
||||||
#include <board/gctrl.h>
|
#include <board/gctrl.h>
|
||||||
@ -19,6 +20,7 @@
|
|||||||
#include <board/pwm.h>
|
#include <board/pwm.h>
|
||||||
#include <board/smbus.h>
|
#include <board/smbus.h>
|
||||||
#include <board/smfi.h>
|
#include <board/smfi.h>
|
||||||
|
#include <board/touchpad.h>
|
||||||
#include <common/debug.h>
|
#include <common/debug.h>
|
||||||
#include <common/macro.h>
|
#include <common/macro.h>
|
||||||
#include <common/version.h>
|
#include <common/version.h>
|
||||||
@ -40,6 +42,7 @@ uint8_t main_cycle = 0;
|
|||||||
void init(void) {
|
void init(void) {
|
||||||
// Must happen first
|
// Must happen first
|
||||||
arch_init();
|
arch_init();
|
||||||
|
board_init();
|
||||||
gctrl_init();
|
gctrl_init();
|
||||||
gpio_init();
|
gpio_init();
|
||||||
|
|
||||||
@ -61,22 +64,6 @@ void init(void) {
|
|||||||
//TODO: INTC
|
//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) {
|
void main(void) {
|
||||||
init();
|
init();
|
||||||
|
|
||||||
@ -120,7 +107,7 @@ void main(void) {
|
|||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
// Passes through touchpad packets
|
// Passes through touchpad packets
|
||||||
touchpad_event(&PS2_3);
|
touchpad_event();
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
// Checks for keyboard/mouse packets from host
|
// Checks for keyboard/mouse packets from host
|
||||||
@ -146,6 +133,9 @@ void main(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Board-specific events
|
||||||
|
board_event();
|
||||||
|
|
||||||
// Handles ACPI communication
|
// Handles ACPI communication
|
||||||
pmc_event(&PMC_1);
|
pmc_event(&PMC_1);
|
||||||
// AP/EC communication over SMFI
|
// AP/EC communication over SMFI
|
@ -252,6 +252,14 @@ void power_off_s5(void) {
|
|||||||
update_power_state();
|
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) {
|
void power_event(void) {
|
||||||
// Always switch to ds5 if EC is running
|
// Always switch to ds5 if EC is running
|
||||||
if (power_state == POWER_STATE_DEFAULT) {
|
if (power_state == POWER_STATE_DEFAULT) {
|
||||||
@ -362,12 +370,7 @@ void power_event(void) {
|
|||||||
#endif
|
#endif
|
||||||
if(rst_new && !rst_last) {
|
if(rst_new && !rst_last) {
|
||||||
DEBUG("%02X: PLT_RST# de-asserted\n", main_cycle);
|
DEBUG("%02X: PLT_RST# de-asserted\n", main_cycle);
|
||||||
|
power_cpu_reset();
|
||||||
// LPC was just reset, enable PNP devices
|
|
||||||
pnp_enable();
|
|
||||||
//TODO: reset KBC and touchpad states
|
|
||||||
|
|
||||||
kbled_reset();
|
|
||||||
}
|
}
|
||||||
rst_last = rst_new;
|
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+=\
|
SCRATCH_SRC+=\
|
||||||
$(COMMON_DIR)/version.c \
|
$(COMMON_DIR)/version.c \
|
||||||
$(BOARD_DIR)/smfi.c
|
$(SYSTEM76_COMMON_DIR)/smfi.c
|
||||||
|
|
||||||
SCRATCH_BUILD=$(BUILD)/scratch
|
SCRATCH_BUILD=$(BUILD)/scratch
|
||||||
SCRATCH_OBJ=$(patsubst src/%.c,$(SCRATCH_BUILD)/%.rel,$(SCRATCH_SRC))
|
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)
|
$(SCRATCH_OBJ): $(SCRATCH_BUILD)/%.rel: src/%.c $(SCRATCH_INCLUDE)
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
$(SCRATCH_CC) $(SCRATCH_CFLAGS) -o $@ -c $<
|
$(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
|
# Set battery I2C bus
|
||||||
CFLAGS+=-DI2C_SMBUS=I2C_0
|
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
|
# Set keyboard LED I2C bus
|
||||||
CFLAGS+=-DI2C_KBLED=I2C_1
|
CFLAGS+=-DI2C_KBLED=I2C_1
|
||||||
|
|
||||||
# Enable debug logging over keyboard parallel port
|
# Enable debug logging over keyboard parallel port
|
||||||
#CFLAGS+=-DPARPORT_DEBUG
|
#CFLAGS+=-DPARPORT_DEBUG
|
||||||
|
|
||||||
# Set scratch ROM parameters
|
# Add system76 common code
|
||||||
SCRATCH_OFFSET=1024
|
include src/board/system76/common/common.mk
|
||||||
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 $<
|
|
||||||
|
@ -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
|
# Set battery I2C bus
|
||||||
CFLAGS+=-DI2C_SMBUS=I2C_0
|
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
|
# Enable debug logging over keyboard parallel port
|
||||||
#CFLAGS+=-DPARPORT_DEBUG
|
#CFLAGS+=-DPARPORT_DEBUG
|
||||||
|
|
||||||
# Set scratch ROM parameters
|
# Add system76 common code
|
||||||
SCRATCH_OFFSET=1024
|
include src/board/system76/common/common.mk
|
||||||
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 $<
|
|
||||||
|
@ -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>
|
#include <stdint.h>
|
||||||
|
|
||||||
void kbled_init(void);
|
void kbled_init(void);
|
||||||
|
void kbled_reset(void);
|
||||||
uint8_t kbled_get(void);
|
uint8_t kbled_get(void);
|
||||||
void kbled_set(uint8_t level);
|
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) {
|
void kbled_init(void) {
|
||||||
// Enable DAC used for KBLIGHT_ADJ
|
// Enable DAC used for KBLIGHT_ADJ
|
||||||
DACPDREG &= ~(1 << KBLED_DAC);
|
DACPDREG &= ~(1 << KBLED_DAC);
|
||||||
// Set DAC to 0V
|
kbled_reset();
|
||||||
KBLED_DACDAT = 0;
|
}
|
||||||
|
|
||||||
|
void kbled_reset(void) {
|
||||||
|
kbled_set(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t kbled_get(void) {
|
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
|
# Set battery I2C bus
|
||||||
CFLAGS+=-DI2C_SMBUS=I2C_4
|
CFLAGS+=-DI2C_SMBUS=I2C_4
|
||||||
|
|
||||||
# Set type-c port manager I2C bus
|
# Set touchpad PS2 bus
|
||||||
CFLAGS+=-DI2C_TCPM=I2C_1
|
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
|
# Enable debug logging over keyboard parallel port
|
||||||
#CFLAGS+=-DPARPORT_DEBUG
|
#CFLAGS+=-DPARPORT_DEBUG
|
||||||
|
|
||||||
# Set scratch ROM parameters
|
# Add system76 common code
|
||||||
SCRATCH_OFFSET=1024
|
include src/board/system76/common/common.mk
|
||||||
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 $<
|
|
||||||
|
@ -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>
|
#include <stdint.h>
|
||||||
|
|
||||||
void kbled_init(void);
|
void kbled_init(void);
|
||||||
|
void kbled_reset(void);
|
||||||
uint8_t kbled_get(void);
|
uint8_t kbled_get(void);
|
||||||
void kbled_set(uint8_t level);
|
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