临时笔记#

参考资料:

  • 内核头文件:include\linux\spi\spi.h

1. SPI Master#

文件:drivers\spi\spi-gpio.c

	spi_gpio = spi_master_get_devdata(master);

	master = spi_alloc_master(...);

	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
	master->flags = master_flags;
	master->bus_num = pdev->id;
	master->num_chipselect = num_devices;
	master->setup = spi_gpio_setup;
	master->cleanup = spi_gpio_cleanup;

	status = of_get_named_gpio(np, "cs-gpios", i);
	spi_gpio->cs_gpios[i] = status;

	spi_gpio->bitbang.master = master;
	spi_gpio->bitbang.chipselect = spi_gpio_chipselect;

	if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) {
		spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
		spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;
		spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
		spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;
	} else {
		spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0;
		spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1;
		spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2;
		spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3;
	}
	spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
	spi_gpio->bitbang.flags = SPI_CS_HIGH;

	status = spi_bitbang_start(&spi_gpio->bitbang);

2. spi_bitbang_start#

	if (master->transfer || master->transfer_one_message)
		return -EINVAL;

	master->prepare_transfer_hardware = spi_bitbang_prepare_hardware;
	master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware;
	master->transfer_one = spi_bitbang_transfer_one;
	master->set_cs = spi_bitbang_set_cs;

	if (!bitbang->txrx_bufs) {
		bitbang->use_dma = 0;
		bitbang->txrx_bufs = spi_bitbang_bufs;
		if (!master->setup) {
			if (!bitbang->setup_transfer)
				bitbang->setup_transfer =
					 spi_bitbang_setup_transfer;
			master->setup = spi_bitbang_setup;
			master->cleanup = spi_bitbang_cleanup;
		}
	}

	ret = spi_register_master(spi_master_get(master));

3. spi_register_master#

	status = of_spi_register_master(master);

	/* If we're using a queued driver, start the queue */
	if (master->transfer)
		dev_info(dev, "master is unqueued, this is deprecated\n");
	else {
		status = spi_master_initialize_queue(master);
		if (status) {
			device_del(&master->dev);
			goto done;
		}
	}

4. spi_master_initialize_queue#

static int spi_master_initialize_queue(struct spi_master *master)
{
	int ret;

	master->transfer = spi_queued_transfer;
	if (!master->transfer_one_message)
		master->transfer_one_message = spi_transfer_one_message;

	/* Initialize and start queue */
	ret = spi_init_queue(master);
	if (ret) {
		dev_err(&master->dev, "problem initializing queue\n");
		goto err_init_queue;
	}
	master->queued = true;
	ret = spi_start_queue(master);
	if (ret) {
		dev_err(&master->dev, "problem starting queue\n");
		goto err_start_queue;
	}

	return 0;

err_start_queue:
	spi_destroy_queue(master);
err_init_queue:
	return ret;
}

5. spi_init_queue#

	kthread_init_worker(&master->kworker);
	master->kworker_task = kthread_run(kthread_worker_fn,
					   &master->kworker, "%s",
					   dev_name(&master->dev));

	kthread_init_work(&master->pump_messages, spi_pump_messages);

6. spi_start_queue#

	kthread_queue_work(&master->kworker, &master->pump_messages);

7. SPI传输#

spi_sync
    __spi_sync
    	message->complete = spi_complete;
		
		if (master->transfer == spi_queued_transfer) {
            status = __spi_queued_transfer(spi, message, false);
				list_add_tail(&msg->queue, &master->queue);
			__spi_pump_messages(master, false);            
                kthread_queue_work(&master->kworker,
                           &master->pump_messages);
            		spi_pump_messages
                        __spi_pump_messages(master, true);
            				ret = master->transfer_one_message(master, master->cur_msg);
            					spi_transfer_one_message
									spi_set_cs(msg->spi, true);
									reinit_completion(&master->xfer_completion);
									ret = master->transfer_one(master, msg->spi, xfer);
            								spi_bitbang_transfer_one
												status = bitbang->txrx_bufs(spi, transfer);
            										spi_bitbang_bufs
                                    ms = wait_for_completion_timeout(&master->xfer_completion,
                                                     msecs_to_jiffies(ms));	                     									spi_finalize_current_message(master);
			wait_for_completion(&done);            
        } else {
            status = spi_async_locked(spi, message);
            	__spi_async
                    return master->transfer(spi, message);
        }

8. spi_bitbang_bufs#

	return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t);

image-20220303143723585

image-20220303144759926

9. bitbang_txrx_16#

image-20220303145227558

上图里的txrx_word来自哪里?spi_master在传输spi_transfer之前要设置。

对于SPI GPIO:

image-20220303145416724

对于IMX:

image-20220303150143475