123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 |
- #include "asm/clock.h"
- #include "timer.h"
- #include "asm/power/p33.h"
- #include "asm/charge.h"
- #include "asm/adc_api.h"
- #include "uart.h"
- #include "device/device.h"
- #include "asm/power_interface.h"
- #include "system/event.h"
- #include "asm/efuse.h"
- #include "gpio.h"
- #include "app_config.h"
- #define LOG_TAG_CONST CHARGE
- #define LOG_TAG "[CHARGE]"
- #define LOG_INFO_ENABLE
- #define LOG_DUMP_ENABLE
- #define LOG_ERROR_ENABLE
- #define LOG_DEBUG_ENABLE
- #include "debug.h"
- typedef struct _CHARGE_VAR {
- struct charge_platform_data *data;
- volatile u8 charge_online_flag;
- volatile u8 charge_event_flag;
- volatile u8 init_ok;
- volatile u8 detect_stop; //检测暂停或者继续
- volatile int ldo5v_timer; //检测LDOIN状态变化的usr timer
- volatile int charge_timer; //检测充电是否充满的usr timer
- volatile int cc_timer; //涓流切恒流的sys timer
- } CHARGE_VAR;
- #define __this (&charge_var)
- static CHARGE_VAR charge_var;
- static u8 charge_flag;
- extern const int set_to_close_timer0_delay;
- #define BIT_LDO5V_IN BIT(0)
- #define BIT_LDO5V_OFF BIT(1)
- #define BIT_LDO5V_KEEP BIT(2)
- u8 get_charge_poweron_en(void)
- {
- return __this->data->charge_poweron_en;
- }
- void charge_check_and_set_pinr(u8 level)
- {
- u8 pinr_io, reg;
- reg = P33_CON_GET(P3_PINR1_CON);
- //开启LDO5V_DET长按复位
- if ((reg & BIT(0)) && ((reg & BIT(3)) == 0)) {
- if (level == 0) {
- P33_CON_SET(P3_PINR1_CON, 2, 1, 0);
- } else {
- P33_CON_SET(P3_PINR1_CON, 2, 1, 1);
- }
- }
- }
- static void udelay(u32 usec)
- {
- if (set_to_close_timer0_delay) {
- JL_MCPWM->MCPWM_CON0 &= ~BIT(8 + 3);
- JL_MCPWM->TMR3_CNT = 0;
- JL_MCPWM->TMR3_PR = clk_get("lsb") / 1000000 * usec;
- JL_MCPWM->TMR3_CON = BIT(10) | BIT(0);
- JL_MCPWM->MCPWM_CON0 |= BIT(8 + 3);
- while (!(JL_MCPWM->TMR3_CON & BIT(12)));
- JL_MCPWM->TMR3_CON = BIT(10);
- JL_MCPWM->MCPWM_CON0 &= ~BIT(8 + 3);
- } else {
- JL_TIMER0->CON = BIT(14);
- JL_TIMER0->CNT = 0;
- JL_TIMER0->PRD = clk_get("timer") / 1000000L * usec; //1us
- JL_TIMER0->CON = BIT(0) | BIT(2) | BIT(6); //sys clk
- while ((JL_TIMER0->CON & BIT(15)) == 0);
- JL_TIMER0->CON = BIT(14);
- }
- }
- static u8 check_charge_state(void)
- {
- u8 online_cnt = 0;
- u8 i = 0;
- __this->charge_online_flag = 0;
- for (i = 0; i < 20; i++) {
- if (LVCMP_DET_GET() || LDO5V_DET_GET()) {
- online_cnt++;
- }
- udelay(1000);
- }
- log_info("online_cnt = %d\n", online_cnt);
- if (online_cnt > 5) {
- __this->charge_online_flag = 1;
- }
- return __this->charge_online_flag;
- }
- void set_charge_online_flag(u8 flag)
- {
- __this->charge_online_flag = flag;
- }
- u8 get_charge_online_flag(void)
- {
- return __this->charge_online_flag;
- }
- void set_charge_event_flag(u8 flag)
- {
- __this->charge_event_flag = flag;
- }
- u8 get_ldo5v_online_hw(void)
- {
- return LDO5V_DET_GET();
- }
- u8 get_lvcmp_det(void)
- {
- return LVCMP_DET_GET();
- }
- u8 get_ldo5v_pulldown_en(void)
- {
- if (!__this->data) {
- return 0;
- }
- if (__this->data->ldo5v_pulldown_keep == 0) {
- return 0;
- }
- return __this->data->ldo5v_pulldown_en;
- }
- u8 get_ldo5v_pulldown_res(void)
- {
- if (__this->data) {
- return __this->data->ldo5v_pulldown_lvl;
- }
- return CHARGE_PULLDOWN_200K;
- }
- void charge_event_to_user(u8 event)
- {
- struct sys_event e;
- e.type = SYS_DEVICE_EVENT;
- e.arg = (void *)DEVICE_EVENT_FROM_CHARGE;
- e.u.dev.event = event;
- e.u.dev.value = 0;
- sys_event_notify(&e);
- }
- void power_enter_charge_mode(void)
- {
- if (TCFG_LOWPOWER_POWER_SEL == PWR_DCDC15) {
- power_set_charge_mode(1);
- power_set_mode(PWR_DCDC15_FOR_CHARGE);
- }
- }
- void power_exit_charge_mode(void)
- {
- if (TCFG_LOWPOWER_POWER_SEL == PWR_DCDC15) {
- power_set_charge_mode(0);
- power_set_mode(TCFG_LOWPOWER_POWER_SEL);
- }
- }
- static void charge_cc_check(void *priv)
- {
- if ((adc_get_voltage(AD_CH_VBAT) * 4 / 10) > CHARGE_CCVOL_V) {
- set_charge_mA(__this->data->charge_mA);
- usr_timer_del(__this->cc_timer);
- __this->cc_timer = 0;
- }
- }
- void charge_start(void)
- {
- log_info("%s\n", __func__);
- if (__this->charge_timer) {
- usr_timer_del(__this->charge_timer);
- __this->charge_timer = 0;
- }
- if ((adc_get_voltage(AD_CH_VBAT) * 4 / 10) > CHARGE_CCVOL_V) {
- set_charge_mA(__this->data->charge_mA);
- } else {
- set_charge_mA(CHARGE_mA_20);
- if (!__this->cc_timer) {
- __this->cc_timer = usr_timer_add(NULL, charge_cc_check, 1000, 1);
- }
- }
- power_awakeup_enable_with_port(IO_CHGFL_DET);
- CHARGE_EN(1);
- charge_event_to_user(CHARGE_EVENT_CHARGE_START);
- }
- void charge_close(void)
- {
- log_info("%s\n", __func__);
- if (charge_flag != BIT_LDO5V_IN) {
- CHARGE_EN(0);
- }
- power_awakeup_disable_with_port(IO_CHGFL_DET);
- charge_event_to_user(CHARGE_EVENT_CHARGE_CLOSE);
- if (__this->charge_timer) {
- usr_timer_del(__this->charge_timer);
- __this->charge_timer = 0;
- }
- if (__this->cc_timer) {
- usr_timer_del(__this->cc_timer);
- __this->cc_timer = 0;
- }
- }
- static void charge_full_detect(void *priv)
- {
- static u16 charge_full_cnt = 0;
- if (CHARGE_FULL_FLAG_GET() && LVCMP_DET_GET()) {
- /* putchar('F'); */
- if (charge_full_cnt < 5) {
- charge_full_cnt++;
- } else {
- charge_full_cnt = 0;
- usr_timer_del(__this->charge_timer);
- __this->charge_timer = 0;
- charge_event_to_user(CHARGE_EVENT_CHARGE_FULL);
- }
- } else {
- /* putchar('K'); */
- charge_full_cnt = 0;
- usr_timer_del(__this->charge_timer);
- __this->charge_timer = 0;
- power_awakeup_enable_with_port(IO_CHGFL_DET);
- }
- }
- static void ldo5v_detect(void *priv)
- {
- /* log_info("%s\n",__func__); */
- static u16 ldo5v_on_cnt = 0;
- static u16 ldo5v_keep_cnt = 0;
- static u16 ldo5v_off_cnt = 0;
- if (__this->detect_stop) {
- return;
- }
- if (LVCMP_DET_GET()) { //ldoin > vbat
- /* putchar('X'); */
- if (ldo5v_on_cnt < __this->data->ldo5v_on_filter) {
- ldo5v_on_cnt++;
- } else {
- /* printf("ldo5V_IN\n"); */
- set_charge_online_flag(1);
- ldo5v_off_cnt = 0;
- ldo5v_keep_cnt = 0;
- //消息线程未准备好接收消息,继续扫描
- if (__this->charge_event_flag == 0) {
- return;
- }
- ldo5v_on_cnt = 0;
- usr_timer_del(__this->ldo5v_timer);
- __this->ldo5v_timer = 0;
- power_enter_charge_mode();
- if ((charge_flag & BIT_LDO5V_IN) == 0) {
- charge_flag = BIT_LDO5V_IN;
- charge_event_to_user(CHARGE_EVENT_LDO5V_IN);
- }
- }
- } else if (LDO5V_DET_GET() == 0) { //ldoin<拔出电压(0.6)
- /* putchar('Q'); */
- if (ldo5v_off_cnt < (__this->data->ldo5v_off_filter + 20)) {
- ldo5v_off_cnt++;
- } else {
- /* printf("ldo5V_OFF\n"); */
- set_charge_online_flag(0);
- ldo5v_on_cnt = 0;
- ldo5v_keep_cnt = 0;
- //消息线程未准备好接收消息,继续扫描
- if (__this->charge_event_flag == 0) {
- return;
- }
- ldo5v_off_cnt = 0;
- usr_timer_del(__this->ldo5v_timer);
- __this->ldo5v_timer = 0;
- power_exit_charge_mode();
- if ((charge_flag & BIT_LDO5V_OFF) == 0) {
- charge_flag = BIT_LDO5V_OFF;
- charge_event_to_user(CHARGE_EVENT_LDO5V_OFF);
- }
- }
- } else { //拔出电压(0.6左右)< ldoin < vbat
- /* putchar('E'); */
- if (ldo5v_keep_cnt < __this->data->ldo5v_keep_filter) {
- ldo5v_keep_cnt++;
- } else {
- /* printf("ldo5V_ERR\n"); */
- set_charge_online_flag(1);
- ldo5v_off_cnt = 0;
- ldo5v_on_cnt = 0;
- //消息线程未准备好接收消息,继续扫描
- if (__this->charge_event_flag == 0) {
- return;
- }
- ldo5v_keep_cnt = 0;
- usr_timer_del(__this->ldo5v_timer);
- power_exit_charge_mode();
- __this->ldo5v_timer = 0;
- if ((charge_flag & BIT_LDO5V_KEEP) == 0) {
- charge_flag = BIT_LDO5V_KEEP;
- if (__this->data->ldo5v_off_filter) {
- charge_event_to_user(CHARGE_EVENT_LDO5V_KEEP);
- }
- }
- }
- }
- }
- void ldoin_wakeup_isr(void)
- {
- if (!__this->init_ok) {
- return;
- }
- /* printf(" %s \n", __func__); */
- if (__this->ldo5v_timer == 0) {
- __this->ldo5v_timer = usr_timer_add(0, ldo5v_detect, 2, 1);
- }
- }
- void charge_wakeup_isr(void)
- {
- if (!__this->init_ok) {
- return;
- }
- /* printf(" %s \n", __func__); */
- power_awakeup_disable_with_port(IO_CHGFL_DET);
- if (__this->charge_timer == 0) {
- __this->charge_timer = usr_timer_add(0, charge_full_detect, 2, 1);
- }
- }
- void charge_set_ldo5v_detect_stop(u8 stop)
- {
- __this->detect_stop = stop;
- }
- u8 get_charge_mA_config(void)
- {
- return __this->data->charge_mA;
- }
- void set_charge_mA(u8 charge_mA)
- {
- static u8 charge_mA_old = 0xff;
- if (charge_mA_old != charge_mA) {
- charge_mA_old = charge_mA;
- CHARGE_mA_SEL(charge_mA);
- }
- }
- const u16 full_table[CHARGE_FULL_V_MAX] = {
- 3962, 4002, 4044, 4086, 4130, 4175, 4222, 4270,
- 4308, 4349, 4391, 4434, 4472, 4517, 4564, 4611
- };
- u16 get_charge_full_value(void)
- {
- ASSERT(__this->init_ok, "charge not init ok!\n");
- ASSERT(__this->data->charge_full_V < CHARGE_FULL_V_MAX);
- return full_table[__this->data->charge_full_V];
- }
- static void charge_config(void)
- {
- u8 charge_4202_trim_val = CHARGE_FULL_V_4222;
- u8 offset = 0;
- u8 charge_full_v_val = 0;
- if (get_vbat_trim() == 0xf) {
- log_info("vbat not trim, use default config!!!!!!");
- } else {
- charge_4202_trim_val = get_vbat_trim(); //4.2V对应的trim出来的实际档位
- }
- log_info("charge_4202_trim_val = %d\n", charge_4202_trim_val);
- if (__this->data->charge_full_V >= CHARGE_FULL_V_4222) {
- offset = __this->data->charge_full_V - CHARGE_FULL_V_4222;
- charge_full_v_val = charge_4202_trim_val + offset;
- if (charge_full_v_val > 0xf) {
- charge_full_v_val = 0xf;
- }
- } else {
- offset = CHARGE_FULL_V_4222 - __this->data->charge_full_V;
- if (charge_4202_trim_val >= offset) {
- charge_full_v_val = charge_4202_trim_val - offset;
- } else {
- charge_full_v_val = 0;
- }
- }
- log_info("charge_full_v_val = %d\n", charge_full_v_val);
- CHARGE_FULL_V_SEL(charge_full_v_val);
- CHARGE_FULL_mA_SEL(__this->data->charge_full_mA);
- /* CHARGE_mA_SEL(__this->data->charge_mA); */
- CHARGE_mA_SEL(CHARGE_mA_20);
- }
- int charge_init(const struct dev_node *node, void *arg)
- {
- log_info("%s\n", __func__);
- __this->data = (struct charge_platform_data *)arg;
- ASSERT(__this->data);
- __this->init_ok = 0;
- __this->charge_online_flag = 0;
- /*先关闭充电使能,后面检测到充电插入再开启*/
- power_awakeup_disable_with_port(IO_CHGFL_DET);
- CHARGE_EN(0);
- /*LDO5V的100K下拉电阻使能*/
- L5V_RES_DET_S_SEL(__this->data->ldo5v_pulldown_lvl);
- L5V_LOAD_EN(__this->data->ldo5v_pulldown_en);
- charge_config();
- if (check_charge_state()) {
- if (__this->ldo5v_timer == 0) {
- __this->ldo5v_timer = usr_timer_add(0, ldo5v_detect, 2, 1);
- }
- } else {
- charge_flag = BIT_LDO5V_OFF;
- power_exit_charge_mode();
- }
- __this->init_ok = 1;
- return 0;
- }
- void charge_module_stop(void)
- {
- if (!__this->init_ok) {
- return;
- }
- charge_close();
- power_awakeup_disable_with_port(IO_LDOIN_DET);
- power_awakeup_disable_with_port(IO_VBTCH_DET);
- if (__this->ldo5v_timer) {
- usr_timer_del(__this->ldo5v_timer);
- __this->ldo5v_timer = 0;
- }
- }
- void charge_module_restart(void)
- {
- if (!__this->init_ok) {
- return;
- }
- if (!__this->ldo5v_timer) {
- __this->ldo5v_timer = usr_timer_add(NULL, ldo5v_detect, 2, 1);
- }
- power_awakeup_enable_with_port(IO_LDOIN_DET);
- power_awakeup_enable_with_port(IO_VBTCH_DET);
- }
- int charge_api_init(void *arg)
- {
- return charge_init(NULL, arg);
- }
- const struct device_operations charge_dev_ops = {
- .init = charge_init,
- };
|