* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
/*
};
struct davinci_nand {
- struct target *target;
-
- uint8_t chipsel; /* chipselect 0..3 == CS2..CS5 */
- uint8_t eccmode;
+ uint8_t chipsel; /* chipselect 0..3 == CS2..CS5 */
+ uint8_t eccmode;
/* Async EMIF controller base */
- uint32_t aemif;
+ uint32_t aemif;
/* NAND chip addresses */
- uint32_t data; /* without CLE or ALE */
- uint32_t cmd; /* with CLE */
- uint32_t addr; /* with ALE */
+ uint32_t data; /* without CLE or ALE */
+ uint32_t cmd; /* with CLE */
+ uint32_t addr; /* with ALE */
/* write acceleration */
- struct arm_nand_data io;
+ struct arm_nand_data io;
/* page i/o for the relevant flavor of hardware ECC */
int (*read_page)(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
int (*write_page)(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
};
-#define NANDFCR 0x60 /* flash control register */
-#define NANDFSR 0x64 /* flash status register */
-#define NANDFECC 0x70 /* 1-bit ECC data, CS0, 1st of 4 */
-#define NAND4BITECCLOAD 0xbc /* 4-bit ECC, load saved values */
-#define NAND4BITECC 0xc0 /* 4-bit ECC data, 1st of 4 */
-#define NANDERRADDR 0xd0 /* 4-bit ECC err addr, 1st of 2 */
-#define NANDERRVAL 0xd8 /* 4-bit ECC err value, 1st of 2 */
+#define NANDFCR 0x60 /* flash control register */
+#define NANDFSR 0x64 /* flash status register */
+#define NANDFECC 0x70 /* 1-bit ECC data, CS0, 1st of 4 */
+#define NAND4BITECCLOAD 0xbc /* 4-bit ECC, load saved values */
+#define NAND4BITECC 0xc0 /* 4-bit ECC data, 1st of 4 */
+#define NANDERRADDR 0xd0 /* 4-bit ECC err addr, 1st of 2 */
+#define NANDERRVAL 0xd8 /* 4-bit ECC err value, 1st of 2 */
static int halted(struct target *target, const char *label)
{
static int davinci_init(struct nand_device *nand)
{
struct davinci_nand *info = nand->controller_priv;
- struct target *target = info->target;
+ struct target *target = nand->target;
uint32_t nandfcr;
if (!halted(target, "init"))
static int davinci_nand_ready(struct nand_device *nand, int timeout)
{
struct davinci_nand *info = nand->controller_priv;
- struct target *target = info->target;
+ struct target *target = nand->target;
uint32_t nandfsr;
/* NOTE: return code is zero/error, else success; not ERROR_* */
static int davinci_command(struct nand_device *nand, uint8_t command)
{
struct davinci_nand *info = nand->controller_priv;
- struct target *target = info->target;
+ struct target *target = nand->target;
if (!halted(target, "command"))
return ERROR_NAND_OPERATION_FAILED;
static int davinci_address(struct nand_device *nand, uint8_t address)
{
struct davinci_nand *info = nand->controller_priv;
- struct target *target = info->target;
+ struct target *target = nand->target;
if (!halted(target, "address"))
return ERROR_NAND_OPERATION_FAILED;
static int davinci_write_data(struct nand_device *nand, uint16_t data)
{
struct davinci_nand *info = nand->controller_priv;
- struct target *target = info->target;
+ struct target *target = nand->target;
if (!halted(target, "write_data"))
return ERROR_NAND_OPERATION_FAILED;
static int davinci_read_data(struct nand_device *nand, void *data)
{
struct davinci_nand *info = nand->controller_priv;
- struct target *target = info->target;
+ struct target *target = nand->target;
if (!halted(target, "read_data"))
return ERROR_NAND_OPERATION_FAILED;
/* REVISIT a bit of native code should let block reads be MUCH faster */
static int davinci_read_block_data(struct nand_device *nand,
- uint8_t *data, int data_size)
+ uint8_t *data, int data_size)
{
struct davinci_nand *info = nand->controller_priv;
- struct target *target = info->target;
+ struct target *target = nand->target;
uint32_t nfdata = info->data;
uint32_t tmp;
}
static int davinci_write_block_data(struct nand_device *nand,
- uint8_t *data, int data_size)
+ uint8_t *data, int data_size)
{
struct davinci_nand *info = nand->controller_priv;
- struct target *target = info->target;
+ struct target *target = nand->target;
uint32_t nfdata = info->data;
uint32_t tmp;
int status;
}
static int davinci_write_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{
struct davinci_nand *info = nand->controller_priv;
uint8_t *ooballoc = NULL;
if (!nand->device)
return ERROR_NAND_DEVICE_NOT_PROBED;
- if (!halted(info->target, "write_page"))
+ if (!halted(nand->target, "write_page"))
return ERROR_NAND_OPERATION_FAILED;
/* Always write both data and OOB ... we are not "raw" I/O! */
if (!data) {
- LOG_ERROR("Missing NAND data; try 'nand raw_access enable'\n");
+ LOG_ERROR("Missing NAND data; try 'nand raw_access enable'");
return ERROR_NAND_OPERATION_FAILED;
}
/* If we're not given OOB, write 0xff where we don't write ECC codes. */
switch (nand->page_size) {
- case 512:
- oob_size = 16;
- break;
- case 2048:
- oob_size = 64;
- break;
- case 4096:
- oob_size = 128;
- break;
- default:
- return ERROR_NAND_OPERATION_FAILED;
+ case 512:
+ oob_size = 16;
+ break;
+ case 2048:
+ oob_size = 64;
+ break;
+ case 4096:
+ oob_size = 128;
+ break;
+ default:
+ return ERROR_NAND_OPERATION_FAILED;
}
if (!oob) {
ooballoc = malloc(oob_size);
}
static int davinci_read_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{
struct davinci_nand *info = nand->controller_priv;
if (!nand->device)
return ERROR_NAND_DEVICE_NOT_PROBED;
- if (!halted(info->target, "read_page"))
+ if (!halted(nand->target, "read_page"))
return ERROR_NAND_OPERATION_FAILED;
return info->read_page(nand, page, data, data_size, oob, oob_size);
static void davinci_write_pagecmd(struct nand_device *nand, uint8_t cmd, uint32_t page)
{
struct davinci_nand *info = nand->controller_priv;
- struct target *target = info->target;
+ struct target *target = nand->target;
int page3 = nand->address_cycles - (nand->page_size == 512);
/* write command ({page,otp}x{read,program} */
static int davinci_seek_column(struct nand_device *nand, uint16_t column)
{
struct davinci_nand *info = nand->controller_priv;
- struct target *target = info->target;
+ struct target *target = nand->target;
/* Random read, we must have issued a page read already */
target_write_u8(target, info->cmd, NAND_CMD_RNDOUT);
}
static int davinci_writepage_tail(struct nand_device *nand,
- uint8_t *oob, uint32_t oob_size)
+ uint8_t *oob, uint32_t oob_size)
{
struct davinci_nand *info = nand->controller_priv;
- struct target *target = info->target;
+ struct target *target = nand->target;
uint8_t status;
if (oob_size)
* All DaVinci family chips support 1-bit ECC on a per-chipselect basis.
*/
static int davinci_write_page_ecc1(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{
unsigned oob_offset;
struct davinci_nand *info = nand->controller_priv;
- struct target *target = info->target;
+ struct target *target = nand->target;
const uint32_t fcr_addr = info->aemif + NANDFCR;
const uint32_t ecc1_addr = info->aemif + NANDFECC + (4 * info->chipsel);
uint32_t fcr, ecc1;
* for 16-bit OOB, those extra bytes are discontiguous.
*/
switch (nand->page_size) {
- case 512:
- oob_offset = 0;
- break;
- case 2048:
- oob_offset = 40;
- break;
- default:
- oob_offset = 80;
- break;
+ case 512:
+ oob_offset = 0;
+ break;
+ case 2048:
+ oob_offset = 40;
+ break;
+ default:
+ oob_offset = 80;
+ break;
}
davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
* manufacturer bad block markers are safe. Contrast: old "infix" style.
*/
static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{
static const uint8_t ecc512[] = {
- 0, 1, 2, 3, 4, /* 5== mfr badblock */
+ 0, 1, 2, 3, 4, /* 5== mfr badblock */
6, 7, /* 8..12 for BBT or JFFS2 */ 13, 14, 15,
};
static const uint8_t ecc2048[] = {
54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
};
static const uint8_t ecc4096[] = {
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
- 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
- 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
- 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
};
struct davinci_nand *info = nand->controller_priv;
const uint8_t *l;
- struct target *target = info->target;
+ struct target *target = nand->target;
const uint32_t fcr_addr = info->aemif + NANDFCR;
const uint32_t ecc4_addr = info->aemif + NAND4BITECC;
uint32_t fcr, ecc4;
* the standard ECC logic can't handle.
*/
switch (nand->page_size) {
- case 512:
- l = ecc512;
- break;
- case 2048:
- l = ecc2048;
- break;
- default:
- l = ecc4096;
- break;
+ case 512:
+ l = ecc512;
+ break;
+ case 2048:
+ l = ecc2048;
+ break;
+ default:
+ l = ecc4096;
+ break;
}
davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
raw_ecc[i] &= 0x03ff03ff;
}
for (i = 0, p = raw_ecc; i < 2; i++, p += 2) {
- oob[*l++] = p[0] & 0xff;
+ oob[*l++] = p[0] & 0xff;
oob[*l++] = ((p[0] >> 8) & 0x03) | ((p[0] >> 14) & 0xfc);
oob[*l++] = ((p[0] >> 22) & 0x0f) | ((p[1] << 4) & 0xf0);
oob[*l++] = ((p[1] >> 4) & 0x3f) | ((p[1] >> 10) & 0xc0);
- oob[*l++] = (p[1] >> 18) & 0xff;
+ oob[*l++] = (p[1] >> 18) & 0xff;
}
} while (data_size);
* (MVL 4.x/5.x kernels, filesystems, etc) may need it more generally.
*/
static int davinci_write_page_ecc4infix(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{
struct davinci_nand *info = nand->controller_priv;
- struct target *target = info->target;
+ struct target *target = nand->target;
const uint32_t fcr_addr = info->aemif + NANDFCR;
const uint32_t ecc4_addr = info->aemif + NAND4BITECC;
uint32_t fcr, ecc4;
/* skip 6 bytes of prepad, then pack 10 packed ecc bytes */
for (i = 0, l = oob + 6, p = raw_ecc; i < 2; i++, p += 2) {
- *l++ = p[0] & 0xff;
+ *l++ = p[0] & 0xff;
*l++ = ((p[0] >> 8) & 0x03) | ((p[0] >> 14) & 0xfc);
*l++ = ((p[0] >> 22) & 0x0f) | ((p[1] << 4) & 0xf0);
*l++ = ((p[1] >> 4) & 0x3f) | ((p[1] >> 10) & 0xc0);
- *l++ = (p[1] >> 18) & 0xff;
+ *l++ = (p[1] >> 18) & 0xff;
}
/* write this "out-of-band" data -- infix */
}
static int davinci_read_page_ecc4infix(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{
int read_size;
int want_col, at_col;
NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
{
struct davinci_nand *info;
- struct target *target;
unsigned long chip, aemif;
enum ecc eccmode;
int chipsel;
* - aemif address
* Plus someday, optionally, ALE and CLE masks.
*/
- if (CMD_ARGC < 5) {
- LOG_ERROR("parameters: %s target "
- "chip_addr hwecc_mode aemif_addr",
- CMD_ARGV[0]);
- goto fail;
- }
-
- target = get_target(CMD_ARGV[1]);
- if (!target) {
- LOG_ERROR("invalid target %s", CMD_ARGV[1]);
- goto fail;
- }
+ if (CMD_ARGC < 5)
+ return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip);
if (chip == 0) {
* AEMIF controller address.
*/
if (aemif == 0x01e00000 /* dm6446, dm357 */
- || aemif == 0x01e10000 /* dm335, dm355 */
- || aemif == 0x01d10000 /* dm365 */
- ) {
+ || aemif == 0x01e10000 /* dm335, dm355 */
+ || aemif == 0x01d10000 /* dm365 */
+ ) {
if (chip < 0x02000000 || chip >= 0x0a000000) {
LOG_ERROR("NAND address %08lx out of range?", chip);
goto fail;
if (info == NULL)
goto fail;
- info->target = target;
info->eccmode = eccmode;
info->chipsel = chipsel;
info->aemif = aemif;
nand->controller_priv = info;
- info->io.target = target;
+ info->io.target = nand->target;
info->io.data = info->data;
info->io.op = ARM_NAND_NONE;
info->read_page = nand_read_page_raw;
switch (eccmode) {
- case HWECC1:
- /* ECC_HW, 1-bit corrections, 3 bytes ECC per 512 data bytes */
- info->write_page = davinci_write_page_ecc1;
- break;
- case HWECC4:
- /* ECC_HW, 4-bit corrections, 10 bytes ECC per 512 data bytes */
- info->write_page = davinci_write_page_ecc4;
- break;
- case HWECC4_INFIX:
- /* Same 4-bit ECC HW, with problematic page/ecc layout */
- info->read_page = davinci_read_page_ecc4infix;
- info->write_page = davinci_write_page_ecc4infix;
- break;
+ case HWECC1:
+ /* ECC_HW, 1-bit corrections, 3 bytes ECC per 512 data bytes */
+ info->write_page = davinci_write_page_ecc1;
+ break;
+ case HWECC4:
+ /* ECC_HW, 4-bit corrections, 10 bytes ECC per 512 data bytes */
+ info->write_page = davinci_write_page_ecc4;
+ break;
+ case HWECC4_INFIX:
+ /* Same 4-bit ECC HW, with problematic page/ecc layout */
+ info->read_page = davinci_read_page_ecc4infix;
+ info->write_page = davinci_write_page_ecc4infix;
+ break;
}
return ERROR_OK;
}
struct nand_flash_controller davinci_nand_controller = {
- .name = "davinci",
- .nand_device_command = davinci_nand_device_command,
- .init = davinci_init,
- .reset = davinci_reset,
- .command = davinci_command,
- .address = davinci_address,
- .write_data = davinci_write_data,
- .read_data = davinci_read_data,
- .write_page = davinci_write_page,
- .read_page = davinci_read_page,
- .write_block_data = davinci_write_block_data,
- .read_block_data = davinci_read_block_data,
- .nand_ready = davinci_nand_ready,
+ .name = "davinci",
+ .usage = "chip_addr hwecc_mode aemif_addr",
+ .nand_device_command = davinci_nand_device_command,
+ .init = davinci_init,
+ .reset = davinci_reset,
+ .command = davinci_command,
+ .address = davinci_address,
+ .write_data = davinci_write_data,
+ .read_data = davinci_read_data,
+ .write_page = davinci_write_page,
+ .read_page = davinci_read_page,
+ .write_block_data = davinci_write_block_data,
+ .read_block_data = davinci_read_block_data,
+ .nand_ready = davinci_nand_ready,
};