From d928ef8a9a149edacf91d74b627d60227929ad9b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 18 Nov 2019 20:34:02 -0700 Subject: [PATCH] Provide battery and peci info through acpi pmc interface --- src/board/system76/galp3-c/acpi.c | 31 +++++++- src/board/system76/galp3-c/battery.c | 24 ++++++ .../system76/galp3-c/include/board/battery.h | 8 ++ .../system76/galp3-c/include/board/peci.h | 12 +++ src/board/system76/galp3-c/main.c | 79 +------------------ src/board/system76/galp3-c/peci.c | 77 ++++++++++++++++++ src/ec/it8587e/include/ec/peci.h | 17 ++++ 7 files changed, 168 insertions(+), 80 deletions(-) create mode 100644 src/board/system76/galp3-c/include/board/peci.h create mode 100644 src/board/system76/galp3-c/peci.c create mode 100644 src/ec/it8587e/include/ec/peci.h diff --git a/src/board/system76/galp3-c/acpi.c b/src/board/system76/galp3-c/acpi.c index cdde06a..cb9ea63 100644 --- a/src/board/system76/galp3-c/acpi.c +++ b/src/board/system76/galp3-c/acpi.c @@ -1,18 +1,43 @@ #include +#include +#include #include uint8_t acpi_read(uint8_t addr) { uint8_t data = 0; - DEBUG("acpi_read %02X = %02X\n", addr, data); + + #define ACPI_8(K, V) \ + case (K): \ + data = (uint8_t)(V); \ + break + + #define ACPI_16(K, V) \ + ACPI_8(K, V); \ + ACPI_8((K) + 1, (V) >> 8) + + #define ACPI_32(K, V) \ + ACPI_16(K, V); \ + ACPI_16((K) + 2, (V) >> 16) + switch (addr) { - //TODO + ACPI_16(0x00, battery_temp); + ACPI_16(0x02, battery_voltage); + ACPI_16(0x04, battery_current); + ACPI_16(0x06, battery_charge); + + ACPI_16(0x10, peci_offset); + ACPI_16(0x12, peci_temp); + ACPI_8 (0x14, peci_duty); } + + DEBUG("acpi_read %02X = %02X\n", addr, data); return data; } void acpi_write(uint8_t addr, uint8_t data) { DEBUG("acpi_write %02X = %02X\n", addr, data); + switch (addr) { - //TODO + //TODO } } diff --git a/src/board/system76/galp3-c/battery.c b/src/board/system76/galp3-c/battery.c index 6d7e5c7..e0715b7 100644 --- a/src/board/system76/galp3-c/battery.c +++ b/src/board/system76/galp3-c/battery.c @@ -40,6 +40,30 @@ int battery_charger_enable(void) { return 0; } +uint16_t battery_temp = 0; +uint16_t battery_voltage = 0; +uint16_t battery_current = 0; +uint16_t battery_charge = 0; + +void battery_event(void) { + int res = 0; + + #define command(N, V) { \ + res = smbus_read(0x0B, V, &N); \ + if (res < 0) { \ + N = 0; \ + return; \ + } \ + } + + command(battery_temp, 0x08); + command(battery_voltage, 0x09); + command(battery_current, 0x0A); + command(battery_charge, 0x0D); + + #undef command +} + void battery_debug(void) { uint16_t data = 0; int res = 0; diff --git a/src/board/system76/galp3-c/include/board/battery.h b/src/board/system76/galp3-c/include/board/battery.h index c098176..3d83562 100644 --- a/src/board/system76/galp3-c/include/board/battery.h +++ b/src/board/system76/galp3-c/include/board/battery.h @@ -1,8 +1,16 @@ #ifndef _BOARD_BATTERY_H #define _BOARD_BATTERY_H +#include + +extern uint16_t battery_temp; +extern uint16_t battery_voltage; +extern uint16_t battery_current; +extern uint16_t battery_charge; + void battery_charger_disable(void); void battery_charger_enable(void); +void battery_event(void); void battery_debug(void); #endif // _BOARD_BATTERY_H diff --git a/src/board/system76/galp3-c/include/board/peci.h b/src/board/system76/galp3-c/include/board/peci.h new file mode 100644 index 0000000..b7e1db3 --- /dev/null +++ b/src/board/system76/galp3-c/include/board/peci.h @@ -0,0 +1,12 @@ +#ifndef _BOARD_PECI_H +#define _BOARD_PECI_H + +#include + +extern int16_t peci_offset; +extern int16_t peci_temp; +extern uint8_t peci_duty; + +void peci_event(void); + +#endif // _BOARD_PECI_H diff --git a/src/board/system76/galp3-c/main.c b/src/board/system76/galp3-c/main.c index 60bd19d..eaf0bea 100644 --- a/src/board/system76/galp3-c/main.c +++ b/src/board/system76/galp3-c/main.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -54,83 +55,6 @@ void init(void) { GCR2 |= (1 << 4); } -// 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) { - static volatile uint8_t __xdata __at(0x3000) HOSTAR; - static volatile uint8_t __xdata __at(0x3001) HOCTLR; - static volatile uint8_t __xdata __at(0x3002) HOCMDR; - static volatile uint8_t __xdata __at(0x3003) HOTRADDR; - static volatile uint8_t __xdata __at(0x3004) HOWRLR; - static volatile uint8_t __xdata __at(0x3005) HORDLR; - static volatile uint8_t __xdata __at(0x3006) HOWRDR; - static volatile uint8_t __xdata __at(0x3007) HORDDR; - static volatile uint8_t __xdata __at(0x3008) HOCTL2R; - static volatile uint8_t __xdata __at(0x3009) RWFCSV; - - // 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; - int16_t offset = ((int16_t)high << 8) | (int16_t)low; - - // Tjunction = 100C for i7-8565U (and probably the same for all WHL-U) - #define T_JUNCTION 10000 - int16_t temp = T_JUNCTION + offset; - - // Set fan based on temp, adapted from - // https://github.com/pop-os/system76-power/blob/master/src/fan.rs#L218 - uint8_t duty = 0; - if (temp >= 9000) { - // 90C = 100% - duty = 255; - } else if (temp >= 8000) { - // 80C = 50% - duty = 128; - } else if (temp >= 7500) { - // 75C = 45% - duty = 115; - } else if (temp >= 6500) { - // 65C = 40% - duty = 102; - } else if (temp >= 5500) { - // 55C = 35% - duty = 90; - } else if (temp >= 4500) { - // 45C = 30% - duty = 77; - } - - if (duty != DCR2) { - DCR2 = duty; - DEBUG("PECI offset=%d, temp=%d = %d\n", offset, temp, duty); - } - } else { - // Default to 50% if there is an error - DCR2 = 128; - } -} - void ac_adapter() { static struct Gpio __code ACIN_N = GPIO(B, 6); static struct Gpio __code LED_ACIN = GPIO(C, 7); @@ -451,6 +375,7 @@ void main(void) { for(;;) { peci_event(); ac_adapter(); + battery_event(); power_button(); kbscan_event(); touchpad_event(&PS2_3); diff --git a/src/board/system76/galp3-c/peci.c b/src/board/system76/galp3-c/peci.c new file mode 100644 index 0000000..6d82935 --- /dev/null +++ b/src/board/system76/galp3-c/peci.c @@ -0,0 +1,77 @@ +#include +#include +#include + +int16_t peci_offset = 0; +int16_t peci_temp = 0; +uint8_t peci_duty = 0; + +// Tjunction = 100C for i7-8565U (and probably the same for all WHL-U) +#define T_JUNCTION 10000 + +// 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) { + // 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 = T_JUNCTION + peci_offset; + + // Set fan based on temp, adapted from + // https://github.com/pop-os/system76-power/blob/master/src/fan.rs#L218 + if (peci_temp >= 9000) { + // 90C = 100% + peci_duty = 255; + } else if (peci_temp >= 8000) { + // 80C = 50% + peci_duty = 128; + } else if (peci_temp >= 7500) { + // 75C = 45% + peci_duty = 115; + } else if (peci_temp >= 6500) { + // 65C = 40% + peci_duty = 102; + } else if (peci_temp >= 5500) { + // 55C = 35% + peci_duty = 90; + } else if (peci_temp >= 4500) { + // 45C = 30% + peci_duty = 77; + } else { + // < 45C = 0% + peci_duty = 0; + } + } else { + // Default to 50% if there is an error + peci_offset = 0; + peci_temp = 0; + peci_duty = 128; + } + + if (peci_duty != DCR2) { + DCR2 = peci_duty; + DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, peci_duty); + } +} diff --git a/src/ec/it8587e/include/ec/peci.h b/src/ec/it8587e/include/ec/peci.h new file mode 100644 index 0000000..65e3a4a --- /dev/null +++ b/src/ec/it8587e/include/ec/peci.h @@ -0,0 +1,17 @@ +#ifndef _EC_PECI_H +#define _EC_PECI_H + +#include + +static volatile uint8_t __xdata __at(0x3000) HOSTAR; +static volatile uint8_t __xdata __at(0x3001) HOCTLR; +static volatile uint8_t __xdata __at(0x3002) HOCMDR; +static volatile uint8_t __xdata __at(0x3003) HOTRADDR; +static volatile uint8_t __xdata __at(0x3004) HOWRLR; +static volatile uint8_t __xdata __at(0x3005) HORDLR; +static volatile uint8_t __xdata __at(0x3006) HOWRDR; +static volatile uint8_t __xdata __at(0x3007) HORDDR; +static volatile uint8_t __xdata __at(0x3008) HOCTL2R; +static volatile uint8_t __xdata __at(0x3009) RWFCSV; + +#endif // _EC_PECI_H