/** * auto_sleep_wakeup_test_notifier_call_chain - notify clients of fb_events * */ int auto_sleep_wakeup_test_notifier_call_chain(unsigned long val, void *v) { return blocking_notifier_call_chain(&auto_sleep_wakeup_test_notifier_list, val, v); }
int memory_notify(unsigned long val, void *v) { return blocking_notifier_call_chain(&memory_chain, val, v); }
void usb_notify_add_device(struct usb_device *udev) { blocking_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev); }
static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, int destroy, struct nlmsghdr *nlh, u32 pid) { struct in_ifaddr *promote = NULL; struct in_ifaddr *ifa, *ifa1 = *ifap; struct in_ifaddr *last_prim = in_dev->ifa_list; struct in_ifaddr *prev_prom = NULL; int do_promote = IN_DEV_PROMOTE_SECONDARIES(in_dev); ASSERT_RTNL(); /* 1. Deleting primary ifaddr forces deletion all secondaries * unless alias promotion is set **/ if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) { struct in_ifaddr **ifap1 = &ifa1->ifa_next; while ((ifa = *ifap1) != NULL) { if (!(ifa->ifa_flags & IFA_F_SECONDARY) && ifa1->ifa_scope <= ifa->ifa_scope) last_prim = ifa; if (!(ifa->ifa_flags & IFA_F_SECONDARY) || ifa1->ifa_mask != ifa->ifa_mask || !inet_ifa_match(ifa1->ifa_address, ifa)) { ifap1 = &ifa->ifa_next; prev_prom = ifa; continue; } if (!do_promote) { *ifap1 = ifa->ifa_next; rtmsg_ifa(RTM_DELADDR, ifa, nlh, pid); blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa); inet_free_ifa(ifa); } else { promote = ifa; break; } } } /* 2. Unlink it */ *ifap = ifa1->ifa_next; /* 3. Announce address deletion */ /* Send message first, then call notifier. At first sight, FIB update triggered by notifier will refer to already deleted ifaddr, that could confuse netlink listeners. It is not true: look, gated sees that route deleted and if it still thinks that ifaddr is valid, it will try to restore deleted routes... Grr. So that, this order is correct. */ rtmsg_ifa(RTM_DELADDR, ifa1, nlh, pid); blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); if (promote) { if (prev_prom) { prev_prom->ifa_next = promote->ifa_next; promote->ifa_next = last_prim->ifa_next; last_prim->ifa_next = promote; } promote->ifa_flags &= ~IFA_F_SECONDARY; rtmsg_ifa(RTM_NEWADDR, promote, nlh, pid); blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote); for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) { if (ifa1->ifa_mask != ifa->ifa_mask || !inet_ifa_match(ifa1->ifa_address, ifa)) continue; fib_add_ifaddr(ifa); } } if (destroy) inet_free_ifa(ifa1); }
static void iom3_recovery_work(struct work_struct *work) { int rec_nest_count = 0; int rc; u32 ack_buffer; u32 tx_buffer; hwlog_err("%s enter\n", __func__); wake_lock(&iom3_rec_wl); recovery_iom3: if(rec_nest_count++ > IOM3_REC_NEST_MAX){ hwlog_err("unlucky recovery iom3 times exceed limit\n"); atomic_set(&iom3_rec_state, IOM3_RECOVERY_FAILED); blocking_notifier_call_chain(&iom3_recovery_notifier_list, IOM3_RECOVERY_FAILED, NULL); atomic_set(&iom3_rec_state, IOM3_RECOVERY_IDLE); wake_unlock(&iom3_rec_wl); hwlog_err("%s exit\n", __func__); return; } //wait for iom3 enter WFI state show_iom3_stat();//only for IOM3 debug //rc = wait_for_iom3_wfi(100); //if(rc < 0 || 0 == rc) {//ioremap error || wait wfi timeout // hwlog_err("RPROC wait for iom3 WFI failed %d, nest_count %d\n", rc, rec_nest_count); // goto recovery_iom3; //} //reload iom3 system tx_buffer = RELOAD_IOM3_CMD; rc = RPROC_SYNC_SEND(HISI_RPROC_LPM3, &tx_buffer, 1, 1, &ack_buffer, 1); if (rc) { hwlog_err("RPROC reload iom3 failed %d, nest_count %d\n", rc, rec_nest_count); goto recovery_iom3; } show_iom3_stat();//only for IOM3 debug reset_i2c_0_controller(); msleep(5); hw_power_reset_for_recovery_iom3(); atomic_set(&iom3_rec_state, IOM3_RECOVERY_MINISYS); //startup iom3 system INIT_COMPLETION(iom3_rec_done); tx_buffer = STARTUP_IOM3_CMD; rc = RPROC_SYNC_SEND(HISI_RPROC_LPM3, &tx_buffer, 1, 1, &ack_buffer, 1); if (rc) { hwlog_err("RPROC start iom3 failed %d, nest_count %d\n", rc, rec_nest_count); goto recovery_iom3; } hwlog_err("RPROC restart iom3 success\n"); show_iom3_stat();//only for IOM3 debug //dynamic loading if (!wait_for_completion_timeout(&iom3_rec_done, 5*HZ)) { hwlog_err("wait for iom3 system ready timeout\n"); msleep(1000); goto recovery_iom3; } //repeat send cmd msleep(100);//wait iom3 finish handle config-data atomic_set(&iom3_rec_state, IOM3_RECOVERY_DOING); hwlog_err("%s doing\n", __func__); blocking_notifier_call_chain(&iom3_recovery_notifier_list, IOM3_RECOVERY_DOING, NULL); operations_when_recovery_iom3(); atomic_set(&iom3_rec_state, IOM3_RECOVERY_IDLE); wake_unlock(&iom3_rec_wl); hwlog_err("%s finish recovery\n", __func__); blocking_notifier_call_chain(&iom3_recovery_notifier_list, IOM3_RECOVERY_IDLE, NULL); hwlog_err("%s exit\n", __func__); return; }
void wcd9xxx_resmgr_notifier_call(struct wcd9xxx_resmgr *resmgr, const enum wcd9xxx_notify_event e) { pr_debug("%s: notifier call event %d\n", __func__, e); blocking_notifier_call_chain(&resmgr->notifier, e, resmgr); }
static int dip_notifier(unsigned int state, void *val) { return blocking_notifier_call_chain(&dip_notifier_list, state, val); }
void vmpressure_notify(unsigned long pressure) { blocking_notifier_call_chain(&vmpressure_notifier, pressure, NULL); }
/** * lcd_notifier_call_chain - notify clients on lcd_events * @val: Value passed unmodified to notifier function * @v: pointer passed unmodified to notifier function * */ int lcd_notifier_call_chain(unsigned long val, void *v) { return blocking_notifier_call_chain(&lcd_notifier_list, val, v); }
/* * SCI to report hardware error is forwarded to the listeners of HED, * it is used by HEST Generic Hardware Error Source with notify type * SCI. */ static void acpi_hed_notify(struct acpi_device *device, u32 event) { blocking_notifier_call_chain(&acpi_hed_notify_list, 0, NULL); }
void usb_notify_remove_bus(struct usb_bus *ubus) { blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus); }
void acc_notify(int event) { blocking_notifier_call_chain(&acc_notifier, event, NULL); }
int munmap(void *addr, size_t len){ int ret; blocking_notifier_call_chain(&munmap_notifier, 0, addr); ret = vm_munmap((unsigned long)addr, len); return ret; }
int iommu_notify_event(struct iommu *obj, int event, void *data) { return blocking_notifier_call_chain(&obj->notifier, event, data); }
int touch_notifier_call_chain(unsigned long val, void *v) { return blocking_notifier_call_chain(&touch_blocking_notifier, val, v); }
//&*&*&*SJ1_20110701, fix adb connect issue. static void do_softint_usb_irq(struct work_struct *work) { struct twl4030_usb *twl = container_of(work, struct twl4030_usb, usb_irq_delay_work.work); static int last_state=USB_EVENT_NONE; int status; static int run_flag=0; mdelay(200); last_state = twl->linkstat; status = twl4030_usb_linkstat(twl); if (status >= 0) { /* FIXME add a set_power() method so that B-devices can * configure the charger appropriately. It's not always * correct to consume VBUS power, and how much current to * consume is a function of the USB configuration chosen * by the host. * * REVISIT usb_gadget_vbus_connect(...) as needed, ditto * its disconnect() sibling, when changing to/from the * USB_LINK_VBUS state. musb_hdrc won't care until it * starts to handle softconnect right. */ if (status == USB_EVENT_NONE) { //&*&*&*QY_20110706, don't send USB_EVENT_NONE again if(last_state==USB_EVENT_NONE) { return ; } //&*&*&*QY_20110706 twl4030_phy_suspend(twl, 0); if(twl->enter_early_suspend == 1) { SendPowerbuttonEvent(); printk("[twl4030-usb]Enter %s, send power suspend event.\n", __FUNCTION__); } if(wake_lock_active(&usb_lock)) wake_unlock(&usb_lock); } else { if(!wake_lock_active(&usb_lock)) wake_lock(&usb_lock); twl4030_phy_resume(twl); } //&*&*&*QY_20110706, don't send USB_EVENT_NONE if last status is USB_EVENT_ID if(status != USB_EVENT_ID) { twl4030_otg_enable(0); //Simon if( (status==USB_EVENT_VBUS) || (status==USB_EVENT_NONE && last_state!=USB_EVENT_ID)) { blocking_notifier_call_chain(&twl->otg.notifier, status, twl->otg.gadget); } } //&*&*&*QY_20110706 //&*&*&*QY_20110706, enable 5V when OTG-cable plug-in else //(status == USB_EVENT_ID) { gpio_direction_output(OTG_EN_1V8, 0); gpio_direction_output(CHG_OFFMODE, 1); if(!run_flag) { //msleep(500); mdelay(3000); } blocking_notifier_call_chain(&twl->otg.notifier, USB_EVENT_ID, twl->otg.gadget); if(run_flag) { //msleep(500); mdelay(1000); } else { msleep(1000); } twl4030_otg_enable(1); //Simon } //&*&*&*QY_20110706 } run_flag=1; sysfs_notify(&twl->dev->kobj, NULL, "vbus"); }
int mdp3_ctrl_notify(struct mdp3_session_data *ses, int event) { return blocking_notifier_call_chain(&ses->notifier_head, event, ses); }
void hwmon_notify(unsigned long val, void *v) { blocking_notifier_call_chain(&hwmon_notifier_list, val, v); }
int exynos_cpufreq_smpl_warn_notify_call_chain(void) { int ret = blocking_notifier_call_chain(&exynos_cpufreq_smpl_warn_notifier_list, 0, NULL); return notifier_to_errno(ret); }
static int acpi_lid_notify_state(struct acpi_device *device, int state) { struct acpi_button *button = acpi_driver_data(device); int ret; ktime_t next_report; bool do_update; /* * In lid_init_state=ignore mode, if user opens/closes lid * frequently with "open" missing, and "last_time" is also updated * frequently, "close" cannot be delivered to the userspace. * So "last_time" is only updated after a timeout or an actual * switch. */ if (lid_init_state != ACPI_BUTTON_LID_INIT_IGNORE || button->last_state != !!state) do_update = true; else do_update = false; next_report = ktime_add(button->last_time, ms_to_ktime(lid_report_interval)); if (button->last_state == !!state && ktime_after(ktime_get(), next_report)) { /* Complain the buggy firmware */ pr_warn_once("The lid device is not compliant to SW_LID.\n"); /* * Send the unreliable complement switch event: * * On most platforms, the lid device is reliable. However * there are exceptions: * 1. Platforms returning initial lid state as "close" by * default after booting/resuming: * https://bugzilla.kernel.org/show_bug.cgi?id=89211 * https://bugzilla.kernel.org/show_bug.cgi?id=106151 * 2. Platforms never reporting "open" events: * https://bugzilla.kernel.org/show_bug.cgi?id=106941 * On these buggy platforms, the usage model of the ACPI * lid device actually is: * 1. The initial returning value of _LID may not be * reliable. * 2. The open event may not be reliable. * 3. The close event is reliable. * * But SW_LID is typed as input switch event, the input * layer checks if the event is redundant. Hence if the * state is not switched, the userspace cannot see this * platform triggered reliable event. By inserting a * complement switch event, it then is guaranteed that the * platform triggered reliable one can always be seen by * the userspace. */ if (lid_init_state == ACPI_BUTTON_LID_INIT_IGNORE) { do_update = true; /* * Do generate complement switch event for "close" * as "close" is reliable and wrong "open" won't * trigger unexpected behaviors. * Do not generate complement switch event for * "open" as "open" is not reliable and wrong * "close" will trigger unexpected behaviors. */ if (!state) { input_report_switch(button->input, SW_LID, state); input_sync(button->input); } } } /* Send the platform triggered reliable event */ if (do_update) { acpi_handle_debug(device->handle, "ACPI LID %s\n", state ? "open" : "closed"); input_report_switch(button->input, SW_LID, !state); input_sync(button->input); button->last_state = !!state; button->last_time = ktime_get(); } if (state) acpi_pm_wakeup_event(&device->dev); ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); if (ret == NOTIFY_DONE) ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); if (ret == NOTIFY_DONE || ret == NOTIFY_OK) { /* * It is also regarded as success if the notifier_chain * returns NOTIFY_OK or NOTIFY_DONE. */ ret = 0; } return ret; }
void summit_fsm_doAction(struct summit_smb347_info *di,int event) { int state=di->current_state; int temp=0; u32 value; int config,command=0; u8 pre_protect_event=0; switch (state){ case STATE_SUSPEND: if(event==USB_EVENT_NONE){ di->usb_online=0; di->ac_online=0; power_supply_changed(&di->usb); power_supply_changed(&di->ac); summit_charge_reset(di); /* * Turn off LEDs when USB is unplugged, * this is safe when the battery is already * discharging or full. There's no way * the battery is being charged when USB * is not connected. */ omap4430_green_led_set(NULL, 0); omap4430_orange_led_set(NULL, 0); CLEAR_BAT_FULL(di->protect_event); //enable low battery interrupt summit_enable_stat_interrupt(di,LOW_BATTERY_TRIGGER_IRQ); /* * Hold the wake lock, and schedule a delayed work * to release it in 1 second */ wake_lock(&di->chrg_lock); schedule_delayed_work(&di->disconnect_work, msecs_to_jiffies(1000)); } break; break; case STATE_INIT: if(event==USB_EVENT_DETECT_SOURCE){ /* * Cancel the scheduled delayed work that * releases the wakelock */ cancel_delayed_work_sync(&di->disconnect_work); di->fake_disconnect=0; if(di->mbid!=0){ temp=-1; config=i2c_smbus_read_byte_data(di->client,SUMMIT_SMB347_STAT_TIMERS); if(IS_BIT_CLEAR(config,5)){//The detect need to be redo again. dev_info(di->dev,"Redo apsd\n"); //disable stat summit_write_config(di,1); config=i2c_smbus_read_byte_data(di->client,SUMMIT_SMB347_STAT_TIMERS); SET_BIT(config,5); i2c_smbus_write_byte_data(di->client,SUMMIT_SMB347_STAT_TIMERS,config); summit_write_config(di,0); summit_config_apsd(di,0); summit_config_apsd(di,1); queue_delayed_work_on(0,summit_work_queue,&di->summit_check_work,msecs_to_jiffies(2000)); }else{//The detect has already done in u-boot dev_info(di->dev,"The detect has already done in u-boot\n"); temp=summit_get_apsd_result(di); writeIntoCBuffer(&di->events,temp); queue_delayed_work_on(0,summit_work_queue,&di->summit_monitor_work,0); } } summit_charger_reconfig(di); summit_config_time_protect(di,1); //reload the protection setting if(IS_ADJUST_CURRENT_VOLTAGE_ENABLE(di->protect_enable) && di->mbid>=4){ summit_adjust_charge_current(di,event); } if(pre_protect_event!=di->protect_event && di->mbid>=4){ summit_protection(di); } } if(event==EVENT_APSD_COMPLETE){ writeIntoCBuffer(&di->events,summit_get_apsd_result(di)); queue_delayed_work_on(0,summit_work_queue,&di->summit_monitor_work,0); } break; case STATE_ONDEMAND: summit_charge_reset(di); break; case STATE_PC: if(event==EVENT_DETECT_PC){ blocking_notifier_call_chain(&di->xceiv->notifier,USB_EVENT_VBUS, di->xceiv->gadget); di->usb_online=1; di->ac_online=0; power_supply_changed(&di->usb); power_supply_changed(&di->ac); } break; case STATE_CD: if(event==USB_EVENT_HOST_CHARGER){ if(di->mbid==0){ summit_switch_mode(di,HC_MODE); } di->usb_online=1; di->ac_online=0; power_supply_changed(&di->usb); power_supply_changed(&di->ac); blocking_notifier_call_chain(&di->xceiv->notifier,USB_EVENT_VBUS, di->xceiv->gadget); } break; case STATE_PC_100: summit_switch_mode(di,USB1_OR_15_MODE); di->usb_online=1; di->ac_online=0; power_supply_changed(&di->usb); power_supply_changed(&di->ac); break; //summit bug: if enable charge,then vbus always exits. case STATE_PC_500: if(event==USB_EVENT_LIMIT_500){ summit_switch_mode(di,USB5_OR_9_MODE); if(di->mbid==0){//summit bug: if enable charge,then vbus always exits. if((di->protect_enable==1 && di->protect_event==0) || di->protect_enable==0) summit_charge_enable(di,1); } di->usb_online=1; di->ac_online=0; power_supply_changed(&di->usb); power_supply_changed(&di->ac); } break; case STATE_OTHER://It will switch to usb5 mode,so need to switch hc mode. if(event==EVENT_DETECT_OTHER){ if(di->mbid==0){ summit_switch_mode(di,HC_MODE); if((di->protect_enable==1 && di->protect_event==0) || di->protect_enable==0) summit_charge_enable(di,1); }else{ summit_write_config(di,1); config=i2c_smbus_read_byte_data(di->client,SUMMIT_SMB347_ENABLE_CONTROL); command&=~(0x1<<(4)); i2c_smbus_write_byte_data(di->client,SUMMIT_SMB347_ENABLE_CONTROL,config); summit_write_config(di,0); summit_switch_mode(di,HC_MODE); } di->usb_online=0; di->ac_online=1; power_supply_changed(&di->usb); power_supply_changed(&di->ac); } //Some PC get a usb port that was detected by Other charger //if(event==EVENT_AICL_COMPLETE) // blocking_notifier_call_chain(&di->xceiv->notifier,USB_EVENT_VBUS, di->xceiv->gadget); break; case STATE_DC: if(event==USB_EVENT_CHARGER){ if(di->mbid==0){ summit_switch_mode(di,HC_MODE); } di->usb_online=0; di->ac_online=1; power_supply_changed(&di->usb); power_supply_changed(&di->ac); } break; case STATE_UC: if(event==EVENT_DETECT_TBD){ if(di->mbid==0){ summit_switch_mode(di,HC_MODE); if((di->protect_enable==1 && di->protect_event==0) || di->protect_enable==0) summit_charge_enable(di,1); } di->usb_online=0; di->ac_online=1; power_supply_changed(&di->usb); power_supply_changed(&di->ac); } break; } pre_protect_event=di->protect_event; switch(event){ case EVENT_FULL_BATTERY: SET_BAT_FULL(di->protect_event); break; case EVENT_RECHARGE_BATTERY: CLEAR_BAT_FULL(di->protect_event); break; case EVENT_BATTERY_I2C_ERROR: SET_BAT_I2C_FAIL(di->protect_event); break; case EVENT_BATTERY_I2C_NORMAL: CLEAR_BAT_I2C_FAIL(di->protect_event); break; case EVENT_NOT_RECOGNIZE_BATTERY: SET_BAT_NOT_RECOGNIZE(di->protect_event); break; case EVENT_RECOGNIZE_BATTERY: CLEAR_BAT_NOT_RECOGNIZE(di->protect_event); break; case EVENT_BATTERY_NTC_ZERO: SET_BAT_NTC_ERR(di->protect_event); break; case EVENT_BATTERY_NTC_NORMAL: CLEAR_BAT_NTC_ERR(di->protect_event); break; case EVENT_WEAK_BATTERY: SET_BAT_TOO_WEAK(di->protect_event); break; case EVENT_TEMP_PROTECT_STEP_2:// -20 < temp < 0 Stop Charge SET_BAT_TOO_COLD_FOR_CHARGE(di->protect_event); break; case EVENT_TEMP_PROTECT_STEP_1:// temp < -20 Stop Discharge SET_BAT_TOO_COLD_FOR_DISCHARGE(di->protect_event); break; case EVENT_TEMP_PROTECT_STEP_8:// 60 > temp SET_BAT_TOO_HOT_FOR_CHARGE(di->protect_event); break; case EVENT_TEMP_PROTECT_STEP_3: case EVENT_TEMP_PROTECT_STEP_4: case EVENT_TEMP_PROTECT_STEP_5: case EVENT_TEMP_PROTECT_STEP_6: case EVENT_TEMP_PROTECT_STEP_7: CLEAR_BAT_TOO_COLD_FOR_CHARGE(di->protect_event); CLEAR_BAT_TOO_COLD_FOR_DISCHARGE(di->protect_event); CLEAR_BAT_TOO_HOT_FOR_CHARGE(di->protect_event); di->bat_thermal_step=event; if(IS_ADJUST_CURRENT_VOLTAGE_ENABLE(di->protect_enable) && di->mbid>=4){ summit_adjust_charge_current(di,event); } break; } if( (pre_protect_event!=di->protect_event && di->mbid>=4 ) || (event==EVENT_RECHECK_PROTECTION)){ if(event==EVENT_RECHECK_PROTECTION) summit_adjust_charge_current(di,di->bat_thermal_step); summit_protection(di); }else if(di->mbid<4){ summit_charge_enable(di,1); } }
void profile_task_exit(struct task_struct *task) { blocking_notifier_call_chain(&task_exit_notifier, 0, task); }
static int acc_notify(int event) { int ret; ret = blocking_notifier_call_chain(&acc_mhl_notifier, event, NULL); return ret; }
void profile_munmap(unsigned long addr) { blocking_notifier_call_chain(&munmap_notifier, 0, (void *)addr); }
int pm_notifier_call_chain(unsigned long val) { int ret = blocking_notifier_call_chain(&pm_chain_head, val, NULL); return notifier_to_errno(ret); }
static ssize_t bq_proc_write(struct file *filp, const char *buff,unsigned long len, void *data) { struct bq27541_info *di=data; u32 reg_val,value; int event = USB_EVENT_VBUS; char messages[256], vol[256]; if (len > 256) len = 256; if (copy_from_user(messages, buff, len)) return -EFAULT; if ('-' == messages[0]) { /* set the register index */ //memcpy(vol, messages+1, len-1); index = (int) simple_strtoul(messages+1, NULL, 10); fake_temp=index*10; printk(KERN_INFO"%s:fake_temp %d\n",__func__, fake_temp); }else if('+'==messages[0]) { // set the register value //memcpy(vol, messages+1, len-1); reg_val = (int)simple_strtoul(messages+1, NULL, 10); fake_full_available_capacity=reg_val*100; printk(KERN_INFO"%s:fake_full_available_capacity %d\n",__func__, fake_full_available_capacity); //you can read value from the register of hardwae in here //i2c_smbus_write_byte_data(di->bat_client, index, reg_val); //printk(KERN_INFO"%s:register 0x%x: set value 0x%x\n",__func__, index, reg_val); }else if ('!' == messages[0]) { switch(messages[1]){ case 'a': cancel_delayed_work(&di->bat_monitor_work); flush_scheduled_work(); break; case 'b': queue_delayed_work(bat_work_queue,&di->bat_monitor_work,msecs_to_jiffies(1000 * 1)); break; case 'c': di->capacity=0; power_supply_changed(&di->bat); break; case 'd': blocking_notifier_call_chain(¬ifier_list, EVENT_UNKNOW_BATTERY, NULL); break; case 'e': blocking_notifier_call_chain(¬ifier_list, EVENT_RECOGNIZE_BATTERY, NULL); break; case 'f': blocking_notifier_call_chain(¬ifier_list, EVENT_NOT_RECOGNIZE_BATTERY, NULL); break; case 'g': blocking_notifier_call_chain(¬ifier_list, EVENT_WEAK_BATTERY, NULL); break; case 'h': blocking_notifier_call_chain(¬ifier_list, EVENT_BATTERY_I2C_ERROR, NULL); break; case 'i': blocking_notifier_call_chain(¬ifier_list, EVENT_FULL_BATTERY, NULL); break; case 'j': blocking_notifier_call_chain(¬ifier_list, EVENT_RECHARGE_BATTERY, NULL); break; case 'k': blocking_notifier_call_chain(¬ifier_list, EVENT_BATTERY_NTC_ZERO, NULL); break; case 'l': blocking_notifier_call_chain(¬ifier_list, EVENT_BATTERY_NTC_NORMAL, NULL); break; case '1'://temp < -20 fake_temp=-200; //blocking_notifier_call_chain(¬ifier_list, EVENT_TEMP_PROTECT_STEP_1, NULL); break; case '2'://-20 < temp < 0 , Stop Charge fake_temp=-250; //blocking_notifier_call_chain(¬ifier_list, EVENT_TEMP_PROTECT_STEP_2, NULL); break; case '3'://0 < temp < 14 , 0.18C (max) to 4.0V fake_temp=-100; //blocking_notifier_call_chain(¬ifier_list, EVENT_TEMP_PROTECT_STEP_3, NULL); break; case '4'://8 < temp < 14 , 0.18C (max) to 4.2V blocking_notifier_call_chain(¬ifier_list, EVENT_TEMP_PROTECT_STEP_4, NULL); break; case '5'://14 < temp < 23 , 0.5C (max) to 4.2V blocking_notifier_call_chain(¬ifier_list, EVENT_TEMP_PROTECT_STEP_5, NULL); break; case '6'://23 < temp < 45 , 0.7C (max) to 4.2V blocking_notifier_call_chain(¬ifier_list, EVENT_TEMP_PROTECT_STEP_6, NULL); break; case '7'://45 < temp < 60 , 0.5C (max) to 4V blocking_notifier_call_chain(¬ifier_list, EVENT_TEMP_PROTECT_STEP_7, NULL); break; case '8'://60 > temp , Stop Charge and Shutdown blocking_notifier_call_chain(¬ifier_list, EVENT_TEMP_PROTECT_STEP_8, NULL); break; } } return len; }
int pm_notifier_call_chain(unsigned long val) { return (blocking_notifier_call_chain(&pm_chain_head, val, NULL) == NOTIFY_BAD) ? -EINVAL : 0; }
void bat_monitor_work_func(struct work_struct *work) { struct bq27541_info *di = container_of(work, struct bq27541_info, bat_monitor_work.work); int err = 0; int new_value=0; int change=0; //For dead battery if(di->err_count>=15){ printk("bat:%s get i2c error\n",__func__); err=bq27x00_battery_voltage(di,&new_value); if (err){ queue_delayed_work(bat_work_queue,&di->bat_monitor_work, msecs_to_jiffies(10000 * 1)); blocking_notifier_call_chain(¬ifier_list, EVENT_BATTERY_I2C_ERROR, NULL); di->health = POWER_SUPPLY_HEALTH_UNKNOWN; power_supply_changed(&di->bat); }else{//dead battery is wake up printk("bat:%s dead battery is wake up\n",__func__); di->err_count=0; queue_delayed_work(bat_work_queue,&di->bat_monitor_work,0); blocking_notifier_call_chain(¬ifier_list, EVENT_BATTERY_I2C_NORMAL, NULL); di->health = POWER_SUPPLY_HEALTH_GOOD; power_supply_changed(&di->bat); } }else{ /* * We query the four most important variables frequently: * * temperature, voltage, capacity, status * * These four are used by various code in upper layers for * power management. The rest of the variables are not that * important or do not change much over time so we do not * need to query them too often */ if (bq27x00_battery_temperature(di, &new_value)) { di->err_count++; } else { if (new_value != di->temp) { di->temp = new_value; change = 1; bat_temp_charge_protect(di); } } if (bq27x00_battery_voltage(di, &new_value)) { di->err_count++; } else { if (new_value != di->voltage) { di->voltage = new_value; change = 1; //Low battery protection //If android with weak battery has some problem and not be shutdown then driver need to turn off the system. if((di->voltage <= HARD_LOW_VOLTAGE_THRESHOLD) && (di->status==POWER_SUPPLY_STATUS_DISCHARGING)) blocking_notifier_call_chain(¬ifier_list, EVENT_WEAK_BATTERY, NULL); } } if (bq27x00_battery_rsoc(di, &new_value)) { di->err_count++; } else { if (new_value != di->capacity) { di->capacity = new_value; change = 1; //Recharge event if((di->status==POWER_SUPPLY_STATUS_NOT_CHARGING) && (di->capacity<=RECHARGE_THRESHOLD)) blocking_notifier_call_chain(¬ifier_list, EVENT_RECHARGE_BATTERY, NULL); } } if (bq27x00_battery_status(di, &new_value)) { di->err_count++; } else { if (new_value!=di->status) { di->status = new_value; change = 1; //Full charge protectition event if (di->status == POWER_SUPPLY_STATUS_FULL) blocking_notifier_call_chain(¬ifier_list, EVENT_FULL_BATTERY, NULL); } } /* * Average current is also required to be * queried frequently for factory testing */ if (bq27x00_battery_current(di, &new_value)){ di->err_count++; } else { if (new_value != di->current_avg) { di->current_avg=new_value; change = 1; } } if (++di->long_count != BQ27541_LONG_COUNT) { /* Done with the important ones, skip the rest for now */ goto update_status; } else { di->long_count = 0; } new_value=twl_get_batntc(); if(new_value!=di->ntc_temp){ if((di->ntc_temp==0) && (new_value>0)) blocking_notifier_call_chain(¬ifier_list, EVENT_BATTERY_NTC_NORMAL, NULL); di->ntc_temp=new_value; if(di->ntc_temp==0) blocking_notifier_call_chain(¬ifier_list, EVENT_BATTERY_NTC_ZERO, NULL); } bq27x00_read(REG_FULL_AVAILABLE_CHARGE, &g_full_available_capacity, 0, di); if (bq27x00_battery_health(di, &new_value)) { di->err_count++; } else { if (new_value != di->health) { di->health = new_value; change = 1; } } /* Query TimeToEmpty() register */ if (bq27x00_battery_time_to_empty(di, &new_value)) { di->err_count++; } else if (new_value != di->time_to_empty) { di->time_to_empty = new_value; change = 1; } /* Query TimeToFull() register */ if (bq27x00_battery_time_to_full(di, &new_value)) { di->err_count++; } else if (new_value != di->time_to_full) { di->time_to_full = new_value; change = 1; } /* Query CycleCount() register */ if (bq27x00_battery_cycle_count(di, &new_value)) { di->err_count++; } else if (new_value != di->cycle_count) { di->cycle_count = new_value; change = 1; } /* Query AveragePower() register */ if (bq27x00_battery_average_power(di, &new_value)) { di->err_count++; } else if (new_value != di->average_power) { di->average_power = new_value; change = 1; } /* Query AvailableEnergy() register */ if (bq27x00_battery_available_energy(di, &new_value)) { di->err_count++; } else if (new_value != di->available_energy) { di->available_energy = new_value; change = 1; } /* Query RemainingCapacity() register */ if (bq27x00_battery_remaining_charge(di, &new_value)) { di->err_count++; } else if (new_value != di->remaining_charge) { di->remaining_charge = new_value; change = 1; } /* Query FullChargeCapacity() register */ if (bq27x00_battery_full_charge(di, &new_value)) { di->err_count++; } else if (new_value != di->full_charge) { di->full_charge = new_value; change = 1; } /* Query FullAvailableCapacity() register */ if (bq27x00_battery_full_charge_uncompensated(di, &new_value)) { di->err_count++; } else if (new_value != di->full_charge_uncompensated) { di->full_charge_uncompensated = new_value; change = 1; } if (++di->manufacturer_id_read_count != 2) { goto update_status; } else { di->manufacturer_id_read_count = 0; } /* Check for manufacturer ID every minute */ new_value = check_manufacturer(di); if (new_value != di->manufacturer){ di->manufacturer = new_value; change = 1; if (di->manufacturer >= 0) blocking_notifier_call_chain(¬ifier_list, EVENT_RECOGNIZE_BATTERY, NULL); if (di->manufacturer == NOT_RECOGNIZE) blocking_notifier_call_chain(¬ifier_list, EVENT_NOT_RECOGNIZE_BATTERY, NULL); if (di->manufacturer == UNKNOW) blocking_notifier_call_chain(¬ifier_list, EVENT_UNKNOW_BATTERY, NULL); } update_status: if (change) { power_supply_changed(&di->bat); // LED function u8 value = 0; if ((di->disable_led == 0) && !twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &value, 0x03)) { if ((di->status == POWER_SUPPLY_STATUS_CHARGING) && (value & (1 << 2))) { if(di->capacity < 90) { /* * Battery being charged, capacity < 90%: Amber LED */ omap4430_green_led_set(NULL, 0); omap4430_orange_led_set(NULL, 255); } else { /* * Battery being charged, capacity >= 90%: Green LED */ omap4430_orange_led_set(NULL, 0); omap4430_green_led_set(NULL, 255); } } else if (di->status == POWER_SUPPLY_STATUS_FULL) { if (value & (1 << 2)) { /* Set to green if connected to USB */ omap4430_orange_led_set(NULL, 0); omap4430_green_led_set(NULL, 255); } else { omap4430_green_led_set(NULL, 0); omap4430_orange_led_set(NULL, 0); } } } } if(di->err_count>=15){ printk("bat:%s get i2c error\n",__func__); queue_delayed_work(bat_work_queue,&di->bat_monitor_work, msecs_to_jiffies(10000 * 1)); }else queue_delayed_work(bat_work_queue,&di->bat_monitor_work, msecs_to_jiffies(5000 * 1)); } }
void usb_notify_add_bus(struct usb_bus *ubus) { blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus); }
void usb_notify_config_device(struct usb_device *udev) { blocking_notifier_call_chain(&usb_notifier_list, USB_DEVICE_CONFIG, udev); }