Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9325fb08 authored by Sahitya Tummala's avatar Sahitya Tummala Committed by Veerabhadrarao Badiganti
Browse files

mmc: sdhci-msm: Add Inline Crypto Engine (ICE) support



Add ICE support to low-level driver sdhci-msm.c. This code is
primarily responsible for enabling ICE (if present),
managing ICE clocks, managing ICE suspend/resume and also provides
a few host->ops for sdhci driver to use ICE functionality.

Change-Id: I3ec62146982c9db0263d5e19f60274163f514859
Signed-off-by: default avatarKrishna Konda <kkonda@codeaurora.org>
Signed-off-by: default avatarSahitya Tummala <stummala@codeaurora.org>
Signed-off-by: default avatarVenkat Gopalakrishnan <venkatg@codeaurora.org>
[subhashj@codeaurora.org: fixed trivial merge conflicts]
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: default avatarVeerabhadrarao Badiganti <vbadigan@codeaurora.org>
parent 01e6ff9f
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@ Required properties:
		      Required "interrupt-names" are "hc_irq" and "pwr_irq".
  - <supply-name>-supply: phandle to the regulator device tree node
			  Required "supply-name" are "vdd" and "vdd-io".
  - qcom,ice-clk-rates: this is an array that specifies supported Inline
		    Crypto Engine (ICE) clock frequencies, Units - Hz.
  - sdhc-msm-crypto: phandle to SDHC ICE node

Required alias:
- The slot number is specified via an alias with the following format
@@ -121,6 +124,7 @@ Example:
                reg-names = "hc_mem", "core_mem";
                interrupts = <0 123 0>, <0 138 0>;
                interrupt-names = "hc_irq", "pwr_irq";
		sdhc-msm-crypto = <&sdcc1_ice>;

		vdd-supply = <&pm8941_l21>;
		vdd-io-supply = <&pm8941_l13>;
@@ -143,6 +147,7 @@ Example:
		qcom,nonremovable;
		qcom,large-address-bus;
		qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
		qcom,ice-clk-rates = <300000000 150000000>;

		qcom,scaling-lower-bus-speed-mode = "DDR52";

+139 −4
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#include <trace/events/mmc.h>

#include "sdhci-msm.h"
#include "sdhci-msm-ice.h"
#include "cmdq_hci.h"

#define QOS_REMOVE_DELAY_MS	10
@@ -1814,6 +1815,8 @@ struct sdhci_msm_pltfm_data *sdhci_msm_populate_pdata(struct device *dev,
	int len, i;
	int clk_table_len;
	u32 *clk_table = NULL;
	int ice_clk_table_len;
	u32 *ice_clk_table = NULL;
	enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW;
	const char *lower_bus_speed = NULL;

@@ -1871,6 +1874,20 @@ struct sdhci_msm_pltfm_data *sdhci_msm_populate_pdata(struct device *dev,
	pdata->sup_clk_table = clk_table;
	pdata->sup_clk_cnt = clk_table_len;

	if (msm_host->ice.pdev) {
		if (sdhci_msm_dt_get_array(dev, "qcom,ice-clk-rates",
				&ice_clk_table, &ice_clk_table_len, 0)) {
			dev_err(dev, "failed parsing supported ice clock rates\n");
			goto out;
		}
		if (!ice_clk_table || !ice_clk_table_len) {
			dev_err(dev, "Invalid clock table\n");
			goto out;
		}
		pdata->sup_ice_clk_table = ice_clk_table;
		pdata->sup_ice_clk_cnt = ice_clk_table_len;
	}

	pdata->vreg_data = devm_kzalloc(dev, sizeof(struct
						    sdhci_msm_slot_reg_data),
					GFP_KERNEL);
@@ -2957,12 +2974,23 @@ static int sdhci_msm_enable_controller_clock(struct sdhci_host *host)
		goto disable_pclk;
	}

	if (!IS_ERR(msm_host->ice_clk)) {
		rc = clk_prepare_enable(msm_host->ice_clk);
		if (rc) {
			pr_err("%s: %s: failed to enable the ice-clk with error %d\n",
				mmc_hostname(host->mmc), __func__, rc);
			goto disable_host_clk;
		}
	}
	atomic_set(&msm_host->controller_clock, 1);
	pr_debug("%s: %s: enabled controller clock\n",
			mmc_hostname(host->mmc), __func__);
	sdhci_msm_registers_restore(host);
	goto out;

disable_host_clk:
	if (!IS_ERR(msm_host->clk))
		clk_disable_unprepare(msm_host->clk);
disable_pclk:
	if (!IS_ERR(msm_host->pclk))
		clk_disable_unprepare(msm_host->pclk);
@@ -2982,10 +3010,10 @@ static void sdhci_msm_disable_controller_clock(struct sdhci_host *host)
		sdhci_msm_registers_save(host);
		if (!IS_ERR(msm_host->clk))
			clk_disable_unprepare(msm_host->clk);
		if (!IS_ERR(msm_host->pclk))
			clk_disable_unprepare(msm_host->pclk);
		if (!IS_ERR(msm_host->ice_clk))
			clk_disable_unprepare(msm_host->ice_clk);
		if (!IS_ERR(msm_host->pclk))
			clk_disable_unprepare(msm_host->pclk);
		sdhci_msm_bus_voting(host, 0);
		atomic_set(&msm_host->controller_clock, 0);
		pr_debug("%s: %s: disabled controller clock\n",
@@ -3073,6 +3101,8 @@ static int sdhci_msm_prepare_clocks(struct sdhci_host *host, bool enable)
disable_controller_clk:
	if (!IS_ERR_OR_NULL(msm_host->clk))
		clk_disable_unprepare(msm_host->clk);
	if (!IS_ERR(msm_host->ice_clk))
		clk_disable_unprepare(msm_host->ice_clk);
	if (!IS_ERR_OR_NULL(msm_host->pclk))
		clk_disable_unprepare(msm_host->pclk);
	atomic_set(&msm_host->controller_clock, 0);
@@ -3378,6 +3408,7 @@ void sdhci_msm_dump_vendor_regs(struct sdhci_host *host)
	int i, index = 0;
	u32 test_bus_val = 0;
	u32 debug_reg[MAX_TEST_BUS] = {0};
	u32 sts = 0;

	sdhci_msm_cache_debug_data(host);
	pr_info("----------- VENDOR REGISTER DUMP -----------\n");
@@ -3440,6 +3471,22 @@ void sdhci_msm_dump_vendor_regs(struct sdhci_host *host)
		pr_info(" Test bus[%d to %d]: 0x%08x 0x%08x 0x%08x 0x%08x\n",
				i, i + 3, debug_reg[i], debug_reg[i+1],
				debug_reg[i+2], debug_reg[i+3]);
	if (host->is_crypto_en) {
		sdhci_msm_ice_get_status(host, &sts);
		pr_info("%s: ICE status %x\n", mmc_hostname(host->mmc), sts);
	}
}

static void sdhci_msm_reset(struct sdhci_host *host, u8 mask)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	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);

	sdhci_reset(host, mask);
}

/*
@@ -4022,6 +4069,8 @@ static unsigned int sdhci_msm_get_current_limit(struct sdhci_host *host)
}

static struct sdhci_ops sdhci_msm_ops = {
	.crypto_engine_cfg = sdhci_msm_ice_cfg,
	.crypto_engine_reset = sdhci_msm_ice_reset,
	.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
	.check_power_status = sdhci_msm_check_power_status,
	.platform_execute_tuning = sdhci_msm_execute_tuning,
@@ -4035,7 +4084,7 @@ static struct sdhci_ops sdhci_msm_ops = {
	.config_auto_tuning_cmd = sdhci_msm_config_auto_tuning_cmd,
	.enable_controller_clock = sdhci_msm_enable_controller_clock,
	.set_bus_width = sdhci_set_bus_width,
	.reset = sdhci_reset,
	.reset = sdhci_msm_reset,
	.clear_set_dumpregs = sdhci_msm_clear_set_dumpregs,
	.enhanced_strobe_mask = sdhci_msm_enhanced_strobe_mask,
	.reset_workaround = sdhci_msm_reset_workaround,
@@ -4234,7 +4283,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)
	host = sdhci_pltfm_init(pdev, &msm_host->sdhci_msm_pdata, 0);
	if (IS_ERR(host)) {
		ret = PTR_ERR(host);
		goto out;
		goto out_host_free;
	}

	pltfm_host = sdhci_priv(host);
@@ -4242,6 +4291,31 @@ static int sdhci_msm_probe(struct platform_device *pdev)
	msm_host->mmc = host->mmc;
	msm_host->pdev = pdev;

	/* get the ice device vops if present */
	ret = sdhci_msm_ice_get_dev(host);
	if (ret == -EPROBE_DEFER) {
		/*
		 * SDHCI driver might be probed before ICE driver does.
		 * In that case we would like to return EPROBE_DEFER code
		 * in order to delay its probing.
		 */
		dev_err(&pdev->dev, "%s: required ICE device not probed yet err = %d\n",
			__func__, ret);
		goto out_host_free;

	} else if (ret == -ENODEV) {
		/*
		 * ICE device is not enabled in DTS file. No need for further
		 * initialization of ICE driver.
		 */
		dev_warn(&pdev->dev, "%s: ICE device is not enabled",
			__func__);
	} else if (ret) {
		dev_err(&pdev->dev, "%s: sdhci_msm_ice_get_dev failed %d\n",
			__func__, ret);
		goto out_host_free;
	}

	/* Extract platform data */
	if (pdev->dev.of_node) {
		ret = of_alias_get_id(pdev->dev.of_node, "sdhc");
@@ -4301,6 +4375,28 @@ static int sdhci_msm_probe(struct platform_device *pdev)
	}
	atomic_set(&msm_host->controller_clock, 1);

	if (msm_host->ice.pdev) {
		/* Setup SDC ICE clock */
		msm_host->ice_clk = devm_clk_get(&pdev->dev, "ice_core_clk");
		if (!IS_ERR(msm_host->ice_clk)) {
			/* ICE core has only one clock frequency for now */
			ret = clk_set_rate(msm_host->ice_clk,
					msm_host->pdata->sup_ice_clk_table[0]);
			if (ret) {
				dev_err(&pdev->dev, "ICE_CLK rate set failed (%d) for %u\n",
					ret,
					msm_host->pdata->sup_ice_clk_table[0]);
				goto pclk_disable;
			}
			ret = clk_prepare_enable(msm_host->ice_clk);
			if (ret)
				goto pclk_disable;

			msm_host->ice_clk_rate =
				msm_host->pdata->sup_clk_table[0];
		}
	}

	/* Setup SDC MMC clock */
	msm_host->clk = devm_clk_get(&pdev->dev, "core_clk");
	if (IS_ERR(msm_host->clk)) {
@@ -4527,6 +4623,21 @@ static int sdhci_msm_probe(struct platform_device *pdev)

	msm_host->mmc->sdr104_wa = msm_host->pdata->sdr104_wa;

	/* Initialize ICE if present */
	if (msm_host->ice.pdev) {
		ret = sdhci_msm_ice_init(host);
		if (ret) {
			dev_err(&pdev->dev, "%s: SDHCi ICE init failed (%d)\n",
					mmc_hostname(host->mmc), ret);
			ret = -EINVAL;
			goto vreg_deinit;
		}
		host->is_crypto_en = true;
		/* Packed commands cannot be encrypted/decrypted using ICE */
		msm_host->mmc->caps2 &= ~(MMC_CAP2_PACKED_WR |
				MMC_CAP2_PACKED_WR_CONTROL);
	}

	init_completion(&msm_host->pwr_irq_completion);

	if (gpio_is_valid(msm_host->pdata->status_gpio)) {
@@ -4666,6 +4777,8 @@ static int sdhci_msm_probe(struct platform_device *pdev)
		clk_disable_unprepare(msm_host->bus_clk);
pltfm_free:
	sdhci_pltfm_free(pdev);
out_host_free:
	devm_kfree(&pdev->dev, msm_host);
out:
	pr_debug("%s: Exit %s\n", dev_name(&pdev->dev), __func__);
	return ret;
@@ -4755,6 +4868,7 @@ static int sdhci_msm_runtime_suspend(struct device *dev)
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_msm_host *msm_host = pltfm_host->priv;
	ktime_t start = ktime_get();
	int ret;

	if (host->mmc->card && mmc_card_sdio(host->mmc->card))
		goto defer_disable_host_irq;
@@ -4776,6 +4890,12 @@ static int sdhci_msm_runtime_suspend(struct device *dev)
	trace_sdhci_msm_runtime_suspend(mmc_hostname(host->mmc), 0,
			ktime_to_us(ktime_sub(ktime_get(), start)));

	if (host->is_crypto_en) {
		ret = sdhci_msm_ice_suspend(host);
		if (ret < 0)
			pr_err("%s: failed to suspend crypto engine %d\n",
					mmc_hostname(host->mmc), ret);
	}
	return 0;
}

@@ -4785,6 +4905,21 @@ static int sdhci_msm_runtime_resume(struct device *dev)
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_msm_host *msm_host = pltfm_host->priv;
	ktime_t start = ktime_get();
	int ret;

	if (host->is_crypto_en) {
		ret = sdhci_msm_enable_controller_clock(host);
		if (ret) {
			pr_err("%s: Failed to enable reqd clocks\n",
					mmc_hostname(host->mmc));
			goto skip_ice_resume;
		}
		ret = sdhci_msm_ice_resume(host);
		if (ret)
			pr_err("%s: failed to resume crypto engine %d\n",
					mmc_hostname(host->mmc), ret);
	}
skip_ice_resume:

	if (host->mmc->card && mmc_card_sdio(host->mmc->card))
		goto defer_enable_host_irq;
+4 −0
Original line number Diff line number Diff line
@@ -628,6 +628,7 @@ struct sdhci_host {
	enum sdhci_power_policy power_policy;

	bool sdio_irq_async_status;
	bool is_crypto_en;

	u32 auto_cmd_err_sts;
	struct ratelimit_state dbg_dump_rs;
@@ -666,6 +667,9 @@ struct sdhci_ops {
	unsigned int    (*get_ro)(struct sdhci_host *host);
	void		(*reset)(struct sdhci_host *host, u8 mask);
	int	(*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
	int	(*crypto_engine_cfg)(struct sdhci_host *host,
				struct mmc_request *mrq, u32 slot);
	int	(*crypto_engine_reset)(struct sdhci_host *host);
	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);