Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
CTCaer
GitHub Repository: CTCaer/hekate
Path: blob/master/bdk/power/bq24193.c
3694 views
1
/*
2
* Battery charger driver for Nintendo Switch's TI BQ24193
3
*
4
* Copyright (c) 2018-2025 CTCaer
5
*
6
* This program is free software; you can redistribute it and/or modify it
7
* under the terms and conditions of the GNU General Public License,
8
* version 2, as published by the Free Software Foundation.
9
*
10
* This program is distributed in the hope it will be useful, but WITHOUT
11
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13
* more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
#include "bq24193.h"
20
#include <soc/i2c.h>
21
#include <utils/util.h>
22
23
static u8 bq24193_get_reg(u8 reg)
24
{
25
return i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, reg);
26
}
27
28
int bq24193_get_version(u32 *value)
29
{
30
u16 data = bq24193_get_reg(BQ24193_VendorPart);
31
if (value)
32
*value = data;
33
34
if (data == 0x2F)
35
return 0;
36
else
37
return 1;
38
}
39
40
int bq24193_get_property(enum BQ24193_reg_prop prop, int *value)
41
{
42
u8 data;
43
44
switch (prop)
45
{
46
case BQ24193_InputVoltageLimit: // Input voltage limit (mV).
47
data = bq24193_get_reg(BQ24193_InputSource);
48
data = (data & BQ24193_INCONFIG_VINDPM_MASK) >> 3;
49
*value = 0;
50
*value += ((data >> 0) & 1) ? 80 : 0;
51
*value += ((data >> 1) & 1) ? 160 : 0;
52
*value += ((data >> 2) & 1) ? 320 : 0;
53
*value += ((data >> 3) & 1) ? 640 : 0;
54
*value += 3880;
55
break;
56
case BQ24193_InputCurrentLimit: // Input current limit (mA).
57
data = bq24193_get_reg(BQ24193_InputSource);
58
data &= BQ24193_INCONFIG_INLIMIT_MASK;
59
switch (data)
60
{
61
case 0:
62
*value = 100;
63
break;
64
case 1:
65
*value = 150;
66
break;
67
case 2:
68
*value = 500;
69
break;
70
case 3:
71
*value = 900;
72
break;
73
case 4:
74
*value = 1200;
75
break;
76
case 5:
77
*value = 1500;
78
break;
79
case 6:
80
*value = 2000;
81
break;
82
case 7:
83
*value = 3000;
84
break;
85
}
86
break;
87
case BQ24193_SystemMinimumVoltage: // Minimum system voltage limit (mV).
88
data = bq24193_get_reg(BQ24193_PORConfig);
89
*value = (data & BQ24193_PORCONFIG_SYSMIN_MASK) >> 1;
90
*value *= 100;
91
*value += 3000;
92
break;
93
case BQ24193_FastChargeCurrentLimit: // Fast charge current limit (mA).
94
data = bq24193_get_reg(BQ24193_ChrgCurr);
95
data = (data & BQ24193_CHRGCURR_ICHG_MASK) >> 2;
96
*value = 0;
97
*value += ((data >> 0) & 1) ? 64 : 0;
98
*value += ((data >> 1) & 1) ? 128 : 0;
99
*value += ((data >> 2) & 1) ? 256 : 0;
100
*value += ((data >> 3) & 1) ? 512 : 0;
101
*value += ((data >> 4) & 1) ? 1024 : 0;
102
*value += ((data >> 5) & 1) ? 2048 : 0;
103
*value += 512;
104
data = bq24193_get_reg(BQ24193_ChrgCurr);
105
data &= BQ24193_CHRGCURR_20PCT_MASK;
106
if (data)
107
*value = *value * 20 / 100; // Fast charge current limit is 20%.
108
break;
109
case BQ24193_ChargeVoltageLimit: // Charge voltage limit (mV).
110
data = bq24193_get_reg(BQ24193_ChrgVolt);
111
data = (data & BQ24193_CHRGVOLT_VREG) >> 2;
112
*value = 0;
113
*value += ((data >> 0) & 1) ? 16 : 0;
114
*value += ((data >> 1) & 1) ? 32 : 0;
115
*value += ((data >> 2) & 1) ? 64 : 0;
116
*value += ((data >> 3) & 1) ? 128 : 0;
117
*value += ((data >> 4) & 1) ? 256 : 0;
118
*value += ((data >> 5) & 1) ? 512 : 0;
119
*value += 3504;
120
break;
121
case BQ24193_RechargeThreshold: // Recharge voltage threshold less than voltage limit (mV).
122
data = bq24193_get_reg(BQ24193_ChrgVolt);
123
data &= BQ24193_IRTHERMAL_THERM_MASK;
124
if (data)
125
*value = 300;
126
else
127
*value = 100;
128
break;
129
case BQ24193_ThermalRegulation: // Thermal regulation threshold (oC).
130
data = bq24193_get_reg(BQ24193_IRCompThermal);
131
data &= BQ24193_IRTHERMAL_THERM_MASK;
132
switch (data)
133
{
134
case 0:
135
*value = 60;
136
break;
137
case 1:
138
*value = 80;
139
break;
140
case 2:
141
*value = 100;
142
break;
143
case 3:
144
*value = 120;
145
break;
146
}
147
break;
148
case BQ24193_ChargeStatus: // 0: Not charging, 1: Pre-charge, 2: Fast charging, 3: Charge termination done
149
data = bq24193_get_reg(BQ24193_Status);
150
*value = (data & BQ24193_STATUS_CHRG_MASK) >> 4;
151
break;
152
case BQ24193_TempStatus: // 0: Normal, 2: Warm, 3: Cool, 5: Cold, 6: Hot.
153
data = bq24193_get_reg(BQ24193_FaultReg);
154
*value = data & BQ24193_FAULT_THERM_MASK;
155
break;
156
case BQ24193_DevID: // Dev ID.
157
data = bq24193_get_reg(BQ24193_VendorPart);
158
*value = data & BQ24193_VENDORPART_DEV_MASK;
159
break;
160
case BQ24193_ProductNumber: // Product number.
161
data = bq24193_get_reg(BQ24193_VendorPart);
162
*value = (data & BQ24193_VENDORPART_PN_MASK) >> 3;
163
break;
164
default:
165
return 1;
166
}
167
return 0;
168
}
169
170
void bq24193_enable_charger()
171
{
172
u8 reg = bq24193_get_reg(BQ24193_PORConfig);
173
174
reg &= ~BQ24193_PORCONFIG_CHGCONFIG_MASK;
175
reg |= BQ24193_PORCONFIG_CHGCONFIG_CHARGER_EN;
176
177
i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_PORConfig, reg);
178
}
179
180
void bq24193_fake_battery_removal()
181
{
182
// Disable watchdog to keep BATFET disabled.
183
u8 value = bq24193_get_reg(BQ24193_ChrgTermTimer);
184
value &= ~BQ24193_CHRGTERM_WATCHDOG_MASK;
185
i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_ChrgTermTimer, value);
186
187
// Force BATFET to disabled state. This disconnects the battery from the system.
188
value = bq24193_get_reg(BQ24193_Misc);
189
value |= BQ24193_MISC_BATFET_DI_MASK;
190
i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_Misc, value);
191
}
192
193