/*
 * drivers/hwmon/nsa320-hwmon.c
 *
 * ZyXEL NSA320 Media Servers
 * hardware monitoring
 *
 * Copyright (C) 2016 Adam Baker <linux@baker-net.org.uk>
 * based on a board file driver
 * Copyright (C) 2012 Peter Schildmann <linux@schildmann.info>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License v2 as published by the
 * Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 */

#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>

/* Tests for error return values rely upon this value being < 0x80 */
#define MAGIC_NUMBER 0x55

/*
 * The Zyxel hwmon MCU is a Holtek HT46R065 that is factory programmed
 * to perform temperature and fan speed monitoring. It is read by taking
 * the active pin low. The 32 bit output word is then clocked onto the
 * data line. The MSB of the data word is a magic nuber to indicate it
 * has been read correctly, the next byte is the fan speed (in hundreds
 * of RPM) and the last two bytes are the temperature (in tenths of a
 * degree)
 */

struct nsa320_hwmon {
	struct mutex		update_lock;	/* lock GPIO operations */
	unsigned long		last_updated;	/* jiffies */
	unsigned long		mcu_data;
	struct gpio_desc	*act;
	struct gpio_desc	*clk;
	struct gpio_desc	*data;
};

enum nsa320_inputs {
	NSA320_TEMP = 0,
	NSA320_FAN = 1,
};

static const char * const nsa320_input_names[] = {
	[NSA320_TEMP] = "System Temperature",
	[NSA320_FAN] = "Chassis Fan",
};

/*
 * Although this protocol looks similar to SPI the long delay
 * between the active (aka chip select) signal and the shorter
 * delay between clock pulses are needed for reliable operation.
 * The delays provided are taken from the manufacturer kernel,
 * testing suggest they probably incorporate a reasonable safety
 * margin. (The single device tested became unreliable if the
 * delay was reduced to 1/10th of this value.)
 */
static s32 nsa320_hwmon_update(struct device *dev)
{
	u32 mcu_data;
	u32 mask;
	struct nsa320_hwmon *hwmon = dev_get_drvdata(dev);

	mutex_lock(&hwmon->update_lock);

	mcu_data = hwmon->mcu_data;

	if (time_after(jiffies, hwmon->last_updated + HZ) || mcu_data == 0) {
		gpiod_set_value(hwmon->act, 1);
		msleep(100);

		mcu_data = 0;
		for (mask = BIT(31); mask; mask >>= 1) {
			gpiod_set_value(hwmon->clk, 0);
			usleep_range(100, 200);
			gpiod_set_value(hwmon->clk, 1);
			usleep_range(100, 200);
			if (gpiod_get_value(hwmon->data))
				mcu_data |= mask;
		}

		gpiod_set_value(hwmon->act, 0);
		dev_dbg(dev, "Read raw MCU data %08x\n", mcu_data);

		if ((mcu_data >> 24) != MAGIC_NUMBER) {
			dev_dbg(dev, "Read invalid MCU data %08x\n", mcu_data);
			mcu_data = -EIO;
		} else {
			hwmon->mcu_data = mcu_data;
			hwmon->last_updated = jiffies;
		}
	}

	mutex_unlock(&hwmon->update_lock);

	return mcu_data;
}

static ssize_t label_show(struct device *dev, struct device_attribute *attr,
			  char *buf)
{
	int channel = to_sensor_dev_attr(attr)->index;

	return sprintf(buf, "%s\n", nsa320_input_names[channel]);
}

static ssize_t temp1_input_show(struct device *dev,
				struct device_attribute *attr, char *buf)
{
	s32 mcu_data = nsa320_hwmon_update(dev);

	if (mcu_data < 0)
		return mcu_data;

	return sprintf(buf, "%d\n", (mcu_data & 0xffff) * 100);
}

static ssize_t fan1_input_show(struct device *dev,
			       struct device_attribute *attr, char *buf)
{
	s32 mcu_data = nsa320_hwmon_update(dev);

	if (mcu_data < 0)
		return mcu_data;

	return sprintf(buf, "%d\n", ((mcu_data & 0xff0000) >> 16) * 100);
}

static SENSOR_DEVICE_ATTR_RO(temp1_label, label, NSA320_TEMP);
static DEVICE_ATTR_RO(temp1_input);
static SENSOR_DEVICE_ATTR_RO(fan1_label, label, NSA320_FAN);
static DEVICE_ATTR_RO(fan1_input);

static struct attribute *nsa320_attrs[] = {
	&sensor_dev_attr_temp1_label.dev_attr.attr,
	&dev_attr_temp1_input.attr,
	&sensor_dev_attr_fan1_label.dev_attr.attr,
	&dev_attr_fan1_input.attr,
	NULL
};

ATTRIBUTE_GROUPS(nsa320);

static const struct of_device_id of_nsa320_hwmon_match[] = {
	{ .compatible = "zyxel,nsa320-mcu", },
	{ },
};

static int nsa320_hwmon_probe(struct platform_device *pdev)
{
	struct nsa320_hwmon	*hwmon;
	struct device		*classdev;

	hwmon = devm_kzalloc(&pdev->dev, sizeof(*hwmon), GFP_KERNEL);
	if (!hwmon)
		return -ENOMEM;

	/* Look up the GPIO pins to use */
	hwmon->act = devm_gpiod_get(&pdev->dev, "act", GPIOD_OUT_LOW);
	if (IS_ERR(hwmon->act))
		return PTR_ERR(hwmon->act);

	hwmon->clk = devm_gpiod_get(&pdev->dev, "clk", GPIOD_OUT_HIGH);
	if (IS_ERR(hwmon->clk))
		return PTR_ERR(hwmon->clk);

	hwmon->data = devm_gpiod_get(&pdev->dev, "data", GPIOD_IN);
	if (IS_ERR(hwmon->data))
		return PTR_ERR(hwmon->data);

	mutex_init(&hwmon->update_lock);

	classdev = devm_hwmon_device_register_with_groups(&pdev->dev,
					"nsa320", hwmon, nsa320_groups);

	return PTR_ERR_OR_ZERO(classdev);

}

/* All allocations use devres so remove() is not needed. */

static struct platform_driver nsa320_hwmon_driver = {
	.probe = nsa320_hwmon_probe,
	.driver = {
		.name = "nsa320-hwmon",
		.of_match_table = of_match_ptr(of_nsa320_hwmon_match),
	},
};

module_platform_driver(nsa320_hwmon_driver);

MODULE_DEVICE_TABLE(of, of_nsa320_hwmon_match);
MODULE_AUTHOR("Peter Schildmann <linux@schildmann.info>");
MODULE_AUTHOR("Adam Baker <linux@baker-net.org.uk>");
MODULE_DESCRIPTION("NSA320 Hardware Monitoring");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:nsa320-hwmon");
