| /** | |
| * @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; | |
| } |