Line data Source code
1 : /* $OpenBSD: sdmmc_io.c,v 1.40 2018/08/09 13:52:36 patrick Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
5 : *
6 : * Permission to use, copy, modify, and distribute this software for any
7 : * purpose with or without fee is hereby granted, provided that the above
8 : * copyright notice and this permission notice appear in all copies.
9 : *
10 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 : */
18 :
19 : /* Routines for SD I/O cards. */
20 :
21 : #include <sys/param.h>
22 : #include <sys/device.h>
23 : #include <sys/kernel.h>
24 : #include <sys/malloc.h>
25 : #include <sys/systm.h>
26 :
27 : #include <dev/sdmmc/sdmmc_ioreg.h>
28 : #include <dev/sdmmc/sdmmcchip.h>
29 : #include <dev/sdmmc/sdmmcvar.h>
30 :
31 : struct sdmmc_intr_handler {
32 : struct sdmmc_softc *ih_softc;
33 : const char *ih_name;
34 : int (*ih_fun)(void *);
35 : void *ih_arg;
36 : TAILQ_ENTRY(sdmmc_intr_handler) entry;
37 : };
38 :
39 : int sdmmc_submatch(struct device *, void *, void *);
40 : int sdmmc_print(void *, const char *);
41 : int sdmmc_io_rw_direct(struct sdmmc_softc *, struct sdmmc_function *,
42 : int, u_char *, int);
43 : int sdmmc_io_rw_extended_subr(struct sdmmc_softc *, struct sdmmc_function *,
44 : bus_dmamap_t, int, u_char *, int, int);
45 : int sdmmc_io_rw_extended(struct sdmmc_softc *, struct sdmmc_function *,
46 : int, u_char *, int, int);
47 : int sdmmc_io_xchg(struct sdmmc_softc *, struct sdmmc_function *,
48 : int, u_char *);
49 : void sdmmc_io_reset(struct sdmmc_softc *);
50 : int sdmmc_io_send_op_cond(struct sdmmc_softc *, u_int32_t, u_int32_t *);
51 : void sdmmc_io_set_blocklen(struct sdmmc_function *, unsigned int);
52 : void sdmmc_io_set_bus_width(struct sdmmc_function *, int);
53 : int sdmmc_io_set_highspeed(struct sdmmc_function *sf, int);
54 :
55 : #ifdef SDMMC_DEBUG
56 : #define DPRINTF(s) printf s
57 : #else
58 : #define DPRINTF(s) /**/
59 : #endif
60 :
61 : #ifdef SDMMC_DEBUG
62 : int sdmmc_verbose = 1;
63 : #else
64 : int sdmmc_verbose = 0;
65 : #endif
66 :
67 : /*
68 : * Initialize SD I/O card functions (before memory cards). The host
69 : * system and controller must support card interrupts in order to use
70 : * I/O functions.
71 : */
72 : int
73 0 : sdmmc_io_enable(struct sdmmc_softc *sc)
74 : {
75 : u_int32_t host_ocr;
76 0 : u_int32_t card_ocr;
77 :
78 0 : rw_assert_wrlock(&sc->sc_lock);
79 :
80 : /* Set host mode to SD "combo" card. */
81 0 : SET(sc->sc_flags, SMF_SD_MODE|SMF_IO_MODE|SMF_MEM_MODE);
82 :
83 : /* Reset I/O functions. */
84 0 : sdmmc_io_reset(sc);
85 :
86 : /*
87 : * Read the I/O OCR value, determine the number of I/O
88 : * functions and whether memory is also present (a "combo
89 : * card") by issuing CMD5. SD memory-only and MMC cards
90 : * do not respond to CMD5.
91 : */
92 0 : if (sdmmc_io_send_op_cond(sc, 0, &card_ocr) != 0) {
93 : /* No SDIO card; switch to SD memory-only mode. */
94 0 : CLR(sc->sc_flags, SMF_IO_MODE);
95 0 : return 0;
96 : }
97 :
98 : /* Parse the additional bits in the I/O OCR value. */
99 0 : if (!ISSET(card_ocr, SD_IO_OCR_MEM_PRESENT)) {
100 : /* SDIO card without memory (not a "combo card"). */
101 : DPRINTF(("%s: no memory present\n", DEVNAME(sc)));
102 0 : CLR(sc->sc_flags, SMF_MEM_MODE);
103 0 : }
104 0 : sc->sc_function_count = SD_IO_OCR_NUM_FUNCTIONS(card_ocr);
105 0 : if (sc->sc_function_count == 0) {
106 : /* Useless SDIO card without any I/O functions. */
107 : DPRINTF(("%s: no I/O functions\n", DEVNAME(sc)));
108 0 : CLR(sc->sc_flags, SMF_IO_MODE);
109 0 : return 0;
110 : }
111 0 : card_ocr &= SD_IO_OCR_MASK;
112 :
113 : /* Set the lowest voltage supported by the card and host. */
114 0 : host_ocr = sdmmc_chip_host_ocr(sc->sct, sc->sch);
115 0 : if (sdmmc_set_bus_power(sc, host_ocr, card_ocr) != 0) {
116 0 : printf("%s: can't supply voltage requested by card\n",
117 0 : DEVNAME(sc));
118 0 : return 1;
119 : }
120 :
121 : /* Send the new OCR value until all cards are ready. */
122 0 : if (sdmmc_io_send_op_cond(sc, host_ocr, NULL) != 0) {
123 0 : printf("%s: can't send I/O OCR\n", DEVNAME(sc));
124 0 : return 1;
125 : }
126 0 : return 0;
127 0 : }
128 :
129 : /*
130 : * Allocate sdmmc_function structures for SD card I/O function
131 : * (including function 0).
132 : */
133 : void
134 0 : sdmmc_io_scan(struct sdmmc_softc *sc)
135 : {
136 : struct sdmmc_function *sf0, *sf;
137 : int i;
138 :
139 0 : rw_assert_wrlock(&sc->sc_lock);
140 :
141 0 : sf0 = sdmmc_function_alloc(sc);
142 0 : sf0->number = 0;
143 0 : if (sdmmc_set_relative_addr(sc, sf0) != 0) {
144 0 : printf("%s: can't set I/O RCA\n", DEVNAME(sc));
145 0 : sdmmc_function_free(sf0);
146 0 : return;
147 : }
148 0 : sc->sc_fn0 = sf0;
149 0 : SIMPLEQ_INSERT_TAIL(&sc->sf_head, sf0, sf_list);
150 :
151 : /* Verify that the RCA has been set by selecting the card. */
152 0 : if (sdmmc_select_card(sc, sf0) != 0) {
153 0 : printf("%s: can't select I/O RCA %d\n", DEVNAME(sc),
154 0 : sf0->rca);
155 0 : SET(sf0->flags, SFF_ERROR);
156 0 : return;
157 : }
158 :
159 0 : for (i = 1; i <= sc->sc_function_count; i++) {
160 0 : sf = sdmmc_function_alloc(sc);
161 0 : sf->number = i;
162 0 : sf->rca = sf0->rca;
163 0 : sf->cookie = sc->sc_cookies[i];
164 :
165 0 : SIMPLEQ_INSERT_TAIL(&sc->sf_head, sf, sf_list);
166 : }
167 0 : }
168 :
169 : /*
170 : * Initialize SDIO card functions.
171 : */
172 : int
173 0 : sdmmc_io_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
174 : {
175 0 : rw_assert_wrlock(&sc->sc_lock);
176 :
177 0 : if (sdmmc_read_cis(sf, &sf->cis) != 0) {
178 0 : printf("%s: can't read CIS\n", DEVNAME(sc));
179 0 : SET(sf->flags, SFF_ERROR);
180 0 : return 1;
181 : }
182 :
183 0 : sdmmc_check_cis_quirks(sf);
184 :
185 0 : if (sdmmc_verbose)
186 0 : sdmmc_print_cis(sf);
187 :
188 0 : if (sf->number == 0) {
189 0 : if (ISSET(sc->sc_caps, SMC_CAPS_SD_HIGHSPEED) &&
190 0 : sdmmc_io_set_highspeed(sf, 1) == 0) {
191 0 : (void)sdmmc_chip_bus_clock(sc->sct, sc->sch,
192 : SDMMC_SDCLK_50MHZ, SDMMC_TIMING_HIGHSPEED);
193 0 : if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE)) {
194 0 : sdmmc_io_set_bus_width(sf, 4);
195 0 : sdmmc_chip_bus_width(sc->sct, sc->sch, 4);
196 0 : }
197 : } else
198 0 : (void)sdmmc_chip_bus_clock(sc->sct, sc->sch,
199 : SDMMC_SDCLK_25MHZ, SDMMC_TIMING_LEGACY);
200 : }
201 :
202 0 : return 0;
203 0 : }
204 :
205 : /*
206 : * Indicate whether the function is ready to operate.
207 : */
208 : int
209 0 : sdmmc_io_function_ready(struct sdmmc_function *sf)
210 : {
211 0 : struct sdmmc_softc *sc = sf->sc;
212 0 : struct sdmmc_function *sf0 = sc->sc_fn0;
213 : u_int8_t rv;
214 :
215 0 : rw_assert_wrlock(&sc->sc_lock);
216 :
217 0 : if (sf->number == 0)
218 0 : return 1; /* FN0 is always ready */
219 :
220 0 : rv = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_READY);
221 :
222 0 : return (rv & (1 << sf->number)) != 0;
223 0 : }
224 :
225 : /*
226 : * Enable the I/O function. Return zero if the function was
227 : * enabled successfully.
228 : */
229 : int
230 0 : sdmmc_io_function_enable(struct sdmmc_function *sf)
231 : {
232 0 : struct sdmmc_softc *sc = sf->sc;
233 0 : struct sdmmc_function *sf0 = sc->sc_fn0;
234 : u_int8_t rv;
235 : int retry = 5;
236 :
237 0 : rw_assert_wrlock(&sc->sc_lock);
238 :
239 0 : if (sf->number == 0)
240 0 : return 0; /* FN0 is always enabled */
241 :
242 0 : rv = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_ENABLE);
243 0 : rv |= (1<<sf->number);
244 0 : sdmmc_io_write_1(sf0, SD_IO_CCCR_FN_ENABLE, rv);
245 :
246 0 : while (!sdmmc_io_function_ready(sf) && retry-- > 0)
247 0 : tsleep(&lbolt, PPAUSE, "pause", 0);
248 0 : return (retry >= 0) ? 0 : ETIMEDOUT;
249 0 : }
250 :
251 : /*
252 : * Disable the I/O function. Return zero if the function was
253 : * disabled successfully.
254 : */
255 : void
256 0 : sdmmc_io_function_disable(struct sdmmc_function *sf)
257 : {
258 0 : struct sdmmc_softc *sc = sf->sc;
259 0 : struct sdmmc_function *sf0 = sc->sc_fn0;
260 : u_int8_t rv;
261 :
262 0 : rw_assert_wrlock(&sc->sc_lock);
263 :
264 0 : if (sf->number == 0)
265 0 : return; /* FN0 is always enabled */
266 :
267 0 : rv = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_ENABLE);
268 0 : rv &= ~(1<<sf->number);
269 0 : sdmmc_io_write_1(sf0, SD_IO_CCCR_FN_ENABLE, rv);
270 0 : }
271 :
272 : void
273 0 : sdmmc_io_attach(struct sdmmc_softc *sc)
274 : {
275 : struct sdmmc_function *sf;
276 0 : struct sdmmc_attach_args saa;
277 :
278 0 : rw_assert_wrlock(&sc->sc_lock);
279 :
280 0 : SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
281 0 : if (sf->number < 1)
282 : continue;
283 :
284 0 : bzero(&saa, sizeof saa);
285 0 : saa.sf = sf;
286 :
287 0 : sf->child = config_found_sm(&sc->sc_dev, &saa, sdmmc_print,
288 : sdmmc_submatch);
289 0 : }
290 0 : }
291 :
292 : int
293 0 : sdmmc_submatch(struct device *parent, void *match, void *aux)
294 : {
295 0 : struct cfdata *cf = match;
296 :
297 : /* Skip the scsibus, it is configured directly. */
298 0 : if (strcmp(cf->cf_driver->cd_name, "scsibus") == 0)
299 0 : return 0;
300 :
301 0 : return cf->cf_attach->ca_match(parent, cf, aux);
302 0 : }
303 :
304 : int
305 0 : sdmmc_print(void *aux, const char *pnp)
306 : {
307 0 : struct sdmmc_attach_args *sa = aux;
308 0 : struct sdmmc_function *sf = sa->sf;
309 0 : struct sdmmc_cis *cis = &sf->sc->sc_fn0->cis;
310 : int i;
311 :
312 0 : if (pnp) {
313 0 : if (sf->number == 0)
314 0 : return QUIET;
315 :
316 0 : for (i = 0; i < 4 && cis->cis1_info[i]; i++)
317 0 : printf("%s%s", i ? ", " : "\"", cis->cis1_info[i]);
318 0 : if (i != 0)
319 0 : printf("\"");
320 :
321 0 : if (cis->manufacturer != SDMMC_VENDOR_INVALID ||
322 0 : cis->product != SDMMC_PRODUCT_INVALID) {
323 0 : printf("%s", i ? " " : "");
324 0 : if (cis->manufacturer != SDMMC_VENDOR_INVALID)
325 0 : printf("manufacturer 0x%04x%s",
326 : cis->manufacturer,
327 0 : cis->product == SDMMC_PRODUCT_INVALID ?
328 : "" : ", ");
329 0 : if (cis->product != SDMMC_PRODUCT_INVALID)
330 0 : printf("product 0x%04x", cis->product);
331 : }
332 0 : printf(" at %s", pnp);
333 0 : }
334 0 : printf(" function %d", sf->number);
335 :
336 0 : if (!pnp) {
337 0 : for (i = 0; i < 3 && cis->cis1_info[i]; i++)
338 0 : printf("%s%s", i ? ", " : " \"", cis->cis1_info[i]);
339 0 : if (i != 0)
340 0 : printf("\"");
341 : }
342 0 : return UNCONF;
343 0 : }
344 :
345 : void
346 0 : sdmmc_io_detach(struct sdmmc_softc *sc)
347 : {
348 : struct sdmmc_function *sf;
349 :
350 0 : rw_assert_wrlock(&sc->sc_lock);
351 :
352 0 : SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
353 0 : if (sf->child != NULL) {
354 0 : config_detach(sf->child, DETACH_FORCE);
355 0 : sf->child = NULL;
356 0 : }
357 : }
358 :
359 0 : KASSERT(TAILQ_EMPTY(&sc->sc_intrq));
360 0 : }
361 :
362 : int
363 0 : sdmmc_io_rw_direct(struct sdmmc_softc *sc, struct sdmmc_function *sf,
364 : int reg, u_char *datap, int arg)
365 : {
366 0 : struct sdmmc_command cmd;
367 : int error;
368 :
369 0 : rw_assert_wrlock(&sc->sc_lock);
370 :
371 : /* Make sure the card is selected. */
372 0 : if ((error = sdmmc_select_card(sc, sf)) != 0) {
373 0 : rw_exit(&sc->sc_lock);
374 0 : return error;
375 : }
376 :
377 0 : arg |= ((sf == NULL ? 0 : sf->number) & SD_ARG_CMD52_FUNC_MASK) <<
378 : SD_ARG_CMD52_FUNC_SHIFT;
379 0 : arg |= (reg & SD_ARG_CMD52_REG_MASK) <<
380 : SD_ARG_CMD52_REG_SHIFT;
381 0 : arg |= (*datap & SD_ARG_CMD52_DATA_MASK) <<
382 : SD_ARG_CMD52_DATA_SHIFT;
383 :
384 0 : bzero(&cmd, sizeof cmd);
385 0 : cmd.c_opcode = SD_IO_RW_DIRECT;
386 0 : cmd.c_arg = arg;
387 0 : cmd.c_flags = SCF_CMD_AC | SCF_RSP_R5;
388 :
389 0 : error = sdmmc_mmc_command(sc, &cmd);
390 0 : *datap = SD_R5_DATA(cmd.c_resp);
391 :
392 0 : return error;
393 0 : }
394 :
395 : /*
396 : * Useful values of `arg' to pass in are either SD_ARG_CMD53_READ or
397 : * SD_ARG_CMD53_WRITE. SD_ARG_CMD53_INCREMENT may be ORed into `arg'
398 : * to access successive register locations instead of accessing the
399 : * same register many times. SD_ARG_CMD53_BLOCK_MODE may be ORed
400 : * into `arg' to indicate that the length is a number of blocks.
401 : */
402 : int
403 0 : sdmmc_io_rw_extended_subr(struct sdmmc_softc *sc, struct sdmmc_function *sf,
404 : bus_dmamap_t dmap, int reg, u_char *datap, int len, int arg)
405 : {
406 0 : struct sdmmc_command cmd;
407 : int error;
408 :
409 0 : rw_assert_wrlock(&sc->sc_lock);
410 :
411 : #if 0
412 : /* Make sure the card is selected. */
413 : if ((error = sdmmc_select_card(sc, sf)) != 0) {
414 : rw_exit(&sc->sc_lock);
415 : return error;
416 : }
417 : #endif
418 :
419 0 : arg |= ((sf == NULL ? 0 : sf->number) & SD_ARG_CMD53_FUNC_MASK) <<
420 : SD_ARG_CMD53_FUNC_SHIFT;
421 0 : arg |= (reg & SD_ARG_CMD53_REG_MASK) <<
422 : SD_ARG_CMD53_REG_SHIFT;
423 0 : arg |= (len & SD_ARG_CMD53_LENGTH_MASK) <<
424 : SD_ARG_CMD53_LENGTH_SHIFT;
425 :
426 0 : bzero(&cmd, sizeof cmd);
427 0 : cmd.c_opcode = SD_IO_RW_EXTENDED;
428 0 : cmd.c_arg = arg;
429 0 : cmd.c_flags = SCF_CMD_AC | SCF_RSP_R5;
430 0 : cmd.c_dmamap = dmap;
431 0 : cmd.c_data = datap;
432 0 : if (ISSET(arg, SD_ARG_CMD53_BLOCK_MODE)) {
433 0 : cmd.c_datalen = len * sf->cur_blklen;
434 0 : cmd.c_blklen = sf->cur_blklen;
435 0 : } else {
436 0 : cmd.c_datalen = len;
437 0 : cmd.c_blklen = MIN(len, sf->cur_blklen);
438 : }
439 :
440 0 : if (!ISSET(arg, SD_ARG_CMD53_WRITE))
441 0 : cmd.c_flags |= SCF_CMD_READ;
442 :
443 0 : error = sdmmc_mmc_command(sc, &cmd);
444 :
445 0 : return error;
446 0 : }
447 :
448 : int
449 0 : sdmmc_io_rw_extended(struct sdmmc_softc *sc, struct sdmmc_function *sf,
450 : int reg, u_char *datap, int len, int arg)
451 : {
452 : int datalen = len, error, read = 0;
453 :
454 0 : if (!ISSET(sc->sc_caps, SMC_CAPS_DMA))
455 0 : return sdmmc_io_rw_extended_subr(sc, sf, NULL, reg,
456 : datap, len, arg);
457 :
458 0 : if (ISSET(arg, SD_ARG_CMD53_BLOCK_MODE))
459 0 : datalen = len * sf->cur_blklen;
460 :
461 0 : if (!ISSET(arg, SD_ARG_CMD53_WRITE))
462 0 : read = 1;
463 :
464 0 : error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmap, datap, datalen,
465 : NULL, BUS_DMA_NOWAIT | (read ? BUS_DMA_READ : BUS_DMA_WRITE));
466 0 : if (error)
467 : goto out;
468 :
469 0 : bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, datalen,
470 : read ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
471 :
472 0 : error = sdmmc_io_rw_extended_subr(sc, sf, sc->sc_dmap, reg,
473 : datap, len, arg);
474 0 : if (error)
475 : goto unload;
476 :
477 0 : bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, datalen,
478 : read ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
479 :
480 : unload:
481 0 : bus_dmamap_unload(sc->sc_dmat, sc->sc_dmap);
482 :
483 : out:
484 0 : return error;
485 0 : }
486 :
487 : u_int8_t
488 0 : sdmmc_io_read_1(struct sdmmc_function *sf, int reg)
489 : {
490 0 : u_int8_t data = 0;
491 :
492 0 : rw_assert_wrlock(&sf->sc->sc_lock);
493 :
494 0 : (void)sdmmc_io_rw_direct(sf->sc, sf, reg, (u_char *)&data,
495 : SD_ARG_CMD52_READ);
496 0 : return data;
497 0 : }
498 :
499 : void
500 0 : sdmmc_io_write_1(struct sdmmc_function *sf, int reg, u_int8_t data)
501 : {
502 0 : rw_assert_wrlock(&sf->sc->sc_lock);
503 :
504 0 : (void)sdmmc_io_rw_direct(sf->sc, sf, reg, (u_char *)&data,
505 : SD_ARG_CMD52_WRITE);
506 0 : }
507 :
508 : u_int16_t
509 0 : sdmmc_io_read_2(struct sdmmc_function *sf, int reg)
510 : {
511 0 : u_int16_t data = 0;
512 :
513 0 : rw_assert_wrlock(&sf->sc->sc_lock);
514 :
515 0 : (void)sdmmc_io_rw_extended_subr(sf->sc, sf, NULL, reg,
516 : (u_char *)&data, 2, SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT);
517 0 : return data;
518 0 : }
519 :
520 : void
521 0 : sdmmc_io_write_2(struct sdmmc_function *sf, int reg, u_int16_t data)
522 : {
523 0 : rw_assert_wrlock(&sf->sc->sc_lock);
524 :
525 0 : (void)sdmmc_io_rw_extended_subr(sf->sc, sf, NULL, reg,
526 0 : (u_char *)&data, 2, SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT);
527 0 : }
528 :
529 : u_int32_t
530 0 : sdmmc_io_read_4(struct sdmmc_function *sf, int reg)
531 : {
532 0 : u_int32_t data = 0;
533 :
534 0 : rw_assert_wrlock(&sf->sc->sc_lock);
535 :
536 0 : (void)sdmmc_io_rw_extended_subr(sf->sc, sf, NULL, reg,
537 : (u_char *)&data, 4, SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT);
538 0 : return data;
539 0 : }
540 :
541 : void
542 0 : sdmmc_io_write_4(struct sdmmc_function *sf, int reg, u_int32_t data)
543 : {
544 0 : rw_assert_wrlock(&sf->sc->sc_lock);
545 :
546 0 : (void)sdmmc_io_rw_extended_subr(sf->sc, sf, NULL, reg,
547 0 : (u_char *)&data, 4, SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT);
548 0 : }
549 :
550 : int
551 0 : sdmmc_io_read_multi_1(struct sdmmc_function *sf, int reg, u_char *data,
552 : int datalen)
553 : {
554 : int blocks, error = 0;
555 :
556 0 : rw_assert_wrlock(&sf->sc->sc_lock);
557 :
558 0 : while (datalen >= sf->cur_blklen) {
559 0 : blocks = MIN(datalen / sf->cur_blklen,
560 : SD_ARG_CMD53_LENGTH_MAX);
561 0 : error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
562 : blocks, SD_ARG_CMD53_READ | SD_ARG_CMD53_BLOCK_MODE);
563 0 : if (error)
564 0 : return error;
565 0 : data += blocks * sf->cur_blklen;
566 0 : datalen -= blocks * sf->cur_blklen;
567 : }
568 :
569 0 : if (datalen)
570 0 : error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
571 : SD_ARG_CMD53_READ);
572 :
573 0 : return error;
574 0 : }
575 :
576 : int
577 0 : sdmmc_io_write_multi_1(struct sdmmc_function *sf, int reg, u_char *data,
578 : int datalen)
579 : {
580 : int blocks, error = 0;
581 :
582 0 : rw_assert_wrlock(&sf->sc->sc_lock);
583 :
584 0 : while (datalen >= sf->cur_blklen) {
585 0 : blocks = MIN(datalen / sf->cur_blklen,
586 : SD_ARG_CMD53_LENGTH_MAX);
587 0 : error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
588 : blocks, SD_ARG_CMD53_WRITE | SD_ARG_CMD53_BLOCK_MODE);
589 0 : if (error)
590 0 : return error;
591 0 : data += blocks * sf->cur_blklen;
592 0 : datalen -= blocks * sf->cur_blklen;
593 : }
594 :
595 0 : if (datalen)
596 0 : error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
597 : SD_ARG_CMD53_WRITE);
598 :
599 0 : return error;
600 0 : }
601 :
602 : int
603 0 : sdmmc_io_read_region_1(struct sdmmc_function *sf, int reg, u_char *data,
604 : int datalen)
605 : {
606 : int blocks, error = 0;
607 :
608 0 : rw_assert_wrlock(&sf->sc->sc_lock);
609 :
610 0 : while (datalen >= sf->cur_blklen) {
611 0 : blocks = MIN(datalen / sf->cur_blklen,
612 : SD_ARG_CMD53_LENGTH_MAX);
613 0 : error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
614 : blocks, SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT |
615 : SD_ARG_CMD53_BLOCK_MODE);
616 0 : if (error)
617 0 : return error;
618 0 : reg += blocks * sf->cur_blklen;
619 0 : data += blocks * sf->cur_blklen;
620 0 : datalen -= blocks * sf->cur_blklen;
621 : }
622 :
623 0 : if (datalen)
624 0 : error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
625 : SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT);
626 :
627 0 : return error;
628 0 : }
629 :
630 : int
631 0 : sdmmc_io_write_region_1(struct sdmmc_function *sf, int reg, u_char *data,
632 : int datalen)
633 : {
634 : int blocks, error = 0;
635 :
636 0 : rw_assert_wrlock(&sf->sc->sc_lock);
637 :
638 0 : while (datalen >= sf->cur_blklen) {
639 0 : blocks = MIN(datalen / sf->cur_blklen,
640 : SD_ARG_CMD53_LENGTH_MAX);
641 0 : error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
642 : blocks, SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT |
643 : SD_ARG_CMD53_BLOCK_MODE);
644 0 : if (error)
645 0 : return error;
646 0 : reg += blocks * sf->cur_blklen;
647 0 : data += blocks * sf->cur_blklen;
648 0 : datalen -= blocks * sf->cur_blklen;
649 : }
650 :
651 0 : if (datalen)
652 0 : error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
653 : SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT);
654 :
655 0 : return error;
656 0 : }
657 :
658 : int
659 0 : sdmmc_io_xchg(struct sdmmc_softc *sc, struct sdmmc_function *sf,
660 : int reg, u_char *datap)
661 : {
662 :
663 0 : rw_assert_wrlock(&sc->sc_lock);
664 :
665 0 : return sdmmc_io_rw_direct(sc, sf, reg, datap,
666 : SD_ARG_CMD52_WRITE|SD_ARG_CMD52_EXCHANGE);
667 : }
668 :
669 : /*
670 : * Reset the I/O functions of the card.
671 : */
672 : void
673 0 : sdmmc_io_reset(struct sdmmc_softc *sc)
674 : {
675 0 : u_int8_t data = CCCR_CTL_RES;
676 :
677 0 : rw_assert_wrlock(&sc->sc_lock);
678 :
679 0 : if (sdmmc_io_rw_direct(sc, NULL, SD_IO_CCCR_CTL, (u_char *)&data,
680 0 : SD_ARG_CMD52_WRITE) == 0)
681 0 : sdmmc_delay(100000);
682 0 : }
683 :
684 : /*
685 : * Get or set the card's I/O OCR value (SDIO).
686 : */
687 : int
688 0 : sdmmc_io_send_op_cond(struct sdmmc_softc *sc, u_int32_t ocr, u_int32_t *ocrp)
689 : {
690 0 : struct sdmmc_command cmd;
691 : int error;
692 : int i;
693 :
694 0 : rw_assert_wrlock(&sc->sc_lock);
695 :
696 : /*
697 : * If we change the OCR value, retry the command until the OCR
698 : * we receive in response has the "CARD BUSY" bit set, meaning
699 : * that all cards are ready for identification.
700 : */
701 0 : for (i = 0; i < 100; i++) {
702 0 : bzero(&cmd, sizeof cmd);
703 0 : cmd.c_opcode = SD_IO_SEND_OP_COND;
704 0 : cmd.c_arg = ocr;
705 0 : cmd.c_flags = SCF_CMD_BCR | SCF_RSP_R4;
706 :
707 0 : error = sdmmc_mmc_command(sc, &cmd);
708 0 : if (error != 0)
709 : break;
710 0 : if (ISSET(MMC_R4(cmd.c_resp), SD_IO_OCR_MEM_READY) ||
711 0 : ocr == 0)
712 : break;
713 : error = ETIMEDOUT;
714 0 : sdmmc_delay(10000);
715 : }
716 0 : if (error == 0 && ocrp != NULL)
717 0 : *ocrp = MMC_R4(cmd.c_resp);
718 :
719 0 : return error;
720 0 : }
721 :
722 : /*
723 : * Card interrupt handling
724 : */
725 :
726 : void
727 0 : sdmmc_intr_enable(struct sdmmc_function *sf)
728 : {
729 0 : struct sdmmc_softc *sc = sf->sc;
730 0 : struct sdmmc_function *sf0 = sc->sc_fn0;
731 : u_int8_t imask;
732 :
733 0 : rw_assert_wrlock(&sc->sc_lock);
734 :
735 0 : imask = sdmmc_io_read_1(sf0, SD_IO_CCCR_INT_ENABLE);
736 0 : imask |= 1 << sf->number;
737 0 : sdmmc_io_write_1(sf0, SD_IO_CCCR_INT_ENABLE, imask);
738 0 : }
739 :
740 : void
741 0 : sdmmc_intr_disable(struct sdmmc_function *sf)
742 : {
743 0 : struct sdmmc_softc *sc = sf->sc;
744 0 : struct sdmmc_function *sf0 = sc->sc_fn0;
745 : u_int8_t imask;
746 :
747 0 : rw_assert_wrlock(&sc->sc_lock);
748 :
749 0 : imask = sdmmc_io_read_1(sf0, SD_IO_CCCR_INT_ENABLE);
750 0 : imask &= ~(1 << sf->number);
751 0 : sdmmc_io_write_1(sf0, SD_IO_CCCR_INT_ENABLE, imask);
752 0 : }
753 :
754 : /*
755 : * Establish a handler for the SDIO card interrupt. Because the
756 : * interrupt may be shared with different SDIO functions, multiple
757 : * handlers can be established.
758 : */
759 : void *
760 0 : sdmmc_intr_establish(struct device *sdmmc, int (*fun)(void *),
761 : void *arg, const char *name)
762 : {
763 0 : struct sdmmc_softc *sc = (struct sdmmc_softc *)sdmmc;
764 : struct sdmmc_intr_handler *ih;
765 : int s;
766 :
767 0 : if (sc->sct->card_intr_mask == NULL)
768 0 : return NULL;
769 :
770 0 : ih = malloc(sizeof *ih, M_DEVBUF, M_WAITOK | M_CANFAIL | M_ZERO);
771 0 : if (ih == NULL)
772 0 : return NULL;
773 :
774 0 : ih->ih_name = name;
775 0 : ih->ih_softc = sc;
776 0 : ih->ih_fun = fun;
777 0 : ih->ih_arg = arg;
778 :
779 0 : s = splhigh();
780 0 : if (TAILQ_EMPTY(&sc->sc_intrq)) {
781 0 : sdmmc_intr_enable(sc->sc_fn0);
782 0 : sdmmc_chip_card_intr_mask(sc->sct, sc->sch, 1);
783 0 : }
784 0 : TAILQ_INSERT_TAIL(&sc->sc_intrq, ih, entry);
785 0 : splx(s);
786 0 : return ih;
787 0 : }
788 :
789 : /*
790 : * Disestablish the given handler.
791 : */
792 : void
793 0 : sdmmc_intr_disestablish(void *cookie)
794 : {
795 0 : struct sdmmc_intr_handler *ih = cookie;
796 0 : struct sdmmc_softc *sc = ih->ih_softc;
797 : int s;
798 :
799 0 : if (sc->sct->card_intr_mask == NULL)
800 0 : return;
801 :
802 0 : s = splhigh();
803 0 : TAILQ_REMOVE(&sc->sc_intrq, ih, entry);
804 0 : if (TAILQ_EMPTY(&sc->sc_intrq)) {
805 0 : sdmmc_chip_card_intr_mask(sc->sct, sc->sch, 0);
806 0 : sdmmc_intr_disable(sc->sc_fn0);
807 0 : }
808 0 : splx(s);
809 :
810 0 : free(ih, M_DEVBUF, sizeof *ih);
811 0 : }
812 :
813 : /*
814 : * Call established SDIO card interrupt handlers. The host controller
815 : * must call this function from its own interrupt handler to handle an
816 : * SDIO interrupt from the card.
817 : */
818 : void
819 0 : sdmmc_card_intr(struct device *sdmmc)
820 : {
821 0 : struct sdmmc_softc *sc = (struct sdmmc_softc *)sdmmc;
822 :
823 0 : if (sc->sct->card_intr_mask == NULL)
824 0 : return;
825 :
826 0 : if (!sdmmc_task_pending(&sc->sc_intr_task))
827 0 : sdmmc_add_task(sc, &sc->sc_intr_task);
828 0 : }
829 :
830 : void
831 0 : sdmmc_intr_task(void *arg)
832 : {
833 0 : struct sdmmc_softc *sc = arg;
834 : struct sdmmc_intr_handler *ih;
835 : int s;
836 :
837 0 : s = splhigh();
838 0 : TAILQ_FOREACH(ih, &sc->sc_intrq, entry) {
839 0 : splx(s);
840 :
841 : /* XXX examine return value and do evcount stuff*/
842 0 : (void)ih->ih_fun(ih->ih_arg);
843 :
844 0 : s = splhigh();
845 : }
846 0 : sdmmc_chip_card_intr_ack(sc->sct, sc->sch);
847 0 : splx(s);
848 0 : }
849 :
850 : void
851 0 : sdmmc_io_set_blocklen(struct sdmmc_function *sf, unsigned int blklen)
852 : {
853 0 : struct sdmmc_softc *sc = sf->sc;
854 0 : struct sdmmc_function *sf0 = sc->sc_fn0;
855 :
856 0 : rw_assert_wrlock(&sc->sc_lock);
857 :
858 0 : if (blklen > sdmmc_chip_host_maxblklen(sc->sct, sc->sch))
859 0 : return;
860 :
861 0 : if (blklen == 0) {
862 0 : blklen = min(512, sdmmc_chip_host_maxblklen(sc->sct, sc->sch));
863 0 : }
864 :
865 0 : sdmmc_io_write_1(sf0, SD_IO_FBR_BASE(sf->number) +
866 0 : SD_IO_FBR_BLOCKLEN, blklen & 0xff);
867 0 : sdmmc_io_write_1(sf0, SD_IO_FBR_BASE(sf->number) +
868 0 : SD_IO_FBR_BLOCKLEN+ 1, (blklen >> 8) & 0xff);
869 0 : sf->cur_blklen = blklen;
870 0 : }
871 :
872 : void
873 0 : sdmmc_io_set_bus_width(struct sdmmc_function *sf, int width)
874 : {
875 : u_int8_t rv;
876 :
877 0 : rw_assert_wrlock(&sf->sc->sc_lock);
878 0 : rv = sdmmc_io_read_1(sf, SD_IO_CCCR_BUS_WIDTH);
879 0 : rv &= ~CCCR_BUS_WIDTH_MASK;
880 0 : if (width == 4)
881 0 : rv |= CCCR_BUS_WIDTH_4;
882 : else
883 : rv |= CCCR_BUS_WIDTH_1;
884 0 : sdmmc_io_write_1(sf, SD_IO_CCCR_BUS_WIDTH, rv);
885 0 : }
886 :
887 : int
888 0 : sdmmc_io_set_highspeed(struct sdmmc_function *sf, int enable)
889 : {
890 : u_int8_t rv;
891 :
892 0 : rw_assert_wrlock(&sf->sc->sc_lock);
893 :
894 0 : rv = sdmmc_io_read_1(sf, SD_IO_CCCR_SPEED);
895 0 : if (enable && !(rv & CCCR_SPEED_SHS))
896 0 : return 1;
897 0 : rv &= ~CCCR_SPEED_MASK;
898 0 : if (enable)
899 0 : rv |= CCCR_SPEED_EHS;
900 0 : sdmmc_io_write_1(sf, SD_IO_CCCR_SPEED, rv);
901 0 : return 0;
902 0 : }
|