blob: 8995aa23d9cb283bac27771caaa962a097cb4e00 (
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
|
/* -*- c -*- */
/*
* Copyright 2009-2011 Ettus Research LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Changes required to work for the Spartan-3A series:
* The ICAP interface on the 3A is 8 bits wide, instead of 32.
* Everything is Xilinx standard LSBit-first.
* The operations are all different.
* Commands are 16 bits long, presented to the ICAP interface 8 bits at a time.
*/
#include <xilinx_s3_icap.h>
#include <memory_map.h>
#include <spi_flash_private.h> //for READ_CMD
/* bit swap end-for-end */
static inline unsigned char
swap8(unsigned char x)
{
unsigned char r = 0;
r |= (x >> 7) & 0x01;
r |= (x >> 5) & 0x02;
r |= (x >> 3) & 0x04;
r |= (x >> 1) & 0x08;
r |= (x << 1) & 0x10;
r |= (x << 3) & 0x20;
r |= (x << 5) & 0x40;
r |= (x << 7) & 0x80;
return r;
}
void
wr_icap(uint8_t x)
{
icap_regs->icap = swap8(x);
}
uint8_t
rd_icap(void)
{
return swap8(icap_regs->icap);
}
void
icap_reload_fpga(uint32_t flash_address)
{
union {
uint32_t i;
uint8_t c[4];
} t;
t.i = flash_address;
//note! t.c[0] MUST contain the byte-wide read command for the flash device used.
//for the 25P64, and most other flash devices, this is 0x03.
t.c[0] = FAST_READ_CMD;
//TODO: look up the watchdog timer, ensure it won't fire too soon
//UG332 p279
wr_icap(0xff);
wr_icap(0xff); //dummy word, probably unnecessary
wr_icap(0xAA);
wr_icap(0x99); //sync word
wr_icap(0x32);
wr_icap(0x61); //Type 1 write General 1 (1 word)
wr_icap(t.c[2]); //bits 15-8
wr_icap(t.c[3]); //bits 7-0
wr_icap(0x32);
wr_icap(0x81); //Type 1 write General 2 (1 word)
wr_icap(t.c[0]); //C0-C8, the byte-wide read command
wr_icap(t.c[1]); //Upper 8 bits of 24-bit address
wr_icap(0x30);
wr_icap(0xA1); //Type 1 write CMD (1 word)
wr_icap(0x00);
wr_icap(0x0E); //REBOOT command
wr_icap(0x20);
wr_icap(0x00); //Type 1 NOP
wr_icap(0x20);
wr_icap(0x00);
}
|