msm: buspm: Add RPM-SMD support for SPDM clocks to buspm module

For bus-profiling, SPDM clocks need to be enabled/disabled from
user-space. This can be done by sending requests through the
buspm IOCTL interface. This patch adds support to send the
SPDM requests to RPM and enables bus profiling on 8974.

Change-Id: Ic9ff04c0de2fb15513156176ad113ca5624e2f25
Signed-off-by: Gagan Mac <gmac@codeaurora.org>
diff --git a/arch/arm/mach-msm/msm-buspm-dev.c b/arch/arm/mach-msm/msm-buspm-dev.c
index a818eed..ec0f1bd 100644
--- a/arch/arm/mach-msm/msm-buspm-dev.c
+++ b/arch/arm/mach-msm/msm-buspm-dev.c
@@ -22,10 +22,17 @@
 #include <linux/uaccess.h>
 #include <linux/miscdevice.h>
 #include <linux/memory_alloc.h>
+#include <mach/rpm-smd.h>
 #include "msm-buspm-dev.h"
 
 #define MSM_BUSPM_DRV_NAME "msm-buspm-dev"
 
+enum msm_buspm_spdm_res {
+	SPDM_RES_ID = 0,
+	SPDM_RES_TYPE = 0x63707362,
+	SPDM_KEY = 0x00006e65,
+	SPDM_SIZE = 4,
+};
 /*
  * Allocate kernel buffer.
  * Currently limited to one buffer per file descriptor.  If alloc() is
@@ -113,6 +120,61 @@
 	return 0;
 }
 
+static int msm_bus_rpm_req(u32 rsc_type, u32 key, u32 hwid,
+	int ctx, u32 val)
+{
+	struct msm_rpm_request *rpm_req;
+	int ret, msg_id;
+
+	rpm_req = msm_rpm_create_request(ctx, rsc_type, SPDM_RES_ID, 1);
+	if (rpm_req == NULL) {
+		pr_err("RPM: Couldn't create RPM Request\n");
+		return -ENXIO;
+	}
+
+	ret = msm_rpm_add_kvp_data(rpm_req, key, (const uint8_t *)&val,
+		(int)(sizeof(uint32_t)));
+	if (ret) {
+		pr_err("RPM: Add KVP failed for RPM Req:%u\n",
+			rsc_type);
+		goto err;
+	}
+
+	pr_debug("Added Key: %d, Val: %u, size: %d\n", key,
+		(uint32_t)val, sizeof(uint32_t));
+	msg_id = msm_rpm_send_request(rpm_req);
+	if (!msg_id) {
+		pr_err("RPM: No message ID for req\n");
+		ret = -ENXIO;
+		goto err;
+	}
+
+	ret = msm_rpm_wait_for_ack(msg_id);
+	if (ret) {
+		pr_err("RPM: Ack failed\n");
+		goto err;
+	}
+
+err:
+	msm_rpm_free_request(rpm_req);
+	return ret;
+}
+
+static int msm_buspm_ioc_cmds(uint32_t arg)
+{
+	switch (arg) {
+	case MSM_BUSPM_SPDM_CLK_DIS:
+	case MSM_BUSPM_SPDM_CLK_EN:
+		return msm_bus_rpm_req(SPDM_RES_TYPE, SPDM_KEY, 0,
+				MSM_RPM_CTX_ACTIVE_SET, arg);
+	default:
+		pr_warn("Unsupported ioctl command: %d\n", arg);
+		return -EINVAL;
+	}
+}
+
+
+
 static long
 msm_buspm_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
@@ -124,6 +186,11 @@
 	unsigned int buflen = msm_buspm_dev_get_buflen(filp);
 	unsigned char *dbgbuf = buf;
 
+	if (_IOC_TYPE(cmd) != MSM_BUSPM_IOC_MAGIC) {
+		pr_err("Wrong IOC_MAGIC.Exiting\n");
+		return -ENOTTY;
+	}
+
 	switch (cmd) {
 	case MSM_BUSPM_IOC_FREE:
 		pr_debug("cmd = 0x%x (FREE)\n", cmd);
@@ -193,6 +260,11 @@
 		}
 		break;
 
+	case MSM_BUSPM_IOC_CMD:
+		pr_debug("IOCTL command: cmd: %d arg: %lu\n", cmd, arg);
+		retval = msm_buspm_ioc_cmds(arg);
+		break;
+
 	default:
 		pr_debug("Unknown command 0x%x\n", cmd);
 		retval = -EINVAL;