/*
 * Windfarm PowerMac thermal control. AD7417 sensors
 *
 * Copyright 2012 Benjamin Herrenschmidt, IBM Corp.
 *
 * Released under the term of the GNU GPL v2.
 */

#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/i2c.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/io.h>
#include <asm/sections.h>

#include "windfarm.h"
#include "windfarm_mpu.h"

#define VERSION "1.0"

struct wf_ad7417_priv {
	struct kref		ref;
	struct i2c_client	*i2c;
	u8			config;
	u8			cpu;
	const struct mpu_data	*mpu;
	struct wf_sensor	sensors[5];
	struct mutex		lock;
};

static int wf_ad7417_temp_get(struct wf_sensor *sr, s32 *value)
{
	struct wf_ad7417_priv *pv = sr->priv;
	u8 buf[2];
	s16 raw;
	int rc;

	*value = 0;
	mutex_lock(&pv->lock);

	/* Read temp register */
	buf[0] = 0;
	rc = i2c_master_send(pv->i2c, buf, 1);
	if (rc < 0)
		goto error;
	rc = i2c_master_recv(pv->i2c, buf, 2);
	if (rc < 0)
		goto error;

	/* Read a a 16-bit signed value */
	raw = be16_to_cpup((__le16 *)buf);

	/* Convert 8.8-bit to 16.16 fixed point */
	*value = ((s32)raw) << 8;

	mutex_unlock(&pv->lock);
	return 0;

error:
	mutex_unlock(&pv->lock);
	return -1;
}

/*
 * Scaling factors for the AD7417 ADC converters (except
 * for the CPU diode which is obtained from the EEPROM).
 * Those values are obtained from the property list of
 * the darwin driver
 */
#define ADC_12V_CURRENT_SCALE	0x0320	/* _AD2 */
#define ADC_CPU_VOLTAGE_SCALE	0x00a0	/* _AD3 */
#define ADC_CPU_CURRENT_SCALE	0x1f40	/* _AD4 */

static void wf_ad7417_adc_convert(struct wf_ad7417_priv *pv,
				  int chan, s32 raw, s32 *value)
{
	switch(chan) {
	case 1: /* Diode */
		*value = (raw * (s32)pv->mpu->mdiode +
			((s32)pv->mpu->bdiode << 12)) >> 2;
		break;
	case 2: /* 12v current */
		*value = raw * ADC_12V_CURRENT_SCALE;
		break;
	case 3: /* core voltage */
		*value = raw * ADC_CPU_VOLTAGE_SCALE;
		break;
	case 4: /* core current */
		*value = raw * ADC_CPU_CURRENT_SCALE;
		break;
	}
}

static int wf_ad7417_adc_get(struct wf_sensor *sr, s32 *value)
{
	struct wf_ad7417_priv *pv = sr->priv;
	int chan = sr - pv->sensors;
	int i, rc;
	u8 buf[2];
	u16 raw;

	*value = 0;
	mutex_lock(&pv->lock);
	for (i = 0; i < 10; i++) {
		/* Set channel */
		buf[0] = 1;
		buf[1] = (pv->config & 0x1f) | (chan << 5);
		rc = i2c_master_send(pv->i2c, buf, 2);
		if (rc < 0)
			goto error;

		/* Wait for conversion */
		msleep(1);

		/* Switch to data register */
		buf[0] = 4;
		rc = i2c_master_send(pv->i2c, buf, 1);
		if (rc < 0)
			goto error;

		/* Read result */
		rc = i2c_master_recv(pv->i2c, buf, 2);
		if (rc < 0)
			goto error;

		/* Read a a 16-bit signed value */
		raw = be16_to_cpup((__le16 *)buf) >> 6;
		wf_ad7417_adc_convert(pv, chan, raw, value);

		dev_vdbg(&pv->i2c->dev, "ADC chan %d [%s]"
			 " raw value: 0x%x, conv to: 0x%08x\n",
			 chan, sr->name, raw, *value);

		mutex_unlock(&pv->lock);
		return 0;

	error:
		dev_dbg(&pv->i2c->dev,
			  "Error reading ADC, try %d...\n", i);
		if (i < 9)
			msleep(10);
	}
	mutex_unlock(&pv->lock);
	return -1;
}

static void wf_ad7417_release(struct kref *ref)
{
	struct wf_ad7417_priv *pv = container_of(ref,
						 struct wf_ad7417_priv, ref);
	kfree(pv);
}

static void wf_ad7417_sensor_release(struct wf_sensor *sr)
{
	struct wf_ad7417_priv *pv = sr->priv;

	kfree(sr->name);
	kref_put(&pv->ref, wf_ad7417_release);
}

static const struct wf_sensor_ops wf_ad7417_temp_ops = {
	.get_value	= wf_ad7417_temp_get,
	.release	= wf_ad7417_sensor_release,
	.owner		= THIS_MODULE,
};

static const struct wf_sensor_ops wf_ad7417_adc_ops = {
	.get_value	= wf_ad7417_adc_get,
	.release	= wf_ad7417_sensor_release,
	.owner		= THIS_MODULE,
};

static void wf_ad7417_add_sensor(struct wf_ad7417_priv *pv,
				 int index, const char *name,
				 const struct wf_sensor_ops *ops)
{
	pv->sensors[index].name = kasprintf(GFP_KERNEL, "%s-%d", name, pv->cpu);
	pv->sensors[index].priv = pv;
	pv->sensors[index].ops = ops;
	if (!wf_register_sensor(&pv->sensors[index]))
		kref_get(&pv->ref);
}

static void wf_ad7417_init_chip(struct wf_ad7417_priv *pv)
{
	int rc;
	u8 buf[2];
	u8 config = 0;

	/*
	 * Read ADC the configuration register and cache it. We
	 * also make sure Config2 contains proper values, I've seen
	 * cases where we got stale grabage in there, thus preventing
	 * proper reading of conv. values
	 */

	/* Clear Config2 */
	buf[0] = 5;
	buf[1] = 0;
	i2c_master_send(pv->i2c, buf, 2);

	/* Read & cache Config1 */
	buf[0] = 1;
	rc = i2c_master_send(pv->i2c, buf, 1);
	if (rc > 0) {
		rc = i2c_master_recv(pv->i2c, buf, 1);
		if (rc > 0) {
			config = buf[0];

			dev_dbg(&pv->i2c->dev, "ADC config reg: %02x\n",
				config);

			/* Disable shutdown mode */
			config &= 0xfe;
			buf[0] = 1;
			buf[1] = config;
			rc = i2c_master_send(pv->i2c, buf, 2);
		}
	}
	if (rc <= 0)
		dev_err(&pv->i2c->dev, "Error reading ADC config\n");

	pv->config = config;
}

static int wf_ad7417_probe(struct i2c_client *client,
			   const struct i2c_device_id *id)
{
	struct wf_ad7417_priv *pv;
	const struct mpu_data *mpu;
	const char *loc;
	int cpu_nr;

	loc = of_get_property(client->dev.of_node, "hwsensor-location", NULL);
	if (!loc) {
		dev_warn(&client->dev, "Missing hwsensor-location property!\n");
		return -ENXIO;
	}

	/*
	 * Identify which CPU we belong to by looking at the first entry
	 * in the hwsensor-location list
	 */
	if (!strncmp(loc, "CPU A", 5))
		cpu_nr = 0;
	else if (!strncmp(loc, "CPU B", 5))
		cpu_nr = 1;
	else {
		pr_err("wf_ad7417: Can't identify location %s\n", loc);
		return -ENXIO;
	}
	mpu = wf_get_mpu(cpu_nr);
	if (!mpu) {
		dev_err(&client->dev, "Failed to retrieve MPU data\n");
		return -ENXIO;
	}

	pv = kzalloc(sizeof(struct wf_ad7417_priv), GFP_KERNEL);
	if (pv == NULL)
		return -ENODEV;

	kref_init(&pv->ref);
	mutex_init(&pv->lock);
	pv->i2c = client;
	pv->cpu = cpu_nr;
	pv->mpu = mpu;
	dev_set_drvdata(&client->dev, pv);

	/* Initialize the chip */
	wf_ad7417_init_chip(pv);

	/*
	 * We cannot rely on Apple device-tree giving us child
	 * node with the names of the individual sensors so we
	 * just hard code what we know about them
	 */
	wf_ad7417_add_sensor(pv, 0, "cpu-amb-temp", &wf_ad7417_temp_ops);
	wf_ad7417_add_sensor(pv, 1, "cpu-diode-temp", &wf_ad7417_adc_ops);
	wf_ad7417_add_sensor(pv, 2, "cpu-12v-current", &wf_ad7417_adc_ops);
	wf_ad7417_add_sensor(pv, 3, "cpu-voltage", &wf_ad7417_adc_ops);
	wf_ad7417_add_sensor(pv, 4, "cpu-current", &wf_ad7417_adc_ops);

	return 0;
}

static int wf_ad7417_remove(struct i2c_client *client)
{
	struct wf_ad7417_priv *pv = dev_get_drvdata(&client->dev);
	int i;

	/* Mark client detached */
	pv->i2c = NULL;

	/* Release sensor */
	for (i = 0; i < 5; i++)
		wf_unregister_sensor(&pv->sensors[i]);

	kref_put(&pv->ref, wf_ad7417_release);

	return 0;
}

static const struct i2c_device_id wf_ad7417_id[] = {
	{ "MAC,ad7417", 0 },
	{ }
};
MODULE_DEVICE_TABLE(i2c, wf_ad7417_id);

static struct i2c_driver wf_ad7417_driver = {
	.driver = {
		.name	= "wf_ad7417",
	},
	.probe		= wf_ad7417_probe,
	.remove		= wf_ad7417_remove,
	.id_table	= wf_ad7417_id,
};

static int wf_ad7417_init(void)
{
	/* This is only supported on these machines */
	if (!of_machine_is_compatible("PowerMac7,2") &&
	    !of_machine_is_compatible("PowerMac7,3") &&
	    !of_machine_is_compatible("RackMac3,1"))
		return -ENODEV;

	return i2c_add_driver(&wf_ad7417_driver);
}

static void wf_ad7417_exit(void)
{
	i2c_del_driver(&wf_ad7417_driver);
}

module_init(wf_ad7417_init);
module_exit(wf_ad7417_exit);

MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
MODULE_DESCRIPTION("ad7417 sensor driver for PowerMacs");
MODULE_LICENSE("GPL");

