static int mmc_spi_command_send(struct mmc_spi_host *host, struct mci_cmd *cmd) { uint8_t r1; uint8_t command[7]; int i; command[0] = 0xff; command[1] = MMC_SPI_CMD(cmd->cmdidx); command[2] = cmd->cmdarg >> 24; command[3] = cmd->cmdarg >> 16; command[4] = cmd->cmdarg >> 8; command[5] = cmd->cmdarg; #ifdef CONFIG_MMC_SPI_CRC_ON command[6] = (crc7(0, &command[1], 5) << 1) | 0x01; #else command[6] = MMC_SPI_CMD0_CRC; #endif mmc_spi_writebytes(host, 7, command); for (i = 0; i < CTOUT; i++) { mmc_spi_readbytes(host, 1, &r1); if (i && ((r1 & 0x80) == 0)) { /* r1 response */ dev_dbg(host->dev, "%s: CMD%d, TRY %d, RESP %x\n", __func__, cmd->cmdidx, i, r1); break; } } return r1; }
//*---------------------------------------------------------------------------- //* Name : ds_read_all_ram() //* Brief : Read all DS18B20 RAM register //* Argument : DS_REG pointer //* Return : Error = -1, OK = 0 //*---------------------------------------------------------------------------- static ds_read_all_ram(DS18B20_REG_T *ds) { int i; uint8 *c = NULL; if(ds == NULL) { return -1; } // reset DS18B20 if(ds_reset() < 0) { return -1; } ds_write_match_rom(ds); ds_write_byte(DS_CMD_READ_RAM); c = &ds->temp_lsb; for(i = 0; i < 9; i ++) { *(c ++) = ds_read_byte(); } // reset DS18B20 if(ds_reset() < 0) { return -1; } // check crc here if(ds->ram_crc7 != crc7(0, &ds->temp_lsb, 8)) { return -1; } // calculate conver time return ds_calculate_conver_time(ds); }
//*---------------------------------------------------------------------------- //* Name : ds_read_all_rom() //* Brief : Read all DS18B20 ROM registers //* Argument : DS_REG pointer //* Return : Error = -1, OK = 0 //*---------------------------------------------------------------------------- static int ds_read_all_rom(DS18B20_REG_T *ds) { int i; if(ds == NULL) { return -1; } // reset DS18B20 if(ds_reset() < 0) { return -1; } // Write commands ds_write_byte(DS_CMD_READ_ROM); // read 8 + 48 + 8 bits ds->ds_id = ds_read_byte(); for(i = 0; i < 6; i++) { ds->serial_num[i] = ds_read_byte(); } ds->rom_crc7 = ds_read_byte(); // check crc7 here if(ds->rom_crc7 != crc7(0, (unsigned char *)ds, 7)) { return -1; } return 0; }
static void wl1251_spi_wake(struct wl1251 *wl) { u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; struct spi_transfer t; struct spi_message m; cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); if (!cmd) { wl1251_error("could not allocate cmd for spi init"); return; } memset(crc, 0, sizeof(crc)); memset(&t, 0, sizeof(t)); spi_message_init(&m); /* * Set WSPI_INIT_COMMAND * the data is being send from the MSB to LSB */ cmd[2] = 0xff; cmd[3] = 0xff; cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX; cmd[0] = 0; cmd[7] = 0; cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3; cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN; if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0) cmd[5] |= WSPI_INIT_CMD_DIS_FIXEDBUSY; else cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY; cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS; crc[0] = cmd[1]; crc[1] = cmd[0]; crc[2] = cmd[7]; crc[3] = cmd[6]; crc[4] = cmd[5]; cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1; cmd[4] |= WSPI_INIT_CMD_END; t.tx_buf = cmd; t.len = WSPI_INIT_CMD_LEN; spi_message_add_tail(&t, &m); spi_sync(wl_to_spi(wl), &m); wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); kfree(cmd); }
static void wl12xx_spi_init(struct device *child) { struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; struct spi_transfer t; struct spi_message m; cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); if (!cmd) { dev_err(child->parent, "could not allocate cmd for spi init\n"); return; } memset(crc, 0, sizeof(crc)); memset(&t, 0, sizeof(t)); spi_message_init(&m); /* * Set WSPI_INIT_COMMAND * the data is being send from the MSB to LSB */ cmd[2] = 0xff; cmd[3] = 0xff; cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX; cmd[0] = 0; cmd[7] = 0; cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3; cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN; if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0) cmd[5] |= WSPI_INIT_CMD_DIS_FIXEDBUSY; else cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY; cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS; crc[0] = cmd[1]; crc[1] = cmd[0]; crc[2] = cmd[7]; crc[3] = cmd[6]; crc[4] = cmd[5]; cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1; cmd[4] |= WSPI_INIT_CMD_END; t.tx_buf = cmd; t.len = WSPI_INIT_CMD_LEN; spi_message_add_tail(&t, &m); spi_sync(to_spi_device(glue->dev), &m); kfree(cmd); }
/** * @brief Sends a command header. * * @param[in] mmcp pointer to the @p MMCDriver object * @param[in] cmd the command id * @param[in] arg the command argument * * @notapi */ static void send_hdr(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) { uint8_t buf[6]; /* Wait for the bus to become idle if a write operation was in progress.*/ wait(mmcp); buf[0] = 0x40 | cmd; buf[1] = arg >> 24; buf[2] = arg >> 16; buf[3] = arg >> 8; buf[4] = arg; /* Calculate CRC for command header, shift to right position, add stop bit.*/ buf[5] = ((crc7(0, buf, 5) & 0x7F) << 1) | 0x01; spiSend(mmcp->config->spip, 6, buf); }
static uint mmc_spi_sendcmd(struct mmc *mmc, ushort cmdidx, u32 cmdarg) { struct spi_slave *spi = mmc->priv; u8 cmdo[7]; u8 r1; int i; cmdo[0] = 0xff; cmdo[1] = MMC_SPI_CMD(cmdidx); cmdo[2] = cmdarg >> 24; cmdo[3] = cmdarg >> 16; cmdo[4] = cmdarg >> 8; cmdo[5] = cmdarg; cmdo[6] = (crc7(0, &cmdo[1], 5) << 1) | 0x01; spi_xfer(spi, sizeof(cmdo) * 8, cmdo, NULL, 0); for (i = 0; i < CTOUT; i++) { spi_xfer(spi, 1 * 8, NULL, &r1, 0); if (i && (r1 & 0x80) == 0) /* r1 response */ break; } debug("%s:cmd%d resp%d %x\n", __func__, cmdidx, i, r1); return r1; }
/* Issue command and read its response. * Returns zero on success, negative for error. * * On error, caller must cope with mmc core retry mechanism. That * means immediate low-level resubmit, which affects the bus lock... */ static int mmc_spi_command_send(struct mmc_spi_host *host, struct mmc_request *mrq, struct mmc_command *cmd, int cs_on) { struct scratch *data = host->data; u8 *cp = data->status; u32 arg = cmd->arg; int status; struct spi_transfer *t; /* We can handle most commands (except block reads) in one full * duplex I/O operation before either starting the next transfer * (data block or command) or else deselecting the card. * * First, write 7 bytes: * - an all-ones byte to ensure the card is ready * - opcode byte (plus start and transmission bits) * - four bytes of big-endian argument * - crc7 (plus end bit) ... always computed, it's cheap * * We init the whole buffer to all-ones, which is what we need * to write while we're reading (later) response data. */ memset(cp++, 0xff, sizeof(data->status)); *cp++ = 0x40 | cmd->opcode; *cp++ = (u8)(arg >> 24); *cp++ = (u8)(arg >> 16); *cp++ = (u8)(arg >> 8); *cp++ = (u8)arg; *cp++ = (crc7(0, &data->status[1], 5) << 1) | 0x01; /* Then, read up to 13 bytes (while writing all-ones): * - N(CR) (== 1..8) bytes of all-ones * - status byte (for all response types) * - the rest of the response, either: * + nothing, for R1 or R1B responses * + second status byte, for R2 responses * + four data bytes, for R3 and R7 responses * * Finally, read some more bytes ... in the nice cases we know in * advance how many, and reading 1 more is always OK: * - N(EC) (== 0..N) bytes of all-ones, before deselect/finish * - N(RC) (== 1..N) bytes of all-ones, before next command * - N(WR) (== 1..N) bytes of all-ones, before data write * * So in those cases one full duplex I/O of at most 21 bytes will * handle the whole command, leaving the card ready to receive a * data block or new command. We do that whenever we can, shaving * CPU and IRQ costs (especially when using DMA or FIFOs). * * There are two other cases, where it's not generally practical * to rely on a single I/O: * * - R1B responses need at least N(EC) bytes of all-zeroes. * * In this case we can *try* to fit it into one I/O, then * maybe read more data later. * * - Data block reads are more troublesome, since a variable * number of padding bytes precede the token and data. * + N(CX) (== 0..8) bytes of all-ones, before CSD or CID * + N(AC) (== 1..many) bytes of all-ones * * In this case we currently only have minimal speedups here: * when N(CR) == 1 we can avoid I/O in response_get(). */ if (cs_on && (mrq->data->flags & MMC_DATA_READ)) { cp += 2; /* min(N(CR)) + status */ /* R1 */ } else { cp += 10; /* max(N(CR)) + status + min(N(RC),N(WR)) */ if (cmd->flags & MMC_RSP_SPI_S2) /* R2/R5 */ cp++; else if (cmd->flags & MMC_RSP_SPI_B4) /* R3/R4/R7 */ cp += 4; else if (cmd->flags & MMC_RSP_BUSY) /* R1B */ cp = data->status + sizeof(data->status); /* else: R1 (most commands) */ } dev_dbg(&host->spi->dev, " mmc_spi: CMD%d, resp %s\n", cmd->opcode, maptype(cmd)); /* send command, leaving chipselect active */ spi_message_init(&host->m); t = &host->t; memset(t, 0, sizeof(*t)); t->tx_buf = t->rx_buf = data->status; t->tx_dma = t->rx_dma = host->data_dma; t->len = cp - data->status; t->cs_change = 1; spi_message_add_tail(t, &host->m); if (host->dma_dev) { host->m.is_dma_mapped = 1; dma_sync_single_for_device(host->dma_dev, host->data_dma, sizeof(*host->data), DMA_BIDIRECTIONAL); } status = spi_sync(host->spi, &host->m); if (host->dma_dev) dma_sync_single_for_cpu(host->dma_dev, host->data_dma, sizeof(*host->data), DMA_BIDIRECTIONAL); if (status < 0) { dev_dbg(&host->spi->dev, " ... write returned %d\n", status); cmd->error = status; return status; } /* after no-data commands and STOP_TRANSMISSION, chipselect off */ return mmc_spi_response_get(host, cmd, cs_on); }