Atmel website | ARM Community | AVR freaks | Technical Support
Banner
 FAQ •  Search •  Register •  Login 

All times are UTC + 1 hour [ DST ]




Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: SPI Interrupt called Mask is 0 and Status is all 1
PostPosted: Wed Mar 30, 2011 12:08 am 
Offline

Joined: Thu Feb 24, 2011 5:26 pm
Posts: 11
I'm writing a SPI Slave kernel module for the at91sam9g20 that will respond to NSSR and RDRF interrupts. The problem I'm having is after I have configured the SPI port, assigned an Interrupt Service Routine and enable the port, my Service Routine gets called constantly. When checking the Interrupt Mask and Status Register I get: IMR = 0x0 and SR = 0x103FB. As soon as I leave the ISR it is called again. I have tried reading the SR during the open function but it always is set to 0x103FB even when no SPI traffic occurs.

static irqreturn_t spi_slave_isr (int irq, void *dev_id)
{
struct spi_slave_dev *dev = dev_id;
u16 val;
u32 status, pending, imr;
int ret = IRQ_NONE;

spi_writel(dev, IDR, SPI_BIT(RDRF));
spi_writel(dev, PTCR, SPI_BIT(RXTDIS));

imr = spi_readl(dev, IMR);
status = spi_readl(dev, SR);
pending = status & imr;

val = spi_readl(dev, RDR) & 0xFFFF;

CDBG("imr (0x%X) sr(0x%X) val(0x%X)\n", imr, status, val);

if (pending & SPI_BIT(RDRF))
ret = IRQ_HANDLED;

sr = spi_readl(dev, SR);

spi_writel(dev, IER, SPI_BIT(RDRF) | SPI_BIT(NSSR));
spi_writel(dev, PTCR, SPI_BIT(RXTEN));

return ret;
}

My setup of the Port / IRQ:
static int spi_slave_open (struct inode *inode, struct file *filp)
{
u32 mr, csr;
int ret;
struct spi_slave_dev *dev;

/* Find Device */
dev = container_of(inode->i_cdev, struct spi_slave_dev, cdev);

dev->regs = ioremap_wc(AT91C_BASE_SPI1, 0x4000);
if (!dev->regs)
{
printk(KERN_INFO "Failed ioremap_wc\n");
return -ENOMEM;
}
/* Disable SPI */
spi_writel(dev, CR, SPI_BIT(SPIDIS));

/* Setup ISR */
ret = request_irq(AT91C_ID_SPI1), // IRQ Number
spi_slave_isr, // ISR
0, // Flags
"spi_slave", // /proc/interrupts
dev);

if (ret)
{
printk(KERN_INFO "SPI Slave Unable to register IRQ\n");
return ret;
}

/* Execute software reset twice per Atmel's AT91Lib*/
spi_writel(dev, CR, SPI_BIT(SWRST));
spi_writel(dev, CR, SPI_BIT(SWRST));

/* Configure MR */
spi_writel(dev, MR, (SPI_BIT(MODFDIS)));

/* Configure PTCR */
spi_writel(dev, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));

/* Configure CS */
spi_writel(dev, CSR0, (SPI_BIT(CPOL) | SPI_BF(BITS, 0)));

/* Clearing everything else */
spi_writel(dev, TDR, 0x00BC);
spi_readl(dev, RDR);

/* Enable SPI */
spi_writel(dev, CR, SPI_BIT(SPIEN));

/* Enable IER & PTCR */
spi_writel(dev, IER, SPI_BIT(RDRF) | SPI_BIT(NSSR));
spi_writel(dev, PTCR, SPI_BIT(RXTEN));

filp->private_data = dev;

return 0;
}


Top
 Profile  
 
 Post subject: [SOLVED] Re: SPI Interrupt called Mask is 0 and Status is al
PostPosted: Wed Mar 30, 2011 8:25 pm 
Offline

Joined: Thu Feb 24, 2011 5:26 pm
Posts: 11
I figured out that the PMC was not maintaining the configuration assigned in U-Boot after Linux booted. I assume this was the issue as I made the following change and the code now works.

......
at91_set_A_periph(AT91_PIN_PB0, 0); /* MISO */
at91_set_A_periph(AT91_PIN_PB1, 0); /* MOSI */
at91_set_A_periph(AT91_PIN_PB2, 0); /* SPCK */
at91_set_A_periph(AT91_PIN_PB3, 0); /* NPCS0 */

/* Enable SPI in PMC */
at91spi1_clk = clk_get(NULL, "spi1_clk");
clk_enable(at91spi1_clk);
.......


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: Baidu [Spider] and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: