]> Git Repo - J-u-boot.git/blob - drivers/mmc/hi6220_dw_mmc.c
c68a9157bfccf16e642cb237dc57e58ab59173dc
[J-u-boot.git] / drivers / mmc / hi6220_dw_mmc.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2015 Linaro
4  * peter.griffin <[email protected]>
5  */
6
7 #include <clk.h>
8 #include <dm.h>
9 #include <dwmmc.h>
10 #include <errno.h>
11 #include <fdtdec.h>
12 #include <malloc.h>
13 #include <reset.h>
14 #include <asm/global_data.h>
15 #include <dm/device_compat.h>
16
17 DECLARE_GLOBAL_DATA_PTR;
18
19 enum hi6220_dwmmc_clk_type {
20         HI6220_DWMMC_CLK_BIU,
21         HI6220_DWMMC_CLK_CIU,
22         HI6220_DWMMC_CLK_CNT,
23 };
24
25 struct hi6220_dwmmc_plat {
26         struct mmc_config cfg;
27         struct mmc mmc;
28 };
29
30 struct hi6220_dwmmc_priv_data {
31         struct dwmci_host host;
32         struct clk *clks[HI6220_DWMMC_CLK_CNT];
33         struct reset_ctl_bulk rsts;
34 };
35
36 struct hisi_mmc_data {
37         unsigned int clock;
38         bool use_fifo;
39         u32 fifoth_val;
40 };
41
42 static int hi6220_dwmmc_of_to_plat(struct udevice *dev)
43 {
44         struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev);
45         struct dwmci_host *host = &priv->host;
46         int ret;
47
48         if (CONFIG_IS_ENABLED(CLK) && CONFIG_IS_ENABLED(DM_RESET)) {
49                 priv->clks[HI6220_DWMMC_CLK_BIU] = devm_clk_get(dev, "biu");
50                 if (IS_ERR(priv->clks[HI6220_DWMMC_CLK_BIU])) {
51                         ret = PTR_ERR(priv->clks[HI6220_DWMMC_CLK_BIU]);
52                         dev_err(dev, "Failed to get BIU clock(ret = %d).\n", ret);
53                         return log_msg_ret("clk", ret);
54                 }
55
56                 priv->clks[HI6220_DWMMC_CLK_CIU] = devm_clk_get(dev, "ciu");
57                 if (IS_ERR(priv->clks[HI6220_DWMMC_CLK_CIU])) {
58                         ret = PTR_ERR(priv->clks[HI6220_DWMMC_CLK_CIU]);
59                         dev_err(dev, "Failed to get CIU clock(ret = %d).\n", ret);
60                         return log_msg_ret("clk", ret);
61                 }
62
63                 ret = reset_get_bulk(dev, &priv->rsts);
64                 if (ret) {
65                         dev_err(dev, "Failed to get resets(ret = %d)", ret);
66                         return log_msg_ret("rst", ret);
67                 }
68         }
69         host->name = dev->name;
70         host->ioaddr = dev_read_addr_ptr(dev);
71         host->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
72                                         "bus-width", 4);
73
74         /* use non-removable property for differentiating SD card and eMMC */
75         if (dev_read_bool(dev, "non-removable"))
76                 host->dev_index = 0;
77         else
78                 host->dev_index = 1;
79
80         host->priv = priv;
81
82         return 0;
83 }
84
85 static int hi6220_dwmmc_probe(struct udevice *dev)
86 {
87         struct hi6220_dwmmc_plat *plat = dev_get_plat(dev);
88         struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
89         struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev);
90         struct dwmci_host *host = &priv->host;
91         struct hisi_mmc_data *mmc_data;
92         int ret;
93
94         mmc_data = (struct hisi_mmc_data *)dev_get_driver_data(dev);
95
96         host->bus_hz = mmc_data->clock;
97         if (CONFIG_IS_ENABLED(CLK) && CONFIG_IS_ENABLED(DM_RESET)) {
98                 ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_BIU]);
99                 if (ret) {
100                         dev_err(dev, "Failed to enable biu clock(ret = %d).\n", ret);
101                         return log_msg_ret("clk", ret);
102                 }
103
104                 ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_CIU]);
105                 if (ret) {
106                         dev_err(dev, "Failed to enable ciu clock(ret = %d).\n", ret);
107                         return log_msg_ret("clk", ret);
108                 }
109
110                 ret = reset_deassert_bulk(&priv->rsts);
111                 if (ret) {
112                         dev_err(dev, "Failed to deassert resets(ret = %d).\n", ret);
113                         return log_msg_ret("rst", ret);
114                 }
115
116                 host->bus_hz = clk_get_rate(priv->clks[HI6220_DWMMC_CLK_CIU]);
117                 if (host->bus_hz <= 0) {
118                         dev_err(dev, "Failed to get ciu clock rate(ret = %d).\n", ret);
119                         return log_msg_ret("clk", ret);
120                 }
121         }
122         dev_dbg(dev, "bus clock rate: %d.\n", host->bus_hz);
123
124         dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, 400000);
125         host->mmc = &plat->mmc;
126
127         host->fifo_mode = mmc_data->use_fifo;
128         host->fifoth_val = mmc_data->fifoth_val;
129         host->mmc->priv = &priv->host;
130         upriv->mmc = host->mmc;
131         host->mmc->dev = dev;
132
133         return dwmci_probe(dev);
134 }
135
136 static int hi6220_dwmmc_bind(struct udevice *dev)
137 {
138         struct hi6220_dwmmc_plat *plat = dev_get_plat(dev);
139         int ret;
140
141         ret = dwmci_bind(dev, &plat->mmc, &plat->cfg);
142         if (ret)
143                 return ret;
144
145         return 0;
146 }
147
148 static const struct hisi_mmc_data hi3660_mmc_data = {
149         .clock = 3200000,
150         .use_fifo = true,
151 };
152
153 static const struct hisi_mmc_data hi6220_mmc_data = {
154         .clock = 50000000,
155         .use_fifo = false,
156 };
157
158 static const struct hisi_mmc_data hi3798mv2x_mmc_data = {
159         .clock = 50000000,
160         .use_fifo = false,
161         // FIFO depth is 256
162         .fifoth_val = MSIZE(4) | RX_WMARK(0x7f) | TX_WMARK(0x80),
163 };
164
165 static const struct udevice_id hi6220_dwmmc_ids[] = {
166         { .compatible = "hisilicon,hi6220-dw-mshc",
167           .data = (ulong)&hi6220_mmc_data },
168         { .compatible = "hisilicon,hi3798cv200-dw-mshc",
169           .data = (ulong)&hi6220_mmc_data },
170         { .compatible = "hisilicon,hi3798mv200-dw-mshc",
171           .data = (ulong)&hi3798mv2x_mmc_data },
172         { .compatible = "hisilicon,hi3660-dw-mshc",
173           .data = (ulong)&hi3660_mmc_data },
174         { }
175 };
176
177 U_BOOT_DRIVER(hi6220_dwmmc_drv) = {
178         .name = "hi6220_dwmmc",
179         .id = UCLASS_MMC,
180         .of_match = hi6220_dwmmc_ids,
181         .of_to_plat = hi6220_dwmmc_of_to_plat,
182         .ops = &dm_dwmci_ops,
183         .bind = hi6220_dwmmc_bind,
184         .probe = hi6220_dwmmc_probe,
185         .priv_auto      = sizeof(struct hi6220_dwmmc_priv_data),
186         .plat_auto      = sizeof(struct hi6220_dwmmc_plat),
187 };
This page took 0.025425 seconds and 2 git commands to generate.