mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			751 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			751 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**
 | 
						|
 * @file powerspan.c Source file for PowerSpan II code.
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
 * (C) Copyright 2005
 | 
						|
 * AMIRIX Systems Inc.
 | 
						|
 *
 | 
						|
 * See file CREDITS for list of people who contributed to this
 | 
						|
 * project.
 | 
						|
 *
 | 
						|
 * This program is free software; you can redistribute it and/or
 | 
						|
 * modify it under the terms of the GNU General Public License as
 | 
						|
 * published by the Free Software Foundation; either version 2 of
 | 
						|
 * the License, or (at your option) any later version.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 * GNU General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License
 | 
						|
 * along with this program; if not, write to the Free Software
 | 
						|
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 | 
						|
 * MA 02111-1307 USA
 | 
						|
 */
 | 
						|
 | 
						|
#include <common.h>
 | 
						|
#include <command.h>
 | 
						|
#include <asm/processor.h>
 | 
						|
#include "powerspan.h"
 | 
						|
#define tolower(x) x
 | 
						|
#include "ap1000.h"
 | 
						|
 | 
						|
#ifdef INCLUDE_PCI
 | 
						|
 | 
						|
/** Write one byte with byte swapping.
 | 
						|
  * @param  addr [IN] the address to write to
 | 
						|
  * @param  val  [IN] the value to write
 | 
						|
  */
 | 
						|
void write1 (unsigned long addr, unsigned char val)
 | 
						|
{
 | 
						|
	volatile unsigned char *p = (volatile unsigned char *) addr;
 | 
						|
 | 
						|
#ifdef VERBOSITY
 | 
						|
	if (gVerbosityLevel > 1) {
 | 
						|
		printf ("write1: addr=%08x val=%02x\n", addr, val);
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	*p = val;
 | 
						|
	PSII_SYNC ();
 | 
						|
}
 | 
						|
 | 
						|
/** Read one byte with byte swapping.
 | 
						|
  * @param  addr  [IN] the address to read from
 | 
						|
  * @return the value at addr
 | 
						|
  */
 | 
						|
unsigned char read1 (unsigned long addr)
 | 
						|
{
 | 
						|
	unsigned char val;
 | 
						|
	volatile unsigned char *p = (volatile unsigned char *) addr;
 | 
						|
 | 
						|
	val = *p;
 | 
						|
	PSII_SYNC ();
 | 
						|
#ifdef VERBOSITY
 | 
						|
	if (gVerbosityLevel > 1) {
 | 
						|
		printf ("read1: addr=%08x val=%02x\n", addr, val);
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	return val;
 | 
						|
}
 | 
						|
 | 
						|
/** Write one 2-byte word with byte swapping.
 | 
						|
  * @param  addr  [IN] the address to write to
 | 
						|
  * @param  val   [IN] the value to write
 | 
						|
  */
 | 
						|
void write2 (unsigned long addr, unsigned short val)
 | 
						|
{
 | 
						|
	volatile unsigned short *p = (volatile unsigned short *) addr;
 | 
						|
 | 
						|
#ifdef VERBOSITY
 | 
						|
	if (gVerbosityLevel > 1) {
 | 
						|
		printf ("write2: addr=%08x val=%04x -> *p=%04x\n", addr, val,
 | 
						|
			((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8));
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	*p = ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8);
 | 
						|
	PSII_SYNC ();
 | 
						|
}
 | 
						|
 | 
						|
/** Read one 2-byte word with byte swapping.
 | 
						|
  * @param  addr  [IN] the address to read from
 | 
						|
  * @return the value at addr
 | 
						|
  */
 | 
						|
unsigned short read2 (unsigned long addr)
 | 
						|
{
 | 
						|
	unsigned short val;
 | 
						|
	volatile unsigned short *p = (volatile unsigned short *) addr;
 | 
						|
 | 
						|
	val = *p;
 | 
						|
	val = ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8);
 | 
						|
	PSII_SYNC ();
 | 
						|
#ifdef VERBOSITY
 | 
						|
	if (gVerbosityLevel > 1) {
 | 
						|
		printf ("read2: addr=%08x *p=%04x -> val=%04x\n", addr, *p,
 | 
						|
			val);
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	return val;
 | 
						|
}
 | 
						|
 | 
						|
/** Write one 4-byte word with byte swapping.
 | 
						|
  * @param  addr  [IN] the address to write to
 | 
						|
  * @param  val   [IN] the value to write
 | 
						|
  */
 | 
						|
void write4 (unsigned long addr, unsigned long val)
 | 
						|
{
 | 
						|
	volatile unsigned long *p = (volatile unsigned long *) addr;
 | 
						|
 | 
						|
#ifdef VERBOSITY
 | 
						|
	if (gVerbosityLevel > 1) {
 | 
						|
		printf ("write4: addr=%08x val=%08x -> *p=%08x\n", addr, val,
 | 
						|
			((val & 0xFF000000) >> 24) |
 | 
						|
			((val & 0x000000FF) << 24) |
 | 
						|
			((val & 0x00FF0000) >>  8) |
 | 
						|
			((val & 0x0000FF00) <<  8));
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	*p = ((val & 0xFF000000) >> 24) | ((val & 0x000000FF) << 24) |
 | 
						|
		((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8);
 | 
						|
	PSII_SYNC ();
 | 
						|
}
 | 
						|
 | 
						|
/** Read one 4-byte word with byte swapping.
 | 
						|
  * @param  addr  [IN] the address to read from
 | 
						|
  * @return the value at addr
 | 
						|
  */
 | 
						|
unsigned long read4 (unsigned long addr)
 | 
						|
{
 | 
						|
	unsigned long val;
 | 
						|
	volatile unsigned long *p = (volatile unsigned long *) addr;
 | 
						|
 | 
						|
	val = *p;
 | 
						|
	val = ((val & 0xFF000000) >> 24) | ((val & 0x000000FF) << 24) |
 | 
						|
		((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8);
 | 
						|
	PSII_SYNC ();
 | 
						|
#ifdef VERBOSITY
 | 
						|
	if (gVerbosityLevel > 1) {
 | 
						|
		printf ("read4: addr=%08x *p=%08x -> val=%08x\n", addr, *p,
 | 
						|
			val);
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	return val;
 | 
						|
}
 | 
						|
 | 
						|
int PCIReadConfig (int bus, int dev, int fn, int reg, int width,
 | 
						|
		   unsigned long *val)
 | 
						|
{
 | 
						|
	unsigned int conAdrVal;
 | 
						|
	unsigned int conDataReg = REG_CONFIG_DATA;
 | 
						|
	unsigned int status;
 | 
						|
	int ret_val = 0;
 | 
						|
 | 
						|
 | 
						|
	/* DEST bit hardcoded to 1: local pci is PCI-2 */
 | 
						|
	/* TYPE bit is hardcoded to 1: all config cycles are local */
 | 
						|
	conAdrVal = (1 << 24)
 | 
						|
		| ((bus & 0xFF) << 16)
 | 
						|
		| ((dev & 0xFF) << 11)
 | 
						|
		| ((fn & 0x07) << 8)
 | 
						|
		| (reg & 0xFC);
 | 
						|
 | 
						|
	/* clear any pending master aborts */
 | 
						|
	write4 (REG_P1_CSR, CLEAR_MASTER_ABORT);
 | 
						|
 | 
						|
	/* Load the conAdrVal value first, then read from pb_conf_data */
 | 
						|
	write4 (REG_CONFIG_ADDRESS, conAdrVal);
 | 
						|
	PSII_SYNC ();
 | 
						|
 | 
						|
 | 
						|
	/* Note: documentation does not match the pspan library code */
 | 
						|
	/* Note: *pData comes back as -1 if device is not present */
 | 
						|
	switch (width) {
 | 
						|
	case 4:
 | 
						|
		*(unsigned int *) val = read4 (conDataReg);
 | 
						|
		break;
 | 
						|
	case 2:
 | 
						|
		*(unsigned short *) val = read2 (conDataReg);
 | 
						|
		break;
 | 
						|
	case 1:
 | 
						|
		*(unsigned char *) val = read1 (conDataReg);
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		ret_val = ILLEGAL_REG_OFFSET;
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	PSII_SYNC ();
 | 
						|
 | 
						|
	/* clear any pending master aborts */
 | 
						|
	status = read4 (REG_P1_CSR);
 | 
						|
	if (status & CLEAR_MASTER_ABORT) {
 | 
						|
		ret_val = NO_DEVICE_FOUND;
 | 
						|
		write4 (REG_P1_CSR, CLEAR_MASTER_ABORT);
 | 
						|
	}
 | 
						|
 | 
						|
	return ret_val;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int PCIWriteConfig (int bus, int dev, int fn, int reg, int width,
 | 
						|
		    unsigned long val)
 | 
						|
{
 | 
						|
	unsigned int conAdrVal;
 | 
						|
	unsigned int conDataReg = REG_CONFIG_DATA;
 | 
						|
	unsigned int status;
 | 
						|
	int ret_val = 0;
 | 
						|
 | 
						|
 | 
						|
	/* DEST bit hardcoded to 1: local pci is PCI-2 */
 | 
						|
	/* TYPE bit is hardcoded to 1: all config cycles are local */
 | 
						|
	conAdrVal = (1 << 24)
 | 
						|
		| ((bus & 0xFF) << 16)
 | 
						|
		| ((dev & 0xFF) << 11)
 | 
						|
		| ((fn & 0x07) << 8)
 | 
						|
		| (reg & 0xFC);
 | 
						|
 | 
						|
	/* clear any pending master aborts */
 | 
						|
	write4 (REG_P1_CSR, CLEAR_MASTER_ABORT);
 | 
						|
 | 
						|
	/* Load the conAdrVal value first, then read from pb_conf_data */
 | 
						|
	write4 (REG_CONFIG_ADDRESS, conAdrVal);
 | 
						|
	PSII_SYNC ();
 | 
						|
 | 
						|
 | 
						|
	/* Note: documentation does not match the pspan library code */
 | 
						|
	/* Note: *pData comes back as -1 if device is not present */
 | 
						|
	switch (width) {
 | 
						|
	case 4:
 | 
						|
		write4 (conDataReg, val);
 | 
						|
		break;
 | 
						|
	case 2:
 | 
						|
		write2 (conDataReg, val);
 | 
						|
		break;
 | 
						|
	case 1:
 | 
						|
		write1 (conDataReg, val);
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		ret_val = ILLEGAL_REG_OFFSET;
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	PSII_SYNC ();
 | 
						|
 | 
						|
	/* clear any pending master aborts */
 | 
						|
	status = read4 (REG_P1_CSR);
 | 
						|
	if (status & CLEAR_MASTER_ABORT) {
 | 
						|
		ret_val = NO_DEVICE_FOUND;
 | 
						|
		write4 (REG_P1_CSR, CLEAR_MASTER_ABORT);
 | 
						|
	}
 | 
						|
 | 
						|
	return ret_val;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int pci_read_config_byte (int bus, int dev, int fn, int reg,
 | 
						|
			  unsigned char *val)
 | 
						|
{
 | 
						|
	unsigned long read_val;
 | 
						|
	int ret_val;
 | 
						|
 | 
						|
	ret_val = PCIReadConfig (bus, dev, fn, reg, 1, &read_val);
 | 
						|
	*val = read_val & 0xFF;
 | 
						|
 | 
						|
	return ret_val;
 | 
						|
}
 | 
						|
 | 
						|
int pci_write_config_byte (int bus, int dev, int fn, int reg,
 | 
						|
			   unsigned char val)
 | 
						|
{
 | 
						|
	return PCIWriteConfig (bus, dev, fn, reg, 1, val);
 | 
						|
}
 | 
						|
 | 
						|
int pci_read_config_word (int bus, int dev, int fn, int reg,
 | 
						|
			  unsigned short *val)
 | 
						|
{
 | 
						|
	unsigned long read_val;
 | 
						|
	int ret_val;
 | 
						|
 | 
						|
	ret_val = PCIReadConfig (bus, dev, fn, reg, 2, &read_val);
 | 
						|
	*val = read_val & 0xFFFF;
 | 
						|
 | 
						|
	return ret_val;
 | 
						|
}
 | 
						|
 | 
						|
int pci_write_config_word (int bus, int dev, int fn, int reg,
 | 
						|
			   unsigned short val)
 | 
						|
{
 | 
						|
	return PCIWriteConfig (bus, dev, fn, reg, 2, val);
 | 
						|
}
 | 
						|
 | 
						|
int pci_read_config_dword (int bus, int dev, int fn, int reg,
 | 
						|
			   unsigned long *val)
 | 
						|
{
 | 
						|
	return PCIReadConfig (bus, dev, fn, reg, 4, val);
 | 
						|
}
 | 
						|
 | 
						|
int pci_write_config_dword (int bus, int dev, int fn, int reg,
 | 
						|
			    unsigned long val)
 | 
						|
{
 | 
						|
	return PCIWriteConfig (bus, dev, fn, reg, 4, val);
 | 
						|
}
 | 
						|
 | 
						|
#endif /* INCLUDE_PCI */
 | 
						|
 | 
						|
int I2CAccess (unsigned char theI2CAddress, unsigned char theDevCode,
 | 
						|
	       unsigned char theChipSel, unsigned char *theValue, int RWFlag)
 | 
						|
{
 | 
						|
	int ret_val = 0;
 | 
						|
	unsigned int reg_value;
 | 
						|
 | 
						|
	reg_value = PowerSpanRead (REG_I2C_CSR);
 | 
						|
 | 
						|
	if (reg_value & I2C_CSR_ACT) {
 | 
						|
		printf ("Error: I2C busy\n");
 | 
						|
		ret_val = I2C_BUSY;
 | 
						|
	} else {
 | 
						|
		reg_value = ((theI2CAddress & 0xFF) << 24)
 | 
						|
			| ((theDevCode & 0x0F) << 12)
 | 
						|
			| ((theChipSel & 0x07) << 9)
 | 
						|
			| I2C_CSR_ERR;
 | 
						|
		if (RWFlag == I2C_WRITE) {
 | 
						|
			reg_value |= I2C_CSR_RW | ((*theValue & 0xFF) << 16);
 | 
						|
		}
 | 
						|
 | 
						|
		PowerSpanWrite (REG_I2C_CSR, reg_value);
 | 
						|
		udelay (1);
 | 
						|
 | 
						|
		do {
 | 
						|
			reg_value = PowerSpanRead (REG_I2C_CSR);
 | 
						|
 | 
						|
			if ((reg_value & I2C_CSR_ACT) == 0) {
 | 
						|
				if (reg_value & I2C_CSR_ERR) {
 | 
						|
					ret_val = I2C_ERR;
 | 
						|
				} else {
 | 
						|
					*theValue =
 | 
						|
						(reg_value & I2C_CSR_DATA) >>
 | 
						|
						16;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		} while (reg_value & I2C_CSR_ACT);
 | 
						|
	}
 | 
						|
 | 
						|
	return ret_val;
 | 
						|
}
 | 
						|
 | 
						|
int EEPROMRead (unsigned char theI2CAddress, unsigned char *theValue)
 | 
						|
{
 | 
						|
	return I2CAccess (theI2CAddress, I2C_EEPROM_DEV, I2C_EEPROM_CHIP_SEL,
 | 
						|
			  theValue, I2C_READ);
 | 
						|
}
 | 
						|
 | 
						|
int EEPROMWrite (unsigned char theI2CAddress, unsigned char theValue)
 | 
						|
{
 | 
						|
	return I2CAccess (theI2CAddress, I2C_EEPROM_DEV, I2C_EEPROM_CHIP_SEL,
 | 
						|
			  &theValue, I2C_WRITE);
 | 
						|
}
 | 
						|
 | 
						|
int do_eeprom (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 | 
						|
{
 | 
						|
	char cmd;
 | 
						|
	int ret_val = 0;
 | 
						|
	unsigned int address = 0;
 | 
						|
	unsigned char value = 1;
 | 
						|
	unsigned char read_value;
 | 
						|
	int ii;
 | 
						|
	int error = 0;
 | 
						|
	unsigned char *mem_ptr;
 | 
						|
	unsigned char default_eeprom[] = EEPROM_DEFAULT;
 | 
						|
 | 
						|
	if (argc < 2) {
 | 
						|
		goto usage;
 | 
						|
	}
 | 
						|
 | 
						|
	cmd = argv[1][0];
 | 
						|
	if (argc > 2) {
 | 
						|
		address = simple_strtoul (argv[2], NULL, 16);
 | 
						|
		if (argc > 3) {
 | 
						|
			value = simple_strtoul (argv[3], NULL, 16) & 0xFF;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	switch (cmd) {
 | 
						|
	case 'r':
 | 
						|
		if (address > 256) {
 | 
						|
			printf ("Illegal Address\n");
 | 
						|
			goto usage;
 | 
						|
		}
 | 
						|
		printf ("@0x%x: ", address);
 | 
						|
		for (ii = 0; ii < value; ii++) {
 | 
						|
			if (EEPROMRead (address + ii, &read_value) !=
 | 
						|
			    0) {
 | 
						|
				printf ("Read Error\n");
 | 
						|
			} else {
 | 
						|
				printf ("0x%02x ", read_value);
 | 
						|
			}
 | 
						|
 | 
						|
			if (((ii + 1) % 16) == 0) {
 | 
						|
				printf ("\n");
 | 
						|
			}
 | 
						|
		}
 | 
						|
		printf ("\n");
 | 
						|
		break;
 | 
						|
	case 'w':
 | 
						|
		if (address > 256) {
 | 
						|
			printf ("Illegal Address\n");
 | 
						|
			goto usage;
 | 
						|
		}
 | 
						|
		if (argc < 4) {
 | 
						|
			goto usage;
 | 
						|
		}
 | 
						|
		if (EEPROMWrite (address, value) != 0) {
 | 
						|
			printf ("Write Error\n");
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case 'g':
 | 
						|
		if (argc != 3) {
 | 
						|
			goto usage;
 | 
						|
		}
 | 
						|
		mem_ptr = (unsigned char *) address;
 | 
						|
		for (ii = 0; ((ii < EEPROM_LENGTH) && (error == 0));
 | 
						|
		     ii++) {
 | 
						|
			if (EEPROMRead (ii, &read_value) != 0) {
 | 
						|
				printf ("Read Error\n");
 | 
						|
				error = 1;
 | 
						|
			} else {
 | 
						|
				*mem_ptr = read_value;
 | 
						|
				mem_ptr++;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case 'p':
 | 
						|
		if (argc != 3) {
 | 
						|
			goto usage;
 | 
						|
		}
 | 
						|
		mem_ptr = (unsigned char *) address;
 | 
						|
		for (ii = 0; ((ii < EEPROM_LENGTH) && (error == 0));
 | 
						|
		     ii++) {
 | 
						|
			if (EEPROMWrite (ii, *mem_ptr) != 0) {
 | 
						|
				printf ("Write Error\n");
 | 
						|
				error = 1;
 | 
						|
			}
 | 
						|
 | 
						|
			mem_ptr++;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case 'd':
 | 
						|
		if (argc != 2) {
 | 
						|
			goto usage;
 | 
						|
		}
 | 
						|
		for (ii = 0; ((ii < EEPROM_LENGTH) && (error == 0));
 | 
						|
		     ii++) {
 | 
						|
			if (EEPROMWrite (ii, default_eeprom[ii]) != 0) {
 | 
						|
				printf ("Write Error\n");
 | 
						|
				error = 1;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		goto usage;
 | 
						|
	}
 | 
						|
 | 
						|
	goto done;
 | 
						|
      usage:
 | 
						|
	printf ("Usage:\n%s\n", cmdtp->help);
 | 
						|
 | 
						|
      done:
 | 
						|
	return ret_val;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
U_BOOT_CMD (eeprom, 4, 0, do_eeprom,
 | 
						|
	    "eeprom  - read/write/copy to/from the PowerSpan II eeprom\n",
 | 
						|
	    "eeprom r OFF [NUM]\n"
 | 
						|
	    "    - read NUM words starting at OFF\n"
 | 
						|
	    "eeprom w OFF VAL\n"
 | 
						|
	    "    - write word VAL at offset OFF\n"
 | 
						|
	    "eeprom g ADD\n"
 | 
						|
	    "    - store contents of eeprom at address ADD\n"
 | 
						|
	    "eeprom p ADD\n"
 | 
						|
	    "    - put data stored at address ADD into the eeprom\n"
 | 
						|
	    "eeprom d\n" "    - return eeprom to default contents\n");
 | 
						|
 | 
						|
unsigned int PowerSpanRead (unsigned int theOffset)
 | 
						|
{
 | 
						|
	volatile unsigned int *ptr =
 | 
						|
		(volatile unsigned int *) (PSPAN_BASEADDR + theOffset);
 | 
						|
	unsigned int ret_val;
 | 
						|
 | 
						|
#ifdef VERBOSITY
 | 
						|
	if (gVerbosityLevel > 1) {
 | 
						|
		printf ("PowerSpanRead: offset=%08x ", theOffset);
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	ret_val = *ptr;
 | 
						|
	PSII_SYNC ();
 | 
						|
 | 
						|
#ifdef VERBOSITY
 | 
						|
	if (gVerbosityLevel > 1) {
 | 
						|
		printf ("value=%08x\n", ret_val);
 | 
						|
	}
 | 
						|
#endif
 | 
						|
 | 
						|
	return ret_val;
 | 
						|
}
 | 
						|
 | 
						|
void PowerSpanWrite (unsigned int theOffset, unsigned int theValue)
 | 
						|
{
 | 
						|
	volatile unsigned int *ptr =
 | 
						|
		(volatile unsigned int *) (PSPAN_BASEADDR + theOffset);
 | 
						|
#ifdef VERBOSITY
 | 
						|
	if (gVerbosityLevel > 1) {
 | 
						|
		printf ("PowerSpanWrite: offset=%08x val=%02x\n", theOffset,
 | 
						|
			theValue);
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	*ptr = theValue;
 | 
						|
	PSII_SYNC ();
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Sets the indicated bits in the indicated register.
 | 
						|
 * @param theOffset [IN] the register to access.
 | 
						|
 * @param theMask   [IN] bits set in theMask will be set in the register.
 | 
						|
 */
 | 
						|
void PowerSpanSetBits (unsigned int theOffset, unsigned int theMask)
 | 
						|
{
 | 
						|
	volatile unsigned int *ptr =
 | 
						|
		(volatile unsigned int *) (PSPAN_BASEADDR + theOffset);
 | 
						|
	unsigned int register_value;
 | 
						|
 | 
						|
#ifdef VERBOSITY
 | 
						|
	if (gVerbosityLevel > 1) {
 | 
						|
		printf ("PowerSpanSetBits: offset=%08x mask=%02x\n",
 | 
						|
			theOffset, theMask);
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	register_value = *ptr;
 | 
						|
	PSII_SYNC ();
 | 
						|
 | 
						|
	register_value |= theMask;
 | 
						|
	*ptr = register_value;
 | 
						|
	PSII_SYNC ();
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Clears the indicated bits in the indicated register.
 | 
						|
 * @param theOffset [IN] the register to access.
 | 
						|
 * @param theMask   [IN] bits set in theMask will be cleared in the register.
 | 
						|
 */
 | 
						|
void PowerSpanClearBits (unsigned int theOffset, unsigned int theMask)
 | 
						|
{
 | 
						|
	volatile unsigned int *ptr =
 | 
						|
		(volatile unsigned int *) (PSPAN_BASEADDR + theOffset);
 | 
						|
	unsigned int register_value;
 | 
						|
 | 
						|
#ifdef VERBOSITY
 | 
						|
	if (gVerbosityLevel > 1) {
 | 
						|
		printf ("PowerSpanClearBits: offset=%08x mask=%02x\n",
 | 
						|
			theOffset, theMask);
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	register_value = *ptr;
 | 
						|
	PSII_SYNC ();
 | 
						|
 | 
						|
	register_value &= ~theMask;
 | 
						|
	*ptr = register_value;
 | 
						|
	PSII_SYNC ();
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Configures a slave image on the local bus, based on the parameters and some hardcoded system values.
 | 
						|
 * Slave Images are images that cause the PowerSpan II to be a master on the PCI bus.  Thus, they
 | 
						|
 *  are outgoing from the standpoint of the local bus.
 | 
						|
 * @param theImageIndex    [IN] the PowerSpan II image to set (assumed to be 0-7).
 | 
						|
 * @param theBlockSize     [IN] the block size of the image (as used by PowerSpan II: PB_SIx_CTL[BS]).
 | 
						|
 * @param theMemIOFlag     [IN] if PX_TGT_USE_MEM_IO, this image will have the MEM_IO bit set.
 | 
						|
 * @param theEndianness    [IN] the endian bits for the image (already shifted, use defines).
 | 
						|
 * @param theLocalBaseAddr [IN] the Local address for the image (assumed to be valid with provided block size).
 | 
						|
 * @param thePCIBaseAddr   [IN] the PCI address for the image (assumed to be valid with provided block size).
 | 
						|
 */
 | 
						|
int SetSlaveImage (int theImageIndex, unsigned int theBlockSize,
 | 
						|
		   int theMemIOFlag, int theEndianness,
 | 
						|
		   unsigned int theLocalBaseAddr, unsigned int thePCIBaseAddr)
 | 
						|
{
 | 
						|
	unsigned int reg_offset = theImageIndex * PB_SLAVE_IMAGE_OFF;
 | 
						|
	unsigned int reg_value = 0;
 | 
						|
 | 
						|
	/* Make sure that the Slave Image is disabled */
 | 
						|
	PowerSpanClearBits ((REGS_PB_SLAVE_CSR + reg_offset),
 | 
						|
			    PB_SLAVE_CSR_IMG_EN);
 | 
						|
 | 
						|
	/* Setup the mask required for requested PB Slave Image configuration */
 | 
						|
	reg_value = PB_SLAVE_CSR_TA_EN | theEndianness | (theBlockSize << 24);
 | 
						|
	if (theMemIOFlag == PB_SLAVE_USE_MEM_IO) {
 | 
						|
		reg_value |= PB_SLAVE_CSR_MEM_IO;
 | 
						|
	}
 | 
						|
 | 
						|
	/* hardcoding the following:
 | 
						|
	   TA_EN = 1
 | 
						|
	   MD_EN = 0
 | 
						|
	   MODE  = 0
 | 
						|
	   PRKEEP = 0
 | 
						|
	   RD_AMT = 0
 | 
						|
	 */
 | 
						|
	PowerSpanWrite ((REGS_PB_SLAVE_CSR + reg_offset), reg_value);
 | 
						|
 | 
						|
	/* these values are not checked by software */
 | 
						|
	PowerSpanWrite ((REGS_PB_SLAVE_BADDR + reg_offset), theLocalBaseAddr);
 | 
						|
	PowerSpanWrite ((REGS_PB_SLAVE_TADDR + reg_offset), thePCIBaseAddr);
 | 
						|
 | 
						|
	/* Enable the Slave Image */
 | 
						|
	PowerSpanSetBits ((REGS_PB_SLAVE_CSR + reg_offset),
 | 
						|
			  PB_SLAVE_CSR_IMG_EN);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Configures a target image on the local bus, based on the parameters and some hardcoded system values.
 | 
						|
 * Target Images are used when the PowerSpan II is acting as a target for an access.  Thus, they
 | 
						|
 *  are incoming from the standpoint of the local bus.
 | 
						|
 * In order to behave better on the host PCI bus, if thePCIBaseAddr is NULL (0x00000000), then the PCI
 | 
						|
 *  base address will not be updated; makes sense given that the hosts own memory should be mapped to
 | 
						|
 *  PCI address 0x00000000.
 | 
						|
 * @param theImageIndex    [IN] the PowerSpan II image to set.
 | 
						|
 * @param theBlockSize     [IN] the block size of the image (as used by PowerSpan II: Px_TIx_CTL[BS]).
 | 
						|
 * @param theMemIOFlag     [IN] if PX_TGT_USE_MEM_IO, this image will have the MEM_IO bit set.
 | 
						|
 * @param theEndianness    [IN] the endian bits for the image (already shifted, use defines).
 | 
						|
 * @param theLocalBaseAddr [IN] the Local address for the image (assumed to be valid with provided block size).
 | 
						|
 * @param thePCIBaseAddr   [IN] the PCI address for the image (assumed to be valid with provided block size).
 | 
						|
 */
 | 
						|
int SetTargetImage (int theImageIndex, unsigned int theBlockSize,
 | 
						|
		    int theMemIOFlag, int theEndianness,
 | 
						|
		    unsigned int theLocalBaseAddr,
 | 
						|
		    unsigned int thePCIBaseAddr)
 | 
						|
{
 | 
						|
	unsigned int csr_reg_offset = theImageIndex * P1_TGT_IMAGE_OFF;
 | 
						|
	unsigned int pci_reg_offset = theImageIndex * P1_BST_OFF;
 | 
						|
	unsigned int reg_value = 0;
 | 
						|
 | 
						|
	/* Make sure that the Slave Image is disabled */
 | 
						|
	PowerSpanClearBits ((REGS_P1_TGT_CSR + csr_reg_offset),
 | 
						|
			    PB_SLAVE_CSR_IMG_EN);
 | 
						|
 | 
						|
	/* Setup the mask required for requested PB Slave Image configuration */
 | 
						|
	reg_value =
 | 
						|
		PX_TGT_CSR_TA_EN | PX_TGT_CSR_BAR_EN | (theBlockSize << 24) |
 | 
						|
		PX_TGT_CSR_RTT_READ | PX_TGT_CSR_WTT_WFLUSH | theEndianness;
 | 
						|
	if (theMemIOFlag == PX_TGT_USE_MEM_IO) {
 | 
						|
		reg_value |= PX_TGT_MEM_IO;
 | 
						|
	}
 | 
						|
 | 
						|
	/* hardcoding the following:
 | 
						|
	   TA_EN = 1
 | 
						|
	   BAR_EN = 1
 | 
						|
	   MD_EN = 0
 | 
						|
	   MODE  = 0
 | 
						|
	   DEST  = 0
 | 
						|
	   RTT = 01010
 | 
						|
	   GBL = 0
 | 
						|
	   CI = 0
 | 
						|
	   WTT = 00010
 | 
						|
	   PRKEEP = 0
 | 
						|
	   MRA = 0
 | 
						|
	   RD_AMT = 0
 | 
						|
	 */
 | 
						|
	PowerSpanWrite ((REGS_P1_TGT_CSR + csr_reg_offset), reg_value);
 | 
						|
 | 
						|
	PowerSpanWrite ((REGS_P1_TGT_TADDR + csr_reg_offset),
 | 
						|
			theLocalBaseAddr);
 | 
						|
 | 
						|
	if (thePCIBaseAddr != (unsigned int) NULL) {
 | 
						|
		PowerSpanWrite ((REGS_P1_BST + pci_reg_offset),
 | 
						|
				thePCIBaseAddr);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Enable the Slave Image */
 | 
						|
	PowerSpanSetBits ((REGS_P1_TGT_CSR + csr_reg_offset),
 | 
						|
			  PB_SLAVE_CSR_IMG_EN);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int do_bridge (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 | 
						|
{
 | 
						|
	char cmd;
 | 
						|
	int ret_val = 1;
 | 
						|
	unsigned int image_index;
 | 
						|
	unsigned int block_size;
 | 
						|
	unsigned int mem_io;
 | 
						|
	unsigned int local_addr;
 | 
						|
	unsigned int pci_addr;
 | 
						|
	int endianness;
 | 
						|
 | 
						|
	if (argc != 8) {
 | 
						|
		goto usage;
 | 
						|
	}
 | 
						|
 | 
						|
	cmd = argv[1][0];
 | 
						|
	image_index = simple_strtoul (argv[2], NULL, 16);
 | 
						|
	block_size = simple_strtoul (argv[3], NULL, 16);
 | 
						|
	mem_io = simple_strtoul (argv[4], NULL, 16);
 | 
						|
	endianness = argv[5][0];
 | 
						|
	local_addr = simple_strtoul (argv[6], NULL, 16);
 | 
						|
	pci_addr = simple_strtoul (argv[7], NULL, 16);
 | 
						|
 | 
						|
 | 
						|
	switch (cmd) {
 | 
						|
	case 'i':
 | 
						|
		if (tolower (endianness) == 'b') {
 | 
						|
			endianness = PX_TGT_CSR_BIG_END;
 | 
						|
		} else if (tolower (endianness) == 'l') {
 | 
						|
			endianness = PX_TGT_CSR_TRUE_LEND;
 | 
						|
		} else {
 | 
						|
			goto usage;
 | 
						|
		}
 | 
						|
		SetTargetImage (image_index, block_size, mem_io,
 | 
						|
				endianness, local_addr, pci_addr);
 | 
						|
		break;
 | 
						|
	case 'o':
 | 
						|
		if (tolower (endianness) == 'b') {
 | 
						|
			endianness = PB_SLAVE_CSR_BIG_END;
 | 
						|
		} else if (tolower (endianness) == 'l') {
 | 
						|
			endianness = PB_SLAVE_CSR_TRUE_LEND;
 | 
						|
		} else {
 | 
						|
			goto usage;
 | 
						|
		}
 | 
						|
		SetSlaveImage (image_index, block_size, mem_io,
 | 
						|
			       endianness, local_addr, pci_addr);
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		goto usage;
 | 
						|
	}
 | 
						|
 | 
						|
	goto done;
 | 
						|
usage:
 | 
						|
	printf ("Usage:\n%s\n", cmdtp->help);
 | 
						|
 | 
						|
done:
 | 
						|
	return ret_val;
 | 
						|
}
 |