This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

McSPI slave mode interrupt handling

Other Parts Discussed in Thread: SYSCONFIG

Hi,

I am having trouble getting an interrupt to fire on McSPI RX0_full event.

When I configure McSPI1 in slave mode, it sits quietly primed for input. 

Then when it receives the first 8 bits from the external master, the interrupt fires.

But the interrupt never fires again?

Here's is the debug version of my interrupt handler that I have added to spi-omap2-mcspi.c :

<code>

/* spi data irq handler */
static irqreturn_t mcspi_pio_irq_handler(int irq, void *dev_id)
{
    struct spi_master *master = dev_id;
   u32 l, d;

   // Identify interrupt event
   l = mcspi_read_reg(master, OMAP2_MCSPI_IRQSTATUS);

   //Read the data RX register to clear RX_full condition
   d = mcspi_read_reg(master, OMAP2_MCSPI_RX0);

   //Write to the data TX register to clear TX_empty condition
   mcspi_write_reg(master, OMAP2_MCSPI_TX0, d);

   dev_dbg(&master->dev, "fm: irq: status: %X data: %X\n", l, d);

   // Reset any interrupt event(s)

   l = 0x00000000;
   MOD_REG_BIT(l, OMAP2_MCSPI_IRQSTATUS_RX0_FULL, 1)
   mcspi_write_reg(master, OMAP2_MCSPI_IRQSTATUS, l);

   // Enable IRQ on RX0 full only
   l = 0x00000000;
   MOD_REG_BIT(l, OMAP2_MCSPI_IRQENABLE_RX0_FULL, 1);
   mcspi_write_reg(master, OMAP2_MCSPI_IRQENABLE, l);

   return IRQ_HANDLED;
}

</code>

Am I missing a step to get the interrupt to fire again?

Note: this is SPI1 (i.e. bus number 2 => the second instance of McSPI ).

Any help would be appreciated.

Regards,

Fergal

  • Hi,

    I found the problem.

    The power management unit is configured by default configured to put the SPI module into idle mode awaiting a wakeup event and wakeup is not supported in slave mode (see section 24.1.2 of am335x Technical Reference manual).

    The following code in  my omap2_mcspi_set_slave_mode function stops the module from going idle.

    <code>

    #define OMAP2_MCSPI_SYSCONFIG 0x10
    #define OMAP2_MCSPI_SYSC_SIDLEMODE_MASK (0x03 << 3)
    #define OMAP2_MCSPI_SYSC_NOIDLE (1<<3)

    l = mcspi_read_reg(master, OMAP2_MCSPI_SYSCONFIG);
    l &= ~OMAP2_MCSPI_SYSC_SIDLEMODE_MASK;
    l |= OMAP2_MCSPI_SYSC_NOIDLE; /* no idle mode */
    mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG, l);
    </code>

    Regards,

    Fergal