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

1.1       nbrk        1: /*
1.4     ! nbrk        2:  * $Id: sdmmc_spi.c,v 1.3 2007/12/24 15:49:40 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:
1.4     ! nbrk       11: #define SPISDMMC_DEBUG
        !            12:
        !            13: #ifdef SPISDMMC_DEBUG
        !            14: #define DPRINTF(x...)  do { printf(x); } while (0)
        !            15: #else
        !            16: #define DPRINTF(x...)  { }
        !            17: #endif
        !            18:
        !            19: #define SPISDMMC_RESP_TIMEOUT 64
        !            20:
1.1       nbrk       21: /*
                     22:  * SD/MMC conversation over SPI bus.
                     23:  */
                     24: struct spisdmmc_dd {
                     25:        struct spi_bus_handle *ss_sbhp;
                     26:
1.4     ! nbrk       27:        struct sdmmc_bus_handle ss_smbh;
1.1       nbrk       28: };
                     29:
1.4     ! nbrk       30: int            spisdmmc_attach(struct device *, uint32_t, uint8_t);
        !            31: uint8_t                spisdmmc_init(void *dd);
        !            32: uint8_t        spisdmmc_send_command(void *dd, uint8_t cmd, uint32_t arg, uint8_t crc);
        !            33: uint8_t        spisdmmc_set_block_size(void *dd, uint16_t size);
        !            34: uint8_t        spisdmmc_read_block(void *dd, uint32_t addr, char *buffp);
1.2       nbrk       35:
                     36:
1.1       nbrk       37:
                     38: struct driver spisdmmc_dr = {
                     39:        sizeof(struct spisdmmc_dd),
                     40:        spisdmmc_attach,
                     41:        NULL,
                     42:        NULL
                     43: };
                     44:
                     45:
                     46: int
                     47: spisdmmc_attach(struct device *self, uint32_t loc, uint8_t flags)
                     48: {
                     49:        struct spisdmmc_dd *ddp = self->dv_devdata;
                     50:        ddp->ss_sbhp = self->dv_parent->dv_aux;
                     51:
                     52:        printf("SPI SD/MMC\n");
                     53:
1.4     ! nbrk       54:        /*
        !            55:         * Interface to children.
        !            56:         */
        !            57:        ddp->ss_smbh.sb_init = spisdmmc_init;
        !            58:        ddp->ss_smbh.sb_send_command = spisdmmc_send_command;
        !            59:        ddp->ss_smbh.sb_set_block_size = spisdmmc_set_block_size;
        !            60: //     ddp->ss_smbh.sb_read_block = spisdmmc_read_block;
        !            61: //     ddp->ss_smbh.sb_write_block = spisdmmc_write_block;
        !            62:        ddp->ss_smbh.sb_dd = ddp;
        !            63:
        !            64:        self->dv_aux = &ddp->ss_smbh;
1.2       nbrk       65:
1.1       nbrk       66:        return(0);
                     67: }
                     68:
                     69:
1.4     ! nbrk       70: uint8_t
        !            71: spisdmmc_init(void *dd)
1.1       nbrk       72: {
1.4     ! nbrk       73:        struct spisdmmc_dd *ddp = dd;
1.1       nbrk       74:        uint8_t i, resp;
                     75:        /*
1.4     ! nbrk       76:         * Initialize SD/MMC card so it can accept generic read/write commands.
        !            77:         * Remember that we should hold CS signal low during all transactions (cmd, resp, data).
1.1       nbrk       78:         */
1.4     ! nbrk       79:
        !            80:        /* CS high */
1.2       nbrk       81:        spi_cs_high(ddp->ss_sbhp);
1.4     ! nbrk       82:        /* wait 80 pulses */
        !            83:        for (i =0; i < 9; i++)
1.3       nbrk       84:                spi_transmit(ddp->ss_sbhp, 0xff);
                     85:
1.2       nbrk       86:        /*
1.4     ! nbrk       87:         * Send CMD0_GO_IDLE_STATE
        !            88:         * CS line will go low in send_command and up before return here.
1.2       nbrk       89:         */
1.4     ! nbrk       90:        resp = spisdmmc_send_command(ddp, CMD0_GO_IDLE_STATE, 0, 0x95);
        !            91:        printf("spisdmmc_init: CMD0 reply 0x%x\n", resp);
1.3       nbrk       92:
1.2       nbrk       93:        return(0);
1.1       nbrk       94: }
                     95:
                     96:
1.4     ! nbrk       97: uint8_t
        !            98: spisdmmc_send_command(void *dd, uint8_t cmd, uint32_t arg, uint8_t crc)
1.1       nbrk       99: {
1.4     ! nbrk      100:        struct spisdmmc_dd *ddp = dd;
        !           101:        uint8_t resp;
        !           102:        /*
        !           103:         * Construct command frame and send command to the card.
        !           104:         * Try to read reply SASPI_RESP_TIMEOUT times and return it if it's R1 response.
        !           105:         * Return 255 if timeout.
        !           106:         */
1.1       nbrk      107:        struct sdmmc_cmdframe sdcf;
1.4     ! nbrk      108:        uint8_t to = 0;
1.1       nbrk      109:
                    110:        /* construct frame */
                    111:        sdcf = sdmmc_command(cmd, arg, crc);
                    112:
1.3       nbrk      113: //     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.4     ! nbrk      114:        /* CS low */
        !           115:        spi_cs_low(ddp->ss_sbhp);
        !           116:
1.2       nbrk      117:        /* transmit cmd */
1.1       nbrk      118:        spi_transmit(ddp->ss_sbhp, sdcf.sc_cmd);
                    119:
1.4     ! nbrk      120:        /* transmit 32 bit argument MSB first */
        !           121:        spi_transmit(ddp->ss_sbhp, sdcf.sc_arg >> 24 );
        !           122:        spi_transmit(ddp->ss_sbhp, sdcf.sc_arg >> 16 );
        !           123:        spi_transmit(ddp->ss_sbhp, sdcf.sc_arg >> 8 );
        !           124:        spi_transmit(ddp->ss_sbhp, sdcf.sc_arg );
1.1       nbrk      125:
                    126:        /* transmit CRC field */
1.2       nbrk      127:        spi_transmit(ddp->ss_sbhp, sdcf.sc_crc);
                    128:
1.4     ! nbrk      129:        /* CS high */
        !           130:        spi_cs_high(ddp->ss_sbhp);
        !           131:
1.2       nbrk      132:        /* XXX Apply NCR clock pulses */
1.3       nbrk      133:        spi_transmit(ddp->ss_sbhp, 0xff);
1.2       nbrk      134:
1.4     ! nbrk      135:        /* CS low */
        !           136:        spi_cs_low(ddp->ss_sbhp);
1.2       nbrk      137:
1.4     ! nbrk      138:        /* read response */
        !           139:        /* XXX what about non-R1 responses? */
        !           140:        while(to < SPISDMMC_RESP_TIMEOUT) {
        !           141:                resp = spi_transmit(ddp->ss_sbhp, 0xff);
1.2       nbrk      142:
1.4     ! nbrk      143: //             if (resp & 0x80 == 0) {
        !           144:                if (resp != 0xff) {
        !           145:                        /* seems like R1 response */
        !           146:                        spi_cs_high(ddp->ss_sbhp);
1.2       nbrk      147:
                    148:                        return(resp);
1.4     ! nbrk      149:                }
        !           150:
        !           151:                to++;
1.2       nbrk      152:        }
                    153:
1.4     ! nbrk      154:        /* timeout */
        !           155:        spi_cs_high(ddp->ss_sbhp);
1.2       nbrk      156:
1.4     ! nbrk      157:        DPRINTF("spisdmmc_send_command: response timeout for cmd %d arg 0x%x crc 0x%x\n", cmd, arg, crc);
1.2       nbrk      158:
1.4     ! nbrk      159:        return(0xff);   /* error */
1.2       nbrk      160: }
                    161:
1.1       nbrk      162:
1.4     ! nbrk      163: uint8_t
        !           164: spisdmmc_set_block_size(void *dd, uint16_t blksize)
1.2       nbrk      165: {
1.4     ! nbrk      166:        struct spisdmmc_dd *ddp = dd;
1.2       nbrk      167:        uint8_t resp;
                    168:        /*
                    169:         * Set block size (CMD16).
                    170:         */
1.4     ! nbrk      171:
1.2       nbrk      172:        return(0);
1.1       nbrk      173: }
                    174:
1.2       nbrk      175:
1.4     ! nbrk      176: uint8_t
        !           177: spisdmmc_read_block(void *dd, uint32_t addr, char *buff)
1.2       nbrk      178: {
1.4     ! nbrk      179:        struct spisdmmc_dd *ddp = dd;
1.2       nbrk      180:        /*
                    181:         * Read block.
                    182:         */
                    183: };
1.1       nbrk      184:

CVSweb