]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/nand/nfc_fsl.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / nand / nfc_fsl.c
1 /*-
2  * Copyright (C) 2012 Juniper Networks, Inc.
3  * Copyright (C) 2009-2012 Semihalf
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 /*
28  * TODO :
29  *
30  *  -- test support for small pages
31  *  -- support for reading ONFI parameters
32  *  -- support for cached and interleaving commands
33  *  -- proper setting of AL bits in FMR
34  */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/proc.h>
42 #include <sys/bus.h>
43 #include <sys/conf.h>
44 #include <sys/kernel.h>
45 #include <sys/module.h>
46 #include <sys/malloc.h>
47 #include <sys/rman.h>
48 #include <sys/sysctl.h>
49 #include <sys/time.h>
50 #include <sys/kdb.h>
51
52 #include <machine/bus.h>
53 #include <machine/fdt.h>
54
55 #include <dev/ofw/ofw_bus.h>
56 #include <dev/ofw/ofw_bus_subr.h>
57
58 #include <powerpc/mpc85xx/lbc.h>
59
60 #include <dev/nand/nand.h>
61 #include <dev/nand/nandbus.h>
62
63 #include "nfc_fsl.h"
64
65 #include "nfc_if.h"
66
67 #define LBC_READ(regname)       lbc_read_reg(dev, (LBC85XX_ ## regname))
68 #define LBC_WRITE(regname, val) lbc_write_reg(dev, (LBC85XX_ ## regname), val)
69
70 enum addr_type {
71         ADDR_NONE,
72         ADDR_ID,
73         ADDR_ROW,
74         ADDR_ROWCOL
75 };
76
77 struct fsl_nfc_fcm {
78         /* Read-only after initialization */
79         uint32_t        reg_fmr;
80
81         /* To be preserved across "start_command" */
82         u_int           buf_ofs;
83         u_int           read_ptr;
84         u_int           status:1;
85
86         /* Command state -- cleared by "start_command" */
87         uint32_t        fcm_startzero;
88         uint32_t        reg_fcr;
89         uint32_t        reg_fir;
90         uint32_t        reg_mdr;
91         uint32_t        reg_fbcr;
92         uint32_t        reg_fbar;
93         uint32_t        reg_fpar;
94         u_int           cmdnr;
95         u_int           opnr;
96         u_int           pg_ofs;
97         enum addr_type  addr_type;
98         u_int           addr_bytes;
99         u_int           row_addr;
100         u_int           column_addr;
101         u_int           data_fir:8;
102         uint32_t        fcm_endzero;
103 };
104
105 struct fsl_nand_softc {
106         struct nand_softc               nand_dev;
107         device_t                        dev;
108         struct resource                 *res;
109         int                             rid;            /* Resourceid */
110         struct lbc_devinfo              *dinfo;
111         struct fsl_nfc_fcm              fcm;
112         uint8_t                         col_cycles;
113         uint8_t                         row_cycles;
114         uint16_t                        pgsz;           /* Page size */
115 };
116
117 static int      fsl_nand_attach(device_t dev);
118 static int      fsl_nand_probe(device_t dev);
119 static int      fsl_nand_detach(device_t dev);
120
121 static int      fsl_nfc_select_cs(device_t dev, uint8_t cs);
122 static int      fsl_nfc_read_rnb(device_t dev);
123 static int      fsl_nfc_send_command(device_t dev, uint8_t command);
124 static int      fsl_nfc_send_address(device_t dev, uint8_t address);
125 static uint8_t  fsl_nfc_read_byte(device_t dev);
126 static int      fsl_nfc_start_command(device_t dev);
127 static void     fsl_nfc_read_buf(device_t dev, void *buf, uint32_t len);
128 static void     fsl_nfc_write_buf(device_t dev, void *buf, uint32_t len);
129
130 static device_method_t fsl_nand_methods[] = {
131         DEVMETHOD(device_probe,         fsl_nand_probe),
132         DEVMETHOD(device_attach,        fsl_nand_attach),
133         DEVMETHOD(device_detach,        fsl_nand_detach),
134
135         DEVMETHOD(nfc_select_cs,        fsl_nfc_select_cs),
136         DEVMETHOD(nfc_read_rnb,         fsl_nfc_read_rnb),
137         DEVMETHOD(nfc_start_command,    fsl_nfc_start_command),
138         DEVMETHOD(nfc_send_command,     fsl_nfc_send_command),
139         DEVMETHOD(nfc_send_address,     fsl_nfc_send_address),
140         DEVMETHOD(nfc_read_byte,        fsl_nfc_read_byte),
141         DEVMETHOD(nfc_read_buf,         fsl_nfc_read_buf),
142         DEVMETHOD(nfc_write_buf,        fsl_nfc_write_buf),
143         { 0, 0 },
144 };
145
146 static driver_t fsl_nand_driver = {
147         "nand",
148         fsl_nand_methods,
149         sizeof(struct fsl_nand_softc),
150 };
151
152 static devclass_t fsl_nand_devclass;
153
154 DRIVER_MODULE(fsl_nand, lbc, fsl_nand_driver, fsl_nand_devclass,
155     0, 0);
156
157 static int fsl_nand_build_address(device_t dev, uint32_t page, uint32_t column);
158 static int fsl_nand_chip_preprobe(device_t dev, struct nand_id *id);
159
160 #ifdef NAND_DEBUG_TIMING
161 static device_t fcm_devs[8];
162 #endif
163
164 #define CMD_SHIFT(cmd_num)      (24 - ((cmd_num) * 8))
165 #define OP_SHIFT(op_num)        (28 - ((op_num) * 4))
166
167 #define FSL_LARGE_PAGE_SIZE     (2112)
168 #define FSL_SMALL_PAGE_SIZE     (528)
169
170 static void
171 fsl_nand_init_regs(struct fsl_nand_softc *sc)
172 {
173         uint32_t or_v, br_v;
174         device_t dev;
175
176         dev = sc->dev;
177
178         sc->fcm.reg_fmr = (15 << FMR_CWTO_SHIFT);
179
180         /*
181          * Setup 4 row cycles and hope that chip ignores superfluous address
182          * bytes.
183          */
184         sc->fcm.reg_fmr |= (2 << FMR_AL_SHIFT);
185
186         /* Reprogram BR(x) */
187         br_v = lbc_read_reg(dev, LBC85XX_BR(sc->dinfo->di_bank));
188         br_v &= 0xffff8000;
189         br_v |= 1 << 11;        /* 8-bit port size */
190         br_v |= 0 << 9;         /* No ECC checking and generation */
191         br_v |= 1 << 5;         /* FCM machine */
192         br_v |= 1;              /* Valid */
193         lbc_write_reg(dev, LBC85XX_BR(sc->dinfo->di_bank), br_v);
194
195         /* Reprogram OR(x) */
196         or_v = lbc_read_reg(dev, LBC85XX_OR(sc->dinfo->di_bank));
197         or_v &= 0xfffffc00;
198         or_v |= 0x03AE;         /* Default POR timing */
199         lbc_write_reg(dev, LBC85XX_OR(sc->dinfo->di_bank), or_v);
200
201         if (or_v & OR_FCM_PAGESIZE) {
202                 sc->pgsz = FSL_LARGE_PAGE_SIZE;
203                 sc->col_cycles = 2;
204                 nand_debug(NDBG_DRV, "%s: large page NAND device at #%d",
205                     device_get_nameunit(dev), sc->dinfo->di_bank);
206         } else {
207                 sc->pgsz = FSL_SMALL_PAGE_SIZE;
208                 sc->col_cycles = 1;
209                 nand_debug(NDBG_DRV, "%s: small page NAND device at #%d",
210                     device_get_nameunit(dev), sc->dinfo->di_bank);
211         }
212 }
213
214 static int
215 fsl_nand_probe(device_t dev)
216 {
217
218         if (!ofw_bus_is_compatible(dev, "fsl,elbc-fcm-nand"))
219                 return (ENXIO);
220
221         device_set_desc(dev, "Freescale localbus FCM Controller");
222         return (BUS_PROBE_DEFAULT);
223 }
224
225 static int
226 fsl_nand_attach(device_t dev)
227 {
228         struct fsl_nand_softc *sc;
229         struct nand_id id;
230         struct nand_params *param;
231         uint32_t num_pages;
232
233         sc = device_get_softc(dev);
234         sc->dev = dev;
235         sc->dinfo = device_get_ivars(dev);
236
237         sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
238             RF_ACTIVE);
239         if (sc->res == NULL) {
240                 device_printf(dev, "could not allocate resources!\n");
241                 return (ENXIO);
242         }
243
244         bzero(&sc->fcm, sizeof(sc->fcm));
245
246         /* Init register and check if HW ECC turned on */
247         fsl_nand_init_regs(sc);
248
249         /* Chip is probed, so determine number of row address cycles */
250         fsl_nand_chip_preprobe(dev, &id);
251         param = nand_get_params(&id);
252         if (param != NULL) {
253                 num_pages = (param->chip_size << 20) / param->page_size;
254                 while(num_pages) {
255                         sc->row_cycles++;
256                         num_pages >>= 8;
257                 }
258
259                 sc->fcm.reg_fmr &= ~(FMR_AL);
260                 sc->fcm.reg_fmr |= (sc->row_cycles - 2) << FMR_AL_SHIFT;
261         }
262
263         nand_init(&sc->nand_dev, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL);
264
265 #ifdef NAND_DEBUG_TIMING
266         fcm_devs[sc->dinfo->di_bank] = dev;
267 #endif
268
269         return (nandbus_create(dev));
270 }
271
272 static int
273 fsl_nand_detach(device_t dev)
274 {
275         struct fsl_nand_softc *sc;
276
277         sc = device_get_softc(dev);
278
279         if (sc->res != NULL)
280                 bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
281
282         return (0);
283 }
284
285 static int
286 fsl_nfc_select_cs(device_t dev, uint8_t cs)
287 {
288
289         // device_printf(dev, "%s(cs=%u)\n", __func__, cs);
290         return ((cs > 0) ? EINVAL : 0);
291 }
292
293 static int
294 fsl_nfc_read_rnb(device_t dev)
295 {
296
297         // device_printf(dev, "%s()\n", __func__);
298         return (0);
299 }
300
301 static int
302 fsl_nfc_send_command(device_t dev, uint8_t command)
303 {
304         struct fsl_nand_softc *sc;
305         struct fsl_nfc_fcm *fcm;
306         uint8_t fir_op;
307
308         // device_printf(dev, "%s(command=%u)\n", __func__, command);
309
310         sc = device_get_softc(dev);
311         fcm = &sc->fcm;
312
313         if (command == NAND_CMD_PROG_END) {
314                 fcm->reg_fir |= (FIR_OP_WB << OP_SHIFT(fcm->opnr));
315                 fcm->opnr++;
316         }
317         fcm->reg_fcr |= command << CMD_SHIFT(fcm->cmdnr);
318         fir_op = (fcm->cmdnr == 0) ? FIR_OP_CW0 : FIR_OP_CM(fcm->cmdnr);
319         fcm->cmdnr++;
320
321         fcm->reg_fir |= (fir_op << OP_SHIFT(fcm->opnr));
322         fcm->opnr++;
323
324         switch (command) {
325         case NAND_CMD_READ_ID:
326                 fcm->data_fir = FIR_OP_RBW;
327                 fcm->addr_type = ADDR_ID;
328                 break;
329         case NAND_CMD_SMALLOOB:
330                 fcm->pg_ofs += 256;
331                 /*FALLTHROUGH*/
332         case NAND_CMD_SMALLB:
333                 fcm->pg_ofs += 256;
334                 /*FALLTHROUGH*/
335         case NAND_CMD_READ: /* NAND_CMD_SMALLA */
336                 fcm->data_fir = FIR_OP_RBW;
337                 fcm->addr_type = ADDR_ROWCOL;
338                 break;
339         case NAND_CMD_STATUS:
340                 fcm->data_fir = FIR_OP_RS;
341                 fcm->status = 1;
342                 break;
343         case NAND_CMD_ERASE:
344                 fcm->addr_type = ADDR_ROW;
345                 break;
346         case NAND_CMD_PROG:
347                 fcm->addr_type = ADDR_ROWCOL;
348                 break;
349         }
350         return (0);
351 }
352
353 static int
354 fsl_nfc_send_address(device_t dev, uint8_t addr)
355 {
356         struct fsl_nand_softc *sc;
357         struct fsl_nfc_fcm *fcm;
358         uint32_t addr_bits;
359
360         // device_printf(dev, "%s(address=%u)\n", __func__, addr);
361
362         sc = device_get_softc(dev);
363         fcm = &sc->fcm;
364
365         KASSERT(fcm->addr_type != ADDR_NONE,
366             ("controller doesn't expect address cycle"));
367
368         addr_bits = addr;
369
370         if (fcm->addr_type == ADDR_ID) {
371                 fcm->reg_fir |= (FIR_OP_UA << OP_SHIFT(fcm->opnr));
372                 fcm->opnr++;
373
374                 fcm->reg_fbcr = 5;
375                 fcm->reg_fbar = 0;
376                 fcm->reg_fpar = 0;
377                 fcm->reg_mdr = addr_bits;
378                 fcm->buf_ofs = 0;
379                 fcm->read_ptr = 0;
380                 return (0);
381         }
382
383         if (fcm->addr_type == ADDR_ROW) {
384                 addr_bits <<= fcm->addr_bytes * 8;
385                 fcm->row_addr |= addr_bits;
386                 fcm->addr_bytes++;
387                 if (fcm->addr_bytes < sc->row_cycles)
388                         return (0);
389         } else {
390                 if (fcm->addr_bytes < sc->col_cycles) {
391                         addr_bits <<= fcm->addr_bytes * 8;
392                         fcm->column_addr |= addr_bits;
393                 } else {
394                         addr_bits <<= (fcm->addr_bytes - sc->col_cycles) * 8;
395                         fcm->row_addr |= addr_bits;
396                 }
397                 fcm->addr_bytes++;
398                 if (fcm->addr_bytes < (sc->row_cycles + sc->col_cycles))
399                         return (0);
400         }
401
402         return (fsl_nand_build_address(dev, fcm->row_addr, fcm->column_addr));
403 }
404
405 static int
406 fsl_nand_build_address(device_t dev, uint32_t row, uint32_t column)
407 {
408         struct fsl_nand_softc *sc;
409         struct fsl_nfc_fcm *fcm;
410         uint32_t byte_count = 0;
411         uint32_t block_address = 0;
412         uint32_t page_address = 0;
413
414         sc = device_get_softc(dev);
415         fcm = &sc->fcm;
416
417         fcm->read_ptr = 0;
418         fcm->buf_ofs = 0;
419
420         if (fcm->addr_type == ADDR_ROWCOL) {
421                 fcm->reg_fir |= (FIR_OP_CA << OP_SHIFT(fcm->opnr));
422                 fcm->opnr++;
423
424                 column += fcm->pg_ofs;
425                 fcm->pg_ofs = 0;
426
427                 page_address |= column;
428
429                 if (column != 0) {
430                         byte_count = sc->pgsz - column;
431                         fcm->read_ptr = column;
432                 }
433         }
434
435         fcm->reg_fir |= (FIR_OP_PA << OP_SHIFT(fcm->opnr));
436         fcm->opnr++;
437
438         if (sc->pgsz == FSL_LARGE_PAGE_SIZE) {
439                 block_address = row >> 6;
440                 page_address |= ((row << FPAR_LP_PI_SHIFT) & FPAR_LP_PI);
441                 fcm->buf_ofs = (row & 1) * 4096;
442         } else {
443                 block_address = row >> 5;
444                 page_address |= ((row << FPAR_SP_PI_SHIFT) & FPAR_SP_PI);
445                 fcm->buf_ofs = (row & 7) * 1024;
446         }
447
448         fcm->reg_fbcr = byte_count;
449         fcm->reg_fbar = block_address;
450         fcm->reg_fpar = page_address;
451         return (0);
452 }
453
454 static int
455 fsl_nfc_start_command(device_t dev)
456 {
457         struct fsl_nand_softc *sc;
458         struct fsl_nfc_fcm *fcm;
459         uint32_t fmr, ltesr_v;
460         int error, timeout;
461
462         // device_printf(dev, "%s()\n", __func__);
463
464         sc = device_get_softc(dev);
465         fcm = &sc->fcm;
466
467         fmr = fcm->reg_fmr | FMR_OP;
468
469         if (fcm->data_fir)
470                 fcm->reg_fir |= (fcm->data_fir << OP_SHIFT(fcm->opnr));
471
472         LBC_WRITE(FIR, fcm->reg_fir);
473         LBC_WRITE(FCR, fcm->reg_fcr);
474
475         LBC_WRITE(FMR, fmr);
476
477         LBC_WRITE(FBCR, fcm->reg_fbcr);
478         LBC_WRITE(FBAR, fcm->reg_fbar);
479         LBC_WRITE(FPAR, fcm->reg_fpar);
480
481         if (fcm->addr_type == ADDR_ID)
482                 LBC_WRITE(MDR, fcm->reg_mdr);
483
484         nand_debug(NDBG_DRV, "BEFORE:\nFMR=%#x, FIR=%#x, FCR=%#x", fmr,
485             fcm->reg_fir, fcm->reg_fcr);
486         nand_debug(NDBG_DRV, "MDR=%#x, FBAR=%#x, FPAR=%#x, FBCR=%#x",
487             LBC_READ(MDR), fcm->reg_fbar, fcm->reg_fpar, fcm->reg_fbcr);
488
489         LBC_WRITE(LSOR, sc->dinfo->di_bank);
490
491         timeout = (cold) ? FSL_FCM_WAIT_TIMEOUT : ~0;
492         error = 0;
493         ltesr_v = LBC_READ(LTESR);
494         while (!error && (ltesr_v & LTESR_CC) == 0) {
495                 if (cold) {
496                         DELAY(1000);
497                         timeout--;
498                         if (timeout < 0)
499                                 error = EWOULDBLOCK;
500                 } else
501                         error = tsleep(device_get_parent(sc->dev), PRIBIO,
502                             "nfcfsl", hz);
503                 ltesr_v = LBC_READ(LTESR);
504         }
505         if (error)
506                 nand_debug(NDBG_DRV, "Command complete wait timeout\n");
507
508         nand_debug(NDBG_DRV, "AFTER:\nLTESR=%#x, LTEDR=%#x, LTEIR=%#x,"
509             " LTEATR=%#x, LTEAR=%#x, LTECCR=%#x", ltesr_v,
510             LBC_READ(LTEDR), LBC_READ(LTEIR), LBC_READ(LTEATR),
511             LBC_READ(LTEAR), LBC_READ(LTECCR));
512
513         bzero(&fcm->fcm_startzero,
514             __rangeof(struct fsl_nfc_fcm, fcm_startzero, fcm_endzero));
515
516         if (fcm->status)
517                 sc->fcm.reg_mdr = LBC_READ(MDR);
518
519         /* Even if timeout occured, we should perform steps below */
520         LBC_WRITE(LTESR, ltesr_v);
521         LBC_WRITE(LTEATR, 0);
522
523         return (error);
524 }
525
526 static uint8_t
527 fsl_nfc_read_byte(device_t dev)
528 {
529         struct fsl_nand_softc *sc = device_get_softc(dev);
530         uint32_t offset;
531
532         // device_printf(dev, "%s()\n", __func__);
533
534         /*
535          * LBC controller allows us to read status into a MDR instead of FCM
536          * buffer. If last operation requested before read_byte() was STATUS,
537          * then return MDR instead of reading a single byte from a buffer.
538          */
539         if (sc->fcm.status) {
540                 sc->fcm.status = 0;
541                 return (sc->fcm.reg_mdr);
542         }
543
544         KASSERT(sc->fcm.read_ptr < sc->pgsz,
545             ("Attempt to read beyond buffer %x %x", sc->fcm.read_ptr,
546             sc->pgsz));
547
548         offset = sc->fcm.buf_ofs + sc->fcm.read_ptr;
549         sc->fcm.read_ptr++;
550         return (bus_read_1(sc->res, offset));
551 }
552
553 static void
554 fsl_nfc_read_buf(device_t dev, void *buf, uint32_t len)
555 {
556         struct fsl_nand_softc *sc = device_get_softc(dev);
557         uint32_t offset;
558         int bytesleft = 0;
559
560         // device_printf(dev, "%s(buf=%p, len=%u)\n", __func__, buf, len);
561
562         nand_debug(NDBG_DRV, "REQUEST OF 0x%0x B (BIB=0x%0x, NTR=0x%0x)",
563             len, sc->pgsz, sc->fcm.read_ptr);
564
565         bytesleft = MIN((unsigned int)len, sc->pgsz - sc->fcm.read_ptr);
566
567         offset = sc->fcm.buf_ofs + sc->fcm.read_ptr;
568         bus_read_region_1(sc->res, offset, buf, bytesleft);
569         sc->fcm.read_ptr += bytesleft;
570 }
571
572 static void
573 fsl_nfc_write_buf(device_t dev, void *buf, uint32_t len)
574 {
575         struct fsl_nand_softc *sc = device_get_softc(dev);
576         uint32_t offset;
577         int bytesleft = 0;
578
579         // device_printf(dev, "%s(buf=%p, len=%u)\n", __func__, buf, len);
580
581         KASSERT(len <= sc->pgsz - sc->fcm.read_ptr,
582             ("Attempt to write beyond buffer"));
583
584         bytesleft = MIN((unsigned int)len, sc->pgsz - sc->fcm.read_ptr);
585
586         nand_debug(NDBG_DRV, "REQUEST TO WRITE 0x%0x (BIB=0x%0x, NTR=0x%0x)",
587             bytesleft, sc->pgsz, sc->fcm.read_ptr);
588
589         offset = sc->fcm.buf_ofs + sc->fcm.read_ptr;
590         bus_write_region_1(sc->res, offset, buf, bytesleft);
591         sc->fcm.read_ptr += bytesleft;
592 }
593
594 static int
595 fsl_nand_chip_preprobe(device_t dev, struct nand_id *id)
596 {
597
598         if (fsl_nfc_send_command(dev, NAND_CMD_RESET) != 0)
599                 return (ENXIO);
600
601         if (fsl_nfc_start_command(dev) != 0)
602                 return (ENXIO);
603
604         DELAY(1000);
605
606         if (fsl_nfc_send_command(dev, NAND_CMD_READ_ID))
607                 return (ENXIO);
608
609         if (fsl_nfc_send_address(dev, 0))
610                 return (ENXIO);
611
612         if (fsl_nfc_start_command(dev) != 0)
613                 return (ENXIO);
614
615         DELAY(25);
616
617         id->man_id = fsl_nfc_read_byte(dev);
618         id->dev_id = fsl_nfc_read_byte(dev);
619
620         nand_debug(NDBG_DRV, "manufacturer id: %x chip id: %x",
621             id->man_id, id->dev_id);
622
623         return (0);
624 }
625
626 #ifdef NAND_DEBUG_TIMING
627
628 static SYSCTL_NODE(_debug, OID_AUTO, fcm, CTLFLAG_RD, 0, "FCM timing");
629
630 static u_int csct = 1;  /* 22:    Chip select to command time (trlx). */
631 SYSCTL_UINT(_debug_fcm, OID_AUTO, csct, CTLFLAG_RW, &csct, 1,
632     "Chip select to command time: determines how far in advance -LCSn is "
633     "asserted prior to any bus activity during a NAND Flash access handled "
634     "by the FCM. This helps meet chip-select setup times for slow memories.");
635
636 static u_int cst = 1;   /* 23:    Command setup time (trlx). */
637 SYSCTL_UINT(_debug_fcm, OID_AUTO, cst, CTLFLAG_RW, &cst, 1,
638     "Command setup time: determines the delay of -LFWE assertion relative to "
639     "the command, address, or data change when the external memory access "
640     "is handled by the FCM.");
641
642 static u_int cht = 1;   /* 24:    Command hold time (trlx). */
643 SYSCTL_UINT(_debug_fcm, OID_AUTO, cht, CTLFLAG_RW, &cht, 1,
644     "Command hold time: determines the -LFWE negation prior to the command, "
645     "address, or data change when the external memory access is handled by "
646     "the FCM.");
647
648 static u_int scy = 2;   /* 25-27: Cycle length in bus clocks */
649 SYSCTL_UINT(_debug_fcm, OID_AUTO, scy, CTLFLAG_RW, &scy, 2,
650     "Cycle length in bus clocks: see RM");
651
652 static u_int rst = 1;   /* 28:    Read setup time (trlx). */
653 SYSCTL_UINT(_debug_fcm, OID_AUTO, rst, CTLFLAG_RW, &rst, 1,
654     "Read setup time: determines the delay of -LFRE assertion relative to "
655     "sampling of read data when the external memory access is handled by "
656     "the FCM.");
657
658 static u_int trlx = 1;  /* 29:    Timing relaxed. */
659 SYSCTL_UINT(_debug_fcm, OID_AUTO, trlx, CTLFLAG_RW, &trlx, 1,
660     "Timing relaxed: modifies the settings of timing parameters for slow "
661     "memories. See RM");
662
663 static u_int ehtr = 1;  /* 30:    Extended hold time on read accesses. */
664 SYSCTL_UINT(_debug_fcm, OID_AUTO, ehtr, CTLFLAG_RW, &ehtr, 1,
665     "Extended hold time on read accesses: indicates with TRLX how many "
666     "cycles are inserted between a read access from the current bank and "
667     "the next access.");
668
669 static u_int
670 fsl_nand_get_timing(void)
671 {
672         u_int timing;
673
674         timing = ((csct & 1) << 9) | ((cst & 1) << 8) | ((cht & 1) << 7) |
675             ((scy & 7) << 4) | ((rst & 1) << 3) | ((trlx & 1) << 2) |
676             ((ehtr & 1) << 1);
677
678         printf("nfc_fsl: timing = %u\n", timing);
679         return (timing);
680 }
681
682 static int
683 fsl_sysctl_program(SYSCTL_HANDLER_ARGS)
684 {
685         struct fsl_nand_softc *sc;
686         int error, i;
687         device_t dev;
688         uint32_t or_v;
689
690         error = sysctl_wire_old_buffer(req, sizeof(int));
691         if (error == 0) {
692                 i = 0;
693                 error = sysctl_handle_int(oidp, &i, 0, req);
694         }
695         if (error != 0 || req->newptr == NULL)
696                 return (error);
697
698         for (i = 0; i < 8; i++) {
699                 dev = fcm_devs[i];
700                 if (dev == NULL)
701                         continue;
702                 sc = device_get_softc(dev);
703
704                 /* Reprogram OR(x) */
705                 or_v = lbc_read_reg(dev, LBC85XX_OR(sc->dinfo->di_bank));
706                 or_v &= 0xfffffc00;
707                 or_v |= fsl_nand_get_timing();
708                 lbc_write_reg(dev, LBC85XX_OR(sc->dinfo->di_bank), or_v);
709         }
710         return (0);
711 }
712
713 SYSCTL_PROC(_debug_fcm, OID_AUTO, program, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
714     fsl_sysctl_program, "I", "write to program FCM with current values");
715
716 #endif /* NAND_DEBUG_TIMING */