in host/mmc_spi.c [1314:1489]
static int mmc_spi_probe(struct spi_device *spi)
{
void *ones;
struct mmc_host *mmc;
struct mmc_spi_host *host;
int status;
bool has_ro = false;
/* We rely on full duplex transfers, mostly to reduce
* per-transfer overheads (by making fewer transfers).
*/
if (spi->master->flags & SPI_MASTER_HALF_DUPLEX)
return -EINVAL;
/* MMC and SD specs only seem to care that sampling is on the
* rising edge ... meaning SPI modes 0 or 3. So either SPI mode
* should be legit. We'll use mode 0 since the steady state is 0,
* which is appropriate for hotplugging, unless the platform data
* specify mode 3 (if hardware is not compatible to mode 0).
*/
if (spi->mode != SPI_MODE_3)
spi->mode = SPI_MODE_0;
spi->bits_per_word = 8;
status = spi_setup(spi);
if (status < 0) {
dev_dbg(&spi->dev, "needs SPI mode %02x, %d KHz; %d\n",
spi->mode, spi->max_speed_hz / 1000,
status);
return status;
}
/* We need a supply of ones to transmit. This is the only time
* the CPU touches these, so cache coherency isn't a concern.
*
* NOTE if many systems use more than one MMC-over-SPI connector
* it'd save some memory to share this. That's evidently rare.
*/
status = -ENOMEM;
ones = kmalloc(MMC_SPI_BLOCKSIZE, GFP_KERNEL);
if (!ones)
goto nomem;
memset(ones, 0xff, MMC_SPI_BLOCKSIZE);
mmc = mmc_alloc_host(sizeof(*host), &spi->dev);
if (!mmc)
goto nomem;
mmc->ops = &mmc_spi_ops;
mmc->max_blk_size = MMC_SPI_BLOCKSIZE;
mmc->max_segs = MMC_SPI_BLOCKSATONCE;
mmc->max_req_size = MMC_SPI_BLOCKSATONCE * MMC_SPI_BLOCKSIZE;
mmc->max_blk_count = MMC_SPI_BLOCKSATONCE;
mmc->caps = MMC_CAP_SPI;
/* SPI doesn't need the lowspeed device identification thing for
* MMC or SD cards, since it never comes up in open drain mode.
* That's good; some SPI masters can't handle very low speeds!
*
* However, low speed SDIO cards need not handle over 400 KHz;
* that's the only reason not to use a few MHz for f_min (until
* the upper layer reads the target frequency from the CSD).
*/
mmc->f_min = 400000;
mmc->f_max = spi->max_speed_hz;
host = mmc_priv(mmc);
host->mmc = mmc;
host->spi = spi;
host->ones = ones;
dev_set_drvdata(&spi->dev, mmc);
/* Platform data is used to hook up things like card sensing
* and power switching gpios.
*/
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;
}
/* preallocate dma buffers */
host->data = kmalloc(sizeof(*host->data), GFP_KERNEL);
if (!host->data)
goto fail_nobuf1;
status = mmc_spi_dma_alloc(host);
if (status)
goto fail_dma;
/* setup message for status/busy readback */
spi_message_init(&host->readback);
host->readback.is_dma_mapped = (host->dma_dev != NULL);
spi_message_add_tail(&host->status, &host->readback);
host->status.tx_buf = host->ones;
host->status.tx_dma = host->ones_dma;
host->status.rx_buf = &host->data->status;
host->status.rx_dma = host->data_dma + offsetof(struct scratch, status);
host->status.cs_change = 1;
/* register card detect irq */
if (host->pdata && host->pdata->init) {
status = host->pdata->init(&spi->dev, mmc_spi_detect_irq, mmc);
if (status != 0)
goto fail_glue_init;
}
/* pass platform capabilities, if any */
if (host->pdata) {
mmc->caps |= host->pdata->caps;
mmc->caps2 |= host->pdata->caps2;
}
status = mmc_add_host(mmc);
if (status != 0)
goto fail_add_host;
/*
* Index 0 is card detect
* Old boardfiles were specifying 1 ms as debounce
*/
status = mmc_gpiod_request_cd(mmc, NULL, 0, false, 1000);
if (status == -EPROBE_DEFER)
goto fail_add_host;
if (!status) {
/*
* The platform has a CD GPIO signal that may support
* interrupts, so let mmc_gpiod_request_cd_irq() decide
* if polling is needed or not.
*/
mmc->caps &= ~MMC_CAP_NEEDS_POLL;
mmc_gpiod_request_cd_irq(mmc);
}
mmc_detect_change(mmc, 0);
/* Index 1 is write protect/read only */
status = mmc_gpiod_request_ro(mmc, NULL, 1, 0);
if (status == -EPROBE_DEFER)
goto fail_add_host;
if (!status)
has_ro = true;
dev_info(&spi->dev, "SD/MMC host %s%s%s%s%s\n",
dev_name(&mmc->class_dev),
host->dma_dev ? "" : ", no DMA",
has_ro ? "" : ", no WP",
(host->pdata && host->pdata->setpower)
? "" : ", no poweroff",
(mmc->caps & MMC_CAP_NEEDS_POLL)
? ", cd polling" : "");
return 0;
fail_add_host:
mmc_remove_host(mmc);
fail_glue_init:
mmc_spi_dma_free(host);
fail_dma:
kfree(host->data);
fail_nobuf1:
mmc_spi_put_pdata(spi);
mmc_free_host(mmc);
nomem:
kfree(ones);
return status;
}