doc: Add MSPI API documentation
Add the mspi.rst doc and related things for document generation. Signed-off-by: Swift Tian <swift.tian@ambiq.com>
This commit is contained in:
parent
8dd5b1e6b8
commit
a86bbd3ebf
@ -172,6 +172,7 @@ REDIRECTS = [
|
||||
('reference/peripherals/led', 'hardware/peripherals/led'),
|
||||
('reference/peripherals/mbox', 'hardware/peripherals/mbox'),
|
||||
('reference/peripherals/mdio', 'hardware/peripherals/mdio'),
|
||||
('reference/peripherals/mspi', 'hardware/peripherals/mspi'),
|
||||
('reference/peripherals/peci', 'hardware/peripherals/peci'),
|
||||
('reference/peripherals/pinmux', 'hardware/peripherals/pinmux'),
|
||||
('reference/peripherals/ps2', 'hardware/peripherals/ps2'),
|
||||
|
||||
@ -41,6 +41,7 @@ Peripherals
|
||||
mdio.rst
|
||||
mipi_dbi.rst
|
||||
mipi_dsi.rst
|
||||
mspi.rst
|
||||
mbox.rst
|
||||
pcie.rst
|
||||
peci.rst
|
||||
|
||||
199
doc/hardware/peripherals/mspi.rst
Normal file
199
doc/hardware/peripherals/mspi.rst
Normal file
@ -0,0 +1,199 @@
|
||||
.. _mspi_api:
|
||||
|
||||
Multi-bit SPI Bus
|
||||
#################
|
||||
|
||||
The MSPI (multi-bit SPI) is provided as a generic API to accommodate
|
||||
advanced SPI peripherals and devices that typically require command,
|
||||
address and data phases, and multiple signal lines during these phases.
|
||||
While the API supports advanced features such as :term:`XIP` and scrambling,
|
||||
it is also compatible with generic SPI.
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 2
|
||||
|
||||
.. _mspi-controller-api:
|
||||
|
||||
MSPI Controller API
|
||||
*******************
|
||||
|
||||
Zephyr's MSPI controller API may be used when a multi-bit SPI controller
|
||||
is present. E.g. Ambiq MSPI, QSPI, OSPI, Flexspi, etc.
|
||||
The API supports single to hex SDR/DDR IO with variable latency and advanced
|
||||
features such as :term:`XIP` and scrambling. Applicable devices include but
|
||||
not limited to high-speed, high density flash/psram memory devices, displays
|
||||
and sensors.
|
||||
|
||||
The MSPI interface contains controller drivers that are SoC platform specific
|
||||
and implement the MSPI APIs, and device drivers that reference these APIs.
|
||||
The relationship between the controller and device drivers is many-to-many to
|
||||
allow for easy switching between platforms.
|
||||
|
||||
Here is a list of generic steps for initializing the MSPI controller and the
|
||||
MSPI bus inside the device driver initialization function:
|
||||
|
||||
#. Initialize the data structure of the MSPI controller driver instance.
|
||||
The usual device defining macros such as :c:macro:`DEVICE_DT_INST_DEFINE`
|
||||
can be used, and the initialization function, config and data provided
|
||||
as a parameter to the macro.
|
||||
|
||||
#. Initialize the hardware, including but not limited to:
|
||||
|
||||
* Check :c:struct:`mspi_cfg` against hardware's own capabilities to prevent
|
||||
incorrect usages.
|
||||
|
||||
* Setup default pinmux.
|
||||
|
||||
* Setup the clock for the controller.
|
||||
|
||||
* Power on the hardware.
|
||||
|
||||
* Configure the hardware using :c:struct:`mspi_cfg` and possibly more
|
||||
platform specific settings.
|
||||
|
||||
* Usually, the :c:struct:`mspi_cfg` is filled from device tree and contains
|
||||
static, boot time parameters. However, if needed, one can use :c:func:`mspi_config`
|
||||
to re-initialize the hardware with new parameters during runtime.
|
||||
|
||||
* Release any lock if applicable.
|
||||
|
||||
#. Perform device driver initialization. As usually, :c:macro:`DEVICE_DT_INST_DEFINE`
|
||||
can be used. Inside device driver initialization function, perform the following
|
||||
required steps.
|
||||
|
||||
#. Call :c:func:`mspi_dev_config` with device specific hardware settings obtained
|
||||
from device datasheets.
|
||||
|
||||
* The :c:struct:`mspi_dev_cfg` should be filled by device tree and helper macro
|
||||
:c:macro:`MSPI_DEVICE_CONFIG_DT` can be used.
|
||||
|
||||
* The controller driver should then validate the members of :c:struct:`mspi_dev_cfg`
|
||||
to prevent incorrect usage.
|
||||
|
||||
* The controller driver should implement a mutex to protect from accidental access.
|
||||
|
||||
* The controller driver may also switch between different devices based on
|
||||
:c:struct:`mspi_dev_id`.
|
||||
|
||||
#. Call API for additional setups if supported by hardware
|
||||
|
||||
* :c:func:`mspi_xip_config` for :term:`XIP` feature
|
||||
|
||||
* :c:func:`mspi_scramble_config` for scrambling feature
|
||||
|
||||
* :c:func:`mspi_timing_config` for platform specific timing setup.
|
||||
|
||||
#. Register any callback with :c:func:`mspi_register_callback` if needed.
|
||||
|
||||
#. Release the controller mutex lock.
|
||||
|
||||
Transceive
|
||||
==========
|
||||
The transceive request is of type :c:struct:`mspi_xfer` which allows dynamic change to
|
||||
the transfer related settings once the mode of operation is determined and configured
|
||||
by :c:func:`mspi_dev_config`.
|
||||
|
||||
The API also supports bulk transfers with different starting addresses and sizes with
|
||||
:c:struct:`mspi_xfer_packet`. However, it is up to the controller implementation
|
||||
whether to support scatter IO and callback management. The controller can determine
|
||||
which user callback to trigger based on :c:enum:`mspi_bus_event_cb_mask` upon completion
|
||||
of each async/sync transfer if the callback had been registered using
|
||||
:c:func:`mspi_register_callback`. Or not to trigger any callback at all with
|
||||
:c:enum:`MSPI_BUS_NO_CB` even if the callbacks are already registered.
|
||||
In which case that a controller supports hardware command queue, user could take full
|
||||
advantage of the hardware performance if scatter IO and callback management are supported
|
||||
by the driver implementation.
|
||||
|
||||
Device Tree
|
||||
===========
|
||||
|
||||
Here is an example for defining an MSPI controller in device tree:
|
||||
The mspi controller's bindings should reference mspi-controller.yaml as one of the base.
|
||||
|
||||
.. code-block:: devicetree
|
||||
|
||||
mspi0: mspi@400 {
|
||||
status = "okay";
|
||||
compatible = "zephyr,mspi-emul-controller";
|
||||
|
||||
reg = < 0x400 0x4 >;
|
||||
#address-cells = < 0x1 >;
|
||||
#size-cells = < 0x0 >;
|
||||
|
||||
clock-frequency = < 0x17d7840 >;
|
||||
op-mode = "MSPI_CONTROLLER";
|
||||
duplex = "MSPI_HALF_DUPLEX";
|
||||
ce-gpios = < &gpio0 0x5 0x1 >, < &gpio0 0x12 0x1 >;
|
||||
dqs-support;
|
||||
|
||||
pinctrl-0 = < &pinmux-mspi0 >;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
Here is an example for defining an MSPI device in device tree:
|
||||
The mspi device's bindings should reference mspi-device.yaml as one of the base.
|
||||
|
||||
.. code-block:: devicetree
|
||||
|
||||
&mspi0 {
|
||||
|
||||
mspi_dev0: mspi_dev0@0 {
|
||||
status = "okay";
|
||||
compatible = "zephyr,mspi-emul-device";
|
||||
|
||||
reg = < 0x0 >;
|
||||
size = < 0x10000 >;
|
||||
|
||||
mspi-max-frequency = < 0x2dc6c00 >;
|
||||
mspi-io-mode = "MSPI_IO_MODE_QUAD";
|
||||
mspi-data-rate = "MSPI_DATA_RATE_SINGLE";
|
||||
mspi-hardware-ce-num = < 0x0 >;
|
||||
read-instruction = < 0xb >;
|
||||
write-instruction = < 0x2 >;
|
||||
instruction-length = "INSTR_1_BYTE";
|
||||
address-length = "ADDR_4_BYTE";
|
||||
rx-dummy = < 0x8 >;
|
||||
tx-dummy = < 0x0 >;
|
||||
xip-config = < 0x0 0x0 0x0 0x0 >;
|
||||
ce-break-config = < 0x0 0x0 >;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
User should specify target operating parameters in the DTS such as ``mspi-max-frequency``,
|
||||
``mspi-io-mode`` and ``mspi-data-rate`` even though they may subject to change during runtime.
|
||||
It should represent the typical configuration of the device during normal operations.
|
||||
|
||||
Multi Peripheral
|
||||
================
|
||||
With :c:struct:`mspi_dev_id` defined as collection of the device index and CE GPIO from
|
||||
device tree, the API supports multiple devices on the same controller instance.
|
||||
The controller driver implementation may or may not support device switching,
|
||||
which can be performed either by software or by hardware. If the switching is handled
|
||||
by software, it should be performed in :c:func:`mspi_dev_config` call.
|
||||
|
||||
The device driver should record the current operating conditions of the device to support
|
||||
software controlled device switching by saving and updating :c:struct:`mspi_dev_cfg` and
|
||||
other relevant mspi struct or private data structures. In particular, :c:struct:`mspi_dev_id`
|
||||
which contains the identity of the device needs to be used for every API call.
|
||||
|
||||
|
||||
Configuration Options
|
||||
*********************
|
||||
|
||||
Related configuration options:
|
||||
|
||||
* :kconfig:option:`CONFIG_MSPI`
|
||||
* :kconfig:option:`CONFIG_MSPI_ASYNC`
|
||||
* :kconfig:option:`CONFIG_MSPI_PERIPHERAL`
|
||||
* :kconfig:option:`CONFIG_MSPI_XIP`
|
||||
* :kconfig:option:`CONFIG_MSPI_SCRAMBLE`
|
||||
* :kconfig:option:`CONFIG_MSPI_TIMING`
|
||||
* :kconfig:option:`CONFIG_MSPI_INIT_PRIORITY`
|
||||
* :kconfig:option:`CONFIG_MSPI_COMPLETION_TIMEOUT_TOLERANCE`
|
||||
|
||||
API Reference
|
||||
*************
|
||||
|
||||
.. doxygengroup:: mspi_interface
|
||||
Loading…
Reference in New Issue
Block a user