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 – 현재 글