Пример #1
0
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;
}
Пример #2
0
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;
}