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