一、驅動挂載與解除安裝
加載子產品之後,檢視完整的系統日志:

1. 子產品加載與解除安裝
WK2124使用spi總線通信,是以在子產品加載的時候向核心注冊spi驅動。
2. 驅動挂載與解除安裝
可以看到spi驅動相容性是"wkmic,wk2124spi",驅動挂載函數probe,解除安裝函數remove。Linux 5.4核心中spi驅動架構沒有resume,是以注釋resume函數實作:
3. SPI讀寫函數
以 wk2xxx_read_global_reg 為例,基于SPI驅動架構,實作如下:
二、probe函數略讀
1. 測試SPI通信是否正常
對應日志為,能讀到寄存器資料,說明SPI通信正常:
2. 解析中斷引腳
函數實作如下,傳回irq編号:
對應日志為:
3. 注冊uart驅動
uart_drriver實作為wk2xxx_uart_driver,使用
uart_register_driver
API注冊進核心,後面進行剖析。
4. 注冊uart端口
uart端口使用
uart_add_one_port
注冊進核心,這些端口的操作函數集為wk2xxx_pops,後面進行剖析。
三、uart驅動架構實作
關于Linux驅動架構,參考文章:i.MX6ULL驅動開發 | 15 - Linux UART 驅動架構。
1. uart_driver結構體實作
需要注意,dev_name 将會是後續注冊的裝置節點名稱,每個注冊的uart端口都會對應一個節點,名稱為ttysWKx。
2. uart_port_ops實作
注冊uart_port的時候,最重要的是端口的操作函數集,也就是 uart_ops 成員中的函數,Linux核心最終調用的都是其中的函數。
其實整個驅動的目的就是實作這些函數,但沒有逐個分析的必要,主要看一下序列槽發送流程和序列槽接收流程。
四、設定序列槽波特率流程
1. enable_ms
enable_ms用于啟用modem狀态中斷:
enable_ms(port)
Enable the modem status interrupts.
This method may be called multiple times. Modem status
interrupts should be disabled when the shutdown
wk2124沒有對應的控制線,是以實作為空:
2. set_termios
set_termios用于設定序列槽屬性,比如更改波特率。
對于波特率是經過了轉碼的:
而且驅動中最大支援到230400,這點在使用者态設定的時候需要注意:
在所有設定參數都準備好之後,調用該函數設定到WK2124中每個子序列槽對應的寄存器中:
其中設定寄存器的代碼如下:
WK2124寄存器如下:
五、序列槽發送資料流程
printk級别要改為 7 4 1 7
1. enable_ms
2. set_termios
3. start_tx(重點)
其中的核心是 workqueue 機制,将發送的内容使用queue_work送出到工作隊列中:
工作隊列實際的處理函數為wk2xxx_work,在其中實際操作wk2124寄存器去完成資料的發送,如下:
六、序列槽接收資料
1. enable_ms
2. set_termios
3. irq中斷函數
4. wk2xxxirq_app
在接收流程的work處理函數wk2xxx_work中,主要調用 wk2xxxirq_app 函數,其中完成一系列與WK2124晶片的操作。
(1)讀取GIFR寄存器
wk2xxx_read_global_reg(s->spi_wk,WK2XXX_GIFR ,dat);
gifr = dat[0];
讀取之後判斷子序列槽是否确實發生了中斷,如果沒有發生則直接return。
(2)讀取子序列槽SIFR寄存器
wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,dat);
sifr = dat[0];
(3)讀取子序列槽SIER寄存器
wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,dat);
sier = dat[0];
5. wk2xxx_rx_chars
wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FDAT,dat);
ch = (int)dat[0];