Hello Everyone,
As https://lore.kernel.org/all/20231125092137.2948-8-amit.kumar-mahapatra@amd.c... thread discussing the addition of stacked and parallel mode support in SPI-NOR has become too long and difficult to follow. Therefore, I'm starting a new email thread to focus on the DT binding changes and the overall implementation architecture for adding stacked and parallel (multi-CS) support in the Kernel. Please share your input on this approach.
Background:
The AMD QSPI controller supports two advanced connection modes(Stacked and Dual Parallel) which allow the controller to treat two different flashes as one storage.
Stacked:
Flashes share the same SPI bus, but different CS line, controller driver asserts the CS of the flash to which it needs to communicate.
Stacked mode is a software abstraction rather than a controller feature or capability. At any given time, the controller communicates with one of the two connected flash devices, as determined by the requested address and data length. If an operation starts on one flash and ends on the other, the core needs to split it into two separate operations and adjust the data length accordingly.
Dual Parallel:
Both the flashes have their separate SPI bus, CS of both the flashes will be asserted/de-asserted at the same time. In this mode data will be split across both the flashes by enabling the STRIPE setting in the controller.
Parallel mode is a controller feature where if the STRIPE bit is set then the controller internally handles the data split during data write to the flashes and while reading data from the flash the controller internally merges data from both the flashes before writing to the controller FIFO. If STRIPE is not enabled, then same data will be sent to both the devices.
In parallel mode both the flashes should be identical.
For more information on the modes please feel free to go through the controller flash interface below https://docs.amd.com/r/en-US/am011-versal-acap-trm/QSPI-Flash-Device-Interfa...
Mirochip QSPI controller also supports "Dual Parallel 8-bit IO mode", but they call it "Twin Quad Mode".
https://ww1.microchip.com/downloads/aemDocuments/documents/MPU32/ProductDocu...
Initially in [1] [2] [3] Miquel had tried to extend MTD-CONCAT driver to support Stacked mode, but the bindings were not accepted.
[1] https://lore.kernel.org/all/20191113171505.26128-4-miquel.raynal@bootlin.com...
[2] https://lore.kernel.org/all/20191127105522.31445-5-miquel.raynal@bootlin.com...
[3]https://lore.kernel.org/all/20211112152411.818321-1-miquel.raynal@bootlin.co...
So, the MTD-CONCAT approach was dropped and the DT bindings that got accepted [4] [5] [6] describe the two flash devices as being one.
[4] https://github.com/torvalds/linux/commit/f89504300e94524d5d5846ff8b728592ac7...
[5] https://github.com/torvalds/linux/commit/eba5368503b4291db7819512600fa014ea1...
[6] https://github.com/torvalds/linux/commit/e2edd1b64f1c79e8abda365149ed62a2a9a...
SPI core changes to support the above bindings were added through the following commit:
https://github.com/torvalds/linux/commit/4d8ff6b0991d5e86b17b235fc46ec62e919...
While adding the support in SPI-NOR we received some inputs/suggestions from Tudor, based on that I am planning to add a new layer between the SPI-NOR and MTD layers to support stacked and parallel configurations. This new layer will be part of the spi-nor and located in mtd/spi-nor/.
This layer would perform the following tasks:
- During probing, store information from all the connected flashes, whether in stacked or parallel mode, and present it as a single device to the MTD layer.
- Register callbacks and manage MTD device registration within the new layer instead of in spi-nor/core.c
- There will very minimal change in spinor/core.c as the stacked & parallel handling will be managed by the new layer on top of SPI-NOR.
- In stacked mode, the new layer will select the appropriate spi-nor flash based on the address provided by the MTD layer during flash operations.
- Manage flash crossover operations in stacked mode.
- Handle odd byte count requests from the MTD layer during flash operations in parallel mode.
For implementing this the current DT binding[1] [2] [3] need to be updated as follows.
stacked-memories DT changes:
- Flash size information can be retrieved directly from the flash, so it has been removed from the DT binding.
- Each stacked flash will have its own flash node. This approach allows flashes of different makes and sizes to be stacked together, as each flash will be probed individually.
- Each of the flash node will have its own "reg" property that will contain its physical CS.
- The stacked-memories DT bindings will contain the phandles of the flash nodes connected in stacked mode.
- The first flash node will contain the mtd partition that would have the cross over memory staring at a memory location in the first flash and ending at some memory location of the 2nd flash
- The new layer will update the mtd->size and other mtd_info parameters after both the flashes are probed and will call mtd_device_register with the combined information.
spi@0 {
flash@0 {
compatible = "jedec,spi-nor"
reg = <0x00>;
stacked-memories = <&flash@0 &flash@1>;
spi-max-frequency = <50000000>;
...
partition@0 {
label = "qspi-0";
reg = <0x0 0xf00000>;
};
}
flash@1 {
compatible = "jedec,spi-nor"
reg = <0x01>;
spi-max-frequency = <50000000>;
...
partition@0 {
label = "qspi-1";
reg = <0x0 0x800000>;
};
}
}
parallel-memories DT changes:
- Flash size information can be retrieved directly from the flash, so it has been removed from the DT binding.
- Each flash connected in parallel mode should be identical and will have one flash node for both the flash devices.
- The "reg" prop will contain the physical CS number for both the connected flashes.
- The new layer will double the mtd-> size and register it with the mtd layer.
spi@0 {
flash@0 {
compatible = "jedec,spi-nor"
reg = <0x00 0x01>;
parallel-memories;
spi-max-frequency = <50000000>;
...
partition@0 {
label = "qspi-0";
reg = <0x0 0xf00000>;
}
};
}
Regards,
Amit