diff --git a/src/board/system76/common/battery.c b/src/board/system76/common/battery.c index bd03543..efe4046 100644 --- a/src/board/system76/common/battery.c +++ b/src/board/system76/common/battery.c @@ -4,19 +4,6 @@ #include #include -#define BATTERY_ADDRESS 0x0B -#define CHARGER_ADDRESS 0x09 - -// 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)) - // Default values to disable battery charging thresholds #define BATTERY_START_DEFAULT 0 #define BATTERY_END_DEFAULT 100 @@ -59,75 +46,6 @@ bool battery_set_end_threshold(uint8_t value) { return true; } -// XXX: Assumption: ac_last is initialized high. -static bool charger_enabled = false; - -int battery_charger_disable(void) { - int res = 0; - - if (!charger_enabled) return 0; - - // Set charge option 0 with 175s watchdog - res = smbus_write( - CHARGER_ADDRESS, - 0x12, - SBC_EN_LWPWR | - SBC_WDTMR_ADJ_175S | - SBC_PWM_FREQ_800KHZ | - SBC_IDCHC_GAIN - ); - - // Disable charge current - res = smbus_write(CHARGER_ADDRESS, 0x14, 0); - if (res < 0) return res; - - // Disable charge voltage - res = smbus_write(CHARGER_ADDRESS, 0x15, 0); - if (res < 0) return res; - - // Disable input current - res = smbus_write(CHARGER_ADDRESS, 0x3F, 0); - if (res < 0) return res; - - DEBUG("Charger disabled\n"); - charger_enabled = false; - return 0; -} - -int battery_charger_enable(void) { - int res = 0; - - if (charger_enabled) return 0; - - res = battery_charger_disable(); - if (res < 0) return res; - - // Set charge current in mA - res = smbus_write(CHARGER_ADDRESS, 0x14, CHARGER_CHARGE_CURRENT); - if (res < 0) return res; - - // Set charge voltage in mV - res = smbus_write(CHARGER_ADDRESS, 0x15, CHARGER_CHARGE_VOLTAGE); - if (res < 0) return res; - - // Set input current in mA - res = smbus_write(CHARGER_ADDRESS, 0x3F, CHARGER_INPUT_CURRENT); - if (res < 0) return res; - - // Set charge option 0 with watchdog disabled - res = smbus_write( - CHARGER_ADDRESS, - 0x12, - SBC_EN_LWPWR | - SBC_PWM_FREQ_800KHZ | - SBC_IDCHC_GAIN - ); - - DEBUG("Charger enabled\n"); - charger_enabled = true; - return 0; -} - /** * Configure the charger based on charging threshold values. */ @@ -187,43 +105,10 @@ void battery_event(void) { command(battery_design_voltage, 0x19); #undef command -} -void battery_debug(void) { - uint16_t data = 0; - int res = 0; + DEBUG("BAT %d mV %d mA\n", battery_voltage, battery_current); - #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, BATTERY_ADDRESS, 0x08); - command(Voltage, BATTERY_ADDRESS, 0x09); - command(Current, BATTERY_ADDRESS, 0x0A); - command(Charge, BATTERY_ADDRESS, 0x0D); - command(Status, BATTERY_ADDRESS, 0x16); - - DEBUG("Charger:\n"); - command(ChargeOption0, CHARGER_ADDRESS, 0x12); - command(ChargeOption1, CHARGER_ADDRESS, 0x3B); - command(ChargeOption2, CHARGER_ADDRESS, 0x38); - command(ChargeOption3, CHARGER_ADDRESS, 0x37); - command(ChargeCurrent, CHARGER_ADDRESS, 0x14); - command(ChargeVoltage, CHARGER_ADDRESS, 0x15); - command(DishargeCurrent, CHARGER_ADDRESS, 0x39); - command(InputCurrent, CHARGER_ADDRESS, 0x3F); - command(ProchotOption0, CHARGER_ADDRESS, 0x3C); - command(ProchotOption1, CHARGER_ADDRESS, 0x3D); - command(ProchotStatus, CHARGER_ADDRESS, 0x3A); - - #undef command + battery_charger_event(); } void battery_reset(void) { diff --git a/src/board/system76/common/charger/bq24780s.c b/src/board/system76/common/charger/bq24780s.c new file mode 100644 index 0000000..4cb536d --- /dev/null +++ b/src/board/system76/common/charger/bq24780s.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-3.0-only +// +// TI BQ24780S Smart Charger +// https://www.ti.com/lit/ds/symlink/bq24780s.pdf + +#include +#include +#include + +// 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)) + +// XXX: Assumption: ac_last is initialized high. +static bool charger_enabled = false; + +int battery_charger_disable(void) { + int res = 0; + + if (!charger_enabled) return 0; + + // Set charge option 0 with 175s watchdog + res = smbus_write( + CHARGER_ADDRESS, + 0x12, + SBC_EN_LWPWR | + SBC_WDTMR_ADJ_175S | + SBC_PWM_FREQ_800KHZ | + SBC_IDCHC_GAIN + ); + + // Disable charge current + res = smbus_write(CHARGER_ADDRESS, 0x14, 0); + if (res < 0) return res; + + // Disable charge voltage + res = smbus_write(CHARGER_ADDRESS, 0x15, 0); + if (res < 0) return res; + + // Disable input current + res = smbus_write(CHARGER_ADDRESS, 0x3F, 0); + if (res < 0) return res; + + DEBUG("Charger disabled\n"); + charger_enabled = false; + return 0; +} + +int battery_charger_enable(void) { + int res = 0; + + if (charger_enabled) return 0; + + res = battery_charger_disable(); + if (res < 0) return res; + + // Set charge current in mA + res = smbus_write(CHARGER_ADDRESS, 0x14, CHARGER_CHARGE_CURRENT); + if (res < 0) return res; + + // Set charge voltage in mV + res = smbus_write(CHARGER_ADDRESS, 0x15, CHARGER_CHARGE_VOLTAGE); + if (res < 0) return res; + + // Set input current in mA + res = smbus_write(CHARGER_ADDRESS, 0x3F, CHARGER_INPUT_CURRENT); + if (res < 0) return res; + + // Set charge option 0 with watchdog disabled + res = smbus_write( + CHARGER_ADDRESS, + 0x12, + SBC_EN_LWPWR | + SBC_PWM_FREQ_800KHZ | + SBC_IDCHC_GAIN + ); + + DEBUG("Charger enabled\n"); + charger_enabled = true; + return 0; +} + +void battery_charger_event(void) { + //TODO: watchdog +} + +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, BATTERY_ADDRESS, 0x08); + command(Voltage, BATTERY_ADDRESS, 0x09); + command(Current, BATTERY_ADDRESS, 0x0A); + command(Charge, BATTERY_ADDRESS, 0x0D); + command(Status, BATTERY_ADDRESS, 0x16); + + DEBUG("Charger (bq24780s):\n"); + command(ChargeOption0, CHARGER_ADDRESS, 0x12); + command(ChargeOption1, CHARGER_ADDRESS, 0x3B); + command(ChargeOption2, CHARGER_ADDRESS, 0x38); + command(ChargeOption3, CHARGER_ADDRESS, 0x37); + command(ChargeCurrent, CHARGER_ADDRESS, 0x14); + command(ChargeVoltage, CHARGER_ADDRESS, 0x15); + command(DishargeCurrent, CHARGER_ADDRESS, 0x39); + command(InputCurrent, CHARGER_ADDRESS, 0x3F); + command(ProchotOption0, CHARGER_ADDRESS, 0x3C); + command(ProchotOption1, CHARGER_ADDRESS, 0x3D); + command(ProchotStatus, CHARGER_ADDRESS, 0x3A); + + #undef command +} diff --git a/src/board/system76/common/common.mk b/src/board/system76/common/common.mk index 4b2a840..83fcd43 100644 --- a/src/board/system76/common/common.mk +++ b/src/board/system76/common/common.mk @@ -24,6 +24,10 @@ 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 charger +CHARGER?=bq24780s +SRC+=$(SYSTEM76_COMMON_DIR)/charger/$(CHARGER).c + # Add scratch ROM include $(SYSTEM76_COMMON_DIR)/scratch/scratch.mk diff --git a/src/board/system76/common/include/board/battery.h b/src/board/system76/common/include/board/battery.h index 50edbe8..1021e42 100644 --- a/src/board/system76/common/include/board/battery.h +++ b/src/board/system76/common/include/board/battery.h @@ -6,6 +6,14 @@ #include #include +#ifndef BATTERY_ADDRESS + #define BATTERY_ADDRESS 0x0B +#endif + +#ifndef CHARGER_ADDRESS + #define CHARGER_ADDRESS 0x09 +#endif + #define BATTERY_INITIALIZED (1U << 7) extern uint16_t battery_temp; @@ -24,11 +32,14 @@ bool battery_set_start_threshold(uint8_t value); uint8_t battery_get_end_threshold(void); bool battery_set_end_threshold(uint8_t value); -int battery_charger_disable(void); -int battery_charger_enable(void); int battery_charger_configure(void); void battery_event(void); -void battery_debug(void); void battery_reset(void); +// Defined by charger/*.c +int battery_charger_disable(void); +int battery_charger_enable(void); +void battery_charger_event(void); +void battery_debug(void); + #endif // _BOARD_BATTERY_H