// SPDX-License-Identifier: GPL-2.0
/*
 * UFS hardware monitoring support
 * Copyright (c) 2021, Western Digital Corporation
 */

#include <linux/hwmon.h>
#include <linux/units.h>

#include <ufs/ufshcd.h>
#include "ufshcd-priv.h"

struct ufs_hwmon_data {
	struct ufs_hba *hba;
	u8 mask;
};

static int ufs_read_temp_enable(struct ufs_hba *hba, u8 mask, long *val)
{
	u32 ee_mask;
	int err;

	err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, QUERY_ATTR_IDN_EE_CONTROL, 0, 0,
				&ee_mask);
	if (err)
		return err;

	*val = (mask & ee_mask & MASK_EE_TOO_HIGH_TEMP) || (mask & ee_mask & MASK_EE_TOO_LOW_TEMP);

	return 0;
}

static int ufs_get_temp(struct ufs_hba *hba, enum attr_idn idn, long *val)
{
	u32 value;
	int err;

	err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, idn, 0, 0, &value);
	if (err)
		return err;

	if (value == 0)
		return -ENODATA;

	*val = ((long)value - 80) * MILLIDEGREE_PER_DEGREE;

	return 0;
}

static int ufs_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
			  long *val)
{
	struct ufs_hwmon_data *data = dev_get_drvdata(dev);
	struct ufs_hba *hba = data->hba;
	int err;

	down(&hba->host_sem);

	if (!ufshcd_is_user_access_allowed(hba)) {
		up(&hba->host_sem);
		return -EBUSY;
	}

	ufshcd_rpm_get_sync(hba);

	switch (attr) {
	case hwmon_temp_enable:
		err = ufs_read_temp_enable(hba, data->mask, val);

		break;
	case hwmon_temp_crit:
		err = ufs_get_temp(hba, QUERY_ATTR_IDN_HIGH_TEMP_BOUND, val);

		break;
	case hwmon_temp_lcrit:
		err = ufs_get_temp(hba, QUERY_ATTR_IDN_LOW_TEMP_BOUND, val);

		break;
	case hwmon_temp_input:
		err = ufs_get_temp(hba, QUERY_ATTR_IDN_CASE_ROUGH_TEMP, val);

		break;
	default:
		err = -EOPNOTSUPP;

		break;
	}

	ufshcd_rpm_put_sync(hba);

	up(&hba->host_sem);

	return err;
}

static int ufs_hwmon_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
			   long val)
{
	struct ufs_hwmon_data *data = dev_get_drvdata(dev);
	struct ufs_hba *hba = data->hba;
	int err;

	if (attr != hwmon_temp_enable)
		return -EINVAL;

	if (val != 0 && val != 1)
		return -EINVAL;

	down(&hba->host_sem);

	if (!ufshcd_is_user_access_allowed(hba)) {
		up(&hba->host_sem);
		return -EBUSY;
	}

	ufshcd_rpm_get_sync(hba);

	if (val == 1)
		err = ufshcd_update_ee_usr_mask(hba, MASK_EE_URGENT_TEMP, 0);
	else
		err = ufshcd_update_ee_usr_mask(hba, 0, MASK_EE_URGENT_TEMP);

	ufshcd_rpm_put_sync(hba);

	up(&hba->host_sem);

	return err;
}

static umode_t ufs_hwmon_is_visible(const void *data,
				    enum hwmon_sensor_types type, u32 attr,
				    int channel)
{
	if (type != hwmon_temp)
		return 0;

	switch (attr) {
	case hwmon_temp_enable:
		return 0644;
	case hwmon_temp_crit:
	case hwmon_temp_lcrit:
	case hwmon_temp_input:
		return 0444;
	default:
		break;
	}
	return 0;
}

static const struct hwmon_channel_info *const ufs_hwmon_info[] = {
	HWMON_CHANNEL_INFO(temp, HWMON_T_ENABLE | HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_LCRIT),
	NULL
};

static const struct hwmon_ops ufs_hwmon_ops = {
	.is_visible	= ufs_hwmon_is_visible,
	.read		= ufs_hwmon_read,
	.write		= ufs_hwmon_write,
};

static const struct hwmon_chip_info ufs_hwmon_hba_info = {
	.ops	= &ufs_hwmon_ops,
	.info	= ufs_hwmon_info,
};

void ufs_hwmon_probe(struct ufs_hba *hba, u8 mask)
{
	struct device *dev = hba->dev;
	struct ufs_hwmon_data *data;
	struct device *hwmon;

	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (!data)
		return;

	data->hba = hba;
	data->mask = mask;

	hwmon = hwmon_device_register_with_info(dev, "ufs", data, &ufs_hwmon_hba_info, NULL);
	if (IS_ERR(hwmon)) {
		dev_warn(dev, "Failed to instantiate hwmon device\n");
		kfree(data);
		return;
	}

	hba->hwmon_device = hwmon;
}

void ufs_hwmon_remove(struct ufs_hba *hba)
{
	struct ufs_hwmon_data *data;

	if (!hba->hwmon_device)
		return;

	data = dev_get_drvdata(hba->hwmon_device);
	hwmon_device_unregister(hba->hwmon_device);
	hba->hwmon_device = NULL;
	kfree(data);
}

void ufs_hwmon_notify_event(struct ufs_hba *hba, u8 ee_mask)
{
	if (!hba->hwmon_device)
		return;

	if (ee_mask & MASK_EE_TOO_HIGH_TEMP)
		hwmon_notify_event(hba->hwmon_device, hwmon_temp, hwmon_temp_max_alarm, 0);

	if (ee_mask & MASK_EE_TOO_LOW_TEMP)
		hwmon_notify_event(hba->hwmon_device, hwmon_temp, hwmon_temp_min_alarm, 0);
}
