static void mxc_register_powerkey(pwrkey_callback pk_cb) { pmic_event_callback_t power_key_event; power_key_event.param = (void *)1; power_key_event.func = (void *)pk_cb; pmic_event_subscribe(EVENT_PWRONI, power_key_event); power_key_event.param = (void *)3; pmic_event_subscribe(EVENT_PWRON3I, power_key_event); }
/*! * This function is used to un/subscribe on RTC event IT. * * @param event type of event. * @param callback event callback function. * @param sub define if Un/subscribe event. * * @return This function returns PMIC_SUCCESS if successful. */ PMIC_STATUS pmic_rtc_event(t_rtc_int event, void *callback, bool sub) { type_event rtc_event; if (callback == NULL) { return PMIC_ERROR; } else { rtc_callback.func = callback; rtc_callback.param = NULL; } switch (event) { case RTC_IT_ALARM: rtc_event = EVENT_TODAI; break; case RTC_IT_1HZ: rtc_event = EVENT_E1HZI; break; case RTC_IT_RST: rtc_event = EVENT_RTCRSTI; break; default: return PMIC_PARAMETER_ERROR; } if (sub == true) { CHECK_ERROR(pmic_event_subscribe(rtc_event, rtc_callback)); } else { CHECK_ERROR(pmic_event_unsubscribe(rtc_event, rtc_callback)); } return PMIC_SUCCESS; }
static void mxc_register_low_power_event(void) { pmic_event_callback_t low_power_event; printk("Register low power event handle.\n"); low_power_event.param = (void *)1; low_power_event.func = (void *)nimbus_low_power_handle; pmic_event_subscribe(EVENT_LOBATLI, low_power_event); }
static void mxc_register_powerkey(pwrkey_callback pk_cb) { pmic_event_callback_t power_key_event; power_key_event.param = (void *)1; power_key_event.func = (void *)pk_cb; pmic_event_subscribe(EVENT_PWRONI, power_key_event); power_key_event.param = (void *)3; pmic_event_subscribe(EVENT_PWRON3I, power_key_event); #ifdef CONFIG_MXC_MC13892_BATTERY0 mxc_register_low_power_event(); #endif #ifdef POWERKEY_HANDLE printk("<INFO> Power key detect...\n"); mxc_pwrkey_getstatus(1); #endif }
static int mc13892_regulator_init(struct mc13892 *mc13892) { unsigned int value; pmic_event_callback_t power_key_event; int register_mask; pr_info("Initializing regulators for MX53 EVK \n"); /* subscribe PWRON1 event to enable ON_OFF key */ power_key_event.param = NULL; power_key_event.func = (void *)power_on_evt_handler; pmic_event_subscribe(EVENT_PWRONI, power_key_event); /* Bit 4 DRM: keep VSRTC and CLK32KMCU on for all states */ #if defined(CONFIG_RTC_DRV_MXC_V2) || defined(CONFIG_RTC_DRV_MXC_V2_MODULE) value = BITFVAL(DRM, 1); register_mask = BITFMASK(DRM); pmic_write_reg(REG_POWER_CTL0, value, register_mask); #endif /* Set the STANDBYSECINV bit, so that STANDBY pin is * interpreted as active low. */ value = BITFVAL(STANDBYSECINV, 1); register_mask = BITFMASK(STANDBYSECINV); pmic_write_reg(REG_POWER_CTL2, value, register_mask); /* Disable coin cell charger since the cell is not rechargeable */ value = BITFVAL(COINCHEN, 0) | BITFVAL(VCOIN, VCOIN_3_0V); register_mask = BITFMASK(COINCHEN) | BITFMASK(VCOIN); pmic_write_reg(REG_POWER_CTL0, value, register_mask); mc13892_register_regulator(mc13892, MC13892_SW1, &sw1_init); mc13892_register_regulator(mc13892, MC13892_SW2, &sw2_init); mc13892_register_regulator(mc13892, MC13892_SW3, &sw3_init); mc13892_register_regulator(mc13892, MC13892_SW4, &sw4_init); mc13892_register_regulator(mc13892, MC13892_SWBST, &swbst_init); mc13892_register_regulator(mc13892, MC13892_VIOHI, &viohi_init); mc13892_register_regulator(mc13892, MC13892_VPLL, &vpll_init); mc13892_register_regulator(mc13892, MC13892_VDIG, &vdig_init); mc13892_register_regulator(mc13892, MC13892_VSD, &vsd_init); mc13892_register_regulator(mc13892, MC13892_VUSB2, &vusb2_init); mc13892_register_regulator(mc13892, MC13892_VVIDEO, &vvideo_init); mc13892_register_regulator(mc13892, MC13892_VAUDIO, &vaudio_init); mc13892_register_regulator(mc13892, MC13892_VCAM, &vcam_init); mc13892_register_regulator(mc13892, MC13892_VGEN1, &vgen1_init); mc13892_register_regulator(mc13892, MC13892_VGEN2, &vgen2_init); mc13892_register_regulator(mc13892, MC13892_VGEN3, &vgen3_init); mc13892_register_regulator(mc13892, MC13892_VUSB, &vusb_init); mc13892_register_regulator(mc13892, MC13892_GPO1, &gpo1_init); mc13892_register_regulator(mc13892, MC13892_GPO2, &gpo2_init); mc13892_register_regulator(mc13892, MC13892_GPO3, &gpo3_init); mc13892_register_regulator(mc13892, MC13892_GPO4, &gpo4_init); return 0; }
/* * Battery low check initial */ static void battery_low_init (struct mc13892_dev_info *di) { int retval = 0; /* * LOBATLI/HI level setting * BPSNS1/0 0:0 -> 2.8V 3.0V */ retval = pmic_write_reg (REG_POWER_CTL0, 0x00000000, 0x00030000); if (retval != PMIC_SUCCESS) { printk ("pmic_battery_probe: can't set BPSNS1/0 %d\n", retval); } battery_create_inputdevice (); bat_event_callback.func = battery_lobatli_callback; bat_event_callback.param = (void *) di; pmic_event_subscribe (EVENT_LOBATLI, bat_event_callback); bat_event_callback.func = battery_lobathi_callback; bat_event_callback.param = (void *) di; pmic_event_subscribe (EVENT_LOBATHI, bat_event_callback); }
/*! * This function wait the Alarm event * * @return This function returns PMIC_SUCCESS if successful. */ PMIC_STATUS pmic_rtc_wait_alarm(void) { DEFINE_WAIT(wait); alarm_callback.func = callback_alarm_synchronous; alarm_callback.param = NULL; CHECK_ERROR(pmic_event_subscribe(EVENT_TODAI, alarm_callback)); prepare_to_wait(&queue_alarm, &wait, TASK_UNINTERRUPTIBLE); schedule(); finish_wait(&queue_alarm, &wait); CHECK_ERROR(pmic_event_unsubscribe(EVENT_TODAI, alarm_callback)); return PMIC_SUCCESS; }
static int mc13892_regulator_init(struct mc13892 *mc13892) { unsigned int value; pmic_event_callback_t power_key_event; int register_mask; printk("Initializing regulators for 3-stack.\n"); if (mxc_cpu_is_rev(CHIP_REV_2_0) < 0) sw2_init.constraints.state_mem.uV = 1100000; /* subscribe PWRON1 event to enable ON_OFF key */ power_key_event.param = NULL; power_key_event.func = (void *)power_on_evt_handler; pmic_event_subscribe(EVENT_PWRONI, power_key_event); /* Bit 4 DRM: keep VSRTC and CLK32KMCU on for all states */ pmic_read_reg(REG_POWER_CTL0, &value, 0xffffff); value |= 0x000010; pmic_write_reg(REG_POWER_CTL0, value, 0xffffff); /* Set the STANDBYSECINV bit, so that STANDBY pin is * interpreted as active low. */ value = BITFVAL(STANDBYSECINV, 1); register_mask = BITFMASK(STANDBYSECINV); pmic_write_reg(REG_POWER_CTL2, value, register_mask); mc13892_register_regulator(mc13892, MC13892_SW1, &sw1_init); mc13892_register_regulator(mc13892, MC13892_SW2, &sw2_init); mc13892_register_regulator(mc13892, MC13892_SW3, &sw3_init); mc13892_register_regulator(mc13892, MC13892_SW4, &sw4_init); mc13892_register_regulator(mc13892, MC13892_SWBST, &swbst_init); mc13892_register_regulator(mc13892, MC13892_VIOHI, &viohi_init); mc13892_register_regulator(mc13892, MC13892_VPLL, &vpll_init); mc13892_register_regulator(mc13892, MC13892_VDIG, &vdig_init); mc13892_register_regulator(mc13892, MC13892_VSD, &vsd_init); mc13892_register_regulator(mc13892, MC13892_VUSB2, &vusb2_init); mc13892_register_regulator(mc13892, MC13892_VVIDEO, &vvideo_init); mc13892_register_regulator(mc13892, MC13892_VAUDIO, &vaudio_init); mc13892_register_regulator(mc13892, MC13892_VCAM, &vcam_init); mc13892_register_regulator(mc13892, MC13892_VGEN1, &vgen1_init); mc13892_register_regulator(mc13892, MC13892_VGEN2, &vgen2_init); mc13892_register_regulator(mc13892, MC13892_VGEN3, &vgen3_init); mc13892_register_regulator(mc13892, MC13892_VUSB, &vusb_init); mc13892_register_regulator(mc13892, MC13892_GPO1, &gpo1_init); mc13892_register_regulator(mc13892, MC13892_GPO2, &gpo2_init); mc13892_register_regulator(mc13892, MC13892_GPO3, &gpo3_init); mc13892_register_regulator(mc13892, MC13892_GPO4, &gpo4_init); return 0; }
static void battery_low_suspend (void) { int rc; pmic_event_callback_t bat_event_callback; battery_poll_statistics [1]++; battery_poll_statistics [6] = 0; LogIn (0x00010000, battery_poll_statistics [1], battery_poll_statistics [0]); /* * previous alarm setting */ pre_alarm [0] = 1; pre_alarm [1] = 0x01FFFF; pre_alarm [2] = 0x007FFF; pmic_read_reg (REG_RTC_ALARM, &(pre_alarm [1]), 0x01FFFF); pmic_read_reg (REG_RTC_DAY_ALARM, &(pre_alarm [2]), 0x007FFF); /* * wakeup after check interval */ rc = battery_set_alarm (); if (rc == 0) { /* * interrupt enable TODAI only */ bat_event_callback.func = battery_poll_callback; bat_event_callback.param = (void *)0; pmic_event_subscribe (EVENT_TODAI, bat_event_callback); pmic_event_for_suspend (EVENT_TODAI); } /* * DCinput Power mode */ gpio_battery_enable ( 0 ); /* * cleanup Power-SW flag */ resume_power_sw_clean (); }
/*! * This function is used to un/subscribe on battery event IT. * * @param event type of event. * @param callback event callback function. * @param sub define if Un/subscribe event. * * @return This function returns 0 if successful. */ PMIC_STATUS mc13783_battery_event(t_batt_event event, void *callback, bool sub) { pmic_event_callback_t bat_callback; type_event bat_event; bat_callback.func = callback; bat_callback.param = NULL; switch (event) { case BAT_IT_CHG_DET: bat_event = EVENT_CHGDETI; break; case BAT_IT_CHG_OVERVOLT: bat_event = EVENT_CHGOVI; break; case BAT_IT_CHG_REVERSE: bat_event = EVENT_CHGREVI; break; case BAT_IT_CHG_SHORT_CIRCUIT: bat_event = EVENT_CHGSHORTI; break; case BAT_IT_CCCV: bat_event = EVENT_CCCVI; break; case BAT_IT_BELOW_THRESHOLD: bat_event = EVENT_CHRGCURRI; break; default: return PMIC_PARAMETER_ERROR; } if (sub == true) { CHECK_ERROR(pmic_event_subscribe(bat_event, bat_callback)); } else { CHECK_ERROR(pmic_event_unsubscribe(bat_event, bat_callback)); } return 0; }
/*! * This function implements IOCTL controls on a PMIC RTC device. * * @param inode pointer on the node * @param file pointer on the file * @param cmd the command * @param arg the parameter * @return This function returns 0 if successful. */ static int pmic_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct timeval *pmic_time = NULL; if (_IOC_TYPE(cmd) != 'p') return -ENOTTY; if (arg) { pmic_time = kmalloc(sizeof(struct timeval), GFP_KERNEL); if (pmic_time == NULL) return -ENOMEM; /* if (copy_from_user(pmic_time, (struct timeval *)arg, sizeof(struct timeval))) { return -EFAULT; } */ } switch (cmd) { case PMIC_RTC_SET_TIME: if (copy_from_user(pmic_time, (struct timeval *)arg, sizeof(struct timeval))) { return -EFAULT; } pr_debug("SET RTC\n"); CHECK_ERROR(pmic_rtc_set_time(pmic_time)); break; case PMIC_RTC_GET_TIME: if (copy_to_user((struct timeval *)arg, pmic_time, sizeof(struct timeval))) { return -EFAULT; } pr_debug("GET RTC\n"); CHECK_ERROR(pmic_rtc_get_time(pmic_time)); break; case PMIC_RTC_SET_ALARM: if (copy_from_user(pmic_time, (struct timeval *)arg, sizeof(struct timeval))) { return -EFAULT; } pr_debug("SET RTC ALARM\n"); CHECK_ERROR(pmic_rtc_set_time_alarm(pmic_time)); break; case PMIC_RTC_GET_ALARM: if (copy_to_user((struct timeval *)arg, pmic_time, sizeof(struct timeval))) { return -EFAULT; } pr_debug("GET RTC ALARM\n"); CHECK_ERROR(pmic_rtc_get_time_alarm(pmic_time)); break; case PMIC_RTC_WAIT_ALARM: printk(KERN_INFO "WAIT ALARM...\n"); CHECK_ERROR(pmic_rtc_event_sub(RTC_IT_ALARM, callback_test_sub)); CHECK_ERROR(pmic_rtc_wait_alarm()); printk(KERN_INFO "ALARM DONE\n"); CHECK_ERROR(pmic_rtc_event_unsub(RTC_IT_ALARM, callback_test_sub)); break; case PMIC_RTC_ALARM_REGISTER: printk(KERN_INFO "PMIC RTC ALARM REGISTER\n"); alarm_callback.func = callback_alarm_asynchronous; alarm_callback.param = NULL; CHECK_ERROR(pmic_event_subscribe(EVENT_TODAI, alarm_callback)); break; case PMIC_RTC_ALARM_UNREGISTER: printk(KERN_INFO "PMIC RTC ALARM UNREGISTER\n"); alarm_callback.func = callback_alarm_asynchronous; alarm_callback.param = NULL; CHECK_ERROR(pmic_event_unsubscribe (EVENT_TODAI, alarm_callback)); pmic_rtc_done = false; break; default: pr_debug("%d unsupported ioctl command\n", (int)cmd); return -EINVAL; } if (arg) { if (copy_to_user((struct timeval *)arg, pmic_time, sizeof(struct timeval))) { return -EFAULT; } kfree(pmic_time); } return 0; }
/*! * This function implements IOCTL controls on a PMIC device. * * @param inode pointer on the node * @param file pointer on the file * @param cmd the command * @param arg the parameter * @return This function returns 0 if successful. */ static int pmic_dev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { register_info reg_info; pmic_event_callback_t event_sub; type_event event; int ret = 0; if (_IOC_TYPE(cmd) != 'P') return -ENOTTY; switch (cmd) { case PMIC_READ_REG: if (copy_from_user(®_info, (register_info *) arg, sizeof(register_info))) { return -EFAULT; } ret = pmic_read_reg(reg_info.reg, &(reg_info.reg_value), 0x00ffffff); pr_debug("read reg %d %x\n", reg_info.reg, reg_info.reg_value); if (copy_to_user((register_info *) arg, ®_info, sizeof(register_info))) { return -EFAULT; } break; case PMIC_WRITE_REG: if (copy_from_user(®_info, (register_info *) arg, sizeof(register_info))) { return -EFAULT; } ret = pmic_write_reg(reg_info.reg, reg_info.reg_value, 0x00ffffff); pr_debug("write reg %d %x\n", reg_info.reg, reg_info.reg_value); if (copy_to_user((register_info *) arg, ®_info, sizeof(register_info))) { return -EFAULT; } break; case PMIC_SUBSCRIBE: if (get_user(event, (int __user *)arg)) { return -EFAULT; } event_sub.func = callbackfn; event_sub.param = (void *)event; ret = pmic_event_subscribe(event, event_sub); pr_debug("subscribe done\n"); break; case PMIC_UNSUBSCRIBE: if (get_user(event, (int __user *)arg)) { return -EFAULT; } event_sub.func = callbackfn; event_sub.param = (void *)event; ret = pmic_event_unsubscribe(event, event_sub); pr_debug("unsubscribe done\n"); break; case PMIC_NOTIFY_USER: if (get_user(event, (int __user *)arg)) { return -EFAULT; } event_sub.func = user_notify_callback; event_sub.param = (void *)event; ret = pmic_event_subscribe(event, event_sub); break; case PMIC_GET_NOTIFY: CIRC_REMOVE(event, pmic_events, CIRC_BUF_MAX); if (put_user(event, (int __user *)arg)) { return -EFAULT; } break; default: printk(KERN_ERR "%d unsupported ioctl command\n", (int)cmd); return -EINVAL; } return ret; }
static int pmic_battery_probe(struct platform_device *pdev) { int retval = 0; struct mc13892_dev_info *di; pmic_event_callback_t bat_event_callback; pmic_version_t pmic_version; //printk("%s %s %d \n",__FILE__,__func__,__LINE__); /* Only apply battery driver for MC13892 V2.0 due to ENGR108085 */ pmic_version = pmic_get_version(); if (pmic_version.revision < 20) { pr_debug("Battery driver is only applied for MC13892 V2.0\n"); return -1; } if (machine_is_mx50_arm2()) { pr_debug("mc13892 charger is not used for this platform\n"); return -1; } di = kzalloc(sizeof(*di), GFP_KERNEL); if (!di) { retval = -ENOMEM; goto di_alloc_failed; } di->init_charge = -1; platform_set_drvdata(pdev, di); di->charger.name = "mc13892_charger"; di->charger.type = POWER_SUPPLY_TYPE_MAINS; di->charger.properties = mc13892_charger_props; di->charger.num_properties = ARRAY_SIZE(mc13892_charger_props); di->charger.get_property = mc13892_charger_get_property; retval = power_supply_register(&pdev->dev, &di->charger); if (retval) { dev_err(di->dev, "failed to register charger\n"); goto charger_failed; } INIT_DELAYED_WORK(&di->monitor_work, mc13892_battery_work); di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev)); if (!di->monitor_wqueue) { retval = -ESRCH; goto workqueue_failed; } queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 10); //queue_delayed_work(di->monitor_wqueue, &di->monitor_work, msecs_to_jiffies(10000)); pmic_stop_coulomb_counter(); pmic_calibrate_coulomb_counter(); //for get correct voltage on the battery when booting with external power. //chg_thread will change it, when next work (chg_work) is start. pmic_set_chg_current(0); INIT_DELAYED_WORK(&di->calc_capacity,mc13892_compute_battery_capacity_from_CC); queue_delayed_work(di->monitor_wqueue, &di->calc_capacity, 0); INIT_DELAYED_WORK(&chg_work, chg_thread); chg_wq = create_singlethread_workqueue("mxc_chg"); if (!chg_wq) { retval = -ESRCH; goto workqueue_failed; } queue_delayed_work(chg_wq, &chg_work, HZ); di->dev = &pdev->dev; di->bat.name = "mc13892_bat"; di->bat.type = POWER_SUPPLY_TYPE_BATTERY; di->bat.properties = mc13892_battery_props; di->bat.num_properties = ARRAY_SIZE(mc13892_battery_props); di->bat.get_property = mc13892_battery_get_property; di->bat.use_for_apm = 1; di->battery_status = POWER_SUPPLY_STATUS_UNKNOWN; //di->battery_status = POWER_SUPPLY_STATUS_DISCHARGING; retval = power_supply_register(&pdev->dev, &di->bat); if (retval) { dev_err(di->dev, "failed to register battery\n"); goto batt_failed; } bat_event_callback.func = charger_online_event_callback; bat_event_callback.param = (void *) di; pmic_event_subscribe(EVENT_CHGDETI, bat_event_callback); retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_enable.attr); if (retval) { printk(KERN_ERR "Battery: Unable to register sysdev entry for Battery"); goto workqueue_failed; } chg_wa_is_active = 1; chg_wa_timer = 0; disable_chg_timer = 0; #if defined(PMIC_MC13892_BATTERY_WORK) work_init(); #endif goto success; workqueue_failed: power_supply_unregister(&di->charger); charger_failed: power_supply_unregister(&di->bat); batt_failed: kfree(di); di_alloc_failed: success: dev_dbg(di->dev, "%s battery probed!\n", __func__); return retval; return 0; }
static int pmic_battery_probe(struct platform_device *pdev) { int retval = 0; struct mc13892_dev_info *di; pmic_event_callback_t bat_event_callback; pmic_version_t pmic_version; /* Only apply battery driver for MC13892 V2.0 due to ENGR108085 */ pmic_version = pmic_get_version(); if (pmic_version.revision < 20) { pr_debug("Battery driver is only applied for MC13892 V2.0\n"); return -1; } if (machine_is_mx50_arm2()) { pr_debug("mc13892 charger is not used for this platform\n"); return -1; } di = kzalloc(sizeof(*di), GFP_KERNEL); if (!di) { retval = -ENOMEM; goto di_alloc_failed; } platform_set_drvdata(pdev, di); di->charger.name = "mc13892_charger"; di->charger.type = POWER_SUPPLY_TYPE_MAINS; di->charger.properties = mc13892_charger_props; di->charger.num_properties = ARRAY_SIZE(mc13892_charger_props); di->charger.get_property = mc13892_charger_get_property; retval = power_supply_register(&pdev->dev, &di->charger); if (retval) { dev_err(di->dev, "failed to register charger\n"); goto charger_failed; } INIT_DELAYED_WORK(&chg_work, chg_thread); chg_wq = create_singlethread_workqueue("mxc_chg"); if (!chg_wq) { retval = -ESRCH; goto workqueue_failed; } INIT_DELAYED_WORK(&di->monitor_work, mc13892_battery_work); di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev)); if (!di->monitor_wqueue) { retval = -ESRCH; goto workqueue_failed; } queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 10); di->dev = &pdev->dev; di->bat.name = "mc13892_bat"; di->bat.type = POWER_SUPPLY_TYPE_BATTERY; di->bat.properties = mc13892_battery_props; di->bat.num_properties = ARRAY_SIZE(mc13892_battery_props); di->bat.get_property = mc13892_battery_get_property; di->bat.use_for_apm = 1; di->battery_status = POWER_SUPPLY_STATUS_UNKNOWN; retval = power_supply_register(&pdev->dev, &di->bat); if (retval) { dev_err(di->dev, "failed to register battery\n"); goto batt_failed; } bat_event_callback.func = charger_online_event_callback; bat_event_callback.param = (void *) di; pmic_event_subscribe(EVENT_CHGDETI, bat_event_callback); retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_enable.attr); if (retval) { printk(KERN_ERR "Battery: Unable to register sysdev entry for Battery"); goto workqueue_failed; } chg_wa_is_active = 1; chg_wa_timer = 0; disable_chg_timer = 0; pmic_stop_coulomb_counter(); pmic_calibrate_coulomb_counter(); goto success; workqueue_failed: power_supply_unregister(&di->charger); charger_failed: power_supply_unregister(&di->bat); batt_failed: kfree(di); di_alloc_failed: success: dev_dbg(di->dev, "%s battery probed!\n", __func__); return retval; return 0; }
static int pmic_battery_probe(struct platform_device *pdev) { int retval = 0; struct mc13892_dev_info *di; #ifndef CONFIG_MACH_MX51_ERDOS pmic_event_callback_t bat_event_callback; #endif /* CONFIG_MACH_MX51_ERDOS */ pmic_version_t pmic_version; /* Only apply battery driver for MC13892 V2.0 due to ENGR108085 */ pmic_version = pmic_get_version(); if (pmic_version.revision < 20) { pr_debug("Battery driver is only applied for MC13892 V2.0\n"); return -1; } di = kzalloc(sizeof(*di), GFP_KERNEL); if (!di) { retval = -ENOMEM; goto di_alloc_failed; } platform_set_drvdata(pdev, di); di->dev = &pdev->dev; di->bat.name = "mc13892_bat"; di->bat.type = POWER_SUPPLY_TYPE_BATTERY; di->bat.properties = mc13892_battery_props; di->bat.num_properties = ARRAY_SIZE(mc13892_battery_props); di->bat.get_property = mc13892_battery_get_property; di->battery_status = POWER_SUPPLY_STATUS_UNKNOWN; retval = power_supply_register(&pdev->dev, &di->bat); if (retval) { dev_err(di->dev, "failed to register battery\n"); goto batt_failed; } di->charger.name = "mc13892_charger"; di->charger.type = POWER_SUPPLY_TYPE_MAINS; di->charger.properties = mc13892_charger_props; di->charger.num_properties = ARRAY_SIZE(mc13892_charger_props); di->charger.get_property = mc13892_charger_get_property; retval = power_supply_register(&pdev->dev, &di->charger); if (retval) { dev_err(di->dev, "failed to register charger\n"); goto charger_failed; } INIT_DELAYED_WORK(&di->monitor_work, mc13892_battery_work); di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev)); if (!di->monitor_wqueue) { retval = -ESRCH; goto workqueue_failed; } queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 10); #ifdef CONFIG_MACH_MX51_ERDOS #ifdef ALWAY_REFON gpio_refon(1); // select measurement #endif /* ALWAY_REFON */ /* * initial value (BATT voltage raw) */ #ifdef CONFIG_PROC_FS proc_create ("battery", 0, NULL, &battery_proc_fops); #endif /* CONFIG_PROC_FS */ battery_low_init (di); #else bat_event_callback.func = charger_online_event_callback; bat_event_callback.param = (void *) di; pmic_event_subscribe(EVENT_CHGDETI, bat_event_callback); pmic_stop_coulomb_counter(); pmic_calibrate_coulomb_counter(); #endif /* CONFIG_MACH_MX51_ERDOS */ goto success; workqueue_failed: power_supply_unregister(&di->charger); charger_failed: power_supply_unregister(&di->bat); batt_failed: kfree(di); di_alloc_failed: success: dev_dbg(di->dev, "%s battery probed!\n", __func__); return retval; return 0; }