⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hal_platform_setup.h

📁 基于ecos的redboot
💻 H
📖 第 1 页 / 共 2 页
字号:
#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 + -