/* * FIRST PART (OPTIONAL): word-at-a-time spi_transfer support. * Use this for GPIO or shift-register level hardware APIs. * * spi_bitbang_cs is in spi_device->controller_state, which is unavailable * to glue code. These bitbang setup() and cleanup() routines are always * used, though maybe they're called from controller-aware code. * * chipselect() and friends may use spi_device->controller_data and * controller registers as appropriate. * * * NOTE: SPI controller pins can often be used as GPIO pins instead, * which means you could use a bitbang driver either to get hardware * working quickly, or testing for differences that aren't speed related.
*/
bitbang = spi_controller_get_devdata(spi->controller); while (likely(count > 0)) {
u8 word = 0;
if (tx)
word = *tx++; else
word = spi->mode & SPI_MOSI_IDLE_HIGH ? 0xFF : 0;
word = txrx_word(spi, ns, word, bits, flags); if (rx)
*rx++ = word;
count -= 1;
} if (bitbang->set_mosi_idle)
bitbang->set_mosi_idle(spi);
bitbang = spi_controller_get_devdata(spi->controller); while (likely(count > 1)) {
u16 word = 0;
if (tx)
word = *tx++; else
word = spi->mode & SPI_MOSI_IDLE_HIGH ? 0xFFFF : 0;
word = txrx_word(spi, ns, word, bits, flags); if (rx)
*rx++ = word;
count -= 2;
} if (bitbang->set_mosi_idle)
bitbang->set_mosi_idle(spi);
bitbang = spi_controller_get_devdata(spi->controller); while (likely(count > 3)) {
u32 word = 0;
if (tx)
word = *tx++; else
word = spi->mode & SPI_MOSI_IDLE_HIGH ? 0xFFFFFFFF : 0;
word = txrx_word(spi, ns, word, bits, flags); if (rx)
*rx++ = word;
count -= 4;
} if (bitbang->set_mosi_idle)
bitbang->set_mosi_idle(spi);
/* * SECOND PART ... simple transfer queue runner. * * This costs a task context per controller, running the queue by * performing each transfer in sequence. Smarter hardware can queue * several DMA transfers at once, and process several controller queues * in parallel; this driver doesn't match such hardware very well. * * Drivers can provide word-at-a-time i/o primitives, or provide * transfer-at-a-time ones to leverage dma or fifo hardware.
*/
if (!ctlr) return -EINVAL; /* * We only need the chipselect callback if we are actually using it. * If we just use GPIO descriptors, it is surplus. If the * SPI_CONTROLLER_GPIO_SS flag is set, we always need to call the * driver-specific chipselect routine.
*/
custom_cs = (!ctlr->use_gpio_descriptors ||
(ctlr->flags & SPI_CONTROLLER_GPIO_SS));
if (custom_cs && !bitbang->chipselect) return -EINVAL;
mutex_init(&bitbang->lock);
if (!ctlr->mode_bits)
ctlr->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
if (ctlr->transfer || ctlr->transfer_one_message) return -EINVAL;
ctlr->prepare_transfer_hardware = spi_bitbang_prepare_hardware;
ctlr->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware;
ctlr->transfer_one = spi_bitbang_transfer_one; /* * When using GPIO descriptors, the ->set_cs() callback doesn't even * get called unless SPI_CONTROLLER_GPIO_SS is set.
*/ if (custom_cs)
ctlr->set_cs = spi_bitbang_set_cs;
if (!bitbang->txrx_bufs) {
bitbang->use_dma = 0;
bitbang->txrx_bufs = spi_bitbang_bufs; if (!ctlr->setup) { if (!bitbang->setup_transfer)
bitbang->setup_transfer =
spi_bitbang_setup_transfer;
ctlr->setup = spi_bitbang_setup;
ctlr->cleanup = spi_bitbang_cleanup;
}
}
return 0;
}
EXPORT_SYMBOL_GPL(spi_bitbang_init);
/** * spi_bitbang_start - start up a polled/bitbanging SPI host controller driver * @bitbang: driver handle * * Caller should have zero-initialized all parts of the structure, and then * provided callbacks for chip selection and I/O loops. If the host controller has * a transfer method, its final step should call spi_bitbang_transfer(); or, * that's the default if the transfer routine is not initialized. It should * also set up the bus number and number of chipselects. * * For i/o loops, provide callbacks either per-word (for bitbanging, or for * hardware that basically exposes a shift register) or per-spi_transfer * (which takes better advantage of hardware like fifos or DMA engines). * * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup(), * spi_bitbang_cleanup() and spi_bitbang_setup_transfer() to handle those SPI * host controller methods. Those methods are the defaults if the bitbang->txrx_bufs * routine isn't initialized. * * This routine registers the spi_controller, which will process requests in a * dedicated task, keeping IRQs unblocked most of the time. To stop * processing those requests, call spi_bitbang_stop(). * * On success, this routine will take a reference to the controller. The caller * is responsible for calling spi_bitbang_stop() to decrement the reference and * spi_controller_put() as counterpart of spi_alloc_host() to prevent a memory * leak.
*/ int spi_bitbang_start(struct spi_bitbang *bitbang)
{ struct spi_controller *ctlr = bitbang->ctlr; int ret;
ret = spi_bitbang_init(bitbang); if (ret) return ret;
/* driver may get busy before register() returns, especially * if someone registered boardinfo for devices
*/
ret = spi_register_controller(spi_controller_get(ctlr)); if (ret)
spi_controller_put(ctlr);
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.