mirror of
https://github.com/fail0verflow/switch-coreboot.git
synced 2025-05-04 01:39:18 -04:00
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:
parent
8e1e3fbfa5
commit
71022a5661
7 changed files with 814 additions and 22 deletions
136
src/include/mtd/doc2000.h
Normal file
136
src/include/mtd/doc2000.h
Normal 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
130
src/include/mtd/nand.h
Normal 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 */
|
52
src/include/mtd/nand_ids.h
Normal file
52
src/include/mtd/nand_ids.h
Normal 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 */
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue