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