xref: /netbsd-src/sys/dev/nand/nand.h (revision 5a58ccfbecb506b305b6ec0fa77e4caac7faed71)
1*5a58ccfbSandvar /*	$NetBSD: nand.h,v 1.21 2022/08/07 11:06:19 andvar Exp $	*/
22b6ee221Sahoka 
32b6ee221Sahoka /*-
42b6ee221Sahoka  * Copyright (c) 2010 Department of Software Engineering,
52b6ee221Sahoka  *		      University of Szeged, Hungary
62b6ee221Sahoka  * Copyright (c) 2010 Adam Hoka <ahoka@NetBSD.org>
72b6ee221Sahoka  * All rights reserved.
82b6ee221Sahoka  *
92b6ee221Sahoka  * This code is derived from software contributed to The NetBSD Foundation
102b6ee221Sahoka  * by the Department of Software Engineering, University of Szeged, Hungary
112b6ee221Sahoka  *
122b6ee221Sahoka  * Redistribution and use in source and binary forms, with or without
132b6ee221Sahoka  * modification, are permitted provided that the following conditions
142b6ee221Sahoka  * are met:
152b6ee221Sahoka  * 1. Redistributions of source code must retain the above copyright
162b6ee221Sahoka  *    notice, this list of conditions and the following disclaimer.
172b6ee221Sahoka  * 2. Redistributions in binary form must reproduce the above copyright
182b6ee221Sahoka  *    notice, this list of conditions and the following disclaimer in the
192b6ee221Sahoka  *    documentation and/or other materials provided with the distribution.
202b6ee221Sahoka  *
212b6ee221Sahoka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
222b6ee221Sahoka  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
232b6ee221Sahoka  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
242b6ee221Sahoka  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
252b6ee221Sahoka  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
262b6ee221Sahoka  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
272b6ee221Sahoka  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
282b6ee221Sahoka  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
292b6ee221Sahoka  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
302b6ee221Sahoka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
312b6ee221Sahoka  * SUCH DAMAGE.
322b6ee221Sahoka  */
332b6ee221Sahoka 
342b6ee221Sahoka #ifndef _NAND_H_
352b6ee221Sahoka #define _NAND_H_
362b6ee221Sahoka 
372b6ee221Sahoka #include <sys/param.h>
382b6ee221Sahoka #include <sys/cdefs.h>
392b6ee221Sahoka 
406e978bedSrin #ifdef _KERNEL_OPT
416e978bedSrin #include "opt_nand.h"
426e978bedSrin #endif
436e978bedSrin 
442b6ee221Sahoka #include <sys/bufq.h>
452b6ee221Sahoka #include <sys/buf.h>
462b6ee221Sahoka #include <sys/time.h>
472b6ee221Sahoka 
48c68f5a83Sahoka #include <dev/nand/onfi.h>
492b6ee221Sahoka #include <dev/flash/flash.h>
500e8f635bSahoka #include <dev/flash/flash_io.h>
512b6ee221Sahoka 
522b6ee221Sahoka #ifdef NAND_DEBUG
538f72be80Sahoka #define DPRINTF(x)	printf x
542b6ee221Sahoka #else
552b6ee221Sahoka #define DPRINTF(x)
562b6ee221Sahoka #endif
572b6ee221Sahoka 
582b6ee221Sahoka /* same as in linux for compatibility */
592b6ee221Sahoka enum {
602b6ee221Sahoka 	NAND_BAD_MARKER_OFFSET		= 0,
612b6ee221Sahoka 	NAND_BAD_MARKER_OFFSET_SMALL	= 5
622b6ee221Sahoka };
632b6ee221Sahoka 
642b6ee221Sahoka /* feature flags use in nc_flags */
652b6ee221Sahoka enum {
662b6ee221Sahoka 	NC_BUSWIDTH_16		= (1<<0),
672b6ee221Sahoka 	NC_SOURCE_SYNC		= (1<<2),
682b6ee221Sahoka 	NC_INTERLEAVED_PE	= (1<<1),
692b6ee221Sahoka 	NC_INTERLEAVED_R	= (1<<3),
702b6ee221Sahoka 	NC_EXTENDED_PARAM	= (1<<4)
712b6ee221Sahoka };
722b6ee221Sahoka 
732b6ee221Sahoka /* various quirks used in nc_quirks */
742b6ee221Sahoka enum {
752b6ee221Sahoka 	NC_QUIRK_NO_READ_START = (1<<0)
762b6ee221Sahoka };
772b6ee221Sahoka 
782b6ee221Sahoka enum {
792b6ee221Sahoka 	NAND_ECC_READ,
802b6ee221Sahoka 	NAND_ECC_WRITE
812b6ee221Sahoka };
822b6ee221Sahoka 
832b6ee221Sahoka enum {
842b6ee221Sahoka 	NAND_ECC_OK,
852b6ee221Sahoka 	NAND_ECC_CORRECTED,
862b6ee221Sahoka 	NAND_ECC_INVALID,
872b6ee221Sahoka 	NAND_ECC_TWOBIT
882b6ee221Sahoka };
892b6ee221Sahoka 
902b6ee221Sahoka enum {
912b6ee221Sahoka 	NAND_ECC_TYPE_HW,
922b6ee221Sahoka 	NAND_ECC_TYPE_SW
932b6ee221Sahoka };
942b6ee221Sahoka 
952b6ee221Sahoka struct nand_bbt {
962b6ee221Sahoka 	uint8_t *nbbt_bitmap;
972b6ee221Sahoka 	size_t nbbt_size;
982b6ee221Sahoka };
992b6ee221Sahoka 
1002b6ee221Sahoka struct nand_ecc {
1012b6ee221Sahoka 	size_t necc_offset;		/* offset of ecc data in oob */
1022b6ee221Sahoka 	size_t necc_size;		/* size of ecc data in oob */
1032b6ee221Sahoka 	size_t necc_block_size;		/* block size used in ecc calc */
104*5a58ccfbSandvar 	size_t necc_code_size;		/* redundant bytes per block */
1052b6ee221Sahoka 	int necc_steps;			/* pagesize / code size */
1062b6ee221Sahoka 	int necc_type;			/* type of the ecc engine */
1072b6ee221Sahoka };
1082b6ee221Sahoka 
1092b6ee221Sahoka /**
1102b6ee221Sahoka  * nand_chip: structure containing the required information
1112b6ee221Sahoka  *	      about the NAND chip.
1122b6ee221Sahoka  */
1132b6ee221Sahoka struct nand_chip {
11414ce4eccSahoka 	struct nand_ecc *nc_ecc; 	/* ecc information */
1152b6ee221Sahoka 	uint8_t	*nc_oob_cache;		/* buffer for oob cache */
1162b6ee221Sahoka 	uint8_t *nc_page_cache;		/* buffer for page cache */
1173c5212aaSahoka 	uint8_t *nc_ecc_cache;		/* buffer for ecc */
1183c5212aaSahoka 	uint64_t nc_size;		/* storage size in bytes */
1193c5212aaSahoka 	uint32_t nc_page_size;		/* page size in bytes */
1203c5212aaSahoka 	uint32_t nc_block_size;		/* block size in bytes */
12114ce4eccSahoka 	uint32_t nc_lun_blocks;		/* LUN size in blocks */
1222b6ee221Sahoka 	uint32_t nc_flags;		/* bitfield flags */
1232b6ee221Sahoka 	uint32_t nc_quirks;		/* bitfield quirks */
1243c5212aaSahoka 	uint32_t nc_page_shift;		/* page shift for page alignment */
1253c5212aaSahoka 	uint32_t nc_page_mask;		/* page mask for page alignment */
1263c5212aaSahoka 	uint32_t nc_block_shift;	/* write shift */
1273c5212aaSahoka 	uint32_t nc_block_mask;		/* write mask */
128e30fb1abSahoka 	uint16_t nc_spare_size;		/* spare (oob) size in bytes */
12914ce4eccSahoka 	uint8_t nc_num_luns;		/* number of LUNs */
1302b6ee221Sahoka 	uint8_t nc_manf_id;		/* manufacturer id */
1312b6ee221Sahoka 	uint8_t nc_dev_id;		/* device id  */
1322b6ee221Sahoka 	uint8_t nc_addr_cycles_row;	/* row cycles for addressing */
1332b6ee221Sahoka 	uint8_t nc_addr_cycles_column;	/* column cycles for addressing */
1342b6ee221Sahoka 	uint8_t nc_badmarker_offs;	/* offset for marking bad blocks */
13514ce4eccSahoka 	bool nc_isonfi;			/* if the device is onfi compliant */
1362b6ee221Sahoka };
1372b6ee221Sahoka 
1382b6ee221Sahoka struct nand_write_cache {
1392b6ee221Sahoka 	struct bintime nwc_creation;
1402b6ee221Sahoka 	struct bintime nwc_last_write;
1412b6ee221Sahoka 	struct bufq_state *nwc_bufq;
1422b6ee221Sahoka 	uint8_t *nwc_data;
1432b6ee221Sahoka 	daddr_t nwc_block;
1442b6ee221Sahoka 	kmutex_t nwc_lock;
1452b6ee221Sahoka 	bool nwc_write_pending;
146d17d98adSahoka 	struct lwp *nwc_thread;
147d17d98adSahoka 	kcondvar_t nwc_cv;
148d17d98adSahoka 	bool nwc_exiting;
1492b6ee221Sahoka };
1502b6ee221Sahoka 
1512b6ee221Sahoka /* driver softc for nand */
1522b6ee221Sahoka struct nand_softc {
1532b6ee221Sahoka 	device_t sc_dev;
154c68f5a83Sahoka 	device_t controller_dev;
1552b6ee221Sahoka 	struct nand_interface *nand_if;
1562b6ee221Sahoka 	void *nand_softc;
1572b6ee221Sahoka 	struct nand_chip sc_chip;
1582b6ee221Sahoka 	struct nand_bbt sc_bbt;
1592b6ee221Sahoka 	size_t sc_part_offset;
1602b6ee221Sahoka 	size_t sc_part_size;
1612b6ee221Sahoka 	kmutex_t sc_device_lock; /* serialize access to chip */
1620e8f635bSahoka 	struct flash_io sc_flash_io;
1632b6ee221Sahoka };
1642b6ee221Sahoka 
1652b6ee221Sahoka /* structure holding the nand api */
166fb19d2b7Scliff struct nand_interface {
167c68f5a83Sahoka 	/* basic nand controller commands */
168c68f5a83Sahoka 	void (*select) (device_t, bool); /* optional */
1692b6ee221Sahoka 	void (*command) (device_t, uint8_t);
1702b6ee221Sahoka 	void (*address) (device_t, uint8_t);
17152682d39Sahoka 	void (*read_buf_1) (device_t, void *, size_t);
17252682d39Sahoka 	void (*read_buf_2) (device_t, void *, size_t);
17352682d39Sahoka 	void (*read_1) (device_t, uint8_t *);
17452682d39Sahoka 	void (*read_2) (device_t, uint16_t *);
17552682d39Sahoka 	void (*write_buf_1) (device_t, const void *, size_t);
17652682d39Sahoka 	void (*write_buf_2) (device_t, const void *, size_t);
17752682d39Sahoka 	void (*write_1) (device_t, uint8_t);
17852682d39Sahoka 	void (*write_2) (device_t, uint16_t);
1792b6ee221Sahoka 	void (*busy) (device_t);
1802b6ee221Sahoka 
181c68f5a83Sahoka 	/* "smart" controllers may override read/program functions */
182c68f5a83Sahoka 	int (*read_page) (device_t, size_t, uint8_t *); /* optional */
183c68f5a83Sahoka 	int (*program_page) (device_t, size_t, const uint8_t *); /* optional */
184c68f5a83Sahoka 
1852b6ee221Sahoka 	/* functions specific to ecc computation */
186c68f5a83Sahoka 	int (*ecc_prepare)(device_t, int); /* optional */
1872b6ee221Sahoka 	int (*ecc_compute)(device_t, const uint8_t *, uint8_t *);
1882b6ee221Sahoka 	int (*ecc_correct)(device_t, uint8_t *, const uint8_t *,
1892b6ee221Sahoka 	    const uint8_t *);
1902b6ee221Sahoka 
191c68f5a83Sahoka 	/* information for the ecc engine */
1922b6ee221Sahoka 	struct nand_ecc ecc;
1932b6ee221Sahoka 
1942b6ee221Sahoka 	/* flash partition information */
1952b6ee221Sahoka 	const struct flash_partition *part_info;
1962b6ee221Sahoka 	int part_num;
1972b6ee221Sahoka };
1982b6ee221Sahoka 
1992b6ee221Sahoka /* attach args */
2002b6ee221Sahoka struct nand_attach_args {
2012b6ee221Sahoka 	struct nand_interface *naa_nand_if;
2022b6ee221Sahoka };
2032b6ee221Sahoka 
20487fd18f8Schristos static __inline void
nand_busy(device_t device)2052b6ee221Sahoka nand_busy(device_t device)
2062b6ee221Sahoka {
207fb19d2b7Scliff 	struct nand_softc * const sc = device_private(device);
2082b6ee221Sahoka 
2092b6ee221Sahoka 	KASSERT(sc->nand_if->select != NULL);
210c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
2112b6ee221Sahoka 
212c68f5a83Sahoka 	sc->nand_if->select(sc->controller_dev, true);
2132b6ee221Sahoka 
2142b6ee221Sahoka 	if (sc->nand_if->busy != NULL) {
215c68f5a83Sahoka 		sc->nand_if->busy(sc->controller_dev);
2162b6ee221Sahoka 	}
2172b6ee221Sahoka 
218c68f5a83Sahoka 	sc->nand_if->select(sc->controller_dev, false);
2192b6ee221Sahoka }
2202b6ee221Sahoka 
22187fd18f8Schristos static __inline void
nand_select(device_t self,bool enable)2222b6ee221Sahoka nand_select(device_t self, bool enable)
2232b6ee221Sahoka {
224fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
2252b6ee221Sahoka 
2262b6ee221Sahoka 	KASSERT(sc->nand_if->select != NULL);
227c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
2282b6ee221Sahoka 
229c68f5a83Sahoka 	sc->nand_if->select(sc->controller_dev, enable);
2302b6ee221Sahoka }
2312b6ee221Sahoka 
23287fd18f8Schristos static __inline void
nand_address(device_t self,uint32_t address)2332b6ee221Sahoka nand_address(device_t self, uint32_t address)
2342b6ee221Sahoka {
235fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
2362b6ee221Sahoka 
2372b6ee221Sahoka 	KASSERT(sc->nand_if->address != NULL);
238c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
2392b6ee221Sahoka 
240c68f5a83Sahoka 	sc->nand_if->address(sc->controller_dev, address);
2412b6ee221Sahoka }
2422b6ee221Sahoka 
24387fd18f8Schristos static __inline void
nand_command(device_t self,uint8_t command)2442b6ee221Sahoka nand_command(device_t self, uint8_t command)
2452b6ee221Sahoka {
246fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
2472b6ee221Sahoka 
2482b6ee221Sahoka 	KASSERT(sc->nand_if->command != NULL);
249c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
2502b6ee221Sahoka 
251c68f5a83Sahoka 	sc->nand_if->command(sc->controller_dev, command);
2522b6ee221Sahoka }
2532b6ee221Sahoka 
25487fd18f8Schristos static __inline void
nand_read_1(device_t self,uint8_t * data)25552682d39Sahoka nand_read_1(device_t self, uint8_t *data)
2562b6ee221Sahoka {
257fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
2582b6ee221Sahoka 
25952682d39Sahoka 	KASSERT(sc->nand_if->read_1 != NULL);
260c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
2612b6ee221Sahoka 
26252682d39Sahoka 	sc->nand_if->read_1(sc->controller_dev, data);
2632b6ee221Sahoka }
2642b6ee221Sahoka 
26587fd18f8Schristos static __inline void
nand_write_1(device_t self,uint8_t data)26652682d39Sahoka nand_write_1(device_t self, uint8_t data)
2672b6ee221Sahoka {
268fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
2692b6ee221Sahoka 
27052682d39Sahoka 	KASSERT(sc->nand_if->write_1 != NULL);
271c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
2722b6ee221Sahoka 
27352682d39Sahoka 	sc->nand_if->write_1(sc->controller_dev, data);
2742b6ee221Sahoka }
2752b6ee221Sahoka 
27687fd18f8Schristos static __inline void
nand_read_2(device_t self,uint16_t * data)27752682d39Sahoka nand_read_2(device_t self, uint16_t *data)
2782b6ee221Sahoka {
279fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
2802b6ee221Sahoka 
28152682d39Sahoka 	KASSERT(sc->nand_if->read_2 != NULL);
282c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
2832b6ee221Sahoka 
28452682d39Sahoka 	sc->nand_if->read_2(sc->controller_dev, data);
2852b6ee221Sahoka }
2862b6ee221Sahoka 
28787fd18f8Schristos static __inline void
nand_write_2(device_t self,uint16_t data)28852682d39Sahoka nand_write_2(device_t self, uint16_t data)
2892b6ee221Sahoka {
290fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
2912b6ee221Sahoka 
29252682d39Sahoka 	KASSERT(sc->nand_if->write_2 != NULL);
293c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
2942b6ee221Sahoka 
29552682d39Sahoka 	sc->nand_if->write_2(sc->controller_dev, data);
2962b6ee221Sahoka }
2972b6ee221Sahoka 
29887fd18f8Schristos static __inline void
nand_read_buf_1(device_t self,void * buf,size_t size)29952682d39Sahoka nand_read_buf_1(device_t self, void *buf, size_t size)
3002b6ee221Sahoka {
301fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
3022b6ee221Sahoka 
30352682d39Sahoka 	KASSERT(sc->nand_if->read_buf_1 != NULL);
304c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
3052b6ee221Sahoka 
30652682d39Sahoka 	sc->nand_if->read_buf_1(sc->controller_dev, buf, size);
3072b6ee221Sahoka }
3082b6ee221Sahoka 
30987fd18f8Schristos static __inline void
nand_read_buf_2(device_t self,void * buf,size_t size)31052682d39Sahoka nand_read_buf_2(device_t self, void *buf, size_t size)
3112b6ee221Sahoka {
312fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
3132b6ee221Sahoka 
31452682d39Sahoka 	KASSERT(sc->nand_if->read_buf_2 != NULL);
315c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
3162b6ee221Sahoka 
31752682d39Sahoka 	sc->nand_if->read_buf_2(sc->controller_dev, buf, size);
3182b6ee221Sahoka }
3192b6ee221Sahoka 
32087fd18f8Schristos static __inline void
nand_write_buf_1(device_t self,const void * buf,size_t size)32152682d39Sahoka nand_write_buf_1(device_t self, const void *buf, size_t size)
3222b6ee221Sahoka {
323fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
3242b6ee221Sahoka 
32552682d39Sahoka 	KASSERT(sc->nand_if->write_buf_1 != NULL);
326c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
3272b6ee221Sahoka 
32852682d39Sahoka 	sc->nand_if->write_buf_1(sc->controller_dev, buf, size);
3292b6ee221Sahoka }
3302b6ee221Sahoka 
33187fd18f8Schristos static __inline void
nand_write_buf_2(device_t self,const void * buf,size_t size)33252682d39Sahoka nand_write_buf_2(device_t self, const void *buf, size_t size)
3332b6ee221Sahoka {
334fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
3352b6ee221Sahoka 
33652682d39Sahoka 	KASSERT(sc->nand_if->write_buf_2 != NULL);
337c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
3382b6ee221Sahoka 
33952682d39Sahoka 	sc->nand_if->write_buf_2(sc->controller_dev, buf, size);
3402b6ee221Sahoka }
3412b6ee221Sahoka 
34287fd18f8Schristos static __inline int
nand_ecc_correct(device_t self,uint8_t * data,const uint8_t * oldcode,const uint8_t * newcode)3432b6ee221Sahoka nand_ecc_correct(device_t self, uint8_t *data, const uint8_t *oldcode,
3442b6ee221Sahoka     const uint8_t *newcode)
3452b6ee221Sahoka {
346fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
3472b6ee221Sahoka 
3482b6ee221Sahoka 	KASSERT(sc->nand_if->ecc_correct != NULL);
349c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
3502b6ee221Sahoka 
351c68f5a83Sahoka 	return sc->nand_if->ecc_correct(sc->controller_dev, data, oldcode, newcode);
3522b6ee221Sahoka }
3532b6ee221Sahoka 
35487fd18f8Schristos static __inline void
nand_ecc_compute(device_t self,const uint8_t * data,uint8_t * code)3552b6ee221Sahoka nand_ecc_compute(device_t self, const uint8_t *data, uint8_t *code)
3562b6ee221Sahoka {
357fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
3582b6ee221Sahoka 
3592b6ee221Sahoka 	KASSERT(sc->nand_if->ecc_compute != NULL);
360c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
3612b6ee221Sahoka 
362c68f5a83Sahoka 	sc->nand_if->ecc_compute(sc->controller_dev, data, code);
3632b6ee221Sahoka }
3642b6ee221Sahoka 
36587fd18f8Schristos static __inline void
nand_ecc_prepare(device_t self,int mode)3662b6ee221Sahoka nand_ecc_prepare(device_t self, int mode)
3672b6ee221Sahoka {
368fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
3692b6ee221Sahoka 
370c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
3712b6ee221Sahoka 
3722b6ee221Sahoka 	if (sc->nand_if->ecc_prepare != NULL)
373c68f5a83Sahoka 		sc->nand_if->ecc_prepare(sc->controller_dev, mode);
374c68f5a83Sahoka }
375c68f5a83Sahoka 
37687fd18f8Schristos static __inline int
nand_program_page(device_t self,size_t offset,const uint8_t * data)377c68f5a83Sahoka nand_program_page(device_t self, size_t offset, const uint8_t *data)
378c68f5a83Sahoka {
379fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
380c68f5a83Sahoka 
381c68f5a83Sahoka 	KASSERT(sc->nand_if->program_page != NULL);
382c68f5a83Sahoka 
383c68f5a83Sahoka 	return sc->nand_if->program_page(self, offset, data);
384c68f5a83Sahoka }
385c68f5a83Sahoka 
38687fd18f8Schristos static __inline int
nand_read_page(device_t self,size_t offset,uint8_t * data)387c68f5a83Sahoka nand_read_page(device_t self, size_t offset, uint8_t *data)
388c68f5a83Sahoka {
389fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
390c68f5a83Sahoka 
391c68f5a83Sahoka 	KASSERT(sc->nand_if->read_page != NULL);
392c68f5a83Sahoka 
393c68f5a83Sahoka 	return sc->nand_if->read_page(self, offset, data);
3942b6ee221Sahoka }
3952b6ee221Sahoka 
3962b6ee221Sahoka #if 0
39787fd18f8Schristos static __inline bool
3986adb739dSahoka nand_block_isbad(device_t self, flash_off_t block)
3992b6ee221Sahoka {
400fb19d2b7Scliff 	struct nand_softc * const sc = device_private(self);
4012b6ee221Sahoka 
4022b6ee221Sahoka 	KASSERT(sc->nand_if->block_isbad != NULL);
403c68f5a83Sahoka 	KASSERT(sc->controller_dev != NULL);
4042b6ee221Sahoka 
405c68f5a83Sahoka 	return sc->nand_if->block_isbad(sc->controller_dev, block);
4062b6ee221Sahoka }
4072b6ee221Sahoka #endif
4082b6ee221Sahoka 
4092b6ee221Sahoka /* Manufacturer IDs defined by JEDEC */
4102b6ee221Sahoka enum {
4112b6ee221Sahoka 	NAND_MFR_UNKNOWN	= 0x00,
4122b6ee221Sahoka 	NAND_MFR_AMD		= 0x01,
4132b6ee221Sahoka 	NAND_MFR_FUJITSU	= 0x04,
4142b6ee221Sahoka 	NAND_MFR_RENESAS	= 0x07,
4152b6ee221Sahoka 	NAND_MFR_STMICRO	= 0x20,
4162b6ee221Sahoka 	NAND_MFR_MICRON		= 0x2c,
4172b6ee221Sahoka 	NAND_MFR_NATIONAL	= 0x8f,
4182b6ee221Sahoka 	NAND_MFR_TOSHIBA	= 0x98,
4192b6ee221Sahoka 	NAND_MFR_HYNIX		= 0xad,
4202b6ee221Sahoka 	NAND_MFR_SAMSUNG	= 0xec
4212b6ee221Sahoka };
4222b6ee221Sahoka 
4232b6ee221Sahoka struct nand_manufacturer {
4242b6ee221Sahoka 	int id;
4252b6ee221Sahoka 	const char *name;
4262b6ee221Sahoka };
4272b6ee221Sahoka 
4282b6ee221Sahoka extern const struct nand_manufacturer nand_mfrs[];
4292b6ee221Sahoka 
43014ce4eccSahoka /*
43114ce4eccSahoka  * Manufacturer specific parameter functions
43214ce4eccSahoka  */
43314ce4eccSahoka int nand_read_parameters_micron(device_t, struct nand_chip *);
43411d96520Sriz int nand_read_parameters_samsung(device_t, struct nand_chip *);
43557ab95bfSjmcneill int nand_read_parameters_toshiba(device_t, struct nand_chip *);
43614ce4eccSahoka 
43714ce4eccSahoka /* debug inlines */
43814ce4eccSahoka 
43987fd18f8Schristos static __inline void
nand_dump_data(const char * name,void * data,size_t len)4402b6ee221Sahoka nand_dump_data(const char *name, void *data, size_t len)
4412b6ee221Sahoka {
4422b6ee221Sahoka 	uint8_t *dump = data;
44378d39fa3Sjruoho 	int i;
44478d39fa3Sjruoho 
44578d39fa3Sjruoho 	printf("dumping %s\n--------------\n", name);
44678d39fa3Sjruoho 	for (i = 0; i < len; i++) {
4472b6ee221Sahoka 		printf("0x%.2hhx ", *dump);
4482b6ee221Sahoka 		dump++;
4492b6ee221Sahoka 	}
4502b6ee221Sahoka 	printf("\n--------------\n");
4512b6ee221Sahoka }
4522b6ee221Sahoka 
453c68f5a83Sahoka /* flash interface implementation */
4546adb739dSahoka int nand_flash_isbad(device_t, flash_off_t, bool *);
4556adb739dSahoka int nand_flash_markbad(device_t, flash_off_t);
4566adb739dSahoka int nand_flash_write(device_t, flash_off_t, size_t, size_t *, const u_char *);
4576adb739dSahoka int nand_flash_read(device_t, flash_off_t, size_t, size_t *, uint8_t *);
458c68f5a83Sahoka int nand_flash_erase(device_t, struct flash_erase_instruction *);
459f1e7eb4dSahoka int nand_flash_submit(device_t, struct buf *);
460c68f5a83Sahoka 
461c68f5a83Sahoka /* nand specific functions */
462c68f5a83Sahoka int nand_erase_block(device_t, size_t);
463c68f5a83Sahoka 
4646adb739dSahoka bool nand_isfactorybad(device_t, flash_off_t);
4656adb739dSahoka bool nand_iswornoutbad(device_t, flash_off_t);
4666adb739dSahoka bool nand_isbad(device_t, flash_off_t);
467c68f5a83Sahoka void nand_markbad(device_t, size_t);
468c68f5a83Sahoka 
469c68f5a83Sahoka //int nand_read_page(device_t, size_t, uint8_t *);
470c68f5a83Sahoka int nand_read_oob(device_t, size_t, uint8_t *);
471c68f5a83Sahoka //int nand_program_page(device_t, size_t, const uint8_t *);
472c68f5a83Sahoka 
473c68f5a83Sahoka device_t nand_attach_mi(struct nand_interface *, device_t);
474c68f5a83Sahoka void nand_init_interface(struct nand_interface *);
47510a1f0e4Sjmcneill void nand_attach_mtdparts(device_t, const char *, const char *);
476c68f5a83Sahoka 
477c68f5a83Sahoka /* controller drivers may use these functions to get info about the chip */
478c68f5a83Sahoka void nand_read_id(device_t, uint8_t *, uint8_t *);
479c68f5a83Sahoka int nand_read_parameter_page(device_t, struct onfi_parameter_page *);
480c68f5a83Sahoka 
481c68f5a83Sahoka /*
482c68f5a83Sahoka  * default functions for driver development
483c68f5a83Sahoka  */
484c68f5a83Sahoka void nand_default_select(device_t, bool);
485c68f5a83Sahoka int nand_default_ecc_compute(device_t, const uint8_t *, uint8_t *);
486c68f5a83Sahoka int nand_default_ecc_correct(device_t, uint8_t *, const uint8_t *,
487c68f5a83Sahoka     const uint8_t *);
488c68f5a83Sahoka int nand_default_read_page(device_t, size_t, uint8_t *);
489c68f5a83Sahoka int nand_default_program_page(device_t, size_t, const uint8_t *);
490c68f5a83Sahoka 
49187fd18f8Schristos static __inline void nand_busy(device_t);
49287fd18f8Schristos static __inline void nand_select(device_t, bool);
49387fd18f8Schristos static __inline void nand_command(device_t, uint8_t);
49487fd18f8Schristos static __inline void nand_address(device_t, uint32_t);
49587fd18f8Schristos static __inline void nand_read_buf_1(device_t, void *, size_t);
49687fd18f8Schristos static __inline void nand_read_buf_2(device_t, void *, size_t);
49787fd18f8Schristos static __inline void nand_read_1(device_t, uint8_t *);
49887fd18f8Schristos static __inline void nand_write_buf_1(device_t, const void *, size_t);
49987fd18f8Schristos static __inline void nand_write_buf_2(device_t, const void *, size_t);
50087fd18f8Schristos //static __inline bool nand_block_isbad(device_t, off_t);
50187fd18f8Schristos //static __inline void nand_block_markbad(device_t, off_t);
50287fd18f8Schristos //static __inline bool nand_isbusy(device_t);
503c68f5a83Sahoka 
5042b6ee221Sahoka #endif	/* _NAND_H_ */
505