// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * AMD MP2 1.1 communication interfaces
 *
 * Copyright (c) 2022, Advanced Micro Devices, Inc.
 * All Rights Reserved.
 *
 * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
 */
#include <linux/amd-pmf-io.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/iopoll.h>

#include "amd_sfh_interface.h"

static struct amd_mp2_dev *emp2;

static int amd_sfh_wait_response(struct amd_mp2_dev *mp2, u8 sid, u32 cmd_id)
{
	struct sfh_cmd_response cmd_resp;

	/* Get response with status within a max of 10000 ms timeout */
	if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp,
				(cmd_resp.response.response == 0 &&
				cmd_resp.response.cmd_id == cmd_id && (sid == 0xff ||
				cmd_resp.response.sensor_id == sid)), 500, 10000000))
		return cmd_resp.response.response;

	return -1;
}

static void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
{
	struct sfh_cmd_base cmd_base;

	cmd_base.ul = 0;
	cmd_base.cmd.cmd_id = ENABLE_SENSOR;
	cmd_base.cmd.intr_disable = 0;
	cmd_base.cmd.sub_cmd_value = 1;
	cmd_base.cmd.sensor_id = info.sensor_idx;

	writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG(0));
}

static void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx)
{
	struct sfh_cmd_base cmd_base;

	cmd_base.ul = 0;
	cmd_base.cmd.cmd_id = DISABLE_SENSOR;
	cmd_base.cmd.intr_disable = 0;
	cmd_base.cmd.sub_cmd_value = 1;
	cmd_base.cmd.sensor_id = sensor_idx;

	writeq(0x0, privdata->mmio + AMD_C2P_MSG(1));
	writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG(0));
}

static void amd_stop_all_sensor(struct amd_mp2_dev *privdata)
{
	struct sfh_cmd_base cmd_base;

	cmd_base.ul = 0;
	cmd_base.cmd.cmd_id = DISABLE_SENSOR;
	cmd_base.cmd.intr_disable = 0;
	/* 0xf indicates all sensors */
	cmd_base.cmd.sensor_id = 0xf;

	writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG(0));
}

static struct amd_mp2_ops amd_sfh_ops = {
	.start = amd_start_sensor,
	.stop = amd_stop_sensor,
	.stop_all = amd_stop_all_sensor,
	.response = amd_sfh_wait_response,
};

void sfh_deinit_emp2(void)
{
	emp2 = NULL;
}

void sfh_interface_init(struct amd_mp2_dev *mp2)
{
	mp2->mp2_ops = &amd_sfh_ops;
	emp2 = mp2;
}

static int amd_sfh_hpd_info(u8 *user_present)
{
	struct hpd_status hpdstatus;

	if (!user_present)
		return -EINVAL;

	if (!emp2 || !emp2->dev_en.is_hpd_present)
		return -ENODEV;

	hpdstatus.val = readl(emp2->mmio + AMD_C2P_MSG(4));
	*user_present = hpdstatus.shpd.presence;

	return 0;
}

static int amd_sfh_als_info(u32 *ambient_light)
{
	struct sfh_als_data als_data;
	void __iomem *sensoraddr;

	if (!ambient_light)
		return -EINVAL;

	if (!emp2 || !emp2->dev_en.is_als_present)
		return -ENODEV;

	sensoraddr = emp2->vsbase +
		(ALS_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +
		OFFSET_SENSOR_DATA_DEFAULT;
	memcpy_fromio(&als_data, sensoraddr, sizeof(struct sfh_als_data));
	*ambient_light = amd_sfh_float_to_int(als_data.lux);

	return 0;
}

int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op)
{
	if (sfh_info) {
		switch (op) {
		case MT_HPD:
			return amd_sfh_hpd_info(&sfh_info->user_present);
		case MT_ALS:
			return amd_sfh_als_info(&sfh_info->ambient_light);
		}
	}
	return -EINVAL;
}
EXPORT_SYMBOL_GPL(amd_get_sfh_info);
