]>
Commit | Line | Data |
---|---|---|
7521af1c WD |
1 | /** |
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 | */ | |
3df5bea0 WD |
41 | void write1 (unsigned long addr, unsigned char val) |
42 | { | |
43 | volatile unsigned char *p = (volatile unsigned char *) addr; | |
44 | ||
7521af1c | 45 | #ifdef VERBOSITY |
3df5bea0 WD |
46 | if (gVerbosityLevel > 1) { |
47 | printf ("write1: addr=%08x val=%02x\n", addr, val); | |
48 | } | |
7521af1c | 49 | #endif |
3df5bea0 WD |
50 | *p = val; |
51 | PSII_SYNC (); | |
7521af1c WD |
52 | } |
53 | ||
54 | /** Read one byte with byte swapping. | |
55 | * @param addr [IN] the address to read from | |
56 | * @return the value at addr | |
57 | */ | |
3df5bea0 WD |
58 | unsigned char read1 (unsigned long addr) |
59 | { | |
60 | unsigned char val; | |
61 | volatile unsigned char *p = (volatile unsigned char *) addr; | |
7521af1c | 62 | |
3df5bea0 WD |
63 | val = *p; |
64 | PSII_SYNC (); | |
7521af1c | 65 | #ifdef VERBOSITY |
3df5bea0 WD |
66 | if (gVerbosityLevel > 1) { |
67 | printf ("read1: addr=%08x val=%02x\n", addr, val); | |
68 | } | |
7521af1c | 69 | #endif |
3df5bea0 | 70 | return val; |
7521af1c WD |
71 | } |
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 | */ | |
3df5bea0 WD |
77 | void write2 (unsigned long addr, unsigned short val) |
78 | { | |
79 | volatile unsigned short *p = (volatile unsigned short *) addr; | |
7521af1c WD |
80 | |
81 | #ifdef VERBOSITY | |
3df5bea0 WD |
82 | if (gVerbosityLevel > 1) { |
83 | printf ("write2: addr=%08x val=%04x -> *p=%04x\n", addr, val, | |
84 | ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8)); | |
85 | } | |
7521af1c | 86 | #endif |
3df5bea0 WD |
87 | *p = ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8); |
88 | PSII_SYNC (); | |
7521af1c WD |
89 | } |
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 | */ | |
3df5bea0 WD |
95 | unsigned short read2 (unsigned long addr) |
96 | { | |
97 | unsigned short val; | |
98 | volatile unsigned short *p = (volatile unsigned short *) addr; | |
99 | ||
100 | val = *p; | |
101 | val = ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8); | |
102 | PSII_SYNC (); | |
7521af1c | 103 | #ifdef VERBOSITY |
3df5bea0 WD |
104 | if (gVerbosityLevel > 1) { |
105 | printf ("read2: addr=%08x *p=%04x -> val=%04x\n", addr, *p, | |
106 | val); | |
107 | } | |
7521af1c | 108 | #endif |
3df5bea0 | 109 | return val; |
7521af1c WD |
110 | } |
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 | */ | |
3df5bea0 WD |
116 | void write4 (unsigned long addr, unsigned long val) |
117 | { | |
118 | volatile unsigned long *p = (volatile unsigned long *) addr; | |
119 | ||
7521af1c | 120 | #ifdef VERBOSITY |
3df5bea0 WD |
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)); | |
127 | } | |
7521af1c | 128 | #endif |
3df5bea0 WD |
129 | *p = ((val & 0xFF000000) >> 24) | ((val & 0x000000FF) << 24) | |
130 | ((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8); | |
131 | PSII_SYNC (); | |
7521af1c WD |
132 | } |
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 | */ | |
3df5bea0 WD |
138 | unsigned long read4 (unsigned long addr) |
139 | { | |
140 | unsigned long val; | |
141 | volatile unsigned long *p = (volatile unsigned long *) addr; | |
142 | ||
143 | val = *p; | |
144 | val = ((val & 0xFF000000) >> 24) | ((val & 0x000000FF) << 24) | | |
145 | ((val & 0x00FF0000) >> 8) | ((val & 0x0000FF00) << 8); | |
146 | PSII_SYNC (); | |
7521af1c | 147 | #ifdef VERBOSITY |
3df5bea0 WD |
148 | if (gVerbosityLevel > 1) { |
149 | printf ("read4: addr=%08x *p=%08x -> val=%08x\n", addr, *p, | |
150 | val); | |
151 | } | |
7521af1c | 152 | #endif |
3df5bea0 | 153 | return val; |
7521af1c WD |
154 | } |
155 | ||
3df5bea0 WD |
156 | int 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; | |
163 | ||
164 | ||
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) | |
170 | | ((fn & 0x07) << 8) | |
171 | | (reg & 0xFC); | |
172 | ||
173 | /* clear any pending master aborts */ | |
174 | write4 (REG_P1_CSR, CLEAR_MASTER_ABORT); | |
175 | ||
176 | /* Load the conAdrVal value first, then read from pb_conf_data */ | |
177 | write4 (REG_CONFIG_ADDRESS, conAdrVal); | |
178 | PSII_SYNC (); | |
179 | ||
180 | ||
181 | /* 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 (); | |
198 | ||
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); | |
204 | } | |
205 | ||
206 | return ret_val; | |
7521af1c WD |
207 | } |
208 | ||
209 | ||
3df5bea0 WD |
210 | int 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; | |
217 | ||
218 | ||
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) | |
224 | | ((fn & 0x07) << 8) | |
225 | | (reg & 0xFC); | |
226 | ||
227 | /* clear any pending master aborts */ | |
228 | write4 (REG_P1_CSR, CLEAR_MASTER_ABORT); | |
229 | ||
230 | /* Load the conAdrVal value first, then read from pb_conf_data */ | |
231 | write4 (REG_CONFIG_ADDRESS, conAdrVal); | |
232 | PSII_SYNC (); | |
233 | ||
234 | ||
235 | /* 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 (); | |
252 | ||
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); | |
258 | } | |
259 | ||
260 | return ret_val; | |
7521af1c WD |
261 | } |
262 | ||
263 | ||
3df5bea0 WD |
264 | int 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; | |
7521af1c | 269 | |
3df5bea0 WD |
270 | ret_val = PCIReadConfig (bus, dev, fn, reg, 1, &read_val); |
271 | *val = read_val & 0xFF; | |
7521af1c | 272 | |
3df5bea0 | 273 | return ret_val; |
7521af1c WD |
274 | } |
275 | ||
3df5bea0 WD |
276 | int 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); | |
7521af1c WD |
280 | } |
281 | ||
3df5bea0 WD |
282 | int 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; | |
7521af1c | 287 | |
3df5bea0 WD |
288 | ret_val = PCIReadConfig (bus, dev, fn, reg, 2, &read_val); |
289 | *val = read_val & 0xFFFF; | |
7521af1c | 290 | |
3df5bea0 | 291 | return ret_val; |
7521af1c WD |
292 | } |
293 | ||
3df5bea0 WD |
294 | int 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); | |
7521af1c WD |
298 | } |
299 | ||
3df5bea0 WD |
300 | int 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); | |
7521af1c WD |
304 | } |
305 | ||
3df5bea0 WD |
306 | int 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); | |
7521af1c WD |
310 | } |
311 | ||
312 | #endif /* INCLUDE_PCI */ | |
313 | ||
3df5bea0 WD |
314 | int 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; | |
319 | ||
320 | reg_value = PowerSpanRead (REG_I2C_CSR); | |
321 | ||
322 | 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 | } | |
333 | ||
334 | PowerSpanWrite (REG_I2C_CSR, reg_value); | |
335 | udelay (1); | |
336 | ||
337 | do { | |
338 | reg_value = PowerSpanRead (REG_I2C_CSR); | |
339 | ||
340 | 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 | } | |
351 | ||
352 | return ret_val; | |
7521af1c WD |
353 | } |
354 | ||
3df5bea0 WD |
355 | int EEPROMRead (unsigned char theI2CAddress, unsigned char *theValue) |
356 | { | |
357 | return I2CAccess (theI2CAddress, I2C_EEPROM_DEV, I2C_EEPROM_CHIP_SEL, | |
358 | theValue, I2C_READ); | |
7521af1c WD |
359 | } |
360 | ||
3df5bea0 WD |
361 | int EEPROMWrite (unsigned char theI2CAddress, unsigned char theValue) |
362 | { | |
363 | return I2CAccess (theI2CAddress, I2C_EEPROM_DEV, I2C_EEPROM_CHIP_SEL, | |
364 | &theValue, I2C_WRITE); | |
7521af1c WD |
365 | } |
366 | ||
54841ab5 | 367 | int do_eeprom (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) |
3df5bea0 WD |
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; | |
378 | ||
379 | if (argc < 2) { | |
380 | goto usage; | |
381 | } | |
382 | ||
383 | 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 | } | |
390 | ||
391 | 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 | } | |
405 | ||
406 | 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 | } | |
451 | ||
452 | 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 | } | |
470 | ||
471 | goto done; | |
472 | usage: | |
473 | printf ("Usage:\n%s\n", cmdtp->help); | |
474 | ||
475 | done: | |
476 | return ret_val; | |
7521af1c WD |
477 | |
478 | } | |
479 | ||
3df5bea0 | 480 | U_BOOT_CMD (eeprom, 4, 0, do_eeprom, |
2fb2604d | 481 | "read/write/copy to/from the PowerSpan II eeprom", |
3df5bea0 WD |
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" | |
a89c33db | 490 | "eeprom d\n" " - return eeprom to default contents"); |
3df5bea0 WD |
491 | |
492 | unsigned int PowerSpanRead (unsigned int theOffset) | |
493 | { | |
494 | volatile unsigned int *ptr = | |
495 | (volatile unsigned int *) (PSPAN_BASEADDR + theOffset); | |
496 | unsigned int ret_val; | |
7521af1c WD |
497 | |
498 | #ifdef VERBOSITY | |
3df5bea0 WD |
499 | if (gVerbosityLevel > 1) { |
500 | printf ("PowerSpanRead: offset=%08x ", theOffset); | |
501 | } | |
7521af1c | 502 | #endif |
3df5bea0 WD |
503 | ret_val = *ptr; |
504 | PSII_SYNC (); | |
7521af1c WD |
505 | |
506 | #ifdef VERBOSITY | |
3df5bea0 WD |
507 | if (gVerbosityLevel > 1) { |
508 | printf ("value=%08x\n", ret_val); | |
509 | } | |
7521af1c WD |
510 | #endif |
511 | ||
3df5bea0 | 512 | return ret_val; |
7521af1c WD |
513 | } |
514 | ||
3df5bea0 WD |
515 | void PowerSpanWrite (unsigned int theOffset, unsigned int theValue) |
516 | { | |
517 | volatile unsigned int *ptr = | |
518 | (volatile unsigned int *) (PSPAN_BASEADDR + theOffset); | |
7521af1c | 519 | #ifdef VERBOSITY |
3df5bea0 WD |
520 | if (gVerbosityLevel > 1) { |
521 | printf ("PowerSpanWrite: offset=%08x val=%02x\n", theOffset, | |
522 | theValue); | |
523 | } | |
7521af1c | 524 | #endif |
3df5bea0 WD |
525 | *ptr = theValue; |
526 | PSII_SYNC (); | |
7521af1c WD |
527 | } |
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 | */ | |
3df5bea0 WD |
534 | void 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; | |
7521af1c WD |
539 | |
540 | #ifdef VERBOSITY | |
3df5bea0 WD |
541 | if (gVerbosityLevel > 1) { |
542 | printf ("PowerSpanSetBits: offset=%08x mask=%02x\n", | |
543 | theOffset, theMask); | |
544 | } | |
7521af1c | 545 | #endif |
3df5bea0 WD |
546 | register_value = *ptr; |
547 | PSII_SYNC (); | |
7521af1c | 548 | |
3df5bea0 WD |
549 | register_value |= theMask; |
550 | *ptr = register_value; | |
551 | PSII_SYNC (); | |
7521af1c WD |
552 | } |
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 | */ | |
3df5bea0 WD |
559 | void 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; | |
7521af1c WD |
564 | |
565 | #ifdef VERBOSITY | |
3df5bea0 WD |
566 | if (gVerbosityLevel > 1) { |
567 | printf ("PowerSpanClearBits: offset=%08x mask=%02x\n", | |
568 | theOffset, theMask); | |
569 | } | |
7521af1c | 570 | #endif |
3df5bea0 WD |
571 | register_value = *ptr; |
572 | PSII_SYNC (); | |
7521af1c | 573 | |
3df5bea0 WD |
574 | register_value &= ~theMask; |
575 | *ptr = register_value; | |
576 | PSII_SYNC (); | |
7521af1c WD |
577 | } |
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 | */ | |
3df5bea0 WD |
590 | int 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; | |
596 | ||
597 | /* Make sure that the Slave Image is disabled */ | |
598 | PowerSpanClearBits ((REGS_PB_SLAVE_CSR + reg_offset), | |
599 | PB_SLAVE_CSR_IMG_EN); | |
600 | ||
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; | |
605 | } | |
606 | ||
607 | /* 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); | |
615 | ||
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); | |
619 | ||
620 | /* Enable the Slave Image */ | |
621 | PowerSpanSetBits ((REGS_PB_SLAVE_CSR + reg_offset), | |
622 | PB_SLAVE_CSR_IMG_EN); | |
623 | ||
624 | return 0; | |
7521af1c WD |
625 | } |
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 | */ | |
3df5bea0 WD |
641 | int 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; | |
649 | ||
650 | /* Make sure that the Slave Image is disabled */ | |
651 | PowerSpanClearBits ((REGS_P1_TGT_CSR + csr_reg_offset), | |
652 | PB_SLAVE_CSR_IMG_EN); | |
653 | ||
654 | /* 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 | } | |
661 | ||
662 | /* 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); | |
677 | ||
678 | PowerSpanWrite ((REGS_P1_TGT_TADDR + csr_reg_offset), | |
679 | theLocalBaseAddr); | |
680 | ||
681 | if (thePCIBaseAddr != (unsigned int) NULL) { | |
682 | PowerSpanWrite ((REGS_P1_BST + pci_reg_offset), | |
683 | thePCIBaseAddr); | |
684 | } | |
685 | ||
686 | /* Enable the Slave Image */ | |
687 | PowerSpanSetBits ((REGS_P1_TGT_CSR + csr_reg_offset), | |
688 | PB_SLAVE_CSR_IMG_EN); | |
689 | ||
690 | return 0; | |
7521af1c WD |
691 | } |
692 | ||
54841ab5 | 693 | int do_bridge (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) |
3df5bea0 WD |
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; | |
703 | ||
704 | if (argc != 8) { | |
705 | goto usage; | |
706 | } | |
707 | ||
708 | 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); | |
715 | ||
716 | ||
717 | 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 | } | |
743 | ||
744 | goto done; | |
745 | usage: | |
746 | printf ("Usage:\n%s\n", cmdtp->help); | |
747 | ||
748 | done: | |
749 | return ret_val; | |
7521af1c | 750 | } |