2 * Copyright (c) 2012 Robert N. M. Watson
5 * This software was developed by SRI International and the University of
6 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7 * ("CTSRD"), as part of the DARPA CRASH research programme.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include <sys/param.h>
36 #include <sys/condvar.h>
39 #include <sys/endian.h>
40 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/module.h>
44 #include <sys/mutex.h>
46 #include <sys/systm.h>
47 #include <sys/taskqueue.h>
49 #include <machine/bus.h>
50 #include <machine/resource.h>
52 #include <geom/geom_disk.h>
54 #include <dev/altera/sdcard/altera_sdcard.h>
56 int altera_sdcard_ignore_crc_errors = 1;
57 int altera_sdcard_verify_rxtx_writes = 1;
60 * Low-level I/O routines for the Altera SD Card University IP Core driver.
62 * XXXRW: Throughout, it is assumed that the IP Core handles multibyte
63 * registers as little endian, as is the case for other Altera IP cores.
64 * However, the specification makes no reference to endianness, so this
65 * assumption might not always be correct.
68 altera_sdcard_read_asr(struct altera_sdcard_softc *sc)
71 return (le16toh(bus_read_2(sc->as_res, ALTERA_SDCARD_OFF_ASR)));
75 altera_sdcard_process_csd0(struct altera_sdcard_softc *sc)
77 uint64_t c_size, c_size_mult, read_bl_len;
78 uint8_t byte0, byte1, byte2;
80 ALTERA_SDCARD_LOCK_ASSERT(sc);
83 * Compute card capacity per SD Card interface description as follows:
85 * Memory capacity = BLOCKNR * BLOCK_LEN
89 * BLOCKNR = (C_SIZE + 1) * MULT
90 * MULT = 2^(C_SIZE_MULT+2)
91 * BLOCK_LEN = 2^READ_BL_LEN
93 read_bl_len = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_READ_BL_LEN_BYTE];
94 read_bl_len &= ALTERA_SDCARD_CSD_READ_BL_LEN_MASK;
96 byte0 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE0];
97 byte0 &= ALTERA_SDCARD_CSD_C_SIZE_MASK0;
98 byte1 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE1];
99 byte2 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE2];
100 byte2 &= ALTERA_SDCARD_CSD_C_SIZE_MASK2;
101 c_size = (byte0 >> ALTERA_SDCARD_CSD_C_SIZE_RSHIFT0) |
102 (byte1 << ALTERA_SDCARD_CSD_C_SIZE_LSHIFT1) |
103 (byte2 << ALTERA_SDCARD_CSD_C_SIZE_LSHIFT2);
105 byte0 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE0];
106 byte0 &= ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK0;
107 byte1 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE1];
108 byte1 &= ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK1;
109 c_size_mult = (byte0 >> ALTERA_SDCARD_CSD_C_SIZE_MULT_RSHIFT0) |
110 (byte1 << ALTERA_SDCARD_CSD_C_SIZE_MULT_LSHIFT1);
113 * If we're just getting back zero's, mark the card as bad, even
114 * though it could just mean a Very Small Disk Indeed.
116 if (c_size == 0 && c_size_mult == 0 && read_bl_len == 0) {
117 device_printf(sc->as_dev, "Ignored zero-size card\n");
120 sc->as_mediasize = (c_size + 1) * (1 << (c_size_mult + 2)) *
126 altera_sdcard_read_csd(struct altera_sdcard_softc *sc)
128 uint8_t csd_structure;
131 ALTERA_SDCARD_LOCK_ASSERT(sc);
134 * XXXRW: Assume for now that when the SD Card IP Core negotiates
135 * voltage/speed/etc, it must use the CSD register, and therefore
136 * populates the SD Card IP Core's cache of the register value. This
137 * means that we can read it without issuing further SD Card commands.
138 * If this assumption proves false, we will (a) get back garbage and
139 * (b) need to add additional states in the driver state machine in
140 * order to query card properties before I/O can start.
142 * XXXRW: Treating this as an array of bytes, so no byte swapping --
143 * is that a safe assumption?
145 KASSERT(((uintptr_t)&sc->as_csd.csd_data) % 2 == 0,
146 ("%s: CSD buffer unaligned", __func__));
147 bus_read_region_2(sc->as_res, ALTERA_SDCARD_OFF_CSD,
148 (uint16_t *)sc->as_csd.csd_data, sizeof(sc->as_csd) / 2);
151 * Interpret the loaded CSD, extracting certain fields and copying
152 * them into the softc for easy software access.
154 * Currently, we support only CSD Version 1.0. If we detect a newer
155 * version, suppress card detection.
157 csd_structure = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_STRUCTURE_BYTE];
158 csd_structure &= ALTERA_SDCARD_CSD_STRUCTURE_MASK;
159 csd_structure >>= ALTERA_SDCARD_CSD_STRUCTURE_RSHIFT;
160 sc->as_csd_structure = csd_structure;
163 * Interpret the CSD field based on its version. Extract fields,
164 * especially mediasize.
166 * XXXRW: Desirable to support further CSD versions here.
168 switch (sc->as_csd_structure) {
170 error = altera_sdcard_process_csd0(sc);
176 device_printf(sc->as_dev,
177 "Ignored disk with unsupported CSD structure (%d)\n",
178 sc->as_csd_structure);
185 * XXXRW: The Altera IP Core specification indicates that RR1 is a 16-bit
186 * register, but all bits it identifies are >16 bit. Most likely, RR1 is a
190 altera_sdcard_read_rr1(struct altera_sdcard_softc *sc)
193 return (le16toh(bus_read_2(sc->as_res, ALTERA_SDCARD_OFF_RR1)));
197 altera_sdcard_write_cmd_arg(struct altera_sdcard_softc *sc, uint32_t cmd_arg)
200 bus_write_4(sc->as_res, ALTERA_SDCARD_OFF_CMD_ARG, htole32(cmd_arg));
204 altera_sdcard_write_cmd(struct altera_sdcard_softc *sc, uint16_t cmd)
207 bus_write_2(sc->as_res, ALTERA_SDCARD_OFF_CMD, htole16(cmd));
211 altera_sdcard_read_rxtx_buffer(struct altera_sdcard_softc *sc, void *data,
215 KASSERT((uintptr_t)data % 2 == 0,
216 ("%s: unaligned data %p", __func__, data));
217 KASSERT((len <= ALTERA_SDCARD_SECTORSIZE) && (len % 2 == 0),
218 ("%s: invalid length %ju", __func__, len));
220 bus_read_region_2(sc->as_res, ALTERA_SDCARD_OFF_RXTX_BUFFER,
221 (uint16_t *)data, len / 2);
225 altera_sdcard_write_rxtx_buffer(struct altera_sdcard_softc *sc, void *data,
228 u_int corrections, differences, i, retry_counter;
231 KASSERT((uintptr_t)data % 2 == 0,
232 ("%s: unaligned data %p", __func__, data));
233 KASSERT((len <= ALTERA_SDCARD_SECTORSIZE) && (len % 2 == 0),
234 ("%s: invalid length %ju", __func__, len));
238 bus_write_region_2(sc->as_res, ALTERA_SDCARD_OFF_RXTX_BUFFER,
239 (uint16_t *)data, len / 2);
242 * XXXRW: Due to a possible hardware bug, the above call to
243 * bus_write_region_2() might not succeed. If the workaround
244 * is enabled, verify each write and retry until it succeeds.
246 * XXXRW: Do we want a limit counter for retries here?
251 if (altera_sdcard_verify_rxtx_writes) {
252 for (i = 0; i < ALTERA_SDCARD_SECTORSIZE; i += 2) {
253 v = bus_read_2(sc->as_res,
254 ALTERA_SDCARD_OFF_RXTX_BUFFER + i);
255 d = *(uint16_t *)((uint8_t *)data + i);
257 if (retry_counter == 0) {
258 bus_write_2(sc->as_res,
259 ALTERA_SDCARD_OFF_RXTX_BUFFER + i,
261 v = bus_read_2(sc->as_res,
262 ALTERA_SDCARD_OFF_RXTX_BUFFER + i);
265 device_printf(sc->as_dev,
266 "%s: single word rewrite worked"
273 device_printf(sc->as_dev,
274 "%s: retrying write -- difference"
275 " %u at offset %u, retry %u\n",
276 __func__, differences, i,
280 if (differences != 0) {
282 if (retry_counter == 1 &&
283 corrections == differences)
287 } while (differences != 0);
289 device_printf(sc->as_dev, "%s: succeeded after %u retries\n",
290 __func__, retry_counter);
294 altera_sdcard_io_start_internal(struct altera_sdcard_softc *sc, struct bio *bp)
297 switch (bp->bio_cmd) {
299 altera_sdcard_write_cmd_arg(sc, bp->bio_pblkno *
300 ALTERA_SDCARD_SECTORSIZE);
301 altera_sdcard_write_cmd(sc, ALTERA_SDCARD_CMD_READ_BLOCK);
305 altera_sdcard_write_rxtx_buffer(sc, bp->bio_data,
307 altera_sdcard_write_cmd_arg(sc, bp->bio_pblkno *
308 ALTERA_SDCARD_SECTORSIZE);
309 altera_sdcard_write_cmd(sc, ALTERA_SDCARD_CMD_WRITE_BLOCK);
313 panic("%s: unsupported I/O operation %d", __func__,
319 altera_sdcard_io_start(struct altera_sdcard_softc *sc, struct bio *bp)
322 ALTERA_SDCARD_LOCK_ASSERT(sc);
323 KASSERT(sc->as_currentbio == NULL,
324 ("%s: bio already started", __func__));
327 * We advertise a block size and maximum I/O size up the stack of the
328 * SD Card IP Core sector size. Catch any attempts to not follow the
331 KASSERT(bp->bio_bcount == ALTERA_SDCARD_SECTORSIZE,
332 ("%s: I/O size not %d", __func__, ALTERA_SDCARD_SECTORSIZE));
333 altera_sdcard_io_start_internal(sc, bp);
334 sc->as_currentbio = bp;
335 sc->as_retriesleft = ALTERA_SDCARD_RETRY_LIMIT;
339 * Handle completed I/O. ASR is passed in to avoid reading it more than once.
340 * Return 1 if the I/O is actually complete (success, or retry limit
341 * exceeded), or 0 if not.
344 altera_sdcard_io_complete(struct altera_sdcard_softc *sc, uint16_t asr)
350 ALTERA_SDCARD_LOCK_ASSERT(sc);
351 KASSERT(!(asr & ALTERA_SDCARD_ASR_CMDINPROGRESS),
352 ("%s: still in progress", __func__));
353 KASSERT(asr & ALTERA_SDCARD_ASR_CARDPRESENT,
354 ("%s: card removed", __func__));
356 bp = sc->as_currentbio;
359 * Handle I/O retries if an error is returned by the device. Various
360 * quirks handled in the process:
362 * 1. ALTERA_SDCARD_ASR_CMDDATAERROR is ignored for BIO_WRITE.
363 * 2. ALTERA_SDCARD_RR1_COMMANDCRCFAILED is optionally ignored for
367 rr1 = altera_sdcard_read_rr1(sc);
368 switch (bp->bio_cmd) {
370 mask = ALTERA_SDCARD_RR1_ERRORMASK;
371 if (altera_sdcard_ignore_crc_errors)
372 mask &= ~ALTERA_SDCARD_RR1_COMMANDCRCFAILED;
373 if (asr & ALTERA_SDCARD_ASR_CMDTIMEOUT)
375 else if ((asr & ALTERA_SDCARD_ASR_CMDDATAERROR) &&
383 if (asr & ALTERA_SDCARD_ASR_CMDTIMEOUT)
393 sc->as_retriesleft--;
394 if (sc->as_retriesleft == 0 || bootverbose)
395 device_printf(sc->as_dev, "%s: %s operation block %ju "
396 "length %ju failed; asr 0x%08x (rr1: 0x%04x)%s\n",
397 __func__, bp->bio_cmd == BIO_READ ? "BIO_READ" :
398 (bp->bio_cmd == BIO_WRITE ? "BIO_WRITE" :
400 bp->bio_pblkno, bp->bio_bcount, asr, rr1,
401 sc->as_retriesleft != 0 ? " retrying" : "");
403 * This attempt experienced an error; possibly retry.
405 if (sc->as_retriesleft != 0) {
406 sc->as_flags |= ALTERA_SDCARD_FLAG_IOERROR;
407 altera_sdcard_io_start_internal(sc, bp);
410 sc->as_flags &= ~ALTERA_SDCARD_FLAG_IOERROR;
413 * Successful I/O completion path.
415 if (sc->as_flags & ALTERA_SDCARD_FLAG_IOERROR) {
416 device_printf(sc->as_dev, "%s: %s operation block %ju"
417 " length %ju succeeded after %d retries\n",
418 __func__, bp->bio_cmd == BIO_READ ? "BIO_READ" :
419 (bp->bio_cmd == BIO_WRITE ? "write" : "unknown"),
420 bp->bio_pblkno, bp->bio_bcount,
421 ALTERA_SDCARD_RETRY_LIMIT - sc->as_retriesleft);
422 sc->as_flags &= ~ALTERA_SDCARD_FLAG_IOERROR;
424 switch (bp->bio_cmd) {
426 altera_sdcard_read_rxtx_buffer(sc, bp->bio_data,
434 panic("%s: unsupported I/O operation %d", __func__,
440 biofinish(bp, NULL, error);
441 sc->as_currentbio = NULL;