€•QwŒsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ+/translations/zh_CN/spi/multiple-data-lanes”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/zh_TW/spi/multiple-data-lanes”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/it_IT/spi/multiple-data-lanes”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/ja_JP/spi/multiple-data-lanes”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/ko_KR/spi/multiple-data-lanes”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒPortuguese (Brazilian)”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/pt_BR/spi/multiple-data-lanes”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/sp_SP/spi/multiple-data-lanes”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒ$SPI devices with multiple data lanes”h]”hŒ$SPI devices with multiple data lanes”…””}”(hh¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhh·h²hh³ŒE/var/lib/git/docbuild/linux/Documentation/spi/multiple-data-lanes.rst”h´KubhŒ paragraph”“”)”}”(hŒùSome specialized SPI controllers and peripherals support multiple data lanes that allow reading more than one word at a time in parallel. This is different from dual/quad/octal SPI where multiple bits of a single word are transferred simultaneously.”h]”hŒùSome specialized SPI controllers and peripherals support multiple data lanes that allow reading more than one word at a time in parallel. This is different from dual/quad/octal SPI where multiple bits of a single word are transferred simultaneously.”…””}”(hhÍh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhÌ)”}”(hŒŸFor example, controllers that support parallel flash memories have this feature as do some simultaneous-sampling ADCs where each channel has its own data lane.”h]”hŒŸFor example, controllers that support parallel flash memories have this feature as do some simultaneous-sampling ADCs where each channel has its own data lane.”…””}”(hhÛh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K hh·h²hubh¶)”}”(hhh]”(h»)”}”(hŒDescribing the wiring”h]”hŒDescribing the wiring”…””}”(hhìh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhhéh²hh³hÊh´KubhÌ)”}”(hXBThe ``spi-tx-bus-width`` and ``spi-rx-bus-width`` properties in the devicetree are used to describe how many data lanes are connected between the controller and how wide each lane is. The number of items in the array indicates how many lanes there are, and the value of each item indicates how many bits wide that lane is.”h]”(hŒThe ”…””}”(hhúh²hh³Nh´NubhŒliteral”“”)”}”(hŒ``spi-tx-bus-width``”h]”hŒspi-tx-bus-width”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhhúubhŒ and ”…””}”(hhúh²hh³Nh´Nubj)”}”(hŒ``spi-rx-bus-width``”h]”hŒspi-rx-bus-width”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhhúubhX properties in the devicetree are used to describe how many data lanes are connected between the controller and how wide each lane is. The number of items in the array indicates how many lanes there are, and the value of each item indicates how many bits wide that lane is.”…””}”(hhúh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khhéh²hubhÌ)”}”(hŒ`For example, a dual-simultaneous-sampling ADC with two 4-bit lanes might be wired up like this::”h]”hŒ_For example, a dual-simultaneous-sampling ADC with two 4-bit lanes might be wired up like this:”…””}”(hj.h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khhéh²hubhŒ literal_block”“”)”}”(hXr+--------------+ +----------+ | SPI | | AD4630 | | Controller | | ADC | | | | | | CS0 |--->| CS | | SCK |--->| SCK | | SDO |--->| SDI | | | | | | SDIA0 |<---| SDOA0 | | SDIA1 |<---| SDOA1 | | SDIA2 |<---| SDOA2 | | SDIA3 |<---| SDOA3 | | | | | | SDIB0 |<---| SDOB0 | | SDIB1 |<---| SDOB1 | | SDIB2 |<---| SDOB2 | | SDIB3 |<---| SDOB3 | | | | | +--------------+ +----------+”h]”hXr+--------------+ +----------+ | SPI | | AD4630 | | Controller | | ADC | | | | | | CS0 |--->| CS | | SCK |--->| SCK | | SDO |--->| SDI | | | | | | SDIA0 |<---| SDOA0 | | SDIA1 |<---| SDOA1 | | SDIA2 |<---| SDOA2 | | SDIA3 |<---| SDOA3 | | | | | | SDIB0 |<---| SDOB0 | | SDIB1 |<---| SDOB1 | | SDIB2 |<---| SDOB2 | | SDIB3 |<---| SDOB3 | | | | | +--------------+ +----------+”…””}”hj>sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1j<h³hÊh´Khhéh²hubhÌ)”}”(hŒ+It is described in a devicetree like this::”h]”hŒ*It is described in a devicetree like this:”…””}”(hjNh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K.hhéh²hubj=)”}”(hŒÛspi { compatible = "my,spi-controller"; ... adc@0 { compatible = "adi,ad4630"; reg = <0>; ... spi-rx-bus-width = <4>, <4>; /* 2 lanes of 4 bits each */ ... }; };”h]”hŒÛspi { compatible = "my,spi-controller"; ... adc@0 { compatible = "adi,ad4630"; reg = <0>; ... spi-rx-bus-width = <4>, <4>; /* 2 lanes of 4 bits each */ ... }; };”…””}”hj\sbah}”(h]”h ]”h"]”h$]”h&]”jLjMuh1j<h³hÊh´K0hhéh²hubhÌ)”}”(hŒõIn most cases, lanes will be wired up symmetrically (A to A, B to B, etc). If this isn't the case, extra ``spi-rx-lane-map`` and ``spi-tx-lane-map`` properties are needed to provide a mapping between controller lanes and the physical lane wires.”h]”(hŒkIn most cases, lanes will be wired up symmetrically (A to A, B to B, etc). If this isn’t the case, extra ”…””}”(hjjh²hh³Nh´Nubj)”}”(hŒ``spi-rx-lane-map``”h]”hŒspi-rx-lane-map”…””}”(hjrh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjjubhŒ and ”…””}”(hjjh²hh³Nh´Nubj)”}”(hŒ``spi-tx-lane-map``”h]”hŒspi-tx-lane-map”…””}”(hj„h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjjubhŒa properties are needed to provide a mapping between controller lanes and the physical lane wires.”…””}”(hjjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K>hhéh²hubhÌ)”}”(hŒnHere is an example where a multi-lane SPI controller has each lane wired to separate single-lane peripherals::”h]”hŒmHere is an example where a multi-lane SPI controller has each lane wired to separate single-lane peripherals:”…””}”(hjœh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KChhéh²hubj=)”}”(hXƒ+--------------+ +----------+ | SPI | | Thing 1 | | Controller | | | | | | | | CS0 |--->| CS | | SDO0 |--->| SDI | | SDI0 |<---| SDO | | SCLK0 |--->| SCLK | | | | | | | +----------+ | | | | +----------+ | | | Thing 2 | | | | | | CS1 |--->| CS | | SDO1 |--->| SDI | | SDI1 |<---| SDO | | SCLK1 |--->| SCLK | | | | | +--------------+ +----------+”h]”hXƒ+--------------+ +----------+ | SPI | | Thing 1 | | Controller | | | | | | | | CS0 |--->| CS | | SDO0 |--->| SDI | | SDI0 |<---| SDO | | SCLK0 |--->| SCLK | | | | | | | +----------+ | | | | +----------+ | | | Thing 2 | | | | | | CS1 |--->| CS | | SDO1 |--->| SDI | | SDI1 |<---| SDO | | SCLK1 |--->| SCLK | | | | | +--------------+ +----------+”…””}”hjªsbah}”(h]”h ]”h"]”h$]”h&]”jLjMuh1j<h³hÊh´KFhhéh²hubhÌ)”}”(hŒ-This is described in a devicetree like this::”h]”hŒ,This is described in a devicetree like this:”…””}”(hj¸h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K[hhéh²hubj=)”}”(hX›spi { compatible = "my,spi-controller"; ... thing1@0 { compatible = "my,thing1"; reg = <0>; ... }; thing2@1 { compatible = "my,thing2"; reg = <1>; ... spi-tx-lane-map = <1>; /* lane 0 is not used, lane 1 is used for tx wire */ spi-rx-lane-map = <1>; /* lane 0 is not used, lane 1 is used for rx wire */ ... }; };”h]”hX›spi { compatible = "my,spi-controller"; ... thing1@0 { compatible = "my,thing1"; reg = <0>; ... }; thing2@1 { compatible = "my,thing2"; reg = <1>; ... spi-tx-lane-map = <1>; /* lane 0 is not used, lane 1 is used for tx wire */ spi-rx-lane-map = <1>; /* lane 0 is not used, lane 1 is used for rx wire */ ... }; };”…””}”hjÆsbah}”(h]”h ]”h"]”h$]”h&]”jLjMuh1j<h³hÊh´K]hhéh²hubhÌ)”}”(hŒ¹The default values of ``spi-rx-bus-width`` and ``spi-tx-bus-width`` are ``<1>``, so these properties can still be omitted even when ``spi-rx-lane-map`` and ``spi-tx-lane-map`` are used.”h]”(hŒThe default values of ”…””}”(hjÔh²hh³Nh´Nubj)”}”(hŒ``spi-rx-bus-width``”h]”hŒspi-rx-bus-width”…””}”(hjÜh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjÔubhŒ and ”…””}”(hjÔh²hh³Nh´Nubj)”}”(hŒ``spi-tx-bus-width``”h]”hŒspi-tx-bus-width”…””}”(hjîh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjÔubhŒ are ”…””}”(hjÔh²hh³Nh´Nubj)”}”(hŒ``<1>``”h]”hŒ<1>”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjÔubhŒ5, so these properties can still be omitted even when ”…””}”(hjÔh²hh³Nh´Nubj)”}”(hŒ``spi-rx-lane-map``”h]”hŒspi-rx-lane-map”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjÔubhŒ and ”…””}”(hjÔh²hh³Nh´Nubj)”}”(hŒ``spi-tx-lane-map``”h]”hŒspi-tx-lane-map”…””}”(hj$h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjÔubhŒ are used.”…””}”(hjÔh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kshhéh²hubeh}”(h]”Œdescribing-the-wiring”ah ]”h"]”Œdescribing the wiring”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kubh¶)”}”(hhh]”(h»)”}”(hŒUsage in a peripheral driver”h]”hŒUsage in a peripheral driver”…””}”(hjGh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjDh²hh³hÊh´KyubhÌ)”}”(hX4These types of SPI controllers generally do not support arbitrary use of the multiple lanes. Instead, they operate in one of a few defined modes. Peripheral drivers should set the :c:type:`struct spi_transfer.multi_lane_mode ` field to indicate which mode they want to use for a given transfer.”h]”(hŒ´These types of SPI controllers generally do not support arbitrary use of the multiple lanes. Instead, they operate in one of a few defined modes. Peripheral drivers should set the ”…””}”(hjUh²hh³Nh´Nubh)”}”(hŒ<:c:type:`struct spi_transfer.multi_lane_mode `”h]”j)”}”(hj_h]”hŒ#struct spi_transfer.multi_lane_mode”…””}”(hjah²hh³Nh´Nubah}”(h]”h ]”(Œxref”Œc”Œc-type”eh"]”h$]”h&]”uh1jhj]ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”Œspi/multiple-data-lanes”Œ refdomain”jlŒreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰Œ reftarget”Œ spi_transfer”uh1hh³hÊh´K{hjUubhŒD field to indicate which mode they want to use for a given transfer.”…””}”(hjUh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K{hjDh²hubhÌ)”}”(hŒ@The possible values for this field have the following semantics:”h]”hŒ@The possible values for this field have the following semantics:”…””}”(hjŠh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K€hjDh²hubhŒ bullet_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hX«:c:macro:`SPI_MULTI_BUS_MODE_SINGLE`: Only use the first lane. Other lanes are ignored. This means that it is operating just like a conventional SPI peripheral. This is the default, so it does not need to be explicitly set. Example:: tx_buf[0] = 0x88; struct spi_transfer xfer = { .tx_buf = tx_buf, .len = 1, }; spi_sync_transfer(spi, &xfer, 1); Assuming the controller is sending the MSB first, the sequence of bits sent over the tx wire would be (right-most bit is sent first):: controller > data bits > peripheral ---------- ---------------- ---------- SDO 0 0-0-0-1-0-0-0-1 SDI 0 ”h]”hŒdefinition_list”“”)”}”(hhh]”hŒdefinition_list_item”“”)”}”(hX:c:macro:`SPI_MULTI_BUS_MODE_SINGLE`: Only use the first lane. Other lanes are ignored. This means that it is operating just like a conventional SPI peripheral. This is the default, so it does not need to be explicitly set. Example:: tx_buf[0] = 0x88; struct spi_transfer xfer = { .tx_buf = tx_buf, .len = 1, }; spi_sync_transfer(spi, &xfer, 1); Assuming the controller is sending the MSB first, the sequence of bits sent over the tx wire would be (right-most bit is sent first):: controller > data bits > peripheral ---------- ---------------- ---------- SDO 0 0-0-0-1-0-0-0-1 SDI 0 ”h]”(hŒterm”“”)”}”(hŒN:c:macro:`SPI_MULTI_BUS_MODE_SINGLE`: Only use the first lane. Other lanes are”h]”(h)”}”(hŒ$:c:macro:`SPI_MULTI_BUS_MODE_SINGLE`”h]”j)”}”(hj¶h]”hŒSPI_MULTI_BUS_MODE_SINGLE”…””}”(hj¸h²hh³Nh´Nubah}”(h]”h ]”(jkjlŒc-macro”eh"]”h$]”h&]”uh1jhj´ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jxŒ refdomain”jlŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰j~ŒSPI_MULTI_BUS_MODE_SINGLE”uh1hh³hÊh´K–hj°ubhŒ*: Only use the first lane. Other lanes are”…””}”(hj°h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1j®h³hÊh´K–hjªubhŒ definition”“”)”}”(hhh]”(hÌ)”}”(hŒignored. This means that it is operating just like a conventional SPI peripheral. This is the default, so it does not need to be explicitly set.”h]”hŒignored. This means that it is operating just like a conventional SPI peripheral. This is the default, so it does not need to be explicitly set.”…””}”(hjâh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KƒhjßubhÌ)”}”(hŒ Example::”h]”hŒExample:”…””}”(hjðh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K†hjßubj=)”}”(hŒytx_buf[0] = 0x88; struct spi_transfer xfer = { .tx_buf = tx_buf, .len = 1, }; spi_sync_transfer(spi, &xfer, 1);”h]”hŒytx_buf[0] = 0x88; struct spi_transfer xfer = { .tx_buf = tx_buf, .len = 1, }; spi_sync_transfer(spi, &xfer, 1);”…””}”hjþsbah}”(h]”h ]”h"]”h$]”h&]”jLjMuh1j<h³hÊh´KˆhjßubhÌ)”}”(hŒ†Assuming the controller is sending the MSB first, the sequence of bits sent over the tx wire would be (right-most bit is sent first)::”h]”hŒ…Assuming the controller is sending the MSB first, the sequence of bits sent over the tx wire would be (right-most bit is sent first):”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K‘hjßubj=)”}”(hŒ{controller > data bits > peripheral ---------- ---------------- ---------- SDO 0 0-0-0-1-0-0-0-1 SDI 0”h]”hŒ{controller > data bits > peripheral ---------- ---------------- ---------- SDO 0 0-0-0-1-0-0-0-1 SDI 0”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”jLjMuh1j<h³hÊh´K”hjßubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÝhjªubeh}”(h]”h ]”h"]”h$]”h&]”uh1j¨h³hÊh´K–hj¥ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjŸubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjšh²hh³Nh´Nubjž)”}”(hXg:c:macro:`SPI_MULTI_BUS_MODE_MIRROR`: Send a single data word over all of the lanes at the same time. This only makes sense for writes and not for reads. Example:: tx_buf[0] = 0x88; struct spi_transfer xfer = { .tx_buf = tx_buf, .len = 1, .multi_lane_mode = SPI_MULTI_BUS_MODE_MIRROR, }; spi_sync_transfer(spi, &xfer, 1); The data is mirrored on each tx wire:: controller > data bits > peripheral ---------- ---------------- ---------- SDO 0 0-0-0-1-0-0-0-1 SDI 0 SDO 1 0-0-0-1-0-0-0-1 SDI 1 ”h]”j¤)”}”(hhh]”j©)”}”(hXI:c:macro:`SPI_MULTI_BUS_MODE_MIRROR`: Send a single data word over all of the lanes at the same time. This only makes sense for writes and not for reads. Example:: tx_buf[0] = 0x88; struct spi_transfer xfer = { .tx_buf = tx_buf, .len = 1, .multi_lane_mode = SPI_MULTI_BUS_MODE_MIRROR, }; spi_sync_transfer(spi, &xfer, 1); The data is mirrored on each tx wire:: controller > data bits > peripheral ---------- ---------------- ---------- SDO 0 0-0-0-1-0-0-0-1 SDI 0 SDO 1 0-0-0-1-0-0-0-1 SDI 1 ”h]”(j¯)”}”(hŒM:c:macro:`SPI_MULTI_BUS_MODE_MIRROR`: Send a single data word over all of the”h]”(h)”}”(hŒ$:c:macro:`SPI_MULTI_BUS_MODE_MIRROR`”h]”j)”}”(hjQh]”hŒSPI_MULTI_BUS_MODE_MIRROR”…””}”(hjSh²hh³Nh´Nubah}”(h]”h ]”(jkjlŒc-macro”eh"]”h$]”h&]”uh1jhjOubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jxŒ refdomain”jlŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰j~ŒSPI_MULTI_BUS_MODE_MIRROR”uh1hh³hÊh´K­hjKubhŒ): Send a single data word over all of the”…””}”(hjKh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1j®h³hÊh´K­hjGubjÞ)”}”(hhh]”(hÌ)”}”(hŒKlanes at the same time. This only makes sense for writes and not for reads.”h]”hŒKlanes at the same time. This only makes sense for writes and not for reads.”…””}”(hj{h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K™hjxubhÌ)”}”(hŒ Example::”h]”hŒExample:”…””}”(hj‰h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Kœhjxubj=)”}”(hŒ«tx_buf[0] = 0x88; struct spi_transfer xfer = { .tx_buf = tx_buf, .len = 1, .multi_lane_mode = SPI_MULTI_BUS_MODE_MIRROR, }; spi_sync_transfer(spi, &xfer, 1);”h]”hŒ«tx_buf[0] = 0x88; struct spi_transfer xfer = { .tx_buf = tx_buf, .len = 1, .multi_lane_mode = SPI_MULTI_BUS_MODE_MIRROR, }; spi_sync_transfer(spi, &xfer, 1);”…””}”hj—sbah}”(h]”h ]”h"]”h$]”h&]”jLjMuh1j<h³hÊh´KžhjxubhÌ)”}”(hŒ&The data is mirrored on each tx wire::”h]”hŒ%The data is mirrored on each tx wire:”…””}”(hj¥h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K¨hjxubj=)”}”(hŒ¡controller > data bits > peripheral ---------- ---------------- ---------- SDO 0 0-0-0-1-0-0-0-1 SDI 0 SDO 1 0-0-0-1-0-0-0-1 SDI 1”h]”hŒ¡controller > data bits > peripheral ---------- ---------------- ---------- SDO 0 0-0-0-1-0-0-0-1 SDI 0 SDO 1 0-0-0-1-0-0-0-1 SDI 1”…””}”hj³sbah}”(h]”h ]”h"]”h$]”h&]”jLjMuh1j<h³hÊh´Kªhjxubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÝhjGubeh}”(h]”h ]”h"]”h$]”h&]”uh1j¨h³hÊh´K­hjDubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj@ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjšh²hh³Nh´Nubjž)”}”(hX6:c:macro:`SPI_MULTI_BUS_MODE_STRIPE`: Send or receive two different data words at the same time, one on each lane. This means that the buffer needs to be sized to hold data for all lanes. Data is interleaved in the buffer, with the first word corresponding to lane 0, the second to lane 1, and so on. Once the last lane is used, the next word in the buffer corresponds to lane 0 again. Accordingly, the buffer size must be a multiple of the number of lanes. This mode works for both reads and writes. Example:: struct spi_transfer xfer = { .rx_buf = rx_buf, .len = 2, .multi_lane_mode = SPI_MULTI_BUS_MODE_STRIPE, }; spi_sync_transfer(spi, &xfer, 1); Each rx wire has a different data word sent simultaneously:: controller < data bits < peripheral ---------- ---------------- ---------- SDI 0 0-0-0-1-0-0-0-1 SDO 0 SDI 1 1-0-0-0-1-0-0-0 SDO 1 After the transfer, ``rx_buf[0] == 0x11`` (word from SDO 0) and ``rx_buf[1] == 0x88`` (word from SDO 1). ”h]”j¤)”}”(hhh]”j©)”}”(hX:c:macro:`SPI_MULTI_BUS_MODE_STRIPE`: Send or receive two different data words at the same time, one on each lane. This means that the buffer needs to be sized to hold data for all lanes. Data is interleaved in the buffer, with the first word corresponding to lane 0, the second to lane 1, and so on. Once the last lane is used, the next word in the buffer corresponds to lane 0 again. Accordingly, the buffer size must be a multiple of the number of lanes. This mode works for both reads and writes. Example:: struct spi_transfer xfer = { .rx_buf = rx_buf, .len = 2, .multi_lane_mode = SPI_MULTI_BUS_MODE_STRIPE, }; spi_sync_transfer(spi, &xfer, 1); Each rx wire has a different data word sent simultaneously:: controller < data bits < peripheral ---------- ---------------- ---------- SDI 0 0-0-0-1-0-0-0-1 SDO 0 SDI 1 1-0-0-0-1-0-0-0 SDO 1 After the transfer, ``rx_buf[0] == 0x11`` (word from SDO 0) and ``rx_buf[1] == 0x88`` (word from SDO 1). ”h]”(j¯)”}”(hŒN:c:macro:`SPI_MULTI_BUS_MODE_STRIPE`: Send or receive two different data words”h]”(h)”}”(hŒ$:c:macro:`SPI_MULTI_BUS_MODE_STRIPE`”h]”j)”}”(hjêh]”hŒSPI_MULTI_BUS_MODE_STRIPE”…””}”(hjìh²hh³Nh´Nubah}”(h]”h ]”(jkjlŒc-macro”eh"]”h$]”h&]”uh1jhjèubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jxŒ refdomain”jlŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰j~ŒSPI_MULTI_BUS_MODE_STRIPE”uh1hh³hÊh´KÊhjäubhŒ*: Send or receive two different data words”…””}”(hjäh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1j®h³hÊh´KÊhjàubjÞ)”}”(hhh]”(hÌ)”}”(hX¥at the same time, one on each lane. This means that the buffer needs to be sized to hold data for all lanes. Data is interleaved in the buffer, with the first word corresponding to lane 0, the second to lane 1, and so on. Once the last lane is used, the next word in the buffer corresponds to lane 0 again. Accordingly, the buffer size must be a multiple of the number of lanes. This mode works for both reads and writes.”h]”hX¥at the same time, one on each lane. This means that the buffer needs to be sized to hold data for all lanes. Data is interleaved in the buffer, with the first word corresponding to lane 0, the second to lane 1, and so on. Once the last lane is used, the next word in the buffer corresponds to lane 0 again. Accordingly, the buffer size must be a multiple of the number of lanes. This mode works for both reads and writes.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K°hjubhÌ)”}”(hŒ Example::”h]”hŒExample:”…””}”(hj"h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K·hjubj=)”}”(hŒ˜struct spi_transfer xfer = { .rx_buf = rx_buf, .len = 2, .multi_lane_mode = SPI_MULTI_BUS_MODE_STRIPE, }; spi_sync_transfer(spi, &xfer, 1);”h]”hŒ˜struct spi_transfer xfer = { .rx_buf = rx_buf, .len = 2, .multi_lane_mode = SPI_MULTI_BUS_MODE_STRIPE, }; spi_sync_transfer(spi, &xfer, 1);”…””}”hj0sbah}”(h]”h ]”h"]”h$]”h&]”jLjMuh1j<h³hÊh´K¹hjubhÌ)”}”(hŒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÁhjubj=)”}”(hŒ¡controller < data bits < peripheral ---------- ---------------- ---------- SDI 0 0-0-0-1-0-0-0-1 SDO 0 SDI 1 1-0-0-0-1-0-0-0 SDO 1”h]”hŒ¡controller < data bits < peripheral ---------- ---------------- ---------- SDI 0 0-0-0-1-0-0-0-1 SDO 0 SDI 1 1-0-0-0-1-0-0-0 SDO 1”…””}”hjLsbah}”(h]”h ]”h"]”h$]”h&]”jLjMuh1j<h³hÊh´KÃhjubhÌ)”}”(hŒhAfter the transfer, ``rx_buf[0] == 0x11`` (word from SDO 0) and ``rx_buf[1] == 0x88`` (word from SDO 1).”h]”(hŒAfter the transfer, ”…””}”(hjZh²hh³Nh´Nubj)”}”(hŒ``rx_buf[0] == 0x11``”h]”hŒrx_buf[0] == 0x11”…””}”(hjbh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjZubhŒ (word from SDO 0) and ”…””}”(hjZh²hh³Nh´Nubj)”}”(hŒ``rx_buf[1] == 0x88``”h]”hŒrx_buf[1] == 0x88”…””}”(hjth²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjZubhŒ (word from SDO 1).”…””}”(hjZh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÈhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÝhjàubeh}”(h]”h ]”h"]”h$]”h&]”uh1j¨h³hÊh´KÊhjÝubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjÙubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjšh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1j˜h³hÊh´K‚hjDh²hubeh}”(h]”Œusage-in-a-peripheral-driver”ah ]”h"]”Œusage in a peripheral driver”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kyubh¶)”}”(hhh]”(h»)”}”(hŒSPI controller driver support”h]”hŒSPI controller driver support”…””}”(hj·h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj´h²hh³hÊh´KÎubhÌ)”}”(hŒTo support multiple data lanes, SPI controller drivers need to set :c:type:`struct spi_controller.num_data_lanes ` to a value greater than 1.”h]”(hŒCTo support multiple data lanes, SPI controller drivers need to set ”…””}”(hjÅh²hh³Nh´Nubh)”}”(hŒ?:c:type:`struct spi_controller.num_data_lanes `”h]”j)”}”(hjÏh]”hŒ$struct spi_controller.num_data_lanes”…””}”(hjÑh²hh³Nh´Nubah}”(h]”h ]”(jkjlŒc-type”eh"]”h$]”h&]”uh1jhjÍubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jxŒ refdomain”jlŒreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰j~Œspi_controller”uh1hh³hÊh´KÐhjÅubhŒ to a value greater than 1.”…””}”(hjÅh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÐhj´h²hubhÌ)”}”(hŒöThen the part of the driver that handles SPI transfers needs to check the :c:type:`struct spi_transfer.multi_lane_mode ` field and implement the appropriate behavior for each supported mode and return an error for unsupported modes.”h]”(hŒJThen the part of the driver that handles SPI transfers needs to check the ”…””}”(hjöh²hh³Nh´Nubh)”}”(hŒ<:c:type:`struct spi_transfer.multi_lane_mode `”h]”j)”}”(hjh]”hŒ#struct spi_transfer.multi_lane_mode”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”(jkjlŒc-type”eh"]”h$]”h&]”uh1jhjþubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jxŒ refdomain”jlŒreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰j~Œ spi_transfer”uh1hh³hÊh´KÔhjöubhŒp field and implement the appropriate behavior for each supported mode and return an error for unsupported modes.”…””}”(hjöh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÔhj´h²hubhÌ)”}”(hŒ)The core SPI code should handle the rest.”h]”hŒ)The core SPI code should handle the rest.”…””}”(hj'h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KÙhj´h²hubeh}”(h]”Œspi-controller-driver-support”ah ]”h"]”Œspi controller driver support”ah$]”h&]”uh1hµhh·h²hh³hÊh´KÎubeh}”(h]”Œ$spi-devices-with-multiple-data-lanes”ah ]”h"]”Œ$spi devices with multiple data lanes”ah$]”h&]”uh1hµhhh²hh³hÊh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÊuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(hºNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”jhŒerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÊŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(jBj?jAj>j±j®j:j7uŒ nametypes”}”(jB‰jA‰j±‰j:‰uh}”(j?h·j>héj®jDj7j´uŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.