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