summaryrefslogtreecommitdiffstats
path: root/board/ap325rxa/cpld-ap325rxa.c
blob: 16fadcbca780e33b76fd40d500ed6ae76668c5ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/***************************************************************
 * Project:
 *	  CPLD SlaveSerial Configuration via embedded microprocessor.
 *
 * Copyright info:
 *
 *	  This is free software; you can redistribute it and/or modify
 *	  it as you like.
 *
 *	  This program is distributed in the hope that it will be useful,
 *	  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Description:
 *
 *      This is the main source file that will allow a microprocessor
 *      to configure Xilinx Virtex, Virtex-E, Virtex-EM, Virtex-II,
 *      and Spartan-II devices via the SlaveSerial Configuration Mode.
 *      This code is discussed in Xilinx Application Note, XAPP502.
 *
 * History:
 *	  3-October-2001  MN/MP  - Created
 *	  20-August-2008  Renesas Solutions - Modified to SH7723
 ****************************************************************/

#include <common.h>

/* Serial */
#define SCIF_BASE 0xffe00000 /* SCIF0 */
#define SCSMR	(vu_short *)(SCIF_BASE + 0x00)
#define SCBRR	(vu_char *)(SCIF_BASE + 0x04)
#define SCSCR	(vu_short *)(SCIF_BASE + 0x08)
#define SC_TDR	(vu_char *)(SCIF_BASE + 0x0C)
#define SC_SR	(vu_short *)(SCIF_BASE + 0x10)
#define SCFCR	(vu_short *)(SCIF_BASE + 0x18)
#define	RFCR	(vu_long *)0xFE400020

#define SCSCR_INIT		0x0038
#define SCSCR_CLR		0x0000
#define SCFCR_INIT		0x0006
#define SCSMR_INIT		0x0080
#define RFCR_CLR		0xA400
#define SCI_TD_E		0x0020
#define SCI_TDRE_CLEAR	0x00df

#define BPS_SETTING_VALUE	1 /* 12.5MHz */
#define WAIT_RFCR_COUNTER	500

/* CPLD data size */
#define CPLD_DATA_SIZE	169216

/* out */
#define CPLD_PFC_ADR	((vu_short *)0xA4050112)

#define CPLD_PROG_ADR	((vu_char *)0xA4050132)
#define CPLD_PROG_DAT	0x80

/* in */
#define CPLD_INIT_ADR	((vu_char *)0xA4050132)
#define CPLD_INIT_DAT	0x40
#define CPLD_DONE_ADR	((vu_char *)0xA4050132)
#define CPLD_DONE_DAT	0x20

#define	HIZCRB			((vu_short *)0xA405015A)

/* data */
#define CPLD_NOMAL_START	0xA0A80000
#define CPLD_SAFE_START		0xA0AC0000
#define MODE_SW				(vu_char *)0xA405012A

static void init_cpld_loader(void)
{

	*SCSCR = SCSCR_CLR;
	*SCFCR = SCFCR_INIT;
	*SCSMR = SCSMR_INIT;

	*SCBRR = BPS_SETTING_VALUE;

	*RFCR = RFCR_CLR; /* Refresh counter clear */

	while (*RFCR < WAIT_RFCR_COUNTER)
		;

	*SCFCR = 0x0; /* RTRG=00, TTRG=00 */
				  /* MCE=0,TFRST=0,RFRST=0,LOOP=0 */
	*SCSCR = SCSCR_INIT;
}

static int check_write_ready(void)
{
	u16 status = *SC_SR;
	return status & SCI_TD_E;
}

static void write_cpld_data(char ch)
{
	while (!check_write_ready())
		;

	*SC_TDR = ch;
	*SC_SR;
	*SC_SR = SCI_TDRE_CLEAR;
}

static int delay(void)
{
	int i;
	int c = 0;
	for (i = 0; i < 200; i++) {
		c = *(volatile int *)0xa0000000;
	}
	return c;
}

/***********************************************************************
 *
 * Function:     slave_serial
 *
 * Description:  Initiates SlaveSerial Configuration.
 *               Calls ShiftDataOut() to output serial data
 *
 ***********************************************************************/
static void slave_serial(void)
{
	int i;
	unsigned char *flash;

	*CPLD_PROG_ADR |= CPLD_PROG_DAT; /* PROGRAM_OE HIGH */
	delay();

	/*
	 * Toggle Program Pin by Toggling Program_OE bit
	 * This is accomplished by writing to the Program Register in the CPLD
	 *
	 * NOTE: The Program_OE bit should be driven high to bring the Virtex
	 *      Program Pin low. Likewise, it should be driven low
	 *      to bring the Virtex Program Pin to High-Z
	 */

	*CPLD_PROG_ADR &= ~CPLD_PROG_DAT; /* PROGRAM_OE LOW */
	delay();

	/*
	 * Bring Program High-Z
	 * (Drive Program_OE bit low to bring Virtex Program Pin to High-Z
	 */

	/* Program_OE bit Low brings the Virtex Program Pin to High Z: */
	*CPLD_PROG_ADR |= CPLD_PROG_DAT; /* PROGRAM_OE HIGH */

	while ((*CPLD_INIT_ADR & CPLD_INIT_DAT) == 0)
		delay();

	/* Begin Slave-Serial Configuration */
	flash = (unsigned char *)CPLD_NOMAL_START;

	for (i = 0; i < CPLD_DATA_SIZE; i++)
		write_cpld_data(*flash++);
}

/***********************************************************************
 *
 * Function: check_done_bit
 *
 * Description: This function takes monitors the CPLD Input Register
 * 		   by checking the status of the DONE bit in that Register.
 *               By doing so, it monitors the Xilinx Virtex device's DONE
 *               Pin to see if configuration bitstream has been properly
 *               loaded
 *
 ***********************************************************************/
static void check_done_bit(void)
{
	while (!(*CPLD_DONE_ADR & CPLD_DONE_DAT))
		;
}

/***********************************************************************
 *
 * Function: init_cpld
 *
 * Description: Begins Slave Serial configuration of Xilinx FPGA
 *
 ***********************************************************************/
void init_cpld(void)
{
	/* Init serial device */
	init_cpld_loader();

	if (*CPLD_DONE_ADR & CPLD_DONE_DAT)	/* Already DONE */
		return;

	*HIZCRB = 0x0000;
	*CPLD_PFC_ADR = 0x7c00;			/* FPGA PROG = OUTPUT */

	/* write CPLD data from NOR flash to device */
	slave_serial();

	/*
	 * Monitor the DONE bit in the CPLD Input Register to see if
	 * configuration successful
	 */

	check_done_bit();
}