| 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. |