Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b357ec6
MT-158113: add MultiTracks SPI transport driver (Host role) for imx8m…
MT-MichaelLoh Aug 16, 2026
d3091e2
MT-158113: fix spi-mt-transport header lookup under out-of-tree kerne…
MT-MichaelLoh Aug 16, 2026
4797fd2
MT-158113: add stdbool.h/stdint.h/stdarg.h kernel-compat shims
MT-MichaelLoh Aug 16, 2026
bb0003d
MT-158113: fix pAbort() no-op race corrupting SPI core state on DMA t…
MT-MichaelLoh Aug 17, 2026
650eefe
MT-158113: log/count link events, add event_counters sysfs attribute
MT-MichaelLoh Aug 18, 2026
2b60361
MT-158113: remove spi-mt-transport driver -- moved to an out-of-tree …
MT-MichaelLoh Aug 18, 2026
271a69d
MT-158113: revive in-tree spi-mt-transport driver, core stays out
MT-MichaelLoh Aug 19, 2026
969c3d4
MT-158113: fix Copilot review findings on the revived in-tree driver
MT-MichaelLoh Aug 19, 2026
a3ec60e
MT-158113: second round of Copilot review fixes
MT-MichaelLoh Aug 19, 2026
05ac4fc
MT-158113: third round of Copilot review fixes (DT schema, fail-fast)
MT-MichaelLoh Aug 19, 2026
47c3d31
MT-158113: fourth round of Copilot review fixes (IRQ0, remove() race)
MT-MichaelLoh Aug 19, 2026
0ddfa20
MT-158113: fifth round of Copilot review fixes (miscdevice UAF, reade…
MT-MichaelLoh Aug 19, 2026
b9362b9
MT-158113: sixth round of Copilot review fixes (wake removed waiters)
MT-MichaelLoh Aug 19, 2026
a506207
MT-158113: seventh round of Copilot review fixes (brace style nit)
MT-MichaelLoh Aug 19, 2026
3315caa
MT-158113: document known tx_in_flight_idx capacity gap (MT-158925)
MT-MichaelLoh Aug 20, 2026
cbe5980
MT-158113: ninth round of Copilot review fixes (probe() IRQ-vs-kref U…
MT-MichaelLoh Aug 20, 2026
d6d05b2
MT-158113: tenth round of Copilot review fixes (va_list portability)
MT-MichaelLoh Aug 20, 2026
f6dab87
MT-158113: add channel 2 (Property Model) support to spi-mt-transport
MT-MichaelLoh Aug 25, 2026
13bf6a0
MT-158113: fix event_callback context type confusion (NULL-deref Oops)
MT-MichaelLoh Aug 25, 2026
89bb2f2
MT-158113: eleventh round of Copilot review fixes (transferComplete o…
MT-MichaelLoh Aug 26, 2026
1496c4b
MT-158113: address PR #46's suppressed Copilot findings (read race, r…
MT-MichaelLoh Aug 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/multitracks,spi-transport.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: MultiTracks SPI transport protocol (Host role)

maintainers:
- Michael Loh <michael@multitracks.com>

description: |
A framed, multi-channel, ack/retry link between an i.MX SoC (Host) and an
STM32-class client MCU (Client) over a raw SPI bus, plus a companion NRDY
GPIO handshake line in addition to the physical SPI SCK/MOSI/MISO lines.
See the firmware repo's firmware-common/spi-transport/docs/ProtocolSpec.md
for the full wire protocol.

NSS and NRDY are bound here as driver-private properties, not the
standard "cs-gpios" -- the protocol holds NSS low continuously across a
multi-step request/ack/clock/complete cycle, not just one SPI transfer,
so the driver owns and drives it directly rather than letting the SPI
core auto-toggle it per-message.

allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#

properties:
compatible:
const: multitracks,spi-transport

reg:
maxItems: 1

multitracks,nss-gpios:
maxItems: 1
description:
Host-driven NSS (transfer request) line, held low across the whole
request/ack/clock/complete cycle. Always GPIO_ACTIVE_HIGH regardless
of the physical wire's true active sense, so the driver's logical
value always equals the literal pin level (the protocol's own
convention is "true = pin HIGH").

multitracks,nrdy-gpios:
maxItems: 1
description:
Client-driven NRDY (ready/ack) line, read by the Host. Same
GPIO_ACTIVE_HIGH convention as multitracks,nss-gpios.

required:
- compatible
- reg
- spi-max-frequency
- multitracks,nss-gpios
- multitracks,nrdy-gpios

unevaluatedProperties: false

examples:
- |
#include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;

spi@0 {
compatible = "multitracks,spi-transport";
reg = <0>;
spi-max-frequency = <500000>;

multitracks,nss-gpios = <&gpio5 13 GPIO_ACTIVE_HIGH>;
multitracks,nrdy-gpios = <&gpio4 29 GPIO_ACTIVE_HIGH>;
};
};

...
2 changes: 2 additions & 0 deletions Documentation/devicetree/bindings/vendor-prefixes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,8 @@ patternProperties:
description: Imagination Technologies Ltd. (formerly MIPS Technologies Inc.)
"^multi-inno,.*":
description: Multi-Inno Technology Co.,Ltd
"^multitracks,.*":
description: MultiTracks.com, LLC
"^mundoreader,.*":
description: Mundo Reader S.L.
"^murata,.*":
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/boot/dts/freescale/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-ab2.dtb imx8mm-ab2-m4.dtb imx8mm-ddr4-ab2.dtb i
dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb imx8mm-evk-rpmsg.dtb imx8mm-evk-rm67191.dtb \
imx8mm-evk-root.dtb imx8mm-evk-inmate.dtb imx8mm-evk-revb-qca-wifi.dtb \
imx8mm-evk-ecspi-slave.dtb \
imx8mm-evk-spi-transport.dtb \
imx8mm-evk-pcie-ep.dtb \
imx8mm-evk-usd-wifi.dtb \
imx8mm-evk-qca-wifi.dtb \
Expand Down
48 changes: 48 additions & 0 deletions arch/arm64/boot/dts/freescale/imx8mm-evk-spi-transport.dts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2026 MultiTracks.com, LLC.
//
// MT-158113: binds the MultiTracks SPI transport driver (Host role) onto
// ecspi2, mirroring the pins already used for this same purpose on the
// mt-connect production board (mt-connect.dts) -- see
// firmware/firmware-common/spi-transport/docs/ProtocolSpec.md for the wire
// protocol and NSS/NRDY handshake this binds to real hardware.
//
// NSS/NRDY are bound here as driver-private "multitracks,nss-gpios"/
// "multitracks,nrdy-gpios" properties, NOT the standard "cs-gpios" -- the
// transport protocol holds
// NSS low continuously across a multi-step request/ack/clock/complete
// cycle, not just one SPI transfer, so the driver must own and drive it
// directly rather than let the SPI core auto-toggle it per-message. Both
// are declared GPIO_ACTIVE_HIGH regardless of the physical wire's true
// active sense, so the driver's gpiod_get/set_value_cansleep() calls
// always see the literal pin level, matching the protocol's own
// "true = pin HIGH" convention (see drivers/spi/spi-mt-transport/
// spi_transport_hw_linux.c).

#include "imx8mm-evk.dts"

/delete-node/ &spidev0;

&ecspi2 {
/delete-property/ cs-gpios;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi2 &pinctrl_ecspi2_cs &pinctrl_ecspi2_nrdy>;

mt_transport0: spi@0 {
compatible = "multitracks,spi-transport";
reg = <0>;
spi-max-frequency = <500000>; /* matches mt-connect.dts; revisit once link timing is measured */

multitracks,nss-gpios = <&gpio5 13 GPIO_ACTIVE_HIGH>;
multitracks,nrdy-gpios = <&gpio4 29 GPIO_ACTIVE_HIGH>;
};
};

&iomuxc {
pinctrl_ecspi2_nrdy: ecspi2nrdygrp {
fsl,pins = <
MX8MM_IOMUXC_SAI3_RXC_GPIO4_IO29 0x82
>;
};
};
21 changes: 21 additions & 0 deletions drivers/spi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1211,6 +1211,27 @@ config SPI_LOOPBACK_TEST
primarily used for development of spi_master drivers
and to detect regressions

config SPI_MT_TRANSPORT
tristate "MultiTracks SPI transport protocol driver (Host role)"
# No COMPILE_TEST: this module's core/ subdirectory only exists once
# Yocto's meta-mt-transport-evk stages it in at build time (see this
# directory's Makefile) -- allmodconfig/allyesconfig CI builds outside
# that pipeline would hard-error on core/ being missing. Found by
# Copilot's PR #46 review.
depends on ARCH_MXC
depends on GPIOLIB
# Driver unconditionally registers dev_groups/DEVICE_ATTR_RO sysfs
# attributes and calls sysfs_emit() -- non-functional without SYSFS.
# Found by Copilot's PR #46 review.
depends on SYSFS
help
Kernel Host-role port of the MultiTracks SPI transport protocol
(see firmware repo firmware-common/spi-transport/) -- a framed,
multi-channel, ack/retry link between an i.MX SoC (Host) and an
STM32-class client MCU (Client) over a raw SPI bus, plus a
companion NRDY GPIO handshake line in addition to the physical
SPI SCK/MOSI/MISO/NSS lines.

config SPI_TLE62X0
tristate "Infineon TLE62X0 (for power switching)"
depends on SYSFS
Expand Down
1 change: 1 addition & 0 deletions drivers/spi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ obj-$(CONFIG_SPI_TEGRA210_QUAD) += spi-tegra210-quad.o
obj-$(CONFIG_SPI_TEGRA114) += spi-tegra114.o
obj-$(CONFIG_SPI_TEGRA20_SFLASH) += spi-tegra20-sflash.o
obj-$(CONFIG_SPI_TEGRA20_SLINK) += spi-tegra20-slink.o
obj-$(CONFIG_SPI_MT_TRANSPORT) += spi-mt-transport/
obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x0.o
spi-thunderx-objs := spi-cavium.o spi-cavium-thunderx.o
obj-$(CONFIG_SPI_THUNDERX) += spi-thunderx.o
Expand Down
5 changes: 5 additions & 0 deletions drivers/spi/spi-mt-transport/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# core/ is the portable SPI transport protocol core -- single source of
# truth lives in the firmware repo (firmware-common/spi-transport/), staged
# here at Yocto build time (see imx8mmini-bb-evk's meta-mt-transport-evk
# linux-imx_%.bbappend), never committed into this repo.
core/
45 changes: 45 additions & 0 deletions drivers/spi/spi-mt-transport/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# SPDX-License-Identifier: GPL-2.0
#
# IMPORTANT -- this module only builds inside the imx8mmini-bb-evk Yocto BSP
# pipeline, not from a plain checkout of this kernel tree built directly
# (e.g. a bare `make -C . M=drivers/spi/spi-mt-transport modules`). The
# core/ referenced below is deliberately NOT committed to this repo (see
# core/'s absence and the .gitignore in this directory) -- it's the
# portable protocol core, whose single source of truth is the firmware
# repo's firmware-common/spi-transport/{src,inc}/. Yocto's
# meta-mt-transport-evk/recipes-kernel/linux-imx/linux-imx_%.bbappend
# fetches it separately and stages it into core/ via a do_patch[postfuncs]
# hook *before* this Makefile ever runs. This Makefile is only ever
# evaluated when CONFIG_SPI_MT_TRANSPORT is already enabled (Kbuild only
# descends here via drivers/spi/Makefile's obj-$(CONFIG_SPI_MT_TRANSPORT)
# line), so the check below fires exactly when it matters and fails fast
# with a clear message instead of the opaque "No rule to make target
# core/spi_transport.o" a missing core/ would otherwise produce deep in
# the build.
# $(src) alone resolves against $(objtree) under Yocto's out-of-tree (O=)
# kernel builds, same reason the ccflags-y line below needs the
# $(srctree)/ prefix -- this check needs it too, or it always reports
# core/ missing even when it's genuinely staged (confirmed via a real
# false-positive build failure without this prefix).
ifeq ($(wildcard $(srctree)/$(src)/core/spi_transport.c),)
$(error spi-mt-transport: core/ is not staged. This module only builds inside \
the imx8mmini-bb-evk Yocto BSP pipeline, which fetches the portable \
protocol core from the firmware repo and stages it into core/ before \
this Makefile runs -- build via bitbake, not a plain kernel checkout)
endif

obj-$(CONFIG_SPI_MT_TRANSPORT) += spi-mt-transport.o
spi-mt-transport-y := \
core/spi_transport.o \
core/spi_transport_channel.o \
core/spi_transport_frame.o \
core/spi_transport_crc16.o \
core/spi_transport_hw.o \
spi_transport_os_linux.o \
spi_transport_hw_linux.o \
spi_mt_transport_drv.o

# $(src) alone resolves against $(objtree) under Yocto's out-of-tree (O=)
# kernel builds; these headers only exist in the source tree, so the
# $(srctree)/ prefix is required or the compile can't find them.
ccflags-y += -I$(srctree)/$(src)/kernel-compat -I$(srctree)/$(src)/core/include
13 changes: 13 additions & 0 deletions drivers/spi/spi-mt-transport/kernel-compat/stdarg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Compat shim only -- NOT part of the portable core (../../../.. relative to here).
*
* The portable core targets hosted C11, so it includes the standard
* <stdarg.h>. Under the kernel's -nostdinc build this cross-compiler's own
* freestanding headers aren't on the search path either, so <stdarg.h>
* doesn't resolve at all -- linux/stdarg.h is the kernel's own sanctioned
* replacement for exactly this case. Only reached via this module's own
* Makefile (ccflags-y += -I$(src)/kernel-compat), so it
* cannot shadow <stdarg.h> anywhere else in the kernel tree.
*/
#include <linux/stdarg.h>
14 changes: 14 additions & 0 deletions drivers/spi/spi-mt-transport/kernel-compat/stdbool.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Compat shim only -- NOT part of the portable core (../../../.. relative to here).
*
* The portable core targets hosted C11, so it includes the standard
* <stdbool.h> for bool/true/false. Under the kernel's -nostdinc build this
* cross-compiler's own freestanding headers aren't on the search path
* either, so <stdbool.h> doesn't resolve at all. linux/types.h (bool) and
* linux/stddef.h (true/false) are the kernel's equivalents. Only reached via
* this module's own Makefile (ccflags-y += -I$(src)/kernel-compat),
* so it cannot shadow <stdbool.h> anywhere else in the kernel tree.
*/
#include <linux/stddef.h>
#include <linux/types.h>
14 changes: 14 additions & 0 deletions drivers/spi/spi-mt-transport/kernel-compat/stdint.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Compat shim only -- NOT part of the portable core (../../../.. relative to here).
*
* The portable core targets hosted C11, so it includes the standard
* <stdint.h> for the fixed-width int types. Under the kernel's -nostdinc
* build this cross-compiler's own freestanding headers aren't on the search
* path either, so <stdint.h> doesn't resolve at all. linux/types.h already
* provides int8_t/uint8_t/.../int64_t/uint64_t (via asm-generic/int-ll64.h)
* with identical signedness/width. Only reached via this module's own
* Makefile (ccflags-y += -I$(src)/kernel-compat), so it
* cannot shadow <stdint.h> anywhere else in the kernel tree.
*/
#include <linux/types.h>
15 changes: 15 additions & 0 deletions drivers/spi/spi-mt-transport/kernel-compat/string.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Compat shim only -- NOT part of the portable core (../../../.. relative to here).
*
* The portable core targets hosted C11 (its STM32/host-native builds use a
* real libc), so it includes the standard <string.h> for memcpy/memset/
* memcmp. The kernel build has no hosted libc and doesn't provide a bare
* <string.h> -- linux/string.h is the kernel's equivalent, with compatible
* signatures for the functions the core actually uses. This shim lets
* <string.h> resolve to it without hand-editing the portable core's .c files
* themselves. Only reached via this module's own Makefile
* (ccflags-y += -I$(src)/kernel-compat), so it cannot shadow <string.h>
* anywhere else in the kernel tree.
*/
#include <linux/string.h>
Loading