static void s3c_bat_work(struct work_struct *work) { struct chg_data *chg = container_of(work, struct chg_data, bat_work); int ret; struct timespec ts; unsigned long flags; mutex_lock(&chg->mutex); s3c_bat_discharge_reason(chg); ret = s3c_cable_status_update(chg); if (ret < 0) goto err; mutex_unlock(&chg->mutex); power_supply_changed(&chg->psy_bat); chg->last_poll = alarm_get_elapsed_realtime(); ts = ktime_to_timespec(chg->last_poll); chg->timestamp = ts.tv_sec; /* prevent suspend before starting the alarm */ local_irq_save(flags); wake_unlock(&chg->work_wake_lock); s3c_program_alarm(chg, FAST_POLL); local_irq_restore(flags); return; err: mutex_unlock(&chg->mutex); wake_unlock(&chg->work_wake_lock); pr_err("battery workqueue fail\n"); }
static void s3c_bat_work(struct work_struct *work) { struct chg_data *chg = container_of(work, struct chg_data, bat_work); int ret; mutex_lock(&chg->mutex); s3c_get_bat_temp(chg); s3c_bat_discharge_reason(chg); ret = s3c_cable_status_update(chg); if (ret < 0) goto err; mutex_unlock(&chg->mutex); power_supply_changed(&chg->psy_bat); mod_timer(&chg->bat_work_timer, jiffies + msecs_to_jiffies(BAT_POLLING_INTERVAL)); wake_unlock(&chg->work_wake_lock); return; err: mutex_unlock(&chg->mutex); wake_unlock(&chg->work_wake_lock); pr_err("battery workqueue fail\n"); }
void s3c_cable_check_status(int flag) { charger_type_t status = 0; if (flag == 0) // Battery status = CHARGER_BATTERY; else // USB status = CHARGER_USB; s3c_cable_status_update(status); }
static void battery_watcher(struct work_struct *work) { int i; unsigned int sum, min, max; bool ac_connected, battery_full; static unsigned int readings[NUMBER_OF_SAMPLES]; dev_dbg(dev, "*** %s: ***\n", __func__); // Read GPIOs. ac_connected = gpio_get_value(nGPIO_AC_Connected) ? true : false; battery_full = gpio_get_value(nGPIO_Battery_Full) ? false : true; // Read ADC. for (i = 0, sum = 0; i < NUMBER_OF_SAMPLES; i++) { readings[i] = s3c_adc_get_adc_data(DRIVER_ADC_CHANNEL); sum += readings[i]; udelay(25); if (i) { if (readings[i] < min) min = readings[i]; if (readings[i] > max) max = readings[i]; } else { min = readings[i]; max = readings[i]; } } // Update history. last_voltages[last_voltage_ptr++] = (sum - min - max) / (NUMBER_OF_SAMPLES - 2); if (num_active_voltages < last_voltage_ptr) num_active_voltages = last_voltage_ptr; last_voltage_ptr %= NUMBER_OF_VALUES_AVG; for (i = 0, sum = 0; i < num_active_voltages; i++) sum += last_voltages[i]; // Update battery. utv210_bat_info.batt_vol_adc = sum / num_active_voltages; // full-battery GPIO is only valid if AC is connected. if (ac_connected && battery_full) utv210_bat_info.batt_is_full = 1; else utv210_bat_info.batt_is_full = 0; // Update cable and battery status(es). utv210_bat_status_update(&utv210_power_supplies[CHARGER_BATTERY]); s3c_cable_status_update(ac_connected ? CHARGER_AC : CHARGER_BATTERY); schedule_delayed_work(&battery_watcher_work, HZ * POLL_INTERVAL_IN_SECS); }
static void max8998_set_cable(struct max8998_charger_callbacks *ptr, enum cable_type_t status) { struct chg_data *chg = container_of(ptr, struct chg_data, callbacks); mutex_lock(&chg->mutex); chg->cable_status = status; if (lpm_charging_mode && (max8998_check_vdcin(chg) != 1) && pm_power_off) pm_power_off(); pr_info("%s : status(%d)\n", __func__, status); s3c_cable_status_update(chg); power_supply_changed(&chg->psy_ac); power_supply_changed(&chg->psy_usb); wake_lock(&chg->work_wake_lock); queue_work(chg->monitor_wqueue, &chg->bat_work); mutex_unlock(&chg->mutex); }
static void s3c_cable_check_status(void) { charger_type_t ostatus=b_status; mutex_lock(&work_lock); if (!gpio_get_value(gpio_ta_connected)) { if (get_usb_power_state()) b_status = CHARGER_USB; else b_status = CHARGER_AC; if (s3c_get_bat_health() != POWER_SUPPLY_HEALTH_GOOD) { dev_info(dev, "%s: Unhealth battery state!\n", __func__); s3c_set_chg_en(DISABLE); } else s3c_set_chg_en(ENABLE); dev_dbg(dev, "%s: status : %s\n", __func__, (b_status == CHARGER_USB) ? "USB" : "AC"); } else { u32 health = s3c_get_bat_health(); b_status = CHARGER_BATTERY; s3c_set_chg_en(DISABLE); if (health == POWER_SUPPLY_HEALTH_OVERHEAT || health == POWER_SUPPLY_HEALTH_COLD) { s3c_set_bat_health(POWER_SUPPLY_HEALTH_GOOD); } } dev_dbg(dev, "%s: gpio_chg_en %s\n", __func__, gpio_get_value_ex(gpio_chg_en)?"disabled":"enabled"); if (ostatus!=b_status) s3c_cable_status_update(b_status); mutex_unlock(&work_lock); }