123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- /*
- * mfc_cmfet.c
- * Samsung Mobile MFC CMFET Module
- *
- * Copyright (C) 2023 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/of.h>
- #include <linux/slab.h>
- #include <linux/mutex.h>
- #include <linux/device.h>
- #include <linux/module.h>
- #include "cps4038_charger.h"
- #define cmfet_log(str, ...) pr_info("[MFC-CMFET]:%s: "str, __func__, ##__VA_ARGS__)
- struct mfc_cmfet {
- struct device *parent;
- mfc_set_cmfet cb_func;
- struct mutex lock;
- union mfc_cmfet_state state;
- /* threshold */
- bool unknown_cmb_ctrl;
- unsigned int high_swell_cc_cv_thr;
- };
- static int mfc_cmfet_parse_dt(struct device_node *np, struct mfc_cmfet *cmfet)
- {
- int ret = 0;
- cmfet->unknown_cmb_ctrl = of_property_read_bool(np, "battery,unknown_cmb_ctrl");
- ret = of_property_read_u32(np, "high_swell_cc_cv_thr", &cmfet->high_swell_cc_cv_thr);
- if (ret < 0)
- cmfet->high_swell_cc_cv_thr = 70;
- cmfet_log("unknown_cmb_ctrl = %d, high_swell_cc_cv_thr = %d\n",
- cmfet->unknown_cmb_ctrl, cmfet->high_swell_cc_cv_thr);
- return 0;
- }
- struct mfc_cmfet *mfc_cmfet_init(struct device *dev, mfc_set_cmfet cb_func)
- {
- struct mfc_cmfet *cmfet;
- int ret = 0;
- if (IS_ERR_OR_NULL(dev) ||
- (cb_func == NULL))
- return ERR_PTR(-EINVAL);
- cmfet = kzalloc(sizeof(struct mfc_cmfet), GFP_KERNEL);
- if (!cmfet)
- return ERR_PTR(-ENOMEM);
- ret = mfc_cmfet_parse_dt(dev->of_node, cmfet);
- if (ret < 0) {
- kfree(cmfet);
- return ERR_PTR(ret);
- }
- mutex_init(&cmfet->lock);
- cmfet->parent = dev;
- cmfet->cb_func = cb_func;
- cmfet->state.value = 0;
- cmfet_log("DONE!!\n");
- return cmfet;
- }
- EXPORT_SYMBOL(mfc_cmfet_init);
- int mfc_cmfet_init_state(struct mfc_cmfet *cmfet)
- {
- if (IS_ERR(cmfet))
- return -EINVAL;
- mutex_lock(&cmfet->lock);
- if (cmfet->state.value != 0) {
- cmfet->state.value = 0;
- cmfet->cb_func(cmfet->parent, &cmfet->state, false, false);
- }
- mutex_unlock(&cmfet->lock);
- return 0;
- }
- EXPORT_SYMBOL(mfc_cmfet_init_state);
- int mfc_cmfet_refresh(struct mfc_cmfet *cmfet)
- {
- if (IS_ERR(cmfet))
- return -EINVAL;
- mutex_lock(&cmfet->lock);
- if (cmfet->state.value != 0)
- cmfet->cb_func(cmfet->parent, &cmfet->state, cmfet->state.cma, cmfet->state.cmb);
- mutex_unlock(&cmfet->lock);
- return 0;
- }
- EXPORT_SYMBOL(mfc_cmfet_refresh);
- static void set_init_state(union mfc_cmfet_state *state, bool cma, bool cmb)
- {
- state->cma = cma;
- state->cmb = cmb;
- }
- static unsigned long long check_tx_default(struct mfc_cmfet *cmfet, union mfc_cmfet_state *state)
- {
- if (state->high_swell)
- state->cmb = (state->bat_cap > cmfet->high_swell_cc_cv_thr);
- if (state->full)
- state->cmb = true;
- if (state->chg_done)
- state->cmb = false;
- return state->value;
- }
- static unsigned long long check_tx_unknown(struct mfc_cmfet *cmfet, union mfc_cmfet_state *state)
- {
- set_init_state(state, true, (cmfet->unknown_cmb_ctrl));
- return state->value;
- }
- static unsigned long long check_tx_p1100(struct mfc_cmfet *cmfet, union mfc_cmfet_state *state)
- {
- set_init_state(state, true, true);
- if (state->vout <= 5500)
- state->cmb = false;
- if (state->chg_done)
- state->cmb = false;
- return state->value;
- }
- static unsigned long long check_tx_n5200(struct mfc_cmfet *cmfet, union mfc_cmfet_state *state)
- {
- set_init_state(state, true, false);
- return check_tx_default(cmfet, state);
- }
- static unsigned long long check_tx_p5200(struct mfc_cmfet *cmfet, union mfc_cmfet_state *state)
- {
- set_init_state(state, true, true);
- if (state->auth)
- state->cmb = false;
- return check_tx_default(cmfet, state);
- }
- static unsigned long long check_cmfet_state(struct mfc_cmfet *cmfet, union mfc_cmfet_state *state)
- {
- switch (state->tx_id) {
- case TX_ID_UNKNOWN:
- return check_tx_unknown(cmfet, state);
- case TX_ID_P1100_PAD:
- return check_tx_p1100(cmfet, state);
- case TX_ID_N5200_V_PAD:
- case TX_ID_N5200_H_PAD:
- return check_tx_n5200(cmfet, state);
- case TX_ID_P5200_PAD:
- return check_tx_p5200(cmfet, state);
- default:
- break;
- }
- set_init_state(state, true, true);
- return check_tx_default(cmfet, state);
- }
- static bool is_changed_state(union mfc_cmfet_state *state1, union mfc_cmfet_state *state2)
- {
- return (state1->cma != state2->cma) || (state1->cmb != state2->cmb);
- }
- static int update_cmfet_state(struct mfc_cmfet *cmfet, union mfc_cmfet_state *state)
- {
- state->value = check_cmfet_state(cmfet, state);
- if (is_changed_state(state, &cmfet->state))
- cmfet->cb_func(cmfet->parent, state, state->cma, state->cmb);
- cmfet->state.value = state->value;
- return 0;
- }
- int mfc_cmfet_set_tx_id(struct mfc_cmfet *cmfet, int tx_id)
- {
- if (IS_ERR(cmfet) ||
- (tx_id < 0) || (tx_id >= 256))
- return -EINVAL;
- mutex_lock(&cmfet->lock);
- if (cmfet->state.tx_id != tx_id) {
- union mfc_cmfet_state temp = { cmfet->state.value, };
- temp.tx_id = tx_id;
- update_cmfet_state(cmfet, &temp);
- }
- mutex_unlock(&cmfet->lock);
- return 0;
- }
- EXPORT_SYMBOL(mfc_cmfet_set_tx_id);
- int mfc_cmfet_set_bat_cap(struct mfc_cmfet *cmfet, int bat_cap)
- {
- if (IS_ERR(cmfet) ||
- (bat_cap < 0) || (bat_cap > 100))
- return -EINVAL;
- mutex_lock(&cmfet->lock);
- if (cmfet->state.bat_cap != bat_cap) {
- union mfc_cmfet_state temp = { cmfet->state.value, };
- temp.bat_cap = bat_cap;
- update_cmfet_state(cmfet, &temp);
- }
- mutex_unlock(&cmfet->lock);
- return 0;
- }
- EXPORT_SYMBOL(mfc_cmfet_set_bat_cap);
- int mfc_cmfet_set_vout(struct mfc_cmfet *cmfet, int vout)
- {
- if (IS_ERR(cmfet) ||
- (vout <= 0))
- return -EINVAL;
- mutex_lock(&cmfet->lock);
- if (cmfet->state.vout != vout) {
- union mfc_cmfet_state temp = { cmfet->state.value, };
- temp.vout = vout;
- update_cmfet_state(cmfet, &temp);
- }
- mutex_unlock(&cmfet->lock);
- return 0;
- }
- EXPORT_SYMBOL(mfc_cmfet_set_vout);
- int mfc_cmfet_set_high_swell(struct mfc_cmfet *cmfet, bool state)
- {
- if (IS_ERR(cmfet))
- return -EINVAL;
- mutex_lock(&cmfet->lock);
- if (cmfet->state.high_swell != state) {
- union mfc_cmfet_state temp = { cmfet->state.value, };
- temp.high_swell = state;
- update_cmfet_state(cmfet, &temp);
- }
- mutex_unlock(&cmfet->lock);
- return 0;
- }
- EXPORT_SYMBOL(mfc_cmfet_set_high_swell);
- int mfc_cmfet_set_full(struct mfc_cmfet *cmfet, bool full)
- {
- if (IS_ERR(cmfet))
- return -EINVAL;
- mutex_lock(&cmfet->lock);
- if (cmfet->state.full != full) {
- union mfc_cmfet_state temp = { cmfet->state.value, };
- temp.full = full;
- update_cmfet_state(cmfet, &temp);
- }
- mutex_unlock(&cmfet->lock);
- return 0;
- }
- EXPORT_SYMBOL(mfc_cmfet_set_full);
- int mfc_cmfet_set_chg_done(struct mfc_cmfet *cmfet, bool chg_done)
- {
- if (IS_ERR(cmfet))
- return -EINVAL;
- mutex_lock(&cmfet->lock);
- if (cmfet->state.chg_done != chg_done) {
- union mfc_cmfet_state temp = { cmfet->state.value, };
- temp.chg_done = chg_done;
- update_cmfet_state(cmfet, &temp);
- }
- mutex_unlock(&cmfet->lock);
- return 0;
- }
- EXPORT_SYMBOL(mfc_cmfet_set_chg_done);
- int mfc_cmfet_set_auth(struct mfc_cmfet *cmfet, bool auth)
- {
- if (IS_ERR(cmfet))
- return -EINVAL;
- mutex_lock(&cmfet->lock);
- if (cmfet->state.auth != auth) {
- union mfc_cmfet_state temp = { cmfet->state.value, };
- temp.auth = auth;
- update_cmfet_state(cmfet, &temp);
- }
- mutex_unlock(&cmfet->lock);
- return 0;
- }
- EXPORT_SYMBOL(mfc_cmfet_set_auth);
- int mfc_cmfet_get_state(struct mfc_cmfet *cmfet, union mfc_cmfet_state *state)
- {
- if (IS_ERR(cmfet) ||
- (state == NULL))
- return -EINVAL;
- mutex_lock(&cmfet->lock);
- state->value = cmfet->state.value;
- mutex_unlock(&cmfet->lock);
- return 0;
- }
- EXPORT_SYMBOL(mfc_cmfet_get_state);
|