xref: /openbmc/u-boot/drivers/mmc/sh_sdhi.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1  // SPDX-License-Identifier: GPL-2.0
2  /*
3   * drivers/mmc/sh_sdhi.c
4   *
5   * SD/MMC driver for Renesas rmobile ARM SoCs.
6   *
7   * Copyright (C) 2011,2013-2017 Renesas Electronics Corporation
8   * Copyright (C) 2014 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
9   * Copyright (C) 2008-2009 Renesas Solutions Corp.
10   */
11  
12  #include <common.h>
13  #include <malloc.h>
14  #include <mmc.h>
15  #include <dm.h>
16  #include <linux/errno.h>
17  #include <linux/compat.h>
18  #include <linux/io.h>
19  #include <linux/sizes.h>
20  #include <asm/arch/rmobile.h>
21  #include <asm/arch/sh_sdhi.h>
22  #include <clk.h>
23  
24  #define DRIVER_NAME "sh-sdhi"
25  
26  struct sh_sdhi_host {
27  	void __iomem *addr;
28  	int ch;
29  	int bus_shift;
30  	unsigned long quirks;
31  	unsigned char wait_int;
32  	unsigned char sd_error;
33  	unsigned char detect_waiting;
34  	unsigned char app_cmd;
35  };
36  
sh_sdhi_writeq(struct sh_sdhi_host * host,int reg,u64 val)37  static inline void sh_sdhi_writeq(struct sh_sdhi_host *host, int reg, u64 val)
38  {
39  	writeq(val, host->addr + (reg << host->bus_shift));
40  }
41  
sh_sdhi_readq(struct sh_sdhi_host * host,int reg)42  static inline u64 sh_sdhi_readq(struct sh_sdhi_host *host, int reg)
43  {
44  	return readq(host->addr + (reg << host->bus_shift));
45  }
46  
sh_sdhi_writew(struct sh_sdhi_host * host,int reg,u16 val)47  static inline void sh_sdhi_writew(struct sh_sdhi_host *host, int reg, u16 val)
48  {
49  	writew(val, host->addr + (reg << host->bus_shift));
50  }
51  
sh_sdhi_readw(struct sh_sdhi_host * host,int reg)52  static inline u16 sh_sdhi_readw(struct sh_sdhi_host *host, int reg)
53  {
54  	return readw(host->addr + (reg << host->bus_shift));
55  }
56  
sh_sdhi_detect(struct sh_sdhi_host * host)57  static void sh_sdhi_detect(struct sh_sdhi_host *host)
58  {
59  	sh_sdhi_writew(host, SDHI_OPTION,
60  		       OPT_BUS_WIDTH_1 | sh_sdhi_readw(host, SDHI_OPTION));
61  
62  	host->detect_waiting = 0;
63  }
64  
sh_sdhi_intr(void * dev_id)65  static int sh_sdhi_intr(void *dev_id)
66  {
67  	struct sh_sdhi_host *host = dev_id;
68  	int state1 = 0, state2 = 0;
69  
70  	state1 = sh_sdhi_readw(host, SDHI_INFO1);
71  	state2 = sh_sdhi_readw(host, SDHI_INFO2);
72  
73  	debug("%s: state1 = %x, state2 = %x\n", __func__, state1, state2);
74  
75  	/* CARD Insert */
76  	if (state1 & INFO1_CARD_IN) {
77  		sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_CARD_IN);
78  		if (!host->detect_waiting) {
79  			host->detect_waiting = 1;
80  			sh_sdhi_detect(host);
81  		}
82  		sh_sdhi_writew(host, SDHI_INFO1_MASK, INFO1M_RESP_END |
83  			       INFO1M_ACCESS_END | INFO1M_CARD_IN |
84  			       INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
85  		return -EAGAIN;
86  	}
87  	/* CARD Removal */
88  	if (state1 & INFO1_CARD_RE) {
89  		sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_CARD_RE);
90  		if (!host->detect_waiting) {
91  			host->detect_waiting = 1;
92  			sh_sdhi_detect(host);
93  		}
94  		sh_sdhi_writew(host, SDHI_INFO1_MASK, INFO1M_RESP_END |
95  			       INFO1M_ACCESS_END | INFO1M_CARD_RE |
96  			       INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
97  		sh_sdhi_writew(host, SDHI_SDIO_INFO1_MASK, SDIO_INFO1M_ON);
98  		sh_sdhi_writew(host, SDHI_SDIO_MODE, SDIO_MODE_OFF);
99  		return -EAGAIN;
100  	}
101  
102  	if (state2 & INFO2_ALL_ERR) {
103  		sh_sdhi_writew(host, SDHI_INFO2,
104  			       (unsigned short)~(INFO2_ALL_ERR));
105  		sh_sdhi_writew(host, SDHI_INFO2_MASK,
106  			       INFO2M_ALL_ERR |
107  			       sh_sdhi_readw(host, SDHI_INFO2_MASK));
108  		host->sd_error = 1;
109  		host->wait_int = 1;
110  		return 0;
111  	}
112  	/* Respons End */
113  	if (state1 & INFO1_RESP_END) {
114  		sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_RESP_END);
115  		sh_sdhi_writew(host, SDHI_INFO1_MASK,
116  			       INFO1M_RESP_END |
117  			       sh_sdhi_readw(host, SDHI_INFO1_MASK));
118  		host->wait_int = 1;
119  		return 0;
120  	}
121  	/* SD_BUF Read Enable */
122  	if (state2 & INFO2_BRE_ENABLE) {
123  		sh_sdhi_writew(host, SDHI_INFO2, ~INFO2_BRE_ENABLE);
124  		sh_sdhi_writew(host, SDHI_INFO2_MASK,
125  			       INFO2M_BRE_ENABLE | INFO2M_BUF_ILL_READ |
126  			       sh_sdhi_readw(host, SDHI_INFO2_MASK));
127  		host->wait_int = 1;
128  		return 0;
129  	}
130  	/* SD_BUF Write Enable */
131  	if (state2 & INFO2_BWE_ENABLE) {
132  		sh_sdhi_writew(host, SDHI_INFO2, ~INFO2_BWE_ENABLE);
133  		sh_sdhi_writew(host, SDHI_INFO2_MASK,
134  			       INFO2_BWE_ENABLE | INFO2M_BUF_ILL_WRITE |
135  			       sh_sdhi_readw(host, SDHI_INFO2_MASK));
136  		host->wait_int = 1;
137  		return 0;
138  	}
139  	/* Access End */
140  	if (state1 & INFO1_ACCESS_END) {
141  		sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_ACCESS_END);
142  		sh_sdhi_writew(host, SDHI_INFO1_MASK,
143  			       INFO1_ACCESS_END |
144  			       sh_sdhi_readw(host, SDHI_INFO1_MASK));
145  		host->wait_int = 1;
146  		return 0;
147  	}
148  	return -EAGAIN;
149  }
150  
sh_sdhi_wait_interrupt_flag(struct sh_sdhi_host * host)151  static int sh_sdhi_wait_interrupt_flag(struct sh_sdhi_host *host)
152  {
153  	int timeout = 10000000;
154  
155  	while (1) {
156  		timeout--;
157  		if (timeout < 0) {
158  			debug(DRIVER_NAME": %s timeout\n", __func__);
159  			return 0;
160  		}
161  
162  		if (!sh_sdhi_intr(host))
163  			break;
164  
165  		udelay(1);	/* 1 usec */
166  	}
167  
168  	return 1; /* Return value: NOT 0 = complete waiting */
169  }
170  
sh_sdhi_clock_control(struct sh_sdhi_host * host,unsigned long clk)171  static int sh_sdhi_clock_control(struct sh_sdhi_host *host, unsigned long clk)
172  {
173  	u32 clkdiv, i, timeout;
174  
175  	if (sh_sdhi_readw(host, SDHI_INFO2) & (1 << 14)) {
176  		printf(DRIVER_NAME": Busy state ! Cannot change the clock\n");
177  		return -EBUSY;
178  	}
179  
180  	sh_sdhi_writew(host, SDHI_CLK_CTRL,
181  		       ~CLK_ENABLE & sh_sdhi_readw(host, SDHI_CLK_CTRL));
182  
183  	if (clk == 0)
184  		return -EIO;
185  
186  	clkdiv = 0x80;
187  	i = CONFIG_SH_SDHI_FREQ >> (0x8 + 1);
188  	for (; clkdiv && clk >= (i << 1); (clkdiv >>= 1))
189  		i <<= 1;
190  
191  	sh_sdhi_writew(host, SDHI_CLK_CTRL, clkdiv);
192  
193  	timeout = 100000;
194  	/* Waiting for SD Bus busy to be cleared */
195  	while (timeout--) {
196  		if ((sh_sdhi_readw(host, SDHI_INFO2) & 0x2000))
197  			break;
198  	}
199  
200  	if (timeout)
201  		sh_sdhi_writew(host, SDHI_CLK_CTRL,
202  			       CLK_ENABLE | sh_sdhi_readw(host, SDHI_CLK_CTRL));
203  	else
204  		return -EBUSY;
205  
206  	return 0;
207  }
208  
sh_sdhi_sync_reset(struct sh_sdhi_host * host)209  static int sh_sdhi_sync_reset(struct sh_sdhi_host *host)
210  {
211  	u32 timeout;
212  	sh_sdhi_writew(host, SDHI_SOFT_RST, SOFT_RST_ON);
213  	sh_sdhi_writew(host, SDHI_SOFT_RST, SOFT_RST_OFF);
214  	sh_sdhi_writew(host, SDHI_CLK_CTRL,
215  		       CLK_ENABLE | sh_sdhi_readw(host, SDHI_CLK_CTRL));
216  
217  	timeout = 100000;
218  	while (timeout--) {
219  		if (!(sh_sdhi_readw(host, SDHI_INFO2) & INFO2_CBUSY))
220  			break;
221  		udelay(100);
222  	}
223  
224  	if (!timeout)
225  		return -EBUSY;
226  
227  	if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
228  		sh_sdhi_writew(host, SDHI_HOST_MODE, 1);
229  
230  	return 0;
231  }
232  
sh_sdhi_error_manage(struct sh_sdhi_host * host)233  static int sh_sdhi_error_manage(struct sh_sdhi_host *host)
234  {
235  	unsigned short e_state1, e_state2;
236  	int ret;
237  
238  	host->sd_error = 0;
239  	host->wait_int = 0;
240  
241  	e_state1 = sh_sdhi_readw(host, SDHI_ERR_STS1);
242  	e_state2 = sh_sdhi_readw(host, SDHI_ERR_STS2);
243  	if (e_state2 & ERR_STS2_SYS_ERROR) {
244  		if (e_state2 & ERR_STS2_RES_STOP_TIMEOUT)
245  			ret = -ETIMEDOUT;
246  		else
247  			ret = -EILSEQ;
248  		debug("%s: ERR_STS2 = %04x\n",
249  		      DRIVER_NAME, sh_sdhi_readw(host, SDHI_ERR_STS2));
250  		sh_sdhi_sync_reset(host);
251  
252  		sh_sdhi_writew(host, SDHI_INFO1_MASK,
253  			       INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
254  		return ret;
255  	}
256  	if (e_state1 & ERR_STS1_CRC_ERROR || e_state1 & ERR_STS1_CMD_ERROR)
257  		ret = -EILSEQ;
258  	else
259  		ret = -ETIMEDOUT;
260  
261  	debug("%s: ERR_STS1 = %04x\n",
262  	      DRIVER_NAME, sh_sdhi_readw(host, SDHI_ERR_STS1));
263  	sh_sdhi_sync_reset(host);
264  	sh_sdhi_writew(host, SDHI_INFO1_MASK,
265  		       INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
266  	return ret;
267  }
268  
sh_sdhi_single_read(struct sh_sdhi_host * host,struct mmc_data * data)269  static int sh_sdhi_single_read(struct sh_sdhi_host *host, struct mmc_data *data)
270  {
271  	long time;
272  	unsigned short blocksize, i;
273  	unsigned short *p = (unsigned short *)data->dest;
274  	u64 *q = (u64 *)data->dest;
275  
276  	if ((unsigned long)p & 0x00000001) {
277  		debug(DRIVER_NAME": %s: The data pointer is unaligned.",
278  		      __func__);
279  		return -EIO;
280  	}
281  
282  	host->wait_int = 0;
283  	sh_sdhi_writew(host, SDHI_INFO2_MASK,
284  		       ~(INFO2M_BRE_ENABLE | INFO2M_BUF_ILL_READ) &
285  		       sh_sdhi_readw(host, SDHI_INFO2_MASK));
286  	sh_sdhi_writew(host, SDHI_INFO1_MASK,
287  		       ~INFO1M_ACCESS_END &
288  		       sh_sdhi_readw(host, SDHI_INFO1_MASK));
289  	time = sh_sdhi_wait_interrupt_flag(host);
290  	if (time == 0 || host->sd_error != 0)
291  		return sh_sdhi_error_manage(host);
292  
293  	host->wait_int = 0;
294  	blocksize = sh_sdhi_readw(host, SDHI_SIZE);
295  	if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
296  		for (i = 0; i < blocksize / 8; i++)
297  			*q++ = sh_sdhi_readq(host, SDHI_BUF0);
298  	else
299  		for (i = 0; i < blocksize / 2; i++)
300  			*p++ = sh_sdhi_readw(host, SDHI_BUF0);
301  
302  	time = sh_sdhi_wait_interrupt_flag(host);
303  	if (time == 0 || host->sd_error != 0)
304  		return sh_sdhi_error_manage(host);
305  
306  	host->wait_int = 0;
307  	return 0;
308  }
309  
sh_sdhi_multi_read(struct sh_sdhi_host * host,struct mmc_data * data)310  static int sh_sdhi_multi_read(struct sh_sdhi_host *host, struct mmc_data *data)
311  {
312  	long time;
313  	unsigned short blocksize, i, sec;
314  	unsigned short *p = (unsigned short *)data->dest;
315  	u64 *q = (u64 *)data->dest;
316  
317  	if ((unsigned long)p & 0x00000001) {
318  		debug(DRIVER_NAME": %s: The data pointer is unaligned.",
319  		      __func__);
320  		return -EIO;
321  	}
322  
323  	debug("%s: blocks = %d, blocksize = %d\n",
324  	      __func__, data->blocks, data->blocksize);
325  
326  	host->wait_int = 0;
327  	for (sec = 0; sec < data->blocks; sec++) {
328  		sh_sdhi_writew(host, SDHI_INFO2_MASK,
329  			       ~(INFO2M_BRE_ENABLE | INFO2M_BUF_ILL_READ) &
330  			       sh_sdhi_readw(host, SDHI_INFO2_MASK));
331  
332  		time = sh_sdhi_wait_interrupt_flag(host);
333  		if (time == 0 || host->sd_error != 0)
334  			return sh_sdhi_error_manage(host);
335  
336  		host->wait_int = 0;
337  		blocksize = sh_sdhi_readw(host, SDHI_SIZE);
338  		if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
339  			for (i = 0; i < blocksize / 8; i++)
340  				*q++ = sh_sdhi_readq(host, SDHI_BUF0);
341  		else
342  			for (i = 0; i < blocksize / 2; i++)
343  				*p++ = sh_sdhi_readw(host, SDHI_BUF0);
344  	}
345  
346  	return 0;
347  }
348  
sh_sdhi_single_write(struct sh_sdhi_host * host,struct mmc_data * data)349  static int sh_sdhi_single_write(struct sh_sdhi_host *host,
350  		struct mmc_data *data)
351  {
352  	long time;
353  	unsigned short blocksize, i;
354  	const unsigned short *p = (const unsigned short *)data->src;
355  	const u64 *q = (const u64 *)data->src;
356  
357  	if ((unsigned long)p & 0x00000001) {
358  		debug(DRIVER_NAME": %s: The data pointer is unaligned.",
359  		      __func__);
360  		return -EIO;
361  	}
362  
363  	debug("%s: blocks = %d, blocksize = %d\n",
364  	      __func__, data->blocks, data->blocksize);
365  
366  	host->wait_int = 0;
367  	sh_sdhi_writew(host, SDHI_INFO2_MASK,
368  		       ~(INFO2M_BWE_ENABLE | INFO2M_BUF_ILL_WRITE) &
369  		       sh_sdhi_readw(host, SDHI_INFO2_MASK));
370  	sh_sdhi_writew(host, SDHI_INFO1_MASK,
371  		       ~INFO1M_ACCESS_END &
372  		       sh_sdhi_readw(host, SDHI_INFO1_MASK));
373  
374  	time = sh_sdhi_wait_interrupt_flag(host);
375  	if (time == 0 || host->sd_error != 0)
376  		return sh_sdhi_error_manage(host);
377  
378  	host->wait_int = 0;
379  	blocksize = sh_sdhi_readw(host, SDHI_SIZE);
380  	if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
381  		for (i = 0; i < blocksize / 8; i++)
382  			sh_sdhi_writeq(host, SDHI_BUF0, *q++);
383  	else
384  		for (i = 0; i < blocksize / 2; i++)
385  			sh_sdhi_writew(host, SDHI_BUF0, *p++);
386  
387  	time = sh_sdhi_wait_interrupt_flag(host);
388  	if (time == 0 || host->sd_error != 0)
389  		return sh_sdhi_error_manage(host);
390  
391  	host->wait_int = 0;
392  	return 0;
393  }
394  
sh_sdhi_multi_write(struct sh_sdhi_host * host,struct mmc_data * data)395  static int sh_sdhi_multi_write(struct sh_sdhi_host *host, struct mmc_data *data)
396  {
397  	long time;
398  	unsigned short i, sec, blocksize;
399  	const unsigned short *p = (const unsigned short *)data->src;
400  	const u64 *q = (const u64 *)data->src;
401  
402  	debug("%s: blocks = %d, blocksize = %d\n",
403  	      __func__, data->blocks, data->blocksize);
404  
405  	host->wait_int = 0;
406  	for (sec = 0; sec < data->blocks; sec++) {
407  		sh_sdhi_writew(host, SDHI_INFO2_MASK,
408  			       ~(INFO2M_BWE_ENABLE | INFO2M_BUF_ILL_WRITE) &
409  			       sh_sdhi_readw(host, SDHI_INFO2_MASK));
410  
411  		time = sh_sdhi_wait_interrupt_flag(host);
412  		if (time == 0 || host->sd_error != 0)
413  			return sh_sdhi_error_manage(host);
414  
415  		host->wait_int = 0;
416  		blocksize = sh_sdhi_readw(host, SDHI_SIZE);
417  		if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
418  			for (i = 0; i < blocksize / 8; i++)
419  				sh_sdhi_writeq(host, SDHI_BUF0, *q++);
420  		else
421  			for (i = 0; i < blocksize / 2; i++)
422  				sh_sdhi_writew(host, SDHI_BUF0, *p++);
423  	}
424  
425  	return 0;
426  }
427  
sh_sdhi_get_response(struct sh_sdhi_host * host,struct mmc_cmd * cmd)428  static void sh_sdhi_get_response(struct sh_sdhi_host *host, struct mmc_cmd *cmd)
429  {
430  	unsigned short i, j, cnt = 1;
431  	unsigned short resp[8];
432  
433  	if (cmd->resp_type & MMC_RSP_136) {
434  		cnt = 4;
435  		resp[0] = sh_sdhi_readw(host, SDHI_RSP00);
436  		resp[1] = sh_sdhi_readw(host, SDHI_RSP01);
437  		resp[2] = sh_sdhi_readw(host, SDHI_RSP02);
438  		resp[3] = sh_sdhi_readw(host, SDHI_RSP03);
439  		resp[4] = sh_sdhi_readw(host, SDHI_RSP04);
440  		resp[5] = sh_sdhi_readw(host, SDHI_RSP05);
441  		resp[6] = sh_sdhi_readw(host, SDHI_RSP06);
442  		resp[7] = sh_sdhi_readw(host, SDHI_RSP07);
443  
444  		/* SDHI REGISTER SPECIFICATION */
445  		for (i = 7, j = 6; i > 0; i--) {
446  			resp[i] = (resp[i] << 8) & 0xff00;
447  			resp[i] |= (resp[j--] >> 8) & 0x00ff;
448  		}
449  		resp[0] = (resp[0] << 8) & 0xff00;
450  	} else {
451  		resp[0] = sh_sdhi_readw(host, SDHI_RSP00);
452  		resp[1] = sh_sdhi_readw(host, SDHI_RSP01);
453  	}
454  
455  #if defined(__BIG_ENDIAN_BITFIELD)
456  	if (cnt == 4) {
457  		cmd->response[0] = (resp[6] << 16) | resp[7];
458  		cmd->response[1] = (resp[4] << 16) | resp[5];
459  		cmd->response[2] = (resp[2] << 16) | resp[3];
460  		cmd->response[3] = (resp[0] << 16) | resp[1];
461  	} else {
462  		cmd->response[0] = (resp[0] << 16) | resp[1];
463  	}
464  #else
465  	if (cnt == 4) {
466  		cmd->response[0] = (resp[7] << 16) | resp[6];
467  		cmd->response[1] = (resp[5] << 16) | resp[4];
468  		cmd->response[2] = (resp[3] << 16) | resp[2];
469  		cmd->response[3] = (resp[1] << 16) | resp[0];
470  	} else {
471  		cmd->response[0] = (resp[1] << 16) | resp[0];
472  	}
473  #endif /* __BIG_ENDIAN_BITFIELD */
474  }
475  
sh_sdhi_set_cmd(struct sh_sdhi_host * host,struct mmc_data * data,unsigned short opc)476  static unsigned short sh_sdhi_set_cmd(struct sh_sdhi_host *host,
477  			struct mmc_data *data, unsigned short opc)
478  {
479  	if (host->app_cmd) {
480  		if (!data)
481  			host->app_cmd = 0;
482  		return opc | BIT(6);
483  	}
484  
485  	switch (opc) {
486  	case MMC_CMD_SWITCH:
487  		return opc | (data ? 0x1c00 : 0x40);
488  	case MMC_CMD_SEND_EXT_CSD:
489  		return opc | (data ? 0x1c00 : 0);
490  	case MMC_CMD_SEND_OP_COND:
491  		return opc | 0x0700;
492  	case MMC_CMD_APP_CMD:
493  		host->app_cmd = 1;
494  	default:
495  		return opc;
496  	}
497  }
498  
sh_sdhi_data_trans(struct sh_sdhi_host * host,struct mmc_data * data,unsigned short opc)499  static unsigned short sh_sdhi_data_trans(struct sh_sdhi_host *host,
500  			struct mmc_data *data, unsigned short opc)
501  {
502  	if (host->app_cmd) {
503  		host->app_cmd = 0;
504  		switch (opc) {
505  		case SD_CMD_APP_SEND_SCR:
506  		case SD_CMD_APP_SD_STATUS:
507  			return sh_sdhi_single_read(host, data);
508  		default:
509  			printf(DRIVER_NAME": SD: NOT SUPPORT APP CMD = d'%04d\n",
510  				opc);
511  			return -EINVAL;
512  		}
513  	} else {
514  		switch (opc) {
515  		case MMC_CMD_WRITE_MULTIPLE_BLOCK:
516  			return sh_sdhi_multi_write(host, data);
517  		case MMC_CMD_READ_MULTIPLE_BLOCK:
518  			return sh_sdhi_multi_read(host, data);
519  		case MMC_CMD_WRITE_SINGLE_BLOCK:
520  			return sh_sdhi_single_write(host, data);
521  		case MMC_CMD_READ_SINGLE_BLOCK:
522  		case MMC_CMD_SWITCH:
523  		case MMC_CMD_SEND_EXT_CSD:;
524  			return sh_sdhi_single_read(host, data);
525  		default:
526  			printf(DRIVER_NAME": SD: NOT SUPPORT CMD = d'%04d\n", opc);
527  			return -EINVAL;
528  		}
529  	}
530  }
531  
sh_sdhi_start_cmd(struct sh_sdhi_host * host,struct mmc_data * data,struct mmc_cmd * cmd)532  static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
533  			struct mmc_data *data, struct mmc_cmd *cmd)
534  {
535  	long time;
536  	unsigned short shcmd, opc = cmd->cmdidx;
537  	int ret = 0;
538  	unsigned long timeout;
539  
540  	debug("opc = %d, arg = %x, resp_type = %x\n",
541  	      opc, cmd->cmdarg, cmd->resp_type);
542  
543  	if (opc == MMC_CMD_STOP_TRANSMISSION) {
544  		/* SDHI sends the STOP command automatically by STOP reg */
545  		sh_sdhi_writew(host, SDHI_INFO1_MASK, ~INFO1M_ACCESS_END &
546  			       sh_sdhi_readw(host, SDHI_INFO1_MASK));
547  
548  		time = sh_sdhi_wait_interrupt_flag(host);
549  		if (time == 0 || host->sd_error != 0)
550  			return sh_sdhi_error_manage(host);
551  
552  		sh_sdhi_get_response(host, cmd);
553  		return 0;
554  	}
555  
556  	if (data) {
557  		if ((opc == MMC_CMD_READ_MULTIPLE_BLOCK) ||
558  		    opc == MMC_CMD_WRITE_MULTIPLE_BLOCK) {
559  			sh_sdhi_writew(host, SDHI_STOP, STOP_SEC_ENABLE);
560  			sh_sdhi_writew(host, SDHI_SECCNT, data->blocks);
561  		}
562  		sh_sdhi_writew(host, SDHI_SIZE, data->blocksize);
563  	}
564  
565  	shcmd = sh_sdhi_set_cmd(host, data, opc);
566  
567  	/*
568  	 *  U-Boot cannot use interrupt.
569  	 *  So this flag may not be clear by timing
570  	 */
571  	sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_RESP_END);
572  
573  	sh_sdhi_writew(host, SDHI_INFO1_MASK,
574  		       INFO1M_RESP_END | sh_sdhi_readw(host, SDHI_INFO1_MASK));
575  	sh_sdhi_writew(host, SDHI_ARG0,
576  		       (unsigned short)(cmd->cmdarg & ARG0_MASK));
577  	sh_sdhi_writew(host, SDHI_ARG1,
578  		       (unsigned short)((cmd->cmdarg >> 16) & ARG1_MASK));
579  
580  	timeout = 100000;
581  	/* Waiting for SD Bus busy to be cleared */
582  	while (timeout--) {
583  		if ((sh_sdhi_readw(host, SDHI_INFO2) & 0x2000))
584  			break;
585  	}
586  
587  	host->wait_int = 0;
588  	sh_sdhi_writew(host, SDHI_INFO1_MASK,
589  		       ~INFO1M_RESP_END & sh_sdhi_readw(host, SDHI_INFO1_MASK));
590  	sh_sdhi_writew(host, SDHI_INFO2_MASK,
591  		       ~(INFO2M_CMD_ERROR | INFO2M_CRC_ERROR |
592  		       INFO2M_END_ERROR | INFO2M_TIMEOUT |
593  		       INFO2M_RESP_TIMEOUT | INFO2M_ILA) &
594  		       sh_sdhi_readw(host, SDHI_INFO2_MASK));
595  
596  	sh_sdhi_writew(host, SDHI_CMD, (unsigned short)(shcmd & CMD_MASK));
597  	time = sh_sdhi_wait_interrupt_flag(host);
598  	if (!time) {
599  		host->app_cmd = 0;
600  		return sh_sdhi_error_manage(host);
601  	}
602  
603  	if (host->sd_error) {
604  		switch (cmd->cmdidx) {
605  		case MMC_CMD_ALL_SEND_CID:
606  		case MMC_CMD_SELECT_CARD:
607  		case SD_CMD_SEND_IF_COND:
608  		case MMC_CMD_APP_CMD:
609  			ret = -ETIMEDOUT;
610  			break;
611  		default:
612  			debug(DRIVER_NAME": Cmd(d'%d) err\n", opc);
613  			debug(DRIVER_NAME": cmdidx = %d\n", cmd->cmdidx);
614  			ret = sh_sdhi_error_manage(host);
615  			break;
616  		}
617  		host->sd_error = 0;
618  		host->wait_int = 0;
619  		host->app_cmd = 0;
620  		return ret;
621  	}
622  
623  	if (sh_sdhi_readw(host, SDHI_INFO1) & INFO1_RESP_END) {
624  		host->app_cmd = 0;
625  		return -EINVAL;
626  	}
627  
628  	if (host->wait_int) {
629  		sh_sdhi_get_response(host, cmd);
630  		host->wait_int = 0;
631  	}
632  
633  	if (data)
634  		ret = sh_sdhi_data_trans(host, data, opc);
635  
636  	debug("ret = %d, resp = %08x, %08x, %08x, %08x\n",
637  	      ret, cmd->response[0], cmd->response[1],
638  	      cmd->response[2], cmd->response[3]);
639  	return ret;
640  }
641  
sh_sdhi_send_cmd_common(struct sh_sdhi_host * host,struct mmc_cmd * cmd,struct mmc_data * data)642  static int sh_sdhi_send_cmd_common(struct sh_sdhi_host *host,
643  				   struct mmc_cmd *cmd, struct mmc_data *data)
644  {
645  	host->sd_error = 0;
646  
647  	return sh_sdhi_start_cmd(host, data, cmd);
648  }
649  
sh_sdhi_set_ios_common(struct sh_sdhi_host * host,struct mmc * mmc)650  static int sh_sdhi_set_ios_common(struct sh_sdhi_host *host, struct mmc *mmc)
651  {
652  	int ret;
653  
654  	ret = sh_sdhi_clock_control(host, mmc->clock);
655  	if (ret)
656  		return -EINVAL;
657  
658  	if (mmc->bus_width == 8)
659  		sh_sdhi_writew(host, SDHI_OPTION,
660  			       OPT_BUS_WIDTH_8 | (~OPT_BUS_WIDTH_M &
661  			       sh_sdhi_readw(host, SDHI_OPTION)));
662  	else if (mmc->bus_width == 4)
663  		sh_sdhi_writew(host, SDHI_OPTION,
664  			       OPT_BUS_WIDTH_4 | (~OPT_BUS_WIDTH_M &
665  			       sh_sdhi_readw(host, SDHI_OPTION)));
666  	else
667  		sh_sdhi_writew(host, SDHI_OPTION,
668  			       OPT_BUS_WIDTH_1 | (~OPT_BUS_WIDTH_M &
669  			       sh_sdhi_readw(host, SDHI_OPTION)));
670  
671  	debug("clock = %d, buswidth = %d\n", mmc->clock, mmc->bus_width);
672  
673  	return 0;
674  }
675  
sh_sdhi_initialize_common(struct sh_sdhi_host * host)676  static int sh_sdhi_initialize_common(struct sh_sdhi_host *host)
677  {
678  	int ret = sh_sdhi_sync_reset(host);
679  
680  	sh_sdhi_writew(host, SDHI_PORTSEL, USE_1PORT);
681  
682  #if defined(__BIG_ENDIAN_BITFIELD)
683  	sh_sdhi_writew(host, SDHI_EXT_SWAP, SET_SWAP);
684  #endif
685  
686  	sh_sdhi_writew(host, SDHI_INFO1_MASK, INFO1M_RESP_END |
687  		       INFO1M_ACCESS_END | INFO1M_CARD_RE |
688  		       INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
689  
690  	return ret;
691  }
692  
693  #ifndef CONFIG_DM_MMC
mmc_priv(struct mmc * mmc)694  static void *mmc_priv(struct mmc *mmc)
695  {
696  	return (void *)mmc->priv;
697  }
698  
sh_sdhi_send_cmd(struct mmc * mmc,struct mmc_cmd * cmd,struct mmc_data * data)699  static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
700  			    struct mmc_data *data)
701  {
702  	struct sh_sdhi_host *host = mmc_priv(mmc);
703  
704  	return sh_sdhi_send_cmd_common(host, cmd, data);
705  }
706  
sh_sdhi_set_ios(struct mmc * mmc)707  static int sh_sdhi_set_ios(struct mmc *mmc)
708  {
709  	struct sh_sdhi_host *host = mmc_priv(mmc);
710  
711  	return sh_sdhi_set_ios_common(host, mmc);
712  }
713  
sh_sdhi_initialize(struct mmc * mmc)714  static int sh_sdhi_initialize(struct mmc *mmc)
715  {
716  	struct sh_sdhi_host *host = mmc_priv(mmc);
717  
718  	return sh_sdhi_initialize_common(host);
719  }
720  
721  static const struct mmc_ops sh_sdhi_ops = {
722  	.send_cmd       = sh_sdhi_send_cmd,
723  	.set_ios        = sh_sdhi_set_ios,
724  	.init           = sh_sdhi_initialize,
725  };
726  
727  #ifdef CONFIG_RCAR_GEN3
728  static struct mmc_config sh_sdhi_cfg = {
729  	.name           = DRIVER_NAME,
730  	.ops            = &sh_sdhi_ops,
731  	.f_min          = CLKDEV_INIT,
732  	.f_max          = CLKDEV_HS_DATA,
733  	.voltages       = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
734  	.host_caps      = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HS |
735  			  MMC_MODE_HS_52MHz,
736  	.part_type      = PART_TYPE_DOS,
737  	.b_max          = CONFIG_SYS_MMC_MAX_BLK_COUNT,
738  };
739  #else
740  static struct mmc_config sh_sdhi_cfg = {
741  	.name           = DRIVER_NAME,
742  	.ops            = &sh_sdhi_ops,
743  	.f_min          = CLKDEV_INIT,
744  	.f_max          = CLKDEV_HS_DATA,
745  	.voltages       = MMC_VDD_32_33 | MMC_VDD_33_34,
746  	.host_caps      = MMC_MODE_4BIT | MMC_MODE_HS,
747  	.part_type      = PART_TYPE_DOS,
748  	.b_max          = CONFIG_SYS_MMC_MAX_BLK_COUNT,
749  };
750  #endif
751  
sh_sdhi_init(unsigned long addr,int ch,unsigned long quirks)752  int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks)
753  {
754  	int ret = 0;
755  	struct mmc *mmc;
756  	struct sh_sdhi_host *host = NULL;
757  
758  	if (ch >= CONFIG_SYS_SH_SDHI_NR_CHANNEL)
759  		return -ENODEV;
760  
761  	host = malloc(sizeof(struct sh_sdhi_host));
762  	if (!host)
763  		return -ENOMEM;
764  
765  	mmc = mmc_create(&sh_sdhi_cfg, host);
766  	if (!mmc) {
767  		ret = -1;
768  		goto error;
769  	}
770  
771  	host->ch = ch;
772  	host->addr = (void __iomem *)addr;
773  	host->quirks = quirks;
774  
775  	if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
776  		host->bus_shift = 2;
777  	else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
778  		host->bus_shift = 1;
779  
780  	return ret;
781  error:
782  	if (host)
783  		free(host);
784  	return ret;
785  }
786  
787  #else
788  
789  struct sh_sdhi_plat {
790  	struct mmc_config cfg;
791  	struct mmc mmc;
792  };
793  
sh_sdhi_dm_send_cmd(struct udevice * dev,struct mmc_cmd * cmd,struct mmc_data * data)794  int sh_sdhi_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
795  			struct mmc_data *data)
796  {
797  	struct sh_sdhi_host *host = dev_get_priv(dev);
798  
799  	return sh_sdhi_send_cmd_common(host, cmd, data);
800  }
801  
sh_sdhi_dm_set_ios(struct udevice * dev)802  int sh_sdhi_dm_set_ios(struct udevice *dev)
803  {
804  	struct sh_sdhi_host *host = dev_get_priv(dev);
805  	struct mmc *mmc = mmc_get_mmc_dev(dev);
806  
807  	return sh_sdhi_set_ios_common(host, mmc);
808  }
809  
810  static const struct dm_mmc_ops sh_sdhi_dm_ops = {
811  	.send_cmd	= sh_sdhi_dm_send_cmd,
812  	.set_ios	= sh_sdhi_dm_set_ios,
813  };
814  
sh_sdhi_dm_bind(struct udevice * dev)815  static int sh_sdhi_dm_bind(struct udevice *dev)
816  {
817  	struct sh_sdhi_plat *plat = dev_get_platdata(dev);
818  
819  	return mmc_bind(dev, &plat->mmc, &plat->cfg);
820  }
821  
sh_sdhi_dm_probe(struct udevice * dev)822  static int sh_sdhi_dm_probe(struct udevice *dev)
823  {
824  	struct sh_sdhi_plat *plat = dev_get_platdata(dev);
825  	struct sh_sdhi_host *host = dev_get_priv(dev);
826  	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
827  	struct clk sh_sdhi_clk;
828  	const u32 quirks = dev_get_driver_data(dev);
829  	fdt_addr_t base;
830  	int ret;
831  
832  	base = devfdt_get_addr(dev);
833  	if (base == FDT_ADDR_T_NONE)
834  		return -EINVAL;
835  
836  	host->addr = devm_ioremap(dev, base, SZ_2K);
837  	if (!host->addr)
838  		return -ENOMEM;
839  
840  	ret = clk_get_by_index(dev, 0, &sh_sdhi_clk);
841  	if (ret) {
842  		debug("failed to get clock, ret=%d\n", ret);
843  		return ret;
844  	}
845  
846  	ret = clk_enable(&sh_sdhi_clk);
847  	if (ret) {
848  		debug("failed to enable clock, ret=%d\n", ret);
849  		return ret;
850  	}
851  
852  	host->quirks = quirks;
853  
854  	if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
855  		host->bus_shift = 2;
856  	else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
857  		host->bus_shift = 1;
858  
859  	plat->cfg.name = dev->name;
860  	plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
861  
862  	switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width",
863  			       1)) {
864  	case 8:
865  		plat->cfg.host_caps |= MMC_MODE_8BIT;
866  		break;
867  	case 4:
868  		plat->cfg.host_caps |= MMC_MODE_4BIT;
869  		break;
870  	case 1:
871  		break;
872  	default:
873  		dev_err(dev, "Invalid \"bus-width\" value\n");
874  		return -EINVAL;
875  	}
876  
877  	sh_sdhi_initialize_common(host);
878  
879  	plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
880  	plat->cfg.f_min = CLKDEV_INIT;
881  	plat->cfg.f_max = CLKDEV_HS_DATA;
882  	plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
883  
884  	upriv->mmc = &plat->mmc;
885  
886  	return 0;
887  }
888  
889  static const struct udevice_id sh_sdhi_sd_match[] = {
890  	{ .compatible = "renesas,sdhi-r8a7795", .data = SH_SDHI_QUIRK_64BIT_BUF },
891  	{ .compatible = "renesas,sdhi-r8a7796", .data = SH_SDHI_QUIRK_64BIT_BUF },
892  	{ /* sentinel */ }
893  };
894  
895  U_BOOT_DRIVER(sh_sdhi_mmc) = {
896  	.name			= "sh-sdhi-mmc",
897  	.id			= UCLASS_MMC,
898  	.of_match		= sh_sdhi_sd_match,
899  	.bind			= sh_sdhi_dm_bind,
900  	.probe			= sh_sdhi_dm_probe,
901  	.priv_auto_alloc_size	= sizeof(struct sh_sdhi_host),
902  	.platdata_auto_alloc_size = sizeof(struct sh_sdhi_plat),
903  	.ops			= &sh_sdhi_dm_ops,
904  };
905  #endif
906