From 92907bcb947345886c0eeb95ef7b859ff2bc06c2 Mon Sep 17 00:00:00 2001 From: Veerabhadrarao Badiganti Date: Sun, 11 Dec 2016 17:04:56 +0530 Subject: [PATCH] mmc: sdhci-msm-ice: Enable ICE HCI if supported Check if the SDHC has ICE HCI support. If support is present, enable the cryptoghrapic support inside SDHC. Also ensure that it is re-enabled after SDHC is reset. By default ICE HCI is disabled. Change-Id: I43a65279088d70b415c396bc3e51e0e510bb7f9c Signed-off-by: Veerabhadrarao Badiganti --- drivers/mmc/host/sdhci-msm-ice.c | 90 ++++++++++++++++++++++++++++++++ drivers/mmc/host/sdhci-msm-ice.h | 19 ++++++- drivers/mmc/host/sdhci-msm.c | 3 ++ drivers/mmc/host/sdhci-msm.h | 4 +- 4 files changed, 114 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-msm-ice.c b/drivers/mmc/host/sdhci-msm-ice.c index 2ef459582aae..dc8d865cfabc 100644 --- a/drivers/mmc/host/sdhci-msm-ice.c +++ b/drivers/mmc/host/sdhci-msm-ice.c @@ -58,6 +58,52 @@ out: return ice_vops; } +static +void sdhci_msm_enable_ice_hci(struct sdhci_host *host, bool enable) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_msm_host *msm_host = pltfm_host->priv; + u32 config = 0; + u32 ice_cap = 0; + + /* + * Enable the cryptographic support inside SDHC. + * This is a global config which needs to be enabled + * all the time. + * Only when it it is enabled, the ICE_HCI capability + * will get reflected in CQCAP register. + */ + config = readl_relaxed(host->ioaddr + HC_VENDOR_SPECIFIC_FUNC4); + + if (enable) + config &= ~DISABLE_CRYPTO; + else + config |= DISABLE_CRYPTO; + writel_relaxed(config, host->ioaddr + HC_VENDOR_SPECIFIC_FUNC4); + + /* + * CQCAP register is in different register space from above + * ice global enable register. So a mb() is required to ensure + * above write gets completed before reading the CQCAP register. + */ + mb(); + + /* + * Check if ICE HCI capability support is present + * If present, enable it. + */ + ice_cap = readl_relaxed(msm_host->cryptoio + ICE_CQ_CAPABILITIES); + if (ice_cap & ICE_HCI_SUPPORT) { + config = readl_relaxed(msm_host->cryptoio + ICE_CQ_CONFIG); + + if (enable) + config |= CRYPTO_GENERAL_ENABLE; + else + config &= ~CRYPTO_GENERAL_ENABLE; + writel_relaxed(config, msm_host->cryptoio + ICE_CQ_CONFIG); + } +} + int sdhci_msm_ice_get_dev(struct sdhci_host *host) { struct device *sdhc_dev; @@ -96,6 +142,37 @@ int sdhci_msm_ice_get_dev(struct sdhci_host *host) return 0; } +static +int sdhci_msm_ice_pltfm_init(struct sdhci_msm_host *msm_host) +{ + struct resource *ice_memres = NULL; + struct platform_device *pdev = msm_host->pdev; + int err = 0; + + if (!msm_host->ice_hci_support) + goto out; + /* + * ICE HCI registers are present in cmdq register space. + * So map the cmdq mem for accessing ICE HCI registers. + */ + ice_memres = platform_get_resource_byname(pdev, + IORESOURCE_MEM, "cmdq_mem"); + if (!ice_memres) { + dev_err(&pdev->dev, "Failed to get iomem resource for ice\n"); + err = -EINVAL; + goto out; + } + msm_host->cryptoio = devm_ioremap(&pdev->dev, + ice_memres->start, + resource_size(ice_memres)); + if (!msm_host->cryptoio) { + dev_err(&pdev->dev, "Failed to remap registers\n"); + err = -ENOMEM; + } +out: + return err; +} + int sdhci_msm_ice_init(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -103,6 +180,13 @@ int sdhci_msm_ice_init(struct sdhci_host *host) int err = 0; 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_error_cb); @@ -110,6 +194,8 @@ int sdhci_msm_ice_init(struct sdhci_host *host) pr_err("%s: ice init err %d\n", mmc_hostname(host->mmc), 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; @@ -227,6 +313,10 @@ int sdhci_msm_ice_reset(struct sdhci_host *host) } } + /* 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", mmc_hostname(host->mmc), msm_host->ice.state); diff --git a/drivers/mmc/host/sdhci-msm-ice.h b/drivers/mmc/host/sdhci-msm-ice.h index 1c4266330290..23922cf7458a 100644 --- a/drivers/mmc/host/sdhci-msm-ice.h +++ b/drivers/mmc/host/sdhci-msm-ice.h @@ -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 @@ -37,6 +37,18 @@ #define CORE_VENDOR_SPEC_ICE_CTRL_INFO_2_n 0x308 #define CORE_VENDOR_SPEC_ICE_CTRL_INFO_3_n 0x30C +/* ICE3.0 register which got added cmdq reg space */ +#define ICE_CQ_CAPABILITIES 0x04 +#define ICE_HCI_SUPPORT (1 << 28) +#define ICE_CQ_CONFIG 0x08 +#define CRYPTO_GENERAL_ENABLE (1 << 1) + +/* ICE3.0 register which got added hc reg space */ +#define HC_VENDOR_SPECIFIC_FUNC4 0x260 +#define DISABLE_CRYPTO (1 << 15) +#define HC_VENDOR_SPECIFIC_ICE_CTRL 0x800 +#define ICE_SW_RST_EN (1 << 0) + /* SDHCI MSM ICE CTRL Info register offset */ enum { OFFSET_SDHCI_MSM_ICE_CTRL_INFO_BYPASS = 0, @@ -76,6 +88,11 @@ enum { SDHCI_MSM_ICE_STATE_SUSPENDED = 2, }; +/* crypto context fields in cmdq data command task descriptor */ +#define DATA_UNIT_NUM(x) (((u64)(x) & 0xFFFFFFFF) << 0) +#define CRYPTO_CONFIG_INDEX(x) (((u64)(x) & 0xFF) << 32) +#define CRYPTO_ENABLE(x) (((u64)(x) & 0x1) << 47) + #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); diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 466e0a2c8483..cd4fb9431811 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -4099,6 +4099,9 @@ static void sdhci_set_default_hw_caps(struct sdhci_msm_host *msm_host, msm_host_offset->CORE_VENDOR_SPEC_CAPABILITIES0); /* keep track of the value in SDHCI_CAPABILITIES */ msm_host->caps_0 = caps; + + if ((major == 1) && (minor >= 0x6b)) + msm_host->ice_hci_support = true; } #ifdef CONFIG_MMC_CQ_HCI diff --git a/drivers/mmc/host/sdhci-msm.h b/drivers/mmc/host/sdhci-msm.h index 6f96ea97bddc..c26636198a22 100644 --- a/drivers/mmc/host/sdhci-msm.h +++ b/drivers/mmc/host/sdhci-msm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-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 @@ -174,6 +174,8 @@ struct sdhci_msm_ice_data { struct sdhci_msm_host { struct platform_device *pdev; void __iomem *core_mem; /* MSM SDCC mapped address */ + void __iomem *cryptoio; /* ICE HCI mapped address */ + bool ice_hci_support; int pwr_irq; /* power irq */ struct clk *clk; /* main SD/MMC bus clock */ struct clk *pclk; /* SDHC peripheral bus clock */