added debug option for get_byte to dump every byte.

Fix for technoland config
Added new anal-retentive DoC code for those who want it to docmil_fill_inbuf
added .h files for new DoC code.
This commit is contained in:
Ronald G. Minnich 2001-10-24 16:13:42 +00:00
parent 8e1e3fbfa5
commit 71022a5661
7 changed files with 814 additions and 22 deletions

136
src/include/mtd/doc2000.h Normal file
View file

@ -0,0 +1,136 @@
/* Linux driver for Disk-On-Chip 2000 */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@mvhi.com> */
/* $Id$ */
#ifndef __MTD_DOC2000_H__
#define __MTD_DOC2000_H__
//#include <linux/mtd/mtd.h>
#define DoC_Sig1 0
#define DoC_Sig2 1
#define DoC_ChipID 0x1000
#define DoC_DOCStatus 0x1001
#define DoC_DOCControl 0x1002
#define DoC_FloorSelect 0x1003
#define DoC_CDSNControl 0x1004
#define DoC_CDSNDeviceSelect 0x1005
#define DoC_ECCConf 0x1006
#define DoC_2k_ECCStatus 0x1007
#define DoC_CDSNSlowIO 0x100d
#define DoC_ECCSyndrome0 0x1010
#define DoC_ECCSyndrome1 0x1011
#define DoC_ECCSyndrome2 0x1012
#define DoC_ECCSyndrome3 0x1013
#define DoC_ECCSyndrome4 0x1014
#define DoC_ECCSyndrome5 0x1015
#define DoC_AliasResolution 0x101b
#define DoC_ConfigInput 0x101c
#define DoC_ReadPipeInit 0x101d
#define DoC_WritePipeTerm 0x101e
#define DoC_LastDataRead 0x101f
#define DoC_NOP 0x1020
#define DoC_Mil_CDSN_IO 0x0800
#define DoC_2k_CDSN_IO 0x1800
/* How to access the device?
* On ARM, it'll be mmap'd directly with 32-bit wide accesses.
* On PPC, it's mmap'd and 16-bit wide.
* Others use readb/writeb
*/
#if defined(__arm__)
#define ReadDOC_(adr, reg) ((unsigned char)(*(__u32 *)(((unsigned long)adr)+(reg<<2))))
#define WriteDOC_(d, adr, reg) do{ *(__u32 *)(((unsigned long)adr)+(reg<<2)) = (__u32)d} while(0)
#elif defined(__ppc__)
#define ReadDOC_(adr, reg) ((unsigned char)(*(__u16 *)(((unsigned long)adr)+(reg<<1))))
#define WriteDOC_(d, adr, reg) do{ *(__u16 *)(((unsigned long)adr)+(reg<<1)) = (__u16)d} while(0)
#else
#define ReadDOC_(adr, reg) readb(((unsigned long)adr) + reg)
#define WriteDOC_(d, adr, reg) writeb(d, ((unsigned long)adr) + reg)
#endif
#if defined(__i386__)
#define USE_MEMCPY
#endif
/* These are provided to directly use the DoC_xxx defines */
#define ReadDOC(adr, reg) ReadDOC_(adr,DoC_##reg)
#define WriteDOC(d, adr, reg) WriteDOC_(d,adr,DoC_##reg)
#define DOC_MODE_RESET 0
#define DOC_MODE_NORMAL 1
#define DOC_MODE_RESERVED1 2
#define DOC_MODE_RESERVED2 3
#define DOC_MODE_MDWREN 4
#define DOC_MODE_CLR_ERR 0x80
#define DOC_ChipID_Doc2k 0x20
#define DOC_ChipID_DocMil 0x30
#define CDSN_CTRL_FR_B 0x80
#define CDSN_CTRL_ECC_IO 0x20
#define CDSN_CTRL_FLASH_IO 0x10
#define CDSN_CTRL_WP 0x08
#define CDSN_CTRL_ALE 0x04
#define CDSN_CTRL_CLE 0x02
#define CDSN_CTRL_CE 0x01
#define DOC_ECC_RESET 0
#define DOC_ECC_ERROR 0x80
#define DOC_ECC_RW 0x20
#define DOC_ECC__EN 0x08
#define DOC_TOGGLE_BIT 0x04
#define DOC_ECC_RESV 0x02
#define DOC_ECC_IGNORE 0x01
/* We have to also set the reserved bit 1 for enable */
#define DOC_ECC_EN (DOC_ECC__EN | DOC_ECC_RESV)
#define DOC_ECC_DIS (DOC_ECC_RESV)
struct Nand {
char floor, chip;
unsigned long curadr;
unsigned char curmode;
/* Also some erase/write/pipeline info when we get that far */
};
#define MAX_FLOORS 4
#define MAX_CHIPS 4
#define MAX_FLOORS_MIL 4
#define MAX_CHIPS_MIL 1
#define ADDR_COLUMN 1
#define ADDR_PAGE 2
#define ADDR_COLUMN_PAGE 3
struct DiskOnChip {
unsigned long physadr;
unsigned long virtadr;
unsigned long totlen;
char ChipID; /* Type of DiskOnChip */
int ioreg;
unsigned long mfr; /* Flash IDs - only one type of flash per device */
unsigned long id;
int chipshift;
char page256;
char pageadrlen;
unsigned long erasesize;
int curfloor;
int curchip;
int numchips;
struct Nand *chips;
struct mtd_info *nextdoc;
};
#endif /* __MTD_DOC2000_H__ */

130
src/include/mtd/nand.h Normal file
View file

@ -0,0 +1,130 @@
/*
* linux/include/linux/mtd/nand.h
*
* Copyright (c) 2000 David Woodhouse <dwmw2@mvhi.com>
* Steven J. Hill <sjhill@cotw.com>
*
* $Id$
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Info:
* Contains standard defines and IDs for NAND flash devices
*
* Changelog:
* 01-31-2000 DMW Created
* 09-18-2000 SJH Moved structure out of the Disk-On-Chip drivers
* so it can be used by other NAND flash device
* drivers. I also changed the copyright since none
* of the original contents of this file are specific
* to DoC devices. David can whack me with a baseball
* bat later if I did something naughty.
* 10-11-2000 SJH Added private NAND flash structure for driver
*/
#ifndef __LINUX_MTD_NAND_H
#define __LINUX_MTD_NAND_H
/*
* Standard NAND flash commands
*/
#define NAND_CMD_READ0 0
#define NAND_CMD_READ1 1
#define NAND_CMD_PAGEPROG 0x10
#define NAND_CMD_READOOB 0x50
#define NAND_CMD_ERASE1 0x60
#define NAND_CMD_STATUS 0x70
#define NAND_CMD_SEQIN 0x80
#define NAND_CMD_READID 0x90
#define NAND_CMD_ERASE2 0xd0
#define NAND_CMD_RESET 0xff
/*
* Enumeration for NAND flash chip state
*/
typedef enum {
FL_READY,
FL_READING,
FL_WRITING,
FL_ERASING,
FL_SYNCING
} nand_state_t;
/*
* NAND Private Flash Chip Data
*
* Structure overview:
*
* IO_ADDR - address to access the 8 I/O lines to the flash device
*
* CTRL_ADDR - address where ALE, CLE and CE control bits are accessed
*
* CLE - location in control word for Command Latch Enable bit
*
* ALE - location in control word for Address Latch Enable bit
*
* NCE - location in control word for nChip Enable bit
*
* chip_lock - spinlock used to protect access to this structure
*
* wq - wait queue to sleep on if a NAND operation is in progress
*
* state - give the current state of the NAND device
*
* page_shift - number of address bits in a page (column address bits)
*
* data_buf - data buffer passed to/from MTD user modules
*
* ecc_code_buf - used only for holding calculated or read ECCs for
* a page read or written when ECC is in use
*
* reserved - padding to make structure fall on word boundary if
* when ECC is in use
*/
/*
* NAND Flash Manufacturer ID Codes
*/
#define NAND_MFR_TOSHIBA 0x98
#define NAND_MFR_SAMSUNG 0xec
/*
* NAND Flash Device ID Structure
*
* Structure overview:
*
* name - Complete name of device
*
* manufacture_id - manufacturer ID code of device.
*
* model_id - model ID code of device.
*
* chipshift - total number of address bits for the device which
* is used to calculate address offsets and the total
* number of bytes the device is capable of.
*
* page256 - denotes if flash device has 256 byte pages or not.
*
* pageadrlen - number of bytes minus one needed to hold the
* complete address into the flash array. Keep in
* mind that when a read or write is done to a
* specific address, the address is input serially
* 8 bits at a time. This structure member is used
* by the read/write routines as a loop index for
* shifting the address out 8 bits at a time.
*
* erasesize - size of an erase block in the flash device.
*/
struct nand_flash_dev {
char * name;
int manufacture_id;
int model_id;
int chipshift;
char page256;
char pageadrlen;
unsigned long erasesize;
};
#endif /* __LINUX_MTD_NAND_H */

View file

@ -0,0 +1,52 @@
/*
* linux/include/linux/mtd/nand_ids.h
*
* Copyright (c) 2000 David Woodhouse <dwmw2@mvhi.com>
* Steven J. Hill <sjhill@cotw.com>
*
* $Id$
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Info:
* Contains standard defines and IDs for NAND flash devices
*
* Changelog:
* 01-31-2000 DMW Created
* 09-18-2000 SJH Moved structure out of the Disk-On-Chip drivers
* so it can be used by other NAND flash device
* drivers. I also changed the copyright since none
* of the original contents of this file are specific
* to DoC devices. David can whack me with a baseball
* bat later if I did something naughty.
* 10-11-2000 SJH Added private NAND flash structure for driver
* 2000-10-13 BE Moved out of 'nand.h' - avoids duplication.
*/
#ifndef __LINUX_MTD_NAND_IDS_H
#define __LINUX_MTD_NAND_IDS_H
static struct nand_flash_dev nand_flash_ids[] = {
{"Toshiba TC5816BDC", NAND_MFR_TOSHIBA, 0x64, 21, 1, 2, 0x1000},
{"Toshiba TC5832DC", NAND_MFR_TOSHIBA, 0x6b, 22, 0, 2, 0x2000},
{"Toshiba TH58V128DC", NAND_MFR_TOSHIBA, 0x73, 24, 0, 2, 0x4000},
{"Toshiba TC58256FT/DC", NAND_MFR_TOSHIBA, 0x75, 25, 0, 2, 0x4000},
{"Toshiba TH58512FT", NAND_MFR_TOSHIBA, 0x76, 26, 0, 3, 0x4000},
{"Toshiba TC58V32DC", NAND_MFR_TOSHIBA, 0xe5, 22, 0, 2, 0x2000},
{"Toshiba TC58V64AFT/DC", NAND_MFR_TOSHIBA, 0xe6, 23, 0, 2, 0x2000},
{"Toshiba TC58V16BDC", NAND_MFR_TOSHIBA, 0xea, 21, 1, 2, 0x1000},
{"Samsung KM29N16000", NAND_MFR_SAMSUNG, 0x64, 21, 1, 2, 0x1000},
{"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0x6b, 22, 0, 2, 0x2000},
{"Samsung KM29U128T", NAND_MFR_SAMSUNG, 0x73, 24, 0, 2, 0x4000},
{"Samsung KM29U256T", NAND_MFR_SAMSUNG, 0x75, 25, 0, 2, 0x4000},
{"Samsung unknown 64Mb", NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000},
{"Samsung KM29W32000", NAND_MFR_SAMSUNG, 0xe3, 22, 0, 2, 0x2000},
{"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0xe5, 22, 0, 2, 0x2000},
{"Samsung KM29U64000", NAND_MFR_SAMSUNG, 0xe6, 23, 0, 2, 0x2000},
{"Samsung KM29W16000", NAND_MFR_SAMSUNG, 0xea, 21, 1, 2, 0x1000},
{NULL,}
};
#endif /* __LINUX_MTD_NAND_IDS_H */

View file

@ -7,7 +7,17 @@ extern unsigned int inptr; /* index of next byte to be processed in inbuf */
extern int fill_inbuf(void);
#ifndef DEBUG_GET_BYTE
#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
#else
#include <printk.h>
static unsigned char get_byte() {
static int byteno = 0;
unsigned char c = (inptr < insize ? inbuf[inptr++] : fill_inbuf());
printk_debug("get_byte 0x%x 0x%x\n", byteno++, c);
return c;
}
#endif
#endif /* ROM_FILL_INBUF_H */

View file

@ -1,4 +1,4 @@
#define DEBG(x)
#define DEBG(x)
#define DEBG1(x)
/* Taken from /usr/src/linux/lib/inflate.c [unmodified]
Used for start32, 1/11/2000

View file

@ -29,7 +29,7 @@ option ZKERNEL_MASK=0x7f
# is we can drop any LinuxBIOS DoC in from any machine and it will work
# fine.
# option DOC_KERNEL_START 0
option DOC_MIL_BASE=0xd000
option DOC_MIL_BASE=0xd0000
option L440BX
object mainboard.o

View file

@ -7,6 +7,11 @@
#include <stddef.h>
#include <rom/fill_inbuf.h>
#ifdef USE_NEW_DOC_CODE
#include <mtd/doc2000.h>
#include <mtd/nand.h>
#include <mtd/nand_ids.h>
#endif
#ifndef DOC_KERNEL_START
#define DOC_KERNEL_START 65536
#endif
@ -20,7 +25,7 @@ static int block_count;
static int firstfill = 1;
static void memcpy_from_doc_mil(void *dest, const void *src, size_t n);
static unsigned char *doc_mil = (unsigned char *) DOC_MIL_BASE;
static volatile unsigned char *doc_mil = (unsigned char *) DOC_MIL_BASE;
#ifdef CHECK_DOC_MIL
static unsigned char *checkbuf;
#endif /* CHECK_DOC_MIL */
@ -28,11 +33,36 @@ static unsigned char *checkbuf;
static unsigned char *ram;
#define K64 (64 * 1024)
#ifdef RESET_DOC
void
reset_doc()
{
#ifdef USE_NEW_DOC_CODE
doc_mil[DoC_DOCControl] = DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET;
doc_mil[DoC_DOCControl] = DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET;
doc_mil[DoC_DOCControl] = DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL;
doc_mil[DoC_DOCControl] = DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL;
#else
*(volatile unsigned char *) (doc_mil + 0x1002) = 0x84;
*(volatile unsigned char *) (doc_mil + 0x1002) = 0x84;
*(volatile unsigned char *) (doc_mil + 0x1002) = 0x85;
*(volatile unsigned char *) (doc_mil + 0x1002) = 0x85;
#endif
}
#endif
int
fill_inbuf(void)
{
redo:
if (firstfill) {
// it is possible that we can get in here and the
// doc has never been reset. So go ahead and reset it again.
#ifdef RESET_DOC
reset_doc();
#endif
if ((ram = malloc(K64)) == NULL) {
printk_emerg("%6d:%s() - ram malloc failed\n",
__LINE__, __FUNCTION__);
@ -55,23 +85,36 @@ fill_inbuf(void)
nvram = (unsigned char *) DOC_KERNEL_START;
}
#ifdef CHECK_DOC_MIL
printk_info("DOC MIL address 0x%x\n", nvram);
#endif
memcpy_from_doc_mil(ram, nvram, K64);
#ifdef CHECK_DOC_MIL
if (checkbuf) {
memcpy_from_doc_mil(checkbuf, nvram, K64);
if (memcmp(checkbuf, ram, K64)) {
int i;
for(i = 0; i < K64; i++)
if (checkbuf[i] != ram[i])
printk_info("at %d First read 0x%x check 0x%x\n",
i, ram[i], checkbuf[i]);
printk_emerg("CHECKBUF FAILS for doc mil!\n");
printk_emerg( "address 0x%x\n", nvram);
goto redo;
}
}
#if 0
{
int i;
printk_info( "First 16 bytes of block: ");
for (i = 0; i < 16; i++)
printk_info("0x%x ", ram[i]);
printk_info( "\n");
int i, j;
for(i = 0; i < K64; i += 16) {
printk_info("0x%x: ", ram + i);
for(j = 0; j < 16; j++)
printk_info("%x ",ram[i+j]);
printk_info( "\n");
}
}
#endif /* 0 */
#endif
printk_debug("%6d:%s() - nvram:0x%p block_count:%d\n",
@ -87,6 +130,412 @@ fill_inbuf(void)
return inbuf[0];
}
#ifdef USE_NEW_DOC_CODE
/**************************************************************************
*
* New DoC code for LinxuBIOS. This code is from:
* doctest.c - a quick and dirty test for DoC2001 in MB BIOS socket
*
* compile: gcc -O2 -g -o doctest doctest.c
*
* Copyright Steven James <pyro@linuxlabs.com>, Linux Labs (www.linuxlabs.com)
*
* License GPL v2 or later (for what it's worth)
*
* DoC access code derived from Linux kernel drivers
* (c) 1999 Machine Vision Holdings, Inc.
* Author: David Woodhouse <dwmw2@mvhi.com>
*
*************************************************************************/
/* Access routines for DoC Mil */
#define _WriteDoC(data, adr, reg) adr[reg] = data
#define WriteDOC(data, adr, reg) _WriteDoC(data, adr, DoC_##reg)
#define _ReadDoC(adr, reg) adr[reg]
#define ReadDOC(adr, reg) _ReadDoC(adr, DoC_##reg)
/* Perform the required delsy cycles by reading from the NOP register */
static void DoC_Delay(volatile char *docptr, unsigned short cycles)
{
volatile char dummy;
int i;
for (i = 0; i < cycles; i++)
dummy = ReadDOC(docptr, NOP);
}
/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
static int _DoC_WaitReady(volatile char *docptr)
{
unsigned short c = 0xffff;
/* Out-of-line routine to wait for chip response */
while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
;
return (c == 0);
}
static __inline__ int DoC_WaitReady(volatile char *docptr)
{
/* This is inline, to optimise the common case, where it's ready instantly */
int ret = 0;
/* 4 read form NOP register should be issued in prior to the read from CDSNControl
see Software Requirement 11.4 item 2. */
DoC_Delay(docptr, 4);
if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B))
/* Call the out-of-line routine to wait */
ret = _DoC_WaitReady(docptr);
/* issue 2 read from NOP register after reading from CDSNControl register
see Software Requirement 11.4 item 2. */
DoC_Delay(docptr, 2);
return ret;
}
/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to
bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
/* SURELY this is wrong what about bit 8? But I could be wrong... SMJ */
static __inline__ void DoC_Command(volatile char *docptr, unsigned char command,
unsigned char xtraflags)
{
/* Assert the CLE (Command Latch Enable) line to the flash chip */
WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl);
DoC_Delay(docptr, 4);
/* Send the command */
WriteDOC(command, docptr, CDSNSlowIO);
WriteDOC(command, docptr, Mil_CDSN_IO);
/* Lower the CLE line */
WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
DoC_Delay(docptr, 4);
}
/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to
bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
static __inline__ void DoC_Address (volatile char *docptr, int numbytes, unsigned long ofs,
unsigned char xtraflags1, unsigned char xtraflags2)
{
/* Assert the ALE (Address Latch Enable line to the flash chip */
WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl);
DoC_Delay(docptr, 4);
/* Send the address */
switch (numbytes)
{
case 1:
/* Send single byte, bits 0-7. */
WriteDOC(ofs & 0xff, docptr, CDSNSlowIO);
WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO);
break;
case 2:
/* Send bits 9-16 followed by 17-23 */
WriteDOC((ofs >> 9) & 0xff, docptr, CDSNSlowIO);
WriteDOC((ofs >> 9) & 0xff, docptr, Mil_CDSN_IO);
WriteDOC((ofs >> 17) & 0xff, docptr, CDSNSlowIO);
WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO);
break;
case 3:
/* Send 0-7, 9-16, then 17-23 */
WriteDOC(ofs & 0xff, docptr, CDSNSlowIO);
WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO);
WriteDOC((ofs >> 9) & 0xff, docptr, CDSNSlowIO);
WriteDOC((ofs >> 9) & 0xff, docptr, Mil_CDSN_IO);
WriteDOC((ofs >> 17) & 0xff, docptr, CDSNSlowIO);
WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO);
break;
default:
return;
}
/* Lower the ALE line */
WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, CDSNControl);
DoC_Delay(docptr, 4);
}
/* DoC_SelectChip: Select a given flash chip within the current floor */
static int DoC_SelectChip(volatile char *docptr, int chip)
{
/* Select the individual flash chip requested */
WriteDOC(chip, docptr, CDSNDeviceSelect);
DoC_Delay(docptr, 4);
/* Wait for it to be ready */
return DoC_WaitReady(docptr);
}
/* DoC_SelectFloor: Select a given floor (bank of flash chips) */
static int DoC_SelectFloor(volatile char *docptr, int floor)
{
/* Select the floor (bank) of chips required */
WriteDOC(floor, docptr, FloorSelect);
/* Wait for the chip to be ready */
return DoC_WaitReady(docptr);
}
/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
static int DoC_IdentChip(volatile char *docptr, int floor, int chip, int *mfr, int *id)
{
int i;
volatile char dummy;
/* Page in the required floor/chip
FIXME: is this supported by Millennium ?? */
DoC_SelectFloor(docptr, floor);
DoC_SelectChip(docptr, chip);
/* Reset the chip, see Software Requirement 11.4 item 1. */
DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP);
DoC_WaitReady(docptr);
/* Read the NAND chip ID: 1. Send ReadID command */
DoC_Command(docptr, NAND_CMD_READID, CDSN_CTRL_WP);
/* Read the NAND chip ID: 2. Send address byte zero */
DoC_Address(docptr, 1, 0x00, CDSN_CTRL_WP, 0x00);
/* Read the manufacturer and device id codes of the flash device through
CDSN Slow IO register see Software Requirement 11.4 item 5.*/
dummy = ReadDOC(docptr, CDSNSlowIO);
DoC_Delay(docptr, 2);
*mfr = ReadDOC(docptr, Mil_CDSN_IO);
dummy = ReadDOC(docptr, CDSNSlowIO);
DoC_Delay(docptr, 2);
*id = ReadDOC(docptr, Mil_CDSN_IO);
/* No response - return failure */
if (*mfr == 0xff || *mfr == 0)
return 0;
/* FIXME: to deal with mulit-flash on multi-Millennium case more carefully */
for (i = 0; nand_flash_ids[i].name != NULL; i++) {
if (*mfr == nand_flash_ids[i].manufacture_id &&
*id == nand_flash_ids[i].model_id) {
printk_info("Flash chip found: Manufacture ID: %2.2X, Chip ID: %2.2X (%s)\n",
*mfr, *id, nand_flash_ids[i].name);
break;
}
}
if (nand_flash_ids[i].name == NULL)
return 0;
else
return 1;
}
static int DoCMil_is_alias(volatile char *docptr1, volatile char *docptr2)
{
int tmp1, tmp2, retval;
if(docptr1 == docptr2)
return(1);
/* Use the alias resolution register which was set aside for this
* purpose. If it's value is the same on both chips, they might
* be the same chip, and we write to one and check for a change in
* the other. It's unclear if this register is usuable in the
* DoC 2000 (it's in the Millenium docs), but it seems to work. */
tmp1 = ReadDOC(docptr1, AliasResolution);
tmp2 = ReadDOC(docptr2, AliasResolution);
if (tmp1 != tmp2)
return 0;
WriteDOC((tmp1+1) % 0xff, docptr1, AliasResolution);
tmp2 = ReadDOC(docptr2, AliasResolution);
if (tmp2 == (tmp1+1) % 0xff)
retval = 1;
else
retval = 0;
/* Restore register contents. May not be necessary, but do it just to
* be safe. */
WriteDOC(tmp1, docptr1, AliasResolution);
return retval;
}
#if 0
int WriteBlockECC(volatile char *docptr, unsigned int block, const char *buf)
{
unsigned char eccbuf[6];
volatile char dummy;
int i;
DoC_SelectFloor(docptr, 0);
DoC_SelectChip(docptr, 0);
/* Reset the chip, see Software Requirement 11.4 item 1. */
DoC_Command(docptr, NAND_CMD_RESET, 0x00);
DoC_WaitReady(docptr);
/* Set device to main plane of flash */
DoC_Command(docptr, NAND_CMD_READ0, 0x00);
/* issue the Serial Data In command to initial the Page Program process
*/
DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
DoC_Address(docptr, 3, block <<9, 0x00, 0x00);
DoC_WaitReady(docptr);
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
/* Write the data via the internal pipeline through CDSN IO register,
see Pipelined Write Operations 11.2 */
for (i = 0; i < 512; i++) {
/* N.B. you have to increase the source address in this way or the
ECC logic will not work properly */
WriteDOC(buf[i], docptr, Mil_CDSN_IO + i);
}
WriteDOC(0x00, docptr, WritePipeTerm);
/* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic
see Reed-Solomon EDC/ECC 11.1 */
WriteDOC(0, docptr, NOP);
WriteDOC(0, docptr, NOP);
WriteDOC(0, docptr, NOP);
/* Read the ECC data through the DiskOnChip ECC logic */
for (i = 0; i < 6; i++) {
eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i);
}
/* ignore the ECC engine */
WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
/* Write the ECC data to flash */
for (i = 0; i < 6; i++) {
WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO + i);
}
/* write the block status BLOCK_USED (0x5555) at the end of ECC data FIXME: this is only a hack for programming the IPL area for LinuxBIOS and should be replace with proper codes in user space utilities */
WriteDOC(0x55, docptr, Mil_CDSN_IO);
WriteDOC(0x55, docptr, Mil_CDSN_IO + 1);
WriteDOC(0x00, docptr, WritePipeTerm);
/* Commit the Page Program command and wait for ready
see Software Requirement 11.4 item 1.*/
DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00);
DoC_WaitReady(docptr);
/* Read the status of the flash device through CDSN Slow IO register
see Software Requirement 11.4 item 5.*/
DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP);
dummy = ReadDOC(docptr, CDSNSlowIO);
DoC_Delay(docptr, 2);
if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
printk_info("Error programming flash\n");
return -EIO;
}
return(0);
}
#endif
int ReadBlockECC( volatile unsigned char *docptr, unsigned int block, char *buf)
{
int i, ret;
volatile char dummy;
unsigned char syndrome[6];
unsigned char eccbuf[6];
/* issue the Read0 or Read1 command depend on which half of the page
we are accessing. Polling the Flash Ready bit after issue 3 bytes
address in Sequence Read Mode, see Software Requirement 11.4 item 1.*/
/* This differs from SiS ipl.S which always issues 0! */
DoC_Command(docptr, 0, CDSN_CTRL_WP);
// DoC_Command(docptr, block & 1, CDSN_CTRL_WP);
DoC_Address(docptr, 3, block << 9, CDSN_CTRL_WP, 0x00);
DoC_WaitReady(docptr);
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
WriteDOC (DOC_ECC_EN, docptr, ECCConf);
dummy = ReadDOC(docptr, ReadPipeInit);
for (i = 0; i < 511; i++) {
buf[i] = ReadDOC(docptr, Mil_CDSN_IO + i);
}
buf[511] = ReadDOC(docptr, LastDataRead);
/* Read the ECC data from Spare Data Area,
see Reed-Solomon EDC/ECC 11.1 */
dummy = ReadDOC(docptr, ReadPipeInit);
for (i = 0; i < 5; i++) {
eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO + i);
}
eccbuf[i] = ReadDOC(docptr, LastDataRead);
/* Flush the pipeline */
dummy = ReadDOC(docptr, ECCConf);
dummy = ReadDOC(docptr, ECCConf);
/* Check the ECC Status */
if (ReadDOC(docptr, ECCConf) & 0x80) {
int nb_errors;
/* There was an ECC error */
printk_info("ECC error in block %u\n",block);
/* Read the ECC syndrom through the DiskOnChip ECC logic.
syndrome will be all ZERO when there is no error */
for (i = 0; i < 6; i++) {
syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i);
}
#ifdef CHECK_ECC
nb_errors = doc_decode_ecc(buf, syndrome);
if(nb_errors <0) {
printk_info("ECC errors uncorrectable!\n");
return(-EIO);
}
printk_info("Corrected %u errors!\n",nb_errors);
#else
printk_info("ECC Syndrom bytes:\n");
for(i=0; i<6 ; i++)
printk_info("%02x,",syndrome[i]);
printk_info("\n");
#endif
}
/* disable the ECC engine */
WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
return(0);
}
#endif
static void
memcpy_from_doc_mil(void *dest, const void *src, size_t n)
{
@ -94,35 +543,50 @@ memcpy_from_doc_mil(void *dest, const void *src, size_t n)
unsigned long address = (unsigned long) src;
for (i = n; i >= 0; i -= 0x200) {
#ifdef USE_NEW_DOC_CODE
ReadBlockECC(doc_mil,(address >> 9), dest);
#else
unsigned short c = 0x1000;
volatile unsigned char dummy;
/* issue Read00 flash command */
*(unsigned char *) (doc_mil + 0x1004) = 0x03;
*(unsigned char *) (doc_mil + 0x800) = 0x00;
*(unsigned char *) (doc_mil + 0x101e) = 0x00;
*(unsigned char *) (doc_mil + 0x1004) = 0x01;
*(volatile unsigned char *) (doc_mil + 0x1004) = 0x03;
*(volatile unsigned char *) (doc_mil + 0x800) = 0x00;
*(volatile unsigned char *) (doc_mil + 0x101e) = 0x00;
*(volatile unsigned char *) (doc_mil + 0x1004) = 0x01;
/* issue Address to flash */
*(unsigned char *) (doc_mil + 0x1004) = 0x05;
*(unsigned char *) (doc_mil + 0x800) = address & 0xff;
*(unsigned char *) (doc_mil + 0x800) = (address >> 9) & 0xff;
*(unsigned char *) (doc_mil + 0x800) = (address >> 17) & 0xff;
*(unsigned char *) (doc_mil + 0x101e) = 0x00;
*(unsigned char *) (doc_mil + 0x1004) = 0x01;
*(volatile unsigned char *) (doc_mil + 0x1004) = 0x05;
*(volatile unsigned char *) (doc_mil + 0x800) = address & 0xff;
*(volatile unsigned char *) (doc_mil + 0x800) = (address >> 9) & 0xff;
*(volatile unsigned char *) (doc_mil + 0x800) = (address >> 17) & 0xff;
*(volatile unsigned char *) (doc_mil + 0x101e) = 0x00;
*(volatile unsigned char *) (doc_mil + 0x1004) = 0x01;
/* We are using the "side effect" of the assignment to force GCC reload
* *(doc_mil + 0x1004) on each iteration */
while (!((dummy = *(unsigned char *) (doc_mil + 0x1004)) & 0x80) && --c)
while (!((dummy = *(volatile unsigned char *) (doc_mil + 0x1004)) & 0x80) && --c)
/* wait for chip response */;
/* copy 512 bytes of data from CDSN_IO registers */
dummy = *(unsigned char *) (doc_mil + 0x101d);
dummy = *(volatile unsigned char *) (doc_mil + 0x101d);
#ifdef CHECK_DOC_MIL
{ unsigned char val; unsigned char *cp = dest;
for(i = 0; i < 0x200; i++) {
val = *(volatile unsigned char *) (doc_mil + 0x800 + i);
printk_info("0x%x: 0x%x\n",
i + address, val);
cp[i] = val;
}
}
#else
memcpy(dest, doc_mil + 0x800, 0x200);
#endif /* CHECK_DOC_MIL */
#endif /* USE_NEW_DOC_CODE */
dest += 0x200;
address += 0x200;
}
}
}
#endif /* USE_DOC_MIL */