mmc_spi.c
来自「linux 内核源代码」· C语言 代码 · 共 1,414 行 · 第 1/3 页
C
1,414 行
dev_dbg(&host->spi->dev, "bogus command\n"); cmd->error = -EINVAL; invalid = 1; } cmd = mrq->stop; if (cmd && !mmc_spi_resp_type(cmd)) { dev_dbg(&host->spi->dev, "bogus STOP command\n"); cmd->error = -EINVAL; invalid = 1; } if (invalid) { dump_stack(); mmc_request_done(host->mmc, mrq); return; } }#endif /* issue command; then optionally data and stop */ status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL); if (status == 0 && mrq->data) { mmc_spi_data_do(host, mrq->cmd, mrq->data, mrq->data->blksz); if (mrq->stop) status = mmc_spi_command_send(host, mrq, mrq->stop, 0); else mmc_cs_off(host); } mmc_request_done(host->mmc, mrq);}/* See Section 6.4.1, in SD "Simplified Physical Layer Specification 2.0" * * NOTE that here we can't know that the card has just been powered up; * not all MMC/SD sockets support power switching. * * FIXME when the card is still in SPI mode, e.g. from a previous kernel, * this doesn't seem to do the right thing at all... */static void mmc_spi_initsequence(struct mmc_spi_host *host){ /* Try to be very sure any previous command has completed; * wait till not-busy, skip debris from any old commands. */ mmc_spi_wait_unbusy(host, r1b_timeout); mmc_spi_readbytes(host, 10); /* * Do a burst with chipselect active-high. We need to do this to * meet the requirement of 74 clock cycles with both chipselect * and CMD (MOSI) high before CMD0 ... after the card has been * powered up to Vdd(min), and so is ready to take commands. * * Some cards are particularly needy of this (e.g. Viking "SD256") * while most others don't seem to care. * * Note that this is one of the places MMC/SD plays games with the * SPI protocol. Another is that when chipselect is released while * the card returns BUSY status, the clock must issue several cycles * with chipselect high before the card will stop driving its output. */ 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"); } }}static char *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 "?";}static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios){ struct mmc_spi_host *host = mmc_priv(mmc); if (host->power_mode != ios->power_mode) { int canpower; canpower = host->pdata && host->pdata->setpower; dev_dbg(&host->spi->dev, "mmc_spi: power %s (%d)%s\n", mmc_powerstring(ios->power_mode), ios->vdd, canpower ? ", can switch" : ""); /* switch power on/off if possible, accounting for * max 250msec powerup time if needed. */ 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 * delivery from data lines! On a shared SPI bus, this * will probably be temporary; 6.4.2 of the simplified SD * spec says this must last at least 1msec. * * - Clock low means CPOL 0, e.g. mode 0 * - MOSI low comes from writing zero * - Chipselect is usually active low... */ if (canpower && ios->power_mode == MMC_POWER_OFF) { int mres; 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_w8r8(host->spi, 0x00) < 0) dev_dbg(&host->spi->dev, "put spi signals to low failed\n"); /* * Now clock should be low due to spi mode 0; * MOSI should be low because of written 0x00; * chipselect should be low (it is active low) * power supply is off, so now MMC is off too! * * FIXME no, chipselect can be high since the * device is inactive and SPI_CS_HIGH is clear... */ 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, "mmc_spi: clock to %d Hz, %d\n", host->spi->max_speed_hz, status); }}static int mmc_spi_get_ro(struct mmc_host *mmc){ struct mmc_spi_host *host = mmc_priv(mmc); if (host->pdata && host->pdata->get_ro) return host->pdata->get_ro(mmc->parent); /* board doesn't support read only detection; assume writeable */ return 0;}static const struct mmc_host_ops mmc_spi_ops = { .request = mmc_spi_request, .set_ios = mmc_spi_set_ios, .get_ro = mmc_spi_get_ro,};/****************************************************************************//* * SPI driver implementation */static irqreturn_tmmc_spi_detect_irq(int irq, void *mmc){ struct mmc_spi_host *host = mmc_priv(mmc); u16 delay_msec = max(host->pdata->detect_delay, (u16)100); mmc_detect_change(mmc, msecs_to_jiffies(delay_msec)); return IRQ_HANDLED;}struct count_children { unsigned n; struct bus_type *bus;};static int maybe_count_child(struct device *dev, void *c){ struct count_children *ccp = c; if (dev->bus == ccp->bus) { if (ccp->n) return -EBUSY; ccp->n++; } return 0;}static int mmc_spi_probe(struct spi_device *spi){ void *ones; struct mmc_host *mmc; struct mmc_spi_host *host; int status; /* 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 it seems to be a * bit less troublesome on some hardware ... unclear why. */ 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 can use the bus safely iff nobody else will interfere with us. * Most commands consist of one SPI message to issue a command, then * several more to collect its response, then possibly more for data * transfer. Clocking access to other devices during that period will * corrupt the command execution. * * Until we have software primitives which guarantee non-interference, * we'll aim for a hardware-level guarantee. * * REVISIT we can't guarantee another device won't be added later... */ if (spi->master->num_chipselect > 1) { struct count_children cc; cc.n = 0; cc.bus = spi->dev.bus; status = device_for_each_child(spi->dev.parent, &cc, maybe_count_child); if (status < 0) { dev_err(&spi->dev, "can't share SPI bus\n"); return status; } dev_warn(&spi->dev, "ASSUMING SPI bus stays unshared!\n"); } /* 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; /* As long as we keep track of the number of successfully * transmitted blocks, we're good for multiwrite. */ mmc->caps = MMC_CAP_SPI | MMC_CAP_MULTIWRITE; /* 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; /* Platform data is used to hook up things like card sensing * and power switching gpios. */ host->pdata = spi->dev.platform_data; 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; } dev_set_drvdata(&spi->dev, mmc); /* preallocate dma buffers */ host->data = kmalloc(sizeof(*host->data), GFP_KERNEL); if (!host->data) goto fail_nobuf1; if (spi->master->dev.parent->dma_mask) { struct device *dev = spi->master->dev.parent; host->dma_dev = dev; host->ones_dma = dma_map_single(dev, ones, MMC_SPI_BLOCKSIZE, DMA_TO_DEVICE); host->data_dma = dma_map_single(dev, host->data, sizeof(*host->data), DMA_BIDIRECTIONAL); /* REVISIT in theory those map operations can fail... */ dma_sync_single_for_cpu(host->dma_dev, host->data_dma, sizeof(*host->data), DMA_BIDIRECTIONAL); } /* 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; } status = mmc_add_host(mmc); if (status != 0) goto fail_add_host; dev_info(&spi->dev, "SD/MMC host %s%s%s%s\n", mmc->class_dev.bus_id, host->dma_dev ? "" : ", no DMA", (host->pdata && host->pdata->get_ro) ? "" : ", no WP", (host->pdata && host->pdata->setpower) ? "" : ", no poweroff"); return 0;fail_add_host: mmc_remove_host (mmc);fail_glue_init: if (host->dma_dev) dma_unmap_single(host->dma_dev, host->data_dma, sizeof(*host->data), DMA_BIDIRECTIONAL); kfree(host->data);fail_nobuf1: mmc_free_host(mmc); dev_set_drvdata(&spi->dev, NULL);nomem: kfree(ones); return status;}static int __devexit mmc_spi_remove(struct spi_device *spi){ struct mmc_host *mmc = dev_get_drvdata(&spi->dev); struct mmc_spi_host *host; if (mmc) { host = mmc_priv(mmc); /* prevent new mmc_detect_change() calls */ if (host->pdata && host->pdata->exit) host->pdata->exit(&spi->dev, mmc); mmc_remove_host(mmc); if (host->dma_dev) { dma_unmap_single(host->dma_dev, host->ones_dma, MMC_SPI_BLOCKSIZE, DMA_TO_DEVICE); dma_unmap_single(host->dma_dev, host->data_dma, sizeof(*host->data), DMA_BIDIRECTIONAL); } kfree(host->data); kfree(host->ones); spi->max_speed_hz = mmc->f_max; mmc_free_host(mmc); dev_set_drvdata(&spi->dev, NULL); } return 0;}static struct spi_driver mmc_spi_driver = { .driver = { .name = "mmc_spi", .bus = &spi_bus_type, .owner = THIS_MODULE, }, .probe = mmc_spi_probe, .remove = __devexit_p(mmc_spi_remove),};static int __init mmc_spi_init(void){ return spi_register_driver(&mmc_spi_driver);}module_init(mmc_spi_init);static void __exit mmc_spi_exit(void){ spi_unregister_driver(&mmc_spi_driver);}module_exit(mmc_spi_exit);MODULE_AUTHOR("Mike Lavender, David Brownell, " "Hans-Peter Nilsson, Jan Nikitenko");MODULE_DESCRIPTION("SPI SD/MMC host driver");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?