[BACK]Return to sdmmc_io.c CVS log [TXT][DIR] Up to [local] / sys / dev / sdmmc

Annotation of sys/dev/sdmmc/sdmmc_io.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: sdmmc_io.c,v 1.9 2007/06/02 01:48:37 uwe 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/kernel.h>
                     23: #include <sys/malloc.h>
                     24: #include <sys/proc.h>
                     25: #include <sys/systm.h>
                     26:
                     27: #include <dev/sdmmc/sdmmc_ioreg.h>
                     28: #include <dev/sdmmc/sdmmcchip.h>
                     29: #include <dev/sdmmc/sdmmcreg.h>
                     30: #include <dev/sdmmc/sdmmcvar.h>
                     31:
                     32: struct sdmmc_intr_handler {
                     33:        struct sdmmc_softc *ih_softc;
                     34:        char *ih_name;
                     35:        int (*ih_fun)(void *);
                     36:        void *ih_arg;
                     37:        TAILQ_ENTRY(sdmmc_intr_handler) entry;
                     38: };
                     39:
                     40: int    sdmmc_submatch(struct device *, void *, void *);
                     41: int    sdmmc_print(void *, const char *);
                     42: int    sdmmc_io_rw_direct(struct sdmmc_softc *, struct sdmmc_function *,
                     43:            int, u_char *, int);
                     44: int    sdmmc_io_rw_extended(struct sdmmc_softc *, struct sdmmc_function *,
                     45:            int, u_char *, int, int);
                     46: int    sdmmc_io_xchg(struct sdmmc_softc *, struct sdmmc_function *,
                     47:            int, u_char *);
                     48: void   sdmmc_io_reset(struct sdmmc_softc *);
                     49: int    sdmmc_io_send_op_cond(struct sdmmc_softc *, u_int32_t, u_int32_t *);
                     50:
                     51: #ifdef SDMMC_DEBUG
                     52: #define DPRINTF(s)     printf s
                     53: #else
                     54: #define DPRINTF(s)     /**/
                     55: #endif
                     56:
                     57: #ifdef SDMMC_DEBUG
                     58: int    sdmmc_verbose = 1;
                     59: #else
                     60: int    sdmmc_verbose = 0;
                     61: #endif
                     62:
                     63: /*
                     64:  * Initialize SD I/O card functions (before memory cards).  The host
                     65:  * system and controller must support card interrupts in order to use
                     66:  * I/O functions.
                     67:  */
                     68: int
                     69: sdmmc_io_enable(struct sdmmc_softc *sc)
                     70: {
                     71:        u_int32_t host_ocr;
                     72:        u_int32_t card_ocr;
                     73:
                     74:        /* Set host mode to SD "combo" card. */
                     75:        SET(sc->sc_flags, SMF_SD_MODE|SMF_IO_MODE|SMF_MEM_MODE);
                     76:
                     77:        /* Reset I/O functions. */
                     78:        sdmmc_io_reset(sc);
                     79:
                     80:        /*
                     81:         * Read the I/O OCR value, determine the number of I/O
                     82:         * functions and whether memory is also present (a "combo
                     83:         * card") by issuing CMD5.  SD memory-only and MMC cards
                     84:         * do not respond to CMD5.
                     85:         */
                     86:        if (sdmmc_io_send_op_cond(sc, 0, &card_ocr) != 0) {
                     87:                /* No SDIO card; switch to SD memory-only mode. */
                     88:                CLR(sc->sc_flags, SMF_IO_MODE);
                     89:                return 0;
                     90:        }
                     91:
                     92:        /* Parse the additional bits in the I/O OCR value. */
                     93:        if (!ISSET(card_ocr, SD_IO_OCR_MEM_PRESENT)) {
                     94:                /* SDIO card without memory (not a "combo card"). */
                     95:                DPRINTF(("%s: no memory present\n", SDMMCDEVNAME(sc)));
                     96:                CLR(sc->sc_flags, SMF_MEM_MODE);
                     97:        }
                     98:        sc->sc_function_count = SD_IO_OCR_NUM_FUNCTIONS(card_ocr);
                     99:        if (sc->sc_function_count == 0) {
                    100:                /* Useless SDIO card without any I/O functions. */
                    101:                DPRINTF(("%s: no I/O functions\n", SDMMCDEVNAME(sc)));
                    102:                CLR(sc->sc_flags, SMF_IO_MODE);
                    103:                return 0;
                    104:        }
                    105:        card_ocr &= SD_IO_OCR_MASK;
                    106:
                    107:        /* Set the lowest voltage supported by the card and host. */
                    108:        host_ocr = sdmmc_chip_host_ocr(sc->sct, sc->sch);
                    109:        if (sdmmc_set_bus_power(sc, host_ocr, card_ocr) != 0) {
                    110:                printf("%s: can't supply voltage requested by card\n",
                    111:                    SDMMCDEVNAME(sc));
                    112:                return 1;
                    113:        }
                    114:
                    115:        /* Reset I/O functions (again). */
                    116:        sdmmc_io_reset(sc);
                    117:
                    118:        /* Send the new OCR value until all cards are ready. */
                    119:        if (sdmmc_io_send_op_cond(sc, host_ocr, NULL) != 0) {
                    120:                printf("%s: can't send I/O OCR\n", SDMMCDEVNAME(sc));
                    121:                return 1;
                    122:        }
                    123:        return 0;
                    124: }
                    125:
                    126: /*
                    127:  * Allocate sdmmc_function structures for SD card I/O function
                    128:  * (including function 0).
                    129:  */
                    130: void
                    131: sdmmc_io_scan(struct sdmmc_softc *sc)
                    132: {
                    133:        struct sdmmc_function *sf0, *sf;
                    134:        int i;
                    135:
                    136:        sf0 = sdmmc_function_alloc(sc);
                    137:        sf0->number = 0;
                    138:        if (sdmmc_set_relative_addr(sc, sf0) != 0) {
                    139:                printf("%s: can't set I/O RCA\n", SDMMCDEVNAME(sc));
                    140:                SET(sf0->flags, SFF_ERROR);
                    141:                return;
                    142:        }
                    143:        sc->sc_fn0 = sf0;
                    144:        SIMPLEQ_INSERT_TAIL(&sc->sf_head, sf0, sf_list);
                    145:
                    146:        /* Verify that the RCA has been set by selecting the card. */
                    147:        if (sdmmc_select_card(sc, sf0) != 0) {
                    148:                printf("%s: can't select I/O RCA %d\n", SDMMCDEVNAME(sc),
                    149:                    sf0->rca);
                    150:                SET(sf0->flags, SFF_ERROR);
                    151:                return;
                    152:        }
                    153:
                    154:        for (i = 1; i <= sc->sc_function_count; i++) {
                    155:                sf = sdmmc_function_alloc(sc);
                    156:                sf->number = i;
                    157:                sf->rca = sf0->rca;
                    158:
                    159:                SIMPLEQ_INSERT_TAIL(&sc->sf_head, sf, sf_list);
                    160:        }
                    161: }
                    162:
                    163: /*
                    164:  * Initialize SDIO card functions.
                    165:  */
                    166: int
                    167: sdmmc_io_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
                    168: {
                    169:        if (sf->number == 0) {
                    170:                sdmmc_io_write_1(sf, SD_IO_CCCR_BUS_WIDTH,
                    171:                    CCCR_BUS_WIDTH_1);
                    172:
                    173:                if (sdmmc_read_cis(sf, &sf->cis) != 0) {
                    174:                        printf("%s: can't read CIS\n", SDMMCDEVNAME(sc));
                    175:                        SET(sf->flags, SFF_ERROR);
                    176:                        return 1;
                    177:                }
                    178:
                    179:                sdmmc_check_cis_quirks(sf);
                    180:
                    181:                if (sdmmc_verbose)
                    182:                        sdmmc_print_cis(sf);
                    183:        }
                    184:        return 0;
                    185: }
                    186:
                    187: /*
                    188:  * Indicate whether the function is ready to operate.
                    189:  */
                    190: int
                    191: sdmmc_io_function_ready(struct sdmmc_function *sf)
                    192: {
                    193:        struct sdmmc_softc *sc = sf->sc;
                    194:        struct sdmmc_function *sf0 = sc->sc_fn0;
                    195:        u_int8_t rv;
                    196:
                    197:        if (sf->number == 0)
                    198:                return 1;       /* FN0 is always ready */
                    199:
                    200:        rv = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_READY);
                    201:        return (rv & (1 << sf->number)) != 0;
                    202: }
                    203:
                    204: /*
                    205:  * Enable the I/O function.  Return zero if the function was
                    206:  * enabled successfully.
                    207:  */
                    208: int
                    209: sdmmc_io_function_enable(struct sdmmc_function *sf)
                    210: {
                    211:        struct sdmmc_softc *sc = sf->sc;
                    212:        struct sdmmc_function *sf0 = sc->sc_fn0;
                    213:        u_int8_t rv;
                    214:        int retry = 5;
                    215:
                    216:        if (sf->number == 0)
                    217:                return 0;       /* FN0 is always enabled */
                    218:
                    219:        SDMMC_LOCK(sc);
                    220:        rv = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_ENABLE);
                    221:        rv |= (1<<sf->number);
                    222:        sdmmc_io_write_1(sf0, SD_IO_CCCR_FN_ENABLE, rv);
                    223:        SDMMC_UNLOCK(sc);
                    224:
                    225:        while (!sdmmc_io_function_ready(sf) && retry-- > 0)
                    226:                tsleep(&lbolt, PPAUSE, "pause", 0);
                    227:        return (retry >= 0) ? 0 : ETIMEDOUT;
                    228: }
                    229:
                    230: /*
                    231:  * Disable the I/O function.  Return zero if the function was
                    232:  * disabled successfully.
                    233:  */
                    234: void
                    235: sdmmc_io_function_disable(struct sdmmc_function *sf)
                    236: {
                    237:        struct sdmmc_softc *sc = sf->sc;
                    238:        struct sdmmc_function *sf0 = sc->sc_fn0;
                    239:        u_int8_t rv;
                    240:
                    241:        if (sf->number == 0)
                    242:                return;         /* FN0 is always enabled */
                    243:
                    244:        SDMMC_LOCK(sc);
                    245:        rv = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_ENABLE);
                    246:        rv &= ~(1<<sf->number);
                    247:        sdmmc_io_write_1(sf0, SD_IO_CCCR_FN_ENABLE, rv);
                    248:        SDMMC_UNLOCK(sc);
                    249: }
                    250:
                    251: void
                    252: sdmmc_io_attach(struct sdmmc_softc *sc)
                    253: {
                    254:        struct sdmmc_function *sf;
                    255:        struct sdmmc_attach_args saa;
                    256:
                    257:        SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
                    258:                if (sf->number < 1)
                    259:                        continue;
                    260:
                    261:                bzero(&saa, sizeof saa);
                    262:                saa.sf = sf;
                    263:
                    264:                sf->child = config_found_sm(&sc->sc_dev, &saa, sdmmc_print,
                    265:                    sdmmc_submatch);
                    266:        }
                    267: }
                    268:
                    269: int
                    270: sdmmc_submatch(struct device *parent, void *match, void *aux)
                    271: {
                    272:        struct cfdata *cf = match;
                    273:
                    274:        /* Skip the scsibus, it is configured directly. */
                    275:        if (strcmp(cf->cf_driver->cd_name, "scsibus") == 0)
                    276:                return 0;
                    277:
                    278:        return cf->cf_attach->ca_match(parent, cf, aux);
                    279: }
                    280:
                    281: int
                    282: sdmmc_print(void *aux, const char *pnp)
                    283: {
                    284:        struct sdmmc_attach_args *sa = aux;
                    285:        struct sdmmc_function *sf = sa->sf;
                    286:        struct sdmmc_cis *cis = &sf->sc->sc_fn0->cis;
                    287:        int i;
                    288:
                    289:        if (pnp) {
                    290:                if (sf->number == 0)
                    291:                        return QUIET;
                    292:
                    293:                for (i = 0; i < 4 && cis->cis1_info[i]; i++)
                    294:                        printf("%s%s", i ? ", " : "\"", cis->cis1_info[i]);
                    295:                if (i != 0)
                    296:                        printf("\"");
                    297:
                    298:                if (cis->manufacturer != SDMMC_VENDOR_INVALID &&
                    299:                    cis->product != SDMMC_PRODUCT_INVALID) {
                    300:                        printf("%s(", i ? " " : "");
                    301:                        if (cis->manufacturer != SDMMC_VENDOR_INVALID)
                    302:                                printf("manufacturer 0x%x%s",
                    303:                                    cis->manufacturer,
                    304:                                    cis->product == SDMMC_PRODUCT_INVALID ?
                    305:                                    "" : ", ");
                    306:                        if (cis->product != SDMMC_PRODUCT_INVALID)
                    307:                                printf("product 0x%x", cis->product);
                    308:                        printf(")");
                    309:                }
                    310:                printf("%sat %s", i ? " " : "", pnp);
                    311:        }
                    312:        printf(" function %d", sf->number);
                    313:
                    314:        if (!pnp) {
                    315:                for (i = 0; i < 3 && cis->cis1_info[i]; i++)
                    316:                        printf("%s%s", i ? ", " : " \"", cis->cis1_info[i]);
                    317:                if (i != 0)
                    318:                        printf("\"");
                    319:        }
                    320:        return UNCONF;
                    321: }
                    322:
                    323: void
                    324: sdmmc_io_detach(struct sdmmc_softc *sc)
                    325: {
                    326:        struct sdmmc_function *sf;
                    327:
                    328:        SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
                    329:                if (sf->child != NULL) {
                    330:                        config_detach(sf->child, DETACH_FORCE);
                    331:                        sf->child = NULL;
                    332:                }
                    333:        }
                    334:
                    335:        KASSERT(TAILQ_EMPTY(&sc->sc_intrq));
                    336: }
                    337:
                    338: int
                    339: sdmmc_io_rw_direct(struct sdmmc_softc *sc, struct sdmmc_function *sf,
                    340:     int reg, u_char *datap, int arg)
                    341: {
                    342:        struct sdmmc_command cmd;
                    343:        int error;
                    344:
                    345:        SDMMC_LOCK(sc);
                    346:
                    347:        /* Make sure the card is selected. */
                    348:        if ((error = sdmmc_select_card(sc, sf)) != 0) {
                    349:                SDMMC_UNLOCK(sc);
                    350:                return error;
                    351:        }
                    352:
                    353:        arg |= ((sf == NULL ? 0 : sf->number) & SD_ARG_CMD52_FUNC_MASK) <<
                    354:            SD_ARG_CMD52_FUNC_SHIFT;
                    355:        arg |= (reg & SD_ARG_CMD52_REG_MASK) <<
                    356:            SD_ARG_CMD52_REG_SHIFT;
                    357:        arg |= (*datap & SD_ARG_CMD52_DATA_MASK) <<
                    358:            SD_ARG_CMD52_DATA_SHIFT;
                    359:
                    360:        bzero(&cmd, sizeof cmd);
                    361:        cmd.c_opcode = SD_IO_RW_DIRECT;
                    362:        cmd.c_arg = arg;
                    363:        cmd.c_flags = SCF_CMD_AC | SCF_RSP_R5;
                    364:
                    365:        error = sdmmc_mmc_command(sc, &cmd);
                    366:        *datap = SD_R5_DATA(cmd.c_resp);
                    367:
                    368:        SDMMC_UNLOCK(sc);
                    369:        return error;
                    370: }
                    371:
                    372: /*
                    373:  * Useful values of `arg' to pass in are either SD_ARG_CMD53_READ or
                    374:  * SD_ARG_CMD53_WRITE.  SD_ARG_CMD53_INCREMENT may be ORed into `arg'
                    375:  * to access successive register locations instead of accessing the
                    376:  * same register many times.
                    377:  */
                    378: int
                    379: sdmmc_io_rw_extended(struct sdmmc_softc *sc, struct sdmmc_function *sf,
                    380:     int reg, u_char *datap, int datalen, int arg)
                    381: {
                    382:        struct sdmmc_command cmd;
                    383:        int error;
                    384:
                    385:        SDMMC_LOCK(sc);
                    386:
                    387: #if 0
                    388:        /* Make sure the card is selected. */
                    389:        if ((error = sdmmc_select_card(sc, sf)) != 0) {
                    390:                SDMMC_UNLOCK(sc);
                    391:                return error;
                    392:        }
                    393: #endif
                    394:
                    395:        arg |= ((sf == NULL ? 0 : sf->number) & SD_ARG_CMD53_FUNC_MASK) <<
                    396:            SD_ARG_CMD53_FUNC_SHIFT;
                    397:        arg |= (reg & SD_ARG_CMD53_REG_MASK) <<
                    398:            SD_ARG_CMD53_REG_SHIFT;
                    399:        arg |= (datalen & SD_ARG_CMD53_LENGTH_MASK) <<
                    400:            SD_ARG_CMD53_LENGTH_SHIFT;
                    401:
                    402:        bzero(&cmd, sizeof cmd);
                    403:        cmd.c_opcode = SD_IO_RW_EXTENDED;
                    404:        cmd.c_arg = arg;
                    405:        cmd.c_flags = SCF_CMD_AC | SCF_RSP_R5;
                    406:        cmd.c_data = datap;
                    407:        cmd.c_datalen = datalen;
                    408:        cmd.c_blklen = MIN(datalen, sdmmc_chip_host_maxblklen(sc->sct, sc->sch));
                    409:
                    410:        if (!ISSET(arg, SD_ARG_CMD53_WRITE))
                    411:                cmd.c_flags |= SCF_CMD_READ;
                    412:
                    413:        error = sdmmc_mmc_command(sc, &cmd);
                    414:        SDMMC_UNLOCK(sc);
                    415:        return error;
                    416: }
                    417:
                    418: u_int8_t
                    419: sdmmc_io_read_1(struct sdmmc_function *sf, int reg)
                    420: {
                    421:        u_int8_t data = 0;
                    422:
                    423:        (void)sdmmc_io_rw_direct(sf->sc, sf, reg, (u_char *)&data,
                    424:            SD_ARG_CMD52_READ);
                    425:        return data;
                    426: }
                    427:
                    428: void
                    429: sdmmc_io_write_1(struct sdmmc_function *sf, int reg, u_int8_t data)
                    430: {
                    431:        (void)sdmmc_io_rw_direct(sf->sc, sf, reg, (u_char *)&data,
                    432:            SD_ARG_CMD52_WRITE);
                    433: }
                    434:
                    435: u_int16_t
                    436: sdmmc_io_read_2(struct sdmmc_function *sf, int reg)
                    437: {
                    438:        u_int16_t data = 0;
                    439:
                    440:        (void)sdmmc_io_rw_extended(sf->sc, sf, reg, (u_char *)&data, 2,
                    441:            SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT);
                    442:        return data;
                    443: }
                    444:
                    445: void
                    446: sdmmc_io_write_2(struct sdmmc_function *sf, int reg, u_int16_t data)
                    447: {
                    448:        (void)sdmmc_io_rw_extended(sf->sc, sf, reg, (u_char *)&data, 2,
                    449:            SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT);
                    450: }
                    451:
                    452: u_int32_t
                    453: sdmmc_io_read_4(struct sdmmc_function *sf, int reg)
                    454: {
                    455:        u_int32_t data = 0;
                    456:
                    457:        (void)sdmmc_io_rw_extended(sf->sc, sf, reg, (u_char *)&data, 4,
                    458:            SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT);
                    459:        return data;
                    460: }
                    461:
                    462: void
                    463: sdmmc_io_write_4(struct sdmmc_function *sf, int reg, u_int32_t data)
                    464: {
                    465:        (void)sdmmc_io_rw_extended(sf->sc, sf, reg, (u_char *)&data, 4,
                    466:            SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT);
                    467: }
                    468:
                    469: int
                    470: sdmmc_io_read_multi_1(struct sdmmc_function *sf, int reg, u_char *data,
                    471:     int datalen)
                    472: {
                    473:        int error;
                    474:
                    475:        while (datalen > SD_ARG_CMD53_LENGTH_MAX) {
                    476:                error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
                    477:                    SD_ARG_CMD53_LENGTH_MAX, SD_ARG_CMD53_READ);
                    478:                if (error)
                    479:                        return error;
                    480:                data += SD_ARG_CMD53_LENGTH_MAX;
                    481:                datalen -= SD_ARG_CMD53_LENGTH_MAX;
                    482:        }
                    483:
                    484:        return sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
                    485:            SD_ARG_CMD53_READ);
                    486: }
                    487:
                    488: int
                    489: sdmmc_io_write_multi_1(struct sdmmc_function *sf, int reg, u_char *data,
                    490:     int datalen)
                    491: {
                    492:        int error;
                    493:
                    494:        while (datalen > SD_ARG_CMD53_LENGTH_MAX) {
                    495:                error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
                    496:                    SD_ARG_CMD53_LENGTH_MAX, SD_ARG_CMD53_WRITE);
                    497:                if (error)
                    498:                        return error;
                    499:                data += SD_ARG_CMD53_LENGTH_MAX;
                    500:                datalen -= SD_ARG_CMD53_LENGTH_MAX;
                    501:        }
                    502:
                    503:        return sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
                    504:            SD_ARG_CMD53_WRITE);
                    505: }
                    506:
                    507: int
                    508: sdmmc_io_xchg(struct sdmmc_softc *sc, struct sdmmc_function *sf,
                    509:     int reg, u_char *datap)
                    510: {
                    511:        return sdmmc_io_rw_direct(sc, sf, reg, datap,
                    512:            SD_ARG_CMD52_WRITE|SD_ARG_CMD52_EXCHANGE);
                    513: }
                    514:
                    515: /*
                    516:  * Reset the I/O functions of the card.
                    517:  */
                    518: void
                    519: sdmmc_io_reset(struct sdmmc_softc *sc)
                    520: {
                    521: #if 0 /* XXX command fails */
                    522:        (void)sdmmc_io_write(sc, NULL, SD_IO_REG_CCCR_CTL, CCCR_CTL_RES);
                    523:        sdmmc_delay(100000);
                    524: #endif
                    525: }
                    526:
                    527: /*
                    528:  * Get or set the card's I/O OCR value (SDIO).
                    529:  */
                    530: int
                    531: sdmmc_io_send_op_cond(struct sdmmc_softc *sc, u_int32_t ocr, u_int32_t *ocrp)
                    532: {
                    533:        struct sdmmc_command cmd;
                    534:        int error;
                    535:        int i;
                    536:
                    537:        SDMMC_LOCK(sc);
                    538:
                    539:        /*
                    540:         * If we change the OCR value, retry the command until the OCR
                    541:         * we receive in response has the "CARD BUSY" bit set, meaning
                    542:         * that all cards are ready for identification.
                    543:         */
                    544:        for (i = 0; i < 100; i++) {
                    545:                bzero(&cmd, sizeof cmd);
                    546:                cmd.c_opcode = SD_IO_SEND_OP_COND;
                    547:                cmd.c_arg = ocr;
                    548:                cmd.c_flags = SCF_CMD_BCR | SCF_RSP_R4;
                    549:
                    550:                error = sdmmc_mmc_command(sc, &cmd);
                    551:                if (error != 0)
                    552:                        break;
                    553:                if (ISSET(MMC_R4(cmd.c_resp), SD_IO_OCR_MEM_READY) ||
                    554:                    ocr == 0)
                    555:                        break;
                    556:                error = ETIMEDOUT;
                    557:                sdmmc_delay(10000);
                    558:        }
                    559:        if (error == 0 && ocrp != NULL)
                    560:                *ocrp = MMC_R4(cmd.c_resp);
                    561:
                    562:        SDMMC_UNLOCK(sc);
                    563:        return error;
                    564: }
                    565:
                    566: /*
                    567:  * Card interrupt handling
                    568:  */
                    569:
                    570: void
                    571: sdmmc_intr_enable(struct sdmmc_function *sf)
                    572: {
                    573:        struct sdmmc_softc *sc = sf->sc;
                    574:        struct sdmmc_function *sf0 = sc->sc_fn0;
                    575:        u_int8_t imask;
                    576:
                    577:        SDMMC_LOCK(sc);
                    578:        imask = sdmmc_io_read_1(sf0, SD_IO_CCCR_INT_ENABLE);
                    579:        imask |= 1 << sf->number;
                    580:        sdmmc_io_write_1(sf0, SD_IO_CCCR_INT_ENABLE, imask);
                    581:        SDMMC_UNLOCK(sc);
                    582: }
                    583:
                    584: void
                    585: sdmmc_intr_disable(struct sdmmc_function *sf)
                    586: {
                    587:        struct sdmmc_softc *sc = sf->sc;
                    588:        struct sdmmc_function *sf0 = sc->sc_fn0;
                    589:        u_int8_t imask;
                    590:
                    591:        SDMMC_LOCK(sc);
                    592:        imask = sdmmc_io_read_1(sf0, SD_IO_CCCR_INT_ENABLE);
                    593:        imask &= ~(1 << sf->number);
                    594:        sdmmc_io_write_1(sf0, SD_IO_CCCR_INT_ENABLE, imask);
                    595:        SDMMC_UNLOCK(sc);
                    596: }
                    597:
                    598: /*
                    599:  * Establish a handler for the SDIO card interrupt.  Because the
                    600:  * interrupt may be shared with different SDIO functions, multiple
                    601:  * handlers can be established.
                    602:  */
                    603: void *
                    604: sdmmc_intr_establish(struct device *sdmmc, int (*fun)(void *),
                    605:     void *arg, const char *name)
                    606: {
                    607:        struct sdmmc_softc *sc = (struct sdmmc_softc *)sdmmc;
                    608:        struct sdmmc_intr_handler *ih;
                    609:        int s;
                    610:
                    611:        if (sc->sct->card_intr_mask == NULL)
                    612:                return NULL;
                    613:
                    614:        ih = malloc(sizeof *ih, M_DEVBUF, M_WAITOK | M_CANFAIL);
                    615:        if (ih == NULL)
                    616:                return NULL;
                    617:
                    618:        bzero(ih, sizeof *ih);
                    619:        ih->ih_name = malloc(strlen(name), M_DEVBUF, M_WAITOK | M_CANFAIL);
                    620:        if (ih->ih_name == NULL) {
                    621:                free(ih, M_DEVBUF);
                    622:                return NULL;
                    623:        }
                    624:        strlcpy(ih->ih_name, name, strlen(name));
                    625:        ih->ih_softc = sc;
                    626:        ih->ih_fun = fun;
                    627:        ih->ih_arg = arg;
                    628:
                    629:        s = splhigh();
                    630:        if (TAILQ_EMPTY(&sc->sc_intrq)) {
                    631:                sdmmc_intr_enable(sc->sc_fn0);
                    632:                sdmmc_chip_card_intr_mask(sc->sct, sc->sch, 1);
                    633:        }
                    634:        TAILQ_INSERT_TAIL(&sc->sc_intrq, ih, entry);
                    635:        splx(s);
                    636:        return ih;
                    637: }
                    638:
                    639: /*
                    640:  * Disestablish the given handler.
                    641:  */
                    642: void
                    643: sdmmc_intr_disestablish(void *cookie)
                    644: {
                    645:        struct sdmmc_intr_handler *ih = cookie;
                    646:        struct sdmmc_softc *sc = ih->ih_softc;
                    647:        int s;
                    648:
                    649:        if (sc->sct->card_intr_mask == NULL)
                    650:                return;
                    651:
                    652:        s = splhigh();
                    653:        TAILQ_REMOVE(&sc->sc_intrq, ih, entry);
                    654:        if (TAILQ_EMPTY(&sc->sc_intrq)) {
                    655:                sdmmc_chip_card_intr_mask(sc->sct, sc->sch, 0);
                    656:                sdmmc_intr_disable(sc->sc_fn0);
                    657:        }
                    658:        splx(s);
                    659:
                    660:        free(ih->ih_name, M_DEVBUF);
                    661:        free(ih, M_DEVBUF);
                    662: }
                    663:
                    664: /*
                    665:  * Call established SDIO card interrupt handlers.  The host controller
                    666:  * must call this function from its own interrupt handler to handle an
                    667:  * SDIO interrupt from the card.
                    668:  */
                    669: void
                    670: sdmmc_card_intr(struct device *sdmmc)
                    671: {
                    672:        struct sdmmc_softc *sc = (struct sdmmc_softc *)sdmmc;
                    673:
                    674:        if (sc->sct->card_intr_mask == NULL)
                    675:                return;
                    676:
                    677:        if (!sdmmc_task_pending(&sc->sc_intr_task))
                    678:                sdmmc_add_task(sc, &sc->sc_intr_task);
                    679: }
                    680:
                    681: void
                    682: sdmmc_intr_task(void *arg)
                    683: {
                    684:        struct sdmmc_softc *sc = arg;
                    685:        struct sdmmc_intr_handler *ih;
                    686:        int s;
                    687:
                    688:        s = splhigh();
                    689:        TAILQ_FOREACH(ih, &sc->sc_intrq, entry) {
                    690:                splx(s);
                    691:
                    692:                /* XXX examine return value and do evcount stuff*/
                    693:                (void)ih->ih_fun(ih->ih_arg);
                    694:
                    695:                s = splhigh();
                    696:        }
                    697:        sdmmc_chip_card_intr_ack(sc->sct, sc->sch);
                    698:        splx(s);
                    699: }

CVSweb