mirror of
git://projects.qi-hardware.com/xburst-tools.git
synced 2024-11-01 18:31:54 +02:00
add usb boot stage2 for device
This commit is contained in:
parent
6a07660a37
commit
3977cdb120
70
flash-tool/device_stage2/Makefile
Normal file
70
flash-tool/device_stage2/Makefile
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||||
|
# By Lucifer
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
FLASH_TOOL_PATH = ..
|
||||||
|
|
||||||
|
CC := mipsel-linux-gcc
|
||||||
|
AR := mipsel-linux-ar rcsv
|
||||||
|
LD := mipsel-linux-ld
|
||||||
|
OBJCOPY := mipsel-linux-objcopy
|
||||||
|
NM := mipsel-linux-nm
|
||||||
|
OBJDUMP := mipsel-linux-objdump
|
||||||
|
|
||||||
|
CFLAGS := -mips32 -O2 -FPIC \
|
||||||
|
-fno-exceptions -ffunction-sections \
|
||||||
|
-fomit-frame-pointer -msoft-float -G 0
|
||||||
|
|
||||||
|
#CFLAGS := -mips32 -O2 -FPIC -mno-abicalls -fno-builtin \
|
||||||
|
|
||||||
|
LDFLAGS := -nostdlib -T target.ld $(CFLAGS)
|
||||||
|
|
||||||
|
LIBS := -lstdc++ -lc -lm -lgcc
|
||||||
|
|
||||||
|
USBBOOTDIR := .
|
||||||
|
|
||||||
|
LIBDIR :=
|
||||||
|
|
||||||
|
#SOURCES += $(wildcard $(USBBOOTDIR)/usb_boot/*.c)
|
||||||
|
|
||||||
|
SOURCES := ./usb_boot/main.c ./usb_boot/udc.c ./usb_boot/cache.c ./usb_boot/serial.c ./usb_boot/boothandler.c
|
||||||
|
SOURCES += $(wildcard $(USBBOOTDIR)/nandflash/*.c)
|
||||||
|
SOURCES += $(wildcard $(USBBOOTDIR)/usb_boot/*.S)
|
||||||
|
|
||||||
|
HEADS := $(SOCDIR)/head.S
|
||||||
|
|
||||||
|
CFLAGS += -I$(SOCDIR)/include -I$(USBBOOTDIR)/usb_boot -I$(USBBOOTDIR)/nandflash -I$(USBBOOTDIR)/include
|
||||||
|
|
||||||
|
OBJS := $(addsuffix .o , $(basename $(notdir $(SOURCES))))
|
||||||
|
HEADO := $(addsuffix .o , $(basename $(notdir $(HEADS))))
|
||||||
|
|
||||||
|
TARGET := usb_boot
|
||||||
|
APP := $(TARGET).elf
|
||||||
|
|
||||||
|
VPATH := $(ARCHDIR) $(SOCDIR) $(OSDIR) $(USBBOOTDIR)/usb_boot $(USBBOOTDIR)/norflash $(USBBOOTDIR)/nandflash
|
||||||
|
|
||||||
|
all: $(APP)
|
||||||
|
$(OBJCOPY) -O binary $(APP) $(TARGET).bin
|
||||||
|
$(OBJDUMP) -D $(APP) > $(TARGET).dump
|
||||||
|
$(NM) $(APP) | sort > $(TARGET).sym
|
||||||
|
$(OBJDUMP) -h $(APP) > $(TARGET).map
|
||||||
|
cp usb_boot.bin $(FLASH_TOOL_PATH)
|
||||||
|
|
||||||
|
$(APP): $(HEADO) $(OBJS) $(EXTLIBS)
|
||||||
|
$(CC) $(LDFLAGS) $^ -o $@
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CC) $(CFLAGS) -o $@ -c $<
|
||||||
|
.cpp.o:
|
||||||
|
$(CC) $(CFLAGS) -fno-rtti -fvtable-gc -o $@ -c $<
|
||||||
|
.S.o:
|
||||||
|
$(CC) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -fr *.o $(APP) $(OBJS) core $(OTHER) *.sym *.map *.dump *.bin *.lib *.~ *.\#
|
||||||
|
|
2356
flash-tool/device_stage2/include/archdefs.h
Normal file
2356
flash-tool/device_stage2/include/archdefs.h
Normal file
File diff suppressed because it is too large
Load Diff
21
flash-tool/device_stage2/include/error.h
Normal file
21
flash-tool/device_stage2/include/error.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef __ERROR_H__
|
||||||
|
#define __ERROR_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All of the return codes
|
||||||
|
*/
|
||||||
|
#define ERR_OK 0
|
||||||
|
#define ERR_TIMOUT 1
|
||||||
|
#define ERR_NOT_ERASED 2
|
||||||
|
#define ERR_PROTECTED 4
|
||||||
|
#define ERR_INVAL 8
|
||||||
|
#define ERR_OPS_NOTSUPPORT 9
|
||||||
|
#define ERR_ALIGN 16
|
||||||
|
#define ERR_UNKNOWN_FLASH_VENDOR 32
|
||||||
|
#define ERR_UNKNOWN_FLASH_TYPE 64
|
||||||
|
#define ERR_PROG_ERROR 128
|
||||||
|
#define ERR_ERASE_ERROR 256
|
||||||
|
#define ERR_WRITE_VERIFY 512
|
||||||
|
#define ERR_NOT_SUPPORT 1024 /* operation not supported */
|
||||||
|
|
||||||
|
#endif /* __ERROR_H__ */
|
56
flash-tool/device_stage2/include/hand.h
Normal file
56
flash-tool/device_stage2/include/hand.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#ifndef __HAND_H__
|
||||||
|
#define __HAND_H__
|
||||||
|
|
||||||
|
struct fw_args_t {
|
||||||
|
/* CPU ID */
|
||||||
|
unsigned int cpu_id;
|
||||||
|
|
||||||
|
/* PLL args */
|
||||||
|
unsigned char ext_clk;
|
||||||
|
unsigned char cpu_speed;
|
||||||
|
unsigned char phm_div;
|
||||||
|
unsigned char use_uart;
|
||||||
|
unsigned int boudrate;
|
||||||
|
|
||||||
|
/* SDRAM args */
|
||||||
|
unsigned char bus_width;
|
||||||
|
unsigned char bank_num;
|
||||||
|
unsigned char row_addr;
|
||||||
|
unsigned char col_addr;
|
||||||
|
unsigned char is_mobile;
|
||||||
|
unsigned char is_busshare;
|
||||||
|
|
||||||
|
/* debug args */
|
||||||
|
unsigned char debug_ops;
|
||||||
|
unsigned char pin_num;
|
||||||
|
unsigned int start;
|
||||||
|
unsigned int size;
|
||||||
|
|
||||||
|
/* for align */
|
||||||
|
/* unsigned char align1; */
|
||||||
|
/* unsigned char align2; */
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct hand_t {
|
||||||
|
|
||||||
|
/* nand flash info */
|
||||||
|
int pt; /* cpu type */
|
||||||
|
unsigned int nand_bw; /* bus width */
|
||||||
|
unsigned int nand_rc; /* row cycle */
|
||||||
|
unsigned int nand_ps; /* page size */
|
||||||
|
unsigned int nand_ppb; /* page number per block */
|
||||||
|
unsigned int nand_force_erase;
|
||||||
|
unsigned int nand_pn; /* page number in total */
|
||||||
|
unsigned int nand_os; /* oob size */
|
||||||
|
unsigned int nand_eccpos;
|
||||||
|
unsigned int nand_bbpage;
|
||||||
|
unsigned int nand_bbpos;
|
||||||
|
unsigned int nand_plane;
|
||||||
|
unsigned int nand_bchbit;
|
||||||
|
unsigned int nand_wppin;
|
||||||
|
unsigned int nand_bpc; /* block number per chip */
|
||||||
|
|
||||||
|
struct fw_args_t fw_args;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#endif /* __HAND_H__ */
|
4520
flash-tool/device_stage2/include/jz4740.h
Normal file
4520
flash-tool/device_stage2/include/jz4740.h
Normal file
File diff suppressed because it is too large
Load Diff
5302
flash-tool/device_stage2/include/jz4750.h
Normal file
5302
flash-tool/device_stage2/include/jz4750.h
Normal file
File diff suppressed because it is too large
Load Diff
820
flash-tool/device_stage2/include/mips.h
Normal file
820
flash-tool/device_stage2/include/mips.h
Normal file
@ -0,0 +1,820 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
* *
|
||||||
|
* PROJECT : MIPS port for uC/OS-II *
|
||||||
|
* *
|
||||||
|
* MODULE : MIPS.h *
|
||||||
|
* *
|
||||||
|
* AUTHOR : Michael Anburaj *
|
||||||
|
* URL : http://geocities.com/michaelanburaj/ *
|
||||||
|
* EMAIL: michaelanburaj@hotmail.com *
|
||||||
|
* *
|
||||||
|
* PROCESSOR : MIPS 4Kc (32 bit RISC) - ATLAS board *
|
||||||
|
* *
|
||||||
|
* TOOL-CHAIN : SDE & Cygnus *
|
||||||
|
* *
|
||||||
|
* DESCRIPTION : *
|
||||||
|
* MIPS processor definitions. *
|
||||||
|
* The basic CPU definitions are found in the file archdefs.h, which *
|
||||||
|
* is included by mips.h. *
|
||||||
|
* *
|
||||||
|
* mips.h implements aliases for some of the definitions in archdefs.h *
|
||||||
|
* and adds various definitions. *
|
||||||
|
* *
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __MIPS_H__
|
||||||
|
#define __MIPS_H__
|
||||||
|
|
||||||
|
#include "archdefs.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* ********************************************************************* */
|
||||||
|
/* Module configuration */
|
||||||
|
|
||||||
|
|
||||||
|
/* ********************************************************************* */
|
||||||
|
/* Interface macro & data definition */
|
||||||
|
|
||||||
|
#ifndef MSK
|
||||||
|
#define MSK(n) ((1 << (n)) - 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CPU registers */
|
||||||
|
#define SYS_CPUREG_ZERO 0
|
||||||
|
#define SYS_CPUREG_AT 1
|
||||||
|
#define SYS_CPUREG_V0 2
|
||||||
|
#define SYS_CPUREG_V1 3
|
||||||
|
#define SYS_CPUREG_A0 4
|
||||||
|
#define SYS_CPUREG_A1 5
|
||||||
|
#define SYS_CPUREG_A2 6
|
||||||
|
#define SYS_CPUREG_A3 7
|
||||||
|
#define SYS_CPUREG_T0 8
|
||||||
|
#define SYS_CPUREG_T1 9
|
||||||
|
#define SYS_CPUREG_T2 10
|
||||||
|
#define SYS_CPUREG_T3 11
|
||||||
|
#define SYS_CPUREG_T4 12
|
||||||
|
#define SYS_CPUREG_T5 13
|
||||||
|
#define SYS_CPUREG_T6 14
|
||||||
|
#define SYS_CPUREG_T7 15
|
||||||
|
#define SYS_CPUREG_S0 16
|
||||||
|
#define SYS_CPUREG_S1 17
|
||||||
|
#define SYS_CPUREG_S2 18
|
||||||
|
#define SYS_CPUREG_S3 19
|
||||||
|
#define SYS_CPUREG_S4 20
|
||||||
|
#define SYS_CPUREG_S5 21
|
||||||
|
#define SYS_CPUREG_S6 22
|
||||||
|
#define SYS_CPUREG_S7 23
|
||||||
|
#define SYS_CPUREG_T8 24
|
||||||
|
#define SYS_CPUREG_T9 25
|
||||||
|
#define SYS_CPUREG_K0 26
|
||||||
|
#define SYS_CPUREG_K1 27
|
||||||
|
#define SYS_CPUREG_GP 28
|
||||||
|
#define SYS_CPUREG_SP 29
|
||||||
|
#define SYS_CPUREG_S8 30
|
||||||
|
#define SYS_CPUREG_FP SYS_CPUREG_S8
|
||||||
|
#define SYS_CPUREG_RA 31
|
||||||
|
|
||||||
|
|
||||||
|
/* CPU register fp ($30) has an alias s8 */
|
||||||
|
#define s8 fp
|
||||||
|
|
||||||
|
|
||||||
|
/* Aliases for System Control Coprocessor (CP0) registers */
|
||||||
|
#define C0_INDEX C0_Index
|
||||||
|
#define C0_RANDOM C0_Random
|
||||||
|
#define C0_ENTRYLO0 C0_EntryLo0
|
||||||
|
#define C0_ENTRYLO1 C0_EntryLo1
|
||||||
|
#define C0_CONTEXT C0_Context
|
||||||
|
#define C0_PAGEMASK C0_PageMask
|
||||||
|
#define C0_WIRED C0_Wired
|
||||||
|
#define C0_BADVADDR C0_BadVAddr
|
||||||
|
#define C0_COUNT C0_Count
|
||||||
|
#define C0_ENTRYHI C0_EntryHi
|
||||||
|
#define C0_COMPARE C0_Compare
|
||||||
|
#define C0_STATUS C0_Status
|
||||||
|
#define C0_CAUSE C0_Cause
|
||||||
|
|
||||||
|
#ifdef C0_PRID /* ArchDefs has an obsolete def. of C0_PRID */
|
||||||
|
#undef C0_PRID
|
||||||
|
#endif
|
||||||
|
#define C0_PRID C0_PRId
|
||||||
|
|
||||||
|
#define C0_CONFIG C0_Config
|
||||||
|
#define C0_CONFIG1 C0_Config1
|
||||||
|
#define C0_LLADDR C0_LLAddr
|
||||||
|
#define C0_WATCHLO C0_WatchLo
|
||||||
|
#define C0_WATCHHI C0_WatchHi
|
||||||
|
#define C0_DEBUG C0_Debug
|
||||||
|
#define C0_PERFCNT C0_PerfCnt
|
||||||
|
#define C0_ERRCTL C0_ErrCtl
|
||||||
|
#define C0_CACHEERR C0_CacheErr
|
||||||
|
#define C0_TAGLO C0_TagLo
|
||||||
|
#define C0_DATALO C0_DataLo
|
||||||
|
#define C0_TAGHI C0_TagHi
|
||||||
|
#define C0_DATAHI C0_DataHi
|
||||||
|
#define C0_ERROREPC C0_ErrorEPC
|
||||||
|
#if 0
|
||||||
|
#define C0_DESAVE C0_DESAVE
|
||||||
|
#define C0_EPC C0_EPC
|
||||||
|
#define C0_DEPC C0_DEPC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* System Control Coprocessor (CP0) registers select fields */
|
||||||
|
#define C0_INDEX_SEL 0 /* TLB Index */
|
||||||
|
#define C0_RANDOM_SEL 0 /* TLB Random */
|
||||||
|
#define C0_TLBLO0_SEL 0 /* TLB EntryLo0 */
|
||||||
|
#define C0_TLBLO1_SEL 0 /* TLB EntryLo1 */
|
||||||
|
#define C0_CONTEXT_SEL 0 /* Context */
|
||||||
|
#define C0_PAGEMASK_SEL 0 /* TLB PageMask */
|
||||||
|
#define C0_WIRED_SEL 0 /* TLB Wired */
|
||||||
|
#define C0_BADVADDR_SEL 0 /* Bad Virtual Address */
|
||||||
|
#define C0_COUNT_SEL 0 /* Count */
|
||||||
|
#define C0_ENTRYHI_SEL 0 /* TLB EntryHi */
|
||||||
|
#define C0_COMPARE_SEL 0 /* Compare */
|
||||||
|
#define C0_STATUS_SEL 0 /* Processor Status */
|
||||||
|
#define C0_CAUSE_SEL 0 /* Exception Cause */
|
||||||
|
#define C0_EPC_SEL 0 /* Exception PC */
|
||||||
|
#define C0_PRID_SEL 0 /* Processor Revision Indentifier */
|
||||||
|
#define C0_CONFIG_SEL 0 /* Config */
|
||||||
|
#define C0_CONFIG1_SEL 1 /* Config1 */
|
||||||
|
#define C0_LLADDR_SEL 0 /* LLAddr */
|
||||||
|
#define C0_WATCHLO_SEL 0 /* WatchpointLo */
|
||||||
|
#define C0_WATCHHI_SEL 0 /* WatchpointHi */
|
||||||
|
#define C0_DEBUG_SEL 0 /* EJTAG Debug Register */
|
||||||
|
#define C0_DEPC_SEL 0 /* Program counter at last EJTAG debug exception */
|
||||||
|
#define C0_PERFCNT_SEL 0 /* Performance counter interface */
|
||||||
|
#define C0_ERRCTL_SEL 0 /* ERRCTL */
|
||||||
|
#define C0_CACHEERR_SEL 0 /* CacheErr */
|
||||||
|
#define C0_TAGLO_SEL 0 /* TagLo */
|
||||||
|
#define C0_DATALO_SEL 1 /* DataLo */
|
||||||
|
#define C0_DTAGLO_SEL 2 /* DTagLo */
|
||||||
|
#define C0_TAGHI_SEL 0 /* TagHi */
|
||||||
|
#define C0_DATAHI_SEL 1 /* DataHi */
|
||||||
|
#define C0_DTAGHI_SEL 2 /* DTagHi */
|
||||||
|
#define C0_ERROREPC_SEL 0 /* ErrorEPC */
|
||||||
|
#define C0_DESAVE_SEL 0 /* EJTAG dbg exc. save register */
|
||||||
|
|
||||||
|
|
||||||
|
/* C0_CONFIG register encoding */
|
||||||
|
|
||||||
|
#define C0_CONFIG_M_SHF S_ConfigMore
|
||||||
|
#define C0_CONFIG_M_MSK M_ConfigMore
|
||||||
|
#define C0_CONFIG_M_BIT C0_CONFIG_M_MSK
|
||||||
|
|
||||||
|
#define C0_CONFIG_BE_SHF S_ConfigBE
|
||||||
|
#define C0_CONFIG_BE_MSK M_ConfigBE
|
||||||
|
#define C0_CONFIG_BE_BIT C0_CONFIG_BE_MSK
|
||||||
|
|
||||||
|
#define C0_CONFIG_AT_SHF S_ConfigAT
|
||||||
|
#define C0_CONFIG_AT_MSK M_ConfigAT
|
||||||
|
#define C0_CONFIG_AT_MIPS32 K_ConfigAT_MIPS32
|
||||||
|
#define C0_CONFIG_AT_MIPS64_32ADDR K_ConfigAT_MIPS64S
|
||||||
|
#define C0_CONFIG_AT_MIPS64 K_ConfigAT_MIPS64
|
||||||
|
|
||||||
|
#define C0_CONFIG_AR_SHF S_ConfigAR
|
||||||
|
#define C0_CONFIG_AR_MSK M_ConfigAR
|
||||||
|
|
||||||
|
#define C0_CONFIG_MT_SHF S_ConfigMT
|
||||||
|
#define C0_CONFIG_MT_MSK M_ConfigMT
|
||||||
|
#define C0_CONFIG_MT_NONE K_ConfigMT_NoMMU
|
||||||
|
#define C0_CONFIG_MT_TLB K_ConfigMT_TLBMMU
|
||||||
|
#define C0_CONFIG_MT_BAT K_ConfigMT_BATMMU
|
||||||
|
#define C0_CONFIG_MT_NON_STD K_ConfigMT_FMMMU
|
||||||
|
|
||||||
|
#define C0_CONFIG_K0_SHF S_ConfigK0
|
||||||
|
#define C0_CONFIG_K0_MSK M_ConfigK0
|
||||||
|
#define C0_CONFIG_K0_WTHRU_NOALLOC K_CacheAttrCWTnWA
|
||||||
|
#define C0_CONFIG_K0_WTHRU_ALLOC K_CacheAttrCWTWA
|
||||||
|
#define C0_CONFIG_K0_UNCACHED K_CacheAttrU
|
||||||
|
#define C0_CONFIG_K0_NONCOHERENT K_CacheAttrCN
|
||||||
|
#define C0_CONFIG_K0_COHERENTXCL K_CacheAttrCCE
|
||||||
|
#define C0_CONFIG_K0_COHERENTXCLW K_CacheAttrCCS
|
||||||
|
#define C0_CONFIG_K0_COHERENTUPD K_CacheAttrCCU
|
||||||
|
#define C0_CONFIG_K0_UNCACHED_ACCEL K_CacheAttrUA
|
||||||
|
|
||||||
|
|
||||||
|
/* WC field.
|
||||||
|
*
|
||||||
|
* This feature is present specifically to support configuration
|
||||||
|
* testing of the core in a lead vehicle, and is not supported
|
||||||
|
* in any other environment. Attempting to use this feature
|
||||||
|
* outside of the scope of a lead vehicle is a violation of the
|
||||||
|
* MIPS Architecture, and may cause unpredictable operation of
|
||||||
|
* the processor.
|
||||||
|
*/
|
||||||
|
#define C0_CONFIG_WC_SHF 19
|
||||||
|
#define C0_CONFIG_WC_MSK (MSK(1) << C0_CONFIG_WC_SHF)
|
||||||
|
#define C0_CONFIG_WC_BIT C0_CONFIG_WC_MSK
|
||||||
|
|
||||||
|
|
||||||
|
/* C0_CONFIG1 register encoding */
|
||||||
|
|
||||||
|
#define C0_CONFIG1_MMUSIZE_SHF S_Config1MMUSize
|
||||||
|
#define C0_CONFIG1_MMUSIZE_MSK M_Config1MMUSize
|
||||||
|
|
||||||
|
#define C0_CONFIG1_IS_SHF S_Config1IS
|
||||||
|
#define C0_CONFIG1_IS_MSK M_Config1IS
|
||||||
|
|
||||||
|
#define C0_CONFIG1_IL_SHF S_Config1IL
|
||||||
|
#define C0_CONFIG1_IL_MSK M_Config1IL
|
||||||
|
|
||||||
|
#define C0_CONFIG1_IA_SHF S_Config1IA
|
||||||
|
#define C0_CONFIG1_IA_MSK M_Config1IA
|
||||||
|
|
||||||
|
#define C0_CONFIG1_DS_SHF S_Config1DS
|
||||||
|
#define C0_CONFIG1_DS_MSK M_Config1DS
|
||||||
|
|
||||||
|
#define C0_CONFIG1_DL_SHF S_Config1DL
|
||||||
|
#define C0_CONFIG1_DL_MSK M_Config1DL
|
||||||
|
|
||||||
|
#define C0_CONFIG1_DA_SHF S_Config1DA
|
||||||
|
#define C0_CONFIG1_DA_MSK M_Config1DA
|
||||||
|
|
||||||
|
#define C0_CONFIG1_WR_SHF S_Config1WR
|
||||||
|
#define C0_CONFIG1_WR_MSK M_Config1WR
|
||||||
|
#define C0_CONFIG1_WR_BIT C0_CONFIG1_WR_MSK
|
||||||
|
|
||||||
|
#define C0_CONFIG1_CA_SHF S_Config1CA
|
||||||
|
#define C0_CONFIG1_CA_MSK M_Config1CA
|
||||||
|
#define C0_CONFIG1_CA_BIT C0_CONFIG1_CA_MSK
|
||||||
|
|
||||||
|
#define C0_CONFIG1_EP_SHF S_Config1EP
|
||||||
|
#define C0_CONFIG1_EP_MSK M_Config1EP
|
||||||
|
#define C0_CONFIG1_EP_BIT C0_CONFIG1_EP_MSK
|
||||||
|
|
||||||
|
#define C0_CONFIG1_FP_SHF S_Config1FP
|
||||||
|
#define C0_CONFIG1_FP_MSK M_Config1FP
|
||||||
|
#define C0_CONFIG1_FP_BIT C0_CONFIG1_FP_MSK
|
||||||
|
|
||||||
|
|
||||||
|
/* C0_STATUS register encoding */
|
||||||
|
|
||||||
|
#define C0_STATUS_CU3_SHF S_StatusCU3
|
||||||
|
#define C0_STATUS_CU3_MSK M_StatusCU3
|
||||||
|
#define C0_STATUS_CU3_BIT C0_STATUS_CU3_MSK
|
||||||
|
|
||||||
|
#define C0_STATUS_CU2_SHF S_StatusCU2
|
||||||
|
#define C0_STATUS_CU2_MSK M_StatusCU2
|
||||||
|
#define C0_STATUS_CU2_BIT C0_STATUS_CU2_MSK
|
||||||
|
|
||||||
|
#define C0_STATUS_CU1_SHF S_StatusCU1
|
||||||
|
#define C0_STATUS_CU1_MSK M_StatusCU1
|
||||||
|
#define C0_STATUS_CU1_BIT C0_STATUS_CU1_MSK
|
||||||
|
|
||||||
|
#define C0_STATUS_CU0_SHF S_StatusCU1
|
||||||
|
#define C0_STATUS_CU0_MSK M_StatusCU1
|
||||||
|
#define C0_STATUS_CU0_BIT C0_STATUS_CU0_MSK
|
||||||
|
|
||||||
|
#define C0_STATUS_RP_SHF S_StatusRP
|
||||||
|
#define C0_STATUS_RP_MSK M_StatusRP
|
||||||
|
#define C0_STATUS_RP_BIT C0_STATUS_RP_MSK
|
||||||
|
|
||||||
|
#define C0_STATUS_FR_SHF S_StatusFR
|
||||||
|
#define C0_STATUS_FR_MSK M_StatusFR
|
||||||
|
#define C0_STATUS_FR_BIT C0_STATUS_FR_MSK
|
||||||
|
|
||||||
|
#define C0_STATUS_RE_SHF S_StatusRE
|
||||||
|
#define C0_STATUS_RE_MSK M_StatusRE
|
||||||
|
#define C0_STATUS_RE_BIT C0_STATUS_RE_MSK
|
||||||
|
|
||||||
|
#define C0_STATUS_BEV_SHF S_StatusBEV
|
||||||
|
#define C0_STATUS_BEV_MSK M_StatusBEV
|
||||||
|
#define C0_STATUS_BEV_BIT C0_STATUS_BEV_MSK
|
||||||
|
|
||||||
|
#define C0_STATUS_TS_SHF S_StatusTS
|
||||||
|
#define C0_STATUS_TS_MSK M_StatusTS
|
||||||
|
#define C0_STATUS_TS_BIT C0_STATUS_TS_MSK
|
||||||
|
|
||||||
|
#define C0_STATUS_SR_SHF S_StatusSR
|
||||||
|
#define C0_STATUS_SR_MSK M_StatusSR
|
||||||
|
#define C0_STATUS_SR_BIT C0_STATUS_SR_MSK
|
||||||
|
|
||||||
|
#define C0_STATUS_NMI_SHF S_StatusNMI
|
||||||
|
#define C0_STATUS_NMI_MSK M_StatusNMI
|
||||||
|
#define C0_STATUS_NMI_BIT C0_STATUS_NMI_MSK
|
||||||
|
|
||||||
|
#define C0_STATUS_IM_SHF S_StatusIM
|
||||||
|
#define C0_STATUS_IM_MSK M_StatusIM
|
||||||
|
/* Note that the the definitions below indicate the interrupt number
|
||||||
|
* rather than the mask.
|
||||||
|
* (0..1 for SW interrupts and 2...7 for HW interrupts)
|
||||||
|
*/
|
||||||
|
#define C0_STATUS_IM_SW0 (S_StatusIM0 - S_StatusIM)
|
||||||
|
#define C0_STATUS_IM_SW1 (S_StatusIM1 - S_StatusIM)
|
||||||
|
#define C0_STATUS_IM_HW0 (S_StatusIM2 - S_StatusIM)
|
||||||
|
#define C0_STATUS_IM_HW1 (S_StatusIM3 - S_StatusIM)
|
||||||
|
#define C0_STATUS_IM_HW2 (S_StatusIM4 - S_StatusIM)
|
||||||
|
#define C0_STATUS_IM_HW3 (S_StatusIM5 - S_StatusIM)
|
||||||
|
#define C0_STATUS_IM_HW4 (S_StatusIM6 - S_StatusIM)
|
||||||
|
#define C0_STATUS_IM_HW5 (S_StatusIM7 - S_StatusIM)
|
||||||
|
|
||||||
|
/* Max interrupt code */
|
||||||
|
#define C0_STATUS_IM_MAX C0_STATUS_IM_HW5
|
||||||
|
|
||||||
|
#define C0_STATUS_KSU_SHF S_StatusKSU
|
||||||
|
#define C0_STATUS_KSU_MSK M_StatusKSU
|
||||||
|
|
||||||
|
#define C0_STATUS_UM_SHF S_StatusUM
|
||||||
|
#define C0_STATUS_UM_MSK M_StatusUM
|
||||||
|
#define C0_STATUS_UM_BIT C0_STATUS_UM_MSK
|
||||||
|
|
||||||
|
#define C0_STATUS_ERL_SHF S_StatusERL
|
||||||
|
#define C0_STATUS_ERL_MSK M_StatusERL
|
||||||
|
#define C0_STATUS_ERL_BIT C0_STATUS_ERL_MSK
|
||||||
|
|
||||||
|
#define C0_STATUS_EXL_SHF S_StatusEXL
|
||||||
|
#define C0_STATUS_EXL_MSK M_StatusEXL
|
||||||
|
#define C0_STATUS_EXL_BIT C0_STATUS_EXL_MSK
|
||||||
|
|
||||||
|
#define C0_STATUS_IE_SHF S_StatusIE
|
||||||
|
#define C0_STATUS_IE_MSK M_StatusIE
|
||||||
|
#define C0_STATUS_IE_BIT C0_STATUS_IE_MSK
|
||||||
|
|
||||||
|
|
||||||
|
/* C0_PRID register encoding */
|
||||||
|
|
||||||
|
#define C0_PRID_OPT_SHF S_PRIdCoOpt
|
||||||
|
#define C0_PRID_OPT_MSK M_PRIdCoOpt
|
||||||
|
|
||||||
|
#define C0_PRID_COMP_SHF S_PRIdCoID
|
||||||
|
#define C0_PRID_COMP_MSK M_PRIdCoID
|
||||||
|
#define C0_PRID_COMP_MIPS K_PRIdCoID_MIPS
|
||||||
|
#define C0_PRID_COMP_NOT_MIPS32_64 0
|
||||||
|
|
||||||
|
#define C0_PRID_PRID_SHF S_PRIdImp
|
||||||
|
#define C0_PRID_PRID_MSK M_PRIdImp
|
||||||
|
|
||||||
|
/* Jade */
|
||||||
|
#define C0_PRID_PRID_4Kc K_PRIdImp_Jade
|
||||||
|
#define C0_PRID_PRID_4Kmp K_PRIdImp_JadeLite /* 4Km/4Kp */
|
||||||
|
/* Emerald */
|
||||||
|
#define C0_PRID_PRID_4KEc K_PRIdImp_4KEc
|
||||||
|
#define C0_PRID_PRID_4KEmp K_PRIdImp_4KEmp
|
||||||
|
/* Coral */
|
||||||
|
#define C0_PRID_PRID_4KSc K_PRIdImp_4KSc
|
||||||
|
/* Opal */
|
||||||
|
#define C0_PRID_PRID_5K K_PRIdImp_Opal
|
||||||
|
/* Ruby */
|
||||||
|
#define C0_PRID_PRID_20Kc K_PRIdImp_Ruby
|
||||||
|
/* Other CPUs */
|
||||||
|
#define C0_PRID_PRID_R4000 K_PRIdImp_R4000
|
||||||
|
#define C0_PRID_PRID_RM52XX K_PRIdImp_R5200
|
||||||
|
#define C0_PRID_PRID_RM70XX 0x27
|
||||||
|
|
||||||
|
#define C0_PRID_REV_SHF S_PRIdRev
|
||||||
|
#define C0_PRID_REV_MSK M_PRIdRev
|
||||||
|
|
||||||
|
|
||||||
|
#define MIPS_4Kc ( (C0_PRID_COMP_MIPS << \
|
||||||
|
C0_PRID_COMP_SHF) | \
|
||||||
|
(C0_PRID_PRID_4Kc << \
|
||||||
|
C0_PRID_PRID_SHF) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define MIPS_4Kmp ( (C0_PRID_COMP_MIPS << \
|
||||||
|
C0_PRID_COMP_SHF) | \
|
||||||
|
(C0_PRID_PRID_4Kmp << \
|
||||||
|
C0_PRID_PRID_SHF) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define MIPS_4KEc ( (C0_PRID_COMP_MIPS << \
|
||||||
|
C0_PRID_COMP_SHF) | \
|
||||||
|
(C0_PRID_PRID_4KEc << \
|
||||||
|
C0_PRID_PRID_SHF) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define MIPS_4KEmp ( (C0_PRID_COMP_MIPS << \
|
||||||
|
C0_PRID_COMP_SHF) | \
|
||||||
|
(C0_PRID_PRID_4KEmp << \
|
||||||
|
C0_PRID_PRID_SHF) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define MIPS_4KSc ( (C0_PRID_COMP_MIPS << \
|
||||||
|
C0_PRID_COMP_SHF) | \
|
||||||
|
(C0_PRID_PRID_4KSc << \
|
||||||
|
C0_PRID_PRID_SHF) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define MIPS_5K ( (C0_PRID_COMP_MIPS << \
|
||||||
|
C0_PRID_COMP_SHF) | \
|
||||||
|
(C0_PRID_PRID_5K << \
|
||||||
|
C0_PRID_PRID_SHF) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define MIPS_20Kc ( (C0_PRID_COMP_MIPS << \
|
||||||
|
C0_PRID_COMP_SHF) | \
|
||||||
|
(C0_PRID_PRID_20Kc << \
|
||||||
|
C0_PRID_PRID_SHF) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define QED_RM52XX ( (C0_PRID_COMP_NOT_MIPS32_64 << \
|
||||||
|
C0_PRID_COMP_SHF) | \
|
||||||
|
(C0_PRID_PRID_RM52XX << \
|
||||||
|
C0_PRID_PRID_SHF) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define QED_RM70XX ( (C0_PRID_COMP_NOT_MIPS32_64 << \
|
||||||
|
C0_PRID_COMP_SHF) | \
|
||||||
|
(C0_PRID_PRID_RM70XX << \
|
||||||
|
C0_PRID_PRID_SHF) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/* C0_ENTRYHI register encoding */
|
||||||
|
|
||||||
|
#define C0_ENTRYHI_VPN2_SHF S_EntryHiVPN2
|
||||||
|
#define C0_ENTRYHI_VPN2_MSK M_EntryHiVPN2
|
||||||
|
|
||||||
|
#define C0_ENTRYHI_ASID_SHF S_EntryHiASID
|
||||||
|
#define C0_ENTRYHI_ASID_MSK M_EntryHiASID
|
||||||
|
|
||||||
|
|
||||||
|
/* C0_CAUSE register encoding */
|
||||||
|
|
||||||
|
#define C0_CAUSE_BD_SHF S_CauseBD
|
||||||
|
#define C0_CAUSE_BD_MSK M_CauseBD
|
||||||
|
#define C0_CAUSE_BD_BIT C0_CAUSE_BD_MSK
|
||||||
|
|
||||||
|
#define C0_CAUSE_CE_SHF S_CauseCE
|
||||||
|
#define C0_CAUSE_CE_MSK M_CauseCE
|
||||||
|
|
||||||
|
#define C0_CAUSE_IV_SHF S_CauseIV
|
||||||
|
#define C0_CAUSE_IV_MSK M_CauseIV
|
||||||
|
#define C0_CAUSE_IV_BIT C0_CAUSE_IV_MSK
|
||||||
|
|
||||||
|
#define C0_CAUSE_WP_SHF S_CauseWP
|
||||||
|
#define C0_CAUSE_WP_MSK M_CauseWP
|
||||||
|
#define C0_CAUSE_WP_BIT C0_CAUSE_WP_MSK
|
||||||
|
|
||||||
|
#define C0_CAUSE_IP_SHF S_CauseIP
|
||||||
|
#define C0_CAUSE_IP_MSK M_CauseIP
|
||||||
|
|
||||||
|
#define C0_CAUSE_CODE_SHF S_CauseExcCode
|
||||||
|
#define C0_CAUSE_CODE_MSK M_CauseExcCode
|
||||||
|
|
||||||
|
#define C0_CAUSE_CODE_INT EX_INT
|
||||||
|
#define C0_CAUSE_CODE_MOD EX_MOD
|
||||||
|
#define C0_CAUSE_CODE_TLBL EX_TLBL
|
||||||
|
#define C0_CAUSE_CODE_TLBS EX_TLBS
|
||||||
|
#define C0_CAUSE_CODE_ADEL EX_ADEL
|
||||||
|
#define C0_CAUSE_CODE_ADES EX_ADES
|
||||||
|
#define C0_CAUSE_CODE_IBE EX_IBE
|
||||||
|
#define C0_CAUSE_CODE_DBE EX_DBE
|
||||||
|
#define C0_CAUSE_CODE_SYS EX_SYS
|
||||||
|
#define C0_CAUSE_CODE_BP EX_BP
|
||||||
|
#define C0_CAUSE_CODE_RI EX_RI
|
||||||
|
#define C0_CAUSE_CODE_CPU EX_CPU
|
||||||
|
#define C0_CAUSE_CODE_OV EX_OV
|
||||||
|
#define C0_CAUSE_CODE_TR EV_TR
|
||||||
|
#define C0_CAUSE_CODE_FPE EX_FPE
|
||||||
|
#define C0_CAUSE_CODE_WATCH EX_WATCH
|
||||||
|
#define C0_CAUSE_CODE_MCHECK EX_MCHECK
|
||||||
|
|
||||||
|
/* Max cause code */
|
||||||
|
#define C0_CAUSE_CODE_MAX EX_MCHECK
|
||||||
|
|
||||||
|
|
||||||
|
/* C0_PAGEMASK register encoding */
|
||||||
|
#define C0_PAGEMASK_MASK_SHF S_PageMaskMask
|
||||||
|
#define C0_PAGEMASK_MASK_MSK M_PageMaskMask
|
||||||
|
#define C0_PAGEMASK_MASK_4K K_PageMask4K
|
||||||
|
#define C0_PAGEMASK_MASK_16K K_PageMask16K
|
||||||
|
#define C0_PAGEMASK_MASK_64K K_PageMask64K
|
||||||
|
#define C0_PAGEMASK_MASK_256K K_PageMask256K
|
||||||
|
#define C0_PAGEMASK_MASK_1M K_PageMask1M
|
||||||
|
#define C0_PAGEMASK_MASK_4M K_PageMask4M
|
||||||
|
#define C0_PAGEMASK_MASK_16M K_PageMask16M
|
||||||
|
|
||||||
|
|
||||||
|
/* C0_ENTRYLO0 register encoding (equiv. to C0_ENTRYLO1) */
|
||||||
|
#define C0_ENTRYLO0_PFN_SHF S_EntryLoPFN
|
||||||
|
#define C0_ENTRYLO0_PFN_MSK M_EntryLoPFN
|
||||||
|
|
||||||
|
#define C0_ENTRYLO0_C_SHF S_EntryLoC
|
||||||
|
#define C0_ENTRYLO0_C_MSK M_EntryLoC
|
||||||
|
|
||||||
|
#define C0_ENTRYLO0_D_SHF S_EntryLoD
|
||||||
|
#define C0_ENTRYLO0_D_MSK M_EntryLoD
|
||||||
|
|
||||||
|
#define C0_ENTRYLO0_V_SHF S_EntryLoV
|
||||||
|
#define C0_ENTRYLO0_V_MSK M_EntryLoV
|
||||||
|
|
||||||
|
#define C0_ENTRYLO0_G_SHF S_EntryLoG
|
||||||
|
#define C0_ENTRYLO0_G_MSK M_EntryLoG
|
||||||
|
|
||||||
|
|
||||||
|
/* FPU (CP1) FIR register encoding */
|
||||||
|
#define C1_FIR_3D_SHF S_FIRConfig3D
|
||||||
|
#define C1_FIR_3D_MSK M_FIRConfig3D
|
||||||
|
|
||||||
|
#define C1_FIR_PS_SHF S_FIRConfigPS
|
||||||
|
#define C1_FIR_PS_MSK M_FIRConfigPS
|
||||||
|
|
||||||
|
#define C1_FIR_D_SHF S_FIRConfigD
|
||||||
|
#define C1_FIR_D_MSK M_FIRConfigD
|
||||||
|
|
||||||
|
#define C1_FIR_S_SHF S_FIRConfigS
|
||||||
|
#define C1_FIR_S_MSK M_FIRConfigS
|
||||||
|
|
||||||
|
#define C1_FIR_PRID_SHF S_FIRImp
|
||||||
|
#define C1_FIR_PRID_MSK M_FIRImp
|
||||||
|
|
||||||
|
#define C1_FIR_REV_SHF S_FIRRev
|
||||||
|
#define C1_FIR_REV_MSK M_FIRRev
|
||||||
|
|
||||||
|
|
||||||
|
/* FPU (CP1) FCSR control/status register */
|
||||||
|
#define C1_FCSR_FCC_SHF S_FCSRFCC7_1
|
||||||
|
#define C1_FCSR_FCC_MSK M_FCSRFCC7_1
|
||||||
|
|
||||||
|
#define C1_FCSR_FS_SHF S_FCSRFS
|
||||||
|
#define C1_FCSR_FS_MSK M_FCSRFS
|
||||||
|
#define C1_FCSR_FS_BIT C1_FCSR_FS_MSK
|
||||||
|
|
||||||
|
#define C1_FCSR_CC_SHF S_FCSRCC
|
||||||
|
#define C1_FCSR_CC_MSK M_FCSRCC
|
||||||
|
|
||||||
|
#define C1_FCSR_IMPL_SHF S_FCSRImpl
|
||||||
|
#define C1_FCSR_IMPL_MSK M_FCSRImpl
|
||||||
|
|
||||||
|
#define C1_FCSR_EXC_SHF S_FCSRExc
|
||||||
|
#define C1_FCSR_EXC_MSK M_FCSRExc
|
||||||
|
|
||||||
|
#define C1_FCSR_ENA_SHF S_FCSREna
|
||||||
|
#define C1_FCSR_ENA_MSK M_FCSREna
|
||||||
|
|
||||||
|
#define C1_FCSR_FLG_SHF S_FCSRFlg
|
||||||
|
#define C1_FCSR_FLG_MSK M_FCSRFlg
|
||||||
|
|
||||||
|
#define C1_FCSR_RM_SHF S_FCSRRM
|
||||||
|
#define C1_FCSR_RM_MSK M_FCSRRM
|
||||||
|
#define C1_FCSR_RM_RN K_FCSRRM_RN
|
||||||
|
#define C1_FCSR_RM_RZ K_FCSRRM_RZ
|
||||||
|
#define C1_FCSR_RM_RP K_FCSRRM_RP
|
||||||
|
#define C1_FCSR_RM_RM K_FCSRRM_RM
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* cache operations */
|
||||||
|
|
||||||
|
#define CACHE_OP( code, type ) ( ((code) << 2) | (type) )
|
||||||
|
|
||||||
|
#define ICACHE_INDEX_INVALIDATE CACHE_OP(0x0, 0)
|
||||||
|
#define ICACHE_INDEX_LOAD_TAG CACHE_OP(0x1, 0)
|
||||||
|
#define ICACHE_INDEX_STORE_TAG CACHE_OP(0x2, 0)
|
||||||
|
#define DCACHE_INDEX_WRITEBACK_INVALIDATE CACHE_OP(0x0, 1)
|
||||||
|
#define DCACHE_INDEX_LOAD_TAG CACHE_OP(0x1, 1)
|
||||||
|
#define DCACHE_INDEX_STORE_TAG CACHE_OP(0x2, 1)
|
||||||
|
#define SCACHE_INDEX_STORE_TAG CACHE_OP(0x2, 3)
|
||||||
|
|
||||||
|
#define ICACHE_ADDR_HIT_INVALIDATE CACHE_OP(0x4, 0)
|
||||||
|
#define ICACHE_ADDR_FILL CACHE_OP(0x5, 0)
|
||||||
|
#define ICACHE_ADDR_FETCH_LOCK CACHE_OP(0x7, 0)
|
||||||
|
#define DCACHE_ADDR_HIT_INVALIDATE CACHE_OP(0x4, 1)
|
||||||
|
#define DCACHE_ADDR_HIT_WRITEBACK_INVALIDATE CACHE_OP(0x5, 1)
|
||||||
|
#define DCACHE_ADDR_HIT_WRITEBACK CACHE_OP(0x6, 1)
|
||||||
|
#define DCACHE_ADDR_FETCH_LOCK CACHE_OP(0x7, 1)
|
||||||
|
|
||||||
|
#define SCACHE_ADDR_HIT_WRITEBACK_INVALIDATE CACHE_OP(0x5, 3)
|
||||||
|
|
||||||
|
/* Workaround for bug in early revisions of MIPS 4K family of
|
||||||
|
* processors. Only relevant in early engineering samples of test
|
||||||
|
* chips (RTL revision <= 3.0).
|
||||||
|
*
|
||||||
|
* The bug is described in :
|
||||||
|
*
|
||||||
|
* MIPS32 4K(tm) Processor Core Family RTL Errata Sheet
|
||||||
|
* MIPS Document No: MD00003
|
||||||
|
*
|
||||||
|
* The bug is identified as : C16
|
||||||
|
*/
|
||||||
|
#ifndef SET_MIPS0
|
||||||
|
#define SET_MIPS0()
|
||||||
|
#define SET_PUSH()
|
||||||
|
#define SET_POP()
|
||||||
|
#endif
|
||||||
|
#define ICACHE_INVALIDATE_WORKAROUND(reg) \
|
||||||
|
SET_PUSH(); \
|
||||||
|
SET_MIPS0(); \
|
||||||
|
la reg, 999f; \
|
||||||
|
SET_POP(); \
|
||||||
|
cache ICACHE_ADDR_FILL, 0(reg); \
|
||||||
|
sync; \
|
||||||
|
nop; nop; nop; nop; \
|
||||||
|
999:
|
||||||
|
|
||||||
|
/* EMPTY_PIPELINE is used for the below cache invalidation operations.
|
||||||
|
* When $I is invalidated, there will still be operations in the
|
||||||
|
* pipeline. We make sure these are 'nop' operations.
|
||||||
|
*/
|
||||||
|
#define EMPTY_PIPELINE nop; nop; nop; nop
|
||||||
|
|
||||||
|
#define ICACHE_INDEX_INVALIDATE_OP(index,scratch) \
|
||||||
|
ICACHE_INVALIDATE_WORKAROUND(scratch); \
|
||||||
|
cache ICACHE_INDEX_INVALIDATE, 0(index); \
|
||||||
|
EMPTY_PIPELINE
|
||||||
|
|
||||||
|
#define ICACHE_ADDR_INVALIDATE_OP(addr,scratch) \
|
||||||
|
ICACHE_INVALIDATE_WORKAROUND(scratch); \
|
||||||
|
cache ICACHE_ADDR_HIT_INVALIDATE, 0(addr); \
|
||||||
|
EMPTY_PIPELINE
|
||||||
|
|
||||||
|
/* The sync used in the below macro is there in case we are installing
|
||||||
|
* a new instruction (flush $D, sync, invalidate $I sequence).
|
||||||
|
*/
|
||||||
|
#define SCACHE_ADDR_HIT_WB_INVALIDATE_OP(reg) \
|
||||||
|
cache SCACHE_ADDR_HIT_WRITEBACK_INVALIDATE, 0(reg); \
|
||||||
|
sync; \
|
||||||
|
EMPTY_PIPELINE
|
||||||
|
|
||||||
|
/* Config1 cache field decoding */
|
||||||
|
#define CACHE_CALC_SPW(s) ( 64 << (s) )
|
||||||
|
#define CACHE_CALC_LS(l) ( (l) ? 2 << (l) : 0 )
|
||||||
|
#define CACHE_CALC_BPW(l,s) ( CACHE_CALC_LS(l) * CACHE_CALC_SPW(s) )
|
||||||
|
#define CACHE_CALC_ASSOC(a) ( (a) + 1 )
|
||||||
|
|
||||||
|
|
||||||
|
/**** Move from/to Coprocessor operations ****/
|
||||||
|
|
||||||
|
/* We use ssnop instead of nop operations in order to handle
|
||||||
|
* superscalar CPUs.
|
||||||
|
* The "sll zero,zero,1" notation is compiler backwards compatible.
|
||||||
|
*/
|
||||||
|
#define SSNOP sll zero,zero,1
|
||||||
|
#define NOPS SSNOP; SSNOP; SSNOP; SSNOP
|
||||||
|
|
||||||
|
#define MFLO(dst) \
|
||||||
|
mflo dst;\
|
||||||
|
NOPS
|
||||||
|
|
||||||
|
/* Workaround for bug in early revisions of MIPS 4K family of
|
||||||
|
* processors.
|
||||||
|
*
|
||||||
|
* This concerns the nop instruction before mtc0 in the
|
||||||
|
* MTC0 macro below.
|
||||||
|
*
|
||||||
|
* The bug is described in :
|
||||||
|
*
|
||||||
|
* MIPS32 4K(tm) Processor Core Family RTL Errata Sheet
|
||||||
|
* MIPS Document No: MD00003
|
||||||
|
*
|
||||||
|
* The bug is identified as : C27
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MTC0(src, dst) \
|
||||||
|
nop; \
|
||||||
|
mtc0 src,dst;\
|
||||||
|
NOPS
|
||||||
|
|
||||||
|
#define DMTC0(src, dst) \
|
||||||
|
nop; \
|
||||||
|
dmtc0 src,dst;\
|
||||||
|
NOPS
|
||||||
|
|
||||||
|
#define MFC0(dst, src) \
|
||||||
|
mfc0 dst,src;\
|
||||||
|
NOPS
|
||||||
|
|
||||||
|
#define DMFC0(dst, src) \
|
||||||
|
dmfc0 dst,src;\
|
||||||
|
NOPS
|
||||||
|
|
||||||
|
#define MFC0_SEL_OPCODE(dst, src, sel)\
|
||||||
|
.##word (0x40000000 | ((dst)<<16) | ((src)<<11) | (sel));\
|
||||||
|
NOPS
|
||||||
|
|
||||||
|
#define MTC0_SEL_OPCODE(dst, src, sel)\
|
||||||
|
.##word (0x40800000 | ((dst)<<16) | ((src)<<11) | (sel));\
|
||||||
|
NOPS
|
||||||
|
|
||||||
|
#define LDC1(dst, src, offs)\
|
||||||
|
.##word (0xd4000000 | ((src)<<21) | ((dst)<<16) | (offs))
|
||||||
|
|
||||||
|
#define SDC1(src, dst, offs)\
|
||||||
|
.##word (0xf4000000 | ((dst)<<21) | ((src)<<16) | (offs))
|
||||||
|
|
||||||
|
|
||||||
|
/* Instruction opcode fields */
|
||||||
|
#define OPC_SPECIAL 0x0
|
||||||
|
#define OPC_REGIM 0x1
|
||||||
|
#define OPC_J 0x2
|
||||||
|
#define OPC_JAL 0x3
|
||||||
|
#define OPC_BEQ 0x4
|
||||||
|
#define OPC_BNE 0x5
|
||||||
|
#define OPC_BLEZ 0x6
|
||||||
|
#define OPC_BGTZ 0x7
|
||||||
|
#define OPC_COP1 0x11
|
||||||
|
#define OPC_JALX 0x1D
|
||||||
|
#define OPC_BEQL 0x14
|
||||||
|
#define OPC_BNEL 0x15
|
||||||
|
#define OPC_BLEZL 0x16
|
||||||
|
#define OPC_BGTZL 0x17
|
||||||
|
|
||||||
|
/* Instruction function fields */
|
||||||
|
#define FUNC_JR 0x8
|
||||||
|
#define FUNC_JALR 0x9
|
||||||
|
|
||||||
|
/* Instruction rt fields */
|
||||||
|
#define RT_BLTZ 0x0
|
||||||
|
#define RT_BGEZ 0x1
|
||||||
|
#define RT_BLTZL 0x2
|
||||||
|
#define RT_BGEZL 0x3
|
||||||
|
#define RT_BLTZAL 0x10
|
||||||
|
#define RT_BGEZAL 0x11
|
||||||
|
#define RT_BLTZALL 0x12
|
||||||
|
#define RT_BGEZALL 0x13
|
||||||
|
|
||||||
|
/* Instruction rs fields */
|
||||||
|
#define RS_BC1 0x08
|
||||||
|
|
||||||
|
/* Access macros for instruction fields */
|
||||||
|
#define MIPS_OPCODE( instr) ((instr) >> 26)
|
||||||
|
#define MIPS_FUNCTION(instr) ((instr) & MSK(6))
|
||||||
|
#define MIPS_RT(instr) (((instr) >> 16) & MSK(5))
|
||||||
|
#define MIPS_RS(instr) (((instr) >> 21) & MSK(5))
|
||||||
|
#define MIPS_OFFSET(instr) ((instr) & 0xFFFF)
|
||||||
|
#define MIPS_TARGET(instr) ((instr) & MSK(26))
|
||||||
|
|
||||||
|
/* Instructions */
|
||||||
|
#define OPCODE_DERET 0x4200001f
|
||||||
|
#define OPCODE_BREAK 0x0005000d
|
||||||
|
#define OPCODE_NOP 0
|
||||||
|
#define OPCODE_JUMP(addr) ( (OPC_J << 26) | (((addr) >> 2) & 0x3FFFFFF) )
|
||||||
|
|
||||||
|
#define DERET .##word OPCODE_DERET
|
||||||
|
|
||||||
|
/* MIPS16e opcodes and instruction field access macros */
|
||||||
|
|
||||||
|
#define MIPS16E_OPCODE(inst) (((inst) >> 11) & 0x1f)
|
||||||
|
#define MIPS16E_I8_FUNCTION(inst) (((inst) >> 8) & 0x7)
|
||||||
|
#define MIPS16E_X(inst) (((inst) >> 26) & 0x1)
|
||||||
|
#define MIPS16E_RR_FUNCTION(inst) (((inst) >> 0) & 0x1f)
|
||||||
|
#define MIPS16E_RY(inst) (((inst) >> 5) & 0x3)
|
||||||
|
#define MIPS16E_OPC_EXTEND 0x1e
|
||||||
|
#define MIPS16E_OPC_JAL_X 0x03
|
||||||
|
#define MIPS16E_OPC_B 0x02
|
||||||
|
#define MIPS16E_OPC_BEQZ 0x04
|
||||||
|
#define MIPS16E_OPC_BNEZ 0x05
|
||||||
|
#define MIPS16E_OPC_I8 0x0c
|
||||||
|
#define MIPS16E_I8_FUNC_BTEQZ 0x00
|
||||||
|
#define MIPS16E_I8_FUNC_BTNEZ 0x01
|
||||||
|
#define MIPS16E_X_JALX 0x01
|
||||||
|
#define MIPS16E_OPC_RR 0x1d
|
||||||
|
#define MIPS16E_RR_FUNC_JALRC 0x00
|
||||||
|
#define MIPS16E_RR_RY_JRRX 0x00
|
||||||
|
#define MIPS16E_RR_RY_JRRA 0x01
|
||||||
|
#define MIPS16E_RR_RY_JALR 0x02
|
||||||
|
#define MIPS16E_RR_RY_JRCRX 0x04
|
||||||
|
#define MIPS16E_RR_RY_JRCRA 0x05
|
||||||
|
#define MIPS16E_RR_RY_JALRC 0x06
|
||||||
|
|
||||||
|
#define MIPS16E_OPCODE_BREAK 0xE805
|
||||||
|
#define MIPS16E_OPCODE_NOP 0x6500
|
||||||
|
|
||||||
|
/* MIPS reset vector */
|
||||||
|
#define MIPS_RESET_VECTOR 0x1fc00000
|
||||||
|
|
||||||
|
/* Clock periods per count register increment */
|
||||||
|
#define MIPS4K_COUNT_CLK_PER_CYCLE 2
|
||||||
|
#define MIPS5K_COUNT_CLK_PER_CYCLE 2
|
||||||
|
#define MIPS20Kc_COUNT_CLK_PER_CYCLE 1
|
||||||
|
|
||||||
|
|
||||||
|
/**** MIPS 4K/5K families specific fields of CONFIG register ****/
|
||||||
|
|
||||||
|
#define C0_CONFIG_MIPS4K5K_K23_SHF S_ConfigK23
|
||||||
|
#define C0_CONFIG_MIPS4K5K_K23_MSK (MSK(3) << C0_CONFIG_MIPS4K5K_K23_SHF)
|
||||||
|
|
||||||
|
#define C0_CONFIG_MIPS4K5K_KU_SHF S_ConfigKU
|
||||||
|
#define C0_CONFIG_MIPS4K5K_KU_MSK (MSK(3) << C0_CONFIG_MIPS4K5K_KU_SHF)
|
||||||
|
|
||||||
|
|
||||||
|
/**** MIPS 20Kc specific fields of CONFIG register ****/
|
||||||
|
|
||||||
|
#define C0_CONFIG_MIPS20KC_EC_SHF 28
|
||||||
|
#define C0_CONFIG_MIPS20KC_EC_MSK (MSK(3) << C0_CONFIG_MIPS20KC_EC_SHF)
|
||||||
|
|
||||||
|
#define C0_CONFIG_MIPS20KC_DD_SHF 27
|
||||||
|
#define C0_CONFIG_MIPS20KC_DD_MSK (MSK(1) << C0_CONFIG_MIPS20KC_DD_SHF)
|
||||||
|
#define C0_CONFIG_MIPS20KC_DD_BIT C0_CONFIG_MIPS20KC_DD_MSK
|
||||||
|
|
||||||
|
#define C0_CONFIG_MIPS20KC_LP_SHF 26
|
||||||
|
#define C0_CONFIG_MIPS20KC_LP_MSK (MSK(1) << C0_CONFIG_MIPS20KC_LP_SHF)
|
||||||
|
#define C0_CONFIG_MIPS20KC_LP_BIT C0_CONFIG_MIPS20KC_LP_MSK
|
||||||
|
|
||||||
|
#define C0_CONFIG_MIPS20KC_SP_SHF 25
|
||||||
|
#define C0_CONFIG_MIPS20KC_SP_MSK (MSK(1) << C0_CONFIG_MIPS20KC_SP_SHF)
|
||||||
|
#define C0_CONFIG_MIPS20KC_SP_BIT C0_CONFIG_MIPS20KC_SP_MSK
|
||||||
|
|
||||||
|
#define C0_CONFIG_MIPS20KC_TI_SHF 24
|
||||||
|
#define C0_CONFIG_MIPS20KC_TI_MSK (MSK(1) << C0_CONFIG_MIPS20KC_TI_SHF)
|
||||||
|
#define C0_CONFIG_MIPS20KC_TI_BIT C0_CONFIG_MIPS20KC_TI_MSK
|
||||||
|
|
||||||
|
|
||||||
|
/* ********************************************************************* */
|
||||||
|
/* Interface function definition */
|
||||||
|
|
||||||
|
|
||||||
|
/* ********************************************************************* */
|
||||||
|
|
||||||
|
#endif /* #ifndef __MIPS_H__ */
|
985
flash-tool/device_stage2/include/mipsregs.h
Normal file
985
flash-tool/device_stage2/include/mipsregs.h
Normal file
@ -0,0 +1,985 @@
|
|||||||
|
/*
|
||||||
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle
|
||||||
|
* Copyright (C) 2000 Silicon Graphics, Inc.
|
||||||
|
* Modified for further R[236]000 support by Paul M. Antoine, 1996.
|
||||||
|
* Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
|
||||||
|
* Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2003 Maciej W. Rozycki
|
||||||
|
*/
|
||||||
|
#ifndef _ASM_MIPSREGS_H
|
||||||
|
#define _ASM_MIPSREGS_H
|
||||||
|
|
||||||
|
#include <linux/config.h>
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following macros are especially useful for __asm__
|
||||||
|
* inline assembler.
|
||||||
|
*/
|
||||||
|
#ifndef __STR
|
||||||
|
#define __STR(x) #x
|
||||||
|
#endif
|
||||||
|
#ifndef STR
|
||||||
|
#define STR(x) __STR(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configure language
|
||||||
|
*/
|
||||||
|
#ifdef __ASSEMBLY__
|
||||||
|
#define _ULCAST_
|
||||||
|
#else
|
||||||
|
#define _ULCAST_ (unsigned long)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Coprocessor 0 register names
|
||||||
|
*/
|
||||||
|
#define CP0_INDEX $0
|
||||||
|
#define CP0_RANDOM $1
|
||||||
|
#define CP0_ENTRYLO0 $2
|
||||||
|
#define CP0_ENTRYLO1 $3
|
||||||
|
#define CP0_CONF $3
|
||||||
|
#define CP0_CONTEXT $4
|
||||||
|
#define CP0_PAGEMASK $5
|
||||||
|
#define CP0_WIRED $6
|
||||||
|
#define CP0_INFO $7
|
||||||
|
#define CP0_BADVADDR $8
|
||||||
|
#define CP0_COUNT $9
|
||||||
|
#define CP0_ENTRYHI $10
|
||||||
|
#define CP0_COMPARE $11
|
||||||
|
#define CP0_STATUS $12
|
||||||
|
#define CP0_CAUSE $13
|
||||||
|
#define CP0_EPC $14
|
||||||
|
#define CP0_PRID $15
|
||||||
|
#define CP0_CONFIG $16
|
||||||
|
#define CP0_LLADDR $17
|
||||||
|
#define CP0_WATCHLO $18
|
||||||
|
#define CP0_WATCHHI $19
|
||||||
|
#define CP0_XCONTEXT $20
|
||||||
|
#define CP0_FRAMEMASK $21
|
||||||
|
#define CP0_DIAGNOSTIC $22
|
||||||
|
#define CP0_DEBUG $23
|
||||||
|
#define CP0_DEPC $24
|
||||||
|
#define CP0_PERFORMANCE $25
|
||||||
|
#define CP0_ECC $26
|
||||||
|
#define CP0_CACHEERR $27
|
||||||
|
#define CP0_TAGLO $28
|
||||||
|
#define CP0_TAGHI $29
|
||||||
|
#define CP0_ERROREPC $30
|
||||||
|
#define CP0_DESAVE $31
|
||||||
|
|
||||||
|
/*
|
||||||
|
* R4640/R4650 cp0 register names. These registers are listed
|
||||||
|
* here only for completeness; without MMU these CPUs are not useable
|
||||||
|
* by Linux. A future ELKS port might take make Linux run on them
|
||||||
|
* though ...
|
||||||
|
*/
|
||||||
|
#define CP0_IBASE $0
|
||||||
|
#define CP0_IBOUND $1
|
||||||
|
#define CP0_DBASE $2
|
||||||
|
#define CP0_DBOUND $3
|
||||||
|
#define CP0_CALG $17
|
||||||
|
#define CP0_IWATCH $18
|
||||||
|
#define CP0_DWATCH $19
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Coprocessor 0 Set 1 register names
|
||||||
|
*/
|
||||||
|
#define CP0_S1_DERRADDR0 $26
|
||||||
|
#define CP0_S1_DERRADDR1 $27
|
||||||
|
#define CP0_S1_INTCONTROL $20
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TX39 Series
|
||||||
|
*/
|
||||||
|
#define CP0_TX39_CACHE $7
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Coprocessor 1 (FPU) register names
|
||||||
|
*/
|
||||||
|
#define CP1_REVISION $0
|
||||||
|
#define CP1_STATUS $31
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FPU Status Register Values
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Status Register Values
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FPU_CSR_FLUSH 0x01000000 /* flush denormalised results to 0 */
|
||||||
|
#define FPU_CSR_COND 0x00800000 /* $fcc0 */
|
||||||
|
#define FPU_CSR_COND0 0x00800000 /* $fcc0 */
|
||||||
|
#define FPU_CSR_COND1 0x02000000 /* $fcc1 */
|
||||||
|
#define FPU_CSR_COND2 0x04000000 /* $fcc2 */
|
||||||
|
#define FPU_CSR_COND3 0x08000000 /* $fcc3 */
|
||||||
|
#define FPU_CSR_COND4 0x10000000 /* $fcc4 */
|
||||||
|
#define FPU_CSR_COND5 0x20000000 /* $fcc5 */
|
||||||
|
#define FPU_CSR_COND6 0x40000000 /* $fcc6 */
|
||||||
|
#define FPU_CSR_COND7 0x80000000 /* $fcc7 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* X the exception cause indicator
|
||||||
|
* E the exception enable
|
||||||
|
* S the sticky/flag bit
|
||||||
|
*/
|
||||||
|
#define FPU_CSR_ALL_X 0x0003f000
|
||||||
|
#define FPU_CSR_UNI_X 0x00020000
|
||||||
|
#define FPU_CSR_INV_X 0x00010000
|
||||||
|
#define FPU_CSR_DIV_X 0x00008000
|
||||||
|
#define FPU_CSR_OVF_X 0x00004000
|
||||||
|
#define FPU_CSR_UDF_X 0x00002000
|
||||||
|
#define FPU_CSR_INE_X 0x00001000
|
||||||
|
|
||||||
|
#define FPU_CSR_ALL_E 0x00000f80
|
||||||
|
#define FPU_CSR_INV_E 0x00000800
|
||||||
|
#define FPU_CSR_DIV_E 0x00000400
|
||||||
|
#define FPU_CSR_OVF_E 0x00000200
|
||||||
|
#define FPU_CSR_UDF_E 0x00000100
|
||||||
|
#define FPU_CSR_INE_E 0x00000080
|
||||||
|
|
||||||
|
#define FPU_CSR_ALL_S 0x0000007c
|
||||||
|
#define FPU_CSR_INV_S 0x00000040
|
||||||
|
#define FPU_CSR_DIV_S 0x00000020
|
||||||
|
#define FPU_CSR_OVF_S 0x00000010
|
||||||
|
#define FPU_CSR_UDF_S 0x00000008
|
||||||
|
#define FPU_CSR_INE_S 0x00000004
|
||||||
|
|
||||||
|
/* rounding mode */
|
||||||
|
#define FPU_CSR_RN 0x0 /* nearest */
|
||||||
|
#define FPU_CSR_RZ 0x1 /* towards zero */
|
||||||
|
#define FPU_CSR_RU 0x2 /* towards +Infinity */
|
||||||
|
#define FPU_CSR_RD 0x3 /* towards -Infinity */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Values for PageMask register
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_CPU_VR41XX
|
||||||
|
|
||||||
|
/* Why doesn't stupidity hurt ... */
|
||||||
|
|
||||||
|
#define PM_1K 0x00000000
|
||||||
|
#define PM_4K 0x00001800
|
||||||
|
#define PM_16K 0x00007800
|
||||||
|
#define PM_64K 0x0001f800
|
||||||
|
#define PM_256K 0x0007f800
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define PM_4K 0x00000000
|
||||||
|
#define PM_16K 0x00006000
|
||||||
|
#define PM_64K 0x0001e000
|
||||||
|
#define PM_256K 0x0007e000
|
||||||
|
#define PM_1M 0x001fe000
|
||||||
|
#define PM_4M 0x007fe000
|
||||||
|
#define PM_16M 0x01ffe000
|
||||||
|
#define PM_64M 0x07ffe000
|
||||||
|
#define PM_256M 0x1fffe000
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Values used for computation of new tlb entries
|
||||||
|
*/
|
||||||
|
#define PL_4K 12
|
||||||
|
#define PL_16K 14
|
||||||
|
#define PL_64K 16
|
||||||
|
#define PL_256K 18
|
||||||
|
#define PL_1M 20
|
||||||
|
#define PL_4M 22
|
||||||
|
#define PL_16M 24
|
||||||
|
#define PL_64M 26
|
||||||
|
#define PL_256M 28
|
||||||
|
|
||||||
|
/*
|
||||||
|
* R4x00 interrupt enable / cause bits
|
||||||
|
*/
|
||||||
|
#define IE_SW0 (_ULCAST_(1) << 8)
|
||||||
|
#define IE_SW1 (_ULCAST_(1) << 9)
|
||||||
|
#define IE_IRQ0 (_ULCAST_(1) << 10)
|
||||||
|
#define IE_IRQ1 (_ULCAST_(1) << 11)
|
||||||
|
#define IE_IRQ2 (_ULCAST_(1) << 12)
|
||||||
|
#define IE_IRQ3 (_ULCAST_(1) << 13)
|
||||||
|
#define IE_IRQ4 (_ULCAST_(1) << 14)
|
||||||
|
#define IE_IRQ5 (_ULCAST_(1) << 15)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* R4x00 interrupt cause bits
|
||||||
|
*/
|
||||||
|
#define C_SW0 (_ULCAST_(1) << 8)
|
||||||
|
#define C_SW1 (_ULCAST_(1) << 9)
|
||||||
|
#define C_IRQ0 (_ULCAST_(1) << 10)
|
||||||
|
#define C_IRQ1 (_ULCAST_(1) << 11)
|
||||||
|
#define C_IRQ2 (_ULCAST_(1) << 12)
|
||||||
|
#define C_IRQ3 (_ULCAST_(1) << 13)
|
||||||
|
#define C_IRQ4 (_ULCAST_(1) << 14)
|
||||||
|
#define C_IRQ5 (_ULCAST_(1) << 15)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bitfields in the R4xx0 cp0 status register
|
||||||
|
*/
|
||||||
|
#define ST0_IE 0x00000001
|
||||||
|
#define ST0_EXL 0x00000002
|
||||||
|
#define ST0_ERL 0x00000004
|
||||||
|
#define ST0_KSU 0x00000018
|
||||||
|
# define KSU_USER 0x00000010
|
||||||
|
# define KSU_SUPERVISOR 0x00000008
|
||||||
|
# define KSU_KERNEL 0x00000000
|
||||||
|
#define ST0_UX 0x00000020
|
||||||
|
#define ST0_SX 0x00000040
|
||||||
|
#define ST0_KX 0x00000080
|
||||||
|
#define ST0_DE 0x00010000
|
||||||
|
#define ST0_CE 0x00020000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bitfields in the R[23]000 cp0 status register.
|
||||||
|
*/
|
||||||
|
#define ST0_IEC 0x00000001
|
||||||
|
#define ST0_KUC 0x00000002
|
||||||
|
#define ST0_IEP 0x00000004
|
||||||
|
#define ST0_KUP 0x00000008
|
||||||
|
#define ST0_IEO 0x00000010
|
||||||
|
#define ST0_KUO 0x00000020
|
||||||
|
/* bits 6 & 7 are reserved on R[23]000 */
|
||||||
|
#define ST0_ISC 0x00010000
|
||||||
|
#define ST0_SWC 0x00020000
|
||||||
|
#define ST0_CM 0x00080000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bits specific to the R4640/R4650
|
||||||
|
*/
|
||||||
|
#define ST0_UM (_ULCAST_(1) << 4)
|
||||||
|
#define ST0_IL (_ULCAST_(1) << 23)
|
||||||
|
#define ST0_DL (_ULCAST_(1) << 24)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bitfields in the TX39 family CP0 Configuration Register 3
|
||||||
|
*/
|
||||||
|
#define TX39_CONF_ICS_SHIFT 19
|
||||||
|
#define TX39_CONF_ICS_MASK 0x00380000
|
||||||
|
#define TX39_CONF_ICS_1KB 0x00000000
|
||||||
|
#define TX39_CONF_ICS_2KB 0x00080000
|
||||||
|
#define TX39_CONF_ICS_4KB 0x00100000
|
||||||
|
#define TX39_CONF_ICS_8KB 0x00180000
|
||||||
|
#define TX39_CONF_ICS_16KB 0x00200000
|
||||||
|
|
||||||
|
#define TX39_CONF_DCS_SHIFT 16
|
||||||
|
#define TX39_CONF_DCS_MASK 0x00070000
|
||||||
|
#define TX39_CONF_DCS_1KB 0x00000000
|
||||||
|
#define TX39_CONF_DCS_2KB 0x00010000
|
||||||
|
#define TX39_CONF_DCS_4KB 0x00020000
|
||||||
|
#define TX39_CONF_DCS_8KB 0x00030000
|
||||||
|
#define TX39_CONF_DCS_16KB 0x00040000
|
||||||
|
|
||||||
|
#define TX39_CONF_CWFON 0x00004000
|
||||||
|
#define TX39_CONF_WBON 0x00002000
|
||||||
|
#define TX39_CONF_RF_SHIFT 10
|
||||||
|
#define TX39_CONF_RF_MASK 0x00000c00
|
||||||
|
#define TX39_CONF_DOZE 0x00000200
|
||||||
|
#define TX39_CONF_HALT 0x00000100
|
||||||
|
#define TX39_CONF_LOCK 0x00000080
|
||||||
|
#define TX39_CONF_ICE 0x00000020
|
||||||
|
#define TX39_CONF_DCE 0x00000010
|
||||||
|
#define TX39_CONF_IRSIZE_SHIFT 2
|
||||||
|
#define TX39_CONF_IRSIZE_MASK 0x0000000c
|
||||||
|
#define TX39_CONF_DRSIZE_SHIFT 0
|
||||||
|
#define TX39_CONF_DRSIZE_MASK 0x00000003
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Status register bits available in all MIPS CPUs.
|
||||||
|
*/
|
||||||
|
#define ST0_IM 0x0000ff00
|
||||||
|
#define STATUSB_IP0 8
|
||||||
|
#define STATUSF_IP0 (_ULCAST_(1) << 8)
|
||||||
|
#define STATUSB_IP1 9
|
||||||
|
#define STATUSF_IP1 (_ULCAST_(1) << 9)
|
||||||
|
#define STATUSB_IP2 10
|
||||||
|
#define STATUSF_IP2 (_ULCAST_(1) << 10)
|
||||||
|
#define STATUSB_IP3 11
|
||||||
|
#define STATUSF_IP3 (_ULCAST_(1) << 11)
|
||||||
|
#define STATUSB_IP4 12
|
||||||
|
#define STATUSF_IP4 (_ULCAST_(1) << 12)
|
||||||
|
#define STATUSB_IP5 13
|
||||||
|
#define STATUSF_IP5 (_ULCAST_(1) << 13)
|
||||||
|
#define STATUSB_IP6 14
|
||||||
|
#define STATUSF_IP6 (_ULCAST_(1) << 14)
|
||||||
|
#define STATUSB_IP7 15
|
||||||
|
#define STATUSF_IP7 (_ULCAST_(1) << 15)
|
||||||
|
#define STATUSB_IP8 0
|
||||||
|
#define STATUSF_IP8 (_ULCAST_(1) << 0)
|
||||||
|
#define STATUSB_IP9 1
|
||||||
|
#define STATUSF_IP9 (_ULCAST_(1) << 1)
|
||||||
|
#define STATUSB_IP10 2
|
||||||
|
#define STATUSF_IP10 (_ULCAST_(1) << 2)
|
||||||
|
#define STATUSB_IP11 3
|
||||||
|
#define STATUSF_IP11 (_ULCAST_(1) << 3)
|
||||||
|
#define STATUSB_IP12 4
|
||||||
|
#define STATUSF_IP12 (_ULCAST_(1) << 4)
|
||||||
|
#define STATUSB_IP13 5
|
||||||
|
#define STATUSF_IP13 (_ULCAST_(1) << 5)
|
||||||
|
#define STATUSB_IP14 6
|
||||||
|
#define STATUSF_IP14 (_ULCAST_(1) << 6)
|
||||||
|
#define STATUSB_IP15 7
|
||||||
|
#define STATUSF_IP15 (_ULCAST_(1) << 7)
|
||||||
|
#define ST0_CH 0x00040000
|
||||||
|
#define ST0_SR 0x00100000
|
||||||
|
#define ST0_TS 0x00200000
|
||||||
|
#define ST0_BEV 0x00400000
|
||||||
|
#define ST0_RE 0x02000000
|
||||||
|
#define ST0_FR 0x04000000
|
||||||
|
#define ST0_CU 0xf0000000
|
||||||
|
#define ST0_CU0 0x10000000
|
||||||
|
#define ST0_CU1 0x20000000
|
||||||
|
#define ST0_CU2 0x40000000
|
||||||
|
#define ST0_CU3 0x80000000
|
||||||
|
#define ST0_XX 0x80000000 /* MIPS IV naming */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bitfields and bit numbers in the coprocessor 0 cause register.
|
||||||
|
*
|
||||||
|
* Refer to your MIPS R4xx0 manual, chapter 5 for explanation.
|
||||||
|
*/
|
||||||
|
#define CAUSEB_EXCCODE 2
|
||||||
|
#define CAUSEF_EXCCODE (_ULCAST_(31) << 2)
|
||||||
|
#define CAUSEB_IP 8
|
||||||
|
#define CAUSEF_IP (_ULCAST_(255) << 8)
|
||||||
|
#define CAUSEB_IP0 8
|
||||||
|
#define CAUSEF_IP0 (_ULCAST_(1) << 8)
|
||||||
|
#define CAUSEB_IP1 9
|
||||||
|
#define CAUSEF_IP1 (_ULCAST_(1) << 9)
|
||||||
|
#define CAUSEB_IP2 10
|
||||||
|
#define CAUSEF_IP2 (_ULCAST_(1) << 10)
|
||||||
|
#define CAUSEB_IP3 11
|
||||||
|
#define CAUSEF_IP3 (_ULCAST_(1) << 11)
|
||||||
|
#define CAUSEB_IP4 12
|
||||||
|
#define CAUSEF_IP4 (_ULCAST_(1) << 12)
|
||||||
|
#define CAUSEB_IP5 13
|
||||||
|
#define CAUSEF_IP5 (_ULCAST_(1) << 13)
|
||||||
|
#define CAUSEB_IP6 14
|
||||||
|
#define CAUSEF_IP6 (_ULCAST_(1) << 14)
|
||||||
|
#define CAUSEB_IP7 15
|
||||||
|
#define CAUSEF_IP7 (_ULCAST_(1) << 15)
|
||||||
|
#define CAUSEB_IV 23
|
||||||
|
#define CAUSEF_IV (_ULCAST_(1) << 23)
|
||||||
|
#define CAUSEB_CE 28
|
||||||
|
#define CAUSEF_CE (_ULCAST_(3) << 28)
|
||||||
|
#define CAUSEB_BD 31
|
||||||
|
#define CAUSEF_BD (_ULCAST_(1) << 31)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bits in the coprocessor 0 config register.
|
||||||
|
*/
|
||||||
|
/* Generic bits. */
|
||||||
|
#define CONF_CM_CACHABLE_NO_WA 0
|
||||||
|
#define CONF_CM_CACHABLE_WA 1
|
||||||
|
#define CONF_CM_UNCACHED 2
|
||||||
|
#define CONF_CM_CACHABLE_NONCOHERENT 3
|
||||||
|
#define CONF_CM_CACHABLE_CE 4
|
||||||
|
#define CONF_CM_CACHABLE_COW 5
|
||||||
|
#define CONF_CM_CACHABLE_CUW 6
|
||||||
|
#define CONF_CM_CACHABLE_ACCELERATED 7
|
||||||
|
#define CONF_CM_CMASK 7
|
||||||
|
#define CONF_BE (_ULCAST_(1) << 15)
|
||||||
|
|
||||||
|
/* Bits common to various processors. */
|
||||||
|
#define CONF_CU (_ULCAST_(1) << 3)
|
||||||
|
#define CONF_DB (_ULCAST_(1) << 4)
|
||||||
|
#define CONF_IB (_ULCAST_(1) << 5)
|
||||||
|
#define CONF_DC (_ULCAST_(7) << 6)
|
||||||
|
#define CONF_IC (_ULCAST_(7) << 9)
|
||||||
|
#define CONF_EB (_ULCAST_(1) << 13)
|
||||||
|
#define CONF_EM (_ULCAST_(1) << 14)
|
||||||
|
#define CONF_SM (_ULCAST_(1) << 16)
|
||||||
|
#define CONF_SC (_ULCAST_(1) << 17)
|
||||||
|
#define CONF_EW (_ULCAST_(3) << 18)
|
||||||
|
#define CONF_EP (_ULCAST_(15)<< 24)
|
||||||
|
#define CONF_EC (_ULCAST_(7) << 28)
|
||||||
|
#define CONF_CM (_ULCAST_(1) << 31)
|
||||||
|
|
||||||
|
/* Bits specific to the R4xx0. */
|
||||||
|
#define R4K_CONF_SW (_ULCAST_(1) << 20)
|
||||||
|
#define R4K_CONF_SS (_ULCAST_(1) << 21)
|
||||||
|
#define R4K_CONF_SB (_ULCAST_(3) << 22)
|
||||||
|
|
||||||
|
/* Bits specific to the R5000. */
|
||||||
|
#define R5K_CONF_SE (_ULCAST_(1) << 12)
|
||||||
|
#define R5K_CONF_SS (_ULCAST_(3) << 20)
|
||||||
|
|
||||||
|
/* Bits specific to the R10000. */
|
||||||
|
#define R10K_CONF_DN (_ULCAST_(3) << 3)
|
||||||
|
#define R10K_CONF_CT (_ULCAST_(1) << 5)
|
||||||
|
#define R10K_CONF_PE (_ULCAST_(1) << 6)
|
||||||
|
#define R10K_CONF_PM (_ULCAST_(3) << 7)
|
||||||
|
#define R10K_CONF_EC (_ULCAST_(15)<< 9)
|
||||||
|
#define R10K_CONF_SB (_ULCAST_(1) << 13)
|
||||||
|
#define R10K_CONF_SK (_ULCAST_(1) << 14)
|
||||||
|
#define R10K_CONF_SS (_ULCAST_(7) << 16)
|
||||||
|
#define R10K_CONF_SC (_ULCAST_(7) << 19)
|
||||||
|
#define R10K_CONF_DC (_ULCAST_(7) << 26)
|
||||||
|
#define R10K_CONF_IC (_ULCAST_(7) << 29)
|
||||||
|
|
||||||
|
/* Bits specific to the VR41xx. */
|
||||||
|
#define VR41_CONF_CS (_ULCAST_(1) << 12)
|
||||||
|
#define VR41_CONF_M16 (_ULCAST_(1) << 20)
|
||||||
|
#define VR41_CONF_AD (_ULCAST_(1) << 23)
|
||||||
|
|
||||||
|
/* Bits specific to the R30xx. */
|
||||||
|
#define R30XX_CONF_FDM (_ULCAST_(1) << 19)
|
||||||
|
#define R30XX_CONF_REV (_ULCAST_(1) << 22)
|
||||||
|
#define R30XX_CONF_AC (_ULCAST_(1) << 23)
|
||||||
|
#define R30XX_CONF_RF (_ULCAST_(1) << 24)
|
||||||
|
#define R30XX_CONF_HALT (_ULCAST_(1) << 25)
|
||||||
|
#define R30XX_CONF_FPINT (_ULCAST_(7) << 26)
|
||||||
|
#define R30XX_CONF_DBR (_ULCAST_(1) << 29)
|
||||||
|
#define R30XX_CONF_SB (_ULCAST_(1) << 30)
|
||||||
|
#define R30XX_CONF_LOCK (_ULCAST_(1) << 31)
|
||||||
|
|
||||||
|
/* Bits specific to the TX49. */
|
||||||
|
#define TX49_CONF_DC (_ULCAST_(1) << 16)
|
||||||
|
#define TX49_CONF_IC (_ULCAST_(1) << 17) /* conflict with CONF_SC */
|
||||||
|
#define TX49_CONF_HALT (_ULCAST_(1) << 18)
|
||||||
|
#define TX49_CONF_CWFON (_ULCAST_(1) << 27)
|
||||||
|
|
||||||
|
/* Bits specific to the MIPS32/64 PRA. */
|
||||||
|
#define MIPS_CONF_MT (_ULCAST_(7) << 7)
|
||||||
|
#define MIPS_CONF_AR (_ULCAST_(7) << 10)
|
||||||
|
#define MIPS_CONF_AT (_ULCAST_(3) << 13)
|
||||||
|
#define MIPS_CONF_M (_ULCAST_(1) << 31)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* R10000 performance counter definitions.
|
||||||
|
*
|
||||||
|
* FIXME: The R10000 performance counter opens a nice way to implement CPU
|
||||||
|
* time accounting with a precission of one cycle. I don't have
|
||||||
|
* R10000 silicon but just a manual, so ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Events counted by counter #0
|
||||||
|
*/
|
||||||
|
#define CE0_CYCLES 0
|
||||||
|
#define CE0_INSN_ISSUED 1
|
||||||
|
#define CE0_LPSC_ISSUED 2
|
||||||
|
#define CE0_S_ISSUED 3
|
||||||
|
#define CE0_SC_ISSUED 4
|
||||||
|
#define CE0_SC_FAILED 5
|
||||||
|
#define CE0_BRANCH_DECODED 6
|
||||||
|
#define CE0_QW_WB_SECONDARY 7
|
||||||
|
#define CE0_CORRECTED_ECC_ERRORS 8
|
||||||
|
#define CE0_ICACHE_MISSES 9
|
||||||
|
#define CE0_SCACHE_I_MISSES 10
|
||||||
|
#define CE0_SCACHE_I_WAY_MISSPREDICTED 11
|
||||||
|
#define CE0_EXT_INTERVENTIONS_REQ 12
|
||||||
|
#define CE0_EXT_INVALIDATE_REQ 13
|
||||||
|
#define CE0_VIRTUAL_COHERENCY_COND 14
|
||||||
|
#define CE0_INSN_GRADUATED 15
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Events counted by counter #1
|
||||||
|
*/
|
||||||
|
#define CE1_CYCLES 0
|
||||||
|
#define CE1_INSN_GRADUATED 1
|
||||||
|
#define CE1_LPSC_GRADUATED 2
|
||||||
|
#define CE1_S_GRADUATED 3
|
||||||
|
#define CE1_SC_GRADUATED 4
|
||||||
|
#define CE1_FP_INSN_GRADUATED 5
|
||||||
|
#define CE1_QW_WB_PRIMARY 6
|
||||||
|
#define CE1_TLB_REFILL 7
|
||||||
|
#define CE1_BRANCH_MISSPREDICTED 8
|
||||||
|
#define CE1_DCACHE_MISS 9
|
||||||
|
#define CE1_SCACHE_D_MISSES 10
|
||||||
|
#define CE1_SCACHE_D_WAY_MISSPREDICTED 11
|
||||||
|
#define CE1_EXT_INTERVENTION_HITS 12
|
||||||
|
#define CE1_EXT_INVALIDATE_REQ 13
|
||||||
|
#define CE1_SP_HINT_TO_CEXCL_SC_BLOCKS 14
|
||||||
|
#define CE1_SP_HINT_TO_SHARED_SC_BLOCKS 15
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These flags define in which priviledge mode the counters count events
|
||||||
|
*/
|
||||||
|
#define CEB_USER 8 /* Count events in user mode, EXL = ERL = 0 */
|
||||||
|
#define CEB_SUPERVISOR 4 /* Count events in supvervisor mode EXL = ERL = 0 */
|
||||||
|
#define CEB_KERNEL 2 /* Count events in kernel mode EXL = ERL = 0 */
|
||||||
|
#define CEB_EXL 1 /* Count events with EXL = 1, ERL = 0 */
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
#define CAUSE_EXCCODE(x) ((CAUSEF_EXCCODE & (x->cp0_cause)) >> CAUSEB_EXCCODE)
|
||||||
|
#define CAUSE_EPC(x) (x->cp0_epc + (((x->cp0_cause & CAUSEF_BD) >> CAUSEB_BD) << 2))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions to access the r10k performance counter and control registers
|
||||||
|
*/
|
||||||
|
#define read_r10k_perf_cntr(counter) \
|
||||||
|
({ unsigned int __res; \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
"mfpc\t%0, "STR(counter) \
|
||||||
|
: "=r" (__res)); \
|
||||||
|
__res;})
|
||||||
|
|
||||||
|
#define write_r10k_perf_cntr(counter,val) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
"mtpc\t%0, "STR(counter) \
|
||||||
|
: : "r" (val));
|
||||||
|
|
||||||
|
#define read_r10k_perf_cntl(counter) \
|
||||||
|
({ unsigned int __res; \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
"mfps\t%0, "STR(counter) \
|
||||||
|
: "=r" (__res)); \
|
||||||
|
__res;})
|
||||||
|
|
||||||
|
#define write_r10k_perf_cntl(counter,val) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
"mtps\t%0, "STR(counter) \
|
||||||
|
: : "r" (val));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros to access the system control coprocessor
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __read_32bit_c0_register(source, sel) \
|
||||||
|
({ int __res; \
|
||||||
|
if (sel == 0) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
"mfc0\t%0, " #source "\n\t" \
|
||||||
|
: "=r" (__res)); \
|
||||||
|
else \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tmips32\n\t" \
|
||||||
|
"mfc0\t%0, " #source ", " #sel "\n\t" \
|
||||||
|
".set\tmips0\n\t" \
|
||||||
|
: "=r" (__res)); \
|
||||||
|
__res; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define __read_64bit_c0_register(source, sel) \
|
||||||
|
({ unsigned long __res; \
|
||||||
|
if (sel == 0) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tmips3\n\t" \
|
||||||
|
"dmfc0\t%0, " #source "\n\t" \
|
||||||
|
".set\tmips0" \
|
||||||
|
: "=r" (__res)); \
|
||||||
|
else \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tmips64\n\t" \
|
||||||
|
"dmfc0\t%0, " #source ", " #sel "\n\t" \
|
||||||
|
".set\tmips0" \
|
||||||
|
: "=r" (__res)); \
|
||||||
|
__res; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define __write_32bit_c0_register(register, sel, value) \
|
||||||
|
do { \
|
||||||
|
if (sel == 0) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
"mtc0\t%z0, " #register "\n\t" \
|
||||||
|
: : "Jr" (value)); \
|
||||||
|
else \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tmips32\n\t" \
|
||||||
|
"mtc0\t%z0, " #register ", " #sel "\n\t" \
|
||||||
|
".set\tmips0" \
|
||||||
|
: : "Jr" (value)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define __write_64bit_c0_register(register, sel, value) \
|
||||||
|
do { \
|
||||||
|
if (sel == 0) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tmips3\n\t" \
|
||||||
|
"dmtc0\t%z0, " #register "\n\t" \
|
||||||
|
".set\tmips0" \
|
||||||
|
: : "Jr" (value)); \
|
||||||
|
else \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tmips64\n\t" \
|
||||||
|
"dmtc0\t%z0, " #register ", " #sel "\n\t" \
|
||||||
|
".set\tmips0" \
|
||||||
|
: : "Jr" (value)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define __read_ulong_c0_register(reg, sel) \
|
||||||
|
((sizeof(unsigned long) == 4) ? \
|
||||||
|
__read_32bit_c0_register(reg, sel) : \
|
||||||
|
__read_64bit_c0_register(reg, sel))
|
||||||
|
|
||||||
|
#define __write_ulong_c0_register(reg, sel, val) \
|
||||||
|
do { \
|
||||||
|
if (sizeof(unsigned long) == 4) \
|
||||||
|
__write_32bit_c0_register(reg, sel, val); \
|
||||||
|
else \
|
||||||
|
__write_64bit_c0_register(reg, sel, val); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These versions are only needed for systems with more than 38 bits of
|
||||||
|
* physical address space running the 32-bit kernel. That's none atm :-)
|
||||||
|
*/
|
||||||
|
#define __read_64bit_c0_split(source, sel) \
|
||||||
|
({ \
|
||||||
|
unsigned long long val; \
|
||||||
|
unsigned long flags; \
|
||||||
|
\
|
||||||
|
local_irq_save(flags); \
|
||||||
|
if (sel == 0) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tmips64\n\t" \
|
||||||
|
"dmfc0\t%M0, " #source "\n\t" \
|
||||||
|
"dsll\t%L0, %M0, 32\n\t" \
|
||||||
|
"dsrl\t%M0, %M0, 32\n\t" \
|
||||||
|
"dsrl\t%L0, %L0, 32\n\t" \
|
||||||
|
".set\tmips0" \
|
||||||
|
: "=r" (val)); \
|
||||||
|
else \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tmips64\n\t" \
|
||||||
|
"dmfc0\t%M0, " #source ", " #sel "\n\t" \
|
||||||
|
"dsll\t%L0, %M0, 32\n\t" \
|
||||||
|
"dsrl\t%M0, %M0, 32\n\t" \
|
||||||
|
"dsrl\t%L0, %L0, 32\n\t" \
|
||||||
|
".set\tmips0" \
|
||||||
|
: "=r" (val)); \
|
||||||
|
local_irq_restore(flags); \
|
||||||
|
\
|
||||||
|
val; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define __write_64bit_c0_split(source, sel, val) \
|
||||||
|
do { \
|
||||||
|
unsigned long flags; \
|
||||||
|
\
|
||||||
|
local_irq_save(flags); \
|
||||||
|
if (sel == 0) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tmips64\n\t" \
|
||||||
|
"dsll\t%L0, %L0, 32\n\t" \
|
||||||
|
"dsrl\t%L0, %L0, 32\n\t" \
|
||||||
|
"dsll\t%M0, %M0, 32\n\t" \
|
||||||
|
"or\t%L0, %L0, %M0\n\t" \
|
||||||
|
"dmtc0\t%L0, " #source "\n\t" \
|
||||||
|
".set\tmips0" \
|
||||||
|
: : "r" (val)); \
|
||||||
|
else \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tmips64\n\t" \
|
||||||
|
"dsll\t%L0, %L0, 32\n\t" \
|
||||||
|
"dsrl\t%L0, %L0, 32\n\t" \
|
||||||
|
"dsll\t%M0, %M0, 32\n\t" \
|
||||||
|
"or\t%L0, %L0, %M0\n\t" \
|
||||||
|
"dmtc0\t%L0, " #source ", " #sel "\n\t" \
|
||||||
|
".set\tmips0" \
|
||||||
|
: : "r" (val)); \
|
||||||
|
local_irq_restore(flags); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define read_c0_index() __read_32bit_c0_register($0, 0)
|
||||||
|
#define write_c0_index(val) __write_32bit_c0_register($0, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_entrylo0() __read_ulong_c0_register($2, 0)
|
||||||
|
#define write_c0_entrylo0(val) __write_ulong_c0_register($2, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_entrylo1() __read_ulong_c0_register($3, 0)
|
||||||
|
#define write_c0_entrylo1(val) __write_ulong_c0_register($3, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_conf() __read_32bit_c0_register($3, 0)
|
||||||
|
#define write_c0_conf(val) __write_32bit_c0_register($3, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_context() __read_ulong_c0_register($4, 0)
|
||||||
|
#define write_c0_context(val) __write_ulong_c0_register($4, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_pagemask() __read_32bit_c0_register($5, 0)
|
||||||
|
#define write_c0_pagemask(val) __write_32bit_c0_register($5, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_wired() __read_32bit_c0_register($6, 0)
|
||||||
|
#define write_c0_wired(val) __write_32bit_c0_register($6, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_info() __read_32bit_c0_register($7, 0)
|
||||||
|
|
||||||
|
#define read_c0_cache() __read_32bit_c0_register($7, 0) /* TX39xx */
|
||||||
|
#define write_c0_cache(val) __write_32bit_c0_register($7, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_count() __read_32bit_c0_register($9, 0)
|
||||||
|
#define write_c0_count(val) __write_32bit_c0_register($9, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_entryhi() __read_ulong_c0_register($10, 0)
|
||||||
|
#define write_c0_entryhi(val) __write_ulong_c0_register($10, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_compare() __read_32bit_c0_register($11, 0)
|
||||||
|
#define write_c0_compare(val) __write_32bit_c0_register($11, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_status() __read_32bit_c0_register($12, 0)
|
||||||
|
#define write_c0_status(val) __write_32bit_c0_register($12, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_cause() __read_32bit_c0_register($13, 0)
|
||||||
|
#define write_c0_cause(val) __write_32bit_c0_register($13, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_prid() __read_32bit_c0_register($15, 0)
|
||||||
|
|
||||||
|
#define read_c0_config() __read_32bit_c0_register($16, 0)
|
||||||
|
#define read_c0_config1() __read_32bit_c0_register($16, 1)
|
||||||
|
#define read_c0_config2() __read_32bit_c0_register($16, 2)
|
||||||
|
#define read_c0_config3() __read_32bit_c0_register($16, 3)
|
||||||
|
#define write_c0_config(val) __write_32bit_c0_register($16, 0, val)
|
||||||
|
#define write_c0_config1(val) __write_32bit_c0_register($16, 1, val)
|
||||||
|
#define write_c0_config2(val) __write_32bit_c0_register($16, 2, val)
|
||||||
|
#define write_c0_config3(val) __write_32bit_c0_register($16, 3, val)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The WatchLo register. There may be upto 8 of them.
|
||||||
|
*/
|
||||||
|
#define read_c0_watchlo0() __read_ulong_c0_register($18, 0)
|
||||||
|
#define read_c0_watchlo1() __read_ulong_c0_register($18, 1)
|
||||||
|
#define read_c0_watchlo2() __read_ulong_c0_register($18, 2)
|
||||||
|
#define read_c0_watchlo3() __read_ulong_c0_register($18, 3)
|
||||||
|
#define read_c0_watchlo4() __read_ulong_c0_register($18, 4)
|
||||||
|
#define read_c0_watchlo5() __read_ulong_c0_register($18, 5)
|
||||||
|
#define read_c0_watchlo6() __read_ulong_c0_register($18, 6)
|
||||||
|
#define read_c0_watchlo7() __read_ulong_c0_register($18, 7)
|
||||||
|
#define write_c0_watchlo0(val) __write_ulong_c0_register($18, 0, val)
|
||||||
|
#define write_c0_watchlo1(val) __write_ulong_c0_register($18, 1, val)
|
||||||
|
#define write_c0_watchlo2(val) __write_ulong_c0_register($18, 2, val)
|
||||||
|
#define write_c0_watchlo3(val) __write_ulong_c0_register($18, 3, val)
|
||||||
|
#define write_c0_watchlo4(val) __write_ulong_c0_register($18, 4, val)
|
||||||
|
#define write_c0_watchlo5(val) __write_ulong_c0_register($18, 5, val)
|
||||||
|
#define write_c0_watchlo6(val) __write_ulong_c0_register($18, 6, val)
|
||||||
|
#define write_c0_watchlo7(val) __write_ulong_c0_register($18, 7, val)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The WatchHi register. There may be upto 8 of them.
|
||||||
|
*/
|
||||||
|
#define read_c0_watchhi0() __read_32bit_c0_register($19, 0)
|
||||||
|
#define read_c0_watchhi1() __read_32bit_c0_register($19, 1)
|
||||||
|
#define read_c0_watchhi2() __read_32bit_c0_register($19, 2)
|
||||||
|
#define read_c0_watchhi3() __read_32bit_c0_register($19, 3)
|
||||||
|
#define read_c0_watchhi4() __read_32bit_c0_register($19, 4)
|
||||||
|
#define read_c0_watchhi5() __read_32bit_c0_register($19, 5)
|
||||||
|
#define read_c0_watchhi6() __read_32bit_c0_register($19, 6)
|
||||||
|
#define read_c0_watchhi7() __read_32bit_c0_register($19, 7)
|
||||||
|
|
||||||
|
#define write_c0_watchhi0(val) __write_32bit_c0_register($19, 0, val)
|
||||||
|
#define write_c0_watchhi1(val) __write_32bit_c0_register($19, 1, val)
|
||||||
|
#define write_c0_watchhi2(val) __write_32bit_c0_register($19, 2, val)
|
||||||
|
#define write_c0_watchhi3(val) __write_32bit_c0_register($19, 3, val)
|
||||||
|
#define write_c0_watchhi4(val) __write_32bit_c0_register($19, 4, val)
|
||||||
|
#define write_c0_watchhi5(val) __write_32bit_c0_register($19, 5, val)
|
||||||
|
#define write_c0_watchhi6(val) __write_32bit_c0_register($19, 6, val)
|
||||||
|
#define write_c0_watchhi7(val) __write_32bit_c0_register($19, 7, val)
|
||||||
|
|
||||||
|
#define read_c0_xcontext() __read_ulong_c0_register($20, 0)
|
||||||
|
#define write_c0_xcontext(val) __write_ulong_c0_register($20, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_intcontrol() __read_32bit_c0_register($20, 1)
|
||||||
|
#define write_c0_intcontrol(val) __write_32bit_c0_register($20, 1, val)
|
||||||
|
|
||||||
|
#define read_c0_framemask() __read_32bit_c0_register($21, 0)
|
||||||
|
#define write_c0_framemask(val) __write_32bit_c0_register($21, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_debug() __read_32bit_c0_register($23, 0)
|
||||||
|
#define write_c0_debug(val) __write_32bit_c0_register($23, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_depc() __read_ulong_c0_register($24, 0)
|
||||||
|
#define write_c0_depc(val) __write_ulong_c0_register($24, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_ecc() __read_32bit_c0_register($26, 0)
|
||||||
|
#define write_c0_ecc(val) __write_32bit_c0_register($26, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_derraddr0() __read_ulong_c0_register($26, 1)
|
||||||
|
#define write_c0_derraddr0(val) __write_ulong_c0_register($26, 1, val)
|
||||||
|
|
||||||
|
#define read_c0_cacheerr() __read_32bit_c0_register($27, 0)
|
||||||
|
|
||||||
|
#define read_c0_derraddr1() __read_ulong_c0_register($27, 1)
|
||||||
|
#define write_c0_derraddr1(val) __write_ulong_c0_register($27, 1, val)
|
||||||
|
|
||||||
|
#define read_c0_taglo() __read_32bit_c0_register($28, 0)
|
||||||
|
#define write_c0_taglo(val) __write_32bit_c0_register($28, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_taghi() __read_32bit_c0_register($29, 0)
|
||||||
|
#define write_c0_taghi(val) __write_32bit_c0_register($29, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_errorepc() __read_ulong_c0_register($30, 0)
|
||||||
|
#define write_c0_errorepc(val) __write_ulong_c0_register($30, 0, val)
|
||||||
|
|
||||||
|
#define read_c0_epc() __read_ulong_c0_register($14, 0)
|
||||||
|
#define write_c0_epc(val) __write_ulong_c0_register($14, 0, val)
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
/*
|
||||||
|
* Macros to access the system control coprocessor
|
||||||
|
*/
|
||||||
|
#define read_32bit_cp0_register(source) \
|
||||||
|
({ int __res; \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tpush\n\t" \
|
||||||
|
".set\treorder\n\t" \
|
||||||
|
"mfc0\t%0,"STR(source)"\n\t" \
|
||||||
|
".set\tpop" \
|
||||||
|
: "=r" (__res)); \
|
||||||
|
__res;})
|
||||||
|
|
||||||
|
#define read_32bit_cp0_set1_register(source) \
|
||||||
|
({ int __res; \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tpush\n\t" \
|
||||||
|
".set\treorder\n\t" \
|
||||||
|
"cfc0\t%0,"STR(source)"\n\t" \
|
||||||
|
".set\tpop" \
|
||||||
|
: "=r" (__res)); \
|
||||||
|
__res;})
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For now use this only with interrupts disabled!
|
||||||
|
*/
|
||||||
|
#define read_64bit_cp0_register(source) \
|
||||||
|
({ int __res; \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tmips3\n\t" \
|
||||||
|
"dmfc0\t%0,"STR(source)"\n\t" \
|
||||||
|
".set\tmips0" \
|
||||||
|
: "=r" (__res)); \
|
||||||
|
__res;})
|
||||||
|
|
||||||
|
#define write_32bit_cp0_register(register,value) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
"mtc0\t%0,"STR(register)"\n\t" \
|
||||||
|
"nop" \
|
||||||
|
: : "r" (value));
|
||||||
|
|
||||||
|
#define write_32bit_cp0_set1_register(register,value) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
"ctc0\t%0,"STR(register)"\n\t" \
|
||||||
|
"nop" \
|
||||||
|
: : "r" (value));
|
||||||
|
|
||||||
|
#define write_64bit_cp0_register(register,value) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tmips3\n\t" \
|
||||||
|
"dmtc0\t%0,"STR(register)"\n\t" \
|
||||||
|
".set\tmips0" \
|
||||||
|
: : "r" (value))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This should be changed when we get a compiler that support the MIPS32 ISA.
|
||||||
|
*/
|
||||||
|
#define read_mips32_cp0_config1() \
|
||||||
|
({ int __res; \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tnoreorder\n\t" \
|
||||||
|
".set\tnoat\n\t" \
|
||||||
|
"#.set\tmips64\n\t" \
|
||||||
|
"#mfc0\t$1, $16, 1\n\t" \
|
||||||
|
"#.set\tmips0\n\t" \
|
||||||
|
".word\t0x40018001\n\t" \
|
||||||
|
"move\t%0,$1\n\t" \
|
||||||
|
".set\tat\n\t" \
|
||||||
|
".set\treorder" \
|
||||||
|
:"=r" (__res)); \
|
||||||
|
__res;})
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Macros to access the floating point coprocessor control registers
|
||||||
|
*/
|
||||||
|
#define read_32bit_cp1_register(source) \
|
||||||
|
({ int __res; \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set\tpush\n\t" \
|
||||||
|
".set\treorder\n\t" \
|
||||||
|
"cfc1\t%0,"STR(source)"\n\t" \
|
||||||
|
".set\tpop" \
|
||||||
|
: "=r" (__res)); \
|
||||||
|
__res;})
|
||||||
|
|
||||||
|
/* TLB operations. */
|
||||||
|
static inline void tlb_probe(void)
|
||||||
|
{
|
||||||
|
__asm__ __volatile__(
|
||||||
|
".set noreorder\n\t"
|
||||||
|
"tlbp\n\t"
|
||||||
|
".set reorder");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void tlb_read(void)
|
||||||
|
{
|
||||||
|
__asm__ __volatile__(
|
||||||
|
".set noreorder\n\t"
|
||||||
|
"tlbr\n\t"
|
||||||
|
".set reorder");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void tlb_write_indexed(void)
|
||||||
|
{
|
||||||
|
__asm__ __volatile__(
|
||||||
|
".set noreorder\n\t"
|
||||||
|
"tlbwi\n\t"
|
||||||
|
".set reorder");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void tlb_write_random(void)
|
||||||
|
{
|
||||||
|
__asm__ __volatile__(
|
||||||
|
".set noreorder\n\t"
|
||||||
|
"tlbwr\n\t"
|
||||||
|
".set reorder");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Manipulate bits in a c0 register.
|
||||||
|
*/
|
||||||
|
#define __BUILD_SET_C0(name,register) \
|
||||||
|
static inline unsigned int \
|
||||||
|
set_c0_##name(unsigned int set) \
|
||||||
|
{ \
|
||||||
|
unsigned int res; \
|
||||||
|
\
|
||||||
|
res = read_c0_##name(); \
|
||||||
|
res |= set; \
|
||||||
|
write_c0_##name(res); \
|
||||||
|
\
|
||||||
|
return res; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static inline unsigned int \
|
||||||
|
clear_c0_##name(unsigned int clear) \
|
||||||
|
{ \
|
||||||
|
unsigned int res; \
|
||||||
|
\
|
||||||
|
res = read_c0_##name(); \
|
||||||
|
res &= ~clear; \
|
||||||
|
write_c0_##name(res); \
|
||||||
|
\
|
||||||
|
return res; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static inline unsigned int \
|
||||||
|
change_c0_##name(unsigned int change, unsigned int new) \
|
||||||
|
{ \
|
||||||
|
unsigned int res; \
|
||||||
|
\
|
||||||
|
res = read_c0_##name(); \
|
||||||
|
res &= ~change; \
|
||||||
|
res |= (new & change); \
|
||||||
|
write_c0_##name(res); \
|
||||||
|
\
|
||||||
|
return res; \
|
||||||
|
}
|
||||||
|
|
||||||
|
__BUILD_SET_C0(status,CP0_STATUS)
|
||||||
|
__BUILD_SET_C0(cause,CP0_CAUSE)
|
||||||
|
__BUILD_SET_C0(config,CP0_CONFIG)
|
||||||
|
|
||||||
|
#define set_cp0_status(x) set_c0_status(x)
|
||||||
|
#define set_cp0_cause(x) set_c0_cause(x)
|
||||||
|
#define set_cp0_config(x) set_c0_config(x)
|
||||||
|
|
||||||
|
#endif /* !__ASSEMBLY__ */
|
||||||
|
|
||||||
|
#endif /* _ASM_MIPSREGS_H */
|
47
flash-tool/device_stage2/include/nandflash.h
Normal file
47
flash-tool/device_stage2/include/nandflash.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#ifndef __NANDLIB_H__
|
||||||
|
#define __NANDLIB_H__
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define u8 unsigned char
|
||||||
|
#define u16 unsigned short
|
||||||
|
#define u32 unsigned int
|
||||||
|
|
||||||
|
/* Jz4740 nandflash interface */
|
||||||
|
unsigned int nand_query_4740(u8 *);
|
||||||
|
int nand_init_4740(int bus_width, int row_cycle, int page_size, int page_per_block,
|
||||||
|
int,int,int,int);
|
||||||
|
int nand_fini_4740(void);
|
||||||
|
u32 nand_program_4740(void *context, int spage, int pages, int option);
|
||||||
|
//int nand_program_oob_4740(void *context, int spage, int pages, void (*notify)(int));
|
||||||
|
u32 nand_erase_4740(int blk_num, int sblk, int force);
|
||||||
|
u32 nand_read_4740(void *buf, u32 startpage, u32 pagenum,int option);
|
||||||
|
u32 nand_read_oob_4740(void *buf, u32 startpage, u32 pagenum);
|
||||||
|
u32 nand_read_raw_4740(void *buf, u32 startpage, u32 pagenum,int);
|
||||||
|
u32 nand_mark_bad_4740(int bad);
|
||||||
|
void nand_enable_4740(u32 csn);
|
||||||
|
void nand_disable_4740(u32 csn);
|
||||||
|
|
||||||
|
/* Jz4750 nandflash interface */
|
||||||
|
unsigned int nand_query_4750(u8 *);
|
||||||
|
//int nand_init_4750(int bus_width, int row_cycle, int page_size, int page_per_block,
|
||||||
|
// int,int,int,int);
|
||||||
|
|
||||||
|
int nand_init_4750(int bus_width, int row_cycle, int page_size, int page_per_block,
|
||||||
|
int bch_bit, int ecc_pos, int bad_pos, int bad_page, int force);
|
||||||
|
|
||||||
|
int nand_fini_4750(void);
|
||||||
|
u32 nand_program_4750(void *context, int spage, int pages, int option);
|
||||||
|
//int nand_program_oob_4740(void *context, int spage, int pages, void (*notify)(int));
|
||||||
|
u32 nand_erase_4750(int blk_num, int sblk, int force);
|
||||||
|
u32 nand_read_4750(void *buf, u32 startpage, u32 pagenum,int option);
|
||||||
|
u32 nand_read_oob_4750(void *buf, u32 startpage, u32 pagenum);
|
||||||
|
u32 nand_read_raw_4750(void *buf, u32 startpage, u32 pagenum,int);
|
||||||
|
u32 nand_mark_bad_4750(int bad);
|
||||||
|
|
||||||
|
void nand_enable_4750(u32 csn);
|
||||||
|
void nand_disable_4750(u32 csn);
|
||||||
|
|
||||||
|
#endif
|
442
flash-tool/device_stage2/include/sysdefs.h
Normal file
442
flash-tool/device_stage2/include/sysdefs.h
Normal file
@ -0,0 +1,442 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
* *
|
||||||
|
* PROJECT : MIPS port for uC/OS-II *
|
||||||
|
* *
|
||||||
|
* MODULE : SYSDEFS.h *
|
||||||
|
* *
|
||||||
|
* AUTHOR : Michael Anburaj *
|
||||||
|
* URL : http://geocities.com/michaelanburaj/ *
|
||||||
|
* EMAIL: michaelanburaj@hotmail.com *
|
||||||
|
* *
|
||||||
|
* PROCESSOR : MIPS 4Kc (32 bit RISC) - ATLAS board *
|
||||||
|
* *
|
||||||
|
* TOOL-CHAIN : SDE & Cygnus *
|
||||||
|
* *
|
||||||
|
* DESCRIPTION : *
|
||||||
|
* System definitions header file. *
|
||||||
|
* *
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __SYSDEFS_H__
|
||||||
|
#define __SYSDEFS_H__
|
||||||
|
|
||||||
|
|
||||||
|
/* ********************************************************************* */
|
||||||
|
/* Module configuration */
|
||||||
|
|
||||||
|
|
||||||
|
/* ********************************************************************* */
|
||||||
|
/* Interface macro & data definition */
|
||||||
|
|
||||||
|
#ifdef _ASSEMBLER_
|
||||||
|
|
||||||
|
/******** ASSEMBLER SPECIFIC DEFINITIONS ********/
|
||||||
|
|
||||||
|
#ifdef __ghs__
|
||||||
|
#define ALIGN(x) .##align (1 << (x))
|
||||||
|
#else
|
||||||
|
#define ALIGN(x) .##align (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __ghs__
|
||||||
|
#define SET_MIPS3()
|
||||||
|
#define SET_MIPS0()
|
||||||
|
#define SET_PUSH()
|
||||||
|
#define SET_POP()
|
||||||
|
#else
|
||||||
|
#define SET_MIPS3() .##set mips3
|
||||||
|
#define SET_MIPS0() .##set mips0
|
||||||
|
#define SET_PUSH() .##set push
|
||||||
|
#define SET_POP() .##set pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Different assemblers have different requirements for how to
|
||||||
|
* indicate that the next section is bss :
|
||||||
|
*
|
||||||
|
* Some use : .bss
|
||||||
|
* Others use : .section bss
|
||||||
|
*
|
||||||
|
* We select which to use based on _BSS_OLD_, which may be defined
|
||||||
|
* in makefile.
|
||||||
|
*/
|
||||||
|
#ifdef _BSS_OLD_
|
||||||
|
#define BSS .##section bss
|
||||||
|
#else
|
||||||
|
#define BSS .##bss
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LEAF(name)\
|
||||||
|
.##text;\
|
||||||
|
.##globl name;\
|
||||||
|
.##ent name;\
|
||||||
|
name:
|
||||||
|
|
||||||
|
|
||||||
|
#define SLEAF(name)\
|
||||||
|
.##text;\
|
||||||
|
.##ent name;\
|
||||||
|
name:
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __ghs__
|
||||||
|
#define END(name)\
|
||||||
|
.##end name
|
||||||
|
#else
|
||||||
|
#define END(name)\
|
||||||
|
.##size name,.-name;\
|
||||||
|
.##end name
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define EXTERN(name)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define U64 unsigned long long
|
||||||
|
#define U32 unsigned int
|
||||||
|
#define U16 unsigned short
|
||||||
|
#define U8 unsigned char
|
||||||
|
#define S64 signed long long
|
||||||
|
#define S32 int
|
||||||
|
#define S16 short int
|
||||||
|
#define S8 signed char
|
||||||
|
#define bool U8
|
||||||
|
|
||||||
|
#ifndef _SIZE_T_
|
||||||
|
#define _SIZE_T_
|
||||||
|
#ifdef __ghs__
|
||||||
|
typedef unsigned int size_t;
|
||||||
|
#else
|
||||||
|
typedef unsigned long size_t;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Sets the result on bPort */
|
||||||
|
#define BIT_SET(bPort,bBitMask) (bPort |= bBitMask)
|
||||||
|
#define BIT_CLR(bPort,bBitMask) (bPort &= ~bBitMask)
|
||||||
|
|
||||||
|
/* Returns the result */
|
||||||
|
#define GET_BIT_SET(bPort,bBitMask) (bPort | bBitMask)
|
||||||
|
#define GET_BIT_CLR(bPort,bBitMask) (bPort & ~bBitMask)
|
||||||
|
|
||||||
|
/* Returns 0 if the condition is False & a non-zero value if it is True */
|
||||||
|
#define TEST_BIT_SET(bPort,bBitMask) (bPort & bBitMask)
|
||||||
|
#define TEST_BIT_CLR(bPort,bBitMask) ((~bPort) & bBitMask)
|
||||||
|
|
||||||
|
/* Split union definitions */
|
||||||
|
typedef union tunSU16
|
||||||
|
{
|
||||||
|
U16 hwHW;
|
||||||
|
struct tst2U8
|
||||||
|
{
|
||||||
|
U8 bB0;
|
||||||
|
U8 bB1;
|
||||||
|
}st2U8;
|
||||||
|
}tunSU16;
|
||||||
|
|
||||||
|
typedef union tunSU32
|
||||||
|
{
|
||||||
|
U32 wW;
|
||||||
|
struct tst2U16
|
||||||
|
{
|
||||||
|
U16 hwHW0;
|
||||||
|
U16 hwHW1;
|
||||||
|
}st2U16;
|
||||||
|
struct tst4U8
|
||||||
|
{
|
||||||
|
U8 bB0;
|
||||||
|
U8 bB1;
|
||||||
|
U8 bB2;
|
||||||
|
U8 bB3;
|
||||||
|
}st4U8;
|
||||||
|
}tunSU32;
|
||||||
|
|
||||||
|
#endif /* #ifdef _ASSEMBLER_ */
|
||||||
|
|
||||||
|
|
||||||
|
/******** DEFINITIONS FOR BOTH ASSEMBLER AND C ********/
|
||||||
|
|
||||||
|
|
||||||
|
#define NO_ERR 0x00000000 /* operation completed successfully */
|
||||||
|
#define ERR 0xffffffff /* operation completed not successfully */
|
||||||
|
|
||||||
|
#define False 0
|
||||||
|
#define True !False
|
||||||
|
|
||||||
|
#define NULL ((void *)0)
|
||||||
|
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
||||||
|
#define MAX(x,y) ((x) > (y) ? (x) : (y))
|
||||||
|
|
||||||
|
#define MAXUINT(w) (\
|
||||||
|
((w) == sizeof(U8)) ? 0xFFU :\
|
||||||
|
((w) == sizeof(U16)) ? 0xFFFFU :\
|
||||||
|
((w) == sizeof(U32)) ? 0xFFFFFFFFU : 0\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define MAXINT(w) (\
|
||||||
|
((w) == sizeof(S8)) ? 0x7F :\
|
||||||
|
((w) == sizeof(S16)) ? 0x7FFF :\
|
||||||
|
((w) == sizeof(S32)) ? 0x7FFFFFFF : 0\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define MSK(n) ((1 << (n)) - 1)
|
||||||
|
|
||||||
|
#define KUSEG_MSK 0x80000000
|
||||||
|
#define KSEG_MSK 0xE0000000
|
||||||
|
#define KUSEGBASE 0x00000000
|
||||||
|
#define KSEG0BASE 0x80000000
|
||||||
|
#define KSEG1BASE 0xA0000000
|
||||||
|
#define KSSEGBASE 0xC0000000
|
||||||
|
#define KSEG3BASE 0xE0000000
|
||||||
|
|
||||||
|
/* Below macros perform the following functions :
|
||||||
|
*
|
||||||
|
* KSEG0 : Converts KSEG0/1 or physical addr (below 0.5GB) to KSEG0.
|
||||||
|
* KSEG1 : Converts KSEG0/1 or physical addr (below 0.5GB) to KSEG1.
|
||||||
|
* PHYS : Converts KSEG0/1 or physical addr (below 0.5GB) to physical address.
|
||||||
|
* KSSEG : Not relevant for converting, but used for determining range.
|
||||||
|
* KSEG3 : Not relevant for converting, but used for determining range.
|
||||||
|
* KUSEG : Not relevant for converting, but used for determining range.
|
||||||
|
* KSEG0A : Same as KSEG0 but operates on register rather than constant.
|
||||||
|
* KSEG1A : Same as KSEG1 but operates on register rather than constant.
|
||||||
|
* PHYSA : Same as PHYS but operates on register rather than constant.
|
||||||
|
* CACHED : Alias for KSEG0 macro .
|
||||||
|
* (Note that KSEG0 cache attribute is determined by K0
|
||||||
|
* field of Config register, but this is typically cached).
|
||||||
|
* UNCACHED : Alias for KSEG1 macro .
|
||||||
|
*/
|
||||||
|
#ifdef _ASSEMBLER_
|
||||||
|
#define KSEG0(addr) (((addr) & ~KSEG_MSK) | KSEG0BASE)
|
||||||
|
#define KSEG1(addr) (((addr) & ~KSEG_MSK) | KSEG1BASE)
|
||||||
|
#define KSSEG(addr) (((addr) & ~KSEG_MSK) | KSSEGBASE)
|
||||||
|
#define KSEG3(addr) (((addr) & ~KSEG_MSK) | KSEG3BASE)
|
||||||
|
#define KUSEG(addr) (((addr) & ~KUSEG_MSK) | KUSEGBASE)
|
||||||
|
#define PHYS(addr) ( (addr) & ~KSEG_MSK)
|
||||||
|
#define KSEG0A(reg) and reg, ~KSEG_MSK; or reg, KSEG0BASE
|
||||||
|
#define KSEG1A(reg) and reg, ~KSEG_MSK; or reg, KSEG1BASE
|
||||||
|
#define PHYSA(reg) and reg, ~KSEG_MSK
|
||||||
|
#else
|
||||||
|
#define KSEG0(addr) (((U32)(addr) & ~KSEG_MSK) | KSEG0BASE)
|
||||||
|
#define KSEG1(addr) (((U32)(addr) & ~KSEG_MSK) | KSEG1BASE)
|
||||||
|
#define KSSEG(addr) (((U32)(addr) & ~KSEG_MSK) | KSSEGBASE)
|
||||||
|
#define KSEG3(addr) (((U32)(addr) & ~KSEG_MSK) | KSEG3BASE)
|
||||||
|
#define KUSEG(addr) (((U32)(addr) & ~KUSEG_MSK) | KUSEGBASE)
|
||||||
|
#define PHYS(addr) ((U32)(addr) & ~KSEG_MSK)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CACHED(addr) KSEG0(addr)
|
||||||
|
#define UNCACHED(addr) KSEG1(addr)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _ASSEMBLER_
|
||||||
|
/* Macroes to access variables at constant addresses
|
||||||
|
* Compensates for signed 16 bit displacement
|
||||||
|
* Typical use: li a0, HIKSEG1(ATLAS_ASCIIWORD)
|
||||||
|
* sw v1, LO_OFFS(ATLAS_ASCIIWORD)(a0)
|
||||||
|
*/
|
||||||
|
#define HIKSEG0(addr) ((KSEG0(addr) + 0x8000) & 0xffff0000)
|
||||||
|
#define HIKSEG1(addr) ((KSEG1(addr) + 0x8000) & 0xffff0000)
|
||||||
|
#define HI_PART(addr) (((addr) + 0x8000) & 0xffff0000)
|
||||||
|
#define LO_OFFS(addr) ((addr) & 0xffff)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Most/Least significant 32 bit from 64 bit double word */
|
||||||
|
#define HI32(data64) ((U32)(data64 >> 32))
|
||||||
|
#define LO32(data64) ((U32)(data64 & 0xFFFFFFFF))
|
||||||
|
|
||||||
|
#define REG8( addr ) (*(volatile U8 *) (addr))
|
||||||
|
#define REG16( addr ) (*(volatile U16 *)(addr))
|
||||||
|
#define REG32( addr ) (*(volatile U32 *)(addr))
|
||||||
|
#define REG64( addr ) (*(volatile U64 *)(addr))
|
||||||
|
|
||||||
|
|
||||||
|
/* Register field mapping */
|
||||||
|
#define REGFIELD(reg, rfld) (((reg) & rfld##_MSK) >> rfld##_SHF)
|
||||||
|
|
||||||
|
/* absolute register address, access */
|
||||||
|
#define REGA(addr) REG32(addr)
|
||||||
|
|
||||||
|
/* physical register address, access: base address + offsett */
|
||||||
|
#define REGP(base,phys) REG32( (U32)(base) + (phys) )
|
||||||
|
|
||||||
|
/* relative register address, access: base address + offsett */
|
||||||
|
#define REG(base,offs) REG32( (U32)(base) + offs##_##OFS )
|
||||||
|
|
||||||
|
/* relative register address, access: base address + offsett */
|
||||||
|
#define REG_8(base,offs) REG8( (U32)(base) + offs##_##OFS )
|
||||||
|
|
||||||
|
/* relative register address, access: base address + offsett */
|
||||||
|
#define REG_16(base,offs) REG16( (U32)(base) + offs##_##OFS )
|
||||||
|
|
||||||
|
/* relative register address, access: base address + offsett */
|
||||||
|
#define REG_64(base,offs) REG64( (U32)(base) + offs##_##OFS )
|
||||||
|
|
||||||
|
/**************************************
|
||||||
|
* Macroes not used by YAMON any more
|
||||||
|
* (kept for backwards compatibility)
|
||||||
|
*/
|
||||||
|
/* register read field */
|
||||||
|
#define REGARD(addr,fld) ((REGA(addr) & addr##_##fld##_##MSK) \
|
||||||
|
>> addr##_##fld##_##SHF)
|
||||||
|
|
||||||
|
/* register write numeric field value */
|
||||||
|
#define REGAWRI(addr,fld,intval) ((REGA(addr) & ~(addr##_##fld##_##MSK))\
|
||||||
|
| ((intval) << addr##_##fld##_##SHF))
|
||||||
|
|
||||||
|
/* register write enumerated field value */
|
||||||
|
#define REGAWRE(addr,fld,enumval) ((REGA(addr) & ~(addr##_##fld##_##MSK))\
|
||||||
|
| ((addr##_##fld##_##enumval) << addr##_##fld##_##SHF))
|
||||||
|
|
||||||
|
|
||||||
|
/* Examples:
|
||||||
|
*
|
||||||
|
* exccode = REGARD(CPU_CAUSE,EXC);
|
||||||
|
*
|
||||||
|
* REGA(SDR_CONTROL) = REGAWRI(OSG_CONTROL,TMO,17)
|
||||||
|
* | REGAWRE(OSG_CONTROL,DTYPE,PC1);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* register read field */
|
||||||
|
#define REGRD(base,offs,fld) ((REG(base,offs) & offs##_##fld##_##MSK) \
|
||||||
|
>> offs##_##fld##_##SHF)
|
||||||
|
|
||||||
|
/* register write numeric field value */
|
||||||
|
#define REGWRI(base,offs,fld,intval)((REG(base,offs)& ~(offs##_##fld##_##MSK))\
|
||||||
|
| (((intval) << offs##_##fld##_##SHF) & offs##_##fld##_##MSK))
|
||||||
|
|
||||||
|
/* register write enumerated field value */
|
||||||
|
#define REGWRE(base,offs,fld,enumval)((REG(base,offs) & ~(offs##_##fld##_##MSK))\
|
||||||
|
| ((offs##_##fld##_##enumval) << offs##_##fld##_##SHF))
|
||||||
|
|
||||||
|
|
||||||
|
/* physical register read field */
|
||||||
|
#define REGPRD(base,phys,fld) ((REGP(base,phys) & phys##_##fld##_##MSK) \
|
||||||
|
>> phys##_##fld##_##SHF)
|
||||||
|
|
||||||
|
/* physical register write numeric field value */
|
||||||
|
#define REGPWRI(base,phys,fld,intval)((REGP(base,phys)& ~(phys##_##fld##_##MSK))\
|
||||||
|
| ((intval) << phys##_##fld##_##SHF))
|
||||||
|
|
||||||
|
/* physical register write enumerated field value */
|
||||||
|
#define REGPWRE(base,phys,fld,enumval)((REGP(base,phys) & ~(phys##_##fld##_##MSK))\
|
||||||
|
| ((phys##_##fld##_##enumval) << phys##_##fld##_##SHF))
|
||||||
|
/*
|
||||||
|
* End of macroes not used by YAMON any more
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
/* Endian related macros */
|
||||||
|
|
||||||
|
#define SWAP_BYTEADDR32( addr ) ( (addr) ^ 0x3 )
|
||||||
|
#define SWAP_U16ADDR32( addr ) ( (addr) ^ 0x2 )
|
||||||
|
|
||||||
|
/* Set byte address to little endian format */
|
||||||
|
#ifdef EL
|
||||||
|
#define SWAP_BYTEADDR_EL(addr) addr
|
||||||
|
#else
|
||||||
|
#define SWAP_BYTEADDR_EL(addr) SWAP_BYTEADDR32( addr )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set byte address to big endian format */
|
||||||
|
#ifdef EB
|
||||||
|
#define SWAP_BYTEADDR_EB(addr) addr
|
||||||
|
#else
|
||||||
|
#define SWAP_BYTEADDR_EB(addr) SWAP_BYTEADDR32( addr )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set U16 address to little endian format */
|
||||||
|
#ifdef EL
|
||||||
|
#define SWAP_U16ADDR_EL(addr) addr
|
||||||
|
#else
|
||||||
|
#define SWAP_U16ADDR_EL(addr) SWAP_U16ADDR32( addr )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set U16 address to big endian format */
|
||||||
|
#ifdef EB
|
||||||
|
#define SWAP_U16ADDR_EB(addr) addr
|
||||||
|
#else
|
||||||
|
#define SWAP_U16ADDR_EB(addr) SWAP_U16ADDR32( addr )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef EL
|
||||||
|
#define REGW32LE(addr, data) REG32(addr) = (data)
|
||||||
|
#define REGR32LE(addr, data) (data) = REG32(addr)
|
||||||
|
#else
|
||||||
|
#define REGW32LE(addr, data) REG32(addr) = SWAPEND32(data)
|
||||||
|
#define REGR32LE(addr, data) (data) = REG32(addr), (data) = SWAPEND32(data)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set of 'LE'-macros, convert by BE: */
|
||||||
|
#ifdef EL
|
||||||
|
#define CPU_TO_LE32( value ) (value)
|
||||||
|
#define LE32_TO_CPU( value ) (value)
|
||||||
|
|
||||||
|
#define CPU_TO_LE16( value ) (value)
|
||||||
|
#define LE16_TO_CPU( value ) (value)
|
||||||
|
#else
|
||||||
|
#define CPU_TO_LE32( value ) ( ( ((U32)value) << 24) | \
|
||||||
|
((0x0000FF00UL & ((U32)value)) << 8) | \
|
||||||
|
((0x00FF0000UL & ((U32)value)) >> 8) | \
|
||||||
|
( ((U32)value) >> 24) )
|
||||||
|
#define LE32_TO_CPU( value ) CPU_TO_LE32( value )
|
||||||
|
|
||||||
|
#define CPU_TO_LE16( value ) ( ((U16)(((U16)value) << 8)) | \
|
||||||
|
((U16)(((U16)value) >> 8)) )
|
||||||
|
#define LE16_TO_CPU( value ) CPU_TO_LE16( value )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set of 'BE'-macros, convert by LE: */
|
||||||
|
#ifdef EB
|
||||||
|
#define CPU_TO_BE32( value ) (value)
|
||||||
|
#define BE32_TO_CPU( value ) (value)
|
||||||
|
|
||||||
|
#define CPU_TO_BE16( value ) (value)
|
||||||
|
#define BE16_TO_CPU( value ) (value)
|
||||||
|
#else
|
||||||
|
#define CPU_TO_BE32( value ) ( ( ((U32)value) << 24) | \
|
||||||
|
((0x0000FF00UL & ((U32)value)) << 8) | \
|
||||||
|
((0x00FF0000UL & ((U32)value)) >> 8) | \
|
||||||
|
( ((U32)value) >> 24) )
|
||||||
|
#define BE32_TO_CPU( value ) CPU_TO_BE32( value )
|
||||||
|
|
||||||
|
#define CPU_TO_BE16( value ) ( ((U16)(((U16)value) << 8)) | \
|
||||||
|
((U16)(((U16)value) >> 8)) )
|
||||||
|
#define BE16_TO_CPU( value ) CPU_TO_BE16( value )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Control characters */
|
||||||
|
#define CTRL_A ('A'-0x40)
|
||||||
|
#define CTRL_B ('B'-0x40)
|
||||||
|
#define CTRL_C ('C'-0x40)
|
||||||
|
#define CTRL_D ('D'-0x40)
|
||||||
|
#define CTRL_E ('E'-0x40)
|
||||||
|
#define CTRL_F ('F'-0x40)
|
||||||
|
#define CTRL_H ('H'-0x40)
|
||||||
|
#define CTRL_K ('K'-0x40)
|
||||||
|
#define CTRL_N ('N'-0x40)
|
||||||
|
#define CTRL_P ('P'-0x40)
|
||||||
|
#define CTRL_U ('U'-0x40)
|
||||||
|
#define BACKSPACE 0x08
|
||||||
|
#define DEL 0x7F
|
||||||
|
#define TAB 0x09
|
||||||
|
#define CR 0x0D /* Enter Key */
|
||||||
|
#define LF 0x0A
|
||||||
|
#define ESC 0x1B
|
||||||
|
#define SP 0x20
|
||||||
|
#define CSI 0x9B
|
||||||
|
|
||||||
|
|
||||||
|
/* DEF2STR(x) converts #define symbol to string */
|
||||||
|
#define DEF2STR1(x) #x
|
||||||
|
#define DEF2STR(x) DEF2STR1(x)
|
||||||
|
|
||||||
|
|
||||||
|
/* ********************************************************************* */
|
||||||
|
/* Interface function definition */
|
||||||
|
|
||||||
|
|
||||||
|
/* ********************************************************************* */
|
||||||
|
|
||||||
|
#endif /*__SYSDEFS_H__*/
|
46
flash-tool/device_stage2/include/udc.h
Normal file
46
flash-tool/device_stage2/include/udc.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#ifndef __UDC_H__
|
||||||
|
#define __UDC_H__
|
||||||
|
|
||||||
|
#include "usb.h"
|
||||||
|
#define MAX_EP0_SIZE 64
|
||||||
|
#define MAX_EP1_SIZE 512
|
||||||
|
|
||||||
|
#define USB_HS 0
|
||||||
|
#define USB_FS 1
|
||||||
|
#define USB_LS 2
|
||||||
|
|
||||||
|
//definitions of EP0
|
||||||
|
#define USB_EP0_IDLE 0
|
||||||
|
#define USB_EP0_RX 1
|
||||||
|
#define USB_EP0_TX 2
|
||||||
|
/* Define maximum packet size for endpoint 0 */
|
||||||
|
#define M_EP0_MAXP 64
|
||||||
|
/* Endpoint 0 status structure */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static __inline__ void usb_setb(u32 port, u8 val)
|
||||||
|
{
|
||||||
|
volatile u8 *ioport = (volatile u8 *)(port);
|
||||||
|
*ioport = (*ioport) | val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ void usb_clearb(u32 port, u8 val)
|
||||||
|
{
|
||||||
|
volatile u8 *ioport = (volatile u8 *)(port);
|
||||||
|
*ioport = (*ioport) & ~val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ void usb_setw(u32 port, u16 val)
|
||||||
|
{
|
||||||
|
volatile u16 *ioport = (volatile u16 *)(port);
|
||||||
|
*ioport = (*ioport) | val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ void usb_clearw(u32 port, u16 val)
|
||||||
|
{
|
||||||
|
volatile u16 *ioport = (volatile u16 *)(port);
|
||||||
|
*ioport = (*ioport) & ~val;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //__UDC_H__
|
207
flash-tool/device_stage2/include/usb.h
Normal file
207
flash-tool/device_stage2/include/usb.h
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
#ifndef __USB_H
|
||||||
|
#define __USB_H
|
||||||
|
|
||||||
|
#ifndef u8
|
||||||
|
#define u8 unsigned char
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef u16
|
||||||
|
#define u16 unsigned short
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef u32
|
||||||
|
#define u32 unsigned int
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef s8
|
||||||
|
#define s8 char
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef s16
|
||||||
|
#define s16 short
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef s32
|
||||||
|
#define s32 int
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int usbdebug;
|
||||||
|
|
||||||
|
enum USB_ENDPOINT_TYPE
|
||||||
|
{
|
||||||
|
ENDPOINT_TYPE_CONTROL,
|
||||||
|
/* Typically used to configure a device when attached to the host.
|
||||||
|
* It may also be used for other device specific purposes, including
|
||||||
|
* control of other pipes on the device.
|
||||||
|
*/
|
||||||
|
ENDPOINT_TYPE_ISOCHRONOUS,
|
||||||
|
/* Typically used for applications which need guaranteed speed.
|
||||||
|
* Isochronous transfer is fast but with possible data loss. A typical
|
||||||
|
* use is audio data which requires a constant data rate.
|
||||||
|
*/
|
||||||
|
ENDPOINT_TYPE_BULK,
|
||||||
|
/* Typically used by devices that generate or consume data in relatively
|
||||||
|
* large and bursty quantities. Bulk transfer has wide dynamic latitude
|
||||||
|
* in transmission constraints. It can use all remaining available bandwidth,
|
||||||
|
* but with no guarantees on bandwidth or latency. Since the USB bus is
|
||||||
|
* normally not very busy, there is typically 90% or more of the bandwidth
|
||||||
|
* available for USB transfers.
|
||||||
|
*/
|
||||||
|
ENDPOINT_TYPE_INTERRUPT
|
||||||
|
/* Typically used by devices that need guaranteed quick responses
|
||||||
|
* (bounded latency).
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum USB_STANDARD_REQUEST_CODE {
|
||||||
|
GET_STATUS,
|
||||||
|
CLEAR_FEATURE,
|
||||||
|
SET_FEATURE = 3,
|
||||||
|
SET_ADDRESS = 5,
|
||||||
|
GET_DESCRIPTOR,
|
||||||
|
SET_DESCRIPTOR,
|
||||||
|
GET_CONFIGURATION,
|
||||||
|
SET_CONFIGURATION,
|
||||||
|
GET_INTERFACE,
|
||||||
|
SET_INTERFACE,
|
||||||
|
SYNCH_FRAME
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum USB_DESCRIPTOR_TYPE {
|
||||||
|
DEVICE_DESCRIPTOR = 1,
|
||||||
|
CONFIGURATION_DESCRIPTOR,
|
||||||
|
STRING_DESCRIPTOR,
|
||||||
|
INTERFACE_DESCRIPTOR,
|
||||||
|
ENDPOINT_DESCRIPTOR,
|
||||||
|
DEVICE_QUALIFIER_DESCRIPTOR,
|
||||||
|
OTHER_SPEED_CONFIGURATION_DESCRIPTOR,
|
||||||
|
INTERFACE_POWER1_DESCRIPTOR
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum USB_FEATURE_SELECTOR {
|
||||||
|
ENDPOINT_HALT,
|
||||||
|
DEVICE_REMOTE_WAKEUP,
|
||||||
|
TEST_MODE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum USB_CLASS_CODE {
|
||||||
|
CLASS_DEVICE,
|
||||||
|
CLASS_AUDIO,
|
||||||
|
CLASS_COMM_AND_CDC_CONTROL,
|
||||||
|
CLASS_HID,
|
||||||
|
CLASS_PHYSICAL = 0x05,
|
||||||
|
CLASS_STILL_IMAGING,
|
||||||
|
CLASS_PRINTER,
|
||||||
|
CLASS_MASS_STORAGE,
|
||||||
|
CLASS_HUB,
|
||||||
|
CLASS_CDC_DATA,
|
||||||
|
CLASS_SMART_CARD,
|
||||||
|
CLASS_CONTENT_SECURITY = 0x0d,
|
||||||
|
CLASS_VIDEO,
|
||||||
|
CLASS_DIAGNOSTIC_DEVICE = 0xdc,
|
||||||
|
CLASS_WIRELESS_CONTROLLER = 0xe0,
|
||||||
|
CLASS_MISCELLANEOUS = 0xef,
|
||||||
|
CLASS_APP_SPECIFIC = 0xfe,
|
||||||
|
CLASS_VENDOR_SPECIFIC = 0xff
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 bmRequestType;
|
||||||
|
u8 bRequest;
|
||||||
|
u16 wValue;
|
||||||
|
u16 wIndex;
|
||||||
|
u16 wLength;
|
||||||
|
} __attribute__ ((packed)) USB_DeviceRequest;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 bLength;
|
||||||
|
u8 bDescriptorType;
|
||||||
|
u16 bcdUSB;
|
||||||
|
u8 bDeviceClass;
|
||||||
|
u8 bDeviceSubClass;
|
||||||
|
u8 bDeviceProtocol;
|
||||||
|
u8 bMaxPacketSize0;
|
||||||
|
u16 idVendor;
|
||||||
|
u16 idProduct;
|
||||||
|
u16 bcdDevice;
|
||||||
|
u8 iManufacturer;
|
||||||
|
u8 iProduct;
|
||||||
|
u8 iSerialNumber;
|
||||||
|
u8 bNumConfigurations;
|
||||||
|
} __attribute__ ((packed)) USB_DeviceDescriptor;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 bLength;
|
||||||
|
u8 bDescriptorType;
|
||||||
|
u16 bcdUSB;
|
||||||
|
u8 bDeviceClass;
|
||||||
|
u8 bDeviceSubClass;
|
||||||
|
u8 bDeviceProtocol;
|
||||||
|
u8 bMaxPacketSize0;
|
||||||
|
u8 bNumConfigurations;
|
||||||
|
u8 bReserved;
|
||||||
|
} __attribute__ ((packed)) USB_DeviceQualifierDescriptor;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 bLength;
|
||||||
|
u8 bDescriptorType;
|
||||||
|
u16 wTotalLength;
|
||||||
|
u8 bNumInterfaces;
|
||||||
|
u8 bConfigurationValue;
|
||||||
|
u8 iConfiguration;
|
||||||
|
u8 bmAttributes;
|
||||||
|
u8 MaxPower;
|
||||||
|
} __attribute__ ((packed)) USB_ConfigDescriptor;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 bLength;
|
||||||
|
u8 bDescriptorType;
|
||||||
|
u16 wTotalLength;
|
||||||
|
u8 bNumInterfaces;
|
||||||
|
u8 bConfigurationValue;
|
||||||
|
u8 iConfiguration;
|
||||||
|
u8 bmAttributes;
|
||||||
|
u8 bMaxPower;
|
||||||
|
} __attribute__ ((packed)) USB_OtherSpeedConfigDescriptor;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 bLength;
|
||||||
|
u8 bDescriptorType;
|
||||||
|
u8 bInterfaceNumber;
|
||||||
|
u8 bAlternateSetting;
|
||||||
|
u8 bNumEndpoints;
|
||||||
|
u8 bInterfaceClass;
|
||||||
|
u8 bInterfaceSubClass;
|
||||||
|
u8 bInterfaceProtocol;
|
||||||
|
u8 iInterface;
|
||||||
|
} __attribute__ ((packed)) USB_InterfaceDescriptor;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 bLegth;
|
||||||
|
u8 bDescriptorType;
|
||||||
|
u8 bEndpointAddress;
|
||||||
|
u8 bmAttributes;
|
||||||
|
u16 wMaxPacketSize;
|
||||||
|
u8 bInterval;
|
||||||
|
} __attribute__ ((packed)) USB_EndPointDescriptor;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 bLength;
|
||||||
|
u8 bDescriptorType;
|
||||||
|
u16 SomeDesriptor[1];
|
||||||
|
} __attribute__ ((packed)) USB_StringDescriptor;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !defined(__USB_H)
|
||||||
|
|
98
flash-tool/device_stage2/include/usb_boot.h
Normal file
98
flash-tool/device_stage2/include/usb_boot.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#ifndef __USB_BOOT_H
|
||||||
|
#define __USB_BOOT_H
|
||||||
|
|
||||||
|
//#define dprintf(x...)
|
||||||
|
//printf(x);
|
||||||
|
|
||||||
|
#define BULK_OUT_BUF_SIZE 0x21000 //buffer size :
|
||||||
|
#define BULK_IN_BUF_SIZE 0x21000 // too
|
||||||
|
|
||||||
|
enum UDC_STATE
|
||||||
|
{
|
||||||
|
IDLE,
|
||||||
|
BULK_IN,
|
||||||
|
BULK_OUT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum USB_JZ4740_REQUEST //add for USB_BOOT
|
||||||
|
{
|
||||||
|
VR_GET_CUP_INFO = 0,
|
||||||
|
VR_SET_DATA_ADDERSS,
|
||||||
|
VR_SET_DATA_LENGTH,
|
||||||
|
VR_FLUSH_CACHES,
|
||||||
|
VR_PROGRAM_START1,
|
||||||
|
VR_PROGRAM_START2,
|
||||||
|
VR_NOR_OPS,
|
||||||
|
VR_NAND_OPS,
|
||||||
|
VR_SDRAM_OPS,
|
||||||
|
VR_CONFIGRATION
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NOR_OPS_TYPE
|
||||||
|
{
|
||||||
|
NOR_INIT = 0,
|
||||||
|
NOR_QUERY,
|
||||||
|
NOR_WRITE,
|
||||||
|
NOR_ERASE_CHIP,
|
||||||
|
NOR_ERASE_SECTOR
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NOR_FLASH_TYPE
|
||||||
|
{
|
||||||
|
NOR_AM29 = 0,
|
||||||
|
NOR_SST28,
|
||||||
|
NOR_SST39x16,
|
||||||
|
NOR_SST39x8
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NAND_OPS_TYPE
|
||||||
|
{
|
||||||
|
NAND_QUERY = 0,
|
||||||
|
NAND_INIT,
|
||||||
|
NAND_MARK_BAD,
|
||||||
|
NAND_READ_OOB,
|
||||||
|
NAND_READ_RAW,
|
||||||
|
NAND_ERASE,
|
||||||
|
NAND_READ,
|
||||||
|
NAND_PROGRAM,
|
||||||
|
NAND_READ_TO_RAM
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SDRAM_OPS_TYPE
|
||||||
|
{
|
||||||
|
SDRAM_LOAD,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
enum DATA_STRUCTURE_OB
|
||||||
|
{
|
||||||
|
DS_flash_info ,
|
||||||
|
DS_hand
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*typedef enum _USB_BOOT_STATUS
|
||||||
|
{
|
||||||
|
USB_NO_ERR =0 ,
|
||||||
|
GET_CPU_INFO_ERR,
|
||||||
|
SET_DATA_ADDRESS_ERR,
|
||||||
|
SET_DATA_LENGTH_ERR,
|
||||||
|
FLUSH_CAHCES_ERR,
|
||||||
|
PROGRAM_START1_ERR,
|
||||||
|
PROGRAM_START2_ERR,
|
||||||
|
NOR_OPS_ERR,
|
||||||
|
NAND_OPS_ERR,
|
||||||
|
NOR_FLASHTYPE_ERR,
|
||||||
|
OPS_NOTSUPPORT_ERR
|
||||||
|
}USB_BOOT_STATUS;*/
|
||||||
|
|
||||||
|
enum OPTION
|
||||||
|
{
|
||||||
|
OOB_ECC,
|
||||||
|
OOB_NO_ECC,
|
||||||
|
NO_OOB,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
811
flash-tool/device_stage2/nandflash/nandflash_4740.c
Normal file
811
flash-tool/device_stage2/nandflash/nandflash_4740.c
Normal file
@ -0,0 +1,811 @@
|
|||||||
|
#include "nandflash.h"
|
||||||
|
#include "jz4740.h"
|
||||||
|
#include "usb_boot.h"
|
||||||
|
#include "hand.h"
|
||||||
|
|
||||||
|
#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
|
||||||
|
#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
|
||||||
|
#define __nand_ecc_rs_encoding() (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING)
|
||||||
|
#define __nand_ecc_rs_decoding() (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_DECODING)
|
||||||
|
#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
|
||||||
|
#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF))
|
||||||
|
#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF))
|
||||||
|
|
||||||
|
#define __nand_ready() ((REG_GPIO_PXPIN(2) & 0x40000000) ? 1 : 0)
|
||||||
|
#define __nand_ecc() (REG_EMC_NFECC & 0x00ffffff)
|
||||||
|
#define __nand_cmd(n) (REG8(cmdport) = (n))
|
||||||
|
#define __nand_addr(n) (REG8(addrport) = (n))
|
||||||
|
#define __nand_data8() REG8(dataport)
|
||||||
|
#define __nand_data16() REG16(dataport)
|
||||||
|
|
||||||
|
#define CMD_READA 0x00
|
||||||
|
#define CMD_READB 0x01
|
||||||
|
#define CMD_READC 0x50
|
||||||
|
#define CMD_ERASE_SETUP 0x60
|
||||||
|
#define CMD_ERASE 0xD0
|
||||||
|
#define CMD_READ_STATUS 0x70
|
||||||
|
#define CMD_CONFIRM 0x30
|
||||||
|
#define CMD_SEQIN 0x80
|
||||||
|
#define CMD_PGPROG 0x10
|
||||||
|
#define CMD_READID 0x90
|
||||||
|
|
||||||
|
#define OOB_BAD_OFF 0x00
|
||||||
|
#define OOB_ECC_OFF 0x04
|
||||||
|
|
||||||
|
#define OP_ERASE 0
|
||||||
|
#define OP_WRITE 1
|
||||||
|
#define OP_READ 2
|
||||||
|
|
||||||
|
#define ECC_BLOCK 512
|
||||||
|
#define ECC_POS 6
|
||||||
|
#define PAR_SIZE 9
|
||||||
|
#define ECC_SIZE 36
|
||||||
|
|
||||||
|
static volatile unsigned char *gpio_base = (volatile unsigned char *)0xb0010000;
|
||||||
|
static volatile unsigned char *emc_base = (volatile unsigned char *)0xb3010000;
|
||||||
|
static volatile unsigned char *addrport = (volatile unsigned char *)0xb8010000;
|
||||||
|
static volatile unsigned char *dataport = (volatile unsigned char *)0xb8000000;
|
||||||
|
static volatile unsigned char *cmdport = (volatile unsigned char *)0xb8008000;
|
||||||
|
|
||||||
|
static int bus = 8, row = 2, pagesize = 2048, oobsize = 64, ppb = 128;
|
||||||
|
static int bad_block_pos,bad_block_page,force_erase,ecc_pos,wp_pin;
|
||||||
|
extern struct hand_t Hand;
|
||||||
|
//static u8 data_buf[2048] = {0};
|
||||||
|
static u8 oob_buf[256] = {0};
|
||||||
|
extern u16 handshake_PKT[4];
|
||||||
|
|
||||||
|
#define dprintf(x) serial_puts(x)
|
||||||
|
|
||||||
|
static unsigned int EMC_CSN[4]=
|
||||||
|
{
|
||||||
|
0xb8000000,
|
||||||
|
0xb4000000,
|
||||||
|
0xa8000000,
|
||||||
|
0xa4000000
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void __nand_sync(void)
|
||||||
|
{
|
||||||
|
unsigned int timeout = 100000;
|
||||||
|
while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--);
|
||||||
|
while (!(REG_GPIO_PXPIN(2) & 0x40000000));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void select_chip(int block)
|
||||||
|
{
|
||||||
|
int t;
|
||||||
|
if (!Hand.nand_bpc) return;
|
||||||
|
t = (block / Hand.nand_bpc) % 4;
|
||||||
|
addrport = (volatile unsigned char *)(EMC_CSN[t] + 0x10000);
|
||||||
|
dataport = (volatile unsigned char *)EMC_CSN[t];
|
||||||
|
cmdport = (volatile unsigned char *)(EMC_CSN[t] + 0x8000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_oob(void *buf, u32 size, u32 pg);
|
||||||
|
static int nand_data_write8(char *buf, int count);
|
||||||
|
static int nand_data_write16(char *buf, int count);
|
||||||
|
static int nand_data_read8(char *buf, int count);
|
||||||
|
static int nand_data_read16(char *buf, int count);
|
||||||
|
static int (*write_proc)(char *, int) = NULL;
|
||||||
|
static int (*read_proc)(char *, int) = NULL;
|
||||||
|
|
||||||
|
static nand_init_gpio(void)
|
||||||
|
{
|
||||||
|
//modify this fun to a specifical borad
|
||||||
|
//this fun init those gpio use by all flash chip
|
||||||
|
//select the gpio function related to flash chip
|
||||||
|
__gpio_as_nand();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void nand_enable_4740(unsigned int csn)
|
||||||
|
{
|
||||||
|
//modify this fun to a specifical borad
|
||||||
|
//this fun to enable the chip select pin csn
|
||||||
|
//the choosn chip can work after this fun
|
||||||
|
//dprintf("\n Enable chip select :%d",csn);
|
||||||
|
__nand_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void nand_disable_4740(unsigned int csn)
|
||||||
|
{
|
||||||
|
//modify this fun to a specifical borad
|
||||||
|
//this fun to enable the chip select pin csn
|
||||||
|
//the choosn chip can not work after this fun
|
||||||
|
//dprintf("\n Disable chip select :%d",csn);
|
||||||
|
__nand_disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int nand_query_4740(u8 *id)
|
||||||
|
{
|
||||||
|
__nand_sync();
|
||||||
|
__nand_cmd(CMD_READID);
|
||||||
|
__nand_addr(0);
|
||||||
|
|
||||||
|
id[0] = __nand_data8(); //VID
|
||||||
|
id[1] = __nand_data8(); //PID
|
||||||
|
id[2] = __nand_data8(); //CHIP ID
|
||||||
|
id[3] = __nand_data8(); //PAGE ID
|
||||||
|
id[4] = __nand_data8(); //PLANE ID
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nand_init_4740(int bus_width, int row_cycle, int page_size, int page_per_block,
|
||||||
|
int bbpage,int bbpos,int force,int ep)
|
||||||
|
{
|
||||||
|
bus = bus_width;
|
||||||
|
row = row_cycle;
|
||||||
|
pagesize = page_size;
|
||||||
|
oobsize = pagesize / 32;
|
||||||
|
ppb = page_per_block;
|
||||||
|
bad_block_pos = bbpos;
|
||||||
|
bad_block_page = bbpage;
|
||||||
|
force_erase = force;
|
||||||
|
ecc_pos = ep;
|
||||||
|
wp_pin = Hand.nand_wppin;
|
||||||
|
|
||||||
|
// nand_enable(0);
|
||||||
|
/* Initialize NAND Flash Pins */
|
||||||
|
if (wp_pin)
|
||||||
|
{
|
||||||
|
__gpio_as_output(wp_pin);
|
||||||
|
__gpio_disable_pull(wp_pin);
|
||||||
|
}
|
||||||
|
nand_init_gpio();
|
||||||
|
select_chip(0);
|
||||||
|
REG_EMC_SMCR1 = 0x0fff7700; //slow speed
|
||||||
|
// REG_EMC_SMCR1 = 0x04444400; //normal speed
|
||||||
|
// REG_EMC_SMCR1 = 0x0d221200; //fast speed
|
||||||
|
|
||||||
|
if (bus == 8) {
|
||||||
|
write_proc = nand_data_write8;
|
||||||
|
read_proc = nand_data_read8;
|
||||||
|
} else {
|
||||||
|
write_proc = nand_data_write16;
|
||||||
|
read_proc = nand_data_read16;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nand_fini_4740(void)
|
||||||
|
{
|
||||||
|
__nand_disable();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read oob <pagenum> pages from <startpage> page.
|
||||||
|
* Don't skip bad block.
|
||||||
|
* Don't use HW ECC.
|
||||||
|
*/
|
||||||
|
u32 nand_read_oob_4740(void *buf, u32 startpage, u32 pagenum)
|
||||||
|
{
|
||||||
|
u32 cnt, cur_page;
|
||||||
|
u8 *tmpbuf;
|
||||||
|
|
||||||
|
tmpbuf = (u8 *)buf;
|
||||||
|
|
||||||
|
cur_page = startpage;
|
||||||
|
cnt = 0;
|
||||||
|
while (cnt < pagenum) {
|
||||||
|
read_oob((void *)tmpbuf, oobsize, cur_page);
|
||||||
|
tmpbuf += oobsize;
|
||||||
|
cur_page++;
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cur_page;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nand_check_block(u32 block)
|
||||||
|
{
|
||||||
|
u32 pg,i;
|
||||||
|
|
||||||
|
if ( bad_block_page >= ppb ) //do absolute bad block detect!
|
||||||
|
{
|
||||||
|
pg = block * ppb + 0;
|
||||||
|
read_oob(oob_buf, oobsize, pg);
|
||||||
|
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
|
||||||
|
{
|
||||||
|
serial_puts("Absolute skip a bad block\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pg = block * ppb + 1;
|
||||||
|
read_oob(oob_buf, oobsize, pg);
|
||||||
|
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
|
||||||
|
{
|
||||||
|
serial_puts("Absolute skip a bad block\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pg = block * ppb + ppb - 2 ;
|
||||||
|
read_oob(oob_buf, oobsize, pg);
|
||||||
|
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
|
||||||
|
{
|
||||||
|
serial_puts("Absolute skip a bad block\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pg = block * ppb + ppb - 1 ;
|
||||||
|
read_oob(oob_buf, oobsize, pg);
|
||||||
|
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
|
||||||
|
{
|
||||||
|
serial_puts("Absolute skip a bad block\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pg = block * ppb + bad_block_page;
|
||||||
|
read_oob(oob_buf, oobsize, pg);
|
||||||
|
if (oob_buf[bad_block_pos] != 0xff)
|
||||||
|
{
|
||||||
|
serial_puts("Skip a bad block\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read data <pagenum> pages from <startpage> page.
|
||||||
|
* Don't skip bad block.
|
||||||
|
* Don't use HW ECC.
|
||||||
|
*/
|
||||||
|
u32 nand_read_raw_4740(void *buf, u32 startpage, u32 pagenum, int option)
|
||||||
|
{
|
||||||
|
u32 cnt, j;
|
||||||
|
u32 cur_page, rowaddr;
|
||||||
|
u8 *tmpbuf;
|
||||||
|
|
||||||
|
tmpbuf = (u8 *)buf;
|
||||||
|
|
||||||
|
cur_page = startpage;
|
||||||
|
cnt = 0;
|
||||||
|
while (cnt < pagenum) {
|
||||||
|
select_chip(cnt / ppb);
|
||||||
|
if ((cur_page % ppb) == 0) {
|
||||||
|
if (nand_check_block(cur_page / ppb)) {
|
||||||
|
cur_page += ppb; // Bad block, set to next block
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__nand_cmd(CMD_READA);
|
||||||
|
__nand_addr(0);
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_addr(0);
|
||||||
|
|
||||||
|
rowaddr = cur_page;
|
||||||
|
for (j = 0; j < row; j++) {
|
||||||
|
__nand_addr(rowaddr & 0xff);
|
||||||
|
rowaddr >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_cmd(CMD_CONFIRM);
|
||||||
|
|
||||||
|
__nand_sync();
|
||||||
|
read_proc(tmpbuf, pagesize);
|
||||||
|
|
||||||
|
tmpbuf += pagesize;
|
||||||
|
if (option != NO_OOB)
|
||||||
|
{
|
||||||
|
read_oob(tmpbuf, oobsize, cur_page);
|
||||||
|
tmpbuf += oobsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_page++;
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cur_page;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nand_erase_4740(int blk_num, int sblk, int force)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
u32 cur, rowaddr;
|
||||||
|
|
||||||
|
if (wp_pin)
|
||||||
|
__gpio_set_pin(wp_pin);
|
||||||
|
cur = sblk * ppb;
|
||||||
|
for (i = 0; i < blk_num; ) {
|
||||||
|
rowaddr = cur;
|
||||||
|
select_chip(cur / ppb);
|
||||||
|
if ( !force )
|
||||||
|
{
|
||||||
|
if (nand_check_block(cur/ppb))
|
||||||
|
{
|
||||||
|
cur += ppb;
|
||||||
|
blk_num += Hand.nand_plane;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__nand_cmd(CMD_ERASE_SETUP);
|
||||||
|
|
||||||
|
for (j = 0; j < row; j++) {
|
||||||
|
__nand_addr(rowaddr & 0xff);
|
||||||
|
rowaddr >>= 8;
|
||||||
|
}
|
||||||
|
__nand_cmd(CMD_ERASE);
|
||||||
|
__nand_sync();
|
||||||
|
__nand_cmd(CMD_READ_STATUS);
|
||||||
|
|
||||||
|
if (__nand_data8() & 0x01)
|
||||||
|
{
|
||||||
|
serial_puts("Erase fail at ");
|
||||||
|
serial_put_hex(cur / ppb);
|
||||||
|
nand_mark_bad_4740(cur/ppb);
|
||||||
|
cur += ppb;
|
||||||
|
blk_num += Hand.nand_plane;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cur += ppb;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wp_pin)
|
||||||
|
__gpio_clear_pin(wp_pin);
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_oob(void *buf, u32 size, u32 pg)
|
||||||
|
{
|
||||||
|
u32 i, coladdr, rowaddr;
|
||||||
|
|
||||||
|
select_chip(pg / ppb);
|
||||||
|
if (pagesize == 512)
|
||||||
|
coladdr = 0;
|
||||||
|
else
|
||||||
|
coladdr = pagesize;
|
||||||
|
|
||||||
|
if (pagesize == 512)
|
||||||
|
/* Send READOOB command */
|
||||||
|
__nand_cmd(CMD_READC);
|
||||||
|
else
|
||||||
|
/* Send READ0 command */
|
||||||
|
__nand_cmd(CMD_READA);
|
||||||
|
|
||||||
|
/* Send column address */
|
||||||
|
__nand_addr(coladdr & 0xff);
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_addr(coladdr >> 8);
|
||||||
|
|
||||||
|
/* Send page address */
|
||||||
|
rowaddr = pg;
|
||||||
|
for (i = 0; i < row; i++) {
|
||||||
|
__nand_addr(rowaddr & 0xff);
|
||||||
|
rowaddr >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send READSTART command for 2048 ps NAND */
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_cmd(CMD_CONFIRM);
|
||||||
|
|
||||||
|
/* Wait for device ready */
|
||||||
|
__nand_sync();
|
||||||
|
|
||||||
|
/* Read oob data */
|
||||||
|
read_proc(buf, size);
|
||||||
|
|
||||||
|
if (pagesize == 512)
|
||||||
|
__nand_sync();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rs_correct(unsigned char *buf, int idx, int mask)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
unsigned short d, d1, dm;
|
||||||
|
|
||||||
|
i = (idx * 9) >> 3;
|
||||||
|
j = (idx * 9) & 0x7;
|
||||||
|
|
||||||
|
i = (j == 0) ? (i - 1) : i;
|
||||||
|
j = (j == 0) ? 7 : (j - 1);
|
||||||
|
|
||||||
|
d = (buf[i] << 8) | buf[i - 1];
|
||||||
|
|
||||||
|
d1 = (d >> j) & 0x1ff;
|
||||||
|
d1 ^= mask;
|
||||||
|
|
||||||
|
dm = ~(0x1ff << j);
|
||||||
|
d = (d & dm) | (d1 << j);
|
||||||
|
|
||||||
|
buf[i - 1] = d & 0xff;
|
||||||
|
buf[i] = (d >> 8) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read data <pagenum> pages from <startpage> page.
|
||||||
|
* Skip bad block if detected.
|
||||||
|
* HW ECC is used.
|
||||||
|
*/
|
||||||
|
u32 nand_read_4740(void *buf, u32 startpage, u32 pagenum, int option)
|
||||||
|
{
|
||||||
|
u32 j, k;
|
||||||
|
u32 cur_page, cur_blk, cnt, rowaddr, ecccnt;
|
||||||
|
u8 *tmpbuf,flag = 0;
|
||||||
|
ecccnt = pagesize / ECC_BLOCK;
|
||||||
|
cur_page = startpage;
|
||||||
|
cnt = 0;
|
||||||
|
tmpbuf = buf;
|
||||||
|
handshake_PKT[3] = 0;
|
||||||
|
|
||||||
|
while (cnt < pagenum) {
|
||||||
|
select_chip(cnt / ppb);
|
||||||
|
/* If this is the first page of the block, check for bad. */
|
||||||
|
if ((cur_page % ppb) == 0) {
|
||||||
|
cur_blk = cur_page / ppb;
|
||||||
|
if (nand_check_block(cur_blk)) {
|
||||||
|
cur_page += ppb; // Bad block, set to next block
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* read oob first */
|
||||||
|
read_oob(oob_buf, oobsize, cur_page);
|
||||||
|
__nand_cmd(CMD_READA);
|
||||||
|
|
||||||
|
__nand_addr(0);
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_addr(0);
|
||||||
|
|
||||||
|
rowaddr = cur_page;
|
||||||
|
for (j = 0; j < row; j++) {
|
||||||
|
__nand_addr(rowaddr & 0xff);
|
||||||
|
rowaddr >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_cmd(CMD_CONFIRM);
|
||||||
|
|
||||||
|
__nand_sync();
|
||||||
|
|
||||||
|
for (j = 0; j < ecccnt; j++) {
|
||||||
|
volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0;
|
||||||
|
u32 stat;
|
||||||
|
flag = 0;
|
||||||
|
|
||||||
|
REG_EMC_NFINTS = 0x0;
|
||||||
|
__nand_ecc_rs_decoding();
|
||||||
|
read_proc(tmpbuf, ECC_BLOCK);
|
||||||
|
for (k = 0; k < PAR_SIZE; k++) {
|
||||||
|
*paraddr++ = oob_buf[ecc_pos + j*PAR_SIZE + k];
|
||||||
|
if (oob_buf[ecc_pos + j*PAR_SIZE + k] != 0xff)
|
||||||
|
flag = 1;
|
||||||
|
}
|
||||||
|
REG_EMC_NFECR |= EMC_NFECR_PRDY;
|
||||||
|
__nand_ecc_decode_sync();
|
||||||
|
__nand_ecc_disable();
|
||||||
|
/* Check decoding */
|
||||||
|
stat = REG_EMC_NFINTS;
|
||||||
|
if (stat & EMC_NFINTS_ERR) {
|
||||||
|
if (stat & EMC_NFINTS_UNCOR) {
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
// serial_puts("\nUncorrectable error occurred\n");
|
||||||
|
// serial_put_hex(cur_page);
|
||||||
|
handshake_PKT[3] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handshake_PKT[3] = 0;
|
||||||
|
u32 errcnt = (stat & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
|
||||||
|
switch (errcnt) {
|
||||||
|
case 4:
|
||||||
|
rs_correct(tmpbuf, (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
|
||||||
|
case 3:
|
||||||
|
rs_correct(tmpbuf, (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
|
||||||
|
case 2:
|
||||||
|
rs_correct(tmpbuf, (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
|
||||||
|
case 1:
|
||||||
|
rs_correct(tmpbuf, (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* increment pointer */
|
||||||
|
tmpbuf += ECC_BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (option)
|
||||||
|
{
|
||||||
|
case OOB_ECC:
|
||||||
|
for (j = 0; j < oobsize; j++)
|
||||||
|
tmpbuf[j] = oob_buf[j];
|
||||||
|
tmpbuf += oobsize;
|
||||||
|
break;
|
||||||
|
case OOB_NO_ECC:
|
||||||
|
for (j = 0; j < ecccnt * PAR_SIZE; j++)
|
||||||
|
oob_buf[ecc_pos + j] = 0xff;
|
||||||
|
for (j = 0; j < oobsize; j++)
|
||||||
|
tmpbuf[j] = oob_buf[j];
|
||||||
|
tmpbuf += oobsize;
|
||||||
|
break;
|
||||||
|
case NO_OOB:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_page++;
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
return cur_page;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nand_program_4740(void *context, int spage, int pages, int option)
|
||||||
|
{
|
||||||
|
u32 i, j, cur, rowaddr;
|
||||||
|
u8 *tmpbuf;
|
||||||
|
u32 ecccnt,oobsize_sav,ecccnt_sav,eccpos_sav;
|
||||||
|
u8 ecc_buf[256];
|
||||||
|
|
||||||
|
if (wp_pin)
|
||||||
|
__gpio_set_pin(wp_pin);
|
||||||
|
restart:
|
||||||
|
tmpbuf = (u8 *)context;
|
||||||
|
ecccnt_sav = ecccnt = pagesize / ECC_BLOCK;
|
||||||
|
oobsize_sav = oobsize;
|
||||||
|
eccpos_sav = ecc_pos;
|
||||||
|
i = 0;
|
||||||
|
cur = spage;
|
||||||
|
|
||||||
|
while (i < pages) {
|
||||||
|
select_chip(cur / ppb);
|
||||||
|
#if 1
|
||||||
|
if ((pagesize == 4096) && (cur < 8)) {
|
||||||
|
ecccnt = 4;
|
||||||
|
oobsize = 64;
|
||||||
|
ecc_pos = 6;
|
||||||
|
} else {
|
||||||
|
ecccnt = ecccnt_sav;
|
||||||
|
oobsize = oobsize_sav;
|
||||||
|
ecc_pos = eccpos_sav;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip 16KB after nand_spl if pagesize=4096 */
|
||||||
|
if ((pagesize == 4096) && (cur == 8))
|
||||||
|
tmpbuf += 16 * 1024;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((cur % ppb) == 0) {
|
||||||
|
if (nand_check_block(cur / ppb)) {
|
||||||
|
cur += ppb; // Bad block, set to next block
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( option != NO_OOB ) //if NO_OOB do not perform vaild check!
|
||||||
|
{
|
||||||
|
for ( j = 0 ; j < pagesize + oobsize; j ++)
|
||||||
|
{
|
||||||
|
if (tmpbuf[j] != 0xff)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( j == oobsize + pagesize )
|
||||||
|
{
|
||||||
|
tmpbuf += ( pagesize + oobsize ) ;
|
||||||
|
i ++;
|
||||||
|
cur ++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pagesize == 512)
|
||||||
|
__nand_cmd(CMD_READA);
|
||||||
|
|
||||||
|
__nand_cmd(CMD_SEQIN);
|
||||||
|
__nand_addr(0);
|
||||||
|
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_addr(0);
|
||||||
|
|
||||||
|
rowaddr = cur;
|
||||||
|
for (j = 0; j < row; j++) {
|
||||||
|
__nand_addr(rowaddr & 0xff);
|
||||||
|
rowaddr >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (option)
|
||||||
|
{
|
||||||
|
case OOB_ECC:
|
||||||
|
write_proc(tmpbuf, pagesize); //write data
|
||||||
|
tmpbuf += pagesize;
|
||||||
|
write_proc((u8 *)tmpbuf, oobsize); //write oob
|
||||||
|
tmpbuf += oobsize;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case OOB_NO_ECC:
|
||||||
|
for (j = 0; j < ecccnt; j++) {
|
||||||
|
volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
REG_EMC_NFINTS = 0x0;
|
||||||
|
__nand_ecc_rs_encoding();
|
||||||
|
write_proc(tmpbuf, ECC_BLOCK);
|
||||||
|
__nand_ecc_encode_sync();
|
||||||
|
__nand_ecc_disable();
|
||||||
|
|
||||||
|
/* Read PAR values */
|
||||||
|
for (k = 0; k < PAR_SIZE; k++) {
|
||||||
|
ecc_buf[j*PAR_SIZE+k] = *paraddr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpbuf += ECC_BLOCK;
|
||||||
|
}
|
||||||
|
for (j = 0; j < oobsize; j++) {
|
||||||
|
oob_buf[j] = tmpbuf[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < ecccnt*PAR_SIZE; j++)
|
||||||
|
oob_buf[ecc_pos + j] = ecc_buf[j];
|
||||||
|
write_proc((u8 *)oob_buf, oobsize);
|
||||||
|
tmpbuf += oobsize;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case NO_OOB: //bin image
|
||||||
|
/* write out data */
|
||||||
|
for (j = 0; j < ecccnt; j++) {
|
||||||
|
volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
REG_EMC_NFINTS = 0x0;
|
||||||
|
__nand_ecc_rs_encoding();
|
||||||
|
write_proc(tmpbuf, ECC_BLOCK);
|
||||||
|
__nand_ecc_encode_sync();
|
||||||
|
__nand_ecc_disable();
|
||||||
|
|
||||||
|
/* Read PAR values */
|
||||||
|
for (k = 0; k < PAR_SIZE; k++) {
|
||||||
|
ecc_buf[j*PAR_SIZE+k] = *paraddr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpbuf += ECC_BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < oobsize; j++) {
|
||||||
|
oob_buf[j] = 0xff;
|
||||||
|
}
|
||||||
|
oob_buf[2] = 0;
|
||||||
|
oob_buf[3] = 0;
|
||||||
|
oob_buf[4] = 0;
|
||||||
|
|
||||||
|
for (j = 0; j < ecccnt*PAR_SIZE; j++) {
|
||||||
|
oob_buf[ecc_pos + j] = ecc_buf[j];
|
||||||
|
}
|
||||||
|
write_proc((u8 *)oob_buf, oobsize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send program confirm command */
|
||||||
|
__nand_cmd(CMD_PGPROG);
|
||||||
|
__nand_sync();
|
||||||
|
|
||||||
|
__nand_cmd(CMD_READ_STATUS);
|
||||||
|
|
||||||
|
if (__nand_data8() & 0x01) /* page program error */
|
||||||
|
{
|
||||||
|
serial_puts("Skip a write fail block\n");
|
||||||
|
nand_erase_4740( 1, cur/ppb, 1); //force erase before
|
||||||
|
nand_mark_bad_4740(cur/ppb);
|
||||||
|
spage += ppb;
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
|
||||||
|
i ++;
|
||||||
|
cur ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wp_pin)
|
||||||
|
__gpio_clear_pin(wp_pin);
|
||||||
|
|
||||||
|
ecccnt = ecccnt_sav;
|
||||||
|
oobsize = oobsize_sav;
|
||||||
|
ecc_pos = eccpos_sav;
|
||||||
|
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 nand_mark_bad_page(u32 page)
|
||||||
|
{
|
||||||
|
u8 badbuf[4096 + 128];
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
if (wp_pin)
|
||||||
|
__gpio_set_pin(wp_pin);
|
||||||
|
//all set to 0x00
|
||||||
|
for (i = 0; i < pagesize + oobsize; i++)
|
||||||
|
badbuf[i] = 0x00;
|
||||||
|
|
||||||
|
__nand_cmd(CMD_READA);
|
||||||
|
__nand_cmd(CMD_SEQIN);
|
||||||
|
|
||||||
|
__nand_addr(0);
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_addr(0);
|
||||||
|
for (i = 0; i < row; i++) {
|
||||||
|
__nand_addr(page & 0xff);
|
||||||
|
page >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_proc((char *)badbuf, pagesize + oobsize);
|
||||||
|
__nand_cmd(CMD_PGPROG);
|
||||||
|
__nand_sync();
|
||||||
|
|
||||||
|
if (wp_pin)
|
||||||
|
__gpio_clear_pin(wp_pin);
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u32 nand_mark_bad_4740(int block)
|
||||||
|
{
|
||||||
|
u32 rowaddr;
|
||||||
|
|
||||||
|
// nand_erase_4740( 1, block, 1); //force erase before
|
||||||
|
if ( bad_block_page >= ppb ) //absolute bad block mark!
|
||||||
|
{ //mark four page!
|
||||||
|
rowaddr = block * ppb + 0;
|
||||||
|
nand_mark_bad_page(rowaddr);
|
||||||
|
|
||||||
|
rowaddr = block * ppb + 1;
|
||||||
|
nand_mark_bad_page(rowaddr);
|
||||||
|
|
||||||
|
rowaddr = block * ppb + ppb - 2;
|
||||||
|
nand_mark_bad_page(rowaddr);
|
||||||
|
|
||||||
|
rowaddr = block * ppb + ppb - 1;
|
||||||
|
nand_mark_bad_page(rowaddr);
|
||||||
|
}
|
||||||
|
else //mark one page only
|
||||||
|
{
|
||||||
|
rowaddr = block * ppb + bad_block_page;
|
||||||
|
nand_mark_bad_page(rowaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rowaddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nand_data_write8(char *buf, int count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u8 *p = (u8 *)buf;
|
||||||
|
for (i=0;i<count;i++)
|
||||||
|
__nand_data8() = *p++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nand_data_write16(char *buf, int count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u16 *p = (u16 *)buf;
|
||||||
|
for (i=0;i<count/2;i++)
|
||||||
|
__nand_data16() = *p++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nand_data_read8(char *buf, int count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u8 *p = (u8 *)buf;
|
||||||
|
for (i=0;i<count;i++)
|
||||||
|
*p++ = __nand_data8();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nand_data_read16(char *buf, int count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u16 *p = (u16 *)buf;
|
||||||
|
for (i=0;i<count/2;i++)
|
||||||
|
*p++ = __nand_data16();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
826
flash-tool/device_stage2/nandflash/nandflash_4750.c
Normal file
826
flash-tool/device_stage2/nandflash/nandflash_4750.c
Normal file
@ -0,0 +1,826 @@
|
|||||||
|
#include "jz4750.h"
|
||||||
|
#include "nandflash.h"
|
||||||
|
#include "usb_boot.h"
|
||||||
|
#include "hand.h"
|
||||||
|
|
||||||
|
#define dprintf(n...)
|
||||||
|
|
||||||
|
#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
|
||||||
|
#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
|
||||||
|
#define __nand_ready() ((REG_GPIO_PXPIN(2) & 0x08000000) ? 1 : 0)
|
||||||
|
#define __nand_cmd(n) (REG8(cmdport) = (n))
|
||||||
|
#define __nand_addr(n) (REG8(addrport) = (n))
|
||||||
|
#define __nand_data8() REG8(dataport)
|
||||||
|
#define __nand_data16() REG16(dataport)
|
||||||
|
|
||||||
|
#define CMD_READA 0x00
|
||||||
|
#define CMD_READB 0x01
|
||||||
|
#define CMD_READC 0x50
|
||||||
|
#define CMD_ERASE_SETUP 0x60
|
||||||
|
#define CMD_ERASE 0xD0
|
||||||
|
#define CMD_READ_STATUS 0x70
|
||||||
|
#define CMD_CONFIRM 0x30
|
||||||
|
#define CMD_SEQIN 0x80
|
||||||
|
#define CMD_PGPROG 0x10
|
||||||
|
#define CMD_READID 0x90
|
||||||
|
|
||||||
|
#define ECC_BLOCK 512
|
||||||
|
|
||||||
|
static volatile unsigned char *gpio_base = (volatile unsigned char *)0xb0010000;
|
||||||
|
static volatile unsigned char *emc_base = (volatile unsigned char *)0xb3010000;
|
||||||
|
static volatile unsigned char *addrport = (volatile unsigned char *)0xb8010000;
|
||||||
|
static volatile unsigned char *dataport = (volatile unsigned char *)0xb8000000;
|
||||||
|
static volatile unsigned char *cmdport = (volatile unsigned char *)0xb8008000;
|
||||||
|
|
||||||
|
static int bus = 8, row = 2, pagesize = 512, oobsize = 16, ppb = 32;
|
||||||
|
static int eccpos = 3, bchbit = 8, par_size = 13, forceerase = 1, wp_pin;
|
||||||
|
static int oobfs = 0; /* 1:store file system information in oob, 0:don't store */
|
||||||
|
static int oobecc = 0; /* Whether the oob data of the binary contains ECC data? */
|
||||||
|
static int bad_block_page = 127; /* Specify the page number of badblock flag inside a block */
|
||||||
|
static u32 bad_block_pos = 0; /* Specify the badblock flag offset inside the oob */
|
||||||
|
static u8 oob_buf[256] = {0};
|
||||||
|
extern struct hand_t Hand;
|
||||||
|
extern u16 handshake_PKT[4];
|
||||||
|
|
||||||
|
static inline void __nand_sync(void)
|
||||||
|
{
|
||||||
|
unsigned int timeout = 10000;
|
||||||
|
while ((REG_GPIO_PXPIN(2) & 0x08000000) && timeout--);
|
||||||
|
while (!(REG_GPIO_PXPIN(2) & 0x08000000));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_oob(void *buf, u32 size, u32 pg);
|
||||||
|
static int nand_data_write8(char *buf, int count);
|
||||||
|
static int nand_data_write16(char *buf, int count);
|
||||||
|
static int nand_data_read8(char *buf, int count);
|
||||||
|
static int nand_data_read16(char *buf, int count);
|
||||||
|
|
||||||
|
static int (*write_proc)(char *, int) = NULL;
|
||||||
|
static int (*read_proc)(char *, int) = NULL;
|
||||||
|
|
||||||
|
inline void nand_enable_4750(unsigned int csn)
|
||||||
|
{
|
||||||
|
//modify this fun to a specifical borad
|
||||||
|
//this fun to enable the chip select pin csn
|
||||||
|
//the choosn chip can work after this fun
|
||||||
|
//dprintf("\n Enable chip select :%d",csn);
|
||||||
|
__nand_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void nand_disable_4750(unsigned int csn)
|
||||||
|
{
|
||||||
|
//modify this fun to a specifical borad
|
||||||
|
//this fun to enable the chip select pin csn
|
||||||
|
//the choosn chip can not work after this fun
|
||||||
|
//dprintf("\n Disable chip select :%d",csn);
|
||||||
|
__nand_disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int nand_query_4750(u8 *id)
|
||||||
|
{
|
||||||
|
__nand_sync();
|
||||||
|
__nand_cmd(CMD_READID);
|
||||||
|
__nand_addr(0);
|
||||||
|
|
||||||
|
id[0] = __nand_data8(); //VID
|
||||||
|
id[1] = __nand_data8(); //PID
|
||||||
|
id[2] = __nand_data8(); //CHIP ID
|
||||||
|
id[3] = __nand_data8(); //PAGE ID
|
||||||
|
id[4] = __nand_data8(); //PLANE ID
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nand_init_4750(int bus_width, int row_cycle, int page_size, int page_per_block,
|
||||||
|
int bch_bit, int ecc_pos, int bad_pos, int bad_page, int force)
|
||||||
|
{
|
||||||
|
bus = bus_width;
|
||||||
|
row = row_cycle;
|
||||||
|
pagesize = page_size;
|
||||||
|
oobsize = pagesize / 32;
|
||||||
|
ppb = page_per_block;
|
||||||
|
bchbit = bch_bit;
|
||||||
|
forceerase = force;
|
||||||
|
eccpos = ecc_pos;
|
||||||
|
bad_block_pos = bad_pos;
|
||||||
|
bad_block_page = bad_page;
|
||||||
|
wp_pin = Hand.nand_wppin;
|
||||||
|
|
||||||
|
if (bchbit == 8)
|
||||||
|
par_size = 13;
|
||||||
|
else
|
||||||
|
par_size = 7;
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
gpio_base = (u8 *)gbase;
|
||||||
|
emc_base = (u8 *)ebase;
|
||||||
|
addrport = (u8 *)aport;
|
||||||
|
dataport = (u8 *)dport;
|
||||||
|
cmdport = (u8 *)cport;
|
||||||
|
#endif
|
||||||
|
/* Initialize NAND Flash Pins */
|
||||||
|
if (bus == 8) {
|
||||||
|
__gpio_as_nand_8bit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wp_pin)
|
||||||
|
{
|
||||||
|
__gpio_as_output(wp_pin);
|
||||||
|
__gpio_disable_pull(wp_pin);
|
||||||
|
}
|
||||||
|
__nand_enable();
|
||||||
|
|
||||||
|
// REG_EMC_SMCR1 = 0x0fff7700; //slow speed
|
||||||
|
REG_EMC_SMCR1 = 0x04444400; //normal speed
|
||||||
|
// REG_EMC_SMCR1 = 0x0d221200; //fast speed
|
||||||
|
|
||||||
|
/* If ECCPOS isn't configured in config file, the initial value is 0 */
|
||||||
|
if (eccpos == 0) {
|
||||||
|
eccpos = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bus == 8) {
|
||||||
|
write_proc = nand_data_write8;
|
||||||
|
read_proc = nand_data_read8;
|
||||||
|
} else {
|
||||||
|
write_proc = nand_data_write16;
|
||||||
|
read_proc = nand_data_read16;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nand_fini_4750(void)
|
||||||
|
{
|
||||||
|
__nand_disable();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read oob <pagenum> pages from <startpage> page.
|
||||||
|
* Don't skip bad block.
|
||||||
|
* Don't use HW ECC.
|
||||||
|
*/
|
||||||
|
u32 nand_read_oob_4750(void *buf, u32 startpage, u32 pagenum)
|
||||||
|
{
|
||||||
|
u32 cnt, cur_page;
|
||||||
|
u8 *tmpbuf;
|
||||||
|
|
||||||
|
tmpbuf = (u8 *)buf;
|
||||||
|
|
||||||
|
cur_page = startpage;
|
||||||
|
cnt = 0;
|
||||||
|
|
||||||
|
while (cnt < pagenum) {
|
||||||
|
read_oob((void *)tmpbuf, oobsize, cur_page);
|
||||||
|
tmpbuf += oobsize;
|
||||||
|
cur_page++;
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cur_page;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nand_check_block(u32 block)
|
||||||
|
{
|
||||||
|
u32 pg,i;
|
||||||
|
|
||||||
|
if ( bad_block_page >= ppb ) //do absolute bad block detect!
|
||||||
|
{
|
||||||
|
pg = block * ppb + 0;
|
||||||
|
read_oob(oob_buf, oobsize, pg);
|
||||||
|
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
|
||||||
|
{
|
||||||
|
serial_puts("Absolute skip a bad block\n");
|
||||||
|
serial_put_hex(block);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pg = block * ppb + 1;
|
||||||
|
read_oob(oob_buf, oobsize, pg);
|
||||||
|
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
|
||||||
|
{
|
||||||
|
serial_puts("Absolute skip a bad block\n");
|
||||||
|
serial_put_hex(block);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pg = block * ppb + ppb - 2 ;
|
||||||
|
read_oob(oob_buf, oobsize, pg);
|
||||||
|
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
|
||||||
|
{
|
||||||
|
serial_puts("Absolute skip a bad block\n");
|
||||||
|
serial_put_hex(block);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pg = block * ppb + ppb - 1 ;
|
||||||
|
read_oob(oob_buf, oobsize, pg);
|
||||||
|
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
|
||||||
|
{
|
||||||
|
serial_puts("Absolute skip a bad block\n");
|
||||||
|
serial_put_hex(block);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pg = block * ppb + bad_block_page;
|
||||||
|
read_oob(oob_buf, oobsize, pg);
|
||||||
|
if (oob_buf[bad_block_pos] != 0xff)
|
||||||
|
{
|
||||||
|
serial_puts("Skip a bad block at");
|
||||||
|
serial_put_hex(block);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read data <pagenum> pages from <startpage> page.
|
||||||
|
* Don't skip bad block.
|
||||||
|
* Don't use HW ECC.
|
||||||
|
*/
|
||||||
|
u32 nand_read_raw_4750(void *buf, u32 startpage, u32 pagenum, int option)
|
||||||
|
{
|
||||||
|
u32 cnt, j;
|
||||||
|
u32 cur_page, rowaddr;
|
||||||
|
u8 *tmpbuf;
|
||||||
|
|
||||||
|
tmpbuf = (u8 *)buf;
|
||||||
|
|
||||||
|
cur_page = startpage;
|
||||||
|
cnt = 0;
|
||||||
|
while (cnt < pagenum) {
|
||||||
|
if ((cur_page % ppb) == 0) {
|
||||||
|
if (nand_check_block(cur_page / ppb)) {
|
||||||
|
cur_page += ppb; // Bad block, set to next block
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__nand_cmd(CMD_READA);
|
||||||
|
__nand_addr(0);
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_addr(0);
|
||||||
|
|
||||||
|
rowaddr = cur_page;
|
||||||
|
for (j = 0; j < row; j++) {
|
||||||
|
__nand_addr(rowaddr & 0xff);
|
||||||
|
rowaddr >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_cmd(CMD_CONFIRM);
|
||||||
|
|
||||||
|
__nand_sync();
|
||||||
|
read_proc(tmpbuf, pagesize);
|
||||||
|
|
||||||
|
tmpbuf += pagesize;
|
||||||
|
if (option != NO_OOB)
|
||||||
|
{
|
||||||
|
read_oob(tmpbuf, oobsize, cur_page);
|
||||||
|
tmpbuf += oobsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_page++;
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cur_page;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u32 nand_erase_4750(int blk_num, int sblk, int force)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
u32 cur, rowaddr;
|
||||||
|
|
||||||
|
if (wp_pin)
|
||||||
|
__gpio_set_pin(wp_pin);
|
||||||
|
cur = sblk * ppb;
|
||||||
|
for (i = 0; i < blk_num; i++) {
|
||||||
|
rowaddr = cur;
|
||||||
|
|
||||||
|
if (!force) /* if set, erase anything */
|
||||||
|
if (nand_check_block(cur/ppb))
|
||||||
|
{
|
||||||
|
cur += ppb;
|
||||||
|
blk_num += Hand.nand_plane;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
__nand_cmd(CMD_ERASE_SETUP);
|
||||||
|
|
||||||
|
for (j = 0; j < row; j++) {
|
||||||
|
__nand_addr(rowaddr & 0xff);
|
||||||
|
rowaddr >>= 8;
|
||||||
|
}
|
||||||
|
__nand_cmd(CMD_ERASE);
|
||||||
|
__nand_sync();
|
||||||
|
__nand_cmd(CMD_READ_STATUS);
|
||||||
|
|
||||||
|
if (__nand_data8() & 0x01)
|
||||||
|
{
|
||||||
|
serial_puts("Erase fail at ");
|
||||||
|
serial_put_hex(cur / ppb);
|
||||||
|
nand_mark_bad_4750(cur / ppb);
|
||||||
|
cur += ppb;
|
||||||
|
blk_num += Hand.nand_plane;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cur += ppb;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wp_pin)
|
||||||
|
__gpio_clear_pin(wp_pin);
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_oob(void *buf, u32 size, u32 pg)
|
||||||
|
{
|
||||||
|
u32 i, coladdr, rowaddr;
|
||||||
|
|
||||||
|
if (pagesize == 512)
|
||||||
|
coladdr = 0;
|
||||||
|
else
|
||||||
|
coladdr = pagesize;
|
||||||
|
|
||||||
|
if (pagesize == 512)
|
||||||
|
/* Send READOOB command */
|
||||||
|
__nand_cmd(CMD_READC);
|
||||||
|
else
|
||||||
|
/* Send READ0 command */
|
||||||
|
__nand_cmd(CMD_READA);
|
||||||
|
|
||||||
|
/* Send column address */
|
||||||
|
__nand_addr(coladdr & 0xff);
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_addr(coladdr >> 8);
|
||||||
|
|
||||||
|
/* Send page address */
|
||||||
|
rowaddr = pg;
|
||||||
|
for (i = 0; i < row; i++) {
|
||||||
|
__nand_addr(rowaddr & 0xff);
|
||||||
|
rowaddr >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send READSTART command for 2048 or 4096 ps NAND */
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_cmd(CMD_CONFIRM);
|
||||||
|
|
||||||
|
/* Wait for device ready */
|
||||||
|
__nand_sync();
|
||||||
|
|
||||||
|
/* Read oob data */
|
||||||
|
read_proc(buf, size);
|
||||||
|
|
||||||
|
if (pagesize == 512)
|
||||||
|
__nand_sync();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bch_correct(unsigned char *dat, int idx)
|
||||||
|
{
|
||||||
|
int i, bit; // the 'bit' of i byte is error
|
||||||
|
i = (idx - 1) >> 3;
|
||||||
|
bit = (idx - 1) & 0x7;
|
||||||
|
dat[i] ^= (1 << bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read data <pagenum> pages from <startpage> page.
|
||||||
|
* Skip bad block if detected.
|
||||||
|
* HW ECC is used.
|
||||||
|
*/
|
||||||
|
u32 nand_read_4750(void *buf, u32 startpage, u32 pagenum, int option)
|
||||||
|
{
|
||||||
|
u32 j, k;
|
||||||
|
u32 cur_page, cur_blk, cnt, rowaddr, ecccnt;
|
||||||
|
u8 *tmpbuf, *p, flag = 0;
|
||||||
|
u32 oob_per_eccsize;
|
||||||
|
|
||||||
|
ecccnt = pagesize / ECC_BLOCK;
|
||||||
|
oob_per_eccsize = eccpos / ecccnt;
|
||||||
|
|
||||||
|
cur_page = startpage;
|
||||||
|
cnt = 0;
|
||||||
|
|
||||||
|
tmpbuf = buf;
|
||||||
|
|
||||||
|
while (cnt < pagenum) {
|
||||||
|
/* If this is the first page of the block, check for bad. */
|
||||||
|
if ((cur_page % ppb) == 0) {
|
||||||
|
cur_blk = cur_page / ppb;
|
||||||
|
if (nand_check_block(cur_blk)) {
|
||||||
|
cur_page += ppb; // Bad block, set to next block
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__nand_cmd(CMD_READA);
|
||||||
|
|
||||||
|
__nand_addr(0);
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_addr(0);
|
||||||
|
|
||||||
|
rowaddr = cur_page;
|
||||||
|
for (j = 0; j < row; j++) {
|
||||||
|
__nand_addr(rowaddr & 0xff);
|
||||||
|
rowaddr >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_cmd(CMD_CONFIRM);
|
||||||
|
|
||||||
|
__nand_sync();
|
||||||
|
|
||||||
|
/* Read data */
|
||||||
|
read_proc((char *)tmpbuf, pagesize);
|
||||||
|
|
||||||
|
/* read oob first */
|
||||||
|
read_proc((char *)oob_buf, oobsize);
|
||||||
|
|
||||||
|
for (j = 0; j < ecccnt; j++) {
|
||||||
|
u32 stat;
|
||||||
|
flag = 0;
|
||||||
|
REG_BCH_INTS = 0xffffffff;
|
||||||
|
|
||||||
|
if (cur_page >= 16384 / pagesize)
|
||||||
|
{
|
||||||
|
if (bchbit == 8)
|
||||||
|
{
|
||||||
|
__ecc_decoding_8bit();
|
||||||
|
par_size = 13;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__ecc_decoding_4bit();
|
||||||
|
par_size = 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__ecc_decoding_8bit();
|
||||||
|
par_size = 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option != NO_OOB)
|
||||||
|
__ecc_cnt_dec(ECC_BLOCK + oob_per_eccsize + par_size);
|
||||||
|
else
|
||||||
|
__ecc_cnt_dec(ECC_BLOCK + par_size);
|
||||||
|
|
||||||
|
for (k = 0; k < ECC_BLOCK; k++) {
|
||||||
|
REG_BCH_DR = tmpbuf[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option != NO_OOB) {
|
||||||
|
for (k = 0; k < oob_per_eccsize; k++) {
|
||||||
|
REG_BCH_DR = oob_buf[oob_per_eccsize * j + k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 0; k < par_size; k++) {
|
||||||
|
REG_BCH_DR = oob_buf[eccpos + j*par_size + k];
|
||||||
|
if (oob_buf[eccpos + j*par_size + k] != 0xff)
|
||||||
|
flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for completion */
|
||||||
|
__ecc_decode_sync();
|
||||||
|
__ecc_disable();
|
||||||
|
/* Check decoding */
|
||||||
|
stat = REG_BCH_INTS;
|
||||||
|
|
||||||
|
if (stat & BCH_INTS_ERR) {
|
||||||
|
if (stat & BCH_INTS_UNCOR) {
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
dprintf("Uncorrectable ECC error occurred\n");
|
||||||
|
handshake_PKT[3] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handshake_PKT[3] = 0;
|
||||||
|
unsigned int errcnt = (stat & BCH_INTS_ERRC_MASK) >> BCH_INTS_ERRC_BIT;
|
||||||
|
switch (errcnt) {
|
||||||
|
case 8:
|
||||||
|
dprintf("correct 8th error\n");
|
||||||
|
bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
|
||||||
|
case 7:
|
||||||
|
dprintf("correct 7th error\n");
|
||||||
|
bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
|
||||||
|
case 6:
|
||||||
|
dprintf("correct 6th error\n");
|
||||||
|
bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
|
||||||
|
case 5:
|
||||||
|
dprintf("correct 5th error\n");
|
||||||
|
bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
|
||||||
|
case 4:
|
||||||
|
dprintf("correct 4th error\n");
|
||||||
|
bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
|
||||||
|
case 3:
|
||||||
|
dprintf("correct 3th error\n");
|
||||||
|
bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
|
||||||
|
case 2:
|
||||||
|
dprintf("correct 2th error\n");
|
||||||
|
bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
|
||||||
|
case 1:
|
||||||
|
dprintf("correct 1th error\n");
|
||||||
|
bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dprintf("no error\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* increment pointer */
|
||||||
|
tmpbuf += ECC_BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (option)
|
||||||
|
{
|
||||||
|
case OOB_ECC:
|
||||||
|
for (j = 0; j < oobsize; j++)
|
||||||
|
tmpbuf[j] = oob_buf[j];
|
||||||
|
tmpbuf += oobsize;
|
||||||
|
break;
|
||||||
|
case OOB_NO_ECC:
|
||||||
|
for (j = 0; j < par_size * ecccnt; j++)
|
||||||
|
oob_buf[eccpos + j] = 0xff;
|
||||||
|
for (j = 0; j < oobsize; j++)
|
||||||
|
tmpbuf[j] = oob_buf[j];
|
||||||
|
tmpbuf += oobsize;
|
||||||
|
break;
|
||||||
|
case NO_OOB:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_page++;
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
return cur_page;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nand_program_4750(void *context, int spage, int pages, int option)
|
||||||
|
{
|
||||||
|
u32 i, j, cur_page, cur_blk, rowaddr;
|
||||||
|
u8 *tmpbuf;
|
||||||
|
u32 ecccnt;
|
||||||
|
u8 ecc_buf[256];
|
||||||
|
u32 oob_per_eccsize;
|
||||||
|
int eccpos_sav = eccpos, bchbit_sav = bchbit, par_size_sav = par_size;
|
||||||
|
int spl_size = 16 * 1024 / pagesize;
|
||||||
|
|
||||||
|
if (wp_pin)
|
||||||
|
__gpio_set_pin(wp_pin);
|
||||||
|
restart:
|
||||||
|
tmpbuf = (u8 *)context;
|
||||||
|
ecccnt = pagesize / ECC_BLOCK;
|
||||||
|
oob_per_eccsize = eccpos / ecccnt;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
cur_page = spage;
|
||||||
|
|
||||||
|
while (i < pages) {
|
||||||
|
if (cur_page < spl_size) {
|
||||||
|
bchbit = 8;
|
||||||
|
eccpos = 3;
|
||||||
|
par_size = 13;
|
||||||
|
} else if (cur_page >= spl_size) {
|
||||||
|
bchbit = bchbit_sav;
|
||||||
|
eccpos = eccpos_sav;
|
||||||
|
par_size = par_size_sav;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cur_page % ppb) == 0) { /* First page of block, test BAD. */
|
||||||
|
if (nand_check_block(cur_page / ppb)) {
|
||||||
|
cur_page += ppb; /* Bad block, set to next block */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( option != NO_OOB ) //if NO_OOB do not perform vaild check!
|
||||||
|
{
|
||||||
|
for ( j = 0 ; j < pagesize + oobsize; j ++)
|
||||||
|
{
|
||||||
|
if (tmpbuf[j] != 0xff)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( j == oobsize + pagesize )
|
||||||
|
{
|
||||||
|
tmpbuf += ( pagesize + oobsize ) ;
|
||||||
|
i ++;
|
||||||
|
cur_page ++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pagesize == 512)
|
||||||
|
__nand_cmd(CMD_READA);
|
||||||
|
|
||||||
|
__nand_cmd(CMD_SEQIN);
|
||||||
|
__nand_addr(0);
|
||||||
|
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_addr(0);
|
||||||
|
|
||||||
|
rowaddr = cur_page;
|
||||||
|
for (j = 0; j < row; j++) {
|
||||||
|
__nand_addr(rowaddr & 0xff);
|
||||||
|
rowaddr >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write out data */
|
||||||
|
for (j = 0; j < ecccnt; j++) {
|
||||||
|
volatile u8 *paraddr;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
paraddr = (volatile u8 *)BCH_PAR0;
|
||||||
|
|
||||||
|
REG_BCH_INTS = 0xffffffff;
|
||||||
|
|
||||||
|
if (bchbit == 8)
|
||||||
|
__ecc_encoding_8bit();
|
||||||
|
else
|
||||||
|
__ecc_encoding_4bit();
|
||||||
|
|
||||||
|
/* Set BCHCNT.DEC_COUNT to data block size in bytes */
|
||||||
|
if (option != NO_OOB)
|
||||||
|
__ecc_cnt_enc(ECC_BLOCK + oob_per_eccsize);
|
||||||
|
else
|
||||||
|
__ecc_cnt_enc(ECC_BLOCK);
|
||||||
|
|
||||||
|
/* Write data in data area to BCH */
|
||||||
|
for (k = 0; k < ECC_BLOCK; k++) {
|
||||||
|
REG_BCH_DR = tmpbuf[ECC_BLOCK * j + k];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write file system information in oob area to BCH */
|
||||||
|
if (option != NO_OOB)
|
||||||
|
{
|
||||||
|
for (k = 0; k < oob_per_eccsize; k++) {
|
||||||
|
REG_BCH_DR = tmpbuf[pagesize + oob_per_eccsize * j + k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__ecc_encode_sync();
|
||||||
|
__ecc_disable();
|
||||||
|
|
||||||
|
/* Read PAR values */
|
||||||
|
for (k = 0; k < par_size; k++) {
|
||||||
|
ecc_buf[j * par_size + k] = *paraddr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_proc((char *)&tmpbuf[ECC_BLOCK * j], ECC_BLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (option)
|
||||||
|
{
|
||||||
|
case OOB_ECC:
|
||||||
|
case OOB_NO_ECC:
|
||||||
|
for (j = 0; j < eccpos; j++) {
|
||||||
|
oob_buf[j] = tmpbuf[pagesize + j];
|
||||||
|
}
|
||||||
|
for (j = 0; j < ecccnt * par_size; j++) {
|
||||||
|
oob_buf[eccpos + j] = ecc_buf[j];
|
||||||
|
}
|
||||||
|
tmpbuf += pagesize + oobsize;
|
||||||
|
break;
|
||||||
|
case NO_OOB: //bin image
|
||||||
|
for (j = 0; j < ecccnt * par_size; j++) {
|
||||||
|
oob_buf[eccpos + j] = ecc_buf[j];
|
||||||
|
}
|
||||||
|
tmpbuf += pagesize;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write out oob buffer */
|
||||||
|
write_proc((u8 *)oob_buf, oobsize);
|
||||||
|
|
||||||
|
/* send program confirm command */
|
||||||
|
__nand_cmd(CMD_PGPROG);
|
||||||
|
__nand_sync();
|
||||||
|
|
||||||
|
__nand_cmd(CMD_READ_STATUS);
|
||||||
|
|
||||||
|
if (__nand_data8() & 0x01) /* page program error */
|
||||||
|
{
|
||||||
|
serial_puts("Skip a write fail block\n");
|
||||||
|
nand_erase_4750( 1, cur_page/ppb, 1); //force erase before
|
||||||
|
nand_mark_bad_4750(cur_page/ppb);
|
||||||
|
spage += ppb;
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
cur_page++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wp_pin)
|
||||||
|
__gpio_clear_pin(wp_pin);
|
||||||
|
bchbit = bchbit_sav;
|
||||||
|
eccpos = eccpos_sav;
|
||||||
|
par_size = par_size_sav;
|
||||||
|
|
||||||
|
return cur_page;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 nand_mark_bad_page(u32 page)
|
||||||
|
{
|
||||||
|
u8 badbuf[4096 + 128];
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
if (wp_pin)
|
||||||
|
__gpio_set_pin(wp_pin);
|
||||||
|
for (i = 0; i < pagesize + oobsize; i++)
|
||||||
|
badbuf[i] = 0x00;
|
||||||
|
//all set to 0x00
|
||||||
|
|
||||||
|
__nand_cmd(CMD_READA);
|
||||||
|
__nand_cmd(CMD_SEQIN);
|
||||||
|
|
||||||
|
__nand_addr(0);
|
||||||
|
if (pagesize != 512)
|
||||||
|
__nand_addr(0);
|
||||||
|
for (i = 0; i < row; i++) {
|
||||||
|
__nand_addr(page & 0xff);
|
||||||
|
page >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_proc((char *)badbuf, pagesize + oobsize);
|
||||||
|
__nand_cmd(CMD_PGPROG);
|
||||||
|
__nand_sync();
|
||||||
|
|
||||||
|
if (wp_pin)
|
||||||
|
__gpio_clear_pin(wp_pin);
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nand_mark_bad_4750(int block)
|
||||||
|
{
|
||||||
|
u32 rowaddr;
|
||||||
|
|
||||||
|
if ( bad_block_page >= ppb ) //absolute bad block mark!
|
||||||
|
{ //mark four page!
|
||||||
|
rowaddr = block * ppb + 0;
|
||||||
|
nand_mark_bad_page(rowaddr);
|
||||||
|
|
||||||
|
rowaddr = block * ppb + 1;
|
||||||
|
nand_mark_bad_page(rowaddr);
|
||||||
|
|
||||||
|
rowaddr = block * ppb + ppb - 2;
|
||||||
|
nand_mark_bad_page(rowaddr);
|
||||||
|
|
||||||
|
rowaddr = block * ppb + ppb - 1;
|
||||||
|
nand_mark_bad_page(rowaddr);
|
||||||
|
}
|
||||||
|
else //mark one page only
|
||||||
|
{
|
||||||
|
rowaddr = block * ppb + bad_block_page;
|
||||||
|
nand_mark_bad_page(rowaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rowaddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nand_data_write8(char *buf, int count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u8 *p = (u8 *)buf;
|
||||||
|
for (i=0;i<count;i++)
|
||||||
|
__nand_data8() = *p++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nand_data_write16(char *buf, int count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u16 *p = (u16 *)buf;
|
||||||
|
for (i=0;i<count/2;i++)
|
||||||
|
__nand_data16() = *p++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nand_data_read8(char *buf, int count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u8 *p = (u8 *)buf;
|
||||||
|
for (i=0;i<count;i++)
|
||||||
|
*p++ = __nand_data8();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nand_data_read16(char *buf, int count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u16 *p = (u16 *)buf;
|
||||||
|
for (i=0;i<count/2;i++)
|
||||||
|
*p++ = __nand_data16();
|
||||||
|
return 0;
|
||||||
|
}
|
32
flash-tool/device_stage2/target.ld
Normal file
32
flash-tool/device_stage2/target.ld
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
OUTPUT_ARCH(mips)
|
||||||
|
ENTRY(_start)
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
ram : ORIGIN = 0x80000000 , LENGTH = 3M
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
.text : { *(.text*) } > ram
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
.rodata : { *(.rodata*) } > ram
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
.sdata : { *(.sdata*) } > ram
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
.data : { *(.data*) *(.scommon*) *(.reginfo*) } > ram
|
||||||
|
|
||||||
|
_gp = ALIGN(16);
|
||||||
|
|
||||||
|
.got : { *(.got*) } > ram
|
||||||
|
_got_end = ABSOLUTE(.);
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
.sbss : { *(.sbss*) } > ram
|
||||||
|
.bss : { *(.bss*) } > ram
|
||||||
|
. = ALIGN (4);
|
||||||
|
}
|
||||||
|
|
351
flash-tool/device_stage2/usb_boot/boothandler.c
Normal file
351
flash-tool/device_stage2/usb_boot/boothandler.c
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
/* USB_BOOT Handle routines*/
|
||||||
|
|
||||||
|
#include"jz4740.h"
|
||||||
|
#include "usb.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "usb_boot.h"
|
||||||
|
#include "hand.h"
|
||||||
|
#include "nandflash.h"
|
||||||
|
#include "udc.h"
|
||||||
|
#define dprintf(x) serial_puts(x)
|
||||||
|
|
||||||
|
unsigned int (*nand_query)(u8 *);
|
||||||
|
int (*nand_init)(int bus_width, int row_cycle, int page_size, int page_per_block,
|
||||||
|
int,int,int,int);
|
||||||
|
int (*nand_fini)(void);
|
||||||
|
u32 (*nand_program)(void *context, int spage, int pages,int option);
|
||||||
|
u32 (*nand_erase)(int blk_num, int sblk, int force);
|
||||||
|
u32 (*nand_read)(void *buf, u32 startpage, u32 pagenum,int option);
|
||||||
|
u32 (*nand_read_oob)(void *buf, u32 startpage, u32 pagenum);
|
||||||
|
u32 (*nand_read_raw)(void *buf, u32 startpage, u32 pagenum,int);
|
||||||
|
u32 (*nand_mark_bad) (int bad);
|
||||||
|
void (*nand_enable) (unsigned int csn);
|
||||||
|
void (*nand_disable) (unsigned int csn);
|
||||||
|
|
||||||
|
struct hand_t Hand,*Hand_p;
|
||||||
|
extern u32 Bulk_out_buf[BULK_OUT_BUF_SIZE];
|
||||||
|
extern u32 Bulk_in_buf[BULK_IN_BUF_SIZE];
|
||||||
|
extern u16 handshake_PKT[4];
|
||||||
|
extern udc_state;
|
||||||
|
extern void *memset(void *, int , size_t);
|
||||||
|
extern void *memcpy(void *, const void *, size_t);
|
||||||
|
|
||||||
|
u32 ret_dat;
|
||||||
|
u32 start_addr; //program operation start address or sector
|
||||||
|
u32 ops_length; //number of operation unit ,in byte or sector
|
||||||
|
u32 ram_addr;
|
||||||
|
|
||||||
|
void config_flash_info()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_data(unsigned int *p, int size)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < size; i ++)
|
||||||
|
serial_put_hex(*p++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void config_hand()
|
||||||
|
{
|
||||||
|
struct hand_t *hand_p;
|
||||||
|
hand_p=(struct hand_t *)Bulk_out_buf;
|
||||||
|
memcpy(&Hand, (unsigned char *)Bulk_out_buf, sizeof(struct hand_t));
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
Hand.nand_bw=hand_p->nand_bw;
|
||||||
|
Hand.nand_rc=hand_p->nand_rc;
|
||||||
|
Hand.nand_ps=hand_p->nand_ps;
|
||||||
|
Hand.nand_ppb=hand_p->nand_ppb;
|
||||||
|
Hand.nand_force_erase=hand_p->nand_force_erase;
|
||||||
|
Hand.nand_pn=hand_p->nand_pn;
|
||||||
|
Hand.nand_os=hand_p->nand_os;
|
||||||
|
|
||||||
|
Hand.nand_eccpos=hand_p->nand_eccpos;
|
||||||
|
Hand.nand_bbpos=hand_p->nand_bbpos;
|
||||||
|
Hand.nand_bbpage=hand_p->nand_bbpage;
|
||||||
|
// memcpy( &Hand.fw_args, (unsigned char *)(start_addr + 0x8), 32 );
|
||||||
|
|
||||||
|
// serial_putc(Hand.nand_eccpos + 48);
|
||||||
|
// serial_putc(Hand.nand_bbpos + 48);
|
||||||
|
// serial_putc(Hand.nand_bbpage + 48);
|
||||||
|
/* dprintf("\n Hand : bw %d rc %d ps %d ppb %d erase %d pn %d os %d", */
|
||||||
|
/* Hand.nand_bw,Hand.nand_rc,Hand.nand_ps,Hand.nand_ppb,Hand.nand_force_erase,Hand.nand_pn,Hand.nand_os); */
|
||||||
|
serial_put_hex(Hand.fw_args.cpu_id);
|
||||||
|
serial_put_hex(Hand.fw_args.ext_clk);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int GET_CUP_INFO_Handle()
|
||||||
|
{
|
||||||
|
char temp1[8]="Boot4740",temp2[8]="Boot4750";
|
||||||
|
dprintf("\n GET_CPU_INFO!");
|
||||||
|
if ( Hand.fw_args.cpu_id == 0x4740 )
|
||||||
|
HW_SendPKT(0,temp1,8);
|
||||||
|
else
|
||||||
|
HW_SendPKT(0,temp2,8);
|
||||||
|
udc_state = IDLE;
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SET_DATA_ADDERSS_Handle(u8 *buf)
|
||||||
|
{
|
||||||
|
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
|
||||||
|
start_addr=(((u32)dreq->wValue)<<16)+(u32)dreq->wIndex;
|
||||||
|
dprintf("\n SET ADDRESS:");
|
||||||
|
serial_put_hex(start_addr);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SET_DATA_LENGTH_Handle(u8 *buf)
|
||||||
|
{
|
||||||
|
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
|
||||||
|
ops_length=(((u32)dreq->wValue)<<16)+(u32)dreq->wIndex;
|
||||||
|
dprintf("\n DATA_LENGTH :");
|
||||||
|
serial_put_hex(ops_length);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FLUSH_CACHES_Handle()
|
||||||
|
{
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PROGRAM_START1_Handle(u8 *buf)
|
||||||
|
{
|
||||||
|
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
|
||||||
|
ram_addr=(((u32)dreq->wValue)<<16)+(u32)dreq->wIndex;
|
||||||
|
//dprintf("\n RAM ADDRESS :%x", ram_addr);
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PROGRAM_START2_Handle(u8 *buf)
|
||||||
|
{
|
||||||
|
void (*f)(void);
|
||||||
|
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
|
||||||
|
f=(void *) ((((u32)dreq->wValue)<<16)+(u32)dreq->wIndex);
|
||||||
|
__dcache_writeback_all();
|
||||||
|
//stop udc connet before execute program!
|
||||||
|
jz_writeb(USB_REG_POWER,0x0); //High speed
|
||||||
|
//dprintf("\n Execute program at %x",(u32)f);
|
||||||
|
f();
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int NOR_OPS_Handle(u8 *buf)
|
||||||
|
{
|
||||||
|
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int NAND_OPS_Handle(u8 *buf)
|
||||||
|
{
|
||||||
|
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
|
||||||
|
u32 temp;
|
||||||
|
int option;
|
||||||
|
u8 CSn;
|
||||||
|
|
||||||
|
CSn = (dreq->wValue>>4) & 0xff;
|
||||||
|
option = (dreq->wValue>>12) & 0xff;
|
||||||
|
nand_enable(CSn);
|
||||||
|
switch ((dreq->wValue)&0xf)
|
||||||
|
{
|
||||||
|
case NAND_QUERY:
|
||||||
|
dprintf("\n Request : NAND_QUERY!");
|
||||||
|
nand_query((u8 *)Bulk_in_buf);
|
||||||
|
HW_SendPKT(1, Bulk_in_buf, 8);
|
||||||
|
handshake_PKT[3]=(u16)ERR_OK;
|
||||||
|
udc_state = BULK_IN;
|
||||||
|
break;
|
||||||
|
case NAND_INIT:
|
||||||
|
dprintf("\n Request : NAND_INIT!");
|
||||||
|
|
||||||
|
break;
|
||||||
|
case NAND_MARK_BAD:
|
||||||
|
dprintf("\n Request : NAND_MARK_BAD!");
|
||||||
|
ret_dat = nand_mark_bad(start_addr);
|
||||||
|
handshake_PKT[0] = (u16) ret_dat;
|
||||||
|
handshake_PKT[1] = (u16) (ret_dat>>16);
|
||||||
|
HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
|
||||||
|
udc_state = IDLE;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case NAND_READ_OOB:
|
||||||
|
dprintf("\n Request : NAND_READ_OOB!");
|
||||||
|
memset(Bulk_in_buf,0,ops_length*Hand.nand_ps);
|
||||||
|
ret_dat = nand_read_oob(Bulk_in_buf,start_addr,ops_length);
|
||||||
|
handshake_PKT[0] = (u16) ret_dat;
|
||||||
|
handshake_PKT[1] = (u16) (ret_dat>>16);
|
||||||
|
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
|
||||||
|
udc_state = BULK_IN;
|
||||||
|
break;
|
||||||
|
case NAND_READ_RAW:
|
||||||
|
dprintf("\n Request : NAND_READ_RAW!");
|
||||||
|
switch (option)
|
||||||
|
{
|
||||||
|
case OOB_ECC:
|
||||||
|
nand_read_raw(Bulk_in_buf,start_addr,ops_length,option);
|
||||||
|
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os));
|
||||||
|
handshake_PKT[0] = (u16) ret_dat;
|
||||||
|
handshake_PKT[1] = (u16) (ret_dat>>16);
|
||||||
|
udc_state = BULK_IN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
nand_read_raw(Bulk_in_buf,start_addr,ops_length,option);
|
||||||
|
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
|
||||||
|
handshake_PKT[0] = (u16) ret_dat;
|
||||||
|
handshake_PKT[1] = (u16) (ret_dat>>16);
|
||||||
|
udc_state = BULK_IN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NAND_ERASE:
|
||||||
|
dprintf("\n Request : NAND_ERASE!");
|
||||||
|
ret_dat = nand_erase(ops_length,start_addr,
|
||||||
|
Hand.nand_force_erase);
|
||||||
|
handshake_PKT[0] = (u16) ret_dat;
|
||||||
|
handshake_PKT[1] = (u16) (ret_dat>>16);
|
||||||
|
HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
|
||||||
|
udc_state = IDLE;
|
||||||
|
dprintf("\n Request : NAND_ERASE_FINISH!");
|
||||||
|
break;
|
||||||
|
case NAND_READ:
|
||||||
|
dprintf("\n Request : NAND_READ!");
|
||||||
|
// dprintf("\n Option : %x",option);
|
||||||
|
switch (option)
|
||||||
|
{
|
||||||
|
case OOB_ECC:
|
||||||
|
ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,OOB_ECC);
|
||||||
|
handshake_PKT[0] = (u16) ret_dat;
|
||||||
|
handshake_PKT[1] = (u16) (ret_dat>>16);
|
||||||
|
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os ));
|
||||||
|
udc_state = BULK_IN;
|
||||||
|
break;
|
||||||
|
case OOB_NO_ECC:
|
||||||
|
ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,OOB_NO_ECC);
|
||||||
|
handshake_PKT[0] = (u16) ret_dat;
|
||||||
|
handshake_PKT[1] = (u16) (ret_dat>>16);
|
||||||
|
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os));
|
||||||
|
udc_state = BULK_IN;
|
||||||
|
break;
|
||||||
|
case NO_OOB:
|
||||||
|
ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,NO_OOB);
|
||||||
|
handshake_PKT[0] = (u16) ret_dat;
|
||||||
|
handshake_PKT[1] = (u16) (ret_dat>>16);
|
||||||
|
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
|
||||||
|
udc_state = BULK_IN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dprintf("\n Request : NAND_READ_FUNISH!");
|
||||||
|
break;
|
||||||
|
case NAND_PROGRAM:
|
||||||
|
dprintf("\n Request : NAND_PROGRAM!");
|
||||||
|
// dprintf("\n Option : %x",option);
|
||||||
|
ret_dat = nand_program((void *)Bulk_out_buf,
|
||||||
|
start_addr,ops_length,option);
|
||||||
|
dprintf("\n NAND_PROGRAM finish!");
|
||||||
|
handshake_PKT[0] = (u16) ret_dat;
|
||||||
|
handshake_PKT[1] = (u16) (ret_dat>>16);
|
||||||
|
HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
|
||||||
|
udc_state = IDLE;
|
||||||
|
break;
|
||||||
|
case NAND_READ_TO_RAM:
|
||||||
|
dprintf("\n Request : NAND_READNAND!");
|
||||||
|
nand_read((u8 *)ram_addr,start_addr,ops_length,NO_OOB);
|
||||||
|
__dcache_writeback_all();
|
||||||
|
handshake_PKT[3]=(u16)ERR_OK;
|
||||||
|
HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
|
||||||
|
udc_state = IDLE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
nand_disable(CSn);
|
||||||
|
return ERR_OPS_NOTSUPPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SDRAM_OPS_Handle(u8 *buf)
|
||||||
|
{
|
||||||
|
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
|
||||||
|
u32 temp,i;
|
||||||
|
u8 *obj;
|
||||||
|
|
||||||
|
switch ((dreq->wValue)&0xf)
|
||||||
|
{
|
||||||
|
case SDRAM_LOAD:
|
||||||
|
// dprintf("\n Request : SDRAM_LOAD!");
|
||||||
|
ret_dat = (u32)memcpy((u8 *)start_addr,Bulk_out_buf,ops_length);
|
||||||
|
handshake_PKT[0] = (u16) ret_dat;
|
||||||
|
handshake_PKT[1] = (u16) (ret_dat>>16);
|
||||||
|
HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
|
||||||
|
udc_state = IDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Borad_Init()
|
||||||
|
{
|
||||||
|
dprintf("\n Borad_init! ");
|
||||||
|
serial_put_hex(Hand.fw_args.cpu_id);
|
||||||
|
switch (Hand.fw_args.cpu_id)
|
||||||
|
{
|
||||||
|
case 0x4740:
|
||||||
|
//Init nand flash
|
||||||
|
nand_init_4740(Hand.nand_bw,Hand.nand_rc,Hand.nand_ps,Hand.nand_ppb,
|
||||||
|
Hand.nand_bbpage,Hand.nand_bbpos,Hand.nand_force_erase,Hand.nand_eccpos);
|
||||||
|
|
||||||
|
nand_program=nand_program_4740;
|
||||||
|
nand_erase =nand_erase_4740;
|
||||||
|
nand_read =nand_read_4740;
|
||||||
|
nand_read_oob=nand_read_oob_4740;
|
||||||
|
nand_read_raw=nand_read_raw_4740;
|
||||||
|
nand_query = nand_query_4740;
|
||||||
|
nand_enable = nand_enable_4740;
|
||||||
|
nand_disable= nand_disable_4740;
|
||||||
|
nand_mark_bad = nand_mark_bad_4740;
|
||||||
|
break;
|
||||||
|
case 0x4750:
|
||||||
|
//Init nand flash
|
||||||
|
nand_init_4750(Hand.nand_bw, Hand.nand_rc, Hand.nand_ps,
|
||||||
|
Hand.nand_ppb, Hand.nand_bchbit, Hand.nand_eccpos,
|
||||||
|
Hand.nand_bbpos, Hand.nand_bbpage, Hand.nand_force_erase);
|
||||||
|
|
||||||
|
nand_program=nand_program_4750;
|
||||||
|
nand_erase =nand_erase_4750;
|
||||||
|
nand_read =nand_read_4750;
|
||||||
|
nand_read_oob=nand_read_oob_4750;
|
||||||
|
nand_read_raw=nand_read_raw_4750;
|
||||||
|
nand_query = nand_query_4750;
|
||||||
|
nand_enable = nand_enable_4750;
|
||||||
|
nand_disable= nand_disable_4750;
|
||||||
|
nand_mark_bad = nand_mark_bad_4750;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
serial_puts("Not support CPU ID!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CONFIGRATION_Handle(u8 *buf)
|
||||||
|
{
|
||||||
|
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
|
||||||
|
switch ((dreq->wValue)&0xf)
|
||||||
|
{
|
||||||
|
case DS_flash_info:
|
||||||
|
dprintf("\n configration :DS_flash_info_t!");
|
||||||
|
config_flash_info();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DS_hand:
|
||||||
|
dprintf("\n configration :DS_hand_t!");
|
||||||
|
config_hand();
|
||||||
|
break;
|
||||||
|
default:;
|
||||||
|
|
||||||
|
}
|
||||||
|
Borad_Init();
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
153
flash-tool/device_stage2/usb_boot/cache.c
Normal file
153
flash-tool/device_stage2/usb_boot/cache.c
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* cache.c
|
||||||
|
*
|
||||||
|
* Handle operation of Jz CPU's cache
|
||||||
|
*
|
||||||
|
* Author: Seeger Chin
|
||||||
|
* e-mail: seeger.chin@gmail.com
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define u32 unsigned int
|
||||||
|
|
||||||
|
#define Index_Invalidate_I 0x00
|
||||||
|
#define Index_Writeback_Inv_D 0x01
|
||||||
|
#define Index_Load_Tag_I 0x04
|
||||||
|
#define Index_Load_Tag_D 0x05
|
||||||
|
#define Index_Store_Tag_I 0x08
|
||||||
|
#define Index_Store_Tag_D 0x09
|
||||||
|
#define Hit_Invalidate_I 0x10
|
||||||
|
#define Hit_Invalidate_D 0x11
|
||||||
|
#define Hit_Writeback_Inv_D 0x15
|
||||||
|
#define Hit_Writeback_I 0x18
|
||||||
|
#define Hit_Writeback_D 0x19
|
||||||
|
|
||||||
|
#define CACHE_SIZE 16*1024
|
||||||
|
#define CACHE_LINE_SIZE 32
|
||||||
|
#define KSEG0 0x80000000
|
||||||
|
|
||||||
|
#define K0_TO_K1() \
|
||||||
|
do { \
|
||||||
|
unsigned long __k0_addr; \
|
||||||
|
\
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
"la %0, 1f\n\t" \
|
||||||
|
"or %0, %0, %1\n\t" \
|
||||||
|
"jr %0\n\t" \
|
||||||
|
"nop\n\t" \
|
||||||
|
"1: nop\n" \
|
||||||
|
: "=&r"(__k0_addr) \
|
||||||
|
: "r" (0x20000000) ); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define K1_TO_K0() \
|
||||||
|
do { \
|
||||||
|
unsigned long __k0_addr; \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
"nop;nop;nop;nop;nop;nop;nop\n\t" \
|
||||||
|
"la %0, 1f\n\t" \
|
||||||
|
"jr %0\n\t" \
|
||||||
|
"nop\n\t" \
|
||||||
|
"1: nop\n" \
|
||||||
|
: "=&r" (__k0_addr)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define INVALIDATE_BTB() \
|
||||||
|
do { \
|
||||||
|
unsigned long tmp; \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
".set mips32\n\t" \
|
||||||
|
"mfc0 %0, $16, 7\n\t" \
|
||||||
|
"nop\n\t" \
|
||||||
|
"ori %0, 2\n\t" \
|
||||||
|
"mtc0 %0, $16, 7\n\t" \
|
||||||
|
"nop\n\t" \
|
||||||
|
".set mips2\n\t" \
|
||||||
|
: "=&r" (tmp)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define SYNC_WB() __asm__ __volatile__ ("sync")
|
||||||
|
|
||||||
|
#define cache_op(op,addr) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
" .set noreorder \n" \
|
||||||
|
" .set mips32\n\t \n" \
|
||||||
|
" cache %0, %1 \n" \
|
||||||
|
" .set mips0 \n" \
|
||||||
|
" .set reorder" \
|
||||||
|
: \
|
||||||
|
: "i" (op), "m" (*(unsigned char *)(addr)))
|
||||||
|
|
||||||
|
void __flush_dcache_line(unsigned long addr)
|
||||||
|
{
|
||||||
|
cache_op(Hit_Writeback_Inv_D, addr);
|
||||||
|
SYNC_WB();
|
||||||
|
}
|
||||||
|
|
||||||
|
void __icache_invalidate_all(void)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
K0_TO_K1();
|
||||||
|
|
||||||
|
asm volatile (".set noreorder\n"
|
||||||
|
".set mips32\n\t"
|
||||||
|
"mtc0\t$0,$28\n\t"
|
||||||
|
"mtc0\t$0,$29\n"
|
||||||
|
".set mips0\n"
|
||||||
|
".set reorder\n");
|
||||||
|
for (i=KSEG0;i<KSEG0+CACHE_SIZE;i+=CACHE_LINE_SIZE)
|
||||||
|
cache_op(Index_Store_Tag_I, i);
|
||||||
|
|
||||||
|
K1_TO_K0();
|
||||||
|
|
||||||
|
INVALIDATE_BTB();
|
||||||
|
}
|
||||||
|
|
||||||
|
void __dcache_invalidate_all(void)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
asm volatile (".set noreorder\n"
|
||||||
|
".set mips32\n\t"
|
||||||
|
"mtc0\t$0,$28\n\t"
|
||||||
|
"mtc0\t$0,$29\n"
|
||||||
|
".set mips0\n"
|
||||||
|
".set reorder\n");
|
||||||
|
for (i=KSEG0;i<KSEG0+CACHE_SIZE;i+=CACHE_LINE_SIZE)
|
||||||
|
cache_op(Index_Store_Tag_D, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __dcache_writeback_all(void)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
for (i=KSEG0;i<KSEG0+CACHE_SIZE;i+=CACHE_LINE_SIZE)
|
||||||
|
cache_op(Index_Writeback_Inv_D, i);
|
||||||
|
SYNC_WB();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dma_cache_wback_inv(unsigned long addr, unsigned long size)
|
||||||
|
{
|
||||||
|
unsigned long end, a;
|
||||||
|
|
||||||
|
if (size >= CACHE_SIZE) {
|
||||||
|
__dcache_writeback_all();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unsigned long dc_lsize = CACHE_LINE_SIZE;
|
||||||
|
|
||||||
|
a = addr & ~(dc_lsize - 1);
|
||||||
|
end = (addr + size - 1) & ~(dc_lsize - 1);
|
||||||
|
while (1) {
|
||||||
|
__flush_dcache_line(a); /* Hit_Writeback_Inv_D */
|
||||||
|
if (a == end)
|
||||||
|
break;
|
||||||
|
a += dc_lsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
flash-tool/device_stage2/usb_boot/head.S
Normal file
37
flash-tool/device_stage2/usb_boot/head.S
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* head.S
|
||||||
|
*
|
||||||
|
* Entry point of the firmware.
|
||||||
|
* The firmware code are executed in the ICache.
|
||||||
|
* Do not edit!
|
||||||
|
* Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.extern c_main
|
||||||
|
|
||||||
|
.globl _start
|
||||||
|
.set noreorder
|
||||||
|
_start:
|
||||||
|
b real_start
|
||||||
|
nop
|
||||||
|
.word 0x0 // its address == start address + 8
|
||||||
|
.word 0x0
|
||||||
|
.word 0x0
|
||||||
|
.word 0x0
|
||||||
|
.word 0x0
|
||||||
|
.word 0x0
|
||||||
|
.word 0x0
|
||||||
|
.word 0x0
|
||||||
|
|
||||||
|
real_start:
|
||||||
|
//----------------------------------------------------
|
||||||
|
// setup stack, jump to C code
|
||||||
|
//----------------------------------------------------
|
||||||
|
add $29, $20, 0x3ffff0 // sp locate at start address offset 0x2ffff0
|
||||||
|
add $25, $20, 0x40 // t9 = usb_main()
|
||||||
|
j $25
|
||||||
|
nop
|
||||||
|
|
||||||
|
.set reorder
|
54
flash-tool/device_stage2/usb_boot/main.c
Normal file
54
flash-tool/device_stage2/usb_boot/main.c
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/* special main file!
|
||||||
|
* do not edit!
|
||||||
|
*/
|
||||||
|
//#include "jz4740.h"
|
||||||
|
#include "hand.h"
|
||||||
|
|
||||||
|
extern void usb_main();
|
||||||
|
unsigned int start_addr,got_start,got_end;
|
||||||
|
extern unsigned int UART_BASE;
|
||||||
|
struct fw_args_t * fw_args;
|
||||||
|
|
||||||
|
void c_main(void)
|
||||||
|
{
|
||||||
|
volatile unsigned int addr,offset;
|
||||||
|
/* get absolute start address */
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"move %0, $20\n\t"
|
||||||
|
: "=r"(start_addr)
|
||||||
|
:
|
||||||
|
);
|
||||||
|
|
||||||
|
/* get related GOT address */
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"la $4, _GLOBAL_OFFSET_TABLE_\n\t"
|
||||||
|
"move %0, $4\n\t"
|
||||||
|
"la $5, _got_end\n\t"
|
||||||
|
"move %1, $5\n\t"
|
||||||
|
: "=r"(got_start),"=r"(got_end)
|
||||||
|
:
|
||||||
|
);
|
||||||
|
|
||||||
|
/* calculate offset and correct GOT*/
|
||||||
|
offset = start_addr - 0x80000000;
|
||||||
|
got_start += offset;
|
||||||
|
got_end += offset;
|
||||||
|
|
||||||
|
for ( addr = got_start + 8; addr < got_end; addr += 4 )
|
||||||
|
{
|
||||||
|
*((volatile unsigned int *)(addr)) += offset; //add offset to correct all GOT
|
||||||
|
}
|
||||||
|
|
||||||
|
fw_args = (struct fw_args_t *)(start_addr + 0x8); //get the fw args from memory
|
||||||
|
if ( fw_args->use_uart > 3 ) fw_args->use_uart = 0;
|
||||||
|
UART_BASE = 0xB0030000 + fw_args->use_uart * 0x1000;
|
||||||
|
|
||||||
|
serial_puts("Start address is :");
|
||||||
|
serial_put_hex(start_addr);
|
||||||
|
serial_puts("Address offset is:");
|
||||||
|
serial_put_hex(offset);
|
||||||
|
serial_puts("GOT correct to :");
|
||||||
|
serial_put_hex(got_start);
|
||||||
|
|
||||||
|
usb_main();
|
||||||
|
}
|
88
flash-tool/device_stage2/usb_boot/serial.c
Normal file
88
flash-tool/device_stage2/usb_boot/serial.c
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#include "jz4750.h"
|
||||||
|
|
||||||
|
volatile u32 UART_BASE;
|
||||||
|
#define CONFIG_BAUDRATE 57600
|
||||||
|
#define CFG_EXTAL 12000000 /* EXTAL freq must=12 MHz !! */
|
||||||
|
|
||||||
|
void serial_setbrg (void)
|
||||||
|
{
|
||||||
|
volatile u8 *uart_lcr = (volatile u8 *)(UART_BASE + OFF_LCR);
|
||||||
|
volatile u8 *uart_dlhr = (volatile u8 *)(UART_BASE + OFF_DLHR);
|
||||||
|
volatile u8 *uart_dllr = (volatile u8 *)(UART_BASE + OFF_DLLR);
|
||||||
|
u32 baud_div, tmp;
|
||||||
|
|
||||||
|
baud_div = CFG_EXTAL / 16 / CONFIG_BAUDRATE;
|
||||||
|
tmp = *uart_lcr;
|
||||||
|
tmp |= UART_LCR_DLAB;
|
||||||
|
*uart_lcr = tmp;
|
||||||
|
|
||||||
|
*uart_dlhr = (baud_div >> 8) & 0xff;
|
||||||
|
*uart_dllr = baud_div & 0xff;
|
||||||
|
|
||||||
|
tmp &= ~UART_LCR_DLAB;
|
||||||
|
*uart_lcr = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial_putc (const char c)
|
||||||
|
{
|
||||||
|
volatile u8 *uart_lsr = (volatile u8 *)(UART_BASE + OFF_LSR);
|
||||||
|
volatile u8 *uart_tdr = (volatile u8 *)(UART_BASE + OFF_TDR);
|
||||||
|
|
||||||
|
if (c == '\n') serial_putc ('\r');
|
||||||
|
|
||||||
|
/* Wait for fifo to shift out some bytes */
|
||||||
|
while ( !((*uart_lsr & (UART_LSR_TDRQ | UART_LSR_TEMT)) == 0x60) );
|
||||||
|
|
||||||
|
*uart_tdr = (u8)c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial_puts (const char *s)
|
||||||
|
{
|
||||||
|
while (*s) {
|
||||||
|
serial_putc (*s++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial_init(void)
|
||||||
|
{
|
||||||
|
volatile u8 *uart_fcr = (volatile u8 *)(UART_BASE + OFF_FCR);
|
||||||
|
volatile u8 *uart_lcr = (volatile u8 *)(UART_BASE + OFF_LCR);
|
||||||
|
volatile u8 *uart_ier = (volatile u8 *)(UART_BASE + OFF_IER);
|
||||||
|
volatile u8 *uart_sircr = (volatile u8 *)(UART_BASE + OFF_SIRCR);
|
||||||
|
|
||||||
|
/* Disable port interrupts while changing hardware */
|
||||||
|
*uart_ier = 0;
|
||||||
|
|
||||||
|
/* Disable UART unit function */
|
||||||
|
*uart_fcr = ~UART_FCR_UUE;
|
||||||
|
|
||||||
|
/* Set both receiver and transmitter in UART mode (not SIR) */
|
||||||
|
*uart_sircr = ~(SIRCR_RSIRE | SIRCR_TSIRE);
|
||||||
|
|
||||||
|
/* Set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */
|
||||||
|
*uart_lcr = UART_LCR_WLEN_8 | UART_LCR_STOP_1;
|
||||||
|
|
||||||
|
/* Set baud rate */
|
||||||
|
serial_setbrg();
|
||||||
|
|
||||||
|
/* Enable UART unit, enable and clear FIFO */
|
||||||
|
*uart_fcr = UART_FCR_UUE | UART_FCR_FE | UART_FCR_TFLS | UART_FCR_RFLS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial_put_hex(unsigned int d)
|
||||||
|
{
|
||||||
|
unsigned char c[12];
|
||||||
|
char i;
|
||||||
|
for(i = 0; i < 8;i++)
|
||||||
|
{
|
||||||
|
c[i] = (d >> ((7 - i) * 4)) & 0xf;
|
||||||
|
if(c[i] < 10)
|
||||||
|
c[i] += 0x30;
|
||||||
|
else
|
||||||
|
c[i] += (0x41 - 10);
|
||||||
|
}
|
||||||
|
c[8] = '\n';
|
||||||
|
c[9] = 0;
|
||||||
|
serial_puts(c);
|
||||||
|
|
||||||
|
}
|
641
flash-tool/device_stage2/usb_boot/udc.c
Normal file
641
flash-tool/device_stage2/usb_boot/udc.c
Normal file
@ -0,0 +1,641 @@
|
|||||||
|
#include <jz4740.h>
|
||||||
|
#include "usb.h"
|
||||||
|
#include "udc.h"
|
||||||
|
#include "usb_boot.h"
|
||||||
|
//#include "mipsregs.h"
|
||||||
|
|
||||||
|
#define dprintf(x...)
|
||||||
|
//serial_puts(x)
|
||||||
|
//printf(x)
|
||||||
|
#define TXFIFOEP0 USB_FIFO_EP0
|
||||||
|
|
||||||
|
u32 Bulk_in_buf[BULK_IN_BUF_SIZE];
|
||||||
|
u32 Bulk_out_buf[BULK_OUT_BUF_SIZE];
|
||||||
|
u32 Bulk_in_size,Bulk_in_finish,Bulk_out_size;
|
||||||
|
u16 handshake_PKT[4]={0,0,0,0};
|
||||||
|
u8 udc_state;
|
||||||
|
|
||||||
|
static u32 rx_buf[32];
|
||||||
|
static u32 tx_buf[32];
|
||||||
|
static u32 tx_size, rx_size, finished,fifo;
|
||||||
|
static u8 ep0state,USB_Version;
|
||||||
|
|
||||||
|
static u32 fifoaddr[] =
|
||||||
|
{
|
||||||
|
TXFIFOEP0, TXFIFOEP0+4 ,TXFIFOEP0+8
|
||||||
|
};
|
||||||
|
|
||||||
|
static u32 fifosize[] = {
|
||||||
|
MAX_EP0_SIZE, MAX_EP1_SIZE
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
void *memset(void *s, int c, size_t count)
|
||||||
|
{
|
||||||
|
char *xs = s;
|
||||||
|
|
||||||
|
while (count--)
|
||||||
|
*xs++ = c;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memcpy(void *dest, const void *src, size_t count)
|
||||||
|
{
|
||||||
|
char *tmp = dest;
|
||||||
|
const char *s = src;
|
||||||
|
|
||||||
|
while (count--)
|
||||||
|
*tmp++ = *s++;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void udcReadFifo(u8 *ptr, int size)
|
||||||
|
{
|
||||||
|
u32 *d = (u32 *)ptr;
|
||||||
|
int s;
|
||||||
|
s = (size + 3) >> 2;
|
||||||
|
while (s--)
|
||||||
|
*d++ = REG32(fifo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void udcWriteFifo(u8 *ptr, int size)
|
||||||
|
{
|
||||||
|
u32 *d = (u32 *)ptr;
|
||||||
|
u8 *c;
|
||||||
|
int s, q;
|
||||||
|
|
||||||
|
if (size > 0) {
|
||||||
|
s = size >> 2;
|
||||||
|
while (s--)
|
||||||
|
REG32(fifo) = *d++;
|
||||||
|
q = size & 3;
|
||||||
|
if (q) {
|
||||||
|
c = (u8 *)d;
|
||||||
|
while (q--)
|
||||||
|
REG8(fifo) = *c++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HW_SendPKT(int ep, const u8 *buf, int size)
|
||||||
|
{
|
||||||
|
// dprintf("EP%d send pkt :%d\n", ep, size);
|
||||||
|
fifo = fifoaddr[ep];
|
||||||
|
|
||||||
|
if (ep!=0)
|
||||||
|
{
|
||||||
|
Bulk_in_size = size;
|
||||||
|
Bulk_in_finish = 0;
|
||||||
|
jz_writeb(USB_REG_INDEX, ep);
|
||||||
|
if (Bulk_in_size - Bulk_in_finish <= fifosize[ep])
|
||||||
|
{
|
||||||
|
udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish),
|
||||||
|
Bulk_in_size - Bulk_in_finish);
|
||||||
|
usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY);
|
||||||
|
Bulk_in_finish = Bulk_in_size;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish),
|
||||||
|
fifosize[ep]);
|
||||||
|
usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY);
|
||||||
|
Bulk_in_finish += fifosize[ep];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //EP0
|
||||||
|
{
|
||||||
|
tx_size = size;
|
||||||
|
finished = 0;
|
||||||
|
memcpy((void *)tx_buf, buf, size);
|
||||||
|
ep0state = USB_EP0_TX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HW_GetPKT(int ep, const u8 *buf, int size)
|
||||||
|
{
|
||||||
|
// dprintf("EP%d read pkt :%d\n", ep, size);
|
||||||
|
memcpy((void *)buf, (u8 *)rx_buf, size);
|
||||||
|
fifo = fifoaddr[ep];
|
||||||
|
if (rx_size > size)
|
||||||
|
rx_size -= size;
|
||||||
|
else {
|
||||||
|
size = rx_size;
|
||||||
|
rx_size = 0;
|
||||||
|
}
|
||||||
|
memcpy((u8 *)rx_buf, (u8 *)((u32)rx_buf+size), rx_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static USB_DeviceDescriptor devDesc =
|
||||||
|
{
|
||||||
|
sizeof(USB_DeviceDescriptor),
|
||||||
|
DEVICE_DESCRIPTOR, //1
|
||||||
|
0x0200, //Version 2.0
|
||||||
|
0xff, //Vendor spec class
|
||||||
|
0xff,
|
||||||
|
0xff,
|
||||||
|
64, /* Ep0 FIFO size */
|
||||||
|
0x601a, //vendor ID
|
||||||
|
0x4740, //Product ID
|
||||||
|
0xffff,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x01
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CONFIG_DESCRIPTOR_LEN (sizeof(USB_ConfigDescriptor) + \
|
||||||
|
sizeof(USB_InterfaceDescriptor) + \
|
||||||
|
sizeof(USB_EndPointDescriptor) * 2)
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
USB_ConfigDescriptor configuration_descriptor;
|
||||||
|
USB_InterfaceDescriptor interface_descritor;
|
||||||
|
USB_EndPointDescriptor endpoint_descriptor[2];
|
||||||
|
} __attribute__ ((packed)) confDesc = {
|
||||||
|
{
|
||||||
|
sizeof(USB_ConfigDescriptor),
|
||||||
|
CONFIGURATION_DESCRIPTOR,
|
||||||
|
CONFIG_DESCRIPTOR_LEN,
|
||||||
|
0x01,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
0xc0, // Self Powered, no remote wakeup
|
||||||
|
0x64 // Maximum power consumption 2000 mA
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sizeof(USB_InterfaceDescriptor),
|
||||||
|
INTERFACE_DESCRIPTOR,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x02, /* ep number */
|
||||||
|
0xff,
|
||||||
|
0xff,
|
||||||
|
0xff,
|
||||||
|
0x00
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{
|
||||||
|
sizeof(USB_EndPointDescriptor),
|
||||||
|
ENDPOINT_DESCRIPTOR,
|
||||||
|
(1 << 7) | 1,// endpoint 2 is IN endpoint
|
||||||
|
2, /* bulk */
|
||||||
|
512,
|
||||||
|
16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sizeof(USB_EndPointDescriptor),
|
||||||
|
ENDPOINT_DESCRIPTOR,
|
||||||
|
(0 << 7) | 1,// endpoint 5 is OUT endpoint
|
||||||
|
2, /* bulk */
|
||||||
|
512, /* OUT EP FIFO size */
|
||||||
|
16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void sendDevDescString(int size)
|
||||||
|
{
|
||||||
|
u16 str_ret[13] = {
|
||||||
|
0x031a,//0x1a=26 byte
|
||||||
|
0x0041,
|
||||||
|
0x0030,
|
||||||
|
0x0030,
|
||||||
|
0x0041,
|
||||||
|
0x0030,
|
||||||
|
0x0030,
|
||||||
|
0x0041,
|
||||||
|
0x0030,
|
||||||
|
0x0030,
|
||||||
|
0x0041,
|
||||||
|
0x0030,
|
||||||
|
0x0030
|
||||||
|
};
|
||||||
|
// dprintf("sendDevDescString size = %d\r\n",size);
|
||||||
|
if(size >= 26)
|
||||||
|
size = 26;
|
||||||
|
str_ret[0] = (0x0300 | size);
|
||||||
|
HW_SendPKT(0, (u8 *)str_ret,size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendDevDesc(int size)
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
case 18:
|
||||||
|
HW_SendPKT(0, (u8 *)&devDesc, sizeof(devDesc));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
HW_SendPKT(0, (u8 *)&devDesc, 8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendConfDesc(int size)
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
case 9:
|
||||||
|
HW_SendPKT(0, (u8 *)&confDesc, 9);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
HW_SendPKT(0, (u8 *)&confDesc, 8);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
HW_SendPKT(0, (u8 *)&confDesc, sizeof(confDesc));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EP0_init(u32 out, u32 out_size, u32 in, u32 in_size)
|
||||||
|
{
|
||||||
|
confDesc.endpoint_descriptor[0].bEndpointAddress = (1<<7) | in;
|
||||||
|
confDesc.endpoint_descriptor[0].wMaxPacketSize = in_size;
|
||||||
|
confDesc.endpoint_descriptor[1].bEndpointAddress = (0<<7) | out;
|
||||||
|
confDesc.endpoint_descriptor[1].wMaxPacketSize = out_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void udc_reset(void)
|
||||||
|
{
|
||||||
|
u8 byte;
|
||||||
|
//data init
|
||||||
|
ep0state = USB_EP0_IDLE;
|
||||||
|
Bulk_in_size = 0;
|
||||||
|
Bulk_in_finish = 0;
|
||||||
|
Bulk_out_size = 0;
|
||||||
|
udc_state = IDLE;
|
||||||
|
tx_size = 0;
|
||||||
|
rx_size = 0;
|
||||||
|
finished = 0;
|
||||||
|
/* Enable the USB PHY */
|
||||||
|
// REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE;
|
||||||
|
/* Disable interrupts */
|
||||||
|
byte=jz_readb(USB_REG_POWER);
|
||||||
|
// dprintf("\nREG_POWER: %02x",byte);
|
||||||
|
jz_writew(USB_REG_INTRINE, 0);
|
||||||
|
jz_writew(USB_REG_INTROUTE, 0);
|
||||||
|
jz_writeb(USB_REG_INTRUSBE, 0);
|
||||||
|
jz_writeb(USB_REG_FADDR,0);
|
||||||
|
jz_writeb(USB_REG_POWER,0x60); //High speed
|
||||||
|
jz_writeb(USB_REG_INDEX,0);
|
||||||
|
jz_writeb(USB_REG_CSR0,0xc0);
|
||||||
|
jz_writeb(USB_REG_INDEX,1);
|
||||||
|
jz_writew(USB_REG_INMAXP,512);
|
||||||
|
jz_writew(USB_REG_INCSR,0x2048);
|
||||||
|
jz_writeb(USB_REG_INDEX,1);
|
||||||
|
jz_writew(USB_REG_OUTMAXP,512);
|
||||||
|
jz_writew(USB_REG_OUTCSR,0x0090);
|
||||||
|
jz_writew(USB_REG_INTRINE,0x3); //enable intr
|
||||||
|
jz_writew(USB_REG_INTROUTE,0x2);
|
||||||
|
jz_writeb(USB_REG_INTRUSBE,0x4);
|
||||||
|
|
||||||
|
byte=jz_readb(USB_REG_POWER);
|
||||||
|
// dprintf("\nREG_POWER: %02x",byte);
|
||||||
|
if ((byte&0x10)==0)
|
||||||
|
{
|
||||||
|
jz_writeb(USB_REG_INDEX,1);
|
||||||
|
jz_writew(USB_REG_INMAXP,64);
|
||||||
|
jz_writew(USB_REG_INCSR,0x2048);
|
||||||
|
jz_writeb(USB_REG_INDEX,1);
|
||||||
|
jz_writew(USB_REG_OUTMAXP,64);
|
||||||
|
jz_writew(USB_REG_OUTCSR,0x0090);
|
||||||
|
USB_Version=USB_FS;
|
||||||
|
fifosize[1]=64;
|
||||||
|
EP0_init(1,64,1,64);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jz_writeb(USB_REG_INDEX,1);
|
||||||
|
jz_writew(USB_REG_INMAXP,512);
|
||||||
|
jz_writew(USB_REG_INCSR,0x2048);
|
||||||
|
jz_writeb(USB_REG_INDEX,1);
|
||||||
|
jz_writew(USB_REG_OUTMAXP,512);
|
||||||
|
jz_writew(USB_REG_OUTCSR,0x0090);
|
||||||
|
USB_Version=USB_HS;
|
||||||
|
fifosize[1]=512;
|
||||||
|
EP0_init(1,512,1,512);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void usbHandleStandDevReq(u8 *buf)
|
||||||
|
{
|
||||||
|
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
|
||||||
|
switch (dreq->bRequest) {
|
||||||
|
case GET_DESCRIPTOR:
|
||||||
|
if (dreq->bmRequestType == 0x80) /* Dev2Host */
|
||||||
|
switch(dreq->wValue >> 8)
|
||||||
|
{
|
||||||
|
case DEVICE_DESCRIPTOR:
|
||||||
|
dprintf("get device\n");
|
||||||
|
sendDevDesc(dreq->wLength);
|
||||||
|
break;
|
||||||
|
case CONFIGURATION_DESCRIPTOR:
|
||||||
|
dprintf("get config\n");
|
||||||
|
sendConfDesc(dreq->wLength);
|
||||||
|
break;
|
||||||
|
case STRING_DESCRIPTOR:
|
||||||
|
if (dreq->wLength == 0x02)
|
||||||
|
HW_SendPKT(0, "\x04\x03", 2);
|
||||||
|
else
|
||||||
|
sendDevDescString(dreq->wLength);
|
||||||
|
//HW_SendPKT(0, "\x04\x03\x09\x04", 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dprintf("\nSet ep0state=TX!");
|
||||||
|
ep0state=USB_EP0_TX;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case SET_ADDRESS:
|
||||||
|
dprintf("\nSET_ADDRESS!");
|
||||||
|
jz_writeb(USB_REG_FADDR,dreq->wValue);
|
||||||
|
break;
|
||||||
|
case GET_STATUS:
|
||||||
|
switch (dreq->bmRequestType) {
|
||||||
|
case 80: /* device */
|
||||||
|
HW_SendPKT(0, "\x01\x00", 2);
|
||||||
|
break;
|
||||||
|
case 81: /* interface */
|
||||||
|
case 82: /* ep */
|
||||||
|
HW_SendPKT(0, "\x00\x00", 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ep0state=USB_EP0_TX;
|
||||||
|
break;
|
||||||
|
case CLEAR_FEATURE:
|
||||||
|
case SET_CONFIGURATION:
|
||||||
|
case SET_INTERFACE:
|
||||||
|
case SET_FEATURE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbHandleVendorReq(u8 *buf)
|
||||||
|
{
|
||||||
|
int ret_state;
|
||||||
|
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
|
||||||
|
switch (dreq->bRequest) {
|
||||||
|
case VR_GET_CUP_INFO:
|
||||||
|
ret_state=GET_CUP_INFO_Handle();
|
||||||
|
break;
|
||||||
|
case VR_SET_DATA_ADDERSS:
|
||||||
|
ret_state=SET_DATA_ADDERSS_Handle(buf);
|
||||||
|
break;
|
||||||
|
case VR_SET_DATA_LENGTH:
|
||||||
|
ret_state=SET_DATA_LENGTH_Handle(buf);
|
||||||
|
break;
|
||||||
|
case VR_FLUSH_CACHES:
|
||||||
|
ret_state=FLUSH_CACHES_Handle();
|
||||||
|
break;
|
||||||
|
case VR_PROGRAM_START1:
|
||||||
|
ret_state=PROGRAM_START1_Handle(buf);
|
||||||
|
break;
|
||||||
|
case VR_PROGRAM_START2:
|
||||||
|
ret_state=PROGRAM_START2_Handle(buf);
|
||||||
|
break;
|
||||||
|
case VR_NOR_OPS:
|
||||||
|
ret_state=NOR_OPS_Handle(buf);
|
||||||
|
Bulk_out_size = 0;
|
||||||
|
//Bulk_in_size = 0;
|
||||||
|
break;
|
||||||
|
case VR_NAND_OPS:
|
||||||
|
NAND_OPS_Handle(buf);
|
||||||
|
Bulk_out_size = 0;
|
||||||
|
//Bulk_in_size = 0;
|
||||||
|
//handshake_PKT[3]=(u16)ret_state;
|
||||||
|
//HW_SendPKT(0,handshake_PKT,sizeof(handshake_PKT));
|
||||||
|
break;
|
||||||
|
case VR_CONFIGRATION:
|
||||||
|
ret_state=CONFIGRATION_Handle(buf);
|
||||||
|
handshake_PKT[3]=(u16)ret_state;
|
||||||
|
HW_SendPKT(1,(u8 *)handshake_PKT,sizeof(handshake_PKT));
|
||||||
|
Bulk_out_size = 0;
|
||||||
|
//Bulk_in_size = 0;
|
||||||
|
break;
|
||||||
|
case VR_SDRAM_OPS:
|
||||||
|
SDRAM_OPS_Handle(buf);
|
||||||
|
Bulk_out_size = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// serial_puts("get here! \n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Handshake_PKT()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (udc_state!=IDLE)
|
||||||
|
{
|
||||||
|
HW_SendPKT(1,(u8 *)handshake_PKT,sizeof(handshake_PKT));
|
||||||
|
udc_state = IDLE;
|
||||||
|
dprintf("\n Send handshake PKT!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbHandleDevReq(u8 *buf)
|
||||||
|
{
|
||||||
|
// dprintf("dev req:%d\n", (buf[0] & (3 << 5)) >> 5);
|
||||||
|
switch ((buf[0] & (3 << 5)) >> 5) {
|
||||||
|
case 0: /* Standard request */
|
||||||
|
usbHandleStandDevReq(buf);
|
||||||
|
break;
|
||||||
|
case 1: /* Class request */
|
||||||
|
break;
|
||||||
|
case 2: /* Vendor request */
|
||||||
|
usbHandleVendorReq(buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EP0_Handler ()
|
||||||
|
{
|
||||||
|
u8 byCSR0;
|
||||||
|
|
||||||
|
/* Read CSR0 */
|
||||||
|
jz_writeb(USB_REG_INDEX, 0);
|
||||||
|
byCSR0 = jz_readb(USB_REG_CSR0);
|
||||||
|
|
||||||
|
/* Check for SentStall
|
||||||
|
if sendtall is set ,clear the sendstall bit*/
|
||||||
|
if (byCSR0 & USB_CSR0_SENTSTALL)
|
||||||
|
{
|
||||||
|
jz_writeb(USB_REG_CSR0, (byCSR0 & ~USB_CSR0_SENDSTALL));
|
||||||
|
ep0state = USB_EP0_IDLE;
|
||||||
|
dprintf("\nSentstall!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for SetupEnd */
|
||||||
|
if (byCSR0 & USB_CSR0_SETUPEND)
|
||||||
|
{
|
||||||
|
jz_writeb(USB_REG_CSR0, (byCSR0 | USB_CSR0_SVDSETUPEND));
|
||||||
|
ep0state = USB_EP0_IDLE;
|
||||||
|
dprintf("\nSetupend!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Call relevant routines for endpoint 0 state */
|
||||||
|
if (ep0state == USB_EP0_IDLE)
|
||||||
|
{
|
||||||
|
if (byCSR0 & USB_CSR0_OUTPKTRDY) //There are datas in fifo
|
||||||
|
{
|
||||||
|
USB_DeviceRequest *dreq;
|
||||||
|
fifo=fifoaddr[0];
|
||||||
|
udcReadFifo((u8 *)rx_buf, sizeof(USB_DeviceRequest));
|
||||||
|
usb_setb(USB_REG_CSR0, 0x48);//clear OUTRD bit
|
||||||
|
dreq = (USB_DeviceRequest *)rx_buf;
|
||||||
|
#if 0
|
||||||
|
dprintf("\nbmRequestType:%02x\nbRequest:%02x\n"
|
||||||
|
"wValue:%04x\nwIndex:%04x\n"
|
||||||
|
"wLength:%04x\n",
|
||||||
|
dreq->bmRequestType,
|
||||||
|
dreq->bRequest,
|
||||||
|
dreq->wValue,
|
||||||
|
dreq->wIndex,
|
||||||
|
dreq->wLength);
|
||||||
|
#endif
|
||||||
|
usbHandleDevReq((u8 *)rx_buf);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
dprintf("0:R DATA\n");
|
||||||
|
}
|
||||||
|
rx_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ep0state == USB_EP0_TX)
|
||||||
|
{
|
||||||
|
fifo=fifoaddr[0];
|
||||||
|
if (tx_size - finished <= 64)
|
||||||
|
{
|
||||||
|
udcWriteFifo((u8 *)((u32)tx_buf+finished),
|
||||||
|
tx_size - finished);
|
||||||
|
finished = tx_size;
|
||||||
|
usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY);
|
||||||
|
usb_setb(USB_REG_CSR0, USB_CSR0_DATAEND); //Set dataend!
|
||||||
|
ep0state=USB_EP0_IDLE;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
udcWriteFifo((u8 *)((u32)tx_buf+finished), 64);
|
||||||
|
usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY);
|
||||||
|
finished += 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EPIN_Handler(u8 EP)
|
||||||
|
{
|
||||||
|
jz_writeb(USB_REG_INDEX, EP);
|
||||||
|
fifo = fifoaddr[EP];
|
||||||
|
|
||||||
|
if (Bulk_in_size-Bulk_in_finish==0)
|
||||||
|
{
|
||||||
|
Handshake_PKT();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Bulk_in_size - Bulk_in_finish <= fifosize[EP])
|
||||||
|
{
|
||||||
|
udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish),
|
||||||
|
Bulk_in_size - Bulk_in_finish);
|
||||||
|
usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
|
||||||
|
Bulk_in_finish = Bulk_in_size;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish),
|
||||||
|
fifosize[EP]);
|
||||||
|
usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
|
||||||
|
Bulk_in_finish += fifosize[EP];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EPOUT_Handler(u8 EP)
|
||||||
|
{
|
||||||
|
u32 size;
|
||||||
|
jz_writeb(USB_REG_INDEX, EP);
|
||||||
|
size = jz_readw(USB_REG_OUTCOUNT);
|
||||||
|
fifo = fifoaddr[EP];
|
||||||
|
udcReadFifo((u8 *)((u32)Bulk_out_buf+Bulk_out_size), size);
|
||||||
|
usb_clearb(USB_REG_OUTCSR,USB_OUTCSR_OUTPKTRDY);
|
||||||
|
Bulk_out_size += size;
|
||||||
|
dprintf("\nEPOUT_handle return!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void udc4740Proc ()
|
||||||
|
{
|
||||||
|
volatile u8 IntrUSB;
|
||||||
|
volatile u16 IntrIn;
|
||||||
|
volatile u16 IntrOut;
|
||||||
|
/* Read interrupt registers */
|
||||||
|
// while(1)
|
||||||
|
// {
|
||||||
|
IntrUSB = jz_readb(USB_REG_INTRUSB);
|
||||||
|
IntrIn = jz_readw(USB_REG_INTRIN);
|
||||||
|
IntrOut = jz_readw(USB_REG_INTROUT);
|
||||||
|
|
||||||
|
if ( IntrUSB == 0 && IntrIn == 0 && IntrOut == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (IntrIn & 2)
|
||||||
|
{
|
||||||
|
dprintf("\nUDC EP1 IN operation!");
|
||||||
|
EPIN_Handler(1);
|
||||||
|
}
|
||||||
|
if (IntrOut & 2)
|
||||||
|
{
|
||||||
|
dprintf("\nUDC EP1 OUT operation!");
|
||||||
|
EPOUT_Handler(1);
|
||||||
|
}
|
||||||
|
if (IntrUSB & USB_INTR_RESET)
|
||||||
|
{
|
||||||
|
dprintf("\nUDC reset intrupt!");
|
||||||
|
udc_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for endpoint 0 interrupt */
|
||||||
|
if (IntrIn & USB_INTR_EP0)
|
||||||
|
{
|
||||||
|
dprintf("\nUDC EP0 operations!");
|
||||||
|
EP0_Handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (USB_Version == USB_FS)
|
||||||
|
IntrIn = jz_readw(USB_REG_INTRIN);
|
||||||
|
// }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//unsigned int g_stack[2049];
|
||||||
|
void usb_main()
|
||||||
|
{
|
||||||
|
u8 byte;
|
||||||
|
|
||||||
|
__dcache_writeback_all();
|
||||||
|
__icache_invalidate_all();
|
||||||
|
|
||||||
|
ep0state = USB_EP0_IDLE;
|
||||||
|
Bulk_in_size = 0;
|
||||||
|
Bulk_in_finish = 0;
|
||||||
|
Bulk_out_size = 0;
|
||||||
|
udc_state = IDLE;
|
||||||
|
tx_size = 0;
|
||||||
|
rx_size = 0;
|
||||||
|
finished = 0;
|
||||||
|
|
||||||
|
byte=jz_readb(USB_REG_POWER);
|
||||||
|
if ((byte&0x10)==0)
|
||||||
|
{
|
||||||
|
USB_Version=USB_FS;
|
||||||
|
fifosize[1]=64;
|
||||||
|
EP0_init(1,64,1,64);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
USB_Version=USB_HS;
|
||||||
|
fifosize[1]=512;
|
||||||
|
EP0_init(1,512,1,512);
|
||||||
|
}
|
||||||
|
|
||||||
|
serial_puts("\n Init UDC");
|
||||||
|
USB_Version=USB_HS;
|
||||||
|
while (1) {
|
||||||
|
udc4740Proc();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user