common: Drop linux/delay.h from common header
[oweals/u-boot.git] / drivers / mmc / iproc_sdhci.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2019 Broadcom.
4  *
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <malloc.h>
11 #include <sdhci.h>
12 #include <linux/delay.h>
13
14 DECLARE_GLOBAL_DATA_PTR;
15
16 struct sdhci_iproc_host {
17         struct sdhci_host host;
18         u32 shadow_cmd;
19         u32 shadow_blk;
20 };
21
22 #define REG_OFFSET_IN_BITS(reg) ((reg) << 3 & 0x18)
23
24 static inline struct sdhci_iproc_host *to_iproc(struct sdhci_host *host)
25 {
26         return (struct sdhci_iproc_host *)host;
27 }
28
29 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
30 static u32 sdhci_iproc_readl(struct sdhci_host *host, int reg)
31 {
32         u32 val = readl(host->ioaddr + reg);
33 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS_TRACE
34         printf("%s %d: readl [0x%02x] 0x%08x\n",
35                host->name, host->index, reg, val);
36 #endif
37         return val;
38 }
39
40 static u16 sdhci_iproc_readw(struct sdhci_host *host, int reg)
41 {
42         u32 val = sdhci_iproc_readl(host, (reg & ~3));
43         u16 word = val >> REG_OFFSET_IN_BITS(reg) & 0xffff;
44         return word;
45 }
46
47 static u8 sdhci_iproc_readb(struct sdhci_host *host, int reg)
48 {
49         u32 val = sdhci_iproc_readl(host, (reg & ~3));
50         u8 byte = val >> REG_OFFSET_IN_BITS(reg) & 0xff;
51         return byte;
52 }
53
54 static void sdhci_iproc_writel(struct sdhci_host *host, u32 val, int reg)
55 {
56         u32 clock = 0;
57 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS_TRACE
58         printf("%s %d: writel [0x%02x] 0x%08x\n",
59                host->name, host->index, reg, val);
60 #endif
61         writel(val, host->ioaddr + reg);
62
63         if (host->mmc)
64                 clock = host->mmc->clock;
65         if (clock <= 400000) {
66                 /* Round up to micro-second four SD clock delay */
67                 if (clock)
68                         udelay((4 * 1000000 + clock - 1) / clock);
69                 else
70                         udelay(10);
71         }
72 }
73
74 /*
75  * The Arasan has a bugette whereby it may lose the content of successive
76  * writes to the same register that are within two SD-card clock cycles of
77  * each other (a clock domain crossing problem). The data
78  * register does not have this problem, which is just as well - otherwise we'd
79  * have to nobble the DMA engine too.
80  *
81  * This wouldn't be a problem with the code except that we can only write the
82  * controller with 32-bit writes.  So two different 16-bit registers are
83  * written back to back creates the problem.
84  *
85  * In reality, this only happens when SDHCI_BLOCK_SIZE and SDHCI_BLOCK_COUNT
86  * are written followed by SDHCI_TRANSFER_MODE and SDHCI_COMMAND.
87  * The BLOCK_SIZE and BLOCK_COUNT are meaningless until a command issued so
88  * the work around can be further optimized. We can keep shadow values of
89  * BLOCK_SIZE, BLOCK_COUNT, and TRANSFER_MODE until a COMMAND is issued.
90  * Then, write the BLOCK_SIZE+BLOCK_COUNT in a single 32-bit write followed
91  * by the TRANSFER+COMMAND in another 32-bit write.
92  */
93 static void sdhci_iproc_writew(struct sdhci_host *host, u16 val, int reg)
94 {
95         struct sdhci_iproc_host *iproc_host = to_iproc(host);
96         u32 word_shift = REG_OFFSET_IN_BITS(reg);
97         u32 mask = 0xffff << word_shift;
98         u32 oldval, newval;
99
100         if (reg == SDHCI_COMMAND) {
101                 /* Write the block now as we are issuing a command */
102                 if (iproc_host->shadow_blk != 0) {
103                         sdhci_iproc_writel(host, iproc_host->shadow_blk,
104                                            SDHCI_BLOCK_SIZE);
105                         iproc_host->shadow_blk = 0;
106                 }
107                 oldval = iproc_host->shadow_cmd;
108         } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) {
109                 /* Block size and count are stored in shadow reg */
110                 oldval = iproc_host->shadow_blk;
111         } else {
112                 /* Read reg, all other registers are not shadowed */
113                 oldval = sdhci_iproc_readl(host, (reg & ~3));
114         }
115         newval = (oldval & ~mask) | (val << word_shift);
116
117         if (reg == SDHCI_TRANSFER_MODE) {
118                 /* Save the transfer mode until the command is issued */
119                 iproc_host->shadow_cmd = newval;
120         } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) {
121                 /* Save the block info until the command is issued */
122                 iproc_host->shadow_blk = newval;
123         } else {
124                 /* Command or other regular 32-bit write */
125                 sdhci_iproc_writel(host, newval, reg & ~3);
126         }
127 }
128
129 static void sdhci_iproc_writeb(struct sdhci_host *host, u8 val, int reg)
130 {
131         u32 oldval = sdhci_iproc_readl(host, (reg & ~3));
132         u32 byte_shift = REG_OFFSET_IN_BITS(reg);
133         u32 mask = 0xff << byte_shift;
134         u32 newval = (oldval & ~mask) | (val << byte_shift);
135
136         sdhci_iproc_writel(host, newval, reg & ~3);
137 }
138 #endif
139
140 static int sdhci_iproc_set_ios_post(struct sdhci_host *host)
141 {
142         u32 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
143
144         /* Reset UHS mode bits */
145         ctrl &= ~SDHCI_CTRL_UHS_MASK;
146
147         if (host->mmc->ddr_mode)
148                 ctrl |= UHS_DDR50_BUS_SPEED;
149
150         sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
151
152         return 0;
153 }
154
155 static struct sdhci_ops sdhci_platform_ops = {
156 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
157         .read_l = sdhci_iproc_readl,
158         .read_w = sdhci_iproc_readw,
159         .read_b = sdhci_iproc_readb,
160         .write_l = sdhci_iproc_writel,
161         .write_w = sdhci_iproc_writew,
162         .write_b = sdhci_iproc_writeb,
163 #endif
164         .set_ios_post = sdhci_iproc_set_ios_post,
165 };
166
167 struct iproc_sdhci_plat {
168         struct mmc_config cfg;
169         struct mmc mmc;
170 };
171
172 static int iproc_sdhci_probe(struct udevice *dev)
173 {
174         struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
175         struct iproc_sdhci_plat *plat = dev_get_platdata(dev);
176         struct sdhci_host *host = dev_get_priv(dev);
177         struct sdhci_iproc_host *iproc_host;
178         int node = dev_of_offset(dev);
179         u32 f_min_max[2];
180         int ret;
181
182         iproc_host = malloc(sizeof(struct sdhci_iproc_host));
183         if (!iproc_host) {
184                 printf("%s: sdhci host malloc fail!\n", __func__);
185                 return -ENOMEM;
186         }
187         iproc_host->shadow_cmd = 0;
188         iproc_host->shadow_blk = 0;
189
190         host->name = dev->name;
191         host->ioaddr = (void *)devfdt_get_addr(dev);
192         host->voltages = MMC_VDD_165_195 |
193                          MMC_VDD_32_33 | MMC_VDD_33_34;
194         host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B;
195         host->host_caps = MMC_MODE_DDR_52MHz;
196         host->index = fdtdec_get_uint(gd->fdt_blob, node, "index", 0);
197         host->ops = &sdhci_platform_ops;
198         host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
199         ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
200                                    "clock-freq-min-max", f_min_max, 2);
201         if (ret) {
202                 printf("sdhci: clock-freq-min-max not found\n");
203                 free(iproc_host);
204                 return ret;
205         }
206         host->max_clk = f_min_max[1];
207         host->bus_width = fdtdec_get_int(gd->fdt_blob,
208                                          dev_of_offset(dev), "bus-width", 4);
209
210         /* Update host_caps for 8 bit bus width */
211         if (host->bus_width == 8)
212                 host->host_caps |= MMC_MODE_8BIT;
213
214         memcpy(&iproc_host->host, host, sizeof(struct sdhci_host));
215
216         iproc_host->host.mmc = &plat->mmc;
217         iproc_host->host.mmc->dev = dev;
218         iproc_host->host.mmc->priv = &iproc_host->host;
219         upriv->mmc = iproc_host->host.mmc;
220
221         ret = sdhci_setup_cfg(&plat->cfg, &iproc_host->host,
222                               f_min_max[1], f_min_max[0]);
223         if (ret) {
224                 free(iproc_host);
225                 return ret;
226         }
227
228         return sdhci_probe(dev);
229 }
230
231 static int iproc_sdhci_bind(struct udevice *dev)
232 {
233         struct iproc_sdhci_plat *plat = dev_get_platdata(dev);
234
235         return sdhci_bind(dev, &plat->mmc, &plat->cfg);
236 }
237
238 static const struct udevice_id iproc_sdhci_ids[] = {
239         { .compatible = "brcm,iproc-sdhci" },
240         { }
241 };
242
243 U_BOOT_DRIVER(iproc_sdhci_drv) = {
244         .name = "iproc_sdhci",
245         .id = UCLASS_MMC,
246         .of_match = iproc_sdhci_ids,
247         .ops = &sdhci_ops,
248         .bind = iproc_sdhci_bind,
249         .probe = iproc_sdhci_probe,
250         .priv_auto_alloc_size = sizeof(struct sdhci_host),
251         .platdata_auto_alloc_size = sizeof(struct iproc_sdhci_plat),
252 };