static int cn_set_property(struct power_supply *psy,
		  enum power_supply_property psp,
		  const union power_supply_propval *val)
{
	int ret;
	struct cn_chip *chip = container_of(psy, struct cn_chip, cn_psy);

	switch (psp) {
	case POWER_SUPPLY_PROP_VIRT_ENABLE_BMS:
		if (!val->intval)
			ret = cn_masked_write_base(chip, BMS_EN_CTL,
					BMS_EN_MASK, 0x00);
		else
			ret = cn_masked_write_base(chip, BMS_EN_CTL,
					BMS_EN_MASK, 0x80);


		if (ret) {
			chip->bms_enabled = 0;
			pr_err("fail to enable bms\n");
		} else {
			chip->bms_enabled = 1;
		}
		break;
	default:
		return -EINVAL;
	}

	return 0;
}
static int __devinit cn_probe(struct spmi_device *spmi)
{
	int rc;
	struct cn_chip *chip;
	struct device *dev = &spmi->dev;

	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
	if (unlikely(!chip)) {
		pr_err("cn_probe: out of memory space\n");
		return -ENOMEM;
	}
	dev_set_drvdata(dev, chip);

	if (chip == NULL) {
		pr_err("kzalloc() failed.\n");
		return -ENOMEM;
	}
	chip->iadc_base = IADC_BASE;
	chip->base = BMS_BASE;
	chip->r_sense_uohm = RSENSE_MICRO_OHM; /*                  */

	rc = spmi_cn_add_controller(chip, spmi);
	if (rc) {
		pr_info("error registering spmi resource %d\n", rc);
		goto error_read;
	}

	rc = set_cn_iadc_channel(chip);
	if (rc) {
		pr_err("Unable to get iadc selected channel = %d\n", rc);
		goto error_read;
	}

	chip->cn_psy.name		= "cn";
	chip->cn_psy.type		= POWER_SUPPLY_TYPE_BMS;
	chip->cn_psy.get_property	= cn_get_property;
	chip->cn_psy.set_property	= cn_set_property;
	chip->cn_psy.properties		= cn_props;
	chip->cn_psy.num_properties	= ARRAY_SIZE(cn_props);
	chip->cn_psy.property_is_writeable =
				cn_power_property_is_writeable;

	rc = power_supply_register(chip->dev, &chip->cn_psy);
	if (rc < 0) {
		pr_err("power_supply_register bms failed rc = %d\n", rc);
		goto unregister_dc;
	}
	/*                   */
	rc = cn_masked_write_base(chip, BMS_EN_CTL, BMS_EN_MASK, 0x80);
	if (rc)
		pr_err("Fail to enable BMS_EN_CTL!! rc=%d\n", rc);
	return 0;
unregister_dc:
	power_supply_unregister(&chip->cn_psy);
error_read:
	kfree(chip);
	return rc;
}
static int cn_suspend(struct device *dev)
{
	int rc;
	struct cn_chip *chip = dev_get_drvdata(dev);
	rc = cn_masked_write_base(chip, BMS_EN_CTL, BMS_EN_MASK, 0x00);
	if (rc)
		pr_err("Fail to disable BMS_EN_CTL!! rc=%d\n", rc);
	return rc;
}
static int cn_set_property(struct power_supply *psy,
		  enum power_supply_property psp,
		  const union power_supply_propval *val)
{
	int ret;
	struct cn_chip *chip = container_of(psy, struct cn_chip, cn_psy);

	switch (psp) {
	case POWER_SUPPLY_PROP_PRESENT:
		if (val->intval)
			ret = cn_masked_write_base(chip, BMS_EN_CTL,
					BMS_EN_MASK, 0x80);
		else
			ret = cn_masked_write_base(chip, BMS_EN_CTL,
					BMS_EN_MASK, 0x00);
		break;
	default:
		return -EINVAL;
	}

	return 0;
}
static int cn_masked_write_iadc(struct cn_chip *chip, u16 addr,
							u8 mask, u8 val)
{
	return cn_masked_write_base(chip, chip->iadc_base + addr, mask, val);
}