/* other than negative (== assign one dynamically), bus_num is fully * board-specific. usually that simplifies to being SOC-specific. * example: one SOC has three SPI controllers, numbered 0..2, * and one board's schematics might show it using SPI-2. software * would normally use bus_num=2 for that controller. */ s16 bus_num;
/* chipselects will be integral to many controllers; some others * might use board-specific GPIOs. */ u16 num_chipselect;
/* some SPI controllers pose alignment requirements on DMAable * buffers; let protocol drivers know about these requirements. */ u16 dma_alignment;
/* spi_device.mode flags understood by this controller driver */ u16 mode_bits;
/* limits on transfer speed */ u32 min_speed_hz; u32 max_speed_hz;
/* other constraints relevant to this driver */ u16 flags; #define SPI_MASTER_HALF_DUPLEX BIT(0) /* can't do full duplex */ #define SPI_MASTER_NO_RX BIT(1) /* can't do buffer read */ #define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */ #define SPI_MASTER_MUST_RX BIT(3) /* requires rx */ #define SPI_MASTER_MUST_TX BIT(4) /* requires tx */
/* * on some hardware transfer / message size may be constrained * the limit may depend on device transfer settings */ size_t (*max_transfer_size)(struct spi_device *spi); size_t (*max_message_size)(struct spi_device *spi);
/* I/O mutex */ structmutexio_mutex;
/* lock and mutex for SPI bus locking */ spinlock_t bus_lock_spinlock; structmutexbus_lock_mutex;
/* flag indicating that the SPI bus is locked for exclusive use */ bool bus_lock_flag;
/* Setup mode and clock, etc (spi driver may call many times). * * IMPORTANT: this may be called when transfers to another * device are active. DO NOT UPDATE SHARED REGISTERS in ways * which could break those transfers. */ int (*setup)(struct spi_device *spi);
/* bidirectional bulk transfers * * + The transfer() method may not sleep; its main role is * just to add the message to the queue. * + For now there's no remove-from-queue operation, or * any other request management * + To a given spi_device, message queueing is pure fifo * * + The master's main job is to process its message queue, * selecting a chip then transferring data * + If there are multiple spi_device children, the i/o queue * arbitration algorithm is unspecified (round robin, fifo, * priority, reservations, preemption, etc) * * + Chipselect stays active during the entire message * (unless modified by spi_transfer.cs_change != 0). * + The message transfers use clock and SPI mode parameters * previously established by setup() for this device */ int (*transfer)(struct spi_device *spi, struct spi_message *mesg);
/* called on release() to free memory provided by spi_master */ void (*cleanup)(struct spi_device *spi);
/* * Used to enable core support for DMA handling, if can_dma() * exists and returns true then the transfer will be mapped * prior to transfer_one() being called. The driver should * not modify or store xfer and dma_tx and dma_rx must be set * while the device is prepared. */ bool (*can_dma)(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer);
/* * These hooks are for drivers that want to use the generic * master transfer queueing mechanism. If these are used, the * transfer() function above must NOT be specified by the driver. * Over time we expect SPI drivers to be phased over to this API. */ bool queued; structkthread_workerkworker; structtask_struct *kworker_task; structkthread_workpump_messages; spinlock_t queue_lock; structlist_headqueue; structspi_message *cur_msg; bool idling; bool busy; bool running; bool rt; bool auto_runtime_pm; bool cur_msg_prepared; bool cur_msg_mapped; structcompletionxfer_completion; size_t max_dma_len;
int (*prepare_transfer_hardware)(struct spi_master *master); int (*transfer_one_message)(struct spi_master *master, struct spi_message *mesg); int (*unprepare_transfer_hardware)(struct spi_master *master); int (*prepare_message)(struct spi_master *master, struct spi_message *message); int (*unprepare_message)(struct spi_master *master, struct spi_message *message); int (*spi_flash_read)(struct spi_device *spi, struct spi_flash_read_message *msg); bool (*flash_read_supported)(struct spi_device *spi);
/* * These hooks are for drivers that use a generic implementation * of transfer_one_message() provied by the core. */ void (*set_cs)(struct spi_device *spi, bool enable); int (*transfer_one)(struct spi_master *master, struct spi_device *spi, struct spi_transfer *transfer); void (*handle_err)(struct spi_master *master, struct spi_message *message);
/* gpio chip select */ int *cs_gpios;
/* statistics */ structspi_statisticsstatistics;
/* DMA channels for use with core dmaengine helpers */ structdma_chan *dma_tx; structdma_chan *dma_rx;
/* dummy data for full duplex devices */ void *dummy_rx; void *dummy_tx;
int (*fw_translate_cs)(struct spi_master *master, unsigned cs); };
/* use a define to avoid include chaining to get THIS_MODULE */ #define spi_register_driver(driver) \ __spi_register_driver(THIS_MODULE, driver) int __spi_register_driver(struct module *owner, struct spi_driver *sdrv) { sdrv->driver.owner = owner; sdrv->driver.bus = &spi_bus_type; if (sdrv->probe) sdrv->driver.probe = spi_drv_probe; if (sdrv->remove) sdrv->driver.remove = spi_drv_remove; if (sdrv->shutdown) sdrv->driver.shutdown = spi_drv_shutdown; return driver_register(&sdrv->driver); }
staticintspi_imx_probe(struct platform_device *pdev) { // 省略... master->dev.of_node = pdev->dev.of_node; ret = spi_bitbang_start(&spi_imx->bitbang); if (ret) { dev_err(&pdev->dev, "bitbang start failed with %d\n", ret); goto out_clk_put; }
if (!master->cs_gpios) { dev_err(&pdev->dev, "No CS GPIOs available\n"); ret = -EINVAL; goto out_clk_put; }
for (i = 0; i < master->num_chipselect; i++) { if (!gpio_is_valid(master->cs_gpios[i])) continue;
ret = devm_gpio_request(&pdev->dev, master->cs_gpios[i], DRIVER_NAME); if (ret) { dev_err(&pdev->dev, "Can't get CS GPIO %i\n", master->cs_gpios[i]); goto out_clk_put; } }
dev_info(&pdev->dev, "probed\n"); // 省略... }
staticvoidspi_imx_chipselect(struct spi_device *spi, int is_active) { int active = is_active != BITBANG_CS_INACTIVE; int dev_is_lowactive = !(spi->mode & SPI_CS_HIGH);