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

Annotation of funnyos/dev/sdmmc/sdmmc_spi.c, Revision 1.2

1.1       nbrk        1: /*
1.2     ! nbrk        2:  * $Id: sdmmc_spi.c,v 1.1 2007/12/20 15:23:15 nbrk Exp $
1.1       nbrk        3:  */
                      4: #include <sys/types.h>
                      5: #include <sys/device.h>
                      6: #include <sys/bus_spi.h>
                      7:
                      8: #include <dev/sdmmc/sdmmcvar.h>
                      9: #include <libkern/printf.h>
                     10:
                     11: /*
                     12:  * SD/MMC conversation over SPI bus.
                     13:  */
                     14: struct spisdmmc_dd {
                     15:        struct spi_bus_handle *ss_sbhp;
                     16:
                     17: //     struct sdmmc_bus_handle;
                     18: };
                     19:
                     20: int    spisdmmc_attach(struct device *, uint32_t, uint8_t);
1.2     ! nbrk       21: void   spisdmmc_send_command(struct spisdmmc_dd *ddp, uint8_t cmd, uint32_t arg, uint32_t crc);
        !            22: uint8_t spisdmmc_get_response(struct spisdmmc_dd *ddp);
        !            23: int    spisdmmc_set_block_size(struct spisdmmc_dd *ddp, uint16_t blksize);
        !            24: void   spisdmmc_read_block(struct spisdmmc_dd *ddp, uint16_t nbytes, char *buffp);
        !            25: uint8_t spisdmmc_get_token(struct spisdmmc_dd *ddp);
        !            26: void   spisdmmc_read_cid(struct spisdmmc_dd *ddp, struct sdmmc_cid *cidp);
        !            27:
        !            28:
1.1       nbrk       29:
                     30: struct driver spisdmmc_dr = {
                     31:        sizeof(struct spisdmmc_dd),
                     32:        spisdmmc_attach,
                     33:        NULL,
                     34:        NULL
                     35: };
                     36:
                     37:
                     38: int
                     39: spisdmmc_attach(struct device *self, uint32_t loc, uint8_t flags)
                     40: {
                     41:        struct spisdmmc_dd *ddp = self->dv_devdata;
                     42:        ddp->ss_sbhp = self->dv_parent->dv_aux;
                     43:
                     44:        printf("SPI SD/MMC\n");
                     45:
1.2     ! nbrk       46:        spisdmmc_init(ddp);
        !            47:
1.1       nbrk       48:        return(0);
                     49: }
                     50:
                     51:
                     52: int
                     53: spisdmmc_init(struct spisdmmc_dd *ddp)
                     54: {
                     55:        uint8_t i, resp;
1.2     ! nbrk       56:        struct sdmmc_cid cid;
1.1       nbrk       57:
                     58:        /*
                     59:         * Apply 80 clock pulses.
                     60:         * XXX assert CS. (NPCS0)
                     61:         */
1.2     ! nbrk       62:        spi_cs_high(ddp->ss_sbhp);
1.1       nbrk       63:        for (i = 0; i < 9; i++)
                     64:                spi_transmit(ddp->ss_sbhp, 0xff);
                     65:        /*
                     66:         * Apply 16 clocks.
                     67:         * XXX deassert CS.
                     68:         */
1.2     ! nbrk       69: //     for (i = 0; i < 2; i ++)
        !            70: //             spi_transmit(ddp->ss_sbhp, 0xff);
1.1       nbrk       71:
                     72:        /*
                     73:         * Send CMD0_GO_IDLE_STATE.
                     74:         */
1.2     ! nbrk       75:        spi_cs_low(ddp->ss_sbhp);
1.1       nbrk       76:        spisdmmc_send_command(ddp, CMD0_GO_IDLE_STATE, 0, CMD0_HARDCODED_CRC);
1.2     ! nbrk       77:
        !            78:        resp = spisdmmc_get_response(ddp);
        !            79:
        !            80:        if (resp != 0) {
1.1       nbrk       81:                printf("spisdmmc_init: CMD0_GO_IDLE_STATE failed with %d\n", resp);
                     82:
                     83:                return(-1);
                     84:        }
1.2     ! nbrk       85:        printf("spisdmmc_init: Card replied to CMD0_GO_IDLE_STATE with 0x%x\n", resp);
        !            86:
        !            87:        /*
        !            88:         * Okay. Try to initialize the card.
        !            89:         * Periodically send CMD1 and poll for response with 0x01 cleared (card exit Idle state).
        !            90:         * CRC is off so we can set it 0xff.
        !            91:         * XXX send 0xff before.
        !            92:         */
        !            93: //     spi_transmit(ddp->ss_sbhp, 0xff);
        !            94:        do {
        !            95:                spisdmmc_send_command(ddp, CMD1_SEND_OP_COND, 0, 0xff);
        !            96:                resp = spisdmmc_get_response(ddp);
        !            97:        } while(resp != 0x00);
        !            98:
        !            99:        printf("spisdmmc_init: Card initialization completed\n");
        !           100:
        !           101:        /*
        !           102:         * Set block size to 512 bytes.
        !           103:         */
        !           104:        if(spisdmmc_set_block_size(ddp, SDMMC_BLOCK_SIZE) == -1) {
        !           105:                printf("spisdmmc_init: failed to set block size\n");
        !           106:                return(-1);
        !           107:        }
        !           108:        printf("spisdmmc_init: block size set to %d\n", SDMMC_BLOCK_SIZE);
1.1       nbrk      109:
1.2     ! nbrk      110:        spisdmmc_read_cid(ddp, &cid);
        !           111:        printf("cid.pnm: %s%s%s%s%s\n", cid.cid_pnm[0], cid.cid_pnm[1], cid.cid_pnm[2], cid.cid_pnm[3], cid.cid_pnm[4]);
        !           112:
        !           113:        return(0);
1.1       nbrk      114: }
                    115:
                    116:
                    117: void
                    118: spisdmmc_send_command(struct spisdmmc_dd *ddp, uint8_t cmd, uint32_t arg, uint32_t crc)
                    119: {
                    120:        struct sdmmc_cmdframe sdcf;
                    121:        uint8_t i;
                    122:
                    123:        /* construct frame */
                    124:        sdcf = sdmmc_command(cmd, arg, crc);
                    125:
1.2     ! nbrk      126:        printf("spisdmmc_send_command: sending cmd %d arg 0x%x crc 0x%x\n", sdcf.sc_cmd & ~0xc0, sdcf.sc_arg, sdcf.sc_crc);
        !           127:        /* transmit cmd */
1.1       nbrk      128:        spi_transmit(ddp->ss_sbhp, sdcf.sc_cmd);
                    129:
                    130:        /* transmit 32 bit argument XXX MSB first */
                    131:        for(i = 0; i < 4; i++)
                    132:                spi_transmit(ddp->ss_sbhp, ((sdcf.sc_arg & (0xff000000 >> i)) >> (8 * (4 - i + 1))) );
                    133:
                    134:        /* transmit CRC field */
1.2     ! nbrk      135:        spi_transmit(ddp->ss_sbhp, sdcf.sc_crc);
        !           136:
        !           137:        /* XXX Apply NCR clock pulses */
        !           138: //     spi_transmit(ddp->ss_sbhp, 0xff);
        !           139: }
        !           140:
        !           141:
        !           142: uint8_t
        !           143: spisdmmc_get_response(struct spisdmmc_dd *ddp)
        !           144: {
        !           145:        uint8_t i, resp;
        !           146:        /*
        !           147:         * Get response from card.
        !           148:         * After command response comes in 8 to 64 pulses (all this bits will be 1).
        !           149:         */
        !           150:
        !           151:        for(i = 0; i < 64; i++) {
        !           152:                resp = spi_transmit(ddp->ss_sbhp, 0xff);
        !           153:
        !           154:                if (resp == 0x00 || resp == 0x01)
        !           155:                        return(resp);
        !           156:        }
        !           157: }
        !           158:
        !           159: uint8_t
        !           160: spisdmmc_get_token(struct spisdmmc_dd *ddp)
        !           161: {
        !           162:        uint16_t i, token;
        !           163:        /*
        !           164:         * Get token.
        !           165:         */
        !           166:
        !           167:        for(i = 0; i < 1000; i++) {
        !           168:                token = spi_transmit(ddp->ss_sbhp, 0xff);
        !           169:
        !           170:                if (token == TOK_READ_BLOCK || token == TOK_WRITE_BLOCK_MULTIPLE)
        !           171:                        return(token);
        !           172:        }
        !           173: }
        !           174:
1.1       nbrk      175:
1.2     ! nbrk      176: int
        !           177: spisdmmc_set_block_size(struct spisdmmc_dd *ddp, uint16_t blksize)
        !           178: {
        !           179:        uint8_t resp;
        !           180:        /*
        !           181:         * Set block size (CMD16).
        !           182:         */
        !           183:        spisdmmc_send_command(ddp,CMD16_SET_BLOCKLEN, blksize, 0xff);
        !           184:        resp = spisdmmc_get_response(ddp);
        !           185:        if (resp != 0x00) {
        !           186:                printf("spisdmmc_set_block_size: set block size to %d failed (0x%x)\n", blksize, resp);
        !           187:                return(-1);
        !           188:        }
        !           189:        return(0);
1.1       nbrk      190: }
                    191:
1.2     ! nbrk      192: void
        !           193: spisdmmc_read_cid(struct spisdmmc_dd *ddp, struct sdmmc_cid *cidp)
        !           194: {
        !           195:        uint8_t resp;
        !           196:        struct sdmmc_cid cid;
        !           197:        /*
        !           198:         * Read Card ID register.
        !           199:         */
        !           200:        spisdmmc_send_command(ddp, CMD10_SEND_CID, 0, 0xff);
        !           201:        resp = spisdmmc_get_response(ddp);
        !           202:        printf("spisdmmc_read_cid: got r1 response 0x%x\n", resp);
        !           203:
        !           204:        /*
        !           205:         * Wait R1 response.
        !           206:         */
        !           207:        if (resp != 0x00) {
        !           208:                printf("spisdmmc_read_cid: bad response 0x%x\n", resp);
        !           209:                return;
        !           210:        }
        !           211:
        !           212:        spisdmmc_read_block(ddp, 16, (char *)&cid);
        !           213: }
        !           214:
        !           215:
        !           216: void
        !           217: spisdmmc_read_block(struct spisdmmc_dd *ddp, uint16_t nbytes, char *buffp)
        !           218: {
        !           219:        uint8_t token;
        !           220:        uint16_t crc;
        !           221:        /*
        !           222:         * Read block.
        !           223:         */
        !           224:        token = spisdmmc_get_token(ddp);
        !           225:        printf("spisdmmc_read_block: got token 0x%x\n", token);
        !           226:        if (token != TOK_READ_BLOCK) {
        !           227:                printf("spisdmmc_read_block: error, foreign token\n");
        !           228:                return;
        !           229:        }
        !           230:        /*
        !           231:         * Okay, next is the data.
        !           232:         */
        !           233:        while(nbytes != 0) {
        !           234:                *buffp = spi_transmit(ddp->ss_sbhp, 0xff);
        !           235:                printf("byte read 0x%x\n", *buffp);
        !           236:
        !           237:                buffp++;
        !           238:                nbytes--;
        !           239:        }
        !           240:
        !           241:        /*
        !           242:         * Read CRC.
        !           243:         */
        !           244:        crc = spi_transmit(ddp->ss_sbhp, 0xff);
        !           245:        crc <<= 8;
        !           246:        crc = spi_transmit(ddp->ss_sbhp, 0xff);
        !           247: };
1.1       nbrk      248:

CVSweb