Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:04

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup lpc32xx_nand_mlc
0007  *
0008  * @brief lpc32xx_mlc_write_blocks() implementation.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2010, 2011 embedded brains GmbH & Co. KG
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #include <bsp/nand-mlc.h>
0037 
0038 #include <string.h>
0039 
0040 static const uint32_t ones_spare [MLC_LARGE_SPARE_WORD_COUNT] = {
0041   0xffffffff,
0042   0xffffffff,
0043   0xffffffff,
0044   0xffffffff,
0045   0xffffffff,
0046   0xffffffff,
0047   0xffffffff,
0048   0xffffffff,
0049   0xffffffff,
0050   0xffffffff,
0051   0xffffffff,
0052   0xffffffff,
0053   0xffffffff,
0054   0xffffffff,
0055   0xffffffff,
0056   0xffffffff
0057 };
0058 
0059 rtems_status_code lpc32xx_mlc_write_blocks(
0060   uint32_t block_begin,
0061   uint32_t block_end,
0062   const void *src,
0063   size_t src_size,
0064   uint32_t *page_data_buffer
0065 )
0066 {
0067   rtems_status_code sc = RTEMS_SUCCESSFUL;
0068   uint32_t pages_per_block = lpc32xx_mlc_pages_per_block();
0069   uint32_t block_count = lpc32xx_mlc_block_count();
0070   uint32_t page_size = lpc32xx_mlc_page_size();
0071   uint32_t block = 0;
0072   const uint8_t *current = src;
0073   const uint8_t *last = current;
0074   const uint8_t *end = current + src_size;
0075 
0076   if (block_begin > block_end || block_end > block_count) {
0077     return RTEMS_INVALID_ID;
0078   }
0079 
0080   for (block = block_begin; block != block_end; ++block) {
0081     uint32_t page_begin = block * pages_per_block;
0082     uint32_t page_end = page_begin + pages_per_block;
0083     uint32_t page = 0;
0084 
0085     sc = lpc32xx_mlc_erase_block_safe_3(block, page_begin, page_end);
0086     if (sc != RTEMS_SUCCESSFUL) {
0087       continue;
0088     }
0089 
0090     for (page = page_begin; page < page_end; ++page) {
0091       uintptr_t remainder = (uintptr_t) end - (uintptr_t) current;
0092       size_t delta = remainder < page_size ? remainder : page_size;
0093 
0094       if (remainder > 0) {
0095         memcpy(page_data_buffer, current, delta);
0096         sc = lpc32xx_mlc_write_page_with_ecc(
0097           page,
0098           page_data_buffer,
0099           ones_spare
0100         );
0101         if (sc != RTEMS_SUCCESSFUL) {
0102           lpc32xx_mlc_erase_block(block);
0103           lpc32xx_mlc_zero_pages(page_begin, page_end);
0104           current = last;
0105           continue;
0106         }
0107 
0108         current += delta;
0109       } else {
0110         goto done;
0111       }
0112     }
0113 
0114     last = current;
0115   }
0116 
0117 done:
0118 
0119   if (current != end) {
0120     return RTEMS_IO_ERROR;
0121   }
0122 
0123   return RTEMS_SUCCESSFUL;
0124 }