summaryrefslogtreecommitdiff
path: root/peripherals/hsmc4
diff options
context:
space:
mode:
Diffstat (limited to 'peripherals/hsmc4')
-rw-r--r--peripherals/hsmc4/hsmc.dir37
-rw-r--r--peripherals/hsmc4/hsmc4.c247
-rw-r--r--peripherals/hsmc4/hsmc4.h73
-rw-r--r--peripherals/hsmc4/hsmc4_ecc.c703
-rw-r--r--peripherals/hsmc4/hsmc4_ecc.h85
5 files changed, 1145 insertions, 0 deletions
diff --git a/peripherals/hsmc4/hsmc.dir b/peripherals/hsmc4/hsmc.dir
new file mode 100644
index 0000000..9ec8bb4
--- /dev/null
+++ b/peripherals/hsmc4/hsmc.dir
@@ -0,0 +1,37 @@
+/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+///
+/// !!!Purpose
+///
+/// Contains the peripheral Static Memory Controller (HSMC4).
+//------------------------------------------------------------------------------
+
diff --git a/peripherals/hsmc4/hsmc4.c b/peripherals/hsmc4/hsmc4.c
new file mode 100644
index 0000000..350da99
--- /dev/null
+++ b/peripherals/hsmc4/hsmc4.c
@@ -0,0 +1,247 @@
+/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "hsmc4.h"
+
+//------------------------------------------------------------------------------
+// Local variables
+//------------------------------------------------------------------------------
+/// Store value of current read only HSMC4_CTRL register.
+static unsigned int hsmc4Ctrl;
+
+//------------------------------------------------------------------------------
+// Internal functions
+//------------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Returns 1 if the host main controller has terminated the command.
+/// read mode.
+/// otherwise returns 0.
+//-----------------------------------------------------------------------------
+unsigned char HSMC4_CommandDone(void)
+{
+ return ((AT91C_BASE_HSMC4->HSMC4_SR & AT91C_HSMC4_CMDDONE) == AT91C_HSMC4_CMDDONE);
+}
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+/// Sets the mode of the HSMC4 to one of the following values:
+/// - AT91C_HSMC4_PAGESIZE
+/// - AT91C_HSMC4_WSPARE
+/// - AT91C_HSMC4_RSPARE
+/// - AT91C_HSMC4_EDGECTRL
+/// - AT91C_HSMC4_RBEDGE
+/// - AT91C_HSMC4_DTOCYC
+/// - AT91C_HSMC4_DTOMUL
+/// \param mode mode.
+//------------------------------------------------------------------------------
+void HSMC4_SetMode(unsigned int mode)
+{
+ AT91C_BASE_HSMC4->HSMC4_CFG = mode;
+}
+
+//-----------------------------------------------------------------------------
+/// Reset the HSMC4 Nand flash controll host.
+//-----------------------------------------------------------------------------
+void HSMC4_ResetNfc(void)
+{
+ //Disable all the HSMC4 interrupts
+ AT91C_BASE_HSMC4 -> HSMC4_IDR = 0xFFFFFFFF;
+ AT91C_BASE_HSMC4 -> HSMC4_CTRL = 0;
+ hsmc4Ctrl = 0;
+}
+
+//-----------------------------------------------------------------------------
+/// Enable NAND flsah controller host through the APB interface.
+//-----------------------------------------------------------------------------
+void HSMC4_EnableNfc(void)
+{
+ hsmc4Ctrl |= AT91C_HSMC4_NFCEN;
+ AT91C_BASE_HSMC4->HSMC4_CTRL = hsmc4Ctrl;
+}
+
+//-----------------------------------------------------------------------------
+/// Acticated and perform a data transfer between the Host and a Nand Flash.
+//-----------------------------------------------------------------------------
+void HSMC4_EnableNfcHost(void)
+{
+ hsmc4Ctrl |= AT91C_HSMC4_HOSTEN;
+ AT91C_BASE_HSMC4->HSMC4_CTRL = hsmc4Ctrl;
+}
+
+//-----------------------------------------------------------------------------
+/// Enable host transfer data from the internal SRAM to the memory device.
+//-----------------------------------------------------------------------------
+void HSMC4_EnableHostTransfer(void)
+{
+ hsmc4Ctrl |= AT91C_HSMC4_HOSTWR;
+ // The HOSTWR field can be modified if the host controller is not busy.
+ while((AT91C_BASE_HSMC4->HSMC4_SR & AT91C_HSMC4_HOSTBUSY) == AT91C_HSMC4_HOSTBUSY);
+ AT91C_BASE_HSMC4->HSMC4_CTRL = hsmc4Ctrl;
+ while((AT91C_BASE_HSMC4->HSMC4_SR & AT91C_HSMC4_HOSTBUSY) == AT91C_HSMC4_HOSTBUSY);
+}
+
+//-----------------------------------------------------------------------------
+/// Enables the host main controller reads both main and spare area in read mode.
+//-----------------------------------------------------------------------------
+void HSMC4_EnableSpareRead(void)
+{
+ AT91C_BASE_HSMC4->HSMC4_CFG |= AT91C_HSMC4_RSPARE;
+}
+
+//-----------------------------------------------------------------------------
+/// The host main controller skips spare area in read mode.
+//-----------------------------------------------------------------------------
+void HSMC4_DisableSpareRead(void)
+{
+ AT91C_BASE_HSMC4->HSMC4_CFG &= 0xFFFFFDFF;
+}
+
+//-----------------------------------------------------------------------------
+/// Enables the host main controller writes both main and spare area in write
+/// mode.
+//-----------------------------------------------------------------------------
+void HSMC4_EnableSpareWrite(void)
+{
+ AT91C_BASE_HSMC4->HSMC4_CFG |= AT91C_HSMC4_WSPARE;
+}
+
+//-----------------------------------------------------------------------------
+/// The host main controller skips spare area in write mode.
+//-----------------------------------------------------------------------------
+void HSMC4_DisableSpareWrite(void)
+{
+ AT91C_BASE_HSMC4->HSMC4_CFG &= 0xFFFFFEFF;
+}
+
+//-----------------------------------------------------------------------------
+/// Returns 1 if the host main controller reads both main and spare area in
+/// read mode.
+/// otherwise returns 0.
+//-----------------------------------------------------------------------------
+unsigned char HSMC4_isSpareRead(void)
+{
+ return (((AT91C_BASE_HSMC4->HSMC4_CFG) >> 9) & 0x1);
+}
+
+//-----------------------------------------------------------------------------
+/// Returns 1 if the host main controller writes both main and spare area in
+/// write mode.
+/// otherwise returns 0.
+//-----------------------------------------------------------------------------
+unsigned char HSMC4_isSpareWrite(void)
+{
+ return (((AT91C_BASE_HSMC4->HSMC4_CFG) >> 8) & 0x1);
+}
+
+
+//-----------------------------------------------------------------------------
+/// Returns 1 if the host main controller has terminated the data transmission.
+/// otherwise returns 0.
+//-----------------------------------------------------------------------------
+unsigned char HSMC4_TransferComplete(void)
+{
+ return ((AT91C_BASE_HSMC4->HSMC4_SR & AT91C_HSMC4_XFRDONE) == AT91C_HSMC4_XFRDONE);
+}
+
+//-----------------------------------------------------------------------------
+/// Returns 1 if edge has been detected on the Ready/Busy line.
+/// otherwise returns 0.
+//-----------------------------------------------------------------------------
+unsigned char HSMC4_isReadyBusy(void)
+{
+ return ((AT91C_BASE_HSMC4->HSMC4_SR & AT91C_HSMC4_RBEDGE0) == AT91C_HSMC4_RBEDGE0);
+}
+
+//-----------------------------------------------------------------------------
+/// Returns 1 if the Controller is activated and accesses the memory device.
+/// otherwise returns 0.
+//-----------------------------------------------------------------------------
+unsigned char HSMC4_isNfcBusy(void)
+{
+ return ((AT91C_BASE_HSMC4->HSMC4_SR & AT91C_HSMC4_HOSTBUSY) == AT91C_HSMC4_HOSTBUSY);
+}
+
+//-----------------------------------------------------------------------------
+/// Returns 1 if the ecc is ready
+/// otherwise returns 0.
+//-----------------------------------------------------------------------------
+unsigned char HSMC4_isEccReady(void)
+{
+ return ((AT91C_BASE_HSMC4->HSMC4_SR & AT91C_HSMC4_ECCRDY) == AT91C_HSMC4_ECCRDY);
+}
+
+//-----------------------------------------------------------------------------
+/// Returns the current status register of the HSMC4 peripheral. This
+/// resets the internal value of the status register, so further read may yield
+/// different values.
+//-----------------------------------------------------------------------------
+unsigned int HSMC4_GetStatus(void)
+{
+ return AT91C_BASE_HSMC4->HSMC4_SR;
+}
+
+//------------------------------------------------------------------------------
+// HOST command functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Returns 1 if the host controller is busy.
+/// otherwise returns 0.
+//------------------------------------------------------------------------------
+unsigned char HSMC4_isHostBusy(void)
+{
+ return (((*((volatile unsigned int *) (CMD_BASE_ADDR + AT91C_HSMC4_HOSTCMD))) & 0x8000000) == 0x8000000);
+}
+
+//------------------------------------------------------------------------------
+/// Uses the HOST nandflash conntroller to send a command to the NFC
+/// \param cmd command to send.
+/// \param addressCycle address cycle when command access id decoded.
+/// \param cycle0 address at first cycle.
+//------------------------------------------------------------------------------
+void HSMC4_SendCommand (unsigned int cmd, unsigned int addressCycle, unsigned int cycle0)
+{
+ volatile unsigned int *pCommandAddress;
+ // Wait until host controller is not busy.
+ while(HSMC4_isHostBusy());
+ // Send the command plus the ADDR_CYCLE
+ pCommandAddress = (volatile unsigned int *) (cmd + CMD_BASE_ADDR);
+ AT91C_BASE_HSMC4->HSMC4_ADDR = cycle0;
+ *pCommandAddress = addressCycle;
+ while( !HSMC4_CommandDone());
+}
+
+
diff --git a/peripherals/hsmc4/hsmc4.h b/peripherals/hsmc4/hsmc4.h
new file mode 100644
index 0000000..47e19bb
--- /dev/null
+++ b/peripherals/hsmc4/hsmc4.h
@@ -0,0 +1,73 @@
+/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef HSMC4_H
+#define HSMC4_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <board.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+#define NFC_SRAM_BASE_ADDRESS 0x20100000
+
+#ifndef BOARD_NF_COMMAND_ADDR
+ #define CMD_BASE_ADDR 0x60000000
+#else
+ #define CMD_BASE_ADDR BOARD_NF_COMMAND_ADDR
+#endif
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+extern void HSMC4_SendCommand (unsigned int cmd, unsigned int addressCycle, unsigned int cycle0);
+extern unsigned char HSMC4_isHostBusy(void);
+extern unsigned char HSMC4_TransferComplete(void);
+extern unsigned char HSMC4_isReadyBusy(void);
+extern unsigned char HSMC4_isNfcBusy(void);
+extern unsigned char HSMC4_isEccReady(void);
+extern void HSMC4_SetMode(unsigned int mode);
+extern void HSMC4_ResetNfc(void);
+extern void HSMC4_EnableNfc(void);
+extern void HSMC4_EnableNfcHost(void);
+
+extern void HSMC4_EnableSpareRead(void);
+extern void HSMC4_DisableSpareRead(void);
+extern void HSMC4_EnableSpareWrite(void);
+extern void HSMC4_DisableSpareWrite(void);
+extern unsigned char HSMC4_isSpareRead(void);
+extern unsigned char HSMC4_isSpareWrite(void);
+extern unsigned int HSMC4_GetStatus(void);
+
+#endif //#ifndef HSMC4_H
+
diff --git a/peripherals/hsmc4/hsmc4_ecc.c b/peripherals/hsmc4/hsmc4_ecc.c
new file mode 100644
index 0000000..e27655f
--- /dev/null
+++ b/peripherals/hsmc4/hsmc4_ecc.c
@@ -0,0 +1,703 @@
+/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+#include "hsmc4.h"
+#include "hsmc4_ecc.h"
+#include <utility/trace.h>
+#include <utility/assert.h>
+
+//------------------------------------------------------------------------------
+// Internal function
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+/// Counts and return the number of bits set to '1' in the given byte.
+/// \param byte Byte to count.
+//------------------------------------------------------------------------------
+static unsigned char CountBitsInByte(unsigned char byte)
+{
+ unsigned char count = 0;
+ while (byte > 0) {
+
+ if (byte & 1) {
+
+ count++;
+ }
+ byte >>= 1;
+ }
+
+ return count;
+}
+//------------------------------------------------------------------------------
+/// Counts and return the number of bits set to '1' in the given hsiao code.
+/// \param code Hsizo code.
+//------------------------------------------------------------------------------
+static unsigned char CountBitsInCode(unsigned char *code)
+{
+ return CountBitsInByte(code[0])
+ + CountBitsInByte(code[1])
+ + CountBitsInByte(code[2]);
+}
+
+//------------------------------------------------------------------------------
+/// Get all ECC parity and Nparity value.
+//------------------------------------------------------------------------------
+void HSMC4_EccGetValue(unsigned int *ecc)
+{
+ ecc[0] = AT91C_BASE_HSMC4->HSMC4_ECCPR0;
+ ecc[1] = AT91C_BASE_HSMC4->HSMC4_ECCPR1;
+ ecc[2] = AT91C_BASE_HSMC4->HSMC4_ECCPR2;
+ ecc[3] = AT91C_BASE_HSMC4->HSMC4_ECCPR3;
+ ecc[4] = AT91C_BASE_HSMC4->HSMC4_ECCPR4;
+ ecc[5] = AT91C_BASE_HSMC4->HSMC4_ECCPR5;
+ ecc[6] = AT91C_BASE_HSMC4->HSMC4_ECCPR6;
+ ecc[7] = AT91C_BASE_HSMC4->HSMC4_ECCPR7;
+ ecc[8] = AT91C_BASE_HSMC4->HSMC4_ECCPR8;
+ ecc[9] = AT91C_BASE_HSMC4->HSMC4_ECCPR9;
+ ecc[10] = AT91C_BASE_HSMC4->HSMC4_ECCPR10;
+ ecc[11] = AT91C_BASE_HSMC4->HSMC4_ECCPR11;
+ ecc[12] = AT91C_BASE_HSMC4->HSMC4_ECCPR12;
+ ecc[13] = AT91C_BASE_HSMC4->HSMC4_ECCPR13;
+ ecc[14] = AT91C_BASE_HSMC4->HSMC4_ECCPR14;
+ ecc[15] = AT91C_BASE_HSMC4->HSMC4_Eccpr15;
+#ifdef DUMP_ECC_PARITY
+ TRACE_INFO("Ecc parity(0-7) %x, %x, %x, %x, %x, %x, %x, %x \n\r",ecc[0],ecc[1],ecc[2],ecc[3],ecc[4],ecc[5],ecc[6],ecc[7]);
+ TRACE_INFO("Ecc parity(8-15) %x, %x, %x, %x, %x, %x, %x, %x \n\r",ecc[8],ecc[9],ecc[10],ecc[11],ecc[12],ecc[13],ecc[14],ecc[15]);
+#endif
+}
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+/// Configures ECC mode in HSMC4 peripheral as specified.
+/// \param type Type of correction.
+/// \param pageSize Page size of NAND flash device.
+//------------------------------------------------------------------------------
+void HSMC4_EccConfigure(unsigned int type, unsigned int pageSize)
+{
+ // Software Reset ECC.
+ AT91C_BASE_HSMC4->HSMC4_ECCCR = (0x1 << 1) ;
+ AT91C_BASE_HSMC4->HSMC4_ECCCMD = type | pageSize;
+}
+
+//------------------------------------------------------------------------------
+/// Returns type of ECC correction setting.
+//------------------------------------------------------------------------------
+unsigned int HSMC4_GetEccCorrectoinType(void)
+{
+ return ((AT91C_BASE_HSMC4->HSMC4_ECCCMD)& AT91C_ECC_TYPCORRECT);
+}
+
+//------------------------------------------------------------------------------
+/// Returns ECC status by giving ecc number
+/// \param eccNumber ecc parity number from 0 to 15.
+//------------------------------------------------------------------------------
+unsigned char HSMC4_GetEccStatus(unsigned char eccNumber)
+{
+ unsigned int status;
+ if (eccNumber < 8){
+ status = AT91C_BASE_HSMC4->HSMC4_ECCSR1;
+ }
+ else {
+ status = AT91C_BASE_HSMC4->HSMC4_ECCSR2;
+ eccNumber -=8;
+ }
+ return ((status >> (eccNumber * 4)) & 0x07);
+}
+//------------------------------------------------------------------------------
+/// Verifies 4-bytes hsiao codes for a data block whose size is a page Size
+/// word. Page words block is verified between the given HSIAO code
+/// generated by hardware and original HSIAO codes store has been previously stored.
+/// Returns 0 if the data is correct, Hsiao_ERROR_SINGLEBIT if one or more
+/// block(s) have had a single bit corrected, or either Hsiao_ERROR_ECC
+/// or Hsiao_ERROR_MULTIPLEBITS.
+/// \param data Data buffer to verify.
+/// \param originalCode Original codes.
+/// \param verifyCode codes to be verified.
+//------------------------------------------------------------------------------
+static unsigned char HSMC4_VerifyPageOf8bitHsiao(
+ unsigned char *data,
+ const unsigned char *originalCode,
+ const unsigned char *verifyCode)
+{
+ unsigned char correctionCode[4];
+ unsigned char bitCount;
+ // Xor both codes together
+ correctionCode[0] = verifyCode[0] ^ originalCode[0];
+ correctionCode[1] = verifyCode[1] ^ originalCode[1];
+ correctionCode[2] = verifyCode[2] ^ originalCode[2];
+ correctionCode[3] = verifyCode[3] ^ originalCode[3];
+ TRACE_DEBUG("Correction code = %02X %02X %02X %02X\n\r",
+ correctionCode[0], correctionCode[1], correctionCode[2], correctionCode[3]);
+ // If all bytes are 0, there is no error
+ if ((correctionCode[0] == 0)
+ && (correctionCode[1] == 0)
+ && (correctionCode[2] == 0)
+ && (correctionCode[3] == 0)) {
+
+ return 0;
+ }
+ // If there is a single bit error, there are 15 bits set to 1
+ bitCount = CountBitsInByte(correctionCode[0]) +
+ CountBitsInByte(correctionCode[1]) +
+ CountBitsInByte(correctionCode[2]) +
+ CountBitsInByte(correctionCode[3]);
+ if (bitCount == 15) {
+ // Get byte and bit indexes
+ unsigned short byte = (correctionCode[0] & 0xf0) >> 4;
+ byte |= (correctionCode[1] & 0xff) << 4;
+ unsigned char bit = correctionCode[0] & 0x0f;
+ // Correct bit
+ TRACE_INFO("Correcting byte #%d at bit %d\n\r", byte, bit);
+ data[byte] ^= (1 << bit);
+
+ return Hsiao_ERROR_SINGLEBIT;
+ }
+
+ // Check if ECC has been corrupted
+ if (bitCount == 1) {
+ return Hsiao_ERROR_ECC;
+ }
+ // Otherwise, this is a multi-bit error
+ else {
+ return Hsiao_ERROR_MULTIPLEBITS;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Verifies 3-bytes hsiao codes for a data block whose size is multiple of
+/// 256 bytes. Each 256-bytes block is verified between the given HSIAO code
+/// generated by hardware and original HSIAO codes store has been previously stored.
+/// Returns 0 if the data is correct, Hsiao_ERROR_SINGLEBIT if one or more
+/// block(s) have had a single bit corrected, or either Hsiao_ERROR_ECC
+/// or Hsiao_ERROR_MULTIPLEBITS.
+/// \param data Data buffer to verify.
+/// \param size Size of the data in words.
+/// \param originalCode Original codes.
+/// \param verifyCode codes to be verified.
+//------------------------------------------------------------------------------
+static unsigned char HSMC4_Verify256x8bitHsiao(
+ unsigned char *data,
+ unsigned int size,
+ const unsigned char *originalCode,
+ const unsigned char *verifyCode)
+{
+ unsigned char correctionCode[3];
+ unsigned int position = 0;
+ unsigned char byte;
+ unsigned char bit;
+ unsigned char error = 0;
+
+ TRACE_DEBUG("HSMC4_Verify512x8bitHsiao()\n\r");
+ while (position < size) {
+ // Xor both codes together
+ correctionCode[0] = verifyCode[0] ^ originalCode[0];
+ correctionCode[1] = verifyCode[1] ^ originalCode[1];
+ correctionCode[2] = verifyCode[2] ^ originalCode[2];
+ TRACE_DEBUG("Correction code = %02X %02X %02X\n\r",
+ correctionCode[0], correctionCode[1], correctionCode[2]);
+
+ // If all bytes are 0, there is no error
+ if ( correctionCode[0] || correctionCode[1] || correctionCode[2]) {
+ // If there is a single bit error, there are 11 bits set to 1
+ if (CountBitsInCode(correctionCode) == 11) {
+ // Get byte and bit indexes
+ byte = (correctionCode[0] & 0xf8) >> 3;
+ byte |= (correctionCode[1] & 0x07) << 5;
+ bit = correctionCode[0] & 0x07;
+ // Correct bit
+ TRACE_INFO("Correcting byte #%d at bit %d\n\r", (position + byte), bit);
+ data[byte] ^= (1 << bit);
+ error = Hsiao_ERROR_SINGLEBIT;
+ }
+ // Check if ECC has been corrupted
+ else if (CountBitsInCode(correctionCode) == 1) {
+ return Hsiao_ERROR_ECC;
+ }
+ else {
+ // Otherwise, this is a multi-bit error
+ return Hsiao_ERROR_MULTIPLEBITS;
+ }
+ }
+ data += 256;
+ originalCode += 3;
+ verifyCode += 3;
+ position += 256;
+ }
+ return error;
+}
+
+//------------------------------------------------------------------------------
+/// Verifies 3-bytes hsiao codes for a data block whose size is multiple of
+/// 512 bytes. Each 512-bytes block is verified between the given HSIAO code
+/// generated by hardware and original HSIAO codes store has been previously stored.
+/// Returns 0 if the data is correct, Hsiao_ERROR_SINGLEBIT if one or more
+/// block(s) have had a single bit corrected, or either Hsiao_ERROR_ECC
+/// or Hsiao_ERROR_MULTIPLEBITS.
+/// \param data Data buffer to verify.
+/// \param size Size of the data in words.
+/// \param originalCode Original codes.
+/// \param verifyCode codes to be verified.
+//------------------------------------------------------------------------------
+static unsigned char HSMC4_Verify512x8bitHsiao(
+ unsigned char *data,
+ unsigned int size,
+ const unsigned char *originalCode,
+ const unsigned char *verifyCode)
+{
+ unsigned char correctionCode[3];
+ unsigned int position = 0;
+ unsigned short byte;
+ unsigned char bit;
+ unsigned char error = 0;
+
+ TRACE_DEBUG("HSMC4_Verify512x8bitHsiao()\n\r");
+ while (position < size) {
+ // Xor both codes together
+ correctionCode[0] = verifyCode[0] ^ originalCode[0];
+ correctionCode[1] = verifyCode[1] ^ originalCode[1];
+ correctionCode[2] = verifyCode[2] ^ originalCode[2];
+ TRACE_DEBUG("Correction code = %02X %02X %02X\n\r",
+ correctionCode[0], correctionCode[1], correctionCode[2]);
+
+ // If all bytes are 0, there is no error
+ if ( correctionCode[0] || correctionCode[1] || correctionCode[2]) {
+ // If there is a single bit error, there are 11 bits set to 1
+ if (CountBitsInCode(correctionCode) == 12) {
+ // Get byte and bit indexes
+ byte = (correctionCode[0] & 0xf8) >> 3;
+ byte |= (correctionCode[1] & 0x0f) << 5;
+ bit = correctionCode[0] & 0x07;
+ // Correct bit
+ TRACE_INFO("Correcting byte #%d at bit %d\n\r", (position + byte), bit);
+ data[byte] ^= (1 << bit);
+ error = Hsiao_ERROR_SINGLEBIT;
+ }
+ // Check if ECC has been corrupted
+ else if (CountBitsInCode(correctionCode) == 1) {
+ return Hsiao_ERROR_ECC;
+ }
+ else {
+ // Otherwise, this is a multi-bit error
+ return Hsiao_ERROR_MULTIPLEBITS;
+ }
+ }
+ data += 512;
+ originalCode += 3;
+ verifyCode += 3;
+ position += 512;
+ }
+ return error;
+}
+
+//------------------------------------------------------------------------------
+/// Verifies 4-bytes hsiao codes for a data block whose size is a page Size
+/// word. Page words block is verified between the given HSIAO code
+/// generated by hardware and original HSIAO codes store has been previously stored.
+/// Returns 0 if the data is correct, Hsiao_ERROR_SINGLEBIT if one or more
+/// block(s) have had a single bit corrected, or either Hsiao_ERROR_ECC
+/// or Hsiao_ERROR_MULTIPLEBITS.
+/// \param data Data buffer to verify.
+/// \param originalCode Original codes.
+/// \param verifyCode codes to be verified.
+//------------------------------------------------------------------------------
+static unsigned char HSMC4_VerifyPageOf16bitHsiao(
+ unsigned short *data,
+ const unsigned char *originalCode,
+ const unsigned char *verifyCode)
+{
+ unsigned char correctionCode[4];
+ unsigned char bitCount;
+ // Xor both codes together
+ correctionCode[0] = verifyCode[0] ^ originalCode[0];
+ correctionCode[1] = verifyCode[1] ^ originalCode[1];
+ correctionCode[2] = verifyCode[2] ^ originalCode[2];
+ correctionCode[3] = verifyCode[3] ^ originalCode[3];
+ TRACE_DEBUG("Correction code = %02X %02X %02X %02X\n\r",
+ correctionCode[0], correctionCode[1], correctionCode[2], correctionCode[3]);
+ // If all bytes are 0, there is no error
+ if ((correctionCode[0] == 0)
+ && (correctionCode[1] == 0)
+ && (correctionCode[2] == 0)
+ && (correctionCode[3] == 0)) {
+
+ return 0;
+ }
+ // If there is a single bit error, there are 11 bits set to 1
+ bitCount = CountBitsInByte(correctionCode[0]) +
+ CountBitsInByte(correctionCode[1]) +
+ CountBitsInByte(correctionCode[2]) +
+ CountBitsInByte(correctionCode[3]);
+ printf("bitCount = %d \n\r",bitCount);
+ if (bitCount == 12) {
+ // Get byte and bit indexes
+ unsigned char word = (correctionCode[0] & 0xf0) >> 4;
+ word |= (correctionCode[1] & 0xff) << 4;
+ unsigned char bit = correctionCode[0] & 0x0f;
+ // Correct bit
+ TRACE_INFO("Correcting word #%d at bit %d\n\r", word, bit);
+ data[word] ^= (1 << bit);
+
+ return Hsiao_ERROR_SINGLEBIT;
+ }
+
+ // Check if ECC has been corrupted
+ if (bitCount == 1) {
+ return Hsiao_ERROR_ECC;
+ }
+ // Otherwise, this is a multi-bit error
+ else {
+ return Hsiao_ERROR_MULTIPLEBITS;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Verifies 3-bytes hsiao codes for a data block whose size is multiple of
+/// 256 word.Each 256-words block is verified between the given HSIAO code
+/// generated by hardware and original HSIAO codes store has been previously stored.
+/// Returns 0 if the data is correct, Hsiao_ERROR_SINGLEBIT if one or more
+/// block(s) have had a single bit corrected, or either Hsiao_ERROR_ECC
+/// or Hsiao_ERROR_MULTIPLEBITS.
+/// \param data Data buffer to verify.
+/// \param size Size of the data in words.
+/// \param originalCode Original codes.
+/// \param verifyCode codes to be verified.
+//------------------------------------------------------------------------------
+static unsigned char HSMC4_Verify256x16bitHsiao(
+ unsigned short *data,
+ unsigned int size,
+ const unsigned char *originalCode,
+ const unsigned char *verifyCode
+ )
+{
+ unsigned char correctionCode[3];
+ unsigned int position = 0;
+ unsigned char word;
+ unsigned char bit;
+ unsigned char error = 0;
+
+ TRACE_DEBUG("HSMC4_Verify512x8bitHsiao()\n\r");
+ while (position < size) {
+ // Xor both codes together
+ correctionCode[0] = verifyCode[0] ^ originalCode[0];
+ correctionCode[1] = verifyCode[1] ^ originalCode[1];
+ correctionCode[2] = verifyCode[2] ^ originalCode[2];
+ TRACE_DEBUG("Correction code = %02X %02X %02X\n\r",
+ correctionCode[0], correctionCode[1], correctionCode[2]);
+
+ // If all bytes are 0, there is no error
+ if ( correctionCode[0] || correctionCode[1] || correctionCode[2]) {
+ // If there is a single bit error, there are 11 bits set to 1
+ if (CountBitsInCode(correctionCode) == 12) {
+ // Get word and bit indexes
+ word = (correctionCode[0] & 0xf0) >> 4;
+ word |= (correctionCode[1] & 0x0f) << 4;
+ bit = correctionCode[0] & 0x0f;
+ // Correct bit
+ TRACE_INFO("Correcting word #%d at bit %d\n\r", (position + word), bit);
+ data[word] ^= (1 << bit);
+ error = Hsiao_ERROR_SINGLEBIT;
+ }
+ // Check if ECC has been corrupted
+ else if (CountBitsInCode(correctionCode) == 1) {
+ return Hsiao_ERROR_ECC;
+ }
+ else {
+ // Otherwise, this is a multi-bit error
+ return Hsiao_ERROR_MULTIPLEBITS;
+ }
+ }
+ data += 256;
+ originalCode += 3;
+ verifyCode += 3;
+ position += 256;
+ }
+ return error;
+}
+
+//------------------------------------------------------------------------------
+/// Verifies hsiao codes for a data block. The block is verified between the given
+/// HSIAO code generated by hardware and original HSIAO codes store has been
+/// previously stored.
+/// Returns 0 if the data is correct, Hsiao_ERROR_SINGLEBIT if one or more
+/// block(s) have had a single bit corrected, or either Hsiao_ERROR_ECC
+/// or Hsiao_ERROR_MULTIPLEBITS.
+/// \param data Data buffer to verify.
+/// \param size Size of the data in words.
+/// \param originalCode Original codes.
+/// \param verifyCode codes to be verified.
+/// \param dataPath 8bit/16bit data path.
+//------------------------------------------------------------------------------
+unsigned char HSMC4_VerifyHsiao(
+ unsigned char *data,
+ unsigned int size,
+ const unsigned char *originalCode,
+ const unsigned char *verifyCode,
+ unsigned char dataPath)
+{
+ unsigned char correctionType;
+ unsigned char error = 0;
+ correctionType = HSMC4_GetEccCorrectoinType();
+ // For 16-bit data path
+ if (dataPath == 16) {
+ switch (correctionType){
+ case AT91C_ECC_TYPCORRECT_ONE_PER_PAGE:
+ error = HSMC4_VerifyPageOf16bitHsiao((unsigned short*)data, originalCode, verifyCode);
+ break;
+ case AT91C_ECC_TYPCORRECT_ONE_EVERY_256_BYTES:
+ error= HSMC4_Verify256x16bitHsiao((unsigned short*)data, size / 2, originalCode, verifyCode);
+ break;
+ case AT91C_ECC_TYPCORRECT_ONE_EVERY_512_BYTES:
+ TRACE_WARNING("16-bit 512 per page correction not yet implement! \n\r");
+ break;
+ }
+ }
+ // For 8-bit data path
+ else {
+ switch (correctionType){
+ case AT91C_ECC_TYPCORRECT_ONE_PER_PAGE:
+ error = HSMC4_VerifyPageOf8bitHsiao(data, originalCode, verifyCode);
+ break;
+ case AT91C_ECC_TYPCORRECT_ONE_EVERY_256_BYTES:
+ error = HSMC4_Verify256x8bitHsiao(data, size, originalCode, verifyCode);
+ break;
+ case AT91C_ECC_TYPCORRECT_ONE_EVERY_512_BYTES:
+ error = HSMC4_Verify512x8bitHsiao(data, size, originalCode, verifyCode);
+ break;
+ }
+ }
+ return error;
+}
+
+//------------------------------------------------------------------------------
+/// Get 32-bit ECC code for 16-bit data path NAND flash.
+/// 32-bit ECC is generated in order to perform one bit correction
+/// for a page in page 512/1024/2048/4096 for 16-bit words
+/// \param size Data size in bytes.
+/// \param code Codes buffer.
+//------------------------------------------------------------------------------
+void HSMC4_Get24bitPerPageEcc(unsigned int pageDataSize, unsigned char *code)
+{
+ unsigned int eccParity;
+ unsigned int eccNparity;
+ unsigned int ecc[16];
+ // Get Parity value.
+ HSMC4_EccGetValue(ecc);
+
+ // ---- P16384'P8192'P4096'P2048' P1024'P512'P256' --- 4th. Ecc Byte to store
+ /// P128' P64' P32' P16' P8' P4' P2' P1' --- 3rd. Ecc Byte to store
+ // ---- P16384 P8192 P4096 P2048 P1024 P512 P256 --- 2nd. Ecc Byte to store
+ // P128 P64 P32 P16 P8 P4 P2 P1 --- 1st. Ecc Byte to store
+
+ // Invert codes (linux compatibility)
+ eccParity = ~(ecc[0]);
+ eccNparity = ~(ecc[1]);
+ TRACE_DEBUG("ecc Parity is 0x%08x, ecc Nparity is 0x%08x \n\r", eccParity, eccNparity);
+ code[0] = eccParity & 0xff;
+ code[1] = (eccParity >> 8 )& 0xff;
+ code[2] = eccNparity & 0xff;
+ code[3] = (eccNparity >> 8 )& 0xff;
+}
+
+//------------------------------------------------------------------------------
+/// Get 24-bit ECC code for 8-bit data path NAND flash.
+/// 24-bit ECC is generated in order to perform one bit correction
+/// for 256 byte in page 512/1024/2048/4096 for 8-bit words
+/// \param size Data size in bytes.
+/// \param code Codes buffer.
+//------------------------------------------------------------------------------
+void HSMC4_Get24bitPer256Ecc(unsigned int pageDataSize, unsigned char *code)
+{
+ unsigned char i;
+ unsigned char numEcc;
+ unsigned int eccParity;
+ unsigned int ecc[16];
+ HSMC4_EccGetValue(ecc);
+ numEcc = pageDataSize / 256;
+
+ // P2048' P1024' P512' P256' P128' P64' P32' P16' --- 3rd. Ecc Byte to store
+ // P8' P4' P2' P1' P2048 P1024 P512 P256 --- 2nd. Ecc Byte to store
+ // P128 P64 P32 P16 P8 P4 P2 P1 --- 1st. Ecc Byte to store
+ for (i = 0; i < numEcc; i++) {
+ // Get Parity and NParity value.
+ eccParity = ecc[i];
+ // Invert codes (linux compatibility)
+ eccParity = ~eccParity;
+ TRACE_DEBUG("ecc Parity%d is 0x%08x \n\r", i, eccParity);
+ code[i * 3] = eccParity & 0xff;
+ code[i * 3 + 1] = (eccParity >> 8) & 0xff;
+ code[i * 3 + 2] = (eccParity >> 16) & 0xff;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Get 24-bit ECC code for 8-bit data path NAND flash.
+/// 24-bit ECC is generated in order to perform one bit correction
+/// for 512 byte in page 512/1024/2048/4096 for 8-bit words
+/// \param size Data size in bytes.
+/// \param code Codes buffer.
+//------------------------------------------------------------------------------
+void HSMC4_Get24bitPer512Ecc(unsigned int pageDataSize, unsigned char *code)
+{
+ unsigned char i;
+ unsigned char numEcc;
+ unsigned int eccParity;
+ unsigned int ecc[16];
+ HSMC4_EccGetValue(ecc);
+ numEcc = pageDataSize / 512;
+
+ // P2048' P1024' P512' P256' P128' P64' P32' P16' --- 3rd. Ecc Byte to store
+ // P8' P4' P2' P1' P2048 P1024 P512 P256 --- 2nd. Ecc Byte to store
+ // P128 P64 P32 P16 P8 P4 P2 P1 --- 1st. Ecc Byte to store
+ for (i = 0; i < numEcc; i++) {
+ // Get Parity and NParity value.
+ eccParity = ecc[i];
+ // Invert codes (linux compatibility)
+ eccParity = ~eccParity;
+ TRACE_DEBUG("ecc Parity%d is 0x%08x \n\r", i, eccParity);
+ code[i * 3] = eccParity & 0xff;
+ code[i * 3 + 1] = (eccParity >> 8) & 0xff;
+ code[i * 3 + 2] = (eccParity >> 16) & 0xff;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Get 32-bit ECC code for 16-bit data path NAND flash.
+/// 32-bit ECC is generated in order to perform one bit correction
+/// for 256 word in page 512/1024/2048/4096 for 16-bit words
+/// \param size Data size in bytes.
+/// \param code Codes buffer.
+//------------------------------------------------------------------------------
+void HSMC4_Get32bitPer256Ecc(unsigned int pageDataSize, unsigned char *code)
+{
+ unsigned char i;
+ unsigned char numEcc;
+ unsigned int eccParity;
+ unsigned int eccNparity;
+ unsigned int ecc[16];
+ HSMC4_EccGetValue(ecc);
+ numEcc = pageDataSize / 256;
+
+ // P2048' P1024' P512' P256' P128' P64' P32' P16' --- 3rd. Ecc Byte to store
+ // P8' P4' P2' P1' P2048 P1024 P512 P256 --- 2nd. Ecc Byte to store
+ // P128 P64 P32 P16 P8 P4 P2 P1 --- 1st. Ecc Byte to store
+ for (i = 0; i < numEcc; i+= 2) {
+ // Get Parity value.
+ eccParity = ecc[i];
+ // Invert codes (linux compatibility)
+ eccParity = ~eccParity;
+ // Get NParity value.
+ eccNparity = ecc[i + 1];
+ eccNparity = ~eccNparity;
+ TRACE_DEBUG("ecc Parity%d is 0x%08x, ecc Nparity%d is 0x%08x \n\r", i, eccParity, i, eccNparity);
+ code[i * 3] = eccParity & 0xff;
+ code[i * 3 + 1] = ((eccParity >> 8) & 0x0f ) | ((eccNparity & 0x0f) << 4);
+ code[i * 3 + 2] = (eccNparity >> 4) & 0xff;
+
+ code[(i + 1) * 3] = (eccParity >> 16) & 0xff;
+ code[(i + 1) * 3 + 1] = ((eccParity >> 24) & 0x0f ) | (((eccNparity >> 16)& 0x0f) << 4);
+ code[(i + 1) * 3 + 2] = (eccNparity >> 20) & 0xff;
+
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Get 32-bit ECC code for 16-bit data path NAND flash.
+/// 32-bit ECC is generated in order to perform one bit correction
+/// for a page in page 512/1024/2048/4096 for 16-bit words
+/// \param size Data size in bytes.
+/// \param code Codes buffer.
+//------------------------------------------------------------------------------
+void HSMC4_Get32bitPerPageEcc(unsigned int pageDataSize, unsigned char *code)
+{
+ unsigned int eccParity;
+ unsigned int eccNparity;
+ unsigned int ecc[16];
+ // Get Parity value.
+ HSMC4_EccGetValue(ecc);
+
+ // ---- P16384'P8192'P4096'P2048' P1024'P512'P256' --- 4th. Ecc Byte to store
+ /// P128' P64' P32' P16' P8' P4' P2' P1' --- 3rd. Ecc Byte to store
+ // ---- P16384 P8192 P4096 P2048 P1024 P512 P256 --- 2nd. Ecc Byte to store
+ // P128 P64 P32 P16 P8 P4 P2 P1 --- 1st. Ecc Byte to store
+
+ // Invert codes (linux compatibility)
+ eccParity = ~(ecc[0]);
+ eccNparity = ~(ecc[1]);
+ TRACE_DEBUG("ecc Parity%d is 0x%08x, ecc Nparity%d is 0x%08x \n\r", eccParity, eccNparity);
+ code[0] = eccParity & 0xff;
+ code[1] = (eccParity >> 8 )& 0xff;
+ code[2] = eccNparity & 0xff;
+ code[3] = (eccNparity >> 8 )& 0xff;
+}
+
+//------------------------------------------------------------------------------
+/// Get ECC code for 8bit/16-bit data path NAND flash by giving data path.
+/// 24-bit or 32-bit ECC is generated in order to perform one bit correction
+/// for a page in page 512/1024/2048/4096.
+/// \param size Data size in bytes.
+/// \param code Codes buffer.
+/// \param dataPath 8bit/16bit data path.
+//------------------------------------------------------------------------------
+void HSMC4_GetEccParity(unsigned int pageDataSize, unsigned char *code, unsigned char dataPath)
+{
+ unsigned char correctionType;
+ correctionType = HSMC4_GetEccCorrectoinType();
+ // For 16-bit data path
+ if (dataPath == 16) {
+ switch (correctionType){
+ case AT91C_ECC_TYPCORRECT_ONE_PER_PAGE:
+ HSMC4_Get32bitPerPageEcc(pageDataSize, code);
+ break;
+ case AT91C_ECC_TYPCORRECT_ONE_EVERY_256_BYTES:
+ HSMC4_Get32bitPer256Ecc(pageDataSize, code);
+ break;
+ case AT91C_ECC_TYPCORRECT_ONE_EVERY_512_BYTES:
+ TRACE_WARNING("16 bit 512 byte correct not yet implement! \n\r");
+ break;
+ }
+ }
+ // For 8-bit data path
+ else {
+ switch (correctionType){
+ case AT91C_ECC_TYPCORRECT_ONE_PER_PAGE:
+ HSMC4_Get24bitPerPageEcc(pageDataSize, code);
+ break;
+ case AT91C_ECC_TYPCORRECT_ONE_EVERY_256_BYTES:
+ HSMC4_Get24bitPer256Ecc(pageDataSize, code);
+ break;
+ case AT91C_ECC_TYPCORRECT_ONE_EVERY_512_BYTES:
+ HSMC4_Get24bitPer512Ecc(pageDataSize, code);
+ break;
+ }
+ }
+} \ No newline at end of file
diff --git a/peripherals/hsmc4/hsmc4_ecc.h b/peripherals/hsmc4/hsmc4_ecc.h
new file mode 100644
index 0000000..8ddcc87
--- /dev/null
+++ b/peripherals/hsmc4/hsmc4_ecc.h
@@ -0,0 +1,85 @@
+/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef HSMC4_ECC_H
+#define HSMC4_ECC_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <board.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "Hsiao Code Errors"
+/// These are the possible errors when trying to verify a block of data encoded
+/// using a Hsiao code:
+///
+/// !Errors:
+/// - Hsiao_ERROR_SINGLEBIT
+/// - Hsiao_ERROR_ECC
+/// - Hsiao_ERROR_MULTIPLEBITS
+
+/// A single bit was incorrect but has been recovered.
+#define Hsiao_ERROR_SINGLEBIT 1
+
+/// The original code has been corrupted.
+#define Hsiao_ERROR_ECC 2
+
+/// Multiple bits are incorrect in the data and they cannot be corrected.
+#define Hsiao_ERROR_MULTIPLEBITS 3
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void HSMC4_EccConfigure(unsigned int type, unsigned int pageSize);
+
+extern unsigned int HSMC4_GetEccCorrectoinType(void);
+
+extern void HSMC4_EccGetValue(unsigned int *ecc);
+
+extern void HSMC4_GetEccParity(
+ unsigned int pageDataSize,
+ unsigned char *code,
+ unsigned char dataPath);
+
+extern unsigned char HSMC4_VerifyHsiao(
+ unsigned char *data,
+ unsigned int size,
+ const unsigned char *originalCode,
+ const unsigned char *verifyCode,
+ unsigned char dataPath);
+
+#endif //#ifndef HSMC4_ECC_H
+
personal git repositories of Harald Welte. Your mileage may vary