From: Ben Warren <bwarren@qstreams.com>
To: u-boot@lists.denx.de
Subject: [U-Boot-Users] FPGA loading question
Date: Thu, 27 Sep 2007 14:31:39 -0400 [thread overview]
Message-ID: <46FBF70B.9060605@qstreams.com> (raw)
In-Reply-To: <3972542e0709271101n4929c08bp381e7d75c3ce72e8@mail.gmail.com>
E Robertson wrote:
> On 9/27/07, Ben Warren <bwarren@qstreams.com> wrote:
>
>> E Robertson wrote:
>>
>>> On 9/27/07, Stefan Roese <sr@denx.de> wrote:
>>>
>>>
>>>> Hi Matthias,
>>>>
>>>> On Thursday 27 September 2007, Matthias Fuchs wrote:
>>>>
>>>>
>>>>> What kind of CPU are you using? Please note that 4xx U-Boot ports have
>>>>> the cache disabled. Without cache booting a Spartan 3E in SS-mode
>>>>> may take very very :-(
>>>>>
>>>>>
>>>> Only 44x have cache disabled. 40x has icache enabled.
>>>>
>>>> BTW: I'm still waiting for the patch to enable the cache on 44x systems... ;)
>>>>
>>>> Viele Gr??e,
>>>> Stefan
>>>>
>>>>
>>> I'm using an NXP ARM9 'A404 and can disable cache on my platform. Due
>>> to my hardware fool-up, I'll have to use a bit banging method.
>>> I'm also concern about loading error and recovery and I'm considering
>>> instead to do the programming in the kernel. If there is a problem for
>>> some reason and the FPGA needs to be reloaded, I'll have to do it in
>>> the kernel anyway.
>>> I'm not sure about embedding a bin file in the kernel driver either
>>> but It's worth pursuing.
>>>
>>>
>> If your design can wait until Linux is booted before programming the
>> FPGA, you have a world of possibilities available. In my designs, I
>> have a simple char driver with a 'write' method that bit-bangs the image
>> in. This way you can keep your image as a file in the file system and
>> can add whatever encryption, wrapper or whatever your heart desires. It
>> makes trying different FPGA images a breeze.
>>
>
> I'm actually in the middle of doing that with a simple char device driver.
> I have'n't got to the bit banging write part yet but I'll appreciate a
> code snip that actually parses the file for the bits. I'm assuming
> it'll be some sort of shift right for a char read increment or some
> sort of XOR operation. I haven't thought through that part yet but is
> that how is normally done?
>
>
/*** Here's my implementation. I'm sure it could be much better, but
it seems to work. Note that all the programming bits are routed through
a CPLD, that's what all the 'cpld*' function calls are for. We use this
on a Virtex II, but Spartan's probably the same. The main structure of
the write function is lifted by Rubini LDD3. I don't really have time
to genericize it for you, but please feel free to ask questions/make
suggestions for improvement. ***/
ssize_t fpga_write(struct file *filp, const char __user *buf,
size_t count, loff_t *f_pos)
{
int i,j;
unsigned char *page_ptr;
struct fpga_dev *dev = filp->private_data;
u8 index = dev->index;
u16 val;
int rc = 0;
if (!(page_ptr = (unsigned char *)__get_free_page(GFP_KERNEL)))
return -ENOMEM;
if (copy_from_user(page_ptr, buf, count))
rc = -EFAULT;
/* First page of data, we set up the programming environment */
if (*f_pos == 0) {
/* First, enable FPGA programming */
cpld_fpga_prog_enable(1);
/* Next, driver nPROG low for 300 ns */
cpld_fpga_write_prog(index, 0);
ndelay(300);
cpld_fpga_write_prog(index, 1);
i = 1000;
while (!cpld_fpga_check_init(index) && --i) {;}
if (count <= 0) {
printk(KERN_ALERT "fpga_write: timed out waiting \n");
return -EFAULT;
}
}
/* Process a byte@a time */
for (i=0;i<count;i++) {
for (j=7;j>=0;j--) {
/* Shift each bit through */
if (page_ptr[i] & (1 << j))
cpld_fpga_write_data(index, 1);
else
cpld_fpga_write_data(index, 0);
}
}
if (cpld_fpga_check_done(index) != 0) {
val = (u16)readFpgaReg(dev->virtAddr + FPGA_ADDR_REV_DBG/2);
printk(KERN_INFO "FPGA%d loaded with version 0x%02x\n",
index, val & 0xff);
}
if (page_ptr)
free_page((u32)page_ptr);
*f_pos += count;
return count;
}
/*** Here's the code from my CPLD driver, that writes the various
control bits (FPGA_DONE, FPGA_PROG, FPGA_DONE, FPGA_INIT) that are
memory mapped into a CPLD register. We have 2 FPGAs, that's what the
device index is for: ***/
u8 cpld_fpga_check_init(u8 device)
{
return (readCpldReg(device == 0 ?
&cpld_device->regs->clFpgaStat :
&cpld_device->regs->liFpgaStat)
& FPGA_INIT);
}
EXPORT_SYMBOL(cpld_fpga_check_init);
u8 cpld_fpga_check_done(u8 device)
{
return (readCpldReg(device == 0 ?
&cpld_device->regs->clFpgaStat :
&cpld_device->regs->liFpgaStat)
& FPGA_DONE);
}
EXPORT_SYMBOL(cpld_fpga_check_done);
int cpld_fpga_write_prog(u8 device, u8 enable)
{
u16 *addr = (device == 0 ?
&cpld_device->regs->clFpgaCtrl :
&cpld_device->regs->liFpgaCtrl);
writeCpldRegRaw(addr, enable ? FPGA_PROG : 0);
return 0;
}
EXPORT_SYMBOL(cpld_fpga_write_prog);
int cpld_fpga_write_clock(u8 device, u8 enable)
{
u16 *addr = (device == 0 ?
&cpld_device->regs->clFpgaCtrl :
&cpld_device->regs->liFpgaCtrl);
writeCpldReg(addr, enable ? FPGA_CLK : ~FPGA_CLK, FPGA_CLK);
return 0;
}
EXPORT_SYMBOL(cpld_fpga_write_clock);
int cpld_fpga_write_data(u8 device, u8 bit)
{
u16 *addr = (device == 0 ?
&cpld_device->regs->clFpgaCtrl :
&cpld_device->regs->liFpgaCtrl);
/* Write data & low clock together */
u16 val = bit ? FPGA_PROG | FPGA_DOUT : FPGA_PROG;
writeCpldRegRaw(addr, val);
/* Drive the clock high */
val |= FPGA_CLK;
writeCpldRegRaw(addr, val);
return 0;
}
EXPORT_SYMBOL(cpld_fpga_write_data)
regards,
Ben
prev parent reply other threads:[~2007-09-27 18:31 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-26 20:48 [U-Boot-Users] FPGA loading question E Robertson
2007-09-27 13:21 ` Matthias Fuchs
2007-09-27 15:47 ` Stefan Roese
2007-09-27 16:10 ` E Robertson
2007-09-27 17:36 ` Ben Warren
2007-09-27 18:01 ` E Robertson
2007-09-27 18:31 ` Ben Warren [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=46FBF70B.9060605@qstreams.com \
--to=bwarren@qstreams.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.