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