1/*-
2 * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
28 * Vybrid Family NAND Flash Controller (NFC)
29 * Chapter 31, Vybrid Reference Manual, Rev. 5, 07/2013
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD$");
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/proc.h>
38#include <sys/bus.h>
39#include <sys/conf.h>
40#include <sys/kernel.h>
41#include <sys/module.h>
42#include <sys/malloc.h>
43#include <sys/rman.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <sys/time.h>
47
48#include <dev/ofw/ofw_bus.h>
49#include <dev/ofw/ofw_bus_subr.h>
50#include <dev/nand/nand.h>
51#include <dev/nand/nandbus.h>
52
53#include <machine/bus.h>
54#include <machine/fdt.h>
55
56#include "nfc_if.h"
57
58#include <arm/freescale/vybrid/vf_common.h>
59
60enum addr_type {
61	ADDR_NONE,
62	ADDR_ID,
63	ADDR_ROW,
64	ADDR_ROWCOL
65};
66
67struct fsl_nfc_fcm {
68	uint32_t	addr_bits;
69	enum addr_type  addr_type;
70	uint32_t	col_addr_bits;
71	uint32_t	row_addr_bits;
72	u_int		read_ptr;
73	u_int		addr_ptr;
74	u_int		command;
75	u_int		code;
76};
77
78struct vf_nand_softc {
79	struct nand_softc 	nand_dev;
80	bus_space_handle_t 	bsh;
81	bus_space_tag_t		bst;
82	struct resource		*res[2];
83	struct fsl_nfc_fcm	fcm;
84};
85
86static struct resource_spec nfc_spec[] = {
87	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
88	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
89	{ -1, 0 }
90};
91
92static int	vf_nand_attach(device_t);
93static int	vf_nand_probe(device_t);
94static int	vf_nand_send_command(device_t, uint8_t);
95static int	vf_nand_send_address(device_t, uint8_t);
96static int	vf_nand_start_command(device_t);
97static uint8_t	vf_nand_read_byte(device_t);
98static void	vf_nand_read_buf(device_t, void *, uint32_t);
99static void	vf_nand_write_buf(device_t, void *, uint32_t);
100static int	vf_nand_select_cs(device_t, uint8_t);
101static int	vf_nand_read_rnb(device_t);
102
103#define	CMD_READ_PAGE		0x7EE0
104#define	CMD_PROG_PAGE		0x7FC0
105#define	CMD_PROG_PAGE_DMA	0xFFC8
106#define	CMD_ERASE		0x4EC0
107#define	CMD_READ_ID		0x4804
108#define	CMD_READ_STATUS		0x4068
109#define	CMD_RESET		0x4040
110#define	CMD_RANDOM_IN		0x7140
111#define	CMD_RANDOM_OUT		0x70E0
112
113#define	CMD_BYTE2_PROG_PAGE	0x10
114#define	CMD_BYTE2_PAGE_READ	0x30
115#define	CMD_BYTE2_ERASE		0xD0
116
117#define	NFC_CMD1	0x3F00	/* Flash command 1 */
118#define	NFC_CMD2	0x3F04	/* Flash command 2 */
119#define	NFC_CAR		0x3F08	/* Column address */
120#define	NFC_RAR		0x3F0C	/* Row address */
121#define	NFC_RPT		0x3F10	/* Flash command repeat */
122#define	NFC_RAI		0x3F14	/* Row address increment */
123#define	NFC_SR1		0x3F18	/* Flash status 1 */
124#define	NFC_SR2		0x3F1C	/* Flash status 2 */
125#define	NFC_DMA_CH1	0x3F20	/* DMA channel 1 address */
126#define	NFC_DMACFG	0x3F24	/* DMA configuration */
127#define	NFC_SWAP	0x3F28	/* Cach swap */
128#define	NFC_SECSZ	0x3F2C	/* Sector size */
129#define	NFC_CFG		0x3F30	/* Flash configuration */
130#define	NFC_DMA_CH2	0x3F34	/* DMA channel 2 address */
131#define	NFC_ISR		0x3F38	/* Interrupt status */
132
133#define	ECCMODE_SHIFT		17
134#define	AIAD_SHIFT		5
135#define	AIBN_SHIFT		4
136#define	PAGECOUNT_SHIFT		0
137#define	BITWIDTH_SHIFT		7
138#define	BITWIDTH8		0
139#define	BITWIDTH16		1
140#define	PAGECOUNT_MASK		0xf
141
142#define	CMD2_BYTE1_SHIFT	24
143#define	CMD2_CODE_SHIFT		8
144#define	CMD2_BUFNO_SHIFT	1
145#define	CMD2_START_SHIFT	0
146
147static device_method_t vf_nand_methods[] = {
148	DEVMETHOD(device_probe,		vf_nand_probe),
149	DEVMETHOD(device_attach,	vf_nand_attach),
150	DEVMETHOD(nfc_start_command,	vf_nand_start_command),
151	DEVMETHOD(nfc_send_command,	vf_nand_send_command),
152	DEVMETHOD(nfc_send_address,	vf_nand_send_address),
153	DEVMETHOD(nfc_read_byte,	vf_nand_read_byte),
154	DEVMETHOD(nfc_read_buf,		vf_nand_read_buf),
155	DEVMETHOD(nfc_write_buf,	vf_nand_write_buf),
156	DEVMETHOD(nfc_select_cs,	vf_nand_select_cs),
157	DEVMETHOD(nfc_read_rnb,		vf_nand_read_rnb),
158	{ 0, 0 },
159};
160
161static driver_t vf_nand_driver = {
162	"nand",
163	vf_nand_methods,
164	sizeof(struct vf_nand_softc),
165};
166
167static devclass_t vf_nand_devclass;
168DRIVER_MODULE(vf_nand, simplebus, vf_nand_driver, vf_nand_devclass, 0, 0);
169
170static int
171vf_nand_probe(device_t dev)
172{
173
174	if (!ofw_bus_status_okay(dev))
175		return (ENXIO);
176
177	if (!ofw_bus_is_compatible(dev, "fsl,mvf600-nand"))
178		return (ENXIO);
179
180	device_set_desc(dev, "Vybrid Family NAND controller");
181	return (BUS_PROBE_DEFAULT);
182}
183
184static int
185vf_nand_attach(device_t dev)
186{
187	struct vf_nand_softc *sc;
188	int err;
189	int reg;
190
191	sc = device_get_softc(dev);
192	if (bus_alloc_resources(dev, nfc_spec, sc->res)) {
193		device_printf(dev, "could not allocate resources!\n");
194		return (ENXIO);
195	}
196
197	sc->bst = rman_get_bustag(sc->res[0]);
198	sc->bsh = rman_get_bushandle(sc->res[0]);
199
200	/* Size in bytes of one elementary transfer unit */
201	WRITE4(sc, NFC_SECSZ, 2048);
202
203	/* Flash mode width */
204	reg = READ4(sc, NFC_CFG);
205	reg |= (BITWIDTH16 << BITWIDTH_SHIFT);
206
207	/* No correction, ECC bypass */
208	reg &= ~(0x7 << ECCMODE_SHIFT);
209
210	/* Disable Auto-incrementing of flash row address */
211	reg &= ~(0x1 << AIAD_SHIFT);
212
213	/* Disable Auto-incrementing of buffer numbers */
214	reg &= ~(0x1 << AIBN_SHIFT);
215
216	/*
217	 * Number of virtual pages (in one physical flash page)
218	 * to be programmed or read, etc.
219	 */
220	reg &= ~(PAGECOUNT_MASK);
221	reg |= (1 << PAGECOUNT_SHIFT);
222	WRITE4(sc, NFC_CFG, reg);
223
224	nand_init(&sc->nand_dev, dev, NAND_ECC_NONE, 0, 0, NULL, NULL);
225	err = nandbus_create(dev);
226	return (err);
227}
228
229static int
230vf_nand_start_command(device_t dev)
231{
232	struct vf_nand_softc *sc;
233	struct fsl_nfc_fcm *fcm;
234	int reg;
235
236	sc = device_get_softc(dev);
237	fcm = &sc->fcm;
238
239	nand_debug(NDBG_DRV,"vf_nand: start command %x", fcm->command);
240
241	/* CMD2 */
242	reg = READ4(sc, NFC_CMD2);
243	reg &= ~(0xff << CMD2_BYTE1_SHIFT);
244	reg |= (fcm->command << CMD2_BYTE1_SHIFT);
245	WRITE4(sc, NFC_CMD2, reg);
246
247	/* CMD1 */
248	if ((fcm->command == NAND_CMD_READ) ||
249	    (fcm->command == NAND_CMD_PROG) ||
250	    (fcm->command == NAND_CMD_ERASE)) {
251		reg = READ4(sc, NFC_CMD1);
252		reg &= ~(0xff << 24);
253
254		if (fcm->command == NAND_CMD_READ)
255			reg |= (CMD_BYTE2_PAGE_READ << 24);
256		else if (fcm->command == NAND_CMD_PROG)
257			reg |= (CMD_BYTE2_PROG_PAGE << 24);
258		else if (fcm->command == NAND_CMD_ERASE)
259			reg |= (CMD_BYTE2_ERASE << 24);
260
261		WRITE4(sc, NFC_CMD1, reg);
262	}
263
264	/* We work with 1st buffer */
265	reg = READ4(sc, NFC_CMD2);
266	reg &= ~(0xf << CMD2_BUFNO_SHIFT);
267	reg |= (0 << CMD2_BUFNO_SHIFT);
268	WRITE4(sc, NFC_CMD2, reg);
269
270	/* Cmd CODE */
271	reg = READ4(sc, NFC_CMD2);
272	reg &= ~(0xffff << CMD2_CODE_SHIFT);
273	reg |= (fcm->code << CMD2_CODE_SHIFT);
274	WRITE4(sc, NFC_CMD2, reg);
275
276	/* Col */
277	if (fcm->addr_type == ADDR_ROWCOL) {
278		reg = READ4(sc, NFC_CAR);
279		reg &= ~(0xffff);
280		reg |= fcm->col_addr_bits;
281		nand_debug(NDBG_DRV,"setting CAR to 0x%08x\n", reg);
282		WRITE4(sc, NFC_CAR, reg);
283	}
284
285	/* Row */
286	reg = READ4(sc, NFC_RAR);
287	reg &= ~(0xffffff);
288	if (fcm->addr_type == ADDR_ID)
289		reg |= fcm->addr_bits;
290	else
291		reg |= fcm->row_addr_bits;
292	WRITE4(sc, NFC_RAR, reg);
293
294	/* Start */
295	reg = READ4(sc, NFC_CMD2);
296	reg |= (1 << CMD2_START_SHIFT);
297	WRITE4(sc, NFC_CMD2, reg);
298
299	/* Wait command completion */
300	while (READ4(sc, NFC_CMD2) & (1 << CMD2_START_SHIFT))
301		;
302
303	return (0);
304}
305
306static int
307vf_nand_send_command(device_t dev, uint8_t command)
308{
309	struct vf_nand_softc *sc;
310	struct fsl_nfc_fcm *fcm;
311
312	nand_debug(NDBG_DRV,"vf_nand: send command %x", command);
313
314	sc = device_get_softc(dev);
315	fcm = &sc->fcm;
316
317	if ((command == NAND_CMD_READ_END) ||
318	    (command == NAND_CMD_PROG_END) ||
319	    (command == NAND_CMD_ERASE_END)) {
320		return (0);
321	}
322
323	fcm->command = command;
324
325	fcm->code = 0;
326	fcm->read_ptr = 0;
327	fcm->addr_type = 0;
328	fcm->addr_bits = 0;
329
330	fcm->addr_ptr = 0;
331	fcm->col_addr_bits = 0;
332	fcm->row_addr_bits = 0;
333
334	switch (command) {
335	case NAND_CMD_READ:
336		fcm->code = CMD_READ_PAGE;
337		fcm->addr_type = ADDR_ROWCOL;
338		break;
339	case NAND_CMD_PROG:
340		fcm->code = CMD_PROG_PAGE;
341		fcm->addr_type = ADDR_ROWCOL;
342		break;
343	case NAND_CMD_PROG_END:
344		break;
345	case NAND_CMD_ERASE_END:
346		break;
347	case NAND_CMD_RESET:
348		fcm->code = CMD_RESET;
349		break;
350	case NAND_CMD_READ_ID:
351		fcm->code = CMD_READ_ID;
352		fcm->addr_type = ADDR_ID;
353		break;
354	case NAND_CMD_READ_PARAMETER:
355		fcm->code = CMD_READ_PAGE;
356		fcm->addr_type = ADDR_ID;
357		break;
358	case NAND_CMD_STATUS:
359		fcm->code = CMD_READ_STATUS;
360		break;
361	case NAND_CMD_ERASE:
362		fcm->code = CMD_ERASE;
363		fcm->addr_type = ADDR_ROW;
364		break;
365	default:
366		nand_debug(NDBG_DRV, "unknown command %d\n", command);
367		return (1);
368	}
369
370	return (0);
371}
372
373static int
374vf_nand_send_address(device_t dev, uint8_t addr)
375{
376	struct vf_nand_softc *sc;
377	struct fsl_nfc_fcm *fcm;
378
379	nand_debug(NDBG_DRV,"vf_nand: send address %x", addr);
380	sc = device_get_softc(dev);
381	fcm = &sc->fcm;
382
383	nand_debug(NDBG_DRV, "setting addr #%d to 0x%02x\n", fcm->addr_ptr, addr);
384
385	if (fcm->addr_type == ADDR_ID) {
386		fcm->addr_bits = addr;
387	} else if (fcm->addr_type == ADDR_ROWCOL) {
388
389		if (fcm->addr_ptr < 2)
390			fcm->col_addr_bits |= (addr << (fcm->addr_ptr * 8));
391		else
392			fcm->row_addr_bits |= (addr << ((fcm->addr_ptr - 2) * 8));
393
394	} else if (fcm->addr_type == ADDR_ROW)
395		fcm->row_addr_bits |= (addr << (fcm->addr_ptr * 8));
396
397	fcm->addr_ptr += 1;
398
399	return (0);
400}
401
402static uint8_t
403vf_nand_read_byte(device_t dev)
404{
405	struct vf_nand_softc *sc;
406	struct fsl_nfc_fcm *fcm;
407	uint8_t data;
408	int sr1, sr2;
409	int b;
410
411	sc = device_get_softc(dev);
412	fcm = &sc->fcm;
413
414	sr1 = READ4(sc, NFC_SR1);
415	sr2 = READ4(sc, NFC_SR2);
416
417	data = 0;
418	if (fcm->addr_type == ADDR_ID) {
419		b = 32 - ((fcm->read_ptr + 1) * 8);
420		data = (sr1 >> b) & 0xff;
421		fcm->read_ptr++;
422	} else if (fcm->command == NAND_CMD_STATUS) {
423		data = sr2 & 0xff;
424	}
425
426	nand_debug(NDBG_DRV,"vf_nand: read %x", data);
427	return (data);
428}
429
430static void
431vf_nand_read_buf(device_t dev, void* buf, uint32_t len)
432{
433	struct vf_nand_softc *sc;
434	struct fsl_nfc_fcm *fcm;
435	uint16_t *tmp;
436	uint8_t *b;
437	int i;
438
439	b = (uint8_t*)buf;
440	sc = device_get_softc(dev);
441	fcm = &sc->fcm;
442
443	nand_debug(NDBG_DRV, "vf_nand: read_buf len %d", len);
444
445	if (fcm->command == NAND_CMD_READ_PARAMETER) {
446		tmp = malloc(len, M_DEVBUF, M_NOWAIT);
447		bus_read_region_2(sc->res[0], 0x0, tmp, len);
448
449		for (i = 0; i < len; i += 2) {
450			b[i] = tmp[i+1];
451			b[i+1] = tmp[i];
452		}
453
454		free(tmp, M_DEVBUF);
455
456#ifdef NAND_DEBUG
457		for (i = 0; i < len; i++) {
458			if (!(i % 16))
459				printf("%s", i == 0 ? "vf_nand:\n" : "\n");
460			printf(" %x", b[i]);
461			if (i == len - 1)
462				printf("\n");
463		}
464#endif
465
466	} else {
467
468		for (i = 0; i < len; i++) {
469			b[i] = READ1(sc, i);
470
471#ifdef NAND_DEBUG
472			if (!(i % 16))
473				printf("%s", i == 0 ? "vf_nand:\n" : "\n");
474			printf(" %x", b[i]);
475			if (i == len - 1)
476				printf("\n");
477#endif
478		}
479
480	}
481}
482
483static void
484vf_nand_write_buf(device_t dev, void* buf, uint32_t len)
485{
486	struct vf_nand_softc *sc;
487	struct fsl_nfc_fcm *fcm;
488	uint8_t *b;
489	int i;
490
491	b = (uint8_t*)buf;
492	sc = device_get_softc(dev);
493	fcm = &sc->fcm;
494
495	nand_debug(NDBG_DRV,"vf_nand: write_buf len %d", len);
496
497	for (i = 0; i < len; i++) {
498		WRITE1(sc, i, b[i]);
499
500#ifdef NAND_DEBUG
501		if (!(i % 16))
502			printf("%s", i == 0 ? "vf_nand:\n" : "\n");
503		printf(" %x", b[i]);
504		if (i == len - 1)
505			printf("\n");
506#endif
507
508	}
509}
510
511static int
512vf_nand_select_cs(device_t dev, uint8_t cs)
513{
514
515	if (cs > 0)
516		return (ENODEV);
517
518	return (0);
519}
520
521static int
522vf_nand_read_rnb(device_t dev)
523{
524
525	/* no-op */
526	return (0); /* ready */
527}
528