1.先读数据手册
FlexSPI block supports following features:
? Flexible sequence engine
? Serial NOR Flash or other device with similar
? Serial NAND Flash
? HyperBus device (HyperFlash/HyperRAM)
?
? Flash access mode
? Single/Dual/Quad/
? SDR/DDR mode
? Individual/Parallel mode
? Support sampling clock mode:
? Internal dummy read strobe loopbacked internally
? Internal dummy read strobe loopbacked from pad
? Flash provided read strobe
? Automatic Data Learning to select correct sample clock phase
2.结构方框图
image.png
2.1 可以使用 AHB BUS 和IPS BUS 两个总线输出命令通LTU Sequence 给外部flash ,使用时选择任意一个。
2.2 与外部flash 接线如下:
image.png
image.png
3.LUT Table
FlexSPI 并不直接通过寄存器来操作SPI Bus上的数据传输,而是提供了一组叫
先看一下
image.png
4.LTU 调用关系
4.1 读取MT35XU256ABA1G12-0AAT数据手册定义如下:
image.png
4.2 代码定义如下: define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */
4.3 为了理解这个控制器先看 linux 调用过程如下:
image.png
4.4 总结调用过程:
上次要读取id时先发读取id命令
4.5 LTU初始化
1 2 3 4 5 6 | #linux static void fsl_flexspi_init_lut(struct fsl_flexspi *flex) { #qnx int init_lut(imx_fspi_t *dev) { |
5.qnx 调用过程
5.1 初始化
image.png
5.2 执行 flashctl -p /dev/fs0 -ev 调用过程
image.png
6. linux 调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #fsl-imx8qxp-mek.dtsi &flexspi0 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flexspi0>; status = "okay"; flash0: mt35xu512aba@0 { reg = <0>; #address-cells = <1>; #size-cells = <1>; compatible = "micron,mt35xu512aba"; spi-max-frequency = <29000000>; spi-nor,ddr-quad-read-dummy = <8>; }; }; pinctrl_flexspi0: flexspi0grp { fsl,pins = < SC_P_QSPI0A_DATA0_LSIO_QSPI0A_DATA0 0x0600004c SC_P_QSPI0A_DATA1_LSIO_QSPI0A_DATA1 0x0600004c SC_P_QSPI0A_DATA2_LSIO_QSPI0A_DATA2 0x0600004c SC_P_QSPI0A_DATA3_LSIO_QSPI0A_DATA3 0x0600004c SC_P_QSPI0A_DQS_LSIO_QSPI0A_DQS 0x0600004c SC_P_QSPI0A_SS0_B_LSIO_QSPI0A_SS0_B 0x0600004c SC_P_QSPI0A_SS1_B_LSIO_QSPI0A_SS1_B 0x0600004c SC_P_QSPI0A_SCLK_LSIO_QSPI0A_SCLK 0x0600004c SC_P_QSPI0B_SCLK_LSIO_QSPI0B_SCLK 0x0600004c SC_P_QSPI0B_DATA0_LSIO_QSPI0B_DATA0 0x0600004c SC_P_QSPI0B_DATA1_LSIO_QSPI0B_DATA1 0x0600004c SC_P_QSPI0B_DATA2_LSIO_QSPI0B_DATA2 0x0600004c SC_P_QSPI0B_DATA3_LSIO_QSPI0B_DATA3 0x0600004c SC_P_QSPI0B_DQS_LSIO_QSPI0B_DQS 0x0600004c SC_P_QSPI0B_SS0_B_LSIO_QSPI0B_SS0_B 0x0600004c SC_P_QSPI0B_SS1_B_LSIO_QSPI0B_SS1_B 0x0600004c >; }; |
1 2 3 4 5 6 7 8 9 | # 匹配设备树 compatible = "micron,mt35xu512aba" 代码: # C:jack.niuSource_Codelinux-toradexdriversmtdspi-norspi-nor.c static const struct flash_info spi_nor_ids[] = { { "mt25qu256", INFO(0x20bb19, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, {"mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_READ | SPI_NOR_SKIP_SFDP) }, } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #目录树 arch/arm64/boot/dts/freescale/fsl-imx8dx.dtsi:3358: compatible = "fsl,imx8qxp-flexspi"; #目录树代码 flexspi0: flexspi@05d120000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx8qxp-flexspi"; reg = <0x0 0x5d120000 0x0 0x10000>, <0x0 0x08000000 0x0 0x10000000>; reg-names = "FlexSPI", "FlexSPI-memory"; interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk IMX8QXP_LSIO_FSPI0_CLK>; assigned-clock-rates = <29000000>; clock-names = "fspi"; power-domains = <&pd_lsio_flexspi0>; status = "disabled"; }; #匹配代码如下 drivers/mtd/spi-nor/fsl-flexspi.c:1162: { .compatible = "fsl,imx8qxp-flexspi", .data = (void *)&imx8qxp_data, }, |
QNX 初始化代码
18.2.5.1 FlexSPI Initialization
FlexSPI controller initialization sequence is as following:
? Enable controller clocks (AHB clock/IP Bus clock/Serial root clock) in System level.
? Set MCR0[MDIS] to 0x1 (Make sure controller is configured in module stop mode)
? Configure module control registers: MCR0, MCR1, MCR2. (Don't change
MCR0[MDIS])
? Configure AHB bus control register (AHBCR) and AHB RX Buffer control register
(AHBRXBUFxCR0) optionally, if AHB command will be used
? Configure Flash control registers (FLSHxCR0,FLSHxCR1,FLSHxCR2) according to
external device type
? Configure DLL control register (DLLxCR) according to sample clock source
selection
? set MCR0[MDIS] to 0x0 (Exit module stop mode)
? Configure LUT as needed (For AHB command or IP command)
? Reset controller optionally (by set MCR0[SWRESET] to 0x1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | /** * imx_fc_flexspi.c * First part of controller initialization. * * @return File descriptor. */ imx_fspi_t *imx_flexspi_open(void) { /* Enable FLEXSPI clock */ mcr_reg = in32(dev->vbase + IMX_FLEXSPI_MCR0); mcr_reg &= ~IMX_FLEXSPI_MCR0_MDIS_MASK; out32(dev->vbase + IMX_FLEXSPI_MCR0, mcr_reg); /* Configure FLEXSPI to use IP access and COMBINATION mode * RXCLKSRC - Flash provided Read strobe and input from DQS pad */ mcr_reg = in32(dev->vbase + IMX_FLEXSPI_MCR0); mcr_reg &= ~(IMX_FLEXSPI_MCR0_ARDFEN_MASK | IMX_FLEXSPI_MCR0_ATDFEN_MASK); if (dev->pads == 8) { mcr_reg |= IMX_FLEXSPI_MCR0_COMBINATIONEN_MASK; } mcr_reg |= (dev->smpl << IMX_FLEXSPI_MCR0_RXCLKSRC_SHIFT); out32(dev->vbase + IMX_FLEXSPI_MCR0, mcr_reg); /* Reset FLEXSPI */ mcr_reg = in32(dev->vbase + IMX_FLEXSPI_MCR0); mcr_reg |= IMX_FLEXSPI_MCR0_SWRESET_MASK; out32(dev->vbase + IMX_FLEXSPI_MCR0, mcr_reg); /* Wait 1ms for domains reset */ delay(1); /* Enable delay line calibration (Flash provided read strobe) */ out32(dev->vbase + IMX_FLEXSPI_DLLACR, IMX_FLEXSPI_DLLACR_DLLEN_MASK); /* Clear RX and TX FIFOs */ out32(dev->vbase + IMX_FLEXSPI_IPTXFCR, IMX_FLEXSPI_IPTXFCR_CLRIPTXF_MASK); out32(dev->vbase + IMX_FLEXSPI_IPRXFCR, IMX_FLEXSPI_IPRXFCR_CLRIPRXF_MASK); |