1 /* ----------------------------------------------------------------------------
\r
2 * SAM Software Package License
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2015, Atmel Corporation
\r
6 * All rights reserved.
\r
8 * Redistribution and use in source and binary forms, with or without
\r
9 * modification, are permitted provided that the following conditions are met:
\r
11 * - Redistributions of source code must retain the above copyright notice,
\r
12 * this list of conditions and the disclaimer below.
\r
14 * Atmel's name may not be used to endorse or promote products derived from
\r
15 * this software without specific prior written permission.
\r
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
\r
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
\r
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
\r
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
\r
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
27 * ----------------------------------------------------------------------------
\r
30 /*----------------------------------------------------------------------------
\r
32 *----------------------------------------------------------------------------*/
\r
37 #include "peripherals/pio.h"
\r
38 #include "peripherals/pmc.h"
\r
39 #include "peripherals/flexcom.h"
\r
40 #include "peripherals/twi.h"
\r
41 #include "peripherals/twid.h"
\r
43 #include "power/act8945a.h"
\r
52 /*----------------------------------------------------------------------------
\r
54 *----------------------------------------------------------------------------*/
\r
56 #define STATE_VSEL 1 // HW config DDR3L
\r
62 trst: 1, // Reset time out 0->260 1->65ms
\r
63 nsysmode: 1, // response of SYSLEV voltage detector, 1->int 0>shutdown
\r
64 nsyslevmsk: 1, // 1->unmask int
\r
65 nsysstat: 1, // 1 if vsys < syslev voltage threshold
\r
66 syslev: 4; // defines SYSLEV voltage threshold
\r
75 scratch: 4, // user area to store system status information
\r
77 mstroff: 1, // Set bit to 1 to turn off all regulators
\r
83 // REG1 @0x20, REG2 @0x30, REG3 @0x40
\r
93 // REG1 @0x21, REG2 @0x31, REG3 @0x41
\r
103 // REG1 @0x22, REG2 @0x32, REG3 @0x42
\r
117 // REG4 @0x51, REG5 @0x55, REG6 @0x61, REG7 @0x65
\r
198 /*----------------------------------------------------------------------------
\r
200 *----------------------------------------------------------------------------*/
\r
203 #define ACT8945A_TWI_ADDRESS 0x5B
\r
205 #define NUM_REGULATORS 7
\r
207 #define IADDR_SYS0 0x00
\r
208 #define IADDR_SYS1 0x01
\r
209 #define IADDR_REG1 0x20
\r
210 #define IADDR_REG2 0x30
\r
211 #define IADDR_REG3 0x40
\r
212 #define IADDR_REG4 0x50
\r
213 #define IADDR_REG5 0x54
\r
214 #define IADDR_REG6 0x60
\r
215 #define IADDR_REG7 0x64
\r
216 #define IADDR_APCH_70 0x70
\r
217 #define IADDR_APCH_71 0x71
\r
218 #define IADDR_APCH_78 0x78
\r
219 #define IADDR_APCH_79 0x79
\r
220 #define IADDR_APCH_7A 0x7a
\r
222 static const uint8_t _iaddr_reg[] = {
\r
223 IADDR_REG1, IADDR_REG2, IADDR_REG3, IADDR_REG4,
\r
224 IADDR_REG5, IADDR_REG6, IADDR_REG7,
\r
227 static const char* _charging_states[4] = {
\r
228 "Suspend/Disable/Fault",
\r
230 "Fast charge/Top-off",
\r
240 static const struct _reg _regs[] = {
\r
241 { "SYS0 ", IADDR_SYS0 },
\r
242 { "SYS1 ", IADDR_SYS1 },
\r
243 { "REG1_20", IADDR_REG1 },
\r
244 { "REG1_21", IADDR_REG1 + 1 },
\r
245 { "REG1_22", IADDR_REG1 + 2 },
\r
246 { "REG2_30", IADDR_REG2 },
\r
247 { "REG2_31", IADDR_REG2 + 1 },
\r
248 { "REG2_32", IADDR_REG2 + 2 },
\r
249 { "REG3_40", IADDR_REG3 },
\r
250 { "REG3_41", IADDR_REG3 + 1 },
\r
251 { "REG3_42", IADDR_REG3 + 2 },
\r
252 { "REG4_50", IADDR_REG4 },
\r
253 { "REG4_51", IADDR_REG4 + 1 },
\r
254 { "REG5_54", IADDR_REG5 },
\r
255 { "REG5_55", IADDR_REG5 + 1 },
\r
256 { "REG6_60", IADDR_REG6 },
\r
257 { "REG6_61", IADDR_REG6 + 1 },
\r
258 { "REG7_64", IADDR_REG7 },
\r
259 { "REG7_65", IADDR_REG7 + 1 },
\r
260 { "APCH_70", IADDR_APCH_70 },
\r
261 { "APCH_71", IADDR_APCH_71 },
\r
262 { "APCH_78", IADDR_APCH_78 },
\r
263 { "APCH_79", IADDR_APCH_79 },
\r
264 { "APCH_7A", IADDR_APCH_7A },
\r
267 static const char *_ovp_setting[4] = {
\r
268 "6.6V", "7.0V", "7.5V", "8.0V",
\r
271 /*------------------------------------------------------------------------------
\r
273 *----------------------------------------------------------------------------*/
\r
275 static bool _act8945a_read_reg(struct _act8945a* act8945a, uint32_t iaddr,
\r
279 struct _buffer in = {
\r
283 act8945a->twid->slave_addr = ACT8945A_TWI_ADDRESS;
\r
284 act8945a->twid->iaddr = iaddr;
\r
285 act8945a->twid->isize = 1;
\r
286 status = twid_transfert(act8945a->twid, &in, 0,
\r
287 twid_finish_transfert_callback, 0);
\r
288 if (status != TWID_SUCCESS)
\r
290 twid_wait_transfert(act8945a->twid);
\r
294 static bool _act8945a_write_reg(struct _act8945a* act8945a, uint32_t iaddr,
\r
298 struct _buffer out = {
\r
299 .data = (uint8_t*)&value,
\r
302 act8945a->twid->slave_addr = ACT8945A_TWI_ADDRESS;
\r
303 act8945a->twid->iaddr = iaddr;
\r
304 act8945a->twid->isize = 1;
\r
305 status = twid_transfert(act8945a->twid, 0, &out,
\r
306 twid_finish_transfert_callback, 0);
\r
307 if (status != TWID_SUCCESS)
\r
309 twid_wait_transfert(act8945a->twid);
\r
313 static bool _act8945a_update_cached_registers(struct _act8945a *act8945a)
\r
315 return _act8945a_read_reg(act8945a, IADDR_SYS0, &act8945a->sys0) &&
\r
316 _act8945a_read_reg(act8945a, IADDR_APCH_78, &act8945a->apch78) &&
\r
317 _act8945a_read_reg(act8945a, IADDR_APCH_79, &act8945a->apch79) &&
\r
318 _act8945a_read_reg(act8945a, IADDR_APCH_7A, &act8945a->apch7a);
\r
321 static void _act8945a_irq_handler(uint32_t group, uint32_t status, void* user_arg)
\r
323 struct _act8945a *act8945a = (struct _act8945a*)user_arg;
\r
325 if (status & act8945a->desc.pin_irq.mask) {
\r
327 union _apch_78 apch78;
\r
328 union _apch_79 apch79;
\r
329 union _apch_7a apch7a;
\r
331 // save previous values
\r
332 sys0.u8 = act8945a->sys0;
\r
333 apch78.u8 = act8945a->apch78;
\r
334 apch79.u8 = act8945a->apch79;
\r
335 apch7a.u8 = act8945a->apch7a;
\r
338 _act8945a_update_cached_registers(act8945a);
\r
341 if (sys0.u8 != act8945a->sys0) {
\r
342 trace_debug("PMIC IRQ: SYST0 changed\r\n");
\r
344 if (apch78.u8 != act8945a->apch78) {
\r
345 if (apch78.bits.chgdat == 0x01)
\r
346 trace_debug("PMIC IRQ: charger state machine, END-OF-CHARGE state\r\n");
\r
348 if (apch79.u8 != act8945a->apch79) {
\r
349 printf("PMIC IRQ: APCH79 changed\r\n");
\r
351 if (apch7a.u8 != act8945a->apch7a) {
\r
352 trace_debug("PMIC IRQ: %s\r\n", _charging_states[apch7a.bits.cstate]);
\r
357 static void _act8945a_lbo_handler(uint32_t group, uint32_t status, void* user_arg)
\r
359 struct _act8945a *act8945a = (struct _act8945a*)user_arg;
\r
361 if (status & act8945a->desc.pin_lbo.mask) {
\r
362 trace_debug("PMIC LBO: Low Battery Output\r\n");
\r
363 if( act8945a->lbo_count++ >= 10)
\r
364 pio_disable_it(&act8945a->desc.pin_lbo);
\r
368 // Enable interrupt on nIRQ pin to MPU
\r
369 static void _act8945a_enable_interrupt_handlers(struct _act8945a *act8945a)
\r
371 /* Configure PMIC line interrupts. */
\r
372 pio_configure_it(&act8945a->desc.pin_irq);
\r
373 pio_add_handler_to_group(act8945a->desc.pin_irq.group,
\r
374 act8945a->desc.pin_irq.mask,
\r
375 &_act8945a_irq_handler,
\r
377 pio_enable_it(&act8945a->desc.pin_irq);
\r
379 /* Configure LBO line interrupts. */
\r
380 act8945a->lbo_count = 0;
\r
381 pio_configure_it(&act8945a->desc.pin_lbo);
\r
382 pio_add_handler_to_group(act8945a->desc.pin_lbo.group,
\r
383 act8945a->desc.pin_lbo.mask,
\r
384 &_act8945a_lbo_handler,
\r
386 pio_enable_it(&act8945a->desc.pin_lbo);
\r
389 static uint16_t _act8945a_convert_voltage_setting(uint8_t setting)
\r
391 uint8_t mul20, mul53;
\r
393 mul20 = (setting & 0x07) >> 0;
\r
394 mul53 = (setting & 0x38) >> 3;
\r
396 if (setting <= 0x17)
\r
397 return (uint16_t)(1000 * (0.6 + (0.2 * mul53) + (0.025 * mul20)));
\r
398 else if (setting <= 0x2F)
\r
399 return (uint16_t)(1000 * (1.2 + (0.4 * (mul53 - 3)) + (0.050 * mul20)));
\r
401 return (uint16_t)(1000 * (2.4 + (0.8 * (mul53 - 6)) + (0.1 * mul20)));
\r
404 /*------------------------------------------------------------------------------
\r
405 * Exported functions
\r
406 *----------------------------------------------------------------------------*/
\r
408 bool act8945a_configure(struct _act8945a *act8945a, struct _twi_desc *twid)
\r
412 act8945a->twid = twid;
\r
413 twid_configure(twid);
\r
415 pio_configure(&act8945a->desc.pin_chglev, 1);
\r
416 pio_configure(&act8945a->desc.pin_irq, 1);
\r
417 pio_configure(&act8945a->desc.pin_lbo, 1);
\r
419 if (!_act8945a_read_reg(act8945a, IADDR_SYS0, &data))
\r
422 /* Set Charge Level */
\r
423 act8945a_set_charge_level(act8945a, ACT8945A_CHARGE_LEVEL_450MA);
\r
425 /* Set level interrupt */
\r
426 act8945a_disable_all_apch_interrupts(act8945a);
\r
427 act8945a_configure_apch_interrupt(act8945a, CHARGE_STATE_INTO_EOC_STATE, true);
\r
428 act8945a_configure_apch_interrupt(act8945a, CHARGE_STATE_OUT_EOC_STATE, true);
\r
429 act8945a_configure_apch_interrupt(act8945a, PRECHARGE_TIME_OUT, true);
\r
430 act8945a_configure_apch_interrupt(act8945a, TOTAL_CHARGE_TIME_OUT, true);
\r
431 act8945a_enable_system_voltage_level_interrupt(act8945a, true);
\r
433 /* Update cached register values */
\r
434 if (!_act8945a_update_cached_registers(act8945a))
\r
437 act8945a_enable_regulator_fault_interrupt(act8945a, 1, true);
\r
438 act8945a_enable_regulator_fault_interrupt(act8945a, 5, true);
\r
440 /* Enable interrupts */
\r
441 _act8945a_enable_interrupt_handlers(act8945a);
\r
446 // Charge Current Selection Input
\r
447 // In USB-Mode: CHGLEV = 1 -> I charge 450mA
\r
448 // CHGLEV = 0 -> I charge 100mA
\r
449 void act8945a_set_charge_level(struct _act8945a *act8945a,
\r
450 enum _act8945a_charge_level level)
\r
453 case ACT8945A_CHARGE_LEVEL_100MA:
\r
454 pio_clear(&act8945a->desc.pin_chglev);
\r
455 trace_debug("Charge Level: 100mA\r\n");
\r
457 case ACT8945A_CHARGE_LEVEL_450MA:
\r
458 pio_set(&act8945a->desc.pin_chglev);
\r
459 trace_debug("Charge Level: 450mA\r\n");
\r
462 trace_warning("Invalid charge level requested: %d\r\n",
\r
468 // Set or Clear an APCH interrupt
\r
469 // Set bit to 1 enable interrupt,
\r
470 // Clear bit to 0 to disable interrupt
\r
471 bool act8945a_configure_apch_interrupt(struct _act8945a *act8945a,
\r
472 enum _act8945a_interrupt interrupt, bool enable)
\r
475 union _apch_78 apch78;
\r
476 union _apch_79 apch79;
\r
478 if (!_act8945a_read_reg(act8945a, IADDR_APCH_78, &apch78.u8) ||
\r
479 !_act8945a_read_reg(act8945a, IADDR_APCH_79, &apch79.u8))
\r
484 // Interrupt generated any time the input supply is disconnected when
\r
485 // INSTAT[] bit is set to 1 and the INDIS[] bit is set to 1.
\r
486 case INPUT_VOLTAGE_OUT_VALID_RANGE: // Interrupt
\r
487 apch78.bits.instat = enable ? 1 : 0;
\r
488 apch79.bits.indis = enable ? 1 : 0;
\r
491 // Interrupt generated any time the input supply is connected when
\r
492 // INSTAT[] bit is set to 1 and the INCON[] bit is set to 1.
\r
493 case INPUT_VOLTAGE_INTO_VALID_RANGE:
\r
494 apch78.bits.instat = enable ? 1 : 0;
\r
495 apch79.bits.incon = enable ? 1 : 0;
\r
498 // Interrupts based upon the status of the battery temperature.
\r
499 // Set the TEMPOUT[] bit to 1 and TEMPSTAT[] bit to 1 to generate
\r
500 // an interrupt when battery temperature goes out of the valid
\r
501 // temperature range.
\r
502 case BATTERY_TEMPERATURE_OUT_RANGE:
\r
503 apch78.bits.tempstat = enable ? 1 : 0;
\r
504 apch79.bits.tempout = enable ? 1 : 0;
\r
507 // Interrupts based upon the status of the battery temperature.
\r
508 // Set the TEMPIN[] bit to 1 and TEMPSTAT[] bit to 1 to generate
\r
509 // an interrupt when battery temperature returns to the valid range.
\r
510 case BATTERY_TEMPERATURE_INTO_RANGE:
\r
511 apch78.bits.tempstat = enable ? 1 : 0;
\r
512 apch79.bits.tempin = enable ? 1 : 0;
\r
515 // Interrupt when the charger state machine goes into the
\r
516 // END-OF-CHARGE (EOC). Set CHGEOCIN[] bit to 1 and CHGSTAT[] bit
\r
517 // to 1 to generate an interrupt when the charger state machine goes
\r
518 // into the END-OF-CHARGE (EOC)state.
\r
519 case CHARGE_STATE_INTO_EOC_STATE:
\r
520 apch78.bits.chgstat = enable ? 1 : 0;
\r
521 apch79.bits.chgeocin = enable ? 1 : 0;
\r
524 // Interrupt when the charger state machine exit the
\r
525 // END-OF-CHARGE (EOC). Set CHGEOCOUT[] bit to 1 and CHGSTAT[] bit
\r
526 // to 1 to generate an interrupt when the charger state machine exits
\r
528 case CHARGE_STATE_OUT_EOC_STATE:
\r
529 apch78.bits.chgstat = enable ? 1 : 0;
\r
530 apch79.bits.chgeocout = enable ? 1 : 0;
\r
533 // Interrupts based upon the status of the charge timers.
\r
534 // Set the TIMRPRE[] bit to 1 and TIMRSTAT[] bit to 1 to generate an
\r
535 // interrupt when the Precondition Timer expires.
\r
536 case PRECHARGE_TIME_OUT:
\r
537 apch78.bits.timrstat = enable ? 1 : 0;
\r
538 apch79.bits.timrpre = enable ? 1 : 0;
\r
541 // Set the TIMRTOT[] bit to 1 and TIMRSTAT[] bit to 1 to generate an
\r
542 // interrupt when the Total-Charge Timer expires.
\r
543 case TOTAL_CHARGE_TIME_OUT:
\r
544 apch78.bits.timrstat = enable ? 1 : 0;
\r
545 apch79.bits.timrtot = enable ? 1 : 0;
\r
549 trace_warning("Unknown interrupt %d\r\n", interrupt);
\r
553 // Write configuration to registers
\r
554 status = _act8945a_write_reg(act8945a, IADDR_APCH_78, apch78.u8);
\r
555 status |= _act8945a_write_reg(act8945a, IADDR_APCH_79, apch79.u8);
\r
560 // Disable all interrupt from APCH
\r
561 bool act8945a_disable_all_apch_interrupts(struct _act8945a *act8945a)
\r
563 return act8945a_configure_apch_interrupt(act8945a, CHARGE_STATE_OUT_EOC_STATE, false) &&
\r
564 act8945a_configure_apch_interrupt(act8945a, INPUT_VOLTAGE_OUT_VALID_RANGE, false) &&
\r
565 act8945a_configure_apch_interrupt(act8945a, BATTERY_TEMPERATURE_OUT_RANGE, false) &&
\r
566 act8945a_configure_apch_interrupt(act8945a, PRECHARGE_TIME_OUT, false) &&
\r
567 act8945a_configure_apch_interrupt(act8945a, CHARGE_STATE_INTO_EOC_STATE, false) &&
\r
568 act8945a_configure_apch_interrupt(act8945a, INPUT_VOLTAGE_INTO_VALID_RANGE, false) &&
\r
569 act8945a_configure_apch_interrupt(act8945a, BATTERY_TEMPERATURE_INTO_RANGE, false) &&
\r
570 act8945a_configure_apch_interrupt(act8945a, TOTAL_CHARGE_TIME_OUT, false);
\r
573 extern bool act8945a_set_system_voltage_detect_threshold(struct _act8945a *act8945a,
\r
574 uint16_t threshold)
\r
578 if (threshold < 2300 || threshold > 3800)
\r
580 if (!_act8945a_read_reg(act8945a, IADDR_SYS0, &sys0.u8))
\r
582 sys0.bits.syslev = (threshold - 2300) / 100;
\r
583 return _act8945a_write_reg(act8945a, IADDR_SYS0, sys0.u8);
\r
586 bool act8945a_enable_system_voltage_level_interrupt(struct _act8945a *act8945a,
\r
591 if (!_act8945a_read_reg(act8945a, IADDR_SYS0, &sys0.u8))
\r
593 sys0.bits.nsyslevmsk = enable ? 1 : 0;
\r
595 sys0.bits.nsysmode = 1; //*************
\r
597 return _act8945a_write_reg(act8945a, IADDR_SYS0, sys0.u8);
\r
600 bool act8945a_set_regulator_voltage(struct _act8945a *act8945a,
\r
601 uint8_t reg, uint16_t vout)
\r
603 // minimum is 600mV
\r
605 trace_warning("Cannot set regulator %d voltage to %dmV, using 600mV instead\r\n", reg, vout);
\r
608 // maximum is 3900mV
\r
610 trace_warning("Cannot set regulator %d voltage to %dmV, using 3900mV instead\r\n", reg, vout);
\r
614 // can only set voltage for regulators 4 to 7
\r
615 if (reg < 4 || reg > 7) {
\r
616 trace_error("Cannot change voltage of regulator %d\r\n", reg);
\r
622 value = (vout - 600) / 25;
\r
623 } else if (vout < 2400) {
\r
624 value = 0x18 + (vout - 1200) / 50;
\r
625 } else if (vout <= 3900) {
\r
626 value = 0x30 + (vout - 2400) / 100;
\r
629 uint32_t iaddr = _iaddr_reg[reg - 1];
\r
630 return _act8945a_write_reg(act8945a, iaddr, value & 0x3f);
\r
633 bool act8945a_enable_regulator(struct _act8945a *act8945a,
\r
634 uint8_t reg, bool enable)
\r
636 if (reg >= 1 && reg <= 3) {
\r
637 union _ctrl1 ctrl1;
\r
638 uint32_t iaddr = _iaddr_reg[reg - 1] + 1;
\r
640 if (!_act8945a_read_reg(act8945a, iaddr, &ctrl1.u8))
\r
643 ctrl1.bits.on = enable ? 1 : 0;
\r
645 if (!_act8945a_write_reg(act8945a, iaddr, ctrl1.u8))
\r
647 } else if (reg >= 4 && reg <= 7) {
\r
648 union _ctrl2 ctrl2;
\r
649 uint32_t iaddr = _iaddr_reg[reg - 1] + 1;
\r
651 if (!_act8945a_read_reg(act8945a, iaddr, &ctrl2.u8))
\r
654 ctrl2.bits.on = enable ? 1 : 0;
\r
656 if (!_act8945a_write_reg(act8945a, iaddr, ctrl2.u8))
\r
659 trace_error("Invalid regulator number %d\r\n", reg);
\r
666 bool act8945a_enable_regulator_fault_interrupt(struct _act8945a *act8945a,
\r
667 uint8_t reg, bool enable)
\r
669 if (reg >= 1 && reg <= 3) {
\r
670 union _ctrl1 ctrl1;
\r
671 uint8_t iaddr = (_iaddr_reg[reg-1]) + 2;
\r
674 if (!_act8945a_read_reg(act8945a, iaddr, &ctrl1.u8))
\r
677 ctrl1.bits.nfltmsk = enable ? 1 : 0;
\r
679 if (!_act8945a_write_reg(act8945a, iaddr, ctrl1.u8))
\r
681 } else if (reg >= 4 && reg <= 7) {
\r
682 union _ctrl2 ctrl2;
\r
683 uint8_t iaddr = (_iaddr_reg[reg-1]) + 1;
\r
685 if (!_act8945a_read_reg(act8945a, iaddr, &ctrl2.u8))
\r
688 ctrl2.bits.nfltmsk = enable ? 1 : 0;
\r
690 if (!_act8945a_write_reg(act8945a, iaddr, ctrl2.u8))
\r
693 trace_error("Invalid regulator number %d\r\n", reg);
\r
700 extern bool act8945a_get_lbo_pin_state(struct _act8945a *act8945a)
\r
702 return pio_get(&act8945a->desc.pin_lbo) ? true : false;
\r
707 extern void act8945a_display_voltage_settings(struct _act8945a *act8945a)
\r
711 trace_info_wp("\r\n-- ACT8945A - Voltage Settings & State --\r\n");
\r
713 for (reg = 0; reg < NUM_REGULATORS; reg++)
\r
715 uint8_t iadd_reg, setting, ctrl;
\r
718 /* Warning VSEL state */
\r
719 iadd_reg = _iaddr_reg[reg];
\r
720 if( (iadd_reg < IADDR_REG4) && (STATE_VSEL == 1) )
\r
723 if (!_act8945a_read_reg(act8945a, iadd_reg, &setting))
\r
726 if (!_act8945a_read_reg(act8945a, iadd_reg + 1, &ctrl))
\r
729 u = _act8945a_convert_voltage_setting(setting);
\r
730 trace_info_wp(" - VOUT_%d (0x%02x) = %dmV", reg + 1, ctrl, u);
\r
732 union _ctrl1 *ctrl1 = (union _ctrl1*)&ctrl;
\r
733 trace_info_wp(" %s", ctrl1->bits.on ? "on" : "off");
\r
734 trace_info_wp(" %s", ctrl1->bits.phase ? "180" : "osc");
\r
735 trace_info_wp(" %s", ctrl1->bits.mode ? "pwm" : "pow-saving");
\r
736 trace_info_wp(" delay:0x%02x", ctrl1->bits.delay);
\r
737 trace_info_wp(" %s", ctrl1->bits.nfltmsk ? "en" : "dis");
\r
738 trace_info_wp(" %s", ctrl1->bits.ok ? "OK" : "<tresh");
\r
740 union _ctrl2 *ctrl2 = (union _ctrl2*)&ctrl;
\r
741 trace_info_wp(" %s", ctrl2->bits.on ? "on": "off");
\r
742 trace_info_wp(" %s", ctrl2->bits.dis ? "off" : "on");
\r
743 trace_info_wp(" %s", ctrl2->bits.lowiq ? "normal" : "low-power");
\r
744 trace_info_wp(" delay:0x%02x", ctrl2->bits.delay);
\r
745 trace_info_wp(" %s", ctrl2->bits.nfltmsk ? "en" : "dis");
\r
746 trace_info_wp(" %s", ctrl2->bits.ok ? "OK" : "<tresh");
\r
748 trace_info_wp("\r\n");
\r
752 if (!_act8945a_read_reg(act8945a, IADDR_SYS0, &sys0.u8))
\r
754 trace_info_wp(" - SYSLEV Failing Treshold (0x%02x) = %dmV\r\n", sys0.u8,
\r
755 2300 + sys0.bits.syslev * 100);
\r
758 void act8945a_dump_registers(struct _act8945a *act8945a)
\r
760 uint8_t reg, data, mask, i;
\r
763 trace_info_wp("\r\n-- ACT8945A - Registers Dump --\r\n");
\r
764 for (reg = 0; reg < ARRAY_SIZE(_regs); reg++) {
\r
765 if (!_act8945a_read_reg(act8945a, _regs[reg].iaddr, &data))
\r
767 trace_info_wp(" - %s: 0x%02X b:", _regs[reg].name, data);
\r
769 for (i=0; i<8; i++, mask>>=1) {
\r
770 printf ("%x", (data&mask) ? 1 : 0);
\r
772 trace_info_wp("\r\n");
\r
774 trace_info_wp("\r\n");
\r
777 void act8945a_display_apch_registers(struct _act8945a *act8945a)
\r
779 union _apch_71 apch71;
\r
780 union _apch_78 apch78;
\r
781 union _apch_79 apch79;
\r
782 union _apch_7a apch7a;
\r
784 trace_info_wp("\r\n-- ACT8945A - APCH Registers --\r\n");
\r
786 // if (!_act8945a_read_reg(act8945a, IADDR_APCH_70, &data))
\r
788 // trace_info_wp(" - APCH @0x70: 0x%02x (reserved)\r\n", data);
\r
790 if (!_act8945a_read_reg(act8945a, IADDR_APCH_71, &apch71.u8))
\r
792 trace_info_wp(" - APCH @0x71: 0x%02x\r\n", apch71.u8);
\r
793 trace_info_wp(" Charge Suspend Control Input: %x\r\n",
\r
794 apch71.bits.suschg);
\r
795 trace_info_wp(" Total Charge Time-out Selection: %x\r\n",
\r
796 apch71.bits.tottimo);
\r
797 trace_info_wp(" Precondition Charge Time-out Sel: %x\r\n",
\r
798 apch71.bits.pretimo);
\r
799 trace_info_wp(" Input Over-Volt Prot.Threshold Sel: %x (%s)\r\n",
\r
800 apch71.bits.ovpset, _ovp_setting[apch71.bits.ovpset]);
\r
802 if (!_act8945a_read_reg(act8945a, IADDR_APCH_78, &apch78.u8))
\r
804 trace_info_wp(" - APCH @0x78: 0x%02x\r\n", apch78.u8);
\r
805 trace_info_wp(" Charge Time-out Interrupt Status: %x\r\n",
\r
806 apch78.bits.timrstat);
\r
807 trace_info_wp(" Battery Temperature Interrupt Status: %x\r\n",
\r
808 apch78.bits.tempstat);
\r
809 trace_info_wp(" Input Voltage Interrupt Status: %x\r\n",
\r
810 apch78.bits.instat);
\r
811 trace_info_wp(" Charge State Interrupt Status: %x\r\n",
\r
812 apch78.bits.chgstat);
\r
813 trace_info_wp(" Charge Timer Status %x\r\n",
\r
814 apch78.bits.timrdat);
\r
815 trace_info_wp(" Temperature Status %x\r\n",
\r
816 apch78.bits.tempdat);
\r
817 trace_info_wp(" Input Voltage Status %x\r\n",
\r
818 apch78.bits.indat);
\r
819 trace_info_wp(" Charge State Machine Status %x\r\n",
\r
820 apch78.bits.chgdat);
\r
822 if (!_act8945a_read_reg(act8945a, IADDR_APCH_79, &apch79.u8))
\r
824 trace_info_wp(" - APCH @0x79: 0x%02x\r\n", apch79.u8);
\r
825 trace_info_wp(" Total Charge Time-out Int Control: %x\r\n",
\r
826 apch79.bits.timrtot);
\r
827 trace_info_wp(" Batt.Temp.Int.Ctrl into valid range: %x\r\n",
\r
828 apch79.bits.tempin);
\r
829 trace_info_wp(" Inp.Voltage Int.Ctrl into valid range: %x\r\n",
\r
830 apch79.bits.incon);
\r
831 trace_info_wp(" Charge State Int Ctrl into EOC state: %x\r\n",
\r
832 apch79.bits.chgeocin);
\r
833 trace_info_wp(" Precharge Time-out Int Ctrl: %x\r\n",
\r
834 apch79.bits.timrpre);
\r
835 trace_info_wp(" Batt.Temp.Int.Ctrl. out valid range: %x\r\n",
\r
836 apch79.bits.tempout);
\r
837 trace_info_wp(" Inp.Voltage Int.Ctrl. out valid range: %x\r\n",
\r
838 apch79.bits.indis);
\r
839 trace_info_wp(" Charge State Int.Ctrl. out EOC state: %x\r\n",
\r
840 apch79.bits.chgeocout);
\r
842 if (!_act8945a_read_reg(act8945a, IADDR_APCH_7A, &apch7a.u8))
\r
844 trace_info_wp(" - APCH @0x7a: 0x%02x\r\n", apch7a.u8);
\r
845 trace_info_wp(" Charge State: %x (%s)\r\n",
\r
846 apch7a.bits.cstate, _charging_states[apch7a.bits.cstate]);
\r
847 trace_info_wp(" ACIN Status: %x\r\n",
\r
848 apch7a.bits.acinstat);
\r
851 void act8945a_display_system_registers(struct _act8945a *act8945a)
\r
856 trace_info_wp("\r\n-- ACT8945A - System Registers --\r\n");
\r
858 if (!_act8945a_read_reg(act8945a, IADDR_SYS0, &sys0.u8))
\r
860 trace_info_wp(" - SYS0 @0x00: 0x%02x\r\n", sys0.u8);
\r
861 trace_info_wp(" Reset Timer Setting: %s\r\n",
\r
862 sys0.bits.trst ? "64ms" : "260ms");
\r
863 trace_info_wp(" SYSLEV Mode Select: %s\r\n",
\r
864 sys0.bits.nsysmode ?"int" : "shutdown");
\r
865 trace_info_wp(" System Voltage Level Int.Mask: %s\r\n",
\r
866 sys0.bits.nsyslevmsk ?"int" : "noint");
\r
867 trace_info_wp(" System Voltage Status: %s\r\n",
\r
868 sys0.bits.nsysstat ? "vsys<syslev" : "vsys>syslev");
\r
869 trace_info_wp(" SYSLEV Failing Treshold value: %dmV\r\n",
\r
870 2300 + sys0.bits.syslev * 100);
\r
872 if (!_act8945a_read_reg(act8945a, IADDR_SYS1, &sys1.u8))
\r
874 trace_info_wp(" - SYS1 @0x01: 0x%02x\r\n", sys1.u8);
\r
875 trace_info_wp(" Master Off Ctrl, All regul: %s\r\n",
\r
876 sys1.bits.mstroff ? "off" : "on");
\r
877 trace_info_wp(" Scratchpad Bits, free user: %x\r\n",
\r
878 sys1.bits.scratch);
\r
881 void act8945a_display_charge_state(struct _act8945a *act8945a)
\r
883 union _apch_7a apch7a;
\r
884 if (!_act8945a_read_reg(act8945a, IADDR_APCH_7A, &apch7a.u8)) return;
\r
886 if (act8945a->apch7a != apch7a.u8) {
\r
887 trace_info_wp(" Charge State: %x (%s)\r\n", apch7a.bits.cstate, _charging_states[apch7a.bits.cstate]);
\r
888 act8945a->apch7a = apch7a.u8;
\r