The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/nand/nand.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: nand.c,v 1.29 2021/08/07 16:19:13 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 /* Common driver for NAND chips implementing the ONFI 2.2 specification */
   35 
   36 #include <sys/cdefs.h>
   37 __KERNEL_RCSID(0, "$NetBSD: nand.c,v 1.29 2021/08/07 16:19:13 thorpej Exp $");
   38 
   39 #include "locators.h"
   40 
   41 #include <sys/param.h>
   42 #include <sys/types.h>
   43 #include <sys/device.h>
   44 #include <sys/kmem.h>
   45 #include <sys/atomic.h>
   46 
   47 #include <dev/flash/flash.h>
   48 #include <dev/flash/flash_io.h>
   49 #include <dev/nand/nand.h>
   50 #include <dev/nand/onfi.h>
   51 #include <dev/nand/hamming.h>
   52 #include <dev/nand/nand_bbt.h>
   53 #include <dev/nand/nand_crc.h>
   54 
   55 #include "opt_nand.h"
   56 
   57 int nand_match(device_t, cfdata_t, void *);
   58 void nand_attach(device_t, device_t, void *);
   59 int nand_detach(device_t, int);
   60 bool nand_shutdown(device_t, int);
   61 
   62 int nand_print(void *, const char *);
   63 
   64 static int nand_search(device_t, cfdata_t, const int *, void *);
   65 static void nand_address_row(device_t, size_t);
   66 static inline uint8_t nand_get_status(device_t);
   67 static void nand_address_column(device_t, size_t, size_t);
   68 static int nand_fill_chip_structure(device_t, struct nand_chip *);
   69 static int nand_scan_media(device_t, struct nand_chip *);
   70 static bool nand_check_wp(device_t);
   71 
   72 CFATTACH_DECL_NEW(nand, sizeof(struct nand_softc),
   73     nand_match, nand_attach, nand_detach, NULL);
   74 
   75 #ifdef NAND_DEBUG
   76 int     nanddebug = NAND_DEBUG;
   77 #endif
   78 
   79 struct flash_interface nand_flash_if = {
   80         .type = FLASH_TYPE_NAND,
   81 
   82         .read = nand_flash_read,
   83         .write = nand_flash_write,
   84         .erase = nand_flash_erase,
   85         .block_isbad = nand_flash_isbad,
   86         .block_markbad = nand_flash_markbad,
   87 
   88         .submit = nand_flash_submit
   89 };
   90 
   91 const struct nand_manufacturer nand_mfrs[] = {
   92         { NAND_MFR_AMD,         "AMD" },
   93         { NAND_MFR_FUJITSU,     "Fujitsu" },
   94         { NAND_MFR_RENESAS,     "Renesas" },
   95         { NAND_MFR_STMICRO,     "ST Micro" },
   96         { NAND_MFR_MICRON,      "Micron" },
   97         { NAND_MFR_NATIONAL,    "National" },
   98         { NAND_MFR_TOSHIBA,     "Toshiba" },
   99         { NAND_MFR_HYNIX,       "Hynix" },
  100         { NAND_MFR_SAMSUNG,     "Samsung" },
  101         { NAND_MFR_UNKNOWN,     "Unknown" }
  102 };
  103 
  104 static const char *
  105 nand_midtoname(int id)
  106 {
  107         int i;
  108 
  109         for (i = 0; nand_mfrs[i].id != 0; i++) {
  110                 if (nand_mfrs[i].id == id)
  111                         return nand_mfrs[i].name;
  112         }
  113 
  114         KASSERT(nand_mfrs[i].id == 0);
  115 
  116         return nand_mfrs[i].name;
  117 }
  118 
  119 /* ARGSUSED */
  120 int
  121 nand_match(device_t parent, cfdata_t match, void *aux)
  122 {
  123         /* pseudo device, always attaches */
  124         return 1;
  125 }
  126 
  127 void
  128 nand_attach(device_t parent, device_t self, void *aux)
  129 {
  130         struct nand_softc *sc = device_private(self);
  131         struct nand_attach_args *naa = aux;
  132         struct nand_chip *chip = &sc->sc_chip;
  133 
  134         sc->sc_dev = self;
  135         sc->controller_dev = parent;
  136         sc->nand_if = naa->naa_nand_if;
  137 
  138         aprint_naive("\n");
  139 
  140         if (nand_check_wp(self)) {
  141                 aprint_error("NAND chip is write protected!\n");
  142                 return;
  143         }
  144 
  145         if (nand_scan_media(self, chip)) {
  146                 return;
  147         }
  148 
  149         nand_flash_if.erasesize = chip->nc_block_size;
  150         nand_flash_if.page_size = chip->nc_page_size;
  151         nand_flash_if.writesize = chip->nc_page_size;
  152 
  153         /* allocate cache */
  154         chip->nc_oob_cache = kmem_alloc(chip->nc_spare_size, KM_SLEEP);
  155         chip->nc_page_cache = kmem_alloc(chip->nc_page_size, KM_SLEEP);
  156 
  157         mutex_init(&sc->sc_device_lock, MUTEX_DEFAULT, IPL_NONE);
  158 
  159         if (flash_sync_thread_init(&sc->sc_flash_io, self, &nand_flash_if)) {
  160                 goto error;
  161         }
  162 
  163         if (!pmf_device_register1(sc->sc_dev, NULL, NULL, nand_shutdown))
  164                 aprint_error_dev(sc->sc_dev,
  165                     "couldn't establish power handler\n");
  166 
  167 #ifdef NAND_BBT
  168         nand_bbt_init(self);
  169         nand_bbt_scan(self);
  170 #endif
  171 
  172         /*
  173          * Attach all our devices
  174          */
  175         config_search(self, NULL,
  176             CFARGS(.search = nand_search));
  177 
  178         return;
  179 error:
  180         kmem_free(chip->nc_oob_cache, chip->nc_spare_size);
  181         kmem_free(chip->nc_page_cache, chip->nc_page_size);
  182         mutex_destroy(&sc->sc_device_lock);
  183 }
  184 
  185 static int
  186 nand_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
  187 {
  188         struct nand_softc *sc = device_private(parent);
  189         struct nand_chip *chip = &sc->sc_chip;
  190         struct flash_attach_args faa;
  191 
  192         if (cf->cf_loc[FLASHBUSCF_DYNAMIC] != 0)
  193                 return 0;
  194 
  195         faa.flash_if = &nand_flash_if;
  196 
  197         faa.partinfo.part_name = NULL;
  198         faa.partinfo.part_offset = cf->cf_loc[FLASHBUSCF_OFFSET];
  199 
  200         if (cf->cf_loc[FLASHBUSCF_SIZE] == 0) {
  201                 faa.partinfo.part_size = chip->nc_size -
  202                     faa.partinfo.part_offset;
  203         } else {
  204                 faa.partinfo.part_size = cf->cf_loc[FLASHBUSCF_SIZE];
  205         }
  206 
  207         if (cf->cf_loc[FLASHBUSCF_READONLY])
  208                 faa.partinfo.part_flags = FLASH_PART_READONLY;
  209         else
  210                 faa.partinfo.part_flags = 0;
  211 
  212         if (config_probe(parent, cf, &faa)) {
  213                 if (config_attach(parent, cf, &faa, nand_print,
  214                                   CFARGS_NONE) != NULL) {
  215                         return 0;
  216                 } else {
  217                         return 1;
  218                 }
  219         }
  220 
  221         return 1;
  222 }
  223 
  224 void
  225 nand_attach_mtdparts(device_t parent, const char *mtd_id, const char *cmdline)
  226 {
  227         struct nand_softc *sc = device_private(parent);
  228         struct nand_chip *chip = &sc->sc_chip;
  229 
  230         flash_attach_mtdparts(&nand_flash_if, parent, chip->nc_size,
  231             mtd_id, cmdline);
  232 }
  233 
  234 int
  235 nand_detach(device_t self, int flags)
  236 {
  237         struct nand_softc *sc = device_private(self);
  238         struct nand_chip *chip = &sc->sc_chip;
  239         int error = 0;
  240 
  241         error = config_detach_children(self, flags);
  242         if (error) {
  243                 return error;
  244         }
  245 
  246         flash_sync_thread_destroy(&sc->sc_flash_io);
  247 #ifdef NAND_BBT
  248         nand_bbt_detach(self);
  249 #endif
  250         /* free oob cache */
  251         kmem_free(chip->nc_oob_cache, chip->nc_spare_size);
  252         kmem_free(chip->nc_page_cache, chip->nc_page_size);
  253         kmem_free(chip->nc_ecc_cache, chip->nc_ecc->necc_size);
  254 
  255         mutex_destroy(&sc->sc_device_lock);
  256 
  257         pmf_device_deregister(sc->sc_dev);
  258 
  259         return error;
  260 }
  261 
  262 int
  263 nand_print(void *aux, const char *pnp)
  264 {
  265         if (pnp != NULL)
  266                 aprint_normal("nand at %s\n", pnp);
  267 
  268         return UNCONF;
  269 }
  270 
  271 /* ask for a nand driver to attach to the controller */
  272 device_t
  273 nand_attach_mi(struct nand_interface *nand_if, device_t parent)
  274 {
  275         struct nand_attach_args arg;
  276 
  277         KASSERT(nand_if != NULL);
  278 
  279         /* fill the defaults if we have null pointers */
  280         if (nand_if->program_page == NULL) {
  281                 nand_if->program_page = &nand_default_program_page;
  282         }
  283 
  284         if (nand_if->read_page == NULL) {
  285                 nand_if->read_page = &nand_default_read_page;
  286         }
  287 
  288         arg.naa_nand_if = nand_if;
  289         return config_found(parent, &arg, nand_print,
  290             CFARGS(.iattr = "nandbus"));
  291 }
  292 
  293 /* default everything to reasonable values, to ease future api changes */
  294 void
  295 nand_init_interface(struct nand_interface *interface)
  296 {
  297         interface->select = &nand_default_select;
  298         interface->command = NULL;
  299         interface->address = NULL;
  300         interface->read_buf_1 = NULL;
  301         interface->read_buf_2 = NULL;
  302         interface->read_1 = NULL;
  303         interface->read_2 = NULL;
  304         interface->write_buf_1 = NULL;
  305         interface->write_buf_2 = NULL;
  306         interface->write_1 = NULL;
  307         interface->write_2 = NULL;
  308         interface->busy = NULL;
  309 
  310         /*-
  311          * most drivers dont want to change this, but some implement
  312          * read/program in one step
  313          */
  314         interface->program_page = &nand_default_program_page;
  315         interface->read_page = &nand_default_read_page;
  316 
  317         /* default to soft ecc, that should work everywhere */
  318         interface->ecc_compute = &nand_default_ecc_compute;
  319         interface->ecc_correct = &nand_default_ecc_correct;
  320         interface->ecc_prepare = NULL;
  321         interface->ecc.necc_code_size = 3;
  322         interface->ecc.necc_block_size = 256;
  323         interface->ecc.necc_type = NAND_ECC_TYPE_SW;
  324 }
  325 
  326 #if 0
  327 /* handle quirks here */
  328 static void
  329 nand_quirks(device_t self, struct nand_chip *chip)
  330 {
  331         /* this is an example only! */
  332         switch (chip->nc_manf_id) {
  333         case NAND_MFR_SAMSUNG:
  334                 if (chip->nc_dev_id == 0x00) {
  335                         /* do something only samsung chips need */
  336                         /* or */
  337                         /* chip->nc_quirks |= NC_QUIRK_NO_READ_START */
  338                 }
  339         }
  340 
  341         return;
  342 }
  343 #endif
  344 
  345 static int
  346 nand_fill_chip_structure_legacy(device_t self, struct nand_chip *chip)
  347 {
  348         switch (chip->nc_manf_id) {
  349         case NAND_MFR_MICRON:
  350                 return nand_read_parameters_micron(self, chip);
  351         case NAND_MFR_SAMSUNG:
  352                 return nand_read_parameters_samsung(self, chip);
  353         case NAND_MFR_TOSHIBA:
  354                 return nand_read_parameters_toshiba(self, chip);
  355         default:
  356                 return 1;
  357         }
  358 
  359         return 0;
  360 }
  361 
  362 /**
  363  * scan media to determine the chip's properties
  364  * this function resets the device
  365  */
  366 static int
  367 nand_scan_media(device_t self, struct nand_chip *chip)
  368 {
  369         struct nand_softc *sc = device_private(self);
  370         struct nand_ecc *ecc;
  371         uint8_t onfi_signature[4];
  372 
  373         nand_select(self, true);
  374         nand_command(self, ONFI_RESET);
  375         KASSERT(nand_get_status(self) & ONFI_STATUS_RDY);
  376         nand_select(self, false);
  377 
  378         /* check if the device implements the ONFI standard */
  379         nand_select(self, true);
  380         nand_command(self, ONFI_READ_ID);
  381         nand_address(self, 0x20);
  382         nand_read_1(self, &onfi_signature[0]);
  383         nand_read_1(self, &onfi_signature[1]);
  384         nand_read_1(self, &onfi_signature[2]);
  385         nand_read_1(self, &onfi_signature[3]);
  386         nand_select(self, false);
  387 
  388 #ifdef NAND_DEBUG
  389         device_printf(self, "signature: %02x %02x %02x %02x\n",
  390             onfi_signature[0], onfi_signature[1],
  391             onfi_signature[2], onfi_signature[3]);
  392 #endif
  393 
  394         if (onfi_signature[0] != 'O' || onfi_signature[1] != 'N' ||
  395             onfi_signature[2] != 'F' || onfi_signature[3] != 'I') {
  396                 chip->nc_isonfi = false;
  397 
  398                 aprint_normal(": Legacy NAND Flash\n");
  399 
  400                 nand_read_id(self, &chip->nc_manf_id, &chip->nc_dev_id);
  401 
  402                 if (nand_fill_chip_structure_legacy(self, chip)) {
  403                         aprint_error_dev(self,
  404                             "can't read device parameters for legacy chip\n");
  405                         return 1;
  406                 }
  407         } else {
  408                 chip->nc_isonfi = true;
  409 
  410                 aprint_normal(": ONFI NAND Flash\n");
  411 
  412                 nand_read_id(self, &chip->nc_manf_id, &chip->nc_dev_id);
  413 
  414                 if (nand_fill_chip_structure(self, chip)) {
  415                         aprint_error_dev(self,
  416                             "can't read device parameters\n");
  417                         return 1;
  418                 }
  419         }
  420 
  421         aprint_normal_dev(self,
  422             "manufacturer id: 0x%.2x (%s), device id: 0x%.2x\n",
  423             chip->nc_manf_id,
  424             nand_midtoname(chip->nc_manf_id),
  425             chip->nc_dev_id);
  426 
  427         aprint_normal_dev(self,
  428             "page size: %" PRIu32 " bytes, spare size: %" PRIu32 " bytes, "
  429             "block size: %" PRIu32 " bytes\n",
  430             chip->nc_page_size, chip->nc_spare_size, chip->nc_block_size);
  431 
  432         aprint_normal_dev(self,
  433             "LUN size: %" PRIu32 " blocks, LUNs: %" PRIu8
  434             ", total storage size: %" PRIu64 " MB\n",
  435             chip->nc_lun_blocks, chip->nc_num_luns,
  436             chip->nc_size / 1024 / 1024);
  437 
  438         aprint_normal_dev(self, "column cycles: %" PRIu8 ", row cycles: %"
  439             PRIu8 ", width: %s\n",
  440             chip->nc_addr_cycles_column, chip->nc_addr_cycles_row,
  441             (chip->nc_flags & NC_BUSWIDTH_16) ? "x16" : "x8");
  442 
  443         ecc = chip->nc_ecc = &sc->nand_if->ecc;
  444 
  445         /*
  446          * calculate the place of ecc data in oob
  447          * we try to be compatible with Linux here
  448          */
  449         switch (chip->nc_spare_size) {
  450         case 8:
  451                 ecc->necc_offset = 0;
  452                 break;
  453         case 16:
  454                 ecc->necc_offset = 0;
  455                 break;
  456         case 32:
  457                 ecc->necc_offset = 0;
  458                 break;
  459         case 64:
  460                 ecc->necc_offset = 40;
  461                 break;
  462         case 128:
  463                 ecc->necc_offset = 80;
  464                 break;
  465         default:
  466                 panic("OOB size %" PRIu32 " is unexpected", chip->nc_spare_size);
  467         }
  468 
  469         ecc->necc_steps = chip->nc_page_size / ecc->necc_block_size;
  470         ecc->necc_size = ecc->necc_steps * ecc->necc_code_size;
  471 
  472         /* check if we fit in oob */
  473         if (ecc->necc_offset + ecc->necc_size > chip->nc_spare_size) {
  474                 panic("NAND ECC bits dont fit in OOB");
  475         }
  476 
  477         /* TODO: mark free oob area available for file systems */
  478 
  479         chip->nc_ecc_cache = kmem_zalloc(ecc->necc_size, KM_SLEEP);
  480 
  481         /*
  482          * calculate badblock marker offset in oob
  483          * we try to be compatible with linux here
  484          */
  485         if (chip->nc_page_size > 512)
  486                 chip->nc_badmarker_offs = 0;
  487         else
  488                 chip->nc_badmarker_offs = 5;
  489 
  490         /* Calculate page shift and mask */
  491         chip->nc_page_shift = ffs(chip->nc_page_size) - 1;
  492         chip->nc_page_mask = ~(chip->nc_page_size - 1);
  493         /* same for block */
  494         chip->nc_block_shift = ffs(chip->nc_block_size) - 1;
  495         chip->nc_block_mask = ~(chip->nc_block_size - 1);
  496 
  497         /* look for quirks here if needed in future */
  498         /* nand_quirks(self, chip); */
  499 
  500         return 0;
  501 }
  502 
  503 void
  504 nand_read_id(device_t self, uint8_t *manf, uint8_t *dev)
  505 {
  506         nand_select(self, true);
  507         nand_command(self, ONFI_READ_ID);
  508         nand_address(self, 0x00);
  509 
  510         nand_read_1(self, manf);
  511         nand_read_1(self, dev);
  512 
  513         nand_select(self, false);
  514 }
  515 
  516 int
  517 nand_read_parameter_page(device_t self, struct onfi_parameter_page *params)
  518 {
  519         uint8_t *bufp;
  520         uint16_t crc;
  521         int i;//, tries = 0;
  522 
  523         KASSERT(sizeof(*params) == 256);
  524 
  525 //read_params:
  526 //      tries++;
  527 
  528         nand_select(self, true);
  529         nand_command(self, ONFI_READ_PARAMETER_PAGE);
  530         nand_address(self, 0x00);
  531 
  532         nand_busy(self);
  533 
  534         /* TODO check the signature if it contains at least 2 letters */
  535 
  536         bufp = (uint8_t *)params;
  537         /* XXX why i am not using read_buf? */
  538         for (i = 0; i < 256; i++) {
  539                 nand_read_1(self, &bufp[i]);
  540         }
  541         nand_select(self, false);
  542 
  543         /* validate the parameter page with the crc */
  544         crc = nand_crc16(bufp, 254);
  545 
  546         if (crc != params->param_integrity_crc) {
  547                 aprint_error_dev(self, "parameter page crc check failed\n");
  548                 /* TODO: we should read the next parameter page copy */
  549                 return 1;
  550         }
  551 
  552         return 0;
  553 }
  554 
  555 static int
  556 nand_fill_chip_structure(device_t self, struct nand_chip *chip)
  557 {
  558         struct onfi_parameter_page params;
  559         uint8_t vendor[13], model[21];
  560         int i;
  561 
  562         if (nand_read_parameter_page(self, &params)) {
  563                 return 1;
  564         }
  565 
  566         /* strip manufacturer and model string */
  567         strlcpy(vendor, params.param_manufacturer, sizeof(vendor));
  568         for (i = 11; i > 0 && vendor[i] == ' '; i--)
  569                 vendor[i] = 0;
  570         strlcpy(model, params.param_model, sizeof(model));
  571         for (i = 19; i > 0 && model[i] == ' '; i--)
  572                 model[i] = 0;
  573 
  574         aprint_normal_dev(self, "vendor: %s, model: %s\n", vendor, model);
  575 
  576         chip->nc_page_size = le32toh(params.param_pagesize);
  577         chip->nc_block_size =
  578             le32toh(params.param_blocksize) * chip->nc_page_size;
  579         chip->nc_spare_size = le16toh(params.param_sparesize);
  580         chip->nc_lun_blocks = le32toh(params.param_lunsize);
  581         chip->nc_num_luns = params.param_numluns;
  582 
  583         chip->nc_size =
  584             chip->nc_block_size * chip->nc_lun_blocks * chip->nc_num_luns;
  585 
  586         /* the lower 4 bits contain the row address cycles */
  587         chip->nc_addr_cycles_row = params.param_addr_cycles & 0x07;
  588         /* the upper 4 bits contain the column address cycles */
  589         chip->nc_addr_cycles_column = (params.param_addr_cycles & ~0x07) >> 4;
  590 
  591         uint16_t features = le16toh(params.param_features);
  592         if (features & ONFI_FEATURE_16BIT) {
  593                 chip->nc_flags |= NC_BUSWIDTH_16;
  594         }
  595 
  596         if (features & ONFI_FEATURE_EXTENDED_PARAM) {
  597                 chip->nc_flags |= NC_EXTENDED_PARAM;
  598         }
  599 
  600         return 0;
  601 }
  602 
  603 /* ARGSUSED */
  604 bool
  605 nand_shutdown(device_t self, int howto)
  606 {
  607         return true;
  608 }
  609 
  610 static void
  611 nand_address_column(device_t self, size_t row, size_t column)
  612 {
  613         struct nand_softc *sc = device_private(self);
  614         struct nand_chip *chip = &sc->sc_chip;
  615         uint8_t i;
  616 
  617         DPRINTF(("addressing row: 0x%jx column: %" PRIu32 "\n",
  618                 (uintmax_t )row, column));
  619 
  620         /* XXX TODO */
  621         row >>= chip->nc_page_shift;
  622 
  623         /* Write the column (subpage) address */
  624         if (chip->nc_flags & NC_BUSWIDTH_16)
  625                 column >>= 1;
  626         for (i = 0; i < chip->nc_addr_cycles_column; i++, column >>= 8)
  627                 nand_address(self, column & 0xff);
  628 
  629         /* Write the row (page) address */
  630         for (i = 0; i < chip->nc_addr_cycles_row; i++, row >>= 8)
  631                 nand_address(self, row & 0xff);
  632 }
  633 
  634 static void
  635 nand_address_row(device_t self, size_t row)
  636 {
  637         struct nand_softc *sc = device_private(self);
  638         struct nand_chip *chip = &sc->sc_chip;
  639         int i;
  640 
  641         /* XXX TODO */
  642         row >>= chip->nc_page_shift;
  643 
  644         /* Write the row (page) address */
  645         for (i = 0; i < chip->nc_addr_cycles_row; i++, row >>= 8)
  646                 nand_address(self, row & 0xff);
  647 }
  648 
  649 static inline uint8_t
  650 nand_get_status(device_t self)
  651 {
  652         uint8_t status;
  653 
  654         nand_command(self, ONFI_READ_STATUS);
  655         nand_busy(self);
  656         nand_read_1(self, &status);
  657 
  658         return status;
  659 }
  660 
  661 static bool
  662 nand_check_wp(device_t self)
  663 {
  664         if (nand_get_status(self) & ONFI_STATUS_WP)
  665                 return false;
  666         else
  667                 return true;
  668 }
  669 
  670 static void
  671 nand_prepare_read(device_t self, flash_off_t row, flash_off_t column)
  672 {
  673         nand_command(self, ONFI_READ);
  674         nand_address_column(self, row, column);
  675         nand_command(self, ONFI_READ_START);
  676 
  677         nand_busy(self);
  678 }
  679 
  680 /* read a page with ecc correction, default implementation */
  681 int
  682 nand_default_read_page(device_t self, size_t offset, uint8_t *data)
  683 {
  684         struct nand_softc *sc = device_private(self);
  685         struct nand_chip *chip = &sc->sc_chip;
  686         size_t b, bs, e, cs;
  687         uint8_t *ecc;
  688         int result;
  689 
  690         nand_prepare_read(self, offset, 0);
  691 
  692         bs = chip->nc_ecc->necc_block_size;
  693         cs = chip->nc_ecc->necc_code_size;
  694 
  695         /* decide if we access by 8 or 16 bits */
  696         if (chip->nc_flags & NC_BUSWIDTH_16) {
  697                 for (b = 0, e = 0; b < chip->nc_page_size; b += bs, e += cs) {
  698                         nand_ecc_prepare(self, NAND_ECC_READ);
  699                         nand_read_buf_2(self, data + b, bs);
  700                         nand_ecc_compute(self, data + b,
  701                             chip->nc_ecc_cache + e);
  702                 }
  703         } else {
  704                 for (b = 0, e = 0; b < chip->nc_page_size; b += bs, e += cs) {
  705                         nand_ecc_prepare(self, NAND_ECC_READ);
  706                         nand_read_buf_1(self, data + b, bs);
  707                         nand_ecc_compute(self, data + b,
  708                             chip->nc_ecc_cache + e);
  709                 }
  710         }
  711 
  712         /* for debugging new drivers */
  713 #if 0
  714         nand_dump_data("page", data, chip->nc_page_size);
  715 #endif
  716 
  717         nand_read_oob(self, offset, chip->nc_oob_cache);
  718         ecc = chip->nc_oob_cache + chip->nc_ecc->necc_offset;
  719 
  720         /* useful for debugging new ecc drivers */
  721 #if 0
  722         printf("dumping ecc %d\n--------------\n", chip->nc_ecc->necc_steps);
  723         for (e = 0; e < chip->nc_ecc->necc_steps; e++) {
  724                 printf("0x");
  725                 for (b = 0; b < cs; b++) {
  726                         printf("%.2hhx", ecc[e+b]);
  727                 }
  728                 printf(" 0x");
  729                 for (b = 0; b < cs; b++) {
  730                         printf("%.2hhx", chip->nc_ecc_cache[e+b]);
  731                 }
  732                 printf("\n");
  733         }
  734         printf("--------------\n");
  735 #endif
  736 
  737         for (b = 0, e = 0; b < chip->nc_page_size; b += bs, e += cs) {
  738                 result = nand_ecc_correct(self, data + b, ecc + e,
  739                     chip->nc_ecc_cache + e);
  740 
  741                 switch (result) {
  742                 case NAND_ECC_OK:
  743                         break;
  744                 case NAND_ECC_CORRECTED:
  745                         aprint_error_dev(self,
  746                             "data corrected with ECC at page offset 0x%jx "
  747                             "block %zu\n", (uintmax_t)offset, b);
  748                         break;
  749                 case NAND_ECC_TWOBIT:
  750                         aprint_error_dev(self,
  751                             "uncorrectable ECC error at page offset 0x%jx "
  752                             "block %zu\n", (uintmax_t)offset, b);
  753                         return EIO;
  754                         break;
  755                 case NAND_ECC_INVALID:
  756                         aprint_error_dev(self,
  757                             "invalid ECC in oob at page offset 0x%jx "
  758                             "block %zu\n", (uintmax_t)offset, b);
  759                         return EIO;
  760                         break;
  761                 default:
  762                         panic("invalid ECC correction errno");
  763                 }
  764         }
  765 
  766         return 0;
  767 }
  768 
  769 int
  770 nand_default_program_page(device_t self, size_t page, const uint8_t *data)
  771 {
  772         struct nand_softc *sc = device_private(self);
  773         struct nand_chip *chip = &sc->sc_chip;
  774         size_t bs, cs, e, b;
  775         uint8_t status;
  776         uint8_t *ecc;
  777 
  778         nand_command(self, ONFI_PAGE_PROGRAM);
  779         nand_address_column(self, page, 0);
  780 
  781         nand_busy(self);
  782 
  783         bs = chip->nc_ecc->necc_block_size;
  784         cs = chip->nc_ecc->necc_code_size;
  785         ecc = chip->nc_oob_cache + chip->nc_ecc->necc_offset;
  786 
  787         /* XXX code duplication */
  788         /* decide if we access by 8 or 16 bits */
  789         if (chip->nc_flags & NC_BUSWIDTH_16) {
  790                 for (b = 0, e = 0; b < chip->nc_page_size; b += bs, e += cs) {
  791                         nand_ecc_prepare(self, NAND_ECC_WRITE);
  792                         nand_write_buf_2(self, data + b, bs);
  793                         nand_ecc_compute(self, data + b, ecc + e);
  794                 }
  795                 /* write oob with ecc correction code */
  796                 nand_write_buf_2(self, chip->nc_oob_cache,
  797                     chip->nc_spare_size);
  798         } else {
  799                 for (b = 0, e = 0; b < chip->nc_page_size; b += bs, e += cs) {
  800                         nand_ecc_prepare(self, NAND_ECC_WRITE);
  801                         nand_write_buf_1(self, data + b, bs);
  802                         nand_ecc_compute(self, data + b, ecc + e);
  803                 }
  804                 /* write oob with ecc correction code */
  805                 nand_write_buf_1(self, chip->nc_oob_cache,
  806                     chip->nc_spare_size);
  807         }
  808 
  809         nand_command(self, ONFI_PAGE_PROGRAM_START);
  810 
  811         nand_busy(self);
  812 
  813         /* for debugging ecc */
  814 #if 0
  815         printf("dumping ecc %d\n--------------\n", chip->nc_ecc->necc_steps);
  816         for (e = 0; e < chip->nc_ecc->necc_steps; e++) {
  817                 printf("0x");
  818                 for (b = 0; b < cs; b++) {
  819                         printf("%.2hhx", ecc[e+b]);
  820                 }
  821                 printf("\n");
  822         }
  823         printf("--------------\n");
  824 #endif
  825 
  826         status = nand_get_status(self);
  827         KASSERT(status & ONFI_STATUS_RDY);
  828         if (status & ONFI_STATUS_FAIL) {
  829                 aprint_error_dev(self, "page program failed!\n");
  830                 return EIO;
  831         }
  832 
  833         return 0;
  834 }
  835 
  836 /* read the OOB of a page */
  837 int
  838 nand_read_oob(device_t self, size_t page, uint8_t *oob)
  839 {
  840         struct nand_softc *sc = device_private(self);
  841         struct nand_chip *chip = &sc->sc_chip;
  842 
  843         nand_prepare_read(self, page, chip->nc_page_size);
  844 
  845         if (chip->nc_flags & NC_BUSWIDTH_16)
  846                 nand_read_buf_2(self, oob, chip->nc_spare_size);
  847         else
  848                 nand_read_buf_1(self, oob, chip->nc_spare_size);
  849 
  850         /* for debugging drivers */
  851 #if 0
  852         nand_dump_data("oob", oob, chip->nc_spare_size);
  853 #endif
  854 
  855         return 0;
  856 }
  857 
  858 static int
  859 nand_write_oob(device_t self, size_t offset, const void *oob)
  860 {
  861         struct nand_softc *sc = device_private(self);
  862         struct nand_chip *chip = &sc->sc_chip;
  863         uint8_t status;
  864 
  865         nand_command(self, ONFI_PAGE_PROGRAM);
  866         nand_address_column(self, offset, chip->nc_page_size);
  867         nand_command(self, ONFI_PAGE_PROGRAM_START);
  868 
  869         nand_busy(self);
  870 
  871         if (chip->nc_flags & NC_BUSWIDTH_16)
  872                 nand_write_buf_2(self, oob, chip->nc_spare_size);
  873         else
  874                 nand_write_buf_1(self, oob, chip->nc_spare_size);
  875 
  876         status = nand_get_status(self);
  877         KASSERT(status & ONFI_STATUS_RDY);
  878         if (status & ONFI_STATUS_FAIL)
  879                 return EIO;
  880         else
  881                 return 0;
  882 }
  883 
  884 void
  885 nand_markbad(device_t self, size_t offset)
  886 {
  887         struct nand_softc *sc = device_private(self);
  888         struct nand_chip *chip = &sc->sc_chip;
  889         flash_off_t blockoffset;
  890 #ifdef NAND_BBT
  891         flash_off_t block;
  892 
  893         block = offset / chip->nc_block_size;
  894 
  895         nand_bbt_block_markbad(self, block);
  896 #endif
  897         blockoffset = offset & chip->nc_block_mask;
  898 
  899         /* check if it is already marked bad */
  900         if (nand_isbad(self, blockoffset))
  901                 return;
  902 
  903         nand_read_oob(self, blockoffset, chip->nc_oob_cache);
  904 
  905         chip->nc_oob_cache[chip->nc_badmarker_offs] = 0x00;
  906         chip->nc_oob_cache[chip->nc_badmarker_offs + 1] = 0x00;
  907 
  908         nand_write_oob(self, blockoffset, chip->nc_oob_cache);
  909 }
  910 
  911 bool
  912 nand_isfactorybad(device_t self, flash_off_t offset)
  913 {
  914         struct nand_softc *sc = device_private(self);
  915         struct nand_chip *chip = &sc->sc_chip;
  916         flash_off_t block, first_page, last_page, page;
  917         int i;
  918 
  919         /* Check for factory bad blocks first
  920          * Factory bad blocks are marked in the first or last
  921          * page of the blocks, see: ONFI 2.2, 3.2.2.
  922          */
  923         block = offset / chip->nc_block_size;
  924         first_page = block * chip->nc_block_size;
  925         last_page = (block + 1) * chip->nc_block_size
  926             - chip->nc_page_size;
  927 
  928         for (i = 0, page = first_page; i < 2; i++, page = last_page) {
  929                 /* address OOB */
  930                 nand_prepare_read(self, page, chip->nc_page_size);
  931 
  932                 if (chip->nc_flags & NC_BUSWIDTH_16) {
  933                         uint16_t word;
  934                         nand_read_2(self, &word);
  935                         if (word == 0x0000)
  936                                 return true;
  937                 } else {
  938                         uint8_t byte;
  939                         nand_read_1(self, &byte);
  940                         if (byte == 0x00)
  941                                 return true;
  942                 }
  943         }
  944 
  945         return false;
  946 }
  947 
  948 bool
  949 nand_iswornoutbad(device_t self, flash_off_t offset)
  950 {
  951         struct nand_softc *sc = device_private(self);
  952         struct nand_chip *chip = &sc->sc_chip;
  953         flash_off_t block;
  954 
  955         /* we inspect the first page of the block */
  956         block = offset & chip->nc_block_mask;
  957 
  958         /* Linux/u-boot compatible badblock handling */
  959         if (chip->nc_flags & NC_BUSWIDTH_16) {
  960                 uint16_t word, mark;
  961 
  962                 nand_prepare_read(self, block,
  963                     chip->nc_page_size + (chip->nc_badmarker_offs & 0xfe));
  964 
  965                 nand_read_2(self, &word);
  966                 mark = htole16(word);
  967                 if (chip->nc_badmarker_offs & 0x01)
  968                         mark >>= 8;
  969                 if ((mark & 0xff) != 0xff)
  970                         return true;
  971         } else {
  972                 uint8_t byte;
  973 
  974                 nand_prepare_read(self, block,
  975                     chip->nc_page_size + chip->nc_badmarker_offs);
  976 
  977                 nand_read_1(self, &byte);
  978                 if (byte != 0xff)
  979                         return true;
  980         }
  981 
  982         return false;
  983 }
  984 
  985 bool
  986 nand_isbad(device_t self, flash_off_t offset)
  987 {
  988 #ifdef NAND_BBT
  989         struct nand_softc *sc = device_private(self);
  990         struct nand_chip *chip = &sc->sc_chip;
  991         flash_off_t block;
  992 
  993         block = offset / chip->nc_block_size;
  994 
  995         return nand_bbt_block_isbad(self, block);
  996 #else
  997         /* ONFI host requirement */
  998         if (nand_isfactorybad(self, offset))
  999                 return true;
 1000 
 1001         /* Look for Linux/U-Boot compatible bad marker */
 1002         if (nand_iswornoutbad(self, offset))
 1003                 return true;
 1004 
 1005         return false;
 1006 #endif
 1007 }
 1008 
 1009 int
 1010 nand_erase_block(device_t self, size_t offset)
 1011 {
 1012         uint8_t status;
 1013 
 1014         /* xxx calculate first page of block for address? */
 1015 
 1016         nand_command(self, ONFI_BLOCK_ERASE);
 1017         nand_address_row(self, offset);
 1018         nand_command(self, ONFI_BLOCK_ERASE_START);
 1019 
 1020         nand_busy(self);
 1021 
 1022         status = nand_get_status(self);
 1023         KASSERT(status & ONFI_STATUS_RDY);
 1024         if (status & ONFI_STATUS_FAIL) {
 1025                 aprint_error_dev(self, "block erase failed!\n");
 1026                 nand_markbad(self, offset);
 1027                 return EIO;
 1028         } else {
 1029                 return 0;
 1030         }
 1031 }
 1032 
 1033 /* default functions for driver development */
 1034 
 1035 /* default ECC using hamming code of 256 byte chunks */
 1036 int
 1037 nand_default_ecc_compute(device_t self, const uint8_t *data, uint8_t *code)
 1038 {
 1039         hamming_compute_256(data, code);
 1040 
 1041         return 0;
 1042 }
 1043 
 1044 int
 1045 nand_default_ecc_correct(device_t self, uint8_t *data, const uint8_t *origcode,
 1046         const uint8_t *compcode)
 1047 {
 1048         return hamming_correct_256(data, origcode, compcode);
 1049 }
 1050 
 1051 void
 1052 nand_default_select(device_t self, bool enable)
 1053 {
 1054         /* do nothing */
 1055         return;
 1056 }
 1057 
 1058 /* implementation of the block device API */
 1059 
 1060 int
 1061 nand_flash_submit(device_t self, struct buf * const bp)
 1062 {
 1063         struct nand_softc *sc = device_private(self);
 1064 
 1065         return flash_io_submit(&sc->sc_flash_io, bp);
 1066 }
 1067 
 1068 /*
 1069  * handle (page) unaligned write to nand
 1070  */
 1071 static int
 1072 nand_flash_write_unaligned(device_t self, flash_off_t offset, size_t len,
 1073     size_t *retlen, const uint8_t *buf)
 1074 {
 1075         struct nand_softc *sc = device_private(self);
 1076         struct nand_chip *chip = &sc->sc_chip;
 1077         flash_off_t first, last, firstoff;
 1078         const uint8_t *bufp;
 1079         flash_off_t addr;
 1080         size_t left, count;
 1081         int error = 0, i;
 1082 
 1083         first = offset & chip->nc_page_mask;
 1084         firstoff = offset & ~chip->nc_page_mask;
 1085         /* XXX check if this should be len - 1 */
 1086         last = (offset + len) & chip->nc_page_mask;
 1087         count = last - first + 1;
 1088 
 1089         addr = first;
 1090         *retlen = 0;
 1091 
 1092         mutex_enter(&sc->sc_device_lock);
 1093         if (count == 1) {
 1094                 if (nand_isbad(self, addr)) {
 1095                         aprint_error_dev(self,
 1096                             "nand_flash_write_unaligned: "
 1097                             "bad block encountered\n");
 1098                         error = EIO;
 1099                         goto out;
 1100                 }
 1101 
 1102                 error = nand_read_page(self, addr, chip->nc_page_cache);
 1103                 if (error) {
 1104                         goto out;
 1105                 }
 1106 
 1107                 memcpy(chip->nc_page_cache + firstoff, buf, len);
 1108 
 1109                 error = nand_program_page(self, addr, chip->nc_page_cache);
 1110                 if (error) {
 1111                         goto out;
 1112                 }
 1113 
 1114                 *retlen = len;
 1115                 goto out;
 1116         }
 1117 
 1118         bufp = buf;
 1119         left = len;
 1120 
 1121         for (i = 0; i < count && left != 0; i++) {
 1122                 if (nand_isbad(self, addr)) {
 1123                         aprint_error_dev(self,
 1124                             "nand_flash_write_unaligned: "
 1125                             "bad block encountered\n");
 1126                         error = EIO;
 1127                         goto out;
 1128                 }
 1129 
 1130                 if (i == 0) {
 1131                         error = nand_read_page(self,
 1132                             addr, chip->nc_page_cache);
 1133                         if (error) {
 1134                                 goto out;
 1135                         }
 1136 
 1137                         memcpy(chip->nc_page_cache + firstoff,
 1138                             bufp, chip->nc_page_size - firstoff);
 1139 
 1140                         printf("program page: %s: %d\n", __FILE__, __LINE__);
 1141                         error = nand_program_page(self,
 1142                             addr, chip->nc_page_cache);
 1143                         if (error) {
 1144                                 goto out;
 1145                         }
 1146 
 1147                         bufp += chip->nc_page_size - firstoff;
 1148                         left -= chip->nc_page_size - firstoff;
 1149                         *retlen += chip->nc_page_size - firstoff;
 1150 
 1151                 } else if (i == count - 1) {
 1152                         error = nand_read_page(self,
 1153                             addr, chip->nc_page_cache);
 1154                         if (error) {
 1155                                 goto out;
 1156                         }
 1157 
 1158                         memcpy(chip->nc_page_cache, bufp, left);
 1159 
 1160                         error = nand_program_page(self,
 1161                             addr, chip->nc_page_cache);
 1162                         if (error) {
 1163                                 goto out;
 1164                         }
 1165 
 1166                         *retlen += left;
 1167                         KASSERT(left < chip->nc_page_size);
 1168 
 1169                 } else {
 1170                         /* XXX debug */
 1171                         if (left > chip->nc_page_size) {
 1172                                 printf("left: %zu, i: %d, count: %zu\n",
 1173                                     left, i, count);
 1174                         }
 1175                         KASSERT(left > chip->nc_page_size);
 1176 
 1177                         error = nand_program_page(self, addr, bufp);
 1178                         if (error) {
 1179                                 goto out;
 1180                         }
 1181 
 1182                         bufp += chip->nc_page_size;
 1183                         left -= chip->nc_page_size;
 1184                         *retlen += chip->nc_page_size;
 1185                 }
 1186 
 1187                 addr += chip->nc_page_size;
 1188         }
 1189 
 1190         KASSERT(*retlen == len);
 1191 out:
 1192         mutex_exit(&sc->sc_device_lock);
 1193 
 1194         return error;
 1195 }
 1196 
 1197 int
 1198 nand_flash_write(device_t self, flash_off_t offset, size_t len, size_t *retlen,
 1199     const uint8_t *buf)
 1200 {
 1201         struct nand_softc *sc = device_private(self);
 1202         struct nand_chip *chip = &sc->sc_chip;
 1203         const uint8_t *bufp;
 1204         size_t pages, page;
 1205         daddr_t addr;
 1206         int error = 0;
 1207 
 1208         if ((offset + len) > chip->nc_size) {
 1209                 DPRINTF(("nand_flash_write: write (off: 0x%jx, len: %ju),"
 1210                         " is over device size (0x%jx)\n",
 1211                         (uintmax_t)offset, (uintmax_t)len,
 1212                         (uintmax_t)chip->nc_size));
 1213                 return EINVAL;
 1214         }
 1215 
 1216         if (len % chip->nc_page_size != 0 ||
 1217             offset % chip->nc_page_size != 0) {
 1218                 return nand_flash_write_unaligned(self,
 1219                     offset, len, retlen, buf);
 1220         }
 1221 
 1222         pages = len / chip->nc_page_size;
 1223         KASSERT(pages != 0);
 1224         *retlen = 0;
 1225 
 1226         addr = offset;
 1227         bufp = buf;
 1228 
 1229         mutex_enter(&sc->sc_device_lock);
 1230         for (page = 0; page < pages; page++) {
 1231                 /* do we need this check here? */
 1232                 if (nand_isbad(self, addr)) {
 1233                         aprint_error_dev(self,
 1234                             "nand_flash_write: bad block encountered\n");
 1235 
 1236                         error = EIO;
 1237                         goto out;
 1238                 }
 1239 
 1240                 error = nand_program_page(self, addr, bufp);
 1241                 if (error) {
 1242                         goto out;
 1243                 }
 1244 
 1245                 addr += chip->nc_page_size;
 1246                 bufp += chip->nc_page_size;
 1247                 *retlen += chip->nc_page_size;
 1248         }
 1249 out:
 1250         mutex_exit(&sc->sc_device_lock);
 1251         DPRINTF(("page programming: retlen: %" PRIu32 ", len: %" PRIu32 "\n", *retlen, len));
 1252 
 1253         return error;
 1254 }
 1255 
 1256 /*
 1257  * handle (page) unaligned read from nand
 1258  */
 1259 static int
 1260 nand_flash_read_unaligned(device_t self, size_t offset,
 1261     size_t len, size_t *retlen, uint8_t *buf)
 1262 {
 1263         struct nand_softc *sc = device_private(self);
 1264         struct nand_chip *chip = &sc->sc_chip;
 1265         daddr_t first, last, count, firstoff;
 1266         uint8_t *bufp;
 1267         daddr_t addr;
 1268         size_t left;
 1269         int error = 0, i;
 1270 
 1271         first = offset & chip->nc_page_mask;
 1272         firstoff = offset & ~chip->nc_page_mask;
 1273         last = (offset + len) & chip->nc_page_mask;
 1274         count = (last - first) / chip->nc_page_size + 1;
 1275 
 1276         addr = first;
 1277         bufp = buf;
 1278         left = len;
 1279         *retlen = 0;
 1280 
 1281         mutex_enter(&sc->sc_device_lock);
 1282         if (count == 1) {
 1283                 error = nand_read_page(self, addr, chip->nc_page_cache);
 1284                 if (error) {
 1285                         goto out;
 1286                 }
 1287 
 1288                 memcpy(bufp, chip->nc_page_cache + firstoff, len);
 1289 
 1290                 *retlen = len;
 1291                 goto out;
 1292         }
 1293 
 1294         for (i = 0; i < count && left != 0; i++) {
 1295                 error = nand_read_page(self, addr, chip->nc_page_cache);
 1296                 if (error) {
 1297                         goto out;
 1298                 }
 1299 
 1300                 if (i == 0) {
 1301                         memcpy(bufp, chip->nc_page_cache + firstoff,
 1302                             chip->nc_page_size - firstoff);
 1303 
 1304                         bufp += chip->nc_page_size - firstoff;
 1305                         left -= chip->nc_page_size - firstoff;
 1306                         *retlen += chip->nc_page_size - firstoff;
 1307 
 1308                 } else if (i == count - 1) {
 1309                         memcpy(bufp, chip->nc_page_cache, left);
 1310                         *retlen += left;
 1311                         KASSERT(left < chip->nc_page_size);
 1312 
 1313                 } else {
 1314                         memcpy(bufp, chip->nc_page_cache, chip->nc_page_size);
 1315 
 1316                         bufp += chip->nc_page_size;
 1317                         left -= chip->nc_page_size;
 1318                         *retlen += chip->nc_page_size;
 1319                 }
 1320 
 1321                 addr += chip->nc_page_size;
 1322         }
 1323         KASSERT(*retlen == len);
 1324 out:
 1325         mutex_exit(&sc->sc_device_lock);
 1326 
 1327         return error;
 1328 }
 1329 
 1330 int
 1331 nand_flash_read(device_t self, flash_off_t offset, size_t len, size_t *retlen,
 1332     uint8_t *buf)
 1333 {
 1334         struct nand_softc *sc = device_private(self);
 1335         struct nand_chip *chip = &sc->sc_chip;
 1336         uint8_t *bufp;
 1337         size_t addr;
 1338         size_t i, pages;
 1339         int error = 0;
 1340 
 1341         *retlen = 0;
 1342 
 1343         DPRINTF(("nand_flash_read: off: 0x%jx, len: %" PRIu32 "\n",
 1344                 (uintmax_t)offset, len));
 1345 
 1346         if (__predict_false((offset + len) > chip->nc_size)) {
 1347                 DPRINTF(("nand_flash_read: read (off: 0x%jx, len: %" PRIu32 "),"
 1348                         " is over device size (%ju)\n", (uintmax_t)offset,
 1349                         len, (uintmax_t)chip->nc_size));
 1350                 return EINVAL;
 1351         }
 1352 
 1353         /* Handle unaligned access, shouldnt be needed when using the
 1354          * block device, as strategy handles it, so only low level
 1355          * accesses will use this path
 1356          */
 1357         /* XXX^2 */
 1358 #if 0
 1359         if (len < chip->nc_page_size)
 1360                 panic("TODO page size is larger than read size");
 1361 #endif
 1362 
 1363         if (len % chip->nc_page_size != 0 ||
 1364             offset % chip->nc_page_size != 0) {
 1365                 return nand_flash_read_unaligned(self,
 1366                     offset, len, retlen, buf);
 1367         }
 1368 
 1369         bufp = buf;
 1370         addr = offset;
 1371         pages = len / chip->nc_page_size;
 1372 
 1373         mutex_enter(&sc->sc_device_lock);
 1374         for (i = 0; i < pages; i++) {
 1375                 /* XXX do we need this check here? */
 1376                 if (nand_isbad(self, addr)) {
 1377                         aprint_error_dev(self, "bad block encountered\n");
 1378                         error = EIO;
 1379                         goto out;
 1380                 }
 1381                 error = nand_read_page(self, addr, bufp);
 1382                 if (error)
 1383                         goto out;
 1384 
 1385                 bufp += chip->nc_page_size;
 1386                 addr += chip->nc_page_size;
 1387                 *retlen += chip->nc_page_size;
 1388         }
 1389 out:
 1390         mutex_exit(&sc->sc_device_lock);
 1391 
 1392         return error;
 1393 }
 1394 
 1395 int
 1396 nand_flash_isbad(device_t self, flash_off_t ofs, bool *is_bad)
 1397 {
 1398         struct nand_softc *sc = device_private(self);
 1399         struct nand_chip *chip = &sc->sc_chip;
 1400         bool result;
 1401 
 1402         if (ofs > chip->nc_size) {
 1403                 DPRINTF(("nand_flash_isbad: offset 0x%jx is larger than"
 1404                         " device size (0x%jx)\n", (uintmax_t)ofs,
 1405                         (uintmax_t)chip->nc_size));
 1406                 return EINVAL;
 1407         }
 1408 
 1409         if (ofs % chip->nc_block_size != 0) {
 1410                 DPRINTF(("offset (0x%jx) is not a multiple of block size "
 1411                         "(%ju)",
 1412                         (uintmax_t)ofs, (uintmax_t)chip->nc_block_size));
 1413                 return EINVAL;
 1414         }
 1415 
 1416         mutex_enter(&sc->sc_device_lock);
 1417         result = nand_isbad(self, ofs);
 1418         mutex_exit(&sc->sc_device_lock);
 1419 
 1420         *is_bad = result;
 1421 
 1422         return 0;
 1423 }
 1424 
 1425 int
 1426 nand_flash_markbad(device_t self, flash_off_t ofs)
 1427 {
 1428         struct nand_softc *sc = device_private(self);
 1429         struct nand_chip *chip = &sc->sc_chip;
 1430 
 1431         if (ofs > chip->nc_size) {
 1432                 DPRINTF(("nand_flash_markbad: offset 0x%jx is larger than"
 1433                         " device size (0x%jx)\n", ofs,
 1434                         (uintmax_t)chip->nc_size));
 1435                 return EINVAL;
 1436         }
 1437 
 1438         if (ofs % chip->nc_block_size != 0) {
 1439                 panic("offset (%ju) is not a multiple of block size (%ju)",
 1440                     (uintmax_t)ofs, (uintmax_t)chip->nc_block_size);
 1441         }
 1442 
 1443         mutex_enter(&sc->sc_device_lock);
 1444         nand_markbad(self, ofs);
 1445         mutex_exit(&sc->sc_device_lock);
 1446 
 1447         return 0;
 1448 }
 1449 
 1450 int
 1451 nand_flash_erase(device_t self,
 1452     struct flash_erase_instruction *ei)
 1453 {
 1454         struct nand_softc *sc = device_private(self);
 1455         struct nand_chip *chip = &sc->sc_chip;
 1456         flash_off_t addr;
 1457         int error = 0;
 1458 
 1459         if (ei->ei_addr < 0 || ei->ei_len < chip->nc_block_size)
 1460                 return EINVAL;
 1461 
 1462         if (ei->ei_addr + ei->ei_len > chip->nc_size) {
 1463                 DPRINTF(("nand_flash_erase: erase address is over the end"
 1464                         " of the device\n"));
 1465                 return EINVAL;
 1466         }
 1467 
 1468         if (ei->ei_addr % chip->nc_block_size != 0) {
 1469                 aprint_error_dev(self,
 1470                     "nand_flash_erase: ei_addr (%ju) is not"
 1471                     " a multiple of block size (%ju)",
 1472                     (uintmax_t)ei->ei_addr,
 1473                     (uintmax_t)chip->nc_block_size);
 1474                 return EINVAL;
 1475         }
 1476 
 1477         if (ei->ei_len % chip->nc_block_size != 0) {
 1478                 aprint_error_dev(self,
 1479                     "nand_flash_erase: ei_len (%ju) is not"
 1480                     " a multiple of block size (%ju)",
 1481                     (uintmax_t)ei->ei_len,
 1482                     (uintmax_t)chip->nc_block_size);
 1483                 return EINVAL;
 1484         }
 1485 
 1486         mutex_enter(&sc->sc_device_lock);
 1487         addr = ei->ei_addr;
 1488         while (addr < ei->ei_addr + ei->ei_len) {
 1489                 if (nand_isbad(self, addr)) {
 1490                         aprint_error_dev(self, "bad block encountered\n");
 1491                         ei->ei_state = FLASH_ERASE_FAILED;
 1492                         error = EIO;
 1493                         goto out;
 1494                 }
 1495 
 1496                 error = nand_erase_block(self, addr);
 1497                 if (error) {
 1498                         ei->ei_state = FLASH_ERASE_FAILED;
 1499                         goto out;
 1500                 }
 1501 
 1502                 addr += chip->nc_block_size;
 1503         }
 1504         mutex_exit(&sc->sc_device_lock);
 1505 
 1506         ei->ei_state = FLASH_ERASE_DONE;
 1507         if (ei->ei_callback != NULL) {
 1508                 ei->ei_callback(ei);
 1509         }
 1510 
 1511         return 0;
 1512 out:
 1513         mutex_exit(&sc->sc_device_lock);
 1514 
 1515         return error;
 1516 }
 1517 
 1518 MODULE(MODULE_CLASS_DRIVER, nand, "flash");
 1519 
 1520 #ifdef _MODULE
 1521 #include "ioconf.c"
 1522 #endif
 1523 
 1524 static int
 1525 nand_modcmd(modcmd_t cmd, void *opaque)
 1526 {
 1527         switch (cmd) {
 1528         case MODULE_CMD_INIT:
 1529 #ifdef _MODULE
 1530                 return config_init_component(cfdriver_ioconf_nand,
 1531                     cfattach_ioconf_nand, cfdata_ioconf_nand);
 1532 #else
 1533                 return 0;
 1534 #endif
 1535         case MODULE_CMD_FINI:
 1536 #ifdef _MODULE
 1537                 return config_fini_component(cfdriver_ioconf_nand,
 1538                     cfattach_ioconf_nand, cfdata_ioconf_nand);
 1539 #else
 1540                 return 0;
 1541 #endif
 1542         default:
 1543                 return ENOTTY;
 1544         }
 1545 }

Cache object: 40128eb1cd842e69194d220caca27c8c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.