qseecom: Enable clocks for the Crypto Engine used by Trustzone.

All interactions with secure applications on TZ by non-secure
apps on HLOS need the crypto clocks on.
Without this, simple operations as loading secure apps in
Trust zone fail.

Change-Id: I37097cb401508f7582de014e502f3709170ca6b2
Signed-off-by: Ramesh Masavarapu <rameshm@codeaurora.org>
This commit is contained in:
Ramesh Masavarapu 2012-09-14 12:11:32 -07:00 committed by Iliyan Malchev
parent b2fe656417
commit bb3b4e5e55
2 changed files with 154 additions and 9 deletions

View file

@ -795,7 +795,6 @@ static DEFINE_CLK_VOTER(pnoc_sdcc3_clk, &pnoc_clk.c, 0);
static DEFINE_CLK_VOTER(pnoc_sdcc4_clk, &pnoc_clk.c, 0);
static DEFINE_CLK_VOTER(pnoc_sps_clk, &pnoc_clk.c, 0);
static DEFINE_CLK_VOTER(pnoc_qseecom_clk, &pnoc_clk.c, 0);
static struct clk_freq_tbl ftbl_gcc_usb30_master_clk[] = {
F(125000000, gpll0, 1, 5, 24),
@ -5046,6 +5045,11 @@ static struct clk_lookup msm_clocks_8974[] = {
CLK_LOOKUP("bus_clk", gcc_ce2_axi_clk.c, "qcrypto.0"),
CLK_LOOKUP("core_clk_src", ce2_clk_src.c, "qcrypto.0"),
CLK_LOOKUP("core_clk", gcc_ce1_clk.c, "qseecom"),
CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, "qseecom"),
CLK_LOOKUP("bus_clk", gcc_ce1_axi_clk.c, "qseecom"),
CLK_LOOKUP("core_clk_src", ce1_clk_src.c, "qseecom"),
CLK_LOOKUP("core_clk", gcc_gp1_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_gp2_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_gp3_clk.c, ""),
@ -5232,7 +5236,6 @@ static struct clk_lookup msm_clocks_8974[] = {
CLK_LOOKUP("core_clk", gcc_prng_ahb_clk.c, "msm_rng"),
CLK_LOOKUP("dfab_clk", pnoc_sps_clk.c, "msm_sps"),
CLK_LOOKUP("bus_clk", pnoc_qseecom_clk.c, "qseecom"),
CLK_LOOKUP("bus_clk", snoc_clk.c, ""),
CLK_LOOKUP("bus_clk", pnoc_clk.c, ""),

View file

@ -38,6 +38,7 @@
#include <mach/msm_bus_board.h>
#include <mach/scm.h>
#include <mach/peripheral-loader.h>
#include <mach/socinfo.h>
#include "qseecom_legacy.h"
#define QSEECOM_DEV "qseecom"
@ -179,6 +180,7 @@ struct qseecom_control {
int send_resp_flag;
uint32_t qseos_version;
struct device *pdev;
};
struct qseecom_client_handle {
@ -208,9 +210,16 @@ struct qseecom_dev_handle {
atomic_t ioctl_count;
};
struct clk *ce_core_clk;
struct clk *ce_clk;
struct clk *ce_core_src_clk;
struct clk *ce_bus_clk;
/* Function proto types */
static int qsee_vote_for_clock(int32_t);
static void qsee_disable_clock_vote(int32_t);
static int __qseecom_init_clk(void);
static void __qseecom_disable_clk(void);
static int __qseecom_is_svc_unique(struct qseecom_dev_handle *data,
struct qseecom_register_listener_req *svc)
@ -1738,9 +1747,131 @@ static const struct file_operations qseecom_fops = {
.release = qseecom_release
};
static int __qseecom_init_clk()
{
int rc = 0;
struct device *pdev;
pdev = qseecom.pdev;
/* Get CE3 src core clk. */
ce_core_src_clk = clk_get(pdev, "core_clk_src");
if (!IS_ERR(ce_core_src_clk)) {
ce_core_src_clk = ce_core_src_clk;
/* Set the core src clk @100Mhz */
rc = clk_set_rate(ce_core_src_clk, 100000000);
if (rc) {
clk_put(ce_core_src_clk);
pr_err("Unable to set the core src clk @100Mhz.\n");
goto err_clk;
}
} else {
pr_warn("Unable to get CE core src clk, set to NULL\n");
ce_core_src_clk = NULL;
}
/* Get CE core clk */
ce_core_clk = clk_get(pdev, "core_clk");
if (IS_ERR(ce_core_clk)) {
rc = PTR_ERR(ce_core_clk);
pr_err("Unable to get CE core clk\n");
if (ce_core_src_clk != NULL)
clk_put(ce_core_src_clk);
goto err_clk;
}
/* Get CE Interface clk */
ce_clk = clk_get(pdev, "iface_clk");
if (IS_ERR(ce_clk)) {
rc = PTR_ERR(ce_clk);
pr_err("Unable to get CE interface clk\n");
if (ce_core_src_clk != NULL)
clk_put(ce_core_src_clk);
clk_put(ce_core_clk);
goto err_clk;
}
/* Get CE AXI clk */
ce_bus_clk = clk_get(pdev, "bus_clk");
if (IS_ERR(ce_bus_clk)) {
rc = PTR_ERR(ce_bus_clk);
pr_err("Unable to get CE BUS interface clk\n");
if (ce_core_src_clk != NULL)
clk_put(ce_core_src_clk);
clk_put(ce_core_clk);
clk_put(ce_clk);
goto err_clk;
}
/* Enable CE core clk */
rc = clk_prepare_enable(ce_core_clk);
if (rc) {
pr_err("Unable to enable/prepare CE core clk\n");
if (ce_core_src_clk != NULL)
clk_put(ce_core_src_clk);
clk_put(ce_core_clk);
clk_put(ce_clk);
goto err_clk;
} else {
/* Enable CE clk */
rc = clk_prepare_enable(ce_clk);
if (rc) {
pr_err("Unable to enable/prepare CE iface clk\n");
clk_disable_unprepare(ce_core_clk);
if (ce_core_src_clk != NULL)
clk_put(ce_core_src_clk);
clk_put(ce_core_clk);
clk_put(ce_clk);
goto err_clk;
} else {
/* Enable AXI clk */
rc = clk_prepare_enable(ce_bus_clk);
if (rc) {
pr_err("Unable to enable/prepare CE iface clk\n");
clk_disable_unprepare(ce_core_clk);
clk_disable_unprepare(ce_clk);
if (ce_core_src_clk != NULL)
clk_put(ce_core_src_clk);
clk_put(ce_core_clk);
clk_put(ce_clk);
goto err_clk;
}
}
}
return rc;
err_clk:
if (rc)
pr_err("Unable to init CE clks, rc = %d\n", rc);
clk_disable_unprepare(ce_clk);
clk_disable_unprepare(ce_core_clk);
clk_disable_unprepare(ce_bus_clk);
if (ce_core_src_clk != NULL)
clk_put(ce_core_src_clk);
clk_put(ce_clk);
clk_put(ce_core_clk);
clk_put(ce_bus_clk);
return rc;
}
static void __qseecom_disable_clk()
{
clk_disable_unprepare(ce_clk);
clk_disable_unprepare(ce_core_clk);
clk_disable_unprepare(ce_bus_clk);
if (ce_core_src_clk != NULL)
clk_put(ce_core_src_clk);
clk_put(ce_clk);
clk_put(ce_core_clk);
clk_put(ce_bus_clk);
}
static int __devinit qseecom_probe(struct platform_device *pdev)
{
int rc;
int ret;
struct device *class_dev;
char qsee_not_legacy = 0;
struct msm_bus_scale_pdata *qseecom_platform_support;
@ -1799,6 +1930,8 @@ static int __devinit qseecom_probe(struct platform_device *pdev)
pil = NULL;
pil_ref_cnt = 0;
}
qseecom.pdev = class_dev;
/* Create ION msm client */
qseecom.ion_clnt = msm_ion_client_create(0x03, "qseecom-kernel");
if (qseecom.ion_clnt == NULL) {
@ -1808,17 +1941,23 @@ static int __devinit qseecom_probe(struct platform_device *pdev)
}
/* register client for bus scaling */
if (!pdev->dev.of_node) {
if (pdev->dev.of_node) {
ret = __qseecom_init_clk();
if (ret)
goto err;
qseecom_platform_support = (struct msm_bus_scale_pdata *)
msm_bus_cl_get_pdata(pdev);
} else {
qseecom_platform_support = (struct msm_bus_scale_pdata *)
pdev->dev.platform_data;
qsee_perf_client = msm_bus_scale_register_client(
qseecom_platform_support);
if (!qsee_perf_client)
pr_err("Unable to register bus client\n");
}
return 0;
qsee_perf_client = msm_bus_scale_register_client(
qseecom_platform_support);
if (!qsee_perf_client)
pr_err("Unable to register bus client\n");
return 0;
err:
device_destroy(driver_class, qseecom_device_no);
class_destroy:
@ -1859,6 +1998,9 @@ static int __devinit qseecom_init(void)
static void __devexit qseecom_exit(void)
{
__qseecom_disable_clk();
device_destroy(driver_class, qseecom_device_no);
class_destroy(driver_class);
unregister_chrdev_region(qseecom_device_no, 1);