1.. _mspi_api:
2
3Multi-bit SPI Bus
4#################
5
6The MSPI (multi-bit SPI) is provided as a generic API to accommodate
7advanced SPI peripherals and devices that typically require command,
8address and data phases, and multiple signal lines during these phases.
9While the API supports advanced features such as :term:`XIP` and scrambling,
10it is also compatible with generic SPI.
11
12.. contents::
13    :local:
14    :depth: 2
15
16.. _mspi-controller-api:
17
18MSPI Controller API
19*******************
20
21Zephyr's MSPI controller API may be used when a multi-bit SPI controller
22is present. E.g. Ambiq MSPI, QSPI, OSPI, Flexspi, etc.
23The API supports single to hex SDR/DDR IO with variable latency and advanced
24features such as :term:`XIP` and scrambling. Applicable devices include but
25not limited to high-speed, high density flash/psram memory devices, displays
26and sensors.
27
28The MSPI interface contains controller drivers that are SoC platform specific
29and implement the MSPI APIs, and device drivers that reference these APIs.
30The relationship between the controller and device drivers is many-to-many to
31allow for easy switching between platforms.
32
33Here is a list of generic steps for initializing the MSPI controller and the
34MSPI bus inside the device driver initialization function:
35
36#. Initialize the data structure of the MSPI controller driver instance.
37   The usual device defining macros such as :c:macro:`DEVICE_DT_INST_DEFINE`
38   can be used, and the initialization function, config and data provided
39   as a parameter to the macro.
40
41#. Initialize the hardware, including but not limited to:
42
43   * Check :c:struct:`mspi_cfg` against hardware's own capabilities to prevent
44     incorrect usages.
45
46   * Setup default pinmux.
47
48   * Setup the clock for the controller.
49
50   * Power on the hardware.
51
52   * Configure the hardware using :c:struct:`mspi_cfg` and possibly more
53     platform specific settings.
54
55   * Usually, the :c:struct:`mspi_cfg` is filled from device tree and contains
56     static, boot time parameters. However, if needed, one can use :c:func:`mspi_config`
57     to re-initialize the hardware with new parameters during runtime.
58
59   * Release any lock if applicable.
60
61#. Perform device driver initialization. As usually, :c:macro:`DEVICE_DT_INST_DEFINE`
62   can be used. Inside device driver initialization function, perform the following
63   required steps.
64
65   #. Call :c:func:`mspi_dev_config` with device specific hardware settings obtained
66      from device datasheets.
67
68      * The :c:struct:`mspi_dev_cfg` should be filled by device tree and helper macro
69        :c:macro:`MSPI_DEVICE_CONFIG_DT` can be used.
70
71      * The controller driver should then validate the members of :c:struct:`mspi_dev_cfg`
72        to prevent incorrect usage.
73
74      * The controller driver should implement a mutex to protect from accidental access.
75
76      * The controller driver may also switch between different devices based on
77        :c:struct:`mspi_dev_id`.
78
79   #. Call API for additional setups if supported by hardware
80
81      * :c:func:`mspi_xip_config` for :term:`XIP` feature
82
83      * :c:func:`mspi_scramble_config` for scrambling feature
84
85      * :c:func:`mspi_timing_config` for platform specific timing setup.
86
87   #. Register any callback with :c:func:`mspi_register_callback` if needed.
88
89   #. Release the controller mutex lock.
90
91Transceive
92==========
93The transceive request is of type :c:struct:`mspi_xfer` which allows dynamic change to
94the transfer related settings once the mode of operation is determined and configured
95by :c:func:`mspi_dev_config`.
96
97The API also supports bulk transfers with different starting addresses and sizes with
98:c:struct:`mspi_xfer_packet`. However, it is up to the controller implementation
99whether to support scatter IO and callback management. The controller can determine
100which user callback to trigger based on :c:enum:`mspi_bus_event_cb_mask` upon completion
101of each async/sync transfer if the callback had been registered using
102:c:func:`mspi_register_callback`. Or not to trigger any callback at all with
103:c:enum:`MSPI_BUS_NO_CB` even if the callbacks are already registered.
104In which case that a controller supports hardware command queue, user could take full
105advantage of the hardware performance if scatter IO and callback management are supported
106by the driver implementation.
107
108Device Tree
109===========
110
111Here is an example for defining an MSPI controller in device tree:
112The mspi controller's bindings should reference mspi-controller.yaml as one of the base.
113
114.. code-block:: devicetree
115
116   mspi0: mspi@400 {
117            status = "okay";
118            compatible = "zephyr,mspi-emul-controller";
119
120            reg = < 0x400 0x4 >;
121            #address-cells = < 0x1 >;
122            #size-cells = < 0x0 >;
123
124            clock-frequency = < 0x17d7840 >;
125            op-mode = "MSPI_CONTROLLER";
126            duplex = "MSPI_HALF_DUPLEX";
127            ce-gpios = < &gpio0 0x5 0x1 >, < &gpio0 0x12 0x1 >;
128            dqs-support;
129
130            pinctrl-0 = < &pinmux-mspi0 >;
131            pinctrl-names = "default";
132   };
133
134Here is an example for defining an MSPI device in device tree:
135The mspi device's bindings should reference mspi-device.yaml as one of the base.
136
137.. code-block:: devicetree
138
139   &mspi0 {
140
141            mspi_dev0: mspi_dev0@0 {
142                     status = "okay";
143                     compatible = "zephyr,mspi-emul-device";
144
145                     reg = < 0x0 >;
146                     size = < 0x10000 >;
147
148                     mspi-max-frequency = < 0x2dc6c00 >;
149                     mspi-io-mode = "MSPI_IO_MODE_QUAD";
150                     mspi-data-rate = "MSPI_DATA_RATE_SINGLE";
151                     mspi-hardware-ce-num = < 0x0 >;
152                     read-instruction = < 0xb >;
153                     write-instruction = < 0x2 >;
154                     instruction-length = "INSTR_1_BYTE";
155                     address-length = "ADDR_4_BYTE";
156                     rx-dummy = < 0x8 >;
157                     tx-dummy = < 0x0 >;
158                     xip-config = < 0x0 0x0 0x0 0x0 >;
159                     ce-break-config = < 0x0 0x0 >;
160            };
161
162   };
163
164User should specify target operating parameters in the DTS such as ``mspi-max-frequency``,
165``mspi-io-mode`` and ``mspi-data-rate`` even though they may subject to change during runtime.
166It should represent the typical configuration of the device during normal operations.
167
168Multi Peripheral
169================
170With :c:struct:`mspi_dev_id` defined as collection of the device index and CE GPIO from
171device tree, the API supports multiple devices on the same controller instance.
172The controller driver implementation may or may not support device switching,
173which can be performed either by software or by hardware. If the switching is handled
174by software, it should be performed in :c:func:`mspi_dev_config` call.
175
176The device driver should record the current operating conditions of the device to support
177software controlled device switching by saving and updating :c:struct:`mspi_dev_cfg` and
178other relevant mspi struct or private data structures. In particular, :c:struct:`mspi_dev_id`
179which contains the identity of the device needs to be used for every API call.
180
181
182Configuration Options
183*********************
184
185Related configuration options:
186
187* :kconfig:option:`CONFIG_MSPI`
188* :kconfig:option:`CONFIG_MSPI_ASYNC`
189* :kconfig:option:`CONFIG_MSPI_PERIPHERAL`
190* :kconfig:option:`CONFIG_MSPI_XIP`
191* :kconfig:option:`CONFIG_MSPI_SCRAMBLE`
192* :kconfig:option:`CONFIG_MSPI_TIMING`
193* :kconfig:option:`CONFIG_MSPI_INIT_PRIORITY`
194* :kconfig:option:`CONFIG_MSPI_COMPLETION_TIMEOUT_TOLERANCE`
195
196API Reference
197*************
198
199.. doxygengroup:: mspi_interface
200