summaryrefslogtreecommitdiffstats
path: root/sys/dev/nand/nand.h
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/nand/nand.h')
-rw-r--r--sys/dev/nand/nand.h385
1 files changed, 385 insertions, 0 deletions
diff --git a/sys/dev/nand/nand.h b/sys/dev/nand/nand.h
new file mode 100644
index 0000000..05101ac
--- /dev/null
+++ b/sys/dev/nand/nand.h
@@ -0,0 +1,385 @@
+/*-
+ * Copyright (C) 2009-2012 Semihalf
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DEV_NAND_H_
+#define _DEV_NAND_H_
+
+#include <sys/bus.h>
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/sx.h>
+#include <sys/taskqueue.h>
+#include <sys/queue.h>
+#include <sys/bio.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/malloc.h>
+
+#include <dev/nand/nand_dev.h>
+
+MALLOC_DECLARE(M_NAND);
+
+/* Read commands */
+#define NAND_CMD_READ 0x00
+#define NAND_CMD_CHNG_READ_COL 0x05
+#define NAND_CMD_READ_END 0x30
+#define NAND_CMD_READ_CACHE 0x31
+#define NAND_CMD_READ_CPBK 0x35
+#define NAND_CMD_READ_CACHE_END 0x3F
+#define NAND_CMD_CHNG_READ_COL_END 0xE0
+
+/* Erase commands */
+#define NAND_CMD_ERASE 0x60
+#define NAND_CMD_ERASE_END 0xD0
+#define NAND_CMD_ERASE_INTLV 0xD1
+
+/* Program commands */
+#define NAND_CMD_PROG 0x80
+#define NAND_CMD_CHNG_WRITE_COL 0x85
+#define NAND_CMD_PROG_END 0x10
+#define NAND_CMD_PROG_INTLV 0x11
+#define NAND_CMD_PROG_CACHE 0x15
+
+/* Misc commands */
+#define NAND_CMD_STATUS 0x70
+#define NAND_CMD_STATUS_ENH 0x78
+#define NAND_CMD_READ_ID 0x90
+#define NAND_CMD_READ_PARAMETER 0xec
+#define NAND_CMD_READ_UNIQUE_ID 0xed
+#define NAND_CMD_GET_FEATURE 0xee
+#define NAND_CMD_SET_FEATURE 0xef
+
+/* Reset commands */
+#define NAND_CMD_SYNCH_RESET 0xfc
+#define NAND_CMD_RESET 0xff
+
+/* Small page flash commands */
+#define NAND_CMD_SMALLA 0x00
+#define NAND_CMD_SMALLB 0x01
+#define NAND_CMD_SMALLOOB 0x50
+
+#define NAND_STATUS_FAIL 0x1
+#define NAND_STATUS_FAILC 0x2
+#define NAND_STATUS_ARDY 0x20
+#define NAND_STATUS_RDY 0x40
+#define NAND_STATUS_WP 0x80
+
+#define NAND_LP_OOB_COLUMN_START 0x800
+#define NAND_LP_OOBSZ 0x40
+#define NAND_SP_OOB_COLUMN_START 0x200
+#define NAND_SP_OOBSZ 0x10
+
+#define PAGE_PARAM_LENGTH 0x100
+#define PAGE_PARAMETER_DEF 0x0
+#define PAGE_PARAMETER_RED_1 0x100
+#define PAGE_PARAMETER_RED_2 0x200
+
+#define ONFI_SIG_ADDR 0x20
+
+#define NAND_MAX_CHIPS 0x4
+#define NAND_MAX_OOBSZ 512
+#define NAND_MAX_PAGESZ 16384
+
+#define NAND_SMALL_PAGE_SIZE 0x200
+
+#define NAND_16_BIT 0x00000001
+
+#define NAND_ECC_NONE 0x0
+#define NAND_ECC_SOFT 0x1
+#define NAND_ECC_FULLHW 0x2
+#define NAND_ECC_PARTHW 0x4
+#define NAND_ECC_MODE_MASK 0x7
+
+#define ECC_OK 0
+#define ECC_CORRECTABLE 1
+#define ECC_ERROR_ECC (-1)
+#define ECC_UNCORRECTABLE (-2)
+
+#define NAND_MAN_SAMSUNG 0xec
+#define NAND_MAN_HYNIX 0xad
+#define NAND_MAN_STMICRO 0x20
+
+struct nand_id {
+ uint8_t man_id;
+ uint8_t dev_id;
+};
+
+struct nand_params {
+ struct nand_id id;
+ char *name;
+ uint32_t chip_size;
+ uint32_t page_size;
+ uint32_t oob_size;
+ uint32_t pages_per_block;
+ uint32_t flags;
+};
+
+/* nand debug levels */
+#define NDBG_NAND 0x01
+#define NDBG_CDEV 0x02
+#define NDBG_GEN 0x04
+#define NDBG_GEOM 0x08
+#define NDBG_BUS 0x10
+#define NDBG_SIM 0x20
+#define NDBG_CTRL 0x40
+#define NDBG_DRV 0x80
+#define NDBG_ECC 0x100
+
+/* nand_debug_function */
+void nand_debug(int level, const char *fmt, ...);
+extern int nand_debug_flag;
+
+/* ONFI features bit*/
+#define ONFI_FEAT_16BIT 0x01
+#define ONFI_FEAT_MULT_LUN 0x02
+#define ONFI_FEAT_INTLV_OPS 0x04
+#define ONFI_FEAT_CPBK_RESTRICT 0x08
+#define ONFI_FEAT_SRC_SYNCH 0x10
+
+/* ONFI optional commands bits */
+#define ONFI_OPTCOM_PROG_CACHE 0x01
+#define ONFI_OPTCOM_READ_CACHE 0x02
+#define ONFI_OPTCOM_GETSET_FEAT 0x04
+#define ONFI_OPTCOM_STATUS_ENH 0x08
+#define ONFI_OPTCOM_COPYBACK 0x10
+#define ONFI_OPTCOM_UNIQUE_ID 0x20
+
+
+/* Layout of parameter page is defined in ONFI */
+struct onfi_params {
+ char signature[4];
+ uint16_t rev;
+ uint16_t features;
+ uint16_t optional_commands;
+ uint8_t res1[22];
+ char manufacturer_name[12];
+ char device_model[20];
+ uint8_t manufacturer_id;
+ uint16_t date;
+ uint8_t res2[13];
+ uint32_t bytes_per_page;
+ uint16_t spare_bytes_per_page;
+ uint32_t bytes_per_partial_page;
+ uint16_t spare_bytes_per_partial_page;
+ uint32_t pages_per_block;
+ uint32_t blocks_per_lun;
+ uint8_t luns;
+ uint8_t address_cycles;
+ uint8_t bits_per_cell;
+ uint16_t max_bad_block_per_lun;
+ uint16_t block_endurance;
+ uint8_t guaranteed_valid_blocks;
+ uint16_t valid_block_endurance;
+ uint8_t programs_per_page;
+ uint8_t partial_prog_attr;
+ uint8_t bits_of_ecc;
+ uint8_t interleaved_addr_bits;
+ uint8_t interleaved_oper_attr;
+ uint8_t res3[13];
+ uint8_t pin_capacitance;
+ uint16_t asynch_timing_mode_support;
+ uint16_t asynch_prog_cache_timing_mode_support;
+ uint16_t t_prog; /* us, max page program time */
+ uint16_t t_bers; /* us, max block erase time */
+ uint16_t t_r; /* us, max page read time */
+ uint16_t t_ccs; /* ns, min change column setup time */
+ uint16_t source_synch_timing_mode_support;
+ uint8_t source_synch_feat;
+ uint16_t clk_input_capacitance;
+ uint16_t io_capacitance;
+ uint16_t input_capacitance;
+ uint8_t input_capacitance_max;
+ uint8_t driver_strength_support;
+ uint8_t res4[12];
+ uint16_t vendor_rev;
+ uint8_t vendor_spec[8];
+ uint16_t crc;
+};
+
+struct nand_ecc_data {
+ int eccsize; /* Number of data bytes per ECC step */
+ int eccmode;
+ int eccbytes; /* Number of ECC bytes per step */
+
+ uint16_t *eccpositions; /* Positions of ecc bytes */
+ uint8_t ecccalculated[NAND_MAX_OOBSZ];
+ uint8_t eccread[NAND_MAX_OOBSZ];
+};
+
+struct ecc_stat {
+ uint32_t ecc_succeded;
+ uint32_t ecc_corrected;
+ uint32_t ecc_failed;
+};
+
+struct page_stat {
+ struct ecc_stat ecc_stat;
+ uint32_t page_read;
+ uint32_t page_raw_read;
+ uint32_t page_written;
+ uint32_t page_raw_written;
+};
+
+struct block_stat {
+ uint32_t block_erased;
+};
+
+struct chip_geom {
+ uint32_t chip_size;
+ uint32_t block_size;
+ uint32_t page_size;
+ uint32_t oob_size;
+
+ uint32_t luns;
+ uint32_t blks_per_lun;
+ uint32_t blks_per_chip;
+ uint32_t pgs_per_blk;
+
+ uint32_t pg_mask;
+ uint32_t blk_mask;
+ uint32_t lun_mask;
+ uint8_t blk_shift;
+ uint8_t lun_shift;
+};
+
+struct nand_chip {
+ device_t dev;
+ struct nand_id id;
+ struct chip_geom chip_geom;
+
+ uint16_t t_prog; /* us, max page program time */
+ uint16_t t_bers; /* us, max block erase time */
+ uint16_t t_r; /* us, max page read time */
+ uint16_t t_ccs; /* ns, min change column setup time */
+ uint8_t num;
+ uint8_t flags;
+
+ struct page_stat *pg_stat;
+ struct block_stat *blk_stat;
+ struct nand_softc *nand;
+ struct nand_bbt *bbt;
+ struct nand_ops *ops;
+ struct cdev *cdev;
+
+ struct disk *ndisk;
+ struct disk *rdisk;
+ struct bio_queue_head bioq; /* bio queue */
+ struct mtx qlock; /* bioq lock */
+ struct taskqueue *tq; /* private task queue for i/o request */
+ struct task iotask; /* i/o processing */
+
+};
+
+struct nand_softc {
+ uint8_t flags;
+
+ char *chip_cdev_name;
+ struct nand_ecc_data ecc;
+};
+
+/* NAND ops */
+int nand_erase_blocks(struct nand_chip *chip, off_t offset, size_t len);
+int nand_prog_pages(struct nand_chip *chip, uint32_t offset, uint8_t *buf,
+ uint32_t len);
+int nand_read_pages(struct nand_chip *chip, uint32_t offset, void *buf,
+ uint32_t len);
+int nand_read_pages_raw(struct nand_chip *chip, uint32_t offset, void *buf,
+ uint32_t len);
+int nand_prog_pages_raw(struct nand_chip *chip, uint32_t offset, void *buf,
+ uint32_t len);
+int nand_read_oob(struct nand_chip *chip, uint32_t page, void *buf,
+ uint32_t len);
+int nand_prog_oob(struct nand_chip *chip, uint32_t page, void *buf,
+ uint32_t len);
+
+int nand_select_cs(device_t dev, uint8_t cs);
+
+int nand_read_parameter(struct nand_softc *nand, struct onfi_params *param);
+int nand_synch_reset(struct nand_softc *nand);
+int nand_chng_read_col(device_t dev, uint32_t col, void *buf, size_t len);
+int nand_chng_write_col(device_t dev, uint32_t col, void *buf, size_t len);
+int nand_get_feature(device_t dev, uint8_t feat, void* buf);
+int nand_set_feature(device_t dev, uint8_t feat, void* buf);
+
+
+int nand_erase_block_intlv(device_t dev, uint32_t block);
+int nand_copyback_read(device_t dev, uint32_t page, uint32_t col,
+ void *buf, size_t len);
+int nand_copyback_prog(device_t dev, uint32_t page, uint32_t col,
+ void *buf, size_t len);
+int nand_copyback_prog_intlv(device_t dev, uint32_t page);
+int nand_prog_cache(device_t dev, uint32_t page, uint32_t col,
+ void *buf, size_t len, uint8_t end);
+int nand_prog_intlv(device_t dev, uint32_t page, uint32_t col,
+ void *buf, size_t len);
+int nand_read_cache(device_t dev, uint32_t page, uint32_t col,
+ void *buf, size_t len, uint8_t end);
+
+int nand_write_ecc(struct nand_softc *nand, uint32_t page, uint8_t *data);
+int nand_read_ecc(struct nand_softc *nand, uint32_t page, uint8_t *data);
+
+int nand_softecc_get(device_t dev, uint8_t *buf, int pagesize, uint8_t *ecc);
+int nand_softecc_correct(device_t dev, uint8_t *buf, int pagesize,
+ uint8_t *readecc, uint8_t *calcecc);
+
+/* Chip initialization */
+void nand_init(struct nand_softc *nand, device_t dev, int ecc_mode,
+ int ecc_bytes, int ecc_size, uint16_t* eccposition, char* cdev_name);
+void nand_detach(struct nand_softc *nand);
+struct nand_params *nand_get_params(struct nand_id *id);
+
+void nand_onfi_set_params(struct nand_chip *chip, struct onfi_params *params);
+void nand_set_params(struct nand_chip *chip, struct nand_params *params);
+int nand_init_stat(struct nand_chip *chip);
+void nand_destroy_stat(struct nand_chip *chip);
+
+/* BBT */
+int nand_init_bbt(struct nand_chip *chip);
+void nand_destroy_bbt(struct nand_chip *chip);
+int nand_update_bbt(struct nand_chip *chip);
+int nand_mark_bad_block(struct nand_chip* chip, uint32_t block_num);
+int nand_check_bad_block(struct nand_chip* chip, uint32_t block_num);
+
+/* cdev creation/removal */
+int nand_make_dev(struct nand_chip* chip);
+void nand_destroy_dev(struct nand_chip *chip);
+
+int create_geom_disk(struct nand_chip* chip);
+int create_geom_raw_disk(struct nand_chip *chip);
+void destroy_geom_disk(struct nand_chip *chip);
+void destroy_geom_raw_disk(struct nand_chip *chip);
+
+int init_chip_geom(struct chip_geom* cg, uint32_t luns, uint32_t blks_per_lun,
+ uint32_t pgs_per_blk, uint32_t pg_size, uint32_t oob_size);
+int nand_row_to_blkpg(struct chip_geom *cg, uint32_t row, uint32_t *lun,
+ uint32_t *blk, uint32_t *pg);
+int page_to_row(struct chip_geom *cg, uint32_t page, uint32_t *row);
+int nand_check_page_boundary(struct nand_chip *chip, uint32_t page);
+void nand_get_chip_param(struct nand_chip *chip, struct chip_param_io *param);
+
+#endif /* _DEV_NAND_H_ */
OpenPOWER on IntegriCloud