static void bq24192_irq_worker(struct work_struct *work) { struct bq24192_chip *chip = container_of(work, struct bq24192_chip, irq_work); union power_supply_propval ret = {0,}; bool ext_pwr; bool wlc_pwr = 0; bool chg_done = false; u8 temp; int rc; unsigned long flags; wake_lock(&chip->irq_wake_lock); msleep(100 * chip->irq_scheduled_time_status); rc = bq24192_read_reg(chip->client, SYSTEM_STATUS_REG, &temp); /* Open up for next possible interrupt handler beyond read reg * asap, lest we miss an interrupt */ spin_lock_irqsave(&chip->irq_work_lock, flags); chip->irq_scheduled_time_status = 0; spin_unlock_irqrestore(&chip->irq_work_lock, flags); if (rc) { pr_err("failed to read SYSTEM_STATUS_REG rc=%d\n", rc); goto irq_worker_exit; } ext_pwr = !!(temp & PG_STAT_MASK); chg_done = (temp & CHARGING_MASK) == 0x30 ? true : false; if (chg_done) { if (chip->batt_health != POWER_SUPPLY_HEALTH_OVERHEAT && bq24192_get_soc_from_batt_psy(chip) < 100) { wake_lock(&chip->extra_chg_lock); bq24192_enable_chg_term(chip, false); bq24192_trigger_recharge(chip); schedule_delayed_work(&chip->extra_chg_work, msecs_to_jiffies(EXTRA_CHG_TIME_MS)); } else { if (chip->batt_health != POWER_SUPPLY_HEALTH_OVERHEAT) bq24192_set_rechg_voltage(chip, VRECHG_300MV); power_supply_changed(&chip->ac_psy); pr_debug("charge done!!\n"); } } if (chip->wlc_psy) { chip->wlc_psy->get_property(chip->wlc_psy, POWER_SUPPLY_PROP_PRESENT, &ret); wlc_pwr = ret.intval; } if ((chip->ext_pwr ^ ext_pwr) || (chip->wlc_pwr ^ wlc_pwr)) { pr_debug("power source changed! ext_pwr = %d wlc_pwr = %d\n", ext_pwr, wlc_pwr); if (wake_lock_active(&chip->icl_wake_lock)) wake_unlock(&chip->icl_wake_lock); if (wake_lock_active(&chip->extra_chg_lock)) wake_unlock(&chip->extra_chg_lock); cancel_delayed_work_sync(&chip->input_limit_work); cancel_delayed_work_sync(&chip->therm_work); cancel_delayed_work_sync(&chip->extra_chg_work); bq24192_enable_chg_term(chip, true); bq24192_step_down_detect_disable(chip); chip->saved_ibat_ma = 0; chip->set_chg_current_ma = chip->chg_current_ma; chip->max_input_i_ma = INPUT_CURRENT_LIMIT_MAX_MA; if (chip->wlc_psy) { if (wlc_pwr && ext_pwr) { chip->wlc_pwr = true; power_supply_set_online(chip->wlc_psy, true); } else if (chip->wlc_pwr && !(ext_pwr && wlc_pwr)) { chip->wlc_pwr = false; power_supply_set_online(chip->wlc_psy, false); } } if (!wlc_pwr) { pr_debug("notify vbus to usb otg ext_pwr = %d\n", ext_pwr); power_supply_set_present(chip->usb_psy, ext_pwr); } chip->ext_pwr = ext_pwr; } irq_worker_exit: wake_lock_timeout(&chip->irq_wake_lock, 2*HZ); }
static void twl4030_madc_bat_ext_changed(struct power_supply *psy) { power_supply_changed(psy); }
static int tps65090_charger_probe(struct platform_device *pdev) { struct tps65090_charger *cdata; struct tps65090_platform_data *pdata; uint8_t status1 = 0; int ret; int irq; pdata = dev_get_platdata(pdev->dev.parent); if (!pdata && pdev->dev.of_node) pdata = tps65090_parse_dt_charger_data(pdev); if (!pdata) { dev_err(&pdev->dev, "%s():no platform data available\n", __func__); return -ENODEV; } cdata = devm_kzalloc(&pdev->dev, sizeof(*cdata), GFP_KERNEL); if (!cdata) { dev_err(&pdev->dev, "failed to allocate memory status\n"); return -ENOMEM; } dev_set_drvdata(&pdev->dev, cdata); cdata->dev = &pdev->dev; cdata->pdata = pdata; cdata->ac.name = "tps65090-ac"; cdata->ac.type = POWER_SUPPLY_TYPE_MAINS; cdata->ac.get_property = tps65090_ac_get_property; cdata->ac.properties = tps65090_ac_props; cdata->ac.num_properties = ARRAY_SIZE(tps65090_ac_props); cdata->ac.supplied_to = pdata->supplied_to; cdata->ac.num_supplicants = pdata->num_supplicants; ret = power_supply_register(&pdev->dev, &cdata->ac); if (ret) { dev_err(&pdev->dev, "failed: power supply register\n"); return ret; } irq = platform_get_irq(pdev, 0); if (irq <= 0) { dev_warn(&pdev->dev, "Unable to get charger irq = %d\n", irq); ret = irq; goto fail_unregister_supply; } cdata->irq = irq; ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, tps65090_charger_isr, 0, "tps65090-charger", cdata); if (ret) { dev_err(cdata->dev, "Unable to register irq %d err %d\n", irq, ret); goto fail_free_irq; } ret = tps65090_config_charger(cdata); if (ret < 0) { dev_err(&pdev->dev, "charger config failed, err %d\n", ret); goto fail_free_irq; } /* Check for charger presence */ ret = tps65090_read(cdata->dev->parent, TPS65090_REG_CG_STATUS1, &status1); if (ret < 0) { dev_err(cdata->dev, "%s(): Error in reading reg 0x%x", __func__, TPS65090_REG_CG_STATUS1); goto fail_free_irq; } if (status1 != 0) { ret = tps65090_enable_charging(cdata, 1); if (ret < 0) { dev_err(cdata->dev, "error enabling charger\n"); goto fail_free_irq; } cdata->ac_online = 1; power_supply_changed(&cdata->ac); } return 0; fail_free_irq: devm_free_irq(cdata->dev, irq, cdata); fail_unregister_supply: power_supply_unregister(&cdata->ac); return ret; }
static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id) { struct pm2xxx_platform_data *pl_data = i2c_client->dev.platform_data; struct power_supply_config psy_cfg = {}; struct pm2xxx_charger *pm2; int ret = 0; u8 val; int i; if (!pl_data) { dev_err(&i2c_client->dev, "No platform data supplied\n"); return -EINVAL; } pm2 = kzalloc(sizeof(struct pm2xxx_charger), GFP_KERNEL); if (!pm2) { dev_err(&i2c_client->dev, "pm2xxx_charger allocation failed\n"); return -ENOMEM; } /* get parent data */ pm2->dev = &i2c_client->dev; pm2->pm2_int = &pm2xxx_int; /* get charger spcific platform data */ if (!pl_data->wall_charger) { dev_err(pm2->dev, "no charger platform data supplied\n"); ret = -EINVAL; goto free_device_info; } pm2->pdata = pl_data->wall_charger; /* get battery specific platform data */ if (!pl_data->battery) { dev_err(pm2->dev, "no battery platform data supplied\n"); ret = -EINVAL; goto free_device_info; } pm2->bat = pl_data->battery; if (!i2c_check_functionality(i2c_client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_READ_WORD_DATA)) { ret = -ENODEV; dev_info(pm2->dev, "pm2301 i2c_check_functionality failed\n"); goto free_device_info; } pm2->config.pm2xxx_i2c = i2c_client; pm2->config.pm2xxx_id = (struct i2c_device_id *) id; i2c_set_clientdata(i2c_client, pm2); /* AC supply */ /* power_supply base class */ pm2->ac_chg_desc.name = pm2->pdata->label; pm2->ac_chg_desc.type = POWER_SUPPLY_TYPE_MAINS; pm2->ac_chg_desc.properties = pm2xxx_charger_ac_props; pm2->ac_chg_desc.num_properties = ARRAY_SIZE(pm2xxx_charger_ac_props); pm2->ac_chg_desc.get_property = pm2xxx_charger_ac_get_property; psy_cfg.supplied_to = pm2->pdata->supplied_to; psy_cfg.num_supplicants = pm2->pdata->num_supplicants; /* pm2xxx_charger sub-class */ pm2->ac_chg.ops.enable = &pm2xxx_charger_ac_en; pm2->ac_chg.ops.kick_wd = &pm2xxx_charger_watchdog_kick; pm2->ac_chg.ops.update_curr = &pm2xxx_charger_update_charger_current; pm2->ac_chg.max_out_volt = pm2xxx_charger_voltage_map[ ARRAY_SIZE(pm2xxx_charger_voltage_map) - 1]; pm2->ac_chg.max_out_curr = pm2xxx_charger_current_map[ ARRAY_SIZE(pm2xxx_charger_current_map) - 1]; pm2->ac_chg.wdt_refresh = WD_KICK_INTERVAL; pm2->ac_chg.enabled = true; pm2->ac_chg.external = true; /* Create a work queue for the charger */ pm2->charger_wq = create_singlethread_workqueue("pm2xxx_charger_wq"); if (pm2->charger_wq == NULL) { ret = -ENOMEM; dev_err(pm2->dev, "failed to create work queue\n"); goto free_device_info; } /* Init work for charger detection */ INIT_WORK(&pm2->ac_work, pm2xxx_charger_ac_work); /* Init work for checking HW status */ INIT_WORK(&pm2->check_main_thermal_prot_work, pm2xxx_charger_check_main_thermal_prot_work); /* Init work for HW failure check */ INIT_DEFERRABLE_WORK(&pm2->check_hw_failure_work, pm2xxx_charger_check_hw_failure_work); /* * VDD ADC supply needs to be enabled from this driver when there * is a charger connected to avoid erroneous BTEMP_HIGH/LOW * interrupts during charging */ pm2->regu = regulator_get(pm2->dev, "vddadc"); if (IS_ERR(pm2->regu)) { ret = PTR_ERR(pm2->regu); dev_err(pm2->dev, "failed to get vddadc regulator\n"); goto free_charger_wq; } /* Register AC charger class */ pm2->ac_chg.psy = power_supply_register(pm2->dev, &pm2->ac_chg_desc, &psy_cfg); if (IS_ERR(pm2->ac_chg.psy)) { dev_err(pm2->dev, "failed to register AC charger\n"); ret = PTR_ERR(pm2->ac_chg.psy); goto free_regulator; } /* Register interrupts */ ret = request_threaded_irq(gpio_to_irq(pm2->pdata->gpio_irq_number), NULL, pm2xxx_charger_irq[0].isr, pm2->pdata->irq_type, pm2xxx_charger_irq[0].name, pm2); if (ret != 0) { dev_err(pm2->dev, "failed to request %s IRQ %d: %d\n", pm2xxx_charger_irq[0].name, gpio_to_irq(pm2->pdata->gpio_irq_number), ret); goto unregister_pm2xxx_charger; } ret = pm_runtime_set_active(pm2->dev); if (ret) dev_err(pm2->dev, "set active Error\n"); pm_runtime_enable(pm2->dev); pm_runtime_set_autosuspend_delay(pm2->dev, PM2XXX_AUTOSUSPEND_DELAY); pm_runtime_use_autosuspend(pm2->dev); pm_runtime_resume(pm2->dev); /* pm interrupt can wake up system */ ret = enable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number)); if (ret) { dev_err(pm2->dev, "failed to set irq wake\n"); goto unregister_pm2xxx_interrupt; } mutex_init(&pm2->lock); if (gpio_is_valid(pm2->pdata->lpn_gpio)) { /* get lpn GPIO from platform data */ pm2->lpn_pin = pm2->pdata->lpn_gpio; /* * Charger detection mechanism requires pulling up the LPN pin * while i2c communication if Charger is not connected * LPN pin of PM2301 is GPIO60 of AB9540 */ ret = gpio_request(pm2->lpn_pin, "pm2301_lpm_gpio"); if (ret < 0) { dev_err(pm2->dev, "pm2301_lpm_gpio request failed\n"); goto disable_pm2_irq_wake; } ret = gpio_direction_output(pm2->lpn_pin, 0); if (ret < 0) { dev_err(pm2->dev, "pm2301_lpm_gpio direction failed\n"); goto free_gpio; } set_lpn_pin(pm2); } /* read interrupt registers */ for (i = 0; i < PM2XXX_NUM_INT_REG; i++) pm2xxx_reg_read(pm2, pm2xxx_interrupt_registers[i], &val); ret = pm2xxx_charger_detection(pm2, &val); if ((ret == 0) && val) { pm2->ac.charger_connected = 1; ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON, AB8500_MAIN_CH_DET); pm2->ac_conn = true; power_supply_changed(pm2->ac_chg.psy); sysfs_notify(&pm2->ac_chg.psy->dev.kobj, NULL, "present"); } return 0; free_gpio: if (gpio_is_valid(pm2->lpn_pin)) gpio_free(pm2->lpn_pin); disable_pm2_irq_wake: disable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number)); unregister_pm2xxx_interrupt: /* disable interrupt */ free_irq(gpio_to_irq(pm2->pdata->gpio_irq_number), pm2); unregister_pm2xxx_charger: /* unregister power supply */ power_supply_unregister(pm2->ac_chg.psy); free_regulator: /* disable the regulator */ regulator_put(pm2->regu); free_charger_wq: destroy_workqueue(pm2->charger_wq); free_device_info: kfree(pm2); return ret; }
int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma) { struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev); int ret = 0; u8 bits; u8 mbcs2, chgmod; unsigned int mbcc5; if (ma >= 1000) { bits = PCF50633_MBCC7_USB_1000mA; ma = 1000; } else if (ma >= 500) { bits = PCF50633_MBCC7_USB_500mA; ma = 500; } else if (ma >= 100) { bits = PCF50633_MBCC7_USB_100mA; ma = 100; } else { bits = PCF50633_MBCC7_USB_SUSPEND; ma = 0; } ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC7, PCF50633_MBCC7_USB_MASK, bits); if (ret) dev_err(pcf->dev, "error setting usb curlim to %d mA\n", ma); else dev_info(pcf->dev, "usb curlim to %d mA\n", ma); /* * We limit the charging current to be the USB current limit. * The reason is that on pcf50633, when it enters PMU Standby mode, * which it does when the device goes "off", the USB current limit * reverts to the variant default. In at least one common case, that * default is 500mA. By setting the charging current to be the same * as the USB limit we set here before PMU standby, we enforce it only * using the correct amount of current even when the USB current limit * gets reset to the wrong thing */ if (mbc->pcf->pdata->charger_reference_current_ma) { mbcc5 = (ma << 8) / mbc->pcf->pdata->charger_reference_current_ma; if (mbcc5 > 255) mbcc5 = 255; pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5); } mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2); chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK); /* If chgmod == BATFULL, setting chgena has no effect. * Datasheet says we need to set resume instead but when autoresume is * used resume doesn't work. Clear and set chgena instead. */ if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL) pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA); else { pcf50633_reg_clear_bits(pcf, PCF50633_REG_MBCC1, PCF50633_MBCC1_CHGENA); pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA); } power_supply_changed(mbc->usb); return ret; }
static int dwc3_otg_set_power(struct usb_phy *phy, unsigned mA) { static int power_supply_type; struct dwc3_otg *dotg = container_of(phy->otg, struct dwc3_otg, otg); #if defined(CONFIG_DWC3_MSM_BC_12_VZW_SUPPORT) && defined(CONFIG_LGE_PM) static bool chglogo_check = false; #endif if (!dotg->psy || !dotg->charger) { dev_err(phy->dev, "no usb power supply/charger registered\n"); return 0; } if (dotg->charger->charging_disabled) return 0; #ifdef CONFIG_LGE_PM if (dotg->charger->chg_type == DWC3_SDP_CHARGER || dotg->charger->chg_type == DWC3_FLOATED_CHARGER) #else if (dotg->charger->chg_type == DWC3_SDP_CHARGER) #endif power_supply_type = POWER_SUPPLY_TYPE_USB; else if (dotg->charger->chg_type == DWC3_CDP_CHARGER) power_supply_type = POWER_SUPPLY_TYPE_USB_CDP; else if (dotg->charger->chg_type == DWC3_DCP_CHARGER || dotg->charger->chg_type == DWC3_PROPRIETARY_CHARGER) power_supply_type = POWER_SUPPLY_TYPE_USB_DCP; else power_supply_type = POWER_SUPPLY_TYPE_UNKNOWN; #ifndef CONFIG_LGE_PM power_supply_set_supply_type(dotg->psy, power_supply_type); #endif #if defined (CONFIG_TOUCHSCREEN_SYNAPTICS_G3) && defined (CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) update_status(1, dotg->charger->chg_type); #endif #if defined(CONFIG_DWC3_MSM_BC_12_VZW_SUPPORT) && defined(CONFIG_LGE_PM) if (!chglogo_check && lge_get_boot_mode() == LGE_BOOT_MODE_CHARGERLOGO && dotg->charger->chg_type == DWC3_SDP_CHARGER) { if (mA > IUNIT) chglogo_check = true; else if (mA <= 2) { dotg->charger->max_power = mA; return 0; } } if (mA > 2 && lge_pm_get_cable_type() != NO_INIT_CABLE) { if (dotg->charger->chg_type == DWC3_DCP_CHARGER) mA = lge_pm_get_ta_current(); } #elif defined(CONFIG_LGE_PM) if (mA > 2 && lge_pm_get_cable_type() != NO_INIT_CABLE) { if (dotg->charger->chg_type == DWC3_SDP_CHARGER) { if (dotg->dwc->gadget.speed == USB_SPEED_SUPER) { if (dotg->charger->max_power > 2) dotg->charger->max_power = 0; mA = DWC3_USB30_CHG_CURRENT; } else { mA = lge_pm_get_usb_current(); } #ifdef CONFIG_QPNP_CHARGER /* For MST, boost current up over 900mA in spite of USB */ if (pseudo_batt_info.mode && mA == 500 ) mA = DWC3_USB30_CHG_CURRENT; #endif } else if (dotg->charger->chg_type == DWC3_DCP_CHARGER) { mA = lge_pm_get_ta_current(); } else if (dotg->charger->chg_type == DWC3_FLOATED_CHARGER) { mA = lge_pm_get_usb_current(); } } #endif if (dotg->charger->chg_type == DWC3_CDP_CHARGER) mA = DWC3_IDEV_CHG_MAX; if (dotg->charger->max_power == mA) return 0; dev_info(phy->dev, "Avail curr from USB = %u\n", mA); /* */ #ifdef CONFIG_LGE_PM #ifndef CONFIG_USB_DWC3_LGE_SINGLE_PSY if (dwc3_otg_get_psy(phy) < 0) goto psy_error; #else if (strcmp(dotg->psy->name, "usb")) { pr_info("%s psy name is %s, so change psy to usb.\n", __func__, dotg->psy->name); dotg->psy = power_supply_get_by_name("usb"); if (!dotg->psy) goto psy_error; } #endif power_supply_set_supply_type(dotg->psy, power_supply_type); #endif #if defined(CONFIG_DWC3_MSM_BC_12_VZW_SUPPORT) && defined(CONFIG_LGE_PM) if (dotg->charger->max_power <= IUNIT && mA > 2) { #else if (dotg->charger->max_power <= 2 && mA > 2) { #endif /* Enable charging */ if (power_supply_set_online(dotg->psy, true)) goto psy_error; if (power_supply_set_current_limit(dotg->psy, 1000*mA)) goto psy_error; #ifdef CONFIG_QPNP_CHARGER if (!strncmp(dotg->psy->name, "ac", 2)) { dotg->psy = power_supply_get_by_name("usb"); if (!dotg->psy) goto psy_error; if (power_supply_set_online(dotg->psy, true)) goto psy_error; if (power_supply_set_supply_type(dotg->psy, power_supply_type)) goto psy_error; if (power_supply_set_current_limit(dotg->psy, 1000*mA)) goto psy_error; dotg->psy = power_supply_get_by_name("ac"); if (!dotg->psy) goto psy_error; } #endif } else if (dotg->charger->max_power > 0 && (mA == 0 || mA == 2)) { /* Disable charging */ if (power_supply_set_online(dotg->psy, false)) goto psy_error; /* Set max current limit */ if (power_supply_set_current_limit(dotg->psy, 0)) goto psy_error; #ifdef CONFIG_QPNP_CHARGER if (!strncmp(dotg->psy->name, "ac", 2)) { dotg->psy = power_supply_get_by_name("usb"); if (!dotg->psy) goto psy_error; if (power_supply_set_online(dotg->psy, false)) goto psy_error; if (power_supply_set_supply_type(dotg->psy, power_supply_type)) goto psy_error; if (power_supply_set_current_limit(dotg->psy, 0)) goto psy_error; dotg->psy = power_supply_get_by_name("ac"); if (!dotg->psy) goto psy_error; } #endif #ifndef CONFIG_USB_DWC3_LGE_SINGLE_PSY dotg->charger->chg_type = DWC3_INVALID_CHARGER; #endif } power_supply_changed(dotg->psy); dotg->charger->max_power = mA; #if defined (CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) || defined(CONFIG_TOUCHSCREEN_ATMEL_S540) #if defined (CONFIG_TOUCHSCREEN_SYNAPTICS_G2) || defined (CONFIG_MACH_MSM8974_TIGERS) || defined(CONFIG_MACH_MSM8974_B1_KR) || defined(CONFIG_MACH_MSM8974_B1W) queue_work(touch_otg_wq, &dotg->touch_work); #endif #endif return 0; psy_error: dev_dbg(phy->dev, "power supply error when setting property\n"); return -ENXIO; } /* IRQs which OTG driver is interested in handling */ #define DWC3_OEVT_MASK (DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT | \ DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT) /** * dwc3_otg_interrupt - interrupt handler for dwc3 otg events. * @_dotg: Pointer to out controller context structure * * Returns IRQ_HANDLED on success otherwise IRQ_NONE. */ static irqreturn_t dwc3_otg_interrupt(int irq, void *_dotg) { struct dwc3_otg *dotg = (struct dwc3_otg *)_dotg; u32 osts, oevt_reg; int ret = IRQ_NONE; int handled_irqs = 0; struct usb_phy *phy = dotg->otg.phy; oevt_reg = dwc3_readl(dotg->regs, DWC3_OEVT); if (!(oevt_reg & DWC3_OEVT_MASK)) return IRQ_NONE; osts = dwc3_readl(dotg->regs, DWC3_OSTS); if ((oevt_reg & DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT) || (oevt_reg & DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT)) { /* * ID sts has changed, set inputs later, in the workqueue * function, switch from A to B or from B to A. */ if (oevt_reg & DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT) { if (osts & DWC3_OTG_OSTS_CONIDSTS) { dev_dbg(phy->dev, "ID set\n"); set_bit(ID, &dotg->inputs); } else { dev_dbg(phy->dev, "ID clear\n"); clear_bit(ID, &dotg->inputs); } handled_irqs |= DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT; } if (oevt_reg & DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT) { if (osts & DWC3_OTG_OSTS_BSESVALID) { dev_dbg(phy->dev, "BSV set\n"); set_bit(B_SESS_VLD, &dotg->inputs); } else { dev_dbg(phy->dev, "BSV clear\n"); clear_bit(B_SESS_VLD, &dotg->inputs); } handled_irqs |= DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT; } queue_delayed_work(system_nrt_wq, &dotg->sm_work, 0); ret = IRQ_HANDLED; /* Clear the interrupts we handled */ dwc3_writel(dotg->regs, DWC3_OEVT, handled_irqs); } return ret; } /** * dwc3_otg_init_sm - initialize OTG statemachine input * @dotg: Pointer to the dwc3_otg structure * */ void dwc3_otg_init_sm(struct dwc3_otg *dotg) { u32 osts = dwc3_readl(dotg->regs, DWC3_OSTS); struct usb_phy *phy = dotg->otg.phy; struct dwc3_ext_xceiv *ext_xceiv; int ret; dev_dbg(phy->dev, "Initialize OTG inputs, osts: 0x%x\n", osts); /* * VBUS initial state is reported after PMIC * driver initialization. Wait for it. */ ret = wait_for_completion_timeout(&dotg->dwc3_xcvr_vbus_init, HZ * 5); if (!ret) { dev_err(phy->dev, "%s: completion timeout\n", __func__); /* We can safely assume no cable connected */ set_bit(ID, &dotg->inputs); } ext_xceiv = dotg->ext_xceiv; dwc3_otg_reset(dotg); if (ext_xceiv && !ext_xceiv->otg_capability) { if (osts & DWC3_OTG_OSTS_CONIDSTS) set_bit(ID, &dotg->inputs); else clear_bit(ID, &dotg->inputs); if (osts & DWC3_OTG_OSTS_BSESVALID) set_bit(B_SESS_VLD, &dotg->inputs); else clear_bit(B_SESS_VLD, &dotg->inputs); } }
static int mc13892_charger_update_status(struct mc13892_dev_info *di) { int ret; #ifndef CONFIG_MACH_MX51_ERDOS unsigned int value; #endif /* CONFIG_MACH_MX51_ERDOS */ int online; #ifdef CONFIG_MACH_MX51_ERDOS ret = pmic_get_dcinput_voltage ((unsigned short *)0); if (ret == 0) { online = 1; } else if (ret == 1) { online = 0; } else { online = di->charger_online; /* keep previous */ } ret = 0; /* * Battery/DCinput update */ if (online == 1) { gpio_battery_enable ( 0 ); } else if (online == 0) { gpio_battery_enable ( 1 ); } if (online != di->charger_online) { di->charger_online = online; /* * check power_supply_register. */ if (di->charger.dev != 0) { dev_info(di->charger.dev, "charger status: %s\n", online ? "online" : "offline"); power_supply_changed(&di->charger); } else { printk ("mc13892_charger_update_status: charger status: %s\n", online ? "online" : "offline"); } } #else ret = pmic_read_reg(REG_INT_SENSE0, &value, BITFMASK(BIT_CHG_DETS)); if (ret == 0) { online = BITFEXT(value, BIT_CHG_DETS); if (online != di->charger_online) { di->charger_online = online; dev_info(di->charger.dev, "charger status: %s\n", online ? "online" : "offline"); power_supply_changed(&di->charger); cancel_delayed_work(&di->monitor_work); queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ / 10); if (online) { pmic_start_coulomb_counter(); pmic_restart_charging(); } else pmic_stop_coulomb_counter(); } } #endif /* CONFIG_MACH_MX51_ERDOS */ return ret; }
static void axp_charging_monitor(struct work_struct *work) { struct axp_charger *charger; uint8_t val,temp_val[4]; int pre_rest_vol,pre_bat_curr_dir; unsigned long power_sply = 0; charger = container_of(work, struct axp_charger, work.work); pre_rest_vol = charger->rest_vol; pre_bat_curr_dir = charger->bat_current_direction; axp_charger_update_state(charger); axp_charger_update(charger, &axp81x_config); axp_read(charger->master, AXP81X_CAP,&val); spin_lock(&charger->charger_lock); charger->rest_vol = (int) (val & 0x7F); spin_unlock(&charger->charger_lock); if (axp_debug & DEBUG_SPLY) { DBG_PSY_MSG(DEBUG_SPLY, "charger->ic_temp = %d\n",charger->ic_temp); DBG_PSY_MSG(DEBUG_SPLY, "charger->bat_temp = %d\n",charger->bat_temp); DBG_PSY_MSG(DEBUG_SPLY, "charger->vbat = %d\n",charger->vbat); DBG_PSY_MSG(DEBUG_SPLY, "charger->ibat = %d\n",charger->ibat); DBG_PSY_MSG(DEBUG_SPLY, "charger->ocv = %d\n",charger->ocv); DBG_PSY_MSG(DEBUG_SPLY, "charger->disvbat = %d\n",charger->disvbat); DBG_PSY_MSG(DEBUG_SPLY, "charger->disibat = %d\n",charger->disibat); power_sply = charger->disvbat * charger->disibat; if (0 != power_sply) power_sply = power_sply/1000; DBG_PSY_MSG(DEBUG_SPLY, "power_sply = %ld mW\n",power_sply); DBG_PSY_MSG(DEBUG_SPLY, "charger->rest_vol = %d\n",charger->rest_vol); axp_reads(charger->master,0xba,2,temp_val); DBG_PSY_MSG(DEBUG_SPLY, "Axp Rdc = %d\n",(((temp_val[0] & 0x1f) <<8) + temp_val[1])*10742/10000); axp_reads(charger->master,0xe0,2,temp_val); DBG_PSY_MSG(DEBUG_SPLY, "Axp batt_max_cap = %d\n",(((temp_val[0] & 0x7f) <<8) + temp_val[1])*1456/1000); axp_reads(charger->master,0xe2,2,temp_val); DBG_PSY_MSG(DEBUG_SPLY, "Axp coulumb_counter = %d\n",(((temp_val[0] & 0x7f) <<8) + temp_val[1])*1456/1000); axp_read(charger->master,0xb8,temp_val); DBG_PSY_MSG(DEBUG_SPLY, "Axp REG_B8 = %x\n",temp_val[0]); axp_reads(charger->master,0xe4,2,temp_val); DBG_PSY_MSG(DEBUG_SPLY, "Axp OCV_percentage = %d\n",(temp_val[0] & 0x7f)); DBG_PSY_MSG(DEBUG_SPLY, "Axp Coulumb_percentage = %d\n",(temp_val[1] & 0x7f)); DBG_PSY_MSG(DEBUG_SPLY, "charger->is_on = %d\n",charger->is_on); DBG_PSY_MSG(DEBUG_SPLY, "charger->bat_current_direction = %d\n",charger->bat_current_direction); DBG_PSY_MSG(DEBUG_SPLY, "charger->charge_on = %d\n",charger->charge_on); DBG_PSY_MSG(DEBUG_SPLY, "charger->ext_valid = %d\n",charger->ext_valid); DBG_PSY_MSG(DEBUG_SPLY, "pmu_runtime_chgcur = %d\n",axp81x_config.pmu_runtime_chgcur); DBG_PSY_MSG(DEBUG_SPLY, "pmu_earlysuspend_chgcur = %d\n",axp81x_config.pmu_earlysuspend_chgcur); DBG_PSY_MSG(DEBUG_SPLY, "pmu_suspend_chgcur = %d\n",axp81x_config.pmu_suspend_chgcur); DBG_PSY_MSG(DEBUG_SPLY, "pmu_shutdown_chgcur = %d\n\n\n",axp81x_config.pmu_shutdown_chgcur); } /* if battery volume changed, inform uevent */ if((charger->rest_vol - pre_rest_vol) || (charger->bat_current_direction != pre_bat_curr_dir)){ axp_reads(charger->master,0xe2,2,temp_val); axp_reads(charger->master,0xe4,2,(temp_val+2)); DBG_PSY_MSG(DEBUG_SPLY, "battery vol change: %d->%d \n", pre_rest_vol, charger->rest_vol); DBG_PSY_MSG(DEBUG_SPLY, "for test %d %d %d %d %d %d\n",charger->vbat,charger->ocv,charger->ibat, (temp_val[2] & 0x7f),(temp_val[3] & 0x7f),(((temp_val[0] & 0x7f) <<8) + temp_val[1])*1456/1000); pre_rest_vol = charger->rest_vol; power_supply_changed(&charger->batt); } /* reschedule for the next time */ schedule_delayed_work(&charger->work, charger->interval); }
static void axp288_charger_extcon_evt_worker(struct work_struct *work) { struct axp288_chrg_info *info = container_of(work, struct axp288_chrg_info, cable.work); int ret, current_limit; bool changed = false; struct extcon_dev *edev = info->cable.edev; bool old_connected = info->cable.connected; /* Determine cable/charger type */ if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_SDP) > 0) { dev_dbg(&info->pdev->dev, "USB SDP charger is connected"); info->cable.connected = true; info->cable.chg_type = POWER_SUPPLY_TYPE_USB; } else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_CDP) > 0) { dev_dbg(&info->pdev->dev, "USB CDP charger is connected"); info->cable.connected = true; info->cable.chg_type = POWER_SUPPLY_TYPE_USB_CDP; } else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_DCP) > 0) { dev_dbg(&info->pdev->dev, "USB DCP charger is connected"); info->cable.connected = true; info->cable.chg_type = POWER_SUPPLY_TYPE_USB_DCP; } else { if (old_connected) dev_dbg(&info->pdev->dev, "USB charger disconnected"); info->cable.connected = false; info->cable.chg_type = POWER_SUPPLY_TYPE_USB; } /* Cable status changed */ if (old_connected != info->cable.connected) changed = true; if (!changed) return; mutex_lock(&info->lock); if (info->is_charger_enabled && !info->cable.connected) { info->enable_charger = false; ret = axp288_charger_enable_charger(info, info->enable_charger); if (ret < 0) dev_err(&info->pdev->dev, "cannot disable charger (%d)", ret); } else if (!info->is_charger_enabled && info->cable.connected) { switch (info->cable.chg_type) { case POWER_SUPPLY_TYPE_USB: current_limit = ILIM_500MA; break; case POWER_SUPPLY_TYPE_USB_CDP: current_limit = ILIM_1500MA; break; case POWER_SUPPLY_TYPE_USB_DCP: current_limit = ILIM_2000MA; break; default: /* Unknown */ current_limit = 0; break; } /* Set vbus current limit first, then enable charger */ ret = axp288_charger_set_vbus_inlmt(info, current_limit); if (ret < 0) { dev_err(&info->pdev->dev, "error setting current limit (%d)", ret); } else { info->enable_charger = (current_limit > 0); ret = axp288_charger_enable_charger(info, info->enable_charger); if (ret < 0) dev_err(&info->pdev->dev, "cannot enable charger (%d)", ret); } } if (changed) info->health = axp288_get_charger_health(info); mutex_unlock(&info->lock); if (changed) power_supply_changed(info->psy_usb); }
static void manta_bat_send_uevent(void) { power_supply_changed(&manta_battery_psy); }
static void update_charge_state(void) { int module_type = 0; int usb_type; if( _usb && !_dcin ) { // usb without DC-in usb_type = atmega_io_getUsbType(); DBG printk("usb_type=%d\n", usb_type); if (usb_type & USB_LOCAL) { if ( usb_charge_level() ) { enable_high_charging(); } else { enable_low_charging(); } } else if (usb_type == USB_EXT) { module_type = atmega_io_getModuleType(); DBG printk("module_type=%d\n", module_type); if ( module_type == MODULE_ID_SERIAL_ADAPTER ) { enable_low_charging(); } else { disable_charging(); } } else { // no charge with only ext usb & can't happen when plugging the PC cable disable_charging(); } goto out; } if( _dcin && !_usb ){ // ! warning ! this case should appears with pc_cable during plug or with // not complete connection, don't enable high charge in this case // enable high charge only if an allowed module is identified module_type = atmega_io_getModuleType(); DBG printk("module_type=%d\n", module_type); if ( is_module_capable_high_charging(module_type) ) { enable_high_charging(); } goto out; } if( _usb && _dcin ){ // Means normally that both the USB cable and DC-in are plugged. // But be careful that both flags are also enabled when plugging the PC cable module_type = atmega_io_getModuleType(); DBG printk("module_type=%d\n", module_type); if ( is_module_capable_high_charging(module_type) ) { enable_high_charging(); } else { // pc cable only or pc cable and micro usb usb_type = atmega_io_getUsbType(); DBG printk("usb_type=%d\n", usb_type); if (usb_type == USB_EXT) { // pc cable only if ( usb_charge_level() ) { enable_high_charging(); } else { enable_low_charging(); } } else // in this case, usb source to check is not the power source enable_low_charging(); } goto out; } if( charge_state && ( !_usb && !_dcin )){ disable_charging(); goto out; } out: #ifdef CONFIG_POWER_SUPPLY power_supply_changed(&main_battery); #endif /* make compiler happy if CONFIG_POWER_SUPPLY is not defined */ return; }
static void bq27x00_update(struct bq27x00_device_info *di) { struct bq27x00_reg_cache cache = {0, }; bool is_bq27500 = di->chip == BQ27500; bool is_bq27510 = di->chip == BQ27510; bool is_bq27425 = di->chip == BQ27425; bool is_bq27742 = di->chip == BQ27742; bool flags_1b = !(is_bq27500 || is_bq27742); cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, flags_1b); if ((cache.flags & 0xff) == 0xff) /* read error */ cache.flags = -1; if (cache.flags >= 0) { if (!is_bq27500 && !is_bq27425 && !is_bq27742 && !is_bq27510 && (cache.flags & BQ27000_FLAG_CI)) { dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n"); cache.capacity = -ENODATA; cache.energy = -ENODATA; cache.time_to_empty = -ENODATA; cache.time_to_empty_avg = -ENODATA; cache.time_to_full = -ENODATA; cache.charge_full = -ENODATA; cache.health = -ENODATA; } else { cache.capacity = bq27x00_battery_read_rsoc(di); if (is_bq27742 || is_bq27510) cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE); else if (!is_bq27425) { cache.energy = bq27x00_battery_read_energy(di); cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE); cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); } cache.charge_full = bq27x00_battery_read_lmd(di); cache.health = bq27x00_battery_read_health(di); } cache.temperature = bq27x00_battery_read_temperature(di); if (!is_bq27425) cache.cycle_count = bq27x00_battery_read_cyct(di); if (is_bq27742) cache.power_avg = bq27x00_battery_read_pwr_avg(di, BQ27742_POWER_AVG); else cache.power_avg = bq27x00_battery_read_pwr_avg(di, BQ27x00_POWER_AVG); /* We only have to read charge design full once */ if (di->charge_design_full <= 0) di->charge_design_full = bq27x00_battery_read_ilmd(di); } if (di->cache.capacity != cache.capacity) power_supply_changed(di->bat); if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) di->cache = cache; di->last_update = jiffies; }
static void dev_detect_isr(struct mhl_tx_ctrl *mhl_ctrl) { uint8_t status, reg ; struct i2c_client *client = mhl_ctrl->i2c_handle; /* INTR_STATUS4 */ status = MHL_SII_REG_NAME_RD(REG_INTR4); pr_debug("%s: reg int4 st=%02X\n", __func__, status); if ((0x00 == status) &&\ (mhl_ctrl->cur_state == POWER_STATE_D3)) { pr_err("%s: invalid intr\n", __func__); return; } if (0xFF == status) { pr_debug("%s: invalid intr 0xff\n", __func__); MHL_SII_REG_NAME_WR(REG_INTR4, status); return; } if ((status & BIT0) && (mhl_ctrl->chip_rev_id < 1)) { pr_debug("%s: scdt intr\n", __func__); scdt_st_chg(client); } if (status & BIT1) pr_debug("mhl: int4 bit1 set\n"); /* mhl_est interrupt */ if (status & BIT2) { pr_debug("%s: mhl_est st=%02X\n", __func__, (int) status); mhl_msm_connection(mhl_ctrl); } else if (status & BIT3) { pr_debug("%s: uUSB-a type dev detct\n", __func__); /* Short RGND */ MHL_SII_REG_NAME_MOD(REG_DISC_STAT2, BIT0 | BIT1, 0x00); mhl_msm_disconnection(mhl_ctrl); power_supply_changed(&mhl_ctrl->mhl_psy); if (mhl_ctrl->notify_usb_online) mhl_ctrl->notify_usb_online(0); } if (status & BIT5) { /* clr intr - reg int4 */ pr_debug("%s: mhl discon: int4 st=%02X\n", __func__, (int)status); reg = MHL_SII_REG_NAME_RD(REG_INTR4); MHL_SII_REG_NAME_WR(REG_INTR4, reg); mhl_msm_disconnection(mhl_ctrl); power_supply_changed(&mhl_ctrl->mhl_psy); if (mhl_ctrl->notify_usb_online) mhl_ctrl->notify_usb_online(0); } if ((mhl_ctrl->cur_state != POWER_STATE_D0_NO_MHL) &&\ (status & BIT6)) { /* rgnd rdy Intr */ pr_debug("%s: rgnd ready intr\n", __func__); switch_mode(mhl_ctrl, POWER_STATE_D0_NO_MHL); mhl_msm_read_rgnd_int(mhl_ctrl); } /* Can't succeed at these in D3 */ if ((mhl_ctrl->cur_state != POWER_STATE_D3) &&\ (status & BIT4)) { /* cbus lockout interrupt? * Hardware detection mechanism figures that * CBUS line is latched and raises this intr * where we force usb switch open and release */ pr_warn("%s: cbus locked out!\n", __func__); force_usb_switch_open(mhl_ctrl); release_usb_switch_open(mhl_ctrl); } MHL_SII_REG_NAME_WR(REG_INTR4, status); return; }
int opchg_battery_set_property(struct power_supply *psy, enum power_supply_property prop, const union power_supply_propval *val) { int rc; struct opchg_charger *chip = container_of(psy, struct opchg_charger, batt_psy); switch (prop) { case POWER_SUPPLY_PROP_STATUS: if (!chip->bms_controlled_charging) return -EINVAL; switch (val->intval) { case POWER_SUPPLY_STATUS_FULL: rc = smb358_charging_disable(chip, SOC, true); if (rc < 0) { dev_err(chip->dev,"Couldn't set charging disable rc = %d\n",rc); } else { chip->batt_full = true; dev_dbg(chip->dev, "status = FULL, batt_full = %d\n",chip->batt_full); } break; case POWER_SUPPLY_STATUS_DISCHARGING: chip->batt_full = false; power_supply_changed(&chip->batt_psy); dev_dbg(chip->dev, "status = DISCHARGING, batt_full = %d\n",chip->batt_full); break; case POWER_SUPPLY_STATUS_CHARGING: rc = smb358_charging_disable(chip, SOC, false); if (rc < 0) { dev_err(chip->dev,"Couldn't set charging disable rc = %d\n",rc); } else { chip->batt_full = false; dev_dbg(chip->dev, "status = CHARGING, batt_full = %d\n",chip->batt_full); } break; default: return -EINVAL; } break; case POWER_SUPPLY_PROP_CHARGING_ENABLED: opchg_config_charging_disable(chip, USER_DISABLE, !val->intval);//smb358_charging(chip, val->intval); break; case POWER_SUPPLY_PROP_CAPACITY: chip->fake_battery_soc = val->intval; power_supply_changed(&chip->batt_psy); break; case POWER_SUPPLY_PROP_BATTERY_CHARGER_ENABLE: chip->is_factory_mode= val->intval; if(chip->is_factory_mode == true) { if(is_project(OPPO_15011)||is_project(OPPO_14045)||is_project(OPPO_15005) || is_project(OPPO_15025)) { opchg_config_charging_disable(chip, FACTORY_MODE_DISABLE, 0); } } else { if(is_project(OPPO_15011)||is_project(OPPO_14045)||is_project(OPPO_15005) || is_project(OPPO_15025)) { opchg_config_charging_disable(chip, FACTORY_MODE_DISABLE, 1); } } break; default: return -EINVAL; } return 0; }
static void rk2918_battery_timer_work(struct work_struct *work) { dprint("func=%s, line=%d :\n", __func__, __LINE__); rk2918_get_bat_status(gBatteryData); rk2918_get_bat_health(gBatteryData); rk2918_get_bat_present(gBatteryData); rk2918_get_bat_voltage(gBatteryData); //to prevent gBatCapacity be changed sharply if (gBatCapacity < 0) { gBatCapacity = 0; } else { if (gBatCapacity > 100) { gBatCapacity = 100; } } rk2918_get_bat_capacity(gBatteryData); if (rk29_battery_dbg_level) { if (++AdcTestCnt >= 20) { AdcTestCnt = 0; printk("\nchg_ok_level =%d, chg_ok= %d, gBatStatus = %d, adc_val = %d, TrueBatVol = %d,gBatVol = %d, gBatCap = %d, captmp = %d, sec = %lu, time_chg_flag = %d, first_flag = %d\n", gBatteryData->charge_ok_level, gpio_get_value(gBatteryData->charge_ok_pin), gBatStatus, AdcTestvalue, adc_to_voltage(AdcTestvalue), gBatVoltage, gBatCapacity, capacitytmp, batteryspendcnt, time_chg_flag, first_flag); } } /*update battery parameter after adc and capacity has been changed*/ if(((gBatStatus != gBatLastStatus) || (gBatPresent != gBatLastPresent) || (gBatCapacity != gBatLastCapacity))&&(suspend_flag==0)) { //for debug if (rk29_battery_dbg_level) { char _tmp_buf[250]; int buf_len = 0; struct file* fp; sprintf(_tmp_buf, "gBatStatus = %d, adc_val = %d, TrueBatVol = %d,gBatVol = %d, gBatCap = %d, captmp = %d, sec = %lu, inter_sec = %lu, time_chg_flag = %d, first_flag = %d\n", gBatStatus, AdcTestvalue, ((AdcTestvalue * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R)), gBatVoltage, gBatCapacity, capacitytmp, batteryspendcnt, batteryspendcnt - last_batteryspendcnt, time_chg_flag, first_flag); buf_len = strlen(_tmp_buf); fp = filp_open(BATT_DBG_FILE,O_RDWR | O_APPEND | O_CREAT, 0); if(IS_ERR(fp)) { printk("bryan---->open file /data/bat_dbg_record.dat failed\n"); } else { kernel_write(fp, _tmp_buf, buf_len ,buf_offset); filp_close(fp,NULL); buf_offset += buf_len; } last_batteryspendcnt = batteryspendcnt; } gBatLastStatus = gBatStatus; gBatLastPresent = gBatPresent; gBatLastCapacity = gBatCapacity; power_supply_changed(&gBatteryData->battery); } }
static void opchg_external_power_changed(struct power_supply *psy) { struct opchg_charger *chip = container_of(psy, struct opchg_charger, batt_psy); union power_supply_propval prop = {0,}; int rc, current_limit = 0, online = 0; if (chip->bms_psy_name) { chip->bms_psy = power_supply_get_by_name((char *)chip->bms_psy_name); } rc = chip->usb_psy->get_property(chip->usb_psy, POWER_SUPPLY_PROP_ONLINE, &prop); if (rc) { dev_err(chip->dev, "Couldn't read USB online property, rc=%d\n", rc); } else { online = prop.intval; } rc = chip->usb_psy->get_property(chip->usb_psy, POWER_SUPPLY_PROP_CURRENT_MAX, &prop); if (rc) { dev_err(chip->dev, "Couldn't read USB current_max property, rc=%d\n", rc); } else { current_limit = prop.intval / 1000; } if(current_limit > chip->limit_current_max_ma) { current_limit = chip->limit_current_max_ma; } //lfc add for charger_ovp chip->charger_vol = opchg_get_prop_charger_voltage_now(chip); opchg_get_charger_ov_status(chip); if(chip->charger_ov_status == true) { dev_err(chip->dev,"%s charger-ovp,return \n",__func__); return ; } opchg_set_enable_volatile_writes(chip); opchg_config_input_chg_current(chip, INPUT_CURRENT_LCD, chip->limit_current_max_ma); opchg_config_input_chg_current(chip, INPUT_CURRENT_CAMERA, chip->limit_current_max_ma); opchg_config_input_chg_current(chip, INPUT_CURRENT_BY_POWER, current_limit); if(is_project(OPPO_14043) || is_project(OPPO_14051) || is_project(OPPO_15005) || is_project(OPPO_15057) || is_project(OPPO_15025)) opchg_set_input_chg_current(chip, chip->max_input_current[INPUT_CURRENT_BY_POWER], false); else opchg_set_input_chg_current(chip, chip->max_input_current[INPUT_CURRENT_MIN], false); if ((chip->multiple_test == 1) && (current_limit >= 500)) { opchg_config_suspend_enable(chip, FACTORY_ENABLE, 1); } opchg_config_over_time(chip, current_limit);//opchg_set_complete_charge_timeout(chip); dev_dbg(chip->dev, "%s set charger input current=%d,online = %d, current_limit = %d\n", __func__,chip->max_input_current[INPUT_CURRENT_MIN], online, current_limit); opchg_check_status(chip); power_supply_changed(&chip->batt_psy); if(is_project(OPPO_14043) || is_project(OPPO_15005) || is_project(OPPO_15025)) { if(qpnp_charger_type_get(chip) == POWER_SUPPLY_TYPE_USB_DCP) { if(!chip->check_stat_again && (current_limit >= 500) && (chip->charging_current > -250)) { msleep(550); opchg_check_status(chip); chip->check_stat_again = true; power_supply_changed(&chip->batt_psy); } } } }
int _charger_state_change_( int category, int value, bool is_sleep ) { printk( "[BM] cate: %d, value: %d\n", category, value ); if( category == STATUS_CATEGORY_CABLE ) { switch( value ) { case POWER_SUPPLY_TYPE_BATTERY : /*Stop monitoring the batt. level for Re-charging*/ sec_bci.battery.monitor_field_rechg_vol = false; /*Stop monitoring the temperature*/ sec_bci.battery.monitor_field_temp = false; sec_bci.battery.confirm_full_by_current = 0; sec_bci.battery.confirm_recharge = 0; sec_bci.charger.charging_timeout = DEFAULT_CHARGING_TIMEOUT; sec_bci.charger.full_charge_dur_sleep = 0x0; break; case POWER_SUPPLY_TYPE_MAINS : sec_bci.charger.charging_timeout = DEFAULT_CHARGING_TIMEOUT; wake_lock_timeout( &sec_bc_wakelock , HZ ); break; case POWER_SUPPLY_TYPE_USB : break; default : break; } goto Out_Charger_State_Change; } else if( category == STATUS_CATEGORY_CHARGING ) { switch( value ) { case POWER_SUPPLY_STATUS_UNKNOWN : case POWER_SUPPLY_STATUS_NOT_CHARGING : //sec_bci.charger.full_charge = false; /*Stop monitoring the batt. level for Re-charging*/ sec_bci.battery.monitor_field_rechg_vol = false; if( sec_bci.battery.battery_health != POWER_SUPPLY_HEALTH_OVERHEAT && sec_bci.battery.battery_health != POWER_SUPPLY_HEALTH_COLD ) { /*Stop monitoring the temperature*/ sec_bci.battery.monitor_field_temp = false; } break; case POWER_SUPPLY_STATUS_DISCHARGING : break; case POWER_SUPPLY_STATUS_FULL : /*Start monitoring the batt. level for Re-charging*/ sec_bci.battery.monitor_field_rechg_vol = true; /*Stop monitoring the temperature*/ sec_bci.battery.monitor_field_temp = false; wake_lock_timeout( &sec_bc_wakelock , HZ ); break; case POWER_SUPPLY_STATUS_CHARGING : /*Start monitoring the temperature*/ sec_bci.battery.monitor_field_temp = true; /*Stop monitoring the batt. level for Re-charging*/ sec_bci.battery.monitor_field_rechg_vol = false; break; case POWER_SUPPLY_STATUS_RECHARGING_FOR_FULL : /*Start monitoring the temperature*/ sec_bci.battery.monitor_field_temp = true; /*Stop monitoring the batt. level for Re-charging*/ sec_bci.battery.monitor_field_rechg_vol = false; /*Not change the battery bar - keep battery full screen*/ //goto Out_Charger_State_Change; break; case POWER_SUPPLY_STATUS_RECHARGING_FOR_TEMP : /*Start monitoring the temperature*/ sec_bci.battery.monitor_field_temp = true; /*Stop monitoring the batt. level for Re-charging*/ sec_bci.battery.monitor_field_rechg_vol = false; break; default : break; } } if( !is_sleep ) { struct battery_device_info *di; struct platform_device *pdev; pdev = to_platform_device( this_dev ); di = platform_get_drvdata( pdev ); cancel_delayed_work( &di->battery_monitor_work ); queue_delayed_work( sec_bci.sec_battery_workq, &di->battery_monitor_work, 5 * HZ ); power_supply_changed( &di->sec_battery ); power_supply_changed( &di->sec_ac ); power_supply_changed( &di->sec_usb ); } else { release_gptimer12( &batt_gptimer_12 ); request_gptimer12( &batt_gptimer_12 ); } Out_Charger_State_Change : return 0; }
static void charger_work(struct work_struct *work) { struct charger_info *di = container_of(work, struct charger_info, work); int next_state; bool limiting_active; bool charge_source; if (is_charging(di)) charger_pet_watchdog(di); charger_lock(di); /* update inputs and limit conditions */ charger_gas_gauge_update(di); charger_check_temp_limits(di); charger_check_battery_level(di); /* aggregate limiting factors */ limiting_active = di->battery_full || di->charge_disabled || di->temperature_lockout; /* hardware ready for charging? */ charge_source = di->vbus_online && !di->otg_online; dev_dbg(di->dev, "%s: battery_full=%d charge_disabled=%d temperature_lockout=%d " "invalid_charger=%d vbus_online=%d usb_online=%d otg_online=%d\n", __func__, di->battery_full, di->charge_disabled, di->temperature_lockout, di->invalid_charger, di->vbus_online, di->usb_online, di->otg_online); /* determine the next charger state */ switch (di->state) { case CHARGER_STATE_UNPLUGGED: case CHARGER_STATE_CHARGING: if (charge_source) { if (limiting_active) next_state = CHARGER_STATE_NOT_CHARGING; else next_state = CHARGER_STATE_CHARGING; } else { next_state = CHARGER_STATE_UNPLUGGED; } break; case CHARGER_STATE_NOT_CHARGING: if (charge_source) { if (limiting_active) next_state = CHARGER_STATE_NOT_CHARGING; else next_state = CHARGER_STATE_CHARGING; } else { next_state = CHARGER_STATE_UNPLUGGED; } break; default: next_state = di->state; // silence compiler warning } /* if the state changed, fulfill the required changes */ if (next_state != di->state) { dev_info(di->dev, "transitioning from %s to %s\n", state_to_str(di->state), state_to_str(next_state)); switch (next_state) { case CHARGER_STATE_UNPLUGGED: wake_lock_timeout(&di->wake_lock, HZ / 2); charger_stop_usb_charger(di); break; case CHARGER_STATE_NOT_CHARGING: if (!is_powered(di)) wake_lock(&di->wake_lock); charger_stop_usb_charger(di); break; case CHARGER_STATE_CHARGING: if (!is_powered(di)) wake_lock(&di->wake_lock); charger_start_usb_charger(di); break; } di->state = next_state; power_supply_changed(&di->usb); twl6030_eval_led_state(di->led, is_powered(di), is_charging(di)); } charger_unlock(di); /* update timer */ mod_timer(&di->timer, di->monitor_interval_jiffies + jiffies); }
static void battery_monitor_work_handler( struct work_struct *work ) { int is_full = 0; int charge_current_adc; struct battery_device_info *di = container_of( work, struct battery_device_info, battery_monitor_work.work ); #if 0 printk( "[BM] battery monitor [Level:%d, ADC:%d, TEMP.:%d, cable: %d] \n",\ get_battery_level_ptg(),\ get_battery_level_adc(),\ get_system_temperature(),\ sec_bci.charger.cable_status ); #endif boot_monitor_count++; if(!boot_complete && boot_monitor_count >= 2) { printk("[BM] boot complete \n"); boot_complete = true; } if(sec_bci.charger.rechg_count > 0) sec_bci.charger.rechg_count--; // printk("[BM] MMC2_DAT0 : %x\n", omap_readw(0x4800215c)); if ( device_config->MONITORING_SYSTEM_TEMP ) sec_bci.battery.battery_temp = get_system_temperature( TEMP_DEG ); else sec_bci.battery.battery_temp = 0; #if 0 update_rcomp_by_temperature(sec_bci.battery.battery_temp); #endif /* Monitoring the battery info. */ sec_bci.battery.battery_level_ptg = get_battery_level_ptg(); msleep(10); sec_bci.battery.battery_level_vol= get_battery_level_adc(); if( !( sec_bci.battery.monitor_field_temp ) && !( sec_bci.battery.monitor_field_rechg_vol ) ) { sec_bci.battery.monitor_duration = MONITOR_DEFAULT_DURATION; } else { // Workaround : check status of cabel at this point. if ( !_cable_status_now_() ) { _battery_state_change_( STATUS_CATEGORY_ETC, ETC_CABLE_IS_DISCONNECTED, CHARGE_DUR_ACTIVE ); } if ( sec_bci.charger.is_charging && device_config->MONITORING_CHG_CURRENT ) { // in charging && enable monitor_chg_current charge_current_adc = get_charging_current_adc_val(); is_full = check_full_charge_using_chg_current( charge_current_adc ); if ( is_full ) { _battery_state_change_( STATUS_CATEGORY_CHARGING, POWER_SUPPLY_STATUS_FULL, CHARGE_DUR_ACTIVE ); } else { battery_monitor_core( CHARGE_DUR_ACTIVE ); } } else { battery_monitor_core( CHARGE_DUR_ACTIVE ); } } #if 1 printk( "[BM] monitor BATT.(%d%%, %dmV, %d*, count=%d, charging=%d)\n", sec_bci.battery.battery_level_ptg, sec_bci.battery.battery_level_vol, sec_bci.battery.battery_temp, boot_monitor_count, sec_bci.charger.is_charging ); #endif //printk("[BM] adc 167 -> %d^, adc 198 -> %d^\n", t2adc_to_temperature(927, 0), t2adc_to_temperature(884, 0)); power_supply_changed( &di->sec_battery ); power_supply_changed( &di->sec_ac ); power_supply_changed( &di->sec_usb ); queue_delayed_work( sec_bci.sec_battery_workq, &di->battery_monitor_work, sec_bci.battery.monitor_duration * HZ); }
static void android_bat_monitor_work(struct work_struct *work) { struct android_bat_data *battery = container_of(work, struct android_bat_data, monitor_work); struct timespec cur_time; wake_lock(&battery->monitor_wake_lock); android_bat_update_data(battery); mutex_lock(&android_bat_state_lock); switch (battery->charging_status) { case POWER_SUPPLY_STATUS_FULL: if (battery->batt_vcell < battery->pdata->recharging_voltage && !battery->recharging) { battery->recharging = true; android_bat_enable_charging(battery, true); pr_info("battery: start recharging, v=%d\n", battery->batt_vcell/1000); } break; case POWER_SUPPLY_STATUS_DISCHARGING: break; case POWER_SUPPLY_STATUS_CHARGING: switch (battery->batt_health) { case POWER_SUPPLY_HEALTH_OVERHEAT: case POWER_SUPPLY_HEALTH_COLD: case POWER_SUPPLY_HEALTH_OVERVOLTAGE: case POWER_SUPPLY_HEALTH_DEAD: case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE: battery->charging_status = POWER_SUPPLY_STATUS_NOT_CHARGING; android_bat_enable_charging(battery, false); pr_info("battery: Not charging, health=%d\n", battery->batt_health); break; default: break; } break; case POWER_SUPPLY_STATUS_NOT_CHARGING: if (battery->batt_health == POWER_SUPPLY_HEALTH_GOOD) { pr_info("battery: battery health recovered\n"); if (battery->charge_source != CHARGE_SOURCE_NONE) { android_bat_enable_charging(battery, true); battery->charging_status = POWER_SUPPLY_STATUS_CHARGING; } else { battery->charging_status = POWER_SUPPLY_STATUS_DISCHARGING; } } break; default: pr_err("%s: Undefined battery status: %d\n", __func__, battery->charging_status); break; } android_bat_charging_timer(battery); get_monotonic_boottime(&cur_time); pr_info("battery: l=%d v=%d c=%d temp=%s%ld.%ld h=%d st=%d%s ct=%lu type=%s\n", battery->batt_soc, battery->batt_vcell/1000, battery->batt_current, battery->batt_temp < 0 ? "-" : "", abs(battery->batt_temp / 10), abs(battery->batt_temp % 10), battery->batt_health, battery->charging_status, battery->recharging ? "r" : "", battery->charging_start_time ? cur_time.tv_sec - battery->charging_start_time : 0, charge_source_str(battery->charge_source)); mutex_unlock(&android_bat_state_lock); power_supply_changed(&battery->psy_bat); battery->last_poll = ktime_get_boottime(); android_bat_monitor_set_alarm(battery, FAST_POLL); wake_unlock(&battery->monitor_wake_lock); return; }
static int dwc3_otg_set_power(struct usb_phy *phy, unsigned mA) { enum power_supply_property power_supply_type; struct dwc3_otg *dotg = container_of(phy->otg, struct dwc3_otg, otg); if (!dotg->psy || !dotg->charger) { dev_err(phy->dev, "no usb power supply/charger registered\n"); return 0; } if (dotg->charger->charging_disabled) return 0; if (not_use_sw_chg_det && (dotg->charger->chg_type != DWC3_INVALID_CHARGER)) { dev_dbg(phy->dev, "SKIP setting power supply type again,chg_type = %d\n", dotg->charger->chg_type); goto skip_psy_type; } if (dotg->charger->chg_type == DWC3_SDP_CHARGER) power_supply_type = POWER_SUPPLY_TYPE_USB; else if (dotg->charger->chg_type == DWC3_CDP_CHARGER) power_supply_type = POWER_SUPPLY_TYPE_USB_CDP; else if (dotg->charger->chg_type == DWC3_DCP_CHARGER || dotg->charger->chg_type == DWC3_PROPRIETARY_CHARGER || dotg->charger->chg_type == DWC3_PROPRIETARY_1000MA || dotg->charger->chg_type == DWC3_PROPRIETARY_500MA) power_supply_type = POWER_SUPPLY_TYPE_USB_DCP; else power_supply_type = POWER_SUPPLY_TYPE_UNKNOWN; power_supply_set_supply_type(dotg->psy, power_supply_type); skip_psy_type: if (dotg->charger->chg_type == DWC3_CDP_CHARGER) mA = DWC3_IDEV_CHG_MAX; if (dotg->charger->max_power == mA) return 0; dev_info(phy->dev, "Avail curr from USB = %u\n", mA); if (dotg->charger->max_power > 0 && (mA == 0 || mA == 2)) { /* Disable charging */ if (power_supply_set_online(dotg->psy, false)) goto psy_error; } else { /* Enable charging */ if (power_supply_set_online(dotg->psy, true)) goto psy_error; } /* Set max current limit in uA */ if (power_supply_set_current_limit(dotg->psy, 1000*mA)) goto psy_error; power_supply_changed(dotg->psy); dotg->charger->max_power = mA; return 0; psy_error: dev_dbg(phy->dev, "power supply error when setting property\n"); return -ENXIO; }
static void bq24297_status_func(struct work_struct *work) { int ret; ret = bq24297_read_reg(SYSTEM_STATUS_REG); this_chip->pg_stat = (ret & PG_STAT_MASK)>>PG_STAT_SHIFT; this_chip->chrg_stat = (ret & CHRG_STAT_MASK)>>CHRG_STAT_SHIFT; this_chip->vbus_stat = (ret & VBUS_STAT_MASK)>>VBUS_STAT_SHIFT; bq24297_print("%s(), reg[8] = 0x%x\n", __FUNCTION__, ret); if (this_chip->pg_stat == 0) { this_chip->usb_online = 0; this_chip->ac_online = 0; } else if (this_chip->pg_stat == 1 && this_chip->vbus_stat == 0x01) { this_chip->usb_online = 1; this_chip->ac_online = 0; } else if (this_chip->pg_stat == 1 && this_chip->vbus_stat == 0x02) { this_chip->usb_online = 0; this_chip->ac_online = 1; } else { return ; } if (this_chip->chrg_stat == 0x00) { this_chip->chrg_stat = POWER_SUPPLY_STATUS_NOT_CHARGING; } else if (this_chip->chrg_stat == 0x01) { this_chip->chrg_stat = POWER_SUPPLY_STATUS_CHARGING; } else if (this_chip->chrg_stat == 0x02) { this_chip->chrg_stat = POWER_SUPPLY_STATUS_CHARGING; } else if (this_chip->chrg_stat == 0x03) { this_chip->chrg_stat = POWER_SUPPLY_STATUS_FULL; } if (this_chip->ac_online) bq24297_set_ac_charge_current(); else if (this_chip->usb_online) bq24297_set_usb_charge_current(); else bq24297_set_usb_charge_current(); if (!this_chip->battery) this_chip->battery = power_supply_get_by_name("battery"); if (this_chip->battery) power_supply_changed(this_chip->battery); }
static void isp1704_charger_work(struct work_struct *data) { int detect; unsigned long event; unsigned power; struct isp1704_charger *isp = container_of(data, struct isp1704_charger, work); static DEFINE_MUTEX(lock); event = isp->event; power = isp->max_power; mutex_lock(&lock); if (event != USB_EVENT_NONE) isp1704_charger_set_power(isp, 1); switch (event) { case USB_EVENT_VBUS: isp->online = true; /* detect charger */ detect = isp1704_charger_detect(isp); if (detect) { isp->present = detect; isp->psy.type = isp1704_charger_type(isp); } switch (isp->psy.type) { case POWER_SUPPLY_TYPE_USB_DCP: isp->current_max = 1800; break; case POWER_SUPPLY_TYPE_USB_CDP: /* * Only 500mA here or high speed chirp * handshaking may break */ isp->current_max = 500; /* FALLTHROUGH */ case POWER_SUPPLY_TYPE_USB: default: /* enable data pullups */ if (isp->phy->otg->gadget) usb_gadget_connect(isp->phy->otg->gadget); } break; case USB_EVENT_NONE: isp->online = false; isp->current_max = 0; isp->present = 0; isp->current_max = 0; isp->psy.type = POWER_SUPPLY_TYPE_USB; /* * Disable data pullups. We need to prevent the controller from * enumerating. * * FIXME: This is here to allow charger detection with Host/HUB * chargers. The pullups may be enabled elsewhere, so this can * not be the final solution. */ if (isp->phy->otg->gadget) usb_gadget_disconnect(isp->phy->otg->gadget); isp1704_charger_set_power(isp, 0); break; case USB_EVENT_ENUMERATED: if (isp->present) isp->current_max = 1800; else isp->current_max = power; break; default: goto out; } power_supply_changed(&isp->psy); out: mutex_unlock(&lock); }
static int pm2xxx_charger_ac_en(struct ux500_charger *charger, int enable, int vset, int iset) { int ret; int volt_index; int curr_index; u8 val; struct pm2xxx_charger *pm2 = to_pm2xxx_charger_ac_device_info(charger); if (enable) { if (!pm2->ac.charger_connected) { dev_dbg(pm2->dev, "AC charger not connected\n"); return -ENXIO; } dev_dbg(pm2->dev, "Enable AC: %dmV %dmA\n", vset, iset); if (!pm2->vddadc_en_ac) { ret = regulator_enable(pm2->regu); if (ret) dev_warn(pm2->dev, "Failed to enable vddadc regulator\n"); else pm2->vddadc_en_ac = true; } ret = pm2xxx_charging_init(pm2); if (ret < 0) { dev_err(pm2->dev, "%s charging init failed\n", __func__); goto error_occured; } volt_index = pm2xxx_voltage_to_regval(vset); curr_index = pm2xxx_current_to_regval(iset); if (volt_index < 0 || curr_index < 0) { dev_err(pm2->dev, "Charger voltage or current too high, " "charging not started\n"); return -ENXIO; } ret = pm2xxx_reg_read(pm2, PM2XXX_BATT_CTRL_REG8, &val); if (ret < 0) { dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__); goto error_occured; } val &= ~PM2XXX_CH_VOLT_MASK; val |= volt_index; ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG8, val); if (ret < 0) { dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__); goto error_occured; } ret = pm2xxx_reg_read(pm2, PM2XXX_BATT_CTRL_REG6, &val); if (ret < 0) { dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__); goto error_occured; } val &= ~PM2XXX_DIR_CH_CC_CURRENT_MASK; val |= curr_index; ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG6, val); if (ret < 0) { dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__); goto error_occured; } if (!pm2->bat->enable_overshoot) { ret = pm2xxx_reg_read(pm2, PM2XXX_LED_CTRL_REG, &val); if (ret < 0) { dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__); goto error_occured; } val |= PM2XXX_ANTI_OVERSHOOT_EN; ret = pm2xxx_reg_write(pm2, PM2XXX_LED_CTRL_REG, val); if (ret < 0) { dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__); goto error_occured; } } ret = pm2xxx_charging_enable_mngt(pm2); if (ret < 0) { dev_err(pm2->dev, "Failed to enable" "pm2xxx ac charger\n"); goto error_occured; } pm2->ac.charger_online = 1; } else { pm2->ac.charger_online = 0; pm2->ac.wd_expired = false; /* Disable regulator if enabled */ if (pm2->vddadc_en_ac) { regulator_disable(pm2->regu); pm2->vddadc_en_ac = false; } ret = pm2xxx_charging_disable_mngt(pm2); if (ret < 0) { dev_err(pm2->dev, "failed to disable" "pm2xxx ac charger\n"); goto error_occured; } dev_dbg(pm2->dev, "PM2301: " "Disabled AC charging\n"); } power_supply_changed(pm2->ac_chg.psy); error_occured: return ret; }
static int param_set_ac_online(const char *key, const struct kernel_param *kp) { ac_online = map_get_value(map_ac_online, key, ac_online); power_supply_changed(&test_power_supplies[0]); return 0; }
static void tegra_battery_poll_timer_func(unsigned long unused) { power_supply_changed(&EC_Bat_supply[NvCharger_Type_Battery]); mod_timer(&poll_timer, jiffies + msecs_to_jiffies(batt_status_poll_period)); }
static void bq24192_external_power_changed(struct power_supply *psy) { struct bq24192_chip *chip = container_of(psy, struct bq24192_chip, ac_psy); union power_supply_propval ret = {0,}; int wlc_online = 0; int wlc_chg_current_ma = 0; chip->usb_psy->get_property(chip->usb_psy, POWER_SUPPLY_PROP_ONLINE, &ret); chip->usb_online = ret.intval; if (chip->wlc_support) { chip->wlc_psy->get_property(chip->wlc_psy, POWER_SUPPLY_PROP_ONLINE, &ret); wlc_online = ret.intval; chip->wlc_psy->get_property(chip->wlc_psy, POWER_SUPPLY_PROP_CURRENT_MAX, &ret); wlc_chg_current_ma = ret.intval / 1000; } if (chip->usb_online && bq24192_is_charger_present(chip)) { chip->usb_psy->get_property(chip->usb_psy, POWER_SUPPLY_PROP_CURRENT_MAX, &ret); bq24192_set_input_vin_limit(chip, chip->vin_limit_mv); bq24192_set_input_i_limit(chip, ret.intval / 1000); bq24192_set_ibat_max(chip, USB_MAX_IBAT_MA); pr_debug("usb is online! i_limit = %d v_limit = %d\n", ret.intval / 1000, chip->vin_limit_mv); } else if (chip->ac_online && bq24192_is_charger_present(chip)) { chip->icl_first = true; bq24192_set_input_vin_limit(chip, chip->icl_vbus_mv - 2 * VIN_LIMIT_STEP_MV); bq24192_set_input_i_limit(chip, adap_tbl[0].input_limit); bq24192_set_ibat_max(chip, adap_tbl[0].chg_limit); wake_lock(&chip->icl_wake_lock); schedule_delayed_work(&chip->input_limit_work, msecs_to_jiffies(200)); pr_debug("ac is online! i_limit = %d v_limit = %d\n", adap_tbl[0].chg_limit, chip->vin_limit_mv); } else if (wlc_online) { chip->dwn_chg_i_ma = chip->wlc_dwn_i_ma; chip->up_chg_i_ma = wlc_chg_current_ma; chip->dwn_input_i_ma = chip->wlc_dwn_input_i_ma; if (bq24192_is_wlc_bounced(chip)) chip->up_input_i_ma = chip->wlc_dwn_input_i_ma; else chip->up_input_i_ma = WLC_INPUT_I_LIMIT_MA; bq24192_set_input_vin_limit(chip, chip->wlc_vin_limit_mv); bq24192_set_input_i_limit(chip, chip->up_input_i_ma); bq24192_set_ibat_max(chip, wlc_chg_current_ma); bq24192_step_down_detect_init(chip); pr_debug("wlc is online! i_limit = %d v_limit = %d\n", wlc_chg_current_ma, chip->wlc_vin_limit_mv); } if (bq24192_is_charger_present(chip)) schedule_delayed_work(&chip->therm_work, msecs_to_jiffies(2000)); chip->usb_psy->get_property(chip->usb_psy, POWER_SUPPLY_PROP_SCOPE, &ret); if (ret.intval) { pr_debug("usb host mode = %d\n", ret.intval); if ((ret.intval == POWER_SUPPLY_SCOPE_SYSTEM) && !bq24192_is_otg_mode(chip)) bq24192_enable_otg(chip, true); else if ((ret.intval == POWER_SUPPLY_SCOPE_DEVICE) && bq24192_is_otg_mode(chip)) bq24192_enable_otg(chip, false); } power_supply_changed(&chip->ac_psy); }