static void sec_bat_initial_check(void) { union power_supply_propval value; switch (abb_get_cable_status()) { case CABLE_TYPE_AC: value.intval = POWER_SUPPLY_TYPE_MAINS; break; case CABLE_TYPE_MISC: value.intval = POWER_SUPPLY_TYPE_MISC; break; case CABLE_TYPE_USB: value.intval = POWER_SUPPLY_TYPE_USB; break; case CABLE_TYPE_CARDOCK: value.intval = POWER_SUPPLY_TYPE_CARDOCK; break; case CABLE_TYPE_NONE: value.intval = POWER_SUPPLY_TYPE_BATTERY; break; default: pr_err("%s: invalid cable :%d\n", __func__, abb_get_cable_status()); return; } psy_do_property("battery", set, POWER_SUPPLY_PROP_ONLINE, value); }
static bool sec_bat_check_by_psy(struct sec_battery_info *battery) { char *psy_name; union power_supply_propval value; bool ret; ret = true; switch (battery->pdata->battery_check_type) { case SEC_BATTERY_CHECK_PMIC: psy_name = battery->pdata->pmic_name; break; case SEC_BATTERY_CHECK_FUELGAUGE: psy_name = "sec-fuelgauge"; break; case SEC_BATTERY_CHECK_CHARGER: psy_name = "sec-charger"; break; default: pr_err("%s: Invalid Battery Check Type\n", __func__); ret = false; goto battery_check_error; break; } psy_do_property(psy_name, get, POWER_SUPPLY_PROP_PRESENT, value); ret = (bool)value.intval; battery_check_error: return ret; }
static bool sec_bat_ovp_uvlo_by_psy(struct sec_battery_info *battery) { char *psy_name; union power_supply_propval value; bool ret; ret = true; switch (battery->pdata->ovp_uvlo_check_type) { case SEC_BATTERY_OVP_UVLO_PMICPOLLING: psy_name = battery->pdata->pmic_name; break; case SEC_BATTERY_OVP_UVLO_CHGPOLLING: psy_name = "sec-charger"; break; default: pr_err("%s: Invalid OVP/UVLO Check Type\n", __func__); ret = false; goto ovp_uvlo_check_error; break; } psy_do_property(psy_name, get, POWER_SUPPLY_PROP_HEALTH, value); if (value.intval != POWER_SUPPLY_HEALTH_GOOD) { battery->health = value.intval; ret = false; } ovp_uvlo_check_error: return ret; }
static int otg_accessory_power(bool enable) { u8 on = (u8)!!enable; union power_supply_propval val; struct device_node *np_charger = NULL; char *charger_name; pr_info("otg accessory power = %d\n", on); np_charger = of_find_node_by_name(NULL, "battery"); if (!np_charger) { pr_err("%s: failed to get the battery device node\n", __func__); return 0; } else { if (!of_property_read_string(np_charger, "battery,charger_name", (char const **)&charger_name)) { pr_info("%s: charger_name = %s\n", __func__, charger_name); } else { pr_err("%s: failed to get the charger name\n" , __func__); return 0; } } val.intval = enable; psy_do_property(charger_name, set, POWER_SUPPLY_PROP_CHARGE_OTG_CONTROL, val); return 0; }
void bq51221_wireless_chg_init(struct i2c_client *client) { int data = 0; union power_supply_propval value; struct bq51221_charger_data *charger = i2c_get_clientdata(client); pr_info("%s\n", __func__); psy_do_property("battery", get, POWER_SUPPLY_PROP_CAPACITY, value); /* init I limit(IOREG) */ bq51221_reg_write(client, BQ51221_REG_CURRENT_REGISTER2, BQ51221_IOREG_100_VALUE); data = bq51221_reg_read(client, BQ51221_REG_CURRENT_REGISTER2); pr_info("%s IOREG = 0x%x \n", __func__, data); /* init CEP timing */ /* init RCVD PWR */ /* read pad mode */ bq51221_get_pad_mode(client); pr_info("%s siop = %d \n" ,__func__, charger->pdata->siop_level ); if ((value.intval < charger->pdata->wireless_cc_cv) && (charger->pdata->pad_mode == BQ51221_PAD_MODE_WPC) && (charger->pdata->siop_level == 100) && !charger->pdata->default_voreg) { /* set VOREG set 5.5V*/ bq51221_set_voreg(charger->client, 0); } else { /* init VOREG with default value */ bq51221_set_voreg(charger->client, 1); } }
static int SM5414_get_charging_status(struct i2c_client *client) { int status = POWER_SUPPLY_STATUS_UNKNOWN; struct sec_charger_info *charger = i2c_get_clientdata(client); int nCHG; u8 int2, chg_en; union power_supply_propval value; SM5414_i2c_read(client, SM5414_INT2, &int2); SM5414_i2c_read(client, SM5414_CTRL, &chg_en); if((int2 & SM5414_INT2_DONE) || (int2 & SM5414_INT2_TOPOFF)) { psy_do_property(charger->pdata->fuelgauge_name, get, POWER_SUPPLY_PROP_CAPACITY, value); if ((value.intval > 96) && (charger->cable_type != POWER_SUPPLY_TYPE_BATTERY)) { status = POWER_SUPPLY_STATUS_FULL; charger->is_fullcharged = true; dev_info(&client->dev, "%s : Power Supply Full\n", __func__); } } else if (chg_en & CHARGE_EN) { nCHG = gpio_get_value(charger->pdata->chg_gpio_en); if ((nCHG) || (charger_health != POWER_SUPPLY_HEALTH_GOOD)) status = POWER_SUPPLY_STATUS_DISCHARGING; else status = POWER_SUPPLY_STATUS_CHARGING; } else { status = POWER_SUPPLY_STATUS_DISCHARGING; } return (int)status; }
int bq51221_set_voreg(struct i2c_client *client, int default_value) { u8 data = 0; int ret = 0; int retry_cnt =0; union power_supply_propval value; struct bq51221_charger_data *charger = i2c_get_clientdata(client); return 0; // concept chagned, vout is always 5V if (charger->pdata->pad_mode == BQ51221_PAD_MODE_PMA) { pr_info("%s PMA MODE, do not set Voreg \n", __func__); return 0; } psy_do_property("battery", get, POWER_SUPPLY_PROP_CAPACITY, value); if ((value.intval >= charger->pdata->wireless_cc_cv) && !default_value) default_value = 1; if (default_value) { /* init VOREG with default value */ ret = bq51221_reg_write(client, BQ51221_REG_CURRENT_REGISTER, 0x01); if(ret < 0) { while(retry_cnt++ < 3) { msleep(50); pr_debug("%s retry_cnt = %d, ret =%d \n",__func__, retry_cnt, ret); /* init VOREG with default value */ ret = bq51221_reg_write(client, BQ51221_REG_CURRENT_REGISTER, 0x01); data = bq51221_reg_read(client, BQ51221_REG_CURRENT_REGISTER); if(ret >= 0) { pr_debug("%s VOREG = 0x%x \n", __func__, data); break; } } } data = bq51221_reg_read(client, BQ51221_REG_CURRENT_REGISTER); pr_info("%s VOREG = 0x%x 5.0V, cnt(%d)\n", __func__, data, retry_cnt); } else { ret = bq51221_reg_write(client, BQ51221_REG_CURRENT_REGISTER, 0x02); if(ret < 0) { while(retry_cnt++ < 3) { msleep(50); pr_debug("%s retry_cnt = %d, ret =%d \n",__func__, retry_cnt, ret); /* init VOREG with default value */ ret = bq51221_reg_write(client, BQ51221_REG_CURRENT_REGISTER, 0x02); data = bq51221_reg_read(client, BQ51221_REG_CURRENT_REGISTER); if(ret >= 0) { pr_debug("%s VOREG = 0x%x \n", __func__, data); break; } } } data = bq51221_reg_read(client, BQ51221_REG_CURRENT_REGISTER); pr_info("%s VOREG = 0x%x 5.5V, cnt(%d)\n", __func__, data, retry_cnt); } return ret; }
static void sec_bat_initial_check(void) { union power_supply_propval value; if (!gpio_get_value_cansleep( PM8921_GPIO_PM_TO_SYS(PMIC_GPIO_TA_nCONNECTED))) psy_do_property("battery", set, POWER_SUPPLY_PROP_ONLINE, value); }
static int adc_get_current(struct i2c_client *client) { union power_supply_propval value; psy_do_property("sec-charger", get, POWER_SUPPLY_PROP_CURRENT_NOW, value); return value.intval; }
static void sec_bat_initial_check(void) { union power_supply_propval value; if (POWER_SUPPLY_TYPE_BATTERY < current_cable_type) { value.intval = current_cable_type<<ONLINE_TYPE_MAIN_SHIFT; psy_do_property("battery", set, POWER_SUPPLY_PROP_ONLINE, value); } else { psy_do_property("sec-charger", get, POWER_SUPPLY_PROP_ONLINE, value); if (value.intval == POWER_SUPPLY_TYPE_WIRELESS) { value.intval = POWER_SUPPLY_TYPE_WIRELESS<<ONLINE_TYPE_MAIN_SHIFT; psy_do_property("battery", set, POWER_SUPPLY_PROP_ONLINE, value); } } }
static void sec_bat_initial_check(void) { union power_supply_propval value; if (POWER_SUPPLY_TYPE_BATTERY != current_cable_type) { value.intval = current_cable_type; psy_do_property("battery", set, POWER_SUPPLY_PROP_ONLINE, value); } }
void cable_initial_check(struct sec_battery_info *battery) { union power_supply_propval value; pr_info("%s : current_cable_type : (%d)\n", __func__, current_cable_type); if (POWER_SUPPLY_TYPE_BATTERY != current_cable_type) { value.intval = current_cable_type; psy_do_property("battery", set, POWER_SUPPLY_PROP_ONLINE, value); } else { psy_do_property(battery->pdata->charger_name, get, POWER_SUPPLY_PROP_ONLINE, value); if (value.intval == POWER_SUPPLY_TYPE_WIRELESS) { value.intval = 1; psy_do_property("wireless", set, POWER_SUPPLY_PROP_ONLINE, value); } } }
static int sec_bat_set_charge( struct sec_battery_info *battery, bool enable) { union power_supply_propval val; int ret; if ((battery->cable_type != POWER_SUPPLY_TYPE_BATTERY) && (battery->health != POWER_SUPPLY_HEALTH_GOOD)) { pr_info("%s: Battery is NOT good!\n", __func__); return -EPERM; } if (enable) { val.intval = battery->cable_type; /*Reset charging start time only in initial charging start */ if (battery->charging_start_time == 0) { battery->charging_start_time = jiffies; battery->charging_next_time = battery->pdata->charging_reset_time; } } else { val.intval = POWER_SUPPLY_TYPE_BATTERY; battery->charging_start_time = 0; battery->charging_passed_time = 0; battery->charging_next_time = 0; battery->full_check_cnt = 0; } battery->temp_high_cnt = 0; battery->temp_low_cnt = 0; battery->temp_recover_cnt = 0; psy_do_property("sec-charger", set, POWER_SUPPLY_PROP_ONLINE, val); psy_do_property("sec-fuelgauge", set, POWER_SUPPLY_PROP_ONLINE, val); return 0; }
static bool sii8240_vbus_present(void) { union power_supply_propval value; psy_do_property("sec-charger", get, POWER_SUPPLY_PROP_ONLINE, value); pr_info("sii8240: sec-charger : %d\n", value.intval); if (value.intval == POWER_SUPPLY_TYPE_BATTERY || value.intval == POWER_SUPPLY_TYPE_WPC) return false; else return true; }
static bool sec_bat_ovp_uvlo_result_callback(int health) { union power_supply_propval value; psy_do_property("sec-charger", get, POWER_SUPPLY_PROP_HEALTH, value); if (value.intval == POWER_SUPPLY_HEALTH_OVERVOLTAGE) { is_ovlo_state = true; } else { is_ovlo_state = false; } return true; }
static void sec_bat_initial_check(void) { union power_supply_propval value; /* check cable by sec_bat_get_cable_type() * for initial check */ value.intval = -1; if (extended_cable_type || !gpio_get_value_cansleep( PM8921_GPIO_PM_TO_SYS(PMIC_GPIO_TA_nCONNECTED))) psy_do_property("battery", set, POWER_SUPPLY_PROP_ONLINE, value); }
/****************************************************************************** * function: tuner_drv_gpio_config_poweron * brief : interruption registration disable control of a driver * date : 2012.12.18 * author : K.Matsumaru(*)(*) * * return : none * input : none * output : none ******************************************************************************/ void tuner_drv_gpio_config_poweron( void ) { #if defined(CONFIG_TMM_CHG_CTRL) union power_supply_propval value; tmm_chg_log("TMM Charge control: Sending TMM Tuner Powered ON Signal\n"); value.intval = TUNER_SWITCHED_ON_SIGNAL; psy_do_property("battery", set, POWER_SUPPLY_PROP_CURRENT_NOW, value); #endif gpio_tlmm_config(GPIO_CFG(isdbtmm_pdata->gpio_spi_di, GPIOMUX_FUNC_1, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(isdbtmm_pdata->gpio_spi_do, GPIOMUX_FUNC_1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(isdbtmm_pdata->gpio_spi_cs, GPIOMUX_FUNC_1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(isdbtmm_pdata->gpio_spi_clk, GPIOMUX_FUNC_1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(isdbtmm_pdata->gpio_int, GPIOMUX_FUNC_1, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(isdbtmm_pdata->gpio_en, GPIOMUX_FUNC_GPIO, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(isdbtmm_pdata->gpio_rst, GPIOMUX_FUNC_GPIO, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(isdbtmm_pdata->gpio_i2c_sda, GPIOMUX_FUNC_3, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(isdbtmm_pdata->gpio_i2c_scl, GPIOMUX_FUNC_3, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), GPIO_CFG_ENABLE); return; }
/*FIXME, need to use more common/proper function for checking a VBUS regardless of H/W charger IC*/ static bool sii8240_vbus_present(void) { bool ret = true; #ifdef MFD_MAX778XX_COMMON union power_supply_propval value; psy_do_property("sec-charger", get, POWER_SUPPLY_PROP_ONLINE, value); pr_info("sec-charger : %d\n", value.intval); if (value.intval == POWER_SUPPLY_TYPE_BATTERY || value.intval == POWER_SUPPLY_TYPE_WIRELESS) ret = false; #else struct sii8240_platform_data *pdata = g_pdata; if (pdata->gpio_ta_int > 0) ret = gpio_get_value_cansleep(pdata->gpio_ta_int) ? false : true; #endif pr_info("VBUS : %s in %s\n", ret ? "IN" : "OUT", __func__); return ret; }
static int adc_get_current(struct i2c_client *client) { union power_supply_propval value; struct sec_fuelgauge_info *fuelgauge = i2c_get_clientdata(client); int current_now; current_now = adc_get_data_by_adc(fuelgauge, get_battery_data(fuelgauge).adc2current_table, get_battery_data(fuelgauge).adc2current_table_size, adc_get_adc_value(fuelgauge, SEC_BAT_ADC_CHANNEL_CURRENT_NOW)); if (!current_now) { psy_do_property("sec-charger", get, POWER_SUPPLY_PROP_CURRENT_NOW, value); current_now = value.intval; } return current_now; }
void bq51221_wireless_chg_init(struct i2c_client *client) { int data = 0; union power_supply_propval value; pr_info("%s\n", __func__); psy_do_property("battery", get, POWER_SUPPLY_PROP_CAPACITY, value); /* init I limit(IOREG) */ bq51221_reg_write(client, BQ51221_REG_CURRENT_REGISTER2, BQ51221_IOREG_100_VALUE); data = bq51221_reg_read(client, BQ51221_REG_CURRENT_REGISTER2); pr_info("%s IOREG = 0x%x \n", __func__, data); /* init CEP timing */ /* init RCVD PWR */ /* read pad mode */ bq51221_get_pad_mode(client); }
static int set_online(int event, int state) { union power_supply_propval val; struct device_node *np_charger = NULL; char *charger_name; if (event == NOTIFY_EVENT_SMTD_EXT_CURRENT) pr_info("request smartdock charging current = %s\n", state ? "1000mA" : "1700mA"); else if (event == NOTIFY_EVENT_MMD_EXT_CURRENT) pr_info("request mmdock charging current = %s\n", state ? "900mA" : "1400mA"); np_charger = of_find_node_by_name(NULL, "battery"); if (!np_charger) { pr_err("%s: failed to get the battery device node\n", __func__); return 0; } else { if (!of_property_read_string(np_charger, "battery,charger_name", (char const **)&charger_name)) { pr_info("%s: charger_name = %s\n", __func__, charger_name); } else { pr_err("%s: failed to get the charger name\n", __func__); return 0; } } if (state) val.intval = POWER_SUPPLY_TYPE_SMART_OTG; else val.intval = POWER_SUPPLY_TYPE_SMART_NOTG; psy_do_property(charger_name, set, POWER_SUPPLY_PROP_ONLINE, val); return 0; }
static void sec_bat_do_fullcharged( struct sec_battery_info *battery) { union power_supply_propval value; if (((battery->pdata->full_check_type == SEC_BATTERY_FULLCHARGED_ADC_DUAL) || (battery->pdata->full_check_type == SEC_BATTERY_FULLCHARGED_FG_CURRENT_DUAL)) && (battery->charging_mode == SEC_BATTERY_CHARGING_NORMAL)) { battery->charging_mode = SEC_BATTERY_CHARGING_2ND; } else { battery->charging_mode = SEC_BATTERY_CHARGING_NONE; sec_bat_set_charge(battery, false); value.intval = POWER_SUPPLY_STATUS_FULL; psy_do_property("sec-fuelgauge", set, POWER_SUPPLY_PROP_STATUS, value); } battery->status = POWER_SUPPLY_STATUS_FULL; }
static int sec_bat_check_cable_callback(void) { union power_supply_propval value; value.intval = 0; psy_do_property("sec-charger", get, POWER_SUPPLY_PROP_CHARGE_COUNTER, value); msleep(500); if (current_cable_type == POWER_SUPPLY_TYPE_BATTERY && value.intval) { pr_info("%s : VBUS IN\n", __func__); return POWER_SUPPLY_TYPE_UARTOFF; } if (current_cable_type == POWER_SUPPLY_TYPE_UARTOFF && !value.intval) { pr_info("%s : VBUS OUT\n", __func__); return POWER_SUPPLY_TYPE_BATTERY; } return current_cable_type; }
static void smb358_check_slow_charging(struct work_struct *work) { struct sec_charger_info *charger = container_of(work, struct sec_charger_info, slow_work.work); u8 i, aicl_data; int aicl_current = 0; union power_supply_propval val; if (charger->pdata->charging_current [charger->cable_type].input_current_limit <= SLOW_CHARGING_CURRENT_STANDARD) { charger->is_slow_charging = true; } else { for(i = 0; i < 10; i++) { msleep(200); smb358_i2c_read(charger->client, SMB358_STATUS_E, &aicl_data); if (aicl_data & 0x10) { /* check AICL complete */ break; } } if (i == 10) { pr_err("%s: aicl not complete, return\n", __func__); charger->is_slow_charging = false; return; } aicl_data &= 0xF; /* get only AICL result field */ switch (aicl_data) { case 0: /* AICL result 300mA */ aicl_current = 300; break; case 1: /* AICL result 500mA */ aicl_current = 500; break; case 2: /* AICL result 700mA */ aicl_current = 700; break; case 3: /* AICL result 1000mA */ aicl_current = 1000; break; case 4: /* AICL result 1200mA */ aicl_current = 1200; break; case 5: /* AICL result 1300mA */ aicl_current = 1300; break; case 6: /* AICL result 1800mA */ aicl_current = 1800; break; case 7: /* AICL result 2000mA */ aicl_current = 2000; break; default: /* etc */ aicl_current = 2000; break; } if (aicl_current <= SLOW_CHARGING_CURRENT_STANDARD) charger->is_slow_charging = true; else charger->is_slow_charging = false; } pr_info("%s: Slow(%d), aicl_current(%d), input_current(%d)\n", __func__, charger->is_slow_charging, aicl_current, charger->pdata->charging_current [charger->cable_type].input_current_limit); psy_do_property("battery", set, POWER_SUPPLY_PROP_CHARGE_TYPE, val); }
static void smb358_charger_function_control( struct i2c_client *client) { struct sec_charger_info *charger = i2c_get_clientdata(client); union power_supply_propval val; int status; u8 data, chgcurrent; union power_supply_propval input_value; psy_do_property("battery", get, POWER_SUPPLY_PROP_STATUS, input_value); status = input_value.intval; if (charger->charging_current < 0) { dev_dbg(&client->dev, "%s : OTG is activated. Ignore command!\n", __func__); return; } psy_do_property("battery", get, POWER_SUPPLY_PROP_HEALTH, input_value); if (input_value.intval == POWER_SUPPLY_HEALTH_UNSPEC_FAILURE) { pr_info("[SMB358] Unspec_failure, charger suspend\n"); smb358_enter_suspend(client); } else if (charger->cable_type == POWER_SUPPLY_TYPE_BATTERY) { /* Charger Disabled */ smb358_set_command(client, SMB358_COMMAND_A, 0xc0); if (status == POWER_SUPPLY_STATUS_FULL) return; pr_info("[SMB358] Set the registers to the default configuration\n"); /* Set the registers to the default configuration */ smb358_set_command(client, SMB358_CHARGE_CURRENT, 0xFE); smb358_set_command(client, SMB358_INPUT_CURRENTLIMIT, 0x74); smb358_set_command(client, SMB358_VARIOUS_FUNCTIONS, 0xD7); data = 0x00; data |= smb358_get_float_voltage_data(charger->pdata->chg_float_voltage); smb358_set_command(client, SMB358_FLOAT_VOLTAGE, data); /* Disable Automatic Recharge */ smb358_set_command(client, SMB358_CHARGE_CONTROL, 0x84); smb358_set_command(client, SMB358_STAT_TIMERS_CONTROL, 0x0F); smb358_set_command(client, SMB358_PIN_ENABLE_CONTROL, 0x09); smb358_set_command(client, SMB358_THERM_CONTROL_A, 0xF0); smb358_set_command(client, SMB358_SYSOK_USB30_SELECTION, 0x08); smb358_set_command(client, SMB358_OTHER_CONTROL_A, 0x01); smb358_set_command(client, SMB358_OTG_TLIM_THERM_CONTROL, 0xF6); smb358_set_command(client, SMB358_LIMIT_CELL_TEMPERATURE_MONITOR, 0xA5); smb358_set_command(client, SMB358_FAULT_INTERRUPT, 0x00); smb358_set_command(client, SMB358_STATUS_INTERRUPT, 0x00); } else { int full_check_type; psy_do_property("battery", get, POWER_SUPPLY_PROP_CHARGE_NOW, val); if (val.intval == SEC_BATTERY_CHARGING_1ST) full_check_type = charger->pdata->full_check_type; else full_check_type = charger->pdata->full_check_type_2nd; smb358_i2c_read(client, SMB358_COMMAND_A, &data); if ((data & 0x10) && charger->pdata->vbus_ctrl_gpio) { int level; /* disable otg & charging */ smb358_clear_reg(client, SMB358_COMMAND_A, 0x12); /* turn off vbus */ gpio_set_value(charger->pdata->vbus_ctrl_gpio, 1); msleep(30); level = gpio_get_value_cansleep(charger->pdata->vbus_ctrl_gpio); pr_info("[SMB358] vbus ctrl gpio %d level %d\n", charger->pdata->vbus_ctrl_gpio, level); /* turn on vbus */ gpio_set_value(charger->pdata->vbus_ctrl_gpio, 0); /* smb358_test_read(client); */ } else if ((data & 0x02) && !((status == POWER_SUPPLY_STATUS_FULL) && ((full_check_type == SEC_BATTERY_FULLCHARGED_CHGGPIO) || (full_check_type == SEC_BATTERY_FULLCHARGED_CHGINT) || (full_check_type == SEC_BATTERY_FULLCHARGED_CHGPSY)))) { chgcurrent = 0; smb358_i2c_read(client, SMB358_CHARGE_CURRENT, &chgcurrent); chgcurrent &= 0xE0; /* get fast charging current */ if (chgcurrent == smb358_get_fast_charging_current_data( charger->charging_current)) { pr_info("[SMB358] Skip the Same charging current setting\n"); schedule_delayed_work(&charger->slow_work, 0); return; } } /* [STEP - 1] ================================================ * Volatile write permission(bit 7) - allow(1) * Charging Enable(bit 1) - Disabled(0, default) * STAT Output(bit 0) - Enabled(0) */ #if defined(CONFIG_MACH_LT02) smb358_set_command(client, SMB358_COMMAND_A, 0xC2); #else smb358_set_command(client, SMB358_COMMAND_A, 0xC0); #endif /* [STEP - 2] ================================================ * USB 5/1(9/1.5) Mode(bit 1) - USB1/USB1.5(0), USB5/USB9(1) * USB/HC Mode(bit 0) - USB5/1 or USB9/1.5 Mode(0) * High-Current Mode(1) */ switch (charger->cable_type) { case POWER_SUPPLY_TYPE_UNKNOWN: case POWER_SUPPLY_TYPE_MAINS: case POWER_SUPPLY_TYPE_USB_CDP: case POWER_SUPPLY_TYPE_MISC: case POWER_SUPPLY_TYPE_WIRELESS: case POWER_SUPPLY_TYPE_CARDOCK: case POWER_SUPPLY_TYPE_UARTOFF: case POWER_SUPPLY_TYPE_LAN_HUB: case POWER_SUPPLY_TYPE_MHL_900: case POWER_SUPPLY_TYPE_MHL_1500: case POWER_SUPPLY_TYPE_SMART_NOTG: /* High-current mode */ data = 0x03; break; case POWER_SUPPLY_TYPE_UPS: case POWER_SUPPLY_TYPE_USB: case POWER_SUPPLY_TYPE_USB_DCP: case POWER_SUPPLY_TYPE_USB_ACA: case POWER_SUPPLY_TYPE_MHL_500: case POWER_SUPPLY_TYPE_MHL_USB: case POWER_SUPPLY_TYPE_SMART_OTG: case POWER_SUPPLY_TYPE_POWER_SHARING: /* USB5 */ data = 0x02; break; default: /* USB1 */ data = 0x00; break; } smb358_set_command(client, SMB358_COMMAND_B, data); /* [STEP 3] Charge Current(0x00) =============================== * Set pre-charge current(bit 4:3) - 450mA(11) * Set fast charge current(bit 7:5) * Set termination current(bit 2:0) */ if (charger->siop_level < 100) { charger->charging_current = charger->charging_current * charger->siop_level / 100; } dev_info(&client->dev, "%s : fast charging current (%dmA)\n", __func__, charger->charging_current); data = 0x18; data |= smb358_get_fast_charging_current_data( charger->charging_current); switch (full_check_type) { case SEC_BATTERY_FULLCHARGED_CHGGPIO: case SEC_BATTERY_FULLCHARGED_CHGINT: case SEC_BATTERY_FULLCHARGED_CHGPSY: if (val.intval == SEC_BATTERY_CHARGING_1ST) { dev_info(&client->dev, "%s : termination current (%dmA)\n", __func__, charger->pdata->charging_current[ charger->cable_type].full_check_current_1st); data |= smb358_get_term_current_limit_data( charger->pdata->charging_current[ charger->cable_type].full_check_current_1st); } else { dev_info(&client->dev, "%s : termination current (%dmA)\n", __func__, charger->pdata->charging_current[ charger->cable_type].full_check_current_2nd); data |= smb358_get_term_current_limit_data( charger->pdata->charging_current[ charger->cable_type].full_check_current_2nd); } break; } smb358_set_command(client, SMB358_CHARGE_CURRENT, data); /* [STEP - 4] ================================================= * Enable(EN) Pin Control(bit 6) - i2c(0), Pin(1) * Pin control(bit 5) - active high(0), active low(1) * USB5/1/HC input State(bit3) - Dual-state input(1) * USB Input Pre-bias(bit 0) - Enable(1) */ data = 0x09; if (charger->pdata->chg_gpio_en) data |= 0x40; if (charger->pdata->chg_polarity_en) data |= 0x20; smb358_set_command(client, SMB358_PIN_ENABLE_CONTROL, data); /* [STEP - 5] =============================================== */ dev_info(&client->dev, "%s : input current (%dmA)\n", __func__, charger->pdata->charging_current [charger->cable_type].input_current_limit); /* Input current limit */ data = 0x00; data |= smb358_get_input_current_limit_data( charger, charger->pdata->charging_current [charger->cable_type].input_current_limit); smb358_set_command(client, SMB358_INPUT_CURRENTLIMIT, data); /* [STEP - 6] ================================================= * Input to System FET(bit 7) - Controlled by Register(1) * Max System voltage(bit 5) - Vflt + 0.1v(0) * AICL(bit 4) - Enalbed(1) * VCHG Function(bit 0) - Enabled(1) */ if (charger->pdata->chg_functions_setting & SEC_CHARGER_NO_GRADUAL_CHARGING_CURRENT) /* disable AICL */ smb358_set_command(client, SMB358_VARIOUS_FUNCTIONS, 0x81); else { /* disable AICL */ smb358_set_command(client, SMB358_VARIOUS_FUNCTIONS, 0x81); /* enable AICL */ smb358_set_command(client, SMB358_VARIOUS_FUNCTIONS, 0x95); } /* [STEP - 7] ================================================= * Pre-charged to Fast-charge Voltage Threshold(Bit 7:6) - 2.3V * Float Voltage(bit 5:0) */ dev_dbg(&client->dev, "%s : float voltage (%dmV)\n", __func__, charger->pdata->chg_float_voltage); data = 0x00; data |= smb358_get_float_voltage_data( charger->pdata->chg_float_voltage); smb358_set_command(client, SMB358_FLOAT_VOLTAGE, data); /* [STEP - 8] ================================================= * Charge control * Automatic Recharge disable(bit 7), * Current Termination disable(bit 6), * BMD disable(bit 5:4), * INOK Output Configuration : Push-pull(bit 3) * APSD disable */ #if defined(CONFIG_MACH_LT02) data = 0xC0; #else data = 0xC1; #endif switch (full_check_type) { case SEC_BATTERY_FULLCHARGED_CHGGPIO: case SEC_BATTERY_FULLCHARGED_CHGINT: case SEC_BATTERY_FULLCHARGED_CHGPSY: /* Enable Current Termination */ data &= 0xB1; break; } smb358_set_command(client, SMB358_CHARGE_CONTROL, data); /* [STEP - 9] ================================================= * STAT active low(bit 7), * Complete charge Timeout(bit 3:2) - Disabled(11) * Pre-charge Timeout(bit 1:0) - Disable(11) */ smb358_set_command(client, SMB358_STAT_TIMERS_CONTROL, 0x1F); #if defined(CONFIG_MACH_LT02) /* [STEP - 10] ================================================= * Mininum System Voltage(bit 6) - 3.15v(1) * Therm monitor(bit 4) - Disabled(1) * Soft Cold/Hot Temp Limit Behavior(bit 3:2, bit 1:0) - * Charger Current + Float voltage Compensation(11) */ smb358_set_command(client, SMB358_THERM_CONTROL_A, 0xB0); #else /* [STEP - 10] ================================================= * Mininum System Voltage(bit 6) - 3.75v(1) * Therm monitor(bit 4) - Disabled(1) * Soft Cold/Hot Temp Limit Behavior(bit 3:2, bit 1:0) - * Charger Current + Float voltage Compensation(11) */ smb358_set_command(client, SMB358_THERM_CONTROL_A, 0xF0); #endif /* [STEP - 11] ================================================ * OTG/ID Pin Control(bit 7:6) - RID Disabled, OTG I2c(00) * Minimum System Voltage(bit 4) - 3.75V(1) * Low-Battery/SYSOK Voltage threshold(bit 3:0) - 2.5V(0001) * if this bit is disabled, * input current for system will be disabled */ smb358_set_command(client, SMB358_OTHER_CONTROL_A, 0x11); /* [STEP - 12] ================================================ * Charge Current Compensation(bit 7:6) - 200mA(00) * Digital Thermal Regulation Threshold(bit 5:4) - 130c * OTG current Limit at USBIN(Bit 3:2) - 900mA(11) * OTG Battery UVLO Threshold(Bit 1:0) - 3.3V(11) */ smb358_set_command(client, SMB358_OTG_TLIM_THERM_CONTROL, 0x3F); /* [STEP - 13] ================================================ * Hard/Soft Limit Cell temp monitor */ smb358_set_command(client, SMB358_LIMIT_CELL_TEMPERATURE_MONITOR, 0x01); /* [STEP - 14] ================================================ * FAULT interrupt - Disabled */ smb358_set_command(client, SMB358_FAULT_INTERRUPT, 0x00); /* [STEP - 15] ================================================ * STATUS ingerrupt - Clear */ smb358_set_command(client, SMB358_STATUS_INTERRUPT, 0x00); /* [STEP - 16] ================================================ * Volatile write permission(bit 7) - allowed(1) * Charging Enable(bit 1) - Enabled(1) * STAT Output(bit 0) - Enabled(0) */ #if !defined(CONFIG_MACH_LT02) smb358_set_command(client, SMB358_COMMAND_A, 0xC2); #endif schedule_delayed_work(&charger->slow_work, 0); } #if 0 #if (defined(CONFIG_MACH_MILLET3G_EUR) || defined(CONFIG_MACH_MATISSE3G_OPEN) || defined(CONFIG_MACH_BERLUTI3G_EUR)) /* Allow time for AICL to complete */ msleep(1000); smb358_aicl_calibrate(client); #endif #endif }
static void sdchg_exynos7420_cs_use_monitor(void *arg, __kernel_time_t curr_sec, bool skip_monitor) { struct sdchg_info_nochip_t *info = sdchg_info->nochip; struct sec_battery_info *battery = (struct sec_battery_info *)arg; int temperature = 0; static int battcond = 0; bool need_set_state = false; bool need_set_alarm = false; int set_alarm_time = 0; bool runned_by_sdchg_poll; #ifdef SDCHG_STATE_MACHINE_RETRY_AT_END_COND static bool state_machine_retry = false; #endif /******************************************/ runned_by_sdchg_poll = sdchg_check_polling_time(curr_sec); temperature = battery->temperature; if (skip_monitor) { #ifdef SDCHG_CHECK_TYPE_SOC value.intval = SEC_BATTERY_CURRENT_MA; psy_do_property(battery->pdata->fuelgauge_name, get, POWER_SUPPLY_PROP_CURRENT_NOW, value); battcond = value.intval; #else battcond = battery->voltage_now; #endif } else { #ifdef SDCHG_CHECK_TYPE_SOC battcond = (short)battery->current_now; #else battcond = (short)battery->voltage_avg; #endif } /******************************************/ if ( temperature >= sdchg_info->temp_start && battcond >= SDCHG_BATTCOND_START) { /******************************************/ if (!info->wake_lock_set) { wake_lock(&info->wake_lock); info->wake_lock_set = true; } /******************************************/ info->need_state = SDCHG_STATE_SET; } /******************************************/ else if (temperature <= sdchg_info->temp_end || battcond <= SDCHG_BATTCOND_END) { info->need_state = SDCHG_STATE_NONE; } /******************************************/ else { if (info->need_state != SDCHG_STATE_NONE) { info->need_state = SDCHG_STATE_SET; } } /******************************************/ /****************************************/ if (info->display_on) { if (info->need_state == SDCHG_STATE_SET) info->need_state = SDCHG_STATE_SET_DISPLAY_ON; } #ifdef SDCHG_STATE_MACHINE_RETRY_AT_END_COND if (info->need_state != SDCHG_STATE_NONE) state_machine_retry = false; #endif /****************************************/ if (info->set_state != info->need_state) { need_set_state = true; if (info->set_state == SDCHG_STATE_NONE) { // none -> discharing { //need_set_alarm = info->state_machine_run = true; //set_alarm_time = SDCHG_DISCHARGING_DELAY; need_set_alarm = false; // in discharing, according to original monitor work time info->state_machine_run = true; } } else { // prev : discharging if (info->need_state == SDCHG_STATE_NONE) { // discharging -> none if (sdchg_ta_attach(battery) || battcond >= SDCHG_BATTCOND_START) { need_set_alarm = info->state_machine_run = true; if (temperature < SDCHG_TEMP_FOR_BATT_CHECK_DELAY) set_alarm_time = SDCHG_BATT_CHECK_DELAY_NORMAL; else set_alarm_time = SDCHG_BATT_CHECK_DELAY_IMMINENT; #ifdef SDCHG_STATE_MACHINE_RETRY_AT_END_COND state_machine_retry = false; #endif } else { #ifdef SDCHG_STATE_MACHINE_RETRY_AT_END_COND #ifdef SDCHG_SELF_TEST need_set_alarm = info->state_machine_run = true; if (temperature < SDCHG_TEMP_FOR_BATT_CHECK_DELAY) set_alarm_time = SDCHG_BATT_CHECK_DELAY_NORMAL; else set_alarm_time = SDCHG_BATT_CHECK_DELAY_IMMINENT; #else if (state_machine_retry) { if (runned_by_sdchg_poll) { need_set_alarm = info->state_machine_run = false; state_machine_retry = false; } else { need_set_alarm = info->state_machine_run = true; if (temperature < SDCHG_TEMP_FOR_BATT_CHECK_DELAY) set_alarm_time = SDCHG_BATT_CHECK_DELAY_NORMAL; else set_alarm_time = SDCHG_BATT_CHECK_DELAY_IMMINENT; } } else { need_set_alarm = info->state_machine_run = true; if (temperature < SDCHG_TEMP_FOR_BATT_CHECK_DELAY) set_alarm_time = SDCHG_BATT_CHECK_DELAY_NORMAL; else set_alarm_time = SDCHG_BATT_CHECK_DELAY_IMMINENT; state_machine_retry = true; } #endif // #ifdef SDCHG_SELF_TEST #else need_set_alarm = info->state_machine_run = false; #endif // #ifdef SDCHG_STATE_MACHINE_RETRY_AT_END_COND } } else { // discharging -> discharging //need_set_alarm = info->state_machine_run = true; //set_alarm_time = SDCHG_DISCHARGING_DELAY; need_set_alarm = false; // in discharing, according to original monitor work time info->state_machine_run = true; } } } /****************************************/ else { //KEEP_GOING: need_set_state = false; if (info->need_state == SDCHG_STATE_NONE) { // prev : none if (sdchg_ta_attach(battery) || battcond >= SDCHG_BATTCOND_START) { need_set_alarm = info->state_machine_run = true; if (temperature < SDCHG_TEMP_FOR_BATT_CHECK_DELAY) set_alarm_time = SDCHG_BATT_CHECK_DELAY_NORMAL; else set_alarm_time = SDCHG_BATT_CHECK_DELAY_IMMINENT; #ifdef SDCHG_STATE_MACHINE_RETRY_AT_END_COND state_machine_retry = false; #endif } else { #ifdef SDCHG_STATE_MACHINE_RETRY_AT_END_COND #ifdef SDCHG_SELF_TEST need_set_alarm = info->state_machine_run = true; if (temperature < SDCHG_TEMP_FOR_BATT_CHECK_DELAY) set_alarm_time = SDCHG_BATT_CHECK_DELAY_NORMAL; else set_alarm_time = SDCHG_BATT_CHECK_DELAY_IMMINENT; #else if (state_machine_retry) { if (runned_by_sdchg_poll) { need_set_alarm = info->state_machine_run = false; state_machine_retry = false; } else { need_set_alarm = info->state_machine_run = true; if (temperature < SDCHG_TEMP_FOR_BATT_CHECK_DELAY) set_alarm_time = SDCHG_BATT_CHECK_DELAY_NORMAL; else set_alarm_time = SDCHG_BATT_CHECK_DELAY_IMMINENT; } } else { need_set_alarm = info->state_machine_run = true; if (temperature < SDCHG_TEMP_FOR_BATT_CHECK_DELAY) set_alarm_time = SDCHG_BATT_CHECK_DELAY_NORMAL; else set_alarm_time = SDCHG_BATT_CHECK_DELAY_IMMINENT; state_machine_retry = true; } #endif // #ifdef SDCHG_SELF_TEST #else need_set_alarm = info->state_machine_run = false; #endif // #ifdef SDCHG_STATE_MACHINE_RETRY_AT_END_COND } } else { // prev : discharging //need_set_alarm = info->state_machine_run = true; //set_alarm_time = SDCHG_DISCHARGING_DELAY; need_set_alarm = false; // in discharing, according to original monitor work time info->state_machine_run = true; } } /****************************************/ if (need_set_state) { current_source_set(info); } if (need_set_alarm) sdchg_set_polling_time(set_alarm_time); else sdchg_set_polling_time(0); #ifdef SDCHG_CHECK_TYPE_SOC pr_info("[SDCHG][%s] soc : %d , temp : %d, state : %s\n", __func__, battcond, temperature, sdchg_state_str[info->set_state]); #else pr_info("[SDCHG][%s] volt : %d , temp : %d, state : %s\n", __func__, battcond, temperature, sdchg_state_str[info->set_state]); #endif if (info->set_state == SDCHG_STATE_NONE) { if (info->wake_lock_set) { wake_lock_timeout(&info->wake_lock, HZ * 10); wake_unlock(&info->wake_lock); info->wake_lock_set = false; } } return; }
static void sec_chg_isr_work(struct work_struct *work) { struct sec_charger_info *charger = container_of(work, struct sec_charger_info, isr_work.work); union power_supply_propval val; dev_info(&charger->client->dev, "%s: Charger Interrupt\n", __func__); if (charger->pdata->full_check_type == SEC_BATTERY_FULLCHARGED_CHGINT) { if (!sec_hal_chg_get_property(charger->client, POWER_SUPPLY_PROP_STATUS, &val)) return; switch (val.intval) { case POWER_SUPPLY_STATUS_DISCHARGING: dev_err(&charger->client->dev, "%s: Interrupted but Discharging\n", __func__); break; case POWER_SUPPLY_STATUS_NOT_CHARGING: dev_err(&charger->client->dev, "%s: Interrupted but NOT Charging\n", __func__); break; case POWER_SUPPLY_STATUS_FULL: dev_info(&charger->client->dev, "%s: Interrupted by Full\n", __func__); psy_do_property("battery", set, POWER_SUPPLY_PROP_STATUS, val); break; case POWER_SUPPLY_STATUS_CHARGING: dev_err(&charger->client->dev, "%s: Interrupted but Charging\n", __func__); break; case POWER_SUPPLY_STATUS_UNKNOWN: default: dev_err(&charger->client->dev, "%s: Invalid Charger Status\n", __func__); break; } } if (charger->pdata->ovp_uvlo_check_type == SEC_BATTERY_OVP_UVLO_CHGINT) { if (!sec_hal_chg_get_property(charger->client, POWER_SUPPLY_PROP_HEALTH, &val)) return; switch (val.intval) { case POWER_SUPPLY_HEALTH_OVERHEAT: case POWER_SUPPLY_HEALTH_COLD: dev_err(&charger->client->dev, "%s: Interrupted but Hot/Cold\n", __func__); break; case POWER_SUPPLY_HEALTH_DEAD: dev_err(&charger->client->dev, "%s: Interrupted but Dead\n", __func__); break; case POWER_SUPPLY_HEALTH_OVERVOLTAGE: case POWER_SUPPLY_HEALTH_UNDERVOLTAGE: dev_info(&charger->client->dev, "%s: Interrupted by OVP/UVLO\n", __func__); psy_do_property("battery", set, POWER_SUPPLY_PROP_HEALTH, val); break; case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE: dev_err(&charger->client->dev, "%s: Interrupted but Unspec\n", __func__); break; case POWER_SUPPLY_HEALTH_GOOD: dev_err(&charger->client->dev, "%s: Interrupted but Good\n", __func__); break; case POWER_SUPPLY_HEALTH_UNKNOWN: default: dev_err(&charger->client->dev, "%s: Invalid Charger Health\n", __func__); break; } } }
static int adc_get_vcell(struct i2c_client *client) { union power_supply_propval cable; union power_supply_propval event; union power_supply_propval is_charging; struct sec_fuelgauge_info *fuelgauge = i2c_get_clientdata(client); int vcell, vcell_raw; vcell = adc_get_data_by_adc(fuelgauge, get_battery_data(fuelgauge).adc2vcell_table, get_battery_data(fuelgauge).adc2vcell_table_size, adc_get_adc_value(fuelgauge, SEC_BAT_ADC_CHANNEL_VOLTAGE_NOW)); vcell_raw = vcell; psy_do_property("battery", get, POWER_SUPPLY_PROP_ONLINE, cable); /* get current event status */ event.intval = BATT_EVENT; psy_do_property("battery", get, POWER_SUPPLY_PROP_TECHNOLOGY, event); psy_do_property("battery", get, POWER_SUPPLY_PROP_CHARGE_NOW, is_charging); if (is_charging.intval != SEC_BATTERY_CHARGING_NONE) { /* compensate voltage by cable only in charging status */ if (cable.intval != POWER_SUPPLY_TYPE_BATTERY) vcell += get_cable_compensation_voltage( fuelgauge, vcell); } else { /* need compensation before cable detection * in power-off charging */ if ((cable.intval == POWER_SUPPLY_TYPE_BATTERY) && (fuelgauge->pdata->is_lpm() || fuelgauge->pdata->check_vbus_status())) { dev_dbg(&client->dev, "%s: VBUS compensation\n", __func__); vcell += get_cable_compensation_voltage( fuelgauge, vcell); } } if (event.intval) { if (fuelgauge->pdata->check_vbus_status() && (event.intval & EVENT_BOOTING)) dev_dbg(&client->dev, "%s: no event compensation " "in booting with charging\n", __func__); else vcell += get_event_compensation_voltage( fuelgauge, event.intval); } #if defined(SEC_FUELGAUGE_ADC_DELTA_COMPENSATION) if (!fuelgauge->pdata->monitor_initial_count) vcell += get_delta_compensation_voltage( fuelgauge, vcell, vcell_raw); #endif return vcell; }
static void smb347_charger_function_control( struct i2c_client *client) { struct sec_charger_info *charger = i2c_get_clientdata(client); union power_supply_propval val; int full_check_type; u8 data; if (charger->charging_current < 0) { dev_dbg(&client->dev, "%s : OTG is activated. Ignore command!\n", __func__); return; } smb347_allow_volatile_writes(client); if (charger->cable_type == POWER_SUPPLY_TYPE_BATTERY) { /* turn off charger */ smb347_set_command(client, SMB347_COMMAND_A, 0x80); /* high current mode for system current */ smb347_set_command(client, SMB347_COMMAND_B, 0x01); } else { /* Pre-charge curr 250mA */ dev_dbg(&client->dev, "%s : fast charging current (%dmA)\n", __func__, charger->charging_current); dev_dbg(&client->dev, "%s : termination current (%dmA)\n", __func__, charger->pdata->charging_current[ charger->cable_type].full_check_current_1st); data = 0x1c; data |= smb347_get_fast_charging_current_data( charger->charging_current); data |= smb347_get_termination_current_limit_data( charger->pdata->charging_current[ charger->cable_type].full_check_current_1st); smb347_set_command(client, SMB347_CHARGE_CURRENT, data); /* Pin enable control */ /* DCIN Input Pre-bias Enable */ data = 0x01; if (charger->pdata->chg_gpio_en) data |= 0x40; if (charger->pdata->chg_polarity_en) data |= 0x20; smb347_set_command(client, SMB347_PIN_ENABLE_CONTROL, data); /* Input current limit */ dev_dbg(&client->dev, "%s : input current (%dmA)\n", __func__, charger->pdata->charging_current [charger->cable_type].input_current_limit); data = 0; data = smb347_get_input_current_limit_data( charger, charger->pdata->charging_current [charger->cable_type].input_current_limit); smb347_set_command(client, SMB347_INPUT_CURRENTLIMIT, data); /* * Input to System FET by Register * Enable AICL, VCHG * Max System voltage =Vflt + 0.1v * Input Source Priority : USBIN */ if (charger->pdata->chg_functions_setting & SEC_CHARGER_NO_GRADUAL_CHARGING_CURRENT) /* disable AICL */ smb347_set_command(client, SMB347_VARIOUS_FUNCTIONS, 0x85); else /* enable AICL */ smb347_set_command(client, SMB347_VARIOUS_FUNCTIONS, 0x95); /* Float voltage, Vprechg : 2.4V */ dev_dbg(&client->dev, "%s : float voltage (%dmV)\n", __func__, charger->pdata->chg_float_voltage); data = 0; data |= smb347_get_float_voltage_data( charger->pdata->chg_float_voltage); smb347_set_command(client, SMB347_FLOAT_VOLTAGE, data); /* Charge control * Automatic Recharge disable, * Current Termination disable, * BMD disable, Recharge Threshold =50mV, * APSD disable */ data = 0xC0; psy_do_property("battery", get, POWER_SUPPLY_PROP_CHARGE_NOW, val); if (val.intval == SEC_BATTERY_CHARGING_1ST) full_check_type = charger->pdata->full_check_type; else full_check_type = charger->pdata->full_check_type_2nd; switch (full_check_type) { case SEC_BATTERY_FULLCHARGED_CHGGPIO: case SEC_BATTERY_FULLCHARGED_CHGINT: case SEC_BATTERY_FULLCHARGED_CHGPSY: /* Enable Current Termination */ data &= 0xBF; break; } smb347_set_command(client, SMB347_CHARGE_CONTROL, data); /* STAT, Timer control : STAT active low, * Complete time out 1527min. */ smb347_set_command(client, SMB347_STAT_TIMERS_CONTROL, 0x1A); /* Pin/Enable * USB 5/1/HC Dual state * DCIN pre-bias Enable */ smb347_set_command(client, SMB347_PIN_ENABLE_CONTROL, 0x09); /* Therm control : * Therm monitor disable, * Minimum System Voltage 3.60V */ smb347_set_command(client, SMB347_THERM_CONTROL_A, 0x7F); /* USB selection : USB2.0(100mA/500mA), * INOK polarity Active low */ smb347_set_command(client, SMB347_SYSOK_USB30_SELECTION, 0x08); /* Other control * Low batt detection disable * Minimum System Voltage 3.60V */ smb347_set_command(client, SMB347_OTHER_CONTROL_A, 0x00); /* OTG tlim therm control */ smb347_set_command(client, SMB347_OTG_TLIM_THERM_CONTROL, 0x3F); /* Limit cell temperature */ smb347_set_command(client, SMB347_LIMIT_CELL_TEMPERATURE_MONITOR, 0x01); /* Fault interrupt : Clear */ smb347_set_command(client, SMB347_FAULT_INTERRUPT, 0x00); /* STATUS ingerrupt : Clear */ smb347_set_command(client, SMB347_STATUS_INTERRUPT, 0x00); /* turn on charger */ smb347_set_command(client, SMB347_COMMAND_A, 0x82); /* HC or USB5 mode */ switch (charger->cable_type) { case POWER_SUPPLY_TYPE_MAINS: case POWER_SUPPLY_TYPE_MISC: /* High-current mode */ data = 0x01; break; case POWER_SUPPLY_TYPE_USB: case POWER_SUPPLY_TYPE_USB_DCP: case POWER_SUPPLY_TYPE_USB_CDP: case POWER_SUPPLY_TYPE_USB_ACA: /* USB5 */ data = 0x02; break; default: /* USB1 */ data = 0x00; break; } smb347_set_command(client, SMB347_COMMAND_B, data); } }
static int sec_bat_get_cable_from_extended_cable_type( int input_extended_cable_type) { int cable_main, cable_sub, cable_power; int cable_type = POWER_SUPPLY_TYPE_UNKNOWN; union power_supply_propval value; int charge_current_max = 0, charge_current = 0; cable_main = GET_MAIN_CABLE_TYPE(input_extended_cable_type); if (cable_main != POWER_SUPPLY_TYPE_UNKNOWN) extended_cable_type = (extended_cable_type & ~(int)ONLINE_TYPE_MAIN_MASK) | (cable_main << ONLINE_TYPE_MAIN_SHIFT); cable_sub = GET_SUB_CABLE_TYPE(input_extended_cable_type); if (cable_sub != ONLINE_SUB_TYPE_UNKNOWN) extended_cable_type = (extended_cable_type & ~(int)ONLINE_TYPE_SUB_MASK) | (cable_sub << ONLINE_TYPE_SUB_SHIFT); cable_power = GET_POWER_CABLE_TYPE(input_extended_cable_type); if (cable_power != ONLINE_POWER_TYPE_UNKNOWN) extended_cable_type = (extended_cable_type & ~(int)ONLINE_TYPE_PWR_MASK) | (cable_power << ONLINE_TYPE_PWR_SHIFT); switch (cable_main) { case POWER_SUPPLY_TYPE_CARDOCK: switch (cable_power) { case ONLINE_POWER_TYPE_BATTERY: cable_type = POWER_SUPPLY_TYPE_BATTERY; break; case ONLINE_POWER_TYPE_TA: switch (cable_sub) { case ONLINE_SUB_TYPE_MHL: cable_type = POWER_SUPPLY_TYPE_USB; break; case ONLINE_SUB_TYPE_AUDIO: case ONLINE_SUB_TYPE_DESK: case ONLINE_SUB_TYPE_SMART_NOTG: case ONLINE_SUB_TYPE_KBD: cable_type = POWER_SUPPLY_TYPE_MAINS; break; case ONLINE_SUB_TYPE_SMART_OTG: cable_type = POWER_SUPPLY_TYPE_CARDOCK; break; } break; case ONLINE_POWER_TYPE_USB: cable_type = POWER_SUPPLY_TYPE_USB; break; default: cable_type = current_cable_type; break; } break; case POWER_SUPPLY_TYPE_MISC: switch (cable_sub) { case ONLINE_SUB_TYPE_MHL: switch (cable_power) { case ONLINE_POWER_TYPE_BATTERY: cable_type = POWER_SUPPLY_TYPE_BATTERY; break; case ONLINE_POWER_TYPE_TA: cable_type = POWER_SUPPLY_TYPE_MISC; charge_current_max = 700; charge_current = 700; break; case ONLINE_POWER_TYPE_USB: cable_type = POWER_SUPPLY_TYPE_USB; charge_current_max = 300; charge_current = 300; break; default: cable_type = cable_main; } break; default: cable_type = cable_main; break; } break; default: cable_type = cable_main; break; } if (charge_current_max == 0) { charge_current_max = charging_current_table[cable_type].input_current_limit; charge_current = charging_current_table[cable_type]. fast_charging_current; } value.intval = charge_current_max; psy_do_property(sec_battery_pdata.charger_name, set, POWER_SUPPLY_PROP_CURRENT_MAX, value); value.intval = charge_current; psy_do_property(sec_battery_pdata.charger_name, set, POWER_SUPPLY_PROP_CURRENT_AVG, value); return cable_type; }