diff --git a/drivers/power/fet-control/fet_control.c b/drivers/power/fet-control/fet_control.c index 2fe17f6d975b..3849b8c44afb 100755 --- a/drivers/power/fet-control/fet_control.c +++ b/drivers/power/fet-control/fet_control.c @@ -35,20 +35,19 @@ #include #include #include -#include -#define RBALANCE_VDIFF_MV 200 +#define RBALANCE_VDIFF_MV 100 +#define MAIN_MV_MID_LO 3600 +#define MAIN_MV_MID_HI 3800 +#define MAIN_CURR_SWITCH 500 #define GPIO_SET_DELAY 50 #define CHRG_FULLCURR_EN 1 -#define CHRG_FULLCURR_DIS 0 #define HBDLY_DISCHARGE_MS 30000 #define HBDLY_CHARGE_MS 6000 static struct fet_control_data { struct device *dev; struct power_supply *main_batt_psy; - struct power_supply *usb_psy; - struct notifier_block ps_notif; struct delayed_work update; bool init_done; bool ps_is_present; @@ -57,14 +56,11 @@ static struct fet_control_data { int battplus_en_gpio; int balance_en_n_gpio; int chrg_fullcurr_en_gpio; - int vbus_ocp_fault_n_gpio; - struct iio_channel *vbatt2_sns_chan; } fetControlData; int battplus_state = -1; int balance_state = -1; int fullcurr_state = -1; -int ocp_fault_n_state = -1; static int get_ps_int_prop(struct power_supply *psy, enum power_supply_property prop) { @@ -183,32 +179,6 @@ static int set_fullcurr_state(const char *val, const struct kernel_param *kp) return 0; } -static int set_ocp_fault_n_state(const char *val, const struct kernel_param *kp) -{ - int rc; - long mode; - - if (!fetControlData.init_done) - return -ENODEV; - - rc = kstrtol(val, 0, &mode); - if (rc) - return rc; - - rc = update_state_gpio(fetControlData.vbus_ocp_fault_n_gpio, !!mode); - if (rc) { - pr_err("Update fet-ctl gpio [%d] failed\n", fetControlData.vbus_ocp_fault_n_gpio); - return rc; - } else { - fullcurr_state = !!mode; - pr_debug("Set using vbus_ocp_fault_n gpio[%d], VAL:[%d]\n", - fetControlData.vbus_ocp_fault_n_gpio, - gpio_get_value(fetControlData.vbus_ocp_fault_n_gpio)); - } - - return 0; -} - static struct kernel_param_ops battplus_ops = { .set = &set_battplus_state, @@ -227,12 +197,6 @@ static struct kernel_param_ops fullcurr_ops = .get = param_get_int, }; -static struct kernel_param_ops ocpfault_ops = -{ - .set = &set_ocp_fault_n_state, - .get = param_get_int, -}; - module_param_cb(battplus_state, &battplus_ops, &battplus_state, @@ -251,182 +215,72 @@ module_param_cb(fullcurr_state, S_IRUGO | S_IWUSR ); -module_param_cb(ocp_fault_n_state, - &ocpfault_ops, - &ocp_fault_n_state, - S_IRUGO | S_IWUSR -); - -static int mmi_is_factory(void) -{ - const char *bootargs_str = NULL; - char *kvpair = NULL; - char *value = NULL; - int ret = -1; - struct device_node *n = of_find_node_by_path("/chosen"); - size_t bootargs_str_len = 0; - - if (n == NULL) - goto ret; - - if (of_property_read_string(n, "mmi,bootconfig", &bootargs_str) != 0) - goto putnode; - - bootargs_str_len = strlen(bootargs_str); - kvpair = strnstr(bootargs_str, "androidboot.mode=", strlen(bootargs_str)); - if (kvpair) { // found key - value = strchr(kvpair, '=') + 1; - if (!strncmp(value, "mot-factory", 11)) - ret = 1; - else - ret = 0; - } - -putnode: - of_node_put(n); -ret: - return ret; -} - static void update_work(struct work_struct *work) { struct fet_control_data *data = container_of(work, struct fet_control_data, update.work); - int main_curr, main_mv, flip_mv = 0, usbtype; - int main_chg = 1, rc = 0; + int main_curr, main_mv; + int main_dischg = -1; int hb_sched_time = HBDLY_DISCHARGE_MS; - int vbatt2_sns_uv = -EINVAL; - const char * usb_types[] = {"UNKNOWN","SDP","DCP","CDP","ACA","Type-C","PD","PD_DRP"}; - fullcurr_state = CHRG_FULLCURR_DIS; - - usbtype = get_ps_int_prop(data->usb_psy, - POWER_SUPPLY_PROP_USB_TYPE); - pr_info("USB-TYPE found:%d [%s]\n", usbtype,usb_types[usbtype] ); - - /* For no Charger connected & battfet already closed, nothing more to be done */ - if (mmi_is_factory()) { - pr_err("Factory Mode- Cancel Work.. \n"); - cancel_delayed_work(&data->update); - return; - } else if (usbtype == POWER_SUPPLY_USB_TYPE_UNKNOWN && battplus_state) { - pr_err("BATTFET Closed & Not Charging- Cancel Work..\n"); + fullcurr_state = CHRG_FULLCURR_EN; + if (battplus_state) { + pr_info("BATTFET Closed- Ending Work..\n"); cancel_delayed_work(&data->update); return; } - /* VMain in mV */ + /*flip_mv = get_ps_int_prop(data->flip_batt_psy, + POWER_SUPPLY_PROP_VOLTAGE_NOW); + flip_mv /= 1000;*/ + main_mv = get_ps_int_prop(data->main_batt_psy, POWER_SUPPLY_PROP_VOLTAGE_NOW); main_mv /= 1000; - /* Main current in uA */ + /* Main current sysfs already in mA */ main_curr = get_ps_int_prop(data->main_batt_psy, POWER_SUPPLY_PROP_CURRENT_NOW); - if (main_curr > 0) + if (main_curr > 0) { pr_info("Charging Main\n"); - else - main_chg = -1; + main_dischg = 1; + } data->main_chg_curr_max = get_ps_int_prop(data->main_batt_psy, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN); + data->main_chg_curr_max /= 1000; if (data->main_chg_curr_max < 0) { pr_err("Failed to get Main Max chrg curr\n"); return; } - ocp_fault_n_state = gpio_get_value(fetControlData.vbus_ocp_fault_n_gpio); - pr_info("ocp_fault_n GPIO:[%d], VAL:[%d]\n", - fetControlData.vbus_ocp_fault_n_gpio, ocp_fault_n_state); - - /* Leave FULLCURR_DIS until charger is connected */ - if (usbtype != POWER_SUPPLY_USB_TYPE_UNKNOWN) { - if ( (main_chg * main_curr > data->main_chg_curr_max / 2) || - !ocp_fault_n_state ) { - fullcurr_state = CHRG_FULLCURR_DIS; - pr_err("WARNING! Main-OC or OCP-TRIP: Main_curr:%d, ocp_fault_n:%d\n", - main_curr, ocp_fault_n_state); - } else { - fullcurr_state = CHRG_FULLCURR_EN; - } - } - - /* Read the ADC pm8350b_vbatt2_sns div3, scale *3 and to mV */ - rc = iio_read_channel_processed(fetControlData.vbatt2_sns_chan, &vbatt2_sns_uv); - if (rc < 0) { - pr_err("Error Reading pm8350b_vbatt2_sns_voltage- rc:%d\n", rc); - return; - } else { - pr_info("SUCCESS reading pm8350b_vbatt2_sns_voltage- VAL-uV:%d\n", vbatt2_sns_uv); - flip_mv = (3 * vbatt2_sns_uv) / 1000; - } - pr_info("Main_curr:%d, main_Ichg_MAX:%d\n", main_curr, data->main_chg_curr_max); - pr_err("Flip-Vbatt: %d, Main-Vbatt: %d\n", flip_mv, main_mv); + pr_info("Flip-Vbatt: --, Main-Vbatt: %d\n", main_mv); /* FET paths set in Batt discharge state */ - if (main_chg == -1) { + if (main_dischg == -1) { /* Leave Balance dflt-en & toggle in/out parallel low-Z battplus fet */ balance_state = 0; - if ((main_mv - flip_mv) < RBALANCE_VDIFF_MV) { + /*if ((main_mv - flip_mv) < RBALANCE_VDIFF_MV) { + battplus_state = 1;*/ + if ( (main_mv >= MAIN_MV_MID_LO && main_mv <= MAIN_MV_MID_HI) && + (main_dischg * main_curr/1000 < MAIN_CURR_SWITCH) ) { battplus_state = 1; pr_info("battplus-EN: %d\n", battplus_state); } else { battplus_state = 0; pr_info("battplus-DIS: %d\n", battplus_state); + schedule_delayed_work(&data->update, msecs_to_jiffies(hb_sched_time)); } - } else { // Full Charging - hb_sched_time = HBDLY_CHARGE_MS; - pr_info("FASTCHG\n"); } /* Update GPIO controls */ update_state_gpio(fetControlData.battplus_en_gpio, battplus_state); update_state_gpio(fetControlData.balance_en_n_gpio, balance_state); update_state_gpio(fetControlData.chrg_fullcurr_en_gpio, fullcurr_state); - //update_state_gpio(fetControlData.vbus_ocp_fault_n_gpio, ocp_fault_n_state); - schedule_delayed_work(&data->update, msecs_to_jiffies(hb_sched_time)); } -static int ps_notify_callback(struct notifier_block *nb, - unsigned long event, void *p) -{ - struct fet_control_data *data = container_of(nb, struct fet_control_data, ps_notif); - struct power_supply *psy = p; - union power_supply_propval pval = {0}; - int retval; - bool present_ps; - - if ((event == PSY_EVENT_PROP_CHANGED) && - psy && psy->desc->get_property && psy->desc->name && - !strncmp(psy->desc->name, "usb", sizeof("usb")) && data) { - pr_info("psy notif: event = %lu\n", event); - - retval = power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE, - &pval); - if (retval) { - pr_err("%s psy get property failed, ERR: %d\n", psy->desc->name, retval); - return retval; - } - present_ps = (pval.intval) ? true : false; - pr_info("%s is %s\n", psy->desc->name, - (present_ps) ? "present" : "not present"); - - if (event == PSY_EVENT_PROP_CHANGED) { - if (data->ps_is_present == present_ps) { - pr_info("ps present state unchanged\n"); - return 0; - } - } - data->ps_is_present = present_ps; - - cancel_delayed_work(&data->update); - schedule_delayed_work(&data->update, msecs_to_jiffies(3000)); - } - - return 0; -} static int parse_dt(struct device_node *node) { @@ -437,7 +291,7 @@ static int parse_dt(struct device_node *node) if (!rc && main_batt_psy_name) { fetControlData.main_batt_psy = power_supply_get_by_name(main_batt_psy_name); if (!fetControlData.main_batt_psy) { - pr_debug("Could not get main batt psy, maybe we are early - defer."); + pr_debug("Could not get flip batt psy and main batt psy, maybe we are early - defer."); return -EPROBE_DEFER; } } @@ -463,13 +317,6 @@ static int parse_dt(struct device_node *node) return -ENODEV; } - fetControlData.vbus_ocp_fault_n_gpio = of_get_named_gpio(node, - "mmi,vbus-ocp-fault-n-gpio", 0); - if (!gpio_is_valid(fetControlData.vbus_ocp_fault_n_gpio)) { - pr_err("ocp-fault-gpio is not valid!\n"); - return -ENODEV; - } - return rc; } @@ -487,21 +334,6 @@ static int fet_control_probe(struct platform_device *pdev) goto fail; } - fetControlData.usb_psy = power_supply_get_by_name("usb"); - if (!fetControlData.usb_psy) { - pr_debug("Could not get usb psy, maybe we are early - defer."); - return -EPROBE_DEFER; - } - - /* Get the ADC device instance pm8350b_vbatt2_sns, gpio3_pu0_div3 */ - fetControlData.vbatt2_sns_chan = iio_channel_get(fetControlData.dev, "pm8350b_vbatt2_sns"); - if (!fetControlData.vbatt2_sns_chan) { - pr_err("Error Getting pm8350b_vbatt2_sns_voltage channel- rc:%d\n",rc); - return -EINVAL; - } else { - pr_info("Found pm8350b_vbatt2_sns voltage channel\n"); - } - rc = gpio_request(fetControlData.battplus_en_gpio, "mmi,flip_battplus_en_gpio"); if (rc) { pr_err("Failed request battplus_en_gpio\n"); @@ -520,12 +352,6 @@ static int fet_control_probe(struct platform_device *pdev) goto fail; } - rc = gpio_request(fetControlData.vbus_ocp_fault_n_gpio, "mmi,vbus-ocp-fault-n-gpio"); - if (rc) { - pr_err("Failed request vbus-ocp-fault-n-gpio\n"); - goto fail; - } - /* Set default Flip Battery Path FETs: battplus path disable*/ rc = gpio_direction_output(fetControlData.battplus_en_gpio, 0); //Path Disabled if (rc) { @@ -548,14 +374,7 @@ static int fet_control_probe(struct platform_device *pdev) pr_err("Unable to set DIR/VAL chrg_fullcurr_en_gpio [%d]\n", fetControlData.chrg_fullcurr_en_gpio); goto fail; } - fullcurr_state = CHRG_FULLCURR_DIS; - - /* Set OCP_FAULT input */ - rc = gpio_direction_input(fetControlData.vbus_ocp_fault_n_gpio); - if (rc) { - pr_err("Unable to set DIR vbus_ocp_fault_n [%d]\n", fetControlData.vbus_ocp_fault_n_gpio); - goto fail; - } + fullcurr_state = CHRG_FULLCURR_EN; pr_info("Flip_battplus_en Init GPIO:[%d], VAL:[%d]\n", fetControlData.battplus_en_gpio, @@ -566,16 +385,6 @@ static int fet_control_probe(struct platform_device *pdev) pr_info("chrg_fullcurr Init GPIO:[%d], VAL:[%d]\n", fetControlData.chrg_fullcurr_en_gpio, gpio_get_value(fetControlData.chrg_fullcurr_en_gpio) ); - pr_info("ocp_fault_n Init GPIO:[%d], VAL:[%d]\n", - fetControlData.vbus_ocp_fault_n_gpio, - gpio_get_value(fetControlData.vbus_ocp_fault_n_gpio) ); - - // Notify on plug/unplug - fetControlData.ps_notif.notifier_call = ps_notify_callback; - if (power_supply_reg_notifier(&fetControlData.ps_notif)) { - pr_err("Failed to register notifier\n"); - goto fail; - } // Work to update the fet & charge current states. INIT_DELAYED_WORK(&fetControlData.update, update_work); @@ -592,11 +401,9 @@ static int fet_control_remove(struct platform_device *pdev) if (fetControlData.init_done) { cancel_delayed_work(&fetControlData.update); - power_supply_unreg_notifier(&fetControlData.ps_notif); gpio_free(fetControlData.battplus_en_gpio); gpio_free(fetControlData.balance_en_n_gpio); gpio_free(fetControlData.chrg_fullcurr_en_gpio); - gpio_free(fetControlData.vbus_ocp_fault_n_gpio); } return 0;