77f0bea7创建于 4月21日历史提交
/****************************************************************************
 * arch/arm/src/imxrt/imxrt_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_ARM_SRC_IMXRT_IMXRT_FLEXSPI_H
#define __ARCH_ARM_SRC_IMXRT_IMXRT_FLEXSPI_H

/****************************************************************************
 * Included Files
 ****************************************************************************/

#include <nuttx/config.h>

#include <stdint.h>
#include <stdbool.h>

#include "chip.h"
#include "imxrt_config.h"

#ifdef CONFIG_IMXRT_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: imxrt_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 *imxrt_flexspi_initialize(int intf);

#undef EXTERN
#if defined(__cplusplus)
}
#endif

#endif /* __ASSEMBLY__ */
#endif /* CONFIG_IMXRT_FLEXSPI */
#endif /* __ARCH_ARM_SRC_IMXRT_IMXRT_FLEXSPI_H */