uboot移植spi驅動


記錄一下在uboot內移植spi驅動的過程

 

芯片:freescale Mpc8308

uboot版本:u-boot-2009.11-rc1.2

需求:我們需要在uboot下通過spi配置一個時鍾芯片(dpll)用來給fpga提供時鍾

 

要移植spi驅動,前提是要通過手冊了解該cpu的spi的結構和寄存器描述,一般作為cpu的外圍設備,spi是有一個spi控制器的

簡單看一下8308的spi模塊結構

 

spi的四根線,MOSI,MISO,CS,CLK

CS以外的幾根線是從Master上引出來的

而CS是由cpu的gpio來扮演的

 

驅動方面

uboot中產品的配置文件我的在include/configs/MPC8308EDD.h

這個是修改過的,

在u-boot-2009.11-rc1.2/driver/spi中找到mpc8xxx_spi.c文件,我們姑且認為這個就是最相近的驅動了(根據芯片名稱與文件名稱)

相關Makefile

COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o 

在lib_ppc/board.c(不通uboot,目錄不同)中有spi_init()的初始化調用,如下

#if defined(CONFIG_HARD_SPI)
static int init_func_spi (void)
{
        puts ("SPI:   ");
        spi_init ();
        puts ("ready\n");
        return (0);
}
#endif

 

將需要的宏添加到MPC8308EDD.h中

/*

 * eSPI - Enhanced SPI
 */
#define CONFIG_HARD_SPI
#define CONFIG_FSL_ESPI

現在spi模塊驅動有了,初始化有了,但是我們還需要一個spi的對象,struct spi_slave

struct spi_slave *spi_slave_init(void)
{

struct spi_slave *slave;
unsigned int    bus = 0;
unsigned int    cs = 3;
unsigned int    mode = SPI_MODE_0;

slave = spi_setup_slave(bus, cs, 1000000, mode);
if (!slave) {
printf("Invalid device %d:%d\n", bus, cs);
return NULL;
}

spi_claim_bus(slave);

return slave;
}
static int spi_read_write(struct spi_slave *spi,
const u8 *cmd, size_t cmd_len,
const u8 *data_out, u8 *data_in,
size_t data_len)
{
unsigned long flags = SPI_XFER_BEGIN;
int ret;

if (data_len == 0)
flags |= SPI_XFER_END;

ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
if (ret) {
debug("SF: Failed to send command (%zu bytes): %d\n",
cmd_len, ret);
} else if (data_len != 0) {
ret = spi_xfer(spi, data_len * 8, data_out, data_in, SPI_XFER_END);
if (ret)
debug("SF: Failed to transfer %zu bytes of data: %d\n",
data_len, ret);
}

return ret;
}

這個spi_read_write是根據我的讀寫需求后補的
在lib_ppc/board.c函數board_init_r最后添加spi的slave初始化
        struct spi_slave *slave;

        slave = spi_slave_init();
目前為止,spi驅動理論上移植完了,一次ok的可能性太小了^_^,后面講問題

 

 

1.一切配置正常但從設備並沒有工作

初始化正常,從設備也配置了,而且spi的各引腳信號都能測到,從設備是一個時鍾芯片,並沒有時鍾輸出

信號能測到那么檢查信號的正確性了,按照時鍾芯片的要求,將spi的初始化模式修改

 

- spi->mode = SPI_MODE_REV | SPI_MODE_MS | SPI_MODE_EN;
- spi->mode = (spi->mode & 0xfff0ffff) | (1 << 16); /* Use SYSCLK / 8
-     (16.67MHz typ.) */
+ spi->mode = 0;
+ spi->mode = SPMODE_INIT_VAL | SPMODE_ENABLE;
+// spi->mode = (spi->mode & 0xfff0ffff) | (1 << 16); /* Use SYSCLK / 8   (16.67MHz typ.) */
  spi->event = 0xffffffff; /* Clear all SPI events */
  spi->mask = 0x00000000; /* Mask  all SPI interrupts */
  spi->com = 0; /* LST bit doesn't do anything, so disregard */
+ printf("mode = 0x%x\n",spi->mode);
  spi->com = 0; /* LST bit doesn't do anything, so disregard */
+ printf("mode = 0x%x\n",spi->mode);


原文鏈接:https://blog.csdn.net/davion_zhang/article/details/50883806


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM