// SPDX-License-Identifier: GPL-2.0
/*
 * nct6775-i2c - I2C driver for the hardware monitoring functionality of
 *	         Nuvoton NCT677x Super-I/O chips
 *
 * Copyright (C) 2022 Zev Weiss <zev@bewilderbeest.net>
 *
 * This driver interacts with the chip via it's "back door" i2c interface, as
 * is often exposed to a BMC.  Because the host may still be operating the
 * chip via the ("front door") LPC interface, this driver cannot assume that
 * it actually has full control of the chip, and in particular must avoid
 * making any changes that could confuse the host's LPC usage of it.  It thus
 * operates in a strictly read-only fashion, with the only exception being the
 * bank-select register (which seems, thankfully, to be replicated for the i2c
 * interface so it doesn't affect the LPC interface).
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include "nct6775.h"

static int nct6775_i2c_read(void *ctx, unsigned int reg, unsigned int *val)
{
	int ret;
	u32 tmp;
	u8 bank = reg >> 8;
	struct nct6775_data *data = ctx;
	struct i2c_client *client = data->driver_data;

	if (bank != data->bank) {
		ret = i2c_smbus_write_byte_data(client, NCT6775_REG_BANK, bank);
		if (ret)
			return ret;
		data->bank = bank;
	}

	ret = i2c_smbus_read_byte_data(client, reg & 0xff);
	if (ret < 0)
		return ret;
	tmp = ret;

	if (nct6775_reg_is_word_sized(data, reg)) {
		ret = i2c_smbus_read_byte_data(client, (reg & 0xff) + 1);
		if (ret < 0)
			return ret;
		tmp = (tmp << 8) | ret;
	}

	*val = tmp;
	return 0;
}

/*
 * The write operation is a dummy so as not to disturb anything being done
 * with the chip via LPC.
 */
static int nct6775_i2c_write(void *ctx, unsigned int reg, unsigned int value)
{
	struct nct6775_data *data = ctx;
	struct i2c_client *client = data->driver_data;

	dev_dbg(&client->dev, "skipping attempted write: %02x -> %03x\n", value, reg);

	/*
	 * This is a lie, but writing anything but the bank-select register is
	 * something this driver shouldn't be doing.
	 */
	return 0;
}

static const struct of_device_id __maybe_unused nct6775_i2c_of_match[] = {
	{ .compatible = "nuvoton,nct6106", .data = (void *)nct6106, },
	{ .compatible = "nuvoton,nct6116", .data = (void *)nct6116, },
	{ .compatible = "nuvoton,nct6775", .data = (void *)nct6775, },
	{ .compatible = "nuvoton,nct6776", .data = (void *)nct6776, },
	{ .compatible = "nuvoton,nct6779", .data = (void *)nct6779, },
	{ .compatible = "nuvoton,nct6791", .data = (void *)nct6791, },
	{ .compatible = "nuvoton,nct6792", .data = (void *)nct6792, },
	{ .compatible = "nuvoton,nct6793", .data = (void *)nct6793, },
	{ .compatible = "nuvoton,nct6795", .data = (void *)nct6795, },
	{ .compatible = "nuvoton,nct6796", .data = (void *)nct6796, },
	{ .compatible = "nuvoton,nct6797", .data = (void *)nct6797, },
	{ .compatible = "nuvoton,nct6798", .data = (void *)nct6798, },
	{ },
};
MODULE_DEVICE_TABLE(of, nct6775_i2c_of_match);

static const struct i2c_device_id nct6775_i2c_id[] = {
	{ "nct6106", nct6106 },
	{ "nct6116", nct6116 },
	{ "nct6775", nct6775 },
	{ "nct6776", nct6776 },
	{ "nct6779", nct6779 },
	{ "nct6791", nct6791 },
	{ "nct6792", nct6792 },
	{ "nct6793", nct6793 },
	{ "nct6795", nct6795 },
	{ "nct6796", nct6796 },
	{ "nct6797", nct6797 },
	{ "nct6798", nct6798 },
	{ }
};
MODULE_DEVICE_TABLE(i2c, nct6775_i2c_id);

static int nct6775_i2c_probe_init(struct nct6775_data *data)
{
	u32 tsi_channel_mask;
	struct i2c_client *client = data->driver_data;

	/*
	 * The i2c interface doesn't provide access to the control registers
	 * needed to determine the presence of other fans, but fans 1 and 2
	 * are (in principle) always there.
	 *
	 * In practice this is perhaps a little silly, because the system
	 * using this driver is mostly likely a BMC, and hence probably has
	 * totally separate fan tachs & pwms of its own that are actually
	 * controlling/monitoring the fans -- these are thus unlikely to be
	 * doing anything actually useful.
	 */
	data->has_fan = 0x03;
	data->has_fan_min = 0x03;
	data->has_pwm = 0x03;

	/*
	 * Because on a BMC this driver may be bound very shortly after power
	 * is first applied to the device, the automatic TSI channel detection
	 * in nct6775_probe() (which has already been run at this point) may
	 * not find anything if a channel hasn't yet produced a temperature
	 * reading.  Augment whatever was found via autodetection (if
	 * anything) with the channels DT says should be active.
	 */
	if (!of_property_read_u32(client->dev.of_node, "nuvoton,tsi-channel-mask",
				  &tsi_channel_mask))
		data->have_tsi_temp |= tsi_channel_mask & GENMASK(NUM_TSI_TEMP - 1, 0);

	return 0;
}

static const struct regmap_config nct6775_i2c_regmap_config = {
	.reg_bits = 16,
	.val_bits = 16,
	.reg_read = nct6775_i2c_read,
	.reg_write = nct6775_i2c_write,
};

static int nct6775_i2c_probe(struct i2c_client *client)
{
	struct nct6775_data *data;
	const struct of_device_id *of_id;
	const struct i2c_device_id *i2c_id;
	struct device *dev = &client->dev;

	of_id = of_match_device(nct6775_i2c_of_match, dev);
	i2c_id = i2c_match_id(nct6775_i2c_id, client);

	if (of_id && (unsigned long)of_id->data != i2c_id->driver_data)
		dev_notice(dev, "Device mismatch: %s in device tree, %s detected\n",
			   of_id->name, i2c_id->name);

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

	data->kind = i2c_id->driver_data;

	data->read_only = true;
	data->driver_data = client;
	data->driver_init = nct6775_i2c_probe_init;

	return nct6775_probe(dev, data, &nct6775_i2c_regmap_config);
}

static struct i2c_driver nct6775_i2c_driver = {
	.class = I2C_CLASS_HWMON,
	.driver = {
		.name = "nct6775-i2c",
		.of_match_table = of_match_ptr(nct6775_i2c_of_match),
	},
	.probe_new = nct6775_i2c_probe,
	.id_table = nct6775_i2c_id,
};

module_i2c_driver(nct6775_i2c_driver);

MODULE_AUTHOR("Zev Weiss <zev@bewilderbeest.net>");
MODULE_DESCRIPTION("I2C driver for NCT6775F and compatible chips");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(HWMON_NCT6775);
