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 <vbadigan@codeaurora.org>
This commit is contained in:
parent
42e1251b38
commit
92907bcb94
4 changed files with 114 additions and 2 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue