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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox