nandbus.c revision 259372
1/*- 2 * Copyright (C) 2009-2012 Semihalf 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#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/10/sys/dev/nand/nandbus.c 259372 2013-12-14 00:55:34Z ian $"); 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/kernel.h> 33#include <sys/socket.h> 34#include <sys/malloc.h> 35#include <sys/module.h> 36#include <sys/bus.h> 37#include <sys/proc.h> 38#include <sys/lock.h> 39#include <sys/mutex.h> 40#include <sys/condvar.h> 41 42#include <dev/nand/nand.h> 43#include <dev/nand/nandbus.h> 44#include "nand_if.h" 45#include "nandbus_if.h" 46#include "nfc_if.h" 47 48#define NAND_NCS 4 49 50static int nandbus_probe(device_t dev); 51static int nandbus_attach(device_t dev); 52static int nandbus_detach(device_t dev); 53 54static int nandbus_child_location_str(device_t, device_t, char *, size_t); 55static int nandbus_child_pnpinfo_str(device_t, device_t, char *, size_t); 56 57static int nandbus_get_status(device_t, uint8_t *); 58static void nandbus_read_buffer(device_t, void *, uint32_t); 59static int nandbus_select_cs(device_t, uint8_t); 60static int nandbus_send_command(device_t, uint8_t); 61static int nandbus_send_address(device_t, uint8_t); 62static int nandbus_start_command(device_t); 63static int nandbus_wait_ready(device_t, uint8_t *); 64static void nandbus_write_buffer(device_t, void *, uint32_t); 65static int nandbus_get_ecc(device_t, void *, uint32_t, void *, int *); 66static int nandbus_correct_ecc(device_t, void *, int, void *, void *); 67static void nandbus_lock(device_t); 68static void nandbus_unlock(device_t); 69 70static int nand_readid(device_t, uint8_t *, uint8_t *); 71static int nand_probe_onfi(device_t, uint8_t *); 72static int nand_reset(device_t); 73 74struct nandbus_softc { 75 device_t dev; 76 struct cv nandbus_cv; 77 struct mtx nandbus_mtx; 78 uint8_t busy; 79}; 80 81static device_method_t nandbus_methods[] = { 82 /* device interface */ 83 DEVMETHOD(device_probe, nandbus_probe), 84 DEVMETHOD(device_attach, nandbus_attach), 85 DEVMETHOD(device_detach, nandbus_detach), 86 DEVMETHOD(device_shutdown, bus_generic_shutdown), 87 88 /* bus interface */ 89 DEVMETHOD(bus_print_child, bus_generic_print_child), 90 DEVMETHOD(bus_driver_added, bus_generic_driver_added), 91 DEVMETHOD(bus_child_pnpinfo_str, nandbus_child_pnpinfo_str), 92 DEVMETHOD(bus_child_location_str, nandbus_child_location_str), 93 94 /* nandbus interface */ 95 DEVMETHOD(nandbus_get_status, nandbus_get_status), 96 DEVMETHOD(nandbus_read_buffer, nandbus_read_buffer), 97 DEVMETHOD(nandbus_select_cs, nandbus_select_cs), 98 DEVMETHOD(nandbus_send_command, nandbus_send_command), 99 DEVMETHOD(nandbus_send_address, nandbus_send_address), 100 DEVMETHOD(nandbus_start_command,nandbus_start_command), 101 DEVMETHOD(nandbus_wait_ready, nandbus_wait_ready), 102 DEVMETHOD(nandbus_write_buffer, nandbus_write_buffer), 103 DEVMETHOD(nandbus_get_ecc, nandbus_get_ecc), 104 DEVMETHOD(nandbus_correct_ecc, nandbus_correct_ecc), 105 DEVMETHOD(nandbus_lock, nandbus_lock), 106 DEVMETHOD(nandbus_unlock, nandbus_unlock), 107 { 0, 0 } 108}; 109 110devclass_t nandbus_devclass; 111 112driver_t nandbus_driver = { 113 "nandbus", 114 nandbus_methods, 115 sizeof(struct nandbus_softc) 116}; 117 118DRIVER_MODULE(nandbus, nand, nandbus_driver, nandbus_devclass, 0, 0); 119 120int 121nandbus_create(device_t nfc) 122{ 123 device_t child; 124 125 child = device_add_child(nfc, "nandbus", -1); 126 if (!child) 127 return (ENODEV); 128 129 bus_generic_attach(nfc); 130 131 return(0); 132} 133 134void 135nandbus_destroy(device_t nfc) 136{ 137 device_t *children; 138 int nchildren, i; 139 140 mtx_lock(&Giant); 141 /* Detach & delete all children */ 142 if (!device_get_children(nfc, &children, &nchildren)) { 143 for (i = 0; i < nchildren; i++) 144 device_delete_child(nfc, children[i]); 145 146 free(children, M_TEMP); 147 } 148 mtx_unlock(&Giant); 149} 150 151static int 152nandbus_probe(device_t dev) 153{ 154 155 device_set_desc(dev, "NAND bus"); 156 157 return (0); 158} 159 160static int 161nandbus_attach(device_t dev) 162{ 163 device_t child, nfc; 164 struct nand_id chip_id; 165 struct nandbus_softc *sc; 166 struct nandbus_ivar *ivar; 167 struct nand_softc *nfc_sc; 168 struct nand_params *chip_params; 169 uint8_t cs, onfi; 170 171 sc = device_get_softc(dev); 172 sc->dev = dev; 173 174 nfc = device_get_parent(dev); 175 nfc_sc = device_get_softc(nfc); 176 177 mtx_init(&sc->nandbus_mtx, "nandbus lock", MTX_DEF, 0); 178 cv_init(&sc->nandbus_cv, "nandbus cv"); 179 180 /* Check each possible CS for existing nand devices */ 181 for (cs = 0; cs < NAND_NCS; cs++) { 182 nand_debug(NDBG_BUS,"probe chip select %x", cs); 183 184 /* Select & reset chip */ 185 if (nandbus_select_cs(dev, cs)) 186 break; 187 188 if (nand_reset(dev)) 189 continue; 190 191 /* Read manufacturer and device id */ 192 if (nand_readid(dev, &chip_id.man_id, &chip_id.dev_id)) 193 continue; 194 195 if (chip_id.man_id == 0xff) 196 continue; 197 198 /* 199 * First try to get info from the table. If that fails, see if 200 * the chip can provide ONFI info. We check the table first to 201 * allow table entries to override info from chips that are 202 * known to provide bad ONFI data. 203 */ 204 onfi = 0; 205 chip_params = nand_get_params(&chip_id); 206 if (chip_params == NULL) { 207 nand_probe_onfi(dev, &onfi); 208 } 209 210 /* 211 * At this point it appears there is a chip at this chipselect, 212 * so if we can't work with it, whine about it. 213 */ 214 if (chip_params == NULL && onfi == 0) { 215 if (bootverbose || (nand_debug_flag & NDBG_BUS)) 216 printf("Chip params not found, chipsel: %d " 217 "(manuf: 0x%0x, chipid: 0x%0x, onfi: %d)\n", 218 cs, chip_id.man_id, chip_id.dev_id, onfi); 219 continue; 220 } 221 222 ivar = malloc(sizeof(struct nandbus_ivar), 223 M_NAND, M_WAITOK); 224 225 if (onfi == 1) { 226 ivar->cs = cs; 227 ivar->cols = 0; 228 ivar->rows = 0; 229 ivar->params = NULL; 230 ivar->man_id = chip_id.man_id; 231 ivar->dev_id = chip_id.dev_id; 232 ivar->is_onfi = onfi; 233 ivar->chip_cdev_name = nfc_sc->chip_cdev_name; 234 235 child = device_add_child(dev, NULL, -1); 236 device_set_ivars(child, ivar); 237 continue; 238 } 239 240 ivar->cs = cs; 241 ivar->cols = 1; 242 ivar->rows = 2; 243 ivar->params = chip_params; 244 ivar->man_id = chip_id.man_id; 245 ivar->dev_id = chip_id.dev_id; 246 ivar->is_onfi = onfi; 247 ivar->chip_cdev_name = nfc_sc->chip_cdev_name; 248 249 /* 250 * Check what type of device we have. 251 * devices bigger than 32MiB have on more row (3) 252 */ 253 if (chip_params->chip_size > 32) 254 ivar->rows++; 255 /* Large page devices have one more col (2) */ 256 if (chip_params->chip_size >= 128 && 257 chip_params->page_size > 512) 258 ivar->cols++; 259 260 child = device_add_child(dev, NULL, -1); 261 device_set_ivars(child, ivar); 262 } 263 264 bus_generic_attach(dev); 265 return (0); 266} 267 268static int 269nandbus_detach(device_t dev) 270{ 271 struct nandbus_softc *sc; 272 273 sc = device_get_softc(dev); 274 275 bus_generic_detach(dev); 276 277 mtx_destroy(&sc->nandbus_mtx); 278 cv_destroy(&sc->nandbus_cv); 279 280 return (0); 281} 282 283static int 284nandbus_child_location_str(device_t bus, device_t child, char *buf, 285 size_t buflen) 286{ 287 struct nandbus_ivar *ivar = device_get_ivars(child); 288 289 snprintf(buf, buflen, "at cs#%d", ivar->cs); 290 return (0); 291} 292 293static int 294nandbus_child_pnpinfo_str(device_t bus, device_t child, char *buf, 295 size_t buflen) 296{ 297 // XXX man id, model id ???? 298 *buf = '\0'; 299 return (0); 300} 301 302static int 303nand_readid(device_t bus, uint8_t *man_id, uint8_t *dev_id) 304{ 305 device_t nfc; 306 307 if (!bus || !man_id || !dev_id) 308 return (EINVAL); 309 310 nand_debug(NDBG_BUS,"read id"); 311 312 nfc = device_get_parent(bus); 313 314 if (NFC_SEND_COMMAND(nfc, NAND_CMD_READ_ID)) { 315 nand_debug(NDBG_BUS,"Error : could not send READ ID command"); 316 return (ENXIO); 317 } 318 319 if (NFC_SEND_ADDRESS(nfc, 0)) { 320 nand_debug(NDBG_BUS,"Error : could not sent address to chip"); 321 return (ENXIO); 322 } 323 324 if (NFC_START_COMMAND(nfc) != 0) { 325 nand_debug(NDBG_BUS,"Error : could not start command"); 326 return (ENXIO); 327 } 328 329 DELAY(25); 330 331 *man_id = NFC_READ_BYTE(nfc); 332 *dev_id = NFC_READ_BYTE(nfc); 333 334 nand_debug(NDBG_BUS,"manufacturer id: %x chip id: %x", *man_id, 335 *dev_id); 336 337 return (0); 338} 339 340static int 341nand_probe_onfi(device_t bus, uint8_t *onfi_compliant) 342{ 343 device_t nfc; 344 char onfi_id[] = {'O', 'N', 'F', 'I', '\0'}; 345 int i; 346 347 nand_debug(NDBG_BUS,"probing ONFI"); 348 349 nfc = device_get_parent(bus); 350 351 if (NFC_SEND_COMMAND(nfc, NAND_CMD_READ_ID)) { 352 nand_debug(NDBG_BUS,"Error : could not sent READ ID command"); 353 return (ENXIO); 354 } 355 356 if (NFC_SEND_ADDRESS(nfc, ONFI_SIG_ADDR)) { 357 nand_debug(NDBG_BUS,"Error : could not sent address to chip"); 358 return (ENXIO); 359 } 360 361 if (NFC_START_COMMAND(nfc) != 0) { 362 nand_debug(NDBG_BUS,"Error : could not start command"); 363 return (ENXIO); 364 } 365 for (i = 0; onfi_id[i] != '\0'; i++) 366 if (NFC_READ_BYTE(nfc) != onfi_id[i]) { 367 nand_debug(NDBG_BUS,"ONFI non-compliant"); 368 *onfi_compliant = 0; 369 return (0); 370 } 371 372 nand_debug(NDBG_BUS,"ONFI compliant"); 373 *onfi_compliant = 1; 374 375 return (0); 376} 377 378static int 379nand_reset(device_t bus) 380{ 381 device_t nfc; 382 nand_debug(NDBG_BUS,"resetting..."); 383 384 nfc = device_get_parent(bus); 385 386 if (NFC_SEND_COMMAND(nfc, NAND_CMD_RESET) != 0) { 387 nand_debug(NDBG_BUS,"Error : could not sent RESET command"); 388 return (ENXIO); 389 } 390 391 if (NFC_START_COMMAND(nfc) != 0) { 392 nand_debug(NDBG_BUS,"Error : could not start RESET command"); 393 return (ENXIO); 394 } 395 396 DELAY(1000); 397 398 return (0); 399} 400 401void 402nandbus_lock(device_t dev) 403{ 404 struct nandbus_softc *sc; 405 406 sc = device_get_softc(dev); 407 408 mtx_lock(&sc->nandbus_mtx); 409 if (sc->busy) 410 cv_wait(&sc->nandbus_cv, &sc->nandbus_mtx); 411 sc->busy = 1; 412 mtx_unlock(&sc->nandbus_mtx); 413} 414 415void 416nandbus_unlock(device_t dev) 417{ 418 struct nandbus_softc *sc; 419 420 sc = device_get_softc(dev); 421 422 mtx_lock(&sc->nandbus_mtx); 423 sc->busy = 0; 424 cv_signal(&sc->nandbus_cv); 425 mtx_unlock(&sc->nandbus_mtx); 426} 427 428int 429nandbus_select_cs(device_t dev, uint8_t cs) 430{ 431 432 return (NFC_SELECT_CS(device_get_parent(dev), cs)); 433} 434 435int 436nandbus_send_command(device_t dev, uint8_t command) 437{ 438 int err; 439 440 if ((err = NFC_SEND_COMMAND(device_get_parent(dev), command))) 441 nand_debug(NDBG_BUS,"Err: Could not send command %x, err %x", 442 command, err); 443 444 return (err); 445} 446 447int 448nandbus_send_address(device_t dev, uint8_t address) 449{ 450 int err; 451 452 if ((err = NFC_SEND_ADDRESS(device_get_parent(dev), address))) 453 nand_debug(NDBG_BUS,"Err: Could not send address %x, err %x", 454 address, err); 455 456 return (err); 457} 458 459int 460nandbus_start_command(device_t dev) 461{ 462 int err; 463 464 if ((err = NFC_START_COMMAND(device_get_parent(dev)))) 465 nand_debug(NDBG_BUS,"Err: Could not start command, err %x", 466 err); 467 468 return (err); 469} 470 471void 472nandbus_read_buffer(device_t dev, void *buf, uint32_t len) 473{ 474 475 NFC_READ_BUF(device_get_parent(dev), buf, len); 476} 477 478void 479nandbus_write_buffer(device_t dev, void *buf, uint32_t len) 480{ 481 482 NFC_WRITE_BUF(device_get_parent(dev), buf, len); 483} 484 485int 486nandbus_get_status(device_t dev, uint8_t *status) 487{ 488 int err; 489 490 if ((err = NANDBUS_SEND_COMMAND(dev, NAND_CMD_STATUS))) 491 return (err); 492 if ((err = NANDBUS_START_COMMAND(dev))) 493 return (err); 494 495 *status = NFC_READ_BYTE(device_get_parent(dev)); 496 497 return (0); 498} 499 500int 501nandbus_wait_ready(device_t dev, uint8_t *status) 502{ 503 struct timeval tv, tv2; 504 505 tv2.tv_sec = 0; 506 tv2.tv_usec = 50 * 5000; /* 10ms */ 507 508 getmicrotime(&tv); 509 timevaladd(&tv, &tv2); 510 511 do { 512 if (NANDBUS_GET_STATUS(dev, status)) 513 return (ENXIO); 514 515 if (*status & NAND_STATUS_RDY) 516 return (0); 517 518 getmicrotime(&tv2); 519 } while (timevalcmp(&tv2, &tv, <=)); 520 521 return (EBUSY); 522} 523 524int 525nandbus_get_ecc(device_t dev, void *buf, uint32_t pagesize, void *ecc, 526 int *needwrite) 527{ 528 529 return (NFC_GET_ECC(device_get_parent(dev), buf, pagesize, ecc, needwrite)); 530} 531 532int 533nandbus_correct_ecc(device_t dev, void *buf, int pagesize, void *readecc, 534 void *calcecc) 535{ 536 537 return (NFC_CORRECT_ECC(device_get_parent(dev), buf, pagesize, 538 readecc, calcecc)); 539} 540 541