2 * @file powerspan.c Source file for PowerSpan II code.
9 * See file CREDITS for list of people who contributed to this
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
30 #include <asm/processor.h>
31 #include "powerspan.h"
37 /** Write one byte with byte swapping.
38 * @param addr [IN] the address to write to
39 * @param val [IN] the value to write
41 void write1 (unsigned long addr, unsigned char val)
43 volatile unsigned char *p = (volatile unsigned char *) addr;
46 if (gVerbosityLevel > 1) {
47 printf ("write1: addr=%08x val=%02x\n", addr, val);
54 /** Read one byte with byte swapping.
55 * @param addr [IN] the address to read from
56 * @return the value at addr
58 unsigned char read1 (unsigned long addr)
61 volatile unsigned char *p = (volatile unsigned char *) addr;
66 if (gVerbosityLevel > 1) {
67 printf ("read1: addr=%08x val=%02x\n", addr, val);
73 /** Write one 2-byte word with byte swapping.
74 * @param addr [IN] the address to write to
75 * @param val [IN] the value to write
77 void write2 (unsigned long addr, unsigned short val)
79 volatile unsigned short *p = (volatile unsigned short *) addr;
82 if (gVerbosityLevel > 1) {
83 printf ("write2: addr=%08x val=%04x -> *p=%04x\n", addr, val,
84 ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8));
87 *p = ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8);
91 /** Read one 2-byte word with byte swapping.
92 * @param addr [IN] the address to read from
93 * @return the value at addr
95 unsigned short read2 (unsigned long addr)
98 volatile unsigned short *p = (volatile unsigned short *) addr;
101 val = ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8);
104 if (gVerbosityLevel > 1) {
105 printf ("read2: addr=%08x *p=%04x -> val=%04x\n", addr, *p,
112 /** Write one 4-byte word with byte swapping.
113 * @param addr [IN] the address to write to
114 * @param val [IN] the value to write
116 void write4 (unsigned long addr, unsigned long val)
118 volatile unsigned long *p = (volatile unsigned long *) addr;
121 if (gVerbosityLevel > 1) {
122 printf ("write4: addr=%08x val=%08x -> *p=%08x\n", addr, val,
123 ((val & 0xFF000000) >> 24) |
124 ((val & 0x000000FF) << 24) |
125 ((val & 0x00FF0000) >> 8) |
126 ((val & 0x0000FF00) << 8));
129 *p = ((val & 0xFF000000) >> 24) | ((val & 0x000000FF) << 24) |
130 ((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8);
134 /** Read one 4-byte word with byte swapping.
135 * @param addr [IN] the address to read from
136 * @return the value at addr
138 unsigned long read4 (unsigned long addr)
141 volatile unsigned long *p = (volatile unsigned long *) addr;
144 val = ((val & 0xFF000000) >> 24) | ((val & 0x000000FF) << 24) |
145 ((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8);
148 if (gVerbosityLevel > 1) {
149 printf ("read4: addr=%08x *p=%08x -> val=%08x\n", addr, *p,
156 int PCIReadConfig (int bus, int dev, int fn, int reg, int width,
159 unsigned int conAdrVal;
160 unsigned int conDataReg = REG_CONFIG_DATA;
165 /* DEST bit hardcoded to 1: local pci is PCI-2 */
166 /* TYPE bit is hardcoded to 1: all config cycles are local */
167 conAdrVal = (1 << 24)
168 | ((bus & 0xFF) << 16)
169 | ((dev & 0xFF) << 11)
173 /* clear any pending master aborts */
174 write4 (REG_P1_CSR, CLEAR_MASTER_ABORT);
176 /* Load the conAdrVal value first, then read from pb_conf_data */
177 write4 (REG_CONFIG_ADDRESS, conAdrVal);
181 /* Note: documentation does not match the pspan library code */
182 /* Note: *pData comes back as -1 if device is not present */
185 *(unsigned int *) val = read4 (conDataReg);
188 *(unsigned short *) val = read2 (conDataReg);
191 *(unsigned char *) val = read1 (conDataReg);
194 ret_val = ILLEGAL_REG_OFFSET;
199 /* clear any pending master aborts */
200 status = read4 (REG_P1_CSR);
201 if (status & CLEAR_MASTER_ABORT) {
202 ret_val = NO_DEVICE_FOUND;
203 write4 (REG_P1_CSR, CLEAR_MASTER_ABORT);
210 int PCIWriteConfig (int bus, int dev, int fn, int reg, int width,
213 unsigned int conAdrVal;
214 unsigned int conDataReg = REG_CONFIG_DATA;
219 /* DEST bit hardcoded to 1: local pci is PCI-2 */
220 /* TYPE bit is hardcoded to 1: all config cycles are local */
221 conAdrVal = (1 << 24)
222 | ((bus & 0xFF) << 16)
223 | ((dev & 0xFF) << 11)
227 /* clear any pending master aborts */
228 write4 (REG_P1_CSR, CLEAR_MASTER_ABORT);
230 /* Load the conAdrVal value first, then read from pb_conf_data */
231 write4 (REG_CONFIG_ADDRESS, conAdrVal);
235 /* Note: documentation does not match the pspan library code */
236 /* Note: *pData comes back as -1 if device is not present */
239 write4 (conDataReg, val);
242 write2 (conDataReg, val);
245 write1 (conDataReg, val);
248 ret_val = ILLEGAL_REG_OFFSET;
253 /* clear any pending master aborts */
254 status = read4 (REG_P1_CSR);
255 if (status & CLEAR_MASTER_ABORT) {
256 ret_val = NO_DEVICE_FOUND;
257 write4 (REG_P1_CSR, CLEAR_MASTER_ABORT);
264 int pci_read_config_byte (int bus, int dev, int fn, int reg,
267 unsigned long read_val;
270 ret_val = PCIReadConfig (bus, dev, fn, reg, 1, &read_val);
271 *val = read_val & 0xFF;
276 int pci_write_config_byte (int bus, int dev, int fn, int reg,
279 return PCIWriteConfig (bus, dev, fn, reg, 1, val);
282 int pci_read_config_word (int bus, int dev, int fn, int reg,
285 unsigned long read_val;
288 ret_val = PCIReadConfig (bus, dev, fn, reg, 2, &read_val);
289 *val = read_val & 0xFFFF;
294 int pci_write_config_word (int bus, int dev, int fn, int reg,
297 return PCIWriteConfig (bus, dev, fn, reg, 2, val);
300 int pci_read_config_dword (int bus, int dev, int fn, int reg,
303 return PCIReadConfig (bus, dev, fn, reg, 4, val);
306 int pci_write_config_dword (int bus, int dev, int fn, int reg,
309 return PCIWriteConfig (bus, dev, fn, reg, 4, val);
312 #endif /* INCLUDE_PCI */
314 int I2CAccess (unsigned char theI2CAddress, unsigned char theDevCode,
315 unsigned char theChipSel, unsigned char *theValue, int RWFlag)
318 unsigned int reg_value;
320 reg_value = PowerSpanRead (REG_I2C_CSR);
322 if (reg_value & I2C_CSR_ACT) {
323 printf ("Error: I2C busy\n");
326 reg_value = ((theI2CAddress & 0xFF) << 24)
327 | ((theDevCode & 0x0F) << 12)
328 | ((theChipSel & 0x07) << 9)
330 if (RWFlag == I2C_WRITE) {
331 reg_value |= I2C_CSR_RW | ((*theValue & 0xFF) << 16);
334 PowerSpanWrite (REG_I2C_CSR, reg_value);
338 reg_value = PowerSpanRead (REG_I2C_CSR);
340 if ((reg_value & I2C_CSR_ACT) == 0) {
341 if (reg_value & I2C_CSR_ERR) {
345 (reg_value & I2C_CSR_DATA) >>
349 } while (reg_value & I2C_CSR_ACT);
355 int EEPROMRead (unsigned char theI2CAddress, unsigned char *theValue)
357 return I2CAccess (theI2CAddress, I2C_EEPROM_DEV, I2C_EEPROM_CHIP_SEL,
361 int EEPROMWrite (unsigned char theI2CAddress, unsigned char theValue)
363 return I2CAccess (theI2CAddress, I2C_EEPROM_DEV, I2C_EEPROM_CHIP_SEL,
364 &theValue, I2C_WRITE);
367 int do_eeprom (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
371 unsigned int address = 0;
372 unsigned char value = 1;
373 unsigned char read_value;
376 unsigned char *mem_ptr;
377 unsigned char default_eeprom[] = EEPROM_DEFAULT;
385 address = simple_strtoul (argv[2], NULL, 16);
387 value = simple_strtoul (argv[3], NULL, 16) & 0xFF;
394 printf ("Illegal Address\n");
397 printf ("@0x%x: ", address);
398 for (ii = 0; ii < value; ii++) {
399 if (EEPROMRead (address + ii, &read_value) !=
401 printf ("Read Error\n");
403 printf ("0x%02x ", read_value);
406 if (((ii + 1) % 16) == 0) {
414 printf ("Illegal Address\n");
420 if (EEPROMWrite (address, value) != 0) {
421 printf ("Write Error\n");
428 mem_ptr = (unsigned char *) address;
429 for (ii = 0; ((ii < EEPROM_LENGTH) && (error == 0));
431 if (EEPROMRead (ii, &read_value) != 0) {
432 printf ("Read Error\n");
435 *mem_ptr = read_value;
444 mem_ptr = (unsigned char *) address;
445 for (ii = 0; ((ii < EEPROM_LENGTH) && (error == 0));
447 if (EEPROMWrite (ii, *mem_ptr) != 0) {
448 printf ("Write Error\n");
459 for (ii = 0; ((ii < EEPROM_LENGTH) && (error == 0));
461 if (EEPROMWrite (ii, default_eeprom[ii]) != 0) {
462 printf ("Write Error\n");
473 printf ("Usage:\n%s\n", cmdtp->help);
480 U_BOOT_CMD (eeprom, 4, 0, do_eeprom,
481 "read/write/copy to/from the PowerSpan II eeprom",
482 "eeprom r OFF [NUM]\n"
483 " - read NUM words starting at OFF\n"
485 " - write word VAL at offset OFF\n"
487 " - store contents of eeprom at address ADD\n"
489 " - put data stored at address ADD into the eeprom\n"
490 "eeprom d\n" " - return eeprom to default contents\n");
492 unsigned int PowerSpanRead (unsigned int theOffset)
494 volatile unsigned int *ptr =
495 (volatile unsigned int *) (PSPAN_BASEADDR + theOffset);
496 unsigned int ret_val;
499 if (gVerbosityLevel > 1) {
500 printf ("PowerSpanRead: offset=%08x ", theOffset);
507 if (gVerbosityLevel > 1) {
508 printf ("value=%08x\n", ret_val);
515 void PowerSpanWrite (unsigned int theOffset, unsigned int theValue)
517 volatile unsigned int *ptr =
518 (volatile unsigned int *) (PSPAN_BASEADDR + theOffset);
520 if (gVerbosityLevel > 1) {
521 printf ("PowerSpanWrite: offset=%08x val=%02x\n", theOffset,
530 * Sets the indicated bits in the indicated register.
531 * @param theOffset [IN] the register to access.
532 * @param theMask [IN] bits set in theMask will be set in the register.
534 void PowerSpanSetBits (unsigned int theOffset, unsigned int theMask)
536 volatile unsigned int *ptr =
537 (volatile unsigned int *) (PSPAN_BASEADDR + theOffset);
538 unsigned int register_value;
541 if (gVerbosityLevel > 1) {
542 printf ("PowerSpanSetBits: offset=%08x mask=%02x\n",
546 register_value = *ptr;
549 register_value |= theMask;
550 *ptr = register_value;
555 * Clears the indicated bits in the indicated register.
556 * @param theOffset [IN] the register to access.
557 * @param theMask [IN] bits set in theMask will be cleared in the register.
559 void PowerSpanClearBits (unsigned int theOffset, unsigned int theMask)
561 volatile unsigned int *ptr =
562 (volatile unsigned int *) (PSPAN_BASEADDR + theOffset);
563 unsigned int register_value;
566 if (gVerbosityLevel > 1) {
567 printf ("PowerSpanClearBits: offset=%08x mask=%02x\n",
571 register_value = *ptr;
574 register_value &= ~theMask;
575 *ptr = register_value;
580 * Configures a slave image on the local bus, based on the parameters and some hardcoded system values.
581 * Slave Images are images that cause the PowerSpan II to be a master on the PCI bus. Thus, they
582 * are outgoing from the standpoint of the local bus.
583 * @param theImageIndex [IN] the PowerSpan II image to set (assumed to be 0-7).
584 * @param theBlockSize [IN] the block size of the image (as used by PowerSpan II: PB_SIx_CTL[BS]).
585 * @param theMemIOFlag [IN] if PX_TGT_USE_MEM_IO, this image will have the MEM_IO bit set.
586 * @param theEndianness [IN] the endian bits for the image (already shifted, use defines).
587 * @param theLocalBaseAddr [IN] the Local address for the image (assumed to be valid with provided block size).
588 * @param thePCIBaseAddr [IN] the PCI address for the image (assumed to be valid with provided block size).
590 int SetSlaveImage (int theImageIndex, unsigned int theBlockSize,
591 int theMemIOFlag, int theEndianness,
592 unsigned int theLocalBaseAddr, unsigned int thePCIBaseAddr)
594 unsigned int reg_offset = theImageIndex * PB_SLAVE_IMAGE_OFF;
595 unsigned int reg_value = 0;
597 /* Make sure that the Slave Image is disabled */
598 PowerSpanClearBits ((REGS_PB_SLAVE_CSR + reg_offset),
599 PB_SLAVE_CSR_IMG_EN);
601 /* Setup the mask required for requested PB Slave Image configuration */
602 reg_value = PB_SLAVE_CSR_TA_EN | theEndianness | (theBlockSize << 24);
603 if (theMemIOFlag == PB_SLAVE_USE_MEM_IO) {
604 reg_value |= PB_SLAVE_CSR_MEM_IO;
607 /* hardcoding the following:
614 PowerSpanWrite ((REGS_PB_SLAVE_CSR + reg_offset), reg_value);
616 /* these values are not checked by software */
617 PowerSpanWrite ((REGS_PB_SLAVE_BADDR + reg_offset), theLocalBaseAddr);
618 PowerSpanWrite ((REGS_PB_SLAVE_TADDR + reg_offset), thePCIBaseAddr);
620 /* Enable the Slave Image */
621 PowerSpanSetBits ((REGS_PB_SLAVE_CSR + reg_offset),
622 PB_SLAVE_CSR_IMG_EN);
628 * Configures a target image on the local bus, based on the parameters and some hardcoded system values.
629 * Target Images are used when the PowerSpan II is acting as a target for an access. Thus, they
630 * are incoming from the standpoint of the local bus.
631 * In order to behave better on the host PCI bus, if thePCIBaseAddr is NULL (0x00000000), then the PCI
632 * base address will not be updated; makes sense given that the hosts own memory should be mapped to
633 * PCI address 0x00000000.
634 * @param theImageIndex [IN] the PowerSpan II image to set.
635 * @param theBlockSize [IN] the block size of the image (as used by PowerSpan II: Px_TIx_CTL[BS]).
636 * @param theMemIOFlag [IN] if PX_TGT_USE_MEM_IO, this image will have the MEM_IO bit set.
637 * @param theEndianness [IN] the endian bits for the image (already shifted, use defines).
638 * @param theLocalBaseAddr [IN] the Local address for the image (assumed to be valid with provided block size).
639 * @param thePCIBaseAddr [IN] the PCI address for the image (assumed to be valid with provided block size).
641 int SetTargetImage (int theImageIndex, unsigned int theBlockSize,
642 int theMemIOFlag, int theEndianness,
643 unsigned int theLocalBaseAddr,
644 unsigned int thePCIBaseAddr)
646 unsigned int csr_reg_offset = theImageIndex * P1_TGT_IMAGE_OFF;
647 unsigned int pci_reg_offset = theImageIndex * P1_BST_OFF;
648 unsigned int reg_value = 0;
650 /* Make sure that the Slave Image is disabled */
651 PowerSpanClearBits ((REGS_P1_TGT_CSR + csr_reg_offset),
652 PB_SLAVE_CSR_IMG_EN);
654 /* Setup the mask required for requested PB Slave Image configuration */
656 PX_TGT_CSR_TA_EN | PX_TGT_CSR_BAR_EN | (theBlockSize << 24) |
657 PX_TGT_CSR_RTT_READ | PX_TGT_CSR_WTT_WFLUSH | theEndianness;
658 if (theMemIOFlag == PX_TGT_USE_MEM_IO) {
659 reg_value |= PX_TGT_MEM_IO;
662 /* hardcoding the following:
676 PowerSpanWrite ((REGS_P1_TGT_CSR + csr_reg_offset), reg_value);
678 PowerSpanWrite ((REGS_P1_TGT_TADDR + csr_reg_offset),
681 if (thePCIBaseAddr != (unsigned int) NULL) {
682 PowerSpanWrite ((REGS_P1_BST + pci_reg_offset),
686 /* Enable the Slave Image */
687 PowerSpanSetBits ((REGS_P1_TGT_CSR + csr_reg_offset),
688 PB_SLAVE_CSR_IMG_EN);
693 int do_bridge (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
697 unsigned int image_index;
698 unsigned int block_size;
700 unsigned int local_addr;
701 unsigned int pci_addr;
709 image_index = simple_strtoul (argv[2], NULL, 16);
710 block_size = simple_strtoul (argv[3], NULL, 16);
711 mem_io = simple_strtoul (argv[4], NULL, 16);
712 endianness = argv[5][0];
713 local_addr = simple_strtoul (argv[6], NULL, 16);
714 pci_addr = simple_strtoul (argv[7], NULL, 16);
719 if (tolower (endianness) == 'b') {
720 endianness = PX_TGT_CSR_BIG_END;
721 } else if (tolower (endianness) == 'l') {
722 endianness = PX_TGT_CSR_TRUE_LEND;
726 SetTargetImage (image_index, block_size, mem_io,
727 endianness, local_addr, pci_addr);
730 if (tolower (endianness) == 'b') {
731 endianness = PB_SLAVE_CSR_BIG_END;
732 } else if (tolower (endianness) == 'l') {
733 endianness = PB_SLAVE_CSR_TRUE_LEND;
737 SetSlaveImage (image_index, block_size, mem_io,
738 endianness, local_addr, pci_addr);
746 printf ("Usage:\n%s\n", cmdtp->help);