]>
git.ipfire.org Git - people/ms/u-boot.git/blob - board/amirix/ap1000/powerspan.c
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
);