static void battery_monitor_work(struct work_struct *work)
{
	int vbatt;
	struct bcl_context *bcl = container_of(work,
			struct bcl_context, battery_monitor_work);

	if (gbcl->bcl_mode == BCL_DEVICE_ENABLED) {
		bcl->btm_mode = BCL_VPH_MONITOR_MODE;
		update_cpu_freq();
		bcl_handle_hotplug();
		bcl_get_battery_voltage(&vbatt);
		pr_debug("vbat is %d\n", vbatt);
		if (bcl_vph_state == BCL_LOW_THRESHOLD) {
			if (vbatt <= gbcl->btm_vph_low_thresh) {
				/*relay the notification to charger ic driver*/
				if (bcl->btm_charger_ic_low_thresh ==
					gbcl->btm_vph_adc_param.low_thr) {
					bcl_hit_shutdown_voltage = true;
				} else
				bcl_config_vph_adc(gbcl,
					BCL_LOW_THRESHOLD_TYPE_MIN);
			} else
				bcl_config_vph_adc(gbcl,
					BCL_HIGH_THRESHOLD_TYPE);
		} else {
			bcl_config_vph_adc(gbcl, BCL_LOW_THRESHOLD_TYPE);
		}
	}
}
static void bcl_vph_notification(enum qpnp_tm_state state, void *ctx)
{
	struct bcl_context *bcl = ctx;
	int ret = 0;

	mutex_lock(&bcl_notify_mutex);
	if (bcl->btm_mode == BCL_MONITOR_DISABLED)
		goto unlock_and_exit;

	switch (state) {
	case ADC_TM_LOW_STATE:
		if (bcl->btm_mode != BCL_VPH_MONITOR_MODE) {
			pr_err("Low thresh received with invalid btm mode:%d\n",
				bcl->btm_mode);
			ibat_mode_set(BCL_DEVICE_DISABLED);
			goto unlock_and_exit;
		}
		pr_debug("Initiating Ibat current monitoring\n");
		bcl_vph_notify(BCL_LOW_THRESHOLD);
		bcl_config_ibat_adc(gbcl, BCL_HIGH_THRESHOLD_TYPE);
		bcl_config_vph_adc(gbcl, BCL_HIGH_THRESHOLD_TYPE);
		bcl->btm_mode = BCL_IBAT_MONITOR_MODE;
		break;
	case ADC_TM_HIGH_STATE:
		if (bcl->btm_mode != BCL_IBAT_MONITOR_MODE
			&& bcl->btm_mode != BCL_IBAT_HIGH_LOAD_MODE) {
			pr_err("High thresh received with invalid btm mode:%d\n"
				, bcl->btm_mode);
			ibat_mode_set(BCL_DEVICE_DISABLED);
			goto unlock_and_exit;
		}
		pr_debug("Exiting Ibat current monitoring\n");
		bcl->btm_mode = BCL_VPH_MONITOR_MODE;
		ret = ibat_disable();
		if (ret) {
			pr_err("Error disabling ibat ADC. err:%d\n", ret);
			goto unlock_and_exit;
		}
		bcl_vph_notify(BCL_HIGH_THRESHOLD);
		bcl_config_vph_adc(gbcl, BCL_LOW_THRESHOLD_TYPE);
		break;
	default:
		goto set_thresh;
	}
unlock_and_exit:
	mutex_unlock(&bcl_notify_mutex);
	return;

set_thresh:
	mutex_unlock(&bcl_notify_mutex);
	bcl_config_vph_adc(gbcl, BCL_HIGH_THRESHOLD_TYPE);
	return;
}
static void power_supply_callback(struct power_supply *psy)
{
	int vbatt = 0;
	if (bcl_hit_shutdown_voltage)
		return;
	if (0 != bcl_get_battery_voltage(&vbatt))
		return;
	if (vbatt <= gbcl->btm_vph_low_thresh) {
		/*relay the notification to charger ic driver*/
		bcl_config_vph_adc(gbcl, BCL_LOW_THRESHOLD_TYPE_MIN);
	} else if ((vbatt  > gbcl->btm_vph_low_thresh) &&
		(vbatt <= gbcl->btm_vph_high_thresh))
		bcl_config_vph_adc(gbcl, BCL_LOW_THRESHOLD_TYPE);
	else
		bcl_config_vph_adc(gbcl, BCL_HIGH_THRESHOLD_TYPE);
}
static int bcl_resume(struct device *dev)
{
	struct bcl_context *bcl = dev_get_drvdata(dev);
	int vbatt = 0;
	if (bcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE &&
		bcl->bcl_mode == BCL_DEVICE_ENABLED) {
		bcl->btm_mode = BCL_VPH_MONITOR_MODE;
		bcl_get_battery_voltage(&vbatt);
		if (vbatt <= gbcl->btm_vph_low_thresh) {
			/*relay the notification to charger ic driver*/
			bcl_config_vph_adc(gbcl, BCL_LOW_THRESHOLD_TYPE_MIN);
		} else if ((vbatt  > gbcl->btm_vph_low_thresh) &&
			(vbatt <= gbcl->btm_vph_high_thresh))
			bcl_config_vph_adc(gbcl, BCL_LOW_THRESHOLD_TYPE);
		else
			bcl_config_vph_adc(gbcl, BCL_HIGH_THRESHOLD_TYPE);
	}
	return 0;
}
static int bcl_resume(struct device *dev)
{
	struct bcl_context *bcl = dev_get_drvdata(dev);

	if (bcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE &&
		bcl->bcl_mode == BCL_DEVICE_ENABLED) {
		bcl->btm_mode = BCL_VPH_MONITOR_MODE;
		bcl_config_vph_adc(bcl, BCL_LOW_THRESHOLD_TYPE);
	}
	return 0;
}
/*
 * Set BCL mode
 */
static void bcl_mode_set(enum bcl_device_mode mode)
{

	int ret = 0;
	if (!gbcl)
		return;
	gbcl->bcl_mode = mode;
	if (BCL_DEVICE_DISABLED == mode) {
		vph_disable();
	} else {
		mutex_lock(&bcl_notify_mutex);
		gbcl->btm_mode = BCL_VPH_MONITOR_MODE;
		mutex_unlock(&bcl_notify_mutex);
		ret = bcl_config_vph_adc(gbcl, BCL_LOW_THRESHOLD_TYPE);
		if (ret) {
				pr_err("Vph config error. ret:%d\n", ret);
				return;
		}
	}
	return;
}
static void ibat_mode_set(enum bcl_device_mode mode)
{
	int ret = 0;

	if (mode == BCL_DEVICE_ENABLED) {
		gbcl->btm_mode = BCL_VPH_MONITOR_MODE;
		ret = bcl_config_vph_adc(gbcl, BCL_LOW_THRESHOLD_TYPE);
		if (ret) {
			pr_err("Vph config error. ret:%d\n", ret);
			gbcl->bcl_mode = BCL_DEVICE_DISABLED;
			gbcl->btm_mode = BCL_MONITOR_DISABLED;
			return;
		}
	} else {
		switch (gbcl->btm_mode) {
		case BCL_IBAT_MONITOR_MODE:
		case BCL_IBAT_HIGH_LOAD_MODE:
			ret = ibat_disable();
			if (ret)
				return;
			ret = vph_disable();
			if (ret)
				return;
			break;
		case BCL_VPH_MONITOR_MODE:
			ret = vph_disable();
			if (ret)
				return;
			break;
		case BCL_MONITOR_DISABLED:
		default:
			break;
		}
		gbcl->btm_mode = BCL_MONITOR_DISABLED;
	}

	return;
}