]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/arm/freescale/vybrid/vf_nfc.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / arm / freescale / vybrid / vf_nfc.c
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
60 enum addr_type {
61         ADDR_NONE,
62         ADDR_ID,
63         ADDR_ROW,
64         ADDR_ROWCOL
65 };
66
67 struct 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
78 struct 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
86 static struct resource_spec nfc_spec[] = {
87         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
88         { SYS_RES_IRQ,          0,      RF_ACTIVE },
89         { -1, 0 }
90 };
91
92 static int      vf_nand_attach(device_t);
93 static int      vf_nand_probe(device_t);
94 static int      vf_nand_send_command(device_t, uint8_t);
95 static int      vf_nand_send_address(device_t, uint8_t);
96 static int      vf_nand_start_command(device_t);
97 static uint8_t  vf_nand_read_byte(device_t);
98 static void     vf_nand_read_buf(device_t, void *, uint32_t);
99 static void     vf_nand_write_buf(device_t, void *, uint32_t);
100 static int      vf_nand_select_cs(device_t, uint8_t);
101 static 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
147 static 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
161 static driver_t vf_nand_driver = {
162         "nand",
163         vf_nand_methods,
164         sizeof(struct vf_nand_softc),
165 };
166
167 static devclass_t vf_nand_devclass;
168 DRIVER_MODULE(vf_nand, simplebus, vf_nand_driver, vf_nand_devclass, 0, 0);
169
170 static int
171 vf_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
184 static int
185 vf_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
229 static int
230 vf_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
306 static int
307 vf_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
373 static int
374 vf_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
402 static uint8_t
403 vf_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
430 static void
431 vf_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
483 static void
484 vf_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
511 static int
512 vf_nand_select_cs(device_t dev, uint8_t cs)
513 {
514
515         if (cs > 0)
516                 return (ENODEV);
517
518         return (0);
519 }
520
521 static int
522 vf_nand_read_rnb(device_t dev)
523 {
524
525         /* no-op */
526         return (0); /* ready */
527 }