static int setup_supply_data(struct device_node *node, struct ricoh_pmu_init_data *s_data) { int err; struct device_node *b_node; struct battery_parameter *battery; phandle fhandle; err = of_property_read_bool(node, "reset-to-system"); if (err) { s_data->reset_to_system = 1; } PARSE_UINT32_PROPERTY(node, "soft_limit_to99", s_data->soft_limit_to99, parse_failed); PARSE_UINT32_PROPERTY(node, "board_battery", fhandle, parse_failed); PARSE_UINT32_PROPERTY(node, "vbus_dcin_short_connect", s_data->vbus_dcin_short_connect, parse_failed); b_node = of_find_node_by_phandle(fhandle); if (!b_node) { DBG("find battery node failed, current:%s\n", node->name); } ALLOC_DEVICES(battery, sizeof(*battery), GFP_KERNEL); if (parse_battery_parameters(b_node, battery)) { DBG("failed to parse battery parameter, node:%s\n", b_node->name); kfree(battery); } else { s_data->board_battery = battery; // attach to axp_supply_init_data } return 0; parse_failed: return -EINVAL; }
int axp202_get_charging_percent(void) { //uint8_t val; //struct axp_adc_res axp_adc; extern int config_battery_rdc; extern struct battery_curve config_battery_curve[]; int i; int ocv = 0; int ocv_diff, percent_diff, ocv_diff2; int charge_status = axp_charger_get_charging_status(); int percent1, percent2; int rest_vol; int avg_voltage, avg_current; static int ocv_full = 0; static int ocv_empty = 0; static int battery_rdc; static struct battery_curve *battery_curve; if (get_battery_para_flag() == PARA_UNPARSED) { /* * this code runs earlier than get_battery_para(), * we need to know battery parameters first. */ if (parse_battery_parameters() > 0) { set_battery_para_flag(PARA_PARSE_SUCCESS); for (i = 0; i < 16; i++) { // find out full & empty ocv in battery curve if (!ocv_empty && board_battery_para.pmu_bat_curve[i].discharge_percent > 0) { ocv_empty = board_battery_para.pmu_bat_curve[i - 1].ocv; } if (!ocv_full && board_battery_para.pmu_bat_curve[i].discharge_percent == 100) { ocv_full = board_battery_para.pmu_bat_curve[i].ocv; } } battery_rdc = board_battery_para.pmu_battery_rdc; battery_curve = board_battery_para.pmu_bat_curve; } else { set_battery_para_flag(PARA_PARSE_FAILED); } } if (get_battery_para_flag() != PARA_PARSE_SUCCESS && !ocv_full) { /* * parse battery parameters failed, use configured parameters */ battery_rdc = config_battery_rdc; battery_curve = config_battery_curve; for (i = 0; i < 16; i++) { // find out full & empty ocv in battery curve if (!ocv_empty && battery_curve[i].discharge_percent > 0) { ocv_empty = battery_curve[i - 1].ocv; } if (!ocv_full && battery_curve[i].discharge_percent == 100) { ocv_full = battery_curve[i].ocv; } } } avg_voltage = 0; avg_current = 0; for (i = 0; i < 8; i++) { // calculate average ocv ocv += axp_calculate_ocv(charge_status, battery_rdc); udelay(2000); } ocv = ocv / 8; avg_voltage /= 8; avg_current /= 8; printf("charge status:%04x, voltage:%4d, current:%4d, ocv is %4d, ", status_reg, avg_voltage, avg_current * (charge_status ? 1 : -1), ocv); if (ocv >= ocv_full) { return 100; } else if (ocv <= ocv_empty) { return 0; } for (i = 0; i < 15; i++) { // find which range this ocv is in if (ocv >= battery_curve[i].ocv && ocv < battery_curve[i + 1].ocv) { break; } } percent1 = (battery_curve[i + 1].charge_percent + battery_curve[i + 1].discharge_percent) / 2; percent2 = (battery_curve[i].charge_percent + battery_curve[i].discharge_percent) / 2; percent_diff = percent1 - percent2; ocv_diff = battery_curve[i + 1].ocv - battery_curve[i].ocv; ocv_diff2 = ocv - battery_curve[i].ocv; rest_vol = (percent_diff * ocv_diff2 + ocv_diff / 2)/ocv_diff; rest_vol += percent2; if (rest_vol > 100) { rest_vol = 100; } else if (rest_vol < 0) { rest_vol = 0; } return rest_vol; }