You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by je...@apache.org on 2019/05/31 10:53:24 UTC
[mynewt-core] branch master updated (e3bbcc0 -> 6b62430)
This is an automated email from the ASF dual-hosted git repository.
jerzy pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git.
from e3bbcc0 Added null device check in os_dev_close (#1850)
new 712aea0 hw/drivers/adc: Add battery reading channel
new 49a09e5 da1469x_charger: Add charger for DA1469x
new 6b62430 hw/mcu/da1469x: Add charger to MCU
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../include/gpadc_da1469x/gpadc_da1469x.h | 7 +
hw/drivers/adc/gpadc_da1469x/src/gpadc_da1469x.c | 27 +
.../include/sdadc_da1469x/sdadc_da1469x.h | 7 +
hw/drivers/adc/sdadc_da1469x/src/sdadc_da1469x.c | 25 +
.../include/da1469x_charger/da1469x_charger.h | 269 +++++
.../chg_ctrl/{bq24040 => da1469x_charger}/pkg.yml | 7 +-
.../chg_ctrl/da1469x_charger/src/da1469x_charger.c | 508 +++++++++
.../da1469x_charger/src/da1469x_charger_shell.c | 1202 ++++++++++++++++++++
hw/drivers/chg_ctrl/da1469x_charger/syscfg.yml | 76 ++
hw/mcu/dialog/da1469x/pkg.yml | 3 +
hw/mcu/dialog/da1469x/src/da1469x_periph.c | 53 +
hw/mcu/dialog/da1469x/syscfg.yml | 16 +
12 files changed, 2197 insertions(+), 3 deletions(-)
create mode 100644 hw/drivers/chg_ctrl/da1469x_charger/include/da1469x_charger/da1469x_charger.h
copy hw/drivers/chg_ctrl/{bq24040 => da1469x_charger}/pkg.yml (86%)
create mode 100644 hw/drivers/chg_ctrl/da1469x_charger/src/da1469x_charger.c
create mode 100644 hw/drivers/chg_ctrl/da1469x_charger/src/da1469x_charger_shell.c
create mode 100644 hw/drivers/chg_ctrl/da1469x_charger/syscfg.yml
[mynewt-core] 03/03: hw/mcu/da1469x: Add charger to MCU
Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 6b62430c7939371309d4a96e93198a31cef0d906
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Thu Apr 25 16:13:47 2019 +0200
hw/mcu/da1469x: Add charger to MCU
da1469x_periph_create() now can create charger device.
---
hw/mcu/dialog/da1469x/pkg.yml | 3 ++
hw/mcu/dialog/da1469x/src/da1469x_periph.c | 53 ++++++++++++++++++++++++++++++
hw/mcu/dialog/da1469x/syscfg.yml | 4 +++
3 files changed, 60 insertions(+)
diff --git a/hw/mcu/dialog/da1469x/pkg.yml b/hw/mcu/dialog/da1469x/pkg.yml
index 5bec5be..4501a85 100644
--- a/hw/mcu/dialog/da1469x/pkg.yml
+++ b/hw/mcu/dialog/da1469x/pkg.yml
@@ -30,6 +30,9 @@ pkg.deps:
- "@apache-mynewt-core/hw/cmsis-core"
- hw/mcu/dialog
+pkg.deps.CHARGER:
+ - hw/drivers/chg_ctrl/da1469x_charger
+
pkg.deps.TRNG:
- "hw/drivers/trng/trng_da1469x"
diff --git a/hw/mcu/dialog/da1469x/src/da1469x_periph.c b/hw/mcu/dialog/da1469x/src/da1469x_periph.c
index 295c743..e2d8ef8 100644
--- a/hw/mcu/dialog/da1469x/src/da1469x_periph.c
+++ b/hw/mcu/dialog/da1469x/src/da1469x_periph.c
@@ -23,6 +23,7 @@
#include "os/os_cputime.h"
#include "mcu/da1469x_hal.h"
#include "mcu/da1469x_dma.h"
+#include "bsp/bsp.h"
#if MYNEWT_VAL(UART_0) || MYNEWT_VAL(UART_1) || MYNEWT_VAL(UART_2)
#include "uart/uart.h"
@@ -70,6 +71,10 @@ static struct trng_dev os_bsp_trng;
#include <sdadc_da1469x/sdadc_da1469x.h>
#endif
+#if MYNEWT_VAL(CHARGER)
+#include "da1469x_charger/da1469x_charger.h"
+#endif
+
#if MYNEWT_VAL(UART_0)
static struct uart_dev os_bsp_uart0;
static const struct da1469x_uart_cfg os_bsp_uart0_cfg = {
@@ -204,6 +209,10 @@ static struct pwm_dev os_bsp_pwm1;
static struct pwm_dev os_bsp_pwm2;
#endif
+#if MYNEWT_VAL(CHARGER)
+struct da1469x_charger_dev da1469x_charger_dev;
+#endif
+
static void
da1469x_periph_create_timers(void)
{
@@ -391,6 +400,49 @@ da1469x_periph_create_spi(void)
#endif
}
+#if MYNEWT_VAL(CHARGER)
+struct da1469x_charger_config cfg = {
+ .ctrl = 63U << CHARGER_CHARGER_CTRL_REG_EOC_INTERVAL_CHECK_THRES_Pos |
+ 1U << CHARGER_CHARGER_CTRL_REG_PRE_CHARGE_MODE_Pos |
+ 1U << CHARGER_CHARGER_CTRL_REG_CHARGE_LOOP_HOLD_Pos |
+ (MYNEWT_VAL(DA1469X_CHARGER_TBAT_MONITOR_MODE)) <<
+ CHARGER_CHARGER_CTRL_REG_TBAT_MONITOR_MODE_Pos |
+ 1U << CHARGER_CHARGER_CTRL_REG_CHARGE_TIMERS_HALT_ENABLE_Pos |
+ (MYNEWT_VAL(DA1469X_CHARGER_NTC_ENABLE)) <<
+ CHARGER_CHARGER_CTRL_REG_TBAT_PROT_ENABLE_Pos |
+ 1U << CHARGER_CHARGER_CTRL_REG_TDIE_PROT_ENABLE_Pos |
+ 1U << CHARGER_CHARGER_CTRL_REG_CHARGER_RESUME_Pos,
+ .ctrl_valid = 1,
+ .voltage_param =
+ DA1469X_ENCODE_V(MYNEWT_VAL(DA1469X_CHARGER_V_OVP)) <<
+ CHARGER_CHARGER_VOLTAGE_PARAM_REG_V_OVP_Pos |
+ DA1469X_ENCODE_V(MYNEWT_VAL(DA1469X_CHARGER_V_REPLENISH)) <<
+ CHARGER_CHARGER_VOLTAGE_PARAM_REG_V_REPLENISH_Pos |
+ DA1469X_ENCODE_V(MYNEWT_VAL(DA1469X_CHARGER_V_PRECHARGE)) <<
+ CHARGER_CHARGER_VOLTAGE_PARAM_REG_V_PRECHARGE_Pos |
+ DA1469X_ENCODE_V(MYNEWT_VAL(DA1469X_CHARGER_V_CHARGE)) <<
+ CHARGER_CHARGER_VOLTAGE_PARAM_REG_V_CHARGE_Pos,
+ .voltage_param_valid = 1,
+ .current_param =
+ DA1469X_ENCODE_PRECHG_I(MYNEWT_VAL(DA1469X_CHARGER_I_PRECHARGE)) |
+ DA1469X_ENCODE_CHG_I(MYNEWT_VAL(DA1469X_CHARGER_I_CHARGE)) |
+ DA1469X_ENCODE_EOC_I(MYNEWT_VAL(DA1469X_CHARGER_I_END_OF_CHARGE)),
+ .current_param_valid = 1,
+};
+#endif
+
+void
+da1469x_periph_create_charger(void)
+{
+#if MYNEWT_VAL(CHARGER)
+ int rc;
+
+ rc = da1469x_charger_create(&da1469x_charger_dev, "charger", &cfg);
+
+ assert(rc == 0);
+#endif
+}
+
void
da1469x_periph_create(void)
{
@@ -403,4 +455,5 @@ da1469x_periph_create(void)
da1469x_periph_create_uart();
da1469x_periph_create_i2c();
da1469x_periph_create_spi();
+ da1469x_periph_create_charger();
}
diff --git a/hw/mcu/dialog/da1469x/syscfg.yml b/hw/mcu/dialog/da1469x/syscfg.yml
index bce3120..22ce0c4 100644
--- a/hw/mcu/dialog/da1469x/syscfg.yml
+++ b/hw/mcu/dialog/da1469x/syscfg.yml
@@ -272,6 +272,10 @@ syscfg.defs:
restrictions:
- '!TIMER_2'
+ CHARGER:
+ description: 'Enable DA1469x charger'
+ value: 0
+
GPADC:
description: 'Enable DA1469x general purpose ADC'
value: 0
[mynewt-core] 01/03: hw/drivers/adc: Add battery reading channel
Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 712aea0f27d1bc5b0c7b5bb017e08bf39208f8e0
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Tue Apr 23 14:51:13 2019 +0200
hw/drivers/adc: Add battery reading channel
When application wants to use ADC (GP or SD) for battery
reading it may enable it with GPADC_BATTERY or SDADC_BATTERY
open device BATTERY_ADC_DEV_NAME and read value from ADC.
adc = (struct adc_dev *)da1469x_open_battery_adc(BATTERY_ADC_DEV_NAME, 1);
adc_read_channel(adc, BATTERY_ADC_CHANNEL, &bat_val);
os_dev_close(&adc->ad_dev);
---
.../include/gpadc_da1469x/gpadc_da1469x.h | 7 ++++++
hw/drivers/adc/gpadc_da1469x/src/gpadc_da1469x.c | 27 ++++++++++++++++++++++
.../include/sdadc_da1469x/sdadc_da1469x.h | 7 ++++++
hw/drivers/adc/sdadc_da1469x/src/sdadc_da1469x.c | 25 ++++++++++++++++++++
hw/mcu/dialog/da1469x/syscfg.yml | 12 ++++++++++
5 files changed, 78 insertions(+)
diff --git a/hw/drivers/adc/gpadc_da1469x/include/gpadc_da1469x/gpadc_da1469x.h b/hw/drivers/adc/gpadc_da1469x/include/gpadc_da1469x/gpadc_da1469x.h
index c8bf3e3..01b9b27 100644
--- a/hw/drivers/adc/gpadc_da1469x/include/gpadc_da1469x/gpadc_da1469x.h
+++ b/hw/drivers/adc/gpadc_da1469x/include/gpadc_da1469x/gpadc_da1469x.h
@@ -66,6 +66,13 @@ struct da1469x_gpadc_chan_cfg {
*/
int da1469x_gpadc_init(struct os_dev *, void *);
+#if MYNEWT_VAL(GPADC_BATTERY)
+
+#define BATTERY_ADC_DEV_NAME "gpadc"
+
+struct os_dev *da1469x_open_battery_adc(const char *dev_name, uint32_t wait);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/drivers/adc/gpadc_da1469x/src/gpadc_da1469x.c b/hw/drivers/adc/gpadc_da1469x/src/gpadc_da1469x.c
index 28b5031..0a7faea 100644
--- a/hw/drivers/adc/gpadc_da1469x/src/gpadc_da1469x.c
+++ b/hw/drivers/adc/gpadc_da1469x/src/gpadc_da1469x.c
@@ -662,3 +662,30 @@ da1469x_gpadc_init(struct os_dev *odev, void *arg)
return 0;
}
+
+#if MYNEWT_VAL(GPADC_BATTERY)
+
+static struct da1469x_gpadc_dev_cfg os_bsp_gpadc_battery_cfg = {
+ .dgdc_gpadc_ctrl = (1U << GPADC_GP_ADC_CTRL_REG_GP_ADC_SE_Pos) |
+ (8U << GPADC_GP_ADC_CTRL_REG_GP_ADC_SEL_Pos),
+ .dgdc_gpadc_ctrl2 = 0,
+ .dgdc_gpadc_ctrl3 = 0,
+ .dgdc_gpadc_set_offp = 0,
+ .dgdc_gpadc_set_offn = 0,
+ .dgdc_gpadc_offp = 0,
+ .dgdc_gpadc_offn = 0,
+};
+
+struct os_dev *
+da1469x_open_battery_adc(const char *dev_name, uint32_t wait)
+{
+ struct os_dev *adc = os_dev_open(dev_name, wait, &os_bsp_gpadc_battery_cfg);
+ if (adc) {
+ /* call adc_chan_config to setup correct multiplier so read returns
+ * value in mV */
+ adc_chan_config((struct adc_dev *)adc, 0, NULL);
+ }
+ return adc;
+}
+
+#endif
diff --git a/hw/drivers/adc/sdadc_da1469x/include/sdadc_da1469x/sdadc_da1469x.h b/hw/drivers/adc/sdadc_da1469x/include/sdadc_da1469x/sdadc_da1469x.h
index 81b8ce6..7244315 100644
--- a/hw/drivers/adc/sdadc_da1469x/include/sdadc_da1469x/sdadc_da1469x.h
+++ b/hw/drivers/adc/sdadc_da1469x/include/sdadc_da1469x/sdadc_da1469x.h
@@ -63,6 +63,13 @@ struct da1469x_sdadc_chan_cfg {
*/
int da1469x_sdadc_init(struct os_dev *, void *);
+#if MYNEWT_VAL(SDADC_BATTERY)
+
+#define BATTERY_ADC_DEV_NAME "sdadc"
+
+struct os_dev *da1469x_open_battery_adc(const char *dev_name, uint32_t wait);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/drivers/adc/sdadc_da1469x/src/sdadc_da1469x.c b/hw/drivers/adc/sdadc_da1469x/src/sdadc_da1469x.c
index dab155f..baef543 100644
--- a/hw/drivers/adc/sdadc_da1469x/src/sdadc_da1469x.c
+++ b/hw/drivers/adc/sdadc_da1469x/src/sdadc_da1469x.c
@@ -453,3 +453,28 @@ da1469x_sdadc_init(struct os_dev *odev, void *arg)
return 0;
}
+
+#if MYNEWT_VAL(SDADC_BATTERY)
+
+static struct da1469x_sdadc_dev_cfg os_bsp_adc_battery_cfg = {
+ .dsdc_sdadc_ctrl = (1U << SDADC_SDADC_CTRL_REG_SDADC_SE_Pos) |
+ (8U << SDADC_SDADC_CTRL_REG_SDADC_INP_SEL_Pos),
+ .dsdc_sdadc_gain_corr = 0,
+ .dsdc_sdadc_offs_corr = 0,
+ .dsdc_sdadc_set_gain_corr = 0,
+ .dsdc_sdadc_set_offs_corr = 0,
+};
+
+struct os_dev *
+da1469x_open_battery_adc(const char *dev_name, uint32_t wait)
+{
+ struct os_dev *adc = os_dev_open(dev_name, wait, &os_bsp_adc_battery_cfg);
+ if (adc) {
+ /* call adc_chan_config to setup correct multiplier so read returns
+ * value in mV */
+ adc_chan_config((struct adc_dev *)adc, 0, NULL);
+ }
+ return adc;
+}
+
+#endif
diff --git a/hw/mcu/dialog/da1469x/syscfg.yml b/hw/mcu/dialog/da1469x/syscfg.yml
index 58fc080..bce3120 100644
--- a/hw/mcu/dialog/da1469x/syscfg.yml
+++ b/hw/mcu/dialog/da1469x/syscfg.yml
@@ -286,6 +286,12 @@ syscfg.defs:
description: >
'DMA priority for GPADC, 0-7'
value: 0
+ GPADC_BATTERY:
+ description: >
+ Enable battery measurement on GPADC
+ value: 0
+ restrictions:
+ - '!SDADC_BATTERY'
SDADC:
description: Enable DA1469x sigma delta ADC
@@ -298,6 +304,12 @@ syscfg.defs:
description: >
'DMA priority for SDADC, 0-7'
value: 0
+ SDADC_BATTERY:
+ description: >
+ Enable battery measurement on SDADC
+ value: 0
+ restrictions:
+ - '!GPADC_BATTERY'
syscfg.restrictions:
- "QSPI_FLASH_ADDRESS_LENGTH==24"
[mynewt-core] 02/03: da1469x_charger: Add charger for DA1469x
Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 49a09e53045c7aa74c75d5bd8ccecccea602c493
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Thu Apr 25 16:08:38 2019 +0200
da1469x_charger: Add charger for DA1469x
This adds basic charger functionality.
Shell command is also added.
---
.../include/da1469x_charger/da1469x_charger.h | 269 +++++
hw/drivers/chg_ctrl/da1469x_charger/pkg.yml | 30 +
.../chg_ctrl/da1469x_charger/src/da1469x_charger.c | 508 +++++++++
.../da1469x_charger/src/da1469x_charger_shell.c | 1202 ++++++++++++++++++++
hw/drivers/chg_ctrl/da1469x_charger/syscfg.yml | 76 ++
5 files changed, 2085 insertions(+)
diff --git a/hw/drivers/chg_ctrl/da1469x_charger/include/da1469x_charger/da1469x_charger.h b/hw/drivers/chg_ctrl/da1469x_charger/include/da1469x_charger/da1469x_charger.h
new file mode 100644
index 0000000..7fbd8a2
--- /dev/null
+++ b/hw/drivers/chg_ctrl/da1469x_charger/include/da1469x_charger/da1469x_charger.h
@@ -0,0 +1,269 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _DA1469X_CHARGER_H
+#define _DA1469X_CHARGER_H
+
+#include <os/os.h>
+#include "os/os_dev.h"
+#include "syscfg/syscfg.h"
+#include "os/os_time.h"
+#if MYNEWT_VAL(DA1469X_CHARGER_USE_CHARGE_CONTROL)
+#include "charge-control/charge_control.h"
+#endif
+
+struct da1469x_charger_config {
+ uint32_t ctrl_valid:1;
+ uint32_t voltage_param_valid:1;
+ uint32_t current_param_valid:1;
+ uint32_t tempset_param_valid:1;
+ uint32_t pre_charge_timer_valid:1;
+ uint32_t cc_charge_timer_valid:1;
+ uint32_t cv_charge_timer_valid:1;
+ uint32_t total_charge_timer_valid:1;
+ uint32_t jeita_v_charge_valid:1;
+ uint32_t jeita_v_precharge_valid:1;
+ uint32_t jeita_v_replenish_valid:1;
+ uint32_t jeita_v_ovp_valid:1;
+ uint32_t jeita_current_valid:1;
+ uint32_t vbat_comp_timer_valid:1;
+ uint32_t vovp_comp_timer_valid:1;
+ uint32_t tdie_comp_timer_valid:1;
+ uint32_t tbat_mon_timer_valid:1;
+ uint32_t tbat_comp_timer_valid:1;
+ uint32_t thot_comp_timer_valid:1;
+ uint32_t pwr_up_timer_valid:1;
+
+ uint32_t ctrl;
+ uint32_t voltage_param;
+ uint32_t current_param;
+ uint32_t tempset_param;
+ uint16_t pre_charge_timer;
+ uint16_t cc_charge_timer;
+ uint16_t cv_charge_timer;
+ uint16_t total_charge_timer;
+ uint16_t jeita_v_charge;
+ uint16_t jeita_v_precharge;
+ uint16_t jeita_v_replenish;
+ uint16_t jeita_v_ovp;
+ uint32_t jeita_current;
+ uint16_t vbat_comp_timer;
+ uint16_t vovp_comp_timer;
+ uint16_t tdie_comp_timer;
+ uint16_t tbat_mon_timer;
+ uint16_t tbat_comp_timer;
+ uint16_t thot_comp_timer;
+ uint16_t pwr_up_timer;
+};
+
+struct da1469x_charger_dev {
+ struct os_dev dev;
+#if MYNEWT_VAL(DA1469X_CHARGER_USE_CHARGE_CONTROL)
+ struct charge_control chg_ctrl;
+#endif
+};
+
+#define DA1469X_ENCODE_V(v) \
+ (((v) < 3800) ? (((v) - 2800) / 50) : \
+ (((v) < 4600) ? ((v) - 3800) / 20 + 20 : \
+ ((v) - 4600) / 100 + 60))
+
+#define DA1469X_ENCODE_CHG_I(i) \
+ (uint16_t)(((i) < 85) ? ((i) / 5) - 1 : \
+ ((i) < 250 ? ((i) / 10) - 8 + 15 : \
+ ((i) / 20) - 12 + 31))
+
+#define DA1469X_ENCODE_PRECHG_I(i) \
+ ((uint16_t)((i) < 9 ? (i) * 2 - 1 : \
+ (i) < 25 ? (i) - 8 + 15 : \
+ (i) / 2 - 12 + 31) << \
+ CHARGER_CHARGER_CURRENT_PARAM_REG_I_PRECHARGE_Pos)
+
+#define DA1469X_ENCODE_EOC_I(i) \
+ ((uint16_t)((i) <= 10 ? ((i) - 4) * 2 / 3 : \
+ (i) < 18 ? 4 + ((i) - 10) / 2 : \
+ ((((i) - 12) / 4) + 8)) << \
+ CHARGER_CHARGER_CURRENT_PARAM_REG_I_END_OF_CHARGE_Pos)
+
+typedef enum {
+ DA1469X_CHARGER_STATE_POWER_UP,
+ DA1469X_CHARGER_STATE_INIT,
+ DA1469X_CHARGER_STATE_DISABLED,
+ DA1469X_CHARGER_STATE_PRE_CHARGE,
+ DA1469X_CHARGER_STATE_CC_CHARGE,
+ DA1469X_CHARGER_STATE_CV_CHARGE,
+ DA1469X_CHARGER_STATE_END_OF_CHARGE,
+ DA1469X_CHARGER_STATE_TDIE_PROT,
+ DA1469X_CHARGER_STATE_TBAT_PROT,
+ DA1469X_CHARGER_STATE_BYPASS,
+ DA1469X_CHARGER_STATE_ERROR,
+} da1469x_charger_state_t;
+
+typedef enum {
+ DA1469X_CHARGER_STATE_IRQ_NONE = 0x0000U,
+ DA1469X_CHARGER_STATE_IRQ_DISABLED_TO_PRECHARGE = 0x0001U,
+ DA1469X_CHARGER_STATE_IRQ_PRECHARGE_TO_CC = 0x0002U,
+ DA1469X_CHARGER_STATE_IRQ_CC_TO_CV = 0x0004U,
+ DA1469X_CHARGER_STATE_IRQ_CC_TO_EOC = 0x0008U,
+ DA1469X_CHARGER_STATE_IRQ_CV_TO_EOC = 0x0010U,
+ DA1469X_CHARGER_STATE_IRQ_EOC_TO_PRECHARGE = 0x0020U,
+ DA1469X_CHARGER_STATE_IRQ_TDIE_PROT_TO_PRECHARGE = 0x0040U,
+ DA1469X_CHARGER_STATE_IRQ_TBAT_PROT_TO_PRECHARGE = 0x0080U,
+ DA1469X_CHARGER_STATE_IRQ_TBAT_STATUS_UPDATE = 0x0100U,
+ DA1469X_CHARGER_STATE_IRQ_CV_TO_CC = 0x0200U,
+ DA1469X_CHARGER_STATE_IRQ_CC_TO_PRECHARGE = 0x0400U,
+ DA1469X_CHARGER_STATE_IRQ_CV_TO_PRECHARGE = 0x0800U,
+ DA1469X_CHARGER_STATE_IRQ_ALL = 0x0FFFU,
+} da1469x_charger_state_irq_t;
+
+typedef enum {
+ DA1469X_CHARGER_ERROR_IRQ_NONE = 0x00U,
+ DA1469X_CHARGER_ERROR_IRQ_PRECHARGE_TIMEOUT = 0x01U,
+ DA1469X_CHARGER_ERROR_IRQ_CC_CHARGE_TIMEOUT = 0x02U,
+ DA1469X_CHARGER_ERROR_IRQ_CV_CHARGE_TIMEOUT = 0x04U,
+ DA1469X_CHARGER_ERROR_IRQ_TOTAL_CHARGE_TIMEOUT = 0x08U,
+ DA1469X_CHARGER_ERROR_IRQ_VBAT_OVP_ERROR = 0x10U,
+ DA1469X_CHARGER_ERROR_IRQ_TDIE_ERROR = 0x20U,
+ DA1469X_CHARGER_ERROR_IRQ_TBAT_ERROR = 0x40U,
+ DA1469X_CHARGER_ERROR_IRQ_ALL = 0x7FU,
+} da1469x_charger_error_irq_t;
+
+/**
+* Set charge currents
+*
+* @param dev the charger device
+* @param ichg charge current (5-560) mA
+* @param iprechg pre-charge current (1-56) mA
+* @param ieoc end-of-charge (percent of charge current 4-40)
+*
+* @return 0 - on success, SYS_EINVAL for invalid parameters
+*/
+int da1469x_charger_set_charge_currents(struct da1469x_charger_dev *dev,
+ uint16_t ichg, uint16_t iprechg,
+ uint8_t ieoc);
+
+/**
+* Set charge voltages
+*
+* @note: All voltage levels must be in 2800-4900 mV range
+*
+* @param dev the charger device
+* @param vchrg charge voltage threshold
+* @param vprechg pre-charge voltage threshold
+* @param vreplenish recharge voltage threshold
+* @param ov over voltage protection limit
+*
+* @return 0 - on success, SYS_EINVAL for invalid parameters
+*/
+int da1469x_charger_set_charge_voltages(struct da1469x_charger_dev *dev,
+ uint16_t vchrg, uint16_t vprechg,
+ uint16_t vreplenish, uint16_t ov);
+
+
+/**
+* Set charger configuration
+*
+* @param dev charger device
+* @param config new configuration to set
+*
+* @return 0 - on success, SYS_EINVAL for invalid parameters
+*/
+int da1469x_charger_set_config(struct da1469x_charger_dev *dev,
+ const struct da1469x_charger_config *config);
+
+/**
+ * Set state change interrupt mask
+ *
+ * Interrupt will be trigger on each state change transition.
+ *
+ * @param dev charger device
+ * @param mask new bit mask of enabled state change interrupts
+ * value should be a bitmask from da1469x_charger_state_irq_t
+ *
+ * @return 0 - on success, SYS_EINVAL for invalid parameters
+ */
+int da1469x_charger_set_state_change_irq_mask(struct da1469x_charger_dev *dev,
+ uint16_t mask);
+
+/**
+ * Set error interrupt mask
+ *
+ * @param dev charger device
+ * @param mask new bit mask of enabled error interrupts
+ * value should be a bitmask from da1469x_charger_error_irq_t
+ *
+ * @return 0 - on success, SYS_EINVAL for invalid parameters
+ */
+int da1469x_charger_set_error_irq_mask(struct da1469x_charger_dev *dev,
+ uint16_t mask);
+
+static inline da1469x_charger_state_t
+da1469x_charger_get_state(struct da1469x_charger_dev *dev)
+{
+ return (da1469x_charger_state_t)((CHARGER->CHARGER_STATUS_REG &
+ CHARGER_CHARGER_STATUS_REG_CHARGER_STATE_Msk) >>
+ CHARGER_CHARGER_STATUS_REG_CHARGER_STATE_Pos);
+}
+
+/**
+ * Function called from os_dev_create
+ *
+ * @note: In normal case use wrapper function da1469x_charger_create()
+ *
+ * @param dev ad1469x_charger_dev to initialize
+ * @param arg da1469x_charger_config initial configuration
+ *
+ * @return 0 - on success, SYS_EINVAL for invalid parameters
+ */
+int da1469x_charger_init(struct os_dev *dev, void *arg);
+
+/**
+ *
+ * @param dev ad1469x_charger_dev to initialize
+ * @param name device name to create
+ * @param cfg da1469x_charger_config initial configuration
+ * @return
+ */
+int da1469x_charger_create(struct da1469x_charger_dev *dev, const char *name,
+ struct da1469x_charger_config *cfg);
+
+
+/**
+ * Function enable charging.
+ *
+ * @param dev ad1469x_charger_dev
+ *
+ * @return 0 - on success, non-zero on failure
+ */
+int da1469x_charger_charge_enable(struct da1469x_charger_dev *dev);
+
+/**
+ * Function disables charging.
+ *
+ * @param dev ad1469x_charger_dev
+ *
+ * @return 0 - on success, non-zero on failure
+ */
+int da1469x_charger_charge_disable(struct da1469x_charger_dev *dev);
+
+#if MYNEWT_VAL(DA1469X_CHARGER_CLI)
+int da1469x_charger_shell_init(struct da1469x_charger_dev *dev);
+#endif
+
+#endif /* _DA1469X_CHARGER_H */
diff --git a/hw/drivers/chg_ctrl/da1469x_charger/pkg.yml b/hw/drivers/chg_ctrl/da1469x_charger/pkg.yml
new file mode 100644
index 0000000..098bfad
--- /dev/null
+++ b/hw/drivers/chg_ctrl/da1469x_charger/pkg.yml
@@ -0,0 +1,30 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: hw/drivers/chg_ctrl/da1469x_charger
+pkg.description:
+pkg.keywords:
+ - Charge Controller
+ - DA1469x
+
+pkg.deps:
+ - "@apache-mynewt-core/kernel/os"
+ - "@apache-mynewt-core/hw/hal"
+pkg.deps.DA1469X_CHARGER_USE_CHARGE_CONTROL:
+ - '@apache-mynewt-core/hw/charge-control'
diff --git a/hw/drivers/chg_ctrl/da1469x_charger/src/da1469x_charger.c b/hw/drivers/chg_ctrl/da1469x_charger/src/da1469x_charger.c
new file mode 100644
index 0000000..3f17bd1
--- /dev/null
+++ b/hw/drivers/chg_ctrl/da1469x_charger/src/da1469x_charger.c
@@ -0,0 +1,508 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <os/mynewt.h>
+#include <da1469x_charger/da1469x_charger.h>
+#include <bsp/bsp.h>
+#if MYNEWT_VAL(DA1469X_CHARGER_USE_CHARGE_CONTROL)
+#include <charge-control/charge_control.h>
+#include <DA1469xAB.h>
+#endif
+
+int
+da1469x_charger_set_charge_currents(struct da1469x_charger_dev *dev,
+ uint16_t ichg, uint16_t iprechg, uint8_t ieoc)
+{
+ uint16_t current_param;
+
+ if (dev == NULL || ichg < 5 || ichg > 560 || iprechg < 1 || iprechg > 56 ||
+ ieoc < 6 || ieoc > 40) {
+ return SYS_EINVAL;
+ }
+
+ /* Charge current */
+ current_param = DA1469X_ENCODE_CHG_I(ichg);
+
+ /* Pre-charge current */
+ current_param |= DA1469X_ENCODE_PRECHG_I(iprechg);
+
+ /* End of charge current as % of charge current */
+ current_param |= DA1469X_ENCODE_EOC_I(ieoc);
+
+ CHARGER->CHARGER_CURRENT_PARAM_REG = current_param;
+
+ return 0;
+}
+
+static inline bool
+bad_v(uint16_t v)
+{
+ return v < 2800 || v > 4900;
+}
+
+static uint16_t
+encode_v(uint16_t v)
+{
+ return (uint16_t)DA1469X_ENCODE_V(v);
+}
+
+int
+da1469x_charger_set_charge_voltages(struct da1469x_charger_dev *dev,
+ uint16_t vchrg, uint16_t vprechg,
+ uint16_t vreplenish, uint16_t ov)
+{
+ uint16_t voltage_param;
+
+ if (dev == NULL || bad_v(vchrg) || bad_v(vprechg) || bad_v(vreplenish) ||
+ bad_v(ov)) {
+ return SYS_EINVAL;
+ }
+
+ voltage_param = encode_v(vchrg) |
+ (encode_v(vprechg) << CHARGER_CHARGER_VOLTAGE_PARAM_REG_V_PRECHARGE_Pos) |
+ (encode_v(vreplenish) << CHARGER_CHARGER_VOLTAGE_PARAM_REG_V_REPLENISH_Pos) |
+ (encode_v(ov) << CHARGER_CHARGER_VOLTAGE_PARAM_REG_V_OVP_Pos);
+
+ CHARGER->CHARGER_VOLTAGE_PARAM_REG = voltage_param;
+
+ return 0;
+}
+
+#define SET_IF_VALID(reg_name, field_name) \
+ if (config->field_name##_valid) { \
+ CHARGER->CHARGER_##reg_name##_REG = config->field_name; \
+ }
+
+int
+da1469x_charger_set_config(struct da1469x_charger_dev *dev,
+ const struct da1469x_charger_config *config)
+{
+ (void)dev;
+
+ SET_IF_VALID(CTRL, ctrl);
+ SET_IF_VALID(VOLTAGE_PARAM, voltage_param);
+ SET_IF_VALID(CURRENT_PARAM, current_param);
+ SET_IF_VALID(TEMPSET_PARAM, tempset_param);
+ SET_IF_VALID(PRE_CHARGE_TIMER, pre_charge_timer);
+ SET_IF_VALID(CC_CHARGE_TIMER, cc_charge_timer);
+ SET_IF_VALID(CV_CHARGE_TIMER, cv_charge_timer);
+ SET_IF_VALID(JEITA_V_CHARGE, jeita_v_charge);
+ SET_IF_VALID(JEITA_V_PRECHARGE, jeita_v_precharge);
+ SET_IF_VALID(JEITA_V_REPLENISH, jeita_v_replenish);
+ SET_IF_VALID(JEITA_V_OVP, jeita_v_ovp);
+ SET_IF_VALID(JEITA_CURRENT, jeita_current);
+ SET_IF_VALID(VBAT_COMP_TIMER, vbat_comp_timer);
+ SET_IF_VALID(VOVP_COMP_TIMER, vovp_comp_timer);
+ SET_IF_VALID(TDIE_COMP_TIMER, tdie_comp_timer);
+ SET_IF_VALID(TBAT_MON_TIMER, tbat_mon_timer);
+ SET_IF_VALID(TBAT_COMP_TIMER, tbat_comp_timer);
+ SET_IF_VALID(THOT_COMP_TIMER, thot_comp_timer);
+ SET_IF_VALID(PWR_UP_TIMER, pwr_up_timer);
+
+ return 0;
+}
+
+#if MYNEWT_VAL(DA1469X_CHARGER_USE_CHARGE_CONTROL)
+static void
+da1469x_vbus_state_changed_event_cb(struct os_event *ev)
+{
+ assert(ev);
+ NVIC_SetPendingIRQ(CHARGER_STATE_IRQn);
+}
+
+static struct os_event da1469x_vbus_state_changed_event = {
+ .ev_cb = da1469x_vbus_state_changed_event_cb,
+};
+
+static void
+da1469x_vbus_isr(void)
+{
+ CRG_TOP->VBUS_IRQ_CLEAR_REG = 1;
+ os_eventq_put(os_eventq_dflt_get(), &da1469x_vbus_state_changed_event);
+}
+
+void da1469x_usb_init(void)
+{
+ NVIC_SetVector(VBUS_IRQn, (uint32_t)da1469x_vbus_isr);
+ CRG_TOP->VBUS_IRQ_CLEAR_REG = 1;
+ NVIC_ClearPendingIRQ(VBUS_IRQn);
+ CRG_TOP->VBUS_IRQ_MASK_REG = CRG_TOP_VBUS_IRQ_MASK_REG_VBUS_IRQ_EN_FALL_Msk |
+ CRG_TOP_VBUS_IRQ_MASK_REG_VBUS_IRQ_EN_RISE_Msk;
+ NVIC_EnableIRQ(VBUS_IRQn);
+}
+
+static void
+da1469x_charger_state_changed_cb(struct os_event *ev)
+{
+ struct da1469x_charger_dev *dev;
+ uint32_t irq_state;
+
+ assert(ev);
+ dev = ev->ev_arg;
+
+ irq_state = CHARGER->CHARGER_STATE_IRQ_STATUS_REG;
+ CHARGER->CHARGER_STATE_IRQ_CLR_REG = irq_state;
+ /* Interrupt generated by charger triggers out of schedule read */
+ charge_control_read(&dev->chg_ctrl, CHARGE_CONTROL_TYPE_STATUS,
+ NULL, NULL, OS_TIMEOUT_NEVER);
+}
+
+static struct os_event da1469x_charger_state_changed_event = {
+ .ev_cb = da1469x_charger_state_changed_cb,
+};
+
+static void
+da1469x_charger_state_isr(void)
+{
+ os_eventq_put(os_eventq_dflt_get(), &da1469x_charger_state_changed_event);
+}
+
+static void
+da1469x_charger_error_cb(struct os_event *ev)
+{
+ struct da1469x_charger_dev *dev;
+ uint32_t irq_state;
+
+ assert(ev);
+ dev = ev->ev_arg;
+
+ irq_state = CHARGER->CHARGER_ERROR_IRQ_STATUS_REG;
+ CHARGER->CHARGER_ERROR_IRQ_CLR_REG = irq_state;
+
+ /* Interrupt generated by charger triggers out of schedule read */
+ charge_control_read(&dev->chg_ctrl, CHARGE_CONTROL_TYPE_FAULT,
+ NULL, NULL, OS_TIMEOUT_NEVER);
+}
+
+static struct os_event da1469x_charger_error_event = {
+ .ev_cb = da1469x_charger_error_cb,
+};
+
+static void
+da1469x_charger_error_isr(void)
+{
+ os_eventq_put(os_eventq_dflt_get(), &da1469x_charger_error_event);
+}
+#endif
+
+void
+da1469x_charger_clock_enable(struct da1469x_charger_dev *dev)
+{
+ (void)dev;
+
+ CRG_SYS->CLK_SYS_REG |= CRG_SYS_CLK_SYS_REG_CLK_CHG_EN_Msk;
+}
+
+void
+da1469x_charger_clock_disable(struct da1469x_charger_dev *dev)
+{
+ (void)dev;
+
+ CRG_SYS->CLK_SYS_REG &= ~CRG_SYS_CLK_SYS_REG_CLK_CHG_EN_Msk;
+}
+
+int
+da1469x_charger_charge_enable(struct da1469x_charger_dev *dev)
+{
+ const uint32_t mask = CHARGER_CHARGER_CTRL_REG_CHARGER_ENABLE_Msk |
+ CHARGER_CHARGER_CTRL_REG_CHARGE_START_Msk;
+ da1469x_charger_clock_enable(dev);
+ if ((CHARGER->CHARGER_CTRL_REG & mask) != mask) {
+ CHARGER->CHARGER_CTRL_REG |= mask;
+ }
+
+ return 0;
+}
+
+int
+da1469x_charger_charge_disable(struct da1469x_charger_dev *dev)
+{
+ const uint32_t mask = CHARGER_CHARGER_CTRL_REG_CHARGER_ENABLE_Msk |
+ CHARGER_CHARGER_CTRL_REG_CHARGE_START_Msk;
+ (void)dev;
+
+ if ((CHARGER->CHARGER_CTRL_REG & mask) != 0) {
+ CHARGER->CHARGER_CTRL_REG &= ~mask;
+ NVIC_SetPendingIRQ(CHARGER_STATE_IRQn);
+ }
+
+ return 0;
+}
+
+int
+da1469x_charger_set_state_change_irq_mask(struct da1469x_charger_dev *dev,
+ da1469x_charger_state_irq_t mask)
+{
+ (void)dev;
+
+ CHARGER->CHARGER_STATE_IRQ_MASK_REG = mask;
+
+ return 0;
+}
+
+int
+da1469x_charger_set_error_irq_mask(struct da1469x_charger_dev *dev,
+ uint16_t mask)
+{
+ (void)dev;
+
+ CHARGER->CHARGER_ERROR_IRQ_MASK_REG = mask;
+
+ return 0;
+}
+
+#if MYNEWT_VAL(DA1469X_CHARGER_USE_CHARGE_CONTROL)
+static int
+da1469x_charger_chg_ctrl_read(struct charge_control *cc, charge_control_type_t type,
+ charge_control_data_func_t data_func, void *data_arg, uint32_t timeout)
+{
+ const uint32_t mask = CHARGER_CHARGER_CTRL_REG_CHARGER_ENABLE_Msk |
+ CHARGER_CHARGER_CTRL_REG_CHARGE_START_Msk;
+ charge_control_status_t status = CHARGE_CONTROL_STATUS_DISABLED;
+ charge_control_fault_t fault = CHARGE_CONTROL_FAULT_NONE;
+ struct da1469x_charger_dev *dev = (struct da1469x_charger_dev *)cc->cc_dev;
+ (void)timeout;
+
+ if (type & CHARGE_CONTROL_TYPE_STATUS) {
+ if ((CHARGER->CHARGER_CTRL_REG & mask) != mask) {
+ status = CHARGE_CONTROL_STATUS_DISABLED;
+ } else if (!(CRG_TOP->ANA_STATUS_REG &
+ CRG_TOP_ANA_STATUS_REG_VBUS_AVAILABLE_Msk)) {
+ status = CHARGE_CONTROL_STATUS_NO_SOURCE;
+ } else {
+ switch (da1469x_charger_get_state(dev)) {
+ case DA1469X_CHARGER_STATE_POWER_UP:
+ case DA1469X_CHARGER_STATE_INIT:
+ case DA1469X_CHARGER_STATE_DISABLED:
+ status = CHARGE_CONTROL_STATUS_DISABLED;
+ break;
+ case DA1469X_CHARGER_STATE_CC_CHARGE:
+ case DA1469X_CHARGER_STATE_CV_CHARGE:
+ case DA1469X_CHARGER_STATE_PRE_CHARGE:
+ status = CHARGE_CONTROL_STATUS_CHARGING;
+ break;
+ case DA1469X_CHARGER_STATE_END_OF_CHARGE:
+ status = CHARGE_CONTROL_STATUS_CHARGE_COMPLETE;
+ break;
+ case DA1469X_CHARGER_STATE_TBAT_PROT:
+ case DA1469X_CHARGER_STATE_TDIE_PROT:
+ status = CHARGE_CONTROL_STATUS_SUSPEND;
+ break;
+ case DA1469X_CHARGER_STATE_ERROR:
+ status = CHARGE_CONTROL_STATUS_FAULT;
+ break;
+ default:
+ break;
+ }
+ }
+ if (data_func) {
+ data_func(cc, data_arg, &status, CHARGE_CONTROL_TYPE_STATUS);
+ }
+ }
+ if (type & CHARGE_CONTROL_TYPE_FAULT) {
+ if (CHARGER->CHARGER_STATUS_REG &
+ CHARGER_CHARGER_STATUS_REG_OVP_EVENTS_DEBOUNCE_CNT_Msk) {
+ fault |= CHARGE_CONTROL_FAULT_OV;
+ }
+ if (CHARGER->CHARGER_STATUS_REG &
+ (CHARGER_CHARGER_STATUS_REG_TBAT_HOT_COMP_OUT_Msk |
+ CHARGER_CHARGER_STATUS_REG_TDIE_COMP_OUT_Msk)) {
+ fault |= CHARGE_CONTROL_FAULT_THERM;
+ }
+ if (fault && data_func) {
+ data_func(cc, data_arg, &fault, CHARGE_CONTROL_TYPE_FAULT);
+ }
+ }
+
+ return 0;
+}
+
+static int
+da1469x_charger_chg_ctrl_get_config(struct charge_control *cc,
+ charge_control_type_t type,
+ struct charge_control_cfg *cfg)
+{
+ (void)cc;
+ (void)type;
+ (void)cfg;
+
+ return SYS_ENOTSUP;
+}
+
+static int
+da1469x_charger_chg_ctrl_set_config(struct charge_control *cc, void *cfg)
+{
+ (void)cc;
+ (void)cfg;
+
+ return SYS_ENOTSUP;
+}
+
+static int
+da1469x_charger_chg_ctrl_get_status(struct charge_control *cc, int *status)
+{
+ struct da1469x_charger_dev *dev = (struct da1469x_charger_dev *)cc->cc_dev;
+
+ *status = (int)da1469x_charger_get_state(dev);
+
+ return 0;
+}
+
+static int
+da1469x_charger_chg_ctrl_get_fault(struct charge_control *cc,
+ charge_control_fault_t *fault)
+{
+ *fault = CHARGE_CONTROL_FAULT_NONE;
+
+ switch (da1469x_charger_get_state((struct da1469x_charger_dev *)cc->cc_dev)) {
+ case DA1469X_CHARGER_STATE_TDIE_PROT:
+ case DA1469X_CHARGER_STATE_TBAT_PROT:
+ *fault |= CHARGE_CONTROL_FAULT_THERM;
+ break;
+ default:
+ break;
+ }
+
+ if (CHARGER->CHARGER_STATUS_REG &
+ CHARGER_CHARGER_STATUS_REG_VBAT_OVP_COMP_OUT_Msk) {
+ *fault |= CHARGE_CONTROL_FAULT_OV;
+ }
+
+ return 0;
+}
+
+static int
+da1469x_charger_chg_ctrl_enable(struct charge_control *cc)
+{
+ return da1469x_charger_charge_enable((struct da1469x_charger_dev *)cc->cc_dev);
+}
+
+static int
+da1469x_charger_chg_ctrl_disable(struct charge_control *cc)
+{
+ return da1469x_charger_charge_disable((struct da1469x_charger_dev *)cc->cc_dev);
+}
+
+/* Exports for the charge control API */
+static const struct charge_control_driver da1469x_charger_chg_ctrl_driver = {
+ .ccd_read = da1469x_charger_chg_ctrl_read,
+ .ccd_get_config = da1469x_charger_chg_ctrl_get_config,
+ .ccd_set_config = da1469x_charger_chg_ctrl_set_config,
+ .ccd_get_status = da1469x_charger_chg_ctrl_get_status,
+ .ccd_get_fault = da1469x_charger_chg_ctrl_get_fault,
+ .ccd_enable = da1469x_charger_chg_ctrl_enable,
+ .ccd_disable = da1469x_charger_chg_ctrl_disable,
+};
+#endif /* DA1469X_CHARGER_USE_CHARGE_CONTROL */
+
+int
+da1469x_charger_init(struct os_dev *dev, void *arg)
+{
+ struct da1469x_charger_dev *charger = (struct da1469x_charger_dev *)dev;
+#if MYNEWT_VAL(DA1469X_CHARGER_USE_CHARGE_CONTROL)
+ struct charge_control *cc;
+#endif
+ const struct da1469x_charger_config *cfg = arg;
+ int rc = 0;
+
+ if (!dev) {
+ rc = SYS_ENODEV;
+ goto err;
+ }
+
+ if (cfg) {
+ rc = da1469x_charger_set_config(charger, cfg);
+ if (rc) {
+ goto err;
+ }
+ }
+
+#if MYNEWT_VAL(DA1469X_CHARGER_USE_CHARGE_CONTROL)
+ cc = &charger->chg_ctrl;
+
+ rc = charge_control_init(cc, dev);
+ if (rc) {
+ goto err;
+ }
+
+ /* Add the driver with all the supported types */
+ rc = charge_control_set_driver(cc, CHARGE_CONTROL_TYPE_STATUS |
+ CHARGE_CONTROL_TYPE_FAULT,
+ (struct charge_control_driver *)&da1469x_charger_chg_ctrl_driver);
+ if (rc) {
+ goto err;
+ }
+
+ charge_control_set_type_mask(cc,
+ CHARGE_CONTROL_TYPE_STATUS |
+ CHARGE_CONTROL_TYPE_FAULT);
+
+ rc = charge_control_mgr_register(cc);
+ if (rc) {
+ goto err;
+ }
+
+ da1469x_charger_state_changed_event.ev_arg = charger;
+ da1469x_charger_error_event.ev_arg = charger;
+
+ da1469x_charger_set_error_irq_mask(charger, DA1469X_CHARGER_ERROR_IRQ_ALL);
+ da1469x_charger_set_state_change_irq_mask(charger,
+ DA1469X_CHARGER_STATE_IRQ_DISABLED_TO_PRECHARGE |
+ DA1469X_CHARGER_STATE_IRQ_CC_TO_EOC |
+ DA1469X_CHARGER_STATE_IRQ_CV_TO_EOC |
+ DA1469X_CHARGER_STATE_IRQ_EOC_TO_PRECHARGE |
+ DA1469X_CHARGER_STATE_IRQ_TDIE_PROT_TO_PRECHARGE |
+ DA1469X_CHARGER_STATE_IRQ_TBAT_PROT_TO_PRECHARGE |
+ DA1469X_CHARGER_STATE_IRQ_TBAT_STATUS_UPDATE);
+
+ NVIC_SetVector(CHARGER_STATE_IRQn, (uint32_t)da1469x_charger_state_isr);
+ NVIC_ClearPendingIRQ(CHARGER_STATE_IRQn);
+ NVIC_EnableIRQ(CHARGER_STATE_IRQn);
+
+ NVIC_SetVector(CHARGER_ERROR_IRQn, (uint32_t)da1469x_charger_error_isr);
+ NVIC_ClearPendingIRQ(CHARGER_ERROR_IRQn);
+ NVIC_EnableIRQ(CHARGER_ERROR_IRQn);
+
+ da1469x_usb_init();
+#endif /* DA1469X_CHARGER_USE_CHARGE_CONTROL */
+
+#if MYNEWT_VAL(DA1469X_CHARGER_CLI)
+ da1469x_charger_shell_init(charger);
+#endif
+
+err:
+ return rc;
+}
+
+int
+da1469x_charger_create(struct da1469x_charger_dev *dev, const char *name,
+ struct da1469x_charger_config *cfg)
+{
+ int rc;
+
+ rc = os_dev_create(&dev->dev, name,
+ OS_DEV_INIT_PRIMARY, OS_DEV_INIT_PRIO_DEFAULT,
+ da1469x_charger_init, cfg);
+
+ return rc;
+}
diff --git a/hw/drivers/chg_ctrl/da1469x_charger/src/da1469x_charger_shell.c b/hw/drivers/chg_ctrl/da1469x_charger/src/da1469x_charger_shell.c
new file mode 100644
index 0000000..272770d
--- /dev/null
+++ b/hw/drivers/chg_ctrl/da1469x_charger/src/da1469x_charger_shell.c
@@ -0,0 +1,1202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <os/mynewt.h>
+
+#if MYNEWT_VAL(DA1469X_CHARGER_CLI)
+
+#include <console/console.h>
+#include <shell/shell.h>
+#include <da1469x_charger/da1469x_charger.h>
+#include <parse/parse.h>
+#include <stdio.h>
+#include <DA1469xAB.h>
+#if MYNEWT_VAL(SDADC_BATTERY)
+#include <sdadc_da1469x/sdadc_da1469x.h>
+#endif
+#if MYNEWT_VAL(GPADC_BATTERY)
+#include <gpadc_da1469x/gpadc_da1469x.h>
+#endif
+
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+#define HELP(a) &(da1469x_charger_##a##_help)
+static const struct shell_cmd_help da1469x_charger_dump_help = {
+ .summary = "Displays charger related registers",
+#if MYNEWT_VAL(DA1469X_CHARGER_CLI_DECODE)
+ .usage = "dump [decode]",
+#else
+ .usage = NULL,
+#endif
+ .params = NULL,
+};
+
+#if MYNEWT_VAL(DA1469X_CHARGER_CLI_DECODE)
+static const struct shell_cmd_help da1469x_charger_decode_help = {
+ .summary = "Enables or disables decoding of registers",
+ .usage = "decode 1 | 0",
+ .params = NULL,
+};
+#endif
+
+static const struct shell_cmd_help da1469x_charger_enable_help = {
+ .summary = "Enables charging",
+ .usage = NULL,
+ .params = NULL,
+};
+
+static const struct shell_cmd_help da1469x_charger_disable_help = {
+ .summary = "Disables charging",
+ .usage = NULL,
+ .params = NULL,
+};
+
+static const struct shell_cmd_help da1469x_charger_status_help = {
+ .summary = "Shows status of charger and battery",
+ .usage = NULL,
+ .params = NULL,
+};
+
+static const struct shell_cmd_help da1469x_charger_clear_irq_help = {
+ .summary = "Clears interrupts",
+ .usage = NULL,
+ .params = NULL,
+};
+
+static const struct shell_cmd_help da1469x_charger_set_i_help = {
+ .summary = "Sets charging currents",
+ .usage = "seti <charge_current> [precharge_current [eoc percentage]]",
+ .params = NULL,
+};
+
+static const struct shell_cmd_help da1469x_charger_set_v_help = {
+ .summary = "Sets charging voltages",
+ .usage = "setv <charge_v> [<precharge_v> [<replenish_v> [ovp_v]]]",
+ .params = NULL,
+};
+
+#if MYNEWT_VAL(DA1469X_CHARGER_USE_CHARGE_CONTROL)
+static const struct shell_cmd_help da1469x_charger_listen_help = {
+ .summary = "Starts or stops charging state notifications",
+ .usage = "listen start | stop",
+ .params = NULL,
+};
+#endif
+
+static const struct shell_cmd_help da1469x_charger_reg_help = {
+ .summary = "Read or writes register",
+ .usage = "<reg_name> ",
+ .params = NULL,
+};
+
+#else
+#define HELP(a) NULL
+#endif
+
+/*
+ * Struct for field name description.
+ * Used for argument validation and field decoding
+ */
+struct reg_field {
+ /* Name of field */
+ const char *fld_name;
+ /* Position of field in register (LSB position) */
+ uint8_t fld_pos;
+ bool fld_show_bits;
+ /* Mask of bit field to set or extract */
+ uint32_t fld_mask;
+ /* Function that will convert register value to descriptive string */
+ const char *(*fld_decode_value)(const struct reg_field *field,
+ uint32_t reg_val, char *buf);
+ /* Argument that could be used by above function */
+ const void *fld_arg;
+};
+
+/**
+* Register structure
+*/
+struct reg {
+ /* Address of the register */
+ volatile uint32_t *addr;
+ /* Name of the register */
+ const char *name;
+ /* Array of bit fields */
+ const struct reg_field *fields;
+};
+
+static const char *const charger_state[] = {
+ "POWER_UP",
+ "INIT",
+ "DISABLED",
+ "PRE_CHARGE",
+ "CC_CHARGE",
+ "CV_CHARGE",
+ "END_OF_CHARGE",
+ "TDIE_PROT",
+ "TBAT_PROT",
+ "BYPASSED",
+ "ERROR",
+ NULL,
+};
+
+static const char *const tbat_status[] = {
+ "",
+ "COLD",
+ "COOL",
+ "",
+ "NORMAL",
+ "",
+ "",
+ "",
+ "WARM",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "HOT",
+ NULL,
+};
+
+#if MYNEWT_VAL(DA1469X_CHARGER_CLI_DECODE)
+
+bool da1469x_charger_cli_decode_fields;
+
+/* Change ix value to string from table.
+ * Table is NULL terminated. Access outside of range will result in
+ * returning ??? string
+ */
+static const char *
+val_decode_from_table(const char *const tab[], int ix)
+{
+ while (ix && tab[ix]) {
+ ix--;
+ tab++;
+ }
+ if (tab[0]) {
+ return tab[0];
+ } else {
+ return "???";
+ }
+}
+
+/* Decode bit field using table with mapped values */
+static const char *
+reg_decode_from_table(const struct reg_field *field,
+ uint32_t reg_val, char *buf)
+{
+ uint32_t val = (reg_val & field->fld_mask) >> field->fld_pos;
+ const char *const *table = field->fld_arg;
+
+ return strcpy(buf, val_decode_from_table(table, val));
+}
+
+#define FIELD_NUM(reg, field) { .fld_name = #field, .fld_pos = CHARGER_CHARGER_##reg##_REG_##field##_Pos, \
+ .fld_show_bits = 0, .fld_mask = CHARGER_CHARGER_##reg##_REG_##field##_Msk }
+#define FIELD_TAB(reg, field, tab) { .fld_name = #field, .fld_pos = CHARGER_CHARGER_##reg##_REG_##field##_Pos, \
+ .fld_show_bits = 1, .fld_mask = CHARGER_CHARGER_##reg##_REG_##field##_Msk, .fld_decode_value = reg_decode_from_table, .fld_arg = tab }
+#define FIELD_FUN(reg, field, fun, arg) { .fld_name = #field, .fld_pos = CHARGER_CHARGER_##reg##_REG_##field##_Pos, \
+ .fld_show_bits = 1, .fld_mask = CHARGER_CHARGER_##reg##_REG_##field##_Msk, .fld_decode_value = fun, .fld_arg = arg }
+
+/* Fields for CTRL register */
+static const struct reg_field CTRL_fields[] = {
+ FIELD_NUM(CTRL, EOC_INTERVAL_CHECK_TIMER),
+ FIELD_NUM(CTRL, EOC_INTERVAL_CHECK_THRES),
+ FIELD_NUM(CTRL, REPLENISH_MODE),
+ FIELD_NUM(CTRL, PRE_CHARGE_MODE),
+ FIELD_NUM(CTRL, CHARGE_LOOP_HOLD),
+ FIELD_NUM(CTRL, JEITA_SUPPORT_DISABLED),
+ FIELD_NUM(CTRL, TBAT_MONITOR_MODE),
+ FIELD_NUM(CTRL, CHARGE_TIMERS_HALT_ENABLE),
+ FIELD_NUM(CTRL, NTC_LOW_DISABLE),
+ FIELD_NUM(CTRL, TBAT_PROT_ENABLE),
+ FIELD_NUM(CTRL, TDIE_ERROR_RESUME),
+ FIELD_NUM(CTRL, TDIE_PROT_ENABLE),
+ FIELD_NUM(CTRL, CHARGER_RESUME),
+ FIELD_NUM(CTRL, CHARGER_BYPASS),
+ FIELD_NUM(CTRL, CHARGE_START),
+ FIELD_NUM(CTRL, CHARGER_ENABLE),
+ { NULL }
+};
+
+static const char *const charger_jeita_state[] = {
+ "CHECK_IDLE",
+ "CHECK_THOT",
+ "CHECK_TCOLD",
+ "CHECK_TWORM",
+ "CHECK_TCOOL",
+ "CHECK_TNORMAL",
+ "UPDATE_TBAT",
+ NULL,
+};
+
+/* Fields for STATUS register */
+static const struct reg_field STATUS_fields[] = {
+ FIELD_NUM(STATUS, OVP_EVENTS_DEBOUNCE_CNT),
+ FIELD_NUM(STATUS, EOC_EVENTS_DEBOUNCE_CNT),
+ FIELD_NUM(STATUS, TDIE_ERROR_DEBOUNCE_CNT),
+ FIELD_TAB(STATUS, CHARGER_JEITA_STATE, charger_jeita_state),
+ FIELD_TAB(STATUS, CHARGER_STATE, charger_state),
+ FIELD_TAB(STATUS, TBAT_STATUS, tbat_status),
+ FIELD_NUM(STATUS, MAIN_TBAT_COMP_OUT),
+ FIELD_NUM(STATUS, TBAT_HOT_COMP_OUT),
+ FIELD_NUM(STATUS, TDIE_COMP_OUT),
+ FIELD_NUM(STATUS, VBAT_OVP_COMP_OUT),
+ FIELD_NUM(STATUS, MAIN_VBAT_COMP_OUT),
+ FIELD_NUM(STATUS, END_OF_CHARGE),
+ FIELD_NUM(STATUS, CHARGER_CV_MODE),
+ FIELD_NUM(STATUS, CHARGER_CC_MODE),
+ FIELD_NUM(STATUS, CHARGER_IS_POWERED_UP),
+ { NULL }
+};
+
+static const char *
+voltage_decode(const struct reg_field *field, uint32_t reg_val, char *buf)
+{
+ uint32_t val = (reg_val & field->fld_mask) >> field->fld_pos;
+
+ if (val < 20) {
+ val = 280 + 5 * val;
+ } else if (val < 60) {
+ val = 380 + 2 * (val - 20);
+ } else {
+ val = 460 + 10 * (val - 60);
+ }
+ sprintf(buf, "%d.%02d V", (int)val / 100, (int)val % 100);
+ return buf;
+}
+
+/* Fields for VOLTAGE_PARAM register */
+static const struct reg_field VOLTAGE_PARAM_fields[] = {
+ FIELD_FUN(VOLTAGE_PARAM, V_OVP, voltage_decode, NULL),
+ FIELD_FUN(VOLTAGE_PARAM, V_REPLENISH, voltage_decode, NULL),
+ FIELD_FUN(VOLTAGE_PARAM, V_PRECHARGE, voltage_decode, NULL),
+ FIELD_FUN(VOLTAGE_PARAM, V_CHARGE, voltage_decode, NULL),
+ { NULL }
+};
+
+static const uint16_t i_eoc[][8] = {
+ { 40, 55, 70, 85, 100, 120, 140, 160},
+ { 88, 121, 154, 187, 220, 264, 308, 352},
+};
+
+static const char *
+current_eoc_decode(const struct reg_field *field, uint32_t reg_val, char *buf)
+{
+ int val;
+ size_t ix = (reg_val & field->fld_mask) >> field->fld_pos;
+ size_t mul = 0;
+
+ if (reg_val & CHARGER_CHARGER_CURRENT_PARAM_REG_I_EOC_DOUBLE_RANGE_Msk) {
+ mul = 1;
+ }
+ val = i_eoc[mul][ix];
+
+ sprintf(buf, "%d.%d %%", val / 10, val % 10);
+
+ return buf;
+}
+
+static const char *
+current_precharge(const struct reg_field *field, uint32_t reg_val, char *buf)
+{
+ int val = (int)((reg_val & field->fld_mask) >> field->fld_pos);
+
+ if (val < 15) {
+ val = 5 + 5 * val;
+ } else if (val < 32) {
+ val = 80 + 10 * (val - 15);
+ } else if (val < 47) {
+ val = 240 + 20 * (val - 31);
+ } else {
+ val = 560;
+ }
+ sprintf(buf, "%d.%d mA", val / 10, val % 10);
+
+ return buf;
+}
+
+static const char *
+current_charge(const struct reg_field *field, uint32_t reg_val, char *buf)
+{
+ int val = (int)((reg_val & field->fld_mask) >> field->fld_pos);
+
+ if (val < 15) {
+ val = 5 + 5 * val;
+ } else if (val < 32) {
+ val = 80 + 10 * (val - 15);
+ } else if (val < 47) {
+ val = 240 + 20 * (val - 31);
+ } else {
+ val = 560;
+ }
+ sprintf(buf, "%d mA", val);
+
+ return buf;
+}
+
+/* Fields for CURRENT_PARAM register */
+static const struct reg_field CURRENT_PARAM_fields[] = {
+ FIELD_NUM(CURRENT_PARAM, I_EOC_DOUBLE_RANGE),
+ FIELD_FUN(CURRENT_PARAM, I_END_OF_CHARGE, current_eoc_decode, NULL),
+ FIELD_FUN(CURRENT_PARAM, I_PRECHARGE, current_precharge, NULL),
+ FIELD_FUN(CURRENT_PARAM, I_CHARGE, current_charge, NULL),
+ { NULL }
+};
+
+static const char *const tdie_max[] = {
+ "0 C",
+ "50 C",
+ "80 C",
+ "90 C",
+ "100 C",
+ "110 C",
+ "120 C",
+ "130 C",
+ NULL,
+};
+
+static const char *
+tbat_temp(const struct reg_field *field, uint32_t reg_val, char *buf)
+{
+ int val = (int)((reg_val & field->fld_mask) >> field->fld_pos);
+
+ val -= 10;
+ sprintf(buf, "%d C", val);
+ return buf;
+}
+
+/* Fields for TEMPSET_PARAM register */
+static const struct reg_field TEMPSET_PARAM_fields[] = {
+ FIELD_TAB(TEMPSET_PARAM, TDIE_MAX, tdie_max),
+ FIELD_FUN(TEMPSET_PARAM, TBAT_HOT, tbat_temp, NULL),
+ FIELD_FUN(TEMPSET_PARAM, TBAT_WARM, tbat_temp, NULL),
+ FIELD_FUN(TEMPSET_PARAM, TBAT_COOL, tbat_temp, NULL),
+ FIELD_FUN(TEMPSET_PARAM, TBAT_COLD, tbat_temp, NULL),
+ { NULL }
+};
+
+/* Fields for PRE_CHARGE_TIMER register */
+static const struct reg_field PRE_CHARGE_TIMER_fields[] = {
+ FIELD_NUM(PRE_CHARGE_TIMER, PRE_CHARGE_TIMER),
+ FIELD_NUM(PRE_CHARGE_TIMER, MAX_PRE_CHARGE_TIME),
+ { NULL }
+};
+
+/* Fields for CC_CHARGE_TIMER register */
+static const struct reg_field CC_CHARGE_TIMER_fields[] = {
+ FIELD_NUM(CC_CHARGE_TIMER, CC_CHARGE_TIMER),
+ FIELD_NUM(CC_CHARGE_TIMER, MAX_CC_CHARGE_TIME),
+ { NULL }
+};
+
+/* Fields for CV_CHARGE_TIMER register */
+static const struct reg_field CV_CHARGE_TIMER_fields[] = {
+ FIELD_NUM(CV_CHARGE_TIMER, CV_CHARGE_TIMER),
+ FIELD_NUM(CV_CHARGE_TIMER, MAX_CV_CHARGE_TIME),
+ { NULL }
+};
+
+/* Fields for TOTAL_CHARGE_TIMER register */
+static const struct reg_field TOTAL_CHARGE_TIMER_fields[] = {
+ FIELD_NUM(TOTAL_CHARGE_TIMER, TOTAL_CHARGE_TIMER),
+ FIELD_NUM(TOTAL_CHARGE_TIMER, MAX_TOTAL_CHARGE_TIME),
+ { NULL }
+};
+
+/* Fields for JEITA_V_CHARGE register */
+static const struct reg_field JEITA_V_CHARGE_fields[] = {
+ FIELD_FUN(JEITA_V_CHARGE, V_CHARGE_TWARM, voltage_decode, NULL),
+ FIELD_FUN(JEITA_V_CHARGE, V_CHARGE_TCOOL, voltage_decode, NULL),
+ { NULL }
+};
+
+/* Fields for JEITA_V_PRECHARGE register */
+static const struct reg_field JEITA_V_PRECHARGE_fields[] = {
+ FIELD_FUN(JEITA_V_PRECHARGE, V_PRECHARGE_TWARM, voltage_decode, NULL),
+ FIELD_FUN(JEITA_V_PRECHARGE, V_PRECHARGE_TCOOL, voltage_decode, NULL),
+ { NULL }
+};
+
+/* Fields for JEITA_V_REPLENISH register */
+static const struct reg_field JEITA_V_REPLENISH_fields[] = {
+ FIELD_FUN(JEITA_V_REPLENISH, V_REPLENISH_TWARM, voltage_decode, NULL),
+ FIELD_FUN(JEITA_V_REPLENISH, V_REPLENISH_TCOOL, voltage_decode, NULL),
+ { NULL }
+};
+
+/* Fields for JEITA_V_OVP register */
+static const struct reg_field JEITA_V_OVP_fields[] = {
+ FIELD_FUN(JEITA_V_OVP, V_OVP_TWARM, voltage_decode, NULL),
+ FIELD_FUN(JEITA_V_OVP, V_OVP_TCOOL, voltage_decode, NULL),
+ { NULL }
+};
+
+/* Fields for JEITA_CURRENT register */
+static const struct reg_field JEITA_CURRENT_fields[] = {
+ FIELD_FUN(JEITA_CURRENT, I_PRECHARGE_TWARM, current_precharge, NULL),
+ FIELD_FUN(JEITA_CURRENT, I_PRECHARGE_TCOOL, current_precharge, NULL),
+ FIELD_FUN(JEITA_CURRENT, I_CHARGE_TWARM, current_charge, NULL),
+ FIELD_FUN(JEITA_CURRENT, I_CHARGE_TCOOL, current_charge, NULL),
+ { NULL }
+};
+
+/* Fields for VBAT_COMP_TIMER register */
+static const struct reg_field VBAT_COMP_TIMER_fields[] = {
+ FIELD_NUM(VBAT_COMP_TIMER, VBAT_COMP_TIMER),
+ FIELD_NUM(VBAT_COMP_TIMER, VBAT_COMP_SETTLING),
+ { NULL }
+};
+
+/* Fields for VOVP_COMP_TIMER register */
+static const struct reg_field VOVP_COMP_TIMER_fields[] = {
+ FIELD_NUM(VOVP_COMP_TIMER, OVP_INTERVAL_CHECK_TIMER),
+ FIELD_NUM(VOVP_COMP_TIMER, VBAT_OVP_COMP_TIMER),
+ FIELD_NUM(VOVP_COMP_TIMER, OVP_INTERVAL_CHECK_THRES),
+ FIELD_NUM(VOVP_COMP_TIMER, VBAT_OVP_COMP_SETTLING),
+ { NULL }
+};
+
+/* Fields for TDIE_COMP_TIMER register */
+static const struct reg_field TDIE_COMP_TIMER_fields[] = {
+ FIELD_NUM(TDIE_COMP_TIMER, TDIE_COMP_TIMER),
+ FIELD_NUM(TDIE_COMP_TIMER, TDIE_COMP_SETTLING),
+ { NULL }
+};
+
+/* Fields for TBAT_MON_TIMER register */
+static const struct reg_field TBAT_MON_TIMER_fields[] = {
+ FIELD_NUM(TBAT_MON_TIMER, TBAT_MON_TIMER),
+ FIELD_NUM(TBAT_MON_TIMER, TBAT_MON_INTERVAL),
+ { NULL }
+};
+
+/* Fields for TBAT_COMP_TIMER register */
+static const struct reg_field TBAT_COMP_TIMER_fields[] = {
+ FIELD_NUM(TBAT_COMP_TIMER, TBAT_COMP_TIMER),
+ FIELD_NUM(TBAT_COMP_TIMER, TBAT_COMP_SETTLING),
+ { NULL }
+};
+
+/* Fields for THOT_COMP_TIMER register */
+static const struct reg_field THOT_COMP_TIMER_fields[] = {
+ FIELD_NUM(THOT_COMP_TIMER, THOT_COMP_TIMER),
+ FIELD_NUM(THOT_COMP_TIMER, THOT_COMP_SETTLING),
+ { NULL }
+};
+
+/* Fields for PWR_UP_TIMER register */
+static const struct reg_field PWR_UP_TIMER_fields[] = {
+ FIELD_NUM(PWR_UP_TIMER, CHARGER_PWR_UP_TIMER),
+ FIELD_NUM(PWR_UP_TIMER, CHARGER_PWR_UP_SETTLING),
+ { NULL }
+};
+
+/* Fields for STATE_IRQ_MASK register */
+static const struct reg_field STATE_IRQ_MASK_fields[] = {
+ FIELD_NUM(STATE_IRQ_MASK, CV_TO_PRECHARGE_IRQ_EN),
+ FIELD_NUM(STATE_IRQ_MASK, CC_TO_PRECHARGE_IRQ_EN),
+ FIELD_NUM(STATE_IRQ_MASK, CV_TO_CC_IRQ_EN),
+ FIELD_NUM(STATE_IRQ_MASK, TBAT_STATUS_UPDATE_IRQ_EN),
+ FIELD_NUM(STATE_IRQ_MASK, TBAT_PROT_TO_PRECHARGE_IRQ_EN),
+ FIELD_NUM(STATE_IRQ_MASK, TDIE_PROT_TO_PRECHARGE_IRQ_EN),
+ FIELD_NUM(STATE_IRQ_MASK, EOC_TO_PRECHARGE_IRQ_EN),
+ FIELD_NUM(STATE_IRQ_MASK, CV_TO_EOC_IRQ_EN),
+ FIELD_NUM(STATE_IRQ_MASK, CC_TO_EOC_IRQ_EN),
+ FIELD_NUM(STATE_IRQ_MASK, CC_TO_CV_IRQ_EN),
+ FIELD_NUM(STATE_IRQ_MASK, PRECHARGE_TO_CC_IRQ_EN),
+ FIELD_NUM(STATE_IRQ_MASK, DISABLED_TO_PRECHARGE_IRQ_EN),
+ { NULL }
+};
+
+/* Fields for ERROR_IRQ_MASK register */
+static const struct reg_field ERROR_IRQ_MASK_fields[] = {
+ FIELD_NUM(ERROR_IRQ_MASK, TBAT_ERROR_IRQ_EN),
+ FIELD_NUM(ERROR_IRQ_MASK, TDIE_ERROR_IRQ_EN),
+ FIELD_NUM(ERROR_IRQ_MASK, VBAT_OVP_ERROR_IRQ_EN),
+ FIELD_NUM(ERROR_IRQ_MASK, TOTAL_CHARGE_TIMEOUT_IRQ_EN),
+ FIELD_NUM(ERROR_IRQ_MASK, CV_CHARGE_TIMEOUT_IRQ_EN),
+ FIELD_NUM(ERROR_IRQ_MASK, CC_CHARGE_TIMEOUT_IRQ_EN),
+ FIELD_NUM(ERROR_IRQ_MASK, PRECHARGE_TIMEOUT_IRQ_EN),
+ { NULL }
+};
+
+/* Fields for STATE_IRQ_STATUS register */
+static const struct reg_field STATE_IRQ_STATUS_fields[] = {
+ FIELD_NUM(STATE_IRQ_STATUS, CV_TO_PRECHARGE_IRQ),
+ FIELD_NUM(STATE_IRQ_STATUS, CC_TO_PRECHARGE_IRQ),
+ FIELD_NUM(STATE_IRQ_STATUS, CV_TO_CC_IRQ),
+ FIELD_NUM(STATE_IRQ_STATUS, TBAT_STATUS_UPDATE_IRQ),
+ FIELD_NUM(STATE_IRQ_STATUS, TBAT_PROT_TO_PRECHARGE_IRQ),
+ FIELD_NUM(STATE_IRQ_STATUS, TDIE_PROT_TO_PRECHARGE_IRQ),
+ FIELD_NUM(STATE_IRQ_STATUS, EOC_TO_PRECHARGE_IRQ),
+ FIELD_NUM(STATE_IRQ_STATUS, CV_TO_EOC_IRQ),
+ FIELD_NUM(STATE_IRQ_STATUS, CC_TO_EOC_IRQ),
+ FIELD_NUM(STATE_IRQ_STATUS, CC_TO_CV_IRQ),
+ FIELD_NUM(STATE_IRQ_STATUS, PRECHARGE_TO_CC_IRQ),
+ FIELD_NUM(STATE_IRQ_STATUS, DISABLED_TO_PRECHARGE_IRQ),
+ { NULL }
+};
+
+/* Fields for ERROR_IRQ_STATUS register */
+static const struct reg_field ERROR_IRQ_STATUS_fields[] = {
+ FIELD_NUM(ERROR_IRQ_STATUS, TBAT_ERROR_IRQ),
+ FIELD_NUM(ERROR_IRQ_STATUS, TDIE_ERROR_IRQ),
+ FIELD_NUM(ERROR_IRQ_STATUS, VBAT_OVP_ERROR_IRQ),
+ FIELD_NUM(ERROR_IRQ_STATUS, TOTAL_CHARGE_TIMEOUT_IRQ),
+ FIELD_NUM(ERROR_IRQ_STATUS, CV_CHARGE_TIMEOUT_IRQ),
+ FIELD_NUM(ERROR_IRQ_STATUS, CC_CHARGE_TIMEOUT_IRQ),
+ FIELD_NUM(ERROR_IRQ_STATUS, PRECHARGE_TIMEOUT_IRQ),
+ { NULL }
+};
+
+/* Fields for STATE_IRQ_CLR register */
+static const struct reg_field STATE_IRQ_CLR_fields[] = {
+ FIELD_NUM(STATE_IRQ_CLR, CV_TO_PRECHARGE_IRQ_CLR),
+ FIELD_NUM(STATE_IRQ_CLR, CC_TO_PRECHARGE_IRQ_CLR),
+ FIELD_NUM(STATE_IRQ_CLR, CV_TO_CC_IRQ_CLR),
+ FIELD_NUM(STATE_IRQ_CLR, TBAT_STATUS_UPDATE_IRQ_CLR),
+ FIELD_NUM(STATE_IRQ_CLR, TBAT_PROT_TO_PRECHARGE_IRQ_CLR),
+ FIELD_NUM(STATE_IRQ_CLR, TDIE_PROT_TO_PRECHARGE_IRQ_CLR),
+ FIELD_NUM(STATE_IRQ_CLR, EOC_TO_PRECHARGE_IRQ_CLR),
+ FIELD_NUM(STATE_IRQ_CLR, CV_TO_EOC_IRQ_CLR),
+ FIELD_NUM(STATE_IRQ_CLR, CC_TO_EOC_IRQ_CLR),
+ FIELD_NUM(STATE_IRQ_CLR, CC_TO_CV_IRQ_CLR),
+ FIELD_NUM(STATE_IRQ_CLR, PRECHARGE_TO_CC_IRQ_CLR),
+ FIELD_NUM(STATE_IRQ_CLR, DISABLED_TO_PRECHARGE_IRQ_CLR),
+ { NULL }
+};
+
+/* Fields for ERROR_IRQ_CLR register */
+static const struct reg_field ERROR_IRQ_CLR_fields[] = {
+ FIELD_NUM(ERROR_IRQ_CLR, TBAT_ERROR_IRQ_CLR),
+ FIELD_NUM(ERROR_IRQ_CLR, TDIE_ERROR_IRQ_CLR),
+ FIELD_NUM(ERROR_IRQ_CLR, VBAT_OVP_ERROR_IRQ_CLR),
+ FIELD_NUM(ERROR_IRQ_CLR, TOTAL_CHARGE_TIMEOUT_IRQ_CLR),
+ FIELD_NUM(ERROR_IRQ_CLR, CV_CHARGE_TIMEOUT_IRQ_CLR),
+ FIELD_NUM(ERROR_IRQ_CLR, CC_CHARGE_TIMEOUT_IRQ_CLR),
+ FIELD_NUM(ERROR_IRQ_CLR, PRECHARGE_TIMEOUT_IRQ_CLR),
+ { NULL }
+};
+
+#define REG(reg_name) { .addr = &CHARGER->CHARGER_##reg_name##_REG, .name = "CHARGER_"#reg_name"_REG", .fields = reg_name##_fields }
+
+#else
+#define da1469x_charger_cli_decode_fields false
+
+#define REG(reg_name) { .addr = &CHARGER->CHARGER_##reg_name##_REG, .name = "CHARGER_"#reg_name"_REG", .fields = NULL }
+#endif
+
+#define REG_NAME(short_name) "CHARGER_"#short_name"_REG"
+
+static const struct reg charger_regs[] = {
+ REG(CTRL),
+ REG(STATUS),
+ REG(VOLTAGE_PARAM),
+ REG(CURRENT_PARAM),
+ REG(TEMPSET_PARAM),
+ REG(PRE_CHARGE_TIMER),
+ REG(CC_CHARGE_TIMER),
+ REG(CV_CHARGE_TIMER),
+ REG(TOTAL_CHARGE_TIMER),
+ REG(JEITA_V_CHARGE),
+ REG(JEITA_V_PRECHARGE),
+ REG(JEITA_V_REPLENISH),
+ REG(JEITA_V_OVP),
+ REG(JEITA_CURRENT),
+ REG(VBAT_COMP_TIMER),
+ REG(VOVP_COMP_TIMER),
+ REG(TDIE_COMP_TIMER),
+ REG(TBAT_MON_TIMER),
+ REG(TBAT_COMP_TIMER),
+ REG(THOT_COMP_TIMER),
+ REG(PWR_UP_TIMER),
+ REG(STATE_IRQ_MASK),
+ REG(ERROR_IRQ_MASK),
+ REG(STATE_IRQ_STATUS),
+ REG(ERROR_IRQ_STATUS),
+ REG(STATE_IRQ_CLR),
+ REG(ERROR_IRQ_CLR),
+};
+#define NUM_CHARGER_REGS ARRAY_SIZE(charger_regs)
+
+static const struct shell_cmd da1469x_charger_shell_cmd_struct;
+
+static int
+da1469x_charger_help(void)
+{
+ console_printf("%s cmd\n", da1469x_charger_shell_cmd_struct.sc_cmd);
+ console_printf("cmd:\n");
+ console_printf("\thelp\n");
+#if MYNEWT_VAL(DA1469X_CHARGER_CLI_DECODE)
+ console_printf("\tdump [decode]\n");
+#else
+ console_printf("\tdump\n");
+#endif
+ console_printf("\tread <reg_name>\n");
+ console_printf("\twrite <reg_anme> <value>\n");
+ console_printf("\tdisable\n");
+ console_printf("\tenable\n");
+ console_printf("\tstatus\n");
+ console_printf("\tseti <charge_i> [<precharge_i> [<eoc_percent>]]\n");
+ console_printf("\tsetv <charge_v> [<precharge_v> [<replenish_v> [<ovp_v>]]]\n");
+#if MYNEWT_VAL(DA1469X_CHARGER_USE_CHARGE_CONTROL)
+ console_printf("\tlisten start | stop\n");
+#endif
+ return 0;
+}
+
+static int
+da1469x_charger_shell_err_too_many_args(const char *cmd_name)
+{
+ console_printf("Error: too many arguments for command \"%s\"\n",
+ cmd_name);
+
+ return SYS_EINVAL;
+}
+
+static int
+da1469x_charger_shell_err_unknown_arg(const char *cmd_name)
+{
+ console_printf("Error: unknown argument \"%s\"\n",
+ cmd_name);
+
+ return SYS_EINVAL;
+}
+
+#if MYNEWT_VAL(DA1469X_CHARGER_CLI_DECODE)
+
+static const char *
+field_bin_value(const struct reg_field *field, uint32_t val, char *buf)
+{
+ uint32_t mask = field->fld_mask >> field->fld_pos;
+ int bits = 0;
+ val = (val & field->fld_mask) >> field->fld_pos;
+
+ for (bits = 0; mask; bits++) {
+ mask >>= 1;
+ }
+ mask = field->fld_mask >> field->fld_pos;
+ buf[bits] = '\0';
+ while (mask) {
+ buf[--bits] = (char)('0' + (val & 1));
+ mask >>= 1;
+ val >>= 1;
+ }
+
+ return buf;
+}
+
+static int
+field_int_value(const struct reg_field *field, uint32_t val)
+{
+ return (int)((val & field->fld_mask) >> field->fld_pos);
+}
+
+static int
+da1469x_charger_shell_cmd_decode(int argc, char **argv)
+{
+ long long val;
+ int status;
+
+ if (argc == 2) {
+ val = parse_ll_bounds(argv[1], 0, 1, &status);
+ if (status == 0) {
+ da1469x_charger_cli_decode_fields = val != 0;
+ }
+ }
+ console_printf("decode %d\n", (int)da1469x_charger_cli_decode_fields);
+
+ return 0;
+}
+
+#endif /* MYNEWT_VAL(DA1469X_CHARGER_CLI_DECODE) */
+
+static void
+da1469x_charger_dump_register(const struct reg *reg, uint32_t val, bool decode)
+{
+#if MYNEWT_VAL(DA1469X_CHARGER_CLI_DECODE)
+ const struct reg_field *field;
+ char binary[33];
+ char buf[50];
+#endif
+ console_printf("%-30s = 0x%08x \n", reg->name, (int)val);
+#if MYNEWT_VAL(DA1469X_CHARGER_CLI_DECODE)
+ if (decode && reg->fields) {
+ for (field = reg->fields; field->fld_name; ++field) {
+ if (field->fld_decode_value) {
+ field->fld_decode_value(field, val, buf);
+ if (field->fld_show_bits) {
+ console_printf("%32s = %s %s\n", field->fld_name,
+ field_bin_value(field, val, binary), buf);
+ } else {
+ console_printf("%32s = %s\n", field->fld_name, buf);
+ }
+ } else {
+ if (field->fld_show_bits) {
+ console_printf("%32s = %s\n", field->fld_name,
+ field_bin_value(field, val, binary));
+ } else {
+ console_printf("%32s = %d\n", field->fld_name,
+ field_int_value(field, val));
+ }
+ }
+ }
+ }
+#endif
+}
+
+static int
+da1469x_charger_shell_cmd_dump(int argc, char **argv)
+{
+ int i;
+ uint32_t val;
+ const struct reg *reg;
+ bool decode = da1469x_charger_cli_decode_fields;
+
+#if MYNEWT_VAL(DA1469X_CHARGER_CLI_DECODE)
+ if (argc > 2) {
+ return da1469x_charger_shell_err_too_many_args(argv[1]);
+ } else if (argc == 2) {
+ if (strcmp(argv[1], "decode") == 0) {
+ decode = true;
+ } else if (strcmp(argv[1], "nodecode") == 0) {
+ decode = false;
+ } else {
+ return da1469x_charger_shell_err_unknown_arg(argv[1]);
+ }
+ }
+#else
+ if (argc > 2) {
+ return da1469x_charger_shell_err_too_many_args(argv[1]);
+ return 0;
+ }
+#endif
+
+ console_printf("========== Charger Regs ==========\n");
+ console_printf("==================================\n\n");
+ for (i = 0; i < NUM_CHARGER_REGS; ++i) {
+ reg = &charger_regs[i];
+ val = *reg->addr;
+ da1469x_charger_dump_register(reg, val, decode);
+ }
+
+ return 0;
+}
+
+static int
+da1469x_charger_shell_cmd_enable(int argc, char **argv)
+{
+ struct da1469x_charger_dev *dev =
+ (struct da1469x_charger_dev *)os_dev_open("charger", 0, NULL);
+ (void)argc;
+ (void)argv;
+
+ if (dev) {
+ da1469x_charger_charge_enable(dev);
+ os_dev_close(&dev->dev);
+ }
+ return 0;
+}
+
+static int
+da1469x_charger_shell_cmd_disable(int argc, char **argv)
+{
+ struct da1469x_charger_dev *dev =
+ (struct da1469x_charger_dev *)os_dev_open("charger", 0, NULL);
+ (void)argc;
+ (void)argv;
+
+ if (dev) {
+ da1469x_charger_charge_disable(dev);
+ os_dev_close(&dev->dev);
+ }
+ return 0;
+}
+
+static int
+da1469x_charger_shell_cmd_status(int argc, char **argv)
+{
+#if MYNEWT_VAL(SDADC_BATTERY) || MYNEWT_VAL(GPADC_BATTERY)
+ struct adc_dev *adc;
+ int bat_val;
+#endif
+ uint32_t val = CHARGER->CHARGER_STATUS_REG;
+ uint32_t state = (val & CHARGER_CHARGER_STATUS_REG_CHARGER_STATE_Msk) >>
+ CHARGER_CHARGER_STATUS_REG_CHARGER_STATE_Pos;
+ uint32_t bat_state = (val & CHARGER_CHARGER_STATUS_REG_TBAT_STATUS_Msk) >>
+ CHARGER_CHARGER_STATUS_REG_TBAT_STATUS_Pos;
+ bool vbus_ok = (CRG_TOP->ANA_STATUS_REG & CRG_TOP_ANA_STATUS_REG_VBUS_AVAILABLE_Msk) != 0;
+ const uint32_t mask = CHARGER_CHARGER_CTRL_REG_CHARGER_ENABLE_Msk |
+ CHARGER_CHARGER_CTRL_REG_CHARGE_START_Msk;
+
+ (void)argc;
+ (void)argv;
+ if ((CHARGER->CHARGER_CTRL_REG & mask) != mask) {
+ console_printf("status = disabled\n");
+ } else if (!vbus_ok) {
+ console_printf("status = enabled (not connected)\n");
+ } else {
+ console_printf("status = %s\n", charger_state[state]);
+ }
+ console_printf(" vbus = %s\n", vbus_ok ? "OK" : "NOK");
+ console_printf(" tbat = %s\n", tbat_status[bat_state]);
+#if MYNEWT_VAL(SDADC_BATTERY) || MYNEWT_VAL(GPADC_BATTERY)
+ adc = (struct adc_dev *)da1469x_open_battery_adc(BATTERY_ADC_DEV_NAME, 1);
+ if (adc) {
+ adc_read_channel(adc, 0, &bat_val);
+ os_dev_close(&adc->ad_dev);
+ console_printf(" vbat = %d mV\n", adc_result_mv(adc, 0, bat_val));
+ }
+#endif
+
+ return 0;
+}
+
+static int
+da1469x_charger_shell_cmd_clear_irq(int argc, char **argv)
+{
+ if (argc == 1) {
+ CHARGER->CHARGER_STATE_IRQ_CLR_REG = 0xFFFFFFFF;
+ CHARGER->CHARGER_ERROR_IRQ_CLR_REG = 0xFFFFFFFF;
+ } else if (0 == strcmp(argv[1], "state")) {
+ CHARGER->CHARGER_STATE_IRQ_CLR_REG = 0xFFFFFFFF;
+ } else if (0 == strcmp(argv[1], "error")) {
+ CHARGER->CHARGER_ERROR_IRQ_CLR_REG = 0xFFFFFFFF;
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+static int
+da1469x_charger_shell_cmd_set_i(int argc, char **argv)
+{
+ int rc;
+ uint32_t val = CHARGER->CHARGER_CURRENT_PARAM_REG;
+ uint32_t i_charge;
+ uint32_t i_precharge;
+ uint32_t i_eoc;
+
+ if (argc > 1) {
+ i_charge = (uint32_t)parse_ll_bounds(argv[1], 5, 560, &rc);
+ if (rc) {
+ console_printf("I_CHARGE should be in range 5-560\n");
+ return 0;
+ }
+ val &= ~CHARGER_CHARGER_CURRENT_PARAM_REG_I_CHARGE_Msk;
+ val |= DA1469X_ENCODE_CHG_I(i_charge);
+ }
+ if (argc > 2) {
+ i_precharge = (uint32_t)parse_ll_bounds(argv[2], 1, 56, &rc);
+ if (rc) {
+ console_printf("I_PRECHARGE should be in range 1-56\n");
+ return 0;
+ }
+ val &= ~CHARGER_CHARGER_CURRENT_PARAM_REG_I_PRECHARGE_Msk;
+ val |= DA1469X_ENCODE_PRECHG_I(i_precharge);
+ }
+ if (argc > 3) {
+ i_eoc = (uint32_t)parse_ll_bounds(argv[3], 4, 35, &rc);
+ if (rc) {
+ console_printf("I_EOC should be in range 4-35\n");
+ return 0;
+ }
+ val &= ~(CHARGER_CHARGER_CURRENT_PARAM_REG_I_END_OF_CHARGE_Msk |
+ CHARGER_CHARGER_CURRENT_PARAM_REG_I_EOC_DOUBLE_RANGE_Msk);
+ val |= DA1469X_ENCODE_EOC_I(i_eoc);
+ }
+ CHARGER->CHARGER_CURRENT_PARAM_REG = val;
+
+ return 0;
+}
+
+static int
+da1469x_charger_shell_cmd_set_v(int argc, char **argv)
+{
+ int rc;
+ uint32_t val = CHARGER->CHARGER_VOLTAGE_PARAM_REG;
+ uint32_t v;
+
+ if (argc > 1 && strcmp("-", argv[1]) != 0) {
+ v = (uint32_t)parse_ll_bounds(argv[1], 2800, 4900, &rc);
+ if (rc) {
+ console_printf("V_CHARGE should be in range 2800-4900\n");
+ return 0;
+ }
+ val &= ~CHARGER_CHARGER_VOLTAGE_PARAM_REG_V_CHARGE_Msk;
+ val |= DA1469X_ENCODE_V(v) << CHARGER_CHARGER_VOLTAGE_PARAM_REG_V_CHARGE_Pos;
+ }
+ if (argc > 2 && strcmp("-", argv[2]) != 0) {
+ v = (uint32_t)parse_ll_bounds(argv[2], 2800, 4900, &rc);
+ if (rc) {
+ console_printf("V_PRECHARGE should be in range 2800-4900\n");
+ return 0;
+ }
+ val &= ~CHARGER_CHARGER_VOLTAGE_PARAM_REG_V_PRECHARGE_Msk;
+ val |= DA1469X_ENCODE_V(v) << CHARGER_CHARGER_VOLTAGE_PARAM_REG_V_PRECHARGE_Pos;
+ }
+ if (argc > 3 && strcmp("-", argv[3]) != 0) {
+ v = (uint32_t)parse_ll_bounds(argv[3], 2800, 4900, &rc);
+ if (rc) {
+ console_printf("V_REPLENISH should be in range 2800-4900\n");
+ return 0;
+ }
+ val &= ~CHARGER_CHARGER_VOLTAGE_PARAM_REG_V_REPLENISH_Msk;
+ val |= DA1469X_ENCODE_V(v) << CHARGER_CHARGER_VOLTAGE_PARAM_REG_V_REPLENISH_Pos;
+ }
+ if (argc > 4 && strcmp("-", argv[4]) != 0) {
+ v = (uint32_t)parse_ll_bounds(argv[4], 2800, 4900, &rc);
+ if (rc) {
+ console_printf("V_OVP should be in range 2800-4900\n");
+ return 0;
+ }
+ val &= ~CHARGER_CHARGER_VOLTAGE_PARAM_REG_V_OVP_Msk;
+ val |= DA1469X_ENCODE_V(v) << CHARGER_CHARGER_VOLTAGE_PARAM_REG_V_OVP_Pos;
+ }
+ CHARGER->CHARGER_VOLTAGE_PARAM_REG = val;
+
+ return 0;
+}
+
+#if MYNEWT_VAL(DA1469X_CHARGER_USE_CHARGE_CONTROL)
+
+int
+da1469x_charger_status_changed(struct charge_control *ctrl, void *arg,
+ void *val, charge_control_type_t type)
+{
+ charge_control_status_t status;
+ charge_control_fault_t fault;
+
+ if (type == CHARGE_CONTROL_TYPE_STATUS) {
+ status = *(charge_control_status_t *)val;
+ switch (status) {
+ case CHARGE_CONTROL_STATUS_DISABLED:
+ console_printf("charger: charging disabled\n");
+ break;
+ case CHARGE_CONTROL_STATUS_NO_SOURCE:
+ console_printf("charger: not connected\n");
+ break;
+ case CHARGE_CONTROL_STATUS_CHARGING:
+ console_printf("charger: charging\n");
+ break;
+ case CHARGE_CONTROL_STATUS_CHARGE_COMPLETE:
+ console_printf("charger: charge complete\n");
+ break;
+ case CHARGE_CONTROL_STATUS_SUSPEND:
+ console_printf("charger: charge suspended due to temperature\n");
+ break;
+ case CHARGE_CONTROL_STATUS_FAULT:
+ console_printf("charger: fault Vbat to high or charge time exceeded\n");
+ break;
+ case CHARGE_CONTROL_STATUS_OTHER:
+ break;
+ }
+ } else if (type == CHARGE_CONTROL_TYPE_FAULT) {
+ fault = *(charge_control_fault_t *)val;
+ switch (fault) {
+ case CHARGE_CONTROL_FAULT_OV:
+ console_printf("charger: fault overvoltage\n");
+ break;
+ case CHARGE_CONTROL_FAULT_THERM:
+ console_printf("charger: fault over temperature\n");
+ break;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+struct charge_control_listener da1469x_listener = {
+ .ccl_type = CHARGE_CONTROL_TYPE_STATUS | CHARGE_CONTROL_TYPE_FAULT,
+ .ccl_func = da1469x_charger_status_changed,
+};
+
+static struct da1469x_charger_dev *charger;
+
+static int
+da1469x_charger_shell_cmd_listen(int argc, char **argv)
+{
+ if (argc > 1) {
+ if (strcmp("start", argv[1]) == 0) {
+ if (charger == NULL) {
+ charger = (struct da1469x_charger_dev *)os_dev_open("charger", 1, NULL);
+ if (charger) {
+ charge_control_register_listener(&charger->chg_ctrl, &da1469x_listener);
+ }
+
+ }
+ } else if (strcmp("stop", argv[1]) == 0) {
+ if (charger) {
+ charge_control_unregister_listener(&charger->chg_ctrl, &da1469x_listener);
+ os_dev_close(&charger->dev);
+ charger = NULL;
+ }
+ }
+ }
+ return 0;
+}
+
+#endif /* MYNEWT_VAL(DA1469X_CHARGER_USE_CHARGE_CONTROL) */
+
+static int
+da1469x_charger_shell_cmd(int argc, char **argv)
+{
+ if (argc == 1) {
+ return da1469x_charger_help();
+ }
+
+ argv++;
+ argc--;
+ if (strcmp(argv[0], "help") == 0) {
+ return da1469x_charger_help();
+#if MYNEWT_VAL(DA1469X_CHARGER_CLI_DECODE)
+ } else if (strcmp(argv[0], "decode") == 0) {
+ return da1469x_charger_shell_cmd_decode(argc, argv);
+#endif
+ } else if (strcmp(argv[0], "dump") == 0) {
+ return da1469x_charger_shell_cmd_dump(argc, argv);
+ } else if (strcmp(argv[0], "enable") == 0) {
+ return da1469x_charger_shell_cmd_enable(argc, argv);
+ } else if (strcmp(argv[0], "disable") == 0) {
+ return da1469x_charger_shell_cmd_disable(argc, argv);
+ } else if (strcmp(argv[0], "status") == 0) {
+ return da1469x_charger_shell_cmd_status(argc, argv);
+ } else if (strcmp(argv[0], "seti") == 0) {
+ return da1469x_charger_shell_cmd_set_i(argc, argv);
+ } else if (strcmp(argv[0], "setv") == 0) {
+ return da1469x_charger_shell_cmd_set_v(argc, argv);
+#if MYNEWT_VAL(DA1469X_CHARGER_USE_CHARGE_CONTROL)
+ } else if (strcmp(argv[0], "listen") == 0) {
+ return da1469x_charger_shell_cmd_listen(argc, argv);
+#endif
+ }
+
+ return da1469x_charger_shell_err_unknown_arg(argv[1]);
+}
+
+static const struct shell_cmd da1469x_charger_shell_cmd_struct = {
+ .sc_cmd = "charger",
+ .sc_cmd_func = da1469x_charger_shell_cmd
+};
+
+static int
+da1469x_charger_reg_cmd(int argc, char **argv)
+{
+ const struct reg *reg = NULL;
+ uint32_t val;
+ int status;
+ int i;
+ bool dump = false;
+ bool decode = da1469x_charger_cli_decode_fields;
+
+ for (i = 0; i < NUM_CHARGER_REGS; ++i) {
+ if (strcasecmp(charger_regs[i].name, argv[0]) == 0) {
+ reg = charger_regs + i;
+ }
+ }
+ if (!reg) {
+ return 0;
+ }
+
+ if (argc == 1) {
+ dump = true;
+#if MYNEWT_VAL(DA1469X_CHARGER_CLI_DECODE)
+ } else if (strcmp(argv[1], "decode") == 0) {
+ dump = true;
+ decode = true;
+#endif
+ } else {
+ val = (uint32_t)parse_ull_bounds(argv[1], 0, 0xFFFFFFFF, &status);
+ if (status) {
+ console_printf("Invalid register value %s\n", argv[1]);
+ return 0;
+ }
+
+ }
+ if (dump) {
+ val = *reg->addr;
+ da1469x_charger_dump_register(reg, val, decode);
+ } else {
+ *reg->addr = val;
+ }
+
+ return 0;
+}
+
+static const struct shell_cmd da1469x_charger_cmds[] = {
+#if MYNEWT_VAL(DA1469X_CHARGER_CLI_DECODE)
+ { "decode", da1469x_charger_shell_cmd_decode, HELP(decode) },
+#endif
+ { "dump", da1469x_charger_shell_cmd_dump, HELP(dump) },
+ { "enable", da1469x_charger_shell_cmd_enable, HELP(enable) },
+ { "disable", da1469x_charger_shell_cmd_disable, HELP(disable) },
+ { "status", da1469x_charger_shell_cmd_status, HELP(status) },
+ { "clrirq", da1469x_charger_shell_cmd_clear_irq, HELP(clear_irq) },
+ { "seti", da1469x_charger_shell_cmd_set_i, HELP(set_i) },
+ { "setv", da1469x_charger_shell_cmd_set_v, HELP(set_v) },
+#if MYNEWT_VAL(DA1469X_CHARGER_USE_CHARGE_CONTROL)
+ { "listen", da1469x_charger_shell_cmd_listen, HELP(listen) },
+#endif
+ { REG_NAME(CTRL), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(STATUS), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(VOLTAGE_PARAM), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(CURRENT_PARAM), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(TEMPSET_PARAM), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(PRE_CHARGE_TIMER), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(CC_CHARGE_TIMER), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(CV_CHARGE_TIMER), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(TOTAL_CHARGE_TIMER), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(JEITA_V_CHARGE), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(JEITA_V_PRECHARGE), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(JEITA_V_REPLENISH), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(JEITA_V_OVP), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(JEITA_CURRENT), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(VBAT_COMP_TIMER), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(VOVP_COMP_TIMER), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(TDIE_COMP_TIMER), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(TBAT_MON_TIMER), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(TBAT_COMP_TIMER), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(THOT_COMP_TIMER), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(PWR_UP_TIMER), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(STATE_IRQ_MASK), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(ERROR_IRQ_MASK), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(STATE_IRQ_STATUS), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(ERROR_IRQ_STATUS), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(STATE_IRQ_CLR), da1469x_charger_reg_cmd, HELP(reg) },
+ { REG_NAME(ERROR_IRQ_CLR), da1469x_charger_reg_cmd, HELP(reg) },
+ { NULL, NULL, NULL }
+};
+
+int
+da1469x_charger_shell_init(struct da1469x_charger_dev *dev)
+{
+ int rc;
+ (void)dev;
+
+ rc = shell_cmd_register(&da1469x_charger_shell_cmd_struct);
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ rc = shell_register("charger", da1469x_charger_cmds);
+ return rc;
+}
+
+#endif
diff --git a/hw/drivers/chg_ctrl/da1469x_charger/syscfg.yml b/hw/drivers/chg_ctrl/da1469x_charger/syscfg.yml
new file mode 100644
index 0000000..83ed95d
--- /dev/null
+++ b/hw/drivers/chg_ctrl/da1469x_charger/syscfg.yml
@@ -0,0 +1,76 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+syscfg.defs:
+ DA1469X_CHARGER:
+ description: 'Charger included in build'
+ value: 1
+ DA1469X_CHARGER_CLI:
+ description: 'Enable shell support for the charger'
+ value: 0
+ DA1469X_CHARGER_CLI_DECODE:
+ description: 'Decode registers fields in shell'
+ value: 0
+ DA1469X_CHARGER_USE_CHARGE_CONTROL:
+ description: 'Enable charge control integration'
+ value: 1
+ DA1469X_CHARGER_NTC_ENABLE:
+ description: >
+ Enable NTC. Set this only if NTC is connected to P0_7 and P1_0.
+ When left disable battery temperature will not be monitored.
+ value: 0
+ DA1469X_CHARGER_TBAT_MONITOR_MODE:
+ description: >
+ Battery monitor mode.
+ 0 - Battery temperature state checked and updated once, as soon as the charger is powered-up and settled
+ 1 - Battery temperature state checked periodically
+ 2 - Battery temperature state checked periodically
+ 3 - When selected, it freezes the Battery temperature monitor FSM
+ Set to 3 when NTC is not present, if not charging current can be changed by JEITA settings on false
+ temperature readings.
+ range: 0..3
+ value: 3
+ DA1469X_CHARGER_V_OVP:
+ descrition: >
+ Over-voltage protection level in (mV)
+ value: 4400
+ DA1469X_CHARGER_V_REPLENISH:
+ descrition: >
+ Voltage to start charging after reaching ond of charge state (mV)
+ value: 4060
+ DA1469X_CHARGER_V_PRECHARGE:
+ descrition: >
+ The voltage level at which the battery is considered as Pre-charged (mv)
+ value: 3200
+ DA1469X_CHARGER_V_CHARGE:
+ descrition: >
+ Charging voltage (mv)
+ value: 4260
+ DA1469X_CHARGER_I_PRECHARGE:
+ descrition: >
+ Pre-charge current (mA)
+ value: 2
+ DA1469X_CHARGER_I_CHARGE:
+ descrition: >
+ Charge current (mA)
+ value: 35
+ DA1469X_CHARGER_I_END_OF_CHARGE:
+ description: >
+ End of charge current settings, 4-35 (%).
+ value: 7