blob: a961d8c81a481732cf25e8f4dc87f21fef7efd4f [file] [log] [blame]
// 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 ddk.protocol.nand;
using zircon.device.nand;
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.
handle<vmo> data_vmo;
/// vmo of OOB data to read or write.
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.
NandOp command;
/// NAND_OP_READ, NAND_OP_WRITE.
NandReadWrite rw;
/// NAND_OP_ERASE.
NandErase erase;
};
[Layout = "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() -> (zircon.device.nand.NandInfo info, usize 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(NandOperation? op) -> (zx.status status, 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);
};