1235537Sgber/*- 2235537Sgber * Copyright (C) 2009-2012 Semihalf 3235537Sgber * All rights reserved. 4235537Sgber * 5235537Sgber * Redistribution and use in source and binary forms, with or without 6235537Sgber * modification, are permitted provided that the following conditions 7235537Sgber * are met: 8235537Sgber * 1. Redistributions of source code must retain the above copyright 9235537Sgber * notice, this list of conditions and the following disclaimer. 10235537Sgber * 2. Redistributions in binary form must reproduce the above copyright 11235537Sgber * notice, this list of conditions and the following disclaimer in the 12235537Sgber * documentation and/or other materials provided with the distribution. 13235537Sgber * 14235537Sgber * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15235537Sgber * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16235537Sgber * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17235537Sgber * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18235537Sgber * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19235537Sgber * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20235537Sgber * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21235537Sgber * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22235537Sgber * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23235537Sgber * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24235537Sgber * SUCH DAMAGE. 25235537Sgber * 26235537Sgber * $FreeBSD$ 27235537Sgber */ 28235537Sgber 29235537Sgber#ifndef _DEV_NAND_H_ 30235537Sgber#define _DEV_NAND_H_ 31235537Sgber 32235537Sgber#include <sys/bus.h> 33235537Sgber#include <sys/param.h> 34235537Sgber#include <sys/lock.h> 35235537Sgber#include <sys/sx.h> 36235537Sgber#include <sys/taskqueue.h> 37235537Sgber#include <sys/queue.h> 38235537Sgber#include <sys/bio.h> 39235537Sgber#include <sys/lock.h> 40235537Sgber#include <sys/mutex.h> 41235537Sgber#include <sys/malloc.h> 42235537Sgber 43235537Sgber#include <dev/nand/nand_dev.h> 44235537Sgber 45235537SgberMALLOC_DECLARE(M_NAND); 46235537Sgber 47235537Sgber/* Read commands */ 48235537Sgber#define NAND_CMD_READ 0x00 49235537Sgber#define NAND_CMD_CHNG_READ_COL 0x05 50235537Sgber#define NAND_CMD_READ_END 0x30 51235537Sgber#define NAND_CMD_READ_CACHE 0x31 52235537Sgber#define NAND_CMD_READ_CPBK 0x35 53235537Sgber#define NAND_CMD_READ_CACHE_END 0x3F 54235537Sgber#define NAND_CMD_CHNG_READ_COL_END 0xE0 55235537Sgber 56235537Sgber/* Erase commands */ 57235537Sgber#define NAND_CMD_ERASE 0x60 58235537Sgber#define NAND_CMD_ERASE_END 0xD0 59235537Sgber#define NAND_CMD_ERASE_INTLV 0xD1 60235537Sgber 61235537Sgber/* Program commands */ 62235537Sgber#define NAND_CMD_PROG 0x80 63235537Sgber#define NAND_CMD_CHNG_WRITE_COL 0x85 64235537Sgber#define NAND_CMD_PROG_END 0x10 65235537Sgber#define NAND_CMD_PROG_INTLV 0x11 66235537Sgber#define NAND_CMD_PROG_CACHE 0x15 67235537Sgber 68235537Sgber/* Misc commands */ 69235537Sgber#define NAND_CMD_STATUS 0x70 70235537Sgber#define NAND_CMD_STATUS_ENH 0x78 71235537Sgber#define NAND_CMD_READ_ID 0x90 72235537Sgber#define NAND_CMD_READ_PARAMETER 0xec 73235537Sgber#define NAND_CMD_READ_UNIQUE_ID 0xed 74235537Sgber#define NAND_CMD_GET_FEATURE 0xee 75235537Sgber#define NAND_CMD_SET_FEATURE 0xef 76235537Sgber 77235537Sgber/* Reset commands */ 78235537Sgber#define NAND_CMD_SYNCH_RESET 0xfc 79235537Sgber#define NAND_CMD_RESET 0xff 80235537Sgber 81235537Sgber/* Small page flash commands */ 82235537Sgber#define NAND_CMD_SMALLA 0x00 83235537Sgber#define NAND_CMD_SMALLB 0x01 84235537Sgber#define NAND_CMD_SMALLOOB 0x50 85235537Sgber 86235537Sgber#define NAND_STATUS_FAIL 0x1 87235537Sgber#define NAND_STATUS_FAILC 0x2 88235537Sgber#define NAND_STATUS_ARDY 0x20 89235537Sgber#define NAND_STATUS_RDY 0x40 90235537Sgber#define NAND_STATUS_WP 0x80 91235537Sgber 92235537Sgber#define NAND_LP_OOB_COLUMN_START 0x800 93235537Sgber#define NAND_LP_OOBSZ 0x40 94235537Sgber#define NAND_SP_OOB_COLUMN_START 0x200 95235537Sgber#define NAND_SP_OOBSZ 0x10 96235537Sgber 97235537Sgber#define PAGE_PARAM_LENGTH 0x100 98235537Sgber#define PAGE_PARAMETER_DEF 0x0 99235537Sgber#define PAGE_PARAMETER_RED_1 0x100 100235537Sgber#define PAGE_PARAMETER_RED_2 0x200 101235537Sgber 102235537Sgber#define ONFI_SIG_ADDR 0x20 103235537Sgber 104235537Sgber#define NAND_MAX_CHIPS 0x4 105235537Sgber#define NAND_MAX_OOBSZ 512 106235537Sgber#define NAND_MAX_PAGESZ 16384 107235537Sgber 108235537Sgber#define NAND_SMALL_PAGE_SIZE 0x200 109235537Sgber 110235537Sgber#define NAND_16_BIT 0x00000001 111235537Sgber 112235537Sgber#define NAND_ECC_NONE 0x0 113235537Sgber#define NAND_ECC_SOFT 0x1 114235537Sgber#define NAND_ECC_FULLHW 0x2 115235537Sgber#define NAND_ECC_PARTHW 0x4 116235537Sgber#define NAND_ECC_MODE_MASK 0x7 117235537Sgber 118235537Sgber#define ECC_OK 0 119235537Sgber#define ECC_CORRECTABLE 1 120235537Sgber#define ECC_ERROR_ECC (-1) 121235537Sgber#define ECC_UNCORRECTABLE (-2) 122235537Sgber 123235537Sgber#define NAND_MAN_SAMSUNG 0xec 124235537Sgber#define NAND_MAN_HYNIX 0xad 125235537Sgber#define NAND_MAN_STMICRO 0x20 126235537Sgber 127235537Sgberstruct nand_id { 128235537Sgber uint8_t man_id; 129235537Sgber uint8_t dev_id; 130235537Sgber}; 131235537Sgber 132235537Sgberstruct nand_params { 133235537Sgber struct nand_id id; 134235537Sgber char *name; 135235537Sgber uint32_t chip_size; 136235537Sgber uint32_t page_size; 137235537Sgber uint32_t oob_size; 138235537Sgber uint32_t pages_per_block; 139235537Sgber uint32_t flags; 140235537Sgber}; 141235537Sgber 142235537Sgber/* nand debug levels */ 143235537Sgber#define NDBG_NAND 0x01 144235537Sgber#define NDBG_CDEV 0x02 145235537Sgber#define NDBG_GEN 0x04 146235537Sgber#define NDBG_GEOM 0x08 147235537Sgber#define NDBG_BUS 0x10 148235537Sgber#define NDBG_SIM 0x20 149235537Sgber#define NDBG_CTRL 0x40 150235537Sgber#define NDBG_DRV 0x80 151235537Sgber#define NDBG_ECC 0x100 152235537Sgber 153235537Sgber/* nand_debug_function */ 154235537Sgbervoid nand_debug(int level, const char *fmt, ...); 155235537Sgberextern int nand_debug_flag; 156235537Sgber 157235537Sgber/* ONFI features bit*/ 158235537Sgber#define ONFI_FEAT_16BIT 0x01 159235537Sgber#define ONFI_FEAT_MULT_LUN 0x02 160235537Sgber#define ONFI_FEAT_INTLV_OPS 0x04 161235537Sgber#define ONFI_FEAT_CPBK_RESTRICT 0x08 162235537Sgber#define ONFI_FEAT_SRC_SYNCH 0x10 163235537Sgber 164235537Sgber/* ONFI optional commands bits */ 165235537Sgber#define ONFI_OPTCOM_PROG_CACHE 0x01 166235537Sgber#define ONFI_OPTCOM_READ_CACHE 0x02 167235537Sgber#define ONFI_OPTCOM_GETSET_FEAT 0x04 168235537Sgber#define ONFI_OPTCOM_STATUS_ENH 0x08 169235537Sgber#define ONFI_OPTCOM_COPYBACK 0x10 170235537Sgber#define ONFI_OPTCOM_UNIQUE_ID 0x20 171235537Sgber 172235537Sgber 173235537Sgber/* Layout of parameter page is defined in ONFI */ 174235537Sgberstruct onfi_params { 175235537Sgber char signature[4]; 176235537Sgber uint16_t rev; 177235537Sgber uint16_t features; 178235537Sgber uint16_t optional_commands; 179235537Sgber uint8_t res1[22]; 180235537Sgber char manufacturer_name[12]; 181235537Sgber char device_model[20]; 182235537Sgber uint8_t manufacturer_id; 183235537Sgber uint16_t date; 184235537Sgber uint8_t res2[13]; 185235537Sgber uint32_t bytes_per_page; 186235537Sgber uint16_t spare_bytes_per_page; 187235537Sgber uint32_t bytes_per_partial_page; 188235537Sgber uint16_t spare_bytes_per_partial_page; 189235537Sgber uint32_t pages_per_block; 190235537Sgber uint32_t blocks_per_lun; 191235537Sgber uint8_t luns; 192235537Sgber uint8_t address_cycles; 193235537Sgber uint8_t bits_per_cell; 194235537Sgber uint16_t max_bad_block_per_lun; 195235537Sgber uint16_t block_endurance; 196235537Sgber uint8_t guaranteed_valid_blocks; 197235537Sgber uint16_t valid_block_endurance; 198235537Sgber uint8_t programs_per_page; 199235537Sgber uint8_t partial_prog_attr; 200235537Sgber uint8_t bits_of_ecc; 201235537Sgber uint8_t interleaved_addr_bits; 202235537Sgber uint8_t interleaved_oper_attr; 203235537Sgber uint8_t res3[13]; 204235537Sgber uint8_t pin_capacitance; 205235537Sgber uint16_t asynch_timing_mode_support; 206235537Sgber uint16_t asynch_prog_cache_timing_mode_support; 207235537Sgber uint16_t t_prog; /* us, max page program time */ 208235537Sgber uint16_t t_bers; /* us, max block erase time */ 209235537Sgber uint16_t t_r; /* us, max page read time */ 210235537Sgber uint16_t t_ccs; /* ns, min change column setup time */ 211235537Sgber uint16_t source_synch_timing_mode_support; 212235537Sgber uint8_t source_synch_feat; 213235537Sgber uint16_t clk_input_capacitance; 214235537Sgber uint16_t io_capacitance; 215235537Sgber uint16_t input_capacitance; 216235537Sgber uint8_t input_capacitance_max; 217235537Sgber uint8_t driver_strength_support; 218235537Sgber uint8_t res4[12]; 219235537Sgber uint16_t vendor_rev; 220235537Sgber uint8_t vendor_spec[8]; 221235537Sgber uint16_t crc; 222251022Sgber}__attribute__((packed)); 223235537Sgber 224235537Sgberstruct nand_ecc_data { 225235537Sgber int eccsize; /* Number of data bytes per ECC step */ 226235537Sgber int eccmode; 227235537Sgber int eccbytes; /* Number of ECC bytes per step */ 228235537Sgber 229235537Sgber uint16_t *eccpositions; /* Positions of ecc bytes */ 230235537Sgber uint8_t ecccalculated[NAND_MAX_OOBSZ]; 231235537Sgber uint8_t eccread[NAND_MAX_OOBSZ]; 232235537Sgber}; 233235537Sgber 234235537Sgberstruct ecc_stat { 235235537Sgber uint32_t ecc_succeded; 236235537Sgber uint32_t ecc_corrected; 237235537Sgber uint32_t ecc_failed; 238235537Sgber}; 239235537Sgber 240235537Sgberstruct page_stat { 241235537Sgber struct ecc_stat ecc_stat; 242235537Sgber uint32_t page_read; 243235537Sgber uint32_t page_raw_read; 244235537Sgber uint32_t page_written; 245235537Sgber uint32_t page_raw_written; 246235537Sgber}; 247235537Sgber 248235537Sgberstruct block_stat { 249235537Sgber uint32_t block_erased; 250235537Sgber}; 251235537Sgber 252235537Sgberstruct chip_geom { 253235537Sgber uint32_t chip_size; 254235537Sgber uint32_t block_size; 255235537Sgber uint32_t page_size; 256235537Sgber uint32_t oob_size; 257235537Sgber 258235537Sgber uint32_t luns; 259235537Sgber uint32_t blks_per_lun; 260235537Sgber uint32_t blks_per_chip; 261235537Sgber uint32_t pgs_per_blk; 262235537Sgber 263235537Sgber uint32_t pg_mask; 264235537Sgber uint32_t blk_mask; 265235537Sgber uint32_t lun_mask; 266235537Sgber uint8_t blk_shift; 267235537Sgber uint8_t lun_shift; 268235537Sgber}; 269235537Sgber 270235537Sgberstruct nand_chip { 271235537Sgber device_t dev; 272235537Sgber struct nand_id id; 273235537Sgber struct chip_geom chip_geom; 274235537Sgber 275235537Sgber uint16_t t_prog; /* us, max page program time */ 276235537Sgber uint16_t t_bers; /* us, max block erase time */ 277235537Sgber uint16_t t_r; /* us, max page read time */ 278235537Sgber uint16_t t_ccs; /* ns, min change column setup time */ 279235537Sgber uint8_t num; 280235537Sgber uint8_t flags; 281235537Sgber 282235537Sgber struct page_stat *pg_stat; 283235537Sgber struct block_stat *blk_stat; 284235537Sgber struct nand_softc *nand; 285235537Sgber struct nand_bbt *bbt; 286235537Sgber struct nand_ops *ops; 287235537Sgber struct cdev *cdev; 288235537Sgber 289235537Sgber struct disk *ndisk; 290235537Sgber struct disk *rdisk; 291235537Sgber struct bio_queue_head bioq; /* bio queue */ 292235537Sgber struct mtx qlock; /* bioq lock */ 293235537Sgber struct taskqueue *tq; /* private task queue for i/o request */ 294235537Sgber struct task iotask; /* i/o processing */ 295235537Sgber 296235537Sgber}; 297235537Sgber 298235537Sgberstruct nand_softc { 299235537Sgber uint8_t flags; 300235537Sgber 301235537Sgber char *chip_cdev_name; 302235537Sgber struct nand_ecc_data ecc; 303235537Sgber}; 304235537Sgber 305235537Sgber/* NAND ops */ 306235537Sgberint nand_erase_blocks(struct nand_chip *chip, off_t offset, size_t len); 307235537Sgberint nand_prog_pages(struct nand_chip *chip, uint32_t offset, uint8_t *buf, 308235537Sgber uint32_t len); 309235537Sgberint nand_read_pages(struct nand_chip *chip, uint32_t offset, void *buf, 310235537Sgber uint32_t len); 311235537Sgberint nand_read_pages_raw(struct nand_chip *chip, uint32_t offset, void *buf, 312235537Sgber uint32_t len); 313235537Sgberint nand_prog_pages_raw(struct nand_chip *chip, uint32_t offset, void *buf, 314235537Sgber uint32_t len); 315235537Sgberint nand_read_oob(struct nand_chip *chip, uint32_t page, void *buf, 316235537Sgber uint32_t len); 317235537Sgberint nand_prog_oob(struct nand_chip *chip, uint32_t page, void *buf, 318235537Sgber uint32_t len); 319235537Sgber 320235537Sgberint nand_select_cs(device_t dev, uint8_t cs); 321235537Sgber 322235537Sgberint nand_read_parameter(struct nand_softc *nand, struct onfi_params *param); 323235537Sgberint nand_synch_reset(struct nand_softc *nand); 324235537Sgberint nand_chng_read_col(device_t dev, uint32_t col, void *buf, size_t len); 325235537Sgberint nand_chng_write_col(device_t dev, uint32_t col, void *buf, size_t len); 326235537Sgberint nand_get_feature(device_t dev, uint8_t feat, void* buf); 327235537Sgberint nand_set_feature(device_t dev, uint8_t feat, void* buf); 328235537Sgber 329235537Sgber 330235537Sgberint nand_erase_block_intlv(device_t dev, uint32_t block); 331235537Sgberint nand_copyback_read(device_t dev, uint32_t page, uint32_t col, 332235537Sgber void *buf, size_t len); 333235537Sgberint nand_copyback_prog(device_t dev, uint32_t page, uint32_t col, 334235537Sgber void *buf, size_t len); 335235537Sgberint nand_copyback_prog_intlv(device_t dev, uint32_t page); 336235537Sgberint nand_prog_cache(device_t dev, uint32_t page, uint32_t col, 337235537Sgber void *buf, size_t len, uint8_t end); 338235537Sgberint nand_prog_intlv(device_t dev, uint32_t page, uint32_t col, 339235537Sgber void *buf, size_t len); 340235537Sgberint nand_read_cache(device_t dev, uint32_t page, uint32_t col, 341235537Sgber void *buf, size_t len, uint8_t end); 342235537Sgber 343235537Sgberint nand_write_ecc(struct nand_softc *nand, uint32_t page, uint8_t *data); 344235537Sgberint nand_read_ecc(struct nand_softc *nand, uint32_t page, uint8_t *data); 345235537Sgber 346235537Sgberint nand_softecc_get(device_t dev, uint8_t *buf, int pagesize, uint8_t *ecc); 347235537Sgberint nand_softecc_correct(device_t dev, uint8_t *buf, int pagesize, 348235537Sgber uint8_t *readecc, uint8_t *calcecc); 349235537Sgber 350235537Sgber/* Chip initialization */ 351235537Sgbervoid nand_init(struct nand_softc *nand, device_t dev, int ecc_mode, 352235537Sgber int ecc_bytes, int ecc_size, uint16_t* eccposition, char* cdev_name); 353235537Sgbervoid nand_detach(struct nand_softc *nand); 354235537Sgberstruct nand_params *nand_get_params(struct nand_id *id); 355235537Sgber 356235537Sgbervoid nand_onfi_set_params(struct nand_chip *chip, struct onfi_params *params); 357235537Sgbervoid nand_set_params(struct nand_chip *chip, struct nand_params *params); 358235537Sgberint nand_init_stat(struct nand_chip *chip); 359235537Sgbervoid nand_destroy_stat(struct nand_chip *chip); 360235537Sgber 361235537Sgber/* BBT */ 362235537Sgberint nand_init_bbt(struct nand_chip *chip); 363235537Sgbervoid nand_destroy_bbt(struct nand_chip *chip); 364235537Sgberint nand_update_bbt(struct nand_chip *chip); 365235537Sgberint nand_mark_bad_block(struct nand_chip* chip, uint32_t block_num); 366235537Sgberint nand_check_bad_block(struct nand_chip* chip, uint32_t block_num); 367235537Sgber 368235537Sgber/* cdev creation/removal */ 369235537Sgberint nand_make_dev(struct nand_chip* chip); 370235537Sgbervoid nand_destroy_dev(struct nand_chip *chip); 371235537Sgber 372235537Sgberint create_geom_disk(struct nand_chip* chip); 373235537Sgberint create_geom_raw_disk(struct nand_chip *chip); 374235537Sgbervoid destroy_geom_disk(struct nand_chip *chip); 375235537Sgbervoid destroy_geom_raw_disk(struct nand_chip *chip); 376235537Sgber 377235537Sgberint init_chip_geom(struct chip_geom* cg, uint32_t luns, uint32_t blks_per_lun, 378235537Sgber uint32_t pgs_per_blk, uint32_t pg_size, uint32_t oob_size); 379235537Sgberint nand_row_to_blkpg(struct chip_geom *cg, uint32_t row, uint32_t *lun, 380235537Sgber uint32_t *blk, uint32_t *pg); 381235537Sgberint page_to_row(struct chip_geom *cg, uint32_t page, uint32_t *row); 382235537Sgberint nand_check_page_boundary(struct nand_chip *chip, uint32_t page); 383235537Sgbervoid nand_get_chip_param(struct nand_chip *chip, struct chip_param_io *param); 384235537Sgber 385235537Sgber#endif /* _DEV_NAND_H_ */ 386