1 /*
2 * Copyright 2017 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <stdint.h>
9 #include <stdbool.h>
10 #include <assert.h>
11
12 #include "fsl_pf1550_charger.h"
13
14 /*******************************************************************************
15 * Code
16 ******************************************************************************/
17
PF1550_SetChargerOperation(pf1550_handle_t * handle,pf1550_charger_operation_t operation)18 void PF1550_SetChargerOperation(pf1550_handle_t *handle, pf1550_charger_operation_t operation)
19 {
20 assert(handle);
21
22 /* Set Charger Operation Mode. */
23 (void)PF1550_ModifyReg(handle, PF1550_CHG_OPER, 0x03U, (uint8_t)operation);
24 }
25
PF1550_SetChargerAttibute(pf1550_handle_t * handle,const pf1550_charger_attribute_t * attribute)26 void PF1550_SetChargerAttibute(pf1550_handle_t *handle, const pf1550_charger_attribute_t *attribute)
27 {
28 uint32_t temp;
29
30 assert(handle);
31 assert(attribute);
32
33 /* Set Fast Charge Current. */
34 temp = (attribute->fastChargeCurrent_mA > 1000U) ? 1000U : attribute->fastChargeCurrent_mA;
35 temp = (attribute->fastChargeCurrent_mA < 100U) ? 100U : temp;
36 temp = (temp - 100U) / 50U;
37 (void)PF1550_ModifyReg(handle, PF1550_CHG_CURR_CNFG, 0x1FU, (uint8_t)temp);
38
39 /* Set Fast Charge Voltage. */
40 temp = (attribute->fastChargeVoltage_uV > 4440000U) ? 4440000U : attribute->fastChargeVoltage_uV;
41 temp = (attribute->fastChargeVoltage_uV < 3500000U) ? 3500000U : temp;
42 temp = (temp - 3340000U) / 20000U;
43 (void)PF1550_ModifyReg(handle, PF1550_BATT_REG, 0x3FU, (uint8_t)temp);
44
45 /* Set Precharge Timer timeout value. */
46 (void)PF1550_ModifyReg(handle, PF1550_CHG_TMR, 0x80U, ((attribute->preChargeTime_min <= 30U) ? 0x0U : 0x80U));
47
48 /* Set Fast-charge Timer timeout value. */
49 temp = (attribute->fastChargeTime_hr > 14U) ? 14U : attribute->fastChargeTime_hr;
50 temp = temp >> 1U;
51 (void)PF1550_ModifyReg(handle, PF1550_CHG_TMR, 0x03U, (uint8_t)temp);
52
53 /* Set End-of-charge timer timeout value. */
54 temp = (attribute->endOfChargeTime_min > 70U) ? 70U : attribute->endOfChargeTime_min;
55 temp = (temp / 10U) << 3U;
56 (void)PF1550_ModifyReg(handle, PF1550_CHG_TMR, 0x38U, (uint8_t)temp);
57
58 /* Set End-of-charge current. */
59 if (attribute->endOfChargeCurrentThreshold_mA >= 50U)
60 {
61 temp = 4U << 4U;
62 }
63 else if (attribute->endOfChargeCurrentThreshold_mA >= 30U)
64 {
65 temp = 3U << 4U;
66 }
67 else if (attribute->endOfChargeCurrentThreshold_mA >= 20U)
68 {
69 temp = 2U << 4U;
70 }
71 else if (attribute->endOfChargeCurrentThreshold_mA >= 10U)
72 {
73 temp = 1U << 4U;
74 }
75 else
76 {
77 temp = 0U;
78 }
79 (void)PF1550_ModifyReg(handle, PF1550_CHG_EOC_CNFG, 0x70U, (uint8_t)temp);
80
81 /* Set Charger restart threshold. */
82 if (attribute->restartVoltageThreshold_uV == 0U)
83 {
84 temp = 3U;
85 }
86 else
87 {
88 temp = (attribute->restartVoltageThreshold_uV > 200000U) ? 200000U : attribute->restartVoltageThreshold_uV;
89 temp = (attribute->restartVoltageThreshold_uV < 100000U) ? 100000U : temp;
90 temp = (temp - 100000U) / 50000U;
91 }
92 (void)PF1550_ModifyReg(handle, PF1550_CHG_EOC_CNFG, 0x03U, (uint8_t)temp);
93
94 /* Set Minimum system regulation voltage */
95 temp = (attribute->miniSystemVoltage_uV > 4300000U) ? 4300000U : attribute->miniSystemVoltage_uV;
96 if (temp <= 3500000U)
97 {
98 temp = 0x0U;
99 }
100 else if (temp <= 3700000U)
101 {
102 temp = 0x1U << 6U;
103 }
104 else
105 {
106 temp = 0x2U << 6U;
107 }
108 (void)PF1550_ModifyReg(handle, PF1550_BATT_REG, 0xC0U, (uint8_t)temp);
109
110 /* Enable Charger Mode Transition interrupt and End-of-charge interrupt. */
111 (void)PF1550_ModifyReg(handle, PF1550_CHG_INT_CNFG, 0x03U, 0x03U);
112 }
113
PF1550_GetChargerStatus(pf1550_handle_t * handle)114 uint32_t PF1550_GetChargerStatus(pf1550_handle_t *handle)
115 {
116 uint32_t status;
117 uint8_t temp = 0U;
118
119 assert(handle);
120
121 status = 0U;
122 (void)PF1550_ReadReg(handle, PF1550_VBUS_SNS, &temp);
123 status |= temp;
124 (void)PF1550_ReadReg(handle, PF1550_CHG_SNS, &temp);
125 status |= (uint32_t)temp << 8U;
126 (void)PF1550_ReadReg(handle, PF1550_BATT_SNS, &temp);
127 status |= (uint32_t)temp << 16U;
128
129 return status;
130 }
131
PF1550_SetChargerWdog(pf1550_handle_t * handle,uint32_t timeout_sec,bool enable)132 void PF1550_SetChargerWdog(pf1550_handle_t *handle, uint32_t timeout_sec, bool enable)
133 {
134 assert(handle);
135
136 if (enable)
137 {
138 (void)PF1550_ModifyReg(handle, PF1550_BATFET_CNFG, 0x40U, ((timeout_sec <= 32U) ? 0x40U : 0x0U));
139 (void)PF1550_ModifyReg(handle, PF1550_CHG_OPER, 0x04U, 0x4U);
140 }
141 else
142 {
143 (void)PF1550_ModifyReg(handle, PF1550_CHG_OPER, 0x04U, 0x0U);
144 }
145 }
146
PF1550_ServiceChargerWdog(pf1550_handle_t * handle)147 void PF1550_ServiceChargerWdog(pf1550_handle_t *handle)
148 {
149 assert(handle);
150
151 (void)PF1550_ModifyReg(handle, PF1550_BATFET_CNFG, 0x03U, 0x1U);
152 }
153
PF1550_EnableBatFET(pf1550_handle_t * handle,bool enable)154 void PF1550_EnableBatFET(pf1550_handle_t *handle, bool enable)
155 {
156 assert(handle);
157
158 (void)PF1550_ModifyReg(handle, PF1550_CHG_OPER, 0x08U, (enable ? 0x0U : 0x8U));
159 }
160
PF1550_SetBatFETAttibute(pf1550_handle_t * handle,const pf1550_batFET_attribute_t * attribute)161 void PF1550_SetBatFETAttibute(pf1550_handle_t *handle, const pf1550_batFET_attribute_t *attribute)
162 {
163 uint32_t temp;
164
165 assert(handle);
166 assert(attribute);
167
168 /* Set VBATT to VSYS FET overcurrent Threshold. */
169 if (attribute->overcurrentThreshold_mA == 0U)
170 {
171 temp = 0x0U;
172 }
173 else if (attribute->overcurrentThreshold_mA >= 3200U)
174 {
175 temp = 0x3U;
176 }
177 else if (attribute->overcurrentThreshold_mA >= 2800U)
178 {
179 temp = 0x2U;
180 }
181 else
182 {
183 temp = 0x1U;
184 }
185 temp = temp << 4U;
186 (void)PF1550_ModifyReg(handle, PF1550_BATFET_CNFG, 0x30U, (uint8_t)temp);
187
188 /* Set BATFET battery overcurrent limit protection. */
189 /* Set BATFET battery overcurrent protection when no VBUS is present. */
190 temp = 0U;
191 temp |= attribute->overcurrentProtectEnable ? 0x0U : 0x8U;
192 temp |= attribute->overcurrentProtectEnableNoVbus ? 0x80U : 0x0U;
193 (void)PF1550_ModifyReg(handle, PF1550_BATFET_CNFG, 0x88U, (uint8_t)temp);
194
195 /* Set BATFET control during battery overvoltage. */
196 /* Set BATFET control during watchdog fault. */
197 /* Set BATFET control during thermistor fault (< Cold or > Hot). */
198 /* Set BATFET control during thermal shutdown. */
199 /* Set BATFET control during charger timer fault. */
200 temp = 0U;
201 temp |= attribute->overvoltageFaultProtectEnable ? 0x1U : 0x0U;
202 temp |= attribute->watchDogFaultProtectEnable ? 0x2U : 0x0U;
203 temp |= attribute->thermalFaultProtectEnable ? 0x4U : 0x0U;
204 temp |= attribute->thermalShutdownProtectEnable ? 0x8U : 0x0U;
205 temp |= attribute->timerFaultProtectEnable ? 0x10U : 0x0U;
206 (void)PF1550_ModifyReg(handle, PF1550_FAULT_BATFET_CNFG, 0x1FU, (uint8_t)temp);
207 }
208
PF1550_SetPowerPathAttibute(pf1550_handle_t * handle,const pf1550_power_path_attribute_t * attribute)209 void PF1550_SetPowerPathAttibute(pf1550_handle_t *handle, const pf1550_power_path_attribute_t *attribute)
210 {
211 uint32_t temp;
212
213 assert(handle);
214 assert(attribute);
215
216 /* Set Maximum Vbus input current limit. */
217 if (attribute->vbusCurrentLimit_mA >= 1500U)
218 {
219 temp = 20U;
220 }
221 else if (attribute->vbusCurrentLimit_mA >= 1000U)
222 {
223 temp = 19U;
224 }
225 else if (attribute->vbusCurrentLimit_mA >= 200U)
226 {
227 temp = (attribute->vbusCurrentLimit_mA + 900U) / 100U;
228 }
229 else if (attribute->vbusCurrentLimit_mA >= 100U)
230 {
231 temp = (attribute->vbusCurrentLimit_mA + 350U) / 50U;
232 }
233 else if (attribute->vbusCurrentLimit_mA >= 10U)
234 {
235 temp = (attribute->vbusCurrentLimit_mA - 10U) / 5U;
236 }
237 else
238 {
239 temp = 0U;
240 }
241 temp = temp << 3U;
242 (void)PF1550_ModifyReg(handle, PF1550_VBUS_INLIM_CNFG, 0xF8U, (uint8_t)temp);
243
244 /* Set VBUS regulation voltage (DPM mode) */
245 temp = (attribute->vbusDpmVoltage_uV < 3900000U) ? 3900000U : attribute->vbusDpmVoltage_uV;
246 temp = (attribute->vbusDpmVoltage_uV > 4600000U) ? 4600000U : temp;
247 temp = (temp - 3900000U) / 100000U;
248 (void)PF1550_ModifyReg(handle, PF1550_VBUS_LIN_DPM, 0x07U, (uint8_t)temp);
249
250 /* Set Dynamic input power management panic stop threshold. */
251 if (attribute->vbusDpmStopThreshold_uV < 250000U)
252 {
253 temp = 0U;
254 }
255 else
256 {
257 temp = 1U;
258 }
259 temp = temp << 5U;
260 (void)PF1550_ModifyReg(handle, PF1550_VBUS_LIN_DPM, 0x20U, (uint8_t)temp);
261
262 /* Set VBUS overvoltage debounce delay. */
263 if (attribute->vbusOvDebounce_us < 1000U)
264 {
265 temp = 1U;
266 }
267 else if (attribute->vbusOvDebounce_us < 10000U)
268 {
269 temp = 2U;
270 }
271 else
272 {
273 temp = 3U;
274 }
275 (void)PF1550_ModifyReg(handle, PF1550_DBNC_DELAY_TIME, 0x03U, (uint8_t)temp);
276
277 /* Set VBUS to VSYS comparator debounce time. */
278 if (attribute->vbus2vsysDebounce_us < 1000U)
279 {
280 temp = 1U;
281 }
282 else if (attribute->vbus2vsysDebounce_us < 10000U)
283 {
284 temp = 2U;
285 }
286 else
287 {
288 temp = 3U;
289 }
290 (void)PF1550_ModifyReg(handle, PF1550_VBUS2SYS_CNFG, 0x03U, (uint8_t)temp);
291
292 /* Set VBUS to VSYS comparator threshold setting. */
293 if (attribute->vbus2vsysThreashold_uV < 175000U)
294 {
295 temp = 0U;
296 }
297 else
298 {
299 temp = 1U << 2U;
300 }
301 (void)PF1550_ModifyReg(handle, PF1550_VBUS2SYS_CNFG, 0x04U, (uint8_t)temp);
302
303 /* Set USBPHY voltage. */
304 if (attribute->usbPhyVoltage_uV < 4900000U)
305 {
306 temp = 0U;
307 }
308 else
309 {
310 temp = 1U << 1U;
311 }
312 (void)PF1550_ModifyReg(handle, PF1550_USB_PHY_LDO_CNFG, 0x02U, (uint8_t)temp);
313
314 /* Set Vsys Wake-up delay. */
315 if (attribute->vsysWakeupDelay_ms < 16U)
316 {
317 temp = 0U;
318 }
319 else if (attribute->vsysWakeupDelay_ms < 32U)
320 {
321 temp = 1U;
322 }
323 else if (attribute->vsysWakeupDelay_ms < 100U)
324 {
325 temp = 2U;
326 }
327 else
328 {
329 temp = 3U;
330 }
331 temp = temp << 4U;
332 (void)PF1550_ModifyReg(handle, PF1550_DBNC_DELAY_TIME, 0x30U, (uint8_t)temp);
333
334 /* Set Active discharger enable for USBPHY. */
335 /* Set USBPHY LDO enable. */
336 temp = attribute->usbPhyDischargerEnbale ? 0x1U : 0x0U;
337 temp |= attribute->usbPhyLdoEnable ? 0x4U : 0x0U;
338 (void)PF1550_ModifyReg(handle, PF1550_USB_PHY_LDO_CNFG, 0x05U, (uint8_t)temp);
339 }
340
PF1550_SetThermalAttibute(pf1550_handle_t * handle,const pf1550_thermal_attribute_t * attribute)341 void PF1550_SetThermalAttibute(pf1550_handle_t *handle, const pf1550_thermal_attribute_t *attribute)
342 {
343 uint32_t temp;
344
345 assert(handle);
346 assert(attribute);
347
348 /* Set Thermistor Configuration. */
349 (void)PF1550_ModifyReg(handle, PF1550_THM_REG_CNFG, 0x03U, (uint8_t)attribute->mode);
350
351 /* Set Junction temperature thermal regulation loop set point. */
352 if (attribute->junctionThermalSetPoint_C < 95)
353 {
354 temp = 0U;
355 }
356 else if (attribute->junctionThermalSetPoint_C < 110)
357 {
358 temp = 1U;
359 }
360 else
361 {
362 temp = 2U;
363 }
364 temp = temp << 2U;
365 (void)PF1550_ModifyReg(handle, PF1550_THM_REG_CNFG, 0x0CU, (uint8_t)temp);
366
367 /* Set Thermistor cold temperature selection. */
368 temp = (attribute->thermalColdThreshold_C <= -10) ? (1U << 4U) : 0U;
369 (void)PF1550_ModifyReg(handle, PF1550_THM_REG_CNFG, 0x10U, (uint8_t)temp);
370
371 /* Set Thermistor cool threshold setting. */
372 temp = (attribute->thermalCoolThreshold_C <= 10) ? (1U << 1U) : 0U;
373 (void)PF1550_ModifyReg(handle, PF1550_THM_ADJ_SETTING, 0x02U, (uint8_t)temp);
374
375 /* Set Thermistor warm threshold setting. */
376 temp = (attribute->thermalWarmThreshold_C < 50) ? 0U : 1U;
377 (void)PF1550_ModifyReg(handle, PF1550_THM_ADJ_SETTING, 0x01U, (uint8_t)temp);
378
379 /* Set Thermistor hot temperature selection. */
380 temp = (attribute->thermalHotThreshold_C < 60) ? (1U << 5U) : 0U;
381 (void)PF1550_ModifyReg(handle, PF1550_THM_REG_CNFG, 0x20U, (uint8_t)temp);
382
383 /* Set JEITA Thermistor battery termination voltage subtraction. */
384 if (attribute->thermalVoltageAdjust_uV >= 200000U)
385 {
386 temp = 3U;
387 }
388 else if (attribute->thermalVoltageAdjust_uV >= 160000U)
389 {
390 temp = 2U;
391 }
392 else if (attribute->thermalVoltageAdjust_uV >= 100000U)
393 {
394 temp = 1U;
395 }
396 else
397 {
398 temp = 0U;
399 }
400 temp = temp << 2U;
401 (void)PF1550_ModifyReg(handle, PF1550_THM_ADJ_SETTING, 0x0CU, (uint8_t)temp);
402
403 /* Set JEITA Thermistor battery charging current setting (percentage of I_FC). */
404 if (attribute->thermalCurrentAdjust_pct >= 100U)
405 {
406 temp = 3U;
407 }
408 else if (attribute->thermalCurrentAdjust_pct >= 75U)
409 {
410 temp = 2U;
411 }
412 else if (attribute->thermalCurrentAdjust_pct >= 50U)
413 {
414 temp = 1U;
415 }
416 else
417 {
418 temp = 0U;
419 }
420 temp = temp << 4U;
421 (void)PF1550_ModifyReg(handle, PF1550_THM_ADJ_SETTING, 0x30U, (uint8_t)temp);
422
423 /* Enable/disable thermal foldback current function. */
424 temp = attribute->thermalFoldbackEnable ? (1U << 7U) : 0U;
425 (void)PF1550_ModifyReg(handle, PF1550_THM_REG_CNFG, 0x80U, (uint8_t)temp);
426 }
427
PF1550_SetledOutput(pf1550_handle_t * handle,bool value)428 void PF1550_SetledOutput(pf1550_handle_t *handle, bool value)
429 {
430 assert(handle);
431
432 (void)PF1550_ModifyReg(handle, PF1550_LED_PWM, 0x80U, (value ? 0x80U : 0x0U));
433 }
434
PF1550_SetLedAttibute(pf1550_handle_t * handle,const pf1550_led_attribute_t * attribute)435 void PF1550_SetLedAttibute(pf1550_handle_t *handle, const pf1550_led_attribute_t *attribute)
436 {
437 uint32_t temp;
438
439 assert(handle);
440 assert(attribute);
441
442 /* Set Controls LED on/blinking mode. */
443 temp = (attribute->mode == kPF1550_LedMode_1) ? (1U << 4U) : 0x0U;
444 (void)PF1550_ModifyReg(handle, PF1550_LED_CNFG, 0x10U, (uint8_t)temp);
445
446 /* Set LED PWM duty cycle setting. */
447 temp = (attribute->pwmDuty_pct > 100U) ? 100U : attribute->pwmDuty_pct;
448 temp = (temp * 32U) / 100U;
449 (void)PF1550_ModifyReg(handle, PF1550_LED_PWM, 0x3FU, (uint8_t)temp);
450
451 /* Set LED driver PWM frequency setting. */
452 if (attribute->pwmFrequency_mHz >= 256000U)
453 {
454 temp = 0U;
455 }
456 else if (attribute->pwmFrequency_mHz >= 8000U)
457 {
458 temp = 1U;
459 }
460 else if (attribute->pwmFrequency_mHz >= 1000U)
461 {
462 temp = 2U;
463 }
464 else
465 {
466 temp = 3U;
467 }
468 (void)PF1550_ModifyReg(handle, PF1550_LED_CNFG, 0x03U, (uint8_t)temp);
469
470 /* Set Enable PWM ramp enable. */
471 temp = attribute->rampEnable ? 0x40U : 0x0U;
472 (void)PF1550_ModifyReg(handle, PF1550_LED_PWM, 0x40U, (uint8_t)temp);
473
474 /* Set Enable software control of LED. */
475 temp = attribute->swCtrlEnable ? 0x20U : 0x0U;
476 (void)PF1550_ModifyReg(handle, PF1550_LED_CNFG, 0x20U, (uint8_t)temp);
477 }
478
479 /*******************************************************************************
480 * EOF
481 ******************************************************************************/
482