static int smb347_read_status(struct smb_charger_callbacks *ptr)
{
	struct smb347_chg_data *chg = container_of(ptr,
			struct smb347_chg_data, callbacks);

	u8 res = 0;
	u8 reg_c;
	int ret;

	ret = smb347_i2c_read(chg->client, SMB347_STATUS_C, &reg_c);
	if (ret < 0) {
		dev_err(&chg->client->dev, "%s: I2C Read fail addr : 0x%x\n",
			__func__, SMB347_STATUS_C);
		msleep(50);
		smb347_i2c_read(chg->client, SMB347_STATUS_C, &reg_c);
	}

	dev_info(&chg->client->dev,
		"addr : 0x%x, data : 0x%x\n", SMB347_STATUS_C, reg_c);

	if (reg_c & SMB347_CHARGER_ERROR)
		res = CHARGER_STATUS_CHARGERERR;
	else if (reg_c & SMB347_CHARGING_STATUS)
		res = CHARGER_STATUS_FULL;

	return res;
}
static int smb347_get_charging_health(struct i2c_client *client)
{
	int health = POWER_SUPPLY_HEALTH_GOOD;
	u8 data_a = 0;
	u8 data_b = 0;
	u8 data_c = 0;
	u8 data_d = 0;
	u8 data_e = 0;

	smb347_i2c_read(client, SMB347_STATUS_A, &data_a);
	dev_info(&client->dev,
		"%s : charger status A(0x%02x)\n", __func__, data_a);
	smb347_i2c_read(client, SMB347_STATUS_B, &data_b);
	dev_info(&client->dev,
		"%s : charger status B(0x%02x)\n", __func__, data_b);
	smb347_i2c_read(client, SMB347_STATUS_C, &data_c);
	dev_info(&client->dev,
		"%s : charger status C(0x%02x)\n", __func__, data_c);
	smb347_i2c_read(client, SMB347_STATUS_D, &data_d);
	dev_info(&client->dev,
		"%s : charger status D(0x%02x)\n", __func__, data_d);
	smb347_i2c_read(client, SMB347_STATUS_E, &data_e);
	dev_info(&client->dev,
		"%s : charger status E(0x%02x)\n", __func__, data_e);

	/* Is enabled ? */
	/*
	if (data_c & 0x01) {
		if (!(data_a & 0x02))	// Input current is NOT OK //
			health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
	}
	*/
	return (int)health;
}
static int smb347_get_charging_status(struct i2c_client *client)
{
	int status = POWER_SUPPLY_STATUS_UNKNOWN;
	u8 data_a = 0;
	u8 data_b = 0;
	u8 data_c = 0;
	u8 data_d = 0;
	u8 data_e = 0;

	smb347_i2c_read(client, SMB347_STATUS_A, &data_a);
	dev_info(&client->dev,
		"%s : charger status A(0x%02x)\n", __func__, data_a);
	smb347_i2c_read(client, SMB347_STATUS_B, &data_b);
	dev_info(&client->dev,
		"%s : charger status B(0x%02x)\n", __func__, data_b);
	smb347_i2c_read(client, SMB347_STATUS_C, &data_c);
	dev_info(&client->dev,
		"%s : charger status C(0x%02x)\n", __func__, data_c);
	smb347_i2c_read(client, SMB347_STATUS_D, &data_d);
	dev_info(&client->dev,
		"%s : charger status D(0x%02x)\n", __func__, data_d);
	smb347_i2c_read(client, SMB347_STATUS_E, &data_e);
	dev_info(&client->dev,
		"%s : charger status E(0x%02x)\n", __func__, data_e);

	/* At least one charge cycle terminated,
	 * Charge current < Termination Current
	 */
	if ((data_c & 0x20) == 0x20) {
		/* top-off by full charging */
		status = POWER_SUPPLY_STATUS_FULL;
		goto charging_status_end;
	}

	/* Is enabled ? */
	if (data_c & 0x01) {
		/* check for 0x06 : no charging (0b00) */
		/* not charging */
		if (!(data_c & 0x06)) {
			status = POWER_SUPPLY_STATUS_NOT_CHARGING;
			goto charging_status_end;
		} else {
			status = POWER_SUPPLY_STATUS_CHARGING;
			goto charging_status_end;
		}
	} else
		status = POWER_SUPPLY_STATUS_DISCHARGING;
charging_status_end:
	return (int)status;
}
static void smb347_test_read(struct i2c_client *client)
{
	u8 data = 0;
	u32 addr = 0;
	for (addr = 0; addr <= 0x0f; addr++) {
		smb347_i2c_read(client, addr, &data);
		dev_dbg(&client->dev,
			"smb347 addr : 0x%02x data : 0x%02x\n", addr, data);
	}
	for (addr = 0x30; addr <= 0x3f; addr++) {
		smb347_i2c_read(client, addr, &data);
		dev_dbg(&client->dev,
			"smb347 addr : 0x%02x data : 0x%02x\n", addr, data);
	}
}
static void smb347_read_regs(struct i2c_client *client, char *str)
{
	u8 data = 0;
	u32 addr = 0;

	for (addr = 0; addr <= 0x0f; addr++) {
		smb347_i2c_read(client, addr, &data);
		sprintf(str+strlen(str), "0x%x, ", data);
	}

	/* "#" considered as new line in application */
	sprintf(str+strlen(str), "#");

	for (addr = 0x30; addr <= 0x3f; addr++) {
		smb347_i2c_read(client, addr, &data);
		sprintf(str+strlen(str), "0x%x, ", data);
	}
}
static void smb347_test_read(struct smb347_chg_data *chg)
{
	u8 data = 0;
	u32 addr = 0;
	pr_info("%s\n", __func__);

	for (addr = 0; addr <= 0x0E; addr++) {
		smb347_i2c_read(chg->client, addr, &data);
		dev_info(&chg->client->dev,
			"smb347 addr : 0x%02x data : 0x%02x\n",	addr, data);
	}

	for (addr = 0x30; addr <= 0x3F; addr++) {
		smb347_i2c_read(chg->client, addr, &data);
		dev_info(&chg->client->dev,
			"smb347 addr : 0x%02x data : 0x%02x\n",	addr, data);
	}
}
static void smb347_allow_volatile_writes(struct i2c_client *client)
{
	int val, reg;
	u8 data;
	reg = SMB347_COMMAND_A;
	val = smb347_i2c_read(client, reg, &data);
	if ((val >= 0) && !(data & 0x80)) {
		dev_dbg(&client->dev,
			"%s : reg(0x%02x): 0x%02x", __func__, reg, data);
		data |= (0x1 << 7);
		if (smb347_i2c_write(client, reg, &data) < 0)
			dev_err(&client->dev, "%s : error!\n", __func__);
		val = smb347_i2c_read(client, reg, &data);
		if (val >= 0) {
			data = (u8) data;
			dev_dbg(&client->dev, " => 0x%02x\n", data);
		}
	}
}
static void smb347_set_charging_current(
		struct i2c_client *client, int charging_current)
{
	struct sec_charger_info *charger = i2c_get_clientdata(client);
	u8 data;

	smb347_i2c_read(client, SMB347_CHARGE_CURRENT, &data);
	data &= 0xe0;
	data |= smb347_get_fast_charging_current_data(charging_current);
	smb347_set_command(client, SMB347_CHARGE_CURRENT, data);
}
static void smb347_set_command(struct i2c_client *client,
				int reg, int datum)
{
	int val;
	u8 data = 0;
	val = smb347_i2c_read(client, reg, &data);
	if (val >= 0) {
		dev_dbg(&client->dev, "%s : reg(0x%02x): 0x%02x",
			__func__, reg, data);
		if (data != datum) {
			data = datum;
			if (smb347_i2c_write(client, reg, &data) < 0)
				dev_err(&client->dev,
					"%s : error!\n", __func__);
			val = smb347_i2c_read(client, reg, &data);
			if (val >= 0)
				dev_dbg(&client->dev, " => 0x%02x\n", data);
		}
	}
}
static void smb347_test_read(void)
{
	struct smb347_chg_data *chg = smb347_chg;
	u8 data = 0;
	u32 addr = 0;
	pr_info("%s\n", __func__);

	/* Only for P4C rev0.2, Check vbus for opeartion charger */
	if (!smb347_check_powersource(chg))
		return;

	for (addr = 0; addr <= 0x0E; addr++) {
		smb347_i2c_read(chg->client, addr, &data);
		pr_info("smb347 addr : 0x%02x data : 0x%02x\n", addr, data);
	}

	for (addr = 0x30; addr <= 0x3F; addr++) {
		smb347_i2c_read(chg->client, addr, &data);
		pr_info("smb347 addr : 0x%02x data : 0x%02x\n", addr, data);
	}
}
static int smb347_get_charger_is_full(void)
{
	struct smb347_chg_data *chg = smb347_chg;
	int status = POWER_SUPPLY_STATUS_UNKNOWN;
	u8 data = 0;

	smb347_i2c_read(chg->client, SMB347_STATUS_C, &data);
	pr_info("%s : 0x%xh(0x%02x)\n", __func__, SMB347_STATUS_C, data);

	if (data & SMB347_CHARGER_ERROR)
		status = POWER_SUPPLY_STATUS_DISCHARGING;
	else if (data & SMB347_CHARGING_STATUS)
		status = POWER_SUPPLY_STATUS_FULL;

	return status;
}
ssize_t sec_hal_chg_store_attrs(struct device *dev,
				const ptrdiff_t offset,
				const char *buf, size_t count)
{
	struct power_supply *psy = dev_get_drvdata(dev);
	struct sec_charger_info *chg =
		container_of(psy, struct sec_charger_info, psy_chg);
	int ret = 0;
	int x = 0;
	u8 data = 0;

	switch (offset) {
	case CHG_REG:
		if (sscanf(buf, "%x\n", &x) == 1) {
			chg->reg_addr = x;
			smb347_i2c_read(chg->client,
				chg->reg_addr, &data);
			chg->reg_data = data;
			dev_dbg(dev, "%s: (read) addr = 0x%x, data = 0x%x\n",
				__func__, chg->reg_addr, chg->reg_data);
			ret = count;
		}
		break;
	case CHG_DATA:
		if (sscanf(buf, "%x\n", &x) == 1) {
			data = (u8)x;
			dev_dbg(dev, "%s: (write) addr = 0x%x, data = 0x%x\n",
				__func__, chg->reg_addr, data);
			smb347_i2c_write(chg->client,
				chg->reg_addr, &data);
			ret = count;
		}
		break;
	default:
		ret = -EINVAL;
		break;
	}

	return ret;
}
int smb347_get_charging_current(void)
{
	struct smb347_chg_data *chg = smb347_chg;
	u8 data = 0;
	int get_current = 0;

	smb347_i2c_read(chg->client, SMB347_CHARGE_CURRENT, &data);
	switch (data >> 5) {
	case 0:
		get_current = 700;
		break;
	case 1:
		get_current = 900;
		break;
	case 2:
		get_current = 1200;
		break;
	case 3:
		get_current = 1500;
		break;
	case 4:
		get_current = 1800;
		break;
	case 5:
		get_current = 2000;
		break;
	case 6:
		get_current = 2200;
		break;
	case 7:
		get_current = 2500;
		break;
	default:
		get_current = 700;
		break;
	}
	pr_debug("%s: Get charging current as %dmA.\n", __func__, get_current);
	return get_current;
}
static int smb347_get_charging_state(void)
{
	struct smb347_chg_data *chg = smb347_chg;
	int status = POWER_SUPPLY_STATUS_UNKNOWN;
	u8 data = 0;

	smb347_i2c_read(chg->client, SMB347_STATUS_C, &data);
	pr_info("%s : 0x%xh(0x%02x)\n", __func__, SMB347_STATUS_C, data);

	if (data & SMB347_CHARGING_ENABLE)
		status = POWER_SUPPLY_STATUS_CHARGING;
	else {
		/* if error bit check, ignore the status of charger-ic */
		if (data & SMB347_CHARGER_ERROR)
			status = POWER_SUPPLY_STATUS_DISCHARGING;
		/* At least one charge cycle terminated */
		/*Charge current < Termination Current */
		else if (data & SMB347_CHARGING_STATUS)
			status = POWER_SUPPLY_STATUS_FULL;
	}

	return status;
}
bool sec_hal_chg_get_property(struct i2c_client *client,
			      enum power_supply_property psp,
			      union power_supply_propval *val)
{
	struct sec_charger_info *charger = i2c_get_clientdata(client);
	u8 data;
	switch (psp) {
	case POWER_SUPPLY_PROP_STATUS:
		val->intval = smb347_get_charging_status(client);
		break;

	case POWER_SUPPLY_PROP_CHARGE_TYPE:
		if (charger->is_charging)
			val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
		else
			val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
		break;

	case POWER_SUPPLY_PROP_HEALTH:
		val->intval = smb347_get_charging_health(client);
		break;
	/* calculated input current limit value */
	case POWER_SUPPLY_PROP_CURRENT_NOW:
	case POWER_SUPPLY_PROP_CURRENT_AVG:	/* charging current */
		if (charger->charging_current) {
			smb347_i2c_read(client, SMB347_STATUS_B, &data);
			if (data & 0x20)
				switch (data & 0x18) {
				case 0:
					val->intval = 100;
					break;
				case 1:
					val->intval = 150;
					break;
				case 2:
					val->intval = 200;
					break;
				case 3:
					val->intval = 250;
					break;
				}
			else
				switch (data & 0x07) {
				case 0:
					val->intval = 700;
					break;
				case 1:
					val->intval = 900;
					break;
				case 2:
					val->intval = 1200;
					break;
				case 3:
					val->intval = 1500;
					break;
				case 4:
					val->intval = 1800;
					break;
				case 5:
					val->intval = 2000;
					break;
				case 6:
					val->intval = 2200;
					break;
				case 7:
					val->intval = 2500;
					break;
				}
		} else
			val->intval = 0;
		dev_dbg(&client->dev,
			"%s : set-current(%dmA), current now(%dmA)\n",
			__func__, charger->charging_current, val->intval);
		break;
	default:
		return false;
	}
	return true;
}