blob: ce9416b59870da46af2e2d89174f99e95d40292a [file] [log] [blame]
// Copyright 2017 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.
#pragma once
#include <assert.h>
#include <stdint.h>
// nand_info_t is used to retrieve various parameters describing the
// geometry of the underlying NAND chip(s). This is retrieved using
// the query api in nand_protocol_ops.
typedef struct nand_info nand_info_t;
struct nand_info {
uint32_t erase_blocksize; // in bytes
uint32_t pagesize; // in bytes
uint64_t device_size; // in bytes
// # of ECC bits per ECC page - in other words, the # of bitflips
// that can be corrected per ECC page.
uint32_t ecc_bits;
};
// nand_op_t's are submitted for processing via the queue() method
// of the nand_protocol.  Once submitted, the contents of the nand_op_t
// 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 nand_op_t was originally queued.
#define NAND_OP_READ_DATA 0x00000001
#define NAND_OP_WRITE_DATA 0x00000002
#define NAND_OP_ERASE 0x00000003
// TBD NAND_OP_READ_OOB, NAND_OP_WRITE_OOB
typedef struct nand_op nand_op_t;
struct nand_op {
// All Commands
uint32_t command;
union {
// NAND_OP_READ_DATA, NAND_OP_WRITE_DATA
struct {
uint32_t command;
// command
zx_handle_t vmo;
// vmo of data to read or write
uint32_t length;
// transfer length in bytes
// (0 is invalid).
// MUST BE A MULTIPLE OF NAND PAGESIZE
uint64_t offset_nand;
// offset into nand in bytes.
// MUST BE NAND PAGESIZE aligned
uint64_t offset_vmo;
// vmo offset in bytes
uint64_t* pages;
// optional physical page list
// Return value from READ_DATA, max corrected bit flips in
// any underlying ECC page read. The above layer(s) can
// compare this returned value against the bits-per-ECC-page
// to decide whether the underlying NAND erase block needs
// to be moved
uint32_t max_bitflips_ecc_page;
} rw;
// NAND_OP_ERASE
struct {
uint64_t offset_nand;
// offset into nand in bytes
// MUST BE NAND ERASEBLOCKSIZE aligned
uint32_t length;
// erase length in bytes(0 is invalid).
// MUST BE NAND ERASEBLOCKSIZE multiple
} erase;
} u;
// The completion_cb() will be called when the nand operation
// succeeds or fails, and cookie will be whatever was set when
// the nand_op was initially queue()'d.
void (*completion_cb)(nand_op_t *nop, zx_status_t status);
void *cookie;
};
typedef struct nand_protocol_ops {
// Obtain the parameters of the nand device (nand_info_t) and
// the required size of nand_txn_t.  The nand_txn_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.
void (*query)(void *ctx, nand_info_t *info_out, size_t *nand_op_size_out);
// Submit an IO request for processing.  Success or failure will
// be reported via the completion_cb() in the nand_op_t. This
// callback may be called before the queue() method returns.
void (*queue)(void *ctx, nand_op_t *op);
// Get list of bad NAND blocks (queried on startup)
// Returns the number of bad blocks found (could be 0).
// Internally the function allocates a table to hold the addresses of
// each bad block found. The returned table needs to be freed by the
// caller. The size of the table returned is
// (num_bad_blocks * sizeof(uint64_t))
void (*get_bad_block_list)(void *ctx, size_t *num_bad_blocks,
uint64_t **blocklist);
} nand_protocol_ops_t;
typedef struct nand_protocol {
nand_protocol_ops_t* ops;
void* ctx;
} nand_protocol_t;