/* * $Id: sdmmc_spi.c,v 1.1 2007/12/20 15:23:15 nbrk Exp $ */ #include #include #include #include #include /* * SD/MMC conversation over SPI bus. */ struct spisdmmc_dd { struct spi_bus_handle *ss_sbhp; // struct sdmmc_bus_handle; }; int spisdmmc_attach(struct device *, uint32_t, uint8_t); struct driver spisdmmc_dr = { sizeof(struct spisdmmc_dd), spisdmmc_attach, NULL, NULL }; int spisdmmc_attach(struct device *self, uint32_t loc, uint8_t flags) { struct spisdmmc_dd *ddp = self->dv_devdata; ddp->ss_sbhp = self->dv_parent->dv_aux; printf("SPI SD/MMC\n"); return(0); } int spisdmmc_init(struct spisdmmc_dd *ddp) { uint8_t i, resp; /* * Apply 80 clock pulses. * XXX assert CS. (NPCS0) */ for (i = 0; i < 9; i++) spi_transmit(ddp->ss_sbhp, 0xff); /* * Apply 16 clocks. * XXX deassert CS. */ for (i = 0; i < 2; i ++) spi_transmit(ddp->ss_sbhp, 0xff); /* * Send CMD0_GO_IDLE_STATE. */ spisdmmc_send_command(ddp, CMD0_GO_IDLE_STATE, 0, CMD0_HARDCODED_CRC); if (spisdmmc_get_response(ddp) != 0) { printf("spisdmmc_init: CMD0_GO_IDLE_STATE failed with %d\n", resp); return(-1); } } void spisdmmc_send_command(struct spisdmmc_dd *ddp, uint8_t cmd, uint32_t arg, uint32_t crc) { struct sdmmc_cmdframe sdcf; uint8_t i; /* construct frame */ sdcf = sdmmc_command(cmd, arg, crc); /* transmit token */ spi_transmit(ddp->ss_sbhp, sdcf.sc_cmd); /* transmit 32 bit argument XXX MSB first */ for(i = 0; i < 4; i++) spi_transmit(ddp->ss_sbhp, ((sdcf.sc_arg & (0xff000000 >> i)) >> (8 * (4 - i + 1))) ); /* transmit CRC field */ spi_transmit(ddp->ss_sbhp, sdcf.sc_cmd) }