Skip to content

Commit 87a8df0

Browse files
Ritesh Harjanistorulf
authored andcommitted
mmc: sdhci-msm: Add CQHCI support for sdhci-msm
This adds CQHCI support for sdhci-msm platforms. Signed-off-by: Ritesh Harjani <[email protected]> Signed-off-by: Veerabhadrarao Badiganti <[email protected]> Acked-by: Adrian Hunter <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ulf Hansson <[email protected]>
1 parent a663f64 commit 87a8df0

File tree

2 files changed

+133
-1
lines changed

2 files changed

+133
-1
lines changed

drivers/mmc/host/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ config MMC_SDHCI_MSM
501501
depends on ARCH_QCOM || (ARM && COMPILE_TEST)
502502
depends on MMC_SDHCI_PLTFM
503503
select MMC_SDHCI_IO_ACCESSORS
504+
select MMC_CQHCI
504505
help
505506
This selects the Secure Digital Host Controller Interface (SDHCI)
506507
support present in Qualcomm SOCs. The controller supports

drivers/mmc/host/sdhci-msm.c

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/regulator/consumer.h>
1616

1717
#include "sdhci-pltfm.h"
18+
#include "cqhci.h"
1819

1920
#define CORE_MCI_VERSION 0x50
2021
#define CORE_VERSION_MAJOR_SHIFT 28
@@ -122,6 +123,10 @@
122123
#define msm_host_writel(msm_host, val, host, offset) \
123124
msm_host->var_ops->msm_writel_relaxed(val, host, offset)
124125

126+
/* CQHCI vendor specific registers */
127+
#define CQHCI_VENDOR_CFG1 0xA00
128+
#define CQHCI_VENDOR_DIS_RST_ON_CQ_EN (0x3 << 13)
129+
125130
struct sdhci_msm_offset {
126131
u32 core_hc_mode;
127132
u32 core_mci_data_cnt;
@@ -1567,6 +1572,127 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
15671572
__sdhci_msm_set_clock(host, clock);
15681573
}
15691574

1575+
/*****************************************************************************\
1576+
* *
1577+
* MSM Command Queue Engine (CQE) *
1578+
* *
1579+
\*****************************************************************************/
1580+
1581+
static u32 sdhci_msm_cqe_irq(struct sdhci_host *host, u32 intmask)
1582+
{
1583+
int cmd_error = 0;
1584+
int data_error = 0;
1585+
1586+
if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error))
1587+
return intmask;
1588+
1589+
cqhci_irq(host->mmc, intmask, cmd_error, data_error);
1590+
return 0;
1591+
}
1592+
1593+
void sdhci_msm_cqe_disable(struct mmc_host *mmc, bool recovery)
1594+
{
1595+
struct sdhci_host *host = mmc_priv(mmc);
1596+
unsigned long flags;
1597+
u32 ctrl;
1598+
1599+
/*
1600+
* When CQE is halted, the legacy SDHCI path operates only
1601+
* on 16-byte descriptors in 64bit mode.
1602+
*/
1603+
if (host->flags & SDHCI_USE_64_BIT_DMA)
1604+
host->desc_sz = 16;
1605+
1606+
spin_lock_irqsave(&host->lock, flags);
1607+
1608+
/*
1609+
* During CQE command transfers, command complete bit gets latched.
1610+
* So s/w should clear command complete interrupt status when CQE is
1611+
* either halted or disabled. Otherwise unexpected SDCHI legacy
1612+
* interrupt gets triggered when CQE is halted/disabled.
1613+
*/
1614+
ctrl = sdhci_readl(host, SDHCI_INT_ENABLE);
1615+
ctrl |= SDHCI_INT_RESPONSE;
1616+
sdhci_writel(host, ctrl, SDHCI_INT_ENABLE);
1617+
sdhci_writel(host, SDHCI_INT_RESPONSE, SDHCI_INT_STATUS);
1618+
1619+
spin_unlock_irqrestore(&host->lock, flags);
1620+
1621+
sdhci_cqe_disable(mmc, recovery);
1622+
}
1623+
1624+
static const struct cqhci_host_ops sdhci_msm_cqhci_ops = {
1625+
.enable = sdhci_cqe_enable,
1626+
.disable = sdhci_msm_cqe_disable,
1627+
};
1628+
1629+
static int sdhci_msm_cqe_add_host(struct sdhci_host *host,
1630+
struct platform_device *pdev)
1631+
{
1632+
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
1633+
struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
1634+
struct cqhci_host *cq_host;
1635+
bool dma64;
1636+
u32 cqcfg;
1637+
int ret;
1638+
1639+
/*
1640+
* When CQE is halted, SDHC operates only on 16byte ADMA descriptors.
1641+
* So ensure ADMA table is allocated for 16byte descriptors.
1642+
*/
1643+
if (host->caps & SDHCI_CAN_64BIT)
1644+
host->alloc_desc_sz = 16;
1645+
1646+
ret = sdhci_setup_host(host);
1647+
if (ret)
1648+
return ret;
1649+
1650+
cq_host = cqhci_pltfm_init(pdev);
1651+
if (IS_ERR(cq_host)) {
1652+
ret = PTR_ERR(cq_host);
1653+
dev_err(&pdev->dev, "cqhci-pltfm init: failed: %d\n", ret);
1654+
goto cleanup;
1655+
}
1656+
1657+
msm_host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD;
1658+
cq_host->ops = &sdhci_msm_cqhci_ops;
1659+
1660+
dma64 = host->flags & SDHCI_USE_64_BIT_DMA;
1661+
1662+
ret = cqhci_init(cq_host, host->mmc, dma64);
1663+
if (ret) {
1664+
dev_err(&pdev->dev, "%s: CQE init: failed (%d)\n",
1665+
mmc_hostname(host->mmc), ret);
1666+
goto cleanup;
1667+
}
1668+
1669+
/* Disable cqe reset due to cqe enable signal */
1670+
cqcfg = cqhci_readl(cq_host, CQHCI_VENDOR_CFG1);
1671+
cqcfg |= CQHCI_VENDOR_DIS_RST_ON_CQ_EN;
1672+
cqhci_writel(cq_host, cqcfg, CQHCI_VENDOR_CFG1);
1673+
1674+
/*
1675+
* SDHC expects 12byte ADMA descriptors till CQE is enabled.
1676+
* So limit desc_sz to 12 so that the data commands that are sent
1677+
* during card initialization (before CQE gets enabled) would
1678+
* get executed without any issues.
1679+
*/
1680+
if (host->flags & SDHCI_USE_64_BIT_DMA)
1681+
host->desc_sz = 12;
1682+
1683+
ret = __sdhci_add_host(host);
1684+
if (ret)
1685+
goto cleanup;
1686+
1687+
dev_info(&pdev->dev, "%s: CQE init: success\n",
1688+
mmc_hostname(host->mmc));
1689+
return ret;
1690+
1691+
cleanup:
1692+
sdhci_cleanup_host(host);
1693+
return ret;
1694+
}
1695+
15701696
/*
15711697
* Platform specific register write functions. This is so that, if any
15721698
* register write needs to be followed up by platform specific actions,
@@ -1731,6 +1857,7 @@ static const struct sdhci_ops sdhci_msm_ops = {
17311857
.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
17321858
.write_w = sdhci_msm_writew,
17331859
.write_b = sdhci_msm_writeb,
1860+
.irq = sdhci_msm_cqe_irq,
17341861
};
17351862

17361863
static const struct sdhci_pltfm_data sdhci_msm_pdata = {
@@ -1753,6 +1880,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)
17531880
u8 core_major;
17541881
const struct sdhci_msm_offset *msm_offset;
17551882
const struct sdhci_msm_variant_info *var_info;
1883+
struct device_node *node = pdev->dev.of_node;
17561884

17571885
host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, sizeof(*msm_host));
17581886
if (IS_ERR(host))
@@ -1948,7 +2076,10 @@ static int sdhci_msm_probe(struct platform_device *pdev)
19482076
pm_runtime_use_autosuspend(&pdev->dev);
19492077

19502078
host->mmc_host_ops.execute_tuning = sdhci_msm_execute_tuning;
1951-
ret = sdhci_add_host(host);
2079+
if (of_property_read_bool(node, "supports-cqe"))
2080+
ret = sdhci_msm_cqe_add_host(host, pdev);
2081+
else
2082+
ret = sdhci_add_host(host);
19522083
if (ret)
19532084
goto pm_runtime_disable;
19542085
sdhci_msm_set_regulator_caps(msm_host);

0 commit comments

Comments
 (0)