| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| library fuchsia.hardware.nand; |
| |
| using fuchsia.hardware.nandinfo; |
| using zx; |
| |
| /// NandOperation's are submitted for processing via the queue() method of the |
| /// Nand Protocol. Once submitted, the contents of the NandOperation may be modified |
| /// while it's being processed. |
| /// |
| /// The completion_cb() must eventually be called upon success or failure and |
| /// at that point the cookie field must contain whatever value was in it when |
| /// the NandOperation was originally queued. |
| /// |
| /// corrected_bit_flips are always related to nand_info.ecc_bits, so it is |
| /// possible to obtain a value that is larger than what is being read (in the oob |
| /// case). On the other hand, if errors cannot be corrected, the operation will |
| /// fail, and corrected_bit_flips will be undefined. |
| |
| /// NOTE: The protocol can be extended with barriers to support controllers that |
| /// may issue multiple simultaneous request to the IO chips. |
| enum NandOp : uint32 { |
| READ = 0x1; |
| WRITE = 0x2; |
| ERASE = 0x3; |
| }; |
| |
| /// A single operation can read or write an arbitrary number of pages, |
| /// including out of band (OOB) data for each page. If either regular |
| /// data or OOB is not required, the relevant VMO handle should be set to |
| /// ZX_HANDLE_INVALID. |
| /// |
| /// Note that length dictates the number of pages to access, regardless |
| /// of the type of data requested: regular data, OOB or both. |
| /// |
| /// The OOB data will be copied to (and from) a contiguous memory range |
| /// starting at the given offset. Note that said offset is given in nand |
| /// pages even though OOB is just a handful of bytes per page. In other |
| /// words, after said offset, the OOB data for each page is located |
| /// nand_info.oob_size bytes apart. |
| /// |
| /// For example, to read 5 pages worth of data + OOB, with page size of |
| /// 2 kB and 16 bytes of OOB per page, setting: |
| /// |
| /// data_vmo = oob_vmo = vmo_handle |
| /// length = 5 |
| /// offset_nand = 20 |
| /// offset_data_vmo = 0 |
| /// offset_oob_vmo = 5 |
| /// |
| /// will transfer pages [20, 24] to the first 2048 * 5 bytes of the vmo, |
| /// followed by 16 * 5 bytes of OOB data starting at offset 2048 * 5. |
| struct NandReadWrite { |
| /// Command. |
| NandOp command; |
| |
| /// vmo of data to read or write. |
| zx.handle:VMO data_vmo; |
| |
| /// vmo of OOB data to read or write. |
| zx.handle:VMO oob_vmo; |
| |
| /// Number of pages to access. |
| /// (0 is invalid). |
| uint32 length; |
| |
| /// Offset into nand, in pages. |
| uint32 offset_nand; |
| |
| /// Data vmo offset in (nand) pages. |
| uint64 offset_data_vmo; |
| |
| /// OOB vmo offset in (nand) pages. |
| uint64 offset_oob_vmo; |
| |
| /// Return value from READ_DATA, max corrected bit flips in any |
| /// underlying ECC chunk read. The caller can compare this value |
| /// against ecc_bits to decide whether the nand erase block needs to |
| /// be recycled. |
| uint32 corrected_bit_flips; |
| }; |
| |
| struct NandErase { |
| /// Command. |
| NandOp command; |
| |
| /// Offset into nand, in erase blocks. |
| uint32 first_block; |
| |
| /// Number of blocks to erase. (0 is invalid). |
| uint32 num_blocks; |
| }; |
| |
| union NandOperation { |
| /// All Commands. |
| 1: NandOp command; |
| |
| /// NAND_OP_READ, NAND_OP_WRITE. |
| 2: NandReadWrite rw; |
| |
| /// NAND_OP_ERASE. |
| 3: NandErase erase; |
| }; |
| |
| [BanjoLayout = "ddk-protocol"] |
| protocol Nand { |
| /// Obtains the parameters of the nand device and the required |
| /// size of |NandOperation|. The |NandOperation| submitted via Queue() must have |
| /// `nand_op_size - sizeof(NandOperation)` bytes available at the end of the |
| /// structure for the use of the driver. |
| Query() -> (fuchsia.hardware.nandinfo.NandInfo info, uint64 nand_op_size); |
| |
| /// Submits an IO request for processing. Success or failure will be reported |
| /// via the callback. The callback may be called before the Queue() method returns. |
| /// Should return ZX_ERR_IO *only* when error ocurred due to underlying hardware. |
| /// When the hardware is not able to correct all bitflips for a page, the |
| /// driver should return ZX_ERR_IO_DATA_INTEGRITY. |
| [Async] |
| Queue([InOut] NandOperation op) -> (zx.status status, [Mutable] NandOperation op); |
| |
| /// Gets the list of bad erase blocks, as reported by the nand manufacturer. |
| /// This should only be called before writing any data to the nand, and the |
| /// returned data should be saved somewhere else, along blocks that become |
| /// bad after they've been in use. |
| GetFactoryBadBlockList() -> (zx.status status, vector<uint32> bad_blocks); |
| }; |