1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** LevelX Component                                                      */
16 /**                                                                       */
17 /**   NAND Flash                                                          */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define LX_SOURCE_CODE
23 
24 
25 /* Disable ThreadX error checking.  */
26 
27 #ifndef LX_DISABLE_ERROR_CHECKING
28 #define LX_DISABLE_ERROR_CHECKING
29 #endif
30 
31 
32 /* Include necessary system files.  */
33 
34 #include "lx_api.h"
35 
36 
37 /**************************************************************************/
38 /*                                                                        */
39 /*  FUNCTION                                               RELEASE        */
40 /*                                                                        */
41 /*    _lx_nand_flash_256byte_ecc_check                    PORTABLE C      */
42 /*                                                           6.1.7        */
43 /*  AUTHOR                                                                */
44 /*                                                                        */
45 /*    William E. Lamie, Microsoft Corporation                             */
46 /*                                                                        */
47 /*  DESCRIPTION                                                           */
48 /*                                                                        */
49 /*    This function checks 256 bytes of a NAND flash and ECC and          */
50 /*    attempts to correct any single bit errors.                          */
51 /*                                                                        */
52 /*  INPUT                                                                 */
53 /*                                                                        */
54 /*    page_buffer                           Page buffer                   */
55 /*    ecc_buffer                            Returned ECC buffer           */
56 /*                                                                        */
57 /*  OUTPUT                                                                */
58 /*                                                                        */
59 /*    return status                                                       */
60 /*                                                                        */
61 /*  CALLS                                                                 */
62 /*                                                                        */
63 /*    _lx_nand_flash_256byte_ecc_compute    Compute ECC for 256 bytes     */
64 /*                                                                        */
65 /*  CALLED BY                                                             */
66 /*                                                                        */
67 /*    _lx_nand_flash_page_ecc_check         NAND page check               */
68 /*                                                                        */
69 /*  RELEASE HISTORY                                                       */
70 /*                                                                        */
71 /*    DATE              NAME                      DESCRIPTION             */
72 /*                                                                        */
73 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
74 /*  09-30-2020     William E. Lamie         Modified comment(s),          */
75 /*                                            resulting in version 6.1    */
76 /*  06-02-2021     Bhupendra Naphade        Modified comment(s),          */
77 /*                                            resulting in version 6.1.7  */
78 /*                                                                        */
79 /**************************************************************************/
_lx_nand_flash_256byte_ecc_check(UCHAR * page_buffer,UCHAR * ecc_buffer)80 UINT  _lx_nand_flash_256byte_ecc_check(UCHAR *page_buffer, UCHAR *ecc_buffer)
81 {
82 
83 INT     i, j;
84 UCHAR   mask;
85 UCHAR   new_ecc_buffer[3];
86 UCHAR   ecc_errors[3];
87 INT     error_count;
88 USHORT  *data;
89 USHORT  byte;
90 USHORT  bit;
91 ULONG   correction_code;
92 
93 
94     /* Clear the error count.  */
95     ecc_errors[0] = 0;
96     ecc_errors[1] = 0;
97     ecc_errors[2] = 0;
98 
99     /* Calculate a new ECC for the 256 byte buffer.  */
100     _lx_nand_flash_256byte_ecc_compute(page_buffer, new_ecc_buffer);
101 
102     /* Clear error count.  */
103     error_count =  0;
104 
105     /* Loop through the ECC bytes to determine if there is an error in the page.  */
106     for (i = 0; i < 3; i++)
107     {
108 
109         /* Check for differences in the ECCs.  */
110         ecc_errors[i] =  new_ecc_buffer[i] ^ ecc_buffer[i];
111 
112         /* Are there any errors?  */
113         if (ecc_errors[i])
114         {
115 
116             /* Accumulate the count of set bits.  */
117             mask = 1;
118             for (j = 0; j < 8; j++)
119             {
120 
121                 /* Is this bit set?  */
122                 if (ecc_errors[i] & mask)
123                 {
124 
125                     /* Yes, increment the count.  */
126                     error_count++;
127                 }
128 
129                 /* Move mask to next bit.  */
130                 mask = (UCHAR) ((mask << 1) & 0xFF);
131             }
132         }
133     }
134 
135     /* Determine if there are any errors.  */
136     if (error_count == 0)
137     {
138 
139         /* Everything is okay, return success.  */
140         return(LX_SUCCESS);
141     }
142 
143     /* Was a correctable error discovered?  */
144     else if (error_count == 11)
145     {
146 
147         /* Initialize bit and byte offset values.  */
148         bit = 0;
149         byte = 0;
150 
151         /* Setup the data pointer.  */
152         data =  (USHORT *) page_buffer;
153 
154         /* Calculate the 32-bit correction code.  */
155         correction_code = (ULONG) (ecc_errors[2] << 16) | (ULONG)(ecc_errors[1] << 8) | (ULONG)ecc_errors[0];
156 
157         /* Unpack the correction code.  */
158         byte = (USHORT) ((byte | ((correction_code >> (21+2)) & 1) << 6) & 0xFFFF);
159         byte = (USHORT) ((byte | ((correction_code >> (19+2)) & 1) << 5) & 0xFFFF);
160         byte = (USHORT) ((byte | ((correction_code >> (17+2)) & 1) << 4) & 0xFFFF);
161         byte = (USHORT) ((byte | ((correction_code >> (15+2)) & 1) << 3) & 0xFFFF);
162         byte = (USHORT) ((byte | ((correction_code >> (13+2)) & 1) << 2) & 0xFFFF);
163         byte = (USHORT) ((byte | ((correction_code >> (11+2)) & 1) << 1) & 0xFFFF);
164         byte = (USHORT) ((byte | ((correction_code >> (9+2))  & 1) << 0) & 0xFFFF);
165         bit  = (USHORT) ((bit | ((correction_code >> (7+2))  & 1) << 3) & 0xFFFF);
166         bit  = (USHORT) ((bit | ((correction_code >> (5+2))  & 1) << 2) & 0xFFFF);
167         bit  = (USHORT) ((bit | ((correction_code >> (3+2))  & 1) << 1) & 0xFFFF);
168         bit  = (USHORT) ((bit | ((correction_code >> (1+2))  & 1) << 0) & 0xFFFF);
169 
170         /* Fix the error.  */
171         data[byte] = (USHORT) ((data[byte] ^ (1 << bit)) & 0xFFFF);
172 
173         /* Return an error corrected status.  */
174       return(LX_NAND_ERROR_CORRECTED);
175     }
176 
177     /* Otherwise, an unrecoverable ECC or data error is present.  */
178     else
179     {
180 
181         /* Return an error.  */
182         return(LX_NAND_ERROR_NOT_CORRECTED);
183     }
184 }
185 
186