diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c index d97a9041fdd9..e7b6b995f5a3 100644 --- a/drivers/mmc/host/cqhci.c +++ b/drivers/mmc/host/cqhci.c @@ -18,6 +18,7 @@ #include #include "cqhci.h" +#include "cqhci-crypto.h" #define DCMD_SLOT 31 #define NUM_SLOTS 32 @@ -138,6 +139,8 @@ static void cqhci_dumpregs(struct cqhci_host *cq_host) cqhci_readl(cq_host, CQHCI_CRI), cqhci_readl(cq_host, CQHCI_CRA)); + cqhci_crypto_debug(cq_host); + if (cq_host->ops->dumpregs) cq_host->ops->dumpregs(mmc); else @@ -258,6 +261,11 @@ static void __cqhci_enable(struct cqhci_host *cq_host) if (cq_host->caps & CQHCI_TASK_DESC_SZ_128) cqcfg |= CQHCI_TASK_DESC_SZ; + if (cqhci_host_is_crypto_supported(cq_host)) { + cqhci_crypto_enable(cq_host); + cqcfg |= CQHCI_ICE_ENABLE; + } + cqhci_writel(cq_host, cqcfg, CQHCI_CFG); cqhci_writel(cq_host, lower_32_bits(cq_host->desc_dma_base), @@ -290,6 +298,9 @@ static void __cqhci_disable(struct cqhci_host *cq_host) { u32 cqcfg; + if (cqhci_host_is_crypto_supported(cq_host)) + cqhci_crypto_disable(cq_host); + cqcfg = cqhci_readl(cq_host, CQHCI_CFG); cqcfg &= ~CQHCI_ENABLE; cqhci_writel(cq_host, cqcfg, CQHCI_CFG); @@ -303,6 +314,8 @@ int cqhci_deactivate(struct mmc_host *mmc) { struct cqhci_host *cq_host = mmc->cqe_private; + cqhci_crypto_suspend(cq_host); + if (cq_host->enabled && cq_host->activated) __cqhci_disable(cq_host); @@ -561,6 +574,30 @@ static inline int cqhci_tag(struct mmc_request *mrq) return mrq->cmd ? DCMD_SLOT : mrq->tag; } +static inline +void cqhci_prep_crypto_desc(struct cqhci_host *cq_host, u64 *task_desc, + u64 ice_ctx) +{ + __le64 *ice_desc = NULL; + + if (cq_host->caps & CQHCI_CAP_CRYPTO_SUPPORT) { + /* + * Get the address of ice context for the given task descriptor. + * ice context is present in the upper 64bits of task descriptor + * ice_conext_base_address = task_desc + 8-bytes + */ + ice_desc = (__le64 *)((u8 *)task_desc + + CQHCI_TASK_DESC_ICE_PARAM_OFFSET); + memset(ice_desc, 0, CQHCI_TASK_DESC_ICE_PARAMS_SIZE); + + /* + * Assign upper 64bits data of task descritor with ice context + */ + if (ice_ctx) + *ice_desc = cpu_to_le64(ice_ctx); + } +} + static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq) { int err = 0; @@ -569,6 +606,7 @@ static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq) int tag = cqhci_tag(mrq); struct cqhci_host *cq_host = mmc->cqe_private; unsigned long flags; + u64 ice_ctx = 0; if (!cq_host->enabled) { pr_err("%s: cqhci: not enabled\n", mmc_hostname(mmc)); @@ -592,9 +630,17 @@ static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq) } if (mrq->data) { + err = cqhci_crypto_get_ctx(cq_host, mrq, &ice_ctx); + if (err) { + pr_err("%s: failed to retrieve crypto ctx for tag %d\n", + mmc_hostname(mmc), tag); + goto out; + } task_desc = (__le64 __force *)get_desc(cq_host, tag); cqhci_prep_task_desc(mrq, &data, 1); *task_desc = cpu_to_le64(data); + cqhci_prep_crypto_desc(cq_host, task_desc, ice_ctx); + err = cqhci_prep_tran_desc(mrq, cq_host, tag); if (err) { pr_err("%s: cqhci: failed to setup tx desc: %d\n", @@ -628,6 +674,9 @@ out_unlock: if (err) cqhci_post_req(mmc, mrq); + if (mrq->data) + cqhci_complete_crypto_desc(cq_host, mrq, NULL); +out: return err; } @@ -635,7 +684,15 @@ out_unlock: static void cqhci_crypto_update_queue(struct mmc_host *mmc, struct request_queue *queue) { - //struct cqhci_host *cq_host = mmc->cqe_private; + struct cqhci_host *cq_host = mmc->cqe_private; + + if (cq_host->caps & CQHCI_CAP_CRYPTO_SUPPORT) { + if (queue) + cqhci_crypto_setup_rq_keyslot_manager(cq_host, queue); + else + pr_err("%s can not register keyslot manager\n", + mmc_hostname(mmc)); + } } #endif @@ -755,6 +812,8 @@ static void cqhci_finish_mrq(struct mmc_host *mmc, unsigned int tag) data = mrq->data; if (data) { + cqhci_complete_crypto_desc(cq_host, mrq, NULL); + if (data->error) data->bytes_xfered = 0; else @@ -942,6 +1001,8 @@ static void cqhci_recovery_start(struct mmc_host *mmc) pr_debug("%s: cqhci: %s\n", mmc_hostname(mmc), __func__); + cqhci_crypto_reset(cq_host); + WARN_ON(!cq_host->recovery_halt); cqhci_halt(mmc, CQHCI_START_HALT_TIMEOUT); @@ -1062,6 +1123,8 @@ static void cqhci_recovery_finish(struct mmc_host *mmc) cqhci_set_irqs(cq_host, CQHCI_IS_MASK); + cqhci_crypto_recovery_finish(cq_host); + pr_debug("%s: cqhci: recovery done\n", mmc_hostname(mmc)); } @@ -1103,6 +1166,11 @@ struct cqhci_host *cqhci_pltfm_init(struct platform_device *pdev) dev_err(&pdev->dev, "failed to remap cqhci regs\n"); return ERR_PTR(-EBUSY); } + +#ifdef CONFIG_MMC_CQHCI_CRYPTO_QTI + cq_host->pdev = pdev; +#endif /* CONFIG_MMC_CQHCI_CRYPTO_QTI */ + dev_dbg(&pdev->dev, "CMDQ ioremap: done\n"); return cq_host; @@ -1148,6 +1216,13 @@ int cqhci_init(struct cqhci_host *cq_host, struct mmc_host *mmc, spin_lock_init(&cq_host->lock); + err = cqhci_host_init_crypto(cq_host); + if (err) { + pr_err("%s: CQHCI version %u.%02u Crypto init failed err %d\n", + mmc_hostname(mmc), cqhci_ver_major(cq_host), + cqhci_ver_minor(cq_host), err); + } + init_completion(&cq_host->halt_comp); init_waitqueue_head(&cq_host->wait_queue); diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h index 0f9806212ee0..7a9b6d00a36c 100644 --- a/drivers/mmc/host/cqhci.h +++ b/drivers/mmc/host/cqhci.h @@ -32,6 +32,7 @@ #define CQHCI_DCMD 0x00001000 #define CQHCI_TASK_DESC_SZ 0x00000100 #define CQHCI_ENABLE 0x00000001 +#define CQHCI_ICE_ENABLE 0x00000002 /* control */ #define CQHCI_CTL 0x0C @@ -148,11 +149,20 @@ #define CQHCI_DAT_LENGTH(x) (((x) & 0xFFFF) << 16) #define CQHCI_DAT_ADDR_LO(x) (((x) & 0xFFFFFFFF) << 32) #define CQHCI_DAT_ADDR_HI(x) (((x) & 0xFFFFFFFF) << 0) +#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) + +/* ICE context is present in the upper 64bits of task descriptor */ +#define CQHCI_TASK_DESC_ICE_PARAM_OFFSET 8 +/* ICE descriptor size */ +#define CQHCI_TASK_DESC_ICE_PARAMS_SIZE 8 struct cqhci_host_ops; struct mmc_host; struct mmc_request; struct cqhci_slot; +struct cqhci_host; /* CCAP - Crypto Capability 100h */ union cqhci_crypto_capabilities { @@ -240,6 +250,7 @@ struct cqhci_host_crypto_variant_ops { struct cqhci_host { const struct cqhci_host_ops *ops; void __iomem *mmio; + void __iomem *icemmio; struct mmc_host *mmc; spinlock_t lock; @@ -255,6 +266,7 @@ struct cqhci_host { u32 dcmd_slot; u32 caps; #define CQHCI_TASK_DESC_SZ_128 0x1 +#define CQHCI_CAP_CRYPTO_SUPPORT 0x2 u32 quirks; #define CQHCI_QUIRK_SHORT_TXFR_DESC_SZ 0x1 @@ -291,6 +303,19 @@ struct cqhci_host { struct completion halt_comp; wait_queue_head_t wait_queue; struct cqhci_slot *slot; + const struct cqhci_host_crypto_variant_ops *crypto_vops; + +#ifdef CONFIG_MMC_CQHCI_CRYPTO + union cqhci_crypto_capabilities crypto_capabilities; + union cqhci_crypto_cap_entry *crypto_cap_array; + u32 crypto_cfg_register; +#ifdef CONFIG_BLK_INLINE_ENCRYPTION + struct keyslot_manager *ksm; +#endif /* CONFIG_BLK_INLINE_ENCRYPTION */ +#endif /* CONFIG_MMC_CQHCI_CRYPTO */ +#ifdef CONFIG_MMC_CQHCI_CRYPTO_QTI + struct platform_device *pdev; +#endif /* CONFIG_MMC_CQHCI_CRYPTO_QTI */ }; struct cqhci_host_ops {