/******************************************************************************
##=============================================================================
##
## emi.c
##
## GT2000 emi init
##
##=============================================================================
#####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 Red Hat, Inc.
# All Rights Reserved.
# -------------------------------------------
#
#####COPYRIGHTEND####
##=============================================================================
#######DESCRIPTIONBEGIN####
##
## Author(s): echo
## Contributors:
## Date: 2003-9
## Description: This file contains any code needed to initialize the
## hardware on GT2000 board.
##
######DESCRIPTIONEND####
##
##=============================================================================
*******************************************************************************/
//#include <hal_regs.h>
#include <hal_io.h>
#include <plf_hci.h>
#include "hal_i2c.h"
#include "hal_regs.h"
extern void emi_init_pre(void);
extern void i2c_init();
extern void i2c_end();
extern int i2ci_write (unsigned char, unsigned char *, unsigned char, int);
extern int i2ci_read(unsigned char, unsigned char *, unsigned char, int);
extern void gpio_led_outb(unsigned char);
extern unsigned int calculate_pclock(void);
//extern unsigned int pclk;
/*-------------------------------------------------------------- */
/* functions for get the system information from SPD/HCI/DEFAULT.*/
/*-------------------------------------------------------------- */
void get_spd_info(unsigned int *data, unsigned char *spd_buf)
{
unsigned char tmp_buf[1];
int ch;
data[ROW] = spd_buf[SPD_DRAM_ROW];
data[COL] = spd_buf[SPD_DRAM_COL];
if ((spd_buf[SPD_DRAM_CHIP] < 1) || (spd_buf[SPD_DRAM_CHIP] > 2))
data[CHIP] = 1;
else
data[CHIP] = spd_buf[SPD_DRAM_CHIP];
if(spd_buf[SPD_DRAM_BANK] == 2)
data[BANK] = 0; //2 bank
else
data[BANK] = 1; //4 bank
if(spd_buf[SPD_DRAM_CAS_LATENCY] & 2)
data[CAS_LATENCY] = 1;
else // should ch=2, but gt2000 don't support CAS_latency 3 cycles
data[CAS_LATENCY] = 1;
data[REFRESH_RATE] = spd_buf[SPD_DRAM_REFRESH_RATE];
data[RCD] = spd_buf[SPD_DRAM_RCD];
data[TPC] = spd_buf[SPD_DRAM_TPC];
data[TRWL] = spd_buf[SPD_DRAM_TRWL];
data[TRAS] = spd_buf[SPD_DRAM_TRAS];
if ((spd_buf[SPD_DRAM_DENSITY] < 0x1) || (spd_buf[SPD_DRAM_DENSITY] > 0x40))
data[DENSITY] = 0x10;
else
data[DENSITY] = spd_buf[SPD_DRAM_DENSITY];
/* Have two dimm slot or not? */
i2ci_read(SPD_DEV2, tmp_buf, SPD_DRAM_CHIP, 1);
if (data[CHIP] == tmp_buf[0])
data[DIMM] = 2;
else
data[DIMM] = 1;
data[SIZE] = (data[DENSITY]<<2) * data[CHIP] * data[DIMM];
// dimm or sodimm only be checked by hci
ch = i2ci_read(HCI_DEV, tmp_buf, HCI_CHIP_TYPE, 1);
if((ch >= 0) & (tmp_buf[0] != 0xff)) {
if(tmp_buf[0] == 1 )
data[SODIMM] = 1;
else
data[SODIMM] = 0;
}
else {
if(DEFAULT_SODIMM == 1 )
data[SODIMM] = 1;
else
data[SODIMM] = 0;
}
return;
}
/* ----------------------------------------------- */
void get_hci_info(unsigned int *data, unsigned char *hci_buf)
{
data[ROW] = hci_buf[HCI_CHIP_ROW];
data[COL] = hci_buf[HCI_CHIP_COL];
data[CHIP] = hci_buf[HCI_CHIP_CHIP];
if(hci_buf[HCI_CHIP_BANK] >= 2)
data[BANK] = 1;
else
data[BANK] = 0;
if(hci_buf[HCI_CHIP_CAS_LATENCY] & 2)
data[CAS_LATENCY] = 1;
else // should ch=2, but gt2000 don't support CAS_latency 3 cycles
data[CAS_LATENCY] = 1;
data[REFRESH_RATE] = hci_buf[HCI_CHIP_REFRESH_RATE];
data[RCD] = hci_buf[HCI_CHIP_RCD];
data[TPC] = hci_buf[HCI_CHIP_TPC];
data[TRWL] = hci_buf[HCI_CHIP_TRWL];
data[TRAS] = hci_buf[HCI_CHIP_TRAS];
data[SIZE] = (1 << hci_buf[HCI_CHIP_SIZE]);
data[DENSITY] = 0;
data[DIMM] = 0;
data[SODIMM] = 0;
return;
}
/* ----------------------------------------------- */
void get_default_info(unsigned int *data)
{
data[ROW] = DEFAULT_ROW;
data[COL] = DEFAULT_COL;
data[CHIP] = DEFAULT_CHIP;
if(DEFAULT_BANK == 2)
data[BANK] = 0; //2 bank
else
data[BANK] = 1; //4 bank
if(DEFAULT_CAS_LATENCY & 2)
data[CAS_LATENCY] = 1;
else // should ch=2, but gt2000 don't support CAS_latency 3 cycles
data[CAS_LATENCY] = 1;
data[REFRESH_RATE] = DEFAULT_REFRESH_RATE;
data[RCD] = DEFAULT_RCD;
data[TPC] = DEFAULT_TPC;
data[TRWL] = DEFAULT_TRWL;
data[TRAS] = DEFAULT_TRAS;
data[SIZE] = DEFAULT_SIZE;
data[DENSITY] = 0;
data[DIMM] = 0;
data[SODIMM] = 0;
return;
}
/* ----------------------------------------------- */
void get_sys_info(unsigned int *sys_info)
{
unsigned char tmp_buf[33];
int tmp;
i2c_init();
if((i2ci_read(SPD_DEV, tmp_buf, 0, 32)) >= 0) {
get_spd_info(sys_info, tmp_buf);
}
else { //get hci information
tmp = i2ci_read(HCI_DEV, tmp_buf, 0, 31);
if((tmp < 0) || (tmp_buf[HCI_CHIP_VERSION] == HCI_VERSION_NULL))
get_default_info(sys_info);
else {
if((tmp_buf[HCI_CHIP_TYPE] == 0) || (tmp_buf[HCI_CHIP_TYPE] == 1)) {
gpio_led_outb(0xe);
while(1); //if DIMM or SO-DIMM, don't try SPD0 again, emi fail
}
else if(tmp_buf[HCI_CHIP_TYPE] == 2)
get_hci_info(sys_info, tmp_buf);
else
get_default_info(sys_info);
}
}
i2c_end();
}
/* -------------------------------------------------------- */
/* functions for adjust bank base and size, fixed DMAR. */
/* min size is 16M */
/* -------------------------------------------------------- */
void write_base_mask(unsigned int bank, unsigned int size, unsigned int base)
{
unsigned int i = 0;
unsigned char mask = 0xFF;
if(!size)
mask = 0xff;
else {
size >>= 24;
while (size > 1) {
size >>= 1;
i++;
}
while (i--)
mask <<= 1;
}
base = (base >> 24) << 8;
outl(REG_EMI_DMAR_BASE + REG_EMI_DMAR_SIZE * bank, mask | base);
}
/* ----------------------------------------------- */
void config_dmar(unsigned int *data)
{
unsigned int size, base, i = 0;
if (data[DIMM] != 0) { // use values in SPD
/* must CS=1/CS=2 */
/* CS=1:CS4L,CS5L, use bank4 and bank5 */
/* CS=2:CS4L,CS4H,CS5L,CS5H, use bank4 and bank5 too */
base = 0x10000000;
size = data[SIZE] * 0x100000 / 2 / data[DIMM];
write_base_mask(0, size, base);
if(data[DIMM] != 2) {
base += size;
wri