1193323Sed/*	$NetBSD: nor.h,v 1.5 2018/04/19 21:50:09 christos Exp $	*/
2193323Sed
3193323Sed/*-
4193323Sed * Copyright (c) 2011 Department of Software Engineering,
5193323Sed *		      University of Szeged, Hungary
6193323Sed * Copyright (c) 2011 Adam Hoka <ahoka@NetBSD.org>
7193323Sed * All rights reserved.
8193323Sed *
9193323Sed * This code is derived from software contributed to The NetBSD Foundation
10193323Sed * by the Department of Software Engineering, University of Szeged, Hungary
11193323Sed *
12193323Sed * Redistribution and use in source and binary forms, with or without
13193323Sed * modification, are permitted provided that the following conditions
14193323Sed * are met:
15193323Sed * 1. Redistributions of source code must retain the above copyright
16193323Sed *    notice, this list of conditions and the following disclaimer.
17193323Sed * 2. Redistributions in binary form must reproduce the above copyright
18193323Sed *    notice, this list of conditions and the following disclaimer in the
19193323Sed *    documentation and/or other materials provided with the distribution.
20193323Sed *
21218893Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22193323Sed * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23193323Sed * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24193323Sed * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25193323Sed * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26202375Srdivacky * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27193323Sed * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28193323Sed * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29193323Sed * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31193323Sed * SUCH DAMAGE.
32193323Sed */
33193323Sed
34195340Sed#ifndef _NOR_H_
35195340Sed#define _NOR_H_
36203954Srdivacky
37193323Sed#include <sys/param.h>
38193323Sed#include <sys/cdefs.h>
39193323Sed
40193323Sed#include <sys/bufq.h>
41193323Sed#include <sys/buf.h>
42193323Sed#include <sys/device.h>
43193323Sed
44193323Sed#include <sys/bus.h>
45198090Srdivacky
46193323Sed#include <dev/flash/flash.h>
47193323Sed#include <dev/flash/flash_io.h>
48193323Sed
49193323Sed#ifdef NOR_DEBUG
50193323Sed#define DPRINTF(x)	do { printf x ; } while (0)
51221345Sdim#else
52193323Sed#define DPRINTF(x)
53193323Sed#endif
54193323Sed
55193323Sed/**
56193323Sed * nor_chip: structure containing the required information
57193323Sed *	      about the NOR chip.
58193323Sed */
59193323Sedstruct nor_chip {
60193323Sed	struct nor_ecc *nc_ecc; 	/* ecc information */
61193323Sed	uint8_t	*nc_oob_cache;		/* buffer for oob cache */
62193323Sed	uint8_t *nc_page_cache;		/* buffer for page cache */
63193323Sed	uint8_t *nc_ecc_cache;
64193323Sed	size_t nc_size;			/* storage size in bytes */
65193323Sed	size_t nc_page_size;		/* page (write buf) size in bytes */
66195340Sed	size_t nc_line_size;		/* read line in bytes */
67195340Sed	size_t nc_block_pages;		/* block size in pages */
68203954Srdivacky	size_t nc_block_size;		/* block size in bytes */
69203954Srdivacky	size_t nc_spare_size;		/* spare (oob) size in bytes */
70193323Sed	uint32_t nc_lun_blocks;		/* LUN size in blocks */
71193323Sed	uint32_t nc_flags;		/* bitfield flags */
72193323Sed	uint32_t nc_quirks;		/* bitfield quirks */
73193323Sed	unsigned int nc_page_shift;	/* page shift for page alignment */
74193323Sed	unsigned int nc_page_mask;	/* page mask for page alignment */
75193323Sed	unsigned int nc_block_shift;	/* write shift */
76193323Sed	unsigned int nc_block_mask;	/* write mask */
77193323Sed	uint8_t nc_num_luns;		/* number of LUNs */
78193323Sed	uint8_t nc_manf_id;		/* manufacturer id */
79193323Sed	uint8_t nc_dev_id;		/* device id  */
80193323Sed	uint8_t nc_badmarker_offs;	/* offset for marking bad blocks */
81193323Sed};
82193323Sed
83193323Sed/* driver softc for nor */
84193323Sedstruct nor_softc {
85195098Sed	device_t sc_dev;
86195098Sed	device_t sc_controller_dev;
87195098Sed	struct flash_interface sc_flash_if;
88193323Sed	struct nor_interface *sc_nor_if;
89193323Sed	void *nor_softc;
90193323Sed	struct nor_chip sc_chip;
91223017Sdim	bus_addr_t sc_bus_addr;		/* chip base address */
92193323Sed	bus_size_t sc_bus_size;		/* total NOR size */
93193323Sed	off_t sc_part_offset;		/* partition start, offset from base */
94193323Sed	size_t sc_part_size;		/* partition size */
95193323Sed	bus_space_tag_t sc_bst;
96193323Sed	bus_space_handle_t sc_bsh;
97195098Sed	kmutex_t sc_device_lock; /* serialize access to chip */
98195098Sed	struct flash_io sc_flash_io;
99195098Sed};
100193323Sed
101193323Sed/* structure holding the nor api */
102193323Sedstruct nor_interface {
103195098Sed	/* basic nor controller commands */
104195098Sed	int  (*scan_media)(device_t self, struct nor_chip *chip);
105195098Sed	void (*init) (device_t);
106193323Sed	void (*select) (device_t, bool); /* optional */
107193323Sed	void (*read_1) (device_t, flash_off_t, uint8_t *);
108193323Sed	void (*read_2) (device_t, flash_off_t, uint16_t *);
109207618Srdivacky	void (*read_4) (device_t, flash_off_t, uint32_t *);
110195098Sed	void (*read_buf_1) (device_t, flash_off_t, uint8_t *, size_t);
111195098Sed	void (*read_buf_2) (device_t, flash_off_t, uint16_t *, size_t);
112195098Sed	void (*read_buf_4) (device_t, flash_off_t, uint32_t *, size_t);
113193323Sed	void (*write_1) (device_t, flash_off_t, uint8_t);
114193323Sed	void (*write_2) (device_t, flash_off_t, uint16_t);
115193323Sed	void (*write_4) (device_t, flash_off_t, uint32_t);
116193323Sed	void (*write_buf_1) (device_t, flash_off_t, const uint8_t *, size_t);
117195098Sed	void (*write_buf_2) (device_t, flash_off_t, const uint16_t *, size_t);
118198090Srdivacky	void (*write_buf_4) (device_t, flash_off_t, const uint32_t *, size_t);
119193323Sed	int  (*busy) (device_t, flash_off_t, u_long);
120193323Sed
121193323Sed	int (*read_page) (device_t, flash_off_t, uint8_t *);
122198090Srdivacky	int (*program_page) (device_t, flash_off_t, const uint8_t *);
123193323Sed	int (*erase_block) (device_t, flash_off_t);
124193323Sed	int (*erase_all) (device_t);
125193323Sed
126193323Sed	void *private;		/* where to attach e.g. struct cfi */
127218893Sdim	int access_width;	/* x8/x16/x32: 1/2/4 */
128218893Sdim
129218893Sdim	/* flash partition information */
130218893Sdim	const struct flash_partition *part_info;
131218893Sdim	int part_num;
132218893Sdim};
133218893Sdim
134193323Sed/* attach args */
135195098Sedstruct nor_attach_args {
136193323Sed	struct nor_interface *naa_nor_if;
137193323Sed};
138202375Srdivacky
139204642Srdivackystatic __inline bool
140202375Srdivackynor_busy(device_t device, flash_off_t offset, u_long usec)
141202375Srdivacky{
142202375Srdivacky	struct nor_softc *sc = device_private(device);
143205218Srdivacky	bool rv;
144205218Srdivacky
145205218Srdivacky	KASSERT(sc->sc_nor_if->select != NULL);
146205218Srdivacky	KASSERT(sc->sc_controller_dev != NULL);
147205218Srdivacky
148218893Sdim	sc->sc_nor_if->select(sc->sc_controller_dev, true);
149221345Sdim
150221345Sdim	if (sc->sc_nor_if->busy != NULL) {
151221345Sdim		rv = sc->sc_nor_if->busy(sc->sc_controller_dev, offset, usec);
152221345Sdim	} else {
153221345Sdim		DELAY(usec);
154221345Sdim		rv = false;
155221345Sdim	}
156221345Sdim
157221345Sdim	sc->sc_nor_if->select(sc->sc_controller_dev, false);
158221345Sdim
159218893Sdim	return rv;
160218893Sdim}
161218893Sdim
162218893Sdimstatic __inline void
163218893Sdimnor_select(device_t self, bool enable)
164218893Sdim{
165218893Sdim	struct nor_softc *sc = device_private(self);
166218893Sdim
167218893Sdim	KASSERT(sc->sc_nor_if->select != NULL);
168218893Sdim	KASSERT(sc->sc_controller_dev != NULL);
169218893Sdim
170218893Sdim	sc->sc_nor_if->select(sc->sc_controller_dev, enable);
171193323Sed}
172193323Sed
173193323Sedstatic __inline void
174193323Sednor_read_1(device_t self, flash_off_t offset, uint8_t *data)
175193323Sed{
176193323Sed	struct nor_softc *sc = device_private(self);
177193323Sed
178193323Sed	KASSERT(sc->sc_nor_if->read_1 != NULL);
179193323Sed	KASSERT(sc->sc_controller_dev != NULL);
180193323Sed
181193323Sed	sc->sc_nor_if->read_1(sc->sc_controller_dev, offset, data);
182193323Sed}
183193323Sed
184193323Sedstatic __inline void
185193323Sednor_read_2(device_t self, flash_off_t offset, uint16_t *data)
186193323Sed{
187193323Sed	struct nor_softc *sc = device_private(self);
188193323Sed
189193323Sed	KASSERT(sc->sc_nor_if->read_2 != NULL);
190193323Sed	KASSERT(sc->sc_controller_dev != NULL);
191193323Sed
192193323Sed	sc->sc_nor_if->read_2(sc->sc_controller_dev, offset, data);
193193323Sed}
194193323Sed
195193323Sedstatic __inline void
196193323Sednor_read_4(device_t self, flash_off_t offset, uint32_t *data)
197193323Sed{
198193323Sed	struct nor_softc *sc = device_private(self);
199193323Sed
200193323Sed	KASSERT(sc->sc_nor_if->read_4 != NULL);
201193323Sed	KASSERT(sc->sc_controller_dev != NULL);
202193323Sed
203193323Sed	sc->sc_nor_if->read_4(sc->sc_controller_dev, offset, data);
204193323Sed}
205193323Sed
206193323Sedstatic __inline void
207193323Sednor_write_1(device_t self, flash_off_t offset, uint8_t data)
208193323Sed{
209193323Sed	struct nor_softc *sc = device_private(self);
210193323Sed
211193323Sed	KASSERT(sc->sc_nor_if->write_1 != NULL);
212193323Sed	KASSERT(sc->sc_controller_dev != NULL);
213193323Sed
214193323Sed	sc->sc_nor_if->write_1(sc->sc_controller_dev, offset, data);
215193323Sed}
216193323Sed
217193323Sedstatic __inline void
218193323Sednor_write_2(device_t self, flash_off_t offset, uint16_t data)
219193323Sed{
220193323Sed	struct nor_softc *sc = device_private(self);
221193323Sed
222193323Sed	KASSERT(sc->sc_nor_if->write_2 != NULL);
223193323Sed	KASSERT(sc->sc_controller_dev != NULL);
224193323Sed
225193323Sed	sc->sc_nor_if->write_2(sc->sc_controller_dev, offset, data);
226193323Sed}
227193323Sed
228193323Sedstatic __inline void
229193323Sednor_write_4(device_t self, flash_off_t offset, uint16_t data)
230193323Sed{
231193323Sed	struct nor_softc *sc = device_private(self);
232198090Srdivacky
233193323Sed	KASSERT(sc->sc_nor_if->write_4 != NULL);
234193323Sed	KASSERT(sc->sc_controller_dev != NULL);
235193323Sed
236193323Sed	sc->sc_nor_if->write_4(sc->sc_controller_dev, offset, data);
237193323Sed}
238193323Sed
239193323Sedstatic __inline void
240193323Sednor_read_buf_1(device_t self, flash_off_t offset, void *buf, size_t size)
241193323Sed{
242193323Sed	struct nor_softc *sc = device_private(self);
243193323Sed
244193323Sed	KASSERT(sc->sc_nor_if->read_buf_1 != NULL);
245193323Sed	KASSERT(sc->sc_controller_dev != NULL);
246193323Sed
247193323Sed	sc->sc_nor_if->read_buf_1(sc->sc_controller_dev, offset, buf, size);
248193323Sed}
249193323Sed
250193323Sedstatic __inline void
251193323Sednor_read_buf_2(device_t self, flash_off_t offset, void *buf, size_t size)
252193323Sed{
253195340Sed	struct nor_softc *sc = device_private(self);
254195340Sed
255195340Sed	KASSERT(sc->sc_nor_if->read_buf_2 != NULL);
256193323Sed	KASSERT(sc->sc_controller_dev != NULL);
257193323Sed
258193323Sed	sc->sc_nor_if->read_buf_2(sc->sc_controller_dev, offset, buf, size);
259193323Sed}
260
261static __inline void
262nor_read_buf_4(device_t self, flash_off_t offset, void *buf, size_t size)
263{
264	struct nor_softc *sc = device_private(self);
265
266	KASSERT(sc->sc_nor_if->read_buf_4 != NULL);
267	KASSERT(sc->sc_controller_dev != NULL);
268
269	sc->sc_nor_if->read_buf_4(sc->sc_controller_dev, offset, buf, size);
270}
271
272static __inline void
273nor_write_buf_1(device_t self, flash_off_t offset, const void *buf, size_t size)
274{
275	struct nor_softc *sc = device_private(self);
276
277	KASSERT(sc->sc_nor_if->write_buf_1 != NULL);
278	KASSERT(sc->sc_controller_dev != NULL);
279
280	sc->sc_nor_if->write_buf_1(sc->sc_controller_dev, offset, buf, size);
281}
282
283static __inline void
284nor_write_buf_2(device_t self, flash_off_t offset, const void *buf, size_t size)
285{
286	struct nor_softc *sc = device_private(self);
287
288	KASSERT(sc->sc_nor_if->write_buf_2 != NULL);
289	KASSERT(sc->sc_controller_dev != NULL);
290
291	sc->sc_nor_if->write_buf_2(sc->sc_controller_dev, offset, buf, size);
292}
293
294static __inline void
295nor_write_buf_4(device_t self, flash_off_t offset, const void *buf, size_t size)
296{
297	struct nor_softc *sc = device_private(self);
298
299	KASSERT(sc->sc_nor_if->write_buf_4 != NULL);
300	KASSERT(sc->sc_controller_dev != NULL);
301
302	sc->sc_nor_if->write_buf_4(sc->sc_controller_dev, offset, buf, size);
303}
304
305static __inline int
306nor_read_page(device_t self, flash_off_t offset, uint8_t *data)
307{
308	struct nor_softc *sc = device_private(self);
309
310	KASSERT(sc->sc_nor_if->read_page != NULL);
311
312	return sc->sc_nor_if->read_page(self, offset, data);
313}
314
315static __inline int
316nor_program_page(device_t self, flash_off_t offset, const uint8_t *data)
317{
318	struct nor_softc *sc = device_private(self);
319
320	KASSERT(sc->sc_nor_if->program_page != NULL);
321
322	return sc->sc_nor_if->program_page(self, offset, data);
323}
324
325static __inline int
326nor_erase_all(device_t self)
327{
328	struct nor_softc *sc = device_private(self);
329
330	KASSERT(sc->sc_nor_if->erase_all != NULL);
331
332	return sc->sc_nor_if->erase_all(self);
333}
334
335static __inline int
336nor_erase_block(device_t self, flash_off_t offset)
337{
338	struct nor_softc *sc = device_private(self);
339
340	KASSERT(sc->sc_nor_if->erase_block != NULL);
341
342	return sc->sc_nor_if->erase_block(self, offset);
343}
344
345/* Manufacturer IDs defined by JEDEC */
346enum {
347	NOR_MFR_UNKNOWN		= 0x00,
348	NOR_MFR_AMD		= 0x01,
349	NOR_MFR_FUJITSU		= 0x04,
350	NOR_MFR_RENESAS		= 0x07,
351	NOR_MFR_STMICRO		= 0x20,
352	NOR_MFR_MICRON		= 0x2c,
353	NOR_MFR_NATIONAL	= 0x8f,
354	NOR_MFR_TOSHIBA		= 0x98,
355	NOR_MFR_HYNIX		= 0xad,
356	NOR_MFGR_MACRONIX	= 0xc2,
357	NOR_MFR_SAMSUNG		= 0xec
358};
359
360struct nor_manufacturer {
361	int id;
362	const char *name;
363};
364
365extern const struct nor_manufacturer nor_mfrs[];
366
367/* public nor specific functions */
368device_t nor_attach_mi(struct nor_interface *, device_t);
369void nor_init_interface(struct nor_interface *);
370
371
372#endif	/* _NOR_H_ */
373