From: wdenk Date: Sun, 3 Nov 2002 01:41:26 +0000 (+0000) Subject: Initial revision X-Git-Tag: LABEL_2006_03_12_0025~982 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=afd7f3d0de7be71ee90478d4dde00dc1a8f9d204;p=u-boot Initial revision --- diff --git a/board/bmw/early_init.S b/board/bmw/early_init.S new file mode 100644 index 0000000000..ec20a67a71 --- /dev/null +++ b/board/bmw/early_init.S @@ -0,0 +1,1172 @@ +#include +#include +#include +#include +#include + +#define USE_V2_INIT 1 /* Jimmy Blair's initialization. */ + + +/* + * Initialize the MMU using BAT entries and hardwired TLB + * This obviates the need for any code in cpu_init_f which + * configures the BAT registers. +*/ +#define MEMORY_MGMT_MSR_BITS (MSR_DR | MSR_IR) /* Data and Inst Relocate */ + .global iommu_setup + /* Initialize IO/MMU mappings via BAT method Ch. 7, + * PPC Programming Reference + */ +iommu_setup: + +/* initialize the BAT registers (SPRs 528 - 543 */ +#define mtibat0u(x) mtspr 528,(x) /* SPR 528 (IBAT0U) */ +#define mtibat0l(x) mtspr 529,(x) /* SPR 529 (IBAT0L) */ +#define mtibat1u(x) mtspr 530,(x) /* SPR 530 (IBAT1U) */ +#define mtibat1l(x) mtspr 531,(x) /* SPR 531 (IBAT1L) */ +#define mtibat2u(x) mtspr 532,(x) /* SPR 532 (IBAT2U) */ +#define mtibat2l(x) mtspr 533,(x) /* SPR 533 (IBAT2L) */ +#define mtibat3u(x) mtspr 534,(x) /* SPR 534 (IBAT3U) */ +#define mtibat3l(x) mtspr 535,(x) /* SPR 535 (IBAT3L) */ +#define mtdbat0u(x) mtspr 536,(x) /* SPR 536 (DBAT0U) */ +#define mtdbat0l(x) mtspr 537,(x) /* SPR 537 (DBAT0L) */ +#define mtdbat1u(x) mtspr 538,(x) /* SPR 538 (DBAT1U) */ +#define mtdbat1l(x) mtspr 539,(x) /* SPR 539 (DBAT1L) */ +#define mtdbat2u(x) mtspr 540,(x) /* SPR 540 (DBAT2U) */ +#define mtdbat2l(x) mtspr 541,(x) /* SPR 541 (DBAT2L) */ +#define mtdbat3u(x) mtspr 542,(x) /* SPR 542 (DBAT3U) */ +#define mtdbat3l(x) mtspr 543,(x) /* SPR 543 (DBAT3L) */ + + +/* PowerPC processors do not necessarily initialize the BAT + registers on power-up or reset. So they are in an unknown + state. Before programming the BATs for the first time, all + BAT registers MUST have their Vs and Vp bits cleared in the + upper BAT half in order to avoid possibly having 2 BATs + valid and mapping the same memory region. + + The reason for this is that, even with address translation + disabled, multiple BAT hits for an address are treated as + programming errors and can cause unpredictable results. + + It is up to the software to make sure it never has 2 IBAT + mappings or 2 DBAT mappings that are valid for the same + addresses. It is not necessary to perform this code + sequence every time the BATs are programmed, only when + there is a possibility that there may be overlapping BAT + entries. + + When programming the BATs in non-reset scenarios, even if + you are sure that your new mapping will not temporarily + create overlapping regions, it is still a wise idea to + invalidate a BAT entry by setting its upper BAT register to + all 0's before programming it. This will avoid having a + BAT marked valid that is in an unknown or transient state +*/ + + addis r5,0,0x0000 + mtibat0u(r5) + mtibat0l(r5) + mtibat1u(r5) + mtibat1l(r5) + mtibat2u(r5) + mtibat2l(r5) + mtibat3u(r5) + mtibat3l(r5) + mtdbat0u(r5) + mtdbat0l(r5) + mtdbat1u(r5) + mtdbat1l(r5) + mtdbat2u(r5) + mtdbat2l(r5) + mtdbat3u(r5) + mtdbat3l(r5) + isync + +/* + * Set up I/D BAT0 + */ + lis r4, CFG_DBAT0L@h + ori r4, r4, CFG_DBAT0L@l + lis r3, CFG_DBAT0U@h + ori r3, r3, CFG_DBAT0U@l + + mtdbat0l(r4) + isync + mtdbat0u(r3) + isync + sync + + lis r4, CFG_IBAT0L@h + ori r4, r4, CFG_IBAT0L@l + lis r3, CFG_IBAT0U@h + ori r3, r3, CFG_IBAT0U@l + + isync + mtibat0l(r4) + isync + mtibat0u(r3) + isync + +/* + * Set up I/D BAT1 + */ + lis r4, CFG_IBAT1L@h + ori r4, r4, CFG_IBAT1L@l + lis r3, CFG_IBAT1U@h + ori r3, r3, CFG_IBAT1U@l + + isync + mtibat1l(r4) + isync + mtibat1u(r3) + isync + mtdbat1l(r4) + isync + mtdbat1u(r3) + isync + sync + +/* + * Set up I/D BAT2 + */ + lis r4, CFG_IBAT2L@h + ori r4, r4, CFG_IBAT2L@l + lis r3, CFG_IBAT2U@h + ori r3, r3, CFG_IBAT2U@l + + isync + mtibat2l(r4) + isync + mtibat2u(r3) + isync + mtdbat2l(r4) + isync + mtdbat2u(r3) + isync + sync + +/* + * Setup I/D BAT3 + */ + lis r4, CFG_IBAT3L@h + ori r4, r4, CFG_IBAT3L@l + lis r3, CFG_IBAT3U@h + ori r3, r3, CFG_IBAT3U@l + + isync + mtibat3l(r4) + isync + mtibat3u(r3) + isync + mtdbat3l(r4) + isync + mtdbat3u(r3) + isync + sync + + +/* + * Invalidate all 64 TLB's + */ + lis r3, 0 + mtctr r3 + lis r5, 4 + +tlblp: + tlbie r3 + sync + addi r3, r3, 0x1000 + cmplw r3, r5 + blt tlblp + + sync + +/* + * Enable Data Translation + */ + lis r4, MEMORY_MGMT_MSR_BITS@h + ori r4, r4, MEMORY_MGMT_MSR_BITS@l + mfmsr r3 + or r3, r4, r3 + mtmsr r3 + isync + sync + + blr + + +#ifdef USE_V2_INIT +/* #define USER_I_CACHE_ENABLE 1*/ /* Fast rom boots */ +/* Macro for hiadjust and lo */ +#define HIADJ(arg) arg@ha +#define HI(arg) arg@h +#define LO(arg) arg@l + +#undef LOADPTR +#define LOADPTR(reg,const32) \ + addis reg,r0,HIADJ(const32); addi reg,reg,LO(const32) + +.globl early_init_f + +early_init_f: +/* MPC8245/BMW CPCI System Init + * Jimmy Blair, Broadcom Corp, 2002. + */ + mflr r11 + /* Zero-out registers */ + + addis r0,r0,0 + mtspr SPRG0,r0 + mtspr SPRG1,r0 + mtspr SPRG2,r0 + mtspr SPRG3,r0 + + /* Set MPU/MSR to a known state. Turn on FP */ + + LOADPTR (r3, MSR_FP) + sync + mtmsr r3 + isync + + /* Init the floating point control/status register */ + + mtfsfi 7,0x0 + mtfsfi 6,0x0 + mtfsfi 5,0x0 + mtfsfi 4,0x0 + mtfsfi 3,0x0 + mtfsfi 2,0x0 + mtfsfi 1,0x0 + mtfsfi 0,0x0 + isync + + /* Set MPU/MSR to a known state. Turn off FP */ + +#if 1 /* Turn off floating point (remove to keep FP on) */ + andi. r3, r3, 0 + sync + mtmsr r3 + isync +#endif + + /* Init the Segment registers */ + + andi. r3, r3, 0 + isync + mtsr 0,r3 + isync + mtsr 1,r3 + isync + mtsr 2,r3 + isync + mtsr 3,r3 + isync + mtsr 4,r3 + isync + mtsr 5,r3 + isync + mtsr 6,r3 + isync + mtsr 7,r3 + isync + mtsr 8,r3 + isync + mtsr 9,r3 + isync + mtsr 10,r3 + isync + mtsr 11,r3 + isync + mtsr 12,r3 + isync + mtsr 13,r3 + isync + mtsr 14,r3 + isync + mtsr 15,r3 + isync + + /* Turn off data and instruction cache control bits */ + + mfspr r3, HID0 + isync + rlwinm r4, r3, 0, 18, 15 /* r4 has ICE and DCE bits cleared */ + sync + isync + mtspr HID0, r4 /* HID0 = r4 */ + isync + + /* Get cpu type */ + + mfspr r28, PVR + rlwinm r28, r28, 16, 16, 31 + + /* invalidate the MPU's data/instruction caches */ + + lis r3, 0x0 + cmpli 0, 0, r28, CPU_TYPE_603 + beq cpuIs603 + cmpli 0, 0, r28, CPU_TYPE_603E + beq cpuIs603 + cmpli 0, 0, r28, CPU_TYPE_603P + beq cpuIs603 + cmpli 0, 0, r28, CPU_TYPE_604R + bne cpuNot604R + +cpuIs604R: + lis r3, 0x0 + mtspr HID0, r3 /* disable the caches */ + isync + ori r4, r4, 0x0002 /* disable BTAC by setting bit 30 */ + +cpuNot604R: + ori r3, r3, (HID0_ICFI |HID0_DCI) + +cpuIs603: + ori r3, r3, (HID0_ICE | HID0_DCE) + or r4, r4, r3 /* set bits */ + sync + isync + mtspr HID0, r4 /* HID0 = r4 */ + andc r4, r4, r3 /* clear bits */ + isync + cmpli 0, 0, r28, CPU_TYPE_604 + beq cpuIs604 + cmpli 0, 0, r28, CPU_TYPE_604E + beq cpuIs604 + cmpli 0, 0, r28, CPU_TYPE_604R + beq cpuIs604 + mtspr HID0, r4 + isync + +#ifdef USER_I_CACHE_ENABLE + b instCacheOn603 +#else + b cacheEnableDone +#endif + +cpuIs604: + LOADPTR (r5, 0x1000) /* loop count, 0x1000 */ + mtspr CTR, r5 +loopDelay: + nop + bdnz loopDelay + isync + mtspr HID0, r4 + isync + + /* turn the Instruction cache ON for faster FLASH ROM boots */ + +#ifdef USER_I_CACHE_ENABLE + + ori r4, r4, (HID0_ICE | HID0_ICFI) + isync /* Synchronize for ICE enable */ + b writeReg4 +instCacheOn603: + ori r4, r4, (HID0_ICE | HID0_ICFI) + rlwinm r3, r4, 0, 21, 19 /* clear the ICFI bit */ + + /* + * The setting of the instruction cache enable (ICE) bit must be + * preceded by an isync instruction to prevent the cache from being + * enabled or disabled while an instruction access is in progress. + */ + isync +writeReg4: + mtspr HID0, r4 /* Enable Instr Cache & Inval cache */ + cmpli 0, 0, r28, CPU_TYPE_604 + beq cacheEnableDone + cmpli 0, 0, r28, CPU_TYPE_604E + beq cacheEnableDone + + mtspr HID0, r3 /* using 2 consec instructions */ + /* PPC603 recommendation */ +#endif +cacheEnableDone: + + /* Detect map A or B */ + + addis r5,r0, HI(CHRP_REG_ADDR) + addis r6,r0, HI(CHRP_REG_DATA) + LOADPTR (r7, KAHLUA_ID) /* Kahlua PCI controller ID */ + LOADPTR (r8, BMC_BASE) + + stwbrx r8,0,(r5) + lwbrx r3,0,(r6) /* Store read value to r3 */ + cmp 0,0,r3,r7 + beq cr0, X4_KAHLUA_START + + /* It's not an 8240, is it an 8245? */ + + LOADPTR (r7, KAHLUA2_ID) /* Kahlua PCI controller ID */ + cmp 0,0,r3,r7 + beq cr0, X4_KAHLUA_START + + /* Save the PCI controller type in r7 */ + mr r7, r3 + + LOADPTR (r5, PREP_REG_ADDR) + LOADPTR (r6, PREP_REG_DATA) + +X4_KAHLUA_START: + /* MPC8245 changes begin here */ + LOADPTR (r3, MPC107_PCI_CMD) /* PCI command reg */ + stwbrx r3,0,r5 + li r4, 6 /* Command register value */ + sthbrx r4, 0, r6 + + LOADPTR (r3, MPC107_PCI_STAT) /* PCI status reg */ + stwbrx r3,0,r5 + li r4, -1 /* Write-to-clear all bits */ + li r3, 2 /* PCI_STATUS is at +2 offset */ + sthbrx r4, r3, r6 + + /*-------PROC_INT1_ADR */ + + LOADPTR (r3, PROC_INT1_ADR) /* Processor I/F Config 1 reg. */ + stwbrx r3,0,r5 + LOADPTR (r4, 0xff141b98) + stwbrx r4,0,r6 + + /*-------PROC_INT2_ADR */ + + LOADPTR (r3, PROC_INT2_ADR) /* Processor I/F Config 2 reg. */ + stwbrx r3,0,r5 + lis r4, 0x2000 /* Flush PCI config writes */ + stwbrx r4,0,r6 + + LOADPTR (r9, KAHLUA2_ID) + cmpl 0, 0, r7, r9 + bne L1not8245 + + /* MIOCR1 -- turn on bit for DLL delay */ + + LOADPTR (r3, MIOCR1_ADR_X) + stwbrx r3,0,r5 + li r4, 0x04 + stb r4, MIOCR1_SHIFT(r6) + + /* For the MPC8245, set register 77 to %00100000 (see Errata #15) */ + /* SDRAM_CLK_DEL (0x77)*/ + + LOADPTR (r3, MIOCR2_ADR_X) + stwbrx r3,0,r5 + li r4, 0x10 + stb r4, MIOCR2_SHIFT(r6) + + /* PMCR2 -- set PCI hold delay to <10>b for 33 MHz */ + + LOADPTR (r3, PMCR2_ADR_X) + stwbrx r3,0,r5 + li r4, 0x20 + stb r4, PMCR2_SHIFT(r6) + + /* Initialize EUMBBAR early since 8245 has internal UART in EUMB */ + + LOADPTR (r3, EUMBBAR) + stwbrx r3,0,r5 + LOADPTR (r4, CFG_EUMB_ADDR) + stwbrx r4,0,r6 + +L1not8245: + + /* Toggle the DLL reset bit in AMBOR */ + + LOADPTR (r3, AMBOR) + stwbrx r3,0,r5 + lbz r4, 0(r6) + + andi. r4, r4, 0xdf + stb r4, 0(r6) /* Clear DLL_RESET */ + sync + + ori r4, r4, 0x20 /* Set DLL_RESET */ + stb r4, 0(r6) + sync + + andi. r4, r4, 0xdf + stb r4, 0(r6) /* Clear DLL_RESET */ + + + /* Enable RCS2, use supplied timings */ + LOADPTR (r3, ERCR1) + stwbrx r3,0,r5 + LOADPTR (r4, 0x80408000) + stwbrx r4,0,r6 + + /* Disable RCS3 parameters */ + LOADPTR (r3, ERCR2) + stwbrx r3,0,r5 + LOADPTR (r4, 0x00000000) + stwbrx r4,0,r6 + + /* RCS3 at 0x70000000, 64KBytes */ + LOADPTR (r3, ERCR2) + stwbrx r3,0,r5 + LOADPTR (r4, 0x00000004) + stwbrx r4,0,r6 + + /*-------MCCR1 */ + +#ifdef INCLUDE_ECC +#define MC_ECC 1 +#else /* INCLUDE_ECC */ +#define MC_ECC 0 +#endif /* INCLUDE_ECC */ + +#define MC1_ROMNAL 8 /* 0-15 */ +#define MC1_ROMFAL 11 /* 0-31 */ +#define MC1_DBUS_SIZE 0 /* 0-3, read only */ +#define MC1_BURST 0 /* 0-1 */ +#define MC1_MEMGO 0 /* 0-1 */ +#define MC1_SREN 1 /* 0-1 */ +#define MC1_RAM_TYPE 0 /* 0-1 */ +#define MC1_PCKEN MC_ECC /* 0-1 */ +#define MC1_BANKBITS 0x5555 /* 2 bits/bank 7-0 */ + + LOADPTR (r3, MEM_CONT1_ADR) /* Set MCCR1 (F0) */ + stwbrx r3,0,r5 + LOADPTR(r4, \ + MC1_ROMNAL << 28 | MC1_ROMFAL << 23 | \ + MC1_DBUS_SIZE << 21 | MC1_BURST << 20 | \ + MC1_MEMGO << 19 | MC1_SREN << 18 | \ + MC1_RAM_TYPE << 17 | MC1_PCKEN << 16 ) + li r3, MC1_BANKBITS + cmpl 0, 0, r7, r9 /* Check for Kahlua2 */ + bne BankBitsAdd + cmpli 0, 0, r3, 0x5555 + beq K2BankBitsHack /* On 8245, 5555 ==> 0 */ +BankBitsAdd: + ori r4, r3, 0 +K2BankBitsHack: + stwbrx r4, 0, r6 + + /*------- MCCR2 */ + +#define MC2_TS_WAIT_TIMER 0 /* 0-7 */ +#define MC2_ASRISE 8 /* 0-15 */ +#define MC2_ASFALL 4 /* 0-15 */ +#define MC2_INLINE_PAR_NOT_ECC 0 /* 0-1 */ +#define MC2_WRITE_PARITY_CHK_EN MC_ECC /* 0-1 */ +#define MC2_INLRD_PARECC_CHK_EN MC_ECC /* 0-1 */ +#define MC2_ECC_EN 0 /* 0-1 */ +#define MC2_EDO 0 /* 0-1 */ +/* +* N.B. This refresh interval looks good up to 85 MHz with Hynix SDRAM. +* May need to be decreased for 100 MHz +*/ +#define MC2_REFINT 0x3a5 /* 0-0x3fff */ +#define MC2_RSV_PG 0 /* 0-1 */ +#define MC2_RMW_PAR MC_ECC /* 0-1 */ + + LOADPTR (r3, MEM_CONT2_ADR) /* Set MCCR2 (F4) */ + stwbrx r3,0,r5 + LOADPTR(r4, \ + MC2_TS_WAIT_TIMER << 29 | MC2_ASRISE << 25 | \ + MC2_ASFALL << 21 | MC2_INLINE_PAR_NOT_ECC << 20 | \ + MC2_WRITE_PARITY_CHK_EN << 19 | \ + MC2_INLRD_PARECC_CHK_EN << 18 | \ + MC2_ECC_EN << 17 | MC2_EDO << 16 | \ + MC2_REFINT << 2 | MC2_RSV_PG << 1 | MC2_RMW_PAR) + cmpl 0, 0, r7, r9 /* Check for Kahlua2 */ + bne notK2 + /* clear Kahlua2 reserved bits */ + LOADPTR (r3, 0xfffcffff) + and r4, r4, r3 +notK2: + stwbrx r4,0,r6 + + /*------- MCCR3 */ + +#define MC_BSTOPRE 0x079 /* 0-0x7ff */ + +#define MC3_BSTOPRE_U (MC_BSTOPRE >> 4 & 0xf) +#define MC3_REFREC 8 /* 0-15 */ +#define MC3_RDLAT (4+MC_ECC) /* 0-15 */ +#define MC3_CPX 0 /* 0-1 */ +#define MC3_RAS6P 0 /* 0-15 */ +#define MC3_CAS5 0 /* 0-7 */ +#define MC3_CP4 0 /* 0-7 */ +#define MC3_CAS3 0 /* 0-7 */ +#define MC3_RCD2 0 /* 0-7 */ +#define MC3_RP1 0 /* 0-7 */ + + LOADPTR (r3, MEM_CONT3_ADR) /* Set MCCR3 (F8) */ + stwbrx r3,0,r5 + LOADPTR(r4, \ + MC3_BSTOPRE_U << 28 | MC3_REFREC << 24 | \ + MC3_RDLAT << 20 | MC3_CPX << 19 | \ + MC3_RAS6P << 15 | MC3_CAS5 << 12 | MC3_CP4 << 9 | \ + MC3_CAS3 << 6 | MC3_RCD2 << 3 | MC3_RP1) + cmpl 0, 0, r7, r9 /* Check for Kahlua2 */ + bne notK2b + /* clear Kahlua2 reserved bits */ + LOADPTR (r3, 0xff000000) + and r4, r4, r3 +notK2b: + stwbrx r4,0,r6 + + /*------- MCCR4 */ + +#define MC4_PRETOACT 3 /* 0-15 */ +#define MC4_ACTOPRE 5 /* 0-15 */ +#define MC4_WMODE 0 /* 0-1 */ +#define MC4_INLINE MC_ECC /* 0-1 */ +#define MC4_REGISTERED (1-MC_ECC) /* 0-1 */ +#define MC4_BSTOPRE_UU (MC_BSTOPRE >> 8 & 3) +#define MC4_REGDIMM 0 /* 0-1 */ +#define MC4_SDMODE_CAS 2 /* 0-7 */ +#define MC4_DBUS_RCS1 1 /* 0-1, 8-bit */ +#define MC4_SDMODE_WRAP 0 /* 0-1 */ +#define MC4_SDMODE_BURST 2 /* 0-7 */ +#define MC4_ACTORW 3 /* 0-15 */ +#define MC4_BSTOPRE_L (MC_BSTOPRE & 0xf) + + LOADPTR (r3, MEM_CONT4_ADR) /* Set MCCR4 (FC) */ + stwbrx r3,0,r5 + LOADPTR(r4, \ + MC4_PRETOACT << 28 | MC4_ACTOPRE << 24 | \ + MC4_WMODE << 23 | MC4_INLINE << 22 | \ + MC4_REGISTERED << 20 | MC4_BSTOPRE_UU << 18 | \ + MC4_DBUS_RCS1 << 17 | \ + MC4_REGDIMM << 15 | MC4_SDMODE_CAS << 12 | \ + MC4_SDMODE_WRAP << 11 | MC4_SDMODE_BURST << 8 | \ + MC4_ACTORW << 4 | MC4_BSTOPRE_L) + cmpl 0, 0, r7, r9 /* Check for Kahlua 2 */ + bne notK2c + /* Turn on Kahlua2 extended ROM space */ + LOADPTR (r3, 0x00200000) + or r4, r4, r3 +notK2c: + stwbrx r4,0,r6 + +#ifdef INCLUDE_ECC + /*------- MEM_ERREN1 */ + + LOADPTR (r3, MEM_ERREN1_ADR) /* Set MEM_ERREN1 (c0) */ + stwbrx r3,0,r5 + lwbrx r4,0,r6 + ori r4,r4,4 /* Set MEM_PERR_EN */ + stwbrx r4,0,r6 +#endif /* INCLUDE_ECC */ + + /*------- MSAR/MEAR */ + + LOADPTR (r3, MEM_START1_ADR) /* Set MSAR1 (80) */ + stwbrx r3,0,r5 + LOADPTR (r4, 0xc0804000) + stwbrx r4,0,r6 + + LOADPTR (r3, MEM_START2_ADR) /* Set MSAR2 (84) */ + stwbrx r3,0,r5 + LOADPTR (r4, 0xc0804000) + stwbrx r4,0,r6 + + LOADPTR (r3, XMEM_START1_ADR) /* Set MESAR1 (88) */ + stwbrx r3,0,r5 + LOADPTR (r4, 0x00000000) + stwbrx r4,0,r6 + + LOADPTR (r3, XMEM_START2_ADR) /* Set MESAR2 (8c) */ + stwbrx r3,0,r5 + LOADPTR (r4, 0x01010101) + stwbrx r4,0,r6 + + LOADPTR (r3, MEM_END1_ADR) /* Set MEAR1 (90) */ + stwbrx r3,0,r5 + LOADPTR (r4, 0xffbf7f3f) + stwbrx r4,0,r6 + + LOADPTR (r3, MEM_END2_ADR) /* Set MEAR2 (94) */ + stwbrx r3,0,r5 + LOADPTR (r4, 0xffbf7f3f) + stwbrx r4,0,r6 + + LOADPTR (r3, XMEM_END1_ADR) /* MEEAR1 (98) */ + stwbrx r3,0,r5 + LOADPTR (r4, 0x00000000) + stwbrx r4,0,r6 + + LOADPTR (r3, XMEM_END2_ADR) /* MEEAR2 (9c) */ + stwbrx r3,0,r5 + LOADPTR (r4, 0x01010101) + stwbrx r4,0,r6 + + /*-------ODCR */ + + LOADPTR (r3, ODCR_ADR_X) /* Set ODCR */ + stwbrx r3,0,r5 + + li r4, 0x7f + stb r4, ODCR_SHIFT(r6) /* ODCR is at +3 offset */ + + /*-------MBEN */ + + LOADPTR (r3, MEM_EN_ADR) /* Set MBEN (a0) */ + stwbrx r3,0,r5 + li r4, 0x01 /* Enable bank 0 */ + stb r4, 0(r6) /* MBEN is at +0 offset */ + +#if 0 /* Jimmy: I think page made is broken */ + /*-------PGMAX */ + + LOADPTR (r3, MPM_ADR_X) + stwbrx r3,0,r5 + li r4, 0x32 + stb r4, MPM_SHIFT(r6) /* PAGE_MODE is at +3 offset */ +#endif + + /* Wait before initializing other registers */ + + lis r4,0x0001 + mtctr r4 + +KahluaX4wait200us: + bdnz KahluaX4wait200us + + /* Set MEMGO bit */ + + LOADPTR (r3, MEM_CONT1_ADR) /* MCCR1 (F0) |= PGMAX */ + stwbrx r3,0,r5 + lwbrx r4,0,r6 /* old MCCR1 */ + oris r4,r4,0x0008 /* MEMGO=1 */ + stwbrx r4, 0, r6 + + /* Wait again */ + + addis r4,r0,0x0002 + ori r4,r4,0xffff + + mtctr r4 + +KahluaX4wait8ref: + bdnz KahluaX4wait8ref + + sync + eieio + mtlr r11 + blr + +#else /* USE_V2_INIT */ + + + +/* U-Boot works, but memory will not run reliably for all address ranges. + * Early U-Boot Working init, but 2.4.19 kernel will crash since memory is not + * initialized correctly. Could work if debugged. + */ +/* PCI Support routines */ + + .globl __pci_config_read_32 +__pci_config_read_32: + lis r4, 0xfec0 + stwbrx r3, r0, r4 + sync + lis r4, 0xfee0 + lwbrx r3, 0, r4 + blr + .globl __pci_config_read_16 +__pci_config_read_16: + lis r4, 0xfec0 + andi. r5, r3, 2 + stwbrx r3, r0, r4 + sync + oris r4, r5, 0xfee0 + lhbrx r3, r0, r4 + blr + .globl __pci_config_read_8 +__pci_config_read_8: + lis r4, 0xfec0 + andi. r5, r3, 3 + stwbrx r3, r0, r4 + sync + oris r4, r5, 0xfee0 + lbz r3, 0(4) + blr + .globl __pci_config_write_32 +__pci_config_write_32: + lis r5, 0xfec0 + stwbrx r3, r0, r5 + sync + lis r5, 0xfee0 + stwbrx r4, r0, r5 + sync + blr + .globl __pci_config_write_16 +__pci_config_write_16: + lis r5, 0xfec0 + andi. r6, r3, 2 + stwbrx r3, r0, 5 + sync + oris r5, r6, 0xfee0 + sthbrx r4, r0, r5 + sync + blr + .globl __pci_config_write_8 +__pci_config_write_8: + lis r5, 0xfec0 + andi. r6, r3, 3 + stwbrx r3, r0, r5 + sync + oris r5, r6, 0xfee0 + stb r4, 0(r5) + sync + blr + .globl in_8 +in_8: + oris r3, r3, 0xfe00 + lbz r3,0(r3) + blr + .globl in_16 +in_16: + oris r3, r3, 0xfe00 + lhbrx r3, 0, r3 + blr + .globl in_16_ne +in_16_ne: + oris r3, r3, 0xfe00 + lhzx r3, 0, r3 + blr + .globl in_32 +in_32: + oris r3, r3, 0xfe00 + lwbrx r3, 0, r3 + blr + .globl out_8 +out_8: + oris r3, r3, 0xfe00 + stb r4, 0(r3) + eieio + blr + .globl out_16 +out_16: + oris r3, r3, 0xfe00 + sthbrx r4, 0, r3 + eieio + blr + .globl out_16_ne +out_16_ne: + oris r3, r3, 0xfe00 + sth r4, 0(r3) + eieio + blr + .globl out_32 +out_32: + oris r3, r3, 0xfe00 + stwbrx r4, 0, r3 + eieio + blr + .globl read_8 +read_8: + lbz r3,0(r3) + blr + .globl read_16 +read_16: + lhbrx r3, 0, r3 + blr + .globl read_32 +read_32: + lwbrx r3, 0, r3 + blr + .globl read_32_ne +read_32_ne: + lwz r3, 0(r3) + blr + .globl write_8 +write_8: + stb r4, 0(r3) + eieio + blr + .globl write_16 +write_16: + sthbrx r4, 0, r3 + eieio + blr + .globl write_32 +write_32: + stwbrx r4, 0, r3 + eieio + blr + .globl write_32_ne +write_32_ne: + stw r4, 0(r3) + eieio + blr + + +.globl early_init_f + +early_init_f: + mflr r11 + lis r10, 0x8000 + + /* PCI Latency Timer */ + li r4, 0x0d + ori r3, r10, PLTR@l + bl __pci_config_write_8 + + /* Cache Line Size */ + li r4, 0x08 + ori r3, r10, PCLSR@l + bl __pci_config_write_8 + + /* PCI Cmd */ + li r4, 6 + ori r3, r10, PCICR@l + bl __pci_config_write_16 + +#if 1 + /* PCI Stat */ + ori r3, r10, PCISR@l + bl __pci_config_read_16 + ori r4, r4, 0xffff + ori r3, r10, PCISR@l + bl __pci_config_write_16 +#endif + + /* PICR1 */ + lis r4, 0xff14 + ori r4, r4, 0x1b98 + ori r3, r10, PICR1@l + bl __pci_config_write_32 + + + /* PICR2 */ + lis r4, 0x0404 + ori r4, r4, 0x0004 + ori r3, r10, PICR2@l + bl __pci_config_write_32 + + /* MIOCR1 */ + li r4, 0x04 + ori r3, r10, MIOCR1@l + bl __pci_config_write_8 + + /* For the MPC8245, set register 77 to %00100000 (see Errata #15) */ + /* SDRAM_CLK_DEL (0x77)*/ + li r4, 0x10 + ori r3, r10, MIOCR2@l + bl __pci_config_write_8 + + /* EUMBBAR */ + lis r4, 0xfc00 + ori r3, r10, EUMBBAR@l + bl __pci_config_write_32 + + /* AMBOR */ + + /* Even if Address Map B is not being used (though it should), + * the memory DLL needs to be cleared/set/cleared before using memory. + */ + + ori r3, r10, AMBOR@l + bl __pci_config_read_8 /* get Current bits */ + + andi. r4, r4, 0xffdf + ori r3, r10, AMBOR@l + bl __pci_config_write_16 /* Clear DLL_RESET */ + + ori r4, r4, 0x0020 + ori r3, r10, AMBOR@l + bl __pci_config_write_16 /* Set DLL_RESET */ + + andi. r4, r4, 0xffdf + ori r3, r10, AMBOR@l + bl __pci_config_write_16 /* Clear DLL_RESET */ + + /* ERCR1 */ + lis r4, 0x8040 /* Enable RCS2, use supplied timings */ + ori r4, r4, 0x8000 + ori r3, r10, ERCR1@l + bl __pci_config_write_32 + + /* ERCR2 */ + lis r4, 0x0000 /* Disable RCS3 parms */ + ori r4, r4, 0x0000 + ori r3, r10, ERCR2@l + bl __pci_config_write_32 + + /* ERCR3 */ + lis r4, 0x0000 /* RCS3 at 0x70000000, 64K bytes */ + ori r4, r4, 0x0004 + ori r3, r10, ERCR2@l + bl __pci_config_write_32 + + /* Preserve memgo bit */ + /* MCCR1 */ + +/* lis r4, 0x75a8 / Safe Local ROM = 11+3 clocks */ + lis r4, 0x75a0 /* Safe Local ROM = 11+3 clocks */ +/* lis r4, 0x73a0 / Fast Local ROM = 7+3 clocks */ +/* oris r4, r4, 0x0010 / Burst ROM/Flash enable */ +/* oris r4, r4, 0x0004 / Self-refresh enable */ + +/* ori r4,r4,0xFFFF / 16Mbit 2bank SDRAM */ +/* ori r4,r4,0xAAAA / 256Mbit 4bank SDRAM (8245 only) */ +/* ori r4,r4,0x5555 / 64Mbit 2bank SDRAM */ + ori r4,r4,0x0000 /* 64Mbit 4bank SDRAM */ + + ori r3, r10, MCCR1@l + bl __pci_config_write_32 + + /* MCCR2 */ + + lis r4,0x0000 +/* oris r4,r4,0x4000 / TS_WAIT_TIMER = 3 clocks */ + oris r4,r4,0x1000 /* ASRISE = 8 clocks */ + oris r4,r4,0x0080 /* ASFALL = 8 clocks */ +/* oris r4,r4,0x0010 / SDRAM Parity (else ECC) */ +/* oris r4,r4,0x0008 / Write parity check */ +/* oris r4,r4,0x0004 / SDRAM inline reads */ + + +/* Select a refresh rate; it needs to match the bus speed; if too */ +/* slow, data may be lost; if too fast, performance is lost. We */ +/* use the fastest value so we run at all speeds. */ +/* Refresh = (15600ns/busclk) - (213 (see UM)). */ + +/* ori r4,r4,0x1d2c / 133 MHz mem bus = 1867 */ +/* ori r4,r4,0x150c / 100 MHz mem bus = 1347 */ +/* ori r4,r4,0x10fc / 83 MHz mem bus = 1087 */ +/* ori r4,r4,0x0cc4 / 66 MHz mem bus = 817 */ + ori r4,r4,0x04cc /* 33 MHz mem bus (SAFE) = 307 */ +/* ori r4,r4,0x0002 / Reserve a page */ +/* ori r4,r4,0x0001 / RWM parity */ + + ori r3, r10, MCCR2@l + bl __pci_config_write_32 + + + /* MCCR3 */ + lis r4,0x0000 /* BSTOPRE_M = 7 (see A/N) */ + oris r4,r4,0x0500 /* REFREC = 8 clocks */ + ori r3, r10, MCCR3@l + bl __pci_config_write_32 + + /* MCCR4 */ /* Turn on registered buffer mode */ + lis r4, 0x2000 /* PRETOACT = 3 clocks */ + oris r4,r4,0x0400 /* ACTOPRE = 5 clocks */ +/* oris r4,r4,0x0080 / Enable 8-beat burst (32-bit bus) */ +/* oris r4,r4,0x0040 / Enable Inline ECC/Parity */ + oris r4,r4,0x0020 /* EXTROM enabled */ + oris r4,r4,0x0010 /* Registered buffers */ +/* oris r4,r4,0x0000 / BSTOPRE_U = 0 (see A/N) */ + oris r4,r4,0x0002 /* DBUS_SIZ[2] (8 bit on RCS1) */ + +/* ori r4,r4,0x8000 / Registered DIMMs */ + ori r4,r4,0x2000 /*CAS Latency (CL=3) (see RDLAT) */ +/* ori r4,r4,0x2000 / CAS Latency (CL=2) (see RDLAT) */ +/* ori r4,r4,0x0300 / Sequential wrap/8-beat burst */ + ori r4,r4,0x0200 /* Sequential wrap/4-beat burst */ + ori r4,r4,0x0030 /* ACTORW = 3 clocks */ + ori r4,r4,0x0009 /* BSTOPRE_L = 9 (see A/N) */ + + ori r3, r10, MCCR4@l + bl __pci_config_write_32 + + /* MSAR1 */ + lis r4, 0xc0804000@h + ori r4, r4, 0xc0804000@l + ori r3, r10, MSAR1@l + bl __pci_config_write_32 + + /* MSAR2 */ + lis r4, 0xc0804000@h + ori r4, r4, 0xc0804000@l + ori r3, r10, MSAR2@l + bl __pci_config_write_32 + + /* MESAR1 */ + lis r4, 0x00000000@h + ori r4, r4, 0x00000000@l + ori r3, r10, EMSAR1@l + bl __pci_config_write_32 + + /* MESAR2 */ + lis r4, 0x01010101@h + ori r4, r4, 0x01010101@l + ori r3, r10, EMSAR2@l + bl __pci_config_write_32 + + /* MEAR1 */ + lis r4, 0xffbf7f3f@h + ori r4, r4, 0xffbf7f3f@l + ori r3, r10, MEAR1@l + bl __pci_config_write_32 + + /* MEAR2 */ + lis r4, 0xffbf7f3f@h + ori r4, r4, 0xffbf7f3f@l + ori r3, r10, MEAR2@l + bl __pci_config_write_32 + + /* MEEAR1 */ + lis r4, 0x00000000@h + ori r4, r4, 0x00000000@l + ori r3, r10, EMEAR1@l + bl __pci_config_write_32 + + /* MEEAR2 */ + lis r4, 0x01010101@h + ori r4, r4, 0x01010101@l + ori r3, r10, EMEAR2@l + bl __pci_config_write_32 + + /* ODCR */ + li r4, 0x7f + ori r3, r10, ODCR@l + bl __pci_config_write_8 + + /* MBER */ + li r4, 0x01 + ori r3, r10, MBER@l + bl __pci_config_write_8 + + /* Page CTR aka PGMAX */ + li r4, 0x32 + ori r3, r10, 0x70 + bl __pci_config_write_8 + +#if 0 + /* CLK Drive */ + ori r4, r10, 0xfc01 /* Top bit will be ignored */ + ori r3, r10, 0x74 + bl __pci_config_write_16 +#endif + + /* delay */ + lis r7, 1 + mtctr r7 +label1: bdnz label1 + + /* Set memgo bit */ + /* MCCR1 */ + ori r3, r10, MCCR1@l + bl __pci_config_read_32 + lis r7, 0x0008 + or r4, r3, r7 + ori r3, r10, MCCR1@l + bl __pci_config_write_32 + + /* delay again */ + lis r7, 1 + mtctr r7 +label2: bdnz label2 +#if 0 +/* DEBUG: Infinite loop, write then read */ +loop: + lis r7, 0xffff + mtctr r7 + li r3, 0x5004 + lis r4, 0xa0a0 + ori r4, r4, 0x5050 + bl write_32_ne + li r3, 0x5004 + bl read_32_ne + bdnz loop +#endif + mtlr r11 + blr +#endif + diff --git a/board/gw8260/flash.c b/board/gw8260/flash.c new file mode 100644 index 0000000000..532dd194d7 --- /dev/null +++ b/board/gw8260/flash.c @@ -0,0 +1,523 @@ +/* + * (C) Copyright 2000 + * Marius Groeger + * Sysgo Real-Time Solutions, GmbH + * + * (C) Copyright 2000, 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 + * Advent Networks, Inc. + * Oliver Brown + * + *-------------------------------------------------------------------- + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/*********************************************************************/ +/* DESCRIPTION: + * This file contains the flash routines for the GW8260 board. + * + * + * + * MODULE DEPENDENCY: + * None + * + * + * RESTRICTIONS/LIMITATIONS: + * + * Only supports the following flash devices: + * AMD 29F080B + * AMD 29F016D + * + * Copyright (c) 2001, Advent Networks, Inc. + * + */ +/*********************************************************************/ + +#include +#include + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + +static ulong flash_get_size (vu_long *addr, flash_info_t *info); +static int write_word (flash_info_t *info, ulong dest, ulong data); + +/*********************************************************************/ +/* functions */ +/*********************************************************************/ + +/*********************************************************************/ +/* NAME: flash_init() - initializes flash banks */ +/* */ +/* DESCRIPTION: */ +/* This function initializes the flash bank(s). */ +/* */ +/* RETURNS: */ +/* The size in bytes of the flash */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +unsigned long flash_init (void) +{ + unsigned long size; + int i; + + /* Init: no FLASHes known */ + for (i=0; i= CFG_FLASH0_BASE + flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, + &flash_info[0]); +#endif + +#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR) +# ifndef CFG_ENV_SIZE +# define CFG_ENV_SIZE CFG_ENV_SECT_SIZE +# endif + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SIZE - 1, + &flash_info[0]); +#endif + + return (CFG_FLASH0_SIZE * 1024 * 1024); /*size*/ +} + +/*********************************************************************/ +/* NAME: flash_print_info() - prints flash imformation */ +/* */ +/* DESCRIPTION: */ +/* This function prints the flash information. */ +/* */ +/* INPUTS: */ +/* flash_info_t *info - flash information structure */ +/* */ +/* OUTPUTS: */ +/* Displays flash information to console */ +/* */ +/* RETURNS: */ +/* None */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +void flash_print_info (flash_info_t *info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch ((info->flash_id >> 16) & 0xff) { + case 0x1: + printf ("AMD "); + break; + default: + printf ("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case AMD_ID_F040B: + printf ("AM29F040B (4 Mbit)\n"); + break; + case AMD_ID_F080B: + printf ("AM29F080B (8 Mbit)\n"); + break; + case AMD_ID_F016D: + printf ("AM29F016D (16 Mbit)\n"); + break; + default: + printf ("Unknown Chip Type\n"); + break; + } + + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i=0; isector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); + return; +} + +/*********************************************************************/ +/* The following code cannot be run from FLASH! */ +/*********************************************************************/ + +/*********************************************************************/ +/* NAME: flash_get_size() - detects the flash size */ +/* */ +/* DESCRIPTION: */ +/* 1) Reads vendor ID and devices ID from the flash devices. */ +/* 2) Initializes flash info struct. */ +/* 3) Return the flash size */ +/* */ +/* INPUTS: */ +/* vu_long *addr - pointer to start of flash */ +/* flash_info_t *info - flash information structure */ +/* */ +/* OUTPUTS: */ +/* None */ +/* */ +/* RETURNS: */ +/* Size of the flash in bytes, or 0 if device id is unknown. */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* Only supports the following devices: */ +/* AM29F080D */ +/* AM29F016D */ +/* */ +/*********************************************************************/ +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ + short i; + vu_long vendor, devid; + ulong base = (ulong)addr; + + /*printf("addr = %08lx\n", (unsigned long)addr); */ + + /* Reset and Write auto select command: read Manufacturer ID */ + addr[0x0000] = 0xf0f0f0f0; + addr[0x0555] = 0xAAAAAAAA; + addr[0x02AA] = 0x55555555; + addr[0x0555] = 0x90909090; + udelay (1000); + + vendor = addr[0]; + /*printf("vendor = %08lx\n", vendor); */ + if (vendor != 0x01010101) { + info->size = 0; + goto out; + } + + devid = addr[1]; + /*printf("devid = %08lx\n", devid); */ + + if ((devid & 0xff) == AMD_ID_F080B) { + info->flash_id = (vendor & 0xff) << 16 | AMD_ID_F080B; + /* we have 16 sectors with 64KB each x 4 */ + info->sector_count = 16; + info->size = 4 * info->sector_count * 64*1024; + } else if ((devid & 0xff) == AMD_ID_F016D){ + info->flash_id = (vendor & 0xff) << 16 | AMD_ID_F016D; + /* we have 32 sectors with 64KB each x 4 */ + info->sector_count = 32; + info->size = 4 * info->sector_count * 64*1024; + } else { + info->size = 0; + goto out; + } + /*printf("sector count = %08x\n", info->sector_count); */ + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) { + /* sector base address */ + info->start[i] = base + i * (info->size / info->sector_count); + /* read sector protection at sector address, (A7 .. A0) = 0x02 */ + /* D0 = 1 if protected */ + addr = (volatile unsigned long *)(info->start[i]); + info->protect[i] = addr[2] & 1; + } + + /* reset command */ + addr = (vu_long *)info->start[0]; + + out: + addr[0] = 0xf0f0f0f0; + + /*printf("size = %08x\n", info->size); */ + return info->size; +} + +/*********************************************************************/ +/* NAME: flash_erase() - erases flash by sector */ +/* */ +/* DESCRIPTION: */ +/* This function erases flash sectors starting for s_first to */ +/* s_last. */ +/* */ +/* INPUTS: */ +/* flash_info_t *info - flash information structure */ +/* int s_first - first sector to erase */ +/* int s_last - last sector to erase */ +/* */ +/* OUTPUTS: */ +/* None */ +/* */ +/* RETURNS: */ +/* Returns 0 for success, 1 for failure. */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/*********************************************************************/ +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + vu_long *addr = (vu_long*)(info->start[0]); + int flag, prot, sect, l_sect; + ulong start, now, last; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + prot = 0; + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr[0x0555] = 0xAAAAAAAA; + addr[0x02AA] = 0x55555555; + addr[0x0555] = 0x80808080; + addr[0x0555] = 0xAAAAAAAA; + addr[0x02AA] = 0x55555555; + udelay (100); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr = (vu_long*)(info->start[sect]); + addr[0] = 0x30303030; + l_sect = sect; + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + + start = get_timer (0); + last = start; + addr = (vu_long*)(info->start[l_sect]); + while ((addr[0] & 0x80808080) != 0x80808080) { + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + return 1; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + serial_putc ('.'); + last = now; + } + } + + DONE: + /* reset to read mode */ + addr = (volatile unsigned long *)info->start[0]; + addr[0] = 0xF0F0F0F0; /* reset bank */ + + printf (" done\n"); + return 0; +} + +/*********************************************************************/ +/* NAME: write_buff() - writes a buffer to flash */ +/* */ +/* DESCRIPTION: */ +/* This function copies a buffer, *src, to flash. */ +/* */ +/* INPUTS: */ +/* flash_info_t *info - flash information structure */ +/* uchar *src - pointer to buffer to write to flash */ +/* ulong addr - address to start write at */ +/* ulong cnt - number of bytes to write to flash */ +/* */ +/* OUTPUTS: */ +/* None */ +/* */ +/* RETURNS: */ +/* 0 - OK */ +/* 1 - write timeout */ +/* 2 - Flash not erased */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/*********************************************************************/ +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong cp, wp, data; + int i, l, rc; + + wp = (addr & ~3); /* get lower word aligned address */ + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i = 0, cp = wp; i < l; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + for (; (i < 4) && (cnt > 0); ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; (cnt == 0) && (i < 4); ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + } + + /* + * handle word aligned part + */ + while (cnt >= 4) { + data = 0; + for (i = 0; i < 4; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + cnt -= 4; + } + + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i = 0, cp = wp; (i < 4) && (cnt > 0); ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; (i < 4); ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + return (write_word(info, wp, data)); +} + +/*********************************************************************/ +/* NAME: write_word() - writes a word to flash */ +/* */ +/* DESCRIPTION: */ +/* This writes a single word to flash. */ +/* */ +/* INPUTS: */ +/* flash_info_t *info - flash information structure */ +/* ulong dest - address to write */ +/* ulong data - data to write */ +/* */ +/* OUTPUTS: */ +/* None */ +/* */ +/* RETURNS: */ +/* 0 - OK */ +/* 1 - write timeout */ +/* 2 - Flash not erased */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/*********************************************************************/ +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ + vu_long *addr = (vu_long*)(info->start[0]); + ulong start; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if ((*((vu_long *)dest) & data) != data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr[0x0555] = 0xAAAAAAAA; + addr[0x02AA] = 0x55555555; + addr[0x0555] = 0xA0A0A0A0; + + *((vu_long *)dest) = data; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); + while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + return (0); +} +/*********************************************************************/ +/* End of flash.c */ +/*********************************************************************/ diff --git a/board/gw8260/gw8260.c b/board/gw8260/gw8260.c new file mode 100644 index 0000000000..7ca1989909 --- /dev/null +++ b/board/gw8260/gw8260.c @@ -0,0 +1,659 @@ +/* + * (C) Copyright 2000 + * Sysgo Real-Time Solutions, GmbH + * Marius Groeger + * + * (C) Copyright 2001 + * Advent Networks, Inc. + * Jay Monkman + * + * (C) Copyright 2001 + * Advent Networks, Inc. + * Oliver Brown + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/*********************************************************************/ +/* DESCRIPTION: + * This file contains the board routines for the GW8260 board. + * + * MODULE DEPENDENCY: + * None + * + * RESTRICTIONS/LIMITATIONS: + * None + * + * Copyright (c) 2001, Advent Networks, Inc. + */ +/*********************************************************************/ + +#include +#include +#include + +/* + * I/O Port configuration table + * + */ +const iop_conf_t iop_conf_tab[4][32] = { + + /* Port A configuration */ + { /* conf ppar psor pdir podr pdat */ + /* PA31 */ { 1, 0, 0, 1, 0, 0 }, /* TP14 */ + /* PA30 */ { 1, 1, 1, 1, 0, 0 }, /* US_RTS */ + /* PA29 */ { 1, 0, 0, 1, 0, 1 }, /* LSSI_DATA */ + /* PA28 */ { 1, 0, 0, 1, 0, 1 }, /* LSSI_CLK */ + /* PA27 */ { 1, 0, 0, 1, 0, 0 }, /* TP12 */ + /* PA26 */ { 1, 0, 0, 0, 0, 0 }, /* IO_STATUS */ + /* PA25 */ { 1, 0, 0, 0, 0, 0 }, /* IO_CLOCK */ + /* PA24 */ { 1, 0, 0, 0, 0, 0 }, /* IO_CONFIG */ + /* PA23 */ { 1, 0, 0, 0, 0, 0 }, /* IO_DONE */ + /* PA22 */ { 1, 0, 0, 0, 0, 0 }, /* IO_DATA */ + /* PA21 */ { 1, 1, 0, 1, 0, 0 }, /* US_TXD3 */ + /* PA20 */ { 1, 1, 0, 1, 0, 0 }, /* US_TXD2 */ + /* PA19 */ { 1, 1, 0, 1, 0, 0 }, /* US_TXD1 */ + /* PA18 */ { 1, 1, 0, 1, 0, 0 }, /* US_TXD0 */ + /* PA17 */ { 1, 1, 0, 0, 0, 0 }, /* DS_RXD0 */ + /* PA16 */ { 1, 1, 0, 0, 0, 0 }, /* DS_RXD1 */ + /* PA15 */ { 1, 1, 0, 0, 0, 0 }, /* DS_RXD2 */ + /* PA14 */ { 1, 1, 0, 0, 0, 0 }, /* DS_RXD3 */ + /* PA13 */ { 1, 0, 0, 1, 0, 0 }, /* SPARE7 */ + /* PA12 */ { 1, 0, 0, 1, 0, 0 }, /* SPARE6 */ + /* PA11 */ { 1, 0, 0, 1, 0, 0 }, /* SPARE5 */ + /* PA10 */ { 1, 0, 0, 1, 0, 0 }, /* SPARE4 */ + /* PA9 */ { 1, 0, 0, 1, 0, 0 }, /* SPARE3 */ + /* PA8 */ { 1, 0, 0, 1, 0, 0 }, /* SPARE2 */ + /* PA7 */ { 1, 0, 0, 0, 0, 0 }, /* LSSI_IN */ + /* PA6 */ { 1, 0, 0, 1, 0, 0 }, /* SPARE0 */ + /* PA5 */ { 1, 0, 0, 1, 0, 0 }, /* DEMOD_RESET_ */ + /* PA4 */ { 1, 0, 0, 1, 0, 0 }, /* MOD_RESET_ */ + /* PA3 */ { 1, 0, 0, 1, 0, 0 }, /* IO_RESET */ + /* PA2 */ { 1, 0, 0, 1, 0, 0 }, /* TX_ENABLE */ + /* PA1 */ { 1, 0, 0, 0, 0, 0 }, /* RX_LOCK */ + /* PA0 */ { 1, 0, 0, 1, 0, 1 } /* MPC_RESET_ */ + }, + + /* Port B configuration */ + { /* conf ppar psor pdir podr pdat */ + /* PB31 */ { 1, 1, 0, 1, 0, 0 }, /* FETH0_TX_ER */ + /* PB30 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_RX_DV */ + /* PB29 */ { 1, 1, 1, 1, 0, 0 }, /* FETH0_TX_EN */ + /* PB28 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_RX_ER */ + /* PB27 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_COL */ + /* PB26 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_CRS */ + /* PB25 */ { 1, 1, 0, 1, 0, 0 }, /* FETH0_TXD3 */ + /* PB24 */ { 1, 1, 0, 1, 0, 0 }, /* FETH0_TXD2 */ + /* PB23 */ { 1, 1, 0, 1, 0, 0 }, /* FETH0_TXD1 */ + /* PB22 */ { 1, 1, 0, 1, 0, 0 }, /* FETH0_TXD0 */ + /* PB21 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_RXD0 */ + /* PB20 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_RXD1 */ + /* PB19 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_RXD2 */ + /* PB18 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_RXD3 */ + /* PB17 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_RX_DV */ + /* PB16 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_RX_ER */ + /* PB15 */ { 1, 1, 0, 1, 0, 0 }, /* FETH1_TX_ER */ + /* PB14 */ { 1, 1, 0, 1, 0, 0 }, /* FETH1_TX_EN */ + /* PB13 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_COL */ + /* PB12 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_CRS */ + /* PB11 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_RXD3 */ + /* PB10 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_RXD2 */ + /* PB9 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_RXD1 */ + /* PB8 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_RXD0 */ + /* PB7 */ { 1, 1, 0, 1, 0, 0 }, /* FETH1_TXD0 */ + /* PB6 */ { 1, 1, 0, 1, 0, 0 }, /* FETH1_TXD1 */ + /* PB5 */ { 1, 1, 0, 1, 0, 0 }, /* FETH1_TXD2 */ + /* PB4 */ { 1, 1, 0, 1, 0, 0 }, /* FETH1_TXD3 */ + /* PB3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PB0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */ + }, + + /* Port C */ + { /* conf ppar psor pdir podr pdat */ + /* PC31 */ { 1, 0, 0, 1, 0, 1 }, /* FAST_RESET_ */ + /* PC30 */ { 1, 0, 0, 1, 0, 1 }, /* FAST_PAUSE_ */ + /* PC29 */ { 1, 0, 0, 1, 0, 0 }, /* FAST_SLEW1 */ + /* PC28 */ { 1, 0, 0, 1, 0, 0 }, /* FAST_SLEW0 */ + /* PC27 */ { 1, 0, 0, 1, 0, 0 }, /* TP13 */ + /* PC26 */ { 1, 0, 0, 0, 0, 0 }, /* RXDECDFLG */ + /* PC25 */ { 1, 0, 0, 0, 0, 0 }, /* RXACQFAIL */ + /* PC24 */ { 1, 0, 0, 0, 0, 0 }, /* RXACQFLG */ + /* PC23 */ { 1, 0, 0, 1, 0, 0 }, /* WD_TCL */ + /* PC22 */ { 1, 0, 0, 1, 0, 0 }, /* WD_EN */ + /* PC21 */ { 1, 0, 0, 1, 0, 0 }, /* US_TXCLK */ + /* PC20 */ { 1, 0, 0, 0, 0, 0 }, /* DS_RXCLK */ + /* PC19 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_RX_CLK */ + /* PC18 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_TX_CLK */ + /* PC17 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_RX_CLK */ + /* PC16 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_TX_CLK */ + /* PC15 */ { 1, 0, 0, 1, 0, 0 }, /* TX_SHUTDOWN_ */ + /* PC14 */ { 1, 0, 0, 0, 0, 0 }, /* RS_232_DTR_ */ + /* PC13 */ { 1, 0, 0, 0, 0, 0 }, /* TXERR */ + /* PC12 */ { 1, 0, 0, 1, 0, 1 }, /* FETH1_MDDIS */ + /* PC11 */ { 1, 0, 0, 1, 0, 1 }, /* FETH0_MDDIS */ + /* PC10 */ { 1, 0, 0, 1, 0, 0 }, /* MDC */ + /* PC9 */ { 1, 0, 0, 1, 1, 1 }, /* MDIO */ + /* PC8 */ { 1, 0, 0, 1, 1, 1 }, /* SER_NUM */ + /* PC7 */ { 1, 1, 0, 0, 0, 0 }, /* US_CTS */ + /* PC6 */ { 1, 1, 0, 0, 0, 0 }, /* DS_CD_ */ + /* PC5 */ { 1, 0, 0, 1, 0, 0 }, /* FETH1_PWRDWN */ + /* PC4 */ { 1, 0, 0, 1, 0, 0 }, /* FETH0_PWRDWN */ + /* PC3 */ { 1, 0, 0, 1, 0, 0 }, /* MPULED3 */ + /* PC2 */ { 1, 0, 0, 1, 0, 0 }, /* MPULED2 */ + /* PC1 */ { 1, 0, 0, 1, 0, 0 }, /* MPULED1 */ + /* PC0 */ { 1, 0, 0, 1, 0, 1 }, /* MPULED0 */ + }, + + /* Port D */ + { /* conf ppar psor pdir podr pdat */ + /* PD31 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD30 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD29 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD28 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD27 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD26 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD25 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD24 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD23 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD22 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD21 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD20 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD19 */ { 1, 1, 1, 0, 0, 0 }, /* not used */ + /* PD18 */ { 1, 1, 1, 0, 0, 0 }, /* not used */ + /* PD17 */ { 1, 1, 1, 0, 0, 0 }, /* not used */ + /* PD16 */ { 1, 1, 1, 0, 0, 0 }, /* not used */ + /* PD15 */ { 1, 1, 1, 0, 1, 1 }, /* SDRAM_SDA */ + /* PD14 */ { 1, 1, 1, 0, 1, 1 }, /* SDRAM_SCL */ + /* PD13 */ { 1, 0, 0, 1, 0, 0 }, /* MPULED7 */ + /* PD12 */ { 1, 0, 0, 1, 0, 0 }, /* MPULED6 */ + /* PD11 */ { 1, 0, 0, 1, 0, 0 }, /* MPULED5 */ + /* PD10 */ { 1, 0, 0, 1, 0, 0 }, /* MPULED4 */ + /* PD9 */ { 1, 1, 0, 1, 0, 0 }, /* RS232_TXD */ + /* PD8 */ { 1, 1, 0, 0, 0, 0 }, /* RD232_RXD */ + /* PD7 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD6 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD5 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD4 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ + /* PD3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ + /* PD0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */ + } +}; + +/*********************************************************************/ +/* NAME: checkboard() - Displays the board type and serial number */ +/* */ +/* OUTPUTS: */ +/* Displays the board type and serial number */ +/* */ +/* RETURNS: */ +/* Always returns 1 */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +int checkboard(void) +{ + char *str; + puts ("Board: Advent Networks gw8260\n"); + + str = getenv("serial#"); + if (str != NULL) { + printf("SN: %s\n", str); + } + return 0; +} + + +#if defined (CFG_DRAM_TEST) +/*********************************************************************/ +/* NAME: move64() - moves a double word (64-bit) */ +/* */ +/* DESCRIPTION: */ +/* this function performs a double word move from the data at */ +/* the source pointer to the location at the destination pointer. */ +/* */ +/* INPUTS: */ +/* unsigned long long *src - pointer to data to move */ +/* */ +/* OUTPUTS: */ +/* unsigned long long *dest - pointer to locate to move data */ +/* */ +/* RETURNS: */ +/* None */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* May cloober fr0. */ +/* */ +/*********************************************************************/ +static void move64(unsigned long long *src, unsigned long long *dest) +{ + asm ("lfd 0, 0(3)\n\t" /* fpr0 = *scr */ + "stfd 0, 0(4)" /* *dest = fpr0 */ + : : : "fr0" ); /* Clobbers fr0 */ + return; +} + + +#if defined (CFG_DRAM_TEST_DATA) + +unsigned long long pattern[]= { + 0xaaaaaaaaaaaaaaaa, + 0xcccccccccccccccc, + 0xf0f0f0f0f0f0f0f0, + 0xff00ff00ff00ff00, + 0xffff0000ffff0000, + 0xffffffff00000000, + 0x00000000ffffffff, + 0x0000ffff0000ffff, + 0x00ff00ff00ff00ff, + 0x0f0f0f0f0f0f0f0f, + 0x3333333333333333, + 0x5555555555555555}; + +/*********************************************************************/ +/* NAME: mem_test_data() - test data lines for shorts and opens */ +/* */ +/* DESCRIPTION: */ +/* Tests data lines for shorts and opens by forcing adjacent data */ +/* to opposite states. Because the data lines could be routed in */ +/* an arbitrary manner the must ensure test patterns ensure that */ +/* every case is tested. By using the following series of binary */ +/* patterns every combination of adjacent bits is test regardless */ +/* of routing. */ +/* */ +/* ...101010101010101010101010 */ +/* ...110011001100110011001100 */ +/* ...111100001111000011110000 */ +/* ...111111110000000011111111 */ +/* */ +/* Carrying this out, gives us six hex patterns as follows: */ +/* */ +/* 0xaaaaaaaaaaaaaaaa */ +/* 0xcccccccccccccccc */ +/* 0xf0f0f0f0f0f0f0f0 */ +/* 0xff00ff00ff00ff00 */ +/* 0xffff0000ffff0000 */ +/* 0xffffffff00000000 */ +/* */ +/* The number test patterns will always be given by: */ +/* */ +/* log(base 2)(number data bits) = log2 (64) = 6 */ +/* */ +/* To test for short and opens to other signals on our boards. we */ +/* simply */ +/* test with the 1's complemnt of the paterns as well. */ +/* */ +/* OUTPUTS: */ +/* Displays failing test pattern */ +/* */ +/* RETURNS: */ +/* 0 - Passed test */ +/* 1 - Failed test */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* Assumes only one one SDRAM bank */ +/* */ +/*********************************************************************/ +int mem_test_data(void) +{ + unsigned long long * pmem = + (unsigned long long *)CFG_SDRAM_BASE ; + unsigned long long temp64; + int num_patterns = sizeof(pattern)/ sizeof(pattern[0]); + int i; + unsigned int hi, lo; + + for ( i = 0; i < num_patterns; i++) { + move64(&(pattern[i]), pmem); + move64(pmem, &temp64); + + /* hi = (temp64>>32) & 0xffffffff; */ + /* lo = temp64 & 0xffffffff; */ + /* printf("\ntemp64 = 0x%08x%08x", hi, lo); */ + + hi = (pattern[i]>>32) & 0xffffffff; + lo = pattern[i] & 0xffffffff; + /* printf("\npattern[%d] = 0x%08x%08x", i, hi, lo); */ + + if (temp64 != pattern[i]){ + printf ("\n Data Test Failed, pattern 0x%08x%08x", hi, lo); + return 1; + } + } + + return 0; +} +#endif /* CFG_DRAM_TEST_DATA */ + +#if defined (CFG_DRAM_TEST_ADDRESS) +/*********************************************************************/ +/* NAME: mem_test_address() - test address lines */ +/* */ +/* DESCRIPTION: */ +/* This function performs a test to verify that each word im */ +/* memory is uniquly addressable. The test sequence is as follows: */ +/* */ +/* 1) write the address of each word to each word. */ +/* 2) verify that each location equals its address */ +/* */ +/* OUTPUTS: */ +/* Displays failing test pattern and address */ +/* */ +/* RETURNS: */ +/* 0 - Passed test */ +/* 1 - Failed test */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +int mem_test_address(void) +{ + volatile unsigned int * pmem = (volatile unsigned int *)CFG_SDRAM_BASE ; + const unsigned int size = (CFG_SDRAM_SIZE * 1024 * 1024)/4; + unsigned int i; + + /* write address to each location */ + for ( i = 0; i < size; i++) { + pmem[i] = i; + } + + /* verify each loaction */ + for ( i = 0; i < size; i++) { + if (pmem[i] != i) { + printf("\n Address Test Failed at 0x%x", i); + return 1; + } + } + return 0; +} +#endif /* CFG_DRAM_TEST_ADDRESS */ + +#if defined (CFG_DRAM_TEST_WALK) +/*********************************************************************/ +/* NAME: mem_march() - memory march */ +/* */ +/* DESCRIPTION: */ +/* Marches up through memory. At each location verifies rmask if */ +/* read = 1. At each location write wmask if write = 1. Displays */ +/* failing address and pattern. */ +/* */ +/* INPUTS: */ +/* volatile unsigned long long * base - start address of test */ +/* unsigned int size - number of dwords(64-bit) to test */ +/* unsigned long long rmask - read verify mask */ +/* unsigned long long wmask - wrtie verify mask */ +/* short read - verifies rmask if read = 1 */ +/* short write - writes wmask if write = 1 */ +/* */ +/* OUTPUTS: */ +/* Displays failing test pattern and address */ +/* */ +/* RETURNS: */ +/* 0 - Passed test */ +/* 1 - Failed test */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +int mem_march(volatile unsigned long long * base, + unsigned int size, + unsigned long long rmask, + unsigned long long wmask, + short read, + short write) +{ + unsigned int i; + unsigned long long temp; + unsigned int hitemp, lotemp, himask, lomask; + + for (i = 0 ; i < size ; i++) { + if (read != 0) { + /* temp = base[i]; */ + move64 ((unsigned long long *)&(base[i]), &temp); + if (rmask != temp) { + hitemp = (temp>>32) & 0xffffffff; + lotemp = temp & 0xffffffff; + himask = (rmask>>32) & 0xffffffff; + lomask = rmask & 0xffffffff; + + printf("\n Walking one's test failed: address = 0x%08x," + "\n\texpected 0x%08x%08x, found 0x%08x%08x", + i<<3, himask, lomask, hitemp, lotemp); + return 1; + } + } + if ( write != 0 ) { + /* base[i] = wmask; */ + move64 (&wmask, (unsigned long long *)&(base[i])); + } + } + return 0; +} +#endif /* CFG_DRAM_TEST_WALK */ + +/*********************************************************************/ +/* NAME: mem_test_walk() - a simple walking ones test */ +/* */ +/* DESCRIPTION: */ +/* Performs a walking ones through entire physical memory. The */ +/* test uses as series of memory marches, mem_march(), to verify */ +/* and write the test patterns to memory. The test sequence is as */ +/* follows: */ +/* 1) march writing 0000...0001 */ +/* 2) march verifying 0000...0001 , writing 0000...0010 */ +/* 3) repeat step 2 shifting masks left 1 bit each time unitl */ +/* the write mask equals 1000...0000 */ +/* 4) march verifying 1000...0000 */ +/* The test fails if any of the memory marches return a failure. */ +/* */ +/* OUTPUTS: */ +/* Displays which pass on the memory test is executing */ +/* */ +/* RETURNS: */ +/* 0 - Passed test */ +/* 1 - Failed test */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +int mem_test_walk(void) +{ + unsigned long long mask; + volatile unsigned long long * pmem = + (volatile unsigned long long *)CFG_SDRAM_BASE ; + const unsigned long size = (CFG_SDRAM_SIZE * 1024 * 1024)/8; + + unsigned int i; + mask = 0x01; + + printf("Initial Pass"); + mem_march(pmem,size,0x0,0x1,0,1); + + printf("\b\b\b\b\b\b\b\b\b\b\b\b"); + printf(" "); + printf("\b\b\b\b\b\b\b\b\b\b\b\b"); + + for (i = 0 ; i < 63 ; i++) { + printf("Pass %2d", i+2); + if ( mem_march(pmem,size, mask,mask << 1, 1, 1) != 0 ){ + /*printf("mask: 0x%x, pass: %d, ", mask, i);*/ + return 1; + } + mask = mask<<1; + printf("\b\b\b\b\b\b\b"); + } + + printf("Last Pass"); + if (mem_march(pmem, size, 0, mask, 0, 1) != 0) { + /* printf("mask: 0x%x", mask); */ + return 1; + } + printf("\b\b\b\b\b\b\b\b\b"); + printf(" "); + printf("\b\b\b\b\b\b\b\b\b"); + + return 0; +} + +/*********************************************************************/ +/* NAME: testdram() - calls any enabled memory tests */ +/* */ +/* DESCRIPTION: */ +/* Runs memory tests if the environment test variables are set to */ +/* 'y'. */ +/* */ +/* INPUTS: */ +/* testdramdata - If set to 'y', data test is run. */ +/* testdramaddress - If set to 'y', address test is run. */ +/* testdramwalk - If set to 'y', walking ones test is run */ +/* */ +/* OUTPUTS: */ +/* None */ +/* */ +/* RETURNS: */ +/* 0 - Passed test */ +/* 1 - Failed test */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +int testdram(void) +{ + char *s; + int rundata, runaddress, runwalk; + + s = getenv ("testdramdata"); + rundata = (s && (*s == 'y')) ? 1 : 0; + s = getenv ("testdramaddress"); + runaddress = (s && (*s == 'y')) ? 1 : 0; + s = getenv ("testdramwalk"); + runwalk = (s && (*s == 'y')) ? 1 : 0; + + if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) { + printf("Testing RAM ... "); + } +#ifdef CFG_DRAM_TEST_DATA + if (rundata == 1) { + if (mem_test_data() == 1){ + return 1; + } + } +#endif +#ifdef CFG_DRAM_TEST_ADDRESS + if (runaddress == 1) { + if (mem_test_address() == 1){ + return 1; + } + } +#endif +#ifdef CFG_DRAM_TEST_WALK + if (runwalk == 1) { + if (mem_test_walk() == 1){ + return 1; + } + } +#endif + if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) { + printf("passed"); + } + return 0; + +} +#endif /* CFG_DRAM_TEST */ + +/*********************************************************************/ +/* NAME: initdram() - initializes SDRAM controller */ +/* */ +/* DESCRIPTION: */ +/* Initializes the MPC8260's SDRAM controller. */ +/* */ +/* INPUTS: */ +/* CFG_IMMR - MPC8260 Internal memory map */ +/* CFG_SDRAM_BASE - Physical start address of SDRAM */ +/* CFG_PSDMR - SDRAM mode register */ +/* CFG_MPTPR - Memory refresh timer prescaler register */ +/* CFG_SDRAM0_SIZE - SDRAM size */ +/* */ +/* RETURNS: */ +/* SDRAM size in bytes */ +/* */ +/* RESTRICTIONS/LIMITATIONS: */ +/* */ +/* */ +/*********************************************************************/ +long int initdram(int board_type) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8260_t *memctl = &immap->im_memctl; + volatile uchar c = 0, *ramaddr = (uchar *)(CFG_SDRAM_BASE + 0x8); + ulong psdmr = CFG_PSDMR; + int i; + + /* + * Quote from 8260 UM (10.4.2 SDRAM Power-On Initialization, 10-35): + * + * "At system reset, initialization software must set up the + * programmable parameters in the memory controller banks registers + * (ORx, BRx, P/LSDMR). After all memory parameters are configured, + * system software should execute the following initialization sequence + * for each SDRAM device. + * + * 1. Issue a PRECHARGE-ALL-BANKS command + * 2. Issue eight CBR REFRESH commands + * 3. Issue a MODE-SET command to initialize the mode register + * + * The initial commands are executed by setting P/LSDMR[OP] and + * accessing the SDRAM with a single-byte transaction." + * + * The appropriate BRx/ORx registers have already been set when we + * get here. The SDRAM can be accessed at the address CFG_SDRAM_BASE. + */ + + memctl->memc_psrt = CFG_PSRT; + memctl->memc_mptpr = CFG_MPTPR; + + memctl->memc_psdmr = psdmr | PSDMR_OP_PREA; + *ramaddr = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_CBRR; + for (i = 0; i < 8; i++){ + *ramaddr = c; + } + memctl->memc_psdmr = psdmr | PSDMR_OP_MRW; + *ramaddr = c; + + memctl->memc_psdmr = psdmr | PSDMR_OP_NORM | PSDMR_RFEN; + *ramaddr = c; + + /* return total ram size */ + return (CFG_SDRAM0_SIZE * 1024 * 1024); +} + +/*********************************************************************/ +/* End of gw8260.c */ +/*********************************************************************/ diff --git a/board/mvs1/flash.c b/board/mvs1/flash.c new file mode 100644 index 0000000000..75d9048bac --- /dev/null +++ b/board/mvs1/flash.c @@ -0,0 +1,719 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Changes for MATRIX Vision MVsensor (C) Copyright 2001 + * MATRIX Vision GmbH / hg, info@matrix-vision.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include + +#undef MVDEBUG +#ifdef MVDEBUG +#define mvdebug debug +#else +#define mvdebug(p) do {} while (0) +#endif + + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + + +#ifdef CONFIG_MVS_16BIT_FLASH + #define FLASH_DATA_MASK 0xffff + #define FLASH_SHIFT 0 +#else + #define FLASH_DATA_MASK 0xffffffff + #define FLASH_SHIFT 1 +#endif + + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (vu_long *address, flash_info_t *info); +static int write_word (flash_info_t *info, ulong dest, ulong data); +static void flash_get_offsets (ulong base, flash_info_t *info); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + unsigned long size_b0, size_b1; + int i; + + /* Init: no FLASHes known */ + for (i=0; i size_b0) { + printf ("## ERROR: " + "Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n", + size_b1, size_b1<<20, + size_b0, size_b0<<20 + ); + flash_info[0].flash_id = FLASH_UNKNOWN; + flash_info[1].flash_id = FLASH_UNKNOWN; + flash_info[0].sector_count = -1; + flash_info[1].sector_count = -1; + flash_info[0].size = 0; + flash_info[1].size = 0; + return (0); + } +#else + size_b1 = 0; +#endif + + /* Remap FLASH according to real size */ + memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000); +#ifdef CONFIG_MVS_16BIT_FLASH + memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_PS_16 | BR_MS_GPCM | BR_V; +#else + memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_PS_32 | BR_MS_GPCM | BR_V; +#endif + + /* Re-do sizing to get full correct info */ + size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]); + + flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]); + + /* monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_FLASH_BASE, + CFG_FLASH_BASE+CFG_MONITOR_LEN-1, + &flash_info[0]); + + if (size_b1) { + memctl->memc_or1 = CFG_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000); +#ifdef CONFIG_MVS_16BIT_FLASH + memctl->memc_br1 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) | + BR_PS_16 | BR_MS_GPCM | BR_V; +#else + memctl->memc_br1 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) | + BR_PS_32 | BR_MS_GPCM | BR_V; +#endif + /* Re-do sizing to get full correct info */ + size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + size_b0), + &flash_info[1]); + + flash_get_offsets (CFG_FLASH_BASE + size_b0, &flash_info[1]); + + /* monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_FLASH_BASE, + CFG_FLASH_BASE+CFG_MONITOR_LEN-1, + &flash_info[1]); + } else { + memctl->memc_br1 = 0; /* invalidate bank */ + + flash_info[1].flash_id = FLASH_UNKNOWN; + flash_info[1].sector_count = -1; + } + + flash_info[0].size = size_b0; + flash_info[1].size = size_b1; + + return (size_b0 + size_b1); +} + +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t *info) +{ + int i; + + /* set up sector start address table */ + if (info->flash_id & FLASH_BTYPE) + { /* bottom boot sector types - these are the useful ones! */ + /* set sector offsets for bottom boot block type */ + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) + { /* AMDLV320B has 8 x 8k bottom boot sectors */ + for (i = 0; i < 8; i++) /* +8k */ + info->start[i] = base + (i * (0x00002000 << FLASH_SHIFT)); + for (; i < info->sector_count; i++) /* +64k */ + info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)) - (0x00070000 << FLASH_SHIFT); + } + else + { /* other types have 4 bottom boot sectors (16,8,8,32) */ + i = 0; + info->start[i++] = base + 0x00000000; /* - */ + info->start[i++] = base + (0x00004000 << FLASH_SHIFT); /* +16k */ + info->start[i++] = base + (0x00006000 << FLASH_SHIFT); /* +8k */ + info->start[i++] = base + (0x00008000 << FLASH_SHIFT); /* +8k */ + info->start[i++] = base + (0x00010000 << FLASH_SHIFT); /* +32k */ + for (; i < info->sector_count; i++) /* +64k */ + info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)) - (0x00030000 << FLASH_SHIFT); + } + } + else + { /* top boot sector types - not so useful */ + /* set sector offsets for top boot block type */ + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) + { /* AMDLV320T has 8 x 8k top boot sectors */ + for (i = 0; i < info->sector_count - 8; i++) /* +64k */ + info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)); + for (; i < info->sector_count; i++) /* +8k */ + info->start[i] = base + (i * (0x00002000 << FLASH_SHIFT)); + } + else + { /* other types have 4 top boot sectors (32,8,8,16) */ + for (i = 0; i < info->sector_count - 4; i++) /* +64k */ + info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)); + + info->start[i++] = base + info->size - (0x00010000 << FLASH_SHIFT); /* -32k */ + info->start[i++] = base + info->size - (0x00008000 << FLASH_SHIFT); /* -8k */ + info->start[i++] = base + info->size - (0x00006000 << FLASH_SHIFT); /* -8k */ + info->start[i] = base + info->size - (0x00004000 << FLASH_SHIFT); /* -16k */ + } + } +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t *info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_AMD: printf ("AMD "); break; + case FLASH_MAN_FUJ: printf ("FUJITSU "); break; + case FLASH_MAN_STM: printf ("ST "); break; + default: printf ("Unknown Vendor "); break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n"); + break; + case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n"); + break; + case FLASH_STMW320DB: printf ("M29W320B (32 Mbit, bottom boot sect)\n"); + break; + case FLASH_STMW320DT: printf ("M29W320T (32 Mbit, top boot sector)\n"); + break; + default: printf ("Unknown Chip Type\n"); + break; + } + + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i=0; isector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); +} + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ + +#define AMD_ID_LV160T_MVS (AMD_ID_LV160T & FLASH_DATA_MASK) +#define AMD_ID_LV160B_MVS (AMD_ID_LV160B & FLASH_DATA_MASK) +#define AMD_ID_LV320T_MVS (AMD_ID_LV320T & FLASH_DATA_MASK) +#define AMD_ID_LV320B_MVS (AMD_ID_LV320B & FLASH_DATA_MASK) +#define STM_ID_W320DT_MVS (STM_ID_29W320DT & FLASH_DATA_MASK) +#define STM_ID_W320DB_MVS (STM_ID_29W320DB & FLASH_DATA_MASK) +#define AMD_MANUFACT_MVS (AMD_MANUFACT & FLASH_DATA_MASK) +#define FUJ_MANUFACT_MVS (FUJ_MANUFACT & FLASH_DATA_MASK) +#define STM_MANUFACT_MVS (STM_MANUFACT & FLASH_DATA_MASK) + +#define AUTOSELECT_ADDR1 0x0555 +#define AUTOSELECT_ADDR2 0x02AA +#define AUTOSELECT_ADDR3 AUTOSELECT_ADDR1 + +#define AUTOSELECT_DATA1 (0x00AA00AA & FLASH_DATA_MASK) +#define AUTOSELECT_DATA2 (0x00550055 & FLASH_DATA_MASK) +#define AUTOSELECT_DATA3 (0x00900090 & FLASH_DATA_MASK) + +#define RESET_BANK_DATA (0x00F000F0 & FLASH_DATA_MASK) + +static ulong flash_get_size (vu_long *address, flash_info_t *info) +{ + short i; +#ifdef CONFIG_MVS_16BIT_FLASH + ushort value; + vu_short *addr = (vu_short *)address; +#else + ulong value; + vu_long *addr = (vu_long *)address; +#endif + ulong base = (ulong)address; + + /* Write auto select command: read Manufacturer ID */ + addr[AUTOSELECT_ADDR1] = AUTOSELECT_DATA1; + addr[AUTOSELECT_ADDR2] = AUTOSELECT_DATA2; + addr[AUTOSELECT_ADDR3] = AUTOSELECT_DATA3; + + value = addr[0]; /* manufacturer ID */ + switch (value) { + case AMD_MANUFACT_MVS: + info->flash_id = FLASH_MAN_AMD; + break; + case FUJ_MANUFACT_MVS: + info->flash_id = FLASH_MAN_FUJ; + break; + case STM_MANUFACT_MVS: + info->flash_id = FLASH_MAN_STM; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + + value = addr[1]; /* device ID */ + switch (value) { + case AMD_ID_LV160T_MVS: + info->flash_id += FLASH_AM160T; + info->sector_count = 37; + info->size = (0x00200000 << FLASH_SHIFT); + break; /* => 2 or 4 MB */ + + case AMD_ID_LV160B_MVS: + info->flash_id += FLASH_AM160B; + info->sector_count = 37; + info->size = (0x00200000 << FLASH_SHIFT); + break; /* => 2 or 4 MB */ + + case AMD_ID_LV320T_MVS: + info->flash_id += FLASH_AM320T; + info->sector_count = 71; + info->size = (0x00400000 << FLASH_SHIFT); + break; /* => 4 or 8 MB */ + + case AMD_ID_LV320B_MVS: + info->flash_id += FLASH_AM320B; + info->sector_count = 71; + info->size = (0x00400000 << FLASH_SHIFT); + break; /* => 4 or 8MB */ + + case STM_ID_W320DT_MVS: + info->flash_id += FLASH_STMW320DT; + info->sector_count = 67; + info->size = (0x00400000 << FLASH_SHIFT); + break; /* => 4 or 8 MB */ + + case STM_ID_W320DB_MVS: + info->flash_id += FLASH_STMW320DB; + info->sector_count = 67; + info->size = (0x00400000 << FLASH_SHIFT); + break; /* => 4 or 8MB */ + + default: + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + + } + + /* set up sector start address table */ + flash_get_offsets (base, info); + + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) { + /* read sector protection at sector address, (A7 .. A0) = 0x02 */ + /* D0 = 1 if protected */ +#ifdef CONFIG_MVS_16BIT_FLASH + addr = (vu_short *)(info->start[i]); +#else + addr = (vu_long *)(info->start[i]); +#endif + info->protect[i] = addr[2] & 1; + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { +#ifdef CONFIG_MVS_16BIT_FLASH + addr = (vu_short *)info->start[0]; +#else + addr = (vu_long *)info->start[0]; +#endif + *addr = RESET_BANK_DATA; /* reset bank */ + } + + return (info->size); +} + + +/*----------------------------------------------------------------------- + */ + +#define ERASE_ADDR1 0x0555 +#define ERASE_ADDR2 0x02AA +#define ERASE_ADDR3 ERASE_ADDR1 +#define ERASE_ADDR4 ERASE_ADDR1 +#define ERASE_ADDR5 ERASE_ADDR2 + +#define ERASE_DATA1 (0x00AA00AA & FLASH_DATA_MASK) +#define ERASE_DATA2 (0x00550055 & FLASH_DATA_MASK) +#define ERASE_DATA3 (0x00800080 & FLASH_DATA_MASK) +#define ERASE_DATA4 ERASE_DATA1 +#define ERASE_DATA5 ERASE_DATA2 + +#define ERASE_SECTOR_DATA (0x00300030 & FLASH_DATA_MASK) +#define ERASE_CHIP_DATA (0x00100010 & FLASH_DATA_MASK) +#define ERASE_CONFIRM_DATA (0x00800080 & FLASH_DATA_MASK) + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ +#ifdef CONFIG_MVS_16BIT_FLASH + vu_short *addr = (vu_short *)(info->start[0]); +#else + vu_long *addr = (vu_long *)(info->start[0]); +#endif + int flag, prot, sect, l_sect; + ulong start, now, last; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + if ((info->flash_id == FLASH_UNKNOWN) || + (info->flash_id > FLASH_AMD_COMP)) { + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return 1; + } + + prot = 0; + for (sect=s_first; sect<=s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr[ERASE_ADDR1] = ERASE_DATA1; + addr[ERASE_ADDR2] = ERASE_DATA2; + addr[ERASE_ADDR3] = ERASE_DATA3; + addr[ERASE_ADDR4] = ERASE_DATA4; + addr[ERASE_ADDR5] = ERASE_DATA5; + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ +#ifdef CONFIG_MVS_16BIT_FLASH + addr = (vu_short *)(info->start[sect]); +#else + addr = (vu_long *)(info->start[sect]); +#endif + addr[0] = ERASE_SECTOR_DATA; + l_sect = sect; + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + + start = get_timer (0); + last = start; +#ifdef CONFIG_MVS_16BIT_FLASH + addr = (vu_short *)(info->start[l_sect]); +#else + addr = (vu_long *)(info->start[l_sect]); +#endif + while ((addr[0] & ERASE_CONFIRM_DATA) != ERASE_CONFIRM_DATA) { + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + return 1; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } + } + +DONE: + /* reset to read mode */ +#ifdef CONFIG_MVS_16BIT_FLASH + addr = (vu_short *)info->start[0]; +#else + addr = (vu_long *)info->start[0]; +#endif + addr[0] = RESET_BANK_DATA; /* reset bank */ + + printf (" done\n"); + return 0; +} + + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ +#define BUFF_INC 4 + ulong cp, wp, data; + int i, l, rc; + + mvdebug (("+write_buff %p ==> 0x%08lx, count = 0x%08lx\n", src, addr, cnt)); + + wp = (addr & ~3); /* get lower word aligned address */ + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + mvdebug ((" handle unaligned start bytes (cnt = 0x%08%lx)\n", cnt)); + data = 0; + for (i=0, cp=wp; i0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt==0 && i= BUFF_INC) { + data = 0; + for (i=0; i0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; istart[0]); + ulong start; + int flag; + + mvdebug (("+write_word (to 0x%08lx)\n", dest)); + /* Check if Flash is (sufficiently) erased */ + if ((*((vu_long *)dest) & data) != data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr[WRITE_ADDR1] = WRITE_DATA1; + addr[WRITE_ADDR2] = WRITE_DATA2; + addr[WRITE_ADDR3] = WRITE_DATA3; + + *((vu_long *)dest) = data; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); + addr = (vu_long *)dest; + while ((*addr & WRITE_CONFIRM_DATA) != (data & WRITE_CONFIRM_DATA)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + + mvdebug (("-write_word\n")); + return (0); +} +#else /* CONFIG_MVS_16BIT_FLASH */ +/*----------------------------------------------------------------------- + * Write a halfword to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_halfword (flash_info_t *info, ulong dest, ushort data) +{ + vu_short *addr = (vu_short *)(info->start[0]); + ulong start; + int flag; + + mvdebug (("+write_halfword (to 0x%08lx)\n", dest)); + /* Check if Flash is (sufficiently) erased */ + if ((*((vu_short *)dest) & data) != data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr[WRITE_ADDR1] = WRITE_DATA1; + addr[WRITE_ADDR2] = WRITE_DATA2; + addr[WRITE_ADDR3] = WRITE_DATA3; + + *((vu_short *)dest) = data; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); + addr = (vu_short *)dest; + while ((*addr & WRITE_CONFIRM_DATA) != (data & WRITE_CONFIRM_DATA)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + mvdebug (("-write_halfword\n")); + return (0); +} + + +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ + int result = 0; + + if (write_halfword (info, dest, (data & ~FLASH_DATA_MASK) >> 16) == 0) + { + dest += 2; + data = data & FLASH_DATA_MASK; + result = write_halfword (info, dest, data); + } + return result; +} +#endif +/*----------------------------------------------------------------------- + */