Merge "mmc: sdhci-msm-ice: Factor out update config from sdhci_msm_ice_cfg"
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c
index bfe1242..7c3638c 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -729,6 +729,15 @@
 		goto ring_doorbell;
 	}
 
+	if (cq_host->ops->crypto_cfg) {
+		err = cq_host->ops->crypto_cfg(mmc, mrq, tag);
+		if (err) {
+			pr_err("%s: failed to configure crypto: err %d tag %d\n",
+					mmc_hostname(mmc), err, tag);
+			goto out;
+		}
+	}
+
 	task_desc = (__le64 __force *)get_desc(cq_host, tag);
 
 	cmdq_prep_task_desc(mrq, &data, 1,
@@ -778,6 +787,8 @@
 			    CMDQ_SEND_STATUS_TRIGGER, CQ_VENDOR_CFG);
 
 	cmdq_runtime_pm_put(cq_host);
+	if (cq_host->ops->crypto_cfg_reset)
+		cq_host->ops->crypto_cfg_reset(mmc, tag);
 	mrq->done(mrq);
 }
 
diff --git a/drivers/mmc/host/cmdq_hci.h b/drivers/mmc/host/cmdq_hci.h
index 5347b3ab..8e9f765 100644
--- a/drivers/mmc/host/cmdq_hci.h
+++ b/drivers/mmc/host/cmdq_hci.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -208,6 +208,9 @@
 	void (*enhanced_strobe_mask)(struct mmc_host *mmc, bool set);
 	int (*reset)(struct mmc_host *mmc);
 	void (*post_cqe_halt)(struct mmc_host *mmc);
+	int (*crypto_cfg)(struct mmc_host *mmc, struct mmc_request *mrq,
+				u32 slot);
+	void (*crypto_cfg_reset)(struct mmc_host *mmc, unsigned int slot);
 };
 
 static inline void cmdq_writel(struct cmdq_host *host, u32 val, int reg)
diff --git a/drivers/mmc/host/sdhci-msm-ice.c b/drivers/mmc/host/sdhci-msm-ice.c
index ba6e51c..acc4ae0 100644
--- a/drivers/mmc/host/sdhci-msm-ice.c
+++ b/drivers/mmc/host/sdhci-msm-ice.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,19 +13,6 @@
 
 #include "sdhci-msm-ice.h"
 
-static void sdhci_msm_ice_success_cb(void *host_ctrl,
-				enum ice_event_completion evt)
-{
-	struct sdhci_msm_host *msm_host = (struct sdhci_msm_host *)host_ctrl;
-
-	if ((msm_host->ice.state == SDHCI_MSM_ICE_STATE_DISABLED &&
-	    evt == ICE_INIT_COMPLETION) || (msm_host->ice.state ==
-	    SDHCI_MSM_ICE_STATE_SUSPENDED && evt == ICE_RESUME_COMPLETION))
-		msm_host->ice.state = SDHCI_MSM_ICE_STATE_ACTIVE;
-
-	complete(&msm_host->ice.async_done);
-}
-
 static void sdhci_msm_ice_error_cb(void *host_ctrl, u32 error)
 {
 	struct sdhci_msm_host *msm_host = (struct sdhci_msm_host *)host_ctrl;
@@ -35,8 +22,6 @@
 
 	if (msm_host->ice.state == SDHCI_MSM_ICE_STATE_ACTIVE)
 		msm_host->ice.state = SDHCI_MSM_ICE_STATE_DISABLED;
-
-	complete(&msm_host->ice.async_done);
 }
 
 static struct platform_device *sdhci_msm_ice_get_pdevice(struct device *dev)
@@ -194,34 +179,69 @@
 	struct sdhci_msm_host *msm_host = pltfm_host->priv;
 	int err = 0;
 
-	init_completion(&msm_host->ice.async_done);
-	if (msm_host->ice.vops->config) {
+	if (msm_host->ice.vops->init) {
+		err = sdhci_msm_ice_pltfm_init(msm_host);
+		if (err)
+			goto out;
+
+		if (msm_host->ice_hci_support)
+			sdhci_msm_enable_ice_hci(host, true);
+
 		err = msm_host->ice.vops->init(msm_host->ice.pdev,
 					msm_host,
-					sdhci_msm_ice_success_cb,
 					sdhci_msm_ice_error_cb);
 		if (err) {
 			pr_err("%s: ice init err %d\n",
 				mmc_hostname(host->mmc), err);
-			return err;
+			sdhci_msm_ice_print_regs(host);
+			if (msm_host->ice_hci_support)
+				sdhci_msm_enable_ice_hci(host, false);
+			goto out;
 		}
+		msm_host->ice.state = SDHCI_MSM_ICE_STATE_ACTIVE;
 	}
 
-	if (!wait_for_completion_timeout(&msm_host->ice.async_done,
-		msecs_to_jiffies(SDHCI_MSM_ICE_COMPLETION_TIMEOUT_MS))) {
-		pr_err("%s: ice init timedout after %d ms\n",
-				mmc_hostname(host->mmc),
-				SDHCI_MSM_ICE_COMPLETION_TIMEOUT_MS);
-		sdhci_msm_ice_print_regs(host);
-		return -ETIMEDOUT;
-	}
+out:
+	return err;
+}
 
-	if (msm_host->ice.state != SDHCI_MSM_ICE_STATE_ACTIVE) {
-		pr_err("%s: ice is in invalid state %d\n",
-			mmc_hostname(host->mmc), msm_host->ice.state);
-		return -EINVAL;
-	}
-	return 0;
+void sdhci_msm_ice_cfg_reset(struct sdhci_host *host, u32 slot)
+{
+	writel_relaxed(SDHCI_MSM_ICE_ENABLE_BYPASS,
+		host->ioaddr + CORE_VENDOR_SPEC_ICE_CTRL_INFO_3_n + 16 * slot);
+}
+
+static
+void sdhci_msm_ice_update_cfg(struct sdhci_host *host, u64 lba,
+			u32 slot, unsigned int bypass, short key_index)
+{
+	unsigned int ctrl_info_val = 0;
+
+	/* Configure ICE index */
+	ctrl_info_val =
+		(key_index &
+		 MASK_SDHCI_MSM_ICE_CTRL_INFO_KEY_INDEX)
+		 << OFFSET_SDHCI_MSM_ICE_CTRL_INFO_KEY_INDEX;
+
+	/* Configure data unit size of transfer request */
+	ctrl_info_val |=
+		(SDHCI_MSM_ICE_TR_DATA_UNIT_512_B &
+		 MASK_SDHCI_MSM_ICE_CTRL_INFO_CDU)
+		 << OFFSET_SDHCI_MSM_ICE_CTRL_INFO_CDU;
+
+	/* Configure ICE bypass mode */
+	ctrl_info_val |=
+		(bypass & MASK_SDHCI_MSM_ICE_CTRL_INFO_BYPASS)
+		 << OFFSET_SDHCI_MSM_ICE_CTRL_INFO_BYPASS;
+
+	writel_relaxed((lba & 0xFFFFFFFF),
+		host->ioaddr + CORE_VENDOR_SPEC_ICE_CTRL_INFO_1_n + 16 * slot);
+	writel_relaxed(((lba >> 32) & 0xFFFFFFFF),
+		host->ioaddr + CORE_VENDOR_SPEC_ICE_CTRL_INFO_2_n + 16 * slot);
+	writel_relaxed(ctrl_info_val,
+		host->ioaddr + CORE_VENDOR_SPEC_ICE_CTRL_INFO_3_n + 16 * slot);
+	/* Ensure ICE registers are configured before issuing SDHCI request */
+	mb();
 }
 
 int sdhci_msm_ice_cfg(struct sdhci_host *host, struct mmc_request *mrq,
@@ -232,7 +252,6 @@
 	int err = 0;
 	struct ice_data_setting ice_set;
 	sector_t lba = 0;
-	unsigned int ctrl_info_val = 0;
 	unsigned int bypass = SDHCI_MSM_ICE_ENABLE_BYPASS;
 	struct request *req;
 
@@ -247,9 +266,10 @@
 	req = mrq->req;
 	if (req) {
 		lba = req->__sector;
-		if (msm_host->ice.vops->config) {
-			err = msm_host->ice.vops->config(msm_host->ice.pdev,
-							req, &ice_set);
+		if (msm_host->ice.vops->config_start) {
+			err = msm_host->ice.vops->config_start(
+							msm_host->ice.pdev,
+							req, &ice_set, false);
 			if (err) {
 				pr_err("%s: ice config failed %d\n",
 						mmc_hostname(host->mmc), err);
@@ -274,32 +294,8 @@
 				ice_set.crypto_data.key_index);
 	}
 
-	/* Configure ICE index */
-	ctrl_info_val =
-		(ice_set.crypto_data.key_index &
-		 MASK_SDHCI_MSM_ICE_CTRL_INFO_KEY_INDEX)
-		 << OFFSET_SDHCI_MSM_ICE_CTRL_INFO_KEY_INDEX;
-
-	/* Configure data unit size of transfer request */
-	ctrl_info_val |=
-		(SDHCI_MSM_ICE_TR_DATA_UNIT_512_B &
-		 MASK_SDHCI_MSM_ICE_CTRL_INFO_CDU)
-		 << OFFSET_SDHCI_MSM_ICE_CTRL_INFO_CDU;
-
-	/* Configure ICE bypass mode */
-	ctrl_info_val |=
-		(bypass & MASK_SDHCI_MSM_ICE_CTRL_INFO_BYPASS)
-		 << OFFSET_SDHCI_MSM_ICE_CTRL_INFO_BYPASS;
-
-	writel_relaxed((lba & 0xFFFFFFFF),
-		host->ioaddr + CORE_VENDOR_SPEC_ICE_CTRL_INFO_1_n + 16 * slot);
-	writel_relaxed(((lba >> 32) & 0xFFFFFFFF),
-		host->ioaddr + CORE_VENDOR_SPEC_ICE_CTRL_INFO_2_n + 16 * slot);
-	writel_relaxed(ctrl_info_val,
-		host->ioaddr + CORE_VENDOR_SPEC_ICE_CTRL_INFO_3_n + 16 * slot);
-
-	/* Ensure ICE registers are configured before issuing SDHCI request */
-	mb();
+	sdhci_msm_ice_update_cfg(host, lba, slot, bypass,
+				ice_set.crypto_data.key_index);
 	return 0;
 }
 
@@ -315,25 +311,19 @@
 		return -EINVAL;
 	}
 
-	init_completion(&msm_host->ice.async_done);
-
 	if (msm_host->ice.vops->reset) {
 		err = msm_host->ice.vops->reset(msm_host->ice.pdev);
 		if (err) {
 			pr_err("%s: ice reset failed %d\n",
 					mmc_hostname(host->mmc), err);
+			sdhci_msm_ice_print_regs(host);
 			return err;
 		}
 	}
 
-	if (!wait_for_completion_timeout(&msm_host->ice.async_done,
-	     msecs_to_jiffies(SDHCI_MSM_ICE_COMPLETION_TIMEOUT_MS))) {
-		pr_err("%s: ice reset timedout after %d ms\n",
-			mmc_hostname(host->mmc),
-			SDHCI_MSM_ICE_COMPLETION_TIMEOUT_MS);
-		sdhci_msm_ice_print_regs(host);
-		return -ETIMEDOUT;
-	}
+	/* If ICE HCI support is present then re-enable it */
+	if (msm_host->ice_hci_support)
+		sdhci_msm_enable_ice_hci(host, true);
 
 	if (msm_host->ice.state != SDHCI_MSM_ICE_STATE_ACTIVE) {
 		pr_err("%s: ice is in invalid state after reset %d\n",
@@ -356,8 +346,6 @@
 		return -EINVAL;
 	}
 
-	init_completion(&msm_host->ice.async_done);
-
 	if (msm_host->ice.vops->resume) {
 		err = msm_host->ice.vops->resume(msm_host->ice.pdev);
 		if (err) {
@@ -367,20 +355,7 @@
 		}
 	}
 
-	if (!wait_for_completion_timeout(&msm_host->ice.async_done,
-		msecs_to_jiffies(SDHCI_MSM_ICE_COMPLETION_TIMEOUT_MS))) {
-		pr_err("%s: ice resume timedout after %d ms\n",
-			mmc_hostname(host->mmc),
-			SDHCI_MSM_ICE_COMPLETION_TIMEOUT_MS);
-		sdhci_msm_ice_print_regs(host);
-		return -ETIMEDOUT;
-	}
-
-	if (msm_host->ice.state != SDHCI_MSM_ICE_STATE_ACTIVE) {
-		pr_err("%s: ice is in invalid state after resume %d\n",
-			mmc_hostname(host->mmc), msm_host->ice.state);
-		return -EINVAL;
-	}
+	msm_host->ice.state = SDHCI_MSM_ICE_STATE_ACTIVE;
 	return 0;
 }
 
diff --git a/drivers/mmc/host/sdhci-msm-ice.h b/drivers/mmc/host/sdhci-msm-ice.h
index 88ef0e2..23922cf 100644
--- a/drivers/mmc/host/sdhci-msm-ice.h
+++ b/drivers/mmc/host/sdhci-msm-ice.h
@@ -17,7 +17,6 @@
 
 #include <linux/io.h>
 #include <linux/of.h>
-#include <linux/async.h>
 #include <linux/blkdev.h>
 #include <crypto/ice.h>
 
@@ -97,6 +96,7 @@
 #ifdef CONFIG_MMC_SDHCI_MSM_ICE
 int sdhci_msm_ice_get_dev(struct sdhci_host *host);
 int sdhci_msm_ice_init(struct sdhci_host *host);
+void sdhci_msm_ice_cfg_reset(struct sdhci_host *host, u32 slot);
 int sdhci_msm_ice_cfg(struct sdhci_host *host, struct mmc_request *mrq,
 			u32 slot);
 int sdhci_msm_ice_reset(struct sdhci_host *host);
@@ -120,6 +120,11 @@
 {
 	return 0;
 }
+
+inline void sdhci_msm_ice_cfg_reset(struct sdhci_host *host, u32 slot)
+{
+}
+
 inline int sdhci_msm_ice_cfg(struct sdhci_host *host,
 		struct mmc_request *mrq, u32 slot)
 {
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 77f7c96..b6c17ec0 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -3474,6 +3474,7 @@
 	if (host->is_crypto_en) {
 		sdhci_msm_ice_get_status(host, &sts);
 		pr_info("%s: ICE status %x\n", mmc_hostname(host->mmc), sts);
+		sdhci_msm_ice_print_regs(host);
 	}
 }
 
@@ -3483,8 +3484,14 @@
 	struct sdhci_msm_host *msm_host = pltfm_host->priv;
 
 	/* Set ICE core to be reset in sync with SDHC core */
-	if (msm_host->ice.pdev)
-		writel_relaxed(1, host->ioaddr + CORE_VENDOR_SPEC_ICE_CTRL);
+	if (msm_host->ice.pdev) {
+		if (msm_host->ice_hci_support)
+			writel_relaxed(1, host->ioaddr +
+						HC_VENDOR_SPECIFIC_ICE_CTRL);
+		else
+			writel_relaxed(1,
+				host->ioaddr + CORE_VENDOR_SPEC_ICE_CTRL);
+	}
 
 	sdhci_reset(host, mask);
 }
diff --git a/drivers/mmc/host/sdhci-msm.h b/drivers/mmc/host/sdhci-msm.h
index 53a8c67..cdbaaa9 100644
--- a/drivers/mmc/host/sdhci-msm.h
+++ b/drivers/mmc/host/sdhci-msm.h
@@ -165,7 +165,6 @@
 
 struct sdhci_msm_ice_data {
 	struct qcom_ice_variant_ops *vops;
-	struct completion async_done;
 	struct platform_device *pdev;
 	int state;
 };
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 1d69a9b..3eada3b 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -3746,6 +3746,27 @@
 			SDHCI_INT_RESPONSE, SDHCI_INT_ENABLE);
 	sdhci_writel(host, SDHCI_INT_RESPONSE, SDHCI_INT_STATUS);
 }
+static int sdhci_cmdq_crypto_cfg(struct mmc_host *mmc,
+		struct mmc_request *mrq, u32 slot)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+
+	if (!host->is_crypto_en)
+		return 0;
+
+	return sdhci_crypto_cfg(host, mrq, slot);
+}
+
+static void sdhci_cmdq_crypto_cfg_reset(struct mmc_host *mmc, unsigned int slot)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+
+	if (!host->is_crypto_en)
+		return;
+
+	if (host->ops->crypto_cfg_reset)
+		host->ops->crypto_cfg_reset(host, slot);
+}
 #else
 static void sdhci_cmdq_set_transfer_params(struct mmc_host *mmc)
 {
@@ -3789,6 +3810,18 @@
 
 static void sdhci_cmdq_post_cqe_halt(struct mmc_host *mmc)
 {
+
+}
+
+static int sdhci_cmdq_crypto_cfg(struct mmc_host *mmc,
+		struct mmc_request *mrq, u32 slot)
+{
+	return 0;
+}
+
+static void sdhci_cmdq_crypto_cfg_reset(struct mmc_host *mmc, unsigned int slot)
+{
+
 }
 #endif
 
@@ -3801,6 +3834,8 @@
 	.enhanced_strobe_mask = sdhci_enhanced_strobe_mask,
 	.post_cqe_halt = sdhci_cmdq_post_cqe_halt,
 	.set_transfer_params = sdhci_cmdq_set_transfer_params,
+	.crypto_cfg	= sdhci_cmdq_crypto_cfg,
+	.crypto_cfg_reset	= sdhci_cmdq_crypto_cfg_reset,
 };
 
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 45296d4..04e806c 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -671,6 +671,7 @@
 	int	(*crypto_engine_cfg)(struct sdhci_host *host,
 				struct mmc_request *mrq, u32 slot);
 	int	(*crypto_engine_reset)(struct sdhci_host *host);
+	void	(*crypto_cfg_reset)(struct sdhci_host *host, unsigned int slot);
 	void	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
 	void	(*hw_reset)(struct sdhci_host *host);
 	void    (*adma_workaround)(struct sdhci_host *host, u32 intmask);