📄 hal_platform_setup.h
字号:
#ifndef CYGONCE_HAL_PLATFORM_SETUP_H
#define CYGONCE_HAL_PLATFORM_SETUP_H
/*=============================================================================
//
// hal_platform_setup.h
//
// Platform specific support for HAL (assembly code)
//
//=============================================================================
//####COPYRIGHTBEGIN####
//
// -------------------------------------------
// The contents of this file are subject to the Red Hat eCos Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.redhat.com/
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations under
// the License.
//
// The Original Code is eCos - Embedded Configurable Operating System,
// released September 30, 1998.
//
// The Initial Developer of the Original Code is Red Hat.
// Portions created by Red Hat are
// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.
// All Rights Reserved.
// -------------------------------------------
//
//####COPYRIGHTEND####
//=============================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): msalter
// Contributors:
// Date: 2000-10-10
// Purpose: Intel IQ80310 platform specific support routines
// Description:
// Usage: #include <cyg/hal/hal_platform_setup.h>
//
//####DESCRIPTIONEND####
//
//===========================================================================*/
#include <pkgconf/system.h> // System-wide configuration info
#include CYGBLD_HAL_PLATFORM_H // Platform specific configuration
#include <cyg/hal/hal_iq80310.h> // Platform specific hardware definitions
#include <cyg/hal/hal_mmu.h> // MMU definitions
// Define macro used to diddle the LEDs during early initialization.
// Can use r0+r1. Argument in \x.
#define CYGHWR_LED_MACRO \
b 667f ;\
666: ;\
.byte 0xc0, 0xf9, 0xa4, 0xb0 ;\
.byte 0x99, 0x92, 0x82, 0xf8 ;\
.byte 0x80, 0x90, 0x88, 0x83 ;\
.byte 0xa7, 0xa1, 0x86, 0x8e ;\
667: ;\
ldr r0, =666b ;\
add r0, r0, #\x ;\
ldrb r1, [r0] ;\
ldr r0, =DISPLAY_RIGHT ;\
str r1, [r0]
// The main useful output of this file is PLATFORM_SETUP1: it invokes lots
// of other stuff (may depend on RAM or ROM start). The other stuff is
// divided into further macros to make it easier to manage what's enabled
// when.
#if defined(CYG_HAL_STARTUP_ROM)
#define PLATFORM_SETUP1 _platform_setup1
//#define CYGHWR_HAL_ARM_HAS_MMU
#else
#define PLATFORM_SETUP1
#endif
#define RAM_BASE 0xa0000000
#define DRAM_SIZE (512*1024*1024) // max size of available SDRAM
#define DCACHE_SIZE (32*1024) // size of the Dcache
#define DCACHE_FLUSH_AREA (RAM_BASE+DRAM_SIZE) // NB: needs page table support
#define MMU_Control_BTB 0x800
// Reserved area for battery backup SDRAM memory test
// This area is not zeroed out by initialization code
#define SDRAM_BATTERY_TEST_BASE 0xA1FFFFF0 // base address of last 16 memory locations in a 32MB SDRAM
// Display 'lvalue:rvalue' on the hex display
// lvalue and rvalue must be of the form 'DISPLAY_x'
// where 'x' is a hex digit from 0-F.
.macro HEX_DISPLAY reg0, reg1, lvalue, rvalue
ldr \reg0, =DISPLAY_LEFT // display left digit
ldr \reg1, =\lvalue
str \reg1, [\reg0]
ldr \reg0, =DISPLAY_RIGHT
ldr \reg1, =\rvalue // display right digit
str \reg1, [\reg0]
.endm
// Trigger the logic analyzer by writing a particular
// address, and triggering on that address.
.macro TRIGGER_LA_ON_ADDRESS address, reg0, reg1
mrc p15, 0, \reg0, c1, c0, 0 // read ARM control register
// CPWAIT \reg0
ldr \reg1, =\address
str \reg0, [\reg1]
.endm
// Delay a bit
.macro DELAY_FOR cycles, reg0
ldr \reg0, =\cycles
subs \reg0, \reg0, #1
subne pc, pc, #0xc
.endm
// wait for coprocessor write complete
.macro CPWAIT reg
mrc p15,0,\reg,c2,c0,0
mov \reg,\reg
sub pc,pc,#4
.endm
// Enable the BTB
.macro BTB_INIT reg
#ifdef CYGSEM_HAL_ARM_IQ80310_BTB
mrc p15, 0, \reg, c1, c0, 0
orr \reg, \reg, #MMU_Control_BTB
mcr p15, 0, \reg, c1, c0, 0
CPWAIT \reg
#endif
.endm
// form a first-level section entry
.macro FL_SECTION_ENTRY base,x,ap,p,d,c,b
.word (\base << 20) | (\x << 12) | (\ap << 10) | (\p << 9) |\
(\d << 5) | (\c << 3) | (\b << 2) | 2
.endm
// form a first-level page table entry
.macro FL_PT_ENTRY base,p,d
// I wanted to use logical operations here, but since I am using symbols later
// to fill in the parameters, I had to use addition to force the assembler to
// do it right
.word \base + (\p << 9) + (\d << 5) + 1
.endm
// form a second level small page entry
.macro SL_SMPAGE_ENTRY base,ap3,ap2,ap1,ap0,c,b
.word (\base << 12) | (\ap3 << 10) | (\ap2 << 8) | (\ap1 << 6) |\
(\ap0 << 4) | (\c << 3) | (\b << 2) | 2
.endm
// form a second level extended small page entry
.macro SL_XSMPAGE_ENTRY base,x,ap,c,b
.word (\base << 12) | (\x << 6) | (\ap << 4) | (\c << 3) | (\b << 2) | 3
.endm
// start of platform setup
.macro _platform_setup1
// This is where we wind up immediately after reset. On the IQ80310, we have
// to jump around a hole in flash which runs from 0x00001000 - 0x0001fff.
// The start of _platform_setup1 will be below 0x1000 and since we need to
// align the mmu table on a 16k boundary, we just branch around the page
// table which we will locate at FLASH_BASE+0x4000.
b _real_platform_setup
.p2align 13
// the following alignment creates the mmu table at address 0x4000.
mmu_table:
// 1MB of FLASH with i80312 MMRs mapped in using 4K small pages so we can
// set the access permission on flash and memory-mapped registers properly.
FL_PT_ENTRY mmu_table_flashbase,0,0
// Remaining 7MB of FLASH
// rw, cacheable, non-bufferable
.set __base,1
.rept 7
FL_SECTION_ENTRY __base,0,3,0,0,1,0
.set __base,__base+1
.endr
// nothing interesting here (Address Translation)
.rept 0xA00 - 0x8
FL_SECTION_ENTRY __base,0,3,0,0,0,0
.set __base,__base+1
.endr
// up to 512MB ECC SDRAM mapped 1-to-1
// first 1MB mapped in 4K chunks
// x=c=b=1
FL_PT_ENTRY mmu_table_rambase,1,0
.set __base,__base+1
.rept 0xC00 - 0xA01
FL_SECTION_ENTRY __base,1,3,1,0,1,1
.set __base,__base+1
.endr
// Cache flush region.
// Don't need physical memory, just a cached area.
.rept 0xD00 - 0xC00
FL_SECTION_ENTRY __base,0,3,0,0,1,1
.set __base,__base+1
.endr
// Alias for first 1MB of FLASH
// rw, cacheable, non-bufferable
FL_SECTION_ENTRY 0x000,0,3,0,0,1,0
.set __base,__base+1
// Invalid
.rept 0xF00 - 0xD01
.word 0
.set __base,__base+1
.endr
// only I/O at 0xFE8xxxxx
.rept 0x1000 - 0xF00
FL_SECTION_ENTRY __base,0,3,0,0,0,0
.set __base,__base+1
.endr
// Immediately after the above table (at 0x8000) is the
// second level page table which breaks up the lowest 1MB
// of physical memory into 4KB sized virtual pages. These
// pages work around a hole in flash (0x1000-0x1fff) used
// by the Yavapai companion chip internal registers.
mmu_table_flashbase:
// Virtual address 0 (Flash boot code).
// Map 4k page at 0x00000000 virt --> 0xA0000000 physical
// This allows us to have a writable vector table.
// Read-Write, cacheable, bufferable
SL_XSMPAGE_ENTRY 0xa0000,1,3,1,1
// Virtual address 0x1000 (Memory mapped registers)
// Map 1-to-1, but don't cache or buffer
// Read-Write, non-cacheable, non-bufferable
.set __base,1
SL_SMPAGE_ENTRY __base,3,3,3,3,0,0
.set __base,__base+1
// Virtual address 0x2000-0x100000 (remainder of flash1)
// Read-Write, cacheable, non-bufferable
.rept 0x100 - 0x2
SL_SMPAGE_ENTRY __base,3,3,3,3,1,0
.set __base,__base+1
.endr
// Now is the second level table for the first megabyte
// of DRAM.
mmu_table_rambase:
// Map first meg of SDRAM
// Read-Write, cacheable, bufferable
.set __base,0xA0000
.rept 0x100
SL_XSMPAGE_ENTRY __base,1,3,1,1
.set __base,__base+1
.endr
_real_platform_setup:
// Drain write and fill buffer
mcr p15,0,r0,c7,c10,4
CPWAIT r0
// Disable write buffer coalescing
mrc p15,0,r0,c1,c0,1
orr r0,r0,#1 // set the disable bit
mcr p15,0,r0,c1,c0,1
CPWAIT r0
// Delay appx 60 ms to let battery-backup reset complete
DELAY_FOR 0x400000, r0
// Eventually we will be able to check a register bit
// to determine when this is complete
HEX_DISPLAY r0, r1, DISPLAY_0, DISPLAY_1
//
// *** I2C interface initialization ***
//
// Setup I2C Slave Address Register
ldr r1, =I2C_DEVID // Load slave address r1.
ldr r2, =ISAR_ADDR // Load address of the I2C Slave Address Register in r2.
ldr r3, =0x0000007f // Load mask in r3.
and r1, r3, r3 // The mask zeroes the 25 MSBs of r1 just to make sure.
str r3, [r2] // Save the value 0x02 (I2C_DEVID) in the register.
// Setup I2C Clock Count Register
ldr r2, =ICCR_ADDR // Load the address of the I2C Clock Control Register in r2.
ldr r3, =0x0000014d // Set for 5.05 us transition time at 66MHz (0x14D = 333).
str r3, [r2] // Save the value in the register.
// Enable I2C Interface Unit - status will be polled
ldr r2, =ICR_ADDR // Load the address of the Control Register in r2.
ldr r1, =ICR_GCALL // Disable General Call (will be master)
ldr r3, =ICR_ENB // Enable I2C unit ).
orr r1, r3, r1 // OR the two and store in R1
ldr r3, =ICR_SCLENB // Enable I2C Clock Generator disabled
orr r1, r3, r1 // OR the two and store in R1
str r1, [r2] // Save the value to the Control Register.
//
// *** Now read the SPD Data ***
//
// Pointers to I2C Registers
ldr r11, =ICR_ADDR // Load the address of the I2C Control Register in r11.
ldr r12, =ISR_ADDR // Load the address of the I2C Status Register in r12.
ldr r13, =IDBR_ADDR // Load the address of the I2C Data Buffer Register in r13.
// Initialize byte counters
ldr r6, =0x00000000 // Counter incremented before byte is read
ldr r7, =0x00000040 // Number of bytes to read in the Presence Detect EEPROM of SDRAM: 64 bytes
ldr r5, =0x00000000 // R5 has running checksum calculation
ldr r9, =I2C_TIMOUT // Timeout limit in case EEPROM does not respond
// At the end of all this, R4 has DRAM size, R8 has bank count, and R10 has Bank size
ldr r10,=0x00000000 // Bank size
ldr r8, =0x00000000 // Bank count
ldr r4, =0x00000000 // SDRAM size
/* FREE REGISTERS ARE R0 - R3 */
// *** Put out address, with WRITE mode ***
// Set SDRAM module address and write mode
ldr r1, =SDRAM_DEVID // Load slave address for SDRAM module: 0xA2 (Presence Detect Data)
bic r1, r1, #IDBR_MODE // Clear read bit (bit #0)
str r1, [r13] // Store to data register
// Initiate dummy write to set EEPROM pointer to 0
ldr r1, [r11] // read the current Control Register value
orr r1, r1, #ICR_START // Set start bit
orr r1, r1, #ICR_TRANSFER // Set transfer bit - bit is self_clearing
str r1, [r11] // Store to control register
// Wait for transmit empty status
ldr r1, =0x00000000 // Initialize I2C timeout counter
0:
add r1, r1, #1 // Increment I2C timeout counter (r1 = r1 + 1)
cmp r1, r9
beq i2c_error // Kick out of SDRAM initialization if timeout occurs
ldr r0, [r12] // Load I2C Status Reg into R0
str r2, =ISR_EMPTY // Poll status register
and r3, r2, r0 // Bit #6 is checked: IDBR Transmit Empty
cmp r3, r2 // If bit = 0 then branch to 0 and check again
bne 0b
str r0, [r12] // Write back status to clear
// *** Write pointer register on EEPROM to 0x00000000 ***
// Set SDRAM module EEPROM address to 0
ldr r1, =0x00000000 // Load base address of SDRAM module EEPROM
str r1, [r13] // Store to data register
// Send address to EEPROM
ldr r1, [r11] // read the current Control Register value
bic r1, r1, #ICR_START // No start bit (already started)
orr r1, r1, #ICR_TRANSFER // Set transfer bit - bit is self_clearing
str r1, [r11] // Store to control register
// Wait for transmit empty status
ldr r1, =0x00000000 // Initialize I2C timeout counter
0:
add r1, r1, #1 // Increment I2C timeout counter (r1 = r1 + 1)
cmp r1, r9
beq i2c_error // Kick out of SDRAM initialization if timeout occurs
ldr r0, [r12] // Load I2C Status Reg into R0 - ld (r12), r10
str r2, =ISR_EMPTY // Poll status register
and r3, r2, r0 // Bit #6 is checked: IDBR Transmit Empty
cmp r3, r2 // If bit = 0 then branch to 0 and check again (r3 = 0x00)
bne 0b
str r0, [r12] // Write back status to clear
// *** Read SDRAM PD data ***
// *** Put out address, with READ mode ***
// Set SDRAM module address and read mode
ldr r0, =SDRAM_DEVID // Load slave address for SDRAM module (0xA2)
orr r1, r0, #IDBR_MODE // Set read bit (bit #0)
str r1, [r13] // Store to data register
// Send next read request
ldr r1, [r11] // read the current Control Register value
orr r1, r1, #ICR_START // Set start bit
orr r1, r1, #ICR_TRANSFER // Set transfer bit - bit is self_clearing
str r1, [r11] // Store to control register
// Wait for transmit empty status
ldr r1, =0x00000000 // Initialize I2C timeout counter
0:
add r1, r1, #1 // Increment I2C timeout counter (r1 = r1 + 1)
cmp r1, r9
beq i2c_error // Kick out of SDRAM initialization if timeout occurs
ldr r0, [r12] // Load I2C Status Reg into R0 - ld (r12), r10
str r2, =ISR_EMPTY // Poll status register
and r3, r2, r0 // Bit #6 is checked: IDBR Transmit Empty
cmp r3, r2 // If bit = 0 then branch to 0 and check again (r3 = 0x00)
bne 0b
str r0, [r12] // Write back status to clear
sdram_loop:
add r6, r6, #1 // Increment byte counter
// *** READ the next Byte!!! ***
ldr r1, [r11] // read the current Control Register value
bic r1, r1, #ICR_START // No start bit (already started)
orr r1, r1, #ICR_TRANSFER // Set transfer bit - bit is self_clearing
// we have to set NACK before reading the last bit
cmp r6, r7 // r7 = 64 (decimal) so if r6 = 64, this is the last byte to be read
bne 1f // If bytes left, skip ahead
orr r1, r1, #ICR_ACK // Set NACK if this is the last byte
orr r1, r1, #ICR_STOP // Set STOP if this is the last byte
1:
str r1, [r11] // Store to control register
// Wait for read full status
ldr r1, =0x00000000 // Initialize I2C timeout counter
0:
add r1, r1, #1 // Increment I2C timeout counter (r1 = r1 + 1)
cmp r1, r9
beq i2c_error // Kick out of SDRAM initialization if timeout occurs
ldr r0, [r12] // Load I2C Status Reg into R0
str r2, =ISR_FULL // Poll status register
and r3, r2, r0 // Bit #6 is checked: IDBR Transmit Empty
cmp r3, r2 // If bit = 0 then branch to 0 and check again
bne 0b
str r0, [r12] // Write back status to clear
// Read the data byte
ldr r1, [r13] // Read the byte
ldr r2, =CHECKSUM_BYTE
cmp r6, r2 // is it the CHECKSUM byte???
beq 1f
add r5, r5, r1 // Add it to the checksum if not the checksum byte
bal 2f // skip checksum comparison
1:
ldr r0, =0xff // If this is the checksum byte, compare it
and r5, r5, r0 // against the calculated checksum
cmp r1, r5
bne bad_checksum // If no match, skip SDRAM controller initialization
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -