u-boot/drivers/mmc/f_sdh30.c
Tom Rini d678a59d2d Revert "Merge patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet""
When bringing in the series 'arm: dts: am62-beagleplay: Fix Beagleplay
Ethernet"' I failed to notice that b4 noticed it was based on next and
so took that as the base commit and merged that part of next to master.

This reverts commit c8ffd1356d, reversing
changes made to 2ee6f3a5f7.

Reported-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Tom Rini <trini@konsulko.com>
2024-05-19 08:16:36 -06:00

144 lines
3.2 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Socionext F_SDH30 eMMC driver
* Copyright 2021 Linaro Ltd.
* Copyright 2021 Socionext, Inc.
*/
#include <common.h>
#include <clk.h>
#include <dm.h>
#include <malloc.h>
#include <sdhci.h>
#define F_SDH30_ESD_CONTROL 0x124
#define F_SDH30_CMD_DAT_DELAY BIT(9)
#define F_SDH30_TEST 0x158
#define F_SDH30_FORCE_CARD_INSERT BIT(6)
struct f_sdh30_data {
void (*init)(struct udevice *dev);
u32 quirks;
};
struct f_sdh30_plat {
struct mmc_config cfg;
struct mmc mmc;
bool enable_cmd_dat_delay;
const struct f_sdh30_data *data;
};
DECLARE_GLOBAL_DATA_PTR;
static void f_sdh30_e51_init(struct udevice *dev)
{
struct f_sdh30_plat *plat = dev_get_plat(dev);
struct sdhci_host *host = dev_get_priv(dev);
u32 val;
val = sdhci_readl(host, F_SDH30_ESD_CONTROL);
if (plat->enable_cmd_dat_delay)
val |= F_SDH30_CMD_DAT_DELAY;
else
val &= ~F_SDH30_CMD_DAT_DELAY;
sdhci_writel(host, val, F_SDH30_ESD_CONTROL);
val = sdhci_readl(host, F_SDH30_TEST);
if (plat->cfg.host_caps & MMC_CAP_NONREMOVABLE)
val |= F_SDH30_FORCE_CARD_INSERT;
else
val &= ~F_SDH30_FORCE_CARD_INSERT;
sdhci_writel(host, val, F_SDH30_TEST);
}
static int f_sdh30_sdhci_probe(struct udevice *dev)
{
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct f_sdh30_plat *plat = dev_get_plat(dev);
struct sdhci_host *host = dev_get_priv(dev);
int ret;
plat->data = (const struct f_sdh30_data *)dev_get_driver_data(dev);
ret = mmc_of_parse(dev, &plat->cfg);
if (ret)
return ret;
host->mmc = &plat->mmc;
host->mmc->dev = dev;
host->mmc->priv = host;
if (plat->data && plat->data->quirks)
host->quirks = plat->data->quirks;
ret = sdhci_setup_cfg(&plat->cfg, host, 200000000, 400000);
if (ret)
return ret;
upriv->mmc = host->mmc;
mmc_set_clock(host->mmc, host->mmc->cfg->f_min, MMC_CLK_ENABLE);
ret = sdhci_probe(dev);
if (ret)
return ret;
if (plat->data && plat->data->init)
plat->data->init(dev);
return 0;
}
static int f_sdh30_of_to_plat(struct udevice *dev)
{
struct sdhci_host *host = dev_get_priv(dev);
struct f_sdh30_plat *plat = dev_get_plat(dev);
host->name = strdup(dev->name);
host->ioaddr = dev_read_addr_ptr(dev);
host->bus_width = dev_read_u32_default(dev, "bus-width", 4);
host->index = dev_read_u32_default(dev, "index", 0);
plat->enable_cmd_dat_delay =
dev_read_bool(dev, "socionext,enable-cmd-dat-delay");
return 0;
}
static int f_sdh30_bind(struct udevice *dev)
{
struct f_sdh30_plat *plat = dev_get_plat(dev);
return sdhci_bind(dev, &plat->mmc, &plat->cfg);
}
static const struct f_sdh30_data f_sdh30_e51_data = {
.init = f_sdh30_e51_init,
.quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_SUPPORT_SINGLE,
};
static const struct udevice_id f_sdh30_mmc_ids[] = {
{
.compatible = "fujitsu,mb86s70-sdhci-3.0",
},
{
.compatible = "socionext,f-sdh30-e51-mmc",
.data = (ulong)&f_sdh30_e51_data,
},
{ }
};
U_BOOT_DRIVER(f_sdh30_drv) = {
.name = "f_sdh30_sdhci",
.id = UCLASS_MMC,
.of_match = f_sdh30_mmc_ids,
.of_to_plat = f_sdh30_of_to_plat,
.ops = &sdhci_ops,
.bind = f_sdh30_bind,
.probe = f_sdh30_sdhci_probe,
.priv_auto = sizeof(struct sdhci_host),
.plat_auto = sizeof(struct f_sdh30_plat),
};