xref: /freebsd/sys/dev/altera/sdcard/altera_sdcard_io.c (revision 8aac90f18aef7c9eea906c3ff9a001ca7b94f375)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2012 Robert N. M. Watson
5  * All rights reserved.
6  *
7  * This software was developed by SRI International and the University of
8  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
9  * ("CTSRD"), as part of the DARPA CRASH research programme.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/param.h>
34 #include <sys/bus.h>
35 #include <sys/condvar.h>
36 #include <sys/conf.h>
37 #include <sys/bio.h>
38 #include <sys/endian.h>
39 #include <sys/kernel.h>
40 #include <sys/lock.h>
41 #include <sys/malloc.h>
42 #include <sys/module.h>
43 #include <sys/mutex.h>
44 #include <sys/rman.h>
45 #include <sys/systm.h>
46 #include <sys/taskqueue.h>
47 
48 #include <machine/bus.h>
49 #include <machine/resource.h>
50 
51 #include <geom/geom_disk.h>
52 
53 #include <dev/altera/sdcard/altera_sdcard.h>
54 
55 int altera_sdcard_ignore_crc_errors = 1;
56 int altera_sdcard_verify_rxtx_writes = 1;
57 
58 /*
59  * Low-level I/O routines for the Altera SD Card University IP Core driver.
60  *
61  * XXXRW: Throughout, it is assumed that the IP Core handles multibyte
62  * registers as little endian, as is the case for other Altera IP cores.
63  * However, the specification makes no reference to endianness, so this
64  * assumption might not always be correct.
65  */
66 uint16_t
67 altera_sdcard_read_asr(struct altera_sdcard_softc *sc)
68 {
69 
70 	return (le16toh(bus_read_2(sc->as_res, ALTERA_SDCARD_OFF_ASR)));
71 }
72 
73 static int
74 altera_sdcard_process_csd0(struct altera_sdcard_softc *sc)
75 {
76 	uint64_t c_size, c_size_mult, read_bl_len;
77 	uint8_t byte0, byte1, byte2;
78 
79 	ALTERA_SDCARD_LOCK_ASSERT(sc);
80 
81 	/*-
82 	 * Compute card capacity per SD Card interface description as follows:
83 	 *
84 	 *   Memory capacity = BLOCKNR * BLOCK_LEN
85 	 *
86 	 * Where:
87 	 *
88 	 *   BLOCKNR = (C_SIZE + 1) * MULT
89 	 *   MULT = 2^(C_SIZE_MULT+2)
90 	 *   BLOCK_LEN = 2^READ_BL_LEN
91 	 */
92 	read_bl_len = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_READ_BL_LEN_BYTE];
93 	read_bl_len &= ALTERA_SDCARD_CSD_READ_BL_LEN_MASK;
94 
95 	byte0 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE0];
96 	byte0 &= ALTERA_SDCARD_CSD_C_SIZE_MASK0;
97 	byte1 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE1];
98 	byte2 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE2];
99 	byte2 &= ALTERA_SDCARD_CSD_C_SIZE_MASK2;
100 	c_size = (byte0 >> ALTERA_SDCARD_CSD_C_SIZE_RSHIFT0) |
101 	    (byte1 << ALTERA_SDCARD_CSD_C_SIZE_LSHIFT1) |
102 	    (byte2 << ALTERA_SDCARD_CSD_C_SIZE_LSHIFT2);
103 
104 	byte0 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE0];
105 	byte0 &= ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK0;
106 	byte1 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE1];
107 	byte1 &= ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK1;
108 	c_size_mult = (byte0 >> ALTERA_SDCARD_CSD_C_SIZE_MULT_RSHIFT0) |
109 	    (byte1 << ALTERA_SDCARD_CSD_C_SIZE_MULT_LSHIFT1);
110 
111 	/*
112 	 * If we're just getting back zero's, mark the card as bad, even
113 	 * though it could just mean a Very Small Disk Indeed.
114 	 */
115 	if (c_size == 0 && c_size_mult == 0 && read_bl_len == 0) {
116 		device_printf(sc->as_dev, "Ignored zero-size card\n");
117 		return (ENXIO);
118 	}
119 	sc->as_mediasize = (c_size + 1) * (1 << (c_size_mult + 2)) *
120 	    (1 << read_bl_len);
121 	return (0);
122 }
123 
124 int
125 altera_sdcard_read_csd(struct altera_sdcard_softc *sc)
126 {
127 	uint8_t csd_structure;
128 	int error;
129 
130 	ALTERA_SDCARD_LOCK_ASSERT(sc);
131 
132 	/*
133 	 * XXXRW: Assume for now that when the SD Card IP Core negotiates
134 	 * voltage/speed/etc, it must use the CSD register, and therefore
135 	 * populates the SD Card IP Core's cache of the register value.  This
136 	 * means that we can read it without issuing further SD Card commands.
137 	 * If this assumption proves false, we will (a) get back garbage and
138 	 * (b) need to add additional states in the driver state machine in
139 	 * order to query card properties before I/O can start.
140 	 *
141 	 * XXXRW: Treating this as an array of bytes, so no byte swapping --
142 	 * is that a safe assumption?
143 	 */
144 	KASSERT(((uintptr_t)&sc->as_csd.csd_data) % 2 == 0,
145 	    ("%s: CSD buffer unaligned", __func__));
146 	bus_read_region_2(sc->as_res, ALTERA_SDCARD_OFF_CSD,
147 	    (uint16_t *)sc->as_csd.csd_data, sizeof(sc->as_csd) / 2);
148 
149 	/*
150 	 * Interpret the loaded CSD, extracting certain fields and copying
151 	 * them into the softc for easy software access.
152 	 *
153 	 * Currently, we support only CSD Version 1.0.  If we detect a newer
154 	 * version, suppress card detection.
155 	 */
156 	csd_structure = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_STRUCTURE_BYTE];
157 	csd_structure &= ALTERA_SDCARD_CSD_STRUCTURE_MASK;
158 	csd_structure >>= ALTERA_SDCARD_CSD_STRUCTURE_RSHIFT;
159 	sc->as_csd_structure = csd_structure;
160 
161 	/*
162 	 * Interpret the CSD field based on its version.  Extract fields,
163 	 * especially mediasize.
164 	 *
165 	 * XXXRW: Desirable to support further CSD versions here.
166 	 */
167 	switch (sc->as_csd_structure) {
168 	case 0:
169 		error = altera_sdcard_process_csd0(sc);
170 		if (error)
171 			return (error);
172 		break;
173 
174 	default:
175 		device_printf(sc->as_dev,
176 		    "Ignored disk with unsupported CSD structure (%d)\n",
177 		    sc->as_csd_structure);
178 		return (ENXIO);
179 	}
180 	return (0);
181 }
182 
183 /*
184  * XXXRW: The Altera IP Core specification indicates that RR1 is a 16-bit
185  * register, but all bits it identifies are >16 bit.  Most likely, RR1 is a
186  * 32-bit register?
187  */
188 static uint16_t
189 altera_sdcard_read_rr1(struct altera_sdcard_softc *sc)
190 {
191 
192 	return (le16toh(bus_read_2(sc->as_res, ALTERA_SDCARD_OFF_RR1)));
193 }
194 
195 static void
196 altera_sdcard_write_cmd_arg(struct altera_sdcard_softc *sc, uint32_t cmd_arg)
197 {
198 
199 	bus_write_4(sc->as_res, ALTERA_SDCARD_OFF_CMD_ARG, htole32(cmd_arg));
200 }
201 
202 static void
203 altera_sdcard_write_cmd(struct altera_sdcard_softc *sc, uint16_t cmd)
204 {
205 
206 	bus_write_2(sc->as_res, ALTERA_SDCARD_OFF_CMD, htole16(cmd));
207 }
208 
209 static void
210 altera_sdcard_read_rxtx_buffer(struct altera_sdcard_softc *sc, void *data,
211     size_t len)
212 {
213 
214 	KASSERT((uintptr_t)data % 2 == 0,
215 	    ("%s: unaligned data %p", __func__, data));
216 	KASSERT((len <= ALTERA_SDCARD_SECTORSIZE) && (len % 2 == 0),
217 	    ("%s: invalid length %ju", __func__, len));
218 
219 	bus_read_region_2(sc->as_res, ALTERA_SDCARD_OFF_RXTX_BUFFER,
220 	    (uint16_t *)data, len / 2);
221 }
222 
223 static void
224 altera_sdcard_write_rxtx_buffer(struct altera_sdcard_softc *sc, void *data,
225     size_t len)
226 {
227 	u_int corrections, differences, i, retry_counter;
228 	uint16_t d, v;
229 
230 	KASSERT((uintptr_t)data % 2 == 0,
231 	    ("%s: unaligned data %p", __func__, data));
232 	KASSERT((len <= ALTERA_SDCARD_SECTORSIZE) && (len % 2 == 0),
233 	    ("%s: invalid length %ju", __func__, len));
234 
235 	retry_counter = 0;
236 	do {
237 		bus_write_region_2(sc->as_res, ALTERA_SDCARD_OFF_RXTX_BUFFER,
238 		    (uint16_t *)data, len / 2);
239 
240 		/*
241 		 * XXXRW: Due to a possible hardware bug, the above call to
242 		 * bus_write_region_2() might not succeed.  If the workaround
243 		 * is enabled, verify each write and retry until it succeeds.
244 		 *
245 		 * XXXRW: Do we want a limit counter for retries here?
246 		 */
247 recheck:
248 		corrections = 0;
249 		differences = 0;
250 		if (altera_sdcard_verify_rxtx_writes) {
251 			for (i = 0; i < ALTERA_SDCARD_SECTORSIZE; i += 2) {
252 				v = bus_read_2(sc->as_res,
253 				    ALTERA_SDCARD_OFF_RXTX_BUFFER + i);
254 				d = *(uint16_t *)((uint8_t *)data + i);
255 				if (v != d) {
256 					if (retry_counter == 0) {
257 						bus_write_2(sc->as_res,
258 						    ALTERA_SDCARD_OFF_RXTX_BUFFER + i,
259 						    d);
260 						v = bus_read_2(sc->as_res,
261 						    ALTERA_SDCARD_OFF_RXTX_BUFFER + i);
262 						if (v == d) {
263 							corrections++;
264 							device_printf(sc->as_dev,
265 							    "%s: single word rewrite worked"
266 							    " at offset %u\n",
267 							    __func__, i);
268 							continue;
269 						}
270 					}
271 					differences++;
272 					device_printf(sc->as_dev,
273 					    "%s: retrying write -- difference"
274 					    " %u at offset %u, retry %u\n",
275 					    __func__, differences, i,
276 					    retry_counter);
277 				}
278 			}
279 			if (differences != 0) {
280 				retry_counter++;
281 				if (retry_counter == 1 &&
282 				    corrections == differences)
283 					goto recheck;
284 			}
285 		}
286 	} while (differences != 0);
287 	if (retry_counter)
288 		device_printf(sc->as_dev, "%s: succeeded after %u retries\n",
289 		    __func__, retry_counter);
290 }
291 
292 static void
293 altera_sdcard_io_start_internal(struct altera_sdcard_softc *sc,
294     struct bio **bpp)
295 {
296 	struct bio *bp;
297 
298 	bp = *bpp;
299 
300 	switch (bp->bio_cmd) {
301 	case BIO_READ:
302 		altera_sdcard_write_cmd_arg(sc, bp->bio_pblkno *
303 		    ALTERA_SDCARD_SECTORSIZE);
304 		altera_sdcard_write_cmd(sc, ALTERA_SDCARD_CMD_READ_BLOCK);
305 		break;
306 
307 	case BIO_WRITE:
308 		altera_sdcard_write_rxtx_buffer(sc, bp->bio_data,
309 		    bp->bio_bcount);
310 		altera_sdcard_write_cmd_arg(sc, bp->bio_pblkno *
311 		    ALTERA_SDCARD_SECTORSIZE);
312 		altera_sdcard_write_cmd(sc, ALTERA_SDCARD_CMD_WRITE_BLOCK);
313 		break;
314 
315 	default:
316 		biofinish(bp, NULL, EOPNOTSUPP);
317 		*bpp = NULL;
318 	}
319 }
320 
321 void
322 altera_sdcard_io_start(struct altera_sdcard_softc *sc, struct bio *bp)
323 {
324 
325 	ALTERA_SDCARD_LOCK_ASSERT(sc);
326 	KASSERT(sc->as_currentbio == NULL,
327 	    ("%s: bio already started", __func__));
328 
329 	/*
330 	 * We advertise a block size and maximum I/O size up the stack of the
331 	 * SD Card IP Core sector size.  Catch any attempts to not follow the
332 	 * rules.
333 	 */
334 	KASSERT(bp->bio_bcount == ALTERA_SDCARD_SECTORSIZE,
335 	    ("%s: I/O size not %d", __func__, ALTERA_SDCARD_SECTORSIZE));
336 	altera_sdcard_io_start_internal(sc, &bp);
337 	sc->as_currentbio = bp;
338 	sc->as_retriesleft = ALTERA_SDCARD_RETRY_LIMIT;
339 }
340 
341 /*
342  * Handle completed I/O.  ASR is passed in to avoid reading it more than once.
343  * Return 1 if the I/O is actually complete (success, or retry limit
344  * exceeded), or 0 if not.
345  */
346 int
347 altera_sdcard_io_complete(struct altera_sdcard_softc *sc, uint16_t asr)
348 {
349 	struct bio *bp;
350 	uint16_t rr1, mask;
351 	int error;
352 
353 	ALTERA_SDCARD_LOCK_ASSERT(sc);
354 	KASSERT(!(asr & ALTERA_SDCARD_ASR_CMDINPROGRESS),
355 	    ("%s: still in progress", __func__));
356 	KASSERT(asr & ALTERA_SDCARD_ASR_CARDPRESENT,
357 	    ("%s: card removed", __func__));
358 
359 	bp = sc->as_currentbio;
360 
361 	/*-
362 	 * Handle I/O retries if an error is returned by the device.  Various
363 	 * quirks handled in the process:
364 	 *
365 	 * 1. ALTERA_SDCARD_ASR_CMDDATAERROR is ignored for BIO_WRITE.
366 	 * 2. ALTERA_SDCARD_RR1_COMMANDCRCFAILED is optionally ignored for
367 	 *    BIO_READ.
368 	 */
369 	error = 0;
370 	rr1 = altera_sdcard_read_rr1(sc);
371 	switch (bp->bio_cmd) {
372 	case BIO_READ:
373 		mask = ALTERA_SDCARD_RR1_ERRORMASK;
374 		if (altera_sdcard_ignore_crc_errors)
375 			mask &= ~ALTERA_SDCARD_RR1_COMMANDCRCFAILED;
376 		if (asr & ALTERA_SDCARD_ASR_CMDTIMEOUT)
377 			error = EIO;
378 		else if ((asr & ALTERA_SDCARD_ASR_CMDDATAERROR) &&
379 		    (rr1 & mask))
380 			error = EIO;
381 		else
382 			error = 0;
383 		break;
384 
385 	case BIO_WRITE:
386 		if (asr & ALTERA_SDCARD_ASR_CMDTIMEOUT)
387 			error = EIO;
388 		else
389 			error = 0;
390 		break;
391 
392 	default:
393 		break;
394 	}
395 	if (error) {
396 		sc->as_retriesleft--;
397 		if (sc->as_retriesleft == 0 || bootverbose)
398 			device_printf(sc->as_dev, "%s: %s operation block %ju "
399 			    "length %ju failed; asr 0x%08x (rr1: 0x%04x)%s\n",
400 			    __func__, bp->bio_cmd == BIO_READ ? "BIO_READ" :
401 			    (bp->bio_cmd == BIO_WRITE ? "BIO_WRITE" :
402 			    "unknown"),
403 			    bp->bio_pblkno, bp->bio_bcount, asr, rr1,
404 			    sc->as_retriesleft != 0 ? " retrying" : "");
405 		/*
406 		 * This attempt experienced an error; possibly retry.
407 		 */
408 		if (sc->as_retriesleft != 0) {
409 			sc->as_flags |= ALTERA_SDCARD_FLAG_IOERROR;
410 			altera_sdcard_io_start_internal(sc, &bp);
411 			return (0);
412 		}
413 		sc->as_flags &= ~ALTERA_SDCARD_FLAG_IOERROR;
414 	} else {
415 		/*
416 		 * Successful I/O completion path.
417 		 */
418 		if (sc->as_flags & ALTERA_SDCARD_FLAG_IOERROR) {
419 			device_printf(sc->as_dev, "%s: %s operation block %ju"
420 			    " length %ju succeeded after %d retries\n",
421 			    __func__, bp->bio_cmd == BIO_READ ? "BIO_READ" :
422 			    (bp->bio_cmd == BIO_WRITE ? "write" : "unknown"),
423 			    bp->bio_pblkno, bp->bio_bcount,
424 			    ALTERA_SDCARD_RETRY_LIMIT - sc->as_retriesleft);
425 			sc->as_flags &= ~ALTERA_SDCARD_FLAG_IOERROR;
426 		}
427 		switch (bp->bio_cmd) {
428 		case BIO_READ:
429 			altera_sdcard_read_rxtx_buffer(sc, bp->bio_data,
430 			    bp->bio_bcount);
431 			break;
432 
433 		case BIO_WRITE:
434 			break;
435 
436 		default:
437 			panic("%s: unsupported I/O operation %d", __func__,
438 			    bp->bio_cmd);
439 		}
440 		bp->bio_resid = 0;
441 		error = 0;
442 	}
443 	biofinish(bp, NULL, error);
444 	sc->as_currentbio = NULL;
445 	return (1);
446 }
447