123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780 |
- /*
- * sb_tx.c
- * Samsung Mobile Wireless TX Driver
- *
- * Copyright (C) 2021 Samsung Electronics
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
- #include <linux/slab.h>
- #include <linux/mutex.h>
- #include <linux/battery/sb_sysfs.h>
- #include <linux/battery/sb_notify.h>
- #include "sec_battery.h"
- #include "sec_charging_common.h"
- #include "sb_pass_through.h"
- #define pt_log(str, ...) pr_info("[PASS-THROUGH]:%s: "str, __func__, ##__VA_ARGS__)
- #define PT_MODULE_NAME "pass-through"
- #define IV_VOTE_NAME "IV"
- #define ICL_VOTE_NAME "ICL"
- #define FCC_VOTE_NAME "FCC"
- #define CHGEN_VOTE_NAME "CHGEN"
- struct sb_pt {
- struct notifier_block nb;
- struct mutex mlock;
- struct wakeup_source *ws;
- struct workqueue_struct *wq;
- struct delayed_work start_work;
- struct delayed_work adjust_work;
- struct delayed_work step_work;
- /* state flags */
- int user_mode;
- int chg_src;
- int step;
- int ref_cap;
- int adj_state;
- unsigned int adj_cnt;
- unsigned int adj_op_cnt;
- /* battery status */
- int cable_type;
- int batt_status;
- int dc_status;
- /* dt data */
- bool is_enabled;
- unsigned int start_delay;
- unsigned int init_delay;
- unsigned int adj_delay;
- unsigned int adj_max_cnt;
- unsigned int min_cap;
- unsigned int fixed_sc_cap;
- unsigned int max_icl;
- unsigned int vfloat;
- char *sc_name;
- char *dc_name;
- char *fg_name;
- };
- enum pt_step {
- PT_STEP_NONE = 0,
- PT_STEP_INIT,
- PT_STEP_PRESET,
- PT_STEP_ADJUST,
- PT_STEP_MONITOR,
- PT_STEP_RESET,
- };
- static const char *get_step_str(int step)
- {
- switch (step) {
- case PT_STEP_NONE:
- return "None";
- case PT_STEP_INIT:
- return "Init";
- case PT_STEP_PRESET:
- return "Preset";
- case PT_STEP_ADJUST:
- return "Adjust";
- case PT_STEP_MONITOR:
- return "Monitor";
- case PT_STEP_RESET:
- return "Reset";
- }
- return "Unknown";
- }
- static void set_misc_event(bool state)
- {
- struct sbn_bit_event misc;
- misc.value = (state) ? BATT_MISC_EVENT_PASS_THROUGH : 0;
- misc.mask = BATT_MISC_EVENT_PASS_THROUGH;
- sb_notify_call(SB_NOTIFY_EVENT_MISC, cast_to_sb_pdata(&misc));
- }
- static int set_dc_ta_volt(struct sb_pt *pt, int value)
- {
- union power_supply_propval val = { value, };
- return psy_do_property(pt->dc_name, set,
- POWER_SUPPLY_EXT_PROP_PASS_THROUGH_MODE_TA_VOL, val);
- }
- /* don't call the mutex lock in static functions */
- static bool check_state(struct sb_pt *pt)
- {
- if (!pt)
- return false;
- if (!pt->is_enabled)
- return false;
- if (pt->user_mode == PTM_NONE)
- return false;
- if (!is_pd_apdo_wire_type(pt->cable_type))
- return false;
- if (pt->batt_status != POWER_SUPPLY_STATUS_CHARGING)
- return false;
- if (pt->step == PT_STEP_NONE) {
- union power_supply_propval value = { 0, };
- value.intval = SEC_FUELGAUGE_CAPACITY_TYPE_DYNAMIC_SCALE;
- psy_do_property(pt->fg_name, get,
- POWER_SUPPLY_PROP_CAPACITY, value);
- if (pt->min_cap >= value.intval)
- return false;
- }
- return true;
- }
- static bool check_preset_state(int dc_status)
- {
- return (dc_status == SEC_DIRECT_CHG_MODE_DIRECT_ON) ||
- (dc_status == SEC_DIRECT_CHG_MODE_DIRECT_DONE) ||
- (dc_status == SEC_DIRECT_CHG_MODE_DIRECT_BYPASS);
- }
- #define CAP_HIGH (1)
- #define CAP_NORMAL (0)
- #define CAP_LOW (-1)
- static int check_cap(struct sb_pt *pt)
- {
- union power_supply_propval value = {0, };
- int ncap1, ncap2, rcap1, rcap2;
- int delta_cap = 0;
- value.intval = SEC_FUELGAUGE_CAPACITY_TYPE_DYNAMIC_SCALE;
- psy_do_property(pt->fg_name, get,
- POWER_SUPPLY_PROP_CAPACITY, value);
- ncap1 = (value.intval / 10);
- ncap2 = (value.intval % 10);
- rcap1 = (pt->ref_cap / 10);
- rcap2 = (pt->ref_cap % 10);
- value.intval = SEC_BATTERY_CURRENT_MA;
- psy_do_property(pt->fg_name, get,
- POWER_SUPPLY_PROP_CURRENT_NOW, value);
- if (ncap1 == rcap1)
- delta_cap = (((ncap2 >= 6) && (value.intval > 0)) ? CAP_HIGH :
- (((ncap2 <= 4) && (value.intval < 0)) ? CAP_LOW : CAP_NORMAL));
- else if (ncap1 > rcap1)
- delta_cap = (value.intval > 0) ? CAP_HIGH : CAP_NORMAL;
- else
- delta_cap = (value.intval < 0) ? CAP_LOW : CAP_NORMAL;
- pt_log("Now Cap(%03d.%d%%), Ref Cap(%03d.%d%%), Current(%04dmA), delta(%d)\n",
- ncap1, ncap2, rcap1, rcap2, value.intval, delta_cap);
- return delta_cap;
- }
- static void clear_state(struct sb_pt *pt, int init_step)
- {
- if (pt->step == PT_STEP_NONE)
- return;
- pt_log("latest step = %d, init_step = %d\n", pt->step, init_step);
- sec_votef(IV_VOTE_NAME, VOTER_PASS_THROUGH, false, 0);
- sec_votef(ICL_VOTE_NAME, VOTER_PASS_THROUGH, false, 0);
- sec_votef(FCC_VOTE_NAME, VOTER_PASS_THROUGH, false, 0);
- sec_votef(CHGEN_VOTE_NAME, VOTER_PASS_THROUGH, false, 0);
- pt->chg_src = SEC_CHARGING_SOURCE_SWITCHING;
- pt->adj_state = CAP_NORMAL;
- pt->adj_cnt = 0;
- pt->adj_op_cnt = 0;
- if (init_step == PT_STEP_NONE) {
- pt->ref_cap = 0;
- /* set charging off before re-starting dc */
- sec_votef(CHGEN_VOTE_NAME, VOTER_PASS_THROUGH, true, SEC_BAT_CHG_MODE_CHARGING_OFF);
- sec_votef(CHGEN_VOTE_NAME, VOTER_PASS_THROUGH, false, 0);
- /* clear event */
- set_misc_event(false);
- sec_pd_detach_with_cc(0);
- }
- pt->step = init_step;
- }
- static void cb_start_work(struct work_struct *work)
- {
- struct sb_pt *pt = container_of(work,
- struct sb_pt, start_work.work);
- mutex_lock(&pt->mlock);
- pt_log("now step = %s\n", get_step_str(pt->step));
- if (!check_state(pt))
- goto end_work;
- if (pt->step == PT_STEP_NONE)
- pt->step = PT_STEP_INIT;
- if (pt->step != PT_STEP_INIT)
- goto end_work;
- __pm_wakeup_event(pt->ws, msecs_to_jiffies(1000));
- queue_delayed_work(pt->wq, &pt->step_work, 0);
- end_work:
- mutex_unlock(&pt->mlock);
- }
- #define PT_ADJ_OP_MAX_CNT 100
- #define PT_ADJ_CURR 500
- static void cb_adjust_work(struct work_struct *work)
- {
- struct sb_pt *pt = container_of(work, struct sb_pt, adjust_work.work);
- union power_supply_propval value = {0, };
- int now_state = CAP_NORMAL;
- mutex_lock(&pt->mlock);
- if (!check_state(pt))
- goto end_work;
- if (pt->step != PT_STEP_ADJUST)
- goto end_work;
- if (pt->chg_src == SEC_CHARGING_SOURCE_SWITCHING) {
- pt->step = PT_STEP_MONITOR;
- goto end_work;
- }
- if (pt->adj_op_cnt++ >= PT_ADJ_OP_MAX_CNT) {
- pt_log("over working(%d) !!\n", pt->adj_op_cnt);
- pt->step = PT_STEP_MONITOR;
- goto end_work;
- }
- now_state = check_cap(pt);
- if (now_state != pt->adj_state) {
- pt->adj_cnt = 0;
- pt->adj_state = now_state;
- goto re_work;
- }
- value.intval = SEC_BATTERY_CURRENT_MA;
- psy_do_property(pt->fg_name, get,
- POWER_SUPPLY_PROP_CURRENT_NOW, value);
- switch (pt->adj_state) {
- case CAP_LOW:
- if (value.intval < (-PT_ADJ_CURR)) {
- pt->adj_cnt = 0;
- set_dc_ta_volt(pt, CAP_LOW);
- } else if (value.intval > (PT_ADJ_CURR)) {
- pt->adj_cnt = 0;
- } else {
- pt->adj_cnt++;
- }
- break;
- case CAP_HIGH:
- if (value.intval > (PT_ADJ_CURR)) {
- pt->adj_cnt = 0;
- set_dc_ta_volt(pt, CAP_HIGH);
- } else if (value.intval < (-PT_ADJ_CURR)) {
- pt->adj_cnt = 0;
- } else {
- pt->adj_cnt++;
- }
- break;
- case CAP_NORMAL:
- if (value.intval < (-PT_ADJ_CURR)) {
- pt->adj_cnt = 0;
- set_dc_ta_volt(pt, CAP_LOW);
- } else if (value.intval > (PT_ADJ_CURR)) {
- pt->adj_cnt = 0;
- set_dc_ta_volt(pt, CAP_HIGH);
- } else {
- pt->adj_cnt++;
- }
- break;
- default:
- break;
- }
- pt_log("ADJ STATE(%d, %d), CURR(%d), CNT(%d)\n",
- pt->adj_state, now_state, value.intval, pt->adj_cnt);
- if (pt->adj_cnt >= pt->adj_max_cnt) {
- pt->step = PT_STEP_MONITOR;
- goto end_work;
- }
- re_work:
- mutex_unlock(&pt->mlock);
- queue_delayed_work(pt->wq, &pt->adjust_work, msecs_to_jiffies(pt->adj_delay));
- return;
- end_work:
- pt->adj_state = CAP_NORMAL;
- pt->adj_cnt = 0;
- pt->adj_op_cnt = 0;
- mutex_unlock(&pt->mlock);
- __pm_relax(pt->ws);
- }
- static void cb_step_work(struct work_struct *work)
- {
- struct sb_pt *pt = container_of(work, struct sb_pt, step_work.work);
- sb_pt_monitor(pt, pt->chg_src);
- }
- static void push_start_work(struct sb_pt *pt, unsigned int delay)
- {
- unsigned int work_state;
- if (!check_state(pt))
- return;
- work_state = work_busy(&pt->start_work.work);
- pt_log("work_state = 0x%x, delay = %d\n", work_state, delay);
- if (!(work_state & (WORK_BUSY_PENDING | WORK_BUSY_RUNNING))) {
- __pm_wakeup_event(pt->ws, msecs_to_jiffies(delay + 1000));
- queue_delayed_work(pt->wq, &pt->start_work, msecs_to_jiffies(delay));
- }
- }
- static ssize_t show_attrs(struct device *dev,
- struct device_attribute *attr, char *buf);
- static ssize_t store_attrs(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
- #define PT_SYSFS_ATTR(_name) \
- { \
- .attr = {.name = #_name, .mode = 0664}, \
- .show = show_attrs, \
- .store = store_attrs, \
- }
- static struct device_attribute pt_attr[] = {
- PT_SYSFS_ATTR(pass_through),
- };
- enum sb_pt_attrs {
- PASS_THROUGH = 0,
- };
- static ssize_t show_attrs(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct sb_pt *pt = sb_sysfs_get_pdata(PT_MODULE_NAME);
- const ptrdiff_t offset = attr - pt_attr;
- ssize_t count = 0;
- switch (offset) {
- case PASS_THROUGH:
- count += scnprintf(buf + count, PAGE_SIZE - count, "%d\n", pt->user_mode);
- break;
- default:
- break;
- }
- return count;
- }
- static ssize_t store_attrs(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct sb_pt *pt = sb_sysfs_get_pdata(PT_MODULE_NAME);
- const ptrdiff_t offset = attr - pt_attr;
- switch (offset) {
- case PASS_THROUGH:
- {
- int x = 0;
- if (sscanf(buf, "%10d\n", &x) == 1) {
- mutex_lock(&pt->mlock);
- pt_log("user_mode = %d <-> %d, %s\n",
- x, pt->user_mode, ((x != PTM_NONE) ? "enabled" : "disabled"));
- x = (x) ? PTM_2TO1 : PTM_NONE;
- if (pt->user_mode != x) {
- pt->user_mode = x;
- if (pt->step != PT_STEP_NONE)
- clear_state(pt, PT_STEP_NONE);
- if (pt->user_mode)
- push_start_work(pt, pt->start_delay);
- }
- mutex_unlock(&pt->mlock);
- }
- }
- break;
- default:
- break;
- }
- return count;
- }
- static int sb_noti_handler(struct notifier_block *nb, unsigned long action, void *data)
- {
- return 0;
- }
- static int parse_dt(struct sb_pt *pt, struct device *parent)
- {
- #if defined(CONFIG_OF)
- struct device_node *np;
- int ret = 0;
- if (!parent)
- return -EINVAL;
- np = of_find_node_by_name(NULL, PT_MODULE_NAME);
- if (!np) {
- pt_log("failed to find root node\n");
- return -ENODEV;
- }
- pt->is_enabled = true;
- sb_of_parse_u32(np, pt, start_delay, 5000);
- sb_of_parse_u32(np, pt, init_delay, 5000);
- sb_of_parse_u32(np, pt, adj_delay, 500);
- sb_of_parse_u32(np, pt, adj_max_cnt, 3);
- sb_of_parse_u32(np, pt, min_cap, 200);
- sb_of_parse_u32(np, pt, fixed_sc_cap, 900);
- sb_of_parse_u32(np, pt, max_icl, 3000);
- sb_of_parse_u32(np, pt, vfloat, 4400);
- np = of_find_node_by_name(NULL, "battery");
- if (np) {
- ret = of_property_read_string(np,
- "battery,fuelgauge_name", (const char **)&pt->fg_name);
- if (ret)
- pt_log("failed to get fg name in battery dt (ret = %d)\n", ret);
- }
- ret = of_property_read_string(parent->of_node,
- "charger,main_charger", (const char **)&pt->sc_name);
- if (ret)
- pt_log("failed to get sc name in dc drv (ret = %d)\n", ret);
- ret = of_property_read_string(parent->of_node,
- "charger,direct_charger", (const char **)&pt->dc_name);
- if (ret)
- pt_log("failed to get dc name in dc drv (ret = %d)\n", ret);
- #endif
- return 0;
- }
- struct sb_pt *sb_pt_init(struct device *parent)
- {
- struct sb_pt *pt;
- int ret = 0;
- pt = kzalloc(sizeof(struct sb_pt), GFP_KERNEL);
- if (!pt)
- return ERR_PTR(-ENOMEM);
- ret = parse_dt(pt, parent);
- pt_log("parse_dt ret = %s\n", (ret) ? "fail" : "success");
- if (ret)
- goto failed_dt;
- pt->wq = create_singlethread_workqueue(PT_MODULE_NAME);
- if (!pt->wq) {
- ret = -ENOMEM;
- goto failed_wq;
- }
- pt->ws = wakeup_source_register(parent, PT_MODULE_NAME);
- INIT_DELAYED_WORK(&pt->start_work, cb_start_work);
- INIT_DELAYED_WORK(&pt->adjust_work, cb_adjust_work);
- INIT_DELAYED_WORK(&pt->step_work, cb_step_work);
- mutex_init(&pt->mlock);
- pt->chg_src = SEC_CHARGING_SOURCE_SWITCHING;
- pt->step = PT_STEP_NONE;
- pt->ref_cap = 0;
- pt->user_mode = PTM_NONE;
- pt->adj_state = CAP_NORMAL;
- pt->adj_cnt = 0;
- pt->adj_op_cnt = 0;
- ret = sb_sysfs_add_attrs(PT_MODULE_NAME, pt, pt_attr, ARRAY_SIZE(pt_attr));
- pt_log("sb_sysfs_add_attrs ret = %s\n", (ret) ? "fail" : "success");
- ret = sb_notify_register(&pt->nb, sb_noti_handler, PT_MODULE_NAME, SB_DEV_MODULE);
- pt_log("sb_notify_register ret = %s\n", (ret) ? "fail" : "success");
- return pt;
- failed_wq:
- failed_dt:
- kfree(pt);
- return ERR_PTR(ret);
- }
- EXPORT_SYMBOL(sb_pt_init);
- int sb_pt_psy_set_property(struct sb_pt *pt, enum power_supply_property psp, const union power_supply_propval *value)
- {
- if (!pt)
- return 0;
- switch ((int)psp) {
- case POWER_SUPPLY_PROP_STATUS:
- pt->batt_status = value->intval;
- break;
- case POWER_SUPPLY_PROP_ONLINE:
- pt->cable_type = value->intval;
- mutex_lock(&pt->mlock);
- if (!is_pd_apdo_wire_type(pt->cable_type) &&
- (pt->step != PT_STEP_NONE))
- clear_state(pt, PT_STEP_NONE);
- mutex_unlock(&pt->mlock);
- break;
- case POWER_SUPPLY_EXT_PROP_DIRECT_CHARGER_MODE:
- /* Caution : dead lock */
- pt->dc_status = value->intval;
- break;
- default:
- break;
- }
- return 0;
- }
- EXPORT_SYMBOL(sb_pt_psy_set_property);
- int sb_pt_psy_get_property(struct sb_pt *pt, enum power_supply_property psp, union power_supply_propval *value)
- {
- int ret = 0;
- if (!pt)
- return 0;
- switch (psp) {
- case POWER_SUPPLY_PROP_STATUS:
- mutex_lock(&pt->mlock);
- if ((pt->step != PT_STEP_NONE) &&
- (pt->chg_src == SEC_CHARGING_SOURCE_SWITCHING)) {
- union power_supply_propval val;
- val.intval = 0;
- psy_do_property(pt->sc_name, get, psp, val);
- if (val.intval == POWER_SUPPLY_STATUS_FULL) {
- ret = -EBUSY;
- pt_log("prevent charging status\n");
- value->intval = POWER_SUPPLY_STATUS_CHARGING;
- }
- }
- mutex_unlock(&pt->mlock);
- break;
- case POWER_SUPPLY_PROP_HEALTH:
- mutex_lock(&pt->mlock);
- if (pt->step != PT_STEP_NONE) {
- union power_supply_propval val;
- val.intval = 0;
- psy_do_property(pt->dc_name, get, psp, val);
- if (val.intval == POWER_SUPPLY_EXT_HEALTH_DC_ERR) {
- pt_log("clear pt state because of DC err(%d)\n", val.intval);
- clear_state(pt, PT_STEP_NONE);
- }
- }
- mutex_unlock(&pt->mlock);
- break;
- default:
- break;
- }
- return ret;
- }
- EXPORT_SYMBOL(sb_pt_psy_get_property);
- int sb_pt_monitor(struct sb_pt *pt, int chg_src)
- {
- if (!pt)
- return -EINVAL;
- mutex_lock(&pt->mlock);
- if (!check_state(pt)) {
- clear_state(pt, PT_STEP_NONE);
- goto end_monitor;
- }
- pt_log("start - step = %s, chg_src = %d, dc_status = %d\n", get_step_str(pt->step), chg_src, pt->dc_status);
- switch (pt->step) {
- case PT_STEP_NONE:
- push_start_work(pt, pt->start_delay);
- pt->chg_src = chg_src;
- break;
- case PT_STEP_INIT:
- if (pt->ref_cap <= 0) {
- union power_supply_propval value = { 0, };
- value.intval = SEC_FUELGAUGE_CAPACITY_TYPE_DYNAMIC_SCALE;
- psy_do_property(pt->fg_name, get,
- POWER_SUPPLY_PROP_CAPACITY, value);
- pt->ref_cap = value.intval;
- pt_log("update ref_cap = %d\n", pt->ref_cap);
- if ((chg_src == SEC_CHARGING_SOURCE_DIRECT) &&
- (pt->ref_cap > pt->fixed_sc_cap)) {
- /* reset chg src to switching charger */
- sec_votef(CHGEN_VOTE_NAME, VOTER_PASS_THROUGH, true, SEC_BAT_CHG_MODE_CHARGING_OFF);
- pt->step = PT_STEP_PRESET;
- break;
- }
- }
- if (chg_src == SEC_CHARGING_SOURCE_SWITCHING) {
- pt->step = PT_STEP_PRESET;
- } else {
- if (check_preset_state(pt->dc_status))
- pt->step = PT_STEP_PRESET;
- else
- push_start_work(pt, pt->init_delay);
- }
- pt->chg_src = chg_src;
- break;
- case PT_STEP_PRESET:
- {
- union power_supply_propval value = { 0, };
- int iv, icl, fcc, chgen;
- if ((chg_src == SEC_CHARGING_SOURCE_DIRECT) &&
- (pt->ref_cap > pt->fixed_sc_cap))
- chg_src = SEC_CHARGING_SOURCE_SWITCHING;
- pt->chg_src = chg_src;
- pt->step = PT_STEP_ADJUST;
- if (chg_src == SEC_CHARGING_SOURCE_SWITCHING) {
- iv = SEC_INPUT_VOLTAGE_5V;
- icl = fcc = pt->max_icl;
- } else {
- iv = SEC_INPUT_VOLTAGE_APDO;
- icl = fcc = pt->max_icl * pt->user_mode;
- }
- chgen = SEC_BAT_CHG_MODE_PASS_THROUGH;
- sec_votef(IV_VOTE_NAME, VOTER_PASS_THROUGH, true, iv);
- sec_votef(ICL_VOTE_NAME, VOTER_PASS_THROUGH, true, icl);
- sec_votef(FCC_VOTE_NAME, VOTER_PASS_THROUGH, true, fcc);
- sec_votef(CHGEN_VOTE_NAME, VOTER_PASS_THROUGH, true, chgen);
- if (chg_src == SEC_CHARGING_SOURCE_SWITCHING) {
- value.intval = pt->user_mode;
- psy_do_property(pt->sc_name, set,
- POWER_SUPPLY_EXT_PROP_PASS_THROUGH_MODE, value);
- /* skip adjust work */
- pt->step = PT_STEP_MONITOR;
- } else {
- value.intval = pt->user_mode;
- psy_do_property(pt->dc_name, set,
- POWER_SUPPLY_EXT_PROP_PASS_THROUGH_MODE, value);
- sec_pd_detach_with_cc(1);
- value.intval = pt->vfloat;
- psy_do_property(pt->dc_name, set,
- POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, value);
- /* set adj state */
- pt->adj_state = check_cap(pt);
- /* start adj work */
- __pm_stay_awake(pt->ws);
- queue_delayed_work(pt->wq, &pt->adjust_work, msecs_to_jiffies(pt->adj_delay));
- }
- set_misc_event(true);
- }
- break;
- case PT_STEP_ADJUST:
- /* not working */
- break;
- case PT_STEP_MONITOR:
- {
- int cap_state = CAP_NORMAL;
- if (pt->chg_src != chg_src) {
- clear_state(pt, PT_STEP_INIT);
- break;
- }
- cap_state = check_cap(pt);
- if (pt->chg_src == SEC_CHARGING_SOURCE_SWITCHING) {
- if (cap_state == CAP_LOW)
- sec_votef(CHGEN_VOTE_NAME, VOTER_PASS_THROUGH, true, SEC_BAT_CHG_MODE_CHARGING);
- else
- sec_votef(CHGEN_VOTE_NAME, VOTER_PASS_THROUGH, true, SEC_BAT_CHG_MODE_PASS_THROUGH);
- } else {
- set_dc_ta_volt(pt, cap_state);
- }
- }
- break;
- case PT_STEP_RESET:
- break;
- default:
- break;
- }
- end_monitor:
- pt_log("end - step = %s\n", get_step_str(pt->step));
- mutex_unlock(&pt->mlock);
- return 0;
- }
- EXPORT_SYMBOL(sb_pt_monitor);
- int sb_pt_check_chg_src(struct sb_pt *pt, int chg_src)
- {
- if (!pt)
- return chg_src;
- if ((pt->step != PT_STEP_NONE) &&
- (pt->ref_cap > pt->fixed_sc_cap))
- return SEC_CHARGING_SOURCE_SWITCHING;
- return chg_src;
- }
- EXPORT_SYMBOL(sb_pt_check_chg_src);
|