/* * Battery charger driver for Nintendo Switch's TI BQ24193 * * Copyright (c) 2018 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "bq24193.h" #include #include static u8 bq24193_get_reg(u8 reg) { return i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, reg); } int bq24193_get_property(enum BQ24193_reg_prop prop, int *value) { u8 data; switch (prop) { case BQ24193_InputVoltageLimit: // Input voltage limit (mV). data = bq24193_get_reg(BQ24193_InputSource); data = (data & BQ24193_INCONFIG_VINDPM_MASK) >> 3; *value = 0; *value += ((data >> 0) & 1) ? 80 : 0; *value += ((data >> 1) & 1) ? 160 : 0; *value += ((data >> 2) & 1) ? 320 : 0; *value += ((data >> 3) & 1) ? 640 : 0; *value += 3880; break; case BQ24193_InputCurrentLimit: // Input current limit (mA). data = bq24193_get_reg(BQ24193_InputSource); data &= BQ24193_INCONFIG_INLIMIT_MASK; switch (data) { case 0: *value = 100; break; case 1: *value = 150; break; case 2: *value = 500; break; case 3: *value = 900; break; case 4: *value = 1200; break; case 5: *value = 1500; break; case 6: *value = 2000; break; case 7: *value = 3000; break; } break; case BQ24193_SystemMinimumVoltage: // Minimum system voltage limit (mV). data = bq24193_get_reg(BQ24193_PORConfig); *value = (data & BQ24193_PORCONFIG_SYSMIN_MASK) >> 1; *value *= 100; *value += 3000; break; case BQ24193_FastChargeCurrentLimit: // Fast charge current limit (mA). data = bq24193_get_reg(BQ24193_ChrgCurr); data = (data & BQ24193_CHRGCURR_ICHG_MASK) >> 2; *value = 0; *value += ((data >> 0) & 1) ? 64 : 0; *value += ((data >> 1) & 1) ? 128 : 0; *value += ((data >> 2) & 1) ? 256 : 0; *value += ((data >> 3) & 1) ? 512 : 0; *value += ((data >> 4) & 1) ? 1024 : 0; *value += ((data >> 5) & 1) ? 2048 : 0; *value += 512; data = bq24193_get_reg(BQ24193_ChrgCurr); data &= BQ24193_CHRGCURR_20PCT_MASK; if (data) *value = *value * 20 / 100; // Fast charge current limit is 20%. break; case BQ24193_ChargeVoltageLimit: // Charge voltage limit (mV). data = bq24193_get_reg(BQ24193_ChrgVolt); data = (data & BQ24193_CHRGVOLT_VREG) >> 2; *value = 0; *value += ((data >> 0) & 1) ? 16 : 0; *value += ((data >> 1) & 1) ? 32 : 0; *value += ((data >> 2) & 1) ? 64 : 0; *value += ((data >> 3) & 1) ? 128 : 0; *value += ((data >> 4) & 1) ? 256 : 0; *value += ((data >> 5) & 1) ? 512 : 0; *value += 3504; break; case BQ24193_RechargeThreshold: // Recharge voltage threshold less than voltage limit (mV). data = bq24193_get_reg(BQ24193_ChrgVolt); data &= BQ24193_IRTHERMAL_THERM_MASK; if (data) *value = 300; else *value = 100; break; case BQ24193_ThermalRegulation: // Thermal regulation threshold (oC). data = bq24193_get_reg(BQ24193_IRCompThermal); data &= BQ24193_IRTHERMAL_THERM_MASK; switch (data) { case 0: *value = 60; break; case 1: *value = 80; break; case 2: *value = 100; break; case 3: *value = 120; break; } break; case BQ24193_ChargeStatus: // 0: Not charging, 1: Pre-charge, 2: Fast charging, 3: Charge termination done data = bq24193_get_reg(BQ24193_Status); *value = (data & BQ24193_STATUS_CHRG_MASK) >> 4; break; case BQ24193_TempStatus: // 0: Normal, 2: Warm, 3: Cool, 5: Cold, 6: Hot. data = bq24193_get_reg(BQ24193_FaultReg); *value = data & BQ24193_FAULT_THERM_MASK; break; case BQ24193_DevID: // Dev ID. data = bq24193_get_reg(BQ24193_VendorPart); *value = data & BQ24193_VENDORPART_DEV_MASK; break; case BQ24193_ProductNumber: // Product number. data = bq24193_get_reg(BQ24193_VendorPart); *value = (data & BQ24193_VENDORPART_PN_MASK) >> 3; break; default: return -1; } return 0; } void bq24193_enable_charger() { u8 reg = bq24193_get_reg(BQ24193_PORConfig); reg &= ~BQ24193_PORCONFIG_CHGCONFIG_MASK; reg |= BQ24193_PORCONFIG_CHGCONFIG_CHARGER_EN; i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_PORConfig, reg); } void bq24193_fake_battery_removal() { // Disable watchdog to keep BATFET disabled. u8 value = bq24193_get_reg(BQ24193_ChrgTermTimer); value &= ~BQ24193_CHRGTERM_WATCHDOG_MASK; i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_ChrgTermTimer, value); // Force BATFET to disabled state. This disconnects the battery from the system. value = bq24193_get_reg(BQ24193_Misc); value |= BQ24193_MISC_BATFET_DI_MASK; i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_Misc, value); }