static int __devinit sec_battery_probe(struct platform_device *pdev) { sec_battery_platform_data_t *pdata = dev_get_platdata(&pdev->dev); struct sec_battery_info *battery; int irq = 0; int ret = 0; pr_debug("%s: SEC Battery Driver Loading\n", __func__); battery = kzalloc(sizeof(*battery), GFP_KERNEL); if (!battery) return -ENOMEM; platform_set_drvdata(pdev, battery); battery->dev = &pdev->dev; battery->pdata = pdata; mutex_init(&battery->adclock); pr_debug("%s: ADC init\n", __func__); adc_init(pdev, pdata, pdata->cable_check_adc_channel); adc_init(pdev, pdata, pdata->check_adc_channel); adc_init(pdev, pdata, pdata->temp_adc_channel); adc_init(pdev, pdata, pdata->temp_amb_adc_channel); adc_init(pdev, pdata, pdata->full_check_adc_channel); wake_lock_init(&battery->monitor_wake_lock, WAKE_LOCK_SUSPEND, "sec-battery-monitor"); wake_lock_init(&battery->cable_wake_lock, WAKE_LOCK_SUSPEND, "sec-battery-cable"); wake_lock_init(&battery->vbus_wake_lock, WAKE_LOCK_SUSPEND, "sec-battery-vbus"); /* initialization of battery info */ battery->status = POWER_SUPPLY_STATUS_DISCHARGING; battery->health = POWER_SUPPLY_HEALTH_GOOD; battery->present = false; battery->long_polling_activated = false; battery->polling_count = 0; battery->polling_time = pdata->short_polling_time; battery->check_count = 0; battery->check_adc_count = 0; battery->check_adc_value = 0; battery->charging_start_time = 0; battery->charging_passed_time = 0; battery->charging_next_time = 0; setup_timer(&battery->event_expired_timer, sec_bat_event_expired_timer_func, (unsigned long)battery); battery->temp_high_threshold = pdata->temp_high_threshold_normal; battery->temp_high_recovery = pdata->temp_high_recovery_normal; battery->temp_low_recovery = pdata->temp_low_recovery_normal; battery->temp_low_threshold = pdata->temp_low_threshold_normal; battery->charging_mode = SEC_BATTERY_CHARGING_NONE; battery->cable_type = POWER_SUPPLY_TYPE_BATTERY; battery->test_activated = false; battery->psy_bat.name = "battery", battery->psy_bat.type = POWER_SUPPLY_TYPE_BATTERY, battery->psy_bat.properties = sec_battery_props, battery->psy_bat.num_properties = ARRAY_SIZE(sec_battery_props), battery->psy_bat.get_property = sec_bat_get_property, battery->psy_bat.set_property = sec_bat_set_property, battery->psy_usb.name = "usb", battery->psy_usb.type = POWER_SUPPLY_TYPE_USB, battery->psy_usb.supplied_to = supply_list, battery->psy_usb.num_supplicants = ARRAY_SIZE(supply_list), battery->psy_usb.properties = sec_power_props, battery->psy_usb.num_properties = ARRAY_SIZE(sec_power_props), battery->psy_usb.get_property = sec_usb_get_property, battery->psy_ac.name = "ac", battery->psy_ac.type = POWER_SUPPLY_TYPE_MAINS, battery->psy_ac.supplied_to = supply_list, battery->psy_ac.num_supplicants = ARRAY_SIZE(supply_list), battery->psy_ac.properties = sec_power_props, battery->psy_ac.num_properties = ARRAY_SIZE(sec_power_props), battery->psy_ac.get_property = sec_ac_get_property; /* init power supplier framework */ ret = power_supply_register(&pdev->dev, &battery->psy_bat); if (ret) { pr_err("%s: Failed to Register psy_bat\n", __func__); goto err_wake_lock; } ret = power_supply_register(&pdev->dev, &battery->psy_usb); if (ret) { pr_err("%s: Failed to Register psy_usb\n", __func__); goto err_supply_unreg_bat; } ret = power_supply_register(&pdev->dev, &battery->psy_ac); if (ret) { pr_err("%s: Failed to Register psy_ac\n", __func__); goto err_supply_unreg_usb; } /* create work queue */ battery->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev)); if (!battery->monitor_wqueue) { pr_err("%s: Fail to Create Workqueue\n", __func__); goto err_supply_unreg_ac; } INIT_WORK(&battery->monitor_work, sec_bat_monitor_work); INIT_WORK(&battery->cable_work, sec_bat_cable_work); if (battery->pdata->bat_gpio_irq) { irq = gpio_to_irq(battery->pdata->bat_gpio_irq); ret = request_threaded_irq(irq, NULL, sec_bat_irq_thread, battery->pdata->bat_irq_attr, "battery-irq", battery); if (ret) { pr_err("%s: Failed to Reqeust IRQ\n", __func__); return ret; } ret = enable_irq_wake(irq); if (ret < 0) pr_err("%s: Failed to Enable Wakeup Source(%d)\n" , __func__, ret); } ret = sec_bat_create_attrs(battery->psy_bat.dev); if (ret) { pr_err("%s : Failed to create_attrs\n", __func__); goto err_supply_unreg_ac; } switch (pdata->polling_type) { case SEC_BATTERY_MONITOR_WORKQUEUE: INIT_DELAYED_WORK_DEFERRABLE(&battery->polling_work, sec_bat_polling_work); break; case SEC_BATTERY_MONITOR_ALARM: battery->last_poll_time = alarm_get_elapsed_realtime(); alarm_init(&battery->polling_alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, sec_bat_alarm); break; default: break; } wake_lock(&battery->monitor_wake_lock); queue_work(battery->monitor_wqueue, &battery->monitor_work); pdata->initial_check(); pr_debug("%s: SEC Battery Driver Loaded\n", __func__); return 0; err_supply_unreg_ac: power_supply_unregister(&battery->psy_ac); err_supply_unreg_usb: power_supply_unregister(&battery->psy_usb); err_supply_unreg_bat: power_supply_unregister(&battery->psy_bat); err_wake_lock: wake_lock_destroy(&battery->monitor_wake_lock); wake_lock_destroy(&battery->cable_wake_lock); wake_lock_destroy(&battery->vbus_wake_lock); mutex_destroy(&battery->adclock); kfree(battery); return ret; }
static __devinit int sec_battery_probe(struct platform_device *pdev) { struct sec_battery_platform_data *pdata = pdev->dev.platform_data; struct chg_data *chg; int ret = 0; pr_info("%s : Samsung Battery Driver Loading\n", __func__); chg = kzalloc(sizeof(*chg), GFP_KERNEL); if (!chg) return -ENOMEM; chg->pdata = pdata; if (!chg->pdata || !chg->pdata->adc_table) { pr_err("%s : No platform data & adc_table supplied\n", __func__); ret = -EINVAL; goto err_bat_table; } chg->psy_bat.name = "battery", chg->psy_bat.type = POWER_SUPPLY_TYPE_BATTERY, chg->psy_bat.properties = sec_battery_props, chg->psy_bat.num_properties = ARRAY_SIZE(sec_battery_props), chg->psy_bat.get_property = sec_bat_get_property, chg->psy_usb.name = "usb", chg->psy_usb.type = POWER_SUPPLY_TYPE_USB, chg->psy_usb.supplied_to = supply_list, chg->psy_usb.num_supplicants = ARRAY_SIZE(supply_list), chg->psy_usb.properties = sec_power_properties, chg->psy_usb.num_properties = ARRAY_SIZE(sec_power_properties), chg->psy_usb.get_property = sec_usb_get_property, chg->psy_ac.name = "ac", chg->psy_ac.type = POWER_SUPPLY_TYPE_MAINS, chg->psy_ac.supplied_to = supply_list, chg->psy_ac.num_supplicants = ARRAY_SIZE(supply_list), chg->psy_ac.properties = sec_power_properties, chg->psy_ac.num_properties = ARRAY_SIZE(sec_power_properties), chg->psy_ac.get_property = sec_ac_get_property, chg->present = 1; chg->polling_interval = POLLING_INTERVAL; chg->bat_info.batt_health = POWER_SUPPLY_HEALTH_GOOD; chg->bat_info.batt_is_full = false; chg->set_charge_timeout = false; chg->bat_info.batt_improper_ta = false; chg->is_recharging = false; #ifdef CONFIG_BATTERY_MAX17042 // Get battery type from fuelgauge driver. if(chg->pdata && chg->pdata->fuelgauge_cb) chg->battery_type = (battery_type_t)chg->pdata->fuelgauge_cb( REQ_TEST_MODE_INTERFACE, TEST_MODE_BATTERY_TYPE_CHECK, 0); // Check UV charging case. if(chg->pdata && chg->pdata->pmic_charger && chg->pdata->pmic_charger->get_connection_status) { if(chg->pdata->pmic_charger->get_connection_status() && check_UV_charging_case(chg)) chg->low_batt_boot_flag = true; } else chg->low_batt_boot_flag = false; // init delayed work INIT_DELAYED_WORK(&chg->full_chg_work, full_comp_work_handler); // Init low batt check threshold values. if(chg->battery_type == SDI_BATTERY_TYPE) chg->check_start_vol = 3550; // Under 3.55V else if(chg->battery_type == ATL_BATTERY_TYPE) chg->check_start_vol = 3450; // Under 3.45V #endif chg->cable_status = CABLE_TYPE_NONE; chg->charging_status = CHARGING_STATUS_NONE; mutex_init(&chg->mutex); platform_set_drvdata(pdev, chg); wake_lock_init(&chg->vbus_wake_lock, WAKE_LOCK_SUSPEND, "vbus_present"); wake_lock_init(&chg->work_wake_lock, WAKE_LOCK_SUSPEND, "sec_battery_work"); INIT_WORK(&chg->bat_work, sec_bat_work); chg->monitor_wqueue = create_freezeable_workqueue(dev_name(&pdev->dev)); if (!chg->monitor_wqueue) { pr_err("Failed to create freezeable workqueue\n"); ret = -ENOMEM; goto err_wake_lock; } chg->last_poll = alarm_get_elapsed_realtime(); alarm_init(&chg->alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, sec_battery_alarm); /* init power supplier framework */ ret = power_supply_register(&pdev->dev, &chg->psy_bat); if (ret) { pr_err("Failed to register power supply psy_bat\n"); goto err_wqueue; } ret = power_supply_register(&pdev->dev, &chg->psy_usb); if (ret) { pr_err("Failed to register power supply psy_usb\n"); goto err_supply_unreg_bat; } ret = power_supply_register(&pdev->dev, &chg->psy_ac); if (ret) { pr_err("Failed to register power supply psy_ac\n"); goto err_supply_unreg_usb; } sec_bat_create_attrs(chg->psy_bat.dev); chg->callbacks.set_cable = sec_bat_set_cable; chg->callbacks.set_status = sec_bat_set_status; chg->callbacks.force_update = sec_bat_force_update; if (chg->pdata->register_callbacks) chg->pdata->register_callbacks(&chg->callbacks); wake_lock(&chg->work_wake_lock); queue_work(chg->monitor_wqueue, &chg->bat_work); p1_lpm_mode_check(chg); return 0; err_supply_unreg_ac: power_supply_unregister(&chg->psy_ac); err_supply_unreg_usb: power_supply_unregister(&chg->psy_usb); err_supply_unreg_bat: power_supply_unregister(&chg->psy_bat); err_wqueue: destroy_workqueue(chg->monitor_wqueue); cancel_work_sync(&chg->bat_work); alarm_cancel(&chg->alarm); err_wake_lock: wake_lock_destroy(&chg->work_wake_lock); wake_lock_destroy(&chg->vbus_wake_lock); mutex_destroy(&chg->mutex); err_bat_table: kfree(chg); return ret; }