[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.3

1.1       nbrk        1: /*
1.3     ! nbrk        2:  * $Id: sdmmc_spi.c,v 1.2 2007/12/21 17:45:26 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:        /*
                     67:         * Send CMD0_GO_IDLE_STATE.
                     68:         */
1.2       nbrk       69:        spi_cs_low(ddp->ss_sbhp);
1.1       nbrk       70:        spisdmmc_send_command(ddp, CMD0_GO_IDLE_STATE, 0, CMD0_HARDCODED_CRC);
1.2       nbrk       71:
                     72:        resp = spisdmmc_get_response(ddp);
                     73:
1.3     ! nbrk       74:        if (resp & R1_IN_IDLE_STATE != 1) {
1.1       nbrk       75:                printf("spisdmmc_init: CMD0_GO_IDLE_STATE failed with %d\n", resp);
                     76:
                     77:                return(-1);
                     78:        }
1.2       nbrk       79:        printf("spisdmmc_init: Card replied to CMD0_GO_IDLE_STATE with 0x%x\n", resp);
                     80:
                     81:        /*
                     82:         * Okay. Try to initialize the card.
                     83:         * Periodically send CMD1 and poll for response with 0x01 cleared (card exit Idle state).
                     84:         * CRC is off so we can set it 0xff.
                     85:         * XXX send 0xff before.
                     86:         */
                     87:        do {
1.3     ! nbrk       88:                spi_cs_high(ddp->ss_sbhp);
        !            89:                spi_transmit(ddp->ss_sbhp, 0xff);
        !            90:
        !            91:                spi_cs_low(ddp->ss_sbhp);
        !            92:
1.2       nbrk       93:                spisdmmc_send_command(ddp, CMD1_SEND_OP_COND, 0, 0xff);
                     94:                resp = spisdmmc_get_response(ddp);
                     95:        } while(resp != 0x00);
                     96:
                     97:        printf("spisdmmc_init: Card initialization completed\n");
                     98:
                     99:        /*
                    100:         * Set block size to 512 bytes.
                    101:         */
                    102:        if(spisdmmc_set_block_size(ddp, SDMMC_BLOCK_SIZE) == -1) {
                    103:                printf("spisdmmc_init: failed to set block size\n");
                    104:                return(-1);
                    105:        }
                    106:        printf("spisdmmc_init: block size set to %d\n", SDMMC_BLOCK_SIZE);
1.1       nbrk      107:
1.2       nbrk      108:        spisdmmc_read_cid(ddp, &cid);
                    109:        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]);
1.3     ! nbrk      110:
1.2       nbrk      111:        return(0);
1.1       nbrk      112: }
                    113:
                    114:
                    115: void
                    116: spisdmmc_send_command(struct spisdmmc_dd *ddp, uint8_t cmd, uint32_t arg, uint32_t crc)
                    117: {
                    118:        struct sdmmc_cmdframe sdcf;
                    119:        uint8_t i;
                    120:
                    121:        /* construct frame */
                    122:        sdcf = sdmmc_command(cmd, arg, crc);
                    123:
1.3     ! nbrk      124: //     printf("spisdmmc_send_command: sending cmd %d arg 0x%x crc 0x%x\n", sdcf.sc_cmd & ~0xc0, sdcf.sc_arg, sdcf.sc_crc);
1.2       nbrk      125:        /* transmit cmd */
1.1       nbrk      126:        spi_transmit(ddp->ss_sbhp, sdcf.sc_cmd);
                    127:
                    128:        /* transmit 32 bit argument XXX MSB first */
                    129:        for(i = 0; i < 4; i++)
                    130:                spi_transmit(ddp->ss_sbhp, ((sdcf.sc_arg & (0xff000000 >> i)) >> (8 * (4 - i + 1))) );
                    131:
                    132:        /* transmit CRC field */
1.2       nbrk      133:        spi_transmit(ddp->ss_sbhp, sdcf.sc_crc);
                    134:
                    135:        /* XXX Apply NCR clock pulses */
1.3     ! nbrk      136:        spi_transmit(ddp->ss_sbhp, 0xff);
1.2       nbrk      137: }
                    138:
                    139:
                    140: uint8_t
                    141: spisdmmc_get_response(struct spisdmmc_dd *ddp)
                    142: {
                    143:        uint8_t i, resp;
                    144:        /*
                    145:         * Get response from card.
                    146:         * After command response comes in 8 to 64 pulses (all this bits will be 1).
                    147:         */
                    148:
                    149:        for(i = 0; i < 64; i++) {
                    150:                resp = spi_transmit(ddp->ss_sbhp, 0xff);
                    151:
1.3     ! nbrk      152: //             if (resp == 0 || resp == 1)
        !           153:                if (resp != 0xff)
1.2       nbrk      154:                        return(resp);
                    155:        }
                    156: }
                    157:
                    158: uint8_t
                    159: spisdmmc_get_token(struct spisdmmc_dd *ddp)
                    160: {
                    161:        uint16_t i, token;
                    162:        /*
                    163:         * Get token.
                    164:         */
                    165:
                    166:        for(i = 0; i < 1000; i++) {
                    167:                token = spi_transmit(ddp->ss_sbhp, 0xff);
                    168:
                    169:                if (token == TOK_READ_BLOCK || token == TOK_WRITE_BLOCK_MULTIPLE)
                    170:                        return(token);
                    171:        }
                    172: }
                    173:
1.1       nbrk      174:
1.2       nbrk      175: int
                    176: spisdmmc_set_block_size(struct spisdmmc_dd *ddp, uint16_t blksize)
                    177: {
                    178:        uint8_t resp;
                    179:        /*
                    180:         * Set block size (CMD16).
                    181:         */
                    182:        spisdmmc_send_command(ddp,CMD16_SET_BLOCKLEN, blksize, 0xff);
                    183:        resp = spisdmmc_get_response(ddp);
                    184:        if (resp != 0x00) {
                    185:                printf("spisdmmc_set_block_size: set block size to %d failed (0x%x)\n", blksize, resp);
                    186:                return(-1);
                    187:        }
                    188:        return(0);
1.1       nbrk      189: }
                    190:
1.2       nbrk      191: void
                    192: spisdmmc_read_cid(struct spisdmmc_dd *ddp, struct sdmmc_cid *cidp)
                    193: {
                    194:        uint8_t resp;
                    195:        struct sdmmc_cid cid;
                    196:        /*
                    197:         * Read Card ID register.
                    198:         */
                    199:        spisdmmc_send_command(ddp, CMD10_SEND_CID, 0, 0xff);
                    200:        resp = spisdmmc_get_response(ddp);
                    201:        printf("spisdmmc_read_cid: got r1 response 0x%x\n", resp);
                    202:
                    203:        /*
                    204:         * Wait R1 response.
                    205:         */
                    206:        if (resp != 0x00) {
                    207:                printf("spisdmmc_read_cid: bad response 0x%x\n", resp);
                    208:                return;
                    209:        }
                    210:
                    211:        spisdmmc_read_block(ddp, 16, (char *)&cid);
                    212: }
                    213:
                    214:
                    215: void
                    216: spisdmmc_read_block(struct spisdmmc_dd *ddp, uint16_t nbytes, char *buffp)
                    217: {
                    218:        uint8_t token;
                    219:        uint16_t crc;
                    220:        /*
                    221:         * Read block.
                    222:         */
                    223:        token = spisdmmc_get_token(ddp);
                    224:        printf("spisdmmc_read_block: got token 0x%x\n", token);
                    225:        if (token != TOK_READ_BLOCK) {
                    226:                printf("spisdmmc_read_block: error, foreign token\n");
                    227:                return;
                    228:        }
                    229:        /*
                    230:         * Okay, next is the data.
                    231:         */
                    232:        while(nbytes != 0) {
                    233:                *buffp = spi_transmit(ddp->ss_sbhp, 0xff);
                    234:                printf("byte read 0x%x\n", *buffp);
                    235:
                    236:                buffp++;
                    237:                nbytes--;
                    238:        }
                    239:
                    240:        /*
                    241:         * Read CRC.
                    242:         */
                    243:        crc = spi_transmit(ddp->ss_sbhp, 0xff);
                    244:        crc <<= 8;
                    245:        crc = spi_transmit(ddp->ss_sbhp, 0xff);
                    246: };
1.1       nbrk      247:

CVSweb