upstream u-boot with additional patches for our devices/boards:
https://lists.denx.de/pipermail/u-boot/2017-March/282789.html (AXP crashes) ;
Gbit ethernet patch for some LIME2 revisions ;
with SPI flash support
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
713 lines
21 KiB
713 lines
21 KiB
19 years ago
|
/**
|
||
|
* @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;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|