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);