/*
 * HWMON Driver for Dialog DA9055
 *
 * Copyright(c) 2012 Dialog Semiconductor Ltd.
 *
 * Author: David Dajun Chen <dchen@diasemi.com>
 *
 *  This program is free software; you can redistribute  it and/or modify it
 *  under  the terms of  the GNU General  Public License as published by the
 *  Free Software Foundation;  either version 2 of the  License, or (at your
 *  option) any later version.
 *
 */

#include <linux/delay.h>
#include <linux/err.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/completion.h>

#include <linux/mfd/da9055/core.h>
#include <linux/mfd/da9055/reg.h>

#define DA9055_ADCIN_DIV	102
#define DA9055_VSYS_DIV	85

#define DA9055_ADC_VSYS	0
#define DA9055_ADC_ADCIN1	1
#define DA9055_ADC_ADCIN2	2
#define DA9055_ADC_ADCIN3	3
#define DA9055_ADC_TJUNC	4

struct da9055_hwmon {
	struct da9055	*da9055;
	struct mutex	hwmon_lock;
	struct mutex	irq_lock;
	struct completion done;
};

static const char * const input_names[] = {
	[DA9055_ADC_VSYS]	= "VSYS",
	[DA9055_ADC_ADCIN1]	= "ADC IN1",
	[DA9055_ADC_ADCIN2]	= "ADC IN2",
	[DA9055_ADC_ADCIN3]	= "ADC IN3",
	[DA9055_ADC_TJUNC]	= "CHIP TEMP",
};

static const u8 chan_mux[DA9055_ADC_TJUNC + 1] = {
	[DA9055_ADC_VSYS]	= DA9055_ADC_MUX_VSYS,
	[DA9055_ADC_ADCIN1]	= DA9055_ADC_MUX_ADCIN1,
	[DA9055_ADC_ADCIN2]	= DA9055_ADC_MUX_ADCIN2,
	[DA9055_ADC_ADCIN3]	= DA9055_ADC_MUX_ADCIN3,
	[DA9055_ADC_TJUNC]	= DA9055_ADC_MUX_T_SENSE,
};

static int da9055_adc_manual_read(struct da9055_hwmon *hwmon,
					unsigned char channel)
{
	int ret;
	unsigned short calc_data;
	unsigned short data;
	unsigned char mux_sel;
	struct da9055 *da9055 = hwmon->da9055;

	if (channel > DA9055_ADC_TJUNC)
		return -EINVAL;

	mutex_lock(&hwmon->irq_lock);

	/* Selects desired MUX for manual conversion */
	mux_sel = chan_mux[channel] | DA9055_ADC_MAN_CONV;

	ret = da9055_reg_write(da9055, DA9055_REG_ADC_MAN, mux_sel);
	if (ret < 0)
		goto err;

	/* Wait for an interrupt */
	if (!wait_for_completion_timeout(&hwmon->done,
					msecs_to_jiffies(500))) {
		dev_err(da9055->dev,
			"timeout waiting for ADC conversion interrupt\n");
		ret = -ETIMEDOUT;
		goto err;
	}

	ret = da9055_reg_read(da9055, DA9055_REG_ADC_RES_H);
	if (ret < 0)
		goto err;

	calc_data = (unsigned short)ret;
	data = calc_data << 2;

	ret = da9055_reg_read(da9055, DA9055_REG_ADC_RES_L);
	if (ret < 0)
		goto err;

	calc_data = (unsigned short)(ret & DA9055_ADC_LSB_MASK);
	data |= calc_data;

	ret = data;

err:
	mutex_unlock(&hwmon->irq_lock);
	return ret;
}

static irqreturn_t da9055_auxadc_irq(int irq, void *irq_data)
{
	struct da9055_hwmon *hwmon = irq_data;

	complete(&hwmon->done);

	return IRQ_HANDLED;
}

/* Conversion function for VSYS and ADCINx */
static inline int volt_reg_to_mv(int value, int channel)
{
	if (channel == DA9055_ADC_VSYS)
		return DIV_ROUND_CLOSEST(value * 1000, DA9055_VSYS_DIV) + 2500;
	else
		return DIV_ROUND_CLOSEST(value * 1000, DA9055_ADCIN_DIV);
}

static int da9055_enable_auto_mode(struct da9055 *da9055, int channel)
{

	return da9055_reg_update(da9055, DA9055_REG_ADC_CONT, 1 << channel,
				1 << channel);

}

static int da9055_disable_auto_mode(struct da9055 *da9055, int channel)
{

	return da9055_reg_update(da9055, DA9055_REG_ADC_CONT, 1 << channel, 0);
}

static ssize_t da9055_read_auto_ch(struct device *dev,
				struct device_attribute *devattr, char *buf)
{
	struct da9055_hwmon *hwmon = dev_get_drvdata(dev);
	int ret, adc;
	int channel = to_sensor_dev_attr(devattr)->index;

	mutex_lock(&hwmon->hwmon_lock);

	ret = da9055_enable_auto_mode(hwmon->da9055, channel);
	if (ret < 0)
		goto hwmon_err;

	usleep_range(10000, 10500);

	adc = da9055_reg_read(hwmon->da9055, DA9055_REG_VSYS_RES + channel);
	if (adc < 0) {
		ret = adc;
		goto hwmon_err_release;
	}

	ret = da9055_disable_auto_mode(hwmon->da9055, channel);
	if (ret < 0)
		goto hwmon_err;

	mutex_unlock(&hwmon->hwmon_lock);

	return sprintf(buf, "%d\n", volt_reg_to_mv(adc, channel));

hwmon_err_release:
	da9055_disable_auto_mode(hwmon->da9055, channel);
hwmon_err:
	mutex_unlock(&hwmon->hwmon_lock);
	return ret;
}

static ssize_t da9055_read_tjunc(struct device *dev,
				 struct device_attribute *devattr, char *buf)
{
	struct da9055_hwmon *hwmon = dev_get_drvdata(dev);
	int tjunc;
	int toffset;

	tjunc = da9055_adc_manual_read(hwmon, DA9055_ADC_TJUNC);
	if (tjunc < 0)
		return tjunc;

	toffset = da9055_reg_read(hwmon->da9055, DA9055_REG_T_OFFSET);
	if (toffset < 0)
		return toffset;

	/*
	 * Degrees celsius = -0.4084 * (ADC_RES - T_OFFSET) + 307.6332
	 * T_OFFSET is a trim value used to improve accuracy of the result
	 */
	return sprintf(buf, "%d\n", DIV_ROUND_CLOSEST(-4084 * (tjunc - toffset)
							+ 3076332, 10000));
}

static ssize_t show_label(struct device *dev,
			  struct device_attribute *devattr, char *buf)
{
	return sprintf(buf, "%s\n",
		       input_names[to_sensor_dev_attr(devattr)->index]);
}

static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, da9055_read_auto_ch, NULL,
			  DA9055_ADC_VSYS);
static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_label, NULL,
			  DA9055_ADC_VSYS);
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, da9055_read_auto_ch, NULL,
			  DA9055_ADC_ADCIN1);
static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_label, NULL,
			  DA9055_ADC_ADCIN1);
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, da9055_read_auto_ch, NULL,
			  DA9055_ADC_ADCIN2);
static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_label, NULL,
			  DA9055_ADC_ADCIN2);
static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, da9055_read_auto_ch, NULL,
			  DA9055_ADC_ADCIN3);
static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL,
			  DA9055_ADC_ADCIN3);

static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, da9055_read_tjunc, NULL,
			  DA9055_ADC_TJUNC);
static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL,
			  DA9055_ADC_TJUNC);

static struct attribute *da9055_attrs[] = {
	&sensor_dev_attr_in0_input.dev_attr.attr,
	&sensor_dev_attr_in0_label.dev_attr.attr,
	&sensor_dev_attr_in1_input.dev_attr.attr,
	&sensor_dev_attr_in1_label.dev_attr.attr,
	&sensor_dev_attr_in2_input.dev_attr.attr,
	&sensor_dev_attr_in2_label.dev_attr.attr,
	&sensor_dev_attr_in3_input.dev_attr.attr,
	&sensor_dev_attr_in3_label.dev_attr.attr,

	&sensor_dev_attr_temp1_input.dev_attr.attr,
	&sensor_dev_attr_temp1_label.dev_attr.attr,
	NULL
};

ATTRIBUTE_GROUPS(da9055);

static int da9055_hwmon_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct da9055_hwmon *hwmon;
	struct device *hwmon_dev;
	int hwmon_irq, ret;

	hwmon = devm_kzalloc(dev, sizeof(struct da9055_hwmon), GFP_KERNEL);
	if (!hwmon)
		return -ENOMEM;

	mutex_init(&hwmon->hwmon_lock);
	mutex_init(&hwmon->irq_lock);

	init_completion(&hwmon->done);
	hwmon->da9055 = dev_get_drvdata(pdev->dev.parent);

	hwmon_irq = platform_get_irq_byname(pdev, "HWMON");
	if (hwmon_irq < 0)
		return hwmon_irq;

	ret = devm_request_threaded_irq(&pdev->dev, hwmon_irq,
					NULL, da9055_auxadc_irq,
					IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
					"adc-irq", hwmon);
	if (ret != 0) {
		dev_err(hwmon->da9055->dev, "DA9055 ADC IRQ failed ret=%d\n",
			ret);
		return ret;
	}

	hwmon_dev = devm_hwmon_device_register_with_groups(dev, "da9055",
							   hwmon,
							   da9055_groups);
	return PTR_ERR_OR_ZERO(hwmon_dev);
}

static struct platform_driver da9055_hwmon_driver = {
	.probe = da9055_hwmon_probe,
	.driver = {
		.name = "da9055-hwmon",
	},
};

module_platform_driver(da9055_hwmon_driver);

MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
MODULE_DESCRIPTION("DA9055 HWMON driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:da9055-hwmon");
