msm: scm-pas: Request bandwidth for auth_and_reset()

The secure processor doesn't have the capability to request
bandwidth itself. Add bandwidth requests for it so that
performance doesn't suffer.

The bus driver is lacking a couple features:

 (1) No control of daytona fabric

 (2) No endpoints for the crypto engine on the daytona fabric

Solve (1) with a clock voter on daytona fabric and (2) with a
bandwidth request for SPS which lives on the daytona fabric.

Change-Id: Ib6ca67043bc3b97dbbecb1b571c4d33721fae11c
CRs-Fixed: 319454
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index b207a72..5521c64 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -4753,6 +4753,7 @@
 static DEFINE_CLK_VOTER(dfab_sdc5_clk, &dfab_clk.c);
 static DEFINE_CLK_VOTER(dfab_sps_clk, &dfab_clk.c);
 static DEFINE_CLK_VOTER(dfab_bam_dmux_clk, &dfab_clk.c);
+static DEFINE_CLK_VOTER(dfab_scm_clk, &dfab_clk.c);
 
 static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c);
 /*
@@ -5375,6 +5376,7 @@
 	CLK_DUMMY("bus_clk",		DFAB_SDC3_CLK,		NULL, 0),
 	CLK_DUMMY("bus_clk",		DFAB_SDC4_CLK,		NULL, 0),
 	CLK_DUMMY("dfab_clk",		DFAB_CLK,		NULL, 0),
+	CLK_DUMMY("bus_clk",		DFAB_SCM_CLK,	"scm", 0),
 	CLK_LOOKUP("usb_hsic_xcvr_fs_clk", usb_hsic_xcvr_fs_clk.c,	NULL),
 	CLK_LOOKUP("usb_hsic_hsic_clk", usb_hsic_hsic_clk.c,	NULL),
 	CLK_LOOKUP("usb_hsic_hsio_cal_clk", usb_hsic_hsio_cal_clk.c,	NULL),
@@ -5625,6 +5627,7 @@
 	CLK_LOOKUP("bus_clk",		dfab_sdc5_clk.c, "msm_sdcc.5"),
 	CLK_LOOKUP("dfab_clk",		dfab_sps_clk.c,	"msm_sps"),
 	CLK_LOOKUP("bus_clk",		dfab_bam_dmux_clk.c,	"BAM_RMNT"),
+	CLK_LOOKUP("bus_clk",		dfab_scm_clk.c,	"scm"),
 
 	CLK_LOOKUP("mem_clk",		ebi1_adm_clk.c, "msm_dmov"),
 
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 9201330..9af21d3 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3209,6 +3209,7 @@
 static DEFINE_CLK_VOTER(dfab_sdc3_clk, &dfab_clk.c);
 static DEFINE_CLK_VOTER(dfab_sdc4_clk, &dfab_clk.c);
 static DEFINE_CLK_VOTER(dfab_sdc5_clk, &dfab_clk.c);
+static DEFINE_CLK_VOTER(dfab_scm_clk, &dfab_clk.c);
 
 static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c);
 static DEFINE_CLK_VOTER(ebi1_adm0_clk,   &ebi1_clk.c);
@@ -3788,6 +3789,7 @@
 	CLK_LOOKUP("bus_clk",		dfab_sdc3_clk.c, "msm_sdcc.3"),
 	CLK_LOOKUP("bus_clk",		dfab_sdc4_clk.c, "msm_sdcc.4"),
 	CLK_LOOKUP("bus_clk",		dfab_sdc5_clk.c, "msm_sdcc.5"),
+	CLK_LOOKUP("bus_clk",		dfab_scm_clk.c,	"scm"),
 
 	CLK_LOOKUP("mem_clk",		ebi1_adm0_clk.c, "msm_dmov.0"),
 	CLK_LOOKUP("mem_clk",		ebi1_adm1_clk.c, "msm_dmov.1"),
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index 5bbffd3..eaaa66d 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -10,12 +10,17 @@
  * GNU General Public License for more details.
  */
 
+#define pr_fmt(fmt) "scm-pas: " fmt
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/clk.h>
 
 #include <mach/scm.h>
 #include <mach/socinfo.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
 #include "scm-pas.h"
 
 #define PAS_INIT_IMAGE_CMD	1
@@ -50,15 +55,89 @@
 }
 EXPORT_SYMBOL(pas_init_image);
 
+static struct msm_bus_paths scm_pas_bw_tbl[] = {
+	{
+		.vectors = (struct msm_bus_vectors[]){
+			{
+				.src = MSM_BUS_MASTER_SPS,
+				.dst = MSM_BUS_SLAVE_EBI_CH0,
+			},
+		},
+		.num_paths = 1,
+	},
+	{
+		.vectors = (struct msm_bus_vectors[]){
+			{
+				.src = MSM_BUS_MASTER_SPS,
+				.dst = MSM_BUS_SLAVE_EBI_CH0,
+				.ib = 492 * 8 * 1000000UL,
+				.ab = 492 * 8 *  100000UL,
+			},
+		},
+		.num_paths = 1,
+	},
+};
+
+static struct msm_bus_scale_pdata scm_pas_bus_pdata = {
+	.usecase = scm_pas_bw_tbl,
+	.num_usecases = ARRAY_SIZE(scm_pas_bw_tbl),
+	.name = "scm_pas",
+};
+
+static uint32_t scm_perf_client;
+static struct clk *scm_bus_clk;
+
+static DEFINE_MUTEX(scm_pas_bw_mutex);
+static int scm_pas_bw_count;
+
+static int scm_pas_enable_bw(void)
+{
+	int ret = 0;
+
+	if (!scm_perf_client || scm_bus_clk)
+		return -EINVAL;
+
+	mutex_lock(&scm_pas_bw_mutex);
+	if (!scm_pas_bw_count) {
+		ret = msm_bus_scale_client_update_request(scm_perf_client, 1);
+		if (ret) {
+			pr_err("bandwidth request failed (%d)\n", ret);
+		} else {
+			ret = clk_enable(scm_bus_clk);
+			if (ret)
+				pr_err("clock enable failed\n");
+		}
+	}
+	if (ret)
+		msm_bus_scale_client_update_request(scm_perf_client, 0);
+	else
+		scm_pas_bw_count++;
+	mutex_unlock(&scm_pas_bw_mutex);
+	return ret;
+}
+
+static void scm_pas_disable_bw(void)
+{
+	mutex_lock(&scm_pas_bw_mutex);
+	if (scm_pas_bw_count-- == 1) {
+		msm_bus_scale_client_update_request(scm_perf_client, 0);
+		clk_disable(scm_bus_clk);
+	}
+	mutex_unlock(&scm_pas_bw_mutex);
+}
+
 int pas_auth_and_reset(enum pas_id id)
 {
-	int ret;
+	int ret, bus_ret;
 	u32 proc = id, scm_ret = 0;
 
+	bus_ret = scm_pas_enable_bw();
 	ret = scm_call(SCM_SVC_PIL, PAS_AUTH_AND_RESET_CMD, &proc,
 			sizeof(proc), &scm_ret, sizeof(scm_ret));
 	if (ret)
-		return ret;
+		scm_ret = ret;
+	if (!bus_ret)
+		scm_pas_disable_bw();
 
 	return scm_ret;
 }
@@ -108,3 +187,19 @@
 	return ret_val;
 }
 EXPORT_SYMBOL(pas_supported);
+
+static int __init scm_pas_init(void)
+{
+	scm_perf_client = msm_bus_scale_register_client(&scm_pas_bus_pdata);
+	if (!scm_perf_client)
+		pr_warn("unable to register bus client\n");
+	scm_bus_clk = clk_get_sys("scm", "bus_clk");
+	if (!IS_ERR(scm_bus_clk)) {
+		clk_set_rate(scm_bus_clk, 64000000);
+	} else {
+		scm_bus_clk = NULL;
+		pr_warn("unable to get bus clock\n");
+	}
+	return 0;
+}
+module_init(scm_pas_init);