blob: f0481553f07716d93cad23407112d89ad065acea [file] [log] [blame]
Wolfgang Denk7521af12005-10-09 01:04:33 +02001/**
2 * @file powerspan.c Source file for PowerSpan II code.
3 */
4
5/*
6 * (C) Copyright 2005
7 * AMIRIX Systems Inc.
8 *
9 * See file CREDITS for list of people who contributed to this
10 * project.
11 *
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.
16 *
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.
21 *
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,
25 * MA 02111-1307 USA
26 */
27
28#include <common.h>
29#include <command.h>
30#include <asm/processor.h>
31#include "powerspan.h"
32#define tolower(x) x
33#include "ap1000.h"
34
35#ifdef INCLUDE_PCI
36
37/** Write one byte with byte swapping.
38 * @param addr [IN] the address to write to
39 * @param val [IN] the value to write
40 */
Wolfgang Denk3df5bea2005-10-09 01:41:48 +020041void write1 (unsigned long addr, unsigned char val)
42{
43 volatile unsigned char *p = (volatile unsigned char *) addr;
44
Wolfgang Denk7521af12005-10-09 01:04:33 +020045#ifdef VERBOSITY
Wolfgang Denk3df5bea2005-10-09 01:41:48 +020046 if (gVerbosityLevel > 1) {
47 printf ("write1: addr=%08x val=%02x\n", addr, val);
48 }
Wolfgang Denk7521af12005-10-09 01:04:33 +020049#endif
Wolfgang Denk3df5bea2005-10-09 01:41:48 +020050 *p = val;
51 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +020052}
53
54/** Read one byte with byte swapping.
55 * @param addr [IN] the address to read from
56 * @return the value at addr
57 */
Wolfgang Denk3df5bea2005-10-09 01:41:48 +020058unsigned char read1 (unsigned long addr)
59{
60 unsigned char val;
61 volatile unsigned char *p = (volatile unsigned char *) addr;
Wolfgang Denk7521af12005-10-09 01:04:33 +020062
Wolfgang Denk3df5bea2005-10-09 01:41:48 +020063 val = *p;
64 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +020065#ifdef VERBOSITY
Wolfgang Denk3df5bea2005-10-09 01:41:48 +020066 if (gVerbosityLevel > 1) {
67 printf ("read1: addr=%08x val=%02x\n", addr, val);
68 }
Wolfgang Denk7521af12005-10-09 01:04:33 +020069#endif
Wolfgang Denk3df5bea2005-10-09 01:41:48 +020070 return val;
Wolfgang Denk7521af12005-10-09 01:04:33 +020071}
72
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
76 */
Wolfgang Denk3df5bea2005-10-09 01:41:48 +020077void write2 (unsigned long addr, unsigned short val)
78{
79 volatile unsigned short *p = (volatile unsigned short *) addr;
Wolfgang Denk7521af12005-10-09 01:04:33 +020080
81#ifdef VERBOSITY
Wolfgang Denk3df5bea2005-10-09 01:41:48 +020082 if (gVerbosityLevel > 1) {
83 printf ("write2: addr=%08x val=%04x -> *p=%04x\n", addr, val,
84 ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8));
85 }
Wolfgang Denk7521af12005-10-09 01:04:33 +020086#endif
Wolfgang Denk3df5bea2005-10-09 01:41:48 +020087 *p = ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8);
88 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +020089}
90
91/** Read one 2-byte word with byte swapping.
92 * @param addr [IN] the address to read from
93 * @return the value at addr
94 */
Wolfgang Denk3df5bea2005-10-09 01:41:48 +020095unsigned short read2 (unsigned long addr)
96{
97 unsigned short val;
98 volatile unsigned short *p = (volatile unsigned short *) addr;
Wolfgang Denk7521af12005-10-09 01:04:33 +020099
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200100 val = *p;
101 val = ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8);
102 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +0200103#ifdef VERBOSITY
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200104 if (gVerbosityLevel > 1) {
105 printf ("read2: addr=%08x *p=%04x -> val=%04x\n", addr, *p,
106 val);
107 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200108#endif
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200109 return val;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200110}
111
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
115 */
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200116void write4 (unsigned long addr, unsigned long val)
117{
118 volatile unsigned long *p = (volatile unsigned long *) addr;
119
Wolfgang Denk7521af12005-10-09 01:04:33 +0200120#ifdef VERBOSITY
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200121 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));
127 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200128#endif
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200129 *p = ((val & 0xFF000000) >> 24) | ((val & 0x000000FF) << 24) |
130 ((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8);
131 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +0200132}
133
134/** Read one 4-byte word with byte swapping.
135 * @param addr [IN] the address to read from
136 * @return the value at addr
137 */
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200138unsigned long read4 (unsigned long addr)
139{
140 unsigned long val;
141 volatile unsigned long *p = (volatile unsigned long *) addr;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200142
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200143 val = *p;
144 val = ((val & 0xFF000000) >> 24) | ((val & 0x000000FF) << 24) |
145 ((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8);
146 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +0200147#ifdef VERBOSITY
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200148 if (gVerbosityLevel > 1) {
149 printf ("read4: addr=%08x *p=%08x -> val=%08x\n", addr, *p,
150 val);
151 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200152#endif
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200153 return val;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200154}
155
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200156int PCIReadConfig (int bus, int dev, int fn, int reg, int width,
157 unsigned long *val)
158{
159 unsigned int conAdrVal;
160 unsigned int conDataReg = REG_CONFIG_DATA;
161 unsigned int status;
162 int ret_val = 0;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200163
164
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200165 /* 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)
170 | ((fn & 0x07) << 8)
171 | (reg & 0xFC);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200172
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200173 /* clear any pending master aborts */
174 write4 (REG_P1_CSR, CLEAR_MASTER_ABORT);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200175
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200176 /* Load the conAdrVal value first, then read from pb_conf_data */
177 write4 (REG_CONFIG_ADDRESS, conAdrVal);
178 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +0200179
180
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200181 /* Note: documentation does not match the pspan library code */
182 /* Note: *pData comes back as -1 if device is not present */
183 switch (width) {
184 case 4:
185 *(unsigned int *) val = read4 (conDataReg);
186 break;
187 case 2:
188 *(unsigned short *) val = read2 (conDataReg);
189 break;
190 case 1:
191 *(unsigned char *) val = read1 (conDataReg);
192 break;
193 default:
194 ret_val = ILLEGAL_REG_OFFSET;
195 break;
196 }
197 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +0200198
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200199 /* 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);
204 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200205
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200206 return ret_val;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200207}
208
209
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200210int PCIWriteConfig (int bus, int dev, int fn, int reg, int width,
211 unsigned long val)
212{
213 unsigned int conAdrVal;
214 unsigned int conDataReg = REG_CONFIG_DATA;
215 unsigned int status;
216 int ret_val = 0;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200217
218
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200219 /* 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)
224 | ((fn & 0x07) << 8)
225 | (reg & 0xFC);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200226
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200227 /* clear any pending master aborts */
228 write4 (REG_P1_CSR, CLEAR_MASTER_ABORT);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200229
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200230 /* Load the conAdrVal value first, then read from pb_conf_data */
231 write4 (REG_CONFIG_ADDRESS, conAdrVal);
232 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +0200233
234
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200235 /* Note: documentation does not match the pspan library code */
236 /* Note: *pData comes back as -1 if device is not present */
237 switch (width) {
238 case 4:
239 write4 (conDataReg, val);
240 break;
241 case 2:
242 write2 (conDataReg, val);
243 break;
244 case 1:
245 write1 (conDataReg, val);
246 break;
247 default:
248 ret_val = ILLEGAL_REG_OFFSET;
249 break;
250 }
251 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +0200252
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200253 /* 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);
258 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200259
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200260 return ret_val;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200261}
262
263
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200264int pci_read_config_byte (int bus, int dev, int fn, int reg,
265 unsigned char *val)
266{
267 unsigned long read_val;
268 int ret_val;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200269
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200270 ret_val = PCIReadConfig (bus, dev, fn, reg, 1, &read_val);
271 *val = read_val & 0xFF;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200272
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200273 return ret_val;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200274}
275
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200276int pci_write_config_byte (int bus, int dev, int fn, int reg,
277 unsigned char val)
278{
279 return PCIWriteConfig (bus, dev, fn, reg, 1, val);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200280}
281
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200282int pci_read_config_word (int bus, int dev, int fn, int reg,
283 unsigned short *val)
284{
285 unsigned long read_val;
286 int ret_val;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200287
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200288 ret_val = PCIReadConfig (bus, dev, fn, reg, 2, &read_val);
289 *val = read_val & 0xFFFF;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200290
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200291 return ret_val;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200292}
293
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200294int pci_write_config_word (int bus, int dev, int fn, int reg,
295 unsigned short val)
296{
297 return PCIWriteConfig (bus, dev, fn, reg, 2, val);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200298}
299
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200300int pci_read_config_dword (int bus, int dev, int fn, int reg,
301 unsigned long *val)
302{
303 return PCIReadConfig (bus, dev, fn, reg, 4, val);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200304}
305
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200306int pci_write_config_dword (int bus, int dev, int fn, int reg,
307 unsigned long val)
308{
309 return PCIWriteConfig (bus, dev, fn, reg, 4, val);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200310}
311
312#endif /* INCLUDE_PCI */
313
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200314int I2CAccess (unsigned char theI2CAddress, unsigned char theDevCode,
315 unsigned char theChipSel, unsigned char *theValue, int RWFlag)
316{
317 int ret_val = 0;
318 unsigned int reg_value;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200319
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200320 reg_value = PowerSpanRead (REG_I2C_CSR);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200321
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200322 if (reg_value & I2C_CSR_ACT) {
323 printf ("Error: I2C busy\n");
324 ret_val = I2C_BUSY;
325 } else {
326 reg_value = ((theI2CAddress & 0xFF) << 24)
327 | ((theDevCode & 0x0F) << 12)
328 | ((theChipSel & 0x07) << 9)
329 | I2C_CSR_ERR;
330 if (RWFlag == I2C_WRITE) {
331 reg_value |= I2C_CSR_RW | ((*theValue & 0xFF) << 16);
332 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200333
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200334 PowerSpanWrite (REG_I2C_CSR, reg_value);
335 udelay (1);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200336
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200337 do {
338 reg_value = PowerSpanRead (REG_I2C_CSR);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200339
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200340 if ((reg_value & I2C_CSR_ACT) == 0) {
341 if (reg_value & I2C_CSR_ERR) {
342 ret_val = I2C_ERR;
343 } else {
344 *theValue =
345 (reg_value & I2C_CSR_DATA) >>
346 16;
347 }
348 }
349 } while (reg_value & I2C_CSR_ACT);
350 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200351
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200352 return ret_val;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200353}
354
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200355int EEPROMRead (unsigned char theI2CAddress, unsigned char *theValue)
356{
357 return I2CAccess (theI2CAddress, I2C_EEPROM_DEV, I2C_EEPROM_CHIP_SEL,
358 theValue, I2C_READ);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200359}
360
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200361int EEPROMWrite (unsigned char theI2CAddress, unsigned char theValue)
362{
363 return I2CAccess (theI2CAddress, I2C_EEPROM_DEV, I2C_EEPROM_CHIP_SEL,
364 &theValue, I2C_WRITE);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200365}
366
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200367int do_eeprom (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
368{
369 char cmd;
370 int ret_val = 0;
371 unsigned int address = 0;
372 unsigned char value = 1;
373 unsigned char read_value;
374 int ii;
375 int error = 0;
376 unsigned char *mem_ptr;
377 unsigned char default_eeprom[] = EEPROM_DEFAULT;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200378
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200379 if (argc < 2) {
380 goto usage;
381 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200382
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200383 cmd = argv[1][0];
384 if (argc > 2) {
385 address = simple_strtoul (argv[2], NULL, 16);
386 if (argc > 3) {
387 value = simple_strtoul (argv[3], NULL, 16) & 0xFF;
388 }
389 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200390
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200391 switch (cmd) {
392 case 'r':
393 if (address > 256) {
394 printf ("Illegal Address\n");
395 goto usage;
396 }
397 printf ("@0x%x: ", address);
398 for (ii = 0; ii < value; ii++) {
399 if (EEPROMRead (address + ii, &read_value) !=
400 0) {
401 printf ("Read Error\n");
402 } else {
403 printf ("0x%02x ", read_value);
404 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200405
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200406 if (((ii + 1) % 16) == 0) {
407 printf ("\n");
408 }
409 }
410 printf ("\n");
411 break;
412 case 'w':
413 if (address > 256) {
414 printf ("Illegal Address\n");
415 goto usage;
416 }
417 if (argc < 4) {
418 goto usage;
419 }
420 if (EEPROMWrite (address, value) != 0) {
421 printf ("Write Error\n");
422 }
423 break;
424 case 'g':
425 if (argc != 3) {
426 goto usage;
427 }
428 mem_ptr = (unsigned char *) address;
429 for (ii = 0; ((ii < EEPROM_LENGTH) && (error == 0));
430 ii++) {
431 if (EEPROMRead (ii, &read_value) != 0) {
432 printf ("Read Error\n");
433 error = 1;
434 } else {
435 *mem_ptr = read_value;
436 mem_ptr++;
437 }
438 }
439 break;
440 case 'p':
441 if (argc != 3) {
442 goto usage;
443 }
444 mem_ptr = (unsigned char *) address;
445 for (ii = 0; ((ii < EEPROM_LENGTH) && (error == 0));
446 ii++) {
447 if (EEPROMWrite (ii, *mem_ptr) != 0) {
448 printf ("Write Error\n");
449 error = 1;
450 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200451
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200452 mem_ptr++;
453 }
454 break;
455 case 'd':
456 if (argc != 2) {
457 goto usage;
458 }
459 for (ii = 0; ((ii < EEPROM_LENGTH) && (error == 0));
460 ii++) {
461 if (EEPROMWrite (ii, default_eeprom[ii]) != 0) {
462 printf ("Write Error\n");
463 error = 1;
464 }
465 }
466 break;
467 default:
468 goto usage;
469 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200470
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200471 goto done;
472 usage:
473 printf ("Usage:\n%s\n", cmdtp->help);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200474
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200475 done:
476 return ret_val;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200477
478}
479
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200480U_BOOT_CMD (eeprom, 4, 0, do_eeprom,
481 "eeprom - read/write/copy to/from the PowerSpan II eeprom\n",
482 "eeprom r OFF [NUM]\n"
483 " - read NUM words starting at OFF\n"
484 "eeprom w OFF VAL\n"
485 " - write word VAL at offset OFF\n"
486 "eeprom g ADD\n"
487 " - store contents of eeprom at address ADD\n"
488 "eeprom p ADD\n"
489 " - put data stored at address ADD into the eeprom\n"
490 "eeprom d\n" " - return eeprom to default contents\n");
Wolfgang Denk7521af12005-10-09 01:04:33 +0200491
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200492unsigned int PowerSpanRead (unsigned int theOffset)
493{
494 volatile unsigned int *ptr =
495 (volatile unsigned int *) (PSPAN_BASEADDR + theOffset);
496 unsigned int ret_val;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200497
498#ifdef VERBOSITY
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200499 if (gVerbosityLevel > 1) {
500 printf ("PowerSpanRead: offset=%08x ", theOffset);
501 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200502#endif
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200503 ret_val = *ptr;
504 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +0200505
506#ifdef VERBOSITY
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200507 if (gVerbosityLevel > 1) {
508 printf ("value=%08x\n", ret_val);
509 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200510#endif
511
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200512 return ret_val;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200513}
514
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200515void PowerSpanWrite (unsigned int theOffset, unsigned int theValue)
516{
517 volatile unsigned int *ptr =
518 (volatile unsigned int *) (PSPAN_BASEADDR + theOffset);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200519#ifdef VERBOSITY
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200520 if (gVerbosityLevel > 1) {
521 printf ("PowerSpanWrite: offset=%08x val=%02x\n", theOffset,
522 theValue);
523 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200524#endif
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200525 *ptr = theValue;
526 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +0200527}
528
529/**
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.
533 */
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200534void PowerSpanSetBits (unsigned int theOffset, unsigned int theMask)
535{
536 volatile unsigned int *ptr =
537 (volatile unsigned int *) (PSPAN_BASEADDR + theOffset);
538 unsigned int register_value;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200539
540#ifdef VERBOSITY
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200541 if (gVerbosityLevel > 1) {
542 printf ("PowerSpanSetBits: offset=%08x mask=%02x\n",
543 theOffset, theMask);
544 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200545#endif
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200546 register_value = *ptr;
547 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +0200548
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200549 register_value |= theMask;
550 *ptr = register_value;
551 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +0200552}
553
554/**
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.
558 */
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200559void PowerSpanClearBits (unsigned int theOffset, unsigned int theMask)
560{
561 volatile unsigned int *ptr =
562 (volatile unsigned int *) (PSPAN_BASEADDR + theOffset);
563 unsigned int register_value;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200564
565#ifdef VERBOSITY
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200566 if (gVerbosityLevel > 1) {
567 printf ("PowerSpanClearBits: offset=%08x mask=%02x\n",
568 theOffset, theMask);
569 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200570#endif
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200571 register_value = *ptr;
572 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +0200573
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200574 register_value &= ~theMask;
575 *ptr = register_value;
576 PSII_SYNC ();
Wolfgang Denk7521af12005-10-09 01:04:33 +0200577}
578
579/**
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).
589 */
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200590int SetSlaveImage (int theImageIndex, unsigned int theBlockSize,
591 int theMemIOFlag, int theEndianness,
592 unsigned int theLocalBaseAddr, unsigned int thePCIBaseAddr)
593{
594 unsigned int reg_offset = theImageIndex * PB_SLAVE_IMAGE_OFF;
595 unsigned int reg_value = 0;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200596
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200597 /* Make sure that the Slave Image is disabled */
598 PowerSpanClearBits ((REGS_PB_SLAVE_CSR + reg_offset),
599 PB_SLAVE_CSR_IMG_EN);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200600
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200601 /* 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;
605 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200606
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200607 /* hardcoding the following:
608 TA_EN = 1
609 MD_EN = 0
610 MODE = 0
611 PRKEEP = 0
612 RD_AMT = 0
613 */
614 PowerSpanWrite ((REGS_PB_SLAVE_CSR + reg_offset), reg_value);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200615
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200616 /* 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);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200619
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200620 /* Enable the Slave Image */
621 PowerSpanSetBits ((REGS_PB_SLAVE_CSR + reg_offset),
622 PB_SLAVE_CSR_IMG_EN);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200623
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200624 return 0;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200625}
626
627/**
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).
640 */
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200641int SetTargetImage (int theImageIndex, unsigned int theBlockSize,
642 int theMemIOFlag, int theEndianness,
643 unsigned int theLocalBaseAddr,
644 unsigned int thePCIBaseAddr)
645{
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;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200649
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200650 /* Make sure that the Slave Image is disabled */
651 PowerSpanClearBits ((REGS_P1_TGT_CSR + csr_reg_offset),
652 PB_SLAVE_CSR_IMG_EN);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200653
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200654 /* Setup the mask required for requested PB Slave Image configuration */
655 reg_value =
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;
660 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200661
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200662 /* hardcoding the following:
663 TA_EN = 1
664 BAR_EN = 1
665 MD_EN = 0
666 MODE = 0
667 DEST = 0
668 RTT = 01010
669 GBL = 0
670 CI = 0
671 WTT = 00010
672 PRKEEP = 0
673 MRA = 0
674 RD_AMT = 0
675 */
676 PowerSpanWrite ((REGS_P1_TGT_CSR + csr_reg_offset), reg_value);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200677
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200678 PowerSpanWrite ((REGS_P1_TGT_TADDR + csr_reg_offset),
679 theLocalBaseAddr);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200680
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200681 if (thePCIBaseAddr != (unsigned int) NULL) {
682 PowerSpanWrite ((REGS_P1_BST + pci_reg_offset),
683 thePCIBaseAddr);
684 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200685
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200686 /* Enable the Slave Image */
687 PowerSpanSetBits ((REGS_P1_TGT_CSR + csr_reg_offset),
688 PB_SLAVE_CSR_IMG_EN);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200689
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200690 return 0;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200691}
692
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200693int do_bridge (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
694{
695 char cmd;
696 int ret_val = 1;
697 unsigned int image_index;
698 unsigned int block_size;
699 unsigned int mem_io;
700 unsigned int local_addr;
701 unsigned int pci_addr;
702 int endianness;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200703
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200704 if (argc != 8) {
705 goto usage;
706 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200707
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200708 cmd = argv[1][0];
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);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200715
716
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200717 switch (cmd) {
718 case 'i':
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;
723 } else {
724 goto usage;
725 }
726 SetTargetImage (image_index, block_size, mem_io,
727 endianness, local_addr, pci_addr);
728 break;
729 case 'o':
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;
734 } else {
735 goto usage;
736 }
737 SetSlaveImage (image_index, block_size, mem_io,
738 endianness, local_addr, pci_addr);
739 break;
740 default:
741 goto usage;
742 }
Wolfgang Denk7521af12005-10-09 01:04:33 +0200743
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200744 goto done;
745usage:
746 printf ("Usage:\n%s\n", cmdtp->help);
Wolfgang Denk7521af12005-10-09 01:04:33 +0200747
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200748done:
749 return ret_val;
Wolfgang Denk7521af12005-10-09 01:04:33 +0200750}