配置核心gpio模擬spi時序的方法
阿新 • • 發佈:2019-01-06
假如你現在有一份基於核心介面SPI的驅動,但是現在你的硬體已經沒有多餘的SPI介面了。怎麼辦?難道我們需要重新寫驅動嗎,像微控制器一樣去操作IO的高低來符合時序。那麼你的工作量就加大了。其實,linux核心已經寫好了模擬SPI時序,你只需要配置好。就可以使用了。下面分享一下個人經驗。
首先,你需要配置CONFIG。
config SPI_GPIO
tristate "GPIO-based bitbanging SPI Master"
depends on GENERIC_GPIO
select SPI_BITBANG
其次,你需要在你的平臺註冊platform_device,保證能讓spi-gpio.c能執行到probe函式。
static struct spi_gpio_platform_data xxx_data = {
.sck = Pin(1),
.mosi = Pin(2),
.miso = Pin(3),
.num_chipselect = 1,
};
struct platform_device xxx_device = {
.name = DRIVER_NAME,
.id = 0,
.dev = {
.platform_data = &xxx_data,
},
};
然後,你需要註冊spi_board_info結構體,並初始化。
static struct spi_board_info xxxxx_board_info[] __initdata = { { .modalias = xxxx, .max_speed_hz = 1200000, .bus_num = 0, .chip_select = 0, .mode = SPI_MODE_x, .controller_data = (void *)Pin(4), }, };
當你完成了以上步驟,恭喜你。模擬SPI已經配置成功了。接下來,你的硬體SPI驅動也可以相容模擬IO的了。
那麼核心是如何實現模擬SPI時序的呢?實現介面在spi-bitbang-txrx.h。
static inline u32 bitbang_txrx_be_cpha0(struct spi_device *spi, unsigned nsecs, unsigned cpol, unsigned flags, u32 word, u8 bits) { /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ /* clock starts at inactive polarity */ for (word <<= (32 - bits); likely(bits); bits--) { /* setup MSB (to slave) on trailing edge */ if ((flags & SPI_MASTER_NO_TX) == 0) setmosi(spi, word & (1 << 31)); spidelay(nsecs); /* T(setup) */ setsck(spi, !cpol); spidelay(nsecs); /* sample MSB (from slave) on leading edge */ word <<= 1; if ((flags & SPI_MASTER_NO_RX) == 0) word |= getmiso(spi); setsck(spi, cpol); } return word; }
上面是SPI模式0和模式2的介面時序實現方法。 仔細分析下,是不是和微控制器SPI模擬時序一樣。