summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSubhash Jadavani <subhashj@codeaurora.org>2014-08-18 18:34:36 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 10:57:15 -0700
commitffbed02d437426e7a4ce05cc4ea762ed97661392 (patch)
tree0372ba562c653537e1d1316148ab1074ed3d33c9
parente740ae3bbe0d1921f8d4d5b203d6ab2978ab497d (diff)
scsi: ufs-msm: request UFS register space access after power collapse
Following UFS core power collapse, all the TZ programmed xPU protection settings would be lost and default protection settings won't allow access to even UFS host controller register address space from non-secure world. Hence we have to explicitly call into TZ to open up atleast UFS host controller & UFS PHY register address space access to non-secure world. Change-Id: Ic05c88e418484a10ad0d651fe2295916117c085e Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> [gbroner@codeaurora.org: fix merge conflicts] Signed-off-by: Gilad Broner <gbroner@codeaurora.org> [subhashj@codeaurora.org: resolved merge conflicts] Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> [venkatg@codeaurora.org: resolved trivial merge conflicts] Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
-rw-r--r--drivers/scsi/ufs/ufs-msm.c73
-rw-r--r--drivers/scsi/ufs/ufs-msm.h1
-rw-r--r--drivers/scsi/ufs/ufshcd.c14
-rw-r--r--drivers/scsi/ufs/ufshcd.h2
4 files changed, 87 insertions, 3 deletions
diff --git a/drivers/scsi/ufs/ufs-msm.c b/drivers/scsi/ufs/ufs-msm.c
index 1ce763e6867d..eb7096317d96 100644
--- a/drivers/scsi/ufs/ufs-msm.c
+++ b/drivers/scsi/ufs/ufs-msm.c
@@ -22,6 +22,7 @@
#include <linux/platform_device.h>
#include <linux/msm-bus.h>
+#include <soc/qcom/scm.h>
#include "ufshcd.h"
#include "unipro.h"
@@ -32,6 +33,7 @@ static int ufs_msm_get_speed_mode(struct ufs_pa_layer_attr *p, char *result);
static int ufs_msm_get_bus_vote(struct ufs_msm_host *host,
const char *speed_mode);
static int ufs_msm_set_bus_vote(struct ufs_msm_host *host, int vote);
+static int ufs_msm_update_sec_cfg(struct ufs_hba *hba, bool restore_sec_cfg);
static int ufs_msm_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
{
@@ -1060,6 +1062,9 @@ static int ufs_msm_init(struct ufs_hba *hba)
hba->priv = (void *)host;
+ /* restore the secure configuration */
+ ufs_msm_update_sec_cfg(hba, true);
+
err = ufs_msm_bus_register(host);
if (err)
goto out_host_free;
@@ -1116,6 +1121,73 @@ void ufs_msm_clk_scale_notify(struct ufs_hba *hba)
dev_req_params->hs_rate);
ufs_msm_update_bus_bw_vote(host);
}
+
+/*
+ * This function should be called to restore the security configuration of UFS
+ * register space after coming out of UFS host core power collapse.
+ *
+ * @hba: host controller instance
+ * @restore_sec_cfg: Set "true" if secure configuration needs to be restored
+ * and set "false" when secure configuration is lost.
+ */
+static int ufs_msm_update_sec_cfg(struct ufs_hba *hba, bool restore_sec_cfg)
+{
+ int ret = 0, scm_ret = 0;
+ struct ufs_msm_host *host = hba->priv;
+
+ /* scm command buffer structrue */
+ struct msm_scm_cmd_buf {
+ unsigned int device_id;
+ unsigned int spare;
+ } cbuf;
+ #define RESTORE_SEC_CFG_CMD 0x2
+ #define UFS_TZ_DEV_ID 19
+
+ if (!host || !hba->vreg_info.vdd_hba ||
+ !(host->sec_cfg_updated ^ restore_sec_cfg)) {
+ return 0;
+ } else if (!restore_sec_cfg) {
+ /*
+ * Clear the flag so next time when this function is called
+ * with restore_sec_cfg set to true, we can restore the secure
+ * configuration.
+ */
+ host->sec_cfg_updated = false;
+ goto out;
+ } else if (hba->clk_gating.state != CLKS_ON) {
+ /*
+ * Clocks should be ON to restore the host controller secure
+ * configuration.
+ */
+ goto out;
+ }
+
+ /*
+ * If we are here, Host controller clocks are running, Host controller
+ * power collapse feature is supported and Host controller has just came
+ * out of power collapse.
+ */
+ cbuf.device_id = UFS_TZ_DEV_ID;
+ ret = scm_call(SCM_SVC_MP,
+ RESTORE_SEC_CFG_CMD,
+ &cbuf, sizeof(cbuf),
+ &scm_ret, sizeof(scm_ret));
+
+ if (ret || scm_ret) {
+ dev_err(hba->dev, "%s: failed, ret %d scm_ret %d\n",
+ __func__, ret, scm_ret);
+ if (!ret)
+ ret = scm_ret;
+ } else {
+ host->sec_cfg_updated = true;
+ }
+
+out:
+ dev_dbg(hba->dev, "%s: ip: restore_sec_cfg %d, op: restore_sec_cfg %d, ret %d scm_ret %d\n",
+ __func__, restore_sec_cfg, host->sec_cfg_updated, ret, scm_ret);
+ return ret;
+}
+
/**
* struct ufs_hba_msm_vops - UFS MSM specific variant operations
*
@@ -1133,5 +1205,6 @@ const struct ufs_hba_variant_ops ufs_hba_msm_vops = {
.pwr_change_notify = ufs_msm_pwr_change_notify,
.suspend = ufs_msm_suspend,
.resume = ufs_msm_resume,
+ .update_sec_cfg = ufs_msm_update_sec_cfg,
};
EXPORT_SYMBOL(ufs_hba_msm_vops);
diff --git a/drivers/scsi/ufs/ufs-msm.h b/drivers/scsi/ufs/ufs-msm.h
index 6e93f1e4846e..dcea272c4459 100644
--- a/drivers/scsi/ufs/ufs-msm.h
+++ b/drivers/scsi/ufs/ufs-msm.h
@@ -134,6 +134,7 @@ struct ufs_msm_host {
struct clk *rx_l1_sync_clk;
struct clk *tx_l1_sync_clk;
bool is_lane_clks_enabled;
+ bool sec_cfg_updated;
};
#define ufs_msm_is_link_off(hba) ufshcd_is_link_off(hba)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 2cb000e3763c..03d76aa7a619 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5360,11 +5360,16 @@ out:
static int ufshcd_setup_hba_vreg(struct ufs_hba *hba, bool on)
{
struct ufs_vreg_info *info = &hba->vreg_info;
+ int ret = 0;
- if (info)
- return ufshcd_toggle_vreg(hba->dev, info->vdd_hba, on);
+ if (info->vdd_hba) {
+ ret = ufshcd_toggle_vreg(hba->dev, info->vdd_hba, on);
- return 0;
+ if (!ret && hba->vops->update_sec_cfg)
+ hba->vops->update_sec_cfg(hba, on);
+ }
+
+ return ret;
}
static int ufshcd_get_vreg(struct device *dev, struct ufs_vreg *vreg)
@@ -5462,6 +5467,9 @@ out:
ufschd_clk_gating_state_to_string(
hba->clk_gating.state));
spin_unlock_irqrestore(hba->host->host_lock, flags);
+ /* restore the secure configuration as clocks are enabled */
+ if (hba->vops->update_sec_cfg)
+ hba->vops->update_sec_cfg(hba, true);
}
return ret;
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index a4bd06965994..43b9c651bb40 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -284,6 +284,7 @@ struct ufs_pwr_mode_info {
* to be set.
* @suspend: called during host controller PM callback
* @resume: called during host controller PM callback
+ * @update_sec_cfg: called to restore host controller secure configuration
* @dbg_register_dump: used to dump controller debug information
*/
struct ufs_hba_variant_ops {
@@ -305,6 +306,7 @@ struct ufs_hba_variant_ops {
struct ufs_pa_layer_attr *);
int (*suspend)(struct ufs_hba *, enum ufs_pm_op);
int (*resume)(struct ufs_hba *, enum ufs_pm_op);
+ int (*update_sec_cfg)(struct ufs_hba *hba, bool restore_sec_cfg);
void (*dbg_register_dump)(struct ufs_hba *hba);
};