This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: 80312 hal support for Intel XScale board


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);
  }
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]