Freescale MPC8314 CPU SPI controller driver updated;

来源:互联网 发布:儿童英语产品网络代理 编辑:程序博客网 时间:2024/05/20 02:55

UBOOT自带的驱动最多一次一次向mpc8314 SPI控制器中写入32bit传送, 但一次发送16bit, 24bit MPC8314 SPI控制器有点问题;
索性改成每次都固定8bit的传送,测试通过;

void mpc8xxx_spi_init(void)
{
        volatile spi8xxx_t *spi = (spi8xxx_t *)SPI_REG_BASE;

        spi->mode = 0;
        spi->mask = 0x00000000; /* Mask  all SPI interrupts */
        spi->com = 0;           /* LST bit doesn't do anything, so disregard */
        spi->event = 0xffffffff;        /* Clear all SPI events */

        spi->mode = SPI_MODE_CP_BEGIN_EDGECLK | SPI_MODE_CI_INACTIVEHIGH | SPI_MODE_LEN(7) | SPI_MODE_PM(0xf) | SPI_MODE_REV | SPI_MODE_MS | SPI_MODE_EN;
}


/* 这个函数的重点修改是:每次最多传送8bit, 而不是原始的最多一次传送32bit */
int mpc8xxx_spi_xfer(struct spi_slave *slave, unsigned int bitlen, const unsigned char *dout,
                unsigned char *din, unsigned long flags)
{
        volatile spi8xxx_t *spi = (spi8xxx_t *)SPI_REG_BASE;
        unsigned int tmpdout, tmpdin, event;
        int numBlks = bitlen / 8 + (bitlen % 8 ? 1 : 0);
        int tm, isRead = 0;
        unsigned char charSize = 8;

        // poll low CS

        spi->event = 0xffffffff;        /* Clear all SPI events */

        /* handle data in 8-bit chunks */ /* 固定每次都按8bit传送; */
        while (numBlks--) {
        tmpdout = 0;
        charSize = (bitlen >= 8 ? 8 : bitlen);

        /* Shift data so it's msb-justified */
        tmpdout = *(u8 *)dout;

        if (bitlen < 8) {
                if (bitlen <= 4)
                        spi->mode = (spi->mode & 0xff0fffff) |
                                    (3 << 20);
                else
                        spi->mode = (spi->mode & 0xff0fffff) |
                                    ((bitlen - 1) << 20);
        } else {
                spi->mode = (spi->mode & 0xff0fffff) | SPI_MODE_LEN(7);
                /* Set up the next iteration if sending > 8 bits */
                bitlen -= 8;
                dout += 1;
        }

        spi->tx = tmpdout;      /* Write the data out */

        /*
         * Wait for SPI transmit to get out
         * or time out (1 second = 1000 ms)
         * The NE event must be read and cleared first
         */
        for (tm = 0, isRead = 0; tm < SPI_TIMEOUT; ++tm) {
                event = spi->event;
                if (event & SPI_EV_NE) {
                        tmpdin = spi->rx;
                        spi->event |= SPI_EV_NE;
                        isRead = 1;

                        *din = tmpdin & 0xff;

                        if (charSize == 8) {
                                din += 1;
                        }
                }
                /*
                 * Only bail when we've had both NE and NF events.
                 * This will cause timeouts on RO devices, so maybe
                 * in the future put an arbitrary delay after writing
                 * the device.  Arbitrary delays suck, though...
                 */
                if (isRead && (event & SPI_EV_NF))
                        break;
        }
        if (tm >= SPI_TIMEOUT)
                puts("*** spi_xfer: Time out during SPI transfer");

        }

        return 0;
}

文:董滨华/董兵华/dongbinghua

原创粉丝点击