/* * 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; }
/* * 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; }
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; }
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; }