Files
rt-thread/components/drivers/sdio/dev_sdhci_dm.c
T
GUI c6498b5f65 [sdio][dm] update for DM (#11078)
* [sdio][dm] import Kconfig for DM

Signed-off-by: GuEe-GUI <2991707448@qq.com>

* [sdio] fixup IRQ and mmcsd threads' stack size default

Signed-off-by: GuEe-GUI <2991707448@qq.com>

* [sdio][dm] Support DM mode

1. Support features read by DM.
2. Support regulator API in drivers.
3. Support send tuning option CMD.
4. Replace `switch_uhs_voltage` by `signal_voltage_switch`.

Signed-off-by: GuEe-GUI <2991707448@qq.com>

* [dm][sdhci] Cleanup the SDHCI

Signed-off-by: GuEe-GUI <2991707448@qq.com>

* [sdio][dm] add new SDIO/SDHCI drivers

1. SDHCI support on PCI bus
2. Synopsys DesignWare MMC Family(MMIO/PCI)

Signed-off-by: GuEe-GUI <2991707448@qq.com>

---------

Signed-off-by: GuEe-GUI <2991707448@qq.com>
2025-12-26 21:04:42 +08:00

164 lines
3.8 KiB
C
Executable File

/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-08-16 zhujiale first version
*/
#include "dev_sdhci_dm.h"
static const struct rt_sdhci_ops sdhci_pltfm_ops =
{
.set_clock = rt_sdhci_set_clock,
.set_bus_width = rt_sdhci_set_bus_width,
.reset = rt_sdhci_reset,
.set_uhs_signaling = rt_sdhci_set_uhs,
};
void rt_sdhci_get_property(struct rt_platform_device *pdev)
{
rt_uint32_t bus_width;
struct rt_device *dev = &pdev->parent;
struct rt_sdhci_host *host = pdev->priv;
struct rt_sdhci_pltfm_host *pltfm_host = rt_sdhci_priv(host);
if (rt_dm_dev_prop_read_bool(dev, "sdhci,auto-cmd12"))
{
host->quirks |= RT_SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
}
if (rt_dm_dev_prop_read_bool(dev, "sdhci,1-bit-only") ||
(!rt_dm_dev_prop_read_u32(dev, "bus-width", &bus_width) && bus_width == 1))
{
host->quirks |= RT_SDHCI_QUIRK_FORCE_1_BIT_DATA;
}
if (rt_dm_dev_prop_read_bool(dev, "broken-cd"))
{
host->quirks |= RT_SDHCI_QUIRK_BROKEN_CARD_DETECTION;
}
if (rt_dm_dev_prop_read_bool(dev, "no-1-8-v"))
{
host->quirks2 |= RT_SDHCI_QUIRK2_NO_1_8_V;
}
rt_dm_dev_prop_read_u32(dev, "clock-frequency", &pltfm_host->clock);
if (rt_dm_dev_prop_read_bool(dev, "keep-power-in-suspend"))
{
host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
}
if (rt_dm_dev_prop_read_bool(dev, "wakeup-source") ||
rt_dm_dev_prop_read_bool(dev, "enable-sdio-wakeup")) /* legacy */
{
host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
}
}
struct rt_sdhci_host *rt_sdhci_pltfm_init(struct rt_platform_device *pdev,
const struct rt_sdhci_pltfm_data *pdata,
rt_size_t priv_size)
{
int irq;
void *ioaddr;
struct rt_sdhci_host *host;
struct rt_device *dev = &pdev->parent;
ioaddr = rt_dm_dev_iomap(dev, 0);
if (!ioaddr)
{
return RT_NULL;
}
irq = rt_dm_dev_get_irq(dev, 0);
if (irq < 0)
{
return RT_NULL;
}
host = rt_sdhci_alloc_host(dev, sizeof(struct rt_sdhci_pltfm_host) + priv_size);
if (!host)
{
return RT_NULL;
}
host->irq = irq;
host->ioaddr = ioaddr;
host->hw_name = rt_dm_dev_get_name(dev);
if (pdata && pdata->ops)
{
host->ops = pdata->ops;
}
else
{
host->ops = &sdhci_pltfm_ops;
}
if (pdata)
{
host->quirks = pdata->quirks;
host->quirks2 = pdata->quirks2;
}
pdev->priv = host;
return host;
}
rt_err_t rt_sdhci_pltfm_init_and_add_host(struct rt_platform_device *pdev,
const struct rt_sdhci_pltfm_data *pdata,
rt_size_t priv_size)
{
rt_err_t ret = RT_EOK;
struct rt_sdhci_host *host;
host = rt_sdhci_pltfm_init(pdev, pdata, priv_size);
if (!host)
{
return -RT_ERROR;
}
rt_sdhci_get_property(pdev);
ret = rt_sdhci_init_host(host);
if (ret)
{
rt_sdhci_pltfm_free(pdev);
}
return ret;
}
void rt_sdhci_pltfm_free(struct rt_platform_device *pdev)
{
struct rt_sdhci_host *host = pdev->priv;
rt_sdhci_free_host(host);
}
rt_err_t rt_sdhci_pltfm_remove(struct rt_platform_device *pdev)
{
rt_bool_t dead;
struct rt_sdhci_host *host = pdev->priv;
dead = (HWREG32(host->ioaddr + RT_SDHCI_INT_STATUS) == 0xffffffff);
rt_sdhci_uninit_host(host, dead);
rt_sdhci_pltfm_free(pdev);
return RT_EOK;
}
rt_uint32_t rt_sdhci_pltfm_clk_get_max_clock(struct rt_sdhci_host *host)
{
struct rt_sdhci_pltfm_host *pltfm_host = rt_sdhci_priv(host);
return rt_clk_get_rate(pltfm_host->clk);
}