From be77c57ac9853169ddb7c41f7c2c343e21ddb9e0 Mon Sep 17 00:00:00 2001 From: Jouni Ukkonen Date: Wed, 29 May 2024 14:38:22 +0300 Subject: [PATCH] imx9: Add flexspi support, ported from imxrt Signed-off-by: Jouni Ukkonen --- arch/arm64/src/imx9/Kconfig | 5 + arch/arm64/src/imx9/Make.defs | 5 + arch/arm64/src/imx9/hardware/imx9_flexspi.h | 603 +++++++++ arch/arm64/src/imx9/imx9_flexspi.c | 1255 +++++++++++++++++++ arch/arm64/src/imx9/imx9_flexspi.h | 574 +++++++++ 5 files changed, 2442 insertions(+) create mode 100644 arch/arm64/src/imx9/hardware/imx9_flexspi.h create mode 100644 arch/arm64/src/imx9/imx9_flexspi.c create mode 100644 arch/arm64/src/imx9/imx9_flexspi.h diff --git a/arch/arm64/src/imx9/Kconfig b/arch/arm64/src/imx9/Kconfig index aa27d2fb3fd01..b7f147f4699f0 100644 --- a/arch/arm64/src/imx9/Kconfig +++ b/arch/arm64/src/imx9/Kconfig @@ -112,6 +112,11 @@ endmenu # LPUART Configuration endmenu # LPUART +config IMX9_FLEXSPI + bool "ENABLE FLEXSPI interface" + default n + + config IMX9_FLEXIO1_PWM depends on PWM bool "Enable FLEXIO1 based PWM generation" diff --git a/arch/arm64/src/imx9/Make.defs b/arch/arm64/src/imx9/Make.defs index c420afd939154..89e58c5d31313 100644 --- a/arch/arm64/src/imx9/Make.defs +++ b/arch/arm64/src/imx9/Make.defs @@ -51,3 +51,8 @@ endif ifeq ($(CONFIG_IMX9_LPSPI), y) CHIP_CSRCS += imx9_lpspi.c endif + +ifeq ($(CONFIG_IMX9_FLEXSPI), y) + CHIP_CSRCS += imx9_flexspi.c +endif + diff --git a/arch/arm64/src/imx9/hardware/imx9_flexspi.h b/arch/arm64/src/imx9/hardware/imx9_flexspi.h new file mode 100644 index 0000000000000..03256ccd1a05d --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx9_flexspi.h @@ -0,0 +1,603 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx9_flexspi.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_FLEXSPI_H +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_FLEXSPI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/imx9_memorymap.h" + +/* FLEXSPI - Register Layout Typedef */ + +struct flexspi_type_s +{ + volatile uint32_t MCR0; /* Module Control Register 0, offset: 0x0 */ + volatile uint32_t MCR1; /* Module Control Register 1, offset: 0x4 */ + volatile uint32_t MCR2; /* Module Control Register 2, offset: 0x8 */ + volatile uint32_t AHBCR; /* AHB Bus Control Register, offset: 0xc */ + volatile uint32_t INTEN; /* Interrupt Enable Register, offset: 0x10 */ + volatile uint32_t INTR; /* Interrupt Register, offset: 0x14 */ + volatile uint32_t LUTKEY; /* LUT Key Register, offset: 0x18 */ + volatile uint32_t LUTCR; /* LUT Control Register, offset: 0x1c */ + volatile uint32_t AHBRXBUFCR0[8]; /* AHB RX Buffer 0 Control Register 0..AHB RX Buffer 7 Control Register 0, array offset: 0x20, array step: 0x4 */ + volatile uint8_t RESERVED_0[32]; + volatile uint32_t FLSHCR0[4]; /* Flash A1 Control Register 0..Flash B2 Control Register 0, array offset: 0x60, array step: 0x4 */ + volatile uint32_t FLSHCR1[4]; /* Flash A1 Control Register 1..Flash B2 Control Register 1, array offset: 0x70, array step: 0x4 */ + volatile uint32_t FLSHCR2[4]; /* Flash A1 Control Register 2..Flash B2 Control Register 2, array offset: 0x80, array step: 0x4 */ + uint8_t RESERVED_1[4]; + volatile uint32_t FLSHCR4; /* Flash Control Register 4, offset: 0x94 */ + uint8_t RESERVED_2[8]; + volatile uint32_t IPCR0; /* IP Control Register 0, offset: 0xa0 */ + volatile uint32_t IPCR1; /* IP Control Register 1, offset: 0xa4 */ + uint8_t RESERVED_3[8]; + volatile uint32_t IPCMD; /* IP Command Register, offset: 0xb0 */ + uint8_t RESERVED_4[4]; + volatile uint32_t IPRXFCR; /* IP RX FIFO Control Register, offset: 0xb8 */ + volatile uint32_t IPTXFCR; /* IP TX FIFO Control Register, offset: 0xbc */ + volatile uint32_t DLLCR[2]; /* DLL Control Register 0, array offset: 0xc0, array step: 0x4 */ + uint8_t RESERVED_5[24]; + volatile uint32_t STS0; /* Status Register 0, offset: 0xe0 */ + volatile uint32_t STS1; /* Status Register 1, offset: 0xe4 */ + volatile uint32_t STS2; /* Status Register 2, offset: 0xe8 */ + volatile uint32_t AHBSPNDSTS; /* AHB Suspend Status Register, offset: 0xec */ + volatile uint32_t IPRXFSTS; /* IP RX FIFO Status Register, offset: 0xf0 */ + volatile uint32_t IPTXFSTS; /* IP TX FIFO Status Register, offset: 0xf4 */ + uint8_t RESERVED_6[8]; + volatile uint32_t RFDR[32]; /* IP RX FIFO Data Register 0..IP RX FIFO Data Register 31, array offset: 0x100, array step: 0x4 */ + volatile uint32_t TFDR[32]; /* IP TX FIFO Data Register 0..IP TX FIFO Data Register 31, array offset: 0x180, array step: 0x4 */ + volatile uint32_t LUT[128]; /* LUT 0..LUT 127, array offset: 0x200, array step: 0x4 */ +}; + +#define IMX9_FLEXSPI_AHBBUFREGIONSTART0_OFFSET 0x440 +#define IMX9_FLEXSPI_AHBBUFREGIONEND0_OFFSET 0x444 +#define IMX9_FLEXSPI_AHBBUFREGIONSTART1_OFFSET 0x448 +#define IMX9_FLEXSPI_AHBBUFREGIONEND1_OFFSET 0x44C +#define IMX9_FLEXSPI_AHBBUFREGIONSTART2_OFFSET 0x450 +#define IMX9_FLEXSPI_AHBBUFREGIONEND2_OFFSET 0x454 +#define IMX9_FLEXSPI_AHBBUFREGIONSTART3_OFFSET 0x458 +#define IMX9_FLEXSPI_AHBBUFREGIONEND3_OFFSET 0x45C + +#define IMX9_FLEXSPI1_AHBBUFREGIONSTART0 (IMX9_FLEXSPI_BASE + IMX9_FLEXSPI_AHBBUFREGIONSTART0_OFFSET) +#define IMX9_FLEXSPI1_AHBBUFREGIONEND0 (IMX9_FLEXSPI_BASE + IMX9_FLEXSPI_AHBBUFREGIONEND0_OFFSET) +#define IMX9_FLEXSPI1_AHBBUFREGIONSTART1 (IMX9_FLEXSPI_BASE + IMX9_FLEXSPI_AHBBUFREGIONSTART1_OFFSET) +#define IMX9_FLEXSPI1_AHBBUFREGIONEND1 (IMX9_FLEXSPI_BASE + IMX9_FLEXSPI_AHBBUFREGIONEND1_OFFSET) +#define IMX9_FLEXSPI1_AHBBUFREGIONSTART2 (IMX9_FLEXSPI_BASE + IMX9_FLEXSPI_AHBBUFREGIONSTART2_OFFSET) +#define IMX9_FLEXSPI1_AHBBUFREGIONEND2 (IMX9_FLEXSPI_BASE + IMX9_FLEXSPI_AHBBUFREGIONEND2_OFFSET) +#define IMX9_FLEXSPI1_AHBBUFREGIONSTART3 (IMX9_FLEXSPI_BASE + IMX9_FLEXSPI_AHBBUFREGIONSTART3_OFFSET) +#define IMX9_FLEXSPI1_AHBBUFREGIONEND3 (IMX9_FLEXSPI_BASE + IMX9_FLEXSPI_AHBBUFREGIONEND3_OFFSET) + + + +/* MCR0 - Module Control Register 0 */ + +#define FLEXSPI_MCR0_SWRESET_MASK (0x1u) +#define FLEXSPI_MCR0_SWRESET_SHIFT (0u) + +/* SWRESET - Software Reset */ + +#define FLEXSPI_MCR0_SWRESET(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR0_SWRESET_SHIFT)) & FLEXSPI_MCR0_SWRESET_MASK) +#define FLEXSPI_MCR0_MDIS_MASK (0x2u) +#define FLEXSPI_MCR0_MDIS_SHIFT (1u) + +/* MDIS - Module Disable */ + +#define FLEXSPI_MCR0_MDIS(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR0_MDIS_SHIFT)) & FLEXSPI_MCR0_MDIS_MASK) +#define FLEXSPI_MCR0_RXCLKSRC_MASK (0x30u) +#define FLEXSPI_MCR0_RXCLKSRC_SHIFT (4u) + +#define FLEXSPI_MCR0_RXCLKSRC(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR0_RXCLKSRC_SHIFT)) & FLEXSPI_MCR0_RXCLKSRC_MASK) +#define FLEXSPI_MCR0_ARDFEN_MASK (0x40u) +#define FLEXSPI_MCR0_ARDFEN_SHIFT (6u) + +#define FLEXSPI_MCR0_ARDFEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR0_ARDFEN_SHIFT)) & FLEXSPI_MCR0_ARDFEN_MASK) +#define FLEXSPI_MCR0_ATDFEN_MASK (0x80u) +#define FLEXSPI_MCR0_ATDFEN_SHIFT (7u) + +#define FLEXSPI_MCR0_ATDFEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR0_ATDFEN_SHIFT)) & FLEXSPI_MCR0_ATDFEN_MASK) +#define FLEXSPI_MCR0_HSEN_MASK (0x800u) +#define FLEXSPI_MCR0_HSEN_SHIFT (11u) + +#define FLEXSPI_MCR0_HSEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR0_HSEN_SHIFT)) & FLEXSPI_MCR0_HSEN_MASK) +#define FLEXSPI_MCR0_DOZEEN_MASK (0x1000u) +#define FLEXSPI_MCR0_DOZEEN_SHIFT (12u) + +#define FLEXSPI_MCR0_DOZEEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR0_DOZEEN_SHIFT)) & FLEXSPI_MCR0_DOZEEN_MASK) +#define FLEXSPI_MCR0_COMBINATIONEN_MASK (0x2000u) +#define FLEXSPI_MCR0_COMBINATIONEN_SHIFT (13u) + +#define FLEXSPI_MCR0_COMBINATIONEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR0_COMBINATIONEN_SHIFT)) & FLEXSPI_MCR0_COMBINATIONEN_MASK) +#define FLEXSPI_MCR0_SCKFREERUNEN_MASK (0x4000u) +#define FLEXSPI_MCR0_SCKFREERUNEN_SHIFT (14u) + +#define FLEXSPI_MCR0_SCKFREERUNEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR0_SCKFREERUNEN_SHIFT)) & FLEXSPI_MCR0_SCKFREERUNEN_MASK) +#define FLEXSPI_MCR0_IPGRANTWAIT_MASK (0xff0000u) +#define FLEXSPI_MCR0_IPGRANTWAIT_SHIFT (16u) + +#define FLEXSPI_MCR0_IPGRANTWAIT(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR0_IPGRANTWAIT_SHIFT)) & FLEXSPI_MCR0_IPGRANTWAIT_MASK) +#define FLEXSPI_MCR0_AHBGRANTWAIT_MASK (0xff000000u) +#define FLEXSPI_MCR0_AHBGRANTWAIT_SHIFT (24u) + +#define FLEXSPI_MCR0_AHBGRANTWAIT(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR0_AHBGRANTWAIT_SHIFT)) & FLEXSPI_MCR0_AHBGRANTWAIT_MASK) + +#define FLEXSPI_MCR1_AHBBUSWAIT_MASK (0xffffu) +#define FLEXSPI_MCR1_AHBBUSWAIT_SHIFT (0u) +#define FLEXSPI_MCR1_AHBBUSWAIT(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR1_AHBBUSWAIT_SHIFT)) & FLEXSPI_MCR1_AHBBUSWAIT_MASK) +#define FLEXSPI_MCR1_SEQWAIT_MASK (0xffff0000u) +#define FLEXSPI_MCR1_SEQWAIT_SHIFT (16u) +#define FLEXSPI_MCR1_SEQWAIT(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR1_SEQWAIT_SHIFT)) & FLEXSPI_MCR1_SEQWAIT_MASK) + +#define FLEXSPI_MCR2_CLRAHBBUFOPT_MASK (0x800u) +#define FLEXSPI_MCR2_CLRAHBBUFOPT_SHIFT (11u) + +#define FLEXSPI_MCR2_CLRAHBBUFOPT(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR2_CLRAHBBUFOPT_SHIFT)) & FLEXSPI_MCR2_CLRAHBBUFOPT_MASK) +#define FLEXSPI_MCR2_CLRLEARNPHASE_MASK (0x4000u) +#define FLEXSPI_MCR2_CLRLEARNPHASE_SHIFT (14u) + +#define FLEXSPI_MCR2_CLRLEARNPHASE(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR2_CLRLEARNPHASE_SHIFT)) & FLEXSPI_MCR2_CLRLEARNPHASE_MASK) +#define FLEXSPI_MCR2_SAMEDEVICEEN_MASK (0x8000u) +#define FLEXSPI_MCR2_SAMEDEVICEEN_SHIFT (15u) + +#define FLEXSPI_MCR2_SAMEDEVICEEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR2_SAMEDEVICEEN_SHIFT)) & FLEXSPI_MCR2_SAMEDEVICEEN_MASK) +#define FLEXSPI_MCR2_SCKBDIFFOPT_MASK (0x80000u) +#define FLEXSPI_MCR2_SCKBDIFFOPT_SHIFT (19u) + +#define FLEXSPI_MCR2_SCKBDIFFOPT(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR2_SCKBDIFFOPT_SHIFT)) & FLEXSPI_MCR2_SCKBDIFFOPT_MASK) +#define FLEXSPI_MCR2_RESUMEWAIT_MASK (0xff000000u) +#define FLEXSPI_MCR2_RESUMEWAIT_SHIFT (24u) + +#define FLEXSPI_MCR2_RESUMEWAIT(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_MCR2_RESUMEWAIT_SHIFT)) & FLEXSPI_MCR2_RESUMEWAIT_MASK) + +#define FLEXSPI_AHBCR_APAREN_MASK (0x1u) +#define FLEXSPI_AHBCR_APAREN_SHIFT (0u) + +#define FLEXSPI_AHBCR_APAREN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_AHBCR_APAREN_SHIFT)) & FLEXSPI_AHBCR_APAREN_MASK) +#define FLEXSPI_AHBCR_CACHABLEEN_MASK (0x8u) +#define FLEXSPI_AHBCR_CACHABLEEN_SHIFT (3u) + +#define FLEXSPI_AHBCR_CACHABLEEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_AHBCR_CACHABLEEN_SHIFT)) & FLEXSPI_AHBCR_CACHABLEEN_MASK) +#define FLEXSPI_AHBCR_BUFFERABLEEN_MASK (0x10u) +#define FLEXSPI_AHBCR_BUFFERABLEEN_SHIFT (4u) + +#define FLEXSPI_AHBCR_BUFFERABLEEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_AHBCR_BUFFERABLEEN_SHIFT)) & FLEXSPI_AHBCR_BUFFERABLEEN_MASK) +#define FLEXSPI_AHBCR_PREFETCHEN_MASK (0x20u) +#define FLEXSPI_AHBCR_PREFETCHEN_SHIFT (5u) + +#define FLEXSPI_AHBCR_PREFETCHEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_AHBCR_PREFETCHEN_SHIFT)) & FLEXSPI_AHBCR_PREFETCHEN_MASK) +#define FLEXSPI_AHBCR_READADDROPT_MASK (0x40u) +#define FLEXSPI_AHBCR_READADDROPT_SHIFT (6u) + +#define FLEXSPI_AHBCR_READADDROPT(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_AHBCR_READADDROPT_SHIFT)) & FLEXSPI_AHBCR_READADDROPT_MASK) + +#define FLEXSPI_INTEN_IPCMDDONEEN_MASK (0x1u) +#define FLEXSPI_INTEN_IPCMDDONEEN_SHIFT (0u) + +#define FLEXSPI_INTEN_IPCMDDONEEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTEN_IPCMDDONEEN_SHIFT)) & FLEXSPI_INTEN_IPCMDDONEEN_MASK) +#define FLEXSPI_INTEN_IPCMDGEEN_MASK (0x2u) +#define FLEXSPI_INTEN_IPCMDGEEN_SHIFT (1u) + +#define FLEXSPI_INTEN_IPCMDGEEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTEN_IPCMDGEEN_SHIFT)) & FLEXSPI_INTEN_IPCMDGEEN_MASK) +#define FLEXSPI_INTEN_AHBCMDGEEN_MASK (0x4u) +#define FLEXSPI_INTEN_AHBCMDGEEN_SHIFT (2u) + +#define FLEXSPI_INTEN_AHBCMDGEEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTEN_AHBCMDGEEN_SHIFT)) & FLEXSPI_INTEN_AHBCMDGEEN_MASK) +#define FLEXSPI_INTEN_IPCMDERREN_MASK (0x8u) +#define FLEXSPI_INTEN_IPCMDERREN_SHIFT (3u) + +#define FLEXSPI_INTEN_IPCMDERREN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTEN_IPCMDERREN_SHIFT)) & FLEXSPI_INTEN_IPCMDERREN_MASK) +#define FLEXSPI_INTEN_AHBCMDERREN_MASK (0x10u) +#define FLEXSPI_INTEN_AHBCMDERREN_SHIFT (4u) + +#define FLEXSPI_INTEN_AHBCMDERREN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTEN_AHBCMDERREN_SHIFT)) & FLEXSPI_INTEN_AHBCMDERREN_MASK) +#define FLEXSPI_INTEN_IPRXWAEN_MASK (0x20u) +#define FLEXSPI_INTEN_IPRXWAEN_SHIFT (5u) + +#define FLEXSPI_INTEN_IPRXWAEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTEN_IPRXWAEN_SHIFT)) & FLEXSPI_INTEN_IPRXWAEN_MASK) +#define FLEXSPI_INTEN_IPTXWEEN_MASK (0x40u) +#define FLEXSPI_INTEN_IPTXWEEN_SHIFT (6u) + +#define FLEXSPI_INTEN_IPTXWEEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTEN_IPTXWEEN_SHIFT)) & FLEXSPI_INTEN_IPTXWEEN_MASK) +#define FLEXSPI_INTEN_SCKSTOPBYRDEN_MASK (0x100u) +#define FLEXSPI_INTEN_SCKSTOPBYRDEN_SHIFT (8u) + +#define FLEXSPI_INTEN_SCKSTOPBYRDEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTEN_SCKSTOPBYRDEN_SHIFT)) & FLEXSPI_INTEN_SCKSTOPBYRDEN_MASK) +#define FLEXSPI_INTEN_SCKSTOPBYWREN_MASK (0x200u) +#define FLEXSPI_INTEN_SCKSTOPBYWREN_SHIFT (9u) +#define FLEXSPI_INTEN_SCKSTOPBYWREN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTEN_SCKSTOPBYWREN_SHIFT)) & FLEXSPI_INTEN_SCKSTOPBYWREN_MASK) + +#define FLEXSPI_INTEN_AHBBUSERROREN_MASK (0x400u) +#define FLEXSPI_INTEN_AHBBUSERROREN_SHIFT (10u) +#define FLEXSPI_INTEN_AHBBUSERROREN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTEN_AHBBUSERROREN_SHIFT)) & FLEXSPI_INTEN_AHBBUSERROREN_MASK) + +#define FLEXSPI_INTEN_SEQTIMEOUTEN_MASK (0x800u) +#define FLEXSPI_INTEN_SEQTIMEOUTEN_SHIFT (11u) +#define FLEXSPI_INTEN_SEQTIMEOUTEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTEN_SEQTIMEOUTEN_SHIFT)) & FLEXSPI_INTEN_SEQTIMEOUTEN_MASK) + +#define FLEXSPI_INTEN_KEYDONE_MASK (0x1000u) +#define FLEXSPI_INTEN_KEYDONE_SHIFT (12u) +#define FLEXSPI_INTEN_KEYDONE(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTEN_KEYDONE_SHIFT)) & FLEXSPI_INTEN_KEYDONE_MASK) + +#define FLEXSPI_INTEN_KEYERROR_MASK (0x2000u) +#define FLEXSPI_INTEN_KEYERROR_SHIFT (13u) +#define FLEXSPI_INTEN_KEYERROR(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTEN_KEYERROR_SHIFT)) & FLEXSPI_INTEN_KEYERROR_MASK) + + +#define FLEXSPI_INTR_IPCMDDONE_MASK (0x1u) +#define FLEXSPI_INTR_IPCMDDONE_SHIFT (0u) + +#define FLEXSPI_INTR_IPCMDDONE(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTR_IPCMDDONE_SHIFT)) & FLEXSPI_INTR_IPCMDDONE_MASK) +#define FLEXSPI_INTR_IPCMDGE_MASK (0x2u) +#define FLEXSPI_INTR_IPCMDGE_SHIFT (1u) + +#define FLEXSPI_INTR_IPCMDGE(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTR_IPCMDGE_SHIFT)) & FLEXSPI_INTR_IPCMDGE_MASK) +#define FLEXSPI_INTR_AHBCMDGE_MASK (0x4u) +#define FLEXSPI_INTR_AHBCMDGE_SHIFT (2u) + +#define FLEXSPI_INTR_AHBCMDGE(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTR_AHBCMDGE_SHIFT)) & FLEXSPI_INTR_AHBCMDGE_MASK) +#define FLEXSPI_INTR_IPCMDERR_MASK (0x8u) +#define FLEXSPI_INTR_IPCMDERR_SHIFT (3u) + +#define FLEXSPI_INTR_IPCMDERR(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTR_IPCMDERR_SHIFT)) & FLEXSPI_INTR_IPCMDERR_MASK) +#define FLEXSPI_INTR_AHBCMDERR_MASK (0x10u) +#define FLEXSPI_INTR_AHBCMDERR_SHIFT (4u) + +#define FLEXSPI_INTR_AHBCMDERR(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTR_AHBCMDERR_SHIFT)) & FLEXSPI_INTR_AHBCMDERR_MASK) +#define FLEXSPI_INTR_IPRXWA_MASK (0x20u) +#define FLEXSPI_INTR_IPRXWA_SHIFT (5u) + +#define FLEXSPI_INTR_IPRXWA(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTR_IPRXWA_SHIFT)) & FLEXSPI_INTR_IPRXWA_MASK) +#define FLEXSPI_INTR_IPTXWE_MASK (0x40u) +#define FLEXSPI_INTR_IPTXWE_SHIFT (6u) + +#define FLEXSPI_INTR_IPTXWE(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTR_IPTXWE_SHIFT)) & FLEXSPI_INTR_IPTXWE_MASK) +#define FLEXSPI_INTR_SCKSTOPBYRD_MASK (0x100u) +#define FLEXSPI_INTR_SCKSTOPBYRD_SHIFT (8u) + +#define FLEXSPI_INTR_SCKSTOPBYRD(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTR_SCKSTOPBYRD_SHIFT)) & FLEXSPI_INTR_SCKSTOPBYRD_MASK) +#define FLEXSPI_INTR_SCKSTOPBYWR_MASK (0x200u) +#define FLEXSPI_INTR_SCKSTOPBYWR_SHIFT (9u) + +#define FLEXSPI_INTR_SCKSTOPBYWR(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTR_SCKSTOPBYWR_SHIFT)) & FLEXSPI_INTR_SCKSTOPBYWR_MASK) +#define FLEXSPI_INTR_AHBBUSTIMEOUT_MASK (0x400u) +#define FLEXSPI_INTR_AHBBUSTIMEOUT_SHIFT (10u) + +#define FLEXSPI_INTR_AHBBUSTIMEOUT(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTR_AHBBUSTIMEOUT_SHIFT)) & FLEXSPI_INTR_AHBBUSTIMEOUT_MASK) +#define FLEXSPI_INTR_SEQTIMEOUT_MASK (0x800u) +#define FLEXSPI_INTR_SEQTIMEOUT_SHIFT (11u) + +#define FLEXSPI_INTR_SEQTIMEOUT(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTR_SEQTIMEOUT_SHIFT)) & FLEXSPI_INTR_SEQTIMEOUT_MASK) + +#define FLEXSPI_INTR_KEYDONE_MASK (0x1000u) +#define FLEXSPI_INTR_KEYDONE_SHIFT (12u) +#define FLEXSPI_INTR_KEYDONE(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTR_KEYDONE_SHIFT)) & FLEXSPI_INTR_KEYDONE_MASK) + +#define FLEXSPI_INTR_KEYERROR_MASK (0x2000u) +#define FLEXSPI_INTR_KEYERROR_SHIFT (13u) +#define FLEXSPI_INTR_KEYERROR(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_INTR_KEYERROR_SHIFT)) & FLEXSPI_INTR_KEYERROR_MASK) + + +#define FLEXSPI_LUTKEY_KEY_MASK (0xffffffffu) +#define FLEXSPI_LUTKEY_KEY_SHIFT (0u) + +#define FLEXSPI_LUTKEY_KEY(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUTKEY_KEY_SHIFT)) & FLEXSPI_LUTKEY_KEY_MASK) + +#define FLEXSPI_LUTCR_LOCK_MASK (0x1u) +#define FLEXSPI_LUTCR_LOCK_SHIFT (0u) + +#define FLEXSPI_LUTCR_LOCK(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUTCR_LOCK_SHIFT)) & FLEXSPI_LUTCR_LOCK_MASK) +#define FLEXSPI_LUTCR_UNLOCK_MASK (0x2u) +#define FLEXSPI_LUTCR_UNLOCK_SHIFT (1u) + +#define FLEXSPI_LUTCR_UNLOCK(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUTCR_UNLOCK_SHIFT)) & FLEXSPI_LUTCR_UNLOCK_MASK) + + +#define FLEXSPI_AHBRXBUFCR0_BUFSZ_MASK (0x1ffu) + +#define FLEXSPI_AHBRXBUFCR0_BUFSZ_SHIFT (0u) + +#define FLEXSPI_AHBRXBUFCR0_BUFSZ(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_AHBRXBUFCR0_BUFSZ_SHIFT)) & FLEXSPI_AHBRXBUFCR0_BUFSZ_MASK) +#define FLEXSPI_AHBRXBUFCR0_MSTRID_MASK (0xf0000u) +#define FLEXSPI_AHBRXBUFCR0_MSTRID_SHIFT (16u) + +#define FLEXSPI_AHBRXBUFCR0_MSTRID(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_AHBRXBUFCR0_MSTRID_SHIFT)) & FLEXSPI_AHBRXBUFCR0_MSTRID_MASK) +#define FLEXSPI_AHBRXBUFCR0_PRIORITY_MASK (0x7000000u) +#define FLEXSPI_AHBRXBUFCR0_PRIORITY_SHIFT (24u) + +#define FLEXSPI_AHBRXBUFCR0_PRIORITY(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_AHBRXBUFCR0_PRIORITY_SHIFT)) & FLEXSPI_AHBRXBUFCR0_PRIORITY_MASK) + +#define FLEXSPI_AHBRXBUFCR0_REGIONEN_MASK (0x40000000u) +#define FLEXSPI_AHBRXBUFCR0_REGIONEN_SHIFT (30u) + +#define FLEXSPI_AHBRXBUFCR0_REGIONEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_AHBRXBUFCR0_REGIONEN_SHIFT)) & FLEXSPI_AHBRXBUFCR0_REGIONEN_MASK) + +#define FLEXSPI_AHBRXBUFCR0_PREFETCHEN_MASK (0x80000000u) +#define FLEXSPI_AHBRXBUFCR0_PREFETCHEN_SHIFT (31u) + +#define FLEXSPI_AHBRXBUFCR0_PREFETCHEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_AHBRXBUFCR0_PREFETCHEN_SHIFT)) & FLEXSPI_AHBRXBUFCR0_PREFETCHEN_MASK) + +#define FLEXSPI_AHBRXBUFCR0_COUNT (4u) + +#define FLEXSPI_FLSHCR0_FLSHSZ_MASK (0x7fffffu) +#define FLEXSPI_FLSHCR0_FLSHSZ_SHIFT (0u) + +#define FLEXSPI_FLSHCR0_FLSHSZ(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR0_FLSHSZ_SHIFT)) & FLEXSPI_FLSHCR0_FLSHSZ_MASK) + +#define FLEXSPI_FLSHCR0_COUNT (4u) + +#define FLEXSPI_FLSHCR1_TCSS_MASK (0x1fu) +#define FLEXSPI_FLSHCR1_TCSS_SHIFT (0u) + +#define FLEXSPI_FLSHCR1_TCSS(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR1_TCSS_SHIFT)) & FLEXSPI_FLSHCR1_TCSS_MASK) +#define FLEXSPI_FLSHCR1_TCSH_MASK (0x3e0u) +#define FLEXSPI_FLSHCR1_TCSH_SHIFT (5u) + +#define FLEXSPI_FLSHCR1_TCSH(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR1_TCSH_SHIFT)) & FLEXSPI_FLSHCR1_TCSH_MASK) +#define FLEXSPI_FLSHCR1_WA_MASK (0x400u) +#define FLEXSPI_FLSHCR1_WA_SHIFT (10u) + +#define FLEXSPI_FLSHCR1_WA(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR1_WA_SHIFT)) & FLEXSPI_FLSHCR1_WA_MASK) +#define FLEXSPI_FLSHCR1_CAS_MASK (0x7800u) +#define FLEXSPI_FLSHCR1_CAS_SHIFT (11u) + +#define FLEXSPI_FLSHCR1_CAS(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR1_CAS_SHIFT)) & FLEXSPI_FLSHCR1_CAS_MASK) +#define FLEXSPI_FLSHCR1_CSINTERVALUNIT_MASK (0x8000u) +#define FLEXSPI_FLSHCR1_CSINTERVALUNIT_SHIFT (15u) + +#define FLEXSPI_FLSHCR1_CSINTERVALUNIT(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR1_CSINTERVALUNIT_SHIFT)) & FLEXSPI_FLSHCR1_CSINTERVALUNIT_MASK) +#define FLEXSPI_FLSHCR1_CSINTERVAL_MASK (0xffff0000u) +#define FLEXSPI_FLSHCR1_CSINTERVAL_SHIFT (16u) + +#define FLEXSPI_FLSHCR1_CSINTERVAL(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR1_CSINTERVAL_SHIFT)) & FLEXSPI_FLSHCR1_CSINTERVAL_MASK) + +#define FLEXSPI_FLSHCR1_COUNT (4u) + +#define FLEXSPI_FLSHCR2_ARDSEQID_MASK (0xfu) +#define FLEXSPI_FLSHCR2_ARDSEQID_SHIFT (0u) + +#define FLEXSPI_FLSHCR2_ARDSEQID(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR2_ARDSEQID_SHIFT)) & FLEXSPI_FLSHCR2_ARDSEQID_MASK) +#define FLEXSPI_FLSHCR2_ARDSEQNUM_MASK (0xe0u) +#define FLEXSPI_FLSHCR2_ARDSEQNUM_SHIFT (5u) + +#define FLEXSPI_FLSHCR2_ARDSEQNUM(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR2_ARDSEQNUM_SHIFT)) & FLEXSPI_FLSHCR2_ARDSEQNUM_MASK) +#define FLEXSPI_FLSHCR2_AWRSEQID_MASK (0xf00u) +#define FLEXSPI_FLSHCR2_AWRSEQID_SHIFT (8u) + +#define FLEXSPI_FLSHCR2_AWRSEQID(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR2_AWRSEQID_SHIFT)) & FLEXSPI_FLSHCR2_AWRSEQID_MASK) +#define FLEXSPI_FLSHCR2_AWRSEQNUM_MASK (0xe000u) +#define FLEXSPI_FLSHCR2_AWRSEQNUM_SHIFT (13u) + +#define FLEXSPI_FLSHCR2_AWRSEQNUM(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR2_AWRSEQNUM_SHIFT)) & FLEXSPI_FLSHCR2_AWRSEQNUM_MASK) +#define FLEXSPI_FLSHCR2_AWRWAIT_MASK (0xfff0000u) +#define FLEXSPI_FLSHCR2_AWRWAIT_SHIFT (16u) +#define FLEXSPI_FLSHCR2_AWRWAIT(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR2_AWRWAIT_SHIFT)) & FLEXSPI_FLSHCR2_AWRWAIT_MASK) +#define FLEXSPI_FLSHCR2_AWRWAITUNIT_MASK (0x70000000u) +#define FLEXSPI_FLSHCR2_AWRWAITUNIT_SHIFT (28u) + +#define FLEXSPI_FLSHCR2_AWRWAITUNIT(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR2_AWRWAITUNIT_SHIFT)) & FLEXSPI_FLSHCR2_AWRWAITUNIT_MASK) +#define FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK (0x80000000u) +#define FLEXSPI_FLSHCR2_CLRINSTRPTR_SHIFT (31u) + +#define FLEXSPI_FLSHCR2_CLRINSTRPTR(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR2_CLRINSTRPTR_SHIFT)) & FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK) + +#define FLEXSPI_FLSHCR2_COUNT (4u) + +#define FLEXSPI_FLSHCR4_WMOPT1_MASK (0x1u) +#define FLEXSPI_FLSHCR4_WMOPT1_SHIFT (0u) + +#define FLEXSPI_FLSHCR4_WMOPT1(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR4_WMOPT1_SHIFT)) & FLEXSPI_FLSHCR4_WMOPT1_MASK) +#define FLEXSPI_FLSHCR4_WMENA_MASK (0x4u) +#define FLEXSPI_FLSHCR4_WMENA_SHIFT (2u) + +#define FLEXSPI_FLSHCR4_WMENA(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR4_WMENA_SHIFT)) & FLEXSPI_FLSHCR4_WMENA_MASK) +#define FLEXSPI_FLSHCR4_WMENB_MASK (0x8u) +#define FLEXSPI_FLSHCR4_WMENB_SHIFT (3u) + +#define FLEXSPI_FLSHCR4_WMENB(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_FLSHCR4_WMENB_SHIFT)) & FLEXSPI_FLSHCR4_WMENB_MASK) + +#define FLEXSPI_IPCR0_SFAR_MASK (0xffffffffu) +#define FLEXSPI_IPCR0_SFAR_SHIFT (0u) + +#define FLEXSPI_IPCR0_SFAR(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPCR0_SFAR_SHIFT)) & FLEXSPI_IPCR0_SFAR_MASK) + +#define FLEXSPI_IPCR1_IDATSZ_MASK (0xffffu) +#define FLEXSPI_IPCR1_IDATSZ_SHIFT (0u) + +#define FLEXSPI_IPCR1_IDATSZ(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPCR1_IDATSZ_SHIFT)) & FLEXSPI_IPCR1_IDATSZ_MASK) +#define FLEXSPI_IPCR1_ISEQID_MASK (0xf0000u) +#define FLEXSPI_IPCR1_ISEQID_SHIFT (16u) + +#define FLEXSPI_IPCR1_ISEQID(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPCR1_ISEQID_SHIFT)) & FLEXSPI_IPCR1_ISEQID_MASK) +#define FLEXSPI_IPCR1_ISEQNUM_MASK (0x7000000u) +#define FLEXSPI_IPCR1_ISEQNUM_SHIFT (24u) + +#define FLEXSPI_IPCR1_ISEQNUM(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPCR1_ISEQNUM_SHIFT)) & FLEXSPI_IPCR1_ISEQNUM_MASK) +#define FLEXSPI_IPCR1_IPAREN_MASK (0x80000000u) +#define FLEXSPI_IPCR1_IPAREN_SHIFT (31u) + +#define FLEXSPI_IPCR1_IPAREN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPCR1_IPAREN_SHIFT)) & FLEXSPI_IPCR1_IPAREN_MASK) + +#define FLEXSPI_IPCMD_TRG_MASK (0x1u) +#define FLEXSPI_IPCMD_TRG_SHIFT (0u) + +#define FLEXSPI_IPCMD_TRG(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPCMD_TRG_SHIFT)) & FLEXSPI_IPCMD_TRG_MASK) + +#define FLEXSPI_IPRXFCR_CLRIPRXF_MASK (0x1u) +#define FLEXSPI_IPRXFCR_CLRIPRXF_SHIFT (0u) + +#define FLEXSPI_IPRXFCR_CLRIPRXF(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPRXFCR_CLRIPRXF_SHIFT)) & FLEXSPI_IPRXFCR_CLRIPRXF_MASK) +#define FLEXSPI_IPRXFCR_RXDMAEN_MASK (0x2u) +#define FLEXSPI_IPRXFCR_RXDMAEN_SHIFT (1u) + +#define FLEXSPI_IPRXFCR_RXDMAEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPRXFCR_RXDMAEN_SHIFT)) & FLEXSPI_IPRXFCR_RXDMAEN_MASK) +#define FLEXSPI_IPRXFCR_RXWMRK_MASK (0x3cu) +#define FLEXSPI_IPRXFCR_RXWMRK_SHIFT (2u) + +#define FLEXSPI_IPRXFCR_RXWMRK(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPRXFCR_RXWMRK_SHIFT)) & FLEXSPI_IPRXFCR_RXWMRK_MASK) + +#define FLEXSPI_IPTXFCR_CLRIPTXF_MASK (0x1u) +#define FLEXSPI_IPTXFCR_CLRIPTXF_SHIFT (0u) + +#define FLEXSPI_IPTXFCR_CLRIPTXF(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPTXFCR_CLRIPTXF_SHIFT)) & FLEXSPI_IPTXFCR_CLRIPTXF_MASK) +#define FLEXSPI_IPTXFCR_TXDMAEN_MASK (0x2u) +#define FLEXSPI_IPTXFCR_TXDMAEN_SHIFT (1u) + +#define FLEXSPI_IPTXFCR_TXDMAEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPTXFCR_TXDMAEN_SHIFT)) & FLEXSPI_IPTXFCR_TXDMAEN_MASK) +#define FLEXSPI_IPTXFCR_TXWMRK_MASK (0x3cu) +#define FLEXSPI_IPTXFCR_TXWMRK_SHIFT (2u) + +#define FLEXSPI_IPTXFCR_TXWMRK(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPTXFCR_TXWMRK_SHIFT)) & FLEXSPI_IPTXFCR_TXWMRK_MASK) + +#define FLEXSPI_DLLCR_DLLEN_MASK (0x1u) +#define FLEXSPI_DLLCR_DLLEN_SHIFT (0u) + +#define FLEXSPI_DLLCR_DLLEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_DLLCR_DLLEN_SHIFT)) & FLEXSPI_DLLCR_DLLEN_MASK) +#define FLEXSPI_DLLCR_DLLRESET_MASK (0x2u) +#define FLEXSPI_DLLCR_DLLRESET_SHIFT (1u) + +#define FLEXSPI_DLLCR_DLLRESET(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_DLLCR_DLLRESET_SHIFT)) & FLEXSPI_DLLCR_DLLRESET_MASK) +#define FLEXSPI_DLLCR_SLVDLYTARGET_MASK (0x78u) +#define FLEXSPI_DLLCR_SLVDLYTARGET_SHIFT (3u) + +#define FLEXSPI_DLLCR_SLVDLYTARGET(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_DLLCR_SLVDLYTARGET_SHIFT)) & FLEXSPI_DLLCR_SLVDLYTARGET_MASK) +#define FLEXSPI_DLLCR_OVRDEN_MASK (0x100u) +#define FLEXSPI_DLLCR_OVRDEN_SHIFT (8u) + +#define FLEXSPI_DLLCR_OVRDEN(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_DLLCR_OVRDEN_SHIFT)) & FLEXSPI_DLLCR_OVRDEN_MASK) +#define FLEXSPI_DLLCR_OVRDVAL_MASK (0x7e00u) +#define FLEXSPI_DLLCR_OVRDVAL_SHIFT (9u) + +#define FLEXSPI_DLLCR_OVRDVAL(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_DLLCR_OVRDVAL_SHIFT)) & FLEXSPI_DLLCR_OVRDVAL_MASK) + +#define FLEXSPI_DLLCR_COUNT (2u) + +#define FLEXSPI_STS0_SEQIDLE_MASK (0x1u) +#define FLEXSPI_STS0_SEQIDLE_SHIFT (0u) + +#define FLEXSPI_STS0_SEQIDLE(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_STS0_SEQIDLE_SHIFT)) & FLEXSPI_STS0_SEQIDLE_MASK) +#define FLEXSPI_STS0_ARBIDLE_MASK (0x2u) +#define FLEXSPI_STS0_ARBIDLE_SHIFT (1u) + +#define FLEXSPI_STS0_ARBIDLE(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_STS0_ARBIDLE_SHIFT)) & FLEXSPI_STS0_ARBIDLE_MASK) +#define FLEXSPI_STS0_ARBCMDSRC_MASK (0xcu) +#define FLEXSPI_STS0_ARBCMDSRC_SHIFT (2u) + +#define FLEXSPI_STS0_ARBCMDSRC(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_STS0_ARBCMDSRC_SHIFT)) & FLEXSPI_STS0_ARBCMDSRC_MASK) + +#define FLEXSPI_STS1_AHBCMDERRID_MASK (0xfu) +#define FLEXSPI_STS1_AHBCMDERRID_SHIFT (0u) + +#define FLEXSPI_STS1_AHBCMDERRID(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_STS1_AHBCMDERRID_SHIFT)) & FLEXSPI_STS1_AHBCMDERRID_MASK) +#define FLEXSPI_STS1_AHBCMDERRCODE_MASK (0xf00u) +#define FLEXSPI_STS1_AHBCMDERRCODE_SHIFT (8u) + +#define FLEXSPI_STS1_AHBCMDERRCODE(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_STS1_AHBCMDERRCODE_SHIFT)) & FLEXSPI_STS1_AHBCMDERRCODE_MASK) +#define FLEXSPI_STS1_IPCMDERRID_MASK (0xf0000u) +#define FLEXSPI_STS1_IPCMDERRID_SHIFT (16u) + +#define FLEXSPI_STS1_IPCMDERRID(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_STS1_IPCMDERRID_SHIFT)) & FLEXSPI_STS1_IPCMDERRID_MASK) +#define FLEXSPI_STS1_IPCMDERRCODE_MASK (0xf000000u) +#define FLEXSPI_STS1_IPCMDERRCODE_SHIFT (24u) + +#define FLEXSPI_STS1_IPCMDERRCODE(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_STS1_IPCMDERRCODE_SHIFT)) & FLEXSPI_STS1_IPCMDERRCODE_MASK) + +#define FLEXSPI_STS2_ASLVLOCK_MASK (0x1u) +#define FLEXSPI_STS2_ASLVLOCK_SHIFT (0u) + +#define FLEXSPI_STS2_ASLVLOCK(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_STS2_ASLVLOCK_SHIFT)) & FLEXSPI_STS2_ASLVLOCK_MASK) +#define FLEXSPI_STS2_AREFLOCK_MASK (0x2u) +#define FLEXSPI_STS2_AREFLOCK_SHIFT (1u) + +#define FLEXSPI_STS2_AREFLOCK(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_STS2_AREFLOCK_SHIFT)) & FLEXSPI_STS2_AREFLOCK_MASK) +#define FLEXSPI_STS2_ASLVSEL_MASK (0xfcu) +#define FLEXSPI_STS2_ASLVSEL_SHIFT (2u) + +#define FLEXSPI_STS2_ASLVSEL(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_STS2_ASLVSEL_SHIFT)) & FLEXSPI_STS2_ASLVSEL_MASK) +#define FLEXSPI_STS2_AREFSEL_MASK (0x3f00u) +#define FLEXSPI_STS2_AREFSEL_SHIFT (8u) + +#define FLEXSPI_STS2_AREFSEL(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_STS2_AREFSEL_SHIFT)) & FLEXSPI_STS2_AREFSEL_MASK) +#define FLEXSPI_STS2_BSLVLOCK_MASK (0x10000u) +#define FLEXSPI_STS2_BSLVLOCK_SHIFT (16u) + +#define FLEXSPI_STS2_BSLVLOCK(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_STS2_BSLVLOCK_SHIFT)) & FLEXSPI_STS2_BSLVLOCK_MASK) +#define FLEXSPI_STS2_BREFLOCK_MASK (0x20000u) +#define FLEXSPI_STS2_BREFLOCK_SHIFT (17u) + +#define FLEXSPI_STS2_BREFLOCK(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_STS2_BREFLOCK_SHIFT)) & FLEXSPI_STS2_BREFLOCK_MASK) +#define FLEXSPI_STS2_BSLVSEL_MASK (0xfc0000u) +#define FLEXSPI_STS2_BSLVSEL_SHIFT (18u) + +#define FLEXSPI_STS2_BSLVSEL(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_STS2_BSLVSEL_SHIFT)) & FLEXSPI_STS2_BSLVSEL_MASK) +#define FLEXSPI_STS2_BREFSEL_MASK (0x3f000000u) +#define FLEXSPI_STS2_BREFSEL_SHIFT (24u) + +#define FLEXSPI_STS2_BREFSEL(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_STS2_BREFSEL_SHIFT)) & FLEXSPI_STS2_BREFSEL_MASK) + +#define FLEXSPI_AHBSPNDSTS_ACTIVE_MASK (0x1u) +#define FLEXSPI_AHBSPNDSTS_ACTIVE_SHIFT (0u) + +#define FLEXSPI_AHBSPNDSTS_ACTIVE(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_AHBSPNDSTS_ACTIVE_SHIFT)) & FLEXSPI_AHBSPNDSTS_ACTIVE_MASK) +#define FLEXSPI_AHBSPNDSTS_BUFID_MASK (0xeU) +#define FLEXSPI_AHBSPNDSTS_BUFID_SHIFT (1u) + +#define FLEXSPI_AHBSPNDSTS_BUFID(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_AHBSPNDSTS_BUFID_SHIFT)) & FLEXSPI_AHBSPNDSTS_BUFID_MASK) +#define FLEXSPI_AHBSPNDSTS_DATLFT_MASK (0xffff0000u) +#define FLEXSPI_AHBSPNDSTS_DATLFT_SHIFT (16u) + +#define FLEXSPI_AHBSPNDSTS_DATLFT(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_AHBSPNDSTS_DATLFT_SHIFT)) & FLEXSPI_AHBSPNDSTS_DATLFT_MASK) + +#define FLEXSPI_IPRXFSTS_FILL_MASK (0xffu) +#define FLEXSPI_IPRXFSTS_FILL_SHIFT (0u) + +#define FLEXSPI_IPRXFSTS_FILL(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPRXFSTS_FILL_SHIFT)) & FLEXSPI_IPRXFSTS_FILL_MASK) +#define FLEXSPI_IPRXFSTS_RDCNTR_MASK (0xffff0000u) +#define FLEXSPI_IPRXFSTS_RDCNTR_SHIFT (16u) + +#define FLEXSPI_IPRXFSTS_RDCNTR(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPRXFSTS_RDCNTR_SHIFT)) & FLEXSPI_IPRXFSTS_RDCNTR_MASK) + +#define FLEXSPI_IPTXFSTS_FILL_MASK (0xffu) +#define FLEXSPI_IPTXFSTS_FILL_SHIFT (0u) + +#define FLEXSPI_IPTXFSTS_FILL(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPTXFSTS_FILL_SHIFT)) & FLEXSPI_IPTXFSTS_FILL_MASK) +#define FLEXSPI_IPTXFSTS_WRCNTR_MASK (0xffff0000u) +#define FLEXSPI_IPTXFSTS_WRCNTR_SHIFT (16u) + +#define FLEXSPI_IPTXFSTS_WRCNTR(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_IPTXFSTS_WRCNTR_SHIFT)) & FLEXSPI_IPTXFSTS_WRCNTR_MASK) + +#define FLEXSPI_RFDR_RXDATA_MASK (0xffffffffu) +#define FLEXSPI_RFDR_RXDATA_SHIFT (0u) + +#define FLEXSPI_RFDR_RXDATA(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_RFDR_RXDATA_SHIFT)) & FLEXSPI_RFDR_RXDATA_MASK) + +#define FLEXSPI_RFDR_COUNT (32u) + +#define FLEXSPI_TFDR_TXDATA_MASK (0xffffffffu) +#define FLEXSPI_TFDR_TXDATA_SHIFT (0u) + +#define FLEXSPI_TFDR_TXDATA(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_TFDR_TXDATA_SHIFT)) & FLEXSPI_TFDR_TXDATA_MASK) + +#define FLEXSPI_TFDR_COUNT (32u) + +#define FLEXSPI_LUT_COUNT (128u) + +#endif /* __ARCH_ARM_SRC_IMX9_HARDWARE_IMX9_FLEXSPI_H */ diff --git a/arch/arm64/src/imx9/imx9_flexspi.c b/arch/arm64/src/imx9/imx9_flexspi.c new file mode 100644 index 0000000000000..e68102741d398 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_flexspi.c @@ -0,0 +1,1255 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_flexspi.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "arm64_internal.h" +#include "barriers.h" + +#include "imx9_gpio.h" +#include "imx9_ccm.h" +#include "imx9_clockconfig.h" +#include "imx9_flexspi.h" +#include "imx9_iomuxc.h" +#include "hardware/imx9_ccm.h" +#include "hardware/imx9_flexspi.h" +#include "hardware/imx9_pinmux.h" + +#ifdef CONFIG_IMX9_FLEXSPI + + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* The state of the FlexSPI controller. + * + */ + +struct imx9_flexspidev_s +{ + struct flexspi_dev_s flexspi; /* Externally visible part of the FlexSPI + * interface */ + + struct flexspi_type_s *base; /* FlexSPI controller register base address */ + + bool initialized; /* TRUE: Controller has been initialized */ + + mutex_t lock; /* Assures mutually exclusive access to + * FlexSPI */ +}; + +/* FlexSPI methods */ + +static int imx9_flexspi_lock(struct flexspi_dev_s *dev, bool lock); +static int imx9_flexspi_transfer_blocking(struct flexspi_dev_s *dev, + struct flexspi_transfer_s *xfer); +static void imx9_flexspi_software_reset(struct flexspi_dev_s *dev); +static void imx9_flexspi_update_lut(struct flexspi_dev_s *dev, + uint32_t index, + const uint32_t *cmd, + uint32_t count); +static void imx9_flexspi_set_device_config(struct flexspi_dev_s *dev, + struct flexspi_device_config_s *config, + enum flexspi_port_e port); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* FlexSPI0 driver operations */ + +static const struct flexspi_ops_s g_flexspi0ops = +{ + .lock = imx9_flexspi_lock, + .transfer_blocking = imx9_flexspi_transfer_blocking, + .software_reset = imx9_flexspi_software_reset, + .update_lut = imx9_flexspi_update_lut, + .set_device_config = imx9_flexspi_set_device_config, +}; + +/* This is the overall state of the FlexSPI0 controller */ + + + +static struct imx9_flexspidev_s g_flexspi0dev = +{ + .flexspi = + { + .ops = &g_flexspi0ops, + }, + .base = (struct flexspi_type_s *)IMX9_FLEXSPI_BASE, + .lock = NXMUTEX_INITIALIZER, +}; + + +#define FREQ_1MHz (1000000ul) +#define FLEXSPI_DLLCR_DEFAULT (0x100ul) +#define FLEXSPI_LUT_KEY_VAL (0x5af05af0ul) + +enum +{ + FLEXSPI_DELAY_CELL_UNIT_MIN = 75, /* 75ps */ + + FLEXSPI_DELAY_CELL_UNIT_MAX = 225, /* 225ps */ +}; + +enum +{ + FLEXSPI_FLASH_A_SAMPLE_CLOCK_SLAVE_DELAY_LOCKED = + FLEXSPI_STS2_ASLVLOCK_MASK, /* Flash A sample clock slave delay line locked */ + + FLEXSPI_FLASH_A_SAMPLE_CLOCK_REF_DELAY_LOCKED = + FLEXSPI_STS2_AREFLOCK_MASK, /* Flash A sample clock reference delay line locked */ + + FLEXSPI_FLASH_B_SAMPLE_CLOCK_SLAVE_DELAY_LOCKED = + FLEXSPI_STS2_BSLVLOCK_MASK, /* Flash B sample clock slave delay line locked */ + + FLEXSPI_FLASH_B_SAMPLE_CLOCK_REF_DELAY_LOCKED = + FLEXSPI_STS2_BREFLOCK_MASK, /* Flash B sample clock reference delay line locked */ +}; + +/* FLEXSPI interrupt status flags */ + +enum flexspi_flags_e +{ + FLEXSPI_KEYERROR_FLAG = FLEXSPI_INTEN_KEYERROR_MASK , + + FLEXSPI_KEYDONE_FLAG = FLEXSPI_INTEN_KEYDONE_MASK, + + FLEXSPI_SEQUENCE_EXECUTION_TIMEOUT_FLAG = FLEXSPI_INTEN_SEQTIMEOUTEN_MASK, /* Sequence execution timeout */ + + FLEXSPI_AHB_BUS_ERROR_FLAG = FLEXSPI_INTEN_AHBBUSERROREN_MASK, /* AHB Bus error flag */ + + FLEXSPI_SCK_STOPPED_BECAUSE_TX_EMPTY_FLAG = + FLEXSPI_INTEN_SCKSTOPBYWREN_MASK, /* SCK is stopped during command + * sequence because Async TX FIFO empty */ + + FLEXSPI_SCK_STOPPED_BECAUSE_RX_FULL_FLAG = + FLEXSPI_INTEN_SCKSTOPBYRDEN_MASK, /* SCK is stopped during command + * sequence because Async RX FIFO full */ + + FLEXSPI_IP_TX_FIFO_WATERMARK_EMPTY_FLAG = FLEXSPI_INTEN_IPTXWEEN_MASK, /* IP TX FIFO WaterMark empty */ + + FLEXSPI_IP_RX_FIFO_WATERMARK_AVAILABLE_FLAG = FLEXSPI_INTEN_IPRXWAEN_MASK, /* IP RX FIFO WaterMark available */ + + FLEXSPI_AHB_COMMAND_SEQUENCE_ERROR_FLAG = + FLEXSPI_INTEN_AHBCMDERREN_MASK, /* AHB triggered Command Sequences Error */ + + FLEXSPI_IP_COMMAND_SEQUENCE_ERROR_FLAG = FLEXSPI_INTEN_IPCMDERREN_MASK, /* IP triggered Command Sequences Error */ + + FLEXSPI_AHB_COMMAND_GRANT_TIMEOUT_FLAG = + FLEXSPI_INTEN_AHBCMDGEEN_MASK, /* AHB triggered Command Sequences Grant Timeout */ + + FLEXSPI_IP_COMMAND_GRANT_TIMEOUT_FLAG = + FLEXSPI_INTEN_IPCMDGEEN_MASK, /* IP triggered Command Sequences Grant Timeout */ + + FLEXSPI_IP_COMMAND_EXECUTION_DONE_FLAG = + FLEXSPI_INTEN_IPCMDDONEEN_MASK, /* IP triggered Command Sequences Execution finished */ + + FLEXSPI_ALL_INTERRUPT_FLAGS = 0x3fffu, /* All flags */ +}; + +/* Common sets of flags used by the driver */ + +enum flexspi_flag_constants_e +{ + /* Errors to check for */ + + ERROR_FLAGS = FLEXSPI_SEQUENCE_EXECUTION_TIMEOUT_FLAG | + FLEXSPI_IP_COMMAND_SEQUENCE_ERROR_FLAG | + FLEXSPI_IP_COMMAND_GRANT_TIMEOUT_FLAG, +}; + +#define FLEXSPI_AHB_BUFFER_COUNT (8) + +struct flexspi_ahb_buffer_config_s +{ + uint8_t priority; /* This priority for AHB Master Read which this AHB RX Buffer is assigned */ + + uint8_t master_index; /* AHB Master ID the AHB RX Buffer is assigned */ + + uint16_t buffer_size; /* AHB buffer size in byte */ + + bool enable_prefetch; /* AHB Read Prefetch Enable for current AHB RX Buffer corresponding Master, allows + * prefetch disable/enable separately for each master */ +}; + +/* FLEXSPI configuration structure */ + +struct flexspi_config_s +{ + enum flexspi_read_sample_clock_e rx_sample_clock; /* Sample Clock source selection for Flash Reading */ + + bool enable_sck_free_running; /* Enable/disable SCK output free-running */ + + bool enable_combination; /* Enable/disable combining PORT A and B Data Pins + * (SIOA[3:0] and SIOB[3:0]) to support Flash Octal mode */ + + bool enable_doze; /* Enable/disable doze mode support */ + + bool enable_half_speed_access; /* Enable/disable divide by 2 of the clock for half + * speed commands */ + + bool enable_sckb_diff_opt; /* Enable/disable SCKB pad use as SCKA differential clock + * output, when enable, Port B flash access is not available */ + + bool enable_same_config_for_all; /* Enable/disable same configuration for all connected devices + * when enabled, same configuration in FLASHA1CRx is applied to all */ + + uint16_t seq_timeout_cycle; /* Timeout wait cycle for command sequence execution, + * timeout after ahb_grant_timeout_cyle*1024 serial root clock cycles */ + + uint8_t ip_grant_timeout_cycle; /* Timeout wait cycle for IP command grant, timeout after + * ip_grant_timeout_cycle*1024 AHB clock cycles */ + + uint8_t tx_watermark; /* FLEXSPI IP transmit watermark value */ + + uint8_t rx_watermark; /* FLEXSPI receive watermark value */ + + struct + { + bool enable_ahb_write_ip_tx_fifo; /* Enable AHB bus write access to IP TX FIFO */ + bool enable_ahb_write_ip_rx_fifo; /* Enable AHB bus write access to IP RX FIFO */ + + uint8_t ahb_grant_timeout_cycle; /* Timeout wait cycle for AHB command grant, + * timeout after ahb_grant_timeout_cyle*1024 AHB clock cycles */ + + uint16_t ahb_bus_timeout_cycle; /* Timeout wait cycle for AHB read/write access, + * timeout after ahb_bus_timeout_cycle*1024 AHB clock cycles */ + + uint8_t resume_wait_cycle; /* Wait cycle for idle state before suspended command sequence + * resume, timeout after ahb_bus_timeout_cycle AHB clock cycles */ + + struct flexspi_ahb_buffer_config_s buffer[FLEXSPI_AHB_BUFFER_COUNT]; /* AHB buffer size */ + + bool enable_clear_ahb_buffer_opt; /* Enable/disable automatically clean AHB RX Buffer and TX Buffer + * when FLEXSPI returns STOP mode ACK */ + + bool enable_read_address_opt; /* Enable/disable remove AHB read burst start address alignment limitation. + * when enable, there is no AHB read burst start address alignment limitation */ + + bool enable_ahb_prefetch; /* Enable/disable AHB read prefetch feature, when enabled, FLEXSPI + * will fetch more data than current AHB burst */ + + bool enable_ahb_bufferable; /* Enable/disable AHB bufferable write access support, when enabled, + * FLEXSPI return before waiting for command execution finished */ + + bool enable_ahb_cachable; /* Enable AHB bus cachable read access support */ + } ahb_config; +}; + +/**************************************************************************** + * Prototypes + ****************************************************************************/ + +/* Check and clear IP command execution errors. + * + * @param base FLEXSPI base pointer. + * @param status interrupt status. + */ + +static int imx9_flexspi_check_and_clear_error(struct flexspi_type_s *base, + uint32_t status); + +/**************************************************************************** + * Variables + ****************************************************************************/ + +/**************************************************************************** + * Code + ****************************************************************************/ + +/* Software reset for the FLEXSPI logic. + * + * This function sets the software reset flags for both AHB and buffer domain + * and resets both AHB buffer and also IP FIFOs. + * + * @param base FLEXSPI peripheral base address. + */ + +static inline void imx9_flexspi_software_reset_private( + struct flexspi_type_s *base) +{ + base->MCR0 |= FLEXSPI_MCR0_SWRESET_MASK; + while (0u != (base->MCR0 & FLEXSPI_MCR0_SWRESET_MASK)) + { + } +} + +/* Returns whether the bus is idle. + * + * @param base FLEXSPI peripheral base address. + * @retval true Bus is idle. + * @retval false Bus is busy. + */ + +static inline bool imx9_flexspi_get_bus_idle_status( + struct flexspi_type_s *base) +{ + return (0u != (base->STS0 & FLEXSPI_STS0_ARBIDLE_MASK)) && + (0u != (base->STS0 & FLEXSPI_STS0_SEQIDLE_MASK)); +} + +static uint32_t imx9_flexspi_configure_dll(struct flexspi_type_s *base, + struct flexspi_device_config_s *config) +{ + bool is_unified_config = true; + uint32_t flexspi_dll_value; + uint32_t dll_value; + uint32_t temp; + + uint32_t rx_sample_clock = (base->MCR0 & FLEXSPI_MCR0_RXCLKSRC_MASK) >> + FLEXSPI_MCR0_RXCLKSRC_SHIFT; + switch (rx_sample_clock) + { + case (uint32_t)FLEXSPI_READ_SAMPLE_CLK_LOOPBACK_INTERNALLY: + case (uint32_t)FLEXSPI_READ_SAMPLE_CLK_LOOPBACK_FROM_DQS_PAD: + case (uint32_t)FLEXSPI_READ_SAMPLE_CLK_LOOPBACK_FROM_SCK_PAD: + is_unified_config = true; + break; + case (uint32_t)FLEXSPI_READ_SAMPLE_CLK_EXTERNAL_INPUT_FROM_DQS_PAD: + if (config->is_sck2_enabled) + { + is_unified_config = true; + } + else + { + is_unified_config = false; + } + break; + default: + assert(false); + break; + } + + if (is_unified_config) + { + flexspi_dll_value = FLEXSPI_DLLCR_DEFAULT; /* 1 fixed delay cells in DLL delay chain */ + } + else + { + if (config->flexspi_root_clk >= 100u * FREQ_1MHz) + { + /* DLLEN = 1, SLVDLYTARGET = 0xF, */ + + flexspi_dll_value = FLEXSPI_DLLCR_DLLEN(1) | + FLEXSPI_DLLCR_SLVDLYTARGET(0x0f); + } + else + { + temp = (uint32_t)config->data_valid_time * 1000u; /* Convert data valid time in ns to ps */ + + dll_value = temp / (uint32_t)FLEXSPI_DELAY_CELL_UNIT_MIN; + if (dll_value * (uint32_t)FLEXSPI_DELAY_CELL_UNIT_MIN < temp) + { + dll_value++; + } + flexspi_dll_value = FLEXSPI_DLLCR_OVRDEN(1) | + FLEXSPI_DLLCR_OVRDVAL(dll_value); + } + } + return flexspi_dll_value; +} + +static int imx9_flexspi_check_and_clear_error(struct flexspi_type_s *base, + uint32_t status) +{ + int result = 0; + + /* Check for error */ + + status &= (uint32_t)ERROR_FLAGS; + if (0u != status) + { + /* Select the correct error code */ + + if (0u != (status & (uint32_t)FLEXSPI_SEQUENCE_EXECUTION_TIMEOUT_FLAG)) + { + result = STATUS_FLEXSPI_SEQUENCE_EXECUTION_TIMEOUT; + } + else if (0u != (status & + (uint32_t)FLEXSPI_IP_COMMAND_SEQUENCE_ERROR_FLAG)) + { + result = STATUS_FLEXSPI_IP_COMMAND_SEQUENCE_ERROR; + } + else if (0u != (status & + (uint32_t)FLEXSPI_IP_COMMAND_GRANT_TIMEOUT_FLAG)) + { + result = STATUS_FLEXSPI_IP_COMMAND_GRANT_TIMEOUT; + } + else + { + assert(false); + } + + /* Clear the flags */ + + base->INTR |= status; + + /* Reset fifos. These flags clear automatically */ + + base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK; + base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK; + } + + return result; +} + +/* Initializes the FLEXSPI module and internal state. + * + * This function enables the clock for FLEXSPI and also configures the + * FLEXSPI with the input configure parameters. Users should call this + * function before any FLEXSPI operations. + * + * param base FLEXSPI peripheral base address. + * param config FLEXSPI configure structure. + */ + +void imx9_flexspi_init(struct flexspi_type_s *base, + const struct flexspi_config_s *config) +{ + uint32_t config_value = 0; + uint8_t i = 0; + + /* Reset peripheral before configuring it */ + base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK; + imx9_flexspi_software_reset_private(base); + + /* Configure MCR0 configuration items */ + + config_value = FLEXSPI_MCR0_RXCLKSRC(config->rx_sample_clock) | + FLEXSPI_MCR0_DOZEEN(config->enable_doze) | + FLEXSPI_MCR0_IPGRANTWAIT(config->ip_grant_timeout_cycle) | + FLEXSPI_MCR0_AHBGRANTWAIT( + config->ahb_config.ahb_grant_timeout_cycle) | + FLEXSPI_MCR0_SCKFREERUNEN(config->enable_sck_free_running) | + FLEXSPI_MCR0_HSEN(config->enable_half_speed_access) | + FLEXSPI_MCR0_COMBINATIONEN(config->enable_combination) | + FLEXSPI_MCR0_ATDFEN( + config->ahb_config.enable_ahb_write_ip_tx_fifo) | + FLEXSPI_MCR0_ARDFEN( + config->ahb_config.enable_ahb_write_ip_rx_fifo) | + FLEXSPI_MCR0_MDIS_MASK; + base->MCR0 = config_value; + + /* Configure MCR1 configurations */ + + config_value = + FLEXSPI_MCR1_SEQWAIT(config->seq_timeout_cycle) | + FLEXSPI_MCR1_AHBBUSWAIT(config->ahb_config.ahb_bus_timeout_cycle); + + base->MCR1 = config_value; + + /* Configure MCR2 configurations */ + + config_value = base->MCR2; + config_value &= ~(FLEXSPI_MCR2_RESUMEWAIT_MASK | + FLEXSPI_MCR2_SCKBDIFFOPT_MASK | + FLEXSPI_MCR2_SAMEDEVICEEN_MASK | + FLEXSPI_MCR2_CLRAHBBUFOPT_MASK); + + config_value |= FLEXSPI_MCR2_RESUMEWAIT( + config->ahb_config.resume_wait_cycle) | + FLEXSPI_MCR2_SCKBDIFFOPT( + config->enable_sckb_diff_opt) | + FLEXSPI_MCR2_SAMEDEVICEEN( + config->enable_same_config_for_all) | + FLEXSPI_MCR2_CLRAHBBUFOPT( + config->ahb_config.enable_clear_ahb_buffer_opt); + + base->MCR2 = config_value; + + /* Configure AHB control items */ + + config_value = base->AHBCR; + config_value &= ~(FLEXSPI_AHBCR_READADDROPT_MASK | + FLEXSPI_AHBCR_PREFETCHEN_MASK | + FLEXSPI_AHBCR_BUFFERABLEEN_MASK | + FLEXSPI_AHBCR_CACHABLEEN_MASK); + + config_value |= FLEXSPI_AHBCR_READADDROPT( + config->ahb_config.enable_read_address_opt) | + FLEXSPI_AHBCR_PREFETCHEN( + config->ahb_config.enable_ahb_prefetch) | + FLEXSPI_AHBCR_BUFFERABLEEN( + config->ahb_config.enable_ahb_bufferable) | + FLEXSPI_AHBCR_CACHABLEEN( + config->ahb_config.enable_ahb_cachable); + + base->AHBCR = config_value; + + /* Configure AHB rx buffers */ + + for (i = 0; i < (uint32_t)FLEXSPI_AHB_BUFFER_COUNT; i++) + { + config_value = base->AHBRXBUFCR0[i]; + + config_value &= ~(FLEXSPI_AHBRXBUFCR0_PREFETCHEN_MASK | + FLEXSPI_AHBRXBUFCR0_PRIORITY_MASK | + FLEXSPI_AHBRXBUFCR0_MSTRID_MASK | + FLEXSPI_AHBRXBUFCR0_BUFSZ_MASK); + + config_value |= FLEXSPI_AHBRXBUFCR0_PREFETCHEN( + config->ahb_config.buffer[i].enable_prefetch) | + FLEXSPI_AHBRXBUFCR0_PRIORITY( + config->ahb_config.buffer[i].priority) | + FLEXSPI_AHBRXBUFCR0_MSTRID( + config->ahb_config.buffer[i].master_index) | + FLEXSPI_AHBRXBUFCR0_BUFSZ((uint32_t) + config->ahb_config.buffer[i].buffer_size / 8u); + + base->AHBRXBUFCR0[i] = config_value; + } + + /* Configure IP FIFO watermarks */ + + base->IPRXFCR &= ~FLEXSPI_IPRXFCR_RXWMRK_MASK; + base->IPRXFCR |= + FLEXSPI_IPRXFCR_RXWMRK((uint32_t)config->rx_watermark / 8u - 1u); + base->IPTXFCR &= ~FLEXSPI_IPTXFCR_TXWMRK_MASK; + base->IPTXFCR |= + FLEXSPI_IPTXFCR_TXWMRK((uint32_t)config->tx_watermark / 8u - 1u); + + /* Reset flash size on all ports */ + + for (i = 0; i < (uint32_t)FLEXSPI_PORT_COUNT; i++) + { + base->FLSHCR0[i] = 0; + } +} + +/* Gets default settings for FLEXSPI. + * + * param config FLEXSPI configuration structure. + */ + +void imx9_flexspi_get_default_config(struct flexspi_config_s *config) +{ + /* Initializes the configure structure to zero */ + + memset(config, 0, sizeof(*config)); + + config->rx_sample_clock = FLEXSPI_READ_SAMPLE_CLK_LOOPBACK_FROM_DQS_PAD; + config->enable_sck_free_running = false; + config->enable_combination = false; + config->enable_doze = true; + config->enable_half_speed_access = false; + config->enable_sckb_diff_opt = false; + config->enable_same_config_for_all = false; + config->seq_timeout_cycle = 0xffff; + config->ip_grant_timeout_cycle = 0xff; + config->tx_watermark = 8; + config->rx_watermark = 8; + config->ahb_config.enable_ahb_write_ip_tx_fifo = false; + config->ahb_config.enable_ahb_write_ip_rx_fifo = false; + config->ahb_config.ahb_grant_timeout_cycle = 0xff; + config->ahb_config.ahb_bus_timeout_cycle = 0xffff; + config->ahb_config.resume_wait_cycle = 0x20; + memset(config->ahb_config.buffer, 0, + sizeof(config->ahb_config.buffer)); + + /* Use invalid master ID 0xF and buffer size 0 for the first several + * buffers. + */ + + for (uint8_t i = 0; i < ((uint8_t)FLEXSPI_AHB_BUFFER_COUNT - 2u); i++) + { + /* Default enable AHB prefetch */ + + config->ahb_config.buffer[i].enable_prefetch = true; + + /* Invalid master index which is no used, so will never hit */ + + config->ahb_config.buffer[i].master_index = 0xf; + + /* Default buffer size 0 for buffer0 to + * buffer(FLEXSPI_AHB_BUFFER_COUNT - 3) + */ + + config->ahb_config.buffer[i].buffer_size = 0; + } + + for (uint8_t i = ((uint8_t)FLEXSPI_AHB_BUFFER_COUNT - 2); + i < (uint8_t)FLEXSPI_AHB_BUFFER_COUNT; i++) + { + config->ahb_config.buffer[i].enable_prefetch = true; /* Default enable + * AHB prefetch. + */ + + config->ahb_config.buffer[i].buffer_size = 256u; /* Default buffer + * size 256 bytes. + */ + } + + config->ahb_config.enable_clear_ahb_buffer_opt = false; + config->ahb_config.enable_read_address_opt = false; + config->ahb_config.enable_ahb_prefetch = false; + config->ahb_config.enable_ahb_bufferable = false; + config->ahb_config.enable_ahb_cachable = false; +} + +/* Configures the connected device parameter. + * + * This function configures the connected device relevant parameters, such + * as the size, command, and so on. The flash configuration value cannot have + * a default value. The user needs to configure it according to the connected + * device. + * + * param base FLEXSPI peripheral base address. + * param config Device configuration parameters. + * param port FLEXSPI Operation port. + */ + +void imx9_flexspi_set_device_config_private(struct flexspi_type_s *base, + struct flexspi_device_config_s *config, + enum flexspi_port_e port) +{ + uint32_t config_value = 0; + uint32_t status_value = 0; + uint8_t index = (uint8_t)port >> 1u; /* PortA with index 0, PortB with index 1 */ + + /* Wait for bus idle before change flash configuration */ + while (!imx9_flexspi_get_bus_idle_status(base)) + { + } + + /* Configure flash size */ + + base->FLSHCR0[port] = config->flash_size; + + /* Configure flash parameters */ + + base->FLSHCR1[port] = + FLEXSPI_FLSHCR1_CSINTERVAL(config->cs_interval) | + FLEXSPI_FLSHCR1_CSINTERVALUNIT(config->cs_interval_unit) | + FLEXSPI_FLSHCR1_TCSH(config->cs_hold_time) | + FLEXSPI_FLSHCR1_TCSS(config->cs_setup_time) | + FLEXSPI_FLSHCR1_CAS(config->columnspace) | + FLEXSPI_FLSHCR1_WA(config->enable_word_address); + + /* Configure AHB operation items */ + + config_value = base->FLSHCR2[port]; + + config_value &= ~(FLEXSPI_FLSHCR2_AWRWAITUNIT_MASK | + FLEXSPI_FLSHCR2_AWRWAIT_MASK | + FLEXSPI_FLSHCR2_AWRSEQNUM_MASK | + FLEXSPI_FLSHCR2_AWRSEQID_MASK | + FLEXSPI_FLSHCR2_ARDSEQNUM_MASK | + FLEXSPI_FLSHCR2_ARDSEQID_MASK); + + config_value |= + FLEXSPI_FLSHCR2_AWRWAITUNIT(config->ahb_write_wait_unit) | + FLEXSPI_FLSHCR2_AWRWAIT(config->ahb_write_wait_interval); + + if (config->awr_seq_number > 0u) + { + config_value |= FLEXSPI_FLSHCR2_AWRSEQID( + (uint32_t)config->awr_seq_index) | + FLEXSPI_FLSHCR2_AWRSEQNUM( + (uint32_t)config->awr_seq_number - 1u); + } + + if (config->ard_seq_number > 0u) + { + config_value |= FLEXSPI_FLSHCR2_ARDSEQID( + (uint32_t)config->ard_seq_index) | + FLEXSPI_FLSHCR2_ARDSEQNUM( + (uint32_t)config->ard_seq_number - 1u); + } + + base->FLSHCR2[port] = config_value; + + /* Configure DLL */ + + config_value = imx9_flexspi_configure_dll(base, config); + base->DLLCR[index] = config_value; + + /* Configure write mask */ + + if (config->enable_write_mask) + { + base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMOPT1_MASK; + } + else + { + base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMOPT1_MASK; + } + + if (index == 0u) /* Port A */ + { + base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENA_MASK; + base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENA(config->enable_write_mask); + } + else + { + base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENB_MASK; + base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENB(config->enable_write_mask); + } + + /* Set RX Sample Clock */ + + config_value = base->MCR0; + config_value &= ~FLEXSPI_MCR0_RXCLKSRC_MASK; + config_value |= FLEXSPI_MCR0_RXCLKSRC(config->rx_sample_clock); + + /* Exit stop mode */ + + config_value &= ~FLEXSPI_MCR0_MDIS_MASK; + + base->MCR0 = config_value; + + /* According to ERR011377, need to delay at least 100 NOPs to ensure the + * DLL is locked. + */ + + status_value = + (index == 0u) ? + ((uint32_t)FLEXSPI_FLASH_A_SAMPLE_CLOCK_SLAVE_DELAY_LOCKED | + (uint32_t)FLEXSPI_FLASH_A_SAMPLE_CLOCK_REF_DELAY_LOCKED) : + ((uint32_t)FLEXSPI_FLASH_B_SAMPLE_CLOCK_SLAVE_DELAY_LOCKED | + (uint32_t)FLEXSPI_FLASH_B_SAMPLE_CLOCK_REF_DELAY_LOCKED); + + if (0u != (config_value & FLEXSPI_DLLCR_DLLEN_MASK)) + { + /* Wait slave delay line locked and slave reference delay line locked */ + while ((base->STS2 & status_value) != status_value) + { + } + + /* Wait at least 100 NOPs */ + + for (uint8_t delay = 100u; delay > 0u; delay--) + { + asm("NOP"); + } + } +} + +/* Updates the LUT table. + * + * param base FLEXSPI peripheral base address. + * param index From which index start to update. + * It could be any index of the LUT table, which also allows + * user to update command content inside a command. Each command + * consists of up to 8 instructions and occupy 4*32-bit memory. + * param cmd Command sequence array. + * param count Number of sequences. + */ + +void imx9_flexspi_update_lut_private(struct flexspi_type_s *base, + uint32_t index, + const uint32_t *cmd, + uint32_t count) +{ + assert(index < 128u); + + uint32_t i = 0; + volatile uint32_t *lut_base; + + /* Wait for bus idle before change flash configuration */ + + while (!imx9_flexspi_get_bus_idle_status(base)) + { + } + + /* Unlock LUT for update */ + + base->LUTKEY = FLEXSPI_LUT_KEY_VAL; + base->LUTCR = 0x02; + + lut_base = &base->LUT[index]; + for (i = 0; i < count; i++) + { + *lut_base++ = *cmd++; + } + + /* Lock LUT */ + + base->LUTKEY = FLEXSPI_LUT_KEY_VAL; + base->LUTCR = 0x01; +} + +/* Sends a buffer of data bytes using blocking method. + * note This function blocks via polling until all bytes have been sent. + * param base FLEXSPI peripheral base address + * param buffer The data bytes to send + * param size The number of data bytes to send + * retval 0 write success without error + * STATUS_FLEXSPI_SEQUENCE_EXECUTION_TIMEOUT sequence execution timeout + * STATUS_FLEXSPI_IP_COMMAND_SEQUENCE_ERROR IP command sequence error + * detected + * STATUS_FLEXSPI_IP_COMMAND_GRANT_TIMEOUT IP command grant + * timeout detected. + */ + +static int imx9_flexspi_write_blocking(struct flexspi_type_s *base, + uint32_t *buffer, size_t size) +{ + uint32_t tx_watermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> + FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1u; + uint32_t status; + int result = 0; + uint32_t i = 0; + + /* Send data buffer */ + + while (0u != size) + { + /* Wait until there is room in the fifo. This also checks for errors */ + + while (0u == ((status = base->INTR) & + (uint32_t)FLEXSPI_IP_TX_FIFO_WATERMARK_EMPTY_FLAG)) + { + } + + result = imx9_flexspi_check_and_clear_error(base, status); + + if (0 != result) + { + return result; + } + + /* Write watermark level data into tx fifo */ + + if (size >= 8u * tx_watermark) + { + for (i = 0u; i < 2u * tx_watermark; i++) + { + base->TFDR[i] = *buffer++; + } + + size = size - 8u * tx_watermark; + } + else + { + for (i = 0u; i < (size / 4u + 1u); i++) + { + base->TFDR[i] = *buffer++; + } + size = 0u; + } + + /* Push a watermark level data into IP TX FIFO */ + + base->INTR |= (uint32_t)FLEXSPI_IP_TX_FIFO_WATERMARK_EMPTY_FLAG; + } + + return result; +} + +/* Receives a buffer of data bytes using a blocking method. + * note This function blocks via polling until all bytes have been sent. + * param base FLEXSPI peripheral base address + * param buffer The data bytes to send + * param size The number of data bytes to receive + * retval 0 read success without error + * retval STATUS_FLEXSPI_SEQUENCE_EXECUTION_TIMEOUT sequence execution + * timeout retval STATUS_FLEXSPI_IP_COMMAND_SEQUENCE_ERROR IP command + * sequence error detected retval STATUS_FLEXSPI_IP_COMMAND_GRANT_TIMEOUT + * IP command grant timeout detected. + */ + +static int imx9_flexspi_read_blocking(struct flexspi_type_s *base, + uint32_t *buffer, size_t size) +{ + uint32_t rx_watermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> + FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1u; + uint32_t status; + int result = 0; + uint32_t i = 0; + bool is_return = false; + + /* Send data buffer */ + + while (0u != size) + { + if (size >= 8u * rx_watermark) + { + /* Wait until there is room in the fifo. This also checks for + * errors. + */ + + while (0u == ((status = base->INTR) & + (uint32_t)FLEXSPI_IP_RX_FIFO_WATERMARK_AVAILABLE_FLAG)) + { + result = imx9_flexspi_check_and_clear_error(base, status); + + if (0 != result) + { + is_return = true; + break; + } + } + } + else + { + /* Wait fill level. This also checks for errors */ + + while (size > ((((base->IPRXFSTS) & FLEXSPI_IPRXFSTS_FILL_MASK) >> + FLEXSPI_IPRXFSTS_FILL_SHIFT) * 8u)) + { + result = imx9_flexspi_check_and_clear_error(base, base->INTR); + + if (0 != result) + { + is_return = true; + break; + } + } + } + + if (is_return) + { + break; + } + + result = imx9_flexspi_check_and_clear_error(base, base->INTR); + + if (0 != result) + { + break; + } + + /* Read watermark level data from rx fifo */ + + if (size >= 8u * rx_watermark) + { + for (i = 0u; i < 2u * rx_watermark; i++) + { + *buffer++ = base->RFDR[i]; + } + + size = size - 8u * rx_watermark; + } + else + { + for (i = 0u; i < ((size + 3u) / 4u); i++) + { + *buffer++ = base->RFDR[i]; + } + size = 0; + } + + /* Pop out a watermark level datas from IP RX FIFO */ + + base->INTR |= (uint32_t)FLEXSPI_IP_RX_FIFO_WATERMARK_AVAILABLE_FLAG; + } + + return result; +} + +/* Brief Execute command to transfer a buffer data bytes using a blocking + * method. param base FLEXSPI peripheral base address param xfer pointer to + * the transfer structure. retval 0 command transfer success without error + * retval STATUS_FLEXSPI_SEQUENCE_EXECUTION_TIMEOUT sequence execution + * timeout retval STATUS_FLEXSPI_IP_COMMAND_SEQUENCE_ERROR IP command + * sequence error detected retval STATUS_FLEXSPI_IP_COMMAND_GRANT_TIMEOUT + * IP command grant timeout detected. + */ + +int imx9_flexspi_transfer_blocking_private(struct flexspi_type_s *base, + struct flexspi_transfer_s *xfer) +{ + uint32_t config_value = 0; + int result = 0; + + /* Clear sequence pointer before sending data to external devices */ + + base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK; + + /* Clear former pending status before start this transfer */ + + base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | + FLEXSPI_INTR_IPCMDERR_MASK | + FLEXSPI_INTR_AHBCMDGE_MASK | + FLEXSPI_INTR_IPCMDGE_MASK; + + /* Configure base address */ + + base->IPCR0 = xfer->device_address; + + /* Reset fifos */ + + base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK; + base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK; + + /* Configure data size */ + + if ((xfer->cmd_type == FLEXSPI_READ) || + (xfer->cmd_type == FLEXSPI_WRITE) || + (xfer->cmd_type == FLEXSPI_CONFIG)) + { + config_value = FLEXSPI_IPCR1_IDATSZ(xfer->data_size); + } + + /* Configure sequence ID */ + + config_value |= + FLEXSPI_IPCR1_ISEQID((uint32_t)xfer->seq_index) | \ + FLEXSPI_IPCR1_ISEQNUM((uint32_t)xfer->seq_number - 1u); + base->IPCR1 = config_value; + + /* Start Transfer */ + + base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK; + + if ((xfer->cmd_type == FLEXSPI_WRITE) || + (xfer->cmd_type == FLEXSPI_CONFIG)) + { + result = imx9_flexspi_write_blocking(base, xfer->data, + xfer->data_size); + } + else if (xfer->cmd_type == FLEXSPI_READ) + { + result = imx9_flexspi_read_blocking(base, xfer->data, + xfer->data_size); + } + + /* Wait for bus idle */ + + while (!imx9_flexspi_get_bus_idle_status(base)) + { + } + + if (xfer->cmd_type == FLEXSPI_COMMAND) + { + result = imx9_flexspi_check_and_clear_error(base, base->INTR); + } + + return result; +} + +/**************************************************************************** + * Name: imx9_flexspi_lock + * + * Description: + * On FlexSPI buses where there are multiple devices, it will be necessary + * to lock FlexSPI to have exclusive access to the buses for a sequence of + * transfers. The bus should be locked before the chip is selected. + * + * Input Parameters: + * dev - Device-specific state data + * lock - true: Lock FlexSPI bus, false: unlock FlexSPI bus + * + * Returned Value: + * Semaphore status + * + ****************************************************************************/ + +static int imx9_flexspi_lock(struct flexspi_dev_s *dev, bool lock) +{ + struct imx9_flexspidev_s *priv = (struct imx9_flexspidev_s *)dev; + int ret; + + spiinfo("lock=%d\n", lock); + if (lock) + { + ret = nxmutex_lock(&priv->lock); + } + else + { + ret = nxmutex_unlock(&priv->lock); + } + + return ret; +} + +/**************************************************************************** + * Name: imx9_flexspi_transfer_blocking + * + * Description: + * Perform one FlexSPI transfer + * + * Input Parameters: + * dev - Device-specific state data + * xfer - Describes the transfer to be performed. + * + * Returned Value: + * 0 on SUCCESS, STATUS_FLEXSPI_SEQUENCE_EXECUTION_TIMEOUT, + * STATUS_FLEXSPI_IP_COMMAND_SEQUENCE_ERROR or + * STATUS_FLEXSPI_IP_COMMAND_GRANT_TIMEOUT otherwise + * + ****************************************************************************/ + +static int imx9_flexspi_transfer_blocking(struct flexspi_dev_s *dev, + struct flexspi_transfer_s *xfer) +{ + struct imx9_flexspidev_s *priv = (struct imx9_flexspidev_s *)dev; + + return (int)imx9_flexspi_transfer_blocking_private(priv->base, xfer); +} + +/**************************************************************************** + * Name: imx9_flexspi_software_reset + * + * Description: + * Performs a software reset of FlexSPI + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void imx9_flexspi_software_reset(struct flexspi_dev_s *dev) +{ + struct imx9_flexspidev_s *priv = (struct imx9_flexspidev_s *)dev; + + imx9_flexspi_software_reset_private(priv->base); +} + +/**************************************************************************** + * Name: imx9_flexspi_update_lut + * + * Description: + * Perform FlexSPI LUT table update + * + * Input Parameters: + * dev - Device-specific state data + * index - Index start to update + * cmd - Command array + * count - Size of the array + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void imx9_flexspi_update_lut(struct flexspi_dev_s *dev, + uint32_t index, + const uint32_t *cmd, + uint32_t count) +{ + struct imx9_flexspidev_s *priv = (struct imx9_flexspidev_s *)dev; + + imx9_flexspi_update_lut_private(priv->base, index, cmd, count); +} + +/**************************************************************************** + * Name: imx9_flexspi_set_device_config + * + * Description: + * Perform FlexSPI device config + * + * Input Parameters: + * dev - Device-specific state data + * config - Config data for external device + * port - Port + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void imx9_flexspi_set_device_config(struct flexspi_dev_s *dev, + struct flexspi_device_config_s *config, + enum flexspi_port_e port) +{ + struct imx9_flexspidev_s *priv = (struct imx9_flexspidev_s *)dev; + + imx9_flexspi_set_device_config_private(priv->base, config, port); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_flexspi_initialize + * + * Description: + * Initialize the selected FlexSPI port in master mode + * + * Input Parameters: + * intf - Interface number(must be zero) + * + * Returned Value: + * Valid FlexSPI device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct flexspi_dev_s *imx9_flexspi_initialize(int intf) +{ + struct imx9_flexspidev_s *priv; + struct flexspi_config_s flexspi_config; + + /* The supported i.MX9 parts have only a single FlexSPI port. */ + DEBUGASSERT(intf == 0); + + if (intf != 0) + { + return NULL; + } + + /* If this function is called multiple times, the following operations + * will be performed multiple times. + */ + + /* Select FlexSPI */ + priv = &g_flexspi0dev; + + /* Enable clocking to the FlexSPI peripheral */ + imx9_ccm_gate_on(CCM_LPCG_FLEXSPI1, true); + /* Configure clock to safe 50MHz, src clock is 800Mhz*/ + imx9_ccm_configure_root_clock(CCM_CR_FLEXSPI1, SYS_PLL1PFD1, 16); + + /* Has the FlexSPI hardware been initialized? */ + if (!priv->initialized) + { + /* Perform hardware initialization. Puts the FlexSPI into an active + * state. + */ + + imx9_flexspi_get_default_config(&flexspi_config); + imx9_flexspi_init(priv->base, &flexspi_config); + + /* Enable interrupts at the NVIC */ + priv->initialized = true; + } + + return &priv->flexspi; +} + +#endif /* CONFIG_IMX9_FLEXSPI */ diff --git a/arch/arm64/src/imx9/imx9_flexspi.h b/arch/arm64/src/imx9/imx9_flexspi.h new file mode 100644 index 0000000000000..abf9bb665cf23 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_flexspi.h @@ -0,0 +1,574 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_flexspi.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_IMX9_FLEXSPI_H +#define __ARCH_ARM64_SRC_IMX9_IMX9_FLEXSPI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "chip.h" + + +#ifdef CONFIG_IMX9_FLEXSPI + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* LUT - LUT 0..LUT 63 */ + +#define FLEXSPI_LUT_OPERAND0_MASK (0xffU) +#define FLEXSPI_LUT_OPERAND0_SHIFT (0U) + +/* OPERAND0 */ + +#define FLEXSPI_LUT_OPERAND0(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUT_OPERAND0_SHIFT)) & FLEXSPI_LUT_OPERAND0_MASK) +#define FLEXSPI_LUT_NUM_PADS0_MASK (0x300U) +#define FLEXSPI_LUT_NUM_PADS0_SHIFT (8U) + +/* NUM_PADS0 */ + +#define FLEXSPI_LUT_NUM_PADS0(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUT_NUM_PADS0_SHIFT)) & FLEXSPI_LUT_NUM_PADS0_MASK) +#define FLEXSPI_LUT_OPCODE0_MASK (0xfc00U) +#define FLEXSPI_LUT_OPCODE0_SHIFT (10U) + +/* OPCODE0 */ + +#define FLEXSPI_LUT_OPCODE0(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUT_OPCODE0_SHIFT)) & FLEXSPI_LUT_OPCODE0_MASK) +#define FLEXSPI_LUT_OPERAND1_MASK (0xff0000U) +#define FLEXSPI_LUT_OPERAND1_SHIFT (16U) + +/* OPERAND1 */ + +#define FLEXSPI_LUT_OPERAND1(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUT_OPERAND1_SHIFT)) & FLEXSPI_LUT_OPERAND1_MASK) +#define FLEXSPI_LUT_NUM_PADS1_MASK (0x3000000U) +#define FLEXSPI_LUT_NUM_PADS1_SHIFT (24U) + +/* NUM_PADS1 - NUM_PADS1 */ + +#define FLEXSPI_LUT_NUM_PADS1(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUT_NUM_PADS1_SHIFT)) & FLEXSPI_LUT_NUM_PADS1_MASK) +#define FLEXSPI_LUT_OPCODE1_MASK (0xfc000000U) +#define FLEXSPI_LUT_OPCODE1_SHIFT (26U) + +/* OPCODE1 */ + +#define FLEXSPI_LUT_OPCODE1(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUT_OPCODE1_SHIFT)) & FLEXSPI_LUT_OPCODE1_MASK) + +/* Formula to form FLEXSPI instructions in LUT table */ + +#define FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) \ + (FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | \ + FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) | \ + FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1)) + +/* Access macros ************************************************************/ + +/**************************************************************************** + * Name: FLEXSPI_LOCK + * + * Description: + * On FlexSPI buses where there are multiple devices, it will be necessary + * to lock FlexSPI to have exclusive access to the buses for a sequence of + * transfers. The bus should be locked before the chip is selected. + * + * Input Parameters: + * dev - Device-specific state data + * lock - true: Lock FlexSPI bus, false: unlock FlexSPI bus + * + * Returned Value: + * None + * + ****************************************************************************/ + +#define FLEXSPI_LOCK(d,l) (d)->ops->lock(d,l) + +/**************************************************************************** + * Name: FLEXSPI_TRANSFER + * + * Description: + * Perform one FlexSPI transfer + * + * Input Parameters: + * dev - Device-specific state data + * xfer - Describes the transfer to be performed. + * + * Returned Value: + * 0 on SUCCESS, STATUS_FLEXSPI_SEQUENCE_EXECUTION_TIMEOUT, + * STATUS_FLEXSPI_IP_COMMAND_SEQUENCE_ERROR or + * STATUS_FLEXSPI_IP_COMMAND_GRANT_TIMEOUT otherwise + * + ****************************************************************************/ + +#define FLEXSPI_TRANSFER(d,x) (d)->ops->transfer_blocking(d,x) + +/**************************************************************************** + * Name: FLEXSPI_SOFTWARE_RESET + * + * Description: + * Perform FlexSPI software reset + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * none + * + ****************************************************************************/ + +#define FLEXSPI_SOFTWARE_RESET(d) (d)->ops->software_reset(d) + +/**************************************************************************** + * Name: FLEXSPI_UPDATE_LUT + * + * Description: + * Perform FlexSPI LUT table update + * + * Input Parameters: + * dev - Device-specific state data + * index - Index start to update + * cmd - Command array + * count - Size of the array + * + * Returned Value: + * none + * + ****************************************************************************/ + +#define FLEXSPI_UPDATE_LUT(d,i,c,n) (d)->ops->update_lut(d,i,c,n) + +/**************************************************************************** + * Name: FLEXSPI_SET_DEVICE_CONFIG + * + * Description: + * Perform FlexSPI device config + * + * Input Parameters: + * dev - Device-specific state data + * config - Config data for external device + * port - Port + * + * Returned Value: + * none + * + ****************************************************************************/ + +#define FLEXSPI_SET_DEVICE_CONFIG(d,c,p) (d)->ops->set_device_config(d,c,p) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* CMD definition of FLEXSPI, use to form LUT instruction, flexspi_command */ + +enum +{ + FLEXSPI_COMMAND_STOP = 0x00, /* Stop execution, deassert CS */ + FLEXSPI_COMMAND_SDR = 0x01, /* Transmit Command code to Flash, + * using SDR mode. + */ + + FLEXSPI_COMMAND_RADDR_SDR = 0x02, /* Transmit Row Address to Flash, + * using SDR mode. + */ + + FLEXSPI_COMMAND_CADDR_SDR = 0x03, /* Transmit Column Address to + * Flash, using SDR mode. + */ + + FLEXSPI_COMMAND_MODE1_SDR = 0x04, /* Transmit 1-bit Mode bits to + * Flash, using SDR mode. + */ + + FLEXSPI_COMMAND_MODE2_SDR = 0x05, /* Transmit 2-bit Mode bits to + * Flash, using SDR mode. + */ + + FLEXSPI_COMMAND_MODE4_SDR = 0x06, /* Transmit 4-bit Mode bits to + * Flash, using SDR mode. + */ + + FLEXSPI_COMMAND_MODE8_SDR = 0x07, /* Transmit 8-bit Mode bits to + * Flash, using SDR mode. + */ + + FLEXSPI_COMMAND_WRITE_SDR = 0x08, /* Transmit Programming Data to + * Flash, using SDR mode. + */ + + FLEXSPI_COMMAND_READ_SDR = 0x09, /* Receive Read Data from Flash, + * using SDR mode. + */ + + FLEXSPI_COMMAND_LEARN_SDR = 0x0a, /* Receive Read Data or Preamble + * bit from Flash, SDR mode. + */ + + FLEXSPI_COMMAND_DATSZ_SDR = 0x0b, /* Transmit Read/Program Data size + * (byte) to Flash, SDR mode. + */ + + FLEXSPI_COMMAND_DUMMY_SDR = 0x0c, /* Leave data lines undriven by + * FlexSPI controller. + */ + + FLEXSPI_COMMAND_DUMMY_RWDS_SDR = 0x0d, /* Leave data lines undriven by + * FlexSPI controller, dummy cycles + * decided by RWDS. + */ + + FLEXSPI_COMMAND_DDR = 0x21, /* Transmit Command code to Flash, + * using DDR mode. + */ + + FLEXSPI_COMMAND_RADDR_DDR = 0x22, /* Transmit Row Address to Flash, + * using DDR mode. + */ + + FLEXSPI_COMMAND_CADDR_DDR = 0x23, /* Transmit Column Address to + * Flash, using DDR mode. + */ + + FLEXSPI_COMMAND_MODE1_DDR = 0x24, /* Transmit 1-bit Mode bits to + * Flash, using DDR mode. + */ + + FLEXSPI_COMMAND_MODE2_DDR = 0x25, /* Transmit 2-bit Mode bits to + * Flash, using DDR mode. + */ + + FLEXSPI_COMMAND_MODE4_DDR = 0x26, /* Transmit 4-bit Mode bits to + * Flash, using DDR mode. + */ + + FLEXSPI_COMMAND_MODE8_DDR = 0x27, /* Transmit 8-bit Mode bits to + * Flash, using DDR mode. + */ + + FLEXSPI_COMMAND_WRITE_DDR = 0x28, /* Transmit Programming Data to + * Flash, using DDR mode. + */ + + FLEXSPI_COMMAND_READ_DDR = 0x29, /* Receive Read Data from Flash, + * using DDR mode. + */ + + FLEXSPI_COMMAND_LEARN_DDR = 0x2a, /* Receive Read Data or Preamble + * bit from Flash, DDR mode. + */ + + FLEXSPI_COMMAND_DATSZ_DDR = 0x2b, /* Transmit Read/Program Data size + * (byte) to Flash, DDR mode. + */ + + FLEXSPI_COMMAND_DUMMY_DDR = 0x2c, /* Leave data lines undriven by + * FlexSPI controller. + */ + + FLEXSPI_COMMAND_DUMMY_RWDS_DDR = 0x2d, /* Leave data lines undriven by + * FlexSPI controller, dummy cycles + * decided by RWDS. + */ + + FLEXSPI_COMMAND_JUMP_ON_CS = 0x1f, /* Stop execution, deassert CS and + * save operand[7:0] as the + * instruction start pointer for + * next sequence + */ +}; + +/* Pad definition of FLEXSPI, use to form LUT instruction */ + +enum flexspi_pad_e +{ + FLEXSPI_1PAD = 0x00, /* Transmit command/address and transmit/receive data + * only through DATA0/DATA1. + */ + + FLEXSPI_2PAD = 0x01, /* Transmit command/address and transmit/receive data + * only through DATA[1:0]. + */ + + FLEXSPI_4PAD = 0x02, /* Transmit command/address and transmit/receive data + * only through DATA[3:0]. + */ + + FLEXSPI_8PAD = 0x03, /* Transmit command/address and transmit/receive data + * only through DATA[7:0]. + */ +}; + +/* FLEXSPI operation port select */ + +enum flexspi_port_e +{ + FLEXSPI_PORT_A1 = 0x0, /* Access flash on A1 port */ + FLEXSPI_PORT_A2, /* Access flash on A2 port */ + FLEXSPI_PORT_B1, /* Access flash on B1 port */ + FLEXSPI_PORT_B2, /* Access flash on B2 port */ + FLEXSPI_PORT_COUNT +}; + +/* Command type */ + +enum flexspi_command_type_e +{ + FLEXSPI_COMMAND, /* FlexSPI operation: Only command, both TX and Rx buffer + * are ignored. + */ + + FLEXSPI_CONFIG, /* FlexSPI operation: Configure device mode, the TX fifo + * size is fixed in LUT. + */ + + FLEXSPI_READ, /* FlexSPI operation: Read, only Rx Buffer is + * effective. + */ + + FLEXSPI_WRITE, /* FlexSPI operation: Read, only Tx Buffer is + * effective. + */ +}; + +/* Status structure of FLEXSPI */ + +enum +{ + STATUS_FLEXSPI_BUSY = 0, /* FLEXSPI is busy */ + + STATUS_FLEXSPI_SEQUENCE_EXECUTION_TIMEOUT = 1, /* Sequence execution + * timeout error occurred + * during FLEXSPI transfer. + */ + + STATUS_FLEXSPI_IP_COMMAND_SEQUENCE_ERROR = 2, /* IP command Sequence + * execution timeout error + * occurred during FLEXSPI + * transfer. + */ + + STATUS_FLEXSPI_IP_COMMAND_GRANT_TIMEOUT = 3, /* IP command grant timeout + * error occurred during + * FLEXSPI transfer. + */ +}; + +/* Transfer structure for FLEXSPI */ + +struct flexspi_transfer_s +{ + uint32_t device_address; /* Operation device address */ + enum flexspi_port_e port; /* Operation port */ + enum flexspi_command_type_e cmd_type; /* Execution command type */ + uint8_t seq_index; /* Sequence ID for command */ + uint8_t seq_number; /* Sequence number for command */ + uint32_t *data; /* Data buffer */ + size_t data_size; /* Data size in bytes */ +}; + +/* FLEXSPI interval unit for flash device select */ + +enum flexspi_cs_interval_cycle_unit_e +{ + FLEXSPI_CS_INTERVAL_UNIT1_SCK_CYCLE = 0x0, /* Chip selection interval: + * CSINTERVAL * 1 serial + * clock cycle. + */ + + FLEXSPI_CS_INTERVAL_UNIT256_SCK_CYCLE = 0x1, /* Chip selection interval: + * CSINTERVAL * 256 serial + * clock cycle. + */ +}; + +/* FLEXSPI AHB wait interval unit for writing */ + +enum flexspi_ahb_write_wait_unit_e +{ + FLEXSPI_AHB_WRITE_WAIT_UNIT2_AHB_CYCLE = 0x0, /* AWRWAIT unit is 2 + * ahb clock cycle. + */ + + FLEXSPI_AHB_WRITE_WAIT_UNIT8_AHB_CYCLE = 0x1, /* AWRWAIT unit is 8 + * ahb clock cycle. + */ + + FLEXSPI_AHB_WRITE_WAIT_UNIT32_AHB_CYCLE = 0x2, /* AWRWAIT unit is 32 + * ahb clock cycle. + */ + + FLEXSPI_AHB_WRITE_WAIT_UNIT128_AHB_CYCLE = 0x3, /* AWRWAIT unit is 128 + * ahb clock cycle. + */ + + FLEXSPI_AHB_WRITE_WAIT_UNIT512_AHB_CYCLE = 0x4, /* AWRWAIT unit is 512 + * ahb clock cycle. + */ + + FLEXSPI_AHB_WRITE_WAIT_UNIT2048_AHB_CYCLE = 0x5, /* AWRWAIT unit is 2048 + * ahb clock cycle. + */ + + FLEXSPI_AHB_WRITE_WAIT_UNIT8192_AHB_CYCLE = 0x6, /* AWRWAIT unit is 8192 + * ahb clock cycle. + */ + + FLEXSPI_AHB_WRITE_WAIT_UNIT32768_AHB_CYCLE = 0x7, /* AWRWAIT unit is 32768 + * ahb clock cycle. + */ +}; + +/* FLEXSPI sample clock source selection for Flash Reading */ + +enum flexspi_read_sample_clock_e +{ + FLEXSPI_READ_SAMPLE_CLK_LOOPBACK_INTERNALLY = 0x0u, /* Dummy Read strobe generated by FlexSPI Controller + * and loopback internally */ + + FLEXSPI_READ_SAMPLE_CLK_LOOPBACK_FROM_DQS_PAD = 0x1u, /* Dummy Read strobe generated by FlexSPI Controller + * and loopback from DQS pad */ + + FLEXSPI_READ_SAMPLE_CLK_LOOPBACK_FROM_SCK_PAD = 0x2u, /* SCK output clock and loopback from SCK pad */ + + FLEXSPI_READ_SAMPLE_CLK_EXTERNAL_INPUT_FROM_DQS_PAD = 0x3u, /* Flash provided Read strobe and input from DQS pad */ +}; + +/* External device configuration items */ + +struct flexspi_device_config_s +{ + uint32_t flexspi_root_clk; /* FLEXSPI serial root clock */ + bool is_sck2_enabled; /* FLEXSPI use SCK2 */ + uint32_t flash_size; /* Flash size in KByte */ + + enum flexspi_cs_interval_cycle_unit_e cs_interval_unit; /* CS interval unit, 1 + * or 256 cycle. + */ + + uint16_t cs_interval; /* CS line assert interval, multiply CS + * interval unit to get the CS line assert + * interval cycles. + */ + + uint8_t cs_hold_time; /* CS line hold time */ + uint8_t cs_setup_time; /* CS line setup time */ + uint8_t data_valid_time; /* Data valid time for external device */ + uint8_t columnspace; /* Column space size */ + bool enable_word_address; /* If enable word address */ + uint8_t awr_seq_index; /* Sequence ID for AHB write command */ + uint8_t awr_seq_number; /* Sequence number for AHB write command */ + uint8_t ard_seq_index; /* Sequence ID for AHB read command */ + uint8_t ard_seq_number; /* Sequence number for AHB read command */ + + enum flexspi_ahb_write_wait_unit_e ahb_write_wait_unit; /* AHB write wait unit */ + + uint16_t ahb_write_wait_interval; /* AHB write wait interval, multiply AHB + * write interval unit to get the AHB + * write wait cycles. + */ + + bool enable_write_mask; /* Enable/Disable FLEXSPI drive DQS pin as write mask + * when writing to external device. + */ + + enum flexspi_read_sample_clock_e rx_sample_clock; /* Sample Clock source selection for Flash Reading */ +}; + +/* The FlexSPI vtable */ + +struct flexspi_dev_s; +struct flexspi_ops_s +{ + int (*lock)(struct flexspi_dev_s *dev, bool lock); + int (*transfer_blocking)(struct flexspi_dev_s *dev, + struct flexspi_transfer_s *xfer); + void (*software_reset)(struct flexspi_dev_s *dev); + void (*update_lut)(struct flexspi_dev_s *dev, + uint32_t index, const uint32_t *cmd, + uint32_t count); + void (*set_device_config)(struct flexspi_dev_s *dev, + struct flexspi_device_config_s *config, + enum flexspi_port_e port); +}; + +/* FlexSPI private data. This structure only defines the initial fields of + * the structure visible to the FlexSPI client. The specific implementation + * may add additional, device specific fields + */ + +struct flexspi_dev_s +{ + const struct flexspi_ops_s *ops; +}; + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_flexspi_initialize + * + * Description: + * Initialize the selected FlexSPI port in master mode + * + * Input Parameters: + * intf - Interface number(must be zero) + * + * Returned Value: + * Valid FlexSPI device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct flexspi_dev_s; +struct flexspi_dev_s *imx9_flexspi_initialize(int intf); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_IMX9_FLEXSPI */ +#endif /* __ARCH_ARM_SRC_IMX9_IMX9_FLEXSPI_H */