1
0
mirror of git://projects.qi-hardware.com/xburst-tools.git synced 2024-11-01 16:25:20 +02:00

add usb boot stage2 for device

This commit is contained in:
xiangfu 2009-05-15 05:00:06 +00:00
parent 6a07660a37
commit 3977cdb120
22 changed files with 17963 additions and 0 deletions

View 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 *.~ *.\#

File diff suppressed because it is too large Load Diff

View 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__ */

View 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__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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__ */

View 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 */

View 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

View 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__*/

View 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__

View 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)

View 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

View 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;
}

View 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;
}

View 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);
}

View 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;
}

View 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;
}
}
}

View 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

View 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();
}

View 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);
}

View 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();
}
}