/* -*- 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 .
*/
/* 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
#include
#include //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);
}