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.

About SPI IRQ

Genius 3400 points

Hi,all:

I'm using DM365EVM Board, and connect SPI1(Master) and SPI0(Slave) using 3-Pin Mode, Configure SPI register and can read/write 16Bits data using polling mode;

And configure to interrupt mode to send/receive data, and Master SPI0 request irq(42) successfully, and at same time it enter interrupt functon one time, but when receive data from SPI1, RXINTFLAG is set to 1,but cannot respond interrupt and have no enter interrupt function.

My question is:

1.How to configure Slave spi to respond to interrupt?

2.And I read the file of /arch/arm/mach-davince/davinci_spi_platform.c, fond only dm365 spi resource only initialized IRQ_DM3XX_SPINT0_0(IRQ 42)

  static struct resource dm3xx_spi_resources[] = {
 [0] = {
  .start = DM3XX_SPI0_BASE,
  .end = DM3XX_SPI0_BASE + (SZ_4K/2) - 1,
  .flags = IORESOURCE_MEM,
 },
 [1] = {
  .start = IRQ_DM3XX_SPINT0_0,
  .end = IRQ_DM3XX_SPINT0_0,
  .flags = IORESOURCE_IRQ,
 },

  Slave spi have no interrupt responce, whether relate to it?

Thans a lot.

  • Hello,

    Linux SPI framework does not support using DM365 as an SPI slave. This is not a limitation of SPI hardware on DM365, but that of open source Linux framework limitation.

    Please have a look comment in include/linux/spi/spi.h

    /*
     * INTERFACES between SPI master-side drivers and SPI infrastructure.
     * (There's no SPI slave support for Linux yet...)
     */

    The suitation remains the same even with the latest available Linux kernel.

    Thanks,

    Sekhar

  • Yes, we have known what your said. it's extractly no spi slave driver in kernel. So we start writing SPI0 Slave driver,  and modify SPI1 to Master in kernel。

    static const u32 spi_iobase = IO_ADDRESS(0x01c66000);//0x01c66800 //0x01c66000
    static const u32 pinmux_iobase = IO_ADDRESS(0x01c40000);

    static inline void davinci_spi_write_reg(
    int reg, u32 val)
    {
    __raw_writel(val, spi_iobase + reg);
    }

    static inline u32 davinci_spi_read_reg(int reg)
    {
    return __raw_readl(spi_iobase + reg);
    }

    static irqreturn_t davinci_spi_slave_irq(s32 irq, void *context_data,
    struct pt_regs *ptregs)
    {
    printk("spi slave interrupt %d\n", irq);

    return 0;
    }

    static int __init davinci_spi_slave_init(void)
    {
    struct clk *clkp;
    unsigned int w;
    int ret;

    printk("davinci_spi_slave_init\n");
    //set pinmux to spi function
    __raw_writel(0xb75affff, pinmux_iobase + 12);
    udelay(100);

    clkp = clk_get (NULL, "SPICLK");
    if (IS_ERR(clkp)) {
    printk("clk_get Err.\n");
    return -1;
    }
    else
    {
    spi1clk = clkp;
    clk_enable (spi1clk);
    }

    //reset spi
    davinci_spi_write_reg(SPIGCR0, 0);
    udelay(100);
    w = (davinci_spi_read_reg(SPIGCR0) & 0xfffffffe) | 0x1;
    davinci_spi_write_reg(SPIGCR0, w);

    //set external clock and slave mode
    w = davinci_spi_read_reg(SPIGCR1) & 0xfffffffc;
    davinci_spi_write_reg(SPIGCR1, w);

    //Enable the SPIx_SOMI, SPIx_SIMO, and SPIx_SCLK pins
    w = (davinci_spi_read_reg(SPIPC0) & 0xfffff1ff) | 0x00000e00;
    davinci_spi_write_reg(SPIPC0, w);

    //set SPIFMTn 8bit
    davinci_spi_write_reg(SPIFMT0, 0x008); //0x3b08
    davinci_spi_write_reg(SPIFMT1, 0x008);
    davinci_spi_write_reg(SPIFMT2, 0x008);
    davinci_spi_write_reg(SPIFMT3, 0x008);

    //enable receive interrupt
    davinci_spi_write_reg(SPIINT, 0x00000100);//0x00000100
    davinci_spi_write_reg(SPILVL, 0x00000000);//0x00000100

    //SPI enable
    w = (davinci_spi_read_reg(SPIGCR1) & 0xfeffffff) | 0x01000000;
    davinci_spi_write_reg(SPIGCR1, w);
    udelay(100);

    //request interrupt
    ret = request_irq(IRQ_DM3XX_SPINT0_0, davinci_spi_slave_irq, IRQF_DISABLED,
    "spi_slave", &davinci_spi_slave_irq);
    if (ret != 0) {
    ret = -EAGAIN;
    printk("request interrupt failed\n");
    }
    }

    static void __exit davinci_spi_slave_exit(void)
    {
    int i;

    free_irq(IRQ_DM3XX_SPINT0_0, NULL);
    clk_disable (spi1clk);

    printk("davinci_mcbsp_exit.\n");

    return;
    }

    module_init(davinci_spi_slave_init);
    module_exit(davinci_spi_slave_exit);

    And when receive data from SPI1, RXINTFLAG of SPI0 is set to 1,but cannot respond interrupt and have no enter interrupt function。

    Can you help me how to set or config SPI0 to respond  to received interrupt?

  • Hi,

         Today,we can entry interrupt function through  modify interrupt function like this:

    static irqreturn_t davinci_spi_slave_irq(s32 irq, void *context_data, struct pt_regs *ptregs)
    {
        u32 int_status, w;
        printk("spi slave interrupt %d\n", irq);
        w = davinci_spi_read_reg(SPIBUF);
       printk("read data 0x%x\n", w);
    }

    But,Master SPI1 send one byte data, the slave SPI0 enter interrupt function twice, the sencond time received data (SPIBUF) is 0, and the first time is correct.

    Why doit enter interrupt function twice?

    Thanks a lot !

  • Hello,

    I noticed that you are not returning IRQ_HANDLED from the ISR. Can you please do that and see if it helps?

    Thanks,

    Sekhar

  • Thanks a lot

     

    Now I know why it enter interruption funtion twice. After master spi execute write(), the function davinci_spi_chipselect() will be executed. And In the function davinci_spi_chipselect() the register SPIDAT1 will be written, so new data send to slave device.