This is the mail archive of the
ecos-discuss@sources.redhat.com
mailing list for the eCos project.
Re: 80312 hal support for Intel XScale board
- To: Mark Salter <msalter at redhat dot com>,rich at accetnetwork dot com
- Subject: Re: [ECOS] 80312 hal support for Intel XScale board
- From: Richard Wicks <rich at accetnetwork dot com>
- Date: Tue, 16 Oct 2001 10:26:38 -0700
- Cc: ecos-discuss at sourceware dot cygnus dot com
- Organization: Accet Networks
- References: <01101512571000.04289@localhost.localdomain> <200110161201.f9GC1PU04637@deneb.localdomain>
- Reply-To: rich at accetnetwork dot com
On Tuesday 16 October 2001 05:01 am, Mark Salter wrote:
> >>>>> Richard Wicks writes:
> >
> > Hello,
> > I think I've found some bugs with the hal support with the Intel XScale
> > board.
>
> ...
>
> > According to the documentation* of the 80312 chip, in section 6.8.5 this
> > UNmasks the interrupt rather than masking it. There is a similar problem
> > with hal_interrupt_unmask. In fact, I think nearly all calls to
> > hal_interrupt_mask() actually unmask the interrupt and nearly all calls
> > to hal_interrupt_unmask() actually mask the interrupt.
>
> Looks like you're right. The only interrupts that we've tested are the
> ethernet and serial.
>
> --Mark
Hello and thanks for the quick confirmation.
I didn't mention it before but there may be other bugs. I get an
"Uncorrectable error during RMW" in
${ECOS_REPOSITORY}/hal/arm/iq80310/current/src/iq80310_misc.c
on (or near) line 422.
This is odd, or perhaps impossible since writing to a doorbell shouldn't do
anything like this. I'm wondering if the interrupt stack is overflowing?
I'm just starting to get into the guts of the interrupt now, but I thought
I'd warn you about it.
For your convenience, I've included a small piece of C code you can use to
send a doorbell interrupt to the XScale board. It's a Linux module that maps
the ATU and then sends a doorbell interrupt on the FIQ# line to the 80200
processor.
Thanks,
-Rich
#define MODULE
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#define VENDOR_ID 0x8086
#define DEVICE_ID 0x530d
#define OFFSET 0x000
#define MAX_TO_DUMP 0x200
#if (0)
#define SWAP_LONG(l) \
( ((l & 0x000000FF) << (8*3)) |\
((l & 0x0000FF00) << (8*1)) |\
((l & 0x00FF0000) >> (8*1)) |\
((l & 0xFF000000) >> (8*3)))
#else
#define SWAP_LONG(l) (l)
#endif
#define IDR_ADDR ((unsigned int)vPtr + 0x20)
#define IISR_ADDR ((unsigned int)vPtr + 0x24)
#define IIMR_ADDR ((unsigned int)vPtr + 0x28)
#define ODR_ADDR ((unsigned int)vPtr + 0x2C)
#define IISR_ADDR ((unsigned int)vPtr + 0x30)
#define OIMR_ADDR ((unsigned int)vPtr + 0x34)
static void
*vPtr=NULL;
int init_module (void)
{
int
iDevsFound = 0;
struct pci_dev
*pPciDev = NULL;
printk ("RBW: init module\n");
while ((pPciDev = pci_find_device (VENDOR_ID, DEVICE_ID, pPciDev)) != NULL)
{
vPtr = ioremap (pci_resource_start(pPciDev,0),
pci_resource_len(pPciDev, 0));
if (vPtr != NULL)
{
int
iIterator;
for (iIterator = 0 ; iIterator < 0x200 ; iIterator += 2)
{
unsigned short
us1,
us2;
pci_read_config_word (pPciDev, iIterator, &us1);
pci_read_config_word (pPciDev, iIterator+0x100, &us2);
printk ("%02x:%04x:%04x\n",iIterator/4,us1,us2);
}
printk ("Remapped memory to %08x\n",(unsigned int)vPtr);
printk ("Dump of %d bytes to follow\n",MAX_TO_DUMP);
// dump a block of memory to verify ATU pci bridge is working
for (iIterator = 0 ; iIterator < MAX_TO_DUMP ; iIterator+=4)
{
if ((iIterator % 16) == 0)
{
printk ("\n%08x :: ",(unsigned int)vPtr + OFFSET + 0 + iIterator);
}
printk ("%08x ",
SWAP_LONG (readl((unsigned int)vPtr + OFFSET + 0 + iIterator)));
}
printk ("\n");
// dump message registers to verify that is working
printk ("IIMR = %08x\n",readl(IIMR_ADDR));
printk ("IDR = %08x\n",readl(IDR_ADDR));
printk ("IISR = %08x\n",readl(IISR_ADDR));
// send a doorbell interrupt
writel (0x00000004,IDR_ADDR); //FIQ#
//writel (0x80000000,IDR_ADDR); //IRQ#
printk ("---------------\n");
// read the resulting message registers
printk ("IIMR = %08x\n",readl(IIMR_ADDR));
// the IDR may or may not be the value we just wrote - there is
// a race condition since the 80200 can handle the interrupt
// and clear the register. chances are the interrupt handler
// isn't that fast though.
printk ("IDR = %08x\n",readl(IDR_ADDR));
printk ("IISR = %08x\n",readl(IISR_ADDR));
}
else
{
printk ("Unable to map memory\n");
}
iDevsFound++;
// only deal with one device for now. Note that vPtr will be
// overwritten if this break isn't here and there are multiple
// devices in the system
break;
}
printk("Found %d devices of %04x:%04x\n",iDevsFound,VENDOR_ID,DEVICE_ID);
return 0;
}
void cleanup_module (void)
{
printk ("RBW: cleanup module\n");
// unmap the memory
if (vPtr != NULL)
{
iounmap (vPtr);
}
}