123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- /*
- * Copyright (c) 2012, Freescale Semiconductor, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * o Redistributions of source code must retain the above copyright notice, this list
- * of conditions and the following disclaimer.
- *
- * o Redistributions in binary form must reproduce the above copyright notice, this
- * list of conditions and the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- *
- * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #if !defined(__gpmi_h_)
- #define __gpmi_h_
- #include "sdk.h"
- #include "bch_ecc.h"
- /*!
- * @file gpmi.h
- * @brief The header file that contains the general definitions for NAND
- *
- * @ingroup diag_nand
- */
- //! @addtogroup diag_nand
- //! @{
- #pragma pack(1)
- //! @brief NAND timings for setting up the GPMI timing.
- //!
- //! This structure holds the timings for the NAND. This data is used by
- //! gpmi_set_timings() to setup the GPMI hardware registers.
- typedef struct GpmiNandTimings
- {
- //! @brief The data setup time (tDS), in nanoseconds.
- uint8_t tDS;
- //! @brief The data hold time (tDH), in nanoseconds.
- uint8_t tDH;
- //! @brief The address setup time (tSU), in nanoseconds.
- //!
- //! This value amalgamates the NAND parameters tCLS, tCS, and tALS.
- uint8_t tSU;
- //! @brief From the NAND datasheet.
- uint8_t tREA;
- //! @brief From the NAND datasheet.
- //!
- //! This is the amount of time that the last contents of the data lines will persist
- //! after the controller drives the -RE signal true.
- //!
- //! EDO Mode: This time is from the NAND spec, and the persistence of data
- //! is determined by (tRLOH + tDH).
- //!
- //! Non-EDO Mode: This time is ignored, because the persistence of data
- //! is determined by tRHOH.
- uint8_t tRLOH;
- //! @brief From the NAND datasheet.
- //!
- //! This is the amount of time that the last contents of the data lines will persist after the
- //! controller drives the -RE signal false.
- //!
- //! EDO Mode: This time is ignored, because the persistence of data is determined by
- //! (tRLOH + tDH).
- //!
- //! Non-EDO Mode: This time is totally due to capacitive effects of the hardware. For reliable
- //! behavior it should be set to zero, unless there is specific knowledge of the trace
- //! capacitance and the persistence of the data values.
- uint8_t tRHOH;
- } GpmiNandTimings_t;
- #pragma pack()
- // Forward declaration.
- typedef struct _apbh_dma_t apbh_dma_t;
- //! @brief DMA wait options.
- //!
- //! These mask values are combined together to form the wait mask that is passed to gpmi_run_dma().
- //! The wait mask indicates which IRQs must fire before the DMA is considered done executing.
- enum _nand_gpmi_dma_wait_mask {
- kNandGpmiDmaWaitMask_Nothing = 0, //!< Do not wait.
- kNandGpmiDmaWaitMask_GpmiDma = 1, //!< Wait for the APBH DMA completion IRQ.
- kNandGpmiDmaWaitMask_Ecc = 2, //!< Wait for the BCH completion IRQ.
- };
- //! @brief APBH DMA channel for GPMI chip select 0.
- #define NAND0_APBH_CH (0)
- //! @brief Number of NAND chip selects supported by this chip.
- //!
- //! This is also implicitly the number of DMA channels in the APBH.
- #define GPMI_CHIP_SELECT_COUNT (4)
- //! @name Error codes
- //@{
- #if !defined(SUCCESS)
- #define SUCCESS (0)
- #endif
- #define ERROR_DDI_NAND_GPMI_NOT_PRESENT (1)
- #define ERROR_DDI_NAND_GPMI_DMA_TIMEOUT (2)
- #define ERROR_DDI_NAND_GPMI_DMA_BUSY (3)
- #define ERROR_DDI_NAND_GPMI_UNCORRECTABLE_ECC (4)
- #define ERROR_DDI_NAND_HAL_WRITE_FAILED (5)
- //@}
- ////////////////////////////////////////////////////////////////////////////////
- // Prototypes
- ////////////////////////////////////////////////////////////////////////////////
- #ifdef __cplusplus
- extern "C" {
- #endif
- //! @name Init and shutdown
- //@{
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Enable and initialize the GPMI driver.
- //!
- //! This function configures the GPMI block using the HW registers based upon
- //! the desired chip and the number of bits. You must call this API for each
- //! chip select that will be used in the application configuration.
- //!
- //! @param[in] minDelay Minimum signal propagation delay in nanoseconds. Pass 0 to use the
- //! default of 5 ns.
- //! @param[in] maxDelay Maximum signal propagation delay in nanoseconds. Pass 0 to use the
- //! default of 9 ns.
- //!
- //! @return SUCCESS
- //! @return ERROR_DDI_NAND_GPMI_NOT_PRESENT
- ////////////////////////////////////////////////////////////////////////////////
- int gpmi_init(uint32_t minDelay, uint32_t maxDelay);
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Resets the GPMI block.
- //!
- //! A soft reset can take multiple clocks to complete, so do NOT gate the
- //! clock when setting soft reset. The reset process will gate the clock
- //! automatically. Poll until this has happened before subsequently
- //! clearing soft reset and clock gate.
- ////////////////////////////////////////////////////////////////////////////////
- void gpmi_soft_reset(void);
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Disable the GPMI driver.
- //!
- //! This function gates the clock to the GPMI peripheral.
- ////////////////////////////////////////////////////////////////////////////////
- void gpmi_disable(void);
- //@}
- //! @name Write enable
- //@{
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Enable writes via the Write Protect line of the NAND.
- //!
- //! Enable or disable writes via the /WP pin of the NAND. This WP line is
- //! shared amongst all the NANDs.
- //!
- //! @param[in] doEnable Enable writes (1) or Disable writes (0) (/WP pin)
- ////////////////////////////////////////////////////////////////////////////////
- void gpmi_enable_writes(bool doEnable);
- //@}
- //! @name DMA Utilities
- //@{
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Synchronously execute a DMA descriptor chain.
- //!
- //! Starts a NAND DMA command associated with the chip select
- //! in the @a chipSelect parameter. Once the DMA is running, this function waits
- //! for the interrupt handler(s) to signal completion.
- //!
- //! @param[in] theDma Pointer to dma command structure. Must be the virtual address,
- //! as it is converted to a physical address before the DMA is started.
- //! @param[in] chipSelect Which NAND chip select should be started.
- //! @param[in] waitMask A bitmask used to indicate criteria for terminating the DMA.
- //! See #_nand_gpmi_dma_wait_mask for more info.
- //! @param[in] timeout Number of microseconds to wait before timing out. If
- //! zero is passed for the timeout, then this function will wait forever.
- //!
- //! @retval SUCCESS The DMA is started.
- //! @retval ERROR_DDI_NAND_GPMI_DMA_BUSY Another DMA is already running.
- //! @retval ERROR_DDI_NAND_GPMI_DMA_TIMEOUT DMA never completed or is still
- //! running. This value is returned explicitly from this function when
- //! the DMA semphore times out, and most DMA chains also return this
- //! error (see below for how) when the GPMI device busy timeout expires.
- //!
- //! @note Uses the BAR field of the last DMA command to signal
- //! result of the DMA chain.
- ////////////////////////////////////////////////////////////////////////////////
- int gpmi_run_dma(apbh_dma_t * theDma, unsigned chipSelect, uint16_t waitMask, uint32_t timeout);
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Returns a Boolean indicating if a DMA is currently running.
- //!
- //! @param u32NANDDeviceNum Specifies which DMA channel to inspect.
- //! @retval true A DMA is currently running.
- //! @retval false The DMA channel is free.
- ////////////////////////////////////////////////////////////////////////////////
- bool gpmi_is_dma_active(uint32_t u32NANDDeviceNum);
- //@}
- //! @name Timing Control Functions
- //@{
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Fill the given timing structure with the safe timings.
- //!
- //! This function is used to get the timings characteristics that work with
- //! every device we've ever known. These timings should be used during initialization
- //! and device discovery. Once the device type is known, timings specific to
- //! that device should be set. Remember to actually set the safe timings once
- //! you get them by calling ddi_gpmi_set_timings().
- //!
- //! @param[out] timings The timings structure that will be set to the safe
- //! timings upon return.
- ////////////////////////////////////////////////////////////////////////////////
- void gpmi_get_safe_timings(GpmiNandTimings_t * timings);
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Set the flash timing for optimal NAND performance.
- //!
- //! Set the optimal NAND timings based upon the passed in NAND timings and the
- //! current GPMI clock.
- //!
- //! @param[in] newTimings Pointer to timing table for the NAND.
- //!
- //! @warning This function assumes all NAND I/O is halted.
- ////////////////////////////////////////////////////////////////////////////////
- void gpmi_set_timings(const GpmiNandTimings_t * newTimings);
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Set the timeout value for wait for ready.
- //!
- //! The timeout value set here is used for the GPMI wait for ready mode. It
- //! will have the most effect upon DMA operations.
- //!
- //! @param[in] busyTimeout Timeout value in microseconds.
- ////////////////////////////////////////////////////////////////////////////////
- void gpmi_set_busy_timeout(uint32_t busyTimeout);
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Returns the current GPMI timings values.
- //!
- //! @return A pointer to the current timing values used by the GPMI block.
- //! This will be the last set of timings passed to gpmi_set_timings().
- ////////////////////////////////////////////////////////////////////////////////
- const GpmiNandTimings_t * gpmi_get_current_timings();
- //@}
- //! @name Common NAND operations
- //!
- //! These functions are used to perform the common set of NAND read and write operations. They
- //! will build an appropriate DMA chain and execute it synchronously.
- //@{
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Configure the driver for a particular NAND type.
- ////////////////////////////////////////////////////////////////////////////////
- int gpmi_nand_configure(unsigned rowBytes, unsigned columnBytes, unsigned pagesPerBlock, const BchEccLayout_t * ecc);
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Reset the NAND.
- ////////////////////////////////////////////////////////////////////////////////
- int gpmi_nand_reset(unsigned chipSelect);
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Read a NAND's ID.
- ////////////////////////////////////////////////////////////////////////////////
- int gpmi_nand_read_id(unsigned chipSelect, uint8_t * resultID);
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Erase a block on a NAND.
- ////////////////////////////////////////////////////////////////////////////////
- int gpmi_nand_erase_block(unsigned chipSelect, uint32_t blockNumber);
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Read raw bytes from a NAND page.
- ////////////////////////////////////////////////////////////////////////////////
- int gpmi_nand_read_raw(unsigned chipSelect, uint32_t pageNumber, uint8_t * buffer, uint32_t offset, uint32_t count);
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Write a NAND page without using ECC.
- ////////////////////////////////////////////////////////////////////////////////
- int gpmi_nand_write_raw(unsigned chipSelect, uint32_t pageNumber, const uint8_t * buffer, uint32_t offset, uint32_t count);
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Read a NAND page using ECC.
- //! @bug Not yet functional.
- ////////////////////////////////////////////////////////////////////////////////
- int gpmi_nand_read_page(unsigned chipSelect, uint32_t pageNumber, uint8_t * buffer, uint8_t * auxBuffer);
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Read the metadata from a NAND page.
- //! @bug Not yet functional.
- ////////////////////////////////////////////////////////////////////////////////
- int gpmi_nand_read_metadata(unsigned chipSelect, uint32_t pageNumber, uint8_t * buffer);
- ////////////////////////////////////////////////////////////////////////////////
- //! @brief Write a NAND page.
- //! @bug Not yet functional.
- ////////////////////////////////////////////////////////////////////////////////
- int gpmi_nand_write_page(unsigned chipSelect, uint32_t pageNumber, const uint8_t * buffer, const uint8_t * auxBuffer);
- //@}
- //! @name Application APIs
- //!
- //! These functions must be implemented by the application. They are intended to isolate the
- //! GPMI driver from board and application specific design choices.
- //@{
- //! @brief Configure GPMI pins.
- void gpmi_iomux_config(void);
- //! @brief External function to enable and configure the GPMI clock.
- void gpmi_nand_clk_setup(void);
- //! @brief Convert a virtual address to a physical address.
- static inline void * nand_virtual_to_physical(const void * virtualAddress) { return (void *)virtualAddress; }
- //@}
- #ifdef __cplusplus
- }
- #endif
- //! @}
- #endif //__gpmi_h_
- ////////////////////////////////////////////////////////////////////////////////
- // EOF
- ////////////////////////////////////////////////////////////////////////////////
|