static int max17047_get_avgvcell(struct i2c_client *client)
{
	struct max17047_fuelgauge_data *fg_data = i2c_get_clientdata(client);
	u8 data[2];
	int ret;
	u32 avgvcell;
	pr_debug("%s\n", __func__);

	ret = max17047_i2c_read(client, MAX17047_REG_AVGVCELL, data);
	if (ret < 0)
		return ret;

	avgvcell = fg_data->avgvcell = ((data[0] >> 3) + (data[1] << 5)) * 625;

	pr_debug("%s: AVGVCELL(0x%02x%02x, %d)\n", __func__,
		 data[1], data[0], avgvcell);
	return avgvcell;
}
/* max17047_get_XXX(); Return current value and update data value */
static int max17047_get_vfocv(struct i2c_client *client)
{
	struct max17047_fuelgauge_data *fg_data = i2c_get_clientdata(client);
	u8 data[2];
	int ret;
	u32 vfocv;
	pr_debug("%s\n", __func__);

	ret = max17047_i2c_read(client, MAX17047_REG_VFOCV, data);
	if (ret < 0)
		return ret;

	vfocv = fg_data->vfocv = ((data[0] >> 3) + (data[1] << 5)) * 625 / 1000;

	pr_debug("%s: VFOCV(0x%02x%02x, %d)\n", __func__,
		 data[1], data[0], vfocv);
	return vfocv * 1000;
}
static int max17047_get_rawsoc(struct i2c_client *client)
{
	struct max17047_fuelgauge_data *fg_data = i2c_get_clientdata(client);
	u8 data[2];
	int ret;
	int rawsoc;
	pr_debug("%s\n", __func__);

	ret = max17047_i2c_read(client, MAX17047_REG_SOC_VF, data);
	if (ret < 0)
		return ret;

	rawsoc = fg_data->rawsoc = (data[1] * 100) + (data[0] * 100 / 256);

	pr_debug("%s: RAWSOC(0x%02x%02x, %d)\n", __func__,
		 data[1], data[0], rawsoc);
	return rawsoc;
}
Ejemplo n.º 4
0
static ssize_t max17047_debugfs_read_defaultdata(struct file *filp,
	char __user *buffer, size_t count, loff_t *ppos)
{
	struct max17047_fuelgauge_data *fg_data = filp->private_data;
	struct i2c_client *client = NULL;
	u8 i2c_data[2];
	int reg = 0;
	char *buf;
	size_t len = 0;
	ssize_t ret;

	if (!fg_data) {
		pr_err("%s : fg_data is null\n", __func__);
		return 0;
	}

	client = fg_data->client;

	if (*ppos != 0)
		return 0;

	if (count < sizeof(buf))
		return -ENOSPC;

	buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	reg = MAX17047_REG_RCOMP;
	max17047_i2c_read(client, reg, i2c_data);
	len += snprintf(buf + len, PAGE_SIZE - len,
		"rcomp=%02x%02x ", i2c_data[1], i2c_data[0]);

	len += snprintf(buf + len, PAGE_SIZE - len,
		"fsoc=%d", fg_data->full_soc);

	len += snprintf(buf + len, PAGE_SIZE - len, "\n");

	ret = simple_read_from_buffer(buffer, len, ppos, buf, PAGE_SIZE);
	kfree(buf);

	return ret;
}
Ejemplo n.º 5
0
static irqreturn_t max17047_fuelgauge_isr(int irq, void *data)
{
	struct max17047_fuelgauge_data *fg_data = data;
	struct i2c_client *client = fg_data->client;
	union power_supply_propval value;
	u8 i2c_data[2];
	pr_info("%s: irq(%d)\n", __func__, irq);
	mutex_lock(&fg_data->irq_lock);

	max17047_i2c_read(client, MAX17047_REG_STATUS, i2c_data);
	pr_info("%s: MAX17047_REG_STATUS(0x%02x%02x)\n", __func__,
					i2c_data[1], i2c_data[0]);

	wake_lock(&fg_data->update_wake_lock);
	schedule_delayed_work(&fg_data->update_work, msecs_to_jiffies(1000));

	mutex_unlock(&fg_data->irq_lock);
	return IRQ_HANDLED;
}
Ejemplo n.º 6
0
static void max17047_alert_init(struct max17047_fuelgauge_data *fg_data)
{
	struct i2c_client *client = fg_data->client;
	u8 i2c_data[2];
	pr_debug("%s\n", __func__);

	/* SALRT Threshold setting */
	/* min 1%, max disable */
	max17047_set_salrt(fg_data, 0x01, 0xFF);

	/* TALRT Threshold setting */
	/* min disable, max disable */
	max17047_set_talrt(fg_data, 0x80, 0x7F);

	/* VALRT Threshold setting */
	/* min disable, max disable */
	max17047_set_valrt(fg_data, 0x00, 0xFF);

	/* Enable SOC alerts */
	max17047_i2c_read(client, MAX17047_REG_CONFIG, i2c_data);
	i2c_data[0] |= (0x1 << 2);
	max17047_i2c_write(client, MAX17047_REG_CONFIG, i2c_data);
}
Ejemplo n.º 7
0
static void max17047_reset_soc(struct i2c_client *client)
{
	u8 data[2];
	pr_info("%s: Before quick-start - "
		"VFOCV(%d), VFSOC(%d)\n",
		__func__, max17047_get_vfocv(client),
		max17047_get_soc(client));

	if (max17047_i2c_read(client, MAX17047_REG_MISCCFG, data) < 0)
		return;

	/* Set bit10 makes quick start */
	data[1] |= (0x1 << 2);
	max17047_i2c_write(client, MAX17047_REG_MISCCFG, data);

	msleep(500);

	pr_info("%s: After quick-start - "
		"VFOCV(%d), VFSOC(%d)\n",
		__func__, max17047_get_vfocv(client),
		max17047_get_soc(client));

	return;
}
Ejemplo n.º 8
0
static int __devinit max17047_fuelgauge_i2c_probe(struct i2c_client *client,
						  const struct i2c_device_id *id)
{
	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
	struct max17047_fuelgauge_data *fg_data;
	int ret;
	u8 i2c_data[2];
	int rawsoc, firstsoc;
	pr_info("%s: max17047 Fuel gauge Driver Loading\n", __func__);

	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
		return -EIO;

	fg_data = kzalloc(sizeof(struct max17047_fuelgauge_data), GFP_KERNEL);
	if (!fg_data)
		return -ENOMEM;

	fg_data->client = client;
	fg_data->pdata = client->dev.platform_data;

	i2c_set_clientdata(client, fg_data);

	mutex_init(&fg_data->irq_lock);

	wake_lock_init(&fg_data->update_wake_lock, WAKE_LOCK_SUSPEND,
							       "fuel-update");

	/* Initialize full_soc, set this before fisrt SOC reading */
	fg_data->full_soc = FULL_SOC_DEFAULT;
	/* first full_soc update */
	rawsoc = max17047_get_rawsoc(fg_data->client);
	if (rawsoc > FULL_SOC_DEFAULT)
		max17047_adjust_fullsoc(client);
	firstsoc = max17047_get_soc(client);
	pr_info("%s: rsoc=%d, fsoc=%d, soc=%d\n", __func__,
			rawsoc, fg_data->full_soc, firstsoc);

	if (fg_data->pdata->psy_name)
		fg_data->fuelgauge.name =
			fg_data->pdata->psy_name;
	else
		fg_data->fuelgauge.name = "max17047-fuelgauge";

	fg_data->fuelgauge.type = POWER_SUPPLY_TYPE_BATTERY;
	fg_data->fuelgauge.properties = max17047_fuelgauge_props;
	fg_data->fuelgauge.num_properties =
				ARRAY_SIZE(max17047_fuelgauge_props);
	fg_data->fuelgauge.get_property = max17047_get_property;
	fg_data->fuelgauge.set_property = max17047_set_property;

	ret = power_supply_register(&client->dev, &fg_data->fuelgauge);
	if (ret) {
		pr_err("%s: failed power supply register\n", __func__);
		goto err_psy_reg_fg;
	}

	/* Initialize fuelgauge registers */
	max17047_reg_init(fg_data);

	/* Initialize fuelgauge alert */
	max17047_alert_init(fg_data);

	/* Request IRQ */
	fg_data->irq = gpio_to_irq(fg_data->pdata->irq_gpio);
	ret = gpio_request(fg_data->pdata->irq_gpio, "fuelgauge-irq");
	if (ret) {
		pr_err("%s: failed requesting gpio %d\n", __func__,
				fg_data->pdata->irq_gpio);
		goto err_irq;
	}
	gpio_direction_input(fg_data->pdata->irq_gpio);
	gpio_free(fg_data->pdata->irq_gpio);

	ret = request_threaded_irq(fg_data->irq, NULL,
				max17047_fuelgauge_isr, IRQF_TRIGGER_FALLING,
				"max17047-alert", fg_data);
	if (ret < 0) {
		pr_err("%s: fail to request max17047 irq: %d: %d\n",
				__func__, fg_data->irq, ret);
		goto err_irq;
	}

	ret = enable_irq_wake(fg_data->irq);
	if (ret < 0) {
		pr_err("%s: failed enable irq wake %d\n", __func__,
						fg_data->irq);
		goto err_enable_irq;
	}

	INIT_DELAYED_WORK_DEFERRABLE(&fg_data->update_work,
					max17047_update_work);
#ifdef DEBUG_FUELGAUGE_POLLING
	INIT_DELAYED_WORK_DEFERRABLE(&fg_data->polling_work,
					max17047_polling_work);
	schedule_delayed_work(&fg_data->polling_work, 0);
#else
	max17047_test_read(fg_data);
#endif

	max17047_i2c_read(client, MAX17047_REG_VERSION, i2c_data);
	pr_info("max17047 fuelgauge(rev.%d%d) initialized.\n", i2c_data[0], i2c_data[1]);

#if defined(CONFIG_TARGET_LOCALE_KOR)
#ifdef CONFIG_DEBUG_FS
	fg_data->fg_debugfs_dir =
		debugfs_create_dir("fg_debug", NULL);
	if (fg_data->fg_debugfs_dir) {
		if (!debugfs_create_file("max17047_regs", 0644,
			fg_data->fg_debugfs_dir,
			fg_data, &max17047_debugfs_fops))
			pr_err("%s : debugfs_create_file, error\n", __func__);
		if (!debugfs_create_file("default_data", 0644,
			fg_data->fg_debugfs_dir,
			fg_data, &max17047_debugfs_fops2))
			pr_err("%s : debugfs_create_file2, error\n", __func__);
	} else
		pr_err("%s : debugfs_create_dir, error\n", __func__);
#endif
#endif

	return 0;

err_enable_irq:
	free_irq(fg_data->irq, fg_data);
err_irq:
	power_supply_unregister(&fg_data->fuelgauge);
err_psy_reg_fg:
	wake_lock_destroy(&fg_data->update_wake_lock);
	mutex_destroy(&fg_data->irq_lock);
	kfree(fg_data);
	return ret;
}
Ejemplo n.º 9
0
static ssize_t max17047_debugfs_read_registers(struct file *filp,
	char __user *buffer, size_t count, loff_t *ppos)
{
	struct max17047_fuelgauge_data *fg_data = filp->private_data;
	struct i2c_client *client = NULL;
	u8 i2c_data[2];
	int reg = 0;
	char *buf;
	size_t len = 0;
	ssize_t ret;

	if (!fg_data) {
		pr_err("%s : fg_data is null\n", __func__);
		return 0;
	}

	client = fg_data->client;

	if (*ppos != 0)
		return 0;

	if (count < sizeof(buf))
		return -ENOSPC;

	buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	reg = MAX17047_REG_STATUS;
	max17047_i2c_read(client, reg, i2c_data);
	len += snprintf(buf + len, PAGE_SIZE - len,
		"status(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]);

	reg = MAX17047_REG_CONFIG;
	max17047_i2c_read(client, reg, i2c_data);
	len += snprintf(buf + len, PAGE_SIZE - len,
		"config(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]);

	reg = MAX17047_REG_RCOMP;
	max17047_i2c_read(client, reg, i2c_data);
	len += snprintf(buf + len, PAGE_SIZE - len,
		"rcomp(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]);

	reg = MAX17047_REG_CGAIN;
	max17047_i2c_read(client, reg, i2c_data);
	len += snprintf(buf + len, PAGE_SIZE - len,
		"cgain(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]);

	reg = MAX17047_REG_SALRT_TH;
	max17047_i2c_read(client, reg, i2c_data);
	len += snprintf(buf + len, PAGE_SIZE - len,
		"salrt(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]);

	reg = MAX17047_REG_MISCCFG;
	max17047_i2c_read(client, reg, i2c_data);
	len += snprintf(buf + len, PAGE_SIZE - len,
		"misc(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]);

	reg = 0x39;
	max17047_i2c_read(client, reg, i2c_data);
	len += snprintf(buf + len, PAGE_SIZE - len,
		"tempc0(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]);

	reg = 0x0F;
	max17047_i2c_read(client, reg, i2c_data);
	len += snprintf(buf + len, PAGE_SIZE - len,
		"remCap(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]);

	reg = 0x10;
	max17047_i2c_read(client, reg, i2c_data);
	len += snprintf(buf + len, PAGE_SIZE - len,
		"fullCap(0x%x)=%02x%02x ", reg, i2c_data[1], i2c_data[0]);

	len += snprintf(buf + len, PAGE_SIZE - len, "\n");

	ret = simple_read_from_buffer(buffer, len, ppos, buf, PAGE_SIZE);
	kfree(buf);

	return ret;
}
Ejemplo n.º 10
0
static int __devinit max17047_fuelgauge_i2c_probe(struct i2c_client *client,
						  const struct i2c_device_id *id)
{
	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
	struct max17047_fuelgauge_data *fuelgauge_data;
	int ret;
	u8 i2c_data[2];

	pr_info("%s: max17047 Fuel gauge Driver Loading\n", __func__);

	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
		return -EIO;

	fuelgauge_data = kzalloc(sizeof(struct max17047_fuelgauge_data), GFP_KERNEL);
	if (!fuelgauge_data)
		return -ENOMEM;

	fuelgauge_data->client = client;
	fuelgauge_data->pdata = client->dev.platform_data;

	i2c_set_clientdata(client, fuelgauge_data);

	if (fuelgauge_data->pdata->psy_name)
		fuelgauge_data->fuelgauge.name =
			fuelgauge_data->pdata->psy_name;
	else
		fuelgauge_data->fuelgauge.name = "max17047-fuelgauge";

	fuelgauge_data->fuelgauge.type = POWER_SUPPLY_TYPE_BATTERY;
	fuelgauge_data->fuelgauge.properties = max17047_fuelgauge_props;
	fuelgauge_data->fuelgauge.num_properties = ARRAY_SIZE(max17047_fuelgauge_props);
	fuelgauge_data->fuelgauge.get_property = max17047_get_property;
	fuelgauge_data->fuelgauge.set_property = max17047_set_property;

	ret = power_supply_register(&client->dev, &fuelgauge_data->fuelgauge);
	if (ret) {
		pr_err("%s: failed power supply register\n", __func__);
		kfree(fuelgauge_data);
		return ret;
	}

	/* Initialize fuelgauge registers */
	max17047_reg_init(fuelgauge_data);

	/* Initialize fuelgauge alert */
	max17047_alert_init(fuelgauge_data);

	/* Request IRQ */
	fuelgauge_data->irq = gpio_to_irq(fuelgauge_data->pdata->irq_gpio);
	ret = gpio_request(fuelgauge_data->pdata->irq_gpio, "fuelgauge-irq");
	if (ret) {
		pr_err("%s: failed requesting gpio %d\n", __func__,
				fuelgauge_data->pdata->irq_gpio);
		return ret;
	}
	gpio_direction_input(fuelgauge_data->pdata->irq_gpio);
	gpio_free(fuelgauge_data->pdata->irq_gpio);
	if (request_irq(fuelgauge_data->irq, max17047_fuelgauge_isr,
			IRQF_TRIGGER_FALLING,
			"max17047-alert",
			fuelgauge_data))
		pr_err("Can NOT request irq 'FUEL_ALERT' %d",
		       fuelgauge_data->irq);

#ifdef DEBUG_FUELGAUGE_POLLING
	INIT_DELAYED_WORK_DEFERRABLE(&fuelgauge_data->polling_work, max17047_polling_work);
	schedule_delayed_work(&fuelgauge_data->polling_work, 0);
#else
	max17047_test_read(fuelgauge_data);
#endif

	max17047_i2c_read(client, MAX17047_REG_VERSION, i2c_data);
	pr_info("max17047 fuelgauge(rev.%d%d) initialized.\n", i2c_data[0], i2c_data[1]);

	return 0;
}