blob: cf5ab31c9012b3dd52c7150568673f251cc8d369 [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.
///
/// Any mention of "in pages" in this file means nand pages, as reported by
/// nand_info.page_size, as opposed to physical memory pages (RAM). That's true
/// even for vmo-related values.
///
/// 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;
/// Optional physical page list.
vector<uint64>? page;
/// 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", DefaultProtocol]
interface Nand {
/// Obtains the parameters of the nand device (nand_info_t) and the required
/// size of nand_op_t. The nand_op_t's submitted via queue() must have
/// nand_op_size_out - sizeof(nand_op_t) bytes available at the end of the
/// structure for the use of the driver.
1: Query() -> (zircon.device.nand.NandInfo info, usize nand_op_size);
/// Submits an IO request for processing. Success or failure will be reported
/// via the completion_cb() in the nand_op_t. The callback may be called
/// before the queue() method returns.
[Async]
2: Queue(NandOperation? op) -> (zx.status s, NandOperation? op);
/// Gets the list of bad erase blocks, as reported by the nand manufacturer.
/// The caller must allocate a table large enough to hold the expected number
/// of entries, and pass the size of that table on |bad_block_len|.
/// On return, |num_bad_blocks| contains the number of bad blocks found.
/// 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.
3: GetFactoryBadBlockList() -> (zx.status s, vector<uint32> bad_blocks);
};