1/* $NetBSD: omap2_nand.c,v 1.5 2021/08/07 16:18:46 thorpej Exp $ */ 2 3/*- 4 * Copyright (c) 2010 Department of Software Engineering, 5 * University of Szeged, Hungary 6 * Copyright (c) 2010 Adam Hoka <ahoka@NetBSD.org> 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by the Department of Software Engineering, University of Szeged, Hungary 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34/* Device driver for the NAND controller found in Texas Instruments OMAP2 35 * and later SOCs. 36 */ 37 38#include <sys/cdefs.h> 39__KERNEL_RCSID(0, "$NetBSD: omap2_nand.c,v 1.5 2021/08/07 16:18:46 thorpej Exp $"); 40 41/* TODO move to opt_* */ 42#undef OMAP2_NAND_HARDWARE_ECC 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/cdefs.h> 47#include <sys/device.h> 48 49#include <sys/bus.h> 50 51#include <arm/ti/omap2_gpmcreg.h> 52 53#include <dev/nand/nand.h> 54#include <dev/nand/onfi.h> 55 56#include <dev/fdt/fdtvar.h> 57 58extern struct flash_interface nand_flash_if; 59extern int flash_print(void *, const char *); 60 61/* GPMC_STATUS */ 62#define WAIT0 __BIT(8) /* active low */ 63 64/* GPMC_ECC_CONTROL */ 65#define ECCCLEAR __BIT(8) 66#define ECCPOINTER __BITS(3,0) 67 68/* GPMC_ECC_CONFIG */ 69#define ECCALGORITHM __BIT(16) 70#define ECCCS __BITS(3,1) 71#define ECC16B __BIT(7) 72#define ECCENABLE __BIT(0) 73/* GPMC_ECC_SIZE_CONFIG */ 74#define ECCSIZE1 __BITS(29,22) 75 76/* GPMC_CONFIG1_i */ 77#define DEVICETYPE __BITS(11,10) 78#define DEVICESIZE __BITS(13,12) 79 80#define MASKEDINT(mask, integer) ((integer) << (ffs(mask) - 1) & mask) 81 82/* NAND status register */ 83#define NAND_WP_BIT __BIT(4) 84 85static int omap2_nand_match(device_t, cfdata_t, void *); 86static void omap2_nand_attach(device_t, device_t, void *); 87 88static void omap2_nand_command(device_t self, uint8_t command); 89static void omap2_nand_address(device_t self, uint8_t address); 90static void omap2_nand_busy(device_t self); 91static void omap2_nand_read_1(device_t self, uint8_t *data); 92static void omap2_nand_write_1(device_t self, uint8_t data); 93static void omap2_nand_read_2(device_t self, uint16_t *data); 94static void omap2_nand_write_2(device_t self, uint16_t data); 95bool omap2_nand_isbusy(device_t self); 96static void omap2_nand_read_buf_1(device_t self, void *buf, size_t len); 97static void omap2_nand_read_buf_2(device_t self, void *buf, size_t len); 98static void omap2_nand_write_buf_1(device_t self, const void *buf, size_t len); 99static void omap2_nand_write_buf_2(device_t self, const void *buf, size_t len); 100 101#ifdef OMAP2_NAND_HARDWARE_ECC 102static int omap2_nand_ecc_init(device_t self); 103static int omap2_nand_ecc_prepare(device_t self, int mode); 104static int omap2_nand_ecc_compute(device_t self, const uint8_t *data, uint8_t *ecc); 105static int omap2_nand_ecc_correct(device_t self, uint8_t *data, const uint8_t *oldecc, 106 const uint8_t *calcecc); 107#endif 108 109struct omap2_nand_softc { 110 device_t sc_dev; 111 device_t sc_nanddev; 112 113 int sc_cs; 114 int sc_buswidth; /* 0: 8bit, 1: 16bit */ 115 116 struct nand_interface sc_nand_if; 117 118 bus_space_tag_t sc_iot; 119 bus_space_handle_t sc_ioh; 120 bus_space_handle_t sc_gpmc_ioh; 121 122 bus_size_t sc_cmd_reg; 123 bus_size_t sc_addr_reg; 124 bus_size_t sc_data_reg; 125}; 126 127static const struct device_compatible_entry compat_data[] = { 128 { .compat = "ti,omap2-nand" }, 129 { .compat = "ti,omap2-onenand" }, 130 DEVICE_COMPAT_EOL 131}; 132 133CFATTACH_DECL_NEW(omapnand, sizeof(struct omap2_nand_softc), omap2_nand_match, 134 omap2_nand_attach, NULL, NULL); 135 136static inline uint32_t 137gpmc_register_read(struct omap2_nand_softc *sc, bus_size_t reg) 138{ 139 return bus_space_read_4(sc->sc_iot, sc->sc_gpmc_ioh, reg); 140} 141 142static inline void 143gpmc_register_write(struct omap2_nand_softc *sc, bus_size_t reg, const uint32_t data) 144{ 145 bus_space_write_4(sc->sc_iot, sc->sc_gpmc_ioh, reg, data); 146} 147 148static void 149omap2_nand_command(device_t self, uint8_t command) 150{ 151 struct omap2_nand_softc *sc = device_private(self); 152 153 bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_cmd_reg, command); 154}; 155 156static void 157omap2_nand_address(device_t self, uint8_t address) 158{ 159 struct omap2_nand_softc *sc = device_private(self); 160 161 bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_addr_reg, address); 162}; 163 164bool 165omap2_nand_isbusy(device_t self) 166{ 167 struct omap2_nand_softc *sc = device_private(self); 168 uint8_t status; 169 170 DELAY(1); /* just to be sure we are not early */ 171 172 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 173 sc->sc_cmd_reg, ONFI_READ_STATUS); 174 175 DELAY(1); 176 177 status = bus_space_read_1(sc->sc_iot, 178 sc->sc_ioh, sc->sc_data_reg); 179 180 return !(status & ONFI_STATUS_RDY); 181}; 182 183static int 184omap2_nand_match(device_t parent, cfdata_t match, void *aux) 185{ 186 struct fdt_attach_args * const faa = aux; 187 188 return of_compatible_match(faa->faa_phandle, compat_data); 189} 190 191static void 192omap2_nand_attach(device_t parent, device_t self, void *aux) 193{ 194 struct omap2_nand_softc *sc = device_private(self); 195 struct fdt_attach_args * const faa = aux; 196 const int phandle = faa->faa_phandle; 197 struct flash_attach_args flash; 198 bus_addr_t addr, part_addr; 199 bus_size_t size, part_size; 200 const u_int *prop; 201 uint32_t val; 202 int len, child; 203 204 if (fdtbus_get_reg(OF_parent(phandle), 0, &addr, &size) != 0) { 205 aprint_error(": couldn't get registers\n"); 206 return; 207 } 208 209 sc->sc_iot = faa->faa_bst; 210 sc->sc_dev = self; 211 212 prop = fdtbus_get_prop(phandle, "reg", &len); 213 if (prop == NULL || len < 4) { 214 aprint_error(": couldn't read reg property\n"); 215 return; 216 } 217 218 sc->sc_cs = be32toh(prop[0]); 219 220 /* map i/o space */ 221 if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_gpmc_ioh) != 0) { 222 aprint_error(": couldn't map registers\n"); 223 return; 224 } 225 if (bus_space_subregion(sc->sc_iot, sc->sc_gpmc_ioh, GPMC_CS_CONFIG(sc->sc_cs), 0x30, &sc->sc_ioh) != 0) { 226 aprint_error(": couldn't map cs registers\n"); 227 return; 228 } 229 230 aprint_naive("\n"); 231 aprint_normal(": CS%d\n", sc->sc_cs); 232 233 sc->sc_cmd_reg = GPMC_NAND_COMMAND_0 - GPMC_CONFIG1_0; 234 sc->sc_addr_reg = GPMC_NAND_ADDRESS_0 - GPMC_CONFIG1_0; 235 sc->sc_data_reg = GPMC_NAND_DATA_0 - GPMC_CONFIG1_0; 236 237 /* turn off write protection if enabled */ 238 val = gpmc_register_read(sc, GPMC_CONFIG); 239 val |= NAND_WP_BIT; 240 gpmc_register_write(sc, GPMC_CONFIG, val); 241 242 /* 243 * do the reset dance for NAND 244 */ 245 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 246 sc->sc_cmd_reg, ONFI_RESET); 247 248 omap2_nand_busy(self); 249 250 /* read GPMC_CONFIG1_i to get buswidth */ 251 val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GPMC_CONFIG1_i); 252 253 if ((val & DEVICESIZE) == MASKEDINT(DEVICESIZE, 0x01)) { 254 /* 16bit */ 255 sc->sc_buswidth = 1; 256 } else if ((val & DEVICESIZE) == MASKEDINT(DEVICESIZE, 0x00)) { 257 /* 8bit */ 258 sc->sc_buswidth = 0; 259 } else { 260 panic("invalid buswidth reported by config1"); 261 } 262 263 nand_init_interface(&sc->sc_nand_if); 264 265 sc->sc_nand_if.command = &omap2_nand_command; 266 sc->sc_nand_if.address = &omap2_nand_address; 267 sc->sc_nand_if.read_buf_1 = &omap2_nand_read_buf_1; 268 sc->sc_nand_if.read_buf_2 = &omap2_nand_read_buf_2; 269 sc->sc_nand_if.read_1 = &omap2_nand_read_1; 270 sc->sc_nand_if.read_2 = &omap2_nand_read_2; 271 sc->sc_nand_if.write_buf_1 = &omap2_nand_write_buf_1; 272 sc->sc_nand_if.write_buf_2 = &omap2_nand_write_buf_2; 273 sc->sc_nand_if.write_1 = &omap2_nand_write_1; 274 sc->sc_nand_if.write_2 = &omap2_nand_write_2; 275 sc->sc_nand_if.busy = &omap2_nand_busy; 276 277#ifdef OMAP2_NAND_HARDWARE_ECC 278 omap2_nand_ecc_init(self); 279 sc->sc_nand_if.ecc_compute = &omap2_nand_ecc_compute; 280 sc->sc_nand_if.ecc_correct = &omap2_nand_ecc_correct; 281 sc->sc_nand_if.ecc_prepare = &omap2_nand_ecc_prepare; 282 sc->sc_nand_if.ecc.necc_code_size = 3; 283 sc->sc_nand_if.ecc.necc_block_size = 512; 284 sc->sc_nand_if.ecc.necc_type = NAND_ECC_TYPE_HW; 285#else 286 sc->sc_nand_if.ecc.necc_code_size = 3; 287 sc->sc_nand_if.ecc.necc_block_size = 256; 288#endif /* OMAP2_NAND_HARDWARE_ECC */ 289 290 if (!pmf_device_register1(sc->sc_dev, NULL, NULL, NULL)) 291 aprint_error_dev(sc->sc_dev, 292 "couldn't establish power handler\n"); 293 294 sc->sc_nanddev = nand_attach_mi(&sc->sc_nand_if, sc->sc_dev); 295 if (sc->sc_nanddev == NULL) 296 return; 297 298 for (child = OF_child(phandle); child; child = OF_peer(child)) { 299 if (!fdtbus_status_okay(child)) 300 continue; 301 302 if (fdtbus_get_reg(child, 0, &part_addr, &part_size) != 0) { 303 aprint_error_dev(self, "couldn't parse partition %s\n", 304 fdtbus_get_string(child, "name")); 305 continue; 306 } 307 308 memset(&flash, 0, sizeof(flash)); 309 flash.flash_if = &nand_flash_if; 310 flash.partinfo.part_offset = part_addr; 311 flash.partinfo.part_size = part_size; 312 flash.partinfo.part_flags = 0; 313 flash.partinfo.part_name = fdtbus_get_string(child, "label"); 314 if (flash.partinfo.part_name == NULL) 315 flash.partinfo.part_name = fdtbus_get_string(child, "name"); 316 317 config_found(sc->sc_nanddev, &flash, flash_print, CFARGS_NONE); 318 } 319} 320 321static void 322omap2_nand_busy(device_t self) 323{ 324 struct omap2_nand_softc *sc = device_private(self); 325 326 while (!(gpmc_register_read(sc, GPMC_STATUS) & WAIT0)) { 327 DELAY(1); 328 } 329} 330 331static void 332omap2_nand_read_1(device_t self, uint8_t *data) 333{ 334 struct omap2_nand_softc *sc = device_private(self); 335 336 *data = bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->sc_data_reg); 337} 338 339static void 340omap2_nand_write_1(device_t self, uint8_t data) 341{ 342 struct omap2_nand_softc *sc = device_private(self); 343 344 bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_data_reg, data); 345} 346 347static void 348omap2_nand_read_2(device_t self, uint16_t *data) 349{ 350 struct omap2_nand_softc *sc = device_private(self); 351 352 *data = bus_space_read_2(sc->sc_iot, sc->sc_ioh, sc->sc_data_reg); 353} 354 355static void 356omap2_nand_write_2(device_t self, uint16_t data) 357{ 358 struct omap2_nand_softc *sc = device_private(self); 359 360 bus_space_write_2(sc->sc_iot, sc->sc_ioh, sc->sc_data_reg, data); 361} 362 363static void 364omap2_nand_read_buf_1(device_t self, void *buf, size_t len) 365{ 366 struct omap2_nand_softc *sc = device_private(self); 367 368 KASSERT(buf != NULL); 369 KASSERT(len >= 1); 370 371 bus_space_read_multi_1(sc->sc_iot, sc->sc_ioh, 372 sc->sc_data_reg, buf, len); 373} 374 375static void 376omap2_nand_read_buf_2(device_t self, void *buf, size_t len) 377{ 378 struct omap2_nand_softc *sc = device_private(self); 379 380 KASSERT(buf != NULL); 381 KASSERT(len >= 2); 382 KASSERT(!(len & 0x01)); 383 384 bus_space_read_multi_2(sc->sc_iot, sc->sc_ioh, 385 sc->sc_data_reg, buf, len / 2); 386} 387 388static void 389omap2_nand_write_buf_1(device_t self, const void *buf, size_t len) 390{ 391 struct omap2_nand_softc *sc = device_private(self); 392 393 KASSERT(buf != NULL); 394 KASSERT(len >= 1); 395 396 bus_space_write_multi_1(sc->sc_iot, sc->sc_ioh, 397 sc->sc_data_reg, buf, len); 398} 399 400static void 401omap2_nand_write_buf_2(device_t self, const void *buf, size_t len) 402{ 403 struct omap2_nand_softc *sc = device_private(self); 404 405 KASSERT(buf != NULL); 406 KASSERT(len >= 2); 407 KASSERT(!(len & 0x01)); 408 409 bus_space_write_multi_2(sc->sc_iot, sc->sc_ioh, 410 sc->sc_data_reg, buf, len / 2); 411} 412 413#ifdef OMAP2_NAND_HARDWARE_ECC 414static uint32_t 415convert_ecc(const uint8_t *ecc) 416{ 417 return ecc[0] | (ecc[1] << 16) | ((ecc[2] & 0xf0) << 20) | 418 ((ecc[2] & 0x0f) << 8); 419} 420 421static int 422omap2_nand_ecc_init(device_t self) 423{ 424 struct omap2_nand_softc *sc = device_private(self); 425 uint32_t val; 426 427 val = gpmc_register_read(sc, GPMC_ECC_CONTROL); 428 /* clear ecc, select ecc register 1 */ 429 val &= ~ECCPOINTER; 430 val |= ECCCLEAR | MASKEDINT(ECCPOINTER, 1); 431 gpmc_register_write(sc, GPMC_ECC_CONTROL, val); 432 433 /* XXX too many MAGIC */ 434 /* set ecc size to 512, set all regs to eccsize1*/ 435 val = gpmc_register_read(sc, GPMC_ECC_SIZE_CONFIG); 436 val &= ~ECCSIZE1; 437 val |= MASKEDINT(ECCSIZE1, 512) | 0x0f; 438 gpmc_register_write(sc, GPMC_ECC_CONTROL, val); 439 440 return 0; 441} 442 443static int 444omap2_nand_ecc_compute(device_t self, const uint8_t *data, uint8_t *ecc) 445{ 446 struct omap2_nand_softc *sc = device_private(self); 447 uint32_t val; 448 449 /* read ecc result register */ 450 val = gpmc_register_read(sc, GPMC_ECC1_RESULT); 451 452 ecc[0] = val & 0xff; 453 ecc[1] = (val >> 16) & 0xff; 454 ecc[2] = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); 455 456 /* disable ecc engine */ 457 val = gpmc_register_read(sc, GPMC_ECC_CONFIG); 458 val &= ~ECCENABLE; 459 gpmc_register_write(sc, GPMC_ECC_CONFIG, val); 460 461 return 0; 462} 463 464static int 465omap2_nand_ecc_prepare(device_t self, int mode) 466{ 467 struct omap2_nand_softc *sc = device_private(self); 468 uint32_t val; 469 470 /* same for read/write */ 471 switch (mode) { 472 case NAND_ECC_READ: 473 case NAND_ECC_WRITE: 474 val = gpmc_register_read(sc, GPMC_ECC_CONTROL); 475 /* clear ecc, select ecc register 1 */ 476 val &= ~ECCPOINTER; 477 val |= ECCCLEAR | MASKEDINT(ECCPOINTER, 1); 478 gpmc_register_write(sc, GPMC_ECC_CONTROL, val); 479 480 val = gpmc_register_read(sc, GPMC_ECC_CONFIG); 481 val &= ~ECCCS; 482 val |= ECCENABLE | MASKEDINT(ECCCS, sc->sc_cs); 483 if (sc->sc_buswidth == 1) 484 val |= ECC16B; 485 else 486 val &= ~ECC16B; 487 gpmc_register_write(sc, GPMC_ECC_CONFIG, val); 488 489 break; 490 default: 491 aprint_error_dev(self, "invalid i/o mode for ecc prepare\n"); 492 return -1; 493 } 494 495 return 0; 496} 497 498static int 499omap2_nand_ecc_correct(device_t self, uint8_t *data, const uint8_t *oldecc, 500 const uint8_t *calcecc) 501{ 502 uint32_t oecc, cecc, xor; 503 uint16_t parity, offset; 504 uint8_t bit; 505 506 oecc = convert_ecc(oldecc); 507 cecc = convert_ecc(calcecc); 508 509 /* get the difference */ 510 xor = oecc ^ cecc; 511 512 /* the data was correct if all bits are zero */ 513 if (xor == 0x00) 514 return NAND_ECC_OK; 515 516 switch (popcount32(xor)) { 517 case 12: 518 /* single byte error */ 519 parity = xor >> 16; 520 bit = (parity & 0x07); 521 offset = (parity >> 3) & 0x01ff; 522 /* correct bit */ 523 data[offset] ^= (0x01 << bit); 524 return NAND_ECC_CORRECTED; 525 case 1: 526 return NAND_ECC_INVALID; 527 default: 528 /* erased page! */ 529 if ((oecc == 0x0fff0fff) && (cecc == 0x00000000)) 530 return NAND_ECC_OK; 531 532 return NAND_ECC_TWOBIT; 533 } 534} 535#endif /* !OMAP2_NAND_HARDWARE_ECC */ 536