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