1 /***************************************************************
2  * Project:
3  *	  CPLD SlaveSerial Configuration via embedded microprocessor.
4  *
5  * Copyright info:
6  *
7  *	  This is free software; you can redistribute it and/or modify
8  *	  it as you like.
9  *
10  *	  This program is distributed in the hope that it will be useful,
11  *	  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *	  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  *
14  * Description:
15  *
16  *      This is the main source file that will allow a microprocessor
17  *      to configure Xilinx Virtex, Virtex-E, Virtex-EM, Virtex-II,
18  *      and Spartan-II devices via the SlaveSerial Configuration Mode.
19  *      This code is discussed in Xilinx Application Note, XAPP502.
20  *
21  * History:
22  *	  3-October-2001  MN/MP  - Created
23  *	  20-August-2008  Renesas Solutions - Modified to SH7723
24  ****************************************************************/
25 
26 #include <common.h>
27 
28 /* Serial */
29 #define SCIF_BASE 0xffe00000 /* SCIF0 */
30 #define SCSMR	(vu_short *)(SCIF_BASE + 0x00)
31 #define SCBRR	(vu_char *)(SCIF_BASE + 0x04)
32 #define SCSCR	(vu_short *)(SCIF_BASE + 0x08)
33 #define SC_TDR	(vu_char *)(SCIF_BASE + 0x0C)
34 #define SC_SR	(vu_short *)(SCIF_BASE + 0x10)
35 #define SCFCR	(vu_short *)(SCIF_BASE + 0x18)
36 #define	RFCR	(vu_long *)0xFE400020
37 
38 #define SCSCR_INIT		0x0038
39 #define SCSCR_CLR		0x0000
40 #define SCFCR_INIT		0x0006
41 #define SCSMR_INIT		0x0080
42 #define RFCR_CLR		0xA400
43 #define SCI_TD_E		0x0020
44 #define SCI_TDRE_CLEAR	0x00df
45 
46 #define BPS_SETTING_VALUE	1 /* 12.5MHz */
47 #define WAIT_RFCR_COUNTER	500
48 
49 /* CPLD data size */
50 #define CPLD_DATA_SIZE	169216
51 
52 /* out */
53 #define CPLD_PFC_ADR	((vu_short *)0xA4050112)
54 
55 #define CPLD_PROG_ADR	((vu_char *)0xA4050132)
56 #define CPLD_PROG_DAT	0x80
57 
58 /* in */
59 #define CPLD_INIT_ADR	((vu_char *)0xA4050132)
60 #define CPLD_INIT_DAT	0x40
61 #define CPLD_DONE_ADR	((vu_char *)0xA4050132)
62 #define CPLD_DONE_DAT	0x20
63 
64 #define	HIZCRB			((vu_short *)0xA405015A)
65 
66 /* data */
67 #define CPLD_NOMAL_START	0xA0A80000
68 #define CPLD_SAFE_START		0xA0AC0000
69 #define MODE_SW				(vu_char *)0xA405012A
70 
71 static void init_cpld_loader(void)
72 {
73 
74 	*SCSCR = SCSCR_CLR;
75 	*SCFCR = SCFCR_INIT;
76 	*SCSMR = SCSMR_INIT;
77 
78 	*SCBRR = BPS_SETTING_VALUE;
79 
80 	*RFCR = RFCR_CLR; /* Refresh counter clear */
81 
82 	while (*RFCR < WAIT_RFCR_COUNTER)
83 		;
84 
85 	*SCFCR = 0x0; /* RTRG=00, TTRG=00 */
86 				  /* MCE=0,TFRST=0,RFRST=0,LOOP=0 */
87 	*SCSCR = SCSCR_INIT;
88 }
89 
90 static int check_write_ready(void)
91 {
92 	u16 status = *SC_SR;
93 	return status & SCI_TD_E;
94 }
95 
96 static void write_cpld_data(char ch)
97 {
98 	while (!check_write_ready())
99 		;
100 
101 	*SC_TDR = ch;
102 	*SC_SR;
103 	*SC_SR = SCI_TDRE_CLEAR;
104 }
105 
106 static int delay(void)
107 {
108 	int i;
109 	int c = 0;
110 	for (i = 0; i < 200; i++) {
111 		c = *(volatile int *)0xa0000000;
112 	}
113 	return c;
114 }
115 
116 /***********************************************************************
117  *
118  * Function:     slave_serial
119  *
120  * Description:  Initiates SlaveSerial Configuration.
121  *               Calls ShiftDataOut() to output serial data
122  *
123  ***********************************************************************/
124 static void slave_serial(void)
125 {
126 	int i;
127 	unsigned char *flash;
128 
129 	*CPLD_PROG_ADR |= CPLD_PROG_DAT; /* PROGRAM_OE HIGH */
130 	delay();
131 
132 	/*
133 	 * Toggle Program Pin by Toggling Program_OE bit
134 	 * This is accomplished by writing to the Program Register in the CPLD
135 	 *
136 	 * NOTE: The Program_OE bit should be driven high to bring the Virtex
137 	 *      Program Pin low. Likewise, it should be driven low
138 	 *      to bring the Virtex Program Pin to High-Z
139 	 */
140 
141 	*CPLD_PROG_ADR &= ~CPLD_PROG_DAT; /* PROGRAM_OE LOW */
142 	delay();
143 
144 	/*
145 	 * Bring Program High-Z
146 	 * (Drive Program_OE bit low to bring Virtex Program Pin to High-Z
147 	 */
148 
149 	/* Program_OE bit Low brings the Virtex Program Pin to High Z: */
150 	*CPLD_PROG_ADR |= CPLD_PROG_DAT; /* PROGRAM_OE HIGH */
151 
152 	while ((*CPLD_INIT_ADR & CPLD_INIT_DAT) == 0)
153 		delay();
154 
155 	/* Begin Slave-Serial Configuration */
156 	flash = (unsigned char *)CPLD_NOMAL_START;
157 
158 	for (i = 0; i < CPLD_DATA_SIZE; i++)
159 		write_cpld_data(*flash++);
160 }
161 
162 /***********************************************************************
163  *
164  * Function: check_done_bit
165  *
166  * Description: This function takes monitors the CPLD Input Register
167  * 		   by checking the status of the DONE bit in that Register.
168  *               By doing so, it monitors the Xilinx Virtex device's DONE
169  *               Pin to see if configuration bitstream has been properly
170  *               loaded
171  *
172  ***********************************************************************/
173 static void check_done_bit(void)
174 {
175 	while (!(*CPLD_DONE_ADR & CPLD_DONE_DAT))
176 		;
177 }
178 
179 /***********************************************************************
180  *
181  * Function: init_cpld
182  *
183  * Description: Begins Slave Serial configuration of Xilinx FPGA
184  *
185  ***********************************************************************/
186 void init_cpld(void)
187 {
188 	/* Init serial device */
189 	init_cpld_loader();
190 
191 	if (*CPLD_DONE_ADR & CPLD_DONE_DAT)	/* Already DONE */
192 		return;
193 
194 	*HIZCRB = 0x0000;
195 	*CPLD_PFC_ADR = 0x7c00;			/* FPGA PROG = OUTPUT */
196 
197 	/* write CPLD data from NOR flash to device */
198 	slave_serial();
199 
200 	/*
201 	 * Monitor the DONE bit in the CPLD Input Register to see if
202 	 * configuration successful
203 	 */
204 
205 	check_done_bit();
206 }
207