📄 atlas_malta.s
字号:
/************************************************************************
*
* atlas_malta.S
*
* Atlas and Malta specific initialisation
*
*
* ######################################################################
*
* Copyright (c) 1999-2000 MIPS Technologies, Inc. All rights reserved.
*
* Unpublished rights reserved under the Copyright Laws of the United States of
* America.
*
* This document contains information that is proprietary to MIPS Technologies,
* Inc. ("MIPS Technologies"). Any copying, modifying or use of this information
* (in whole or in part) which is not expressly permitted in writing by MIPS
* Technologies or a contractually-authorized third party is strictly
* prohibited. At a minimum, this information is protected under unfair
* competition laws and the expression of the information contained herein is
* protected under federal copyright laws. Violations thereof may result in
* criminal penalties and fines.
* MIPS Technologies or any contractually-authorized third party reserves the
* right to change the information contained in this document to improve
* function, design or otherwise. MIPS Technologies does not assume any
* liability arising out of the application or use of this information. Any
* license under patent rights or any other intellectual property rights owned
* by MIPS Technologies or third parties shall be conveyed by MIPS Technologies
* or any contractually-authorized third party in a separate license agreement
* between the parties.
* The information contained in this document constitutes one or more of the
* following: commercial computer software, commercial computer software
* documentation or other commercial items. If the user of this information, or
* any related documentation of any kind, including related technical data or
* manuals, is an agency, department, or other entity of the United States
* government ("Government"), the use, duplication, reproduction, release,
* modification, disclosure, or transfer of this information, or any related
* documentation of any kind, is restricted in accordance with Federal
* Acquisition Regulation 12.212 for civilian agencies and Defense Federal
* Acquisition Regulation Supplement 227.7202 for military agencies. The use of
* this information by the Government is further restricted in accordance with
* the terms of the license agreement(s) and/or applicable contract terms and
* conditions covering this information from MIPS Technologies or any
* contractually-authorized third party.
*
************************************************************************/
/************************************************************************
* Include files
************************************************************************/
#include <sysdefs.h>
#include <mips.h>
#include <pci_api.h>
#include <i2c.h>
#include <init.h>
#include <product.h>
#include <atlas.h>
#include <malta.h>
#include <saa9730.h> /* Atlas specific */
/************************************************************************
* Definitions
************************************************************************/
/**** Display platform. Modifies t9..t5 (due to DISP_STR) and t0 ****/
#define DISP_PLATFORM \
li t0, PRODUCT_MALTA_ID; \
beq t0, k0, 1f; \
nop; \
DISP_STR( msg_atlas ); \
b 2f; \
nop; \
1: \
DISP_STR( msg_malta ); \
2:
/******** Definitions for I2C controller on Malta ********/
#define SCL_TX MALTA_I2COE_I2CSCL_BIT
#define SCL_RX 0
#define SDA_TX MALTA_I2COE_I2CSDA_BIT
#define SDA_RX 0
#define SCL_HI MALTA_I2COUT_I2CSCL_BIT
#define SCL_LO 0
#define SDA_HI MALTA_I2COUT_I2CSDA_BIT
#define SDA_LO 0
/* Loop counter for PAUSE loop :
*
* Each iteration of loop consists of two instructions, i.e. two
* processor clock cycles (assuming cached operation).
*
* A pause loop should delay the processor half an I2C clock cycle.
*
* We assume a max. processor frequency of 1000MHz.
*/
#define PAUSE_COUNT (1000000 / MAX_I2C_FREQ_KHZ / 2 / 2)
#define PAUSE \
li t7, PAUSE_COUNT; \
10: \
bne t7, zero, 10b; \
addiu t7, -1
#define I2C_DIRECTION( scl, sda ) \
li t7, KSEG1(MALTA_I2COE); \
li t6, (scl) | (sda); \
sw t6, 0(t7); \
PAUSE
#define I2C_TX( scl, sda ) \
li t7, KSEG1(MALTA_I2COUT); \
li t6, (scl) | (sda); \
sw t6, 0(t7); \
PAUSE
#define I2C_RX( reg ) \
li t7, KSEG1(MALTA_I2CINP); \
lw reg, 0(t7); \
andi reg, MALTA_I2CINP_I2CSDA_MSK; \
srl reg, MALTA_I2CINP_I2CSDA_SHF; \
PAUSE
#define I2C_FPGA_ENABLE \
li t7, KSEG1(MALTA_I2COE); \
li t6, (SCL_RX) | (SDA_RX); \
sw t6, 0(t7); \
li t7, KSEG1(MALTA_I2COUT); \
li t6, (SCL_HI) | (SDA_HI); \
sw t6, 0(t7); \
li t7, KSEG1(MALTA_I2CSEL); \
li t6, MALTA_I2CSEL_FPGA_BIT; \
sw t6, 0(t7); \
PAUSE
/************************************************************************
* Public variables
************************************************************************/
/************************************************************************
* Static variables
************************************************************************/
/************************************************************************
* Implementation : Public functions
************************************************************************/
/************************************************************************
*
* sys_init_atlas_malta
* Description :
* -------------
*
* Determine SDRAM parameters and configure North Bridge.
*
* SDRAM configuration is conservative since we do not know the bus
* frequency yet. However, after this function has been called,
* a memory test can be performed. Later, when we know the bus
* frequency, the SDRAM configuration may be optimised.
*
* Parameters :
* ------------
*
* k0 = Platform ID
*
* Return values :
* ---------------
*
* v0 = error code (0 = no error)
* v1 = RAM size in bytes
*
************************************************************************/
LEAF(sys_init_atlas_malta)
.set noreorder
#define PCIMEM_DEFAULT s0
#define RA gp
#define MEMSIZE sp
move RA, ra
DISP_PLATFORM
/* Get default base address for PCI memory access */
jal sys_core_get_pcimem_base
nop
move PCIMEM_DEFAULT, v0
/* For Malta we skip setup of SAA9730, since it is Atlas specific */
li t0, PRODUCT_MALTA_ID
beq t0, k0, setup_sdram
nop
/* Setup SAA9730 memory mapping */
li a0, ATLAS_DEVNUM_SAA9730
li a1, PCI_CFG_BASE1
move a2, PCIMEM_DEFAULT
li a3, KSEG1(ATLAS_CORECTRL_BASE)
jal sys_core_config_write
nop
bne v0, zero, error_init
nop
/* Enable SAA9730 memory space
* (read/modify/write PCI Command register).
*/
li a0, ATLAS_DEVNUM_SAA9730
li a1, PCI_SC
li a2, KSEG1(ATLAS_CORECTRL_BASE)
jal sys_core_config_read
nop
bne v0, zero, error_init
nop
li t0, PCI_SC_CMD_MS_BIT | PCI_SC_CMD_SERR_BIT
or a2, v1, t0
li a0, ATLAS_DEVNUM_SAA9730
li a1, PCI_SC
li a3, KSEG1(ATLAS_CORECTRL_BASE)
jal sys_core_config_write
nop
bne v0, zero, error_init
nop
/* Init I2C controller in SAA9730 (run as slow as possible) */
li t0, SAA9730_I2CSC_I2CCC_6400 << SAA9730_I2CSC_I2CCC_SHF
/* Base address of SAA9730 */
KSEG1A( PCIMEM_DEFAULT )
sw t0, SAA9730_I2CSC_OFS( PCIMEM_DEFAULT )
setup_sdram:
/* Get max SDRAM module bank size */
jal sys_core_get_max_sdram_bank
nop
move a1, v0
/* Determine SDRAM parameters */
li a0, ATLAS_SYSTEMRAM_SIZE
jal sys_determine_sdram_parms
nop
bne v0, zero, error_init
nop
addu MEMSIZE, t1, t2
/* Configure North Bridge SDRAM parameters */
li a0, ATLAS_CPUFREQ_LOWEST_MHZ
move a1, v1
move a2, t0
move a3, t1
move t0, t2
li t1, KSEG1(ATLAS_CORECTRL_BASE)
jal sys_core_configure_sdram
nop
bne v0, zero, error_init
nop
/* Configure North Bridge memory map */
li a0, ATLAS_PCIMEM1_BASE
li a1, ATLAS_PCIMEM1_SIZE + ATLAS_PCIMEM2_SIZE
li a2, ATLAS_PCIMEM3_BASE
li a3, ATLAS_PCIMEM3_SIZE
li t0, ATLAS_SYSTEMFLASH_BASE
li t1, ATLAS_SYSTEMFLASH_SIZE + ATLAS_MONITORFLASH_SIZE
li t2, KSEG1(ATLAS_CORECTRL_BASE)
jal sys_core_setup_decode
nop
bne v0, zero, error_init
nop
/* If Malta, remap PCI I/O.
* We need to do this since the PIIX4 device on Malta requires
* IO mapping to start at 0.
*/
/* For Malta we skip setup of SAA9730, since it is Atlas specific */
li t0, PRODUCT_MALTA_ID
bne t0, k0, 1f
nop
li a0, KSEG1(ATLAS_CORECTRL_BASE)
jal sys_core_remap_pci_io
nop
1:
/* Setup return parameters */
move v0, zero
move v1, MEMSIZE
error_init:
jr RA
nop
#undef PCIMEM_DEFAULT
#undef RA
#undef MEMSIZE
END(sys_init_atlas_malta)
/************************************************************************
*
* sys_spd_read
* Description :
* -------------
*
* Function for reading data byte from SPD (or other serial EEPROM device).
*
* Parameters :
* ------------
*
* a0 = sub-address
* k0 = Platform ID
*
* Return values :
* ---------------
*
* v0 = error code (0 if OK)
* v1 = byte read
*
************************************************************************/
LEAF(sys_spd_read)
#define SPD_ADDR t0
#define SUB_ADDR t1
#define RA t2
move RA, ra
DISP_STR( msg_spd )
/* Setup SPD address and sub-address */
li SPD_ADDR, (CORE_EEPROM_IICADR_SPD000 << 1)
move SUB_ADDR, a0
/* Branch on platform */
li t3, PRODUCT_ATLASA_ID
beq t3, k0, eeprom_atlas
nop
/* Malta */
eeprom_malta:
/* Set I2C registers in FPGA to a well-defined state (not
* really necessary).
* Macros use t7..t6.
*/
I2C_FPGA_ENABLE
jal iic_malta_start
nop
ori a0, SPD_ADDR, I2C_WRITE_BIT /* SPD address + write bit */
jal iic_malta_write
nop
li a0, I2C_ACK_BIT
bne v0, a0, error_eeprom
li v0, ERROR_SPD
move a0, SUB_ADDR /* Subaddress */
jal iic_malta_write
nop
li a0, I2C_ACK_BIT
bne v0, a0, error_eeprom
li v0, ERROR_SPD
jal iic_malta_start
nop
ori a0, SPD_ADDR, I2C_READ_BIT /* SPD address + read bit */
jal iic_malta_write
nop
li a0, I2C_ACK_BIT
bne v0, a0, error_eeprom
li v0, ERROR_SPD
/* Read data */
jal iic_malta_read /* Returns data in v0 */
nop
move v1, v0
jal iic_malta_stop
nop
b eeprom_done
nop
iic_malta_start :
I2C_DIRECTION( SCL_TX, SDA_TX )
I2C_TX( SCL_HI, SDA_HI )
I2C_TX( SCL_HI, SDA_LO ) /* Hi to Lo transition -> START */
I2C_TX( SCL_LO, SDA_LO )
jr ra
nop
iic_malta_write :
/* a0 = byte to write
* v0 := ACK/NACK bit
*/
I2C_DIRECTION( SCL_TX, SDA_TX )
li t3, 7 /* 8 bit loop counter */
1:
/* Determine data[t3] (MSb to be transmitted first) */
srlv t4, a0, t3
andi t4, 1
beq t4, zero, 2f
nop
I2C_TX( SCL_LO, SDA_HI ) /* Set SDA */
I2C_TX( SCL_HI, SDA_HI ) /* Clock Hi */
I2C_TX( SCL_LO, SDA_HI ) /* Clock Lo */
b 3f
nop
2:
I2C_TX( SCL_LO, SDA_LO ) /* Clear SDA */
I2C_TX( SCL_HI, SDA_LO ) /* Clock Hi */
I2C_TX( SCL_LO, SDA_LO ) /* Clock lo */
3:
bne t3, zero, 1b
addiu t3, -1
/* Get acknowledge.
*
* Note : Between the time that clock was driven low (see above)
* and the direction of SDA is changed (see below),
* there may be a conflict where both the I2C master and
* the I2C slave are driving SDA. Hardware allows for
* this (open drain implementation).
*/
I2C_DIRECTION( SCL_TX, SDA_RX )
I2C_TX( SCL_HI, SDA_HI ) /* Clock Hi, dummy SDA */
I2C_RX( v0 ) /* Read SDA */
I2C_TX( SCL_LO, SDA_HI ) /* Clock Lo, dummy SDA */
jr ra
nop
iic_malta_read :
/* v0 := data read */
I2C_DIRECTION( SCL_TX, SDA_RX )
move v0, zero /* Init result register */
li t3, 8 /* 8 bit loop counter */
1:
sll v0, 1
I2C_TX( SCL_HI, SDA_HI ) /* Clock Hi, dummy SDA */
I2C_RX( t4 ) /* Read SDA */
I2C_TX( SCL_LO, SDA_HI ) /* Clock Lo, dummy SDA */
addiu t3, -1
bne t3, zero, 1b
or v0, t4
/* Generate NACK */
I2C_TX( SCL_LO, I2C_NACK_BIT )
I2C_DIRECTION( SCL_TX, SDA_TX )
I2C_TX( SCL_HI, I2C_NACK_BIT )
I2C_TX( SCL_LO, I2C_NACK_BIT )
jr ra
nop
iic_malta_stop :
I2C_DIRECTION( SCL_TX, SDA_TX )
I2C_TX( SCL_LO, SDA_LO )
I2C_TX( SCL_HI, SDA_LO ) /* Lo to Hi transition -> STOP */
I2C_TX( SCL_HI, SDA_HI )
I2C_TX( SCL_LO, SDA_HI )
jr ra
nop
/* ATLAS */
eeprom_atlas:
/* Write EEPROM address, sub-address, EEPROM address */
/* Byte1 : Sub-address */
sll a0, SUB_ADDR, SAA9730_I2CTFR_BYTE1_SHF
ori a0, SAA9730_I2CTFR_ATTR_CONT << SAA9730_I2CTFR_BYTE1ATTR_SHF
/* Byte2 : EEPROM address */
ori t3, SPD_ADDR, I2C_WRITE_BIT /* Last bit indicates write */
sll t3, SAA9730_I2CTFR_BYTE2_SHF
ori t3, t3, SAA9730_I2CTFR_ATTR_START << SAA9730_I2CTFR_BYTE2ATTR_SHF
or a0, t3
/* Byte0 : EEPROM address again */
ori t3, SPD_ADDR, I2C_READ_BIT
sll t3, SAA9730_I2CTFR_BYTE0_SHF
ori t3, t3, SAA9730_I2CTFR_ATTR_START << SAA9730_I2CTFR_BYTE0ATTR_SHF
or a0, t3
/* Get default base address for PCI memory access, which is the
* also the address used for the SAA9730 device.
*/
jal sys_core_get_pcimem_base
nop
move a1, v0
KSEG1A( a1 )
/* Perform operation */
jal i2c_atlas
nop
/* Read byte */
/* Byte2 : data will be read hereto */
li a0, SAA9730_I2CTFR_ATTR_STOP << SAA9730_I2CTFR_BYTE2ATTR_SHF
/* Perform operation */
jal i2c_atlas
nop
/* Byte2 now contains the data read. Read it and shift it,
* placing the result in v1.
*/
lw v1, SAA9730_I2CTFR_OFS(a1)
and v1, SAA9730_I2CTFR_BYTE2_MSK
srl v1, SAA9730_I2CTFR_BYTE2_SHF
b eeprom_done
nop
i2c_atlas :
/* a0 = data, a1 = base address of SAA9730 */
/* Request write operation */
sw a0, SAA9730_I2CTFR_OFS(a1)
/* Poll Busy flag */
li a0, SAA9730_I2CTFR_BUSY_MSK
1:
lw t3, SAA9730_I2CTFR_OFS(a1)
and t3, a0
bne t3, zero, 1b
nop
/* Check error flag */
li a0, SAA9730_I2CTFR_ERR_MSK
lw t3, SAA9730_I2CTFR_OFS(a1)
and t3, a0
bne t3, zero, error_eeprom
li v0, ERROR_SPD
jr ra
nop
/* Done */
eeprom_done:
move v0, zero
error_eeprom:
DISP_PLATFORM
jr RA
nop
END(sys_spd_read)
.text
/* Messages */
.text
MSG( msg_atlas, "ATLAS" )
MSG( msg_malta, "MALTA" )
MSG( msg_spd, "SPD" )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -