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 70enum addr_type { 71 ADDR_NONE, 72 ADDR_ID, 73 ADDR_ROW, 74 ADDR_ROWCOL 75}; 76 77struct 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 105struct 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 117static int fsl_nand_attach(device_t dev); 118static int fsl_nand_probe(device_t dev); 119static int fsl_nand_detach(device_t dev); 120 121static int fsl_nfc_select_cs(device_t dev, uint8_t cs); 122static int fsl_nfc_read_rnb(device_t dev); 123static int fsl_nfc_send_command(device_t dev, uint8_t command); 124static int fsl_nfc_send_address(device_t dev, uint8_t address); 125static uint8_t fsl_nfc_read_byte(device_t dev); 126static int fsl_nfc_start_command(device_t dev); 127static void fsl_nfc_read_buf(device_t dev, void *buf, uint32_t len); 128static void fsl_nfc_write_buf(device_t dev, void *buf, uint32_t len); 129 130static 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 146static driver_t fsl_nand_driver = { 147 "nand", 148 fsl_nand_methods, 149 sizeof(struct fsl_nand_softc), 150}; 151 152static devclass_t fsl_nand_devclass; 153 154DRIVER_MODULE(fsl_nand, lbc, fsl_nand_driver, fsl_nand_devclass, 155 0, 0); 156 157static int fsl_nand_build_address(device_t dev, uint32_t page, uint32_t column); 158static int fsl_nand_chip_preprobe(device_t dev, struct nand_id *id); 159 160#ifdef NAND_DEBUG_TIMING 161static 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 170static void 171fsl_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 214static int 215fsl_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 225static int 226fsl_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 272static int 273fsl_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 285static int 286fsl_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 293static int 294fsl_nfc_read_rnb(device_t dev) 295{ 296 297 // device_printf(dev, "%s()\n", __func__); 298 return (0); 299} 300 301static int 302fsl_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 353static int 354fsl_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 405static int 406fsl_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 454static int 455fsl_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 526static uint8_t 527fsl_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 553static void 554fsl_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 572static void 573fsl_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 594static int 595fsl_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 628static SYSCTL_NODE(_debug, OID_AUTO, fcm, CTLFLAG_RD, 0, "FCM timing"); 629 630static u_int csct = 1; /* 22: Chip select to command time (trlx). */ 631SYSCTL_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 636static u_int cst = 1; /* 23: Command setup time (trlx). */ 637SYSCTL_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 642static u_int cht = 1; /* 24: Command hold time (trlx). */ 643SYSCTL_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 648static u_int scy = 2; /* 25-27: Cycle length in bus clocks */ 649SYSCTL_UINT(_debug_fcm, OID_AUTO, scy, CTLFLAG_RW, &scy, 2, 650 "Cycle length in bus clocks: see RM"); 651 652static u_int rst = 1; /* 28: Read setup time (trlx). */ 653SYSCTL_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 658static u_int trlx = 1; /* 29: Timing relaxed. */ 659SYSCTL_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 663static u_int ehtr = 1; /* 30: Extended hold time on read accesses. */ 664SYSCTL_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 669static u_int 670fsl_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 682static int 683fsl_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 713SYSCTL_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 */ 717