xref: /netbsd-src/sys/arch/evbsh3/t_sh7706lan/scimci.c (revision 7433666e375b3ac4cc764df5a6726be98bc1cdd5)
1 /*	$NetBSD: scimci.c,v 1.5 2023/12/20 14:50:01 thorpej Exp $	*/
2 
3 /*-
4  * Copyright (C) 2009 NONAKA Kimihiro <nonaka@netbsd.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * Serial Peripheral interface driver to access MMC card
30  */
31 
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: scimci.c,v 1.5 2023/12/20 14:50:01 thorpej Exp $");
34 
35 #include <sys/param.h>
36 #include <sys/device.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/proc.h>
40 #include <sys/bus.h>
41 #include <sys/intr.h>
42 
43 #include <sh3/devreg.h>
44 #include <sh3/pfcreg.h>
45 #include <sh3/scireg.h>
46 
47 #include <dev/sdmmc/sdmmcvar.h>
48 #include <dev/sdmmc/sdmmcchip.h>
49 
50 #include <evbsh3/t_sh7706lan/t_sh7706lanvar.h>
51 
52 #ifdef SCIMCI_DEBUG
53 int scimci_debug = 1;
54 #define DPRINTF(n,s)	do { if ((n) <= scimci_debug) printf s; } while (0)
55 #else
56 #define DPRINTF(n,s)	do {} while (0)
57 #endif
58 
59 static int	scimci_host_reset(sdmmc_chipset_handle_t);
60 static uint32_t	scimci_host_ocr(sdmmc_chipset_handle_t);
61 static int	scimci_host_maxblklen(sdmmc_chipset_handle_t);
62 static int	scimci_card_detect(sdmmc_chipset_handle_t);
63 static int	scimci_write_protect(sdmmc_chipset_handle_t);
64 static int	scimci_bus_power(sdmmc_chipset_handle_t, uint32_t);
65 static int	scimci_bus_clock(sdmmc_chipset_handle_t, int);
66 static int	scimci_bus_width(sdmmc_chipset_handle_t, int);
67 static void	scimci_exec_command(sdmmc_chipset_handle_t,
68 		    struct sdmmc_command *);
69 
70 static struct sdmmc_chip_functions scimci_chip_functions = {
71 	/* host controller reset */
72 	.host_reset		= scimci_host_reset,
73 
74 	/* host controller capabilities */
75 	.host_ocr		= scimci_host_ocr,
76 	.host_maxblklen		= scimci_host_maxblklen,
77 
78 	/* card detection */
79 	.card_detect		= scimci_card_detect,
80 
81 	/* write protect */
82 	.write_protect		= scimci_write_protect,
83 
84 	/* bus power, clock frequency, width */
85 	.bus_power		= scimci_bus_power,
86 	.bus_clock		= scimci_bus_clock,
87 	.bus_width		= scimci_bus_width,
88 
89 	/* command execution */
90 	.exec_command		= scimci_exec_command,
91 
92 	/* card interrupt */
93 	.card_enable_intr	= NULL,
94 	.card_intr_ack		= NULL,
95 };
96 
97 static void	scimci_spi_initialize(sdmmc_chipset_handle_t);
98 
99 static struct sdmmc_spi_chip_functions scimci_spi_chip_functions = {
100 	.initialize		= scimci_spi_initialize,
101 };
102 
103 #define	CSR_SET_1(reg,set,mask) 					\
104 do {									\
105 	uint8_t _r;							\
106 	_r = _reg_read_1((reg));					\
107 	_r &= ~(mask);							\
108 	_r |= (set);							\
109 	_reg_write_1((reg), _r);					\
110 } while (/*CONSTCOND*/0)
111 
112 #define	CSR_SET_2(reg,set,mask) 					\
113 do {									\
114 	uint16_t _r;							\
115 	_r = _reg_read_2((reg));					\
116 	_r &= ~(mask);							\
117 	_r |= (set);							\
118 	_reg_write_2((reg), _r);					\
119 } while (/*CONSTCOND*/0)
120 
121 #define	CSR_CLR_1(reg,clr)	 					\
122 do {									\
123 	uint8_t _r;							\
124 	_r = _reg_read_1((reg));					\
125 	_r &= ~(clr);							\
126 	_reg_write_1((reg), _r);					\
127 } while (/*CONSTCOND*/0)
128 
129 #define	CSR_CLR_2(reg,clr)	 					\
130 do {									\
131 	uint16_t _r;							\
132 	_r = _reg_read_2((reg));					\
133 	_r &= ~(clr);							\
134 	_reg_write_2((reg), _r);					\
135 } while (/*CONSTCOND*/0)
136 
137 #define SCPCR_CLK_MASK	0x000C
138 #define SCPCR_CLK_IN	0x000C
139 #define SCPCR_CLK_OUT	0x0004
140 #define SCPDR_CLK	0x02
141 #define SCPCR_DAT_MASK	0x0003
142 #define SCPCR_DAT_IN	0x0003
143 #define SCPCR_DAT_OUT	0x0001
144 #define SCPDR_DAT	0x01
145 #define SCPCR_CMD_MASK	0x0030
146 #define SCPCR_CMD_IN	0x0030
147 #define SCPCR_CMD_OUT	0x0010
148 #define SCPDR_CMD	0x04
149 #define SCPCR_CS_MASK	0x00C0
150 #define SCPCR_CS_IN	0x00C0
151 #define SCPCR_CS_OUT	0x0040
152 #define SCPDR_CS	0x08
153 #define PGCR_EJECT	0x0300
154 #define PGDR_EJECT	0x10
155 
156 /* SCSCR */
157 #define SCSCR_SCK_OUT	0
158 #define SCSCR_SCK_IN	(SCSCR_CKE1)
159 
160 #define LOW_SPEED	144
161 #define MID_SPEED	48
162 #define MMC_TIME_OVER	1000
163 
164 struct scimci_softc {
165 	device_t sc_dev;
166 	device_t sc_sdmmc;
167 };
168 
169 static int scimci_match(device_t, cfdata_t, void *);
170 static void scimci_attach(device_t, device_t, void *);
171 
172 CFATTACH_DECL_NEW(scimci, sizeof(struct scimci_softc),
173     scimci_match, scimci_attach, NULL, NULL);
174 
175 static void scimci_putc(int);
176 static void scimci_putc_sw(void);
177 static int scimci_getc(void);
178 static void scimci_getc_sw(void);
179 static void scimci_cmd_cfgread(struct scimci_softc *, struct sdmmc_command *);
180 static void scimci_cmd_read(struct scimci_softc *, struct sdmmc_command *);
181 static void scimci_cmd_write(struct scimci_softc *, struct sdmmc_command *);
182 
183 void scimci_read_buffer(u_char *buf);
184 void scimci_write_buffer(const u_char *buf);
185 
186 /*ARGSUSED*/
187 static int
scimci_match(device_t parent,cfdata_t cf,void * aux)188 scimci_match(device_t parent, cfdata_t cf, void *aux)
189 {
190 
191 	if (IS_SH7706LSR)
192 		return 0;
193 	return 1;
194 }
195 
196 /*ARGSUSED*/
197 static void
scimci_attach(device_t parent,device_t self,void * aux)198 scimci_attach(device_t parent, device_t self, void *aux)
199 {
200 	struct scimci_softc *sc = device_private(self);
201 	struct sdmmcbus_attach_args saa;
202 
203 	sc->sc_dev = self;
204 
205 	aprint_naive("\n");
206 	aprint_normal(": SCI MMC controller\n");
207 
208 	/* Setup */
209 	CSR_SET_2(SH7709_SCPCR, SCPCR_CLK_OUT | SCPCR_CMD_OUT,
210 	    SCPCR_CLK_MASK | SCPCR_CMD_MASK);
211 	CSR_CLR_2(SH7709_SCPCR, SCPCR_CMD_MASK);
212 	CSR_SET_1(SH7709_SCPDR, SCPDR_CLK | SCPDR_CMD, 0);
213 	CSR_SET_2(SH7709_SCPCR, SCPCR_CS_OUT, SCPCR_CS_MASK);
214 
215 	SHREG_SCSCR = 0x00;
216 	SHREG_SCSSR = 0x00;
217 	SHREG_SCSCMR = 0xfa;	/* MSB first */
218 	SHREG_SCSMR = SCSMR_CA;	/* clock sync mode */
219 	SHREG_SCBRR = LOW_SPEED;
220 	delay(1000);		/* wait 1ms */
221 
222 	/*
223 	 * Attach the generic SD/MMC bus driver.  (The bus driver must
224 	 * not invoke any chipset functions before it is attached.)
225 	 */
226 	memset(&saa, 0, sizeof(saa));
227 	saa.saa_busname = "sdmmc";
228 	saa.saa_sct = &scimci_chip_functions;
229 	saa.saa_spi_sct = &scimci_spi_chip_functions;
230 	saa.saa_sch = sc;
231 	saa.saa_clkmin = 4000 / (LOW_SPEED + 1);
232 	saa.saa_clkmax = 4000 / (MID_SPEED + 1);
233 	saa.saa_caps = SMC_CAPS_SPI_MODE
234 		     | SMC_CAPS_SINGLE_ONLY
235 		     | SMC_CAPS_POLL_CARD_DET;
236 
237 	sc->sc_sdmmc = config_found(sc->sc_dev, &saa, NULL, CFARGS_NONE);
238 	if (sc->sc_sdmmc == NULL)
239 		aprint_error_dev(sc->sc_dev, "couldn't attach bus\n");
240 }
241 
242 /*
243  * SCI access functions
244  */
245 static void
scimci_putc(int c)246 scimci_putc(int c)
247 {
248 
249 	CSR_SET_2(SH7709_SCPCR, SCPCR_CLK_OUT, SCPCR_CLK_MASK);
250 	SHREG_SCSCR = SCSCR_TE | SCSCR_SCK_OUT;
251 	while ((SHREG_SCSSR & SCSSR_TDRE) == 0)
252 		continue;
253 	CSR_CLR_2(SH7709_SCPCR, SCPCR_CLK_MASK);
254 	SHREG_SCTDR = (uint8_t)c;
255 	(void) SHREG_SCSSR;
256 	SHREG_SCSSR = 0;
257 }
258 
259 static void
scimci_putc_sw(void)260 scimci_putc_sw(void)
261 {
262 
263 	while ((SHREG_SCSSR & SCSSR_TEND) == 0)
264 		continue;
265 
266 	CSR_SET_2(SH7709_SCPCR, SCPCR_CLK_IN, 0);
267 	SHREG_SCSCR |= SCSCR_SCK_IN;
268 	CSR_CLR_2(SH7709_SCPCR, SCPCR_CLK_MASK);
269 	SHREG_SCSMR = 0;
270 	SHREG_SCSCR = SCSCR_SCK_OUT;
271 	SHREG_SCSSR = 0;
272 	SHREG_SCSMR = SCSMR_CA;
273 }
274 
275 static int
scimci_getc(void)276 scimci_getc(void)
277 {
278 	int c;
279 
280 	SHREG_SCSCR = SCSCR_RE | SCSCR_SCK_OUT;
281 	if (SHREG_SCSSR & SCSSR_ORER) {
282 		SHREG_SCSSR &= ~SCSSR_ORER;
283 		return -1;
284 	}
285 	CSR_CLR_2(SH7709_SCPCR, SCPCR_CLK_MASK);
286 	while ((SHREG_SCSSR & SCSSR_RDRF) == 0)
287 		continue;
288 	c = SHREG_SCRDR;
289 	(void) SHREG_SCSSR;
290 	SHREG_SCSSR = 0;
291 
292 	return (uint8_t)c;
293 }
294 
295 static void
scimci_getc_sw(void)296 scimci_getc_sw(void)
297 {
298 
299 	SHREG_SCBRR = LOW_SPEED;
300 	while ((SHREG_SCSSR & SCSSR_RDRF) == 0)
301 		continue;
302 	(void) SHREG_SCRDR;
303 
304 	CSR_SET_2(SH7709_SCPCR, SCPCR_CLK_IN, 0);
305 	SHREG_SCSCR |= SCSCR_SCK_IN;
306 	CSR_CLR_2(SH7709_SCPCR, SCPCR_CLK_MASK);
307 	SHREG_SCSMR = 0;
308 	SHREG_SCSCR = SCSCR_SCK_OUT;
309 	SHREG_SCSSR = 0;
310 	SHREG_SCSMR = SCSMR_CA;
311 }
312 
313 /*
314  * Reset the host controller.  Called during initialization, when
315  * cards are removed, upon resume, and during error recovery.
316  */
317 /*ARGSUSED*/
318 static int
scimci_host_reset(sdmmc_chipset_handle_t sch)319 scimci_host_reset(sdmmc_chipset_handle_t sch)
320 {
321 
322 	return 0;
323 }
324 
325 /*ARGSUSED*/
326 static uint32_t
scimci_host_ocr(sdmmc_chipset_handle_t sch)327 scimci_host_ocr(sdmmc_chipset_handle_t sch)
328 {
329 
330 	return MMC_OCR_3_2V_3_3V|MMC_OCR_3_3V_3_4V;
331 }
332 
333 /*ARGSUSED*/
334 static int
scimci_host_maxblklen(sdmmc_chipset_handle_t sch)335 scimci_host_maxblklen(sdmmc_chipset_handle_t sch)
336 {
337 
338 	return 512;
339 }
340 
341 /*ARGSUSED*/
342 static int
scimci_card_detect(sdmmc_chipset_handle_t sch)343 scimci_card_detect(sdmmc_chipset_handle_t sch)
344 {
345 	uint8_t reg;
346 	int s;
347 
348 	s = splserial();
349 	CSR_SET_2(SH7709_PGCR, PGCR_EJECT, 0);
350 	reg = _reg_read_1(SH7709_PGDR);
351 	splx(s);
352 
353 	return !(reg & PGDR_EJECT);
354 }
355 
356 /*ARGSUSED*/
357 static int
scimci_write_protect(sdmmc_chipset_handle_t sch)358 scimci_write_protect(sdmmc_chipset_handle_t sch)
359 {
360 
361 	return 0;	/* non-protect */
362 }
363 
364 /*
365  * Set or change SD bus voltage and enable or disable SD bus power.
366  * Return zero on success.
367  */
368 /*ARGSUSED*/
369 static int
scimci_bus_power(sdmmc_chipset_handle_t sch,uint32_t ocr)370 scimci_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
371 {
372 
373 	if ((ocr & (MMC_OCR_3_2V_3_3V|MMC_OCR_3_3V_3_4V)) == 0)
374 		return 1;
375 
376 	/*XXX???*/
377 	return 0;
378 }
379 
380 /*
381  * Set or change MMCLK frequency or disable the MMC clock.
382  * Return zero on success.
383  */
384 /*ARGSUSED*/
385 static int
scimci_bus_clock(sdmmc_chipset_handle_t sch,int freq)386 scimci_bus_clock(sdmmc_chipset_handle_t sch, int freq)
387 {
388 
389 	return 0;
390 }
391 
392 /*ARGSUSED*/
393 static int
scimci_bus_width(sdmmc_chipset_handle_t sch,int width)394 scimci_bus_width(sdmmc_chipset_handle_t sch, int width)
395 {
396 
397 	if (width != 1)
398 		return 1;
399 	return 0;
400 }
401 
402 /*ARGSUSED*/
403 static void
scimci_spi_initialize(sdmmc_chipset_handle_t sch)404 scimci_spi_initialize(sdmmc_chipset_handle_t sch)
405 {
406 	int i, s;
407 
408 	s = splserial();
409 	CSR_SET_1(SH7709_SCPDR, SCPDR_CS, 0);
410 	for (i = 0; i < 20; i++)
411 		scimci_putc(0xff);
412 	scimci_putc_sw();
413 	CSR_CLR_1(SH7709_SCPDR, SCPDR_CS);
414 	splx(s);
415 }
416 
417 static void
scimci_exec_command(sdmmc_chipset_handle_t sch,struct sdmmc_command * cmd)418 scimci_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
419 {
420 	struct scimci_softc *sc = (struct scimci_softc *)sch;
421 	uint16_t resp;
422 	int timo;
423 	int s;
424 
425 	DPRINTF(1,("%s: start cmd %d arg=%#x data=%p dlen=%d flags=%#x "
426 	    "proc=%p \"%s\"\n", device_xname(sc->sc_dev),
427 	    cmd->c_opcode, cmd->c_arg, cmd->c_data, cmd->c_datalen,
428 	    cmd->c_flags, curproc, curproc ? curproc->p_comm : ""));
429 
430 	s = splhigh();
431 
432 	if (cmd->c_opcode == MMC_GO_IDLE_STATE)
433 		SHREG_SCBRR = LOW_SPEED;
434 	else
435 		SHREG_SCBRR = MID_SPEED;
436 
437 	scimci_putc(0xff);
438 	scimci_putc(0x40 | (cmd->c_opcode & 0x3f));
439 	scimci_putc((cmd->c_arg >> 24) & 0xff);
440 	scimci_putc((cmd->c_arg >> 16) & 0xff);
441 	scimci_putc((cmd->c_arg >> 8) & 0xff);
442 	scimci_putc((cmd->c_arg >> 0) & 0xff);
443 	scimci_putc((cmd->c_opcode == MMC_GO_IDLE_STATE) ? 0x95 :
444 	    (cmd->c_opcode == SD_SEND_IF_COND) ? 0x87 : 0); /* CRC */
445 	scimci_putc(0xff);
446 	scimci_putc_sw();
447 
448 	timo = MMC_TIME_OVER;
449 	while ((resp = scimci_getc()) & 0x80) {
450 		if(--timo == 0) {
451 			DPRINTF(1, ("%s: response timeout\n",
452 			    device_xname(sc->sc_dev)));
453 			scimci_getc_sw();
454 			cmd->c_error = ETIMEDOUT;
455 			goto out;
456 		}
457 	}
458 	if (ISSET(cmd->c_flags, SCF_RSP_SPI_S2)) {
459 		resp |= (uint16_t)scimci_getc() << 8;
460 	} else if (ISSET(cmd->c_flags, SCF_RSP_SPI_B4)) {
461 		cmd->c_resp[1] =  (uint32_t) scimci_getc() << 24;
462 		cmd->c_resp[1] |= (uint32_t) scimci_getc() << 16;
463 		cmd->c_resp[1] |= (uint32_t) scimci_getc() << 8;
464 		cmd->c_resp[1] |= (uint32_t) scimci_getc();
465 		DPRINTF(1, ("R3 resp: %#x\n", cmd->c_resp[1]));
466 	}
467 	scimci_getc_sw();
468 
469 	cmd->c_resp[0] = resp;
470 	if (resp != 0 && resp != R1_SPI_IDLE) {
471 		DPRINTF(1, ("%s: response error: %#x\n",
472 		    device_xname(sc->sc_dev), resp));
473 		cmd->c_error = EIO;
474 		goto out;
475 	}
476 	DPRINTF(1, ("R1 resp: %#x\n", resp));
477 
478 	if (cmd->c_datalen > 0) {
479 		if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
480 			/* XXX: swap in this place? */
481 			if (cmd->c_opcode == MMC_SEND_CID ||
482 			    cmd->c_opcode == MMC_SEND_CSD) {
483 				sdmmc_response res;
484 				uint32_t *p = cmd->c_data;
485 
486 				scimci_cmd_cfgread(sc, cmd);
487 				res[0] = be32toh(p[3]);
488 				res[1] = be32toh(p[2]);
489 				res[2] = be32toh(p[1]);
490 				res[3] = be32toh(p[0]);
491 				memcpy(p, &res, sizeof(res));
492 			} else {
493 				scimci_cmd_read(sc, cmd);
494 			}
495 		} else {
496 			scimci_cmd_write(sc, cmd);
497 		}
498 	}
499 
500 out:
501 	SET(cmd->c_flags, SCF_ITSDONE);
502 	splx(s);
503 
504 	DPRINTF(1,("%s: cmd %d done (flags=%#x error=%d)\n",
505 	  device_xname(sc->sc_dev), cmd->c_opcode, cmd->c_flags, cmd->c_error));
506 }
507 
508 static void
scimci_cmd_cfgread(struct scimci_softc * sc,struct sdmmc_command * cmd)509 scimci_cmd_cfgread(struct scimci_softc *sc, struct sdmmc_command *cmd)
510 {
511 	u_char *data = cmd->c_data;
512 	int timo;
513 	int c;
514 	int i;
515 
516 	/* wait data token */
517 	for (timo = MMC_TIME_OVER; timo > 0; timo--) {
518 		c = scimci_getc();
519 		if (c < 0) {
520 			aprint_error_dev(sc->sc_dev, "cfg read i/o error\n");
521 			cmd->c_error = EIO;
522 			return;
523 		}
524 		if (c != 0xff)
525 			break;
526 	}
527 	if (timo == 0) {
528 		aprint_error_dev(sc->sc_dev, "cfg read timeout\n");
529 		cmd->c_error = ETIMEDOUT;
530 		return;
531 	}
532 	if (c != 0xfe) {
533 		aprint_error_dev(sc->sc_dev, "cfg read error (data=%#x)\n", c);
534 		cmd->c_error = EIO;
535 		return;
536 	}
537 
538 	/* data read */
539 	SHREG_SCSCR = SCSCR_RE | SCSCR_SCK_OUT;
540 	data[0] = '\0'; /* XXXFIXME!!! */
541 	for (i = 1 /* XXXFIXME!!!*/ ; i < cmd->c_datalen; i++) {
542 		while ((SHREG_SCSSR & SCSSR_RDRF) == 0)
543 			continue;
544 		data[i] = SHREG_SCRDR;
545 		(void) SHREG_SCSSR;
546 		SHREG_SCSSR = 0;
547 	}
548 
549 	SHREG_SCBRR = LOW_SPEED;
550 	(void) scimci_getc();
551 	(void) scimci_getc();
552 	(void) scimci_getc();
553 	scimci_getc_sw();
554 
555 #ifdef SCIMCI_DEBUG
556 	sdmmc_dump_data(NULL, cmd->c_data, cmd->c_datalen);
557 #endif
558 }
559 
560 static void
scimci_cmd_read(struct scimci_softc * sc,struct sdmmc_command * cmd)561 scimci_cmd_read(struct scimci_softc *sc, struct sdmmc_command *cmd)
562 {
563 	u_char *data = cmd->c_data;
564 	int timo;
565 	int c;
566 	int i;
567 
568 	/* wait data token */
569 	for (timo = MMC_TIME_OVER; timo > 0; timo--) {
570 		c = scimci_getc();
571 		if (c < 0) {
572 			aprint_error_dev(sc->sc_dev, "read i/o error\n");
573 			cmd->c_error = EIO;
574 			return;
575 		}
576 		if (c != 0xff)
577 			break;
578 	}
579 	if (timo == 0) {
580 		aprint_error_dev(sc->sc_dev, "read timeout\n");
581 		cmd->c_error = ETIMEDOUT;
582 		return;
583 	}
584 	if (c != 0xfe) {
585 		aprint_error_dev(sc->sc_dev, "read error (data=%#x)\n", c);
586 		cmd->c_error = EIO;
587 		return;
588 	}
589 
590 	/* data read */
591 	SHREG_SCBRR = MID_SPEED;
592 	SHREG_SCSCR = SCSCR_RE | SCSCR_SCK_OUT;
593 	for (i = 0; i < cmd->c_datalen; i++) {
594 		while ((SHREG_SCSSR & SCSSR_RDRF) == 0)
595 			continue;
596 		data[i] = SHREG_SCRDR;
597 		(void) SHREG_SCSSR;
598 		SHREG_SCSSR = 0;
599 	}
600 
601 	SHREG_SCBRR = LOW_SPEED;
602 	(void) scimci_getc();
603 	(void) scimci_getc();
604 	(void) scimci_getc();
605 	scimci_getc_sw();
606 
607 #ifdef SCIMCI_DEBUG
608 	sdmmc_dump_data(NULL, cmd->c_data, cmd->c_datalen);
609 #endif
610 }
611 
612 static void
scimci_cmd_write(struct scimci_softc * sc,struct sdmmc_command * cmd)613 scimci_cmd_write(struct scimci_softc *sc, struct sdmmc_command *cmd)
614 {
615 	char *data = cmd->c_data;
616 	int timo;
617 	int c;
618 	int i;
619 
620 	scimci_putc(0xff);
621 	scimci_putc(0xfe);
622 
623 	/* data write */
624 	SHREG_SCBRR = MID_SPEED;
625 	SHREG_SCSCR = SCSCR_TE | SCSCR_SCK_OUT;
626 	for (i = 0; i < cmd->c_datalen; i++) {
627 		while ((SHREG_SCSSR & SCSSR_TDRE) == 0)
628 			continue;
629 		SHREG_SCTDR = data[i];
630 		(void) SHREG_SCSSR;
631 		SHREG_SCSSR = 0;
632 	}
633 
634 	SHREG_SCBRR = LOW_SPEED;
635 	scimci_putc(0);
636 	scimci_putc(0);
637 	scimci_putc(0);
638 	scimci_putc_sw();
639 
640 	for (timo = MMC_TIME_OVER; timo > 0; timo--) {
641 		c = scimci_getc();
642 		if (c < 0) {
643 			aprint_error_dev(sc->sc_dev, "write i/o error\n");
644 			cmd->c_error = EIO;
645 			scimci_getc_sw();
646 			return;
647 		}
648 		if (c == 0xff)
649 			break;
650 	}
651 	if (timo == 0) {
652 		aprint_error_dev(sc->sc_dev, "write timeout\n");
653 		cmd->c_error = ETIMEDOUT;
654 	}
655 	scimci_getc_sw();
656 }
657