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