/* One of the critical speed parameters is the amount of data which may *betransferredinonecommand.Ifthisvalueistoolow,theSDcard *controllerhastodomultiplepartialblockwrites(argggh!).With *today(2008)SDcardsthereislittlespeedgainifwetransfermore *than64KBytesatatime.Sousethisvalueuntilthereisanyindication *thatweshoulddomorehere.
*/ #define MMC_SPI_BLOCKSATONCE 128
/* for bulk data transfers */ struct spi_transfer token, t, crc, early_status; struct spi_message m;
/* for status readback */ struct spi_transfer status; struct spi_message readback;
/* buffer used for commands and for message "overhead" */ struct scratch *data;
/* Specs say to write ones most of the time, even when the card *hasnoneedtoreaditsinputdata;andmanycardswon'tcare. *Thisisoursourceofthoseones.
*/ void *ones;
};
staticchar *maptype(struct mmc_command *cmd)
{ switch (mmc_spi_resp_type(cmd)) { case MMC_RSP_SPI_R1: return"R1"; case MMC_RSP_SPI_R1B: return"R1B"; case MMC_RSP_SPI_R2: return"R2/R5"; case MMC_RSP_SPI_R3: return"R3/R4/R7"; default: return"?";
}
}
/* return zero, else negative errno after setting cmd->error */ staticint mmc_spi_response_get(struct mmc_spi_host *host, struct mmc_command *cmd, int cs_on)
{ unsignedlong timeout_ms;
u8 *cp = host->data->status;
u8 *end = cp + host->t.len; int value = 0; int bitshift;
u8 leftover = 0; unsignedshort rotator; int i;
/* Except for data block reads, the whole response will already *bestoredinthescratchbuffer.It'ssomewhereafterthe *commandandthefirstbytewereadafterit.Weignorethat *firstbyte.AfterSTOP_TRANSMISSIONcommanditmayinclude *twodatabits,butotherwiseit'sallones.
*/
cp += 8; while (cp < end && *cp == 0xff)
cp++;
/* Data block reads (R1 response types) may need more data... */ if (cp == end) {
cp = host->data->status;
end = cp+1;
/* Card sends N(CR) (== 1..8) bytes of all-ones then one *statusbyte...andwealreadyscanned2bytes. * *REVISITblockreadpathsusenastybyte-at-a-timeI/O *soitcanalwaysDMAdirectlyintothetargetbuffer. *It'dprobablybebettertomemcpy()thefirstchunkand *avoidextrai/ocalls... * *Notewecheckformorethan8bytes,becauseinpractice, *someSDcardsareslow...
*/ for (i = 2; i < 16; i++) {
value = mmc_spi_readbytes(host, 1); if (value < 0) goto done; if (*cp != 0xff) goto checkstatus;
}
value = -ETIMEDOUT; goto done;
}
checkstatus:
bitshift = 0; if (*cp & 0x80) { /* Houston, we have an ugly card with a bit-shifted response */
rotator = *cp++ << 8; /* read the next byte */ if (cp == end) {
value = mmc_spi_readbytes(host, 1); if (value < 0) goto done;
cp = host->data->status;
end = cp+1;
}
rotator |= *cp++; while (rotator & 0x8000) {
bitshift++;
rotator <<= 1;
}
cmd->resp[0] = rotator >> 8;
leftover = rotator;
} else {
cmd->resp[0] = *cp++;
}
cmd->error = 0;
/* Status byte: the entire seven-bit R1 response. */ if (cmd->resp[0] != 0) { if ((R1_SPI_PARAMETER | R1_SPI_ADDRESS)
& cmd->resp[0])
value = -EFAULT; /* Bad address */ elseif (R1_SPI_ILLEGAL_COMMAND & cmd->resp[0])
value = -ENOSYS; /* Function not implemented */ elseif (R1_SPI_COM_CRC & cmd->resp[0])
value = -EILSEQ; /* Illegal byte sequence */ elseif ((R1_SPI_ERASE_SEQ | R1_SPI_ERASE_RESET)
& cmd->resp[0])
value = -EIO; /* I/O error */ /* else R1_SPI_IDLE, "it's resetting" */
}
switch (mmc_spi_resp_type(cmd)) {
/* SPI R1B == R1 + busy; STOP_TRANSMISSION (for multiblock reads) *andless-commonstufflikevariouseraseoperations.
*/ case MMC_RSP_SPI_R1B: /* maybe we read all the busy tokens already */ while (cp < end && *cp == 0)
cp++; if (cp == end) {
timeout_ms = cmd->busy_timeout ? cmd->busy_timeout :
MMC_SPI_R1B_TIMEOUT_MS;
mmc_spi_wait_unbusy(host, msecs_to_jiffies(timeout_ms));
} break;
/* SPI R2 == R1 + second status byte; SEND_STATUS *SPIR5==R1+databyte;IO_RW_DIRECT
*/ case MMC_RSP_SPI_R2: /* read the next byte */ if (cp == end) {
value = mmc_spi_readbytes(host, 1); if (value < 0) goto done;
cp = host->data->status;
end = cp+1;
} if (bitshift) {
rotator = leftover << 8;
rotator |= *cp << bitshift;
cmd->resp[0] |= (rotator & 0xFF00);
} else {
cmd->resp[0] |= *cp << 8;
} break;
/* SPI R3, R4, or R7 == R1 + 4 bytes */ case MMC_RSP_SPI_R3:
rotator = leftover << 8;
cmd->resp[1] = 0; for (i = 0; i < 4; i++) {
cmd->resp[1] <<= 8; /* read the next byte */ if (cp == end) {
value = mmc_spi_readbytes(host, 1); if (value < 0) goto done;
cp = host->data->status;
end = cp+1;
} if (bitshift) {
rotator |= *cp++ << bitshift;
cmd->resp[1] |= (rotator >> 8);
rotator <<= 8;
} else {
cmd->resp[1] |= *cp++;
}
} break;
/* SPI R1 == just one status byte */ case MMC_RSP_SPI_R1: break;
default:
dev_dbg(&host->spi->dev, "bad response type %04x\n",
mmc_spi_resp_type(cmd)); if (value >= 0)
value = -EINVAL; goto done;
}
/* disable chipselect on errors and some success cases */ if (value >= 0 && cs_on) return value;
done: if (value < 0)
cmd->error = value;
mmc_cs_off(host); return value;
}
/* Issue command and read its response. *Returnszeroonsuccess,negativeforerror. * *Onerror,callermustcopewithmmccoreretrymechanism.That *meansimmediatelow-levelresubmit,whichaffectsthebuslock...
*/ staticint
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; int status; struct spi_transfer *t;
/* We can handle most commands (except block reads) in one full *duplexI/Ooperationbeforeeitherstartingthenexttransfer *(datablockorcommand)orelsedeselectingthecard. * *First,write7bytes: *-anall-onesbytetoensurethecardisready *-opcodebyte(plusstartandtransmissionbits) *-fourbytesofbig-endianargument *-crc7(plusendbit)...alwayscomputed,it'scheap * *Weinitthewholebuffertoall-ones,whichiswhatweneed *towritewhilewe'rereading(later)responsedata.
*/
memset(cp, 0xff, sizeof(data->status));
status = spi_sync_locked(host->spi, &host->m); 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);
}
/* Build data message with up to four separate transfers. For TX, we *startbywritingthedatatoken.Andinmostcases,wefinishwith *astatustransfer. * *WealwaysprovideTXdatafordataandCRC.TheMMC/SDprotocol *requiresustowriteones;butLinuxdefaultstowritingzeroes; *soweexplicitlyinitializeittoallonesonRXpaths.
*/ staticvoid
mmc_spi_setup_data_message(struct mmc_spi_host *host, bool multiple, bool write)
{ struct spi_transfer *t; struct scratch *scratch = host->data;
spi_message_init(&host->m);
/* for reads, readblock() skips 0xff bytes before finding *thetoken;forwrites,thistransferissuesthattoken.
*/ if (write) {
t = &host->token;
memset(t, 0, sizeof(*t));
t->len = 1; if (multiple)
scratch->data_token = SPI_TOKEN_MULTI_WRITE; else
scratch->data_token = SPI_TOKEN_SINGLE;
t->tx_buf = &scratch->data_token;
spi_message_add_tail(t, &host->m);
}
/* Body of transfer is buffer, then CRC ... *eitherTX-only,orRXwithTX-ones.
*/
t = &host->t;
memset(t, 0, sizeof(*t));
t->tx_buf = host->ones; /* length and actual buffer info are written later */
spi_message_add_tail(t, &host->m);
t = &host->crc;
memset(t, 0, sizeof(*t));
t->len = 2; if (write) { /* the actual CRC may get written later */
t->tx_buf = &scratch->crc_val;
} else {
t->tx_buf = host->ones;
t->rx_buf = &scratch->crc_val;
}
spi_message_add_tail(t, &host->m);
/* First 3 bit of pattern are undefined */
pattern |= 0xE0000000;
/* left-adjust to leading 0 bit */ while (pattern & 0x80000000)
pattern <<= 1; /* right-adjust for pattern matching. Code is in bit 4..0 now. */
pattern >>= 27;
switch (pattern) { case SPI_RESPONSE_ACCEPTED:
status = 0; break; case SPI_RESPONSE_CRC_ERR: /* host shall then issue MMC_STOP_TRANSMISSION */
status = -EILSEQ; break; case SPI_RESPONSE_WRITE_ERR: /* host shall then issue MMC_STOP_TRANSMISSION, *andshouldMMC_SEND_STATUStosortitout
*/
status = -EIO; break; default:
status = -EPROTO; break;
} if (status != 0) {
dev_dbg(&spi->dev, "write error %02x (%d)\n",
scratch->status[0], status); return status;
}
t->tx_buf += t->len;
/* Return when not busy. If we didn't collect that status yet, *we'llneedsomemoreI/O.
*/ for (i = 4; i < sizeof(scratch->status); i++) { /* card is non-busy if the most recent bit is 1 */ if (scratch->status[i] & 0x01) return0;
} return mmc_spi_wait_unbusy(host, timeout);
}
/* At least one SD card sends an all-zeroes byte when N(CX) *applies,beforetheall-onesbytes...justcopewiththat.
*/
status = mmc_spi_readbytes(host, 1); if (status < 0) return status;
status = scratch->status[0]; if (status == 0xff || status == 0)
status = mmc_spi_readtoken(host, timeout);
/* The token may be bit-shifted... *thefirst0-bitprecedesthedatastream.
*/
bitshift = 7; while (status & 0x80) {
status <<= 1;
bitshift--;
}
leftover = status << 1;
status = spi_sync_locked(spi, &host->m); if (status < 0) {
dev_dbg(&spi->dev, "read error %d\n", status); return status;
}
if (bitshift) { /* Walk through the data and the crc and do *allthemagictogetbyte-aligneddata.
*/
u8 *cp = t->rx_buf; unsignedint len; unsignedint bitright = 8 - bitshift;
u8 temp; for (len = t->len; len; len--) {
temp = *cp;
*cp++ = leftover | (temp >> bitshift);
leftover = temp << bitright;
}
cp = (u8 *) &scratch->crc_val;
temp = *cp;
*cp++ = leftover | (temp >> bitshift);
leftover = temp << bitright;
temp = *cp;
*cp = leftover | (temp >> bitshift);
}
if (host->mmc->use_spi_crc) {
u16 crc = crc_itu_t(0, t->rx_buf, t->len);
/* Handle scatterlist segments one at a time, with synch for *each512-byteblock
*/
for_each_sg(data->sg, sg, data->sg_len, n_sg) { int status = 0; void *kmap_addr; unsigned length = sg->length;
/* allow pio too; we don't allow highmem */
kmap_addr = kmap(sg_page(sg)); if (write)
t->tx_buf = kmap_addr + sg->offset; else
t->rx_buf = kmap_addr + sg->offset;
/* transfer each block, and update request status */ while (length) {
t->len = min(length, blk_size);
if (write)
status = mmc_spi_writeblock(host, t, timeout); else
status = mmc_spi_readblock(host, t, timeout); if (status < 0) break;
data->bytes_xfered += t->len;
length -= t->len;
if (!multiple) break;
}
/* discard mappings */ if (write) /* nothing to do */; else
flush_dcache_page(sg_page(sg));
kunmap(sg_page(sg));
if (status < 0) {
data->error = status;
dev_dbg(&spi->dev, "%s status %d\n", write_or_read, status); break;
}
}
/* NOTE some docs describe an MMC-only SET_BLOCK_COUNT (CMD23) that *canbeissuedbeforemultiblockwrites.Unlikeitsmorewidely *documentedanalogueforSDcards(SET_WR_BLK_ERASE_COUNT,ACMD23), *thatcanaffecttheSTOP_TRANlogic.Complete(andcurrent) *MMCspecsshouldsortthatoutbeforeLinuxstartsusingCMD23.
*/ if (write && multiple) { struct scratch *scratch = host->data; int tmp; constunsigned statlen = sizeof(scratch->status);
dev_dbg(&spi->dev, " STOP_TRAN\n");
/* Tweak the per-block message we set up earlier by morphing *ittoholdsinglebufferwiththetokenfollowedbysome *all-onesbytes...skipN(BR)(0..1),scantherestfor *"notbusyanylonger"status,andleavechipselected.
*/
INIT_LIST_HEAD(&host->m.transfers);
list_add(&host->early_status.transfer_list,
&host->m.transfers);
if (mrq->stop)
status = mmc_spi_command_send(host, mrq, mrq->stop, 0); else
mmc_cs_off(host);
}
/* release the bus */
spi_bus_unlock(host->spi->controller);
mmc_request_done(host->mmc, mrq);
}
/* See Section 6.4.1, in SD "Simplified Physical Layer Specification 2.0" * *NOTEthatherewecan'tknowthatthecardhasjustbeenpoweredup; *notallMMC/SDsocketssupportpowerswitching. * *FIXMEwhenthecardisstillinSPImode,e.g.fromapreviouskernel, *thisdoesn'tseemtodotherightthingatall...
*/ staticvoid mmc_spi_initsequence(struct mmc_spi_host *host)
{ /* Try to be very sure any previous command has completed; *waittillnot-busy,skipdebrisfromanyoldcommands.
*/
mmc_spi_wait_unbusy(host, msecs_to_jiffies(MMC_SPI_INIT_TIMEOUT_MS));
mmc_spi_readbytes(host, 10);
/* *Doaburstwithchipselectactive-high.Weneedtodothisto *meettherequirementof74clockcycleswithbothchipselect *andCMD(MOSI)highbeforeCMD0...afterthecardhasbeen *powereduptoVdd(min),andsoisreadytotakecommands. * *Somecardsareparticularlyneedyofthis(e.g.Viking"SD256") *whilemostothersdon'tseemtocare. * *NotethatthisisoneoftheplacesMMC/SDplaysgameswiththe *SPIprotocol.Anotheristhatwhenchipselectisreleasedwhile *thecardreturnsBUSYstatus,theclockmustissueseveralcycles *withchipselecthighbeforethecardwillstopdrivingitsoutput. * *SPI_CS_HIGHmeans"asserted"here.Insomecaseslikewhenusing *GPIOsforchipselect,SPI_CS_HIGHissetbutthiswillbelogically *invertedbygpiolib,soifwewanttoascertaintodriveithigh *weshouldtogglethedefaultwithanXORaswedohere.
*/
host->spi->mode ^= SPI_CS_HIGH; if (spi_setup(host->spi) != 0) { /* Just warn; most cards work without it. */
dev_warn(&host->spi->dev, "can't change chip-select polarity\n");
host->spi->mode ^= SPI_CS_HIGH;
} else {
mmc_spi_readbytes(host, 18);
host->spi->mode ^= SPI_CS_HIGH; if (spi_setup(host->spi) != 0) { /* Wot, we can't get the same setup we had before? */
dev_err(&host->spi->dev, "can't restore chip-select polarity\n");
}
}
}
staticchar *mmc_powerstring(u8 power_mode)
{ switch (power_mode) { case MMC_POWER_OFF: return"off"; case MMC_POWER_UP: return"up"; case MMC_POWER_ON: return"on";
} return"?";
}
/* switch power on/off if possible, accounting for *max250msecpoweruptimeifneeded.
*/ if (canpower) { switch (ios->power_mode) { case MMC_POWER_OFF: case MMC_POWER_UP:
host->pdata->setpower(&host->spi->dev,
ios->vdd); if (ios->power_mode == MMC_POWER_UP)
msleep(host->powerup_msecs);
}
}
/* See 6.4.1 in the simplified SD card physical spec 2.0 */ if (ios->power_mode == MMC_POWER_ON)
mmc_spi_initsequence(host);
/* If powering down, ground all card inputs to avoid power *deliveryfromdatalines!OnasharedSPIbus,this *willprobablybetemporary;6.4.2ofthesimplifiedSD *specsaysthismustlastatleast1msec. * *-ClocklowmeansCPOL0,e.g.mode0 *-MOSIlowcomesfromwritingzero *-Chipselectisusuallyactivelow...
*/ if (canpower && ios->power_mode == MMC_POWER_OFF) { int mres;
u8 nullbyte = 0;
host->spi->mode &= ~(SPI_CPOL|SPI_CPHA);
mres = spi_setup(host->spi); if (mres < 0)
dev_dbg(&host->spi->dev, "switch to SPI mode 0 failed\n");
if (spi_write(host->spi, &nullbyte, 1) < 0)
dev_dbg(&host->spi->dev, "put spi signals to low failed\n");
/* *Nowclockshouldbelowduetospimode0; *MOSIshouldbelowbecauseofwritten0x00; *chipselectshouldbelow(itisactivelow) *powersupplyisoff,sonowMMCisofftoo! * *FIXMEno,chipselectcanbehighsincethe *deviceisinactiveandSPI_CS_HIGHisclear...
*/
msleep(10); if (mres == 0) {
host->spi->mode |= (SPI_CPOL|SPI_CPHA);
mres = spi_setup(host->spi); if (mres < 0)
dev_dbg(&host->spi->dev, "switch back to SPI mode 3 failed\n");
}
}
host->power_mode = ios->power_mode;
}
if (host->spi->max_speed_hz != ios->clock && ios->clock != 0) { int status;
host->spi->max_speed_hz = ios->clock;
status = spi_setup(host->spi);
dev_dbg(&host->spi->dev, " clock to %d Hz, %d\n",
host->spi->max_speed_hz, status);
}
}
/* We rely on full duplex transfers, mostly to reduce *per-transferoverheads(bymakingfewertransfers).
*/ if (spi->controller->flags & SPI_CONTROLLER_HALF_DUPLEX) return -EINVAL;
/* MMC and SD specs only seem to care that sampling is on the *risingedge...meaningSPImodes0or3.SoeitherSPImode *shouldbelegit.We'llusemode0sincethesteadystateis0, *whichisappropriateforhotplugging,unlesstheplatformdata *specifymode3(ifhardwareisnotcompatibletomode0).
*/ if (spi->mode != SPI_MODE_3)
spi->mode = SPI_MODE_0;
spi->bits_per_word = 8;
/* We need a supply of ones to transmit. This is the only time *theCPUtouchesthese,socachecoherencyisn'taconcern. * *NOTEifmanysystemsusemorethanoneMMC-over-SPIconnector *it'dsavesomememorytosharethis.That'sevidentlyrare.
*/
status = -ENOMEM;
ones = kmalloc(MMC_SPI_BLOCKSIZE, GFP_KERNEL); if (!ones) goto nomem;
memset(ones, 0xff, MMC_SPI_BLOCKSIZE);
mmc = devm_mmc_alloc_host(&spi->dev, sizeof(*host)); if (!mmc) goto nomem;
/* SPI doesn't need the lowspeed device identification thing for *MMCorSDcards,sinceitnevercomesupinopendrainmode. *That'sgood;someSPImasterscan'thandleverylowspeeds! * *However,lowspeedSDIOcardsneednothandleover400KHz; *that'stheonlyreasonnottouseafewMHzforf_min(until *theupperlayerreadsthetargetfrequencyfromtheCSD).
*/ if (spi->controller->min_speed_hz > 400000)
dev_warn(&spi->dev,"Controller unable to reduce bus clock to 400 KHz\n");
/* Platform data is used to hook up things like card sensing *andpowerswitchinggpios.
*/
host->pdata = mmc_spi_get_pdata(spi); if (host->pdata)
mmc->ocr_avail = host->pdata->ocr_mask; if (!mmc->ocr_avail) {
dev_warn(&spi->dev, "ASSUMING 3.2-3.4 V slot power\n");
mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
} if (host->pdata && host->pdata->setpower) {
host->powerup_msecs = host->pdata->powerup_msecs; if (!host->powerup_msecs || host->powerup_msecs > 250)
host->powerup_msecs = 250;
}
/* Index 1 is write protect/read only */
status = mmc_gpiod_request_ro(mmc, NULL, 1, 0); if (status == -EPROBE_DEFER) goto fail_gpiod_request; if (!status)
has_ro = true;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.