blob: aba11d5a7568beea4d860b4224c0170fdfaa95cb [file] [log] [blame]
wdenkb6e4c402004-01-02 16:05:07 +00001/*
2 * (C) Copyright 2001
3 * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 *
23 * Adapted for PATI
24 */
25
26#include <common.h>
27#include <command.h>
28#define PLX9056_LOC
29#include "plx9056.h"
30#include "pati.h"
31#include "pci_eeprom.h"
32
33extern void show_pld_regs(void);
Wolfgang Denk54841ab2010-06-28 22:00:46 +020034extern int do_mplcommon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
wdenkb6e4c402004-01-02 16:05:07 +000035
36extern void user_led0(int led_on);
37extern void user_led1(int led_on);
38
39/* ------------------------------------------------------------------------- */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020040#if defined(CONFIG_SYS_PCI_CON_DEVICE)
wdenkb6e4c402004-01-02 16:05:07 +000041extern void pci_con_disc(void);
42extern void pci_con_connect(void);
43#endif
44
45/******************************************************************************
46 * Eeprom Support
47 ******************************************************************************/
48unsigned long get32(unsigned long addr)
49{
50 unsigned long *p=(unsigned long *)addr;
51 return *p;
52}
53
54void set32(unsigned long addr,unsigned long data)
55{
56 unsigned long *p=(unsigned long *)addr;
57 *p=data;
58}
59
60#define PCICFG_GET_REG(x) (get32((x) + PCI_CONFIG_BASE))
61#define PCICFG_SET_REG(x,y) (set32((x) + PCI_CONFIG_BASE,(y)))
62
63
64/******************************************************************************
65 * reload_pci_eeprom
66 ******************************************************************************/
67
68static void reload_pci_eeprom(void)
69{
70 unsigned long reg;
71 /* Set Bit 29 and clear it again */
72 reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT);
73 udelay(1);
74 /* set it*/
75 reg|=(1<<29);
76 PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg);
77 /* EECLK @ 33MHz = 125kHz
78 * -> extra long load = 32 * 16bit = 512Bit @ 125kHz = 4.1msec
79 * use 20msec
80 */
81 udelay(20000); /* wait 20ms */
82 reg &= ~(1<<29); /* set it low */
83 PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg);
84 udelay(1); /* wait some time */
85}
86
87/******************************************************************************
88 * clock_pci_eeprom
89 ******************************************************************************/
90
91static void clock_pci_eeprom(void)
92{
93 unsigned long reg;
94 /* clock is low, data is valid */
95 reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT);
96 udelay(1);
97 /* set clck high */
98 reg|=(1<<24);
99 PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg);
100 udelay(1); /* wait some time */
101 reg &= ~(1<<24); /* set clock low */
102 PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg);
103 udelay(1); /* wait some time */
104}
105
106/******************************************************************************
107 * send_pci_eeprom_cmd
108 ******************************************************************************/
109static void send_pci_eeprom_cmd(unsigned long cmd, unsigned char len)
110{
111 unsigned long reg;
112 int i;
113 reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT);
114 /* Clear all EEPROM bits */
115 reg &= ~(0xF << 24);
116 /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */
117 PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg);
118 udelay(1); /* wait some time */
119 /* Enable EEPROM Chip Select */
120 reg |= (1 << 25);
121 PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg);
122 /* Send EEPROM command - one bit at a time */
123 for (i = (int)(len-1); i >= 0; i--) {
124 /* Check if current bit is 0 or 1 */
125 if (cmd & (1 << i))
126 PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,(reg | (1<<26)));
127 else
128 PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg);
129 clock_pci_eeprom();
130 }
131}
132
133/******************************************************************************
134 * write_pci_eeprom_offs
135 ******************************************************************************/
136static void write_pci_eeprom_offs(unsigned short offset, unsigned short value)
137{
138 unsigned long reg;
139 int bitpos, cmdshft, cmdlen, timeout;
140 /* we're using the Eeprom 93CS66 */
141 cmdshft = 2;
142 cmdlen = EE66_CMD_LEN;
143 /* Send Write_Enable command to EEPROM */
144 send_pci_eeprom_cmd((EE_WREN << cmdshft),cmdlen);
145 /* Send EEPROM Write command and offset to EEPROM */
146 send_pci_eeprom_cmd((EE_WRITE << cmdshft) | (offset / 2),cmdlen);
147 reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT);
148 /* Clear all EEPROM bits */
149 reg &= ~(0xF << 24);
150 /* Make sure EEDO Input is disabled for some PLX chips */
151 reg &= ~(1 << 31);
152 /* Enable EEPROM Chip Select */
153 reg |= (1 << 25);
154 /* Write 16-bit value to EEPROM - one bit at a time */
155 for (bitpos = 15; bitpos >= 0; bitpos--) {
156 /* Get bit value and shift into result */
157 if (value & (1 << bitpos))
158 PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,(reg | (1<<26)));
159 else
160 PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg );
161 clock_pci_eeprom();
162 } /* for */
163 /* Deselect Chip */
164 PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg & ~(1 << 25));
165 /* Re-select Chip */
166 PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg | (1 << 25));
167 /* A small delay is needed to let EEPROM complete */
168 timeout = 0;
169 do {
170 udelay(10);
171 reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT);
172 timeout++;
173 } while (((reg & (1 << 27)) == 0) && timeout < 20000);
174 /* Send Write_Disable command to EEPROM */
175 send_pci_eeprom_cmd((EE_WDS << cmdshft),cmdlen);
176 /* Clear Chip Select and all other EEPROM bits */
177 PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg & ~(0xF << 24));
178}
179
180
181/******************************************************************************
182 * read_pci_eeprom_offs
183 ******************************************************************************/
184static void read_pci_eeprom_offs(unsigned short offset, unsigned short *pvalue)
185{
186 unsigned long reg;
187 int bitpos, cmdshft, cmdlen;
188 /* we're using the Eeprom 93CS66 */
189 cmdshft = 2;
190 cmdlen = EE66_CMD_LEN;
191 /* Send EEPROM read command and offset to EEPROM */
192 send_pci_eeprom_cmd((EE_READ << cmdshft) | (offset / 2),cmdlen);
193 /* Set EEPROM write output bit */
194 reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT);
195 /* Set EEDO Input enable */
196 reg |= (1 << 31);
197 PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg | (1 << 26));
198 /* Get 16-bit value from EEPROM - one bit at a time */
199 for (bitpos = 0; bitpos < 16; bitpos++) {
200 clock_pci_eeprom();
201 udelay(10);
202 reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT);
203 /* Get bit value and shift into result */
204 if (reg & (1 << 27))
205 *pvalue = (unsigned short)((*pvalue << 1) | 1);
206 else
207 *pvalue = (unsigned short)(*pvalue << 1);
208 }
209 /* Clear EEDO Input enable */
210 reg &= ~(1 << 31);
211 /* Clear Chip Select and all other EEPROM bits */
212 PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg & ~(0xF << 24));
213}
214
215
216/******************************************************************************
217 * EEPROM read/writes
218******************************************************************************/
219
220#undef EEPROM_DBG
221static int pati_pci_eeprom_erase(void)
222{
223 int i;
224 printf("Erasing EEPROM ");
225 for( i=0; i < PATI_EEPROM_LAST_OFFSET; i+=2) {
226 write_pci_eeprom_offs(i,0xffff);
227 if((i%0x10))
228 printf(".");
229 }
230 printf("\nDone\n");
231 return 0;
232}
233
234static int pati_pci_eeprom_prg(void)
235{
236 int i;
237 i=0;
238 printf("Programming EEPROM ");
239 while(pati_eeprom[i].offset<0xffff) {
240 write_pci_eeprom_offs(pati_eeprom[i].offset,pati_eeprom[i].value);
241 #ifdef EEPROM_DBG
242 printf("0x%04X: 0x%04X\n",pati_eeprom[i].offset, pati_eeprom[i].value);
243 #else
244 if((i%0x10))
245 printf(".");
246 #endif
247 i++;
248 }
249 printf("\nDone\n");
250 return 0;
251}
252
253static int pati_pci_eeprom_write(unsigned short offset, unsigned long addr, unsigned short size)
254{
255 int i;
256 unsigned short value;
257 unsigned short *buffer =(unsigned short *)addr;
258 if((offset + size) > PATI_EEPROM_LAST_OFFSET) {
259 size = PATI_EEPROM_LAST_OFFSET - offset;
260 }
261 printf("Write To EEPROM from 0x%lX to 0x%X 0x%X words\n", addr, offset, size/2);
262 for( i = offset; i< (offset + size); i+=2) {
263 value = *buffer++;
264 write_pci_eeprom_offs(i,value);
265 #ifdef EEPROM_DBG
266 printf("0x%04X: 0x%04X\n",i, value);
267 #else
268 if((i%0x10))
269 printf(".");
270 #endif
271 }
272 printf("\nDone\n");
273 return 0;
274}
275
276static int pati_pci_eeprom_read(unsigned short offset, unsigned long addr, unsigned short size)
277{
278 int i;
Wolfgang Denkd39041f2009-07-19 01:15:52 +0200279 unsigned short value = 0;
wdenkb6e4c402004-01-02 16:05:07 +0000280 unsigned short *buffer =(unsigned short *)addr;
281 if((offset + size) > PATI_EEPROM_LAST_OFFSET) {
282 size = PATI_EEPROM_LAST_OFFSET - offset;
283 }
284 printf("Read from EEPROM from 0x%X to 0x%lX 0x%X words\n", offset, addr, size/2);
285 for( i = offset; i< (offset + size); i+=2) {
286 read_pci_eeprom_offs(i,&value);
287 *buffer++=value;
288 #ifdef EEPROM_DBG
289 printf("0x%04X: 0x%04X\n",i, value);
290 #else
291 if((i%0x10))
292 printf(".");
293 #endif
294 }
295 printf("\nDone\n");
296 return 0;
297}
298
wdenkb6e4c402004-01-02 16:05:07 +0000299/******************************************************************************
300 * PCI Bridge Registers Dump
301*******************************************************************************/
302static void display_pci_regs(void)
303{
304 printf(" PCI9056_SPACE0_RANGE %08lX\n",PCICFG_GET_REG(PCI9056_SPACE0_RANGE));
305 printf(" PCI9056_SPACE0_REMAP %08lX\n",PCICFG_GET_REG(PCI9056_SPACE0_REMAP));
306 printf(" PCI9056_LOCAL_DMA_ARBIT %08lX\n",PCICFG_GET_REG(PCI9056_LOCAL_DMA_ARBIT));
307 printf(" PCI9056_ENDIAN_DESC %08lX\n",PCICFG_GET_REG(PCI9056_ENDIAN_DESC));
308 printf(" PCI9056_EXP_ROM_RANGE %08lX\n",PCICFG_GET_REG(PCI9056_EXP_ROM_RANGE));
309 printf(" PCI9056_EXP_ROM_REMAP %08lX\n",PCICFG_GET_REG(PCI9056_EXP_ROM_REMAP));
310 printf(" PCI9056_SPACE0_ROM_DESC %08lX\n",PCICFG_GET_REG(PCI9056_SPACE0_ROM_DESC));
311 printf(" PCI9056_DM_RANGE %08lX\n",PCICFG_GET_REG(PCI9056_DM_RANGE));
312 printf(" PCI9056_DM_MEM_BASE %08lX\n",PCICFG_GET_REG(PCI9056_DM_MEM_BASE));
313 printf(" PCI9056_DM_IO_BASE %08lX\n",PCICFG_GET_REG(PCI9056_DM_IO_BASE));
314 printf(" PCI9056_DM_PCI_MEM_REMAP %08lX\n",PCICFG_GET_REG(PCI9056_DM_PCI_MEM_REMAP));
315 printf(" PCI9056_DM_PCI_IO_CONFIG %08lX\n",PCICFG_GET_REG(PCI9056_DM_PCI_IO_CONFIG));
316 printf(" PCI9056_SPACE1_RANGE %08lX\n",PCICFG_GET_REG(PCI9056_SPACE1_RANGE));
317 printf(" PCI9056_SPACE1_REMAP %08lX\n",PCICFG_GET_REG(PCI9056_SPACE1_REMAP));
318 printf(" PCI9056_SPACE1_DESC %08lX\n",PCICFG_GET_REG(PCI9056_SPACE1_DESC));
319 printf(" PCI9056_DM_DAC %08lX\n",PCICFG_GET_REG(PCI9056_DM_DAC));
320 printf(" PCI9056_MAILBOX0 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX0));
321 printf(" PCI9056_MAILBOX1 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX1));
322 printf(" PCI9056_MAILBOX2 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX2));
323 printf(" PCI9056_MAILBOX3 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX3));
324 printf(" PCI9056_MAILBOX4 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX4));
325 printf(" PCI9056_MAILBOX5 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX5));
326 printf(" PCI9056_MAILBOX6 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX6));
327 printf(" PCI9056_MAILBOX7 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX7));
328 printf(" PCI9056_PCI_TO_LOC_DBELL %08lX\n",PCICFG_GET_REG(PCI9056_PCI_TO_LOC_DBELL));
329 printf(" PCI9056_LOC_TO_PCI_DBELL %08lX\n",PCICFG_GET_REG(PCI9056_LOC_TO_PCI_DBELL));
330 printf(" PCI9056_INT_CTRL_STAT %08lX\n",PCICFG_GET_REG(PCI9056_INT_CTRL_STAT));
331 printf(" PCI9056_EEPROM_CTRL_STAT %08lX\n",PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT));
332 printf(" PCI9056_PERM_VENDOR_ID %08lX\n",PCICFG_GET_REG(PCI9056_PERM_VENDOR_ID));
333 printf(" PCI9056_REVISION_ID %08lX\n",PCICFG_GET_REG(PCI9056_REVISION_ID));
334 printf(" \n");
335 printf(" PCI9056_VENDOR_ID %08lX\n",PCICFG_GET_REG(PCI9056_VENDOR_ID));
336 printf(" PCI9056_COMMAND %08lX\n",PCICFG_GET_REG(PCI9056_COMMAND));
337 printf(" PCI9056_REVISION %08lX\n",PCICFG_GET_REG(PCI9056_REVISION));
338 printf(" PCI9056_CACHE_SIZE %08lX\n",PCICFG_GET_REG(PCI9056_CACHE_SIZE));
339 printf(" PCI9056_RTR_BASE %08lX\n",PCICFG_GET_REG(PCI9056_RTR_BASE));
340 printf(" PCI9056_RTR_IO_BASE %08lX\n",PCICFG_GET_REG(PCI9056_RTR_IO_BASE));
341 printf(" PCI9056_LOCAL_BASE0 %08lX\n",PCICFG_GET_REG(PCI9056_LOCAL_BASE0));
342 printf(" PCI9056_LOCAL_BASE1 %08lX\n",PCICFG_GET_REG(PCI9056_LOCAL_BASE1));
343 printf(" PCI9056_UNUSED_BASE1 %08lX\n",PCICFG_GET_REG(PCI9056_UNUSED_BASE1));
344 printf(" PCI9056_UNUSED_BASE2 %08lX\n",PCICFG_GET_REG(PCI9056_UNUSED_BASE2));
345 printf(" PCI9056_CIS_PTR %08lX\n",PCICFG_GET_REG(PCI9056_CIS_PTR));
346 printf(" PCI9056_SUB_ID %08lX\n",PCICFG_GET_REG(PCI9056_SUB_ID));
347 printf(" PCI9056_EXP_ROM_BASE %08lX\n",PCICFG_GET_REG(PCI9056_EXP_ROM_BASE));
348 printf(" PCI9056_CAP_PTR %08lX\n",PCICFG_GET_REG(PCI9056_CAP_PTR));
349 printf(" PCI9056_INT_LINE %08lX\n",PCICFG_GET_REG(PCI9056_INT_LINE));
350 printf(" PCI9056_PM_CAP_ID %08lX\n",PCICFG_GET_REG(PCI9056_PM_CAP_ID));
351 printf(" PCI9056_PM_CSR %08lX\n",PCICFG_GET_REG(PCI9056_PM_CSR));
352 printf(" PCI9056_HS_CAP_ID %08lX\n",PCICFG_GET_REG(PCI9056_HS_CAP_ID));
353 printf(" PCI9056_VPD_CAP_ID %08lX\n",PCICFG_GET_REG(PCI9056_VPD_CAP_ID));
354 printf(" PCI9056_VPD_DATA %08lX\n",PCICFG_GET_REG(PCI9056_VPD_DATA));
355}
356
357
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200358int do_pati(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
wdenkb6e4c402004-01-02 16:05:07 +0000359{
360 if (strcmp(argv[1], "info") == 0)
361 {
362 show_pld_regs();
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200363 return 0;
wdenkb6e4c402004-01-02 16:05:07 +0000364 }
365 if (strcmp(argv[1], "pci") == 0)
366 {
367 display_pci_regs();
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200368 return 0;
wdenkb6e4c402004-01-02 16:05:07 +0000369 }
370 if (strcmp(argv[1], "led") == 0)
371 {
372 int led_nr,led_on;
373 led_nr = (int)simple_strtoul(argv[2], NULL, 10);
374 led_on = (int)simple_strtoul(argv[3], NULL, 10);
375 if(!led_nr)
376 user_led0(led_on);
377 else
378 user_led1(led_on);
379 return 0;
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200380 }
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200381#if defined(CONFIG_SYS_PCI_CON_DEVICE)
wdenkb6e4c402004-01-02 16:05:07 +0000382 if (strcmp(argv[1], "con") == 0) {
383 pci_con_connect();
384 return 0;
385 }
386 if (strcmp(argv[1], "disc") == 0) {
387 pci_con_disc();
388 return 0;
389 }
390#endif
391 if (strcmp(argv[1], "eeprom") == 0) {
392 unsigned long addr;
393 int size, offset;
394 offset = 0;
395 size = PATI_EEPROM_LAST_OFFSET;
396 if(argc>2) {
397 if(argc>3) {
398 addr = simple_strtoul(argv[3], NULL, 16);
399 if(argc>4)
400 offset = (int) simple_strtoul(argv[4], NULL, 16);
401 if(argc>5)
402 size = (int) simple_strtoul(argv[5], NULL, 16);
403 if (strcmp(argv[2], "read") == 0) {
404 return (pati_pci_eeprom_read(offset, addr, size));
405 }
406 if (strcmp(argv[2], "write") == 0) {
407 return (pati_pci_eeprom_write(offset, addr, size));
408 }
409 }
410 if (strcmp(argv[2], "prg") == 0) {
411 return (pati_pci_eeprom_prg());
412 }
413 if (strcmp(argv[2], "era") == 0) {
414 return (pati_pci_eeprom_erase());
415 }
416 if (strcmp(argv[2], "reload") == 0) {
417 reload_pci_eeprom();
418 return 0;
419 }
420
421
422 }
423 }
424
425 return (do_mplcommon(cmdtp, flag, argc, argv));
426}
427
428U_BOOT_CMD(
429 pati, 8, 1, do_pati,
Peter Tyser2fb26042009-01-27 18:03:12 -0600430 "PATI specific Cmds",
wdenkb6e4c402004-01-02 16:05:07 +0000431 "info - displays board information\n"
432 "pati pci - displays PCI registers\n"
433 "pati led <nr> <on> \n"
434 " - switch LED <nr> <on>\n"
435 "pati flash mem [SrcAddr]\n"
436 " - updates U-Boot with image in memory\n"
437 "pati eeprom <cmd> - PCI EEPROM sub-system\n"
438 " read <addr> <offset> <size>\n"
439 " - read PCI EEPROM to <addr> from <offset> <size> words\n"
440 " write <addr> <offset> <size>\n"
441 " - write PCI EEPROM from <addr> to <offset> <size> words\n"
442 " prg - programm PCI EEPROM with default values\n"
443 " era - erase PCI EEPROM (write all word to 0xffff)\n"
444 " reload- Reload PCI Bridge with EEPROM Values\n"
445 " NOTE: <addr> must start on word boundary\n"
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200446 " <offset> and <size> must be even byte values"
wdenkb6e4c402004-01-02 16:05:07 +0000447);
448
449/* ------------------------------------------------------------------------- */