iomap.c 9.67 KB

/*************************************************************************
 *
 *  File: iomap.c
 *
 *  This file contains routines to initialize various hardware subsystems 
 *  such as the RDRAM, PI domain configuration.
 *
 *  $Header: /root/leakn64/depot/rf/sw/bbplayer/iosim/src/iomap.c,v 1.7 2002/11/07 19:36:31 was Exp $
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include "iomap.h"
#include "trace.h"
#include "verify.h"

typedef	volatile unsigned int	vu_int;

extern int ConfigRdramV;


/*
 * Stub routine to delay CPU clock cycles
 */
void 
cpuWait(int count)
{
	int i;

	/* 
	 * This generates around a 10 clock delay in verilog model 
	 * (4 for writing to reg + 6 for IPC)
	 */
	for (i = 0; i < count; i++)
		IO_WRITE(MI_NOOP_REG, 0);
}

#define RDRAM_2_DEVICE_ID	4	/* 6'd4 */
#define RDRAM_3_DEVICE_ID	6	/* 6'd6 */

#define RDRAM_2_CONFIG		0x1000	/* 'b0000_0001_0000_0000_0000 */
#define RDRAM_3_CONFIG		0x1800	/* 'b0000_0001_1000_0000_0000 */

/*
 * Initialize RDRAM with proper settings
 * Assumes that RDRAM #0 always exists; RDRAM #1, on the other hand, is
 * configurable.
 */
void 
RdramInit(int rdramSize)
{
	unsigned int ret;
	unsigned int size;
#ifdef sgi
	/*
	 * Check for valid size - can only have 2, 4, 6, or 8MB
	 */
	size = (rdramSize < 2) ? 2 : rdramSize;
	size = (rdramSize > 8) ? 8 : size;
	size &= 0xe;
	printf("RdramInit: configuring for %d MB\n", size);

	/* Set reset mode */
	IO_WRITE(RI_MODE_REG, RDRAM_RESET_MODE);
	/*IO_WRITE(RI_CONFIG_REG, 0x08);*/

	/*  By Kishor to make full speed test work on HP */
	IO_WRITE(RI_CONFIG_REG, 0x1f); 

	/* Wait for the current register to propagate (32 cycles) */
	cpuWait(4);

	/* Load the current control register */
	IO_WRITE(RI_CURRENT_LOAD_REG, 0);

	/* Set RAC transmit and receive selects */
	IO_WRITE(RI_SELECT_REG, 0x14);

	/* Wait for reset to take hold (80 cycles) */
	cpuWait(9);

	/* Set mode to standby */
	/* IO_WRITE(RI_MODE_REG, {HIGH, HIGH, RDRAM_STANDBY_MODE}); */
	IO_WRITE(RI_MODE_REG, 0x0e);

	/* Use the MI init mode to init RDRAM delay register */ 
	IO_WRITE(MI_INIT_MODE_REG, 0x10F); /* {2'b10, 7'd15} =? 0x2F */
	IO_WRITE(RDRAM_DELAY_REG | RDRAM_GLOBAL_CONFIG, 0x18082838);

	IO_WRITE(RDRAM_RAS_INTERVAL_REG | RDRAM_GLOBAL_CONFIG, 0x01070a04);

	/* If size == 8 MB, then we activate the 2nd and 3rd RDRAM which use
	 * 2MB module 
	 */
	if (size == 8) {
		/* Initialize RDRAM 3 */ 
		/* { RDRAM_3_DEVICE_ID, 2'b0, 8'b0, 8'b0, 8'b0 } */
		/* { 8'b0001_1000, 8'b0, 8'b0, 8'b0 } */
		IO_WRITE(RDRAM_DEVICE_ID_REG, 0x18000000); 

		/* +RDRAM_3_CONFIG, { 8'b0000_0010, 8'b0, 8'b0, 8'b0 } */
		IO_WRITE(RDRAM_MODE_REG + RDRAM_3_CONFIG, 0x02000000);

		/* Validate banks before refreshing begins */
		ret = IO_READ(0x00600000);
		ret = IO_READ(0x00700000);

		/* Initialize RDRAM 2 */ 
		/* { RDRAM_2_DEVICE_ID, 2'b0, 8'b0, 8'b0, 8'b0 } */
		/* { 8'b0001_0000, 8'b0, 8'b0, 8'b0 } */
		IO_WRITE(RDRAM_DEVICE_ID_REG, 0x10000000); 

		/* +RDRAM_2_CONFIG, { 8'b0000_0010, 8'b0, 8'b0, 8'b0 } */
		IO_WRITE(RDRAM_MODE_REG + RDRAM_2_CONFIG, 0x02000000);

		/* Validate banks before refreshing begins */
		ret = IO_READ(0x00400000);
		ret = IO_READ(0x00500000);

	}  /* if 8 */

	/* If size >= 4 MB, then we activate the 2nd RDRAM (2MB module) */
	if (size >= 4) {
		/* Initialize RDRAM 1 */
		IO_WRITE(RDRAM_DEVICE_ID_REG, 0x08000000); 
		IO_WRITE(RDRAM_MODE_REG + RDRAM_1_CONFIG, 0x02000000);

		/* Validate banks before refreshing begins */
		ret = IO_READ(0x00200000);
		ret = IO_READ(0x00300000);
	}

	/* If size == 6 MB, then we activate the 4th and 5th RDRAM which use
	 * 1MB module 
	 */
	if (size == 6) {
		/* Initialize RDRAM 5 */ 
		/* { RDRAM_5_DEVICE_ID, 2'b0, 8'b0, 8'b0, 8'b0 } 10100_0_0_0 */
		IO_WRITE(RDRAM_DEVICE_ID_REG, 0x14000000); 
		/* +RDRAM_5_CONFIG, { 8'b1100_0110, 8'b1000_000, 8'b0, 8'b0 } */
		IO_WRITE(RDRAM_MODE_REG + 0x1400, 0xc6800000);

		/* Validate banks before refreshing begins */
		ret = IO_READ(0x00500000);

		/* Initialize RDRAM 4 */ 
		/* { RDRAM_4_DEVICE_ID, 2'b0, 8'b0, 8'b0, 8'b0 } */
		IO_WRITE(RDRAM_DEVICE_ID_REG, 0x10000000); 
		/* +RDRAM_4_CONFIG, { 8'b1100_0110, 8'b1000_000, 8'b0, 8'b0 } */
		IO_WRITE(RDRAM_MODE_REG + 0x1000, 0xc6800000);

		/* Validate banks before refreshing begins */
		ret = IO_READ(0x00400000);
	}

	/* Initialize RDRAM 0 */
	IO_WRITE(RDRAM_DEVICE_ID_REG, 0); 
	IO_WRITE(RDRAM_MODE_REG + RDRAM_0_CONFIG, 0x02000000);

	/* Validate banks before refreshing begins */
	ret = IO_READ(0x00000000);
	ret = IO_READ(0x00100000);

	/* Enable refresh */
	/* IO_WRITE(RI_REFRESH_REG, 0x00063432); */
#if 0
	write_word(BUS_ADDRESS_RI_REFRESH, 3, 'b1_1_0_00110100_00110100');
	/* IO_WRITE(RI_REFRESH_REG, 0x00063434); */
#endif
	/* (BUS_ADDRESS_RI_REFRESH, 3, 'b0011_1_1_0_00110100_00110010); */
	IO_WRITE(RI_REFRESH_REG, 0x001e3432);
	
	/* Wait for the post-write-reg delay (10 cycles) */
	cpuWait(1);
#ifdef __DUMP_VERIFY_INFO_
        {
             /* DUMP info for Test 107 */
             printf("\n **** Dump Verify info * * * * * \n");
             printf("0x00-0x10 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
                    IO_READ(VERIFY_INFO_PHYSADDR),
                    IO_READ(VERIFY_INFO_PHYSADDR+4),
                    IO_READ(VERIFY_INFO_PHYSADDR+8),
                    IO_READ(VERIFY_INFO_PHYSADDR+0xc));
            
             printf("0x10-0x20 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
                    IO_READ(VERIFY_INFO_PHYSADDR+0x10),
                    IO_READ(VERIFY_INFO_PHYSADDR+0x14),
                    IO_READ(VERIFY_INFO_PHYSADDR+0x18),
                    IO_READ(VERIFY_INFO_PHYSADDR+0x1c));
             
             printf("0x20-0x30 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
                    IO_READ(VERIFY_INFO_PHYSADDR+0x20),
                    IO_READ(VERIFY_INFO_PHYSADDR+0x24),
                    IO_READ(VERIFY_INFO_PHYSADDR+0x28),
                    IO_READ(VERIFY_INFO_PHYSADDR+0x2c));

             printf("0x30-0x40 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
                    IO_READ(VERIFY_INFO_PHYSADDR+0x30),
                    IO_READ(VERIFY_INFO_PHYSADDR+0x34),
                    IO_READ(VERIFY_INFO_PHYSADDR+0x38),
                    IO_READ(VERIFY_INFO_PHYSADDR+0x3c));

             printf("0x40-0x50 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
                    IO_READ(VERIFY_INFO_PHYSADDR+0x40),
                    IO_READ(VERIFY_INFO_PHYSADDR+0x44),
                    IO_READ(VERIFY_INFO_PHYSADDR+0x48),
                    IO_READ(VERIFY_INFO_PHYSADDR+0x4c));

             printf("0x50-0x60 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
                    IO_READ(VERIFY_INFO_PHYSADDR+0x50),
                    IO_READ(VERIFY_INFO_PHYSADDR+0x54),
                    IO_READ(VERIFY_INFO_PHYSADDR+0x58),
                    IO_READ(VERIFY_INFO_PHYSADDR+0x5c));

        }
#endif
	#endif

}  /* end of RdramInit */


/*
 * Configure the domain registers for better Peripheral Interface (PI)
 * throughput
 */
void 
PiConfigDomain(unsigned int domReg, int lat, int pwd, int pgs, int rls)
{
	IO_WRITE(domReg+PI_DOM_LAT_OFS, lat & 0xFF);
	IO_WRITE(domReg+PI_DOM_PWD_OFS, pwd & 0xFF);
	IO_WRITE(domReg+PI_DOM_PGS_OFS, pgs & 0x0F);
	IO_WRITE(domReg+PI_DOM_RLS_OFS, rls & 0x03);
}


/*
 * Initialize various HW subsystems
 */
void 
IoInit(void)
{
#if 0
	/* Initialize the RDRAMs */
	if (ConfigRdramV == 0)
		RdramInit(RDRAM_1_ENABLED);

	/* Initialize the Peripheral Interface (PI) controller */
	/* Initial test cause the IO busy bit to always be set? */
	PiConfigDomain(PI_DOMAIN1_REG, 0x80, 0x20, 0x02, 0x03);
	PiConfigDomain(PI_DOMAIN2_REG, 0x80, 0x20, 0x03, 0x03);
#endif


}  /* IoInit */

      /* * * *  Porting to linux system * * * * * */
  /* Change all SIGSEGV error handler to socket call */
#include  "simipc.h"
#include  <errno.h>
#include  <memory.h>
int interrupt_vector;
int debug_interrupt ;

int linux_IO_Request(IpcPkt *req, IpcPkt *rsp)
{
    int ret =0, i, fd;

    for (i = 0; i < 3; i++) {
        if ((fd = IpcOpen(IPC_CLIENT)) < 0) {
            return(-1);
        }

        if (IpcConnect(fd) < 0) {
            IpcClose(fd);
            if (errno == ECONNREFUSED) {
                continue;       /* Try again */
            } else ret = -1;
        } else {
           ret = 0;
           break;
        }
     }

     if (ret == -1) {
         return(-1);
     }

     if (IpcSend(fd, (char *)req, sizeof(IpcPkt)) < 0) {
         IpcClose(fd);
         return(-1);
     }

     if (IpcReceive(fd, (char *)rsp, sizeof(IpcPkt)) < 0) {
         IpcClose(fd);
         return(-1);
     }

     IpcClose(fd);
     interrupt_vector = (ntohl(rsp->code) >> 10) & 0x3f;
     debug_interrupt = (ntohl(rsp->code) >> 9) & 0x01 ;
     return 0;
}

unsigned int linux_io_read(unsigned long addr)
{
    IpcPkt          req, rsp;

    memset(&req, 0, sizeof(IpcPkt));
    memset(&rsp, 0, sizeof(IpcPkt));

    req.length = htonl(sizeof(IpcPkt));
    req.code   = htonl(DIR_SINGLE_LOAD);
    req.size   = htonl(SIZE_4BYTE);
    req.address = htonl(addr);

    if (linux_IO_Request(&req, &rsp) < 0) {
        fprintf(stderr, "Fatal error: Cannot read from RCP!\n\n");
        return 0;
    }

    if ((ntohl(rsp.code) & 0x1ff) == RSP_DATA) {
        return ntohl(rsp.data[0]);
    } else {
        fprintf(stderr, "Fatal error: wrong status\n\n");
    }

    return 0;
}

void   linux_io_write(unsigned long addr, vu_int data)
{
    IpcPkt          req, rsp;

    memset(&req, 0, sizeof(IpcPkt));
    memset(&rsp, 0, sizeof(IpcPkt));

    req.length = htonl(sizeof(IpcPkt));
    req.code   = htonl(DIR_SINGLE_STORE);
    req.size   = htonl(SIZE_4BYTE);
    req.address = htonl(addr);
    req.data[0] = htonl(data);

    if (linux_IO_Request(&req, &rsp) < 0) {
        fprintf(stderr, "Fatal error: Cannot Write to RCP!\n\n");
        return;
    }

    if ((ntohl(rsp.code) & 0x1ff) != RSP_OK) {
        fprintf(stderr, "Fatal error: write to RCP wrong!\n\n");
    }

    return;
}