SPI Controller Core
SPI Master & Slave 컨트롤러 등록
spi_register_controller()
호환을 위해 spi_register_master() 매크로 함수는 spi_register_controller()를 호출한다.
drivers/spi/spi.c
/** * spi_register_controller - register SPI master or slave controller * @ctlr: initialized master, originally from spi_alloc_master() or * spi_alloc_slave() * Context: can sleep * * SPI controllers connect to their drivers using some non-SPI bus, * such as the platform bus. The final stage of probe() in that code * includes calling spi_register_controller() to hook up to this SPI bus glue. * * SPI controllers use board specific (often SOC specific) bus numbers, * and board-specific addressing for SPI devices combines those numbers * with chip select numbers. Since SPI does not directly support dynamic * device identification, boards need configuration tables telling which * chip is at which address. * * This must be called from context that can sleep. It returns zero on * success, else a negative error code (dropping the controller's refcount). * After a successful return, the caller is responsible for calling * spi_unregister_controller(). * * Return: zero on success, else a negative error code. */
int spi_register_controller(struct spi_controller *ctlr)
{
struct device *dev = ctlr->dev.parent;
struct boardinfo *bi;
int status = -ENODEV;
int id, first_dynamic;
if (!dev)
return -ENODEV;
if (!spi_controller_is_slave(ctlr)) {
status = of_spi_register_master(ctlr);
if (status)
return status;
}
/* even if it's just one always-selected device, there must
* be at least one chipselect
*/
if (ctlr->num_chipselect == 0)
return -EINVAL;
/* allocate dynamic bus number using Linux idr */
if ((ctlr->bus_num < 0) && ctlr->dev.of_node) {
id = of_alias_get_id(ctlr->dev.of_node, "spi");
if (id >= 0) {
ctlr->bus_num = id;
mutex_lock(&board_lock);
id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num,
ctlr->bus_num + 1, GFP_KERNEL);
mutex_unlock(&board_lock);
if (WARN(id < 0, "couldn't get idr"))
return id == -ENOSPC ? -EBUSY : id;
}
}
if (ctlr->bus_num < 0) {
first_dynamic = of_alias_get_highest_id("spi");
if (first_dynamic < 0)
first_dynamic = 0;
else
first_dynamic++;
mutex_lock(&board_lock);
id = idr_alloc(&spi_master_idr, ctlr, first_dynamic,
0, GFP_KERNEL);
mutex_unlock(&board_lock);
if (WARN(id < 0, "couldn't get idr"))
return id;
ctlr->bus_num = id;
}
INIT_LIST_HEAD(&ctlr->queue);
spin_lock_init(&ctlr->queue_lock);
spin_lock_init(&ctlr->bus_lock_spinlock);
mutex_init(&ctlr->bus_lock_mutex);
mutex_init(&ctlr->io_mutex);
ctlr->bus_lock_flag = 0;
init_completion(&ctlr->xfer_completion);
if (!ctlr->max_dma_len)
ctlr->max_dma_len = INT_MAX;
SPI 마스터 또는 슬레이브 컨트롤러를 등록한다.
- 코드 라인 11~15에서 등록할 컨트롤러가 슬레이브가 아닌 경우 디바이스 트리로부터 칩셀렉트를 위해 gpio 핀 정보들을 읽어온다.
- 1개 이상의 “cs-gpios” 속성 값을 읽어 해당하는 gpio 핀 번호를 ctlr->cs_gpios[]에 대입한다.
- 코드 라인 20~21에서 선택할 수 있는 슬레이브 칩 수가 0인 경우 에러를 반환한다.
- 코드 라인 23~34에서 spi 버스 번호가 0을 초과한, 즉 다수인경우 “spi” alias 명을 찾아 id 값으로 버스 번호를 적용하여 idr 할당한다.
- 코드 라인 35~49에서 spi 버스 번호가 0 미만인 경우 “spi” alias명으로 찾은 가장 높은 id 값 +1로 버스 번호를 적용하여 idr 할당한다.
- 코드 라인 50~58에서 spi 컨트롤러의 멤버들을 초기화한다.
/* register the device, then userspace will see it.
* registration fails if the bus ID is in use.
*/
dev_set_name(&ctlr->dev, "spi%u", ctlr->bus_num);
status = device_add(&ctlr->dev);
if (status < 0) {
/* free bus id */
mutex_lock(&board_lock);
idr_remove(&spi_master_idr, ctlr->bus_num);
mutex_unlock(&board_lock);
goto done;
}
dev_dbg(dev, "registered %s %s\n",
spi_controller_is_slave(ctlr) ? "slave" : "master",
dev_name(&ctlr->dev));
/* If we're using a queued driver, start the queue */
if (ctlr->transfer)
dev_info(dev, "controller is unqueued, this is deprecated\n");
else {
status = spi_controller_initialize_queue(ctlr);
if (status) {
device_del(&ctlr->dev);
/* free bus id */
mutex_lock(&board_lock);
idr_remove(&spi_master_idr, ctlr->bus_num);
mutex_unlock(&board_lock);
goto done;
}
}
/* add statistics */
spin_lock_init(&ctlr->statistics.lock);
mutex_lock(&board_lock);
list_add_tail(&ctlr->list, &spi_controller_list);
list_for_each_entry(bi, &board_list, list)
spi_match_controller_to_boardinfo(ctlr, &bi->board_info);
mutex_unlock(&board_lock);
/* Register devices from the device tree and ACPI */
of_register_spi_devices(ctlr);
acpi_register_spi_devices(ctlr);
done:
return status;
}
EXPORT_SYMBOL_GPL(spi_register_controller);
- 코드 라인 4~15에서 “spi<bus#>” 명으로 디바이스를 추가한다.
- 예) “registered master spi0” 또는 “registered slave spi1” 형식으로 디버그 메시지를 출력한다.
- 코드 라인 18~30에서 (*transfer) 후크 함수는 deprecated될 예정이다. 이 함수가 지정되지 않은 경우큐 방식을 사용하기 위해 spi 컨트롤러용 큐를 초기화한다.
- 코드 라인 32에서 통계 관련 락을 초기화한다.
- 코드 라인 34~38에서 전역 spi_controller_list에 컨트롤러를 추가한다. 그런 후 컨트롤러가 전역 board_list에 있는 디바이스와 매치되는 경우 spi_new_device() 함수를 호출하여 spi 디바이스로 추가 등록한다.
- 코드 라인 41에서 컨트롤러 노드의 하위 노드의 SPI 디바이스들을 추가한다.
- of_register_spi_device() -> 다음 각종 spi 디바이스 속성 값을 파싱한 후 -> spi_add_device()
- “spi-cpha”
- “spi-cpol”
- “spi-cs-high”
- “spi-3wire”
- “spi-tx-bus-width”
- “spi-rx-bus-width”
- “slave”
- “reg”
- “spi-max-frequency”
- of_register_spi_device() -> 다음 각종 spi 디바이스 속성 값을 파싱한 후 -> spi_add_device()
- 코드 라인 42에서 ACPI 펌웨어에서 spi 디바이스 정보를 읽어와서 추가한다.
of_register_spi_devices()
drivers/spi/spi.c
/**
* of_register_spi_devices() - Register child devices onto the SPI bus
* @ctlr: Pointer to spi_controller device
*
* Registers an spi_device for each child node of controller node which
* represents a valid SPI slave.
*/
static void of_register_spi_devices(struct spi_controller *ctlr)
{
struct spi_device *spi;
struct device_node *nc;
if (!ctlr->dev.of_node)
return;
for_each_available_child_of_node(ctlr->dev.of_node, nc) {
if (of_node_test_and_set_flag(nc, OF_POPULATED))
continue;
spi = of_register_spi_device(ctlr, nc);
if (IS_ERR(spi)) {
dev_warn(&ctlr->dev,
"Failed to create SPI device for %pOF\n", nc);
of_node_clear_flag(nc, OF_POPULATED);
}
}
}
컨트롤러 디바이스 트리 노드의 하위 노드들을 대상으로 매치되는 spi 디바이스들을 모두 등록한다.
of_register_spi_device()
drivers/spi/spi.c
static struct spi_device *
of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc)
{
struct spi_device *spi;
int rc;
/* Alloc an spi_device */
spi = spi_alloc_device(ctlr);
if (!spi) {
dev_err(&ctlr->dev, "spi_device alloc error for %pOF\n", nc);
rc = -ENOMEM;
goto err_out;
}
/* Select device driver */
rc = of_modalias_node(nc, spi->modalias,
sizeof(spi->modalias));
if (rc < 0) {
dev_err(&ctlr->dev, "cannot find modalias for %pOF\n", nc);
goto err_out;
}
rc = of_spi_parse_dt(ctlr, spi, nc);
if (rc)
goto err_out;
/* Store a pointer to the node in the device structure */
of_node_get(nc);
spi->dev.of_node = nc;
/* Register the new device */
rc = spi_add_device(spi);
if (rc) {
dev_err(&ctlr->dev, "spi_device register error %pOF\n", nc);
goto err_of_node_put;
}
return spi;
err_of_node_put:
of_node_put(nc);
err_out:
spi_dev_put(spi);
return ERR_PTR(rc);
}
컨트롤러 디바이스 트리 노드의 지정한 하위 노드의 spi 디바이스 하나를 등록한다.
- 코드 라인 8~13에서 spi 디바이스를 할당 받아 초기화한다.
- 코드 라인 16~21에서 “compatible” 속성 값에서 회사명과 컴마(“,”)를 제외한 드라이버명을 spi->modalias에 대입한다.
- 코드 라인 23~25에서 spi 디바이스 노드에서 다음 속성들을 파싱해온다.
- “spi-cpha”
- “spi-cpol”
- “spi-cs-high”
- “spi-3wire”
- “spi-tx-bus-width”
- “spi-rx-bus-width”
- “slave”
- “reg”
- “spi-max-frequency”
- 코드 라인 28~29에서 spi 디바이스의 참조 카운터를 1 증가시키고, 디바이스 트리의 spi 디바이스 노드를 가리키게 한다.
- 코드 라인 32~36에서 spi 디바이스를 추가한다.
spi_add_device()
drivers/spi/spi.c
/**
* spi_add_device - Add spi_device allocated with spi_alloc_device
* @spi: spi_device to register
*
* Companion function to spi_alloc_device. Devices allocated with
* spi_alloc_device can be added onto the spi bus with this function.
*
* Return: 0 on success; negative errno on failure
*/
int spi_add_device(struct spi_device *spi)
{
static DEFINE_MUTEX(spi_add_lock);
struct spi_controller *ctlr = spi->controller;
struct device *dev = ctlr->dev.parent;
int status;
/* Chipselects are numbered 0..max; validate. */
if (spi->chip_select >= ctlr->num_chipselect) {
dev_err(dev, "cs%d >= max %d\n", spi->chip_select,
ctlr->num_chipselect);
return -EINVAL;
}
/* Set the bus ID string */
spi_dev_set_name(spi);
/* We need to make sure there's no other device with this
* chipselect **BEFORE** we call setup(), else we'll trash
* its configuration. Lock against concurrent add() calls.
*/
mutex_lock(&spi_add_lock);
status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check);
if (status) {
dev_err(dev, "chipselect %d already in use\n",
spi->chip_select);
goto done;
}
if (ctlr->cs_gpios)
spi->cs_gpio = ctlr->cs_gpios[spi->chip_select];
/* Drivers may modify this initial i/o setup, but will
* normally rely on the device being setup. Devices
* using SPI_CS_HIGH can't coexist well otherwise...
*/
status = spi_setup(spi);
if (status < 0) {
dev_err(dev, "can't setup %s, status %d\n",
dev_name(&spi->dev), status);
goto done;
}
/* Device may be bound to an active driver when this returns */
status = device_add(&spi->dev);
if (status < 0)
dev_err(dev, "can't add %s, status %d\n",
dev_name(&spi->dev), status);
else
dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));
done:
mutex_unlock(&spi_add_lock);
return status;
}
EXPORT_SYMBOL_GPL(spi_add_device);
spi 디바이스를 칩셀렉션하고 hw 설정한 후 추가한다.
- 코드 라인 9~13에서 최대 슬레이브 칩 수를 초과하는 칩이 선택된 경우 에러를 반환한다.
- 코드 라인 16에서 버스 번호를 포함하여 spi 디바이스 명을 결정하는데 다음 둘 중 하나를 사용한다.
- acpi를 사용하는 경우 “spi-<device name>” 포맷을 사용한다.
- 그 외의 경우 “<컨트롤러명>.<칩 셀렉트 번호>” 포맷을 사용한다.
- 코드 라인 24~29에서 spi 디바이스가 이미 셋업되어 사용중인지 확인한다. 사용중이면 경고 메시지를 출력하고 등록을 포기한다.
- 코드 라인 31~32에서 gpio를 사용하여 칩셀렉트를 하는 경우 사용할 gpio 번호를 지정한다.
- 코드 라인 38~43에서 spi 디바이스를 hw 설정한다.
- 코드 라인 46~51에서 spi 디바이스를 추가한다.
spi_setup()
drivers/spi/spi.c
/** * spi_setup - setup SPI mode and clock rate * @spi: the device whose settings are being modified * Context: can sleep, and no requests are queued to the device * * SPI protocol drivers may need to update the transfer mode if the * device doesn't work with its default. They may likewise need * to update clock rates or word sizes from initial values. This function * changes those settings, and must be called from a context that can sleep. * Except for SPI_CS_HIGH, which takes effect immediately, the changes take * effect the next time the device is selected and data is transferred to * or from it. When this function returns, the spi device is deselected. * * Note that this call will fail if the protocol driver specifies an option * that the underlying controller or its driver does not support. For * example, not all hardware supports wire transfers using nine bit words, * LSB-first wire encoding, or active-high chipselects. * * Return: zero on success, else a negative error code. */
int spi_setup(struct spi_device *spi)
{
unsigned bad_bits, ugly_bits;
int status;
/* check mode to prevent that DUAL and QUAD set at the same time
*/
if (((spi->mode & SPI_TX_DUAL) && (spi->mode & SPI_TX_QUAD)) ||
((spi->mode & SPI_RX_DUAL) && (spi->mode & SPI_RX_QUAD))) {
dev_err(&spi->dev,
"setup: can not select dual and quad at the same time\n");
return -EINVAL;
}
/* if it is SPI_3WIRE mode, DUAL and QUAD should be forbidden
*/
if ((spi->mode & SPI_3WIRE) && (spi->mode &
(SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)))
return -EINVAL;
/* help drivers fail *cleanly* when they need options
* that aren't supported with their current controller
*/
bad_bits = spi->mode & ~spi->controller->mode_bits;
ugly_bits = bad_bits &
(SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD);
if (ugly_bits) {
dev_warn(&spi->dev,
"setup: ignoring unsupported mode bits %x\n",
ugly_bits);
spi->mode &= ~ugly_bits;
bad_bits &= ~ugly_bits;
}
if (bad_bits) {
dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
bad_bits);
return -EINVAL;
}
if (!spi->bits_per_word)
spi->bits_per_word = 8;
status = __spi_validate_bits_per_word(spi->controller,
spi->bits_per_word);
if (status)
return status;
if (!spi->max_speed_hz)
spi->max_speed_hz = spi->controller->max_speed_hz;
if (spi->controller->setup)
status = spi->controller->setup(spi);
spi_set_cs(spi, false);
dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s%u bits/w, %u Hz max --> %d\n",
(int) (spi->mode & (SPI_CPOL | SPI_CPHA)),
(spi->mode & SPI_CS_HIGH) ? "cs_high, " : "",
(spi->mode & SPI_LSB_FIRST) ? "lsb, " : "",
(spi->mode & SPI_3WIRE) ? "3wire, " : "",
(spi->mode & SPI_LOOP) ? "loopback, " : "",
spi->bits_per_word, spi->max_speed_hz,
status);
return status;
}
spi 디바이스의 클럭 모드 및 속도 등을 설정한다.
- 코드 라인 8~13에서 spi 디바이스가 동시에 dual 및 quad 설정을 요청하는 경우 에러 미세지를 출력하고 에러를 반환한다.
- 코드 라인 16~18에서 3wire 모드가 선택된 경우 dual 및 quad와 같이 설정할 수 없다.
- 코드 라인 22~36에서 spi 컨트롤러가 지원하지 않는 모드를 요청한 경우 에러 메시지를 출력하고 에러를 반환한다.
- 단 컨트롤러가 지원하지 않는 dual 또는 quad 요청을 한 경우 에러를 반환하지 않고 모드 플래그에서 제거한다.
- 코드 라인 38~39에서 워드당 비트 수를 0으로 요청한 경우 디폴트로 8 비트를 사용한다.
- 코드 라인 41~44에서 컨트롤러에 워드당 비트수 제한 마스크 이내에서 사용되어야 하고 워드당 비트 수가 32를 초과한 경우 에러를 반환한다.
- 코드 라인 46~47에서 spi 디바이스의 속도 제한 값이 없는 경우 spi 컨트롤러의 값을 사용한다.
- 코드 라인 49~50에서 spi 디바이스 설정 값으로 spi 컨트롤러를 설정한다.
- 코드 라인 52에서 spi 디바이스의 칩 셀렉트를 하지 않도록 설정한다.
- 코드 라인 54에서 설정 정보를 출력한다.
- “setup mode %d, “%s%s%s%s%u bits/w, %d Hz max –> %d”
- 1) cpol 또는 cpha 모드 비트만을 출력한다.
- 2) cs_high 여부
- 3) lsb 부터 출력하는지 여부
- 4) 3wire 모드 여부
- 5) loopback 모드 여부
- 6) 워드당 비트 수
- 7) 최대 제한 속도
- 8) 설정 상태 값
- “setup mode %d, “%s%s%s%s%u bits/w, %d Hz max –> %d”
Kernel API
SPI 전송
spi_async()
- 비동기 메시지 전송 요청
- 메시지 전송이 완료되면 지정한 콜백 함수가 호출된다.
- irq context 또는 process context 모두에서 사용할 수 있다.
drivers/spi/spi.c
/** * spi_async - asynchronous SPI transfer * @spi: device with which data will be exchanged * @message: describes the data transfers, including completion callback * Context: any (irqs may be blocked, etc) * * This call may be used in_irq and other contexts which can't sleep, * as well as from task contexts which can sleep. * * The completion callback is invoked in a context which can't sleep. * Before that invocation, the value of message->status is undefined. * When the callback is issued, message->status holds either zero (to * indicate complete success) or a negative error code. After that * callback returns, the driver which issued the transfer request may * deallocate the associated memory; it's no longer in use by any SPI * core or controller driver code. * * Note that although all messages to a spi_device are handled in * FIFO order, messages may go to different devices in other orders. * Some device might be higher priority, or have various "hard" access * time requirements, for example. * * On detection of any fault during the transfer, processing of * the entire message is aborted, and the device is deselected. * Until returning from the associated message completion callback, * no other spi_message queued to that device will be processed. * (This rule applies equally to all the synchronous transfer calls, * which are wrappers around this core asynchronous primitive.) * * Return: zero on success, else a negative error code. */
int spi_async(struct spi_device *spi, struct spi_message *message)
{
struct spi_controller *ctlr = spi->controller;
int ret;
unsigned long flags;
ret = __spi_validate(spi, message);
if (ret != 0)
return ret;
spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags);
if (ctlr->bus_lock_flag)
ret = -EBUSY;
else
ret = __spi_async(spi, message);
spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags);
return ret;
}
EXPORT_SYMBOL_GPL(spi_async);
준비된 @message를 @spi 슬레이브 장치로 비동기 전송한다. 결과가 0이면 정상이다.
- 코드 라인 7~9에서 @message가 적절한지 유효 검사를 수행한다.
- 코드 라인 11~18에서 spinlock을 획득한 채로 SPI 비동기 전송을 수행한다.
- 코드 라인 20에서 결과를 반환한다. (결과 0이면 정상)
__spi_async()
drivers/spi/spi.c
static int __spi_async(struct spi_device *spi, struct spi_message *message)
{
struct spi_controller *ctlr = spi->controller;
message->spi = spi;
SPI_STATISTICS_INCREMENT_FIELD(&ctlr->statistics, spi_async);
SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, spi_async);
trace_spi_message_submit(message);
return ctlr->transfer(spi, message);
}
준비된 @message를 @spi 슬레이브 장치로 비동기 전송한다. 결과가 0이면 정상이다.
- 코드 라인 3에서 spi 슬레이브 장치가 소속한 spi 컨트롤러를 알아온다.
- 코드 라인 7~8에서 spi 컨트롤러와 슬레이브측의 spi_async 카운터를 각각 1씩 증가시킨다.
- 코드 라인 10에서 trace 메시지를 출력한다.
- 코드 라인 12에서 컨트롤러에 구현된 (*transfer) 함수를 사용하여 @message를 @spi 슬레이브 디바이스에 비동기 전송한다.
spi_sync()
- 동기 메시지 전송 요청
- 슬립 가능한 프로세스 context에서만 사용할 수 있다.
- irq context에서 사용하면 안된다.
drivers/spi/spi.c
/** * spi_sync - blocking/synchronous SPI data transfers * @spi: device with which data will be exchanged * @message: describes the data transfers * Context: can sleep * * This call may only be used from a context that may sleep. The sleep * is non-interruptible, and has no timeout. Low-overhead controller * drivers may DMA directly into and out of the message buffers. * * Note that the SPI device's chip select is active during the message, * and then is normally disabled between messages. Drivers for some * frequently-used devices may want to minimize costs of selecting a chip, * by leaving it selected in anticipation that the next message will go * to the same chip. (That may increase power usage.) * * Also, the caller is guaranteeing that the memory associated with the * message will not be freed before this call returns. * * Return: zero on success, else a negative error code. */
int spi_sync(struct spi_device *spi, struct spi_message *message)
{
int ret;
mutex_lock(&spi->controller->bus_lock_mutex);
ret = __spi_sync(spi, message);
mutex_unlock(&spi->controller->bus_lock_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(spi_sync);
준비된 @message를 @spi 슬레이브 장치로 동기 전송한다. 결과가 0이면 정상이다.
- 코드 라인 5~7에서 spi 컨트롤러의 버스 락을 획득한채로 @spi 슬레이브 디바이스에게 @message를 동기 전송한다.
- 코드 라인 9에서 결과 값을 반환한다.
__spi_sync()
drivers/spi/spi.c
static int __spi_sync(struct spi_device *spi, struct spi_message *message)
{
DECLARE_COMPLETION_ONSTACK(done);
int status;
struct spi_controller *ctlr = spi->controller;
unsigned long flags;
status = __spi_validate(spi, message);
if (status != 0)
return status;
message->complete = spi_complete;
message->context = &done;
message->spi = spi;
SPI_STATISTICS_INCREMENT_FIELD(&ctlr->statistics, spi_sync);
SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, spi_sync);
/* If we're not using the legacy transfer method then we will
* try to transfer in the calling context so special case.
* This code would be less tricky if we could remove the
* support for driver implemented message queues.
*/
if (ctlr->transfer == spi_queued_transfer) {
spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags);
trace_spi_message_submit(message);
status = __spi_queued_transfer(spi, message, false);
spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags);
} else {
status = spi_async_locked(spi, message);
}
if (status == 0) {
/* Push out the messages in the calling context if we
* can.
*/
if (ctlr->transfer == spi_queued_transfer) {
SPI_STATISTICS_INCREMENT_FIELD(&ctlr->statistics,
spi_sync_immediate);
SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics,
spi_sync_immediate);
__spi_pump_messages(ctlr, false);
}
wait_for_completion(&done);
status = message->status;
}
message->context = NULL;
return status;
}
준비된 @message를 @spi 슬레이브 장치로 동기 전송한다. 결과가 0이면 정상이다.
- 코드 라인 3에서 동기 전송의 완료를 대기하기 위해 사용할 값을 준비한다.
- 코드 라인 5에서 @spi 슬레이브 장치가 소속한 spi 컨트롤러를 알아온다.
- 코드 라인 8~10에서 @message의 유효성 검사를 수행한다.
- 코드 라인 12~14에서 메시지에 전송완료를 대기 준비와 spi 슬레이브 디바이스를 지정한다.
- 코드 라인 16~17에서 spi 컨트롤러와 슬레이브측의 spi_sync 카운터를 각각 1씩 증가시킨다.
- 코드 라인 24~31에서 queued 전송이 가능한 spi 컨트롤러인 경우 이 방식으로 @message를 @spi 슬레이브 디바이스에 전송을 하도록 큐에 추가한다.
- 코드 라인 32~34에서 queued 전송이 가능하지 않은 spi 컨트롤러인 경우 @message를 @spi 슬레이브 디바이스에 비동기 전송을 요청한다.
- 코드 라인 36~50에서 성공적으로 전송 요청을 하였으면 전송이 완료될 때까지 대기한다. queued 전송이 가능한 spi 컨트롤러의 경우 spi 컨트롤러와 슬레이브측의 spi_sync_immediate 카운터를 각각 1씩 증가시킨다.
- 코드 라인 51~52에서 message의 context를 null로 하고, 결과 값을 반환한다.
spi_complete()
drivers/spi/spi.c
/* Utility methods for SPI protocol drivers, layered on
* top of the core. Some other utility methods are defined as
* inline functions.
*/
static void spi_complete(void *arg)
{
complete(arg);
}
spi 전송이 실제 완료된 경우 complete를 호출한다.
spi_queued_transfer()
drivers/spi/spi.c
/**
* spi_queued_transfer - transfer function for queued transfers
* @spi: spi device which is requesting transfer
* @msg: spi message which is to handled is queued to driver queue
*
* Return: zero on success, else a negative error code.
*/
static int spi_queued_transfer(struct spi_device *spi, struct spi_message *msg)
{
return __spi_queued_transfer(spi, msg, true);
}
@spi 디바이스로 전송할 @msg를 spi 컨트롤러의 큐에 추가한다. 또한 컨트롤러의 spi 메시지 전송용 워커 스레드가 동작하지 않고 있으면 깨워 동작시킨다. 메시지를 큐에 잘 추가한 경우 성공 값 0을 반환한다.
__spi_queued_transfer()
drivers/spi/spi.c
static int __spi_queued_transfer(struct spi_device *spi,
struct spi_message *msg,
bool need_pump)
{
struct spi_controller *ctlr = spi->controller;
unsigned long flags;
spin_lock_irqsave(&ctlr->queue_lock, flags);
if (!ctlr->running) {
spin_unlock_irqrestore(&ctlr->queue_lock, flags);
return -ESHUTDOWN;
}
msg->actual_length = 0;
msg->status = -EINPROGRESS;
list_add_tail(&msg->queue, &ctlr->queue);
if (!ctlr->busy && need_pump)
kthread_queue_work(&ctlr->kworker, &ctlr->pump_messages);
spin_unlock_irqrestore(&ctlr->queue_lock, flags);
return 0;
}
@spi 디바이스로 전송할 @msg를 spi 컨트롤러의 큐에 추가한다. @need_pump가 요청되면 컨트롤러의 spi 메시지 전송용 워커 스레드가 동작하지 않고 있으면 깨워 동작시킨다. 메시지를 큐에 잘 추가한 경우 성공 값 0을 반환한다.
- 코드 라인 5에서 @spi 슬레이브 디바이스가 소속한 spi 컨트롤러를 알아온다.
- 코드 라인 8에서 spi 컨트롤러의 큐에 대한 락을 획득한다.
- 코드 라인 10~13에서 spi 컨트롤러가 동작 중이지 않고 꺼져 있는 상태면, -ESHUTDOWN 에러를 반환한다.
- 코드 라인 14~15에서 메시지의 전송 직전 초기 상태로 actual_legnth를 0으로 그리고 상태를 -EINPROGRESS로 지정한다.
- 코드 라인 17에서 spi 컨트롤러의 큐에 @msg를 추가한다.
- 코드 라인 18~19에서 @need_pump가 요청되면 컨트롤러의 spi 메시지 전송용 워커 스레드가 동작하지 않고 있으면 깨워 동작시킨다.
- 코드 라인 21~22에서 spi 컨트롤러의 큐에 대한 락을 풀고, 성공 결과 값 0을 반환한다.
__spi_pump_messages()
drivers/spi/spi.c – 1/2
/** * __spi_pump_messages - function which processes spi message queue * @ctlr: controller to process queue for * @in_kthread: true if we are in the context of the message pump thread * * This function checks if there is any spi message in the queue that * needs processing and if so call out to the driver to initialize hardware * and transfer each message. * * Note that it is called both from the kthread itself and also from * inside spi_sync(); the queue extraction handling at the top of the * function should deal with this safely. */
static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread)
{
unsigned long flags;
bool was_busy = false;
int ret;
/* Lock queue */
spin_lock_irqsave(&ctlr->queue_lock, flags);
/* Make sure we are not already running a message */
if (ctlr->cur_msg) {
spin_unlock_irqrestore(&ctlr->queue_lock, flags);
return;
}
/* If another context is idling the device then defer */
if (ctlr->idling) {
kthread_queue_work(&ctlr->kworker, &ctlr->pump_messages);
spin_unlock_irqrestore(&ctlr->queue_lock, flags);
return;
}
/* Check if the queue is idle */
if (list_empty(&ctlr->queue) || !ctlr->running) {
if (!ctlr->busy) {
spin_unlock_irqrestore(&ctlr->queue_lock, flags);
return;
}
/* Only do teardown in the thread */
if (!in_kthread) {
kthread_queue_work(&ctlr->kworker,
&ctlr->pump_messages);
spin_unlock_irqrestore(&ctlr->queue_lock, flags);
return;
}
ctlr->busy = false;
ctlr->idling = true;
spin_unlock_irqrestore(&ctlr->queue_lock, flags);
kfree(ctlr->dummy_rx);
ctlr->dummy_rx = NULL;
kfree(ctlr->dummy_tx);
ctlr->dummy_tx = NULL;
if (ctlr->unprepare_transfer_hardware &&
ctlr->unprepare_transfer_hardware(ctlr))
dev_err(&ctlr->dev,
"failed to unprepare transfer hardware\n");
if (ctlr->auto_runtime_pm) {
pm_runtime_mark_last_busy(ctlr->dev.parent);
pm_runtime_put_autosuspend(ctlr->dev.parent);
}
trace_spi_controller_idle(ctlr);
spin_lock_irqsave(&ctlr->queue_lock, flags);
ctlr->idling = false;
spin_unlock_irqrestore(&ctlr->queue_lock, flags);
return;
}
queued 전송을 지원하는 spi 컨트롤러의 전송을 시작한다. 이 함수가 스레드 내부에서 호출된 경우 @in_kthread가 설정되어 요청된다.
- 코드 라인 8에서 @ctrl spi 컨트롤러에 큐잉된 메시지를 꺼내기 위해 @ctrl spi 컨트롤러의 큐 락을 건다.
- 코드 라인 11~13에서 이미 전송 중인 경우 락을 풀고 함수를 빠져나간다.
- 코드 라인 16~20에서 spi 컨트롤러가 다른 코드의 요청으로 인해 절전 진행 중(idling) 상태라면 메시지 전송을 이번 호출에서 유예(defer)시켜 다음 타임에 전송하도록 spi 전송 스레드를 다시 깨워 이 함수를 호출하도록 요청해놓고 함수를 빠져나간다.
- 코드 라인 23에서 spi 컨트롤러의 큐가 비어 있거나, shutdown 상태인 경우이다.
- 코드 라인 24~27에서 spi 컨트롤러가 busy 상태가 아니라면 메시지가 없는 상태로 이 함수가 호출된 상태이므로 그냥 함수를 빠져나간다.
- 코드 라인 30~35에서 스레드 내부에서 호출되지 않은 경우 이번 호출에서 유예(defer)시켜 다음 타임에 전송하도록 spi 전송 스레드를 다시 깨워 이 함수를 호출하도록 요청해놓고 함수를 빠져나간다.
- 코드 라인 37~39에서 spi 컨트롤러를 절전 상태로 변경하기 위해 busy 상태를 false로, idling 상태를 true로 변경하고 스핀락을 푼다.
- 코드 라인 41~44에서 spi 컨트롤러의 dumy_rx 및 dump_txㄹ르 해제하고 null을 대입한다.
- 코드 라인 45~48에서 spi 컨트롤러의 (*unprepare_transfer_hardware)가 지원되면 호출하여, spi 컨트롤러의 전원등을 끈다.
- 코드 라인 49~52에서 spi 컨트롤러의 (*auto_runtime_pm)가 지원되면 @spi 컨트롤러 디바이스의 마지막 busy 타임을 갱신하고, 절전 상태로 전환시킨다.
- 코드 라인 53에서 spi 컨트롤러가 절전(idle) 상태로 진입하였다는 메시지를 출력한다.
- 코드 라인 55~59에서 절전(idle) 상태로 진입이 완료되었으므로, spin 락을 획득한 생태로 spi 컨트롤러의 idling 상태를 false로 변경하고, 함수를 빠져나간다.
drivers/spi/spi.c – 2/2
/* Extract head of queue */
ctlr->cur_msg =
list_first_entry(&ctlr->queue, struct spi_message, queue);
list_del_init(&ctlr->cur_msg->queue);
if (ctlr->busy)
was_busy = true;
else
ctlr->busy = true;
spin_unlock_irqrestore(&ctlr->queue_lock, flags);
mutex_lock(&ctlr->io_mutex);
if (!was_busy && ctlr->auto_runtime_pm) {
ret = pm_runtime_get_sync(ctlr->dev.parent);
if (ret < 0) {
pm_runtime_put_noidle(ctlr->dev.parent);
dev_err(&ctlr->dev, "Failed to power device: %d\n",
ret);
mutex_unlock(&ctlr->io_mutex);
return;
}
}
if (!was_busy)
trace_spi_controller_busy(ctlr);
if (!was_busy && ctlr->prepare_transfer_hardware) {
ret = ctlr->prepare_transfer_hardware(ctlr);
if (ret) {
dev_err(&ctlr->dev,
"failed to prepare transfer hardware\n");
if (ctlr->auto_runtime_pm)
pm_runtime_put(ctlr->dev.parent);
mutex_unlock(&ctlr->io_mutex);
return;
}
}
trace_spi_message_start(ctlr->cur_msg);
if (ctlr->prepare_message) {
ret = ctlr->prepare_message(ctlr, ctlr->cur_msg);
if (ret) {
dev_err(&ctlr->dev, "failed to prepare message: %d\n",
ret);
ctlr->cur_msg->status = ret;
spi_finalize_current_message(ctlr);
goto out;
}
ctlr->cur_msg_prepared = true;
}
ret = spi_map_msg(ctlr, ctlr->cur_msg);
if (ret) {
ctlr->cur_msg->status = ret;
spi_finalize_current_message(ctlr);
goto out;
}
ret = ctlr->transfer_one_message(ctlr, ctlr->cur_msg);
if (ret) {
dev_err(&ctlr->dev,
"failed to transfer one message from queue\n");
goto out;
}
out:
mutex_unlock(&ctlr->io_mutex);
/* Prod the scheduler in case transfer_one() was busy waiting */
if (!ret)
cond_resched();
}
- 코드 라인 2~5에서 큐에서 처음 메시지를 하나 꺼내서 컨트롤러가 처리 중인 메시지로 둔다.
- 코드 라인 6~10에서 spi 컨트롤러를 busy 상태로 변경한다. 이미 busy 상태인 경우 was_busy에 true를 대입하고, 스핀락을 푼다.
- 코드 라인 12에서 spi 컨트롤러의 io 락을 획득한다.
- 코드 라인 14~23에서 io 락을 획득하였으므로 다시 한 번 확인하여 여전히 절전 중이면 함수를 빠져나간다.
- 코드 라인 25~26에서 spi 컨트롤러가 busy 상태가 아니었었으면(!was_busy) busy 상태로 진입했다는 트레이스 메시지를 출력한다.
- 코드 라인 28~45에서 spi 컨트롤러가 busy 상태가 아니었었고(!was_busy) spi 컨트롤러가 (*prepare_transfer_hardware)를 지원하는 경우 호출하여 spi 컨트롤러의 파워를 다시 켠다.
- 코드 라인 47에서 이제 막 전송을 시작하기 위해 트레이스 메시지를 출력한다.
- 코드 라인 49~59에서 spi 컨트롤러가 메시지 전송 전에 처리할 일을 수행하기 위해 spi 컨트롤러의 (*prepare_message)를 호출한다.
- 코드 라인 61~66에서 DMA 전송을 사용하는 spi 컨트롤러인 경우 DMA용 버퍼를 준비하고 매핑한다.
- 코드 라인 68~73에서 PTP 시스템 타임스탬프를 추가한다.
- spi: Add a PTP system timestamp to the transfer structure (2019, k)
- 코드 라인 75~80에서 spi 컨트롤러의 (*transfer_one_message)를 호출하여 메시지를 전송한다.
- 코드 라인 82~87에서 out: 레이블이다. io 락을 해제하고 함수를 나가는데, 전송이 실패(busy waiting)한 경우 preemption 포인트를 수행한다.
spi_finalize_current_message()
drivers/spi/spi.c
/**
* spi_finalize_current_message() - the current message is complete
* @ctlr: the controller to return the message to
*
* Called by the driver to notify the core that the message in the front of the
* queue is complete and can be removed from the queue.
*/
void spi_finalize_current_message(struct spi_controller *ctlr)
{
struct spi_message *mesg;
unsigned long flags;
int ret;
spin_lock_irqsave(&ctlr->queue_lock, flags);
mesg = ctlr->cur_msg;
spin_unlock_irqrestore(&ctlr->queue_lock, flags);
spi_unmap_msg(ctlr, mesg);
if (ctlr->cur_msg_prepared && ctlr->unprepare_message) {
ret = ctlr->unprepare_message(ctlr, mesg);
if (ret) {
dev_err(&ctlr->dev, "failed to unprepare message: %d\n",
ret);
}
}
spin_lock_irqsave(&ctlr->queue_lock, flags);
ctlr->cur_msg = NULL;
ctlr->cur_msg_prepared = false;
kthread_queue_work(&ctlr->kworker, &ctlr->pump_messages);
spin_unlock_irqrestore(&ctlr->queue_lock, flags);
trace_spi_message_done(mesg);
mesg->state = NULL;
if (mesg->complete)
mesg->complete(mesg->context);
}
EXPORT_SYMBOL_GPL(spi_finalize_current_message);
@ctrl spi 컨트롤러가 처리한 메시지의 완료 처리를 수행한다.
- 코드 라인 7~9에서 spi 컨트롤러가 처리한 메시지를 알아온다.
- 코드 라인 11에서 DMA 방식의 컨트롤러인 경우 DMA 버퍼의 매핑을 해제한다.
- 코드 라인 13~19에서 메시지의 처리가 완료된 후 처리할 일을 수행하기 위해, spi 컨트롤러가 (*unprepare_message)를 호출한다.
- 코드 라인 21~25에서 스핀락을 획득한 채로 spi 컨트롤러의 cur_msg에 null 을 대입하고, cur_msg_prepared에 false를 대입한 후 다시 다음 메시지 처리를 수행하도록 워커 스레드를 큐잉한다.
- 코드 라인 27에서 메시지 처리 완료 트레이스 메시지를 출력한다.
- 코드 라인 29~31에서 메시지의 상태를 null로 바꾸고, 메시지의 처리가 완료된 경우 complete를 호출하여, sinc 상태에서 대기 중인 태스크를 깨운다.
spi_write() & spi_read()
- spi_sync()를 호출하여 사용한다.
spi_read_flash()
- SPI 플래시를 읽을 수 있도록 최적화된 함수를 제공한다.
spi_message_init()
- SPI 메시지 초기화
spi_message_add_tail()
- 전송 요청을 메시지의 전송 리스트에 추가한다.
- spi_message->transfers 리스트에 spi_transfer->transfer_list를 추가한다.
구조체
spi_device 구조체
/** * struct spi_device - Controller side proxy for an SPI slave device * @dev: Driver model representation of the device. * @controller: SPI controller used with the device. * @master: Copy of controller, for backwards compatibility. * @max_speed_hz: Maximum clock rate to be used with this chip * (on this board); may be changed by the device's driver. * The spi_transfer.speed_hz can override this for each transfer. * @chip_select: Chipselect, distinguishing chips handled by @controller. * @mode: The spi mode defines how data is clocked out and in. * This may be changed by the device's driver. * The "active low" default for chipselect mode can be overridden * (by specifying SPI_CS_HIGH) as can the "MSB first" default for * each word in a transfer (by specifying SPI_LSB_FIRST). * @bits_per_word: Data transfers involve one or more words; word sizes * like eight or 12 bits are common. In-memory wordsizes are * powers of two bytes (e.g. 20 bit samples use 32 bits). * This may be changed by the device's driver, or left at the * default (0) indicating protocol words are eight bit bytes. * The spi_transfer.bits_per_word can override this for each transfer. * @irq: Negative, or the number passed to request_irq() to receive * interrupts from this device. * @controller_state: Controller's runtime state * @controller_data: Board-specific definitions for controller, such as * FIFO initialization parameters; from board_info.controller_data * @modalias: Name of the driver to use with this device, or an alias * for that name. This appears in the sysfs "modalias" attribute * for driver coldplugging, and in uevents used for hotplugging * @cs_gpio: gpio number of the chipselect line (optional, -ENOENT when * when not using a GPIO line) * * @statistics: statistics for the spi_device * * A @spi_device is used to interchange data between an SPI slave * (usually a discrete chip) and CPU memory. * * In @dev, the platform_data is used to hold information about this * device that's meaningful to the device's protocol driver, but not * to its controller. One example might be an identifier for a chip * variant with slightly different functionality; another might be * information about how this particular board wires the chip's pins. */
struct spi_device {
struct device dev;
struct spi_controller *controller;
struct spi_controller *master; /* compatibility layer */
u32 max_speed_hz;
u8 chip_select;
u8 bits_per_word;
u16 mode;
#define SPI_CPHA 0x01 /* clock phase */
#define SPI_CPOL 0x02 /* clock polarity */
#define SPI_MODE_0 (0|0) /* (original MicroWire) */
#define SPI_MODE_1 (0|SPI_CPHA)
#define SPI_MODE_2 (SPI_CPOL|0)
#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
#define SPI_CS_HIGH 0x04 /* chipselect active high? */
#define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
#define SPI_3WIRE 0x10 /* SI/SO signals shared */
#define SPI_LOOP 0x20 /* loopback mode */
#define SPI_NO_CS 0x40 /* 1 dev/bus, no chipselect */
#define SPI_READY 0x80 /* slave pulls low to pause */
#define SPI_TX_DUAL 0x100 /* transmit with 2 wires */
#define SPI_TX_QUAD 0x200 /* transmit with 4 wires */
#define SPI_RX_DUAL 0x400 /* receive with 2 wires */
#define SPI_RX_QUAD 0x800 /* receive with 4 wires */
int irq;
void *controller_state;
void *controller_data;
char modalias[SPI_NAME_SIZE];
int cs_gpio; /* chip select gpio */
/* the statistics */
struct spi_statistics statistics;
/*
* likely need more hooks for more protocol options affecting how
* the controller talks to each chip, like:
* - memory packing (12 bit samples into low bits, others zeroed)
* - priority
* - drop chipselect after each word
* - chipselect delays
* - ...
*/
};
spi 슬레이브 디바이스를 표현하는 구조체
- dev
- 디바이스 구조체
- *controller
- spi 컨트롤러를 가리킨다.
- *master
- spi 컨트롤러를 가리킨다. (호환을 위해 사용한다)
- max_speed_hz
- 디바이스가 처리할 수 있는 최대 처리 가능한 클럭
- chip_select
- 이 슬레이브 디바이스를 선택하기 위해 사용해야 할 chip 셀렉트 번호
- bits_per_word
- 한 번에 전송할 수 있는 워드 처리 대역 비트
- 보통 8 bits 또는 16bits를 사용하고, 32 bits를 지원하는 디바이스도 있다.
- mode
- spi 디바이스가 지원하는 기능들을 표현한다.
- irq
- spi 디바이스가 인터럽트를 사용하는 경우 지정된다.
- controller_state
- 컨트롤러의 런타임 상태
- controller_data
- 컨트롤러를 위한 보드별 설정이 담긴다.
- modalias[]
- 이 슬레이브 디바이스를 사용하기 위한 이름이 담긴다.
- cs_gpio
- chip 셀렉션을 위한 gpio 번호로 legacy 코드를 지원하기 위해 사용된다.
- statistics
- spi 디바이스 통계
spi_message 구조체
include/linux/spi/spi.h
/** * struct spi_message - one multi-segment SPI transaction * @transfers: list of transfer segments in this transaction * @spi: SPI device to which the transaction is queued * @is_dma_mapped: if true, the caller provided both dma and cpu virtual * addresses for each transfer buffer * @complete: called to report transaction completions * @context: the argument to complete() when it's called * @frame_length: the total number of bytes in the message * @actual_length: the total number of bytes that were transferred in all * successful segments * @status: zero for success, else negative errno * @queue: for use by whichever driver currently owns the message * @state: for use by whichever driver currently owns the message * @resources: for resource management when the spi message is processed * * A @spi_message is used to execute an atomic sequence of data transfers, * each represented by a struct spi_transfer. The sequence is "atomic" * in the sense that no other spi_message may use that SPI bus until that * sequence completes. On some systems, many such sequences can execute as * as single programmed DMA transfer. On all systems, these messages are * queued, and might complete after transactions to other devices. Messages * sent to a given spi_device are always executed in FIFO order. * * The code that submits an spi_message (and its spi_transfers) * to the lower layers is responsible for managing its memory. * Zero-initialize every field you don't set up explicitly, to * insulate against future API updates. After you submit a message * and its transfers, ignore them until its completion callback. */
struct spi_message {
struct list_head transfers;
struct spi_device *spi;
unsigned is_dma_mapped:1;
/* REVISIT: we might want a flag affecting the behavior of the
* last transfer ... allowing things like "read 16 bit length L"
* immediately followed by "read L bytes". Basically imposing
* a specific message scheduling algorithm.
*
* Some controller drivers (message-at-a-time queue processing)
* could provide that as their default scheduling algorithm. But
* others (with multi-message pipelines) could need a flag to
* tell them about such special cases.
*/
/* completion is reported through a callback */
void (*complete)(void *context);
void *context;
unsigned frame_length;
unsigned actual_length;
int status;
/* for optional use by whatever driver currently owns the
* spi_message ... between calls to spi_async and then later
* complete(), that's the spi_controller controller driver.
*/
struct list_head queue;
void *state;
/* list of spi_res reources when the spi message is processed */
struct list_head resources;
};
spi 메시지를 표현한다.
- transfers
- 트랜잭션을 구성하는 전송 리스트
- *spi
- 트랜잭션이 향할 spi 디바이스
- is_dma_mapped
- dma를 지원한다.
- (*complete)
- 트랜잭션이 완료되면 호출되는 후크 함수이다.
- *context
- (*complete) 호출될 때 사용되는 argument를 가리킨다.
- frame_length
- 메시지 전체 바이트 수
- actual_length
- 성공리에 SPI 전송된 전체 바이트 수
- status
- 0=성공, 음수=에러
- queue
- spi 컨트롤러의 큐에 등록될 때 사용하는 노드이다.
- *state
- 메시지 상태
- resources
- spi 메시지가 처리되었을 때 리소스 관리를 위해 사용한다.
/** * struct spi_transfer - a read/write buffer pair * @tx_buf: data to be written (dma-safe memory), or NULL * @rx_buf: data to be read (dma-safe memory), or NULL * @tx_dma: DMA address of tx_buf, if @spi_message.is_dma_mapped * @rx_dma: DMA address of rx_buf, if @spi_message.is_dma_mapped * @tx_nbits: number of bits used for writing. If 0 the default * (SPI_NBITS_SINGLE) is used. * @rx_nbits: number of bits used for reading. If 0 the default * (SPI_NBITS_SINGLE) is used. * @len: size of rx and tx buffers (in bytes) * @speed_hz: Select a speed other than the device default for this * transfer. If 0 the default (from @spi_device) is used. * @bits_per_word: select a bits_per_word other than the device default * for this transfer. If 0 the default (from @spi_device) is used. * @cs_change: affects chipselect after this transfer completes * @delay_usecs: microseconds to delay after this transfer before * (optionally) changing the chipselect status, then starting * the next transfer or completing this @spi_message. * @transfer_list: transfers are sequenced through @spi_message.transfers * @tx_sg: Scatterlist for transmit, currently not for client use * @rx_sg: Scatterlist for receive, currently not for client use * * SPI transfers always write the same number of bytes as they read. * Protocol drivers should always provide @rx_buf and/or @tx_buf. * In some cases, they may also want to provide DMA addresses for * the data being transferred; that may reduce overhead, when the * underlying driver uses dma. * * If the transmit buffer is null, zeroes will be shifted out * while filling @rx_buf. If the receive buffer is null, the data * shifted in will be discarded. Only "len" bytes shift out (or in). * It's an error to try to shift out a partial word. (For example, by * shifting out three bytes with word size of sixteen or twenty bits; * the former uses two bytes per word, the latter uses four bytes.) * * In-memory data values are always in native CPU byte order, translated * from the wire byte order (big-endian except with SPI_LSB_FIRST). So * for example when bits_per_word is sixteen, buffers are 2N bytes long * (@len = 2N) and hold N sixteen bit words in CPU byte order. * * When the word size of the SPI transfer is not a power-of-two multiple * of eight bits, those in-memory words include extra bits. In-memory * words are always seen by protocol drivers as right-justified, so the * undefined (rx) or unused (tx) bits are always the most significant bits. * * All SPI transfers start with the relevant chipselect active. Normally * it stays selected until after the last transfer in a message. Drivers * can affect the chipselect signal using cs_change. * * (i) If the transfer isn't the last one in the message, this flag is * used to make the chipselect briefly go inactive in the middle of the * message. Toggling chipselect in this way may be needed to terminate * a chip command, letting a single spi_message perform all of group of * chip transactions together. * * (ii) When the transfer is the last one in the message, the chip may * stay selected until the next transfer. On multi-device SPI busses * with nothing blocking messages going to other devices, this is just * a performance hint; starting a message to another device deselects * this one. But in other cases, this can be used to ensure correctness. * Some devices need protocol transactions to be built from a series of * spi_message submissions, where the content of one message is determined * by the results of previous messages and where the whole transaction * ends when the chipselect goes intactive. * * When SPI can transfer in 1x,2x or 4x. It can get this transfer information * from device through @tx_nbits and @rx_nbits. In Bi-direction, these * two should both be set. User can set transfer mode with SPI_NBITS_SINGLE(1x) * SPI_NBITS_DUAL(2x) and SPI_NBITS_QUAD(4x) to support these three transfer. * * The code that submits an spi_message (and its spi_transfers) * to the lower layers is responsible for managing its memory. * Zero-initialize every field you don't set up explicitly, to * insulate against future API updates. After you submit a message * and its transfers, ignore them until its completion callback. */
struct spi_transfer {
/* it's ok if tx_buf == rx_buf (right?)
* for MicroWire, one buffer must be null
* buffers must work with dma_*map_single() calls, unless
* spi_message.is_dma_mapped reports a pre-existing mapping
*/
const void *tx_buf;
void *rx_buf;
unsigned len;
dma_addr_t tx_dma;
dma_addr_t rx_dma;
struct sg_table tx_sg;
struct sg_table rx_sg;
unsigned cs_change:1;
unsigned tx_nbits:3;
unsigned rx_nbits:3;
#define SPI_NBITS_SINGLE 0x01 /* 1bit transfer */
#define SPI_NBITS_DUAL 0x02 /* 2bits transfer */
#define SPI_NBITS_QUAD 0x04 /* 4bits transfer */
u8 bits_per_word;
u16 delay_usecs;
u32 speed_hz;
struct list_head transfer_list;
};
- tx_buf
- 전송할 데이터를 가리키는 버퍼로 dma-safe되어야 한다.
- 이 값이 null인 경우 rx 비트를 수신시 마다 0이 shift 출력된다.
- rx_buf
- 수신한 데이터를 저장할 버퍼로 dma-safe되어야 한다.
- null 가능
- len
- tx 및 rx 버퍼 크기
- tx_dma
- tx dma 사용 시 tx_buf의 dma 주소
- rx_dma
- rx dma 사용 시 rx_buf의 dma 주소
- tx_sg
- tx용 Scatterlist
- rx_sg
- rx용 Scatterlist
- cs_change
- 전송 완료 후 chip select 필요 시
- tx_nbits
- 0인 경우 SPI_NBITS_SINGLE과 동일
- SPI_NBITS_SINGLE(1)
- tx 시 한 클럭에 1비트 전송
- SPI_NBITS_DUAL(2)
- tx 시 한 클럭에 2비트 전송
- SPI_NBITS_QUAd(4)
- tx 시 한 클럭에 4비트 전송
- rx_nbits
- tx_nbits와 동일
- bits_per_word
- 워드 전송 시 사용할 비트 수
- 0=디폴트 사용
- 대부분의 경우 8비트를 사용하지만,
- 터치 스크린 컨트롤러는 16비트를 사용하는 경우도 있고,
- TI사의 A/D 또는 D/A 컨버터는 12비트를 사용하는 경우도 있다.
- delay_usecs
- 전송 후 필요한 딜레이
- speed_hz
- 사용할 스피드
- 0=디폴트 사용
- transfer_list
- spi_message.transfers를 통해 순차 처리할 전송들이다.
참고
- SPI Subsystem -1- (Basic) | 문c
- SPI Subsystem -2- (Driver) | 문c – 현재 글