Add support for AP1000 board.
Patch by James MacAulay, 07 Oct 2005
diff --git a/board/amirix/ap1000/powerspan.c b/board/amirix/ap1000/powerspan.c
new file mode 100644
index 0000000..fe395cc
--- /dev/null
+++ b/board/amirix/ap1000/powerspan.c
@@ -0,0 +1,712 @@
+/**
+ * @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;
+
+}
+
+
+