This source file includes following definitions.
- sdmmc_match
- sdmmc_attach
- sdmmc_detach
- sdmmc_create_thread
- sdmmc_task_thread
- sdmmc_add_task
- sdmmc_del_task
- sdmmc_needs_discover
- sdmmc_discover_task
- sdmmc_card_attach
- sdmmc_card_detach
- sdmmc_enable
- sdmmc_disable
- sdmmc_set_bus_power
- sdmmc_function_alloc
- sdmmc_function_free
- sdmmc_scan
- sdmmc_init
- sdmmc_delay
- sdmmc_app_command
- sdmmc_mmc_command
- sdmmc_go_idle_state
- sdmmc_set_relative_addr
- sdmmc_set_bus_width
- sdmmc_select_card
- sdmmc_ioctl
- sdmmc_dump_command
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 #include <sys/param.h>
26 #include <sys/device.h>
27 #include <sys/kernel.h>
28 #include <sys/kthread.h>
29 #include <sys/malloc.h>
30 #include <sys/proc.h>
31 #include <sys/systm.h>
32
33 #include <scsi/scsi_all.h>
34 #include <scsi/scsiconf.h>
35
36 #include <dev/sdmmc/sdmmc_ioreg.h>
37 #include <dev/sdmmc/sdmmc_scsi.h>
38 #include <dev/sdmmc/sdmmcchip.h>
39 #include <dev/sdmmc/sdmmcreg.h>
40 #include <dev/sdmmc/sdmmcvar.h>
41
42 #ifdef SDMMC_IOCTL
43 #include "bio.h"
44 #if NBIO < 1
45 #undef SDMMC_IOCTL
46 #endif
47 #include <dev/biovar.h>
48 #endif
49
50 int sdmmc_match(struct device *, void *, void *);
51 void sdmmc_attach(struct device *, struct device *, void *);
52 int sdmmc_detach(struct device *, int);
53 void sdmmc_create_thread(void *);
54 void sdmmc_task_thread(void *);
55 void sdmmc_discover_task(void *);
56 void sdmmc_card_attach(struct sdmmc_softc *);
57 void sdmmc_card_detach(struct sdmmc_softc *, int);
58 int sdmmc_enable(struct sdmmc_softc *);
59 void sdmmc_disable(struct sdmmc_softc *);
60 int sdmmc_scan(struct sdmmc_softc *);
61 int sdmmc_init(struct sdmmc_softc *);
62 int sdmmc_set_bus_width(struct sdmmc_function *);
63 #ifdef SDMMC_IOCTL
64 int sdmmc_ioctl(struct device *, u_long, caddr_t);
65 #endif
66
67 #define DEVNAME(sc) SDMMCDEVNAME(sc)
68
69 #ifdef SDMMC_DEBUG
70 int sdmmcdebug = 0;
71 extern int sdhcdebug;
72 void sdmmc_dump_command(struct sdmmc_softc *, struct sdmmc_command *);
73 #define DPRINTF(n,s) do { if ((n) <= sdmmcdebug) printf s; } while (0)
74 #else
75 #define DPRINTF(n,s) do {} while (0)
76 #endif
77
78 struct cfattach sdmmc_ca = {
79 sizeof(struct sdmmc_softc), sdmmc_match, sdmmc_attach, sdmmc_detach
80 };
81
82 struct cfdriver sdmmc_cd = {
83 NULL, "sdmmc", DV_DULL
84 };
85
86 int
87 sdmmc_match(struct device *parent, void *match, void *aux)
88 {
89 struct cfdata *cf = match;
90 struct sdmmcbus_attach_args *saa = aux;
91
92 return strcmp(saa->saa_busname, cf->cf_driver->cd_name) == 0;
93 }
94
95 void
96 sdmmc_attach(struct device *parent, struct device *self, void *aux)
97 {
98 struct sdmmc_softc *sc = (struct sdmmc_softc *)self;
99 struct sdmmcbus_attach_args *saa = aux;
100
101 printf("\n");
102
103 sc->sct = saa->sct;
104 sc->sch = saa->sch;
105
106 SIMPLEQ_INIT(&sc->sf_head);
107 TAILQ_INIT(&sc->sc_tskq);
108 TAILQ_INIT(&sc->sc_intrq);
109 sdmmc_init_task(&sc->sc_discover_task, sdmmc_discover_task, sc);
110 sdmmc_init_task(&sc->sc_intr_task, sdmmc_intr_task, sc);
111 lockinit(&sc->sc_lock, PRIBIO, DEVNAME(sc), 0, LK_CANRECURSE);
112
113 #ifdef SDMMC_IOCTL
114 if (bio_register(self, sdmmc_ioctl) != 0)
115 printf("%s: unable to register ioctl\n", DEVNAME(sc));
116 #endif
117
118
119
120
121
122 #ifdef DO_CONFIG_PENDING
123 config_pending_incr();
124 #endif
125 kthread_create_deferred(sdmmc_create_thread, sc);
126 }
127
128 int
129 sdmmc_detach(struct device *self, int flags)
130 {
131 struct sdmmc_softc *sc = (struct sdmmc_softc *)self;
132
133 sc->sc_dying = 1;
134 while (sc->sc_task_thread != NULL) {
135 wakeup(&sc->sc_tskq);
136 tsleep(sc, PWAIT, "mmcdie", 0);
137 }
138 return 0;
139 }
140
141 void
142 sdmmc_create_thread(void *arg)
143 {
144 struct sdmmc_softc *sc = arg;
145
146 if (kthread_create(sdmmc_task_thread, sc, &sc->sc_task_thread,
147 "%s", DEVNAME(sc)) != 0)
148 printf("%s: can't create task thread\n", DEVNAME(sc));
149
150 #ifdef DO_CONFIG_PENDING
151 config_pending_decr();
152 #endif
153 }
154
155 void
156 sdmmc_task_thread(void *arg)
157 {
158 struct sdmmc_softc *sc = arg;
159 struct sdmmc_task *task;
160 int s;
161
162 sdmmc_needs_discover(&sc->sc_dev);
163
164 s = splsdmmc();
165 while (!sc->sc_dying) {
166 for (task = TAILQ_FIRST(&sc->sc_tskq); task != NULL;
167 task = TAILQ_FIRST(&sc->sc_tskq)) {
168 splx(s);
169 sdmmc_del_task(task);
170 task->func(task->arg);
171 s = splsdmmc();
172 }
173 tsleep(&sc->sc_tskq, PWAIT, "mmctsk", 0);
174 }
175 splx(s);
176
177 if (ISSET(sc->sc_flags, SMF_CARD_PRESENT))
178 sdmmc_card_detach(sc, DETACH_FORCE);
179
180 sc->sc_task_thread = NULL;
181 wakeup(sc);
182 kthread_exit(0);
183 }
184
185 void
186 sdmmc_add_task(struct sdmmc_softc *sc, struct sdmmc_task *task)
187 {
188 int s;
189
190 s = splsdmmc();
191 TAILQ_INSERT_TAIL(&sc->sc_tskq, task, next);
192 task->onqueue = 1;
193 task->sc = sc;
194 wakeup(&sc->sc_tskq);
195 splx(s);
196 }
197
198 void
199 sdmmc_del_task(struct sdmmc_task *task)
200 {
201 struct sdmmc_softc *sc = task->sc;
202 int s;
203
204 if (sc == NULL)
205 return;
206
207 s = splsdmmc();
208 task->sc = NULL;
209 task->onqueue = 0;
210 TAILQ_REMOVE(&sc->sc_tskq, task, next);
211 splx(s);
212 }
213
214 void
215 sdmmc_needs_discover(struct device *self)
216 {
217 struct sdmmc_softc *sc = (struct sdmmc_softc *)self;
218
219 if (!sdmmc_task_pending(&sc->sc_discover_task))
220 sdmmc_add_task(sc, &sc->sc_discover_task);
221 }
222
223 void
224 sdmmc_discover_task(void *arg)
225 {
226 struct sdmmc_softc *sc = arg;
227
228 if (sdmmc_chip_card_detect(sc->sct, sc->sch)) {
229 if (!ISSET(sc->sc_flags, SMF_CARD_PRESENT)) {
230 SET(sc->sc_flags, SMF_CARD_PRESENT);
231 sdmmc_card_attach(sc);
232 }
233 } else {
234 if (ISSET(sc->sc_flags, SMF_CARD_PRESENT)) {
235 CLR(sc->sc_flags, SMF_CARD_PRESENT);
236 sdmmc_card_detach(sc, DETACH_FORCE);
237 }
238 }
239 }
240
241
242
243
244 void
245 sdmmc_card_attach(struct sdmmc_softc *sc)
246 {
247 DPRINTF(1,("%s: attach card\n", DEVNAME(sc)));
248
249 SDMMC_LOCK(sc);
250 CLR(sc->sc_flags, SMF_CARD_ATTACHED);
251
252
253
254
255 if (sdmmc_enable(sc) != 0) {
256 printf("%s: can't enable card\n", DEVNAME(sc));
257 goto err;
258 }
259
260
261
262
263
264 if (sdmmc_scan(sc) != 0) {
265 printf("%s: no functions\n", DEVNAME(sc));
266 goto err;
267 }
268
269
270
271
272 if (sdmmc_init(sc) != 0) {
273 printf("%s: init failed\n", DEVNAME(sc));
274 goto err;
275 }
276
277
278 if (ISSET(sc->sc_flags, SMF_MEM_MODE))
279 sdmmc_scsi_attach(sc);
280
281
282 if (ISSET(sc->sc_flags, SMF_IO_MODE))
283 sdmmc_io_attach(sc);
284
285 SET(sc->sc_flags, SMF_CARD_ATTACHED);
286 SDMMC_UNLOCK(sc);
287 return;
288 err:
289 sdmmc_card_detach(sc, DETACH_FORCE);
290 SDMMC_UNLOCK(sc);
291 }
292
293
294
295
296
297 void
298 sdmmc_card_detach(struct sdmmc_softc *sc, int flags)
299 {
300 struct sdmmc_function *sf, *sfnext;
301
302 DPRINTF(1,("%s: detach card\n", DEVNAME(sc)));
303
304 if (ISSET(sc->sc_flags, SMF_CARD_ATTACHED)) {
305
306 if (ISSET(sc->sc_flags, SMF_IO_MODE))
307 sdmmc_io_detach(sc);
308
309
310 if (ISSET(sc->sc_flags, SMF_MEM_MODE))
311 sdmmc_scsi_detach(sc);
312
313 CLR(sc->sc_flags, SMF_CARD_ATTACHED);
314 }
315
316
317 sdmmc_disable(sc);
318
319
320 for (sf = SIMPLEQ_FIRST(&sc->sf_head); sf != NULL; sf = sfnext) {
321 sfnext = SIMPLEQ_NEXT(sf, sf_list);
322 sdmmc_function_free(sf);
323 }
324 SIMPLEQ_INIT(&sc->sf_head);
325 sc->sc_function_count = 0;
326 sc->sc_fn0 = NULL;
327 }
328
329 int
330 sdmmc_enable(struct sdmmc_softc *sc)
331 {
332 u_int32_t host_ocr;
333 int error;
334
335
336
337
338
339 host_ocr = sdmmc_chip_host_ocr(sc->sct, sc->sch);
340 error = sdmmc_chip_bus_power(sc->sct, sc->sch, host_ocr);
341 if (error != 0) {
342 printf("%s: can't supply bus power\n", DEVNAME(sc));
343 goto err;
344 }
345
346
347
348
349 error = sdmmc_chip_bus_clock(sc->sct, sc->sch, SDMMC_SDCLK_400KHZ);
350 if (error != 0) {
351 printf("%s: can't supply clock\n", DEVNAME(sc));
352 goto err;
353 }
354
355
356 sdmmc_delay(100000);
357
358
359 if ((error = sdmmc_io_enable(sc)) != 0)
360 goto err;
361
362
363 if (ISSET(sc->sc_flags, SMF_MEM_MODE) &&
364 (error = sdmmc_mem_enable(sc)) != 0)
365 goto err;
366
367
368 if (ISSET(sc->sc_flags, SMF_SD_MODE))
369 (void)sdmmc_chip_bus_clock(sc->sct, sc->sch,
370 SDMMC_SDCLK_25MHZ);
371
372 err:
373 if (error != 0)
374 sdmmc_disable(sc);
375 return error;
376 }
377
378 void
379 sdmmc_disable(struct sdmmc_softc *sc)
380 {
381
382
383
384 (void)sdmmc_select_card(sc, NULL);
385
386
387 (void)sdmmc_chip_bus_clock(sc->sct, sc->sch, SDMMC_SDCLK_OFF);
388 (void)sdmmc_chip_bus_power(sc->sct, sc->sch, 0);
389 }
390
391
392
393
394 int
395 sdmmc_set_bus_power(struct sdmmc_softc *sc, u_int32_t host_ocr,
396 u_int32_t card_ocr)
397 {
398 u_int32_t bit;
399
400
401 DPRINTF(1,("%s: host_ocr=%x ", DEVNAME(sc), host_ocr));
402 host_ocr &= card_ocr;
403 for (bit = 4; bit < 23; bit++) {
404 if (ISSET(host_ocr, 1<<bit)) {
405 host_ocr &= 3<<bit;
406 break;
407 }
408 }
409 DPRINTF(1,("card_ocr=%x new_ocr=%x\n", card_ocr, host_ocr));
410
411 if (host_ocr == 0 ||
412 sdmmc_chip_bus_power(sc->sct, sc->sch, host_ocr) != 0)
413 return 1;
414 return 0;
415 }
416
417 struct sdmmc_function *
418 sdmmc_function_alloc(struct sdmmc_softc *sc)
419 {
420 struct sdmmc_function *sf;
421
422 MALLOC(sf, struct sdmmc_function *, sizeof *sf, M_DEVBUF,
423 M_WAITOK);
424 bzero(sf, sizeof *sf);
425 sf->sc = sc;
426 sf->number = -1;
427 sf->cis.manufacturer = SDMMC_VENDOR_INVALID;
428 sf->cis.product = SDMMC_PRODUCT_INVALID;
429 sf->cis.function = SDMMC_FUNCTION_INVALID;
430 return sf;
431 }
432
433 void
434 sdmmc_function_free(struct sdmmc_function *sf)
435 {
436 FREE(sf, M_DEVBUF);
437 }
438
439
440
441
442
443 int
444 sdmmc_scan(struct sdmmc_softc *sc)
445 {
446
447 if (ISSET(sc->sc_flags, SMF_IO_MODE))
448 sdmmc_io_scan(sc);
449
450
451 if (ISSET(sc->sc_flags, SMF_MEM_MODE))
452 sdmmc_mem_scan(sc);
453
454
455 if (SIMPLEQ_EMPTY(&sc->sf_head)) {
456 printf("%s: can't identify card\n", DEVNAME(sc));
457 return 1;
458 }
459 return 0;
460 }
461
462
463
464
465
466 int
467 sdmmc_init(struct sdmmc_softc *sc)
468 {
469 struct sdmmc_function *sf;
470
471
472 SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
473 if (ISSET(sc->sc_flags, SMF_IO_MODE) &&
474 sdmmc_io_init(sc, sf) != 0)
475 printf("%s: i/o init failed\n", DEVNAME(sc));
476
477 if (ISSET(sc->sc_flags, SMF_MEM_MODE) &&
478 sdmmc_mem_init(sc, sf) != 0)
479 printf("%s: mem init failed\n", DEVNAME(sc));
480 }
481
482
483 SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
484 if (!ISSET(sf->flags, SFF_ERROR))
485 return 0;
486 }
487
488 return 1;
489 }
490
491 void
492 sdmmc_delay(u_int usecs)
493 {
494 int ticks = usecs / (1000000 / hz);
495
496 if (ticks > 0)
497 tsleep(&sdmmc_delay, PWAIT, "mmcdly", ticks);
498 else
499 delay(usecs);
500 }
501
502 int
503 sdmmc_app_command(struct sdmmc_softc *sc, struct sdmmc_command *cmd)
504 {
505 struct sdmmc_command acmd;
506 int error;
507
508 SDMMC_LOCK(sc);
509
510 bzero(&acmd, sizeof acmd);
511 acmd.c_opcode = MMC_APP_CMD;
512 acmd.c_arg = 0;
513 acmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
514
515 error = sdmmc_mmc_command(sc, &acmd);
516 if (error != 0) {
517 SDMMC_UNLOCK(sc);
518 return error;
519 }
520
521 if (!ISSET(MMC_R1(acmd.c_resp), MMC_R1_APP_CMD)) {
522
523 SDMMC_UNLOCK(sc);
524 return ENODEV;
525 }
526
527 error = sdmmc_mmc_command(sc, cmd);
528 SDMMC_UNLOCK(sc);
529 return error;
530 }
531
532
533
534
535
536
537 int
538 sdmmc_mmc_command(struct sdmmc_softc *sc, struct sdmmc_command *cmd)
539 {
540 int error;
541
542 SDMMC_LOCK(sc);
543
544 sdmmc_chip_exec_command(sc->sct, sc->sch, cmd);
545
546 #ifdef SDMMC_DEBUG
547 sdmmc_dump_command(sc, cmd);
548 #endif
549
550 error = cmd->c_error;
551 wakeup(cmd);
552
553 SDMMC_UNLOCK(sc);
554 return error;
555 }
556
557
558
559
560 void
561 sdmmc_go_idle_state(struct sdmmc_softc *sc)
562 {
563 struct sdmmc_command cmd;
564
565 bzero(&cmd, sizeof cmd);
566 cmd.c_opcode = MMC_GO_IDLE_STATE;
567 cmd.c_flags = SCF_CMD_BC | SCF_RSP_R0;
568
569 (void)sdmmc_mmc_command(sc, &cmd);
570 }
571
572
573
574
575 int
576 sdmmc_set_relative_addr(struct sdmmc_softc *sc,
577 struct sdmmc_function *sf)
578 {
579 struct sdmmc_command cmd;
580
581 bzero(&cmd, sizeof cmd);
582
583 if (ISSET(sc->sc_flags, SMF_SD_MODE)) {
584 cmd.c_opcode = SD_SEND_RELATIVE_ADDR;
585 cmd.c_flags = SCF_CMD_BCR | SCF_RSP_R6;
586 } else {
587 cmd.c_opcode = MMC_SET_RELATIVE_ADDR;
588 cmd.c_arg = MMC_ARG_RCA(sf->rca);
589 cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
590 }
591
592 if (sdmmc_mmc_command(sc, &cmd) != 0)
593 return 1;
594
595 if (ISSET(sc->sc_flags, SMF_SD_MODE))
596 sf->rca = SD_R6_RCA(cmd.c_resp);
597 return 0;
598 }
599
600
601
602
603 int
604 sdmmc_set_bus_width(struct sdmmc_function *sf)
605 {
606 struct sdmmc_softc *sc = sf->sc;
607 struct sdmmc_command cmd;
608 int error;
609
610 SDMMC_LOCK(sc);
611
612 if (!ISSET(sc->sc_flags, SMF_SD_MODE)) {
613 SDMMC_UNLOCK(sc);
614 return EOPNOTSUPP;
615 }
616
617 if ((error = sdmmc_select_card(sc, sf)) != 0) {
618 SDMMC_UNLOCK(sc);
619 return error;
620 }
621
622 bzero(&cmd, sizeof cmd);
623 cmd.c_opcode = SD_APP_SET_BUS_WIDTH;
624 cmd.c_arg = SD_ARG_BUS_WIDTH_4;
625 cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
626 error = sdmmc_app_command(sc, &cmd);
627 SDMMC_UNLOCK(sc);
628 return error;
629 }
630
631 int
632 sdmmc_select_card(struct sdmmc_softc *sc, struct sdmmc_function *sf)
633 {
634 struct sdmmc_command cmd;
635 int error;
636
637 if (sc->sc_card == sf || (sf && sc->sc_card &&
638 sc->sc_card->rca == sf->rca)) {
639 sc->sc_card = sf;
640 return 0;
641 }
642
643 bzero(&cmd, sizeof cmd);
644 cmd.c_opcode = MMC_SELECT_CARD;
645 cmd.c_arg = sf == NULL ? 0 : MMC_ARG_RCA(sf->rca);
646 cmd.c_flags = SCF_CMD_AC | (sf == NULL ? SCF_RSP_R0 : SCF_RSP_R1);
647 error = sdmmc_mmc_command(sc, &cmd);
648 if (error == 0 || sf == NULL)
649 sc->sc_card = sf;
650 return error;
651 }
652
653 #ifdef SDMMC_IOCTL
654 int
655 sdmmc_ioctl(struct device *self, u_long request, caddr_t addr)
656 {
657 struct sdmmc_softc *sc = (struct sdmmc_softc *)self;
658 struct sdmmc_command *ucmd;
659 struct sdmmc_command cmd;
660 void *data;
661 int error;
662
663 switch (request) {
664 #ifdef SDMMC_DEBUG
665 case SDIOCSETDEBUG:
666 sdmmcdebug = (((struct bio_sdmmc_debug *)addr)->debug) & 0xff;
667 sdhcdebug = (((struct bio_sdmmc_debug *)addr)->debug >> 8) & 0xff;
668 break;
669 #endif
670
671 case SDIOCEXECMMC:
672 case SDIOCEXECAPP:
673 ucmd = &((struct bio_sdmmc_command *)addr)->cmd;
674
675
676 if (ucmd->c_datalen > 524288)
677 return ENOMEM;
678
679
680 if ((ucmd->c_datalen > 0 && ucmd->c_data == NULL) ||
681 (ucmd->c_datalen < 1 && ucmd->c_data != NULL) ||
682 ucmd->c_datalen < 0)
683 return EINVAL;
684
685 bzero(&cmd, sizeof cmd);
686 cmd.c_opcode = ucmd->c_opcode;
687 cmd.c_arg = ucmd->c_arg;
688 cmd.c_flags = ucmd->c_flags;
689 cmd.c_blklen = ucmd->c_blklen;
690
691 if (ucmd->c_data) {
692 data = malloc(ucmd->c_datalen, M_TEMP,
693 M_WAITOK | M_CANFAIL);
694 if (data == NULL)
695 return ENOMEM;
696 if (copyin(ucmd->c_data, data, ucmd->c_datalen))
697 return EFAULT;
698
699 cmd.c_data = data;
700 cmd.c_datalen = ucmd->c_datalen;
701 }
702
703 if (request == SDIOCEXECMMC)
704 error = sdmmc_mmc_command(sc, &cmd);
705 else
706 error = sdmmc_app_command(sc, &cmd);
707 if (error && !cmd.c_error)
708 cmd.c_error = error;
709
710 bcopy(&cmd.c_resp, ucmd->c_resp, sizeof cmd.c_resp);
711 ucmd->c_flags = cmd.c_flags;
712 ucmd->c_error = cmd.c_error;
713
714 if (ucmd->c_data && copyout(data, ucmd->c_data,
715 ucmd->c_datalen))
716 return EFAULT;
717
718 if (ucmd->c_data)
719 free(data, M_TEMP);
720 break;
721
722 default:
723 return ENOTTY;
724 }
725 return 0;
726 }
727 #endif
728
729 #ifdef SDMMC_DEBUG
730 void
731 sdmmc_dump_command(struct sdmmc_softc *sc, struct sdmmc_command *cmd)
732 {
733 int i;
734
735 DPRINTF(1,("%s: cmd %u arg=%#x data=%#x dlen=%d flags=%#x "
736 "proc=\"%s\" (error %d)\n", DEVNAME(sc), cmd->c_opcode,
737 cmd->c_arg, cmd->c_data, cmd->c_datalen, cmd->c_flags,
738 curproc ? curproc->p_comm : "", cmd->c_error));
739
740 if (cmd->c_error || sdmmcdebug < 1)
741 return;
742
743 printf("%s: resp=", DEVNAME(sc));
744 if (ISSET(cmd->c_flags, SCF_RSP_136))
745 for (i = 0; i < sizeof cmd->c_resp; i++)
746 printf("%02x ", ((u_char *)cmd->c_resp)[i]);
747 else if (ISSET(cmd->c_flags, SCF_RSP_PRESENT))
748 for (i = 0; i < 4; i++)
749 printf("%02x ", ((u_char *)cmd->c_resp)[i]);
750 printf("\n");
751 }
752 #endif