Example #1
0
/*
 * API function
 * 
 * Registers the event handler structure
 * 
 * Return 	0	on success
 *     		<0	on failure
 */
int twl4030battery_event_register(struct twl4030battery_events events)
{
	twl4030battery_event.battery_level = events.battery_level;
	twl4030battery_event.battery_presence = events.battery_presence;
	twl4030battery_event.charger_presence = events.charger_presence;
	twl4030battery_event.bci_status = events.bci_status;
	
	twl4030battery_event.battery_sw_level_event_cfg = (
		events.battery_sw_level_event_cfg & (EVT_LVL_4_EN |
		EVT_LVL_3_EN | EVT_LVL_2_EN | EVT_LVL_1_EN)) ;
	
	if(events.battery_level == NULL)
	{
		twl4030battery_hw_level_en(EVT_DISABLE);
	}
	else
	{
		twl4030battery_hw_level_en(EVT_ENABLE);
		twl4030battery_level_evt();	
	}
	
	if(events.battery_presence == NULL)
	{
		twl4030battery_hw_presence_en(EVT_DISABLE);
	}
	else
	{
		twl4030battery_hw_presence_en(EVT_ENABLE);
		twl4030battery_presence_evt();
	}
	
	if(events.charger_presence == NULL)
	{
		twl4030charger_hw_presence_en(EVT_DISABLE);
	}
	else
	{
		twl4030charger_hw_presence_en(EVT_ENABLE);
		twl4030charger_presence_evt();
	}
	
	if(events.bci_status == NULL)
	{
		twl4030bci_sw_status_en(EVT_DISABLE);
		flush_scheduled_work();
	}
	else
	{
		twl4030bci_status_tmr.expires = jiffies + CHG_STS_DLY;
		add_timer(&twl4030bci_status_tmr);
		twl4030battery_event.temp_std = -1;
		twl4030bci_status_evt();
	}
	
	return 0;
}
static int __exit twl4030_bci_battery_remove(struct platform_device *pdev)
{
	struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
	int irq;

	twl4030charger_ac_en(DISABLE);
	twl4030charger_usb_en(DISABLE);
	twl4030battery_hw_level_en(DISABLE);
	twl4030battery_hw_presence_en(DISABLE);

	irq = platform_get_irq(pdev, 0);
	free_irq(irq, di);

	irq = platform_get_irq(pdev, 1);
	free_irq(irq, NULL);

	flush_scheduled_work();
	power_supply_unregister(&di->bat);
/* LGE_CHANGE_S [[email protected]] 2010-3-12, android NOT need bk battery voltage*/
#if BK_BATT
    power_supply_unregister(&di->bk_bat);
#endif //BK_BATT
/* LGE_CHANGE_E [[email protected]] 2010-3-12, android NOT need bk battery voltage*/
	platform_set_drvdata(pdev, NULL);
	kfree(di);

	return 0;
}
Example #3
0
/*
 * Interrupt service routine
 * 
 * Attends to BCI interruptions events, 
 * specifically BATSTS (battery connection and removal)
 * VBATOV (main battery voltage threshold) events
 * 
 */
static irqreturn_t twl4030battery_interrupt(int irq, void *dev_id)
{
	int ret;
	u8 isr1a_val, isr2a_val, clear_2a, clear_1a;

	if ((ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr1a_val, 
				REG_BCIISR1A)))	
		return IRQ_NONE;
	
	if ((ret = twl4030_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &isr2a_val, 
				REG_BCIISR2A)))
		return IRQ_NONE;
	
	clear_2a = (isr2a_val & VBATLVL_ISR1)? (VBATLVL_ISR1): 0;
	clear_1a = (isr1a_val & BATSTS_ISR1)? (BATSTS_ISR1): 0;
	
	/* cleaning BCI interrupt status flags */
	if ((ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 
			clear_1a , REG_BCIISR1A)))
	return IRQ_NONE;
	
	if ((ret = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 
			clear_2a , REG_BCIISR2A)))
	return IRQ_NONE;
		
			
	/* battery connetion or removal event */
	if (isr1a_val & BATSTS_ISR1)
	{
		ret = twl4030battery_presence_evt();
		if (ret == -ENXIO)
		{
			twl4030battery_hw_presence_en(EVT_DISABLE);
			return IRQ_HANDLED;
		}
		if (ret)
			return IRQ_NONE;		
	}
		
	/* battery voltage threshold event*/
	else if (isr2a_val & VBATLVL_ISR1)
	{
		ret = twl4030battery_level_evt();
		if (ret == -ENXIO)
		{
			twl4030battery_hw_level_en(EVT_DISABLE);
			return IRQ_HANDLED;
		}	
		if (ret)
			return IRQ_NONE;
	}
	/* Only for debuging purpouses this branch never be taken */
	else
		return IRQ_NONE;
			
	return IRQ_HANDLED;		
}
Example #4
0
static int __exit twl4030_bci_battery_remove(struct platform_device *pdev)
{
	struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
	int irq;

	twl4030charger_ac_en(DISABLE);
	twl4030charger_usb_en(DISABLE);
	twl4030battery_hw_level_en(DISABLE);
	twl4030battery_hw_presence_en(DISABLE);

	irq = platform_get_irq(pdev, 0);
	free_irq(irq, di);

	irq = platform_get_irq(pdev, 1);
	free_irq(irq, NULL);

	flush_scheduled_work();
	power_supply_unregister(&di->bat);
	power_supply_unregister(&di->bk_bat);
	platform_set_drvdata(pdev, NULL);
	kfree(di);

	return 0;
}
static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
{
	struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
	struct twl4030_bci_device_info *di;
	int irq;
	int ret;

	therm_tbl = pdata->battery_tmp_tbl;

	di = kzalloc(sizeof(*di), GFP_KERNEL);
	if (!di)
		return -ENOMEM;

	di->dev = &pdev->dev;

	// S[, 20120725, [email protected], Enable charging by fake mode.
	if (thermal_fakemode)
		di->temp_control = UNLIMITED_TEMP_VAL;
	else
		di->temp_control = 0;
	// E], 20120725, [email protected], Enable charging by fake mode.

	/* refer - com_android_server_BatteryService.cpp */
	di->bat.name = "battery";
	di->bat.supplied_to = twl4030_bci_supplied_to;
	di->bat.num_supplicants = ARRAY_SIZE(twl4030_bci_supplied_to);
	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bat.properties = twl4030_bci_battery_props;
	di->bat.num_properties = ARRAY_SIZE(twl4030_bci_battery_props);
	di->bat.get_property = twl4030_bci_battery_get_property;
	di->bat.set_property = twl4030_bci_battery_set_property; // 20120725, [email protected], Enable charging by fake mode.
	di->bat.external_power_changed = NULL;
	di->bat.set_charged = NULL;

/* LGE_CHANGE_S [[email protected]] 2010-3-12, android NOT need bk battery voltage*/
#if BK_BATT
	di->bk_bat.name = "twl4030_bci_bk_battery";
	di->bk_bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bk_bat.properties = twl4030_bk_bci_battery_props;
	di->bk_bat.num_properties = ARRAY_SIZE(twl4030_bk_bci_battery_props);
	di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
	di->bk_bat.external_power_changed = NULL;
	di->bk_bat.set_charged = NULL;
#endif //BK_BATT
/* LGE_CHANGE_E [[email protected]] 2010-3-12, android NOT need bk battery voltage*/


	di->ac.name = "ac";
	di->ac.type = POWER_SUPPLY_TYPE_MAINS; //LGE_CHANGE [[email protected]] 2010-01-12
	di->ac.properties = twl4030_ac_usb_bci_battery_props;
	di->ac.num_properties = ARRAY_SIZE(twl4030_ac_usb_bci_battery_props);
	di->ac.get_property = twl4030_ac_bci_battery_get_property;
	di->ac.external_power_changed = NULL;
	di->ac.set_charged = NULL;
	di->usb.name = "usb";
	di->usb.type = POWER_SUPPLY_TYPE_USB; //LGE_CHANGE [[email protected]] 2010-01-12
	di->usb.properties = twl4030_ac_usb_bci_battery_props;
	di->usb.num_properties = ARRAY_SIZE(twl4030_ac_usb_bci_battery_props);
	di->usb.get_property = twl4030_usb_bci_battery_get_property;
	di->usb.external_power_changed = NULL;
	di->usb.set_charged = NULL;

	twl4030charger_ac_en(DISABLE);
	twl4030charger_usb_en(DISABLE);
	twl4030battery_hw_level_en(DISABLE);
	twl4030battery_hw_presence_en(DISABLE);
	platform_set_drvdata(pdev, di);

	/* enabling GPCH09 for read back battery voltage */
	ret = twl4030backupbatt_voltage_setup();
	if (ret)
		goto voltage_setup_fail;

	/* REVISIT do we need to request both IRQs ?? */

	/* request BCI interruption */
	irq = platform_get_irq(pdev, 1);
	ret = request_irq(irq, twl4030battery_interrupt,
		0, pdev->name, NULL);
	if (ret) {
		dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
			irq, ret);
		goto batt_irq_fail;
	}

	/* request Power interruption */
	irq = platform_get_irq(pdev, 0);
	ret = request_irq(irq, twl4030charger_interrupt,
		0, pdev->name, di);

	if (ret) {
		dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
			irq, ret);
		goto chg_irq_fail;
	}

	ret = power_supply_register(&pdev->dev, &di->bat);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register main battery\n");
		goto batt_failed;
	}

	INIT_DELAYED_WORK_DEFERRABLE(&di->twl4030_bci_monitor_work, twl4030_bci_battery_work);
	schedule_delayed_work(&di->twl4030_bci_monitor_work, 5 * HZ); //[email protected] add delay for secure ops

/* LGE_CHANGE_S [[email protected]] 2010-3-12, android NOT need bk battery voltage*/
#if BK_BATT
	ret = power_supply_register(&pdev->dev, &di->bk_bat);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register backup battery\n");
		goto bk_batt_failed;
	}

	INIT_DELAYED_WORK_DEFERRABLE(&di->twl4030_bk_bci_monitor_work, twl4030_bk_bci_battery_work);
	schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, HZ*1);
#endif //BK_BATT
/* LGE_CHANGE_E [[email protected]] 2010-3-12, android NOT need bk battery voltage*/

	ret = power_supply_register(&pdev->dev, &di->ac);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register battery ac online\n");
		goto ac_online_failed;
	}

	ret = power_supply_register(&pdev->dev, &di->usb);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register battery usb online\n");
		goto usb_online_failed;
	}
    ret = device_create_file(&pdev->dev, &dev_attr_pif);
    if (ret) {
        printk( "PIF detection register failed: Fail\n");
        return ret;
    }

    ret = device_create_file(&pdev->dev, &dev_attr_gauge_if);
    if (ret) {
        printk( "chager off sysfs register failed: Fail\n");
        return ret;
    }
	// Update First Battery Information
	refer_di = di;
	twl4030_bci_battery_read_status(di);
	set_battery_status(di);	
	
	backup_battery_info(di);
	di->bk_voltage_uV = 3700;
	return 0;

usb_online_failed:
	power_supply_unregister(&di->bat);
ac_online_failed:
	power_supply_unregister(&di->bat);
#if BK_BATT
bk_batt_failed:
#endif
	power_supply_unregister(&di->bat);
batt_failed:
	free_irq(irq, di);
chg_irq_fail:
	irq = platform_get_irq(pdev, 1);
	free_irq(irq, NULL);
batt_irq_fail:
voltage_setup_fail:
	twl4030charger_ac_en(DISABLE);
	twl4030charger_usb_en(DISABLE);
	twl4030battery_hw_level_en(DISABLE);
	twl4030battery_hw_presence_en(DISABLE);
	kfree(di);

	return ret;
}
Example #6
0
static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
{
	struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
	struct twl4030_bci_device_info *di;
	int irq;
	int ret;

	therm_tbl = pdata->battery_tmp_tbl;
	bci_charging_current = pdata->twl4030_bci_charging_current;

	di = kzalloc(sizeof(*di), GFP_KERNEL);
	if (!di)
		return -ENOMEM;

	di->dev = &pdev->dev;
	di->bat.name = "twl4030_bci_battery";
	di->bat.supplied_to = twl4030_bci_supplied_to;
	di->bat.num_supplicants = ARRAY_SIZE(twl4030_bci_supplied_to);
	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bat.properties = twl4030_bci_battery_props;
	di->bat.num_properties = ARRAY_SIZE(twl4030_bci_battery_props);
	di->bat.get_property = twl4030_bci_battery_get_property;
	di->bat.external_power_changed =
			twl4030_bci_battery_external_power_changed;

	di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;

	di->bk_bat.name = "twl4030_bci_bk_battery";
	di->bk_bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bk_bat.properties = twl4030_bk_bci_battery_props;
	di->bk_bat.num_properties = ARRAY_SIZE(twl4030_bk_bci_battery_props);
	di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
	di->bk_bat.external_power_changed = NULL;

	/*
	 * Android expects a battery type POWER_SUPPLY_TYPE_USB
	 * as a usb charger battery. This battery
	 * and its "online" property are used to determine if the
	 * usb cable is plugged in or not.
	 */
	di->usb_bat.name = "twl4030_bci_usb_src";
	di->usb_bat.supplied_to = twl4030_bci_supplied_to;
	di->usb_bat.type = POWER_SUPPLY_TYPE_USB;
	di->usb_bat.properties = twl4030_usb_battery_props;
	di->usb_bat.num_properties = ARRAY_SIZE(twl4030_usb_battery_props);
	di->usb_bat.get_property = twl4030_usb_battery_get_property;
	di->usb_bat.external_power_changed = NULL;

	twl4030charger_ac_en(ENABLE);
	twl4030charger_usb_en(ENABLE);
	twl4030battery_hw_level_en(ENABLE);
	twl4030battery_hw_presence_en(ENABLE);

	platform_set_drvdata(pdev, di);

	/* settings for temperature sensing */
	ret = twl4030battery_temp_setup();
	if (ret)
		goto temp_setup_fail;

	/* enabling GPCH09 for read back battery voltage */
	ret = twl4030backupbatt_voltage_setup();
	if (ret)
		goto voltage_setup_fail;

	/* REVISIT do we need to request both IRQs ?? */

	/* request BCI interruption */
	irq = platform_get_irq(pdev, 1);
	ret = request_irq(irq, twl4030battery_interrupt,
		0, pdev->name, NULL);
	if (ret) {
		dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
			irq, ret);
		goto batt_irq_fail;
	}

	/* request Power interruption */
	irq = platform_get_irq(pdev, 0);
	ret = request_irq(irq, twl4030charger_interrupt,
		0, pdev->name, di);

	if (ret) {
		dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
			irq, ret);
		goto chg_irq_fail;
	}

	ret = power_supply_register(&pdev->dev, &di->bat);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register main battery\n");
		goto batt_failed;
	}

	INIT_DELAYED_WORK_DEFERRABLE(&di->twl4030_bci_monitor_work,
				twl4030_bci_battery_work);
	schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);

	ret = power_supply_register(&pdev->dev, &di->bk_bat);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register backup battery\n");
		goto bk_batt_failed;
	}

	INIT_DELAYED_WORK_DEFERRABLE(&di->twl4030_bk_bci_monitor_work,
				twl4030_bk_bci_battery_work);
	schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);

	ret = power_supply_register(&pdev->dev, &di->usb_bat);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register usb battery\n");
		goto usb_batt_failed;
	}

	return 0;

usb_batt_failed:
	power_supply_unregister(&di->bk_bat);
bk_batt_failed:
	power_supply_unregister(&di->bat);
batt_failed:
	free_irq(irq, di);
chg_irq_fail:
	irq = platform_get_irq(pdev, 1);
	free_irq(irq, NULL);
batt_irq_fail:
voltage_setup_fail:
temp_setup_fail:
	twl4030charger_ac_en(DISABLE);
	twl4030charger_usb_en(DISABLE);
	twl4030battery_hw_level_en(DISABLE);
	twl4030battery_hw_presence_en(DISABLE);
	kfree(di);

	return ret;
}