Beispiel #1
0
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);
}
Beispiel #2
0
/*!
 * 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;
}
Beispiel #6
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);
}
Beispiel #7
0
/*!
 * 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;
}
Beispiel #9
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 ();
}
Beispiel #10
0
/*!
 * 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;
}
Beispiel #11
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;
}
Beispiel #12
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(&reg_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, &reg_info,
				 sizeof(register_info))) {
			return -EFAULT;
		}
		break;

	case PMIC_WRITE_REG:
		if (copy_from_user(&reg_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, &reg_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;
}
Beispiel #13
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;

	//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;
}
Beispiel #14
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;
}
Beispiel #15
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;
}