static void twl6030charger_ctrl_work_handler(struct work_struct *work) { struct charger_device_info *di = container_of(work, struct charger_device_info, twl6030charger_ctrl_work.work); int ret; int n_usbic_state; int charger_fault = 0; long int events; u8 stat_toggle, stat_reset, stat_set = 0; u8 charge_state = 0; u8 present_charge_state = 0; u8 ac_or_vbus, no_ac_and_vbus = 0; u8 hw_state = 0, temp = 0; dev_dbg(di->dev, "[TA] %s start\n",__func__); clear_charge_start_time(); /* read charger controller_stat1 */ ret = twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &present_charge_state, CONTROLLER_STAT1); if (ret) return 0; twl_i2c_read_u8(TWL6030_MODULE_ID0, &hw_state, STS_HW_CONDITIONS); charge_state = di->stat1; stat_toggle = charge_state ^ present_charge_state; stat_set = stat_toggle & present_charge_state; stat_reset = stat_toggle & charge_state; no_ac_and_vbus = !((present_charge_state) & (VBUS_DET | VAC_DET)); ac_or_vbus = charge_state & (VBUS_DET | VAC_DET); if (no_ac_and_vbus && ac_or_vbus) { dev_dbg(di->dev, "[TA] No Charging source\n"); /* disable charging when no source present */ } charge_state = present_charge_state; di->stat1 = present_charge_state; if (stat_reset & VBUS_DET) { /* On a USB detach, UNMASK VBUS OVP if masked*/ twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &temp, CHARGERUSB_INT_MASK); if (temp & MASK_MCHARGERUSB_FAULT) twl_i2c_write_u8(TWL6030_MODULE_CHARGER, (temp & ~MASK_MCHARGERUSB_FAULT), CHARGERUSB_INT_MASK); dev_dbg(di->dev, "[TA] Charging source removed\n"); change_cable_status(POWER_SUPPLY_TYPE_BATTERY, di); #ifdef CONFIG_DYNAMIC_TSP_SETTINGS_FOR_CHARGER_STATE set_tsp_for_ta_detect(0); #endif } if (stat_set & VBUS_DET) { /* In HOST mode (ID GROUND) when a device is connected, Mask * VBUS OVP interrupt and do no enable usb charging */ if (hw_state & STS_USB_ID) { twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &temp, CHARGERUSB_INT_MASK); if (!(temp & MASK_MCHARGERUSB_FAULT)) twl_i2c_write_u8(TWL6030_MODULE_CHARGER, (temp | MASK_MCHARGERUSB_FAULT), CHARGERUSB_INT_MASK); } else { n_usbic_state = get_real_usbic_state(); dev_dbg(di->dev, "[TA] cable_detection_isr handler. usbic_state: %d\n", n_usbic_state); switch (n_usbic_state) { case MICROUSBIC_5W_CHARGER: case MICROUSBIC_TA_CHARGER: case MICROUSBIC_USB_CHARGER: case MICROUSBIC_PHONE_USB: case MICROUSBIC_USB_CABLE: case MICROUSBIC_MHL_CHARGER: case MICROUSBIC_JIG_USB_ON: if (sec_bci->charger.cable_status == POWER_SUPPLY_TYPE_USB || sec_bci->charger.cable_status == POWER_SUPPLY_TYPE_MAINS ){ dev_dbg(di->dev, "[TA] Already Plugged\n"); break; } /*Check VF */ sec_bci->battery.battery_vf_ok = check_battery_vf(); /*TA or USB or MHL is inserted */ if (n_usbic_state == MICROUSBIC_USB_CABLE) { //current : 395mA dev_dbg(di->dev,"[TA] USB CABLE PLUGGED\n"); change_cable_status(POWER_SUPPLY_TYPE_USB, di); #ifdef CONFIG_DYNAMIC_TSP_SETTINGS_FOR_CHARGER_STATE set_tsp_for_ta_detect(1); #endif } else if (n_usbic_state == MICROUSBIC_MHL_CHARGER) { //current : 395mA dev_dbg(di->dev,"[TA] MHL CABLE PLUGGED\n"); change_cable_status(POWER_SUPPLY_TYPE_USB, di); #ifdef CONFIG_DYNAMIC_TSP_SETTINGS_FOR_CHARGER_STATE set_tsp_for_ta_detect(1); #endif } else if (n_usbic_state == MICROUSBIC_JIG_USB_ON) { //current : 1000mA dev_dbg(di->dev,"[TA] JIG_USB_ON CABLE PLUGGED\n"); change_cable_status(POWER_SUPPLY_TYPE_MAINS, di); #ifdef CONFIG_DYNAMIC_TSP_SETTINGS_FOR_CHARGER_STATE set_tsp_for_ta_detect(1); #endif } else { //current : 1000mA dev_dbg(di->dev,"[TA] CHARGER CABLE PLUGGED\n"); change_cable_status(POWER_SUPPLY_TYPE_MAINS, di); #ifdef CONFIG_DYNAMIC_TSP_SETTINGS_FOR_CHARGER_STATE set_tsp_for_ta_detect(1); #endif } break; default: ; } } } if (sec_bci->charger.prev_cable_status == -1 && sec_bci->charger.cable_status == -1) { dev_dbg(di->dev,"[TA] Fisrt time after bootig.\n"); change_cable_status(POWER_SUPPLY_TYPE_BATTERY, di); #ifdef CONFIG_DYNAMIC_TSP_SETTINGS_FOR_CHARGER_STATE set_tsp_for_ta_detect(0); #endif } if (stat_set & CONTROLLER_STAT1_FAULT_WDG) { // charger_fault = 1; dev_dbg(di->dev, "Fault watchdog fired\n"); } if (stat_reset & CONTROLLER_STAT1_FAULT_WDG) dev_dbg(di->dev, "Fault watchdog recovered\n"); if (stat_set & CONTROLLER_STAT1_BAT_REMOVED) dev_dbg(di->dev, "Battery removed\n"); if (stat_reset & CONTROLLER_STAT1_BAT_REMOVED) dev_dbg(di->dev, "Battery inserted\n"); if (stat_set & CONTROLLER_STAT1_BAT_TEMP_OVRANGE) dev_dbg(di->dev, "Battery temperature overrange\n"); if (stat_reset & CONTROLLER_STAT1_BAT_TEMP_OVRANGE) dev_dbg(di->dev, "Battery temperature within range\n"); if (charger_fault) { change_charge_status(POWER_SUPPLY_STATUS_NOT_CHARGING); dev_err(di->dev, "Charger Fault stop charging\n"); } }
static void cable_detection_work_handler( struct work_struct * work ) // ---------------------------------------------------------------------------- // Description : // Input Argument : // Return Value : None { printk( "cable_detection_work_handler :----------------------------- \n"); struct charger_driver_info *di = container_of( work, struct charger_driver_info, cable_detection_work.work ); int n_usbic_state; int count; int ret; if ( !sec_bci->ready ) { queue_delayed_work( sec_bci->sec_battery_workq, &di->cable_detection_work, HZ ); return; } clear_charge_start_time(); #ifdef CONFIG_USB_SWITCH_FSA9480 n_usbic_state = di->cable_status; #else n_usbic_state = get_real_usbic_state(); #endif printk( "[TA] cable_detection_isr handler. usbic_state: %d\n", n_usbic_state ); if ( sec_bci->charger.use_ta_nconnected_irq ) { if ( gpio_get_value( KTA_NCONN_GPIO ) ) { count = 0; while ( count < 10 ) { if ( gpio_get_value( KTA_NCONN_GPIO ) ) { count++; msleep( 1 ); if ( count == 10 ) { n_usbic_state = -10; printk( "[TA] CABLE UNPLUGGED.\n" ); } } else break; } } } // Workaround for Archer [ if ( !n_usbic_state && sec_bci->charger.use_ta_nconnected_irq ) { if ( !gpio_get_value( KTA_NCONN_GPIO ) ) n_usbic_state = MICROUSBIC_5W_CHARGER; } // ] switch ( n_usbic_state ) { #ifdef CONFIG_USB_SWITCH_FSA9480 case CABLE_TYPE_USB : case CABLE_TYPE_AC : #else case MICROUSBIC_5W_CHARGER : case MICROUSBIC_TA_CHARGER : case MICROUSBIC_USB_CHARGER : case MICROUSBIC_PHONE_USB : case MICROUSBIC_USB_CABLE : #endif if ( sec_bci->charger.cable_status == POWER_SUPPLY_TYPE_USB || sec_bci->charger.cable_status == POWER_SUPPLY_TYPE_MAINS ) { printk( "[TA] already Plugged.\n" ); goto Out_IRQ_Cable_Det; } #ifdef WR_ADC /* Workaround to get proper adc value */ #ifdef CONFIG_USB_SWITCH_FSA9480 if(n_usbic_state != CABLE_TYPE_USB) #else if(n_usbic_state != MICROUSBIC_USB_CABLE) #endif { if ( !di->usb3v1_is_enabled ) { ret = regulator_enable( di->usb3v1 ); if ( ret ) printk("Regulator 3v1 error!!\n"); else di->usb3v1_is_enabled = true; } } twl_i2c_write_u8( TWL4030_MODULE_PM_RECEIVER, REMAP_ACTIVE, TWL4030_VUSB3V1_REMAP ); twl_i2c_write_u8( TWL4030_MODULE_PM_RECEIVER, REMAP_ACTIVE, TWL4030_VINTANA2_REMAP ); msleep( 100 ); #endif /*Check VF*/ sec_bci->battery.battery_vf_ok = check_battery_vf(); /*TA or USB is inserted*/ #ifdef CONFIG_USB_SWITCH_FSA9480 if ( n_usbic_state == CABLE_TYPE_USB ) #else if ( n_usbic_state == MICROUSBIC_USB_CABLE ) #endif { //current : 482mA printk( "[TA] USB CABLE PLUGGED\n" ); change_cable_status( POWER_SUPPLY_TYPE_USB, di, CHARGE_DUR_ACTIVE ); } else { //current : 636mA printk( "[TA] CHARGER CABLE PLUGGED\n" ); change_cable_status( POWER_SUPPLY_TYPE_MAINS, di, CHARGE_DUR_ACTIVE ); } if ( device_config->SUPPORT_CHG_ING_IRQ ) enable_irq( KCHG_ING_IRQ ); break; default: if ( sec_bci->charger.prev_cable_status != POWER_SUPPLY_TYPE_BATTERY && sec_bci->charger.cable_status == POWER_SUPPLY_TYPE_BATTERY ) { printk( "[TA] already Unplugged.\n" ); goto Out_IRQ_Cable_Det; } else if ( sec_bci->charger.prev_cable_status == -1 && sec_bci->charger.cable_status == -1 ) { // first time after booting. printk( "[TA] Fisrt time after bootig.\n" ); goto FirstTime_Boot; } disable_irq( KCHG_ING_IRQ ); #ifdef WR_ADC /* Workaround to get proper adc value */ if ( di->usb3v1_is_enabled ) regulator_disable( di->usb3v1 ); di->usb3v1_is_enabled = false; twl_i2c_write_u8( TWL4030_MODULE_PM_RECEIVER, REMAP_OFF, TWL4030_VUSB3V1_REMAP ); twl_i2c_write_u8( TWL4030_MODULE_PM_RECEIVER, REMAP_OFF, TWL4030_VINTANA2_REMAP ); #endif FirstTime_Boot: /*TA or USB is ejected*/ printk( "[TA] CABLE UNPLUGGED\n" ); change_cable_status( POWER_SUPPLY_TYPE_BATTERY, di, CHARGE_DUR_ACTIVE ); break; } Out_IRQ_Cable_Det: ; #ifdef USE_DISABLE_CONN_IRQ #ifdef MANAGE_CONN_IRQ enable_irq_conn( true ); #else if ( !sec_bci->charger.use_ta_nconnected_irq ) enable_irq( KUSB_CONN_IRQ ); enable_irq( KTA_NCONN_IRQ ); #endif #endif }
static void change_charge_status(int status) { switch (status) { case POWER_SUPPLY_STATUS_UNKNOWN: case POWER_SUPPLY_STATUS_NOT_CHARGING: case POWER_SUPPLY_STATUS_DISCHARGING: if (sec_bci->battery.battery_health != POWER_SUPPLY_HEALTH_DEAD) disable_charging(); #ifdef HIGH_TEMP_GAURD_FOR_CAMCORDER sec_bci->charger.camera_recording_inout = 0; #endif break; case POWER_SUPPLY_STATUS_FULL: break; case POWER_SUPPLY_STATUS_FULL_END: sec_bci->charger.rechg_count = 4; /*Cancel timer */ clear_charge_start_time(); disable_charging(); break; case POWER_SUPPLY_STATUS_CHARGING: if (sec_bci->battery.battery_vf_ok) { sec_bci->battery.battery_health = POWER_SUPPLY_HEALTH_GOOD; /*Start monitoring charging time */ set_charge_start_time(); enable_charging(); break; } else { sec_bci->battery.battery_health = POWER_SUPPLY_HEALTH_DEAD; status = POWER_SUPPLY_STATUS_DISCHARGING; printk( KERN_INFO "[TA] INVALID BATTERY, %d !! \n", status); disable_charging(); break; } case POWER_SUPPLY_STATUS_RECHARGING_FOR_FULL: /*Start monitoring charging time */ sec_bci->charger.charging_timeout = DEFAULT_RECHARGING_TIMEOUT; set_charge_start_time(); enable_charging(); break; case POWER_SUPPLY_STATUS_RECHARGING_FOR_TEMP: enable_charging(); break; default: ; } sec_bci->charger.prev_charge_status = sec_bci->charger.charge_status; sec_bci->charger.charge_status = status; _charger_state_change_(STATUS_CATEGORY_CHARGING, status); }
static void change_charge_status( int status, bool is_sleep ) // ---------------------------------------------------------------------------- // Description : // Input Argument : // Return Value : { switch ( status ) { case POWER_SUPPLY_STATUS_UNKNOWN : case POWER_SUPPLY_STATUS_DISCHARGING : case POWER_SUPPLY_STATUS_NOT_CHARGING : disable_charging( is_sleep ); break; case POWER_SUPPLY_STATUS_FULL : disable_charging( is_sleep ); /*Cancel timer*/ clear_charge_start_time(); break; case POWER_SUPPLY_STATUS_CHARGING : if ( sec_bci->battery.battery_vf_ok ) { sec_bci->battery.battery_health = POWER_SUPPLY_HEALTH_GOOD; /*Start monitoring charging time*/ set_charge_start_time(); enable_charging( is_sleep ); } else { sec_bci->battery.battery_health = POWER_SUPPLY_HEALTH_DEAD; status = POWER_SUPPLY_STATUS_NOT_CHARGING; disable_charging( is_sleep ); printk( "[TA] INVALID BATTERY, %d !! \n", status ); } break; case POWER_SUPPLY_STATUS_RECHARGING_FOR_FULL : /*Start monitoring charging time*/ sec_bci->charger.charging_timeout = DEFAULT_RECHARGING_TIMEOUT; set_charge_start_time(); enable_charging( is_sleep ); break; case POWER_SUPPLY_STATUS_RECHARGING_FOR_TEMP : enable_charging( is_sleep ); break; default : ; } sec_bci->charger.prev_charge_status = sec_bci->charger.charge_status; sec_bci->charger.charge_status = status; _charger_state_change_( STATUS_CATEGORY_CHARGING, status, is_sleep ); }