Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The purpose of this page is to describe the Linux Zynq QSPI driver for Xilinx QSPI PS

Table of Contents

Introduction

This page provides information about the Zynq QSPI driver which can be found on Xilinx Git as spi-zynq-qspi.c
Zynq

The purpose of this page is to describe the Linux Zynq QSPI driver for Xilinx QSPI PS

Table of Contents

Introduction

This page provides information about the Zynq QSPI driver which can be found on Xilinx Git as spi-zynq-qspi.c
Zynq has one QSPI hard IP. This is built on top of Cadence SPI with support for QSPI flash devices, linear read and single, parallel and stacked flash configurations.

MTD layer handles all the flash devices used with QSPI. This layer handles flash devices of different makes (Micron/Numonyx, Winbond and Spansion being the most common)
of different sizes from 128Mbit to 1Gbit2Gbit. The features of all flash devices are not alike and hence handled through different flags indicating the support.
This layer was customized by xilinx to support parallel and stacked configurations. It can be found at drivers/mtd/devicesspi-nor/m25p80core.c on Xilinx Git.

HW/IP Features

  • 32-bit AXI interface for Linear Addressing mode transfers
  • 32-bit APB interface for I/O mode transfers
  • Programmable bus protocol for flash memories from Micron and Spansion
  • Legacy SPI and scalable performance: 1x, 2x, 4x, 8x I/O widths
  • Flexible I/O
  • 16 MB addressing per device (32 MB for two devices)
  • Device densities up to 128 Mb for I/O and linear mode. Densities greater than 128 Mb are
  • supported in I/O mode.
  • I/O mode (flash commands and data)
    • Software issues instructions and manages flash operations
    • Interrupts for FIFO control
    • 63-word RxFIFO, 63-word TxFIFO
  • Linear addressing mode (executable read accesses)
    • Memory reads and writes are interpreted by the controller
    • AXI port buffers up to four read requests
    • AXI incrementing and wrapping address functions

Features Supported in Driver

  • Master mode
  • Single, parallel and dual stacked modes
    • Single - One flash device is connected using one slave select, one clock and four data lines.
    • Parallel - Two flash devices are connected using common slave select and separate data lines.
    • Stacked - Two flash devices are connected using separate slave selects and common data lines.
  • Driver uses manual chip select and auto start.
  • Programmable clock frequency, polarity and phase
  • Interrupt support
  • Rx bus width of 1 to 4 - supports quad read.
  • Tx bus width of 1 to 4 (Current support in custom MTD layer is for bus width of 1)
  • Support for SPI NOR flash devices of sizes from 128Mbit to 1Gbit2Gbit.
  • Various flash related features supported in customized MTD - such as bank selection, lock/unlock in single, parallel and stacked modes

Missing Features and known Issues/Limitations in Driver

  • 4-byte commands are not supported on this controller.
  • This driver does not use linear read.
  • In dual parallel mode, all register read responses (other than status) are obtained only from lower flash device by the controller.lower flash device by the controller.

Important AR links

  • 2023.1/2023.2 - Zynq 7000: Continuous empty flash messages observed when booting in QSPI boot mode using jffs2 root filesystem AR-Link

  • 2023.1 - Zynq-7000: QSPI dual-stacked configuration not working properly AR Link

Kernel Configuration Options

The following config options need to be enabled
CONFIG_ZYNQ_SPI_QSPI
It depends on on SPI_MEM, SPI_MASTER and ARCH_ZYNQImage Removed
To use in dual stacked mode, enable
CONFIG_ZYNQ_SPI_QSPI_
DUAL_STACKED
Image Removed
Image Added
If required, enable MTD block devices support - MTD_BLKDEVS

Device-tree

Refer to spi-zynq-qspi.txtyaml for the complete description.
These are some specific points to be noted about
the qspi properties:
- qspi-mode - Currenlty unused. 0 if single, 1 if parallel and 2 if stacked.
- is-dual - Set if parallel. Reset if single or stacked.
the qspi properties:
- parallel-memories - Define if flashes are connected in parallel.
- stacked-memories - Define if flashes are connected in stacked.
For details of the above connection mode refer spi-peripheral-props.yaml spi-controller.yaml 

Example (single mode):
The following example shows adding a QSPI node to the devicetree in single mode.
Code Block
themeMidnight
qspi: qspi@e000d000 {
    	  compatible = "xlnx,zynq-qspi-1.0";
      clock-namesreg = "ref_clk", "pclk"<0xe000d000 0x1000>;
      clocksinterrupt-parent = <&&clkc 10>, <&&clkc 43>;<0x4>;
      interrupts = <0x0 0x13 0x4>;
      clocks  interrupt-parent = <&&ps7_scugic_0>= <0x1 0xa 0x1 0x2b>;
      interruptsclock-names = <0 19 4>"ref_clk", "pclk";
      is-dualstatus = <0>"okay";
      num#address-cscells = <1><0x1>;
      reg#size-cells = <0xe000d000 0x1000><0x0>;
      xlnx,fb-clk = <0x1>;
      xlnx,qspi-mode = <0x0>u-boot,dm-pre-reloc;
	  num-cs = <0x1>;
      #address-cellsspi-rx-bus-width = <1><0x4>;
      #size-cellsspi-tx-bus-width = <0><0x4>;

      flash@0 {
              compatible = "n25q128", "jedec,spi-nor";
              reg = <0x0>;
              spi-tx-bus-width = <1>;
              spi-rx-bus-width = <4>;
              spi-max-frequency = <50000000>;
              #address-cells = <1>;
              #size-cells = <1>;
              partition@qspi-fsbl-uboot {
                        label = "qspi-fsbl-uboot";
                        reg = <0x0 0x100000>;
              };
              partition@qspi-linux {
                        label = "qspi-linux";
                        reg = <0x100000 0x500000>;
              };
              partition@qspi-device-tree {
                        label = "qspi-device-tree";
                        reg = <0x600000 0x20000>;
              };
              partition@qspi-rootfs {
                        label = "qspi-rootfs";
                        reg = <0x620000 0x5E0000>;
              };
              partition@qspi-bitstream {
                        label = "qspi-bitstream";
                        reg = <0xC00000 0x400000>;
              };
      };
};

Test Procedure

This section details the common tests using jffs2 and flashcp.
In order to test different flash sizes and configurations (single, parallel, stacked), the above devicetree should be modified and relevant hardware and design should be used.

QSPI flash testing with flashcp


#List the MTD partitions present and select a partition
cat /proc/mtd
Code Block
themeMidnight
dev:    size   erasesize  name
mtd0: 00500000 00001000 "boot"
mtd1: 00020000 00001000 "bootenv"
mtd2: 00a80000 00001000 "kernel"
mtd3: 00060000 00001000 "spare"

#Creating a file to be written to the flash\
dd if=/dev/urandom of=./sample.bin bs=1024 count=4096
Code Block
themeMidnight
4096+0 records in
4096+0 records out
4194304 bytes (4.0MB) copied, 3.227253 seconds, 1.2MB/s
#Write the file to the partition - this erases the partition, writes the file and verifies
flashcp -v ./sample.bin /dev/mtd0
Code Block
themeMidnight
Erasing block: 32/32 (100%)
Writing kb: 4088/4096 (99%)
Verifying kb: 4088/4096 (99%)

QSPI flash testing with jffs2


#List the MTD partitions present and select a partition
cat /proc/mtd
Code Block
themeMidnight
dev:    size   erasesize  name
mtd0: 00100000 00020000 "qspi-fsbl-uboot"
mtd1: 00500000 00020000 "qspi-linux"
mtd2: 00020000 00020000 "qspi-device-tree"
mtd3: 005e0000 00020000 "qspi-rootfs"
mtd4: 00400000 00020000 "qspi-bitstream"
#Erase a the whole partition with jffs2 markers
flash_eraseall -j /dev/mtd3
Code Block
themeMidnight
Erasing 128 Kibyte @ 5c0000 - 97% complete. Cleanmarker written at 5c0000.
Erasing 128 Kibyte @ 5e0000 - 100% complete.
#create a directory
mkdir qspi_flash0
#Mount the partition to spi_flash0
mount -t jffs2 /dev/mtdblock3 /qspi_flash0
#Create a file to be written to the flash
dd if=/dev/urandom of=./sample.bin bs=1024 count=4096
Code Block
themeMidnight
4096+0 records in
4096+0 records out
4194304 bytes (4.0MB) copied, 3.227253 seconds, 1.2MB/s
#Write the file to the flash
cp ./sample.bin /qspi_flash0/
#Check the presence of the file(s) in spi_flash0
ls /qspi_flash0
Code Block
themeMidnight
sample.bin
#Unmount
umount spi_flash0
#Mount again - MTD 0 to spi_flash0
mount -t jffs2 /dev/mtdblock3 /qspi_flash0
#Compare the files - there should be no differences
diff ./sample.bin /qspi_flash0/sample.bin
#Unmount
umount qspi_flash0
#The data can be verified again after a power on reset if desired.
#//
mtdspeedtest is used to measure the performance of the driver.

Expected Output

Code BlockthemeMidnight
#List the MTD partitions present and select a partition # cat /proc/mtd dev: size erasesize name mtd0: 00500000 00001000 "boot" mtd1: 00020000 00001000 "bootenv" mtd2: 00a80000 00001000 "kernel" mtd3: 00060000 00001000 "spare" Code Block
themeMidnight
#flash_eraseall -j /dev/mtd3 Erasing 128 Kibyte @ 5c0000 - 97% complete. Cleanmarker written at 5c0000. Erasing 128 Kibyte @ 5e0000 - 100% complete. #create a directory #mkdir qspi_flash0 #mount -t jffs2 /dev/mtdblock3 /qspi_flash0 #dd if=/dev/urandom of=./sample.bin bs=1024 count=4096 4096+0 records in 4096+0 records out 4194304 bytes (4.0MB) copied, 3.227253 seconds, 1.2MB/s #cp ./sample.bin /qspi_flash0/ #ls /qspi_flash0 sample.bin #umount spi/

mtdspeedtest is used to measure the performance of the driver.

Expected Output

Code Block
themeMidnight
#List the MTD partitions present and select a partition
# cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00500000 00001000 "boot"
mtd1: 00020000 00001000 "bootenv"
mtd2: 00a80000 00001000 "kernel"
mtd3: 00060000 00001000 "spare"
 


Code Block
themeMidnight
#flash_eraseall -j /dev/mtd3
Erasing 128 Kibyte @ 5c0000 - 97% complete. Cleanmarker written at 5c0000.
Erasing 128 Kibyte @ 5e0000 - 100% complete.
#create a directory
#mkdir qspi_flash0
#mount -t jffs2 /dev/mtdblock3 /qspi_flash0
#diff #dd if=/dev/urandom of=./sample.bin /qspi_flash0/sample.bin
 
 

Performance Details

Single

Read: 21333 KB/s
Write: 304 KB/s

Dual

Read: 42666 KB/s
Write: 465 KB/s

Mainline Status

Not Mainlined

Change Log

  • 2016.3

    • Summary
      • None
    • Commits
      • None
  • 2016.4

    • Summary
      • None
    • Commits
      • None
  • 2017.1

    • Summary
      • None
    • Commits
      • None
  • 2017.2

    • Summary
      • None
    • Commits
      • None
  • 2017.3

    • Summary
      • Fix warnings reported by check patch
      • Fix sparse warning in driver
      • Fix incorrect spelling in one comment
      • Fix coding style violations
    • Commits
  • 2017.4

    • Summary
      • None
    • Commits
      • None
  • 2018.1

    • Summary
      • None
    • Commits
      • None
  • 2018.2

    • Summary
      • None
    • Commits
  • 2018.3

    • Summary
      • Added support for gpio-cs
    • Commits
  • 2019.1

    • Summary
      • Updated driver as per the new spi-nor framework.
    • Commits
  • 2019.2

    • Summary
      • None
    • Commits
      • None
  • 2020.1

  • Summary
    • Upgrade Zynq qspi Driver as oer kernel v5.4
  • Commits6cac93c
    bs=1024 count=4096
    4096+0 records in
    4096+0 records out
    4194304 bytes (4.0MB) copied, 3.227253 seconds, 1.2MB/s
    #cp ./sample.bin /qspi_flash0/
    #ls /qspi_flash0
    sample.bin
    #umount spi_flash0
    #mount -t jffs2 /dev/mtdblock3 /qspi_flash0
    #diff ./sample.bin /qspi_flash0/sample.bin
     
     

    Performance Details

    Single

    Read: 21333 KB/s
    Write: 304 KB/s

    Dual

    Read: 42666 KB/s
    Write: 465 KB/s

    Mainline Status

    Not Mainlined

    Change Log

    • 2023.2

      • Summary
        • Fix issue while accessing the upper flash in stacked connection mode
        • Avoid writing EAR register for flashes less than 16MB
      • Commits
    • 2023.1

      • Summary
        • Replace all spi->chip_select and spi->cs_gpiod references with function call
        • Add multi-cs support as per new DT bindings
      • Commits
    • 2022.2

      • Summary
        • Remove multiple instances of clock enable
        • Fix a NULL pointer dereference in zynq_qspi_exec_mem_op()
      • Commits
    • 2022.1

      • Summary
        • Fix some wrong goto jumps & missing error code
        • Use wait_for_completion_timeout to make zynq_qspi_exec_mem_op not interruptible
        • Fix buffer overflow in zynq_qspi_exec_mem_op
      • Commits


    ...