static int ncp6335d_get_voltage(struct regulator_dev *rdev)
{
	unsigned int val;
	int rc;
	struct ncp6335d_info *dd = rdev_get_drvdata(rdev);

	mutex_lock(&dd->ncp_mutex);
	if (dd->is_suspend) {
		rc = dd->curr_voltage;
		dev_dbg(dd->dev, "Get voltage after suspend, (%d)\n", rc);
		goto out;
	}

	rc = ncp6335x_read(dd, dd->vsel_reg, &val);
	if (rc) {
		dev_err(dd->dev, "Unable to get volatge rc(%d)", rc);
		return rc;
	}
	dd->curr_voltage = ((val & NCP6335D_VOUT_SEL_MASK) * dd->step_size) +
				dd->min_voltage;

	rc = dd->curr_voltage;

	dump_registers(dd, dd->vsel_reg, __func__);

out:
	mutex_unlock(&dd->ncp_mutex);
	return rc;
}
static void dump_registers(struct ncp6335d_info *dd,
                           unsigned int reg, const char *func)
{
    unsigned int val = 0;

    ncp6335x_read(dd, reg, &val);
    dev_dbg(dd->dev, "%s: NCP6335D: Reg = %x, Val = %x\n", func, reg, val);
}
static void dump_registers(struct ncp6335d_info *dd,
			unsigned int reg, const char *func)
{
	unsigned int val = 0;

	ncp6335x_read(dd, reg, &val);
	dev_dbg(dd->dev, "%s: NCP6335D: Reg = %x, Val = %x\n", func, reg, val);
#ifdef CONFIG_MACH_YULONG
	if (reg == 0x13 && val != 0x19) { // add by wangshujun 2014.12.17,
		// some ncp chip reg 0x13 default value is not 0x19
		// it will lead to system reboot,so we force modify it to 19h
		pr_err("yulong:NCP6335D reg 0x%x val origin is 0x%x\n", reg, val);
		val = 0x19;
		ncp6335x_write(dd, reg, val);
		ncp6335x_read(dd, reg, &val);
		pr_err("yulong:NCP6335D reg 0x%x modify to 0x%x\n", reg, val);
	}
#endif
}
static int ncp6335d_restore_working_reg(struct device_node *node,
                                        struct ncp6335d_info *dd)
{
    int ret;
    unsigned int val1;
    unsigned int val2;
    unsigned int val3;

    /* Restore register from back up register */
    ret = ncp6335x_read(dd, dd->vsel_backup_reg, &val1);
    dev_err(dd->dev, "%s: khl NCP6335D: Reg_back1= %x, Val = %x\n", __func__, dd->vsel_backup_reg, val1);

    if (ret < 0) {
        dev_err(dd->dev, "Failed to get backup data from reg %d, ret = %d\n",
                dd->vsel_backup_reg, ret);
        return ret;
    }
    ret = ncp6335x_read(dd, dd->vsel_reg, &val2);
    dev_err(dd->dev, "%s: khl NCP6335D: Reg_back2= %x, Val = %x\n", __func__, dd->vsel_reg, val2);

#if 0
    ret = ncp6335x_update_bits(dd, dd->vsel_reg,
                               NCP6335D_VOUT_SEL_MASK, val);
#else
    ret = ncp6335x_update_bits(dd, dd->vsel_reg,
                               0xFF, (val1 |0x80));
    ret = ncp6335x_read(dd, dd->vsel_reg, &val3);

    dev_err(dd->dev, "%s: khl NCP6335D: Reg_back3= %x, Val = %x\n", __func__, dd->vsel_reg, val3);

#endif

    if (ret < 0) {
        dev_err(dd->dev, "Failed to update working reg %d, ret = %d\n",
                dd->vsel_reg,  ret);
        return ret;
    }


    return ret;
}
static int get_reg(void *data, u64 *val)
{
	struct ncp6335d_info *dd = data;
	int rc;
	unsigned int temp = 0;

	rc = ncp6335x_read(dd, dd->peek_poke_address, &temp);
	if (rc < 0)
		dev_err(dd->dev, "Couldn't read reg %x rc = %d\n",
				dd->peek_poke_address, rc);
	else
		*val = temp;

	return rc;
}
static int ncp6335d_get_voltage(struct regulator_dev *rdev)
{
    unsigned int val;
    int rc;
    struct ncp6335d_info *dd = rdev_get_drvdata(rdev);

    rc = ncp6335x_read(dd, dd->vsel_reg, &val);
    if (rc) {
        dev_err(dd->dev, "Unable to get volatge rc(%d)", rc);
        return rc;
    }
    dd->curr_voltage = ((val & NCP6335D_VOUT_SEL_MASK) * dd->step_size) +
                       dd->min_voltage;

    dump_registers(dd, dd->vsel_reg, __func__);

    return dd->curr_voltage;
}
static unsigned int ncp6335d_get_mode(struct regulator_dev *rdev)
{
	unsigned int val;
	int rc;
	struct ncp6335d_info *dd = rdev_get_drvdata(rdev);

	rc = ncp6335x_read(dd, REG_NCP6335D_COMMAND, &val);
	if (rc) {
		dev_err(dd->dev, "Unable to get regulator mode rc(%d)\n", rc);
		return rc;
	}

	dump_registers(dd, REG_NCP6335D_COMMAND, __func__);

	if (val & dd->mode_bit)
		return REGULATOR_MODE_FAST;

	return REGULATOR_MODE_NORMAL;
}
static int ncp6335d_restore_working_reg(struct device_node *node,
					struct ncp6335d_info *dd)
{
	int ret;
	unsigned int val;

	/* Restore register from back up register */
	ret = ncp6335x_read(dd, dd->vsel_backup_reg, &val);
	if (ret < 0) {
		dev_err(dd->dev, "Failed to get backup data from reg %d, ret = %d\n",
			dd->vsel_backup_reg, ret);
		return ret;
	}

	ret = ncp6335x_update_bits(dd, dd->vsel_reg,
					NCP6335D_VOUT_SEL_MASK, val);
	if (ret < 0) {
		dev_err(dd->dev, "Failed to update working reg %d, ret = %d\n",
			dd->vsel_reg,  ret);
		return ret;
	}

	return ret;
}
static int ncp6335d_regulator_probe(struct i2c_client *client,
					const struct i2c_device_id *id)
{
	int rc;
	unsigned int val = 0;
	struct ncp6335d_info *dd;
	const struct ncp6335d_platform_data *pdata;
	struct regulator_config config = { };
#ifdef CONFIG_MACH_YULONG
	/* the i2c address of ncp6335d is somehow changed, trying to poll if failed.
	   [email protected]  2014-12-29*/
	int i2c_addr_backup[3] = { 0x18, 0x10, 0x14};
	int i_a = 0;

	pr_err("%s:ncp addr is 0x%2x\n",__func__,client->addr);
#endif

	if (client->dev.of_node)
		pdata = ncp6335d_get_of_platform_data(client);
	else
		pdata = client->dev.platform_data;

	if (!pdata) {
		dev_err(&client->dev, "Platform data not specified\n");
		return -EINVAL;
	}

	dd = devm_kzalloc(&client->dev, sizeof(*dd), GFP_KERNEL);
	if (!dd) {
		dev_err(&client->dev, "Unable to allocate memory\n");
		return -ENOMEM;
	}

	if (client->dev.of_node) {
		rc = ncp6335d_parse_dt(client, dd);
		if (rc)
			return rc;
	} else {
		dd->step_size	= NCP6335D_STEP_VOLTAGE_UV;
		dd->min_voltage	= NCP6335D_MIN_VOLTAGE_UV;
		dd->min_slew_ns	= NCP6335D_MIN_SLEW_NS;
		dd->max_slew_ns	= NCP6335D_MAX_SLEW_NS;
	}

	dd->regmap = devm_regmap_init_i2c(client, &ncp6335d_regmap_config);
	if (IS_ERR(dd->regmap)) {
		dev_err(&client->dev, "Error allocating regmap\n");
		return PTR_ERR(dd->regmap);
	}

#ifdef CONFIG_MACH_YULONG
AGAIN:
#endif
	rc = ncp6335x_read(dd, REG_NCP6335D_PID, &val);
	if (rc) {
		dev_err(&client->dev, "Unable to identify NCP6335D, rc(%d)\n",
									rc);

#ifdef CONFIG_MACH_YULONG
		dev_err(&client->dev, "ncp addr is 0x%2x, force addr as 0x%2x and retry\n",
				client->addr, i2c_addr_backup[i_a]);

		while (i_a < 3) {
			client->addr = i2c_addr_backup[i_a];
			i_a++;
			goto AGAIN;
		}
#endif

		return rc;
	}
	dev_info(&client->dev, "Detected Regulator NCP6335D PID = %d\n", val);

	dd->init_data = pdata->init_data;
	dd->dev = &client->dev;
	i2c_set_clientdata(client, dd);

	mutex_init(&dd->ncp_mutex);

	rc = ncp6335d_init(client, dd, pdata);
	if (rc) {
		dev_err(&client->dev, "Unable to intialize the regulator\n");
		return -EINVAL;
	}

	config.dev = &client->dev;
	config.init_data = dd->init_data;
	config.regmap = dd->regmap;
	config.driver_data = dd;
	config.of_node = client->dev.of_node;

	dd->regulator = regulator_register(&rdesc, &config);

	if (IS_ERR(dd->regulator)) {
		dev_err(&client->dev, "Unable to register regulator rc(%ld)",
						PTR_ERR(dd->regulator));

		return PTR_ERR(dd->regulator);
	}

	dd->debug_root = debugfs_create_dir("ncp6335x", NULL);
	if (!dd->debug_root)
		dev_err(&client->dev, "Couldn't create debug dir\n");

	if (dd->debug_root) {
		struct dentry *ent;

		ent = debugfs_create_x32("address", S_IFREG | S_IWUSR | S_IRUGO,
					  dd->debug_root,
					  &(dd->peek_poke_address));
		if (!ent)
			dev_err(&client->dev, "Couldn't create address debug file rc = %d\n",
									rc);

		ent = debugfs_create_file("data", S_IFREG | S_IWUSR | S_IRUGO,
					  dd->debug_root, dd,
					  &poke_poke_debug_ops);
		if (!ent)
			dev_err(&client->dev, "Couldn't create data debug file rc = %d\n",
									rc);
	}

	return 0;
}
static int ncp6335d_init(struct i2c_client *client, struct ncp6335d_info *dd,
			const struct ncp6335d_platform_data *pdata)
{
	int rc;
	unsigned int val;

	switch (pdata->default_vsel) {
	case NCP6335D_VSEL0:
		dd->vsel_reg = REG_NCP6335D_PROGVSEL0;
		dd->vsel_backup_reg = REG_NCP6335D_PROGVSEL1;
		dd->mode_bit = NCP6335D_PWM_MODE0;
	break;
	case NCP6335D_VSEL1:
		dd->vsel_reg = REG_NCP6335D_PROGVSEL1;
		dd->vsel_backup_reg = REG_NCP6335D_PROGVSEL0;
		dd->mode_bit = NCP6335D_PWM_MODE1;
	break;
	default:
		dev_err(dd->dev, "Invalid VSEL ID %d\n", pdata->default_vsel);
		return -EINVAL;
	}

	if (of_property_read_bool(client->dev.of_node, "onnn,restore-reg")) {
		rc = ncp6335d_restore_working_reg(client->dev.of_node, dd);
		if (rc)
			return rc;
	}

	rc = ncp6335d_parse_gpio(client->dev.of_node, dd);
	if (rc)
		return rc;

	/* get the current programmed voltage */
	rc = ncp6335x_read(dd, dd->vsel_reg, &val);
	if (rc) {
		dev_err(dd->dev, "Unable to get volatge rc(%d)", rc);
		return rc;
	}
	dd->curr_voltage = ((val & NCP6335D_VOUT_SEL_MASK) *
				dd->step_size) + dd->min_voltage;

	/* set discharge */
	rc = ncp6335x_update_bits(dd, REG_NCP6335D_PGOOD,
					NCP6335D_PGOOD_DISCHG,
					(pdata->discharge_enable ?
					NCP6335D_PGOOD_DISCHG : 0));
	if (rc) {
		dev_err(dd->dev, "Unable to set Active Discharge rc(%d)\n", rc);
		return -EINVAL;
	}

	/* set slew rate */
	if (pdata->slew_rate_ns < dd->min_slew_ns ||
			pdata->slew_rate_ns > dd->max_slew_ns) {
		dev_err(dd->dev, "Invalid slew rate %d\n", pdata->slew_rate_ns);
		return -EINVAL;
	}

	dd->slew_rate = pdata->slew_rate_ns;
	val = DIV_ROUND_UP(pdata->slew_rate_ns, dd->min_slew_ns);
	val = ilog2(val);

	rc = ncp6335x_update_bits(dd, REG_NCP6335D_TIMING,
			NCP6335D_SLEW_MASK, val << NCP6335D_SLEW_SHIFT);
	if (rc)
		dev_err(dd->dev, "Unable to set slew rate rc(%d)\n", rc);

	/* Set Sleep mode bit */
	rc = ncp6335x_update_bits(dd, REG_NCP6335D_COMMAND,
				NCP6335D_SLEEP_MODE, pdata->sleep_enable ?
						NCP6335D_SLEEP_MODE : 0);
	if (rc)
		dev_err(dd->dev, "Unable to set sleep mode (%d)\n", rc);

	dump_registers(dd, REG_NCP6335D_COMMAND, __func__);
	dump_registers(dd, REG_NCP6335D_PROGVSEL0, __func__);
	dump_registers(dd, REG_NCP6335D_TIMING, __func__);
	dump_registers(dd, REG_NCP6335D_PGOOD, __func__);

	return rc;
}
static int ncp6335d_regulator_probe(struct i2c_client *client,
                                    const struct i2c_device_id *id)
{
    int rc;
    unsigned int val = 0;
    struct ncp6335d_info *dd;
    const struct ncp6335d_platform_data *pdata;
    struct regulator_config config = { };

    if (client->dev.of_node)
        pdata = ncp6335d_get_of_platform_data(client);
    else
        pdata = client->dev.platform_data;

    if (!pdata) {
        dev_err(&client->dev, "Platform data not specified\n");
        return -EINVAL;
    }

    dd = devm_kzalloc(&client->dev, sizeof(*dd), GFP_KERNEL);
    if (!dd) {
        dev_err(&client->dev, "Unable to allocate memory\n");
        return -ENOMEM;
    }

    if (client->dev.of_node) {
        rc = ncp6335d_parse_dt(client, dd);
        if (rc)
            return rc;
    } else {
        dd->step_size	= NCP6335D_STEP_VOLTAGE_UV;
        dd->min_voltage	= NCP6335D_MIN_VOLTAGE_UV;
        dd->min_slew_ns	= NCP6335D_MIN_SLEW_NS;
        dd->max_slew_ns	= NCP6335D_MAX_SLEW_NS;
    }

    dd->regmap = devm_regmap_init_i2c(client, &ncp6335d_regmap_config);
    if (IS_ERR(dd->regmap)) {
        dev_err(&client->dev, "Error allocating regmap\n");
        return PTR_ERR(dd->regmap);
    }

    rc = ncp6335x_read(dd, REG_NCP6335D_PID, &val);
    if (rc) {
        dev_err(&client->dev, "Unable to identify NCP6335D, rc(%d)\n",
                rc);
        return rc;
    }
    dev_info(&client->dev, "Detected Regulator NCP6335D PID = %d\n", val);

    dd->init_data = pdata->init_data;
    dd->dev = &client->dev;
    i2c_set_clientdata(client, dd);

    rc = ncp6335d_init(client, dd, pdata);
    if (rc) {
        dev_err(&client->dev, "Unable to intialize the regulator\n");
        return -EINVAL;
    }

    config.dev = &client->dev;
    config.init_data = dd->init_data;
    config.regmap = dd->regmap;
    config.driver_data = dd;
    config.of_node = client->dev.of_node;

    dd->regulator = regulator_register(&rdesc, &config);

    if (IS_ERR(dd->regulator)) {
        dev_err(&client->dev, "Unable to register regulator rc(%ld)",
                PTR_ERR(dd->regulator));

        return PTR_ERR(dd->regulator);
    }

    dd->debug_root = debugfs_create_dir("ncp6335x", NULL);
    if (!dd->debug_root)
        dev_err(&client->dev, "Couldn't create debug dir\n");

    if (dd->debug_root) {
        struct dentry *ent;

        ent = debugfs_create_x32("address", S_IFREG | S_IWUSR | S_IRUGO,
                                 dd->debug_root,
                                 &(dd->peek_poke_address));
        if (!ent)
            dev_err(&client->dev, "Couldn't create address debug file rc = %d\n",
                    rc);

        ent = debugfs_create_file("data", S_IFREG | S_IWUSR | S_IRUGO,
                                  dd->debug_root, dd,
                                  &poke_poke_debug_ops);
        if (!ent)
            dev_err(&client->dev, "Couldn't create data debug file rc = %d\n",
                    rc);
    }

    return 0;
}