Introduction ============ In MDM9x25, new NAND controller(NANDc) has been added and it has the following major changes as compared to its previous version - 1. It includes Secured BAM-Lite and the support for ADM(Application Data Mover) has been removed. 2. It includes 4 bit BCH ECC and the support for 4 bit Reed Solomon ECC has been removed. 3. The support for Dual NAND controllers has been removed and thus the software features like ping-pong mode and interleave mode are deprecated. 4. It includes support for dual buffers in case of read and one dedicated write buffer to each processor (Modem and Apps). This new NAND driver takes care of all the above new hardware changes. In addition to the above hardware changes, it also takes care of software device tree changes. Hardware description ==================== The NANDc Core: --------------- Qualcomm Parallel Interface Controller (QPIC), formerly named EBI2, is a wrapper module which integrates a NAND controller core and a LCD controller core and multiplexes their access to shared parallel interfaces pins. Both controller cores are accessible to processors (Modem and Apps), and share master access to the Peripheral NoC (Network on Chip) via a BAM module. In MDM9x25, QPIC is located on the peripheral NoC, connected via a 32-bit AHB Master port and a 32-bit AHB Slave Port. The NANDc register interface goes through AHB Slave Port and data transfers using BAM goes through AHB Master Port. The NAND Controller (NANDc) is a hardware core which manages the access to an off-chip NAND device. BAM-Lite: --------- BAM(Bus Access Manager) can transfer data between a peripheral and memory, or between two peripherals in a BAM to BAM mode. Each BAM contains multiple DMA channels, called pipes. A pipe provides a unidirectional data transfer engine, capable of either receiving data in consumer mode, or transmitting data in producer mode. The consumer fetches the data from the source system memory, and the producer writes data to the destination system memory. BAM-Lite's interface is similar to the BAM interface with slight changes to the sideband interface. BAM-Lite is an area-optimized version of BAM. BAM-Lite supports new features such as Notify-When-Done(NWD), pipe lock/unlock and command descriptors. NANDc has a secured BAM-Lite which provides DMA support for the NANDc and command support for accessing the NANDc registers. It is called secured because it has an integrated APU (Address Protection Unit) that validates every access to BAM and its peripheral registers. The NANDc has in total 6 BAM pipes - 3 pipes are dedicated for each processor (Modem and Apps) at the hardware level. Software description ==================== The NAND device is shared between two independent file systems, each running on a different processor - the application processor (Apps) and the Modem. The NAND driver uses BAM driver to transfer NAND operation requests and data to/from the NAND Controller (NANDc) core through the BAM pipes. Every NANDc register read/write access must go through BAM as it facilitates security mechanisms to enable simultaneous access to NAND device from both processors (Modem and Apps). The Apps NAND driver registers NANDc BAM peripheral with BAM driver, allocates endpoints and descriptor FIFO memory and registers for complete event notification for the following pipes: - system consumer pipe for data (pipe#0) : This BAM pipe will be used for transferring data from system memory to NANDc i.e., during write. - system producer pipe for data (pipe#1) : This BAM pipe will be used for transferring data from NANDc to system memory i.e., during read. - system consumer pipe for commands (pipe#2) : This BAM pipe will be used for both reading and writing to NANDc registers. It can be configured either as consumer pipe or producer pipe but as per HW team's recommendation it is configured as consumer pipe. Control path: ------------- Each NAND operation can be described as a set of BAM command or/and data descriptors. A command descriptor(CD) points to the starting address of a command block. Each command block may contain a set of command elements where each command element is a single NANDc register read/write. The NAND driver submits all command descriptors to its system consumer pipe#2. Data path: ---------- A Data Descriptor(DD) points to the start of a data block which is a sequential chunk of data. For page write operations, the NAND driver submits data descriptors to system consumer pipe#0 and as per the descriptors submitted, the BAM reads data from the data block into the NANDc buffer. For page read operations, the NAND driver submits data descriptors to system producer pipe#1 and as per the descriptors submitted, the BAM reads data from the NANDc buffer into the data block. The driver submits a CD/DD using BAM driver APIs sps_transfer_one()/ sps_transfer(). To this API, flags is passed as one of the arguments and if SPS_IOVEC_FLAG_CMD is passed, then it is identified as a CD. Otherwise, it is identified as a DD. The other valid SPS flags for a CD/DD are - - SPS_IOVEC_FLAG_INT : This flag indicates BAM driver to raise BAM interrupt after the current descriptor with this flag has been processed by BAM HW. This flag is applicable for both CD and DD. - SPS_IOVEC_FLAG_NWD : This flag indicates BAM HW to not process next descriptors until it receives an acknowledgement by NANDc that the current descriptor with this flag is completely executed. This flag is applicable only for a CD. - SPS_IOVEC_FLAG_LOCK: This flag marks the beginning of a series of commands and it indicates that all the CDs submitted on this pipe must be executed atomically without any interruption by commands from other pipes. This is applicable only for a CD. - SPS_IOVEC_FLAG_UNLOCK: This flag marks the end of a series of commands and it indicates that the other pipe that was locked due to SPS_IOVEC_FLAG_LOCK flag can be unblocked after the current CD with this flag is executed. This is applicable only for a CD. - SPS_IOVEC_FLAG_EOT - This flag indicates to BAM driver that the current descriptor with this flag is the last descriptor submitted during write operation. This is applicable only for a DD. Error handling: --------------- After a page read/write complete notification from BAM, NAND driver validates the values read from NANDc registers to confirm the success/failure of page read/write operation. For example, after a page read/write is complete, the drivers reads the NANDc status registers to check for any operational errors, protection violation errors and device status errors, number of correctable/ uncorrectable errors reported by the controller. Based on the error conditions that are met, the driver reports appropriate error codes to upper layers. The upper layers respond to these errors and take appropriate action. Design ====== The existing NAND driver (ADM based) can not be reused due to many major HW changes (see Introduction section) in the new NANDc core. Some of the complex features (Dual NAND controllers support) too are deprecated in the new NANDc. Hence, a new NAND driver is written to take care of both SPS/BAM changes and other controller specific changes. The rest of the interaction with MTD and YAFFS2 remains same as its previous version of NAND driver msm_nand.c. Power Management ================ Two clocks are supplied by the system's clock controller to NANDc - AHB clock and interface clock. The interface clock is the clock that drives some of the HW blocks within NANDc. As of now, both these clocks are always on. But NANDc provides clock gating if some of the QPIC clock control registers are configured. The clock gating is yet to be enabled by driver. SMP/Multi-Core ============== The locking mechanism for page read/write operations is taken care of by the higher layers such as MTD/YAFFS2 and only one single page operation can happen at any time on a given partition. For a single page operation, there is always only one context associated within the driver and thus no additional handling is required within the driver. But it is possible for file system to issue one request on partition and at the same time to issue another request on another partition as each partition corresponds to different MTD block device. This situation is handled within the driver by properly acquiring a mutex lock before submitting any command/data descriptors to any of the BAM pipes. Security ======== The same NAND device is accessible from both processors (Modem and Apps) and thus to avoid any configuration overwrite issues during a page operation, driver on each processor (Modem and Apps) must explicitly use BAM pipe lock/unlock mechanism. This is taken care of by the NAND driver. The partition violation issues are prevented by an MPU (Memory Protection Unit) that is attached to NANDc. Performance =========== None. Interface ========= The NAND driver registers each partition on NAND device as a MTD block device using mtd_device_register(). As part of this registration, the following ops (struct mtd_info *mtd) are registered with MTD layer for each partition: mtd->_block_isbad = msm_nand_block_isbad; mtd->_block_markbad = msm_nand_block_markbad; mtd->_read = msm_nand_read; mtd->_write = msm_nand_write; mtd->_read_oob = msm_nand_read_oob; mtd->_write_oob = msm_nand_write_oob; mtd->_erase = msm_nand_erase; msm_nand_block_isbad() - This checks if a block is bad or not by reading bad block byte in the first page of a block. A block is considered as bad if bad block byte location contains any value other than 0xFF. msm_nand_block_markbad() - This marks a block as bad by writing 0 to the entire first page of the block and thus writing 0 to bad block byte location. msm_nand_read/write() - This is used to read/write only main data from/to single/multiple pages within NAND device. The YAFFS2 file system can send read/write request for two types of data - - Main data : This is the actual data to be read/written from/to a page during a read/write operation on this device. The size of this data request is typically based on the page size of the device (2K/4K). - OOB(Out Of Band) data : This is the spare data that will be used by file system to keep track of its meta data/tags associated with the actual data. As of now, the file system needs only 16 bytes to accommodate this data. The NAND driver always writes this data towards the end of main data. It is up to the file system whether or not to send a read/write request for OOB data along with main data. msm_nand_read_oob()/write_oob() - This is used to read/write both main data and spare data from/to single/multiple pages within NAND device. msm_nand_erase() - This erases the complete block by sending erase command to the device. The YAFFS2 file system registers as the user of MTD device and uses the ops exposed by the NAND driver to perform read/write/erase operations on NAND device. As of now, the driver can work with only YAFFS2 file system. An attempt to use it with any other file system might demand additional changes in the driver. Driver parameters ================= None. Config options ============== The config option MTD_MSM_QPIC_NAND enables this driver. Dependencies ============ It depends on the following kernel components: - SPS/BAM driver - MTD core layer - To add necessary NANDc and BAM resources to .dts file It depends on the following non-kernel components: The partition information of the NAND device must be passed by Modem subsystem to Apps boot loader and Apps boot loader must update the .dts file with the partition information as per the defined MTD bindings. The detailed information on MTD bindings can be found at - Documentation/devicetree/bindings/mtd/msm_qpic_nand.txt User space utilities ==================== None. Other ===== No changes other than device tree changes are anticipated. Known issues ============ None. To do ===== The NANDc core supports clock gating and is not yet supported by the driver.