-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
NAND Flash memory emulation and ECC calculation helpers for use by NA…
…ND controllers. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2753 c046a42c-6fe2-441c-8c8c-71466251a162
- Loading branch information
balrog
committed
Apr 30, 2007
1 parent
18c9b56
commit 3e3d581
Showing
4 changed files
with
723 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* | ||
* Calculate Error-correcting Codes. Used by NAND Flash controllers | ||
* (not by NAND chips). | ||
* | ||
* Copyright (c) 2006 Openedhand Ltd. | ||
* Written by Andrzej Zaborowski <balrog@zabor.org> | ||
* | ||
* This code is licensed under the GNU GPL v2. | ||
*/ | ||
|
||
struct ecc_state_s { | ||
uint8_t cp; /* Column parity */ | ||
uint16_t lp[2]; /* Line parity */ | ||
uint16_t count; | ||
}; | ||
|
||
/* | ||
* Pre-calculated 256-way 1 byte column parity. Table borrowed from Linux. | ||
*/ | ||
static const uint8_t nand_ecc_precalc_table[] = { | ||
0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, | ||
0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, | ||
0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, | ||
0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, | ||
0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, | ||
0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, | ||
0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, | ||
0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, | ||
0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, | ||
0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, | ||
0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, | ||
0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, | ||
0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, | ||
0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, | ||
0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, | ||
0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, | ||
0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, | ||
0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, | ||
0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, | ||
0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, | ||
0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, | ||
0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, | ||
0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, | ||
0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, | ||
0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, | ||
0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, | ||
0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, | ||
0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, | ||
0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, | ||
0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, | ||
0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, | ||
0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, | ||
}; | ||
|
||
/* Update ECC parity count. */ | ||
static inline uint8_t ecc_digest(struct ecc_state_s *s, uint8_t sample) | ||
{ | ||
uint8_t idx = nand_ecc_precalc_table[sample]; | ||
|
||
s->cp ^= idx & 0x3f; | ||
if (idx & 0x40) { | ||
s->lp[0] ^= ~s->count; | ||
s->lp[1] ^= s->count; | ||
} | ||
s->count ++; | ||
|
||
return sample; | ||
} | ||
|
||
/* Reinitialise the counters. */ | ||
static inline void ecc_reset(struct ecc_state_s *s) | ||
{ | ||
s->lp[0] = 0x0000; | ||
s->lp[1] = 0x0000; | ||
s->cp = 0x00; | ||
s->count = 0; | ||
} |
Oops, something went wrong.