]> Git Repo - J-u-boot.git/blob - drivers/mmc/f_sdh30.c
Merge tag 'u-boot-imx-master-20250127' of https://gitlab.denx.de/u-boot/custodians...
[J-u-boot.git] / drivers / mmc / f_sdh30.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Socionext F_SDH30 eMMC driver
4  * Copyright 2021 Linaro Ltd.
5  * Copyright 2021 Socionext, Inc.
6  */
7
8 #include <clk.h>
9 #include <dm.h>
10 #include <malloc.h>
11 #include <sdhci.h>
12
13 #define F_SDH30_ESD_CONTROL             0x124
14 #define F_SDH30_CMD_DAT_DELAY           BIT(9)
15
16 #define F_SDH30_TEST                    0x158
17 #define F_SDH30_FORCE_CARD_INSERT       BIT(6)
18
19 struct f_sdh30_data {
20         void (*init)(struct udevice *dev);
21         u32 quirks;
22 };
23
24 struct f_sdh30_plat {
25         struct mmc_config cfg;
26         struct mmc mmc;
27
28         bool enable_cmd_dat_delay;
29         const struct f_sdh30_data *data;
30 };
31
32 DECLARE_GLOBAL_DATA_PTR;
33
34 static void f_sdh30_e51_init(struct udevice *dev)
35 {
36         struct f_sdh30_plat *plat = dev_get_plat(dev);
37         struct sdhci_host *host = dev_get_priv(dev);
38         u32 val;
39
40         val = sdhci_readl(host, F_SDH30_ESD_CONTROL);
41         if (plat->enable_cmd_dat_delay)
42                 val |= F_SDH30_CMD_DAT_DELAY;
43         else
44                 val &= ~F_SDH30_CMD_DAT_DELAY;
45         sdhci_writel(host, val, F_SDH30_ESD_CONTROL);
46
47         val = sdhci_readl(host, F_SDH30_TEST);
48         if (plat->cfg.host_caps & MMC_CAP_NONREMOVABLE)
49                 val |= F_SDH30_FORCE_CARD_INSERT;
50         else
51                 val &= ~F_SDH30_FORCE_CARD_INSERT;
52         sdhci_writel(host, val, F_SDH30_TEST);
53 }
54
55 static int f_sdh30_sdhci_probe(struct udevice *dev)
56 {
57         struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
58         struct f_sdh30_plat *plat = dev_get_plat(dev);
59         struct sdhci_host *host = dev_get_priv(dev);
60         int ret;
61
62         plat->data = (const struct f_sdh30_data *)dev_get_driver_data(dev);
63
64         ret = mmc_of_parse(dev, &plat->cfg);
65         if (ret)
66                 return ret;
67
68         host->mmc = &plat->mmc;
69         host->mmc->dev = dev;
70         host->mmc->priv = host;
71
72         if (plat->data && plat->data->quirks)
73                 host->quirks = plat->data->quirks;
74
75         ret = sdhci_setup_cfg(&plat->cfg, host, 200000000, 400000);
76         if (ret)
77                 return ret;
78
79         upriv->mmc = host->mmc;
80
81         mmc_set_clock(host->mmc, host->mmc->cfg->f_min, MMC_CLK_ENABLE);
82
83         ret = sdhci_probe(dev);
84         if (ret)
85                 return ret;
86
87         if (plat->data && plat->data->init)
88                 plat->data->init(dev);
89
90         return 0;
91 }
92
93 static int f_sdh30_of_to_plat(struct udevice *dev)
94 {
95         struct sdhci_host *host = dev_get_priv(dev);
96         struct f_sdh30_plat *plat = dev_get_plat(dev);
97
98         host->name = strdup(dev->name);
99         host->ioaddr = dev_read_addr_ptr(dev);
100         host->bus_width = dev_read_u32_default(dev, "bus-width", 4);
101         host->index = dev_read_u32_default(dev, "index", 0);
102
103         plat->enable_cmd_dat_delay =
104                 dev_read_bool(dev, "socionext,enable-cmd-dat-delay");
105
106         return 0;
107 }
108
109 static int f_sdh30_bind(struct udevice *dev)
110 {
111         struct f_sdh30_plat *plat = dev_get_plat(dev);
112
113         return sdhci_bind(dev, &plat->mmc, &plat->cfg);
114 }
115
116 static const struct f_sdh30_data f_sdh30_e51_data = {
117         .init = f_sdh30_e51_init,
118         .quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_SUPPORT_SINGLE,
119 };
120
121 static const struct udevice_id f_sdh30_mmc_ids[] = {
122         {
123                 .compatible = "fujitsu,mb86s70-sdhci-3.0",
124         },
125         {
126                 .compatible = "socionext,f-sdh30-e51-mmc",
127                 .data = (ulong)&f_sdh30_e51_data,
128         },
129         { }
130 };
131
132 U_BOOT_DRIVER(f_sdh30_drv) = {
133         .name           = "f_sdh30_sdhci",
134         .id             = UCLASS_MMC,
135         .of_match       = f_sdh30_mmc_ids,
136         .of_to_plat     = f_sdh30_of_to_plat,
137         .ops            = &sdhci_ops,
138         .bind           = f_sdh30_bind,
139         .probe          = f_sdh30_sdhci_probe,
140         .priv_auto      = sizeof(struct sdhci_host),
141         .plat_auto      = sizeof(struct f_sdh30_plat),
142 };
This page took 0.030619 seconds and 4 git commands to generate.