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 spi slave support on linux

Other Parts Discussed in Thread: SYSCONFIG

I want to use the mcspi0 as spi slave. As it is not currently supported in kernel, I modified the omap2_mcspi.c to support slave mode

I need to enable the SPI interrupts RX receive of data.

when I enable the interrupts OMAP2_MCSPI_IRQENABLE_RX0_FULL and OMAP2_MCSPI_IRQENABLE_RX0_OVERFLOW

 I found that I am not getting any interrupts but the whole system hangs after 30 sec.

But if OMAP2_MCSPI_IRQENABLE_RX0_FULL enable bit is not set I am not facing any hang up issues. Is interrupt modes already tested in kernel.

 

 

Following configuration are done for enabling the module and configure it as slave

  

int omap2_mcspi_setup_transfer(struct spi_slave_device *spi )

{

 

                struct omap2_mcspi *mcspi = g_mcspi;

                u8 word_len = spi->bits_per_word;

                u32 reg_val;

                _SPI_DBG(" ");

                mcspi->char_len = spi->bits_per_word;

                omap2_mcspi_set_enable(mcspi, 0);

 

                reg_val =  mcspi_read_reg(mcspi, OMAP2_MCSPI_CHCONF0);

 

                /* set SPI mode 0..3 */

                if (spi->mode & SPI_CPOL)

                                reg_val |= OMAP2_MCSPI_CHCONF_POL;

                else

                                reg_val &= ~OMAP2_MCSPI_CHCONF_POL;

                if (spi->mode & SPI_CPHA)

                                reg_val |= OMAP2_MCSPI_CHCONF_PHA;

                else

                                reg_val &= ~OMAP2_MCSPI_CHCONF_PHA;

 

                /* set chipselect polarity; manage with FORCE */

                if (!(spi->mode & SPI_CS_HIGH))

                                reg_val |= OMAP2_MCSPI_CHCONF_EPOL;                /* active-low; normal */

                else

                                reg_val &= ~OMAP2_MCSPI_CHCONF_EPOL;

 

                /* wordlength */

                reg_val &= ~OMAP2_MCSPI_CHCONF_WL_MASK;

                reg_val |= (word_len - 1) << 7;

 

                /* SPIDAT[0] for RX and SPIDAT[1] for TX */

               

                reg_val &= ~(OMAP2_MCSPI_CHCONF_IS|OMAP2_MCSPI_CHCONF_DPE1);

                reg_val |= OMAP2_MCSPI_CHCONF_DPE0;

               

                mcspi_write_reg(mcspi, OMAP2_MCSPI_CHCONF0, reg_val);

 

                omap2_mcspi_set_enable(mcspi, OMAP2_MCSPI_CHCTRL_EN);

 

                _SPI_DBG("enable RX interrupt");

                /* enable RX interrupt */

                mcspi_write_reg(mcspi, OMAP2_MCSPI_IRQENABLE, (OMAP2_MCSPI_IRQENABLE_RX0_FULL|OMAP2_MCSPI_IRQENABLE_RX0_OVERFLOW ));

                //OMAP2_MCSPI_IRQENABLE_RX0_FULL

                return 0;

}

 

probe function

 

                r = platform_get_resource(pdev, IORESOURCE_MEM, 0);

                if (r == NULL) {

                                status = -ENODEV;

                                goto err1;

                }

                if (!request_mem_region(r->start, (r->end - r->start) + 1,

                                                dev_name(&pdev->dev))) {

                                status = -EBUSY;

                                goto err1;

                }

 

                g_mcspi->phys = r->start;

                g_mcspi->base = ioremap(r->start, r->end - r->start + 1);

                if (!g_mcspi->base) {

                                dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");

                                status = -ENOMEM;

                                goto err1aa;

                }

               

                               

                /* intialize share lock */

                spin_lock_init(&g_mcspi->rx_fifo_lock);

 

                error = kfifo_alloc(&g_mcspi->rx_fifo, 512, GFP_KERNEL);

                if (error) {

                                printk(KERN_ERR "g_mcspi->rx_fifo failed\n");

                                goto err1a;

                }

                               

                init_completion(&g_mcspi->rx_completion);

 

               

                g_mcspi->ick = clk_get(&pdev->dev, "ick");

                if (IS_ERR(g_mcspi->ick)) {

                                printk(KERN_ERR  "can't get mcspi_ick\n");

                                status = PTR_ERR(g_mcspi->ick);

                                goto err1a;

                }

                g_mcspi->fck = clk_get(&pdev->dev, "fck");

                if (IS_ERR(g_mcspi->fck)) {

                                printk(KERN_ERR "can't get mcspi_fck\n");

                                status = PTR_ERR(g_mcspi->fck);

                                goto err2;

                }

 

                g_mcspi->irq = platform_get_irq(pdev, 0);

                _SPI_DBG( "g_mcspi->irq =  0x%x in %s ", g_mcspi->irq, pdev->name );

                if (g_mcspi->irq <= 0) {

                                status = -EINVAL;

                                goto err1a;

                }

                /* request irq for SPI */

                rc = request_irq(g_mcspi->irq, omap2_spi_isr, 0, pdev->name, g_mcspi);

                if (rc != 0)

                {

                                printk(KERN_ERR "request IRQ 0x%x in %s failed with rc  %d", g_mcspi->irq, pdev->name, rc);

                                status = rc;

                                goto err1a;

                }

                _SPI_DBG( "request irq for SPI done " );

                if (omap2_mcspi_reset(g_mcspi) < 0)

                {

                                printk(KERN_ERR  "failed omap2_mcspi_reset ");

                                goto err4;

                }

 

static void omap2_mcspi_set_slave_mode(struct omap2_mcspi *mcspi)

{

                u32 l;

 

                /* setup for  slave mode

                 * only singe channel is supported in slave mode

                 */

                l = mcspi_read_reg(mcspi, OMAP2_MCSPI_MODULCTRL);

                MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0);

                MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 1);

                MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);

                mcspi_write_reg(mcspi, OMAP2_MCSPI_MODULCTRL, l);

 

 

}

static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)

{

            u32                              tmp;

 

            if (omap2_mcspi_enable_clocks(mcspi))

                        return -1;

 

            mcspi_write_reg(mcspi, OMAP2_MCSPI_SYSCONFIG,

                                    OMAP2_MCSPI_SYSCONFIG_SOFTRESET);

            do {

                        tmp = mcspi_read_reg(mcspi, OMAP2_MCSPI_SYSSTATUS);

            } while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE));

 

            tmp = OMAP2_MCSPI_SYSCONFIG_AUTOIDLE |

                        OMAP2_MCSPI_SYSCONFIG_SMARTIDLE;

            mcspi_write_reg(mcspi, OMAP2_MCSPI_SYSCONFIG, tmp);

           

 

            omap2_mcspi_set_slave_mode(mcspi);

        /* clock remain enabled 

          omap2_mcspi_disable_clocks(mcspi);*/

            return 0;

 

 

when I enable the interrupts OMAP2_MCSPI_IRQENABLE_RX0_FULL and OMAP2_MCSPI_IRQENABLE_RX0_OVERFLOW

 I found that I am not getting any interrupts but the whole system hangs after 30 sec.

But if OMAP2_MCSPI_IRQENABLE_RX0_FULL enable bit is not set I am not facing any hang up issues.