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.

omap4460 spi master receive problem

Other Parts Discussed in Thread: 4460

Hello ,

First my environment as follow:

Soft:

android 4.0 ,kernel 3.0.21

mcspi1 ,cs3

Hardware:

omap 4460

Second My problem is as follow:

Problem;

When I try to transmit data from mcspi1_simo (cpu omap4460),I can see data wave at the mcspi1_simo,at the same time data wave at  the mcspi1_somi . But problem is I can't read any data from  rx_register when I use pio mode not dma. Can you tell me how to check this  problem? thanks.

    OMAP4_MUX(MCSPI1_CLK, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),

    OMAP4_MUX(MCSPI1_SOMI, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
  
    OMAP4_MUX(MCSPI1_SIMO, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
   
    OMAP4_MUX(MCSPI1_CS3, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),

  • Hello,

    Do you use the SPI fifo?

    If so, then maybe you try to read the RX register before the FIFO threshold is reached (that is before Buffer almost full, MCSPI_XFERLEVEL[15:8] AFL, leve  is reached). For additional information on this check Section 23.4.4.4 FIFO Buffer Management and Section 23.4.4.4.1 Buffer Almost Full of OMAP4460 TRM.

    Best Regards,
    Yordan

  • Hello ,

    I don't use spi fifo,but pio mode . It's your own release code in omap2_mcspi.c as follow:

    Can it read receive data by this function or not?

    static unsigned
    omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
    {
        struct omap2_mcspi    *mcspi;
        struct omap2_mcspi_cs    *cs = spi->controller_state;
        unsigned int        count, c;
        u32            l;
        void __iomem        *base = cs->base;
        void __iomem        *tx_reg;
        void __iomem        *rx_reg;
        void __iomem        *chstat_reg;
        int            word_len;

        mcspi = spi_master_get_devdata(spi->master);
        count = xfer->len;
        c = count;
        word_len = cs->word_len;
        printk("sdfsdfdsf\n");
        l = mcspi_cached_chconf0(spi);

        dump(spi);
            
        /* We store the pre-calculated register addresses on stack to speed
         * up the transfer loop. */
        tx_reg        = base + OMAP2_MCSPI_TX0;
        rx_reg        = base + OMAP2_MCSPI_RX0;
        chstat_reg    = base + OMAP2_MCSPI_CHSTAT0;

        if (c < (word_len>>3))
            return 0;

        if (word_len <= 8) {
            u8        *rx;
            const u8    *tx;

            rx = xfer->rx_buf;
            tx = xfer->tx_buf;

            do {
                c -= 1;
                if (tx != NULL) {
                    if (mcspi_wait_for_reg_bit(chstat_reg,
                            OMAP2_MCSPI_CHSTAT_TXS) < 0) {
                        dev_err(&spi->dev, "TXS timed out\n");
                        goto out;
                    }
                    dev_vdbg(&spi->dev, "write-%d %02x\n",
                            word_len, *tx);
                    __raw_writel(*tx++, tx_reg);
                }
                if (rx != NULL) {
                    if (mcspi_wait_for_reg_bit(chstat_reg,
                            OMAP2_MCSPI_CHSTAT_RXS) < 0) {
                        dev_err(&spi->dev, "RXS timed out\n");
                        goto out;
                    }

                    if (c == 1 && tx == NULL &&
                        (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                        omap2_mcspi_set_enable(spi, 0);
                        *rx++ = __raw_readl(rx_reg);
                        dev_vdbg(&spi->dev, "read-%d %02x\n",
                                word_len, *(rx - 1));
                        if (mcspi_wait_for_reg_bit(chstat_reg,
                            OMAP2_MCSPI_CHSTAT_RXS) < 0) {
                            dev_err(&spi->dev,
                                "RXS timed out\n");
                            goto out;
                        }
                        c = 0;
                    } else if (c == 0 && tx == NULL) {
                        omap2_mcspi_set_enable(spi, 0);
                    }

                    *rx++ = __raw_readl(rx_reg);
                    dev_vdbg(&spi->dev, "read-%d %02x\n",
                            word_len, *(rx - 1));
                }
            } while (c);
        } else if (word_len <= 16) {
            u16        *rx;
            const u16    *tx;

            rx = xfer->rx_buf;
            tx = xfer->tx_buf;
            do {
                c -= 2;
                if (tx != NULL) {
                    if (mcspi_wait_for_reg_bit(chstat_reg,
                            OMAP2_MCSPI_CHSTAT_TXS) < 0) {
                        dev_err(&spi->dev, "TXS timed out\n");
                        goto out;
                    }
                    dev_vdbg(&spi->dev, "write-%d %04x\n",
                            word_len, *tx);
                    __raw_writel(*tx++, tx_reg);
                }
                if (rx != NULL) {
                    if (mcspi_wait_for_reg_bit(chstat_reg,
                            OMAP2_MCSPI_CHSTAT_RXS) < 0) {
                        dev_err(&spi->dev, "RXS timed out\n");
                        goto out;
                    }

                    if (c == 2 && tx == NULL &&
                        (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                        omap2_mcspi_set_enable(spi, 0);
                        *rx++ = __raw_readl(rx_reg);
                        dev_vdbg(&spi->dev, "read-%d %04x\n",
                                word_len, *(rx - 1));
                        if (mcspi_wait_for_reg_bit(chstat_reg,
                            OMAP2_MCSPI_CHSTAT_RXS) < 0) {
                            dev_err(&spi->dev,
                                "RXS timed out\n");
                            goto out;
                        }
                        c = 0;
                    } else if (c == 0 && tx == NULL) {
                        omap2_mcspi_set_enable(spi, 0);
                    }
                    omap2_mcspi_set_enable(spi, 0);

                    *rx++ = __raw_readl(rx_reg);
                    printk("rx is %0x ,rx-1 is %0x\n",*rx ,*(rx-1));
                    dev_vdbg(&spi->dev, "read-%d %04x\n",
                            word_len, *(rx - 1));
                }
            } while (c >= 2);
        } else if (word_len <= 32) {
            u32        *rx;
            const u32    *tx;

            rx = xfer->rx_buf;
            tx = xfer->tx_buf;
            do {
                c -= 4;
                if (tx != NULL) {
                    if (mcspi_wait_for_reg_bit(chstat_reg,
                            OMAP2_MCSPI_CHSTAT_TXS) < 0) {
                        dev_err(&spi->dev, "TXS timed out\n");
                        goto out;
                    }
                    dev_vdbg(&spi->dev, "write-%d %08x\n",
                            word_len, *tx);
                    __raw_writel(*tx++, tx_reg);
                }
                if (rx != NULL) {
                    if (mcspi_wait_for_reg_bit(chstat_reg,
                            OMAP2_MCSPI_CHSTAT_RXS) < 0) {
                        dev_err(&spi->dev, "RXS timed out\n");
                        goto out;
                    }

                    if (c == 4 && tx == NULL &&
                        (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                        omap2_mcspi_set_enable(spi, 0);
                        *rx++ = __raw_readl(rx_reg);
                        dev_vdbg(&spi->dev, "read-%d %08x\n",
                                word_len, *(rx - 1));
                        if (mcspi_wait_for_reg_bit(chstat_reg,
                            OMAP2_MCSPI_CHSTAT_RXS) < 0) {
                            dev_err(&spi->dev,
                                "RXS timed out\n");
                            goto out;
                        }
                        c = 0;
                    } else if (c == 0 && tx == NULL) {
                        omap2_mcspi_set_enable(spi, 0);
                    }

                    *rx++ = __raw_readl(rx_reg);
                    dev_vdbg(&spi->dev, "read-%d %08x\n",
                            word_len, *(rx - 1));
                }
            } while (c >= 4);
        }

        /* for TX_ONLY mode, be sure all words have shifted out */
        if (xfer->rx_buf == NULL) {
            if (mcspi_wait_for_reg_bit(chstat_reg,
                    OMAP2_MCSPI_CHSTAT_TXS) < 0) {
                dev_err(&spi->dev, "TXS timed out\n");
            } else if (mcspi_wait_for_reg_bit(chstat_reg,
                    OMAP2_MCSPI_CHSTAT_EOT) < 0)
                dev_err(&spi->dev, "EOT timed out\n");

            /* disable chan to purge rx datas received in TX_ONLY transfer,
             * otherwise these rx datas will affect the direct following
             * RX_ONLY transfer.
             */
            omap2_mcspi_set_enable(spi, 0);
        }
    out:
        omap2_mcspi_set_enable(spi, 1);
        return count - c;
    }