RK3399驱动开发 | 04 - WK2124串口芯片驱动浅析

Posted Mculover666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RK3399驱动开发 | 04 - WK2124串口芯片驱动浅析相关的知识,希望对你有一定的参考价值。

一、驱动挂载与卸载

加载模块之后,查看完整的系统日志:

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 method is
	called.

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];

以上是关于RK3399驱动开发 | 04 - WK2124串口芯片驱动浅析的主要内容,如果未能解决你的问题,请参考以下文章

RK3399驱动开发 | 03 - WK2124串口芯片驱动调试

RK3399驱动开发 | 03 - WK2124串口芯片驱动调试

RK3399驱动开发 | 05 - 使用lszrz压测串口传输(wk2124)

使用lszrz压测串口传输(RK3399 + wk2124)

RK3399驱动开发 | 10 - RK3399以太网gmac调试

RK3399驱动开发 | 10 - RK3399以太网gmac调试