126 lines
3.6 KiB
C

/*
* 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 "sdhci-platform.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)
{
struct rt_device *dev = &pdev->parent;
struct rt_sdhci_host *host = pdev->priv;
struct rt_sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
rt_uint32_t bus_width;
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) == 0 && 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,
size_t priv_size)
{
struct rt_sdhci_host *host;
struct rt_device *dev = &pdev->parent;
void *ioaddr;
int irq;
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;
}
int rt_sdhci_pltfm_init_and_add_host(struct rt_platform_device *pdev,
const struct rt_sdhci_pltfm_data *pdata,
size_t priv_size)
{
struct rt_sdhci_host *host;
int ret = 0;
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);
}
void rt_sdhci_pltfm_remove(struct rt_platform_device *pdev)
{
struct rt_sdhci_host *host = pdev->priv;
int dead = (readl(host->ioaddr + RT_SDHCI_INT_STATUS) == 0xffffffff);
rt_sdhci_uninit_host(host, dead);
rt_sdhci_pltfm_free(pdev);
}