blob: fc10bb256a4df53107d54fe89f060e8f37dd72f1 [file] [log] [blame]
Paul Burton8e142842018-12-16 19:25:20 -03001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Ingenic JZ MMC driver
4 *
5 * Copyright (c) 2013 Imagination Technologies
6 * Author: Paul Burton <paul.burton@imgtec.com>
7 */
8
Paul Burton8e142842018-12-16 19:25:20 -03009#include <malloc.h>
10#include <mmc.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060011#include <asm/global_data.h>
Paul Burton8e142842018-12-16 19:25:20 -030012#include <asm/io.h>
13#include <asm/unaligned.h>
14#include <errno.h>
Simon Glass9bc15642020-02-03 07:36:16 -070015#include <dm/device_compat.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060016#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060017#include <linux/delay.h>
Paul Burton8e142842018-12-16 19:25:20 -030018#include <mach/jz4780.h>
19#include <wait_bit.h>
20
21/* Registers */
22#define MSC_STRPCL 0x000
23#define MSC_STAT 0x004
24#define MSC_CLKRT 0x008
25#define MSC_CMDAT 0x00c
26#define MSC_RESTO 0x010
27#define MSC_RDTO 0x014
28#define MSC_BLKLEN 0x018
29#define MSC_NOB 0x01c
30#define MSC_SNOB 0x020
31#define MSC_IMASK 0x024
32#define MSC_IREG 0x028
33#define MSC_CMD 0x02c
34#define MSC_ARG 0x030
35#define MSC_RES 0x034
36#define MSC_RXFIFO 0x038
37#define MSC_TXFIFO 0x03c
38#define MSC_LPM 0x040
39#define MSC_DMAC 0x044
40#define MSC_DMANDA 0x048
41#define MSC_DMADA 0x04c
42#define MSC_DMALEN 0x050
43#define MSC_DMACMD 0x054
44#define MSC_CTRL2 0x058
45#define MSC_RTCNT 0x05c
46#define MSC_DBG 0x0fc
47
48/* MSC Clock and Control Register (MSC_STRPCL) */
49#define MSC_STRPCL_EXIT_MULTIPLE BIT(7)
50#define MSC_STRPCL_EXIT_TRANSFER BIT(6)
51#define MSC_STRPCL_START_READWAIT BIT(5)
52#define MSC_STRPCL_STOP_READWAIT BIT(4)
53#define MSC_STRPCL_RESET BIT(3)
54#define MSC_STRPCL_START_OP BIT(2)
55#define MSC_STRPCL_CLOCK_CONTROL_STOP BIT(0)
56#define MSC_STRPCL_CLOCK_CONTROL_START BIT(1)
57
58/* MSC Status Register (MSC_STAT) */
59#define MSC_STAT_AUTO_CMD_DONE BIT(31)
60#define MSC_STAT_IS_RESETTING BIT(15)
61#define MSC_STAT_SDIO_INT_ACTIVE BIT(14)
62#define MSC_STAT_PRG_DONE BIT(13)
63#define MSC_STAT_DATA_TRAN_DONE BIT(12)
64#define MSC_STAT_END_CMD_RES BIT(11)
65#define MSC_STAT_DATA_FIFO_AFULL BIT(10)
66#define MSC_STAT_IS_READWAIT BIT(9)
67#define MSC_STAT_CLK_EN BIT(8)
68#define MSC_STAT_DATA_FIFO_FULL BIT(7)
69#define MSC_STAT_DATA_FIFO_EMPTY BIT(6)
70#define MSC_STAT_CRC_RES_ERR BIT(5)
71#define MSC_STAT_CRC_READ_ERROR BIT(4)
72#define MSC_STAT_CRC_WRITE_ERROR BIT(2)
73#define MSC_STAT_CRC_WRITE_ERROR_NOSTS BIT(4)
74#define MSC_STAT_TIME_OUT_RES BIT(1)
75#define MSC_STAT_TIME_OUT_READ BIT(0)
76
77/* MSC Bus Clock Control Register (MSC_CLKRT) */
78#define MSC_CLKRT_CLK_RATE_MASK 0x7
79
80/* MSC Command Sequence Control Register (MSC_CMDAT) */
81#define MSC_CMDAT_IO_ABORT BIT(11)
82#define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << 9)
83#define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << 9)
84#define MSC_CMDAT_DMA_EN BIT(8)
85#define MSC_CMDAT_INIT BIT(7)
86#define MSC_CMDAT_BUSY BIT(6)
87#define MSC_CMDAT_STREAM_BLOCK BIT(5)
88#define MSC_CMDAT_WRITE BIT(4)
89#define MSC_CMDAT_DATA_EN BIT(3)
90#define MSC_CMDAT_RESPONSE_MASK (0x7 << 0)
91#define MSC_CMDAT_RESPONSE_NONE (0x0 << 0) /* No response */
92#define MSC_CMDAT_RESPONSE_R1 (0x1 << 0) /* Format R1 and R1b */
93#define MSC_CMDAT_RESPONSE_R2 (0x2 << 0) /* Format R2 */
94#define MSC_CMDAT_RESPONSE_R3 (0x3 << 0) /* Format R3 */
95#define MSC_CMDAT_RESPONSE_R4 (0x4 << 0) /* Format R4 */
96#define MSC_CMDAT_RESPONSE_R5 (0x5 << 0) /* Format R5 */
97#define MSC_CMDAT_RESPONSE_R6 (0x6 << 0) /* Format R6 */
98
99/* MSC Interrupts Mask Register (MSC_IMASK) */
100#define MSC_IMASK_TIME_OUT_RES BIT(9)
101#define MSC_IMASK_TIME_OUT_READ BIT(8)
102#define MSC_IMASK_SDIO BIT(7)
103#define MSC_IMASK_TXFIFO_WR_REQ BIT(6)
104#define MSC_IMASK_RXFIFO_RD_REQ BIT(5)
105#define MSC_IMASK_END_CMD_RES BIT(2)
106#define MSC_IMASK_PRG_DONE BIT(1)
107#define MSC_IMASK_DATA_TRAN_DONE BIT(0)
108
109/* MSC Interrupts Status Register (MSC_IREG) */
110#define MSC_IREG_TIME_OUT_RES BIT(9)
111#define MSC_IREG_TIME_OUT_READ BIT(8)
112#define MSC_IREG_SDIO BIT(7)
113#define MSC_IREG_TXFIFO_WR_REQ BIT(6)
114#define MSC_IREG_RXFIFO_RD_REQ BIT(5)
115#define MSC_IREG_END_CMD_RES BIT(2)
116#define MSC_IREG_PRG_DONE BIT(1)
117#define MSC_IREG_DATA_TRAN_DONE BIT(0)
118
119struct jz_mmc_plat {
120 struct mmc_config cfg;
121 struct mmc mmc;
122};
123
124struct jz_mmc_priv {
125 void __iomem *regs;
126 u32 flags;
127/* priv flags */
128#define JZ_MMC_BUS_WIDTH_MASK 0x3
129#define JZ_MMC_BUS_WIDTH_1 0x0
130#define JZ_MMC_BUS_WIDTH_4 0x2
131#define JZ_MMC_BUS_WIDTH_8 0x3
132#define JZ_MMC_SENT_INIT BIT(2)
133};
134
135static int jz_mmc_clock_rate(void)
136{
137 return 24000000;
138}
139
Ezequiel Garcia36202fd2019-01-07 18:13:25 -0300140#if CONFIG_IS_ENABLED(MMC_WRITE)
141static inline void jz_mmc_write_data(struct jz_mmc_priv *priv, struct mmc_data *data)
142{
143 int sz = DIV_ROUND_UP(data->blocks * data->blocksize, 4);
144 const void *buf = data->src;
145
146 while (sz--) {
147 u32 val = get_unaligned_le32(buf);
148
149 wait_for_bit_le32(priv->regs + MSC_IREG,
150 MSC_IREG_TXFIFO_WR_REQ,
151 true, 10000, false);
152 writel(val, priv->regs + MSC_TXFIFO);
153 buf += 4;
154 }
155}
156#else
157static void jz_mmc_write_data(struct jz_mmc_priv *priv, struct mmc_data *data)
158{}
159#endif
160
161static inline int jz_mmc_read_data(struct jz_mmc_priv *priv, struct mmc_data *data)
162{
163 int sz = data->blocks * data->blocksize;
164 void *buf = data->dest;
165 u32 stat, val;
166
167 do {
168 stat = readl(priv->regs + MSC_STAT);
169
170 if (stat & MSC_STAT_TIME_OUT_READ)
171 return -ETIMEDOUT;
172 if (stat & MSC_STAT_CRC_READ_ERROR)
173 return -EINVAL;
174 if (stat & MSC_STAT_DATA_FIFO_EMPTY) {
175 udelay(10);
176 continue;
177 }
178 do {
179 val = readl(priv->regs + MSC_RXFIFO);
180 if (sz == 1)
181 *(u8 *)buf = (u8)val;
182 else if (sz == 2)
183 put_unaligned_le16(val, buf);
184 else if (sz >= 4)
185 put_unaligned_le32(val, buf);
186 buf += 4;
187 sz -= 4;
188 stat = readl(priv->regs + MSC_STAT);
189 } while (!(stat & MSC_STAT_DATA_FIFO_EMPTY));
190 } while (!(stat & MSC_STAT_DATA_TRAN_DONE));
191 return 0;
192}
193
Paul Burton8e142842018-12-16 19:25:20 -0300194static int jz_mmc_send_cmd(struct mmc *mmc, struct jz_mmc_priv *priv,
195 struct mmc_cmd *cmd, struct mmc_data *data)
196{
197 u32 stat, mask, cmdat = 0;
198 int i, ret;
199
200 /* stop the clock */
201 writel(MSC_STRPCL_CLOCK_CONTROL_STOP, priv->regs + MSC_STRPCL);
202 ret = wait_for_bit_le32(priv->regs + MSC_STAT,
203 MSC_STAT_CLK_EN, false, 10000, false);
204 if (ret)
205 return ret;
206
207 writel(0, priv->regs + MSC_DMAC);
208
209 /* setup command */
210 writel(cmd->cmdidx, priv->regs + MSC_CMD);
211 writel(cmd->cmdarg, priv->regs + MSC_ARG);
212
213 if (data) {
214 /* setup data */
215 cmdat |= MSC_CMDAT_DATA_EN;
216 if (data->flags & MMC_DATA_WRITE)
217 cmdat |= MSC_CMDAT_WRITE;
218
219 writel(data->blocks, priv->regs + MSC_NOB);
220 writel(data->blocksize, priv->regs + MSC_BLKLEN);
221 } else {
222 writel(0, priv->regs + MSC_NOB);
223 writel(0, priv->regs + MSC_BLKLEN);
224 }
225
226 /* setup response */
227 switch (cmd->resp_type) {
228 case MMC_RSP_NONE:
229 break;
230 case MMC_RSP_R1:
231 case MMC_RSP_R1b:
232 cmdat |= MSC_CMDAT_RESPONSE_R1;
233 break;
234 case MMC_RSP_R2:
235 cmdat |= MSC_CMDAT_RESPONSE_R2;
236 break;
237 case MMC_RSP_R3:
238 cmdat |= MSC_CMDAT_RESPONSE_R3;
239 break;
240 default:
241 break;
242 }
243
244 if (cmd->resp_type & MMC_RSP_BUSY)
245 cmdat |= MSC_CMDAT_BUSY;
246
247 /* set init for the first command only */
248 if (!(priv->flags & JZ_MMC_SENT_INIT)) {
249 cmdat |= MSC_CMDAT_INIT;
250 priv->flags |= JZ_MMC_SENT_INIT;
251 }
252
253 cmdat |= (priv->flags & JZ_MMC_BUS_WIDTH_MASK) << 9;
254
255 /* write the data setup */
256 writel(cmdat, priv->regs + MSC_CMDAT);
257
258 /* unmask interrupts */
259 mask = 0xffffffff & ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_TIME_OUT_RES);
260 if (data) {
261 mask &= ~MSC_IMASK_DATA_TRAN_DONE;
262 if (data->flags & MMC_DATA_WRITE) {
263 mask &= ~MSC_IMASK_TXFIFO_WR_REQ;
264 } else {
265 mask &= ~(MSC_IMASK_RXFIFO_RD_REQ |
266 MSC_IMASK_TIME_OUT_READ);
267 }
268 }
269 writel(mask, priv->regs + MSC_IMASK);
270
271 /* clear interrupts */
272 writel(0xffffffff, priv->regs + MSC_IREG);
273
274 /* start the command (& the clock) */
275 writel(MSC_STRPCL_START_OP | MSC_STRPCL_CLOCK_CONTROL_START,
276 priv->regs + MSC_STRPCL);
277
278 /* wait for completion */
279 for (i = 0; i < 100; i++) {
280 stat = readl(priv->regs + MSC_IREG);
281 stat &= MSC_IREG_END_CMD_RES | MSC_IREG_TIME_OUT_RES;
282 if (stat)
283 break;
284 mdelay(1);
285 }
286 writel(stat, priv->regs + MSC_IREG);
287 if (stat & MSC_IREG_TIME_OUT_RES)
288 return -ETIMEDOUT;
289
290 if (cmd->resp_type & MMC_RSP_PRESENT) {
291 /* read the response */
292 if (cmd->resp_type & MMC_RSP_136) {
293 u16 a, b, c, i;
294
295 a = readw(priv->regs + MSC_RES);
296 for (i = 0; i < 4; i++) {
297 b = readw(priv->regs + MSC_RES);
298 c = readw(priv->regs + MSC_RES);
299 cmd->response[i] =
300 (a << 24) | (b << 8) | (c >> 8);
301 a = c;
302 }
303 } else {
304 cmd->response[0] = readw(priv->regs + MSC_RES) << 24;
305 cmd->response[0] |= readw(priv->regs + MSC_RES) << 8;
306 cmd->response[0] |= readw(priv->regs + MSC_RES) & 0xff;
307 }
308 }
Ezequiel Garcia36202fd2019-01-07 18:13:25 -0300309 if (data) {
310 if (data->flags & MMC_DATA_WRITE)
311 jz_mmc_write_data(priv, data);
312 else if (data->flags & MMC_DATA_READ) {
313 ret = jz_mmc_read_data(priv, data);
314 if (ret)
315 return ret;
Paul Burton8e142842018-12-16 19:25:20 -0300316 }
Paul Burton8e142842018-12-16 19:25:20 -0300317 }
318
319 return 0;
320}
321
322static int jz_mmc_set_ios(struct mmc *mmc, struct jz_mmc_priv *priv)
323{
324 u32 real_rate = jz_mmc_clock_rate();
325 u8 clk_div = 0;
326
327 /* calculate clock divide */
328 while ((real_rate > mmc->clock) && (clk_div < 7)) {
329 real_rate >>= 1;
330 clk_div++;
331 }
332 writel(clk_div & MSC_CLKRT_CLK_RATE_MASK, priv->regs + MSC_CLKRT);
333
334 /* set the bus width for the next command */
335 priv->flags &= ~JZ_MMC_BUS_WIDTH_MASK;
336 if (mmc->bus_width == 8)
337 priv->flags |= JZ_MMC_BUS_WIDTH_8;
338 else if (mmc->bus_width == 4)
339 priv->flags |= JZ_MMC_BUS_WIDTH_4;
340 else
341 priv->flags |= JZ_MMC_BUS_WIDTH_1;
342
343 return 0;
344}
345
346static int jz_mmc_core_init(struct mmc *mmc)
347{
348 struct jz_mmc_priv *priv = mmc->priv;
349 int ret;
350
351 /* Reset */
352 writel(MSC_STRPCL_RESET, priv->regs + MSC_STRPCL);
353 ret = wait_for_bit_le32(priv->regs + MSC_STAT,
354 MSC_STAT_IS_RESETTING, false, 10000, false);
355 if (ret)
356 return ret;
357
358 /* Maximum timeouts */
359 writel(0xffff, priv->regs + MSC_RESTO);
360 writel(0xffffffff, priv->regs + MSC_RDTO);
361
362 /* Enable low power mode */
363 writel(0x1, priv->regs + MSC_LPM);
364
365 return 0;
366}
367
368#if !CONFIG_IS_ENABLED(DM_MMC)
369
370static int jz_mmc_legacy_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
371 struct mmc_data *data)
372{
373 struct jz_mmc_priv *priv = mmc->priv;
374
375 return jz_mmc_send_cmd(mmc, priv, cmd, data);
376}
377
378static int jz_mmc_legacy_set_ios(struct mmc *mmc)
379{
380 struct jz_mmc_priv *priv = mmc->priv;
381
382 return jz_mmc_set_ios(mmc, priv);
383};
384
385static const struct mmc_ops jz_msc_ops = {
386 .send_cmd = jz_mmc_legacy_send_cmd,
387 .set_ios = jz_mmc_legacy_set_ios,
388 .init = jz_mmc_core_init,
389};
390
391static struct jz_mmc_priv jz_mmc_priv_static;
392static struct jz_mmc_plat jz_mmc_plat_static = {
393 .cfg = {
394 .name = "MSC",
395 .ops = &jz_msc_ops,
396
397 .voltages = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 |
398 MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 |
399 MMC_VDD_33_34 | MMC_VDD_34_35 | MMC_VDD_35_36,
400 .host_caps = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS,
401
402 .f_min = 375000,
403 .f_max = 48000000,
404 .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
405 },
406};
407
408int jz_mmc_init(void __iomem *base)
409{
410 struct mmc *mmc;
411
412 jz_mmc_priv_static.regs = base;
413
414 mmc = mmc_create(&jz_mmc_plat_static.cfg, &jz_mmc_priv_static);
415
416 return mmc ? 0 : -ENODEV;
417}
418
419#else /* CONFIG_DM_MMC */
420
421#include <dm.h>
422DECLARE_GLOBAL_DATA_PTR;
423
424static int jz_mmc_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
425 struct mmc_data *data)
426{
427 struct jz_mmc_priv *priv = dev_get_priv(dev);
428 struct mmc *mmc = mmc_get_mmc_dev(dev);
429
430 return jz_mmc_send_cmd(mmc, priv, cmd, data);
431}
432
433static int jz_mmc_dm_set_ios(struct udevice *dev)
434{
435 struct jz_mmc_priv *priv = dev_get_priv(dev);
436 struct mmc *mmc = mmc_get_mmc_dev(dev);
437
438 return jz_mmc_set_ios(mmc, priv);
439};
440
441static const struct dm_mmc_ops jz_msc_ops = {
442 .send_cmd = jz_mmc_dm_send_cmd,
443 .set_ios = jz_mmc_dm_set_ios,
444};
445
Simon Glassaad29ae2020-12-03 16:55:21 -0700446static int jz_mmc_of_to_plat(struct udevice *dev)
Paul Burton8e142842018-12-16 19:25:20 -0300447{
448 struct jz_mmc_priv *priv = dev_get_priv(dev);
Simon Glassfa20e932020-12-03 16:55:20 -0700449 struct jz_mmc_plat *plat = dev_get_plat(dev);
Paul Burton8e142842018-12-16 19:25:20 -0300450 struct mmc_config *cfg;
451 int ret;
452
Masahiro Yamadaa89b4de2020-07-17 14:36:48 +0900453 priv->regs = map_physmem(dev_read_addr(dev), 0x100, MAP_NOCACHE);
Paul Burton8e142842018-12-16 19:25:20 -0300454 cfg = &plat->cfg;
455
456 cfg->name = "MSC";
457 cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
458
459 ret = mmc_of_parse(dev, cfg);
460 if (ret < 0) {
461 dev_err(dev, "failed to parse host caps\n");
462 return ret;
463 }
464
465 cfg->f_min = 400000;
466 cfg->f_max = 52000000;
467
468 cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
469 cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
470
471 return 0;
472}
473
474static int jz_mmc_bind(struct udevice *dev)
475{
Simon Glassfa20e932020-12-03 16:55:20 -0700476 struct jz_mmc_plat *plat = dev_get_plat(dev);
Paul Burton8e142842018-12-16 19:25:20 -0300477
478 return mmc_bind(dev, &plat->mmc, &plat->cfg);
479}
480
481static int jz_mmc_probe(struct udevice *dev)
482{
483 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
484 struct jz_mmc_priv *priv = dev_get_priv(dev);
Simon Glassfa20e932020-12-03 16:55:20 -0700485 struct jz_mmc_plat *plat = dev_get_plat(dev);
Paul Burton8e142842018-12-16 19:25:20 -0300486
487 plat->mmc.priv = priv;
488 upriv->mmc = &plat->mmc;
489 return jz_mmc_core_init(&plat->mmc);
490}
491
492static const struct udevice_id jz_mmc_ids[] = {
493 { .compatible = "ingenic,jz4780-mmc" },
494 { }
495};
496
497U_BOOT_DRIVER(jz_mmc_drv) = {
498 .name = "jz_mmc",
499 .id = UCLASS_MMC,
500 .of_match = jz_mmc_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -0700501 .of_to_plat = jz_mmc_of_to_plat,
Paul Burton8e142842018-12-16 19:25:20 -0300502 .bind = jz_mmc_bind,
503 .probe = jz_mmc_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700504 .priv_auto = sizeof(struct jz_mmc_priv),
Simon Glass71fa5b42020-12-03 16:55:18 -0700505 .plat_auto = sizeof(struct jz_mmc_plat),
Paul Burton8e142842018-12-16 19:25:20 -0300506 .ops = &jz_msc_ops,
507};
508#endif /* CONFIG_DM_MMC */