static ssize_t
mode_store(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{
	if (!gbcl) {
		pr_err("No gbcl pointer\n");
		return -EPERM;
	}
	if (!strncmp(buf, "enable", 6))
		bcl_mode_set(BCL_DEVICE_ENABLED);
	else if (!strncmp(buf, "disable", 7))
		bcl_mode_set(BCL_DEVICE_DISABLED);
	else
		return -EINVAL;
	return count;
}
static ssize_t
mode_store(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{
	if (!gbcl)
		return -EPERM;

	if (!strncmp(buf, "enabled", 7))
		bcl_mode_set(BCL_DEVICE_ENABLED);
	else if (!strncmp(buf, "disabled", 8))
		bcl_mode_set(BCL_DEVICE_DISABLED);
	else
		return -EINVAL;

	return count;
}
static ssize_t
mode_store(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{
	if (!gbcl)
		return -EPERM;

	if (!strcmp(buf, "enable")) {
		bcl_mode_set(BCL_DEVICE_ENABLED);
		bcl_update_online_mask();
		pr_info("bcl enabled\n");
	} else if (!strcmp(buf, "disable")) {
		bcl_mode_set(BCL_DEVICE_DISABLED);
		cpumask_clear(bcl_cpu_online_mask);
		pr_info("bcl disabled\n");
	} else {
		return -EINVAL;
	}

	return count;
}
static int bcl_probe(struct platform_device *pdev)
{
	struct bcl_context *bcl = NULL;
	int ret = 0;
	enum bcl_device_mode bcl_mode = BCL_DEVICE_DISABLED;

	bcl = devm_kzalloc(&pdev->dev, sizeof(struct bcl_context), GFP_KERNEL);
	if (!bcl) {
		pr_err("Cannot allocate bcl_context\n");
		return -ENOMEM;
	}

	/* For BCL */
	/* Init default BCL params */
	if (of_property_read_bool(pdev->dev.of_node, "qcom,bcl-enable"))
		bcl_mode = BCL_DEVICE_ENABLED;
	else
		bcl_mode = BCL_DEVICE_DISABLED;
	bcl->bcl_mode = BCL_DEVICE_DISABLED;
	bcl->dev = &pdev->dev;
	bcl->bcl_monitor_type = BCL_IAVAIL_MONITOR_TYPE;
	bcl->bcl_threshold_mode[BCL_LOW_THRESHOLD_TYPE] =
					BCL_IAVAIL_THRESHOLD_DISABLED;
	bcl->bcl_threshold_mode[BCL_HIGH_THRESHOLD_TYPE] =
					BCL_IAVAIL_THRESHOLD_DISABLED;
	bcl->bcl_threshold_value_ma[BCL_LOW_THRESHOLD_TYPE] = 0;
	bcl->bcl_threshold_value_ma[BCL_HIGH_THRESHOLD_TYPE] = 0;
	bcl->bcl_vbat_min = BATTERY_VOLTAGE_MIN;
	snprintf(bcl->bcl_type, BCL_NAME_LENGTH, "%s",
			bcl_type[BCL_IAVAIL_MONITOR_TYPE]);
	bcl->bcl_poll_interval_msec = BCL_POLL_INTERVAL;

	if (of_property_read_bool(pdev->dev.of_node, "qcom,bcl-no-bms"))
		bcl->bcl_no_bms = true;
	else
		bcl->bcl_no_bms = false;

	bcl_frequency_mask = get_mask_from_core_handle(pdev,
					 "qcom,bcl-freq-control-list");
	bcl_hotplug_mask = get_mask_from_core_handle(pdev,
					 "qcom,bcl-hotplug-list");
	bcl_soc_hotplug_mask = get_mask_from_core_handle(pdev,
					 "qcom,bcl-soc-hotplug-list");

	if (!bcl_hotplug_mask && !bcl_soc_hotplug_mask)
		bcl_hotplug_enabled = false;
	else
		bcl_hotplug_enabled = true;

	if (of_property_read_bool(pdev->dev.of_node,
		"qcom,bcl-framework-interface"))
		ret = probe_bcl_periph_prop(bcl);
	else
		ret = probe_btm_properties(bcl);

	if (ret == -EPROBE_DEFER)
		return ret;

	ret = create_bcl_sysfs(bcl);
	if (ret < 0) {
		pr_err("Cannot create bcl sysfs\n");
		return ret;
	}
	cpumask_clear(bcl_cpu_online_mask);
	bcl_psy.name = bcl_psy_name;
	bcl_psy.type = POWER_SUPPLY_TYPE_BMS;
	bcl_psy.get_property     = bcl_battery_get_property;
	bcl_psy.set_property     = bcl_battery_set_property;
	bcl_psy.num_properties = 0;
#ifndef CONFIG_LGE_PM
	bcl_psy.external_power_changed = power_supply_callback;
#endif

	gbcl = bcl;
	platform_set_drvdata(pdev, bcl);
	INIT_DEFERRABLE_WORK(&bcl->bcl_iavail_work, bcl_iavail_work);
	INIT_WORK(&bcl_hotplug_work, bcl_handle_hotplug);
	if (bcl_hotplug_enabled)
		register_cpu_notifier(&bcl_cpu_notifier);
	if (bcl_mode == BCL_DEVICE_ENABLED)
		bcl_mode_set(bcl_mode);

	return 0;
}
static int bcl_probe(struct platform_device *pdev)
{
	struct bcl_context *bcl = NULL;
	int ret = 0, i = 0, cpu = 0;
	enum bcl_device_mode bcl_mode = BCL_DEVICE_DISABLED;
	struct device_node *core_phandle = NULL;

	bcl = devm_kzalloc(&pdev->dev, sizeof(struct bcl_context), GFP_KERNEL);
	if (!bcl) {
		pr_err("Cannot allocate bcl_context\n");
		return -ENOMEM;
	}

	/* For BCL */
	/* Init default BCL params */
	if (of_property_read_bool(pdev->dev.of_node, "qcom,bcl-enable"))
		bcl_mode = BCL_DEVICE_ENABLED;
	else
		bcl_mode = BCL_DEVICE_DISABLED;
	bcl->dev = &pdev->dev;
	bcl->bcl_monitor_type = BCL_IBAT_MONITOR_TYPE;
	bcl->bcl_threshold_mode[BCL_LOW_THRESHOLD_TYPE] =
					BCL_IAVAIL_THRESHOLD_DISABLED;
	bcl->bcl_threshold_mode[BCL_HIGH_THRESHOLD_TYPE] =
					BCL_IAVAIL_THRESHOLD_DISABLED;
	bcl->bcl_threshold_value_ma[BCL_LOW_THRESHOLD_TYPE] = 0;
	bcl->bcl_threshold_value_ma[BCL_HIGH_THRESHOLD_TYPE] = 0;
	bcl->bcl_vbat_min = BATTERY_VOLTAGE_MIN;
	snprintf(bcl->bcl_type, BCL_NAME_LENGTH, "%s",
			bcl_type[BCL_IBAT_MONITOR_TYPE]);
	bcl->bcl_poll_interval_msec = BCL_POLL_INTERVAL;

	if (of_property_read_bool(pdev->dev.of_node, "qcom,bcl-no-bms"))
		bcl->bcl_no_bms = true;
	else
		bcl->bcl_no_bms = false;

	core_phandle = of_parse_phandle(pdev->dev.of_node,
			"qcom,bcl-hotplug-list", i++);
	while (core_phandle) {
		bcl_hotplug_enabled = true;
		for_each_possible_cpu(cpu) {
			if (of_get_cpu_node(cpu, NULL) == core_phandle)
				bcl_hotplug_mask |= BIT(cpu);
		}
		core_phandle = of_parse_phandle(pdev->dev.of_node,
			"qcom,bcl-hotplug-list", i++);
	}
	if (!bcl_hotplug_mask)
		bcl_hotplug_enabled = false;

	ret = probe_btm_properties(bcl);

	if (ret == -EPROBE_DEFER)
		return ret;

	ret = create_bcl_sysfs(bcl);
	if (ret < 0) {
		pr_err("Cannot create bcl sysfs\n");
		return ret;
	}

	gbcl = bcl;
	platform_set_drvdata(pdev, bcl);
	bcl->battery_monitor_wq = alloc_workqueue(
				"battery_monitor", WQ_MEM_RECLAIM, 1);
	if (!bcl->battery_monitor_wq) {
			pr_err("Requesting  battery_monitor wq failed\n");
			return 0;
	}
	INIT_WORK(&bcl->battery_monitor_work, battery_monitor_work);
	if (bcl_hotplug_enabled)
		register_cpu_notifier(&bcl_cpu_notifier);
	if (bcl_mode == BCL_DEVICE_ENABLED)
		bcl_mode_set(bcl_mode);

	return 0;
}