/*
 * Copyright 2017-2018 NXP
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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/err.h>
#include <linux/slab.h>
#include <linux/imx_rpmsg.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_qos.h>
#include <linux/reboot.h>
#include <linux/rpmsg.h>
#include <linux/uaccess.h>
#include <linux/virtio.h>
#include "common.h"

#define RPMSG_TIMEOUT 1000

#define PM_RPMSG_TYPE		0
#define HEATBEAT_RPMSG_TYPE	2

enum pm_rpmsg_cmd {
	PM_RPMSG_MODE,
	PM_RPMSG_HEART_BEAT,
	PM_RPMSG_HEART_BEAT_OFF,
};

enum pm_rpmsg_power_mode {
	PM_RPMSG_HSRUN,
	PM_RPMSG_RUN,
	PM_RPMSG_VLPR,
	PM_RPMSG_WAIT,
	PM_RPMSG_VLPS,
	PM_RPMSG_VLLS,
	PM_RPMSG_REBOOT,
	PM_RPMSG_SHUTDOWN,
};

struct pm_rpmsg_info {
	struct rpmsg_device *rpdev;
	struct device *dev;
	struct pm_rpmsg_data *msg;
	struct pm_qos_request pm_qos_req;
	struct notifier_block restart_handler;
	struct completion cmd_complete;
	bool first_flag;
	struct mutex lock;
};

static struct pm_rpmsg_info pm_rpmsg;

static struct delayed_work heart_beat_work;

static bool heartbeat_off;

struct pm_rpmsg_data {
	struct imx_rpmsg_head header;
	u8 data;
} __attribute__ ((packed));

static int pm_send_message(struct pm_rpmsg_data *msg,
			struct pm_rpmsg_info *info, bool ack)
{
	int err;

	if (!info->rpdev) {
		dev_dbg(info->dev,
			"rpmsg channel not ready, m4 image ready?\n");
		return -EINVAL;
	}

	mutex_lock(&info->lock);
	pm_qos_add_request(&info->pm_qos_req,
			PM_QOS_CPU_DMA_LATENCY, 0);

	reinit_completion(&info->cmd_complete);

	err = rpmsg_send(info->rpdev->ept, (void *)msg,
			    sizeof(struct pm_rpmsg_data));

	if (err) {
		dev_err(&info->rpdev->dev, "rpmsg_send failed: %d\n", err);
		goto err_out;
	}

	if (ack) {
		err = wait_for_completion_timeout(&info->cmd_complete,
					msecs_to_jiffies(RPMSG_TIMEOUT));
		if (!err) {
			dev_err(&info->rpdev->dev, "rpmsg_send timeout!\n");
			err = -ETIMEDOUT;
			goto err_out;
		}

		if (info->msg->data != 0) {
			dev_err(&info->rpdev->dev, "rpmsg not ack %d!\n",
				info->msg->data);
			err = -EINVAL;
			goto err_out;
		}

		err = 0;
	}

err_out:
	pm_qos_remove_request(&info->pm_qos_req);
	mutex_unlock(&info->lock);

	return err;
}

static int pm_vlls_notify_m4(bool enter)
{
	struct pm_rpmsg_data msg;

	msg.header.cate = IMX_RMPSG_LIFECYCLE;
	msg.header.major = IMX_RMPSG_MAJOR;
	msg.header.minor = IMX_RMPSG_MINOR;
	msg.header.type = PM_RPMSG_TYPE;
	msg.header.cmd = PM_RPMSG_MODE;
	msg.data = enter ? PM_RPMSG_VLLS : PM_RPMSG_RUN;

	return pm_send_message(&msg, &pm_rpmsg, true);
}

void pm_shutdown_notify_m4(void)
{
	struct pm_rpmsg_data msg;

	msg.header.cate = IMX_RMPSG_LIFECYCLE;
	msg.header.major = IMX_RMPSG_MAJOR;
	msg.header.minor = IMX_RMPSG_MINOR;
	msg.header.type = PM_RPMSG_TYPE;
	msg.header.cmd = PM_RPMSG_MODE;
	msg.data = PM_RPMSG_SHUTDOWN;
	/* No ACK from M4 */
	pm_send_message(&msg, &pm_rpmsg, false);

	imx7ulp_poweroff();
}

void pm_reboot_notify_m4(void)
{
	struct pm_rpmsg_data msg;

	msg.header.cate = IMX_RMPSG_LIFECYCLE;
	msg.header.major = IMX_RMPSG_MAJOR;
	msg.header.minor = IMX_RMPSG_MINOR;
	msg.header.type = PM_RPMSG_TYPE;
	msg.header.cmd = PM_RPMSG_MODE;
	msg.data = PM_RPMSG_REBOOT;

	pm_send_message(&msg, &pm_rpmsg, true);

}

void  pm_heartbeat_off_notify_m4(bool enter)
{
	struct pm_rpmsg_data msg;

	msg.header.cate = IMX_RMPSG_LIFECYCLE;
	msg.header.major = IMX_RMPSG_MAJOR;
	msg.header.minor = IMX_RMPSG_MINOR;
	msg.header.type = PM_RPMSG_TYPE;
	msg.header.cmd = PM_RPMSG_HEART_BEAT_OFF;
	msg.data = enter ? 0 : 1;

	pm_send_message(&msg, &pm_rpmsg, true);
}

static void pm_heart_beat_work_handler(struct work_struct *work)
{
	struct pm_rpmsg_data msg;

	/* Notify M4 side A7 in RUN mode at boot time */
	if (pm_rpmsg.first_flag) {
		pm_vlls_notify_m4(false);

		pm_heartbeat_off_notify_m4(heartbeat_off);

		pm_rpmsg.first_flag = false;
	}

	if (!heartbeat_off) {
		msg.header.cate = IMX_RMPSG_LIFECYCLE;
		msg.header.major = IMX_RMPSG_MAJOR;
		msg.header.minor = IMX_RMPSG_MINOR;
		msg.header.type = HEATBEAT_RPMSG_TYPE;
		msg.header.cmd = PM_RPMSG_HEART_BEAT;
		msg.data = 0;
		pm_send_message(&msg, &pm_rpmsg, false);

		schedule_delayed_work(&heart_beat_work,
			msecs_to_jiffies(30000));
	}
}

static void pm_poweroff_rpmsg(void)
{
	pm_shutdown_notify_m4();
	pr_emerg("Unable to poweroff system\n");
}

static int pm_restart_handler(struct notifier_block *this, unsigned long mode,
				void *cmd)
{
	pm_reboot_notify_m4();

	return NOTIFY_DONE;
}

static int pm_rpmsg_probe(struct rpmsg_device *rpdev)
{
	int ret;

	pm_rpmsg.rpdev = rpdev;

	dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
			rpdev->src, rpdev->dst);

	init_completion(&pm_rpmsg.cmd_complete);
	mutex_init(&pm_rpmsg.lock);

	INIT_DELAYED_WORK(&heart_beat_work,
		pm_heart_beat_work_handler);

	pm_rpmsg.first_flag = true;
	schedule_delayed_work(&heart_beat_work, 0);

	pm_rpmsg.restart_handler.notifier_call = pm_restart_handler;
	pm_rpmsg.restart_handler.priority = 128;
	ret = register_restart_handler(&pm_rpmsg.restart_handler);
	if (ret)
		dev_err(&rpdev->dev, "cannot register restart handler\n");

	pm_power_off = pm_poweroff_rpmsg;

	return 0;
}

static int pm_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
			void *priv, u32 src)
{
	struct pm_rpmsg_data *msg = (struct pm_rpmsg_data *)data;

	pm_rpmsg.msg = msg;

	complete(&pm_rpmsg.cmd_complete);

	return 0;
}

static void pm_rpmsg_remove(struct rpmsg_device *rpdev)
{
	dev_info(&rpdev->dev, "pm rpmsg driver is removed\n");
}

static struct rpmsg_device_id pm_rpmsg_id_table[] = {
	{ .name	= "rpmsg-life-cycle-channel" },
	{ },
};

static struct rpmsg_driver pm_rpmsg_driver = {
	.drv.name	= "pm_rpmsg",
	.drv.owner	= THIS_MODULE,
	.id_table	= pm_rpmsg_id_table,
	.probe		= pm_rpmsg_probe,
	.callback	= pm_rpmsg_cb,
	.remove		= pm_rpmsg_remove,
};

#ifdef CONFIG_PM_SLEEP
static int pm_heartbeat_suspend(struct device *dev)
{
	int err;

	err = pm_vlls_notify_m4(true);
	if (err)
		return err;

	cancel_delayed_work_sync(&heart_beat_work);

	return 0;
}

static int pm_heartbeat_resume(struct device *dev)
{
	int err;

	err = pm_vlls_notify_m4(false);
	if (err)
		return err;

	schedule_delayed_work(&heart_beat_work,
			msecs_to_jiffies(10000));

	return 0;
}
#endif

static int pm_heartbeat_probe(struct platform_device *pdev)
{
	platform_set_drvdata(pdev, &pm_rpmsg);

	return register_rpmsg_driver(&pm_rpmsg_driver);
}

static const struct of_device_id pm_heartbeat_id[] = {
	{"fsl,heartbeat-rpmsg",},
	{},
};
MODULE_DEVICE_TABLE(of, pm_heartbeat_id);

static const struct dev_pm_ops pm_heartbeat_ops = {
	 SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_heartbeat_suspend,
				      pm_heartbeat_resume)
};

static struct platform_driver pm_heartbeat_driver = {
	.driver = {
		.name = "heartbeat-rpmsg",
		.owner = THIS_MODULE,
		.of_match_table = pm_heartbeat_id,
		.pm = &pm_heartbeat_ops,
		},
	.probe = pm_heartbeat_probe,
};

static int __init setup_heartbeat(char *str)
{
	heartbeat_off = true;

	return 1;
};
__setup("heartbeat_off", setup_heartbeat);

module_platform_driver(pm_heartbeat_driver);

MODULE_DESCRIPTION("Freescale PM rpmsg driver");
MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>");
MODULE_LICENSE("GPL");
