// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved.
 */

#include "ssp.h"

#define SSP_DEV (&data->spi->dev)
#define SSP_GET_MESSAGE_TYPE(data) (data & (3 << SSP_RW))

/*
 * SSP -> AP Instruction
 * They tell what packet type can be expected. In the future there will
 * be less of them. BYPASS means common sensor packets with accel, gyro,
 * hrm etc. data. LIBRARY and META are mock-up's for now.
 */
#define SSP_MSG2AP_INST_BYPASS_DATA		0x37
#define SSP_MSG2AP_INST_LIBRARY_DATA		0x01
#define SSP_MSG2AP_INST_DEBUG_DATA		0x03
#define SSP_MSG2AP_INST_BIG_DATA		0x04
#define SSP_MSG2AP_INST_META_DATA		0x05
#define SSP_MSG2AP_INST_TIME_SYNC		0x06
#define SSP_MSG2AP_INST_RESET			0x07

#define SSP_UNIMPLEMENTED -1

struct ssp_msg_header {
	u8 cmd;
	__le16 length;
	__le16 options;
	__le32 data;
} __attribute__((__packed__));

struct ssp_msg {
	u16 length;
	u16 options;
	struct list_head list;
	struct completion *done;
	struct ssp_msg_header *h;
	char *buffer;
};

static const int ssp_offset_map[SSP_SENSOR_MAX] = {
	[SSP_ACCELEROMETER_SENSOR] =		SSP_ACCELEROMETER_SIZE +
						SSP_TIME_SIZE,
	[SSP_GYROSCOPE_SENSOR] =		SSP_GYROSCOPE_SIZE +
						SSP_TIME_SIZE,
	[SSP_GEOMAGNETIC_UNCALIB_SENSOR] =	SSP_UNIMPLEMENTED,
	[SSP_GEOMAGNETIC_RAW] =			SSP_UNIMPLEMENTED,
	[SSP_GEOMAGNETIC_SENSOR] =		SSP_UNIMPLEMENTED,
	[SSP_PRESSURE_SENSOR] =			SSP_UNIMPLEMENTED,
	[SSP_GESTURE_SENSOR] =			SSP_UNIMPLEMENTED,
	[SSP_PROXIMITY_SENSOR] =		SSP_UNIMPLEMENTED,
	[SSP_TEMPERATURE_HUMIDITY_SENSOR] =	SSP_UNIMPLEMENTED,
	[SSP_LIGHT_SENSOR] =			SSP_UNIMPLEMENTED,
	[SSP_PROXIMITY_RAW] =			SSP_UNIMPLEMENTED,
	[SSP_ORIENTATION_SENSOR] =		SSP_UNIMPLEMENTED,
	[SSP_STEP_DETECTOR] =			SSP_UNIMPLEMENTED,
	[SSP_SIG_MOTION_SENSOR] =		SSP_UNIMPLEMENTED,
	[SSP_GYRO_UNCALIB_SENSOR] =		SSP_UNIMPLEMENTED,
	[SSP_GAME_ROTATION_VECTOR] =		SSP_UNIMPLEMENTED,
	[SSP_ROTATION_VECTOR] =			SSP_UNIMPLEMENTED,
	[SSP_STEP_COUNTER] =			SSP_UNIMPLEMENTED,
	[SSP_BIO_HRM_RAW] =			SSP_BIO_HRM_RAW_SIZE +
						SSP_TIME_SIZE,
	[SSP_BIO_HRM_RAW_FAC] =			SSP_BIO_HRM_RAW_FAC_SIZE +
						SSP_TIME_SIZE,
	[SSP_BIO_HRM_LIB] =			SSP_BIO_HRM_LIB_SIZE +
						SSP_TIME_SIZE,
};

#define SSP_HEADER_SIZE		(sizeof(struct ssp_msg_header))
#define SSP_HEADER_SIZE_ALIGNED	(ALIGN(SSP_HEADER_SIZE, 4))

static struct ssp_msg *ssp_create_msg(u8 cmd, u16 len, u16 opt, u32 data)
{
	struct ssp_msg_header h;
	struct ssp_msg *msg;

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

	h.cmd = cmd;
	h.length = cpu_to_le16(len);
	h.options = cpu_to_le16(opt);
	h.data = cpu_to_le32(data);

	msg->buffer = kzalloc(SSP_HEADER_SIZE_ALIGNED + len,
			      GFP_KERNEL | GFP_DMA);
	if (!msg->buffer) {
		kfree(msg);
		return NULL;
	}

	msg->length = len;
	msg->options = opt;

	memcpy(msg->buffer, &h, SSP_HEADER_SIZE);

	return msg;
}

/*
 * It is a bit heavy to do it this way but often the function is used to compose
 * the message from smaller chunks which are placed on the stack.  Often the
 * chunks are small so memcpy should be optimalized.
 */
static inline void ssp_fill_buffer(struct ssp_msg *m, unsigned int offset,
				   const void *src, unsigned int len)
{
	memcpy(&m->buffer[SSP_HEADER_SIZE_ALIGNED + offset], src, len);
}

static inline void ssp_get_buffer(struct ssp_msg *m, unsigned int offset,
				  void *dest, unsigned int len)
{
	memcpy(dest, &m->buffer[SSP_HEADER_SIZE_ALIGNED + offset],  len);
}

#define SSP_GET_BUFFER_AT_INDEX(m, index) \
	(m->buffer[SSP_HEADER_SIZE_ALIGNED + index])
#define SSP_SET_BUFFER_AT_INDEX(m, index, val) \
	(m->buffer[SSP_HEADER_SIZE_ALIGNED + index] = val)

static void ssp_clean_msg(struct ssp_msg *m)
{
	kfree(m->buffer);
	kfree(m);
}

static int ssp_print_mcu_debug(char *data_frame, int *data_index,
			       int received_len)
{
	int length = data_frame[(*data_index)++];

	if (length > received_len - *data_index || length <= 0) {
		ssp_dbg("[SSP]: MSG From MCU-invalid debug length(%d/%d)\n",
			length, received_len);
		return -EPROTO;
	}

	ssp_dbg("[SSP]: MSG From MCU - %s\n", &data_frame[*data_index]);

	*data_index += length;

	return 0;
}

/*
 * It was designed that way - additional lines to some kind of handshake,
 * please do not ask why - only the firmware guy can know it.
 */
static int ssp_check_lines(struct ssp_data *data, bool state)
{
	int delay_cnt = 0;

	gpiod_set_value_cansleep(data->ap_mcu_gpiod, state);

	while (gpiod_get_value_cansleep(data->mcu_ap_gpiod) != state) {
		usleep_range(3000, 3500);

		if (data->shut_down || delay_cnt++ > 500) {
			dev_err(SSP_DEV, "%s:timeout, hw ack wait fail %d\n",
				__func__, state);

			if (!state)
				gpiod_set_value_cansleep(data->ap_mcu_gpiod, 1);

			return -ETIMEDOUT;
		}
	}

	return 0;
}

static int ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg,
			   struct completion *done, int timeout)
{
	int status;
	/*
	 * check if this is a short one way message or the whole transfer has
	 * second part after an interrupt
	 */
	const bool use_no_irq = msg->length == 0;

	if (data->shut_down)
		return -EPERM;

	msg->done = done;

	mutex_lock(&data->comm_lock);

	status = ssp_check_lines(data, false);
	if (status < 0)
		goto _error_locked;

	status = spi_write(data->spi, msg->buffer, SSP_HEADER_SIZE);
	if (status < 0) {
		gpiod_set_value_cansleep(data->ap_mcu_gpiod, 1);
		dev_err(SSP_DEV, "%s spi_write fail\n", __func__);
		goto _error_locked;
	}

	if (!use_no_irq) {
		mutex_lock(&data->pending_lock);
		list_add_tail(&msg->list, &data->pending_list);
		mutex_unlock(&data->pending_lock);
	}

	status = ssp_check_lines(data, true);
	if (status < 0) {
		if (!use_no_irq) {
			mutex_lock(&data->pending_lock);
			list_del(&msg->list);
			mutex_unlock(&data->pending_lock);
		}
		goto _error_locked;
	}

	mutex_unlock(&data->comm_lock);

	if (!use_no_irq && done)
		if (wait_for_completion_timeout(done,
						msecs_to_jiffies(timeout)) ==
		    0) {
			mutex_lock(&data->pending_lock);
			list_del(&msg->list);
			mutex_unlock(&data->pending_lock);

			data->timeout_cnt++;
			return -ETIMEDOUT;
		}

	return 0;

_error_locked:
	mutex_unlock(&data->comm_lock);
	data->timeout_cnt++;
	return status;
}

static inline int ssp_spi_sync_command(struct ssp_data *data,
				       struct ssp_msg *msg)
{
	return ssp_do_transfer(data, msg, NULL, 0);
}

static int ssp_spi_sync(struct ssp_data *data, struct ssp_msg *msg,
			int timeout)
{
	DECLARE_COMPLETION_ONSTACK(done);

	if (WARN_ON(!msg->length))
		return -EPERM;

	return ssp_do_transfer(data, msg, &done, timeout);
}

static int ssp_handle_big_data(struct ssp_data *data, char *dataframe, int *idx)
{
	/* mock-up, it will be changed with adding another sensor types */
	*idx += 8;
	return 0;
}

static int ssp_parse_dataframe(struct ssp_data *data, char *dataframe, int len)
{
	int idx, sd;
	struct ssp_sensor_data *spd;
	struct iio_dev **indio_devs = data->sensor_devs;

	for (idx = 0; idx < len;) {
		switch (dataframe[idx++]) {
		case SSP_MSG2AP_INST_BYPASS_DATA:
			if (idx >= len)
				return -EPROTO;
			sd = dataframe[idx++];
			if (sd < 0 || sd >= SSP_SENSOR_MAX) {
				dev_err(SSP_DEV,
					"Mcu data frame1 error %d\n", sd);
				return -EPROTO;
			}

			if (indio_devs[sd]) {
				spd = iio_priv(indio_devs[sd]);
				if (spd->process_data) {
					if (idx >= len)
						return -EPROTO;
					spd->process_data(indio_devs[sd],
							  &dataframe[idx],
							  data->timestamp);
				}
			} else {
				dev_err(SSP_DEV, "no client for frame\n");
			}

			idx += ssp_offset_map[sd];
			break;
		case SSP_MSG2AP_INST_DEBUG_DATA:
			if (idx >= len)
				return -EPROTO;
			sd = ssp_print_mcu_debug(dataframe, &idx, len);
			if (sd) {
				dev_err(SSP_DEV,
					"Mcu data frame3 error %d\n", sd);
				return sd;
			}
			break;
		case SSP_MSG2AP_INST_LIBRARY_DATA:
			idx += len;
			break;
		case SSP_MSG2AP_INST_BIG_DATA:
			ssp_handle_big_data(data, dataframe, &idx);
			break;
		case SSP_MSG2AP_INST_TIME_SYNC:
			data->time_syncing = true;
			break;
		case SSP_MSG2AP_INST_RESET:
			ssp_queue_ssp_refresh_task(data, 0);
			break;
		}
	}

	if (data->time_syncing)
		data->timestamp = ktime_get_real_ns();

	return 0;
}

/* threaded irq */
int ssp_irq_msg(struct ssp_data *data)
{
	char *buffer;
	u8 msg_type;
	int ret;
	u16 length, msg_options;
	struct ssp_msg *msg = NULL, *iter, *n;

	ret = spi_read(data->spi, data->header_buffer, SSP_HEADER_BUFFER_SIZE);
	if (ret < 0) {
		dev_err(SSP_DEV, "header read fail\n");
		return ret;
	}

	length = le16_to_cpu(data->header_buffer[1]);
	msg_options = le16_to_cpu(data->header_buffer[0]);

	if (length == 0) {
		dev_err(SSP_DEV, "length received from mcu is 0\n");
		return -EINVAL;
	}

	msg_type = SSP_GET_MESSAGE_TYPE(msg_options);

	switch (msg_type) {
	case SSP_AP2HUB_READ:
	case SSP_AP2HUB_WRITE:
		/*
		 * this is a small list, a few elements - the packets can be
		 * received with no order
		 */
		mutex_lock(&data->pending_lock);
		list_for_each_entry_safe(iter, n, &data->pending_list, list) {
			if (iter->options == msg_options) {
				list_del(&iter->list);
				msg = iter;
				break;
			}
		}

		if (!msg) {
			/*
			 * here can be implemented dead messages handling
			 * but the slave should not send such ones - it is to
			 * check but let's handle this
			 */
			buffer = kmalloc(length, GFP_KERNEL | GFP_DMA);
			if (!buffer) {
				ret = -ENOMEM;
				goto _unlock;
			}

			/* got dead packet so it is always an error */
			ret = spi_read(data->spi, buffer, length);
			if (ret >= 0)
				ret = -EPROTO;

			kfree(buffer);

			dev_err(SSP_DEV, "No match error %x\n",
				msg_options);

			goto _unlock;
		}

		if (msg_type == SSP_AP2HUB_READ)
			ret = spi_read(data->spi,
				       &msg->buffer[SSP_HEADER_SIZE_ALIGNED],
				       msg->length);

		if (msg_type == SSP_AP2HUB_WRITE) {
			ret = spi_write(data->spi,
					&msg->buffer[SSP_HEADER_SIZE_ALIGNED],
					msg->length);
			if (msg_options & SSP_AP2HUB_RETURN) {
				msg->options =
					SSP_AP2HUB_READ | SSP_AP2HUB_RETURN;
				msg->length = 1;

				list_add_tail(&msg->list, &data->pending_list);
				goto _unlock;
			}
		}

		if (msg->done)
			if (!completion_done(msg->done))
				complete(msg->done);
_unlock:
		mutex_unlock(&data->pending_lock);
		break;
	case SSP_HUB2AP_WRITE:
		buffer = kzalloc(length, GFP_KERNEL | GFP_DMA);
		if (!buffer)
			return -ENOMEM;

		ret = spi_read(data->spi, buffer, length);
		if (ret < 0) {
			dev_err(SSP_DEV, "spi read fail\n");
			kfree(buffer);
			break;
		}

		ret = ssp_parse_dataframe(data, buffer, length);

		kfree(buffer);
		break;

	default:
		dev_err(SSP_DEV, "unknown msg type\n");
		return -EPROTO;
	}

	return ret;
}

void ssp_clean_pending_list(struct ssp_data *data)
{
	struct ssp_msg *msg, *n;

	mutex_lock(&data->pending_lock);
	list_for_each_entry_safe(msg, n, &data->pending_list, list) {
		list_del(&msg->list);

		if (msg->done)
			if (!completion_done(msg->done))
				complete(msg->done);
	}
	mutex_unlock(&data->pending_lock);
}

int ssp_command(struct ssp_data *data, char command, int arg)
{
	int ret;
	struct ssp_msg *msg;

	msg = ssp_create_msg(command, 0, SSP_AP2HUB_WRITE, arg);
	if (!msg)
		return -ENOMEM;

	ssp_dbg("%s - command 0x%x %d\n", __func__, command, arg);

	ret = ssp_spi_sync_command(data, msg);
	ssp_clean_msg(msg);

	return ret;
}

int ssp_send_instruction(struct ssp_data *data, u8 inst, u8 sensor_type,
			 u8 *send_buf, u8 length)
{
	int ret;
	struct ssp_msg *msg;

	if (data->fw_dl_state == SSP_FW_DL_STATE_DOWNLOADING) {
		dev_err(SSP_DEV, "%s - Skip Inst! DL state = %d\n",
			__func__, data->fw_dl_state);
		return -EBUSY;
	} else if (!(data->available_sensors & BIT(sensor_type)) &&
		   (inst <= SSP_MSG2SSP_INST_CHANGE_DELAY)) {
		dev_err(SSP_DEV, "%s - Bypass Inst Skip! - %u\n",
			__func__, sensor_type);
		return -EIO; /* just fail */
	}

	msg = ssp_create_msg(inst, length + 2, SSP_AP2HUB_WRITE, 0);
	if (!msg)
		return -ENOMEM;

	ssp_fill_buffer(msg, 0, &sensor_type, 1);
	ssp_fill_buffer(msg, 1, send_buf, length);

	ssp_dbg("%s - Inst = 0x%x, Sensor Type = 0x%x, data = %u\n",
		__func__, inst, sensor_type, send_buf[1]);

	ret = ssp_spi_sync(data, msg, 1000);
	ssp_clean_msg(msg);

	return ret;
}

int ssp_get_chipid(struct ssp_data *data)
{
	int ret;
	char buffer;
	struct ssp_msg *msg;

	msg = ssp_create_msg(SSP_MSG2SSP_AP_WHOAMI, 1, SSP_AP2HUB_READ, 0);
	if (!msg)
		return -ENOMEM;

	ret = ssp_spi_sync(data, msg, 1000);

	buffer = SSP_GET_BUFFER_AT_INDEX(msg, 0);

	ssp_clean_msg(msg);

	return ret < 0 ? ret : buffer;
}

int ssp_set_magnetic_matrix(struct ssp_data *data)
{
	int ret;
	struct ssp_msg *msg;

	msg = ssp_create_msg(SSP_MSG2SSP_AP_SET_MAGNETIC_STATIC_MATRIX,
			     data->sensorhub_info->mag_length, SSP_AP2HUB_WRITE,
			     0);
	if (!msg)
		return -ENOMEM;

	ssp_fill_buffer(msg, 0, data->sensorhub_info->mag_table,
			data->sensorhub_info->mag_length);

	ret = ssp_spi_sync(data, msg, 1000);
	ssp_clean_msg(msg);

	return ret;
}

unsigned int ssp_get_sensor_scanning_info(struct ssp_data *data)
{
	int ret;
	__le32 result;
	u32 cpu_result = 0;

	struct ssp_msg *msg = ssp_create_msg(SSP_MSG2SSP_AP_SENSOR_SCANNING, 4,
					     SSP_AP2HUB_READ, 0);
	if (!msg)
		return 0;

	ret = ssp_spi_sync(data, msg, 1000);
	if (ret < 0) {
		dev_err(SSP_DEV, "%s - spi read fail %d\n", __func__, ret);
		goto _exit;
	}

	ssp_get_buffer(msg, 0, &result, 4);
	cpu_result = le32_to_cpu(result);

	dev_info(SSP_DEV, "%s state: 0x%08x\n", __func__, cpu_result);

_exit:
	ssp_clean_msg(msg);
	return cpu_result;
}

unsigned int ssp_get_firmware_rev(struct ssp_data *data)
{
	int ret;
	__le32 result;

	struct ssp_msg *msg = ssp_create_msg(SSP_MSG2SSP_AP_FIRMWARE_REV, 4,
					     SSP_AP2HUB_READ, 0);
	if (!msg)
		return SSP_INVALID_REVISION;

	ret = ssp_spi_sync(data, msg, 1000);
	if (ret < 0) {
		dev_err(SSP_DEV, "%s - transfer fail %d\n", __func__, ret);
		ret = SSP_INVALID_REVISION;
		goto _exit;
	}

	ssp_get_buffer(msg, 0, &result, 4);
	ret = le32_to_cpu(result);

_exit:
	ssp_clean_msg(msg);
	return ret;
}
